diff options
Diffstat (limited to 'arch/blackfin/mach-common/interrupt.S')
-rw-r--r-- | arch/blackfin/mach-common/interrupt.S | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S new file mode 100644 index 000000000000..dd45664f0d02 --- /dev/null +++ b/arch/blackfin/mach-common/interrupt.S | |||
@@ -0,0 +1,253 @@ | |||
1 | /* | ||
2 | * File: arch/blackfin/mach-common/interrupt.S | ||
3 | * Based on: | ||
4 | * Author: D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca> | ||
5 | * Kenneth Albanowski <kjahds@kjahds.com> | ||
6 | * | ||
7 | * Created: ? | ||
8 | * Description: Interrupt Entries | ||
9 | * | ||
10 | * Modified: | ||
11 | * Copyright 2004-2006 Analog Devices Inc. | ||
12 | * | ||
13 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, see the file COPYING, or write | ||
27 | * to the Free Software Foundation, Inc., | ||
28 | * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
29 | */ | ||
30 | |||
31 | #include <asm/blackfin.h> | ||
32 | #include <asm/mach/irq.h> | ||
33 | #include <linux/autoconf.h> | ||
34 | #include <linux/linkage.h> | ||
35 | #include <asm/entry.h> | ||
36 | #include <asm/asm-offsets.h> | ||
37 | |||
38 | #include <asm/mach-common/context.S> | ||
39 | |||
40 | #ifdef CONFIG_I_ENTRY_L1 | ||
41 | .section .l1.text | ||
42 | #else | ||
43 | .text | ||
44 | #endif | ||
45 | |||
46 | .align 4 /* just in case */ | ||
47 | |||
48 | /* | ||
49 | * initial interrupt handlers | ||
50 | */ | ||
51 | |||
52 | #ifndef CONFIG_KGDB | ||
53 | /* interrupt routine for emulation - 0 */ | ||
54 | /* Currently used only if GDB stub is not in - invalid */ | ||
55 | /* gdb-stub set the evt itself */ | ||
56 | /* save registers for post-mortem only */ | ||
57 | ENTRY(_evt_emulation) | ||
58 | SAVE_ALL_SYS | ||
59 | #ifdef CONFIG_FRAME_POINTER | ||
60 | fp = 0; | ||
61 | #endif | ||
62 | r0 = IRQ_EMU; | ||
63 | r1 = sp; | ||
64 | SP += -12; | ||
65 | call _irq_panic; | ||
66 | SP += 12; | ||
67 | /* - GDB stub fills this in by itself (if defined) */ | ||
68 | rte; | ||
69 | #endif | ||
70 | |||
71 | /* Common interrupt entry code. First we do CLI, then push | ||
72 | * RETI, to keep interrupts disabled, but to allow this state to be changed | ||
73 | * by local_bh_enable. | ||
74 | * R0 contains the interrupt number, while R1 may contain the value of IPEND, | ||
75 | * or garbage if IPEND won't be needed by the ISR. */ | ||
76 | __common_int_entry: | ||
77 | [--sp] = fp; | ||
78 | [--sp] = usp; | ||
79 | |||
80 | [--sp] = i0; | ||
81 | [--sp] = i1; | ||
82 | [--sp] = i2; | ||
83 | [--sp] = i3; | ||
84 | |||
85 | [--sp] = m0; | ||
86 | [--sp] = m1; | ||
87 | [--sp] = m2; | ||
88 | [--sp] = m3; | ||
89 | |||
90 | [--sp] = l0; | ||
91 | [--sp] = l1; | ||
92 | [--sp] = l2; | ||
93 | [--sp] = l3; | ||
94 | |||
95 | [--sp] = b0; | ||
96 | [--sp] = b1; | ||
97 | [--sp] = b2; | ||
98 | [--sp] = b3; | ||
99 | [--sp] = a0.x; | ||
100 | [--sp] = a0.w; | ||
101 | [--sp] = a1.x; | ||
102 | [--sp] = a1.w; | ||
103 | |||
104 | [--sp] = LC0; | ||
105 | [--sp] = LC1; | ||
106 | [--sp] = LT0; | ||
107 | [--sp] = LT1; | ||
108 | [--sp] = LB0; | ||
109 | [--sp] = LB1; | ||
110 | |||
111 | [--sp] = ASTAT; | ||
112 | |||
113 | [--sp] = r0; /* Skip reserved */ | ||
114 | [--sp] = RETS; | ||
115 | r2 = RETI; | ||
116 | [--sp] = r2; | ||
117 | [--sp] = RETX; | ||
118 | [--sp] = RETN; | ||
119 | [--sp] = RETE; | ||
120 | [--sp] = SEQSTAT; | ||
121 | [--sp] = r1; /* IPEND - R1 may or may not be set up before jumping here. */ | ||
122 | |||
123 | /* Switch to other method of keeping interrupts disabled. */ | ||
124 | #ifdef CONFIG_DEBUG_HWERR | ||
125 | r1 = 0x3f; | ||
126 | sti r1; | ||
127 | #else | ||
128 | cli r1; | ||
129 | #endif | ||
130 | [--sp] = RETI; /* orig_pc */ | ||
131 | /* Clear all L registers. */ | ||
132 | r1 = 0 (x); | ||
133 | l0 = r1; | ||
134 | l1 = r1; | ||
135 | l2 = r1; | ||
136 | l3 = r1; | ||
137 | #ifdef CONFIG_FRAME_POINTER | ||
138 | fp = 0; | ||
139 | #endif | ||
140 | |||
141 | #ifdef ANOMALY_05000283 | ||
142 | cc = r7 == r7; | ||
143 | p5.h = 0xffc0; | ||
144 | p5.l = 0x0014; | ||
145 | if cc jump 1f; | ||
146 | r7.l = W[p5]; | ||
147 | 1: | ||
148 | #endif | ||
149 | r1 = sp; | ||
150 | SP += -12; | ||
151 | call _do_irq; | ||
152 | SP += 12; | ||
153 | call _return_from_int; | ||
154 | .Lcommon_restore_context: | ||
155 | RESTORE_CONTEXT | ||
156 | rti; | ||
157 | |||
158 | /* interrupt routine for ivhw - 5 */ | ||
159 | ENTRY(_evt_ivhw) | ||
160 | SAVE_CONTEXT | ||
161 | #ifdef CONFIG_FRAME_POINTER | ||
162 | fp = 0; | ||
163 | #endif | ||
164 | #ifdef ANOMALY_05000283 | ||
165 | cc = r7 == r7; | ||
166 | p5.h = 0xffc0; | ||
167 | p5.l = 0x0014; | ||
168 | if cc jump 1f; | ||
169 | r7.l = W[p5]; | ||
170 | 1: | ||
171 | #endif | ||
172 | p0.l = lo(TBUFCTL); | ||
173 | p0.h = hi(TBUFCTL); | ||
174 | r0 = 1; | ||
175 | [p0] = r0; | ||
176 | r0 = IRQ_HWERR; | ||
177 | r1 = sp; | ||
178 | |||
179 | #ifdef CONFIG_HARDWARE_PM | ||
180 | r7 = SEQSTAT; | ||
181 | r7 = r7 >>> 0xe; | ||
182 | r6 = 0x1F; | ||
183 | r7 = r7 & r6; | ||
184 | r5 = 0x12; | ||
185 | cc = r7 == r5; | ||
186 | if cc jump .Lcall_do_ovf; /* deal with performance counter overflow */ | ||
187 | #endif | ||
188 | |||
189 | SP += -12; | ||
190 | call _irq_panic; | ||
191 | SP += 12; | ||
192 | rti; | ||
193 | #ifdef CONFIG_HARDWARE_PM | ||
194 | .Lcall_do_ovf: | ||
195 | |||
196 | SP += -12; | ||
197 | call _pm_overflow; | ||
198 | SP += 12; | ||
199 | |||
200 | jump .Lcommon_restore_context; | ||
201 | #endif | ||
202 | |||
203 | /* interrupt routine for evt2 - 2. This is NMI. */ | ||
204 | ENTRY(_evt_evt2) | ||
205 | SAVE_CONTEXT | ||
206 | #ifdef CONFIG_FRAME_POINTER | ||
207 | fp = 0; | ||
208 | #endif | ||
209 | #ifdef ANOMALY_05000283 | ||
210 | cc = r7 == r7; | ||
211 | p5.h = 0xffc0; | ||
212 | p5.l = 0x0014; | ||
213 | if cc jump 1f; | ||
214 | r7.l = W[p5]; | ||
215 | 1: | ||
216 | #endif | ||
217 | r0 = IRQ_NMI; | ||
218 | r1 = sp; | ||
219 | SP += -12; | ||
220 | call _asm_do_IRQ; | ||
221 | SP += 12; | ||
222 | RESTORE_CONTEXT | ||
223 | rtn; | ||
224 | |||
225 | /* interrupt routine for core timer - 6 */ | ||
226 | ENTRY(_evt_timer) | ||
227 | TIMER_INTERRUPT_ENTRY(EVT_IVTMR_P) | ||
228 | |||
229 | /* interrupt routine for evt7 - 7 */ | ||
230 | ENTRY(_evt_evt7) | ||
231 | INTERRUPT_ENTRY(EVT_IVG7_P) | ||
232 | ENTRY(_evt_evt8) | ||
233 | INTERRUPT_ENTRY(EVT_IVG8_P) | ||
234 | ENTRY(_evt_evt9) | ||
235 | INTERRUPT_ENTRY(EVT_IVG9_P) | ||
236 | ENTRY(_evt_evt10) | ||
237 | INTERRUPT_ENTRY(EVT_IVG10_P) | ||
238 | ENTRY(_evt_evt11) | ||
239 | INTERRUPT_ENTRY(EVT_IVG11_P) | ||
240 | ENTRY(_evt_evt12) | ||
241 | INTERRUPT_ENTRY(EVT_IVG12_P) | ||
242 | ENTRY(_evt_evt13) | ||
243 | INTERRUPT_ENTRY(EVT_IVG13_P) | ||
244 | |||
245 | |||
246 | /* interrupt routine for system_call - 15 */ | ||
247 | ENTRY(_evt_system_call) | ||
248 | SAVE_CONTEXT_SYSCALL | ||
249 | #ifdef CONFIG_FRAME_POINTER | ||
250 | fp = 0; | ||
251 | #endif | ||
252 | call _system_call; | ||
253 | jump .Lcommon_restore_context; | ||