From 2d2e1d3c404d7e5bd20d6e1ad910e440eaf6c14d Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 9 May 2011 10:09:26 +0200 Subject: [PATCH] ARM: SAMSUNG: Convert irq-vic-timer to generic irq chip Signed-off-by: Thomas Gleixner Acked-by: Kukjin Kim Signed-off-by: Mark Brown --- arch/arm/mach-s3c64xx/irq.c | 7 +- arch/arm/plat-s5p/irq.c | 6 +- .../plat-samsung/include/plat/irq-vic-timer.h | 2 +- arch/arm/plat-samsung/irq-vic-timer.c | 69 +++++++------------ 4 files changed, 29 insertions(+), 55 deletions(-) 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.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-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) -{ - 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); + } } -- 2.30.2