Skip to content

Commit

Permalink
Merge branch 'samsung-irq' of git://git.kernel.org/pub/scm/linux/kern…
Browse files Browse the repository at this point in the history
…el/git/broonie/misc-2.6 into devel-stable
  • Loading branch information
Russell King committed May 11, 2011
2 parents 805499a + bd7e388 commit 1cf02bb
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 215 deletions.
7 changes: 1 addition & 6 deletions arch/arm/mach-s3c64xx/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,7 @@ void __init s3c64xx_init_irq(u32 vic0_valid, u32 vic1_valid)
vic_init(VA_VIC1, IRQ_VIC1_BASE, vic1_valid, 0);

/* add the timer sub-irqs */

s3c_init_vic_timer_irq(IRQ_TIMER0_VIC, IRQ_TIMER0);
s3c_init_vic_timer_irq(IRQ_TIMER1_VIC, IRQ_TIMER1);
s3c_init_vic_timer_irq(IRQ_TIMER2_VIC, IRQ_TIMER2);
s3c_init_vic_timer_irq(IRQ_TIMER3_VIC, IRQ_TIMER3);
s3c_init_vic_timer_irq(IRQ_TIMER4_VIC, IRQ_TIMER4);
s3c_init_vic_timer_irq(5, IRQ_TIMER0);

