1 | /** |
---|
2 | *@file interrupt.c |
---|
3 | * |
---|
4 | *@brief |
---|
5 | * - This file implements interrupt dispatcher. Most of the code is taken from |
---|
6 | * the 533 implementation for blackfin. Since 52X supports 56 line and 2 ISR |
---|
7 | * registers some portion is written twice. |
---|
8 | * |
---|
9 | * Target: TLL6527v1-0 |
---|
10 | * Compiler: |
---|
11 | * |
---|
12 | * COPYRIGHT (c) 2010 by ECE Northeastern University. |
---|
13 | * |
---|
14 | * The license and distribution terms for this file may be |
---|
15 | * found in the file LICENSE in this distribution or at |
---|
16 | * http://www.rtems.org/license |
---|
17 | * |
---|
18 | * @author Rohan Kangralkar, ECE, Northeastern University |
---|
19 | * (kangralkar.r@husky.neu.edu) |
---|
20 | * |
---|
21 | * LastChange: |
---|
22 | */ |
---|
23 | |
---|
24 | #include <rtems.h> |
---|
25 | #include <rtems/libio.h> |
---|
26 | |
---|
27 | #include <bsp.h> |
---|
28 | #include <libcpu/cecRegs.h> |
---|
29 | #include <libcpu/sicRegs.h> |
---|
30 | #include <string.h> |
---|
31 | #include <bsp/interrupt.h> |
---|
32 | |
---|
33 | #define SIC_IAR_COUNT_SET0 4 |
---|
34 | #define SIC_IAR_BASE_ADDRESS_0 0xFFC00150 |
---|
35 | |
---|
36 | /** |
---|
37 | * There are two implementations for the interrupt handler. |
---|
38 | * 1. INTERRUPT_USE_TABLE: uses tables for finding the right ISR. |
---|
39 | * 2. Uses link list to find the user ISR. |
---|
40 | * |
---|
41 | * |
---|
42 | * 1. INTERRUPT_USE_TABLE |
---|
43 | * Space requirement: |
---|
44 | * - Array to hold CEC masks size: CEC_INTERRUPT_COUNT(9)*(2*int).9*2*4= 72B |
---|
45 | * - Array to hold isr function pointers IRQ_MAX(56)*sizeof(bfin_isr_t)= 896B |
---|
46 | * - Array for bit twidlling 32 bytes. |
---|
47 | * - Global Mask 8 bytes. |
---|
48 | * - Total = 1008 Bytes Aprox |
---|
49 | * |
---|
50 | * Time requirements |
---|
51 | * The worst case time is about the same for jumping to the user ISR. With a |
---|
52 | * variance of one conditional statement. |
---|
53 | * |
---|
54 | * 2. Using link list. |
---|
55 | * Space requirement: |
---|
56 | * - Array to hold CEC mask CEC_INTERRUPT_COUNT(9)*(sizeof(vectors)). |
---|
57 | * 9*3*4= 108B |
---|
58 | * - Array to hold isr IRQ_MAX(56)*sizeof(bfin_isr_t) The structure has |
---|
59 | * additional pointers 56*7*4=1568B |
---|
60 | * - Global Mask 8 bytes. |
---|
61 | * Total = 1684. |
---|
62 | * Time requirements |
---|
63 | * In the worst case all the lines can be on one CEC line to 56 entries have |
---|
64 | * to be traversed to find the right user ISR. |
---|
65 | * But this implementation has benefit of being flexible, Providing |
---|
66 | * additional user assigned priority. and may consume less space |
---|
67 | * if all devices are not supported. |
---|
68 | */ |
---|
69 | |
---|
70 | /** |
---|
71 | * TODO: To place the dispatcher routine code in L1. |
---|
72 | */ |
---|
73 | |
---|
74 | #if INTERRUPT_USE_TABLE |
---|
75 | |
---|
76 | |
---|
77 | /****************************************************************************** |
---|
78 | * Static variables |
---|
79 | *****************************************************************************/ |
---|
80 | /** |
---|
81 | * @var sic_isr0_mask |
---|
82 | * @brief copy of the mask of SIC ISR. The SIC ISR is cleared by the device |
---|
83 | * the relevant SIC_ISRx bit is not cleared unless the interrupt |
---|
84 | * service routine clears the mechanism that generated interrupt |
---|
85 | */ |
---|
86 | static uint32_t sic_isr0_mask = 0; |
---|
87 | |
---|
88 | /** |
---|
89 | * @var sic_isr0_mask |
---|
90 | * @brief copy of the mask of SIC ISR. The SIC ISR is cleared by the device |
---|
91 | * the relevant SIC_ISRx bit is not cleared unless the interrupt |
---|
92 | * service routine clears the mechanism that generated interrupt |
---|
93 | */ |
---|
94 | static uint32_t sic_isr1_mask = 0; |
---|
95 | |
---|
96 | |
---|
97 | /** |
---|
98 | * @var sic_isr |
---|
99 | * @brief An array of sic register mask for each of the 16 core interrupt lines |
---|
100 | */ |
---|
101 | static struct { |
---|
102 | uint32_t mask0; |
---|
103 | uint32_t mask1; |
---|
104 | } vectors[CEC_INTERRUPT_COUNT]; |
---|
105 | |
---|
106 | /** |
---|
107 | * @var ivt |
---|
108 | * @brief Contains a table of ISR and arguments. The ISR jumps directly to |
---|
109 | * these ISR. |
---|
110 | */ |
---|
111 | static bfin_isr_t ivt[IRQ_MAX]; |
---|
112 | |
---|
113 | /** |
---|
114 | * http://graphics.stanford.edu/~seander/bithacks.html for more details |
---|
115 | */ |
---|
116 | static const char clz_table[32] = |
---|
117 | { |
---|
118 | 0, 31, 9, 30, 3, 8, 18, 29, 2, 5, 7, 14, 12, 17, |
---|
119 | 22, 28, 1, 10, 4, 19, 6, 15, 13, 23, 11, 20, 16, |
---|
120 | 24, 21, 25, 26, 27 |
---|
121 | }; |
---|
122 | |
---|
123 | /** |
---|
124 | * finds the first bit set from the left. look at |
---|
125 | * http://graphics.stanford.edu/~seander/bithacks.html for more details |
---|
126 | * @param n |
---|
127 | * @return |
---|
128 | */ |
---|
129 | static unsigned long clz(unsigned long n) |
---|
130 | { |
---|
131 | unsigned long c = 0x7dcd629; /* magic constant... */ |
---|
132 | |
---|
133 | n |= (n >> 1); |
---|
134 | n |= (n >> 2); |
---|
135 | n |= (n >> 4); |
---|
136 | n |= (n >> 8); |
---|
137 | n |= (n >> 16); |
---|
138 | if (n == 0) return 32; |
---|
139 | n = c + (c * n); |
---|
140 | return 31 - clz_table[n >> 27]; /* For little endian */ |
---|
141 | } |
---|
142 | |
---|
143 | |
---|
144 | |
---|
145 | /** |
---|
146 | * Centralized Interrupt dispatcher routine. This routine dispatches interrupts |
---|
147 | * to the user ISR. The priority is according to the blackfin SIC. |
---|
148 | * The first level of priority is handled in the hardware at the core event |
---|
149 | * controller. The second level of interrupt is handled according to the line |
---|
150 | * number that goes in to the SIC. |
---|
151 | * * SIC_0 has higher priority than SIC 1. |
---|
152 | * * Inside the SIC the priority is assigned according to the line number. |
---|
153 | * Lower the line number higher the priority. |
---|
154 | * |
---|
155 | * In order to change the interrupt priority we may |
---|
156 | * 1. change the SIC IAR registers or |
---|
157 | * 2. Assign priority and extract it inside this function and call the ISR |
---|
158 | * according tot the priority. |
---|
159 | * |
---|
160 | * @param vector IVG number. |
---|
161 | * @return |
---|
162 | */ |
---|
163 | static rtems_isr interruptHandler(rtems_vector_number vector) { |
---|
164 | uint32_t mask = 0; |
---|
165 | int id = 0; |
---|
166 | /** |
---|
167 | * Enable for debugging |
---|
168 | * |
---|
169 | * static volatile uint32_t spurious_sic0 = 0; |
---|
170 | * static volatile uint32_t spurious_source = 0; |
---|
171 | * static volatile uint32_t spurious_sic1 = 0; |
---|
172 | */ |
---|
173 | |
---|
174 | /** |
---|
175 | * Extract the vector number relative to the SIC start line |
---|
176 | */ |
---|
177 | vector -= CEC_INTERRUPT_BASE_VECTOR; |
---|
178 | |
---|
179 | /** |
---|
180 | * Check for bounds |
---|
181 | */ |
---|
182 | if (vector >= 0 && vector < CEC_INTERRUPT_COUNT) { |
---|
183 | |
---|
184 | /** |
---|
185 | * Extract information and execute ISR from SIC 0 |
---|
186 | */ |
---|
187 | mask = *(uint32_t volatile *) SIC_ISR & |
---|
188 | *(uint32_t volatile *) SIC_IMASK & vectors[vector].mask0; |
---|
189 | id = clz(mask); |
---|
190 | if ( SIC_ISR0_MAX > id ) { |
---|
191 | /** Parameter check */ |
---|
192 | if( NULL != ivt[id].pFunc) { |
---|
193 | /** Call the relevant function with argument */ |
---|
194 | ivt[id].pFunc( ivt[id].pArg ); |
---|
195 | } else { |
---|
196 | /** |
---|
197 | * spurious interrupt we should not be getting this |
---|
198 | * spurious_sic0++; |
---|
199 | * spurious_source = id; |
---|
200 | */ |
---|
201 | } |
---|
202 | } else { |
---|
203 | /** |
---|
204 | * we look at SIC 1 |
---|
205 | */ |
---|
206 | } |
---|
207 | |
---|
208 | |
---|
209 | /** |
---|
210 | * Extract information and execute ISR from SIC 1 |
---|
211 | */ |
---|
212 | mask = *(uint32_t volatile *) (SIC_ISR + SIC_ISR_PITCH) & |
---|
213 | *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH) & |
---|
214 | vectors[vector].mask1; |
---|
215 | id = clz(mask)+SIC_ISR0_MAX; |
---|
216 | if ( IRQ_MAX > id ) { |
---|
217 | /** Parameter Check */ |
---|
218 | if( NULL != ivt[id].pFunc ) { |
---|
219 | /** Call the relevant function with argument */ |
---|
220 | ivt[id].pFunc( ivt[id].pArg ); |
---|
221 | } else { |
---|
222 | /** |
---|
223 | * spurious interrupt we should not be getting this |
---|
224 | * |
---|
225 | * spurious_sic1++; |
---|
226 | * spurious_source = id; |
---|
227 | */ |
---|
228 | } |
---|
229 | } else { |
---|
230 | /** |
---|
231 | * we continue |
---|
232 | */ |
---|
233 | } |
---|
234 | |
---|
235 | } |
---|
236 | } |
---|
237 | |
---|
238 | |
---|
239 | |
---|
240 | /** |
---|
241 | * This routine registers a new ISR. It will write a new entry to the IVT table |
---|
242 | * @param isr contains a callback function and source |
---|
243 | * @return rtems status code |
---|
244 | */ |
---|
245 | rtems_status_code bfin_interrupt_register(bfin_isr_t *isr) { |
---|
246 | rtems_interrupt_level isrLevel; |
---|
247 | int id = 0; |
---|
248 | int position = 0; |
---|
249 | |
---|
250 | /** |
---|
251 | * Sanity Check |
---|
252 | */ |
---|
253 | if ( NULL == isr ){ |
---|
254 | return RTEMS_UNSATISFIED; |
---|
255 | } |
---|
256 | |
---|
257 | /** |
---|
258 | * Sanity check. The register function should at least provide callback func |
---|
259 | */ |
---|
260 | if ( NULL == isr->pFunc ) { |
---|
261 | return RTEMS_UNSATISFIED; |
---|
262 | } |
---|
263 | |
---|
264 | id = isr->source; |
---|
265 | |
---|
266 | /** |
---|
267 | * Parameter Check. We already have a function registered here. First |
---|
268 | * unregister and then a new function can be allocated. |
---|
269 | */ |
---|
270 | if ( NULL != ivt[id].pFunc ) { |
---|
271 | return RTEMS_UNSATISFIED; |
---|
272 | } |
---|
273 | |
---|
274 | rtems_interrupt_disable(isrLevel); |
---|
275 | /** |
---|
276 | * Assign the new function pointer to the ISR Dispatcher |
---|
277 | * */ |
---|
278 | ivt[id].pFunc = isr->pFunc; |
---|
279 | ivt[id].pArg = isr->pArg; |
---|
280 | |
---|
281 | |
---|
282 | /** find out which isr mask has to be set to enable the interrupt */ |
---|
283 | if ( SIC_ISR0_MAX > id ) { |
---|
284 | sic_isr0_mask |= 0x1<<id; |
---|
285 | *(uint32_t volatile *) SIC_IMASK |= 0x1<<id; |
---|
286 | } else { |
---|
287 | position = id - SIC_ISR0_MAX; |
---|
288 | sic_isr1_mask |= 0x1<<position; |
---|
289 | *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH) |= 0x1<<position; |
---|
290 | } |
---|
291 | |
---|
292 | rtems_interrupt_enable(isrLevel); |
---|
293 | |
---|
294 | return RTEMS_SUCCESSFUL; |
---|
295 | } |
---|
296 | |
---|
297 | |
---|
298 | /** |
---|
299 | * This function unregisters a registered interrupt handler. |
---|
300 | * @param isr |
---|
301 | */ |
---|
302 | rtems_status_code bfin_interrupt_unregister(bfin_isr_t *isr) { |
---|
303 | rtems_interrupt_level isrLevel; |
---|
304 | int id = 0; |
---|
305 | int position = 0; |
---|
306 | |
---|
307 | /** |
---|
308 | * Sanity Check |
---|
309 | */ |
---|
310 | if ( NULL == isr ){ |
---|
311 | return RTEMS_UNSATISFIED; |
---|
312 | } |
---|
313 | |
---|
314 | id = isr->source; |
---|
315 | |
---|
316 | rtems_interrupt_disable(isrLevel); |
---|
317 | /** |
---|
318 | * Assign the new function pointer to the ISR Dispatcher |
---|
319 | * */ |
---|
320 | ivt[id].pFunc = NULL; |
---|
321 | ivt[id].pArg = NULL; |
---|
322 | |
---|
323 | |
---|
324 | /** find out which isr mask has to be set to enable the interrupt */ |
---|
325 | if ( SIC_ISR0_MAX > id ) { |
---|
326 | sic_isr0_mask &= ~(0x1<<id); |
---|
327 | *(uint32_t volatile *) SIC_IMASK &= ~(0x1<<id); |
---|
328 | } else { |
---|
329 | position = id - SIC_ISR0_MAX; |
---|
330 | sic_isr1_mask &= ~(0x1<<position); |
---|
331 | *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH) &= ~(0x1<<position); |
---|
332 | } |
---|
333 | |
---|
334 | rtems_interrupt_enable(isrLevel); |
---|
335 | |
---|
336 | return RTEMS_SUCCESSFUL; |
---|
337 | } |
---|
338 | |
---|
339 | |
---|
340 | |
---|
341 | |
---|
342 | /** |
---|
343 | * blackfin interrupt initialization routine. It initializes the bfin ISR |
---|
344 | * dispatcher. It will also create SIC CEC map which will be used for |
---|
345 | * identifying the ISR. |
---|
346 | */ |
---|
347 | void bfin_interrupt_init(void) { |
---|
348 | int source; |
---|
349 | int vector; |
---|
350 | uint32_t r; |
---|
351 | int i; |
---|
352 | int j; |
---|
353 | |
---|
354 | *(uint32_t volatile *) SIC_IMASK = 0; |
---|
355 | *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH) = 0; |
---|
356 | |
---|
357 | memset(vectors, 0, sizeof(vectors)); |
---|
358 | /* build mask0 showing what SIC sources drive each CEC vector */ |
---|
359 | source = 0; |
---|
360 | |
---|
361 | /** |
---|
362 | * The bf52x has 8 IAR registers but they do not have a constant pitch. |
---|
363 | * |
---|
364 | */ |
---|
365 | for (i = 0; i < SIC_IAR_COUNT; i++) { |
---|
366 | if ( SIC_IAR_COUNT_SET0 > i ) { |
---|
367 | r = *(uint32_t volatile *) (SIC_IAR_BASE_ADDRESS + i * SIC_IAR_PITCH); |
---|
368 | } else { |
---|
369 | r = *(uint32_t volatile *) (SIC_IAR_BASE_ADDRESS_0 + |
---|
370 | ((i-SIC_IAR_COUNT_SET0) * SIC_IAR_PITCH)); |
---|
371 | } |
---|
372 | |
---|
373 | for (j = 0; j < 8; j++) { |
---|
374 | vector = r & 0x0f; |
---|
375 | if (vector >= 0 && vector < CEC_INTERRUPT_COUNT) { |
---|
376 | /* install our local handler */ |
---|
377 | if (vectors[vector].mask0 == 0 && vectors[vector].mask1 == 0){ |
---|
378 | set_vector(interruptHandler, vector + CEC_INTERRUPT_BASE_VECTOR, 1); |
---|
379 | } |
---|
380 | if ( SIC_ISR0_MAX > source ) { |
---|
381 | vectors[vector].mask0 |= (1 << source); |
---|
382 | } else { |
---|
383 | vectors[vector].mask1 |= (1 << (source - SIC_ISR0_MAX)); |
---|
384 | } |
---|
385 | } |
---|
386 | r >>= 4; |
---|
387 | source++; |
---|
388 | } |
---|
389 | } |
---|
390 | } |
---|
391 | |
---|
392 | |
---|
393 | |
---|
394 | |
---|
395 | |
---|
396 | #else |
---|
397 | |
---|
398 | static struct { |
---|
399 | uint32_t mask0; |
---|
400 | uint32_t mask1; |
---|
401 | bfin_isr_t *head; |
---|
402 | } vectors[CEC_INTERRUPT_COUNT]; |
---|
403 | |
---|
404 | static uint32_t globalMask0; |
---|
405 | static uint32_t globalMask1; |
---|
406 | |
---|
407 | static rtems_isr interruptHandler(rtems_vector_number vector) { |
---|
408 | bfin_isr_t *isr = NULL; |
---|
409 | uint32_t sourceMask0 = 0; |
---|
410 | uint32_t sourceMask1 = 0; |
---|
411 | rtems_interrupt_level isrLevel; |
---|
412 | |
---|
413 | rtems_interrupt_disable(isrLevel); |
---|
414 | vector -= CEC_INTERRUPT_BASE_VECTOR; |
---|
415 | if (vector >= 0 && vector < CEC_INTERRUPT_COUNT) { |
---|
416 | isr = vectors[vector].head; |
---|
417 | sourceMask0 = *(uint32_t volatile *) SIC_ISR & |
---|
418 | *(uint32_t volatile *) SIC_IMASK; |
---|
419 | sourceMask1 = *(uint32_t volatile *) (SIC_ISR + SIC_ISR_PITCH) & |
---|
420 | *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH); |
---|
421 | while (isr) { |
---|
422 | if ((sourceMask0 & isr->mask0) || (sourceMask1 & isr->mask1)) { |
---|
423 | isr->isr(isr->_arg); |
---|
424 | sourceMask0 = *(uint32_t volatile *) SIC_ISR & |
---|
425 | *(uint32_t volatile *) SIC_IMASK; |
---|
426 | sourceMask1 = *(uint32_t volatile *) (SIC_ISR + SIC_ISR_PITCH) & |
---|
427 | *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH); |
---|
428 | } |
---|
429 | isr = isr->next; |
---|
430 | } |
---|
431 | } |
---|
432 | rtems_interrupt_enable(isrLevel); |
---|
433 | } |
---|
434 | |
---|
435 | /** |
---|
436 | * Initializes the interrupt module |
---|
437 | */ |
---|
438 | void bfin_interrupt_init(void) { |
---|
439 | int source; |
---|
440 | int vector; |
---|
441 | uint32_t r; |
---|
442 | int i; |
---|
443 | int j; |
---|
444 | |
---|
445 | globalMask0 = ~(uint32_t) 0; |
---|
446 | globalMask1 = ~(uint32_t) 0; |
---|
447 | *(uint32_t volatile *) SIC_IMASK = 0; |
---|
448 | *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH) = 0; |
---|
449 | |
---|
450 | memset(vectors, 0, sizeof(vectors)); |
---|
451 | /* build mask0 showing what SIC sources drive each CEC vector */ |
---|
452 | source = 0; |
---|
453 | |
---|
454 | /** |
---|
455 | * The bf52x has 8 IAR registers but they do not have a constant pitch. |
---|
456 | * |
---|
457 | */ |
---|
458 | for (i = 0; i < SIC_IAR_COUNT; i++) { |
---|
459 | if ( SIC_IAR_COUNT_SET0 > i ) { |
---|
460 | r = *(uint32_t volatile *) (SIC_IAR_BASE_ADDRESS + i * SIC_IAR_PITCH); |
---|
461 | } else { |
---|
462 | r = *(uint32_t volatile *) (SIC_IAR_BASE_ADDRESS_0 + |
---|
463 | ((i-SIC_IAR_COUNT_SET0) * SIC_IAR_PITCH)); |
---|
464 | } |
---|
465 | for (j = 0; j < 8; j++) { |
---|
466 | vector = r & 0x0f; |
---|
467 | if (vector >= 0 && vector < CEC_INTERRUPT_COUNT) { |
---|
468 | /* install our local handler */ |
---|
469 | if (vectors[vector].mask0 == 0 && vectors[vector].mask1 == 0){ |
---|
470 | set_vector(interruptHandler, vector + CEC_INTERRUPT_BASE_VECTOR, 1); |
---|
471 | } |
---|
472 | if ( SIC_ISR0_MAX > source ) { |
---|
473 | vectors[vector].mask0 |= (1 << source); |
---|
474 | } else { |
---|
475 | vectors[vector].mask1 |= (1 << (source - SIC_ISR0_MAX)); |
---|
476 | } |
---|
477 | } |
---|
478 | r >>= 4; |
---|
479 | source++; |
---|
480 | } |
---|
481 | } |
---|
482 | } |
---|
483 | |
---|
484 | /* modify SIC_IMASK based on ISR list for a particular CEC vector */ |
---|
485 | static void setMask(uint32_t vector) { |
---|
486 | bfin_isr_t *isr = NULL; |
---|
487 | uint32_t mask = 0; |
---|
488 | uint32_t r = 0; |
---|
489 | |
---|
490 | mask = 0; |
---|
491 | isr = vectors[vector].head; |
---|
492 | while (isr) { |
---|
493 | mask |= isr->mask0; |
---|
494 | isr = isr->next; |
---|
495 | } |
---|
496 | r = *(uint32_t volatile *) SIC_IMASK; |
---|
497 | r &= ~vectors[vector].mask0; |
---|
498 | r |= mask; |
---|
499 | r &= globalMask0; |
---|
500 | *(uint32_t volatile *) SIC_IMASK = r; |
---|
501 | |
---|
502 | |
---|
503 | mask = 0; |
---|
504 | isr = vectors[vector].head; |
---|
505 | while (isr) { |
---|
506 | mask |= isr->mask1; |
---|
507 | isr = isr->next; |
---|
508 | } |
---|
509 | r = *(uint32_t volatile *) (SIC_IMASK+ SIC_IMASK_PITCH); |
---|
510 | r &= ~vectors[vector].mask1; |
---|
511 | r |= mask; |
---|
512 | r &= globalMask1; |
---|
513 | *(uint32_t volatile *) (SIC_IMASK+ SIC_IMASK_PITCH) = r; |
---|
514 | } |
---|
515 | |
---|
516 | /* add an ISR to the list for whichever vector it belongs to */ |
---|
517 | rtems_status_code bfin_interrupt_register(bfin_isr_t *isr) { |
---|
518 | bfin_isr_t *walk; |
---|
519 | rtems_interrupt_level isrLevel; |
---|
520 | |
---|
521 | /* find the appropriate vector */ |
---|
522 | for (isr->vector = 0; isr->vector < CEC_INTERRUPT_COUNT; isr->vector++) |
---|
523 | if ( (vectors[isr->vector].mask0 & (1 << isr->source) ) || \ |
---|
524 | (vectors[isr->vector].mask1 & (1 << (isr->source - SIC_ISR0_MAX)) )) |
---|
525 | break; |
---|
526 | if (isr->vector < CEC_INTERRUPT_COUNT) { |
---|
527 | isr->next = NULL; |
---|
528 | isr->mask0 = 0; |
---|
529 | isr->mask1 = 0; |
---|
530 | rtems_interrupt_disable(isrLevel); |
---|
531 | /* find the current end of the list */ |
---|
532 | walk = vectors[isr->vector].head; |
---|
533 | while (walk && walk->next) |
---|
534 | walk = walk->next; |
---|
535 | /* append new isr to list */ |
---|
536 | if (walk) |
---|
537 | walk->next = isr; |
---|
538 | else |
---|
539 | vectors[isr->vector].head = isr; |
---|
540 | rtems_interrupt_enable(isrLevel); |
---|
541 | } else |
---|
542 | /* we failed, but make vector a legal value so other calls into |
---|
543 | this module with this isr descriptor won't do anything bad */ |
---|
544 | isr->vector = 0; |
---|
545 | return RTEMS_SUCCESSFUL; |
---|
546 | } |
---|
547 | |
---|
548 | rtems_status_code bfin_interrupt_unregister(bfin_isr_t *isr) { |
---|
549 | bfin_isr_t *walk, *prev; |
---|
550 | rtems_interrupt_level isrLevel; |
---|
551 | |
---|
552 | rtems_interrupt_disable(isrLevel); |
---|
553 | walk = vectors[isr->vector].head; |
---|
554 | prev = NULL; |
---|
555 | /* find this isr in our list */ |
---|
556 | while (walk && walk != isr) { |
---|
557 | prev = walk; |
---|
558 | walk = walk->next; |
---|
559 | } |
---|
560 | if (walk) { |
---|
561 | /* if found, remove it */ |
---|
562 | if (prev) |
---|
563 | prev->next = walk->next; |
---|
564 | else |
---|
565 | vectors[isr->vector].head = walk->next; |
---|
566 | /* fix up SIC_IMASK if necessary */ |
---|
567 | setMask(isr->vector); |
---|
568 | } |
---|
569 | rtems_interrupt_enable(isrLevel); |
---|
570 | return RTEMS_SUCCESSFUL; |
---|
571 | } |
---|
572 | |
---|
573 | void bfin_interrupt_enable(bfin_isr_t *isr, bool enable) { |
---|
574 | rtems_interrupt_level isrLevel; |
---|
575 | |
---|
576 | rtems_interrupt_disable(isrLevel); |
---|
577 | if ( SIC_ISR0_MAX > isr->source ) { |
---|
578 | isr->mask0 = enable ? (1 << isr->source) : 0; |
---|
579 | *(uint32_t volatile *) SIC_IMASK |= isr->mask0; |
---|
580 | } else { |
---|
581 | isr->mask1 = enable ? (1 << (isr->source - SIC_ISR0_MAX)) : 0; |
---|
582 | *(uint32_t volatile *) (SIC_IMASK + SIC_IMASK_PITCH) |= isr->mask1; |
---|
583 | } |
---|
584 | |
---|
585 | //setMask(isr->vector); |
---|
586 | rtems_interrupt_enable(isrLevel); |
---|
587 | } |
---|
588 | |
---|
589 | void bfin_interrupt_enable_all(int source, bool enable) { |
---|
590 | rtems_interrupt_level isrLevel; |
---|
591 | int vector; |
---|
592 | bfin_isr_t *walk; |
---|
593 | |
---|
594 | for (vector = 0; vector < CEC_INTERRUPT_COUNT; vector++) |
---|
595 | if ( (vectors[vector].mask0 & (1 << source) ) || \ |
---|
596 | (vectors[vector].mask1 & (1 << (source - SIC_ISR0_MAX)) )) |
---|
597 | break; |
---|
598 | if (vector < CEC_INTERRUPT_COUNT) { |
---|
599 | rtems_interrupt_disable(isrLevel); |
---|
600 | walk = vectors[vector].head; |
---|
601 | while (walk) { |
---|
602 | walk->mask0 = enable ? (1 << source) : 0; |
---|
603 | walk = walk->next; |
---|
604 | } |
---|
605 | |
---|
606 | walk = vectors[vector].head; |
---|
607 | while (walk) { |
---|
608 | walk->mask1 = enable ? (1 << (source - SIC_ISR0_MAX)) : 0; |
---|
609 | walk = walk->next; |
---|
610 | } |
---|
611 | setMask(vector); |
---|
612 | rtems_interrupt_enable(isrLevel); |
---|
613 | } |
---|
614 | } |
---|
615 | |
---|
616 | void bfin_interrupt_enable_global(int source, bool enable) { |
---|
617 | int vector; |
---|
618 | rtems_interrupt_level isrLevel; |
---|
619 | |
---|
620 | for (vector = 0; vector < CEC_INTERRUPT_COUNT; vector++) |
---|
621 | if ( (vectors[vector].mask0 & (1 << source) ) || \ |
---|
622 | (vectors[vector].mask1 & (1 << (source - SIC_ISR0_MAX)) )) |
---|
623 | break; |
---|
624 | if (vector < CEC_INTERRUPT_COUNT) { |
---|
625 | rtems_interrupt_disable(isrLevel); |
---|
626 | if ( SIC_ISR0_MAX > source ) { |
---|
627 | if (enable) |
---|
628 | globalMask0 |= 1 << source; |
---|
629 | else |
---|
630 | globalMask0 &= ~(1 << source); |
---|
631 | }else { |
---|
632 | if (enable) |
---|
633 | globalMask1 |= 1 << (source - SIC_ISR0_MAX); |
---|
634 | else |
---|
635 | globalMask1 &= ~(1 << (source - SIC_ISR0_MAX)); |
---|
636 | } |
---|
637 | setMask(vector); |
---|
638 | rtems_interrupt_enable(isrLevel); |
---|
639 | } |
---|
640 | } |
---|
641 | |
---|
642 | #endif |
---|