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 / int-highpri-template.S
1 // High-Priority Interrupt Handler Template
2 // $Id: //depot/rel/Cottonwood/Xtensa/OS/xtos/int-highpri-template.S#3 $
3
4 // Copyright (c) 2004-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 // This file provides skeleton code for writing high-priority interrupt
27 // handlers in assembler for performance.
28 //
29 // By default, this file is included by inth-template.S .
30 // The default Makefile defines _INTERRUPT_LEVEL when assembling
31 // inth-template.S for each medium and high priority interrupt level.
32 //
33 // To use this template file, define a macro called _INTERRUPT_LEVEL
34 // to be the interrupt priority level of the vector, then include this file.
35
36
37 #include <xtensa/coreasm.h>
38 #include "xtos-internal.h"
39
40
41 #if XCHAL_HAVE_INTERRUPTS
42
43 #define INTERRUPT_MASK          XCHAL_INTLEVEL_MASK(_INTERRUPT_LEVEL)
44 #define SINGLE_INTERRUPT        (INTERRUPT_MASK & (INTERRUPT_MASK - 1) == 0)
45 #define SINGLE_INT_NUM          XCHAL_INTLEVEL_NUM(_INTERRUPT_LEVEL)
46
47
48 //  NOTE:  It is strongly recommended that high-priority
49 //  interrupt handlers be written in assembly.
50 //
51 //  High-priority interrupt handlers can be written in C,
52 //  but only at the cost of an unreasonable amount of state
53 //  save and restore (including the entire physical address
54 //  register file and others, see int-highpri-dispatcher.S)
55 //  that makes high-priority interrupt dispatching much slower
56 //  than for low and medium priority interrupts.
57 //  (Low and medium priority interrupts are masked by atomic
58 //   register window operations, so they take advantage of a
59 //   coherent window state for fast entry.  High priority
60 //   interrupts are not masked by window operations so they
61 //   can interrupt them, leading to a potentially incoherent
62 //   window state at the time of the interrupt.  Given that
63 //   high priority handlers must save and restore everything
64 //   they touch, they end up needing to save and restore the
65 //   entire window state [physical address register file etc.]
66 //   and all exception state which they can also interrupt.)
67 //  See also the Microprocessor Programmer's Guide.
68
69 //  High-priority interrupts are designed to be very fast and with
70 //  very low latency.
71 //  Typical high-priority interrupt service routines are kept
72 //  relatively small and fast.  Either there is little to do,
73 //  or the routine handles only the necessary high priority
74 //  activities related to a device and leaves the rest
75 //  (other more complex and time-consuming activities)
76 //  to be scheduled later, eg. by triggering a level-one
77 //  (low-priority) or medium-priority software interrupt whose
78 //  handler can be written in C for the more extensive processing.
79
80 //  NOTE:  The following handler is just skeleton example
81 //  code.  It is NOT a functional handler.  For software, edge-
82 //  triggered and write-error interrupts, it simply does nothing
83 //  and return.  For other types (timer and level-triggered),
84 //  this code does not clear the source(s) of interrupt,
85 //  hence if any interrupt at this priority level are both enabled
86 //  and triggered, the processor repeatedly takes the interrupt
87 //  in a loop.  This is all okay as a default, because
88 //  XTOS (and other operating systems) clears the INTENABLE
89 //  register at startup, requiring the application to
90 //  enable specific interrupts before they can be taken.
91 //  So as long as you don't enable any interrupt of this
92 //  priority level, this example handler will never execute.
93
94 // Exports
95 .global LABEL(_Level,FromVector)
96
97         .data
98         .align  4
99 LABEL(int,save):
100         .space  4       // save area
101
102         .text
103         .align  4
104 LABEL(_Level,FromVector):
105         //  The vectoring code has already saved a2 in EXCSAVEn.
106         //  Save any other registers we'll use:
107         movi    a2, LABEL(int,save)
108         s32i    a1, a2, 0
109         //  ... add more as needed (increase save area accordingly) ...
110
111         //  WRITE YOUR INTERRUPT HANDLING CODE HERE...
112
113         //  If multiple interrupts are mapped to this priority level,
114         //  you'll probably need to distinguish which interrupt(s)
115         //  occurred by reading the INTERRUPT (INTREAD) and
116         //  INTENABLE registers, and'ing them together, and
117         //  looking at what bits are set in both.
118         //  If any of the interrupts are level-triggered, be ready
119         //  to handle the case where no interrupts are to be handled
120         //  -- this is called a spurious interrupt, and can happen
121         //  when the level-triggered interrupt line goes inactive
122         //  after the interrupt is taken but before the INTERRUPT
123         //  register is read.
124
125         //  You'll also normally want to clear the source of
126         //  the interrupt before returning, to avoid getting
127         //  the same interrupt again immediately.  For illustration,
128         //  this code clears all software, edge-triggered, and
129         //  write-error interrupts at this priority level (if any).
130         //  NOTE: Timer interrupts must be cleared by writing to
131         //  the corresponding CCOMPAREn register; and level-sensitive
132         //  interrupts can only be cleared externally, usually by
133         //  requesting the associated device to do so (in a
134         //  device-specific manner).
135         //
136         movi    a1, INTERRUPT_MASK
137         wsr     a1, INTCLEAR
138
139         //  Restore registers:
140         l32i    a1, a2, 0
141 #if HAVE_XSR
142         movi    a2, LABEL(_Level,FromVector)    // restore handler address
143         xsr     a2, EXCSAVE_LEVEL
144 #else
145         rsr     a2, EXCSAVE_LEVEL
146 #endif
147         //  ... add more if more are saved above ...
148
149         //  Return:
150         rfi     _INTERRUPT_LEVEL
151
152         .size   LABEL(_Level,FromVector), . - LABEL(_Level,FromVector)
153
154 #endif /* XCHAL_HAVE_INTERRUPTS */