OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [arch/] [mips/] [vr4181/] [common/] [int_handler.S] - Rev 1765

Compare with Previous | Blame | View Log

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

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.