summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Galvan <martin.galvan@tallertechnologies.com>2016-02-28 00:19:33 +0100
committerBen Gras <ben@minix3.org>2016-02-28 00:23:02 +0100
commit8c5c53f4788eb74264a053f8293fed26da85b764 (patch)
tree89d62ce07b2a2baa2cc0a1301ff2c7da0863a742
parentrtems: Avoid __RTEMS_USE_TICKS_FOR_STATISTICS__ (diff)
downloadrtems-8c5c53f4788eb74264a053f8293fed26da85b764.tar.bz2
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.
-rw-r--r--c/src/lib/libbsp/arm/beagle/irq.c82
-rw-r--r--c/src/lib/libcpu/arm/shared/include/omap3.h3
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 c6485cd79b..d080a5e851 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 f28e5e5406..0cc43d6383 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