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