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

4.104.115
Last change on this file since c193baad was 359e537, checked in by Ralf Corsepius <ralf.corsepius@…>, on 11/30/09 at 05:09:41

Whitespace removal.

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