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

Last change on this file since b2ed712 was b2ed712, checked in by Sebastian Huber <sebastian.huber@…>, on Aug 25, 2017 at 8:58:58 AM

Include missing <string.h>

Update #2133.

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