1 //
2 // interrupts.c - interrupts related constants and functions
3 //
4 // $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/interrupts.c#1 $
5
6 // Copyright (c) 2002-2004 Tensilica Inc.
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining
9 // a copy of this software and associated documentation files (the
10 // "Software"), to deal in the Software without restriction, including
11 // without limitation the rights to use, copy, modify, merge, publish,
12 // distribute, sublicense, and/or sell copies of the Software, and to
13 // permit persons to whom the Software is furnished to do so, subject to
14 // the following conditions:
15 //
16 // The above copyright notice and this permission notice shall be included
17 // in all copies or substantial portions of the Software.
18 //
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27 #include <xtensa/config/core.h>
28
29 #if XCHAL_HAVE_INTERRUPTS
30
31 /* For internal use by the HAL: */
32 // static void xthal_vpri_lock(void);
33 // static void xthal_vpri_unlock(void);
34 extern void xthal_vpri_lock(void);
35 extern void xthal_vpri_unlock(void);
36
37
38 /*
39 * Definitions:
40 *
41 * Virtual interrupt level = 0 .. 0xFF
42 *
43 * ...
44 */
45
46 #define XTHAL_DEFAULT_SOFTPRI 4 /* default software priority (range 0..15) */
47 /* IMPORTANT: if you change this, you also
48 need to update the initial resolvemap[]
49 value below... */
50
51 /*
52 * Macros to convert between:
53 * intlevel (0..15) and software priority within an intlevel (0..15)
54 * and
55 * virtual interrupt priority (0..0xFF), which is a combination of the above two.
56 */
57 #define XTHAL_VPRI_INTLEVEL(vpri) (((vpri) >> 4) & 0xF)
58 #define XTHAL_VPRI_SOFTPRI(vpri) ((vpri) & 0xF)
59 #define XTHAL_VPRI(intlevel,softpri) ((((intlevel)&0xF)<<4)|((softpri)&0xF))
60
61
62 /*
63 * Virtual priority management data structures.
64 * This structure is instantiated as Xthal_vpri_state (below).
65 *
66 * IMPORTANT: if you change anything in this structure,
67 * you must accordingly change structure offsets
68 * defined in int_asm.S .
69 *
70 * IMPORTANT: the worst-case offset of the resolvemap[] field is 976 bytes
71 * (0x10 + 0x40*15), which is accessed in int_asm.S at a further
72 * offset of 8*4==32 for a total offset of 1008, very close
73 * to l32i's offset limit of 1020. So you can't push it much
74 * further.
75 *
76 * [INTERNAL NOTE: There might be a trick that will save 64 bytes,
77 * if really needed, by trimming 15 word entries from the start
78 * of enablemap[] ... -MG]
79 */
80 typedef struct XtHalVPriState {
81 /*
82 * Current virtual interrupt priority (0x0F .. 0xFF)
83 * (or actually, 0x0F .. XCHAL_NUM_INTLEVELS*0x10+0x0F).
84 * Virtual priorities 0x00 to 0x0E are mapped to 0x0F (they're all
85 * equivalent, because there's no such thing as a level 0 interrupt),
86 * which may help optimize the size of enablemap[] in the future.
87 * Virtual priorities above XCHAL_NUM_INTLEVELS*0x10+0x0F are
88 * mapped to XCHAL_NUM_INTLEVELS*0x10+0x0F, which is equivalent.
89 *
90 * NOTE: this variable is actually part of the processor context,
91 * which means (for most OSes) that it must be saved
92 * in the task control block along with other register state.
93 */
94 unsigned char vpri; // current virtual interrupt priority (0x0F..0xFF)
95 unsigned char locklevel; // real interrupt level used to get exclusive
96 // access to this structure; MUST be at least one (1)
97 unsigned char lockvpri; // virtual interrupt level used to get exclusive
98 // access to this structure; MUST be XTHAL_VPRI(locklevel,15)
99 // (so it's at least 0x1F); placed here for efficiency
100 unsigned char pad0; // (alignment padding, unused)
101
102 unsigned enabled; // mask of which interrupts are enabled, regardless of level
103 // (level masking is applied on top of this)
104
105 unsigned lockmask; // (unused?) INTENABLE value used to lock out
106 // interrupts for exclusive access to this structure
107
108 unsigned pad1; // (alignment padding, unused)
109
110 /*
111 * For each virtual interrupt priority, this array provides the
112 * bitmask of interrupts of greater virtual priority
113 * (ie. the set of interrupts to enable at that virtual priority,
114 * if all interrupts were enabled in field 'enabled').
115 */
116 unsigned enablemap[XCHAL_NUM_INTLEVELS+1][16];
117
118 /*
119 * Table entries for intlevel 'i' are bitmasks defined as follows,
120 * with map == Xthal_vpri_resolvemap[i-1]:
121 * map[8+(x=0)] = ints at pri x + 8..15 (8-15)
122 * map[4+(x=0,8)] = ints at pri x + 4..7 (4-7,12-15)
123 * map[2+(x=0,4,8,12)] = ints at pri x + 2..3 (2-3,6-7,10-11,14-15)
124 * map[1+(x=0,2..12,14)] = ints at pri x + 1 (1,3,5,7,9,11,13,15)
125 * map[0] = 0 (unused; for alignment)
126 */
127 unsigned resolvemap[XCHAL_NUM_INTLEVELS][16];
128
129 } XtHalVPriState;
130
131
132 extern XtHalVPriState Xthal_vpri_state;
133 extern unsigned char Xthal_int_vpri[32];
134 extern XtHalVoidFunc * Xthal_tram_trigger_fn;
135
136 extern void xthal_null_func(void);
137
138 /* Shorthand for structure members: */
139 #define Xthal_vpri_level Xthal_vpri_state.vpri
140 #define Xthal_vpri_locklevel Xthal_vpri_state.locklevel
141 #define Xthal_vpri_lockvpri Xthal_vpri_state.lockvpri
142 #define Xthal_vpri_enabled Xthal_vpri_state.enabled
143 #define Xthal_vpri_lockmask Xthal_vpri_state.lockmask // unused?
144 #define Xthal_vpri_enablemap Xthal_vpri_state.enablemap
145 #define Xthal_vpri_resolvemap Xthal_vpri_state.resolvemap
146 #if 0
147 Combined refs:
148 - enablemap, vpri, enabled (xthal_set_vpri[_nw])
149 - enablemap, vpri, enabled, resolvemap (xthal_get_intpending_nw)
150 - enablemap, vpri, enabled, locklevel (xthal_vpri_lock)
151 - enablemap, vpri, enabled (xthal_vpri_unlock)
152 #endif
153
154 #endif /* XCHAL_HAVE_INTERRUPTS */
155
156
157
158 #if defined(__SPLIT__num_intlevels)
159
160 // the number of interrupt levels
161 const unsigned char Xthal_num_intlevels = XCHAL_NUM_INTLEVELS;
162
163 #endif
164
165 #if defined(__SPLIT__num_interrupts)
166
167 // the number of interrupts
168 const unsigned char Xthal_num_interrupts = XCHAL_NUM_INTERRUPTS;
169
170 #endif
171
172 #if defined(__SPLIT__excm_level)
173
174 // the highest level of interrupts masked by PS.EXCM (if XEA2)
175 const unsigned char Xthal_excm_level = XCHAL_EXCM_LEVEL;
176
177 #endif
178
179 #if defined(__SPLIT__intlevel_mask)
180
181 // mask of interrupts at each intlevel
182 const unsigned Xthal_intlevel_mask[16] = {
183 XCHAL_INTLEVEL_MASKS
184 };
185
186 #endif
187
188 #if defined(__SPLIT__intlevel_andbelow_mask)
189
190 // mask for level 1 to N interrupts
191 const unsigned Xthal_intlevel_andbelow_mask[16] = {
192 XCHAL_INTLEVEL_ANDBELOW_MASKS
193 };
194
195 #endif
196
197 #if defined(__SPLIT__intlevel)
198
199 // level per interrupt
200 const unsigned char Xthal_intlevel[32] = {
201 XCHAL_INT_LEVELS
202 };
203
204 #endif
205
206 #if defined(__SPLIT__inttype)
207
208 // type of each interrupt
209 const unsigned char Xthal_inttype[32] = {
210 XCHAL_INT_TYPES
211 };
212
213 #endif
214
215 #if defined(__SPLIT__inttype_mask)
216
217 const unsigned Xthal_inttype_mask[XTHAL_MAX_INTTYPES] = {
218 XCHAL_INTTYPE_MASKS
219 };
220
221 #endif
222
223 #if defined(__SPLIT__timer_interrupt)
224
225 // interrupts assigned to each timer (CCOMPARE0 to CCOMPARE3), -1 if unassigned
226 const int Xthal_timer_interrupt[XTHAL_MAX_TIMERS] = {
227 XCHAL_TIMER_INTERRUPTS
228 };
229
230 #endif
231
232 #if defined(__SPLIT__vpri)
233
234 #if XCHAL_HAVE_INTERRUPTS
235
236 /*
237 * Note: this structure changes dynamically at run-time,
238 * but is initialized here for efficiency and simplicity,
239 * according to configuration.
240 */
241 XtHalVPriState Xthal_vpri_state = {
242 0x00, /* vpri */
243 1, /* locklevel */
244 0x1F, /* lockvpri */
245 0, /* pad0 */
246 0x00000000, /* enabled */
247 0x00000000, /* lockmask (unused?) */
248 0, /* pad1 */
249
250 #define DEFAULT_ENABLEMAP(levela,levelb) \
251 { (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 0 ? levela : levelb)), \
252 (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 1 ? levela : levelb)), \
253 (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 2 ? levela : levelb)), \
254 (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 3 ? levela : levelb)), \
255 (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 4 ? levela : levelb)), \
256 (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 5 ? levela : levelb)), \
257 (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 6 ? levela : levelb)), \
258 (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 7 ? levela : levelb)), \
259 (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 8 ? levela : levelb)), \
260 (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI > 9 ? levela : levelb)), \
261 (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI >10 ? levela : levelb)), \
262 (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI >11 ? levela : levelb)), \
263 (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI >12 ? levela : levelb)), \
264 (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI >13 ? levela : levelb)), \
265 (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI >14 ? levela : levelb)), \
266 (XCHAL_INTLEVEL15_ANDBELOW_MASK & ~(XTHAL_DEFAULT_SOFTPRI >15 ? levela : levelb)) }
267
268 /* Xthal_vpri_enablemap[XCHAL_NUM_INTLEVELS+1][16]: */
269 {
270 DEFAULT_ENABLEMAP(XCHAL_INTLEVEL0_ANDBELOW_MASK,XCHAL_INTLEVEL0_ANDBELOW_MASK),
271 #if XCHAL_NUM_INTLEVELS >= 1
272 DEFAULT_ENABLEMAP(XCHAL_INTLEVEL0_ANDBELOW_MASK,XCHAL_INTLEVEL1_ANDBELOW_MASK),
273 #endif
274 #if XCHAL_NUM_INTLEVELS >= 2
275 DEFAULT_ENABLEMAP(XCHAL_INTLEVEL1_ANDBELOW_MASK,XCHAL_INTLEVEL2_ANDBELOW_MASK),
276 #endif
277 #if XCHAL_NUM_INTLEVELS >= 3
278 DEFAULT_ENABLEMAP(XCHAL_INTLEVEL2_ANDBELOW_MASK,XCHAL_INTLEVEL3_ANDBELOW_MASK),
279 #endif
280 #if XCHAL_NUM_INTLEVELS >= 4
281 DEFAULT_ENABLEMAP(XCHAL_INTLEVEL3_ANDBELOW_MASK,XCHAL_INTLEVEL4_ANDBELOW_MASK),
282 #endif
283 #if XCHAL_NUM_INTLEVELS >= 5
284 DEFAULT_ENABLEMAP(XCHAL_INTLEVEL4_ANDBELOW_MASK,XCHAL_INTLEVEL5_ANDBELOW_MASK),
285 #endif
286 #if XCHAL_NUM_INTLEVELS >= 6
287 DEFAULT_ENABLEMAP(XCHAL_INTLEVEL5_ANDBELOW_MASK,XCHAL_INTLEVEL6_ANDBELOW_MASK),
288 #endif
289 #if XCHAL_NUM_INTLEVELS >= 7
290 # error Interrupt levels greater than 6 not currently supported in the HAL interrupt routines.
291 #endif
292 },
293
294 /* Xthal_vpri_resolvemap[XCHAL_NUM_INTLEVELS][16]: */
295 {
296 #if XCHAL_NUM_INTLEVELS >= 1 /* set for default soft priority of 4: */
297 {0,0,0,0, XCHAL_INTLEVEL1_MASK,0,0,0, 0,0,0,0, 0,0,0,0},
298 #endif
299 #if XCHAL_NUM_INTLEVELS >= 2 /* set for default soft priority of 4: */
300 {0,0,0,0, XCHAL_INTLEVEL2_MASK,0,0,0, 0,0,0,0, 0,0,0,0},
301 #endif
302 #if XCHAL_NUM_INTLEVELS >= 3 /* set for default soft priority of 4: */
303 {0,0,0,0, XCHAL_INTLEVEL3_MASK,0,0,0, 0,0,0,0, 0,0,0,0},
304 #endif
305 #if XCHAL_NUM_INTLEVELS >= 4 /* set for default soft priority of 4: */
306 {0,0,0,0, XCHAL_INTLEVEL4_MASK,0,0,0, 0,0,0,0, 0,0,0,0},
307 #endif
308 #if XCHAL_NUM_INTLEVELS >= 5 /* set for default soft priority of 4: */
309 {0,0,0,0, XCHAL_INTLEVEL5_MASK,0,0,0, 0,0,0,0, 0,0,0,0},
310 #endif
311 #if XCHAL_NUM_INTLEVELS >= 6 /* set for default soft priority of 4: */
312 {0,0,0,0, XCHAL_INTLEVEL6_MASK,0,0,0, 0,0,0,0, 0,0,0,0},
313 #endif
314 #if XCHAL_NUM_INTLEVELS >= 7 /* set for default soft priority of 4: */
315 # error Interrupt levels greater than 6 not currently supported in the HAL interrupt routines.
316 #endif
317 }
318
319 };
320
321
322 /*
323 * Virtual (software) priority (0x00..0xFF) of each interrupt.
324 * This isn't referenced by assembler.
325 */
326 unsigned char Xthal_int_vpri[32] = {
327 #define DEFAULT_INTVPRI(level) (level ? ((level << 4) | XTHAL_DEFAULT_SOFTPRI) : 0)
328 DEFAULT_INTVPRI( XCHAL_INT0_LEVEL ),
329 DEFAULT_INTVPRI( XCHAL_INT1_LEVEL ),
330 DEFAULT_INTVPRI( XCHAL_INT2_LEVEL ),
331 DEFAULT_INTVPRI( XCHAL_INT3_LEVEL ),
332 DEFAULT_INTVPRI( XCHAL_INT4_LEVEL ),
333 DEFAULT_INTVPRI( XCHAL_INT5_LEVEL ),
334 DEFAULT_INTVPRI( XCHAL_INT6_LEVEL ),
335 DEFAULT_INTVPRI( XCHAL_INT7_LEVEL ),
336 DEFAULT_INTVPRI( XCHAL_INT8_LEVEL ),
337 DEFAULT_INTVPRI( XCHAL_INT9_LEVEL ),
338 DEFAULT_INTVPRI( XCHAL_INT10_LEVEL ),
339 DEFAULT_INTVPRI( XCHAL_INT11_LEVEL ),
340 DEFAULT_INTVPRI( XCHAL_INT12_LEVEL ),
341 DEFAULT_INTVPRI( XCHAL_INT13_LEVEL ),
342 DEFAULT_INTVPRI( XCHAL_INT14_LEVEL ),
343 DEFAULT_INTVPRI( XCHAL_INT15_LEVEL ),
344 DEFAULT_INTVPRI( XCHAL_INT16_LEVEL ),
345 DEFAULT_INTVPRI( XCHAL_INT17_LEVEL ),
346 DEFAULT_INTVPRI( XCHAL_INT18_LEVEL ),
347 DEFAULT_INTVPRI( XCHAL_INT19_LEVEL ),
348 DEFAULT_INTVPRI( XCHAL_INT20_LEVEL ),
349 DEFAULT_INTVPRI( XCHAL_INT21_LEVEL ),
350 DEFAULT_INTVPRI( XCHAL_INT22_LEVEL ),
351 DEFAULT_INTVPRI( XCHAL_INT23_LEVEL ),
352 DEFAULT_INTVPRI( XCHAL_INT24_LEVEL ),
353 DEFAULT_INTVPRI( XCHAL_INT25_LEVEL ),
354 DEFAULT_INTVPRI( XCHAL_INT26_LEVEL ),
355 DEFAULT_INTVPRI( XCHAL_INT27_LEVEL ),
356 DEFAULT_INTVPRI( XCHAL_INT28_LEVEL ),
357 DEFAULT_INTVPRI( XCHAL_INT29_LEVEL ),
358 DEFAULT_INTVPRI( XCHAL_INT30_LEVEL ),
359 DEFAULT_INTVPRI( XCHAL_INT31_LEVEL )
360 };
361
362
363 #if 0
364 /*
365 * A number of things may have already been written not calling
366 * this function, so it isn't straightforward to start requiring it:
367 */
368 void xthal_vpri_init( int default_vpri )
369 {
370 int i, j;
371
372 Xthal_vpri_level = 0; /* vpri */
373 Xthal_vpri_locklevel = 1; /* locklevel */
374 Xthal_vpri_lockvpri = 0x1F; /* lockvpri */
375 Xthal_vpri_enabled = 0x00000000; /* enabled */
376 Xthal_vpri_lockmask = 0x00000000; /* lockmask (unused?) */
377 for( i = 0; i < XCHAL_NUM_INTLEVELS; i++ ) {
378 for( j = 0; j < 16; j++ )
379 Xthal_vpri_enablemap[i][j] = XCHAL_INTLEVEL15_ANDBELOW_MASK
380 & ~Xthal_intlevel_andbelow_mask[i - (j < default_vpri && i > 0)];
381 }
382 for( i = 1; i < XCHAL_NUM_INTLEVELS; i++ ) {
383 for( j = 0; j < 16; j++ )
384 Xthal_vpri_resolvemap[i-1][j] = 0;
385 if( (default_vpri & 1) != 0 )
386 Xthal_vpri_resolvemap[i-1][default_vpri & 0xF] |= Xthal_intlevel_mask[i];
387 if( (default_vpri & 2) != 0 )
388 Xthal_vpri_resolvemap[i-1][default_vpri & 0xE] |= Xthal_intlevel_mask[i];
389 if( (default_vpri & 4) != 0 )
390 Xthal_vpri_resolvemap[i-1][default_vpri & 0xC] |= Xthal_intlevel_mask[i];
391 if( (default_vpri & 8) != 0 )
392 Xthal_vpri_resolvemap[i-1][default_vpri & 0x8] |= Xthal_intlevel_mask[i];
393 }
394 for( i = 0; i < 32; i++ )
395 Xthal_int_vpri[i] = (Xthal_intlevel[i] << 4) | (default_vpri & 0xF);
396 }
397 #endif /*0*/
398
xthal_null_func(void)399 void xthal_null_func(void) { }
400 XtHalVoidFunc *Xthal_tram_trigger_fn = xthal_null_func;
401
402
403 #endif /* XCHAL_HAVE_INTERRUPTS */
404
405 #endif
406
407 #if defined(__SPLIT__vpri_to_intlevel)
408
409 /*
410 * xthal_vpri_to_intlevel
411 *
412 * Converts a virtual interrupt priority to the closest equivalent
413 * (equal or higher) interrupt level.
414 */
xthal_vpri_to_intlevel(unsigned vpri)415 unsigned xthal_vpri_to_intlevel(unsigned vpri)
416 {
417 #if XCHAL_HAVE_INTERRUPTS
418 return( XTHAL_VPRI_INTLEVEL( vpri ) );
419 #else
420 return( vpri );
421 #endif
422 }
423
424 #endif
425
426 #if defined(__SPLIT__intlevel_to_vpri)
427
428 /*
429 * xthal_intlevel_to_vpri
430 *
431 * Converts an interrupt level to a virtual interrupt priority.
432 */
xthal_intlevel_to_vpri(unsigned intlevel)433 unsigned xthal_intlevel_to_vpri(unsigned intlevel)
434 {
435 #if XCHAL_HAVE_INTERRUPTS
436 return( XTHAL_VPRI( intlevel, 0xF ) );
437 #else
438 return( intlevel );
439 #endif
440 }
441
442 #endif
443
444 #if defined(__SPLIT__vpri_int_enable)
445
446 /*
447 * xthal_int_enable
448 *
449 * Enables given set of interrupts, and returns previous enabled-state of these interrupts.
450 */
xthal_int_enable(unsigned mask)451 unsigned xthal_int_enable(unsigned mask)
452 {
453 #if XCHAL_HAVE_INTERRUPTS
454 unsigned prev_enabled, syncmask;
455
456 xthal_vpri_lock();
457 prev_enabled = Xthal_vpri_enabled | Xthal_tram_enabled;
458
459 /* Figure out which bits must go in Xthal_tram_enabled: */
460 syncmask = (mask & Xthal_tram_pending & Xthal_tram_sync);
461 if( syncmask != 0 ) {
462 Xthal_tram_enabled |= syncmask;
463 mask &= ~syncmask;
464 /*
465 * If we are re-enabling a pending trampolined interrupt,
466 * there is a possibility that the level-1 software interrupt
467 * is no longer pending, having already occurred (without processing
468 * the trampoline because it was disabled). So we have to
469 * ensure that the level-1 software interrupt used for trampolining
470 * is pending.
471 * We let the BSP do this rather than the HAL, because it could
472 * potentially use an external level-1 interrupt to trampoline
473 * (if proper hardware was available) rather than a software interrupt.
474 */
475 (*Xthal_tram_trigger_fn)();
476 }
477 /* The rest go in the global enabled mask: */
478 Xthal_vpri_enabled |= mask;
479
480 xthal_vpri_unlock(); /* update INTENABLE as per current vpri */
481 return( prev_enabled );
482
483 #else /* XCHAL_HAVE_INTERRUPTS */
484 return( 0 );
485 #endif /* XCHAL_HAVE_INTERRUPTS */
486 }
487
488 #endif
489
490 #if defined(__SPLIT__vpri_int_disable)
491
492 /*
493 * xthal_int_disable
494 *
495 * Disables given set of interrupts, and returns previous enabled-state of these interrupts.
496 */
xthal_int_disable(unsigned mask)497 unsigned xthal_int_disable(unsigned mask)
498 {
499 #if XCHAL_HAVE_INTERRUPTS
500 unsigned prev_enabled;
501
502 xthal_vpri_lock();
503 prev_enabled = Xthal_vpri_enabled | Xthal_tram_enabled;
504 Xthal_vpri_enabled &= ~mask;
505 Xthal_tram_enabled &= ~mask;
506 xthal_vpri_unlock(); /* update INTENABLE as per current vpri */
507 return( prev_enabled );
508 #else
509 return( 0 );
510 #endif
511 }
512
513 #endif
514
515 #if defined(__SPLIT__set_vpri_locklevel)
516
xthal_set_vpri_locklevel(unsigned intlevel)517 void xthal_set_vpri_locklevel(unsigned intlevel)
518 {
519 #if XCHAL_HAVE_INTERRUPTS
520 if( intlevel < 1 )
521 intlevel = 1;
522 else if( intlevel > XCHAL_NUM_INTLEVELS )
523 intlevel = XCHAL_NUM_INTLEVELS;
524 Xthal_vpri_state.locklevel = intlevel;
525 Xthal_vpri_state.lockvpri = XTHAL_VPRI(intlevel, 15);
526 #endif
527 }
528
529 #endif
530
531 #if defined(__SPLIT__get_vpri_locklevel)
532
xthal_get_vpri_locklevel(void)533 unsigned xthal_get_vpri_locklevel(void)
534 {
535 #if XCHAL_HAVE_INTERRUPTS
536 return( Xthal_vpri_state.locklevel );
537 #else
538 return( 1 ); /* must return at least 1, some OSes assume this */
539 #endif
540 }
541
542 #endif
543
544 #if defined(__SPLIT__set_int_vpri)
545
546 /*
547 * xthal_set_int_vpri (was intSetL1Pri)
548 *
549 * Set the virtual (software) priority of an interrupt.
550 * Note: the intlevel of an interrupt CANNOT be changed -- this is
551 * set in hardware according to the core configuration file.
552 *
553 * intnum interrupt number (0..31)
554 * vpri virtual interrupt priority (0..15, or intlevel*16+(0..15) )
555 */
xthal_set_int_vpri(int intnum,int vpri)556 int xthal_set_int_vpri(int intnum, int vpri)
557 {
558 #if XCHAL_HAVE_INTERRUPTS
559 unsigned mask, maskoff, basepri, prevpri, intlevel, *maskp, i;
560
561 /*
562 * Verify parameters:
563 */
564 if( (unsigned)intnum >= XCHAL_NUM_INTERRUPTS || (unsigned)vpri > 0xFF )
565 return( 0 ); /* error: bad parameter(s) */
566 /*
567 * If requested priority specifies an intlevel, it must match that
568 * of the interrupt specified; otherwise (0..15) the proper intlevel of
569 * the specified interrupt is assumed, and added to the parameter:
570 */
571 intlevel = Xthal_intlevel[intnum]; /* intnum's intlevel */
572 if( intlevel == 0 || intlevel > XCHAL_NUM_INTLEVELS )
573 return( 0 ); /* error: no support for setting priority of NMI etc. */
574 basepri = intlevel << 4; /* intnum's base soft-pri. */
575 if( vpri > 0x0F ) { /* intlevel portion given? */
576 if( (vpri & 0xF0) != basepri ) /* then it must be correct */
577 return( 0 ); /* error: intlevel mismatch */
578 vpri &= 0x0F; /* remove it */
579 }
580
581 mask = 1L << intnum;
582
583 /*
584 * Lock interrupts during virtual priority data structure updates:
585 */
586 xthal_vpri_lock();
587
588 /*
589 * Update virtual priority of 'intnum':
590 */
591 prevpri = Xthal_int_vpri[intnum]; /* save for return value */
592 Xthal_int_vpri[intnum] = basepri | vpri;
593 /* This interrupt must only be enabled at virtual priorities lower than its own: */
594 for( i = 0; i < vpri; i++ )
595 Xthal_vpri_enablemap[0][basepri++] |= mask;
596 maskoff = ~mask;
597 for( ; i <= 0x0F; i++ )
598 Xthal_vpri_enablemap[0][basepri++] &= maskoff;
599
600 /*
601 * Update the prioritization table used to resolve priorities by binary search:
602 */
603 /* Remove interrupt <intnum> from prioritization table: */
604 maskp = Xthal_vpri_resolvemap[intlevel-1];
605 for (i=0; i<16; i++)
606 maskp[i] &= maskoff;
607 /* Add interrupt <intnum> to prioritization table at its (new) given priority: */
608 if( vpri & 0x1 )
609 maskp[vpri] |= mask;
610 if( vpri & 0x2 )
611 maskp[vpri & 0xE] |= mask;
612 if( vpri & 0x4 )
613 maskp[vpri & 0xC] |= mask;
614 if( vpri & 0x8 )
615 maskp[vpri & 0x8] |= mask;
616
617 /*
618 * Unlock interrupts (back to current level) and update INTENABLE:
619 */
620 xthal_vpri_unlock();
621
622 return( prevpri );
623 #else /* XCHAL_HAVE_INTERRUPTS */
624 return( 0 );
625 #endif /* XCHAL_HAVE_INTERRUPTS */
626 } /* xthal_set_int_vpri */
627
628 #endif
629
630 #if defined(__SPLIT__get_int_vpri)
631
xthal_get_int_vpri(int intnum)632 int xthal_get_int_vpri(int intnum)
633 {
634 #if XCHAL_HAVE_INTERRUPTS
635 if( (unsigned)intnum >= XCHAL_NUM_INTERRUPTS )
636 return( 0 ); /* error: bad parameter */
637 return( Xthal_int_vpri[intnum] );
638 #else
639 return( 0 );
640 #endif
641 }
642
643
644 #endif
645
646 #if defined(__SPLIT__trampolines)
647
648
649 /*
650 SUPPORT FOR TRAMPOLINES
651
652 NOTE: trampolining is a special case.
653 There are two ways (defined here) to trampoline down
654 from a high-level interrupt to a level-one interrupt.
655
656 a) Synchronous (restrained) trampolining.
657 Trampolining without clearing the high-level interrupt,
658 letting the level-one interrupt handler clear the
659 source of the interrupt.
660 Here the high-level interrupt must be kept disabled
661 while trampolining down, and re-enabled after the
662 level-one interrupt handler completes.
663 This is what one might do to "convert" a high-level
664 interrupt into a level-one interrupt.
665 The high-level interrupt handler code can be generic.
666 [One could argue this type of trampolining isn't required,
667 which may? be true...]
668 b) Asynchronous (free) trampolining.
669 Trampolining when clearing the high-level interrupt
670 right away in the high-level interrupt handler.
671 Here the high-level interrupt is allowed to remain
672 enabled while trampolining occurs. This is very
673 useful when some processing must occur with low
674 latency, but the rest of the processing can occur
675 at lower (eg. level-one) priority. It is particularly
676 useful when the lower-priority processing occurs
677 for only some of the high-level interrupts.
678 Of course this requires custom assembler code to
679 handle the high-level interrupt and clear the source
680 of the interrupt, so the high-level interrupt handler
681 cannot be generic (as opposed to synchronous trampolining).
682
683 In both cases, a level-one software interrupt is used
684 for trampolining (one could also trampoline from level
685 m to n, m > n, n > 1, but that isn't nearly as useful;
686 it's generally the ability to execute C code and
687 to process exceptions that is sought after).
688
689 Default trampolining support is currently implemented as follows.
690
691 Trampoline handler:
692
693 A high-level interrupt is considered enabled if *either*
694 its INTENABLE bit or its xt_tram_ints bit is set
695 (note that both should never be set at the same time).
696
697 */
698
699
700 /* These are described in xtensa/hal.h (assumed initialized to zero, in BSS): */
701 unsigned Xthal_tram_pending;
702 unsigned Xthal_tram_enabled;
703 unsigned Xthal_tram_sync;
704
705
706
xthal_set_tram_trigger_func(XtHalVoidFunc * trigger_fn)707 XtHalVoidFunc* xthal_set_tram_trigger_func( XtHalVoidFunc *trigger_fn )
708 {
709 #if XCHAL_HAVE_INTERRUPTS
710 XtHalVoidFunc *fn;
711
712 fn = Xthal_tram_trigger_fn;
713 Xthal_tram_trigger_fn = trigger_fn;
714 return( fn );
715 #else
716 (void)trigger_fn;
717 return( 0 );
718 #endif
719 }
720
721
722 /*
723 * xthal_tram_set_sync
724 *
725 * Configure type of trampoline for a high-level interrupt.
726 * By default any trampoline is asynchronous, this need only
727 * be called to tell the Core HAL that a high-level interrupt
728 * will be using synchronous trampolining (down to a level-1 interrupt).
729 *
730 * intnum interrupt number (0 .. 31)
731 * sync 0 = async, 1 = synchronous
732 *
733 * Returns previous sync state of interrupt (0 or 1)
734 * or -1 if invalid interrupt number provided.
735 */
xthal_tram_set_sync(int intnum,int sync)736 int xthal_tram_set_sync( int intnum, int sync )
737 {
738 #if XCHAL_HAVE_INTERRUPTS
739 unsigned mask;
740 int prev;
741
742 if( (unsigned)intnum >= XCHAL_NUM_INTERRUPTS )
743 return( -1 );
744 mask = 1L << intnum;
745 prev = ((Xthal_tram_sync & mask) != 0);
746 if( sync )
747 Xthal_tram_sync |= mask;
748 else
749 Xthal_tram_sync &= ~mask;
750 return( prev );
751 #else /* XCHAL_HAVE_INTERRUPTS */
752 return( 0 );
753 #endif /* XCHAL_HAVE_INTERRUPTS */
754 }
755
756
757 /*
758 * xthal_tram_pending_to_service
759 *
760 * This is called by the trampoline interrupt handler
761 * (eg. by a level-one software interrupt handler)
762 * to obtain the bitmask of high-level interrupts
763 * that it must service.
764 * Returns that bitmask (note: this can sometimes be zero,
765 * eg. if currently executing level-one code disables the high-level
766 * interrupt before the trampoline handler has a chance to run).
767 *
768 * This call automatically clears the trampoline pending
769 * bits for the interrupts in the returned mask.
770 * So the caller *must* process all interrupts that have
771 * a corresponding bit set if the value returned by this function
772 * (otherwise those interrupts may likely be lost).
773 *
774 * This function should be called with level-one interrupts disabled
775 * (via INTENABLE; can't be via PS.INTLEVEL because this is C code).
776 */
xthal_tram_pending_to_service(void)777 unsigned xthal_tram_pending_to_service( void )
778 {
779 #if XCHAL_HAVE_INTERRUPTS
780 unsigned service_mask;
781
782 service_mask = ( Xthal_tram_pending
783 & (Xthal_vpri_enabled | Xthal_tram_enabled) ) ;
784
785 /*
786 * Clear trampoline pending bits.
787 * Each bit must be cleared *before* processing of the corresponding
788 * interrupt occurs, to avoid missing interrupts.
789 * Here we just clear all bits for simplicity and convenience.
790 */
791 Xthal_tram_pending &= ~service_mask;
792
793 return( service_mask );
794 #else /* XCHAL_HAVE_INTERRUPTS */
795 return( 0 );
796 #endif /* XCHAL_HAVE_INTERRUPTS */
797 }
798
799 /*
800 * xthal_tram_done
801 *
802 * This is called by the trampoline interrupt handler
803 * (eg. by a level-one software interrupt handler)
804 * to indicate that processing of a trampolined interrupt
805 * (eg. one or more of the bits it received from
806 * xthal_tram_acknowledge()) has completed.
807 *
808 * For asynchronously trampolined interrupt(s), there is nothing to do.
809 * For synchronously trampolined interrupt(s), the high-level
810 * interrupt(s) must be re-enabled (presumably the level-one
811 * interrupt handler that just completed has cleared the source
812 * of the high-level interrupt).
813 *
814 * This function should be called with level-one interrupts disabled
815 * (via INTENABLE; can't be via PS.INTLEVEL because this is C code).
816 */
xthal_tram_done(unsigned serviced_mask)817 void xthal_tram_done( unsigned serviced_mask )
818 {
819 #if XCHAL_HAVE_INTERRUPTS
820 serviced_mask &= Xthal_tram_enabled; /* sync. trampolined interrupts that completed */
821 Xthal_tram_enabled &= ~serviced_mask;
822 xthal_int_enable( serviced_mask );
823 #endif
824 }
825
826 #endif
827
828 #if defined(__SPLIT__deprecated)
829
830
831 /**********************************************************************/
832
833 #ifdef INCLUDE_DEPRECATED_HAL_CODE
834 /* These definitions were present in an early beta version of the HAL and should not be used: */
835 const unsigned Xthal_num_int_levels = XCHAL_NUM_INTLEVELS;
836 const unsigned Xthal_num_ints = XCHAL_NUM_INTERRUPTS;
837 __asm__(".global Xthal_int_level_mask\n" ".set Xthal_int_level_mask, Xthal_intlevel_mask+4");
838 __asm__(".global Xthal_int_level1_to_n_mask\n" ".set Xthal_int_level1_to_n_mask, Xthal_intlevel_andbelow_mask+8");
839 /*const unsigned Xthal_int_level_mask[15] = { XCHAL_INTLEVEL_MASKS }; ... minus the first entry ...*/
840 /*const unsigned Xthal_int_level1_to_n_mask[14] = { XCHAL_INTLEVEL_ANDBELOW_MASKS }; ... minus the first two entries ...*/
841 const unsigned Xthal_int_level[32] = { XCHAL_INT_LEVELS };
842 const unsigned Xthal_int_type_edge = XCHAL_INTTYPE_MASK_EXTERN_EDGE;
843 const unsigned Xthal_int_type_level = XCHAL_INTTYPE_MASK_EXTERN_LEVEL;
844 const unsigned Xthal_int_type_timer = XCHAL_INTTYPE_MASK_TIMER;
845 const unsigned Xthal_int_type_software = XCHAL_INTTYPE_MASK_SOFTWARE;
846 #endif /* INCLUDE_DEPRECATED_HAL_CODE */
847
848
849 #endif /* SPLITs */
850
851