123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- /*
- * 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)
|