[rtems commit] am335x irq handling improvement

Ben Gras beng at rtems.org
Sat Feb 27 23:25:49 UTC 2016


Module:    rtems
Branch:    master
Commit:    8c5c53f4788eb74264a053f8293fed26da85b764
Changeset: http://git.rtems.org/rtems/commit/?id=8c5c53f4788eb74264a053f8293fed26da85b764

Author:    Martin Galvan <martin.galvan at tallertechnologies.com>
Date:      Sun Feb 28 00:19:33 2016 +0100

am335x irq handling improvement

This patch makes the following changes to the Beaglebone IRQ handling code:

- Disable support for nested interrupts.
- Detect spurious IRQs using the SPURIOUSIRQ field of the INTC_SIR_IRQ register.
- Acknowledge spurious IRQs by setting the NewIRQAgr bit of the INTC_CONTROL
  register. This cleans the SPURIOUSIRQ field and allows new interrupts
  to be generated.
- Improve the get_mir_reg function a bit.

Closes #2580.

---

 c/src/lib/libbsp/arm/beagle/irq.c           | 82 +++++++++++++++--------------
 c/src/lib/libcpu/arm/shared/include/omap3.h |  3 +-
 2 files changed, 44 insertions(+), 41 deletions(-)

diff --git a/c/src/lib/libbsp/arm/beagle/irq.c b/c/src/lib/libbsp/arm/beagle/irq.c
index c6485cd..d080a5e 100644
--- a/c/src/lib/libbsp/arm/beagle/irq.c
+++ b/c/src/lib/libbsp/arm/beagle/irq.c
@@ -18,6 +18,7 @@
 #include <bsp.h>
 #include <bsp/irq-generic.h>
 #include <bsp/linker-symbols.h>
+#include <bsp/fatal.h>
 
 #include <rtems/score/armv4.h>
 
@@ -43,77 +44,78 @@ static struct omap_intr omap_intr = {
 };
 #endif
 
