linux/arch/mips/dec/int-handler.S
<<
>>
Prefs
   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 * completly 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                 PTR_LA t1,cpu_mask_nr_tbl
 1501:              lw      t2,(t1)
 151                nop
 152                and     t2,t0
 153                beqz    t2,1b
 154                 addu   t1,2*PTRSIZE            # delay slot
 155
 156                /*
 157                 * Do the low-level stuff
 158                 */
 159                lw      a0,(-PTRSIZE)(t1)
 160                nop
 161                bgez    a0,handle_it            # irq_nr >= 0?
 162                                                # irq_nr < 0: it is an address
 163                 nop
 164                jr      a0
 165                                                # a trick to save a branch:
 166                 lui    t2,(KN03_IOASIC_BASE>>16)&0xffff
 167                                                # upper part of IOASIC Address
 168
 169/*
 170 * Handle "IRQ Controller" Interrupts
 171 * Masked Interrupts are still visible and have to be masked "by hand".
 172 */
 173                FEXPORT(kn02_io_int)            # 3max
 174                lui     t0,(KN02_CSR_BASE>>16)&0xffff
 175                                                # get interrupt status and mask
 176                lw      t0,(t0)
 177                nop
 178                andi    t1,t0,KN02_IRQ_ALL
 179                b       1f
 180                 srl    t0,16                   # shift interrupt mask
 181
 182                FEXPORT(kn02xa_io_int)          # 3min/maxine
 183                lui     t2,(KN02XA_IOASIC_BASE>>16)&0xffff
 184                                                # upper part of IOASIC Address
 185
 186                FEXPORT(kn03_io_int)            # 3max+ (t2 loaded earlier)
 187                lw      t0,IO_REG_SIR(t2)       # get status: IOASIC sir
 188                lw      t1,IO_REG_SIMR(t2)      # get mask:   IOASIC simr
 189                nop
 190
 1911:              and     t0,t1                   # mask out allowed ones
 192
 193                beqz    t0,spurious
 194
 195                /*
 196                 * Find irq with highest priority
 197                 */
 198                 PTR_LA t1,asic_mask_nr_tbl
 1992:              lw      t2,(t1)
 200                nop
 201                and     t2,t0
 202                beq     zero,t2,2b
 203                 addu   t1,2*PTRSIZE            # delay slot
 204
 205                /*
 206                 * Do the low-level stuff
 207                 */
 208                lw      a0,%lo(-PTRSIZE)(t1)
 209                nop
 210                bgez    a0,handle_it            # irq_nr >= 0?
 211                                                # irq_nr < 0: it is an address
 212                 nop
 213                jr      a0
 214                 nop                            # delay slot
 215
 216/*
 217 * Dispatch low-priority interrupts.  We reconsider all status
 218 * bits again, which looks like a lose, but it makes the code
 219 * simple and O(log n), so it gets compensated.
 220 */
 221                FEXPORT(cpu_all_int)            # HALT, timers, software junk
 222                li      a0,DEC_CPU_IRQ_BASE
 223                srl     t0,CAUSEB_IP
 224                li      t1,CAUSEF_IP>>CAUSEB_IP # mask
 225                b       1f
 226                 li     t2,4                    # nr of bits / 2
 227
 228                FEXPORT(kn02_all_int)           # impossible ?
 229                li      a0,KN02_IRQ_BASE
 230                li      t1,KN02_IRQ_ALL         # mask
 231                b       1f
 232                 li     t2,4                    # nr of bits / 2
 233
 234                FEXPORT(asic_all_int)           # various I/O ASIC junk
 235                li      a0,IO_IRQ_BASE
 236                li      t1,IO_IRQ_ALL           # mask
 237                b       1f
 238                 li     t2,8                    # nr of bits / 2
 239
 240/*
 241 * Dispatch DMA interrupts -- O(log n).
 242 */
 243                FEXPORT(asic_dma_int)           # I/O ASIC DMA events
 244                li      a0,IO_IRQ_BASE+IO_INR_DMA
 245                srl     t0,IO_INR_DMA
 246                li      t1,IO_IRQ_DMA>>IO_INR_DMA # mask
 247                li      t2,8                    # nr of bits / 2
 248
 249                /*
 250                 * Find irq with highest priority.
 251                 * Highest irq number takes precedence.
 252                 */
 2531:              srlv    t3,t1,t2
 2542:              xor     t1,t3
 255                and     t3,t0,t1
 256                beqz    t3,3f
 257                 nop
 258                move    t0,t3
 259                addu    a0,t2
 2603:              srl     t2,1
 261                bnez    t2,2b
 262                 srlv   t3,t1,t2
 263
 264handle_it:
 265                j       dec_irq_dispatch
 266                 nop
 267
 268#ifdef CONFIG_32BIT
 269fpu:
 270                j       handle_fpe_int
 271                 nop
 272#endif
 273
 274spurious:
 275                j       spurious_interrupt
 276                 nop
 277                END(plat_irq_dispatch)
 278
 279/*
 280 * Generic unimplemented interrupt routines -- cpu_mask_nr_tbl
 281 * and asic_mask_nr_tbl are initialized to point all interrupts here.
 282 * The tables are then filled in by machine-specific initialisation
 283 * in dec_setup().
 284 */
 285                FEXPORT(dec_intr_unimplemented)
 286                move    a1,t0                   # cheats way of printing an arg!
 287                PANIC("Unimplemented cpu interrupt! CP0_CAUSE: 0x%08x");
 288
 289                FEXPORT(asic_intr_unimplemented)
 290                move    a1,t0                   # cheats way of printing an arg!
 291                PANIC("Unimplemented asic interrupt! ASIC ISR: 0x%08x");
 292