s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs));
}
116 changes: 27 additions & 89 deletions arch/arm/plat-s5p/irq-gpioint.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,72 +41,11 @@ struct s5p_gpioint_bank {

LIST_HEAD(banks);

static int s5p_gpioint_get_offset(struct irq_data *data)
static int s5p_gpioint_set_type(struct irq_data *d, unsigned int type)
{
struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
return data->irq - chip->irq_base;
}

static void s5p_gpioint_ack(struct irq_data *data)
{
struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
int group, offset, pend_offset;
unsigned int value;

group = chip->group;
offset = s5p_gpioint_get_offset(data);
pend_offset = REG_OFFSET(group);

value = __raw_readl(GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
value |= BIT(offset);
__raw_writel(value, GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
}

static void s5p_gpioint_mask(struct irq_data *data)
{
struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
int group, offset, mask_offset;
unsigned int value;

group = chip->group;
offset = s5p_gpioint_get_offset(data);
mask_offset = REG_OFFSET(group);

value = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
value |= BIT(offset);
__raw_writel(value, GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
}

static void s5p_gpioint_unmask(struct irq_data *data)
{
struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
int group, offset, mask_offset;
unsigned int value;

group = chip->group;
offset = s5p_gpioint_get_offset(data);
mask_offset = REG_OFFSET(group);

value = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
value &= ~BIT(offset);
__raw_writel(value, GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
}

static void s5p_gpioint_mask_ack(struct irq_data *data)
{
s5p_gpioint_mask(data);
s5p_gpioint_ack(data);
}

static int s5p_gpioint_set_type(struct irq_data *data, unsigned int type)
{
struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
int group, offset, con_offset;
unsigned int value;

group = chip->group;
offset = s5p_gpioint_get_offset(data);
con_offset = REG_OFFSET(group);
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
struct irq_chip_type *ct = gc->chip_types;
unsigned int shift = (d->irq - gc->irq_base) << 2;

switch (type) {
case IRQ_TYPE_EDGE_RISING:
Expand All @@ -130,23 +69,12 @@ static int s5p_gpioint_set_type(struct irq_data *data, unsigned int type)
return -EINVAL;
}

value = __raw_readl(GPIO_BASE(chip) + CON_OFFSET + con_offset);
value &= ~(0x7 << (offset * 0x4));
value |= (type << (offset * 0x4));
__raw_writel(value, GPIO_BASE(chip) + CON_OFFSET + con_offset);

gc->type_cache &= ~(0x7 << shift);
gc->type_cache |= type << shift;
writel(gc->type_cache, gc->reg_base + ct->regs.type);
return 0;
}

static struct irq_chip s5p_gpioint = {
.name = "s5p_gpioint",
.irq_ack = s5p_gpioint_ack,
.irq_mask = s5p_gpioint_mask,
.irq_mask_ack = s5p_gpioint_mask_ack,
.irq_unmask = s5p_gpioint_unmask,
.irq_set_type = s5p_gpioint_set_type,
};

static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
{
struct s5p_gpioint_bank *bank = irq_get_handler_data(irq);
Expand Down Expand Up @@ -179,9 +107,10 @@ static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
{
static int used_gpioint_groups = 0;
int irq, group = chip->group;
int i;
int group = chip->group;
struct s5p_gpioint_bank *bank = NULL;
struct irq_chip_generic *gc;
struct irq_chip_type *ct;

if (used_gpioint_groups >= S5P_GPIOINT_GROUP_COUNT)
return -ENOMEM;
Expand Down Expand Up @@ -211,19 +140,28 @@ static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
* chained GPIO irq has been successfully registered, allocate new gpio
* int group and assign irq nubmers
*/

chip->irq_base = S5P_GPIOINT_BASE +
used_gpioint_groups * S5P_GPIOINT_GROUP_SIZE;
used_gpioint_groups++;

bank->chips[group - bank->start] = chip;
for (i = 0; i < chip->chip.ngpio; i++) {
irq = chip->irq_base + i;
irq_set_chip(irq, &s5p_gpioint);
irq_set_handler_data(irq, chip);
irq_set_handler(irq, handle_level_irq);
set_irq_flags(irq, IRQF_VALID);
}

gc = irq_alloc_generic_chip("s5p_gpioint", 1, chip->irq_base,
(void __iomem *)GPIO_BASE(chip),
handle_level_irq);
if (!gc)
return -ENOMEM;
ct = gc->chip_types;
ct->chip.irq_ack = irq_gc_ack;
ct->chip.irq_mask = irq_gc_mask_set_bit;
ct->chip.irq_unmask = irq_gc_mask_clr_bit;
ct->chip.irq_set_type = s5p_gpioint_set_type,
ct->regs.ack = PEND_OFFSET + REG_OFFSET(chip->group);
ct->regs.mask = MASK_OFFSET + REG_OFFSET(chip->group);
ct->regs.type = CON_OFFSET + REG_OFFSET(chip->group);
irq_setup_generic_chip(gc, IRQ_MSK(chip->chip.ngpio),
IRQ_GC_INIT_MASK_CACHE,
IRQ_NOREQUEST | IRQ_NOPROBE, 0);
return 0;
}

Expand Down
6 changes: 1 addition & 5 deletions arch/arm/plat-s5p/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,7 @@ void __init s5p_init_irq(u32 *vic, u32 num_vic)
vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0);
#endif

s3c_init_vic_timer_irq(IRQ_TIMER0_VIC, IRQ_TIMER0);
s3c_init_vic_timer_irq(IRQ_TIMER1_VIC, IRQ_TIMER1);
s3c_init_vic_timer_irq(IRQ_TIMER2_VIC, IRQ_TIMER2);
s3c_init_vic_timer_irq(IRQ_TIMER3_VIC, IRQ_TIMER3);
s3c_init_vic_timer_irq(IRQ_TIMER4_VIC, IRQ_TIMER4);
s3c_init_vic_timer_irq(5, IRQ_TIMER0);

s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs));
}
2 changes: 1 addition & 1 deletion arch/arm/plat-samsung/include/plat/irq-vic-timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
* published by the Free Software Foundation.
*/

extern void s3c_init_vic_timer_irq(unsigned int vic, unsigned int timer);
extern void s3c_init_vic_timer_irq(unsigned int num, unsigned int timer_irq);
83 changes: 12 additions & 71 deletions arch/arm/plat-samsung/irq-uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,60 +27,6 @@
/* Note, we make use of the fact that the parent IRQs, IRQ_UART[0..3]
* are consecutive when looking up the interrupt in the demux routines.
*/

static inline void __iomem *s3c_irq_uart_base(struct irq_data *data)
{
struct s3c_uart_irq *uirq = irq_data_get_irq_chip_data(data);
return uirq->regs;
}

static inline unsigned int s3c_irq_uart_bit(unsigned int irq)
{
return irq & 3;
}

static void s3c_irq_uart_mask(struct irq_data *data)
{
void __iomem *regs = s3c_irq_uart_base(data);
unsigned int bit = s3c_irq_uart_bit(data->irq);
u32 reg;

reg = __raw_readl(regs + S3C64XX_UINTM);
reg |= (1 << bit);
__raw_writel(reg, regs + S3C64XX_UINTM);
}

static void s3c_irq_uart_maskack(struct irq_data *data)
{
void __iomem *regs = s3c_irq_uart_base(data);
unsigned int bit = s3c_irq_uart_bit(data->irq);
u32 reg;

reg = __raw_readl(regs + S3C64XX_UINTM);
reg |= (1 << bit);
__raw_writel(reg, regs + S3C64XX_UINTM);
__raw_writel(1 << bit, regs + S3C64XX_UINTP);
}

static void s3c_irq_uart_unmask(struct irq_data *data)
{
void __iomem *regs = s3c_irq_uart_base(data);
unsigned int bit = s3c_irq_uart_bit(data->irq);
u32 reg;

reg = __raw_readl(regs + S3C64XX_UINTM);
reg &= ~(1 << bit);
__raw_writel(reg, regs + S3C64XX_UINTM);
}

static void s3c_irq_uart_ack(struct irq_data *data)
{
void __iomem *regs = s3c_irq_uart_base(data);
unsigned int bit = s3c_irq_uart_bit(data->irq);

__raw_writel(1 << bit, regs + S3C64XX_UINTP);
}

static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc)
{
struct s3c_uart_irq *uirq = desc->irq_data.handler_data;
Expand All @@ -97,30 +43,25 @@ static void s3c_irq_demux_uart(unsigned int irq, struct irq_desc *desc)
generic_handle_irq(base + 3);
}

static struct irq_chip s3c_irq_uart = {
.name = "s3c-uart",
.irq_mask = s3c_irq_uart_mask,
.irq_unmask = s3c_irq_uart_unmask,
.irq_mask_ack = s3c_irq_uart_maskack,
.irq_ack = s3c_irq_uart_ack,
};

static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq)
{
void __iomem *reg_base = uirq->regs;
unsigned int irq;
int offs;
struct irq_chip_generic *gc;
struct irq_chip_type *ct;

/* mask all interrupts at the start. */
__raw_writel(0xf, reg_base + S3C64XX_UINTM);

for (offs = 0; offs < 3; offs++) {
irq = uirq->base_irq + offs;

irq_set_chip_and_handler(irq, &s3c_irq_uart, handle_level_irq);
irq_set_chip_data(irq, uirq);
set_irq_flags(irq, IRQF_VALID);
}
gc = irq_alloc_generic_chip("s3c-uart", 1, uirq->base_irq, reg_base,
handle_level_irq);
ct = gc->chip_types;
ct->chip.irq_ack = irq_gc_ack;
ct->chip.irq_mask = irq_gc_mask_set_bit;
ct->chip.irq_unmask = irq_gc_mask_clr_bit;
ct->regs.ack = S3C64XX_UINTP;
ct->regs.mask = S3C64XX_UINTM;
irq_setup_generic_chip(gc, IRQ_MSK(4), IRQ_GC_INIT_MASK_CACHE,
IRQ_NOREQUEST | IRQ_NOPROBE, 0);

irq_set_handler_data(uirq->parent_irq, uirq);
irq_set_chained_handler(uirq->parent_irq, s3c_irq_demux_uart);
Expand Down
69 changes: 26 additions & 43 deletions arch/arm/plat-samsung/irq-vic-timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,60 +28,43 @@ static void s3c_irq_demux_vic_timer(unsigned int irq, struct irq_desc *desc)
}

/* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */

static void s3c_irq_timer_mask(struct irq_data *data)
{
u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
u32 mask = (u32)data->chip_data;

reg &= 0x1f; /* mask out pending interrupts */
reg &= ~mask;
__raw_writel(reg, S3C64XX_TINT_CSTAT);
}

static void s3c_irq_timer_unmask(struct irq_data *data)
static void s3c_irq_timer_ack(struct irq_data *d)
{
u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
u32 mask = (u32)data->chip_data;
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
u32 mask = (1 << 5) << (d->irq - gc->irq_base);

reg &= 0x1f; /* mask out pending interrupts */
reg |= mask;
__raw_writel(reg, S3C64XX_TINT_CSTAT);
irq_reg_writel(mask | gc->mask_cache, gc->reg_base);
}

static void s3c_irq_timer_ack(struct irq_data *data)
{
u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
u32 mask = (u32)data->chip_data;

reg &= 0x1f;
reg |= mask << 5;
__raw_writel(reg, S3C64XX_TINT_CSTAT);
}

static struct irq_chip s3c_irq_timer = {
.name = "s3c-timer",
.irq_mask = s3c_irq_timer_mask,
.irq_unmask = s3c_irq_timer_unmask,
.irq_ack = s3c_irq_timer_ack,
};

