au_icu.c revision 1.2.6.3 1 1.2.6.3 jdolecek /* $NetBSD: au_icu.c,v 1.2.6.3 2002/10/10 18:34:03 jdolecek Exp $ */
2 1.2.6.2 jdolecek
3 1.2.6.2 jdolecek /*-
4 1.2.6.2 jdolecek * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 1.2.6.2 jdolecek * All rights reserved.
6 1.2.6.2 jdolecek *
7 1.2.6.2 jdolecek * This code is derived from software contributed to The NetBSD Foundation
8 1.2.6.2 jdolecek * by Jason R. Thorpe.
9 1.2.6.2 jdolecek *
10 1.2.6.2 jdolecek * Redistribution and use in source and binary forms, with or without
11 1.2.6.2 jdolecek * modification, are permitted provided that the following conditions
12 1.2.6.2 jdolecek * are met:
13 1.2.6.2 jdolecek * 1. Redistributions of source code must retain the above copyright
14 1.2.6.2 jdolecek * notice, this list of conditions and the following disclaimer.
15 1.2.6.2 jdolecek * 2. Redistributions in binary form must reproduce the above copyright
16 1.2.6.2 jdolecek * notice, this list of conditions and the following disclaimer in the
17 1.2.6.2 jdolecek * documentation and/or other materials provided with the distribution.
18 1.2.6.2 jdolecek * 3. All advertising materials mentioning features or use of this software
19 1.2.6.2 jdolecek * must display the following acknowledgement:
20 1.2.6.2 jdolecek * This product includes software developed by the NetBSD
21 1.2.6.2 jdolecek * Foundation, Inc. and its contributors.
22 1.2.6.2 jdolecek * 4. Neither the name of The NetBSD Foundation nor the names of its
23 1.2.6.2 jdolecek * contributors may be used to endorse or promote products derived
24 1.2.6.2 jdolecek * from this software without specific prior written permission.
25 1.2.6.2 jdolecek *
26 1.2.6.2 jdolecek * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 1.2.6.2 jdolecek * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 1.2.6.2 jdolecek * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 1.2.6.2 jdolecek * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 1.2.6.2 jdolecek * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 1.2.6.2 jdolecek * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 1.2.6.2 jdolecek * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 1.2.6.2 jdolecek * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 1.2.6.2 jdolecek * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 1.2.6.2 jdolecek * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 1.2.6.2 jdolecek * POSSIBILITY OF SUCH DAMAGE.
37 1.2.6.2 jdolecek */
38 1.2.6.2 jdolecek
39 1.2.6.2 jdolecek /*
40 1.2.6.2 jdolecek * Interrupt support for the Alchemy Semiconductor Au1x00 CPUs.
41 1.2.6.2 jdolecek *
42 1.2.6.2 jdolecek * The Alchemy Semiconductor Au1x00's interrupts are wired to two internal
43 1.2.6.2 jdolecek * interrupt controllers.
44 1.2.6.2 jdolecek */
45 1.2.6.2 jdolecek
46 1.2.6.2 jdolecek #include "opt_ddb.h"
47 1.2.6.2 jdolecek
48 1.2.6.2 jdolecek #include <sys/param.h>
49 1.2.6.2 jdolecek #include <sys/queue.h>
50 1.2.6.2 jdolecek #include <sys/malloc.h>
51 1.2.6.2 jdolecek #include <sys/systm.h>
52 1.2.6.2 jdolecek #include <sys/device.h>
53 1.2.6.2 jdolecek #include <sys/kernel.h>
54 1.2.6.2 jdolecek
55 1.2.6.2 jdolecek #include <machine/bus.h>
56 1.2.6.2 jdolecek #include <machine/intr.h>
57 1.2.6.2 jdolecek
58 1.2.6.2 jdolecek #include <mips/locore.h>
59 1.2.6.2 jdolecek #include <mips/alchemy/include/aureg.h>
60 1.2.6.2 jdolecek #include <mips/alchemy/include/auvar.h>
61 1.2.6.2 jdolecek
62 1.2.6.2 jdolecek #define REGVAL(x) *((__volatile u_int32_t *)(MIPS_PHYS_TO_KSEG1((x))))
63 1.2.6.2 jdolecek
64 1.2.6.2 jdolecek /*
65 1.2.6.2 jdolecek * This is a mask of bits to clear in the SR when we go to a
66 1.2.6.2 jdolecek * given hardware interrupt priority level.
67 1.2.6.2 jdolecek */
68 1.2.6.2 jdolecek
69 1.2.6.2 jdolecek const u_int32_t ipl_sr_bits[_IPL_N] = {
70 1.2.6.2 jdolecek 0, /* 0: IPL_NONE */
71 1.2.6.2 jdolecek
72 1.2.6.2 jdolecek MIPS_SOFT_INT_MASK_0, /* 1: IPL_SOFT */
73 1.2.6.2 jdolecek
74 1.2.6.2 jdolecek MIPS_SOFT_INT_MASK_0, /* 2: IPL_SOFTCLOCK */
75 1.2.6.2 jdolecek
76 1.2.6.2 jdolecek MIPS_SOFT_INT_MASK_0, /* 3: IPL_SOFTNET */
77 1.2.6.2 jdolecek
78 1.2.6.2 jdolecek MIPS_SOFT_INT_MASK_0, /* 4: IPL_SOFTSERIAL */
79 1.2.6.2 jdolecek
80 1.2.6.2 jdolecek MIPS_SOFT_INT_MASK_0|
81 1.2.6.2 jdolecek MIPS_SOFT_INT_MASK_1|
82 1.2.6.2 jdolecek MIPS_INT_MASK_0, /* 5: IPL_BIO */
83 1.2.6.2 jdolecek
84 1.2.6.2 jdolecek MIPS_SOFT_INT_MASK_0|
85 1.2.6.2 jdolecek MIPS_SOFT_INT_MASK_1|
86 1.2.6.2 jdolecek MIPS_INT_MASK_0, /* 6: IPL_NET */
87 1.2.6.2 jdolecek
88 1.2.6.2 jdolecek MIPS_SOFT_INT_MASK_0|
89 1.2.6.2 jdolecek MIPS_SOFT_INT_MASK_1|
90 1.2.6.2 jdolecek MIPS_INT_MASK_0, /* 7: IPL_{SERIAL,TTY} */
91 1.2.6.2 jdolecek
92 1.2.6.2 jdolecek MIPS_SOFT_INT_MASK_0|
93 1.2.6.2 jdolecek MIPS_SOFT_INT_MASK_1|
94 1.2.6.2 jdolecek MIPS_INT_MASK_0|
95 1.2.6.2 jdolecek MIPS_INT_MASK_1|
96 1.2.6.2 jdolecek MIPS_INT_MASK_2|
97 1.2.6.2 jdolecek MIPS_INT_MASK_3|
98 1.2.6.2 jdolecek MIPS_INT_MASK_4|
99 1.2.6.2 jdolecek MIPS_INT_MASK_5, /* 8: IPL_{CLOCK,HIGH} */
100 1.2.6.2 jdolecek };
101 1.2.6.2 jdolecek
102 1.2.6.2 jdolecek /*
103 1.2.6.2 jdolecek * This is a mask of bits to clear in the SR when we go to a
104 1.2.6.2 jdolecek * given software interrupt priority level.
105 1.2.6.2 jdolecek * Hardware ipls are port/board specific.
106 1.2.6.2 jdolecek */
107 1.2.6.2 jdolecek const u_int32_t ipl_si_to_sr[_IPL_NSOFT] = {
108 1.2.6.2 jdolecek MIPS_SOFT_INT_MASK_0, /* IPL_SOFT */
109 1.2.6.2 jdolecek MIPS_SOFT_INT_MASK_0, /* IPL_SOFTCLOCK */
110 1.2.6.2 jdolecek MIPS_SOFT_INT_MASK_0, /* IPL_SOFTNET */
111 1.2.6.2 jdolecek MIPS_SOFT_INT_MASK_0, /* IPL_SOFTSERIAL */
112 1.2.6.2 jdolecek };
113 1.2.6.2 jdolecek
114 1.2.6.2 jdolecek #define NIRQS 64
115 1.2.6.2 jdolecek
116 1.2.6.2 jdolecek const char *au1000_intrnames[NIRQS] = {
117 1.2.6.2 jdolecek "uart0",
118 1.2.6.2 jdolecek "uart1",
119 1.2.6.2 jdolecek "uart2",
120 1.2.6.2 jdolecek "uart3",
121 1.2.6.2 jdolecek "ssi0",
122 1.2.6.2 jdolecek "ssi1",
123 1.2.6.2 jdolecek "dma0",
124 1.2.6.2 jdolecek "dma1",
125 1.2.6.2 jdolecek "dma2",
126 1.2.6.2 jdolecek "dma3",
127 1.2.6.2 jdolecek "dma4",
128 1.2.6.2 jdolecek "dma5",
129 1.2.6.2 jdolecek "dma6",
130 1.2.6.2 jdolecek "dma7",
131 1.2.6.2 jdolecek "pc0",
132 1.2.6.2 jdolecek "pc0 match1",
133 1.2.6.2 jdolecek "pc0 match2",
134 1.2.6.2 jdolecek "pc0 match3",
135 1.2.6.2 jdolecek "pc1",
136 1.2.6.2 jdolecek "pc1 match1",
137 1.2.6.2 jdolecek "pc1 match2",
138 1.2.6.2 jdolecek "pc1 match3",
139 1.2.6.2 jdolecek "irda tx",
140 1.2.6.2 jdolecek "irda rx",
141 1.2.6.2 jdolecek "usb intr",
142 1.2.6.2 jdolecek "usb suspend",
143 1.2.6.2 jdolecek "usb host",
144 1.2.6.2 jdolecek "ac97",
145 1.2.6.2 jdolecek "mac0",
146 1.2.6.2 jdolecek "mac1",
147 1.2.6.2 jdolecek "i2s",
148 1.2.6.2 jdolecek "ac97 cmd",
149 1.2.6.2 jdolecek
150 1.2.6.2 jdolecek "gpio 0",
151 1.2.6.2 jdolecek "gpio 1",
152 1.2.6.2 jdolecek "gpio 2",
153 1.2.6.2 jdolecek "gpio 3",
154 1.2.6.2 jdolecek "gpio 4",
155 1.2.6.2 jdolecek "gpio 5",
156 1.2.6.2 jdolecek "gpio 6",
157 1.2.6.2 jdolecek "gpio 7",
158 1.2.6.2 jdolecek "gpio 8",
159 1.2.6.2 jdolecek "gpio 9",
160 1.2.6.2 jdolecek "gpio 10",
161 1.2.6.2 jdolecek "gpio 11",
162 1.2.6.2 jdolecek "gpio 12",
163 1.2.6.2 jdolecek "gpio 13",
164 1.2.6.2 jdolecek "gpio 14",
165 1.2.6.2 jdolecek "gpio 15",
166 1.2.6.2 jdolecek "gpio 16",
167 1.2.6.2 jdolecek "gpio 17",
168 1.2.6.2 jdolecek "gpio 18",
169 1.2.6.2 jdolecek "gpio 19",
170 1.2.6.2 jdolecek "gpio 20",
171 1.2.6.2 jdolecek "gpio 21",
172 1.2.6.2 jdolecek "gpio 22",
173 1.2.6.2 jdolecek "gpio 23",
174 1.2.6.2 jdolecek "gpio 24",
175 1.2.6.2 jdolecek "gpio 25",
176 1.2.6.2 jdolecek "gpio 26",
177 1.2.6.2 jdolecek "gpio 27",
178 1.2.6.2 jdolecek "gpio 28",
179 1.2.6.2 jdolecek "gpio 29",
180 1.2.6.2 jdolecek "gpio 30",
181 1.2.6.2 jdolecek "gpio 31",
182 1.2.6.2 jdolecek };
183 1.2.6.2 jdolecek
184 1.2.6.2 jdolecek struct au1000_intrhead {
185 1.2.6.2 jdolecek struct evcnt intr_count;
186 1.2.6.2 jdolecek int intr_refcnt;
187 1.2.6.2 jdolecek };
188 1.2.6.2 jdolecek struct au1000_intrhead au1000_intrtab[NIRQS];
189 1.2.6.2 jdolecek
190 1.2.6.2 jdolecek #define NINTRS 4 /* MIPS INT0 - INT3 */
191 1.2.6.2 jdolecek
192 1.2.6.2 jdolecek struct au1000_cpuintr {
193 1.2.6.2 jdolecek LIST_HEAD(, evbmips_intrhand) cintr_list;
194 1.2.6.2 jdolecek struct evcnt cintr_count;
195 1.2.6.2 jdolecek };
196 1.2.6.2 jdolecek
197 1.2.6.2 jdolecek struct au1000_cpuintr au1000_cpuintrs[NINTRS];
198 1.2.6.2 jdolecek const char *au1000_cpuintrnames[NINTRS] = {
199 1.2.6.2 jdolecek "icu 0, req 0",
200 1.2.6.2 jdolecek "icu 0, req 1",
201 1.2.6.2 jdolecek "icu 1, req 0",
202 1.2.6.2 jdolecek "icu 1, req 1",
203 1.2.6.2 jdolecek };
204 1.2.6.2 jdolecek
205 1.2.6.2 jdolecek void
206 1.2.6.2 jdolecek au_intr_init(void)
207 1.2.6.2 jdolecek {
208 1.2.6.2 jdolecek int i;
209 1.2.6.2 jdolecek
210 1.2.6.2 jdolecek for (i = 0; i < NINTRS; i++) {
211 1.2.6.2 jdolecek LIST_INIT(&au1000_cpuintrs[i].cintr_list);
212 1.2.6.2 jdolecek evcnt_attach_dynamic(&au1000_cpuintrs[i].cintr_count,
213 1.2.6.2 jdolecek EVCNT_TYPE_INTR, NULL, "mips", au1000_cpuintrnames[i]);
214 1.2.6.2 jdolecek }
215 1.2.6.2 jdolecek
216 1.2.6.2 jdolecek evcnt_attach_static(&mips_int5_evcnt);
217 1.2.6.2 jdolecek
218 1.2.6.2 jdolecek for (i = 0; i < NIRQS; i++) {
219 1.2.6.2 jdolecek /* XXX steering - use an irqmap array? */
220 1.2.6.2 jdolecek
221 1.2.6.2 jdolecek au1000_intrtab[i].intr_refcnt = 0;
222 1.2.6.2 jdolecek evcnt_attach_dynamic(&au1000_intrtab[i].intr_count,
223 1.2.6.2 jdolecek EVCNT_TYPE_INTR, NULL, "au1000", au1000_intrnames[i]);
224 1.2.6.2 jdolecek }
225 1.2.6.2 jdolecek }
226 1.2.6.2 jdolecek
227 1.2.6.2 jdolecek void *
228 1.2.6.2 jdolecek au_intr_establish(int irq, int req, int level, int type,
229 1.2.6.2 jdolecek int (*func)(void *), void *arg)
230 1.2.6.2 jdolecek {
231 1.2.6.2 jdolecek struct evbmips_intrhand *ih;
232 1.2.6.2 jdolecek uint32_t icu_base;
233 1.2.6.2 jdolecek int cpu_intr, s;
234 1.2.6.2 jdolecek
235 1.2.6.2 jdolecek if (irq >= NIRQS)
236 1.2.6.3 jdolecek panic("au_intr_establish: bogus IRQ %d", irq);
237 1.2.6.2 jdolecek if (req > 1)
238 1.2.6.3 jdolecek panic("au_intr_establish: bogus request %d", req);
239 1.2.6.2 jdolecek
240 1.2.6.2 jdolecek ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
241 1.2.6.2 jdolecek if (ih == NULL)
242 1.2.6.2 jdolecek return (NULL);
243 1.2.6.2 jdolecek
244 1.2.6.2 jdolecek ih->ih_func = func;
245 1.2.6.2 jdolecek ih->ih_arg = arg;
246 1.2.6.2 jdolecek ih->ih_irq = irq;
247 1.2.6.2 jdolecek
248 1.2.6.2 jdolecek s = splhigh();
249 1.2.6.2 jdolecek
250 1.2.6.2 jdolecek /*
251 1.2.6.2 jdolecek * First, link it into the tables.
252 1.2.6.2 jdolecek * XXX do we want a separate list (really, should only be one item, not
253 1.2.6.2 jdolecek * a list anyway) per irq, not per cpu interrupt?
254 1.2.6.2 jdolecek */
255 1.2.6.2 jdolecek cpu_intr = (irq < 32 ? 0 : 2);
256 1.2.6.2 jdolecek LIST_INSERT_HEAD(&au1000_cpuintrs[cpu_intr].cintr_list, ih, ih_q);
257 1.2.6.2 jdolecek
258 1.2.6.2 jdolecek /*
259 1.2.6.2 jdolecek * Now enable it.
260 1.2.6.2 jdolecek */
261 1.2.6.2 jdolecek if (au1000_intrtab[irq].intr_refcnt++ == 0) {
262 1.2.6.2 jdolecek icu_base = (irq < 32) ? IC0_BASE : IC1_BASE;
263 1.2.6.2 jdolecek
264 1.2.6.2 jdolecek irq &= 31; /* throw away high bit if set */
265 1.2.6.2 jdolecek irq = 1 << irq; /* only used as a mask from here on */
266 1.2.6.2 jdolecek
267 1.2.6.2 jdolecek /* XXX Only high-level interrupts for now */
268 1.2.6.2 jdolecek switch (type) {
269 1.2.6.2 jdolecek case IST_NONE:
270 1.2.6.2 jdolecek case IST_PULSE:
271 1.2.6.2 jdolecek case IST_EDGE:
272 1.2.6.2 jdolecek panic("unsupported irq type %d", type);
273 1.2.6.2 jdolecek case IST_LEVEL:
274 1.2.6.2 jdolecek REGVAL(icu_base + IC_CONFIG2_SET) = irq;
275 1.2.6.2 jdolecek REGVAL(icu_base + IC_CONFIG1_CLEAR) = irq;
276 1.2.6.2 jdolecek REGVAL(icu_base + IC_CONFIG0_SET) = irq;
277 1.2.6.2 jdolecek }
278 1.2.6.2 jdolecek
279 1.2.6.2 jdolecek /* XXX handle GPIO interrupts - not done at all yet */
280 1.2.6.2 jdolecek if (cpu_intr & 0x1)
281 1.2.6.2 jdolecek REGVAL(icu_base + IC_ASSIGN_REQUEST_CLEAR) = irq;
282 1.2.6.2 jdolecek else
283 1.2.6.2 jdolecek REGVAL(icu_base + IC_ASSIGN_REQUEST_SET) = irq;
284 1.2.6.2 jdolecek
285 1.2.6.2 jdolecek /* Associate interrupt with peripheral */
286 1.2.6.2 jdolecek REGVAL(icu_base + IC_SOURCE_SET) = irq;
287 1.2.6.2 jdolecek
288 1.2.6.2 jdolecek /* Actually enable the interrupt */
289 1.2.6.2 jdolecek REGVAL(icu_base + IC_MASK_SET) = irq;
290 1.2.6.2 jdolecek
291 1.2.6.2 jdolecek /* And allow the interrupt to interrupt idle */
292 1.2.6.2 jdolecek REGVAL(icu_base + IC_WAKEUP_SET) = irq;
293 1.2.6.2 jdolecek }
294 1.2.6.2 jdolecek splx(s);
295 1.2.6.2 jdolecek
296 1.2.6.2 jdolecek return (ih);
297 1.2.6.2 jdolecek }
298 1.2.6.2 jdolecek
299 1.2.6.2 jdolecek void
300 1.2.6.2 jdolecek au_intr_disestablish(void *cookie)
301 1.2.6.2 jdolecek {
302 1.2.6.2 jdolecek struct evbmips_intrhand *ih = cookie;
303 1.2.6.2 jdolecek uint32_t icu_base;
304 1.2.6.2 jdolecek int irq, s;
305 1.2.6.2 jdolecek
306 1.2.6.2 jdolecek irq = ih->ih_irq;
307 1.2.6.2 jdolecek
308 1.2.6.2 jdolecek s = splhigh();
309 1.2.6.2 jdolecek
310 1.2.6.2 jdolecek /*
311 1.2.6.2 jdolecek * First, remove it from the table.
312 1.2.6.2 jdolecek */
313 1.2.6.2 jdolecek LIST_REMOVE(ih, ih_q);
314 1.2.6.2 jdolecek
315 1.2.6.2 jdolecek /*
316 1.2.6.2 jdolecek * Now, disable it, if there is nothing remaining on the
317 1.2.6.2 jdolecek * list.
318 1.2.6.2 jdolecek */
319 1.2.6.2 jdolecek if (au1000_intrtab[irq].intr_refcnt-- == 1) {
320 1.2.6.2 jdolecek icu_base = (irq < 32) ? IC0_BASE : IC1_BASE;
321 1.2.6.2 jdolecek
322 1.2.6.2 jdolecek irq &= 31; /* throw away high bit if set */
323 1.2.6.2 jdolecek irq = 1 << irq; /* only used as a mask from here on */
324 1.2.6.2 jdolecek
325 1.2.6.2 jdolecek REGVAL(icu_base + IC_CONFIG2_CLEAR) = irq;
326 1.2.6.2 jdolecek REGVAL(icu_base + IC_CONFIG1_CLEAR) = irq;
327 1.2.6.2 jdolecek REGVAL(icu_base + IC_CONFIG0_CLEAR) = irq;
328 1.2.6.2 jdolecek
329 1.2.6.2 jdolecek /* XXX disable with MASK_CLEAR and WAKEUP_CLEAR */
330 1.2.6.2 jdolecek }
331 1.2.6.2 jdolecek
332 1.2.6.2 jdolecek splx(s);
333 1.2.6.2 jdolecek
334 1.2.6.2 jdolecek free(ih, M_DEVBUF);
335 1.2.6.2 jdolecek }
336 1.2.6.2 jdolecek
337 1.2.6.2 jdolecek void
338 1.2.6.2 jdolecek au_iointr(u_int32_t status, u_int32_t cause, u_int32_t pc, u_int32_t ipending)
339 1.2.6.2 jdolecek {
340 1.2.6.2 jdolecek struct evbmips_intrhand *ih;
341 1.2.6.2 jdolecek int level;
342 1.2.6.2 jdolecek u_int32_t icu_base, irqmask;
343 1.2.6.2 jdolecek
344 1.2.6.2 jdolecek for (level = 3; level >= 0; level--) {
345 1.2.6.2 jdolecek if ((ipending & (MIPS_INT_MASK_0 << level)) == 0)
346 1.2.6.2 jdolecek continue;
347 1.2.6.2 jdolecek
348 1.2.6.2 jdolecek /*
349 1.2.6.2 jdolecek * XXX the following may well be slow to execute.
350 1.2.6.2 jdolecek * investigate and possibly speed up.
351 1.2.6.2 jdolecek *
352 1.2.6.2 jdolecek * is something like:
353 1.2.6.2 jdolecek *
354 1.2.6.2 jdolecek * irqmask = REGVAL(
355 1.2.6.2 jdolecek * (level & 4 == 0) ? IC0_BASE ? IC1_BASE +
356 1.2.6.2 jdolecek * (level & 2 == 0) ? IC_REQUEST0_INT : IC_REQUEST1_INT);
357 1.2.6.2 jdolecek *
358 1.2.6.2 jdolecek * be any better?
359 1.2.6.2 jdolecek *
360 1.2.6.2 jdolecek */
361 1.2.6.2 jdolecek switch (level) {
362 1.2.6.2 jdolecek case 0:
363 1.2.6.2 jdolecek icu_base = IC0_BASE;
364 1.2.6.2 jdolecek irqmask = REGVAL(icu_base + IC_REQUEST0_INT);
365 1.2.6.2 jdolecek break;
366 1.2.6.2 jdolecek case 1:
367 1.2.6.2 jdolecek icu_base = IC0_BASE;
368 1.2.6.2 jdolecek irqmask = REGVAL(icu_base + IC_REQUEST1_INT);
369 1.2.6.2 jdolecek break;
370 1.2.6.2 jdolecek case 2:
371 1.2.6.2 jdolecek icu_base = IC1_BASE;
372 1.2.6.2 jdolecek irqmask = REGVAL(icu_base + IC_REQUEST0_INT);
373 1.2.6.2 jdolecek break;
374 1.2.6.2 jdolecek case 3:
375 1.2.6.2 jdolecek icu_base = IC1_BASE;
376 1.2.6.2 jdolecek irqmask = REGVAL(icu_base + IC_REQUEST1_INT);
377 1.2.6.2 jdolecek break;
378 1.2.6.2 jdolecek }
379 1.2.6.2 jdolecek au1000_cpuintrs[level].cintr_count.ev_count++;
380 1.2.6.2 jdolecek LIST_FOREACH(ih, &au1000_cpuintrs[level].cintr_list, ih_q) {
381 1.2.6.2 jdolecek /* XXX should check is see if interrupt is masked? */
382 1.2.6.2 jdolecek if (1 << ih->ih_irq & irqmask) {
383 1.2.6.2 jdolecek au1000_intrtab[ih->ih_irq].intr_count.ev_count++;
384 1.2.6.2 jdolecek (*ih->ih_func)(ih->ih_arg);
385 1.2.6.2 jdolecek
386 1.2.6.2 jdolecek REGVAL(icu_base + IC_MASK_CLEAR) = 1 << ih->ih_irq;
387 1.2.6.2 jdolecek REGVAL(icu_base + IC_MASK_SET) = 1 << ih->ih_irq;
388 1.2.6.2 jdolecek }
389 1.2.6.2 jdolecek }
390 1.2.6.2 jdolecek cause &= ~(MIPS_INT_MASK_0 << level);
391 1.2.6.2 jdolecek }
392 1.2.6.2 jdolecek
393 1.2.6.2 jdolecek /* Re-enable anything that we have processed. */
394 1.2.6.2 jdolecek _splset(MIPS_SR_INT_IE | ((status & ~cause) & MIPS_HARD_INT_MASK));
395 1.2.6.2 jdolecek }
396