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