aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/common/vic.c38
-rw-r--r--arch/arm/include/asm/hardware/vic.h3
2 files changed, 41 insertions, 0 deletions
diff --git a/arch/arm/common/vic.c b/arch/arm/common/vic.c
index a227a7d53700..0a69547e0312 100644
--- a/arch/arm/common/vic.c
+++ b/arch/arm/common/vic.c
@@ -31,6 +31,7 @@
31#include <linux/device.h> 31#include <linux/device.h>
32#include <linux/amba/bus.h> 32#include <linux/amba/bus.h>
33 33
34#include <asm/exception.h>
34#include <asm/mach/irq.h> 35#include <asm/mach/irq.h>
35#include <asm/hardware/vic.h> 36#include <asm/hardware/vic.h>
36 37
@@ -428,3 +429,40 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent)
428 return -EIO; 429 return -EIO;
429} 430}
430#endif /* CONFIG OF */ 431#endif /* CONFIG OF */
432
433#ifdef CONFIG_MULTI_IRQ_HANDLER
434/*
435 * Handle each interrupt in a single VIC. Returns non-zero if we've
436 * handled at least one interrupt. This does a single read of the
437 * status register and handles all interrupts in order from LSB first.
438 */
439static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
440{
441 u32 stat, irq;
442 int handled = 0;
443
444 stat = readl_relaxed(vic->base + VIC_IRQ_STATUS);
445 while (stat) {
446 irq = ffs(stat) - 1;
447 handle_IRQ(irq_domain_to_irq(&vic->domain, irq), regs);
448 stat &= ~(1 << irq);
449 handled = 1;
450 }
451
452 return handled;
453}
454
455/*
456 * Keep iterating over all registered VIC's until there are no pending
457 * interrupts.
458 */
459asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs)
460{
461 int i, handled;
462
463 do {
464 for (i = 0, handled = 0; i < vic_id; ++i)
465 handled |= handle_one_vic(&vic_devices[i], regs);
466 } while (handled);
467}
468#endif /* CONFIG_MULTI_IRQ_HANDLER */
diff --git a/arch/arm/include/asm/hardware/vic.h b/arch/arm/include/asm/hardware/vic.h
index b348a545de23..f42ebd619590 100644
--- a/arch/arm/include/asm/hardware/vic.h
+++ b/arch/arm/include/asm/hardware/vic.h
@@ -45,8 +45,11 @@
45#include <linux/types.h> 45#include <linux/types.h>
46 46
47struct device_node; 47struct device_node;
48struct pt_regs;
49
48void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources); 50void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
49int vic_of_init(struct device_node *node, struct device_node *parent); 51int vic_of_init(struct device_node *node, struct device_node *parent);
52void vic_handle_irq(struct pt_regs *regs);
50 53
51#endif /* __ASSEMBLY__ */ 54#endif /* __ASSEMBLY__ */
52#endif 55#endif