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