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 */
16
17#include <asm/asm.h>
18#include <asm/regdef.h>
19#include <asm/mipsregs.h>
20#include <asm/stackframe.h>
21
22#include <asm/vr4181/vr4181.h>
23
24/*
25 * [jsun]
26 * See include/asm/vr4181/irq.h for IRQ assignment and strategy.
27 */
28
29	.text
30	.set	noreorder
31
32	.align	5
33	NESTED(vr4181_handle_irq, PT_SIZE, ra)
34
35	.set	noat
36	SAVE_ALL
37	CLI
38
39	.set	at
40	.set	noreorder
41
42	mfc0	t0, CP0_CAUSE
43	mfc0	t2, CP0_STATUS
44
45	and	t0, t2
46
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
65
66	.set	reorder
67do_spurious:
68	j	spurious_interrupt
69
70/*
71 * regular CPU irqs
72 */
73ll_cputimer_irq:
74	li	a0, VR4181_IRQ_TIMER
75	move	a1, sp
76	jal	do_IRQ
77	j	ret_from_irq
78
79
80ll_cpu_ip0:
81	li	a0, VR4181_IRQ_SW1
82	move	a1, sp
83	jal	do_IRQ
84	j	ret_from_irq
85
86ll_cpu_ip1:
87	li	a0, VR4181_IRQ_SW2
88	move	a1, sp
89	jal	do_IRQ
90	j	ret_from_irq
91
92ll_cpu_ip3:
93	li	a0, VR4181_IRQ_INT1
94	move	a1, sp
95	jal	do_IRQ
96	j	ret_from_irq
97
98ll_cpu_ip4:
99	li	a0, VR4181_IRQ_INT2
100	move	a1, sp
101	jal	do_IRQ
102	j	ret_from_irq
103
104ll_cpu_ip5:
105	li	a0, VR4181_IRQ_INT3
106	move	a1, sp
107	jal	do_IRQ
108	j	ret_from_irq
109
110ll_cpu_ip6:
111	li	a0, VR4181_IRQ_INT4
112	move	a1, sp
113	jal	do_IRQ
114	j	ret_from_irq
115
116/*
117 *  One of the sys irq has happend.
118 *
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)
124 *
125 *  Then we do binary search to find the exact interrupt source.
126 */
127ll_cpu_ip2:
128
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
135
136	/* check for GPIO interrupts */
137	andi	t1, t0, 0x0100
138	bnez	t1, check_gpio_int
139
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
143
144check_sysint2:
145
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
152
153check_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
161
162/*
163 *  When we reach check_16, we have 16-bit status in t0 and base irq number
164 *  in a0.
165 */
166check_16:
167	andi	t1, t0, 0xff
168	bnez	t1, check_8
169
170	srl	t0, 8
171	addi	a0, 8
172	j	check_8
173
174/*
175 *  When we reach check_8, we have 8-bit status in t0 and base irq number
176 *  in a0.
177 */
178check_8:
179	andi	t1, t0, 0xf
180	bnez	t1, check_4
181
182	srl	t0, 4
183	addi	a0, 4
184	j	check_4
185
186/*
187 *  When we reach check_4, we have 4-bit status in t0 and base irq number
188 *  in a0.
189 */
190check_4:
191	andi	t0, t0, 0xf
192	beqz	t0, do_spurious
193
194loop:
195	andi	t2, t0, 0x1
196	srl	t0, 1
197	addi	a0, 1
198	beqz	t2, loop
199
200found_it:
201	move	a1, sp
202	jal	do_IRQ
203
204	j	ret_from_irq
205
206	END(vr4181_handle_irq)
207