[PATCH 1/6] ARM: OMAP3: Warn about spurious interrupts

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxx>
---
 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 c40fc37..636e282 100644
--- a/arch/arm/mach-omap2/irq.c
+++ b/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);

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux