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