diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2011-09-06 04:56:17 -0400 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2011-11-15 13:14:02 -0500 |
commit | 2db1499784da653f7e257d98fefdebc65fde7c40 (patch) | |
tree | a7fb2699e1282f96d315df926fb41bf4f49c4dd0 | |
parent | 368b8e252335725ea72d7bcbb3b1c8837b8dfeed (diff) |
ARM: omap2/3: Add global omap2/3_intc_handle_irq() functions
Provide the OMAP2/3 IRQ code with low level handlers that can be used
by platforms using CONFIG_MULTI_IRQ_HANDLER. Though the handlers are
written in C, the compiled code looks very similar to its assembly
counterpart (at least with my gcc 4.4.1).
Tested-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-rw-r--r-- | arch/arm/mach-omap2/irq.c | 50 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/irqs.h | 2 |
2 files changed, 52 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index 65f1be6a182c..ec52bee0e089 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <mach/hardware.h> | 17 | #include <mach/hardware.h> |
18 | #include <asm/exception.h> | ||
18 | #include <asm/mach/irq.h> | 19 | #include <asm/mach/irq.h> |
19 | 20 | ||
20 | 21 | ||
@@ -35,6 +36,11 @@ | |||
35 | /* Number of IRQ state bits in each MIR register */ | 36 | /* Number of IRQ state bits in each MIR register */ |
36 | #define IRQ_BITS_PER_REG 32 | 37 | #define IRQ_BITS_PER_REG 32 |
37 | 38 | ||
39 | #define OMAP2_IRQ_BASE OMAP2_L4_IO_ADDRESS(OMAP24XX_IC_BASE) | ||
40 | #define OMAP3_IRQ_BASE OMAP2_L4_IO_ADDRESS(OMAP34XX_IC_BASE) | ||
41 | #define INTCPS_SIR_IRQ_OFFSET 0x0040 /* omap2/3 active interrupt offset */ | ||
42 | #define ACTIVEIRQ_MASK 0x7f /* omap2/3 active interrupt bits */ | ||
43 | |||
38 | /* | 44 | /* |
39 | * OMAP2 has a number of different interrupt controllers, each interrupt | 45 | * OMAP2 has a number of different interrupt controllers, each interrupt |
40 | * controller is identified as its own "bank". Register definitions are | 46 | * controller is identified as its own "bank". Register definitions are |
@@ -191,6 +197,44 @@ void __init ti816x_init_irq(void) | |||
191 | omap_init_irq(OMAP34XX_IC_BASE, 128); | 197 | omap_init_irq(OMAP34XX_IC_BASE, 128); |
192 | } | 198 | } |
193 | 199 | ||
200 | static inline void omap_intc_handle_irq(void __iomem *base_addr, struct pt_regs *regs) | ||
201 | { | ||
202 | u32 irqnr; | ||
203 | |||
204 | do { | ||
205 | irqnr = readl_relaxed(base_addr + 0x98); | ||
206 | if (irqnr) | ||
207 | goto out; | ||
208 | |||
209 | irqnr = readl_relaxed(base_addr + 0xb8); | ||
210 | if (irqnr) | ||
211 | goto out; | ||
212 | |||
213 | irqnr = readl_relaxed(base_addr + 0xd8); | ||
214 | #ifdef CONFIG_SOC_OMAPTI816X | ||
215 | if (irqnr) | ||
216 | goto out; | ||
217 | irqnr = readl_relaxed(base_addr + 0xf8); | ||
218 | #endif | ||
219 | |||
220 | out: | ||
221 | if (!irqnr) | ||
222 | break; | ||
223 | |||
224 | irqnr = readl_relaxed(base_addr + INTCPS_SIR_IRQ_OFFSET); | ||
225 | irqnr &= ACTIVEIRQ_MASK; | ||
226 | |||
227 | if (irqnr) | ||
228 | handle_IRQ(irqnr, regs); | ||
229 | } while (irqnr); | ||
230 | } | ||
231 | |||
232 | asmlinkage void __exception_irq_entry omap2_intc_handle_irq(struct pt_regs *regs) | ||
233 | { | ||
234 | void __iomem *base_addr = OMAP2_IRQ_BASE; | ||
235 | omap_intc_handle_irq(base_addr, regs); | ||
236 | } | ||
237 | |||
194 | #ifdef CONFIG_ARCH_OMAP3 | 238 | #ifdef CONFIG_ARCH_OMAP3 |
195 | static struct omap3_intc_regs intc_context[ARRAY_SIZE(irq_banks)]; | 239 | static struct omap3_intc_regs intc_context[ARRAY_SIZE(irq_banks)]; |
196 | 240 | ||
@@ -263,4 +307,10 @@ void omap3_intc_resume_idle(void) | |||
263 | /* Re-enable autoidle */ | 307 | /* Re-enable autoidle */ |
264 | intc_bank_write_reg(1, &irq_banks[0], INTC_SYSCONFIG); | 308 | intc_bank_write_reg(1, &irq_banks[0], INTC_SYSCONFIG); |
265 | } | 309 | } |
310 | |||
311 | asmlinkage void __exception_irq_entry omap3_intc_handle_irq(struct pt_regs *regs) | ||
312 | { | ||
313 | void __iomem *base_addr = OMAP3_IRQ_BASE; | ||
314 | omap_intc_handle_irq(base_addr, regs); | ||
315 | } | ||
266 | #endif /* CONFIG_ARCH_OMAP3 */ | 316 | #endif /* CONFIG_ARCH_OMAP3 */ |
diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h index 30e10719b774..8b19a63fab68 100644 --- a/arch/arm/plat-omap/include/plat/irqs.h +++ b/arch/arm/plat-omap/include/plat/irqs.h | |||
@@ -448,6 +448,8 @@ void omap_intc_restore_context(void); | |||
448 | void omap3_intc_suspend(void); | 448 | void omap3_intc_suspend(void); |
449 | void omap3_intc_prepare_idle(void); | 449 | void omap3_intc_prepare_idle(void); |
450 | void omap3_intc_resume_idle(void); | 450 | void omap3_intc_resume_idle(void); |
451 | void omap2_intc_handle_irq(struct pt_regs *regs); | ||
452 | void omap3_intc_handle_irq(struct pt_regs *regs); | ||
451 | #endif | 453 | #endif |
452 | 454 | ||
453 | #include <mach/hardware.h> | 455 | #include <mach/hardware.h> |