Initial cut of the open ath9k htc firmware.
[open-ath9k-htc-firmware.git] / target_firmware / magpie_fw_dev / build / magpie_1_1 / sboot / athos / src / xtos / xtos-internal.h
1 /*
2  * xtos-internal.h  --  internal definitions for single-threaded run-time
3  *
4  * Copyright (c) 2003-2010 Tensilica Inc.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sublicense, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25
26 #ifndef XTOS_INTERNAL_H
27 #define XTOS_INTERNAL_H
28
29 #include <xtensa/config/core.h>
30 #include <xtensa/xtruntime.h>
31 #include <xtensa/xtruntime-frames.h>
32 #include <xtensa/xtensa-versions.h>
33 #ifndef XTOS_PARAMS_H   /* this to allow indirect inclusion of this header from the outside */
34 #include "xtos-params.h"
35 #endif
36
37 /*  Relative ordering of subpriorities within an interrupt level (or vector):  */
38 #define XTOS_SPO_ZERO_LO        0       /* lower (eg. zero) numbered interrupts are lower  priority than higher numbered interrupts */
39 #define XTOS_SPO_ZERO_HI        1       /* lower (eg. zero) numbered interrupts are higher priority than higher numbered interrupts */
40
41
42 /*  Sanity check some parameters from xtos-params.h:  */
43 #if XTOS_LOCKLEVEL < XCHAL_EXCM_LEVEL || XTOS_LOCKLEVEL > 15
44 # error Invalid XTOS_LOCKLEVEL value, must be >= EXCM_LEVEL and <= 15, please fix xtos-params.h
45 #endif
46
47 /*  Mask of interrupts locked out at XTOS_LOCKLEVEL:  */
48 #define XTOS_LOCKOUT_MASK       XCHAL_INTLEVEL_ANDBELOW_MASK(XTOS_LOCKLEVEL)
49 /*  Mask of interrupts that can still be enabled at XTOS_LOCKLEVEL:  */
50 #define XTOS_UNLOCKABLE_MASK    (0xFFFFFFFF-XTOS_LOCKOUT_MASK)
51
52 /*  Don't set this:  */
53 #define XTOS_HIGHINT_TRAMP      0       /* mapping high-pri ints to low-pri not auto-supported */
54 #define XTOS_VIRTUAL_INTERRUPT  XTOS_HIGHINT_TRAMP      /* partially-virtualized INTERRUPT register not currently supported */
55 #if XTOS_HIGHINT_TRAMP
56 # error Automatically-generated high-level interrupt trampolines are not presently supported.
57 #endif
58
59 /*
60  *  If single interrupt at level-one, sub-prioritization is irrelevant:
61  */
62 #if defined(XCHAL_INTLEVEL1_NUM)
63 # undef XTOS_SUBPRI
64 # define XTOS_SUBPRI 0                  /* override - only one interrupt */
65 #endif
66
67 /*
68  *  In XEA1, the INTENABLE special register must be virtualized to provide
69  *  standard XTOS functionality.
70  *  In XEA2, this is only needed for software interrupt prioritization.
71  */
72 #if XTOS_SUBPRI || XCHAL_HAVE_XEA1
73 #define XTOS_VIRTUAL_INTENABLE  1
74 #else
75 #define XTOS_VIRTUAL_INTENABLE  0
76 #endif
77
78 /*
79  *  If single interrupt per priority, then fairness is irrelevant:
80  */
81 #if (XTOS_SUBPRI && !XTOS_SUBPRI_GROUPS) || defined(XCHAL_INTLEVEL1_NUM)
82 # undef XTOS_INT_FAIRNESS
83 # define XTOS_INT_FAIRNESS      0
84 #endif
85
86 /*  Identify special case interrupt handling code in int-lowpri-dispatcher.S:  */
87 #define XTOS_INT_SPECIALCASE    (XTOS_SUBPRI_ORDER == XTOS_SPO_ZERO_HI && XTOS_INT_FAIRNESS == 0 && XTOS_SUBPRI_GROUPS == 0)
88
89 /*
90  *  Determine whether to extend the interrupt entry array:
91  */
92 #define XIE_EXTEND              (XTOS_VIRTUAL_INTENABLE && !XTOS_INT_SPECIALCASE)
93
94 /*  If we have the NSAU instruction, ordering of interrupts is reversed in _xtos_interrupt_table[]:  */
95 #if XCHAL_HAVE_NSA
96 # define MAPINT(n)      ((XCHAL_NUM_INTERRUPTS-1)-(n))
97 # ifdef _ASMLANGUAGE
98         .macro  mapint  an
99         neg     \an, \an
100         addi    \an, \an, XCHAL_NUM_INTERRUPTS-1
101         .endm
102 # endif
103 #else /* no NSA */
104 # define MAPINT(n)      (n)
105 # ifdef _ASMLANGUAGE
106         .macro  mapint  an
107         .endm
108 # endif
109 #endif
110
111
112 #if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
113
114 /***********   Useful macros   ***********/
115
116 /*
117  *  A useful looping macro:
118  *  'iterate' invokes 'what' (an instruction, pseudo-op or other macro)
119  *  multiple times, passing it a numbered parameter from 'from' to 'to'
120  *  inclusively.  Does not invoke 'what' at all if from > to.
121  *  Maximum difference between 'from' and 'to' is 99 minus nesting depth
122  *  (GNU 'as' doesn't allow nesting deeper than 100).
123  */
124         .macro  iterate         from, to, what
125         .ifeq   ((\to-\from) & ~0xFFF)
126         \what   \from
127         iterate "(\from+1)", \to, \what
128         .endif
129         .endm   // iterate
130
131
132
133         //  rsilft
134         //
135         //  Execute RSIL \ar, \tolevel if \tolevel is different than \fromlevel.
136         //  This way the RSIL is avoided if we know at assembly time that
137         //  it will not change the level.  Typically, this means the \ar register
138         //  is ignored, ie. RSIL is used only to change PS.INTLEVEL.
139         //
140         .macro  rsilft  ar, fromlevel, tolevel
141 #if XCHAL_HAVE_INTERRUPTS
142         .if \fromlevel - \tolevel
143         rsil    \ar, \tolevel
144         .endif
145 #endif
146         .endm
147
148
149         //  Save LOOP and MAC16 registers, if configured, to the exception stack
150         //  frame pointed to by address register \esf, using \aa and \ab as temporaries.
151         //
152         //  This macro essentially saves optional registers that the compiler uses by
153         //  default when present.
154         //  Note that the acclo/acchi subset of MAC16 may be used even if others
155         //  multipliers are present (e.g. mul16, mul32).
156         //
157         //  Only two temp registers required for this code to be optimal (no interlocks) in both
158         //  T10xx (Athens) and Xtensa LX microarchitectures (both 5 and 7 stage pipes):
159         //
160         .macro  save_loops_mac16        esf, aa, ab
161 #if XCHAL_HAVE_LOOPS
162         rsr     \aa, LCOUNT
163         rsr     \ab, LBEG
164         s32i    \aa, \esf, UEXC_lcount
165         rsr     \aa, LEND
166         s32i    \ab, \esf, UEXC_lbeg
167         s32i    \aa, \esf, UEXC_lend
168 #endif
169 #if XCHAL_HAVE_MAC16
170         rsr     \aa, ACCLO
171         rsr     \ab, ACCHI
172         s32i    \aa, \esf, UEXC_acclo
173         s32i    \ab, \esf, UEXC_acchi
174 # if XTOS_SAVE_ALL_MAC16
175         rsr     \aa, M0
176         rsr     \ab, M1
177         s32i    \aa, \esf, UEXC_mr + 0
178         s32i    \ab, \esf, UEXC_mr + 4
179         rsr     \aa, M2
180         rsr     \ab, M3
181         s32i    \aa, \esf, UEXC_mr + 8
182         s32i    \ab, \esf, UEXC_mr + 12
183 # endif
184 #endif
185         .endm
186
187         //  Restore LOOP and MAC16 registers, if configured, from the exception stack
188         //  frame pointed to by address register \esf, using \aa, \ab and \ac as temporaries.
189         //
190         //  Three temp registers are required for this code to be optimal (no interlocks) in
191         //  Xtensa LX microarchitectures with 7-stage pipe; otherwise only two
192         //  registers would be needed.
193         //
194         .macro  restore_loops_mac16     esf, aa, ab, ac
195 #if XCHAL_HAVE_LOOPS
196         l32i    \aa, \esf, UEXC_lcount
197         l32i    \ab, \esf, UEXC_lbeg
198         l32i    \ac, \esf, UEXC_lend
199         wsr     \aa, LCOUNT
200         wsr     \ab, LBEG
201         wsr     \ac, LEND
202 #endif
203 #if XCHAL_HAVE_MAC16
204         l32i    \aa, \esf, UEXC_acclo
205         l32i    \ab, \esf, UEXC_acchi
206 # if XTOS_SAVE_ALL_MAC16
207         l32i    \ac, \esf, UEXC_mr + 0
208         wsr     \aa, ACCLO
209         wsr     \ab, ACCHI
210         wsr     \ac, M0
211         l32i    \aa, \esf, UEXC_mr + 4
212         l32i    \ab, \esf, UEXC_mr + 8
213         l32i    \ac, \esf, UEXC_mr + 12
214         wsr     \aa, M1
215         wsr     \ab, M2
216         wsr     \ac, M3
217 # else
218         wsr     \aa, ACCLO
219         wsr     \ab, ACCHI
220 # endif
221 #endif
222         .endm
223
224
225 /*  Offsets from _xtos_intstruct structure:  */
226         .struct 0
227 #if XTOS_VIRTUAL_INTENABLE
228 XTOS_ENABLED_OFS:       .space  4       /* _xtos_enabled variable */
229 XTOS_VPRI_ENABLED_OFS:  .space  4       /* _xtos_vpri_enabled variable */
230 #endif
231 #if XTOS_VIRTUAL_INTERRUPT
232 XTOS_PENDING_OFS:       .space  4       /* _xtos_pending variable */
233 #endif
234         .text
235
236
237 #if XTOS_VIRTUAL_INTENABLE
238         // Update INTENABLE register, computing it as follows:
239         //      INTENABLE = _xtos_enabled & _xtos_vpri_enabled
240         //                      [ & ~_xtos_pending ]
241         //
242         // Entry:
243         //      register ax = &_xtos_intstruct
244         //      register ay, az undefined (temporaries)
245         //      PS.INTLEVEL set to XTOS_LOCKLEVEL or higher (eg. via xtos_lock)
246         //      window overflows prevented (PS.WOE=0, PS.EXCM=1, or overflows
247         //              already done for registers ax, ay, az)
248         //
249         // Exit:
250         //      registers ax, ay, az clobbered
251         //      PS unchanged
252         //      caller needs to SYNC (?) for INTENABLE changes to take effect
253         //
254         // Note: in other software prioritization schemes/implementations,
255         // the term <_xtos_vpri_enabled> in the above expression is often
256         // replaced with another expression that computes the set of
257         // interrupts allowed to be enabled at the current software virtualized
258         // interrupt priority.
259         //
260         // For example, a simple alternative implementation of software
261         // prioritization for XTOS might have been the following:
262         //      INTENABLE = _xtos_enabled & (vpri_enabled | UNLOCKABLE_MASK)
263         // which removes the need for the interrupt dispatcher to 'or' the
264         // UNLOCKABLE_MASK bits into _xtos_vpri_enabled, and lets other code
265         // disable all lockout level interrupts by just clearing _xtos_vpri_enabled
266         // rather than setting it to UNLOCKABLE_MASK.
267         // Other implementations sometimes use a table, eg:
268         //      INTENABLE = _xtos_enabled & enable_table[current_vpri]
269         // The HAL (used by some 3rd party OSes) uses essentially a table-driven
270         // version, with other tables enabling run-time changing of priorities.
271         //
272         .macro  xtos_update_intenable   ax, ay, az
273         //movi  \ax, _xtos_intstruct
274         l32i    \ay, \ax, XTOS_VPRI_ENABLED_OFS         // ay = _xtos_vpri_enabled
275         l32i    \az, \ax, XTOS_ENABLED_OFS              // az = _xtos_enabled
276         //interlock
277         and     \az, \az, \ay           // az = _xtos_enabled & _xtos_vpri_enabled
278 # if XTOS_VIRTUAL_INTERRUPT
279         l32i    \ay, \ax, XTOS_PENDING_OFS              // ay = _xtos_pending
280         movi    \ax, -1
281         xor     \ay, \ay, \ax           // ay = ~_xtos_pending
282         and     \az, \az, \ay           // az &= ~_xtos_pending
283 # endif
284         wsr     \az, INTENABLE
285         .endm
286 #endif /* VIRTUAL_INTENABLE */
287
288         .macro  xtos_lock       ax
289         rsil    \ax, XTOS_LOCKLEVEL     // lockout
290         .endm
291
292         .macro  xtos_unlock     ax
293         wsr     \ax, PS                 // unlock
294         rsync
295         .endm
296
297 /*  Offsets to XtosIntHandlerEntry structure fields (see below):  */
298 # define XIE_HANDLER    0
299 # define XIE_ARG        4
300 # define XIE_SIZE       8
301 # if XIE_EXTEND
302 #  define XIE_VPRIMASK  (XIE_SIZE*XCHAL_NUM_INTERRUPTS+0)       /* if VIRTUAL_INTENABLE [SUBPRI||XEA1] && !SPECIALCASE */
303 #  define XIE_LEVELMASK (XIE_SIZE*XCHAL_NUM_INTERRUPTS+4)       /* [fairness preloop]  if FAIRNESS && SUBPRI [&& SUBPRI_GROUPS] */
304 # endif
305
306 /*  To simplify code:  */
307 # if XCHAL_HAVE_NSA
308 #  define IFNSA(a,b)    a
309 # else
310 #  define IFNSA(a,b)    b
311 # endif
312
313 #else /* !_ASMLANGUAGE && !__ASSEMBLER__ */
314
315 /*
316  *  Interrupt handler table entry.
317  *  Unregistered entries have 'handler' point to _xtos_unhandled_interrupt().
318  */
319 typedef struct XtosIntHandlerEntry {
320     _xtos_handler       handler;
321     void *              arg;
322 } XtosIntHandlerEntry;
323 # if XIE_EXTEND
324 typedef struct XtosIntMaskEntry {
325     unsigned            vpri_mask;      /* mask of interrupts enabled when this interrupt is taken */
326     unsigned            level_mask;     /* mask of interrupts at this interrupt's level */
327 } XtosIntMaskEntry;
328 # endif
329
330 #endif /* !_ASMLANGUAGE && !__ASSEMBLER__ */
331
332 /*
333  *  Notes...
334  *
335  *  XEA1 and interrupt-SUBPRIoritization both imply virtualization of INTENABLE.
336  *  Synchronous trampoloines imply partial virtualization of the INTERRUPT
337  *  register, which in turn also implies virtualization of INTENABLE register.
338  *  High-level interrupts manipulating the set of enabled interrupts implies
339  *  at least a high XTOS_LOCK_LEVEL, although not necessarily INTENABLE virtualization.
340  *
341  *  With INTENABLE register virtualization, at all times the INTENABLE
342  *  register reflects the expression:
343  *      (set of interrupts enabled) & (set of interrupts enabled by current
344  *                                      virtual priority)
345  *
346  *  Unrelated (DBREAK semantics):
347  *
348  *      A[31-6] = DBA[3-6]
349  *      ---------------------
350  *      A[5-0] & DBC[5-C] & szmask
351  *
352  *      = DBA[5-0] & szmask
353  *                      ^___  ???
354  */
355
356
357 /*  Report whether the XSR instruction is available (conservative):  */
358 #define HAVE_XSR        (XCHAL_HAVE_XEA2 || !XCHAL_HAVE_EXCEPTIONS)
359 /*
360  *  This is more accurate, but not a reliable test in software releases prior to 6.0
361  *  (where the targeted hardware parameter was not explicit in the XPG):
362  *
363  *#define HAVE_XSR      (XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_T1040_0)
364  */
365
366
367
368 /* Macros for supporting hi-level and medium-level interrupt handling. */
369
370 #if XCHAL_NUM_INTLEVELS > 6
371 #error Template files (*-template.S) limit support to interrupt levels <= 6
372 #endif
373
374 #if  defined(__XTENSA_WINDOWED_ABI__) && XCHAL_HAVE_CALL4AND12 == 0
375 #error CALL8-only is not supported!
376 #endif
377
378 #define INTERRUPT_IS_HI(level)  \
379         ( XCHAL_HAVE_INTERRUPTS && \
380          (XCHAL_EXCM_LEVEL < level) && \
381          (XCHAL_NUM_INTLEVELS >= level) && \
382          (XCHAL_HAVE_DEBUG ? XCHAL_DEBUGLEVEL != level : 1))
383
384 #define INTERRUPT_IS_MED(level) \
385         (XCHAL_HAVE_INTERRUPTS && (XCHAL_EXCM_LEVEL >= level))
386
387
388 #define _JOIN(x,y)      x ## y
389 #define JOIN(x,y)       _JOIN(x,y)
390
391 #define _JOIN3(a,b,c)   a ## b ## c
392 #define JOIN3(a,b,c)    _JOIN3(a,b,c)
393
394 #define LABEL(x,y)              JOIN3(x,_INTERRUPT_LEVEL,y)
395 #define EXCSAVE_LEVEL           JOIN(EXCSAVE_,_INTERRUPT_LEVEL)
396 #define INTLEVEL_VSIZE          JOIN3(XSHAL_INTLEVEL,_INTERRUPT_LEVEL,_VECTOR_SIZE)
397
398
399
400 #endif /* XTOS_INTERNAL_H */
401