/* * arch/mips/vr4181/common/int_handler.S * * Adapted to the VR4181 and almost entirely rewritten: * Copyright (C) 1999 Bradley D. LaRonde and Michael Klar * * Clean up to conform to the new IRQ * Copyright (C) 2001 MontaVista Software Inc. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * */ #include #include #include #include #include /* * [jsun] * See include/asm/vr4181/irq.h for IRQ assignment and strategy. */ .text .set noreorder .align 5 NESTED(vr4181_handle_irq, PT_SIZE, ra) .set noat SAVE_ALL CLI .set at .set noreorder mfc0 t0, CP0_CAUSE mfc0 t2, CP0_STATUS and t0, t2 /* we check IP3 first; it happens most frequently */ andi t1, t0, STATUSF_IP3 bnez t1, ll_cpu_ip3 andi t1, t0, STATUSF_IP2 bnez t1, ll_cpu_ip2 andi t1, t0, STATUSF_IP7 /* cpu timer */ bnez t1, ll_cputimer_irq andi t1, t0, STATUSF_IP4 bnez t1, ll_cpu_ip4 andi t1, t0, STATUSF_IP5 bnez t1, ll_cpu_ip5 andi t1, t0, STATUSF_IP6 bnez t1, ll_cpu_ip6 andi t1, t0, STATUSF_IP0 /* software int 0 */ bnez t1, ll_cpu_ip0 andi t1, t0, STATUSF_IP1 /* software int 1 */ bnez t1, ll_cpu_ip1 nop .set reorder do_spurious: j spurious_interrupt /* * regular CPU irqs */ ll_cputimer_irq: li a0, VR4181_IRQ_TIMER move a1, sp jal do_IRQ j ret_from_irq ll_cpu_ip0: li a0, VR4181_IRQ_SW1 move a1, sp jal do_IRQ j ret_from_irq ll_cpu_ip1: li a0, VR4181_IRQ_SW2 move a1, sp jal do_IRQ j ret_from_irq ll_cpu_ip3: li a0, VR4181_IRQ_INT1 move a1, sp jal do_IRQ j ret_from_irq ll_cpu_ip4: li a0, VR4181_IRQ_INT2 move a1, sp jal do_IRQ j ret_from_irq ll_cpu_ip5: li a0, VR4181_IRQ_INT3 move a1, sp jal do_IRQ j ret_from_irq ll_cpu_ip6: li a0, VR4181_IRQ_INT4 move a1, sp jal do_IRQ j ret_from_irq /* * One of the sys irq has happend. * * In the interest of speed, we first determine in the following order * which 16-irq block have pending interrupts: * sysint1 (16 sources, including cascading intrs from GPIO) * sysint2 * gpio (16 intr sources) * * Then we do binary search to find the exact interrupt source. */ ll_cpu_ip2: lui t3,%hi(VR4181_SYSINT1REG) lhu t0,%lo(VR4181_SYSINT1REG)(t3) lhu t2,%lo(VR4181_MSYSINT1REG)(t3) and t0, 0xfffb /* hack - remove RTC Long 1 intr */ and t0, t2 beqz t0, check_sysint2 /* check for GPIO interrupts */ andi t1, t0, 0x0100 bnez t1, check_gpio_int /* so we have an interrupt in sysint1 which is not gpio int */ li a0, VR4181_SYS_IRQ_BASE - 1 j check_16 check_sysint2: lhu t0,%lo(VR4181_SYSINT2REG)(t3) lhu t2,%lo(VR4181_MSYSINT2REG)(t3) and t0, 0xfffe /* hack - remove RTC Long 2 intr */ and t0, t2 li a0, VR4181_SYS_IRQ_BASE + 16 - 1 j check_16 check_gpio_int: lui t3,%hi(VR4181_GPINTMSK) lhu t0,%lo(VR4181_GPINTMSK)(t3) lhu t2,%lo(VR4181_GPINTSTAT)(t3) xori t0, 0xffff /* why? reverse logic? */ and t0, t2 li a0, VR4181_GPIO_IRQ_BASE - 1 j check_16 /* * When we reach check_16, we have 16-bit status in t0 and base irq number * in a0. */ check_16: andi t1, t0, 0xff bnez t1, check_8 srl t0, 8 addi a0, 8 j check_8 /* * When we reach check_8, we have 8-bit status in t0 and base irq number * in a0. */ check_8: andi t1, t0, 0xf bnez t1, check_4 srl t0, 4 addi a0, 4 j check_4 /* * When we reach check_4, we have 4-bit status in t0 and base irq number * in a0. */ check_4: andi t0, t0, 0xf beqz t0, do_spurious loop: andi t2, t0, 0x1 srl t0, 1 addi a0, 1 beqz t2, loop found_it: move a1, sp jal do_IRQ j ret_from_irq END(vr4181_handle_irq)