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

5
Last change on this file since c6810c8 was c6810c8, checked in by Sebastian Huber <sebastian.huber@…>, on 06/19/17 at 12:09:28

bsps: Improve interrupt vector enable/disable API

Change bsp_interrupt_vector_enable() and bsp_interrupt_vector_disable()
to not return a status code. Add bsp_interrupt_assert() and use it to
validate the vector number in the vector enable/disable implementations.

  • Property mode set to 100644
File size: 4.4 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
35#ifdef RTEMS_SMP
36#include <rtems/score/smp.h>
37#include <rtems/score/smpimpl.h>
38#endif
39
40typedef struct {
41  unsigned long enable_reg_addr;
42  unsigned long disable_reg_addr;
43} bcm2835_irq_ctrl_reg_t;
44
45static const bcm2835_irq_ctrl_reg_t bcm2835_irq_ctrl_reg_table[] = {
46  { BCM2835_IRQ_ENABLE1, BCM2835_IRQ_DISABLE1 },
47  { BCM2835_IRQ_ENABLE2, BCM2835_IRQ_DISABLE2 },
48  { BCM2835_IRQ_ENABLE_BASIC, BCM2835_IRQ_DISABLE_BASIC }
49};
50
51static inline const bcm2835_irq_ctrl_reg_t *
52bsp_vector_to_reg(rtems_vector_number vector)
53{
54  return bcm2835_irq_ctrl_reg_table + (vector >> 5);
55}
56
57static inline uint32_t
58bsp_vector_to_mask(rtems_vector_number vector)
59{
60  return 1 << (vector & 0x1f);
61}
62
63static const int bcm2835_irq_speedup_table[] =
64{
65  /*  0 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  0,
66  /*  1 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  1,
67  /*  2 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  2,
68  /*  3 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  3,
69  /*  4 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  4,
70  /*  5 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  5,
71  /*  6 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  6,
72  /*  7 */ BCM2835_IRQ_ID_BASIC_BASE_ID +  7,
73  /*  8 */ -1, /* One or more bits set in pending register 1 */
74  /*  9 */ -2, /* One or more bits set in pending register 2 */
75  /* 10 */  7, /* GPU IRQ 7 */
76  /* 11 */  9, /* GPU IRQ 9 */
77  /* 12 */ 10, /* GPU IRQ 10 */
78  /* 13 */ 18, /* GPU IRQ 18 */
79  /* 14 */ 19, /* GPU IRQ 19 */
80  /* 15 */ 53, /* GPU IRQ 53 */
81  /* 16 */ 54, /* GPU IRQ 54 */
82  /* 17 */ 55, /* GPU IRQ 55 */
83  /* 18 */ 56, /* GPU IRQ 56 */
84  /* 19 */ 57, /* GPU IRQ 57 */
85  /* 20 */ 62, /* GPU IRQ 62 */
86};
87
88/*
89 * Define which basic peding register (BCM2835_IRQ_BASIC) bits
90 * should be processed through bcm2835_irq_speedup_table
91 */
92
93#define BCM2835_IRQ_BASIC_SPEEDUP_USED_BITS 0x1ffcff
94
95/*
96 * Determine the source of the interrupt and dispatch the correct handler.
97 */
98void bsp_interrupt_dispatch(void)
99{
100  unsigned int pend;
101  unsigned int pend_bit;
102
103  rtems_vector_number vector = 255;
104
105#ifdef RTEMS_SMP
106  uint32_t cpu_index_self = _SMP_Get_current_processor();
107  uint32_t local_source = BCM2835_REG(BCM2836_IRQ_SOURCE_REG(cpu_index_self));
108
109  if ( local_source & BCM2836_IRQ_SOURCE_MBOX3 ) {
110    /* reset mailbox 3 contents to zero */
111    BCM2835_REG(BCM2836_MAILBOX_3_READ_CLEAR_BASE + 0x10 * cpu_index_self) = 0xffffffff;
112    _SMP_Inter_processor_interrupt_handler();
113  }
114  if ( cpu_index_self != 0 )
115    return;
116#endif /* RTEMS_SMP */
117
118  pend = BCM2835_REG(BCM2835_IRQ_BASIC);
119  if ( pend & BCM2835_IRQ_BASIC_SPEEDUP_USED_BITS ) {
120    pend_bit = ffs(pend) - 1;
121    vector = bcm2835_irq_speedup_table[pend_bit];
122  } else {
123    pend = BCM2835_REG(BCM2835_IRQ_PENDING1);
124    if ( pend != 0 ) {
125      pend_bit = ffs(pend) - 1;
126      vector = pend_bit;
127    } else {
128      pend = BCM2835_REG(BCM2835_IRQ_PENDING2);
129      if ( pend != 0 ) {
130        pend_bit = ffs(pend) - 1;
131        vector = pend_bit + 32;
132      }
133    }
134  }
135
136  if ( vector < 255 )
137  {
138      bsp_interrupt_handler_dispatch(vector);
139  }
140}
141
142void bsp_interrupt_vector_enable(rtems_vector_number vector)
143{
144  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
145  BCM2835_REG(bsp_vector_to_reg(vector)->enable_reg_addr) =
146              bsp_vector_to_mask(vector);
147}
148
149void bsp_interrupt_vector_disable(rtems_vector_number vector)
150{
151  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
152  BCM2835_REG(bsp_vector_to_reg(vector)->disable_reg_addr) =
153              bsp_vector_to_mask(vector);
154}
155
156void bsp_interrupt_handler_default(rtems_vector_number vector)
157{
158    printk("spurious interrupt: %lu\n", vector);
159}
160
161rtems_status_code bsp_interrupt_facility_initialize(void)
162{
163   BCM2835_REG(BCM2835_IRQ_DISABLE1) = 0xffffffff;
164   BCM2835_REG(BCM2835_IRQ_DISABLE2) = 0xffffffff;
165   BCM2835_REG(BCM2835_IRQ_DISABLE_BASIC) = 0xffffffff;
166   BCM2835_REG(BCM2835_IRQ_FIQ_CTRL) = 0;
167   return RTEMS_SUCCESSFUL;
168}
Note: See TracBrowser for help on using the repository browser.