diff --git a/arch/arm/mach-s3c64xx/irq.c b/arch/arm/mach-s3c64xx/irq.c index 67a145d440f3..97660c8141ae 100644 --- a/arch/arm/mach-s3c64xx/irq.c +++ b/arch/arm/mach-s3c64xx/irq.c @@ -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)); } diff --git a/arch/arm/plat-s5p/irq-gpioint.c b/arch/arm/plat-s5p/irq-gpioint.c index cd6d67c8382a..135abda31c9a 100644 --- a/arch/arm/plat-s5p/irq-gpioint.c +++ b/arch/arm/plat-s5p/irq-gpioint.c @@ -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: @@ -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); @@ -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; @@ -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; } diff --git a/arch/arm/plat-s5p/irq.c b/arch/arm/plat-s5p/irq.c index 5560b12035d1..a97c08957f49 100644 --- a/arch/arm/plat-s5p/irq.c +++ b/arch/arm/plat-s5p/irq.c @@ -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)); } diff --git a/arch/arm/plat-samsung/include/plat/irq-vic-timer.h b/arch/arm/plat-samsung/include/plat/irq-vic-timer.h index a90b53431b5b..5b9c42fd32d7 100644 --- a/arch/arm/plat-samsung/include/plat/irq-vic-timer.h +++ b/arch/arm/plat-samsung/include/plat/irq-vic-timer.h @@ -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); diff --git a/arch/arm/plat-samsung/irq-uart.c b/arch/arm/plat-samsung/irq-uart.c index 4d4e571af553..32582c0958e3 100644 --- a/arch/arm/plat-samsung/irq-uart.c +++ b/arch/arm/plat-samsung/irq-uart.c @@ -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; @@ -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); diff --git a/arch/arm/plat-samsung/irq-vic-timer.c b/arch/arm/plat-samsung/irq-vic-timer.c index d6ad66ab9290..a607546ddbd0 100644 --- a/arch/arm/plat-samsung/irq-vic-timer.c +++ b/arch/arm/plat-samsung/irq-vic-timer.c @@ -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) +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_unmask(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_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); + } }