/**
* s3c_init_vic_timer_irq() - initialise timer irq chanined off VIC.\
* @parent_irq: The parent IRQ on the VIC for the timer.
* @timer_irq: The IRQ to be used for the timer.
* @num: Number of timers to initialize
* @timer_irq: Base IRQ number to be used for the timers.
*
* Register the necessary IRQ chaining and support for the timer IRQs
* chained of the VIC.
*/
void __init s3c_init_vic_timer_irq(unsigned int parent_irq,
unsigned int timer_irq)
void __init s3c_init_vic_timer_irq(unsigned int num, unsigned int timer_irq)
{
unsigned int pirq[5] = { IRQ_TIMER0_VIC, IRQ_TIMER1_VIC, IRQ_TIMER2_VIC,
IRQ_TIMER3_VIC, IRQ_TIMER4_VIC };
struct irq_chip_generic *s3c_tgc;
struct irq_chip_type *ct;
unsigned int i;

irq_set_chained_handler(parent_irq, s3c_irq_demux_vic_timer);
irq_set_handler_data(parent_irq, (void *)timer_irq);
s3c_tgc = irq_alloc_generic_chip("s3c-timer", 1, timer_irq,
S3C64XX_TINT_CSTAT, handle_level_irq);
ct = s3c_tgc->chip_types;
ct->chip.irq_mask = irq_gc_mask_clr_bit;
ct->chip.irq_unmask = irq_gc_mask_set_bit;
ct->chip.irq_ack = s3c_irq_timer_ack;
irq_setup_generic_chip(s3c_tgc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
IRQ_NOREQUEST | IRQ_NOPROBE, 0);
/* Clear the upper bits of the mask_cache*/
s3c_tgc->mask_cache &= 0x1f;

irq_set_chip_and_handler(timer_irq, &s3c_irq_timer, handle_level_irq);
irq_set_chip_data(timer_irq, (void *)(1 << (timer_irq - IRQ_TIMER0)));
set_irq_flags(timer_irq, IRQF_VALID);
for (i = 0; i < num; i++, timer_irq++) {
irq_set_chained_handler(pirq[i], s3c_irq_demux_vic_timer);
irq_set_handler_data(pirq[i], (void *)timer_irq);
}
}

0 comments on commit 1cf02bb

Please sign in to comment.