207 lines
3.7 KiB
ArmAsm
207 lines
3.7 KiB
ArmAsm
/*
|
|
* 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)
|