Linux-2.6.12-rc2
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / arch / mips / vr4181 / common / int_handler.S
blob2c041b8ee52be092bc5095a35f34a7f27c609a90
1 /*
2  * arch/mips/vr4181/common/int_handler.S
3  *
4  * Adapted to the VR4181 and almost entirely rewritten:
5  * Copyright (C) 1999 Bradley D. LaRonde and Michael Klar
6  *
7  * Clean up to conform to the new IRQ
8  * Copyright (C) 2001 MontaVista Software Inc.
9  * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
10  *
11  * This file is subject to the terms and conditions of the GNU General Public
12  * License.  See the file "COPYING" in the main directory of this archive
13  * for more details.
14  *
15  */
17 #include <asm/asm.h>
18 #include <asm/regdef.h>
19 #include <asm/mipsregs.h>
20 #include <asm/stackframe.h>
22 #include <asm/vr4181/vr4181.h>
25  * [jsun]
26  * See include/asm/vr4181/irq.h for IRQ assignment and strategy.
27  */
29         .text
30         .set    noreorder
32         .align  5
33         NESTED(vr4181_handle_irq, PT_SIZE, ra)
35         .set    noat
36         SAVE_ALL
37         CLI
39         .set    at
40         .set    noreorder
42         mfc0    t0, CP0_CAUSE
43         mfc0    t2, CP0_STATUS
45         and     t0, t2
47         /* we check IP3 first; it happens most frequently */
48         andi    t1, t0, STATUSF_IP3
49         bnez    t1, ll_cpu_ip3
50         andi    t1, t0, STATUSF_IP2
51         bnez    t1, ll_cpu_ip2
52         andi    t1, t0, STATUSF_IP7     /* cpu timer */
53         bnez    t1, ll_cputimer_irq
54         andi    t1, t0, STATUSF_IP4
55         bnez    t1, ll_cpu_ip4
56         andi    t1, t0, STATUSF_IP5
57         bnez    t1, ll_cpu_ip5
58         andi    t1, t0, STATUSF_IP6
59         bnez    t1, ll_cpu_ip6
60         andi    t1, t0, STATUSF_IP0     /* software int 0 */
61         bnez    t1, ll_cpu_ip0
62         andi    t1, t0, STATUSF_IP1     /* software int 1 */
63         bnez    t1, ll_cpu_ip1
64         nop
66         .set    reorder
67 do_spurious:
68         j       spurious_interrupt
71  * regular CPU irqs
72  */
73 ll_cputimer_irq:
74         li      a0, VR4181_IRQ_TIMER
75         move    a1, sp
76         jal     do_IRQ
77         j       ret_from_irq
80 ll_cpu_ip0:
81         li      a0, VR4181_IRQ_SW1
82         move    a1, sp
83         jal     do_IRQ
84         j       ret_from_irq
86 ll_cpu_ip1:
87         li      a0, VR4181_IRQ_SW2
88         move    a1, sp
89         jal     do_IRQ
90         j       ret_from_irq
92 ll_cpu_ip3:
93         li      a0, VR4181_IRQ_INT1
94         move    a1, sp
95         jal     do_IRQ
96         j       ret_from_irq
98 ll_cpu_ip4:
99         li      a0, VR4181_IRQ_INT2
100         move    a1, sp
101         jal     do_IRQ
102         j       ret_from_irq
104 ll_cpu_ip5:
105         li      a0, VR4181_IRQ_INT3
106         move    a1, sp
107         jal     do_IRQ
108         j       ret_from_irq
110 ll_cpu_ip6:
111         li      a0, VR4181_IRQ_INT4
112         move    a1, sp
113         jal     do_IRQ
114         j       ret_from_irq
117  *  One of the sys irq has happend.
119  *  In the interest of speed, we first determine in the following order
120  *  which 16-irq block have pending interrupts:
121  *      sysint1 (16 sources, including cascading intrs from GPIO)
122  *      sysint2
123  *      gpio (16 intr sources)
125  *  Then we do binary search to find the exact interrupt source.
126  */
127 ll_cpu_ip2:
129         lui     t3,%hi(VR4181_SYSINT1REG)
130         lhu     t0,%lo(VR4181_SYSINT1REG)(t3)
131         lhu     t2,%lo(VR4181_MSYSINT1REG)(t3)
132         and     t0, 0xfffb              /* hack - remove RTC Long 1 intr */
133         and     t0, t2
134         beqz    t0, check_sysint2
136         /* check for GPIO interrupts */
137         andi    t1, t0, 0x0100
138         bnez    t1, check_gpio_int
140         /* so we have an interrupt in sysint1 which is not gpio int */
141         li      a0, VR4181_SYS_IRQ_BASE - 1
142         j       check_16
144 check_sysint2:
146         lhu     t0,%lo(VR4181_SYSINT2REG)(t3)
147         lhu     t2,%lo(VR4181_MSYSINT2REG)(t3)
148         and     t0, 0xfffe              /* hack - remove RTC Long 2 intr */
149         and     t0, t2
150         li      a0, VR4181_SYS_IRQ_BASE + 16 - 1
151         j       check_16
153 check_gpio_int:
154         lui     t3,%hi(VR4181_GPINTMSK)
155         lhu     t0,%lo(VR4181_GPINTMSK)(t3)
156         lhu     t2,%lo(VR4181_GPINTSTAT)(t3)
157         xori    t0, 0xffff                      /* why? reverse logic? */
158         and     t0, t2
159         li      a0, VR4181_GPIO_IRQ_BASE - 1
160         j       check_16
163  *  When we reach check_16, we have 16-bit status in t0 and base irq number
164  *  in a0.
165  */
166 check_16:
167         andi    t1, t0, 0xff
168         bnez    t1, check_8
170         srl     t0, 8
171         addi    a0, 8
172         j       check_8
175  *  When we reach check_8, we have 8-bit status in t0 and base irq number
176  *  in a0.
177  */
178 check_8:
179         andi    t1, t0, 0xf
180         bnez    t1, check_4
182         srl     t0, 4
183         addi    a0, 4
184         j       check_4
187  *  When we reach check_4, we have 4-bit status in t0 and base irq number
188  *  in a0.
189  */
190 check_4:
191         andi    t0, t0, 0xf
192         beqz    t0, do_spurious
194 loop:
195         andi    t2, t0, 0x1
196         srl     t0, 1
197         addi    a0, 1
198         beqz    t2, loop
200 found_it:
201         move    a1, sp
202         jal     do_IRQ
204         j       ret_from_irq
206         END(vr4181_handle_irq)