Commit | Line | Data |
---|---|---|
7162ba03 BD |
1 | /* arch/arm/plat-samsung/irq-vic-timer.c |
2 | * originally part of arch/arm/plat-s3c64xx/irq.c | |
3 | * | |
4 | * Copyright 2008 Openmoko, Inc. | |
5 | * Copyright 2008 Simtec Electronics | |
6 | * Ben Dooks <ben@simtec.co.uk> | |
7 | * http://armlinux.simtec.co.uk/ | |
8 | * | |
9 | * S3C64XX - Interrupt handling | |
10 | * | |
11 | * This program is free software; you can redistribute it and/or modify | |
12 | * it under the terms of the GNU General Public License version 2 as | |
13 | * published by the Free Software Foundation. | |
14 | */ | |
15 | ||
16 | #include <linux/kernel.h> | |
17 | #include <linux/interrupt.h> | |
18 | #include <linux/irq.h> | |
19 | #include <linux/io.h> | |
20 | ||
21 | #include <mach/map.h> | |
22 | #include <plat/irq-vic-timer.h> | |
23 | #include <plat/regs-timer.h> | |
24 | ||
995b528a MS |
25 | #include <asm/mach/irq.h> |
26 | ||
7162ba03 BD |
27 | static void s3c_irq_demux_vic_timer(unsigned int irq, struct irq_desc *desc) |
28 | { | |
995b528a MS |
29 | struct irq_chip *chip = irq_get_chip(irq); |
30 | chained_irq_enter(chip, desc); | |
04ea1cc8 | 31 | generic_handle_irq((int)desc->irq_data.handler_data); |
995b528a | 32 | chained_irq_exit(chip, desc); |
7162ba03 BD |
33 | } |
34 | ||
35 | /* We assume the IRQ_TIMER0..IRQ_TIMER4 range is continuous. */ | |
2d2e1d3c | 36 | static void s3c_irq_timer_ack(struct irq_data *d) |
7162ba03 | 37 | { |
2d2e1d3c TG |
38 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
39 | u32 mask = (1 << 5) << (d->irq - gc->irq_base); | |
7162ba03 | 40 | |
2d2e1d3c | 41 | irq_reg_writel(mask | gc->mask_cache, gc->reg_base); |
7162ba03 BD |
42 | } |
43 | ||
7162ba03 BD |
44 | /** |
45 | * s3c_init_vic_timer_irq() - initialise timer irq chanined off VIC.\ | |
2d2e1d3c TG |
46 | * @num: Number of timers to initialize |
47 | * @timer_irq: Base IRQ number to be used for the timers. | |
7162ba03 BD |
48 | * |
49 | * Register the necessary IRQ chaining and support for the timer IRQs | |
50 | * chained of the VIC. | |
51 | */ | |
2d2e1d3c | 52 | void __init s3c_init_vic_timer_irq(unsigned int num, unsigned int timer_irq) |
7162ba03 | 53 | { |
2d2e1d3c TG |
54 | unsigned int pirq[5] = { IRQ_TIMER0_VIC, IRQ_TIMER1_VIC, IRQ_TIMER2_VIC, |
55 | IRQ_TIMER3_VIC, IRQ_TIMER4_VIC }; | |
56 | struct irq_chip_generic *s3c_tgc; | |
57 | struct irq_chip_type *ct; | |
58 | unsigned int i; | |
7162ba03 | 59 | |
2d2e1d3c TG |
60 | s3c_tgc = irq_alloc_generic_chip("s3c-timer", 1, timer_irq, |
61 | S3C64XX_TINT_CSTAT, handle_level_irq); | |
691abd0a TP |
62 | |
63 | if (!s3c_tgc) { | |
64 | pr_err("%s: irq_alloc_generic_chip for IRQ %d failed\n", | |
65 | __func__, timer_irq); | |
66 | return; | |
67 | } | |
68 | ||
2d2e1d3c TG |
69 | ct = s3c_tgc->chip_types; |
70 | ct->chip.irq_mask = irq_gc_mask_clr_bit; | |
71 | ct->chip.irq_unmask = irq_gc_mask_set_bit; | |
72 | ct->chip.irq_ack = s3c_irq_timer_ack; | |
73 | irq_setup_generic_chip(s3c_tgc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, | |
74 | IRQ_NOREQUEST | IRQ_NOPROBE, 0); | |
75 | /* Clear the upper bits of the mask_cache*/ | |
76 | s3c_tgc->mask_cache &= 0x1f; | |
7162ba03 | 77 | |
2d2e1d3c TG |
78 | for (i = 0; i < num; i++, timer_irq++) { |
79 | irq_set_chained_handler(pirq[i], s3c_irq_demux_vic_timer); | |
80 | irq_set_handler_data(pirq[i], (void *)timer_irq); | |
81 | } | |
7162ba03 | 82 | } |