source: rtems/c/src/lib/libbsp/arm/raspberrypi/irq/irq.c @ d216c5d6

5
Last change on this file since d216c5d6 was d216c5d6, checked in by Pavel Pisa <pisa@…>, on 07/23/16 at 10:10:34

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.

  • Property mode set to 100644
File size: 4.0 KB
Line 
1/**
2 * @file irq.c
3 *
4 * @ingroup raspberrypi_interrupt
5 *
6 * @brief Interrupt support.
7 */
8
9/*
10 * Copyright (c) 2014 Andre Marques <andre.lousa.marques at gmail.com>
11 *
12 * Copyright (c) 2009
13 * embedded brains GmbH
14 * Obere Lagerstr. 30
15 * D-82178 Puchheim
16 * Germany
17 * <rtems@embedded-brains.de>
18 *
19 * The license and distribution terms for this file may be
20 * found in the file LICENSE in this distribution or at
21 * http://www.rtems.org/license/LICENSE.
22 */
23
24#include <rtems/score/armv4.h>
25
26#include <bsp.h>
27#include <bsp/irq.h>
28#include <bsp/irq-generic.h>
29#include <bsp/raspberrypi.h>
30#include <bsp/linker-symbols.h>
31#include <bsp/mmu.h>
32#include <rtems/bspIo.h>
33#include <strings.h>
34
35typedef struct {
36  unsigned long enable_reg_addr;
37  unsigned long disable_reg_addr;
38} bcm2835_irq_ctrl_reg_t;
39
40static const bcm2835_irq_ctrl_reg_t bcm2835_irq_ctrl_reg_table[] = {
41  { BCM2835_IRQ_ENABLE1, BCM2835_IRQ_DISABLE1 },
42  { BCM2835_IRQ_ENABLE2, BCM2835_IRQ_DISABLE2 },
43  { BCM2835_IRQ_ENABLE_BASIC, BCM2835_IRQ_DISABLE_BASIC }
44};
45
46static inline const bcm2835_irq_ctrl_reg_t *
47bsp_vector_to_reg(rtems_vector_number vector)
48{
49  return bcm2835_irq_ctrl_reg_table + (vector >> 5);
50}
51
52static inline uint32_t
53bsp_vector_to_mask(rtems_vector_number vector)
54{
55  return 1 << (vector & 0x1f);
56}
57
58static const int bcm2835_irq_speedup_table[] =
59{
60  /*  0 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  0,
61  /*  1 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  1,
62  /*  2 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  2,
63  /*  3 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  3,
64  /*  4 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  4,
65  /*  5 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  5,
66  /*  6 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  6,
67  /*  7 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  7,
68  /*  8 */ -1, /* One or more bits set in pending register 1 */
69  /*  9 */ -2, /* One or more bits set in pending register 2 */
70  /* 10 */  7, /* GPU IRQ 7 */
71  /* 11 */  9, /* GPU IRQ 9 */
72  /* 12 */ 10, /* GPU IRQ 10 */
73  /* 13 */ 18, /* GPU IRQ 18 */
74  /* 14 */ 19, /* GPU IRQ 19 */
75  /* 15 */ 53, /* GPU IRQ 53 */
76  /* 16 */ 54, /* GPU IRQ 54 */
77  /* 17 */ 55, /* GPU IRQ 55 */
78  /* 18 */ 56, /* GPU IRQ 56 */
79  /* 19 */ 57, /* GPU IRQ 57 */
80  /* 20 */ 62, /* GPU IRQ 62 */
81};
82
83/*
84 * Define which basic peding register (BCM2835_IRQ_BASIC) bits
85 * should be processed through bcm2835_irq_speedup_table
86 */
87
88#define BCM2835_IRQ_BASIC_SPEEDUP_USED_BITS 0x1ffcff
89
90/*
91 * Determine the source of the interrupt and dispatch the correct handler.
92 */
93void bsp_interrupt_dispatch(void)
94{
95  unsigned int pend;
96  unsigned int pend_bit;
97
98  rtems_vector_number vector = 255;
99
100  pend = BCM2835_REG(BCM2835_IRQ_BASIC);
101  if ( pend & BCM2835_IRQ_BASIC_SPEEDUP_USED_BITS ) {
102    pend_bit = ffs(pend) - 1;
103    vector = bcm2835_irq_speedup_table[pend_bit];
104  } else {
105    pend = BCM2835_REG(BCM2835_IRQ_PENDING1);
106    if ( pend != 0 ) {
107      pend_bit = ffs(pend) - 1;
108      vector = pend_bit;
109    } else {
110      pend = BCM2835_REG(BCM2835_IRQ_PENDING2);
111      if ( pend != 0 ) {
112        pend_bit = ffs(pend) - 1;
113        vector = pend_bit + 32;
114      }
115    }
116  }
117
118  if ( vector < 255 )
119  {
120      bsp_interrupt_handler_dispatch(vector);
121  }
122}
123
124rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
125{
126  if ( vector > BSP_INTERRUPT_VECTOR_MAX )
127    return RTEMS_INVALID_ID;
128
129  BCM2835_REG(bsp_vector_to_reg(vector)->enable_reg_addr) =
130              bsp_vector_to_mask(vector);
131
132  return RTEMS_SUCCESSFUL;
133}
134
135rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
136{
137  if ( vector > BSP_INTERRUPT_VECTOR_MAX )
138    return RTEMS_INVALID_ID;
139
140  BCM2835_REG(bsp_vector_to_reg(vector)->disable_reg_addr) =
141              bsp_vector_to_mask(vector);
142
143  return RTEMS_SUCCESSFUL;
144}
145
146void bsp_interrupt_handler_default(rtems_vector_number vector)
147{
148    printk("spurious interrupt: %lu\n", vector);
149}
150
151rtems_status_code bsp_interrupt_facility_initialize(void)
152{
153   BCM2835_REG(BCM2835_IRQ_DISABLE1) = 0xffffffff;
154   BCM2835_REG(BCM2835_IRQ_DISABLE2) = 0xffffffff;
155   BCM2835_REG(BCM2835_IRQ_DISABLE_BASIC) = 0xffffffff;
156   BCM2835_REG(BCM2835_IRQ_FIQ_CTRL) = 0;
157   return RTEMS_SUCCESSFUL;
158}
Note: See TracBrowser for help on using the repository browser.