blob: 00cecdcc75f215cb6e5a6581442774996fcc26f3 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * arch/mips/dec/int-handler.S
3 *
4 * Copyright (C) 1995, 1996, 1997 Paul M. Antoine and Harald Koerfgen
Maciej W. Rozyckia5fc9c02005-07-01 16:10:40 +00005 * Copyright (C) 2000, 2001, 2002, 2003, 2005 Maciej W. Rozycki
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 *
Maciej W. Rozyckia5fc9c02005-07-01 16:10:40 +00007 * Written by Ralf Baechle and Andreas Busse, modified for DECstation
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 * support by Paul Antoine and Harald Koerfgen.
9 *
10 * completly rewritten:
11 * Copyright (C) 1998 Harald Koerfgen
12 *
13 * Rewritten extensively for controller-driven IRQ support
14 * by Maciej W. Rozycki.
15 */
Maciej W. Rozyckia5fc9c02005-07-01 16:10:40 +000016
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include <asm/addrspace.h>
Maciej W. Rozyckia5fc9c02005-07-01 16:10:40 +000018#include <asm/asm.h>
19#include <asm/mipsregs.h>
20#include <asm/regdef.h>
21#include <asm/stackframe.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022
23#include <asm/dec/interrupts.h>
24#include <asm/dec/ioasic_addrs.h>
25#include <asm/dec/ioasic_ints.h>
26#include <asm/dec/kn01.h>
27#include <asm/dec/kn02.h>
28#include <asm/dec/kn02xa.h>
29#include <asm/dec/kn03.h>
30
Maciej W. Rozyckia5fc9c02005-07-01 16:10:40 +000031#define KN02_CSR_BASE CKSEG1ADDR(KN02_SLOT_BASE + KN02_CSR)
32#define KN02XA_IOASIC_BASE CKSEG1ADDR(KN02XA_SLOT_BASE + IOASIC_IOCTL)
33#define KN03_IOASIC_BASE CKSEG1ADDR(KN03_SLOT_BASE + IOASIC_IOCTL)
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
35 .text
36 .set noreorder
37/*
Ralf Baechlee4ac58a2006-04-03 17:56:36 +010038 * plat_irq_dispatch: Interrupt handler for DECstations
Linus Torvalds1da177e2005-04-16 15:20:36 -070039 *
40 * We follow the model in the Indy interrupt code by David Miller, where he
41 * says: a lot of complication here is taken away because:
42 *
43 * 1) We handle one interrupt and return, sitting in a loop
44 * and moving across all the pending IRQ bits in the cause
45 * register is _NOT_ the answer, the common case is one
46 * pending IRQ so optimize in that direction.
47 *
48 * 2) We need not check against bits in the status register
49 * IRQ mask, that would make this routine slow as hell.
50 *
51 * 3) Linux only thinks in terms of all IRQs on or all IRQs
52 * off, nothing in between like BSD spl() brain-damage.
53 *
Maciej W. Rozyckia5fc9c02005-07-01 16:10:40 +000054 * Furthermore, the IRQs on the DECstations look basically (barring
Linus Torvalds1da177e2005-04-16 15:20:36 -070055 * software IRQs which we don't use at all) like...
56 *
57 * DS2100/3100's, aka kn01, aka Pmax:
58 *
59 * MIPS IRQ Source
60 * -------- ------
61 * 0 Software (ignored)
62 * 1 Software (ignored)
63 * 2 SCSI
64 * 3 Lance Ethernet
65 * 4 DZ11 serial
66 * 5 RTC
Maciej W. Rozyckia5fc9c02005-07-01 16:10:40 +000067 * 6 Memory Controller & Video
Linus Torvalds1da177e2005-04-16 15:20:36 -070068 * 7 FPU
69 *
70 * DS5000/200, aka kn02, aka 3max:
71 *
72 * MIPS IRQ Source
73 * -------- ------
74 * 0 Software (ignored)
75 * 1 Software (ignored)
76 * 2 TurboChannel
77 * 3 RTC
78 * 4 Reserved
79 * 5 Memory Controller
80 * 6 Reserved
81 * 7 FPU
82 *
83 * DS5000/1xx's, aka kn02ba, aka 3min:
84 *
85 * MIPS IRQ Source
86 * -------- ------
87 * 0 Software (ignored)
88 * 1 Software (ignored)
89 * 2 TurboChannel Slot 0
90 * 3 TurboChannel Slot 1
91 * 4 TurboChannel Slot 2
92 * 5 TurboChannel Slot 3 (ASIC)
93 * 6 Halt button
94 * 7 FPU/R4k timer
95 *
96 * DS5000/2x's, aka kn02ca, aka maxine:
97 *
98 * MIPS IRQ Source
99 * -------- ------
100 * 0 Software (ignored)
101 * 1 Software (ignored)
102 * 2 Periodic Interrupt (100usec)
103 * 3 RTC
104 * 4 I/O write timeout
105 * 5 TurboChannel (ASIC)
106 * 6 Halt Keycode from Access.Bus keyboard (CTRL-ALT-ENTER)
107 * 7 FPU/R4k timer
108 *
109 * DS5000/2xx's, aka kn03, aka 3maxplus:
110 *
111 * MIPS IRQ Source
112 * -------- ------
113 * 0 Software (ignored)
114 * 1 Software (ignored)
115 * 2 System Board (ASIC)
116 * 3 RTC
117 * 4 Reserved
118 * 5 Memory
119 * 6 Halt Button
120 * 7 FPU/R4k timer
121 *
122 * We handle the IRQ according to _our_ priority (see setup.c),
123 * then we just return. If multiple IRQs are pending then we will
124 * just take another exception, big deal.
125 */
126 .align 5
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100127 NESTED(plat_irq_dispatch, PT_SIZE, ra)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 .set noreorder
129
130 /*
131 * Get pending Interrupts
132 */
133 mfc0 t0,CP0_CAUSE # get pending interrupts
134 mfc0 t1,CP0_STATUS
Ralf Baechle875d43e2005-09-03 15:56:16 -0700135#ifdef CONFIG_32BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 lw t2,cpu_fpu_mask
137#endif
138 andi t0,ST0_IM # CAUSE.CE may be non-zero!
139 and t0,t1 # isolate allowed ones
140
141 beqz t0,spurious
142
Ralf Baechle875d43e2005-09-03 15:56:16 -0700143#ifdef CONFIG_32BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 and t2,t0
145 bnez t2,fpu # handle FPU immediately
146#endif
147
148 /*
149 * Find irq with highest priority
150 */
151 PTR_LA t1,cpu_mask_nr_tbl
1521: lw t2,(t1)
153 nop
154 and t2,t0
155 beqz t2,1b
156 addu t1,2*PTRSIZE # delay slot
157
158 /*
159 * Do the low-level stuff
160 */
161 lw a0,(-PTRSIZE)(t1)
162 nop
163 bgez a0,handle_it # irq_nr >= 0?
164 # irq_nr < 0: it is an address
165 nop
166 jr a0
167 # a trick to save a branch:
168 lui t2,(KN03_IOASIC_BASE>>16)&0xffff
169 # upper part of IOASIC Address
170
171/*
172 * Handle "IRQ Controller" Interrupts
173 * Masked Interrupts are still visible and have to be masked "by hand".
174 */
175 FEXPORT(kn02_io_int) # 3max
176 lui t0,(KN02_CSR_BASE>>16)&0xffff
177 # get interrupt status and mask
178 lw t0,(t0)
179 nop
180 andi t1,t0,KN02_IRQ_ALL
181 b 1f
182 srl t0,16 # shift interrupt mask
183
184 FEXPORT(kn02xa_io_int) # 3min/maxine
185 lui t2,(KN02XA_IOASIC_BASE>>16)&0xffff
186 # upper part of IOASIC Address
187
188 FEXPORT(kn03_io_int) # 3max+ (t2 loaded earlier)
189 lw t0,IO_REG_SIR(t2) # get status: IOASIC sir
190 lw t1,IO_REG_SIMR(t2) # get mask: IOASIC simr
191 nop
192
1931: and t0,t1 # mask out allowed ones
194
195 beqz t0,spurious
196
197 /*
198 * Find irq with highest priority
199 */
200 PTR_LA t1,asic_mask_nr_tbl
2012: lw t2,(t1)
202 nop
203 and t2,t0
204 beq zero,t2,2b
205 addu t1,2*PTRSIZE # delay slot
206
207 /*
208 * Do the low-level stuff
209 */
210 lw a0,%lo(-PTRSIZE)(t1)
211 nop
212 bgez a0,handle_it # irq_nr >= 0?
213 # irq_nr < 0: it is an address
214 nop
215 jr a0
216 nop # delay slot
217
218/*
219 * Dispatch low-priority interrupts. We reconsider all status
220 * bits again, which looks like a lose, but it makes the code
221 * simple and O(log n), so it gets compensated.
222 */
223 FEXPORT(cpu_all_int) # HALT, timers, software junk
224 li a0,DEC_CPU_IRQ_BASE
225 srl t0,CAUSEB_IP
226 li t1,CAUSEF_IP>>CAUSEB_IP # mask
227 b 1f
228 li t2,4 # nr of bits / 2
229
230 FEXPORT(kn02_all_int) # impossible ?
231 li a0,KN02_IRQ_BASE
232 li t1,KN02_IRQ_ALL # mask
233 b 1f
234 li t2,4 # nr of bits / 2
235
236 FEXPORT(asic_all_int) # various I/O ASIC junk
237 li a0,IO_IRQ_BASE
238 li t1,IO_IRQ_ALL # mask
239 b 1f
240 li t2,8 # nr of bits / 2
241
242/*
243 * Dispatch DMA interrupts -- O(log n).
244 */
245 FEXPORT(asic_dma_int) # I/O ASIC DMA events
246 li a0,IO_IRQ_BASE+IO_INR_DMA
247 srl t0,IO_INR_DMA
248 li t1,IO_IRQ_DMA>>IO_INR_DMA # mask
249 li t2,8 # nr of bits / 2
250
251 /*
252 * Find irq with highest priority.
253 * Highest irq number takes precedence.
254 */
2551: srlv t3,t1,t2
2562: xor t1,t3
257 and t3,t0,t1
258 beqz t3,3f
259 nop
260 move t0,t3
261 addu a0,t2
2623: srl t2,1
263 bnez t2,2b
264 srlv t3,t1,t2
265
266handle_it:
Atsushi Nemoto187933f2006-10-25 23:57:04 +0900267 j dec_irq_dispatch
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 nop
269
Ralf Baechle875d43e2005-09-03 15:56:16 -0700270#ifdef CONFIG_32BIT
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271fpu:
272 j handle_fpe_int
273 nop
274#endif
275
276spurious:
Atsushi Nemotof431baa2006-10-09 01:24:23 +0900277 j spurious_interrupt
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 nop
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100279 END(plat_irq_dispatch)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280
281/*
282 * Generic unimplemented interrupt routines -- cpu_mask_nr_tbl
283 * and asic_mask_nr_tbl are initialized to point all interrupts here.
284 * The tables are then filled in by machine-specific initialisation
285 * in dec_setup().
286 */
287 FEXPORT(dec_intr_unimplemented)
288 move a1,t0 # cheats way of printing an arg!
289 PANIC("Unimplemented cpu interrupt! CP0_CAUSE: 0x%08x");
290
291 FEXPORT(asic_intr_unimplemented)
292 move a1,t0 # cheats way of printing an arg!
293 PANIC("Unimplemented asic interrupt! ASIC ISR: 0x%08x");