Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * Copyright (C) 1995, 1996, 1997 Paul M. Antoine and Harald Koerfgen
0004  * Copyright (C) 2000, 2001, 2002, 2003, 2005  Maciej W. Rozycki
0005  *
0006  * Written by Ralf Baechle and Andreas Busse, modified for DECstation
0007  * support by Paul Antoine and Harald Koerfgen.
0008  *
0009  * completely rewritten:
0010  * Copyright (C) 1998 Harald Koerfgen
0011  *
0012  * Rewritten extensively for controller-driven IRQ support
0013  * by Maciej W. Rozycki.
0014  */
0015 
0016 #include <asm/addrspace.h>
0017 #include <asm/asm.h>
0018 #include <asm/mipsregs.h>
0019 #include <asm/regdef.h>
0020 #include <asm/stackframe.h>
0021 
0022 #include <asm/dec/interrupts.h>
0023 #include <asm/dec/ioasic_addrs.h>
0024 #include <asm/dec/ioasic_ints.h>
0025 #include <asm/dec/kn01.h>
0026 #include <asm/dec/kn02.h>
0027 #include <asm/dec/kn02xa.h>
0028 #include <asm/dec/kn03.h>
0029 
0030 #define KN02_CSR_BASE       CKSEG1ADDR(KN02_SLOT_BASE + KN02_CSR)
0031 #define KN02XA_IOASIC_BASE  CKSEG1ADDR(KN02XA_SLOT_BASE + IOASIC_IOCTL)
0032 #define KN03_IOASIC_BASE    CKSEG1ADDR(KN03_SLOT_BASE + IOASIC_IOCTL)
0033 
0034         .text
0035         .set    noreorder
0036 /*
0037  * plat_irq_dispatch: Interrupt handler for DECstations
0038  *
0039  * We follow the model in the Indy interrupt code by David Miller, where he
0040  * says: a lot of complication here is taken away because:
0041  *
0042  * 1) We handle one interrupt and return, sitting in a loop
0043  *    and moving across all the pending IRQ bits in the cause
0044  *    register is _NOT_ the answer, the common case is one
0045  *    pending IRQ so optimize in that direction.
0046  *
0047  * 2) We need not check against bits in the status register
0048  *    IRQ mask, that would make this routine slow as hell.
0049  *
0050  * 3) Linux only thinks in terms of all IRQs on or all IRQs
0051  *    off, nothing in between like BSD spl() brain-damage.
0052  *
0053  * Furthermore, the IRQs on the DECstations look basically (barring
0054  * software IRQs which we don't use at all) like...
0055  *
0056  * DS2100/3100's, aka kn01, aka Pmax:
0057  *
0058  *  MIPS IRQ    Source
0059  *  --------    ------
0060  *         0    Software (ignored)
0061  *         1    Software (ignored)
0062  *         2    SCSI
0063  *         3    Lance Ethernet
0064  *         4    DZ11 serial
0065  *         5    RTC
0066  *         6    Memory Controller & Video
0067  *         7    FPU
0068  *
0069  * DS5000/200, aka kn02, aka 3max:
0070  *
0071  *  MIPS IRQ    Source
0072  *  --------    ------
0073  *         0    Software (ignored)
0074  *         1    Software (ignored)
0075  *         2    TurboChannel
0076  *         3    RTC
0077  *         4    Reserved
0078  *         5    Memory Controller
0079  *         6    Reserved
0080  *         7    FPU
0081  *
0082  * DS5000/1xx's, aka kn02ba, aka 3min:
0083  *
0084  *  MIPS IRQ    Source
0085  *  --------    ------
0086  *         0    Software (ignored)
0087  *         1    Software (ignored)
0088  *         2    TurboChannel Slot 0
0089  *         3    TurboChannel Slot 1
0090  *         4    TurboChannel Slot 2
0091  *         5    TurboChannel Slot 3 (ASIC)
0092  *         6    Halt button
0093  *         7    FPU/R4k timer
0094  *
0095  * DS5000/2x's, aka kn02ca, aka maxine:
0096  *
0097  *  MIPS IRQ    Source
0098  *  --------    ------
0099  *         0    Software (ignored)
0100  *         1    Software (ignored)
0101  *         2    Periodic Interrupt (100usec)
0102  *         3    RTC
0103  *         4    I/O write timeout
0104  *         5    TurboChannel (ASIC)
0105  *         6    Halt Keycode from Access.Bus keyboard (CTRL-ALT-ENTER)
0106  *         7    FPU/R4k timer
0107  *
0108  * DS5000/2xx's, aka kn03, aka 3maxplus:
0109  *
0110  *  MIPS IRQ    Source
0111  *  --------    ------
0112  *         0    Software (ignored)
0113  *         1    Software (ignored)
0114  *         2    System Board (ASIC)
0115  *         3    RTC
0116  *         4    Reserved
0117  *         5    Memory
0118  *         6    Halt Button
0119  *         7    FPU/R4k timer
0120  *
0121  * We handle the IRQ according to _our_ priority (see setup.c),
0122  * then we just return.  If multiple IRQs are pending then we will
0123  * just take another exception, big deal.
0124  */
0125         .align  5
0126         NESTED(plat_irq_dispatch, PT_SIZE, ra)
0127         .set    noreorder
0128 
0129         /*
0130          * Get pending Interrupts
0131          */
0132         mfc0    t0,CP0_CAUSE        # get pending interrupts
0133         mfc0    t1,CP0_STATUS
0134 #if defined(CONFIG_32BIT) && defined(CONFIG_MIPS_FP_SUPPORT)
0135         lw  t2,cpu_fpu_mask
0136 #endif
0137         andi    t0,ST0_IM       # CAUSE.CE may be non-zero!
0138         and t0,t1           # isolate allowed ones
0139 
0140         beqz    t0,spurious
0141 
0142 #if defined(CONFIG_32BIT) && defined(CONFIG_MIPS_FP_SUPPORT)
0143          and    t2,t0
0144         bnez    t2,fpu          # handle FPU immediately
0145 #endif
0146 
0147         /*
0148          * Find irq with highest priority
0149          */
0150         # open coded PTR_LA t1, cpu_mask_nr_tbl
0151 #if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
0152         # open coded la t1, cpu_mask_nr_tbl
0153         lui t1, %hi(cpu_mask_nr_tbl)
0154         addiu   t1, %lo(cpu_mask_nr_tbl)
0155 #else
0156 #error GCC `-msym32' option required for 64-bit DECstation builds
0157 #endif
0158 1:      lw  t2,(t1)
0159         nop
0160         and t2,t0
0161         beqz    t2,1b
0162          addu   t1,2*PTRSIZE        # delay slot
0163 
0164         /*
0165          * Do the low-level stuff
0166          */
0167         lw  a0,(-PTRSIZE)(t1)
0168         nop
0169         bgez    a0,handle_it        # irq_nr >= 0?
0170                         # irq_nr < 0: it is an address
0171          nop
0172         jr  a0
0173                         # a trick to save a branch:
0174          lui    t2,(KN03_IOASIC_BASE>>16)&0xffff
0175                         # upper part of IOASIC Address
0176 
0177 /*
0178  * Handle "IRQ Controller" Interrupts
0179  * Masked Interrupts are still visible and have to be masked "by hand".
0180  */
0181         FEXPORT(kn02_io_int)        # 3max
0182         lui t0,(KN02_CSR_BASE>>16)&0xffff
0183                         # get interrupt status and mask
0184         lw  t0,(t0)
0185         nop
0186         andi    t1,t0,KN02_IRQ_ALL
0187         b   1f
0188          srl    t0,16           # shift interrupt mask
0189 
0190         FEXPORT(kn02xa_io_int)      # 3min/maxine
0191         lui t2,(KN02XA_IOASIC_BASE>>16)&0xffff
0192                         # upper part of IOASIC Address
0193 
0194         FEXPORT(kn03_io_int)        # 3max+ (t2 loaded earlier)
0195         lw  t0,IO_REG_SIR(t2)   # get status: IOASIC sir
0196         lw  t1,IO_REG_SIMR(t2)  # get mask:   IOASIC simr
0197         nop
0198 
0199 1:      and t0,t1           # mask out allowed ones
0200 
0201         beqz    t0,spurious
0202 
0203         /*
0204          * Find irq with highest priority
0205          */
0206         # open coded PTR_LA t1,asic_mask_nr_tbl
0207 #if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
0208         # open coded la t1, asic_mask_nr_tbl
0209         lui t1, %hi(asic_mask_nr_tbl)
0210         addiu   t1, %lo(asic_mask_nr_tbl)
0211 #else
0212 #error GCC `-msym32' option required for 64-bit DECstation builds
0213 #endif
0214 2:      lw  t2,(t1)
0215         nop
0216         and t2,t0
0217         beq zero,t2,2b
0218          addu   t1,2*PTRSIZE        # delay slot
0219 
0220         /*
0221          * Do the low-level stuff
0222          */
0223         lw  a0,%lo(-PTRSIZE)(t1)
0224         nop
0225         bgez    a0,handle_it        # irq_nr >= 0?
0226                         # irq_nr < 0: it is an address
0227          nop
0228         jr  a0
0229          nop                # delay slot
0230 
0231 /*
0232  * Dispatch low-priority interrupts.  We reconsider all status
0233  * bits again, which looks like a lose, but it makes the code
0234  * simple and O(log n), so it gets compensated.
0235  */
0236         FEXPORT(cpu_all_int)        # HALT, timers, software junk
0237         li  a0,DEC_CPU_IRQ_BASE
0238         srl t0,CAUSEB_IP
0239         li  t1,CAUSEF_IP>>CAUSEB_IP # mask
0240         b   1f
0241          li t2,4            # nr of bits / 2
0242 
0243         FEXPORT(kn02_all_int)       # impossible ?
0244         li  a0,KN02_IRQ_BASE
0245         li  t1,KN02_IRQ_ALL     # mask
0246         b   1f
0247          li t2,4            # nr of bits / 2
0248 
0249         FEXPORT(asic_all_int)       # various I/O ASIC junk
0250         li  a0,IO_IRQ_BASE
0251         li  t1,IO_IRQ_ALL       # mask
0252         b   1f
0253          li t2,8            # nr of bits / 2
0254 
0255 /*
0256  * Dispatch DMA interrupts -- O(log n).
0257  */
0258         FEXPORT(asic_dma_int)       # I/O ASIC DMA events
0259         li  a0,IO_IRQ_BASE+IO_INR_DMA
0260         srl t0,IO_INR_DMA
0261         li  t1,IO_IRQ_DMA>>IO_INR_DMA # mask
0262         li  t2,8            # nr of bits / 2
0263 
0264         /*
0265          * Find irq with highest priority.
0266          * Highest irq number takes precedence.
0267          */
0268 1:      srlv    t3,t1,t2
0269 2:      xor t1,t3
0270         and t3,t0,t1
0271         beqz    t3,3f
0272          nop
0273         move    t0,t3
0274         addu    a0,t2
0275 3:      srl t2,1
0276         bnez    t2,2b
0277          srlv   t3,t1,t2
0278 
0279 handle_it:
0280         j   dec_irq_dispatch
0281          nop
0282 
0283 #if defined(CONFIG_32BIT) && defined(CONFIG_MIPS_FP_SUPPORT)
0284 fpu:
0285         lw  t0,fpu_kstat_irq
0286         nop
0287         lw  t1,(t0)
0288         nop
0289         addu    t1,1
0290         j   handle_fpe_int
0291          sw t1,(t0)
0292 #endif
0293 
0294 spurious:
0295         j   spurious_interrupt
0296          nop
0297         END(plat_irq_dispatch)
0298 
0299 /*
0300  * Generic unimplemented interrupt routines -- cpu_mask_nr_tbl
0301  * and asic_mask_nr_tbl are initialized to point all interrupts here.
0302  * The tables are then filled in by machine-specific initialisation
0303  * in dec_setup().
0304  */
0305         FEXPORT(dec_intr_unimplemented)
0306         move    a1,t0           # cheats way of printing an arg!
0307         ASM_PANIC("Unimplemented cpu interrupt! CP0_CAUSE: 0x%08x");
0308 
0309         FEXPORT(asic_intr_unimplemented)
0310         move    a1,t0           # cheats way of printing an arg!
0311         ASM_PANIC("Unimplemented asic interrupt! ASIC ISR: 0x%08x");