root/arch/mips/dec/int-handler.S

/* [<][>][^][v][top][bottom][index][help] */
   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 #ifdef CONFIG_32BIT
 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 #ifdef CONFIG_32BIT
 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 #ifdef CONFIG_32BIT
 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                 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                 PANIC("Unimplemented asic interrupt! ASIC ISR: 0x%08x");

/* [<][>][^][v][top][bottom][index][help] */