blob: 2c041b8ee52be092bc5095a35f34a7f27c609a90 [file] [log] [blame]
/*
* 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 <asm/asm.h>
#include <asm/regdef.h>
#include <asm/mipsregs.h>
#include <asm/stackframe.h>
#include <asm/vr4181/vr4181.h>
/*
* [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)