Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | /* * 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) |