import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / arch / mips / dec / int-handler.S
1 /*
2  * arch/mips/dec/int-handler.S
3  *
4  * Copyright (C) 1995, 1996, 1997 Paul M. Antoine and Harald Koerfgen
5  * Copyright (C) 2000, 2001, 2002, 2003  Maciej W. Rozycki
6  *
7  * Written by Ralf Baechle and Andreas Busse, modified for DECStation
8  * 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  */
16 #include <asm/asm.h>
17 #include <asm/regdef.h>
18 #include <asm/mipsregs.h>
19 #include <asm/stackframe.h>
20 #include <asm/addrspace.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
31                 .text
32                 .set    noreorder
33 /*
34  * decstation_handle_int: Interrupt handler for DECStations
35  *
36  * We follow the model in the Indy interrupt code by David Miller, where he
37  * says: a lot of complication here is taken away because:
38  *
39  * 1) We handle one interrupt and return, sitting in a loop
40  *    and moving across all the pending IRQ bits in the cause
41  *    register is _NOT_ the answer, the common case is one
42  *    pending IRQ so optimize in that direction.
43  *
44  * 2) We need not check against bits in the status register
45  *    IRQ mask, that would make this routine slow as hell.
46  *
47  * 3) Linux only thinks in terms of all IRQs on or all IRQs
48  *    off, nothing in between like BSD spl() brain-damage.
49  *
50  * Furthermore, the IRQs on the DECStations look basically (barring
51  * software IRQs which we don't use at all) like...
52  *
53  * DS2100/3100's, aka kn01, aka Pmax:
54  *
55  *      MIPS IRQ        Source
56  *      --------        ------
57  *             0        Software (ignored)
58  *             1        Software (ignored)
59  *             2        SCSI
60  *             3        Lance Ethernet
61  *             4        DZ11 serial
62  *             5        RTC
63  *             6        Memory Controller
64  *             7        FPU
65  *
66  * DS5000/200, aka kn02, aka 3max:
67  *
68  *      MIPS IRQ        Source
69  *      --------        ------
70  *             0        Software (ignored)
71  *             1        Software (ignored)
72  *             2        TurboChannel
73  *             3        RTC
74  *             4        Reserved
75  *             5        Memory Controller
76  *             6        Reserved
77  *             7        FPU
78  *
79  * DS5000/1xx's, aka kn02ba, aka 3min:
80  *
81  *      MIPS IRQ        Source
82  *      --------        ------
83  *             0        Software (ignored)
84  *             1        Software (ignored)
85  *             2        TurboChannel Slot 0
86  *             3        TurboChannel Slot 1
87  *             4        TurboChannel Slot 2
88  *             5        TurboChannel Slot 3 (ASIC)
89  *             6        Halt button
90  *             7        FPU/R4k timer
91  *
92  * DS5000/2x's, aka kn02ca, aka maxine:
93  *
94  *      MIPS IRQ        Source
95  *      --------        ------
96  *             0        Software (ignored)
97  *             1        Software (ignored)
98  *             2        Periodic Interrupt (100usec)
99  *             3        RTC
100  *             4        I/O write timeout
101  *             5        TurboChannel (ASIC)
102  *             6        Halt Keycode from Access.Bus keyboard (CTRL-ALT-ENTER)
103  *             7        FPU/R4k timer
104  *
105  * DS5000/2xx's, aka kn03, aka 3maxplus:
106  *
107  *      MIPS IRQ        Source
108  *      --------        ------
109  *             0        Software (ignored)
110  *             1        Software (ignored)
111  *             2        System Board (ASIC)
112  *             3        RTC
113  *             4        Reserved
114  *             5        Memory
115  *             6        Halt Button
116  *             7        FPU/R4k timer
117  *
118  * We handle the IRQ according to _our_ priority (see setup.c),
119  * then we just return.  If multiple IRQs are pending then we will
120  * just take another exception, big deal.
121  */
122                 .align  5
123                 NESTED(decstation_handle_int, PT_SIZE, ra)
124                 .set    noat
125                 SAVE_ALL
126                 CLI                             # TEST: interrupts should be off
127                 .set    at
128                 .set    noreorder
129
130                 /*
131                  * Get pending Interrupts
132                  */
133                 mfc0    t0,CP0_CAUSE            # get pending interrupts
134                 mfc0    t1,CP0_STATUS
135 #ifdef CONFIG_MIPS32
136                 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
143 #ifdef CONFIG_MIPS32
144                  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
152 1:              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
193 1:              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
201 2:              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                  */
255 1:              srlv    t3,t1,t2
256 2:              xor     t1,t3
257                 and     t3,t0,t1
258                 beqz    t3,3f
259                  nop
260                 move    t0,t3
261                 addu    a0,t2
262 3:              srl     t2,1
263                 bnez    t2,2b
264                  srlv   t3,t1,t2
265
266 handle_it:
267                 jal     do_IRQ
268                  move   a1,sp
269
270                 j       ret_from_irq
271                  nop
272
273 #ifdef CONFIG_MIPS32
274 fpu:
275                 j       handle_fpe_int
276                  nop
277 #endif
278
279 spurious:
280                 j       spurious_interrupt
281                  nop
282                 END(decstation_handle_int)
283
284 /*
285  * Generic unimplemented interrupt routines -- cpu_mask_nr_tbl
286  * and asic_mask_nr_tbl are initialized to point all interrupts here.
287  * The tables are then filled in by machine-specific initialisation
288  * in dec_setup().
289  */
290                 FEXPORT(dec_intr_unimplemented)
291                 move    a1,t0                   # cheats way of printing an arg!
292                 PANIC("Unimplemented cpu interrupt! CP0_CAUSE: 0x%08x");
293
294                 FEXPORT(asic_intr_unimplemented)
295                 move    a1,t0                   # cheats way of printing an arg!
296                 PANIC("Unimplemented asic interrupt! ASIC ISR: 0x%08x");