summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavel Pisa <pisa@cmp.felk.cvut.cz>2016-07-23 12:10:34 +0200
committerPavel Pisa <pisa@cmp.felk.cvut.cz>2016-07-23 12:10:34 +0200
commitd216c5d6a2325551accb836429a6ac9cc2b2f4b7 (patch)
tree9094c3d919b14410ad7206f5068591e5737f60f9
parentarm/raspberrypi: remove duplicate setup of IRQ handler in the main ARM except... (diff)
downloadrtems-d216c5d6a2325551accb836429a6ac9cc2b2f4b7.tar.bz2
arm/raspberrypi: change interrupt dispatch and enable to generic vector id based approach.
Using conditional branches to find bits is extremely inefficient and for asynchronous delivery of different interrupt sources lead to total confusion of branch prediction unit.
-rw-r--r--c/src/lib/libbsp/arm/raspberrypi/include/irq.h4
-rw-r--r--c/src/lib/libbsp/arm/raspberrypi/irq/irq.c226
2 files changed, 89 insertions, 141 deletions
diff --git a/c/src/lib/libbsp/arm/raspberrypi/include/irq.h b/c/src/lib/libbsp/arm/raspberrypi/include/irq.h
index 9825097c5b..b55e264c51 100644
--- a/c/src/lib/libbsp/arm/raspberrypi/include/irq.h
+++ b/c/src/lib/libbsp/arm/raspberrypi/include/irq.h
@@ -52,11 +52,15 @@
#define BCM2835_IRQ_ID_UART 57
+#define BCM2835_IRQ_ID_BASIC_BASE_ID 64
#define BCM2835_IRQ_ID_TIMER_0 64
#define BCM2835_IRQ_ID_MAILBOX_0 65
#define BCM2835_IRQ_ID_DOORBELL_0 66
#define BCM2835_IRQ_ID_DOORBELL_1 67
#define BCM2835_IRQ_ID_GPU0_HALTED 68
+#define BCM2835_IRQ_ID_GPU1_HALTED 69
+#define BCM2835_IRQ_ID_ILL_ACCESS_1 70
+#define BCM2835_IRQ_ID_ILL_ACCESS_0 71
#define BSP_INTERRUPT_VECTOR_MIN (0)
#define BSP_INTERRUPT_VECTOR_MAX (BCM2835_INTC_TOTAL_IRQ - 1)
diff --git a/c/src/lib/libbsp/arm/raspberrypi/irq/irq.c b/c/src/lib/libbsp/arm/raspberrypi/irq/irq.c
index 86e2716e04..e654d077c9 100644
--- a/c/src/lib/libbsp/arm/raspberrypi/irq/irq.c
+++ b/c/src/lib/libbsp/arm/raspberrypi/irq/irq.c
@@ -30,55 +30,89 @@
#include <bsp/linker-symbols.h>
#include <bsp/mmu.h>
#include <rtems/bspIo.h>
+#include <strings.h>
+
+typedef struct {
+ unsigned long enable_reg_addr;
+ unsigned long disable_reg_addr;
+} bcm2835_irq_ctrl_reg_t;
+
+static const bcm2835_irq_ctrl_reg_t bcm2835_irq_ctrl_reg_table[] = {
+ { BCM2835_IRQ_ENABLE1, BCM2835_IRQ_DISABLE1 },
+ { BCM2835_IRQ_ENABLE2, BCM2835_IRQ_DISABLE2 },
+ { BCM2835_IRQ_ENABLE_BASIC, BCM2835_IRQ_DISABLE_BASIC }
+};
+
+static inline const bcm2835_irq_ctrl_reg_t *
+bsp_vector_to_reg(rtems_vector_number vector)
+{
+ return bcm2835_irq_ctrl_reg_table + (vector >> 5);
+}
+
+static inline uint32_t
+bsp_vector_to_mask(rtems_vector_number vector)
+{
+ return 1 << (vector & 0x1f);
+}
+
+static const int bcm2835_irq_speedup_table[] =
+{
+ /* 0 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 0,
+ /* 1 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 1,
+ /* 2 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 2,
+ /* 3 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 3,
+ /* 4 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 4,
+ /* 5 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 5,
+ /* 6 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 6,
+ /* 7 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 7,
+ /* 8 */ -1, /* One or more bits set in pending register 1 */
+ /* 9 */ -2, /* One or more bits set in pending register 2 */
+ /* 10 */ 7, /* GPU IRQ 7 */
+ /* 11 */ 9, /* GPU IRQ 9 */
+ /* 12 */ 10, /* GPU IRQ 10 */
+ /* 13 */ 18, /* GPU IRQ 18 */
+ /* 14 */ 19, /* GPU IRQ 19 */
+ /* 15 */ 53, /* GPU IRQ 53 */
+ /* 16 */ 54, /* GPU IRQ 54 */
+ /* 17 */ 55, /* GPU IRQ 55 */
+ /* 18 */ 56, /* GPU IRQ 56 */
+ /* 19 */ 57, /* GPU IRQ 57 */
+ /* 20 */ 62, /* GPU IRQ 62 */
+};
+
+/*
+ * Define which basic peding register (BCM2835_IRQ_BASIC) bits
+ * should be processed through bcm2835_irq_speedup_table
+ */
+
+#define BCM2835_IRQ_BASIC_SPEEDUP_USED_BITS 0x1ffcff
/*
-** Determine the source of the interrupt and dispatch the correct handler.
-*/
+ * Determine the source of the interrupt and dispatch the correct handler.
+ */
void bsp_interrupt_dispatch(void)
{
+ unsigned int pend;
+ unsigned int pend_bit;
+
rtems_vector_number vector = 255;
- /* ARM timer */
- if ( BCM2835_REG(BCM2835_IRQ_BASIC) & 0x1 )
- {
- vector = BCM2835_IRQ_ID_TIMER_0;
- }
- /* UART 0 */
- else if ( BCM2835_REG(BCM2835_IRQ_BASIC) & BCM2835_BIT(19) )
- {
- vector = BCM2835_IRQ_ID_UART;
- }
- /* GPIO 0*/
- else if ( BCM2835_REG(BCM2835_IRQ_PENDING2) & BCM2835_BIT(17) )
- {
- vector = BCM2835_IRQ_ID_GPIO_0;
- }
- else if ( BCM2835_REG(BCM2835_IRQ_PENDING2) & BCM2835_BIT(18) )
- {
- vector = BCM2835_IRQ_ID_GPIO_1;
- }
- else if ( BCM2835_REG(BCM2835_IRQ_PENDING2) & BCM2835_BIT(19) )
- {
- vector = BCM2835_IRQ_ID_GPIO_2;
- }
- else if ( BCM2835_REG(BCM2835_IRQ_PENDING2) & BCM2835_BIT(20) )
- {
- vector = BCM2835_IRQ_ID_GPIO_3;
- }
- /* I2C */
- else if ( BCM2835_REG(BCM2835_IRQ_PENDING2) & BCM2835_BIT(21) )
- {
- vector = BCM2835_IRQ_ID_I2C;
- }
- /* SPI */
- else if ( BCM2835_REG(BCM2835_IRQ_PENDING2) & BCM2835_BIT(22) )
- {
- vector = BCM2835_IRQ_ID_SPI;
- }
- /* USB */
- else if ( BCM2835_REG(BCM2835_IRQ_PENDING1) & BCM2835_BIT(9) )
- {
- vector = BCM2835_IRQ_ID_USB;
+ pend = BCM2835_REG(BCM2835_IRQ_BASIC);
+ if ( pend & BCM2835_IRQ_BASIC_SPEEDUP_USED_BITS ) {
+ pend_bit = ffs(pend) - 1;
+ vector = bcm2835_irq_speedup_table[pend_bit];
+ } else {
+ pend = BCM2835_REG(BCM2835_IRQ_PENDING1);
+ if ( pend != 0 ) {
+ pend_bit = ffs(pend) - 1;
+ vector = pend_bit;
+ } else {
+ pend = BCM2835_REG(BCM2835_IRQ_PENDING2);
+ if ( pend != 0 ) {
+ pend_bit = ffs(pend) - 1;
+ vector = pend_bit + 32;
+ }
+ }
}
if ( vector < 255 )
@@ -89,112 +123,22 @@ void bsp_interrupt_dispatch(void)
rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
{
- rtems_interrupt_level level;
+ if ( vector > BSP_INTERRUPT_VECTOR_MAX )
+ return RTEMS_INVALID_ID;
- rtems_interrupt_disable(level);
-
- /* ARM Timer */
- if ( vector == BCM2835_IRQ_ID_TIMER_0 )
- {
- BCM2835_REG(BCM2835_IRQ_ENABLE_BASIC) = 0x1;
- }
- /* UART 0 */
- else if ( vector == BCM2835_IRQ_ID_UART )
- {
- BCM2835_REG(BCM2835_IRQ_ENABLE2) = BCM2835_BIT(25);
- }
- /* GPIO 0 */
- else if ( vector == BCM2835_IRQ_ID_GPIO_0 )
- {
- BCM2835_REG(BCM2835_IRQ_ENABLE2) = BCM2835_BIT(17);
- }
- /* GPIO 1 */
- else if ( vector == BCM2835_IRQ_ID_GPIO_1 )
- {
- BCM2835_REG(BCM2835_IRQ_ENABLE2) = BCM2835_BIT(18);
- }
- /* GPIO 2 */
- else if ( vector == BCM2835_IRQ_ID_GPIO_2 )
- {
- BCM2835_REG(BCM2835_IRQ_ENABLE2) = BCM2835_BIT(19);
- }
- /* GPIO 3 */
- else if ( vector == BCM2835_IRQ_ID_GPIO_3 )
- {
- BCM2835_REG(BCM2835_IRQ_ENABLE2) = BCM2835_BIT(20);
- }
- /* I2C */
- else if ( vector == BCM2835_IRQ_ID_I2C )
- {
- BCM2835_REG(BCM2835_IRQ_ENABLE2) = BCM2835_BIT(21);
- }
- /* SPI */
- else if ( vector == BCM2835_IRQ_ID_SPI )
- {
- BCM2835_REG(BCM2835_IRQ_ENABLE2) = BCM2835_BIT(22);
- }
- /* USB */
- else if ( vector == BCM2835_IRQ_ID_USB )
- {
- BCM2835_REG(BCM2835_IRQ_ENABLE1) = BCM2835_BIT(9);
- }
-
- rtems_interrupt_enable(level);
+ BCM2835_REG(bsp_vector_to_reg(vector)->enable_reg_addr) =
+ bsp_vector_to_mask(vector);
return RTEMS_SUCCESSFUL;
}
rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
{
- rtems_interrupt_level level;
-
- rtems_interrupt_disable(level);
-
- if ( vector == BCM2835_IRQ_ID_TIMER_0 )
- {
- BCM2835_REG(BCM2835_IRQ_DISABLE_BASIC) = 0x1;
- }
- else if ( vector == BCM2835_IRQ_ID_UART )
- {
- BCM2835_REG(BCM2835_IRQ_DISABLE2) = BCM2835_BIT(25);
- }
- /* GPIO 0 */
- else if ( vector == BCM2835_IRQ_ID_GPIO_0 )
- {
- BCM2835_REG(BCM2835_IRQ_DISABLE2) = BCM2835_BIT(17);
- }
- /* GPIO 1 */
- else if ( vector == BCM2835_IRQ_ID_GPIO_1 )
- {
- BCM2835_REG(BCM2835_IRQ_DISABLE2) = BCM2835_BIT(18);
- }
- /* GPIO 2 */
- else if ( vector == BCM2835_IRQ_ID_GPIO_2 )
- {
- BCM2835_REG(BCM2835_IRQ_DISABLE2) = BCM2835_BIT(19);
- }
- /* GPIO 3 */
- else if ( vector == BCM2835_IRQ_ID_GPIO_3 )
- {
- BCM2835_REG(BCM2835_IRQ_DISABLE2) = BCM2835_BIT(20);
- }
- /* I2C */
- else if ( vector == BCM2835_IRQ_ID_I2C )
- {
- BCM2835_REG(BCM2835_IRQ_DISABLE2) = BCM2835_BIT(21);
- }
- /* SPI */
- else if ( vector == BCM2835_IRQ_ID_SPI )
- {
- BCM2835_REG(BCM2835_IRQ_DISABLE2) = BCM2835_BIT(22);
- }
- /* USB */
- else if ( vector == BCM2835_IRQ_ID_USB )
- {
- BCM2835_REG(BCM2835_IRQ_DISABLE1) = BCM2835_BIT(9);
- }
+ if ( vector > BSP_INTERRUPT_VECTOR_MAX )
+ return RTEMS_INVALID_ID;
- rtems_interrupt_enable(level);
+ BCM2835_REG(bsp_vector_to_reg(vector)->disable_reg_addr) =
+ bsp_vector_to_mask(vector);
return RTEMS_SUCCESSFUL;
}