aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-samsung/irq-vic-timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-samsung/irq-vic-timer.c')
-rw-r--r--arch/arm/plat-samsung/irq-vic-timer.c69
1 files changed, 26 insertions, 43 deletions
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)
28} 28}
29 29
30/* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */ 30/* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */
31 31static void s3c_irq_timer_ack(struct irq_data *d)
32static void s3c_irq_timer_mask(struct irq_data *data)
33{
34 u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
35 u32 mask = (u32)data->chip_data;
36
37 reg &= 0x1f; /* mask out pending interrupts */
38 reg &= ~mask;
39 __raw_writel(reg, S3C64XX_TINT_CSTAT);
40}
41
42static void s3c_irq_timer_unmask(struct irq_data *data)
43{ 32{
44 u32 reg = __raw_readl(S3C64XX_TINT_CSTAT); 33 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
45 u32 mask = (u32)data->chip_data; 34 u32 mask = (1 << 5) << (d->irq - gc->irq_base);
46 35
47 reg &= 0x1f; /* mask out pending interrupts */ 36 irq_reg_writel(mask | gc->mask_cache, gc->reg_base);
48 reg |= mask;
49 __raw_writel(reg, S3C64XX_TINT_CSTAT);
50} 37}
51 38
52static void s3c_irq_timer_ack(struct irq_data *data)
53{
54 u32 reg = __raw_readl(S3C64XX_TINT_CSTAT);
55 u32 mask = (u32)data->chip_data;
56
57 reg &= 0x1f;
58 reg |= mask << 5;
59 __raw_writel(reg, S3C64XX_TINT_CSTAT);
60}
61
62static struct irq_chip s3c_irq_timer = {
63 .name = "s3c-timer",
64 .irq_mask = s3c_irq_timer_mask,
65 .irq_unmask = s3c_irq_timer_unmask,
66 .irq_ack = s3c_irq_timer_ack,
67};
68
69/** 39/**
70 * s3c_init_vic_timer_irq() - initialise timer irq chanined off VIC.\ 40 * s3c_init_vic_timer_irq() - initialise timer irq chanined off VIC.\
71 * @parent_irq: The parent IRQ on the VIC for the timer. 41 * @num: Number of timers to initialize
72 * @timer_irq: The IRQ to be used for the timer. 42 * @timer_irq: Base IRQ number to be used for the timers.
73 * 43 *
74 * Register the necessary IRQ chaining and support for the timer IRQs 44 * Register the necessary IRQ chaining and support for the timer IRQs
75 * chained of the VIC. 45 * chained of the VIC.
76 */ 46 */
77void __init s3c_init_vic_timer_irq(unsigned int parent_irq, 47void __init s3c_init_vic_timer_irq(unsigned int num, unsigned int timer_irq)
78 unsigned int timer_irq)
79{ 48{
49 unsigned int pirq[5] = { IRQ_TIMER0_VIC, IRQ_TIMER1_VIC, IRQ_TIMER2_VIC,
50 IRQ_TIMER3_VIC, IRQ_TIMER4_VIC };
51 struct irq_chip_generic *s3c_tgc;
52 struct irq_chip_type *ct;
53 unsigned int i;
80 54
81 irq_set_chained_handler(parent_irq, s3c_irq_demux_vic_timer); 55 s3c_tgc = irq_alloc_generic_chip("s3c-timer", 1, timer_irq,
82 irq_set_handler_data(parent_irq, (void *)timer_irq); 56 S3C64XX_TINT_CSTAT, handle_level_irq);
57 ct = s3c_tgc->chip_types;
58 ct->chip.irq_mask = irq_gc_mask_clr_bit;
59 ct->chip.irq_unmask = irq_gc_mask_set_bit;
60 ct->chip.irq_ack = s3c_irq_timer_ack;
61 irq_setup_generic_chip(s3c_tgc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
62 IRQ_NOREQUEST | IRQ_NOPROBE, 0);
63 /* Clear the upper bits of the mask_cache*/
64 s3c_tgc->mask_cache &= 0x1f;
83 65
84 irq_set_chip_and_handler(timer_irq, &s3c_irq_timer, handle_level_irq); 66 for (i = 0; i < num; i++, timer_irq++) {
85 irq_set_chip_data(timer_irq, (void *)(1 << (timer_irq - IRQ_TIMER0))); 67 irq_set_chained_handler(pirq[i], s3c_irq_demux_vic_timer);
86 set_irq_flags(timer_irq, IRQF_VALID); 68 irq_set_handler_data(pirq[i], (void *)timer_irq);
69 }
87} 70}