summaryrefslogtreecommitdiffstats
path: root/c
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-10-02 10:40:35 +0200
commit78627fe2825d19f810c60d4b2a42aea717712d7f (patch)
tree92abe21cda94b951a9ed025c796a6b002b0162bf /c
parentarm/raspberrypi: remove duplicate setup of IRQ handler in the main ARM except... (diff)
downloadrtems-78627fe2825d19f810c60d4b2a42aea717712d7f.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. Updates #2783
Diffstat (limited to 'c')
-rw-r--r--c/src/lib/libbsp/arm/raspberrypi/include/irq.h4
-rw-r--r--c/src/lib/libbsp/arm/raspberrypi/irq/irq.c133
2 files changed, 94 insertions, 43 deletions
diff --git a/c/src/lib/libbsp/arm/raspberrypi/include/irq.h b/c/src/lib/libbsp/arm/raspberrypi/include/irq.h
index 7ccfd3bf31..22ee29beb1 100644
--- a/c/src/lib/libbsp/arm/raspberrypi/include/irq.h
+++ b/c/src/lib/libbsp/arm/raspberrypi/include/irq.h
@@ -51,11 +51,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 ce5b363f5d..e654d077c9 100644
--- a/c/src/lib/libbsp/arm/raspberrypi/irq/irq.c
+++ b/c/src/lib/libbsp/arm/raspberrypi/irq/irq.c
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file irq.c
*
* @ingroup raspberrypi_interrupt
*
@@ -7,6 +7,8 @@
*/
/*
+ * Copyright (c) 2014 Andre Marques <andre.lousa.marques at gmail.com>
+ *
* Copyright (c) 2009
* embedded brains GmbH
* Obere Lagerstr. 30
@@ -27,78 +29,123 @@
#include <bsp/raspberrypi.h>
#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 */
+};
/*
-** Determine the source of the interrupt and dispatch the correct handler.
-*/
+ * 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.
+ */
void bsp_interrupt_dispatch(void)
{
- rtems_vector_number vector = 255;
+ unsigned int pend;
+ unsigned int pend_bit;
- /* ARM timer */
- if (BCM2835_REG(BCM2835_IRQ_BASIC) && 0x1)
- {
- vector = BCM2835_IRQ_ID_TIMER_0;
+ rtems_vector_number vector = 255;
- }
- /* UART 0 */
- else if ( BCM2835_REG(BCM2835_IRQ_BASIC) && BCM2835_BIT(19))
- {
- vector = BCM2835_IRQ_ID_UART;
+ 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 )
{
bsp_interrupt_handler_dispatch(vector);
}
-
}
rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
{
- rtems_interrupt_level level;
-
- rtems_interrupt_disable(level);
+ if ( vector > BSP_INTERRUPT_VECTOR_MAX )
+ return RTEMS_INVALID_ID;
- /* 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);
-
- }
- 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;
+ if ( vector > BSP_INTERRUPT_VECTOR_MAX )
+ return RTEMS_INVALID_ID;
- 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);
- }
- rtems_interrupt_enable(level);
+ BCM2835_REG(bsp_vector_to_reg(vector)->disable_reg_addr) =
+ bsp_vector_to_mask(vector);
return RTEMS_SUCCESSFUL;
}
-
void bsp_interrupt_handler_default(rtems_vector_number vector)
{
- printk("spurious interrupt: %u\n", vector);
+ printk("spurious interrupt: %lu\n", vector);
}
rtems_status_code bsp_interrupt_facility_initialize(void)