source: rtems/c/src/lib/libcpu/bfin/interrupt/interrupt.c @ c499856

4.11
Last change on this file since c499856 was c499856, checked in by Chris Johns <chrisj@…>, on Mar 20, 2014 at 9:10:47 PM

Change all references of rtems.com to rtems.org.

  • Property mode set to 100644
File size: 4.9 KB
Line 
1/*  Support for Blackfin interrupt controller
2 *
3 *  Copyright (c) 2008 Kallisti Labs, Los Gatos, CA, USA
4 *             written by Allan Hessenflow <allanh@kallisti.com>
5 *
6 *  The license and distribution terms for this file may be
7 *  found in the file LICENSE in this distribution or at
8 *  http://www.rtems.org/license/LICENSE.
9 */
10
11
12#include <rtems.h>
13#include <rtems/libio.h>
14
15#include <bsp.h>
16#include <libcpu/cecRegs.h>
17#include <libcpu/sicRegs.h>
18#include "interrupt.h"
19
20
21static struct {
22  uint32_t mask;
23  bfin_isr_t *head;
24} vectors[CEC_INTERRUPT_COUNT];
25
26static uint32_t globalMask;
27
28
29static rtems_isr interruptHandler(rtems_vector_number vector) {
30  bfin_isr_t *isr;
31  uint32_t sourceMask;
32
33  vector -= CEC_INTERRUPT_BASE_VECTOR;
34  if (vector >= 0 && vector < CEC_INTERRUPT_COUNT) {
35    isr = vectors[vector].head;
36    sourceMask = *(uint32_t volatile *) SIC_ISR &
37                 *(uint32_t volatile *) SIC_IMASK;
38    while (isr) {
39      if (sourceMask & isr->mask) {
40        isr->isr(isr->source);
41        sourceMask = *(uint32_t volatile *) SIC_ISR &
42                     *(uint32_t volatile *) SIC_IMASK;
43      }
44      isr = isr->next;
45    }
46  }
47}
48
49void bfin_interrupt_init(void) {
50  int source;
51  int vector;
52  uint32_t r;
53  int i;
54  int j;
55
56  globalMask = ~(uint32_t) 0;
57  *(uint32_t volatile *) SIC_IMASK = 0;
58  memset(vectors, 0, sizeof(vectors));
59  /* build mask showing what SIC sources drive each CEC vector */
60  source = 0;
61  for (i = 0; i < SIC_IAR_COUNT; i++) {
62    r = *(uint32_t volatile *) (SIC_IAR_BASE_ADDRESS + i * SIC_IAR_PITCH);
63    for (j = 0; j < 8; j++) {
64      vector = r & 0x0f;
65      if (vector >= 0 && vector < CEC_INTERRUPT_COUNT) {
66        if (vectors[vector].mask == 0)
67          /* install our local handler */
68          set_vector(interruptHandler, vector + CEC_INTERRUPT_BASE_VECTOR, 1);
69        vectors[vector].mask |= (1 << source);
70      }
71      r >>= 4;
72      source++;
73    }
74  }
75}
76
77/* modify SIC_IMASK based on ISR list for a particular CEC vector */
78static void setMask(int vector) {
79  bfin_isr_t *isr;
80  uint32_t mask;
81  uint32_t r;
82
83  mask = 0;
84  isr = vectors[vector].head;
85  while (isr) {
86    mask |= isr->mask;
87    isr = isr->next;
88  }
89  r = *(uint32_t volatile *) SIC_IMASK;
90  r &= ~vectors[vector].mask;
91  r |= mask;
92  r &= globalMask;
93  *(uint32_t volatile *) SIC_IMASK = r;
94}
95
96/* add an ISR to the list for whichever vector it belongs to */
97void bfin_interrupt_register(bfin_isr_t *isr) {
98  bfin_isr_t *walk;
99  rtems_interrupt_level isrLevel;
100
101  /* find the appropriate vector */
102  for (isr->vector = 0; isr->vector < CEC_INTERRUPT_COUNT; isr->vector++)
103    if (vectors[isr->vector].mask & (1 << isr->source))
104      break;
105  if (isr->vector < CEC_INTERRUPT_COUNT) {
106    isr->next = NULL;
107    isr->mask = 0;
108    rtems_interrupt_disable(isrLevel);
109    /* find the current end of the list */
110    walk = vectors[isr->vector].head;
111    while (walk && walk->next)
112      walk = walk->next;
113    /* append new isr to list */
114    if (walk)
115      walk->next = isr;
116    else
117      vectors[isr->vector].head = isr;
118    rtems_interrupt_enable(isrLevel);
119  } else
120    /* we failed, but make vector a legal value so other calls into
121       this module with this isr descriptor won't do anything bad */
122    isr->vector = 0;
123}
124
125void bfin_interrupt_unregister(bfin_isr_t *isr) {
126  bfin_isr_t *walk, *prev;
127  rtems_interrupt_level isrLevel;
128
129  rtems_interrupt_disable(isrLevel);
130  walk = vectors[isr->vector].head;
131  prev = NULL;
132  /* find this isr in our list */
133  while (walk && walk != isr) {
134    prev = walk;
135    walk = walk->next;
136  }
137  if (walk) {
138    /* if found, remove it */
139    if (prev)
140      prev->next = walk->next;
141    else
142      vectors[isr->vector].head = walk->next;
143    /* fix up SIC_IMASK if necessary */
144    setMask(isr->vector);
145  }
146  rtems_interrupt_enable(isrLevel);
147}
148
149void bfin_interrupt_enable(bfin_isr_t *isr, bool enable) {
150  rtems_interrupt_level isrLevel;
151
152  rtems_interrupt_disable(isrLevel);
153  isr->mask = enable ? (1 << isr->source) : 0;
154  setMask(isr->vector);
155  rtems_interrupt_enable(isrLevel);
156}
157
158void bfin_interrupt_enable_all(int source, bool enable) {
159  rtems_interrupt_level isrLevel;
160  int vector;
161  bfin_isr_t *walk;
162
163  for (vector = 0; vector < CEC_INTERRUPT_COUNT; vector++)
164    if (vectors[vector].mask & (1 << source))
165      break;
166  if (vector < CEC_INTERRUPT_COUNT) {
167    rtems_interrupt_disable(isrLevel);
168    walk = vectors[vector].head;
169    while (walk) {
170      walk->mask = enable ? (1 << source) : 0;
171      walk = walk->next;
172    }
173    setMask(vector);
174    rtems_interrupt_enable(isrLevel);
175  }
176}
177
178void bfin_interrupt_enable_global(int source, bool enable) {
179  int vector;
180  rtems_interrupt_level isrLevel;
181
182  for (vector = 0; vector < CEC_INTERRUPT_COUNT; vector++)
183    if (vectors[vector].mask & (1 << source))
184      break;
185  if (vector < CEC_INTERRUPT_COUNT) {
186    rtems_interrupt_disable(isrLevel);
187    if (enable)
188      globalMask |= 1 << source;
189    else
190      globalMask &= ~(1 << source);
191    setMask(vector);
192    rtems_interrupt_enable(isrLevel);
193  }
194}
195
Note: See TracBrowser for help on using the repository browser.