diff options
author | Tony Lindgren <tony@atomide.com> | 2008-12-10 20:36:52 -0500 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2008-12-10 20:36:52 -0500 |
commit | 6ccc4c0dedf8cc63bf4f7c0cfa1b72c4a5fae148 (patch) | |
tree | 06c73419e0e8ed509c371052b5e02f8199140cd2 /arch/arm | |
parent | 64ce2907b1966593d3b4ce5396adb17d7348637d (diff) |
ARM: OMAP3: Warn about spurious interrupts
In the case of spurious interrupt, the handler for previous interrupt
handler needs to flush posted writes with a read back of the interrupt
ack register. Warn about handlers that need to flush posted writes.
Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-omap2/irq.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index c40fc378a251..636e2821af7d 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #define INTC_REVISION 0x0000 | 23 | #define INTC_REVISION 0x0000 |
24 | #define INTC_SYSCONFIG 0x0010 | 24 | #define INTC_SYSCONFIG 0x0010 |
25 | #define INTC_SYSSTATUS 0x0014 | 25 | #define INTC_SYSSTATUS 0x0014 |
26 | #define INTC_SIR 0x0040 | ||
26 | #define INTC_CONTROL 0x0048 | 27 | #define INTC_CONTROL 0x0048 |
27 | #define INTC_MIR_CLEAR0 0x0088 | 28 | #define INTC_MIR_CLEAR0 0x0088 |
28 | #define INTC_MIR_SET0 0x008c | 29 | #define INTC_MIR_SET0 0x008c |
@@ -60,6 +61,30 @@ static u32 intc_bank_read_reg(struct omap_irq_bank *bank, u16 reg) | |||
60 | return __raw_readl(bank->base_reg + reg); | 61 | return __raw_readl(bank->base_reg + reg); |
61 | } | 62 | } |
62 | 63 | ||
64 | static int previous_irq; | ||
65 | |||
66 | /* | ||
67 | * On 34xx we can get occasional spurious interrupts if the ack from | ||
68 | * an interrupt handler does not get posted before we unmask. Warn about | ||
69 | * the interrupt handlers that need to flush posted writes. | ||
70 | */ | ||
71 | static int omap_check_spurious(unsigned int irq) | ||
72 | { | ||
73 | u32 sir, spurious; | ||
74 | |||
75 | sir = intc_bank_read_reg(&irq_banks[0], INTC_SIR); | ||
76 | spurious = sir >> 6; | ||
77 | |||
78 | if (spurious > 1) { | ||
79 | printk(KERN_WARNING "Spurious irq %i: 0x%08x, please flush " | ||
80 | "posted write for irq %i\n", | ||
81 | irq, sir, previous_irq); | ||
82 | return spurious; | ||
83 | } | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
63 | /* XXX: FIQ and additional INTC support (only MPU at the moment) */ | 88 | /* XXX: FIQ and additional INTC support (only MPU at the moment) */ |
64 | static void omap_ack_irq(unsigned int irq) | 89 | static void omap_ack_irq(unsigned int irq) |
65 | { | 90 | { |
@@ -70,6 +95,20 @@ static void omap_mask_irq(unsigned int irq) | |||
70 | { | 95 | { |
71 | int offset = irq & (~(IRQ_BITS_PER_REG - 1)); | 96 | int offset = irq & (~(IRQ_BITS_PER_REG - 1)); |
72 | 97 | ||
98 | if (cpu_is_omap34xx()) { | ||
99 | int spurious = 0; | ||
100 | |||
101 | /* | ||
102 | * INT_34XX_GPT12_IRQ is also the spurious irq. Maybe because | ||
103 | * it is the highest irq number? | ||
104 | */ | ||
105 | if (irq == INT_34XX_GPT12_IRQ) | ||
106 | spurious = omap_check_spurious(irq); | ||
107 | |||
108 | if (!spurious) | ||
109 | previous_irq = irq; | ||
110 | } | ||
111 | |||
73 | irq &= (IRQ_BITS_PER_REG - 1); | 112 | irq &= (IRQ_BITS_PER_REG - 1); |
74 | 113 | ||
75 | intc_bank_write_reg(1 << irq, &irq_banks[0], INTC_MIR_SET0 + offset); | 114 | intc_bank_write_reg(1 << irq, &irq_banks[0], INTC_MIR_SET0 + offset); |