blob: 14ef800a564d811a58335b782b0c0e3baa3251c0 [file] [log] [blame]
Bryan Wu1394f032007-05-06 14:50:22 -07001/*
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>
Robin Getz669b7922007-06-21 16:34:08 +080037#include <asm/trace.h>
Bryan Wu1394f032007-05-06 14:50:22 -070038
39#include <asm/mach-common/context.S>
40
41#ifdef CONFIG_I_ENTRY_L1
42.section .l1.text
43#else
44.text
45#endif
46
47.align 4 /* just in case */
48
49/*
50 * initial interrupt handlers
51 */
52
53#ifndef CONFIG_KGDB
54 /* interrupt routine for emulation - 0 */
55 /* Currently used only if GDB stub is not in - invalid */
56 /* gdb-stub set the evt itself */
57 /* save registers for post-mortem only */
58ENTRY(_evt_emulation)
59 SAVE_ALL_SYS
60#ifdef CONFIG_FRAME_POINTER
61 fp = 0;
62#endif
63 r0 = IRQ_EMU;
64 r1 = sp;
65 SP += -12;
66 call _irq_panic;
67 SP += 12;
68 /* - GDB stub fills this in by itself (if defined) */
69 rte;
Mike Frysinger51be24c2007-06-11 15:31:30 +080070ENDPROC(_evt_emulation)
Bryan Wu1394f032007-05-06 14:50:22 -070071#endif
72
73/* Common interrupt entry code. First we do CLI, then push
74 * RETI, to keep interrupts disabled, but to allow this state to be changed
75 * by local_bh_enable.
76 * R0 contains the interrupt number, while R1 may contain the value of IPEND,
77 * or garbage if IPEND won't be needed by the ISR. */
78__common_int_entry:
79 [--sp] = fp;
80 [--sp] = usp;
81
82 [--sp] = i0;
83 [--sp] = i1;
84 [--sp] = i2;
85 [--sp] = i3;
86
87 [--sp] = m0;
88 [--sp] = m1;
89 [--sp] = m2;
90 [--sp] = m3;
91
92 [--sp] = l0;
93 [--sp] = l1;
94 [--sp] = l2;
95 [--sp] = l3;
96
97 [--sp] = b0;
98 [--sp] = b1;
99 [--sp] = b2;
100 [--sp] = b3;
101 [--sp] = a0.x;
102 [--sp] = a0.w;
103 [--sp] = a1.x;
104 [--sp] = a1.w;
105
106 [--sp] = LC0;
107 [--sp] = LC1;
108 [--sp] = LT0;
109 [--sp] = LT1;
110 [--sp] = LB0;
111 [--sp] = LB1;
112
113 [--sp] = ASTAT;
114
115 [--sp] = r0; /* Skip reserved */
116 [--sp] = RETS;
117 r2 = RETI;
118 [--sp] = r2;
119 [--sp] = RETX;
120 [--sp] = RETN;
121 [--sp] = RETE;
122 [--sp] = SEQSTAT;
123 [--sp] = r1; /* IPEND - R1 may or may not be set up before jumping here. */
124
125 /* Switch to other method of keeping interrupts disabled. */
126#ifdef CONFIG_DEBUG_HWERR
127 r1 = 0x3f;
128 sti r1;
129#else
130 cli r1;
131#endif
132 [--sp] = RETI; /* orig_pc */
133 /* Clear all L registers. */
134 r1 = 0 (x);
135 l0 = r1;
136 l1 = r1;
137 l2 = r1;
138 l3 = r1;
139#ifdef CONFIG_FRAME_POINTER
140 fp = 0;
141#endif
142
Mike Frysinger1aafd902007-07-25 11:19:14 +0800143#if ANOMALY_05000283 || ANOMALY_05000315
Bryan Wu1394f032007-05-06 14:50:22 -0700144 cc = r7 == r7;
145 p5.h = 0xffc0;
146 p5.l = 0x0014;
147 if cc jump 1f;
148 r7.l = W[p5];
1491:
150#endif
151 r1 = sp;
152 SP += -12;
153 call _do_irq;
154 SP += 12;
155 call _return_from_int;
156.Lcommon_restore_context:
157 RESTORE_CONTEXT
158 rti;
159
160/* interrupt routine for ivhw - 5 */
161ENTRY(_evt_ivhw)
162 SAVE_CONTEXT
163#ifdef CONFIG_FRAME_POINTER
164 fp = 0;
165#endif
Mike Frysinger1aafd902007-07-25 11:19:14 +0800166#if ANOMALY_05000283
Bryan Wu1394f032007-05-06 14:50:22 -0700167 cc = r7 == r7;
168 p5.h = 0xffc0;
169 p5.l = 0x0014;
170 if cc jump 1f;
171 r7.l = W[p5];
1721:
173#endif
Robin Getz669b7922007-06-21 16:34:08 +0800174
175 trace_buffer_stop(p0, r0);
176
Bryan Wu1394f032007-05-06 14:50:22 -0700177 r0 = IRQ_HWERR;
178 r1 = sp;
179
180#ifdef CONFIG_HARDWARE_PM
181 r7 = SEQSTAT;
182 r7 = r7 >>> 0xe;
183 r6 = 0x1F;
184 r7 = r7 & r6;
185 r5 = 0x12;
186 cc = r7 == r5;
187 if cc jump .Lcall_do_ovf; /* deal with performance counter overflow */
188#endif
189
190 SP += -12;
191 call _irq_panic;
192 SP += 12;
193 rti;
194#ifdef CONFIG_HARDWARE_PM
195.Lcall_do_ovf:
196
197 SP += -12;
198 call _pm_overflow;
199 SP += 12;
200
201 jump .Lcommon_restore_context;
202#endif
203
204/* interrupt routine for evt2 - 2. This is NMI. */
205ENTRY(_evt_evt2)
206 SAVE_CONTEXT
207#ifdef CONFIG_FRAME_POINTER
208 fp = 0;
209#endif
Mike Frysinger1aafd902007-07-25 11:19:14 +0800210#if ANOMALY_05000283
Bryan Wu1394f032007-05-06 14:50:22 -0700211 cc = r7 == r7;
212 p5.h = 0xffc0;
213 p5.l = 0x0014;
214 if cc jump 1f;
215 r7.l = W[p5];
2161:
217#endif
218 r0 = IRQ_NMI;
219 r1 = sp;
220 SP += -12;
221 call _asm_do_IRQ;
222 SP += 12;
223 RESTORE_CONTEXT
224 rtn;
225
226/* interrupt routine for core timer - 6 */
227ENTRY(_evt_timer)
228 TIMER_INTERRUPT_ENTRY(EVT_IVTMR_P)
229
230/* interrupt routine for evt7 - 7 */
231ENTRY(_evt_evt7)
232 INTERRUPT_ENTRY(EVT_IVG7_P)
233ENTRY(_evt_evt8)
234 INTERRUPT_ENTRY(EVT_IVG8_P)
235ENTRY(_evt_evt9)
236 INTERRUPT_ENTRY(EVT_IVG9_P)
237ENTRY(_evt_evt10)
238 INTERRUPT_ENTRY(EVT_IVG10_P)
239ENTRY(_evt_evt11)
240 INTERRUPT_ENTRY(EVT_IVG11_P)
241ENTRY(_evt_evt12)
242 INTERRUPT_ENTRY(EVT_IVG12_P)
243ENTRY(_evt_evt13)
244 INTERRUPT_ENTRY(EVT_IVG13_P)
245
246
247 /* interrupt routine for system_call - 15 */
248ENTRY(_evt_system_call)
249 SAVE_CONTEXT_SYSCALL
250#ifdef CONFIG_FRAME_POINTER
251 fp = 0;
252#endif
253 call _system_call;
254 jump .Lcommon_restore_context;
Mike Frysinger51be24c2007-06-11 15:31:30 +0800255ENDPROC(_evt_system_call)