-static int irqs_enabled[BSP_INTERRUPT_VECTOR_MAX+1];
+/* Enables interrupts at the Interrupt Controller side. */
+static inline void omap_irq_ack(void)
+{
+  mmio_write(omap_intr.base + OMAP3_INTCPS_CONTROL, OMAP3_INTR_NEWIRQAGR);
 
-volatile static int level = 0;
+  /* Flush data cache to make sure all the previous writes are done
+     before re-enabling interrupts. */
+  flush_data_cache();
+}
 
 void bsp_interrupt_dispatch(void)
 {
-  /* get irq */
-  uint32_t reg = mmio_read(omap_intr.base + OMAP3_INTCPS_SIR_IRQ);
-  int irq;
-  irq = reg & OMAP3_INTR_ACTIVEIRQ_MASK;
+  const uint32_t reg = mmio_read(omap_intr.base + OMAP3_INTCPS_SIR_IRQ);
 
-  if(!irqs_enabled[irq]) {
-	/* Ignore spurious interrupt */
-  } else {
-    bsp_interrupt_vector_disable(irq);
-
-    /* enable new interrupts, and flush data cache to make sure
-     * it hits the intc
-     */
-    mmio_write(omap_intr.base + OMAP3_INTCPS_CONTROL, OMAP3_INTR_NEWIRQAGR);
-    flush_data_cache();
-    mmio_read(omap_intr.base + OMAP3_INTCPS_SIR_IRQ);
-    flush_data_cache();
-
-    /* keep current irq masked but enable unmasked ones */
-    uint32_t psr = _ARMV4_Status_irq_enable();
-    bsp_interrupt_handler_dispatch(irq);
-
-    _ARMV4_Status_restore(psr);
+  if ((reg & OMAP3_INTR_SPURIOUSIRQ_MASK) != OMAP3_INTR_SPURIOUSIRQ_MASK) {
+    const rtems_vector_number irq = reg & OMAP3_INTR_ACTIVEIRQ_MASK;
 
-    bsp_interrupt_vector_enable(irq);
+    bsp_interrupt_handler_dispatch(irq);
+  } else {
+    /* Ignore spurious interrupts. We'll still ACK it so new interrupts
+       can be generated. */
   }
+
+  omap_irq_ack();
 }
 
-static uint32_t get_mir_reg(int vector, uint32_t *mask)
+/* There are 4 32-bit interrupt mask registers for a total of 128 interrupts.
+   The IRQ number tells us which register to use. */
+static uint32_t omap_get_mir_reg(rtems_vector_number vector, uint32_t *const mask)
 {
-  *mask = 1UL << (vector % 32);
-
-  if(vector <   0) while(1) ;
-  if(vector <  32) return OMAP3_INTCPS_MIR0;
-  if(vector <  64) return OMAP3_INTCPS_MIR1;
-  if(vector <  96) return OMAP3_INTCPS_MIR2;
-  if(vector < 128) return OMAP3_INTCPS_MIR3;
-  while(1) ;
+  uint32_t mir_reg;
+
+  /* Select which bit to set/clear in the MIR register. */
+  *mask = 1ul << (vector % 32u);
+
+  if (vector < 32u) {
+    mir_reg = OMAP3_INTCPS_MIR0;
+  } else if (vector < 64u) {
+    mir_reg = OMAP3_INTCPS_MIR1;
+  } else if (vector < 96u) {
+    mir_reg = OMAP3_INTCPS_MIR2;
+  } else if (vector < 128u) {
+    mir_reg = OMAP3_INTCPS_MIR3;
+  } else {
+    /* Invalid IRQ number. This should never happen. */
+    bsp_fatal(0);
+  }
+
+  return mir_reg;
 }
 
 rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
 {
   uint32_t mask, cur;
-  uint32_t mir_reg = get_mir_reg(vector, &mask);
+  uint32_t mir_reg = omap_get_mir_reg(vector, &mask);
 
   cur = mmio_read(omap_intr.base + mir_reg);
   mmio_write(omap_intr.base + mir_reg, cur & ~mask);
   flush_data_cache();
 
-  irqs_enabled[vector] = 1;
-
   return RTEMS_SUCCESSFUL;
 }
 
 rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
 {
   uint32_t mask, cur;
-  uint32_t mir_reg = get_mir_reg(vector, &mask);
+  uint32_t mir_reg = omap_get_mir_reg(vector, &mask);
 
   cur = mmio_read(omap_intr.base + mir_reg);
   mmio_write(omap_intr.base + mir_reg, cur | mask);
   flush_data_cache();
 
-  irqs_enabled[vector] = 0;
-
   return RTEMS_SUCCESSFUL;
 }
 
diff --git a/c/src/lib/libcpu/arm/shared/include/omap3.h b/c/src/lib/libcpu/arm/shared/include/omap3.h
index f28e5e5..0cc43d6 100644
--- a/c/src/lib/libcpu/arm/shared/include/omap3.h
+++ b/c/src/lib/libcpu/arm/shared/include/omap3.h
@@ -72,7 +72,8 @@
 #define OMAP3_INTR_ILR(base,m) \
     (base + OMAP3_INTCPS_ILR0 + 0x4 * (m))
 
-#define OMAP3_INTR_ACTIVEIRQ_MASK 0x7f /* Active IRQ mask for SIR_IRQ */
+#define OMAP3_INTR_SPURIOUSIRQ_MASK (0x1FFFFFF << 7) /* Spurious IRQ mask for SIR_IRQ */
+#define OMAP3_INTR_ACTIVEIRQ_MASK 0x7F /* Active IRQ mask for SIR_IRQ */
 #define OMAP3_INTR_NEWIRQAGR      0x1  /* New IRQ Generation */
 
 #define OMAP3_DM337X_NR_IRQ_VECTORS    96




More information about the vc mailing list