From a9273cc4d413be875b18969abc8ef99ad9ce17e1 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 10 Dec 2008 17:36:52 -0800 Subject: [PATCH] --- yaml --- r: 123741 b: refs/heads/master c: 6ccc4c0dedf8cc63bf4f7c0cfa1b72c4a5fae148 h: refs/heads/master i: 123739: ebff1f4f67feefe420cd5c0e8723655ff4016aec v: v3 --- [refs] | 2 +- trunk/arch/arm/mach-omap2/irq.c | 39 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index 101fccb0aa9f..9553de0803d7 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 64ce2907b1966593d3b4ce5396adb17d7348637d +refs/heads/master: 6ccc4c0dedf8cc63bf4f7c0cfa1b72c4a5fae148 diff --git a/trunk/arch/arm/mach-omap2/irq.c b/trunk/arch/arm/mach-omap2/irq.c index c40fc378a251..636e2821af7d 100644 --- a/trunk/arch/arm/mach-omap2/irq.c +++ b/trunk/arch/arm/mach-omap2/irq.c @@ -23,6 +23,7 @@ #define INTC_REVISION 0x0000 #define INTC_SYSCONFIG 0x0010 #define INTC_SYSSTATUS 0x0014 +#define INTC_SIR 0x0040 #define INTC_CONTROL 0x0048 #define INTC_MIR_CLEAR0 0x0088 #define INTC_MIR_SET0 0x008c @@ -60,6 +61,30 @@ static u32 intc_bank_read_reg(struct omap_irq_bank *bank, u16 reg) return __raw_readl(bank->base_reg + reg); } +static int previous_irq; + +/* + * On 34xx we can get occasional spurious interrupts if the ack from + * an interrupt handler does not get posted before we unmask. Warn about + * the interrupt handlers that need to flush posted writes. + */ +static int omap_check_spurious(unsigned int irq) +{ + u32 sir, spurious; + + sir = intc_bank_read_reg(&irq_banks[0], INTC_SIR); + spurious = sir >> 6; + + if (spurious > 1) { + printk(KERN_WARNING "Spurious irq %i: 0x%08x, please flush " + "posted write for irq %i\n", + irq, sir, previous_irq); + return spurious; + } + + return 0; +} + /* XXX: FIQ and additional INTC support (only MPU at the moment) */ static void omap_ack_irq(unsigned int irq) { @@ -70,6 +95,20 @@ static void omap_mask_irq(unsigned int irq) { int offset = irq & (~(IRQ_BITS_PER_REG - 1)); + if (cpu_is_omap34xx()) { + int spurious = 0; + + /* + * INT_34XX_GPT12_IRQ is also the spurious irq. Maybe because + * it is the highest irq number? + */ + if (irq == INT_34XX_GPT12_IRQ) + spurious = omap_check_spurious(irq); + + if (!spurious) + previous_irq = irq; + } + irq &= (IRQ_BITS_PER_REG - 1); intc_bank_write_reg(1 << irq, &irq_banks[0], INTC_MIR_SET0 + offset);