aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/vr41xx/common/icu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/vr41xx/common/icu.c')
-rw-r--r--arch/mips/vr41xx/common/icu.c757
1 files changed, 757 insertions, 0 deletions
diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c
new file mode 100644
index 000000000000..c842661144cb
--- /dev/null
+++ b/arch/mips/vr41xx/common/icu.c
@@ -0,0 +1,757 @@
1/*
2 * icu.c, Interrupt Control Unit routines for the NEC VR4100 series.
3 *
4 * Copyright (C) 2001-2002 MontaVista Software Inc.
5 * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
6 * Copyright (C) 2003-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
7 * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23/*
24 * Changes:
25 * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
26 * - New creation, NEC VR4122 and VR4131 are supported.
27 * - Added support for NEC VR4111 and VR4121.
28 *
29 * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
30 * - Coped with INTASSIGN of NEC VR4133.
31 */
32#include <linux/errno.h>
33#include <linux/init.h>
34#include <linux/interrupt.h>
35#include <linux/irq.h>
36#include <linux/module.h>
37#include <linux/smp.h>
38#include <linux/types.h>
39
40#include <asm/cpu.h>
41#include <asm/io.h>
42#include <asm/irq.h>
43#include <asm/irq_cpu.h>
44#include <asm/vr41xx/vr41xx.h>
45
46extern asmlinkage void vr41xx_handle_interrupt(void);
47
48extern void init_vr41xx_giuint_irq(void);
49extern void giuint_irq_dispatch(struct pt_regs *regs);
50
51static uint32_t icu1_base;
52static uint32_t icu2_base;
53
54static struct irqaction icu_cascade = {
55 .handler = no_action,
56 .mask = CPU_MASK_NONE,
57 .name = "cascade",
58};
59
60static unsigned char sysint1_assign[16] = {
61 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
62static unsigned char sysint2_assign[16] = {
63 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
64
65#define SYSINT1REG_TYPE1 KSEG1ADDR(0x0b000080)
66#define SYSINT2REG_TYPE1 KSEG1ADDR(0x0b000200)
67
68#define SYSINT1REG_TYPE2 KSEG1ADDR(0x0f000080)
69#define SYSINT2REG_TYPE2 KSEG1ADDR(0x0f0000a0)
70
71#define SYSINT1REG 0x00
72#define PIUINTREG 0x02
73#define INTASSIGN0 0x04
74#define INTASSIGN1 0x06
75#define GIUINTLREG 0x08
76#define DSIUINTREG 0x0a
77#define MSYSINT1REG 0x0c
78#define MPIUINTREG 0x0e
79#define MAIUINTREG 0x10
80#define MKIUINTREG 0x12
81#define MGIUINTLREG 0x14
82#define MDSIUINTREG 0x16
83#define NMIREG 0x18
84#define SOFTREG 0x1a
85#define INTASSIGN2 0x1c
86#define INTASSIGN3 0x1e
87
88#define SYSINT2REG 0x00
89#define GIUINTHREG 0x02
90#define FIRINTREG 0x04
91#define MSYSINT2REG 0x06
92#define MGIUINTHREG 0x08
93#define MFIRINTREG 0x0a
94#define PCIINTREG 0x0c
95 #define PCIINT0 0x0001
96#define SCUINTREG 0x0e
97 #define SCUINT0 0x0001
98#define CSIINTREG 0x10
99#define MPCIINTREG 0x12
100#define MSCUINTREG 0x14
101#define MCSIINTREG 0x16
102#define BCUINTREG 0x18
103 #define BCUINTR 0x0001
104#define MBCUINTREG 0x1a
105
106#define SYSINT1_IRQ_TO_PIN(x) ((x) - SYSINT1_IRQ_BASE) /* Pin 0-15 */
107#define SYSINT2_IRQ_TO_PIN(x) ((x) - SYSINT2_IRQ_BASE) /* Pin 0-15 */
108
109#define read_icu1(offset) readw(icu1_base + (offset))
110#define write_icu1(val, offset) writew((val), icu1_base + (offset))
111
112#define read_icu2(offset) readw(icu2_base + (offset))
113#define write_icu2(val, offset) writew((val), icu2_base + (offset))
114
115#define INTASSIGN_MAX 4
116#define INTASSIGN_MASK 0x0007
117
118static inline uint16_t set_icu1(uint8_t offset, uint16_t set)
119{
120 uint16_t res;
121
122 res = read_icu1(offset);
123 res |= set;
124 write_icu1(res, offset);
125
126 return res;
127}
128
129static inline uint16_t clear_icu1(uint8_t offset, uint16_t clear)
130{
131 uint16_t res;
132
133 res = read_icu1(offset);
134 res &= ~clear;
135 write_icu1(res, offset);
136
137 return res;
138}
139
140static inline uint16_t set_icu2(uint8_t offset, uint16_t set)
141{
142 uint16_t res;
143
144 res = read_icu2(offset);
145 res |= set;
146 write_icu2(res, offset);
147
148 return res;
149}
150
151static inline uint16_t clear_icu2(uint8_t offset, uint16_t clear)
152{
153 uint16_t res;
154
155 res = read_icu2(offset);
156 res &= ~clear;
157 write_icu2(res, offset);
158
159 return res;
160}
161
162/*=======================================================================*/
163
164void vr41xx_enable_piuint(uint16_t mask)
165{
166 irq_desc_t *desc = irq_desc + PIU_IRQ;
167 unsigned long flags;
168
169 if (current_cpu_data.cputype == CPU_VR4111 ||
170 current_cpu_data.cputype == CPU_VR4121) {
171 spin_lock_irqsave(&desc->lock, flags);
172 set_icu1(MPIUINTREG, mask);
173 spin_unlock_irqrestore(&desc->lock, flags);
174 }
175}
176
177EXPORT_SYMBOL(vr41xx_enable_piuint);
178
179void vr41xx_disable_piuint(uint16_t mask)
180{
181 irq_desc_t *desc = irq_desc + PIU_IRQ;
182 unsigned long flags;
183
184 if (current_cpu_data.cputype == CPU_VR4111 ||
185 current_cpu_data.cputype == CPU_VR4121) {
186 spin_lock_irqsave(&desc->lock, flags);
187 clear_icu1(MPIUINTREG, mask);
188 spin_unlock_irqrestore(&desc->lock, flags);
189 }
190}
191
192EXPORT_SYMBOL(vr41xx_disable_piuint);
193
194void vr41xx_enable_aiuint(uint16_t mask)
195{
196 irq_desc_t *desc = irq_desc + AIU_IRQ;
197 unsigned long flags;
198
199 if (current_cpu_data.cputype == CPU_VR4111 ||
200 current_cpu_data.cputype == CPU_VR4121) {
201 spin_lock_irqsave(&desc->lock, flags);
202 set_icu1(MAIUINTREG, mask);
203 spin_unlock_irqrestore(&desc->lock, flags);
204 }
205}
206
207EXPORT_SYMBOL(vr41xx_enable_aiuint);
208
209void vr41xx_disable_aiuint(uint16_t mask)
210{
211 irq_desc_t *desc = irq_desc + AIU_IRQ;
212 unsigned long flags;
213
214 if (current_cpu_data.cputype == CPU_VR4111 ||
215 current_cpu_data.cputype == CPU_VR4121) {
216 spin_lock_irqsave(&desc->lock, flags);
217 clear_icu1(MAIUINTREG, mask);
218 spin_unlock_irqrestore(&desc->lock, flags);
219 }
220}
221
222EXPORT_SYMBOL(vr41xx_disable_aiuint);
223
224void vr41xx_enable_kiuint(uint16_t mask)
225{
226 irq_desc_t *desc = irq_desc + KIU_IRQ;
227 unsigned long flags;
228
229 if (current_cpu_data.cputype == CPU_VR4111 ||
230 current_cpu_data.cputype == CPU_VR4121) {
231 spin_lock_irqsave(&desc->lock, flags);
232 set_icu1(MKIUINTREG, mask);
233 spin_unlock_irqrestore(&desc->lock, flags);
234 }
235}
236
237EXPORT_SYMBOL(vr41xx_enable_kiuint);
238
239void vr41xx_disable_kiuint(uint16_t mask)
240{
241 irq_desc_t *desc = irq_desc + KIU_IRQ;
242 unsigned long flags;
243
244 if (current_cpu_data.cputype == CPU_VR4111 ||
245 current_cpu_data.cputype == CPU_VR4121) {
246 spin_lock_irqsave(&desc->lock, flags);
247 clear_icu1(MKIUINTREG, mask);
248 spin_unlock_irqrestore(&desc->lock, flags);
249 }
250}
251
252EXPORT_SYMBOL(vr41xx_disable_kiuint);
253
254void vr41xx_enable_dsiuint(uint16_t mask)
255{
256 irq_desc_t *desc = irq_desc + DSIU_IRQ;
257 unsigned long flags;
258
259 spin_lock_irqsave(&desc->lock, flags);
260 set_icu1(MDSIUINTREG, mask);
261 spin_unlock_irqrestore(&desc->lock, flags);
262}
263
264EXPORT_SYMBOL(vr41xx_enable_dsiuint);
265
266void vr41xx_disable_dsiuint(uint16_t mask)
267{
268 irq_desc_t *desc = irq_desc + DSIU_IRQ;
269 unsigned long flags;
270
271 spin_lock_irqsave(&desc->lock, flags);
272 clear_icu1(MDSIUINTREG, mask);
273 spin_unlock_irqrestore(&desc->lock, flags);
274}
275
276EXPORT_SYMBOL(vr41xx_disable_dsiuint);
277
278void vr41xx_enable_firint(uint16_t mask)
279{
280 irq_desc_t *desc = irq_desc + FIR_IRQ;
281 unsigned long flags;
282
283 spin_lock_irqsave(&desc->lock, flags);
284 set_icu2(MFIRINTREG, mask);
285 spin_unlock_irqrestore(&desc->lock, flags);
286}
287
288EXPORT_SYMBOL(vr41xx_enable_firint);
289
290void vr41xx_disable_firint(uint16_t mask)
291{
292 irq_desc_t *desc = irq_desc + FIR_IRQ;
293 unsigned long flags;
294
295 spin_lock_irqsave(&desc->lock, flags);
296 clear_icu2(MFIRINTREG, mask);
297 spin_unlock_irqrestore(&desc->lock, flags);
298}
299
300EXPORT_SYMBOL(vr41xx_disable_firint);
301
302void vr41xx_enable_pciint(void)
303{
304 irq_desc_t *desc = irq_desc + PCI_IRQ;
305 unsigned long flags;
306
307 if (current_cpu_data.cputype == CPU_VR4122 ||
308 current_cpu_data.cputype == CPU_VR4131 ||
309 current_cpu_data.cputype == CPU_VR4133) {
310 spin_lock_irqsave(&desc->lock, flags);
311 write_icu2(PCIINT0, MPCIINTREG);
312 spin_unlock_irqrestore(&desc->lock, flags);
313 }
314}
315
316EXPORT_SYMBOL(vr41xx_enable_pciint);
317
318void vr41xx_disable_pciint(void)
319{
320 irq_desc_t *desc = irq_desc + PCI_IRQ;
321 unsigned long flags;
322
323 if (current_cpu_data.cputype == CPU_VR4122 ||
324 current_cpu_data.cputype == CPU_VR4131 ||
325 current_cpu_data.cputype == CPU_VR4133) {
326 spin_lock_irqsave(&desc->lock, flags);
327 write_icu2(0, MPCIINTREG);
328 spin_unlock_irqrestore(&desc->lock, flags);
329 }
330}
331
332EXPORT_SYMBOL(vr41xx_disable_pciint);
333
334void vr41xx_enable_scuint(void)
335{
336 irq_desc_t *desc = irq_desc + SCU_IRQ;
337 unsigned long flags;
338
339 if (current_cpu_data.cputype == CPU_VR4122 ||
340 current_cpu_data.cputype == CPU_VR4131 ||
341 current_cpu_data.cputype == CPU_VR4133) {
342 spin_lock_irqsave(&desc->lock, flags);
343 write_icu2(SCUINT0, MSCUINTREG);
344 spin_unlock_irqrestore(&desc->lock, flags);
345 }
346}
347
348EXPORT_SYMBOL(vr41xx_enable_scuint);
349
350void vr41xx_disable_scuint(void)
351{
352 irq_desc_t *desc = irq_desc + SCU_IRQ;
353 unsigned long flags;
354
355 if (current_cpu_data.cputype == CPU_VR4122 ||
356 current_cpu_data.cputype == CPU_VR4131 ||
357 current_cpu_data.cputype == CPU_VR4133) {
358 spin_lock_irqsave(&desc->lock, flags);
359 write_icu2(0, MSCUINTREG);
360 spin_unlock_irqrestore(&desc->lock, flags);
361 }
362}
363
364EXPORT_SYMBOL(vr41xx_disable_scuint);
365
366void vr41xx_enable_csiint(uint16_t mask)
367{
368 irq_desc_t *desc = irq_desc + CSI_IRQ;
369 unsigned long flags;
370
371 if (current_cpu_data.cputype == CPU_VR4122 ||
372 current_cpu_data.cputype == CPU_VR4131 ||
373 current_cpu_data.cputype == CPU_VR4133) {
374 spin_lock_irqsave(&desc->lock, flags);
375 set_icu2(MCSIINTREG, mask);
376 spin_unlock_irqrestore(&desc->lock, flags);
377 }
378}
379
380EXPORT_SYMBOL(vr41xx_enable_csiint);
381
382void vr41xx_disable_csiint(uint16_t mask)
383{
384 irq_desc_t *desc = irq_desc + CSI_IRQ;
385 unsigned long flags;
386
387 if (current_cpu_data.cputype == CPU_VR4122 ||
388 current_cpu_data.cputype == CPU_VR4131 ||
389 current_cpu_data.cputype == CPU_VR4133) {
390 spin_lock_irqsave(&desc->lock, flags);
391 clear_icu2(MCSIINTREG, mask);
392 spin_unlock_irqrestore(&desc->lock, flags);
393 }
394}
395
396EXPORT_SYMBOL(vr41xx_disable_csiint);
397
398void vr41xx_enable_bcuint(void)
399{
400 irq_desc_t *desc = irq_desc + BCU_IRQ;
401 unsigned long flags;
402
403 if (current_cpu_data.cputype == CPU_VR4122 ||
404 current_cpu_data.cputype == CPU_VR4131 ||
405 current_cpu_data.cputype == CPU_VR4133) {
406 spin_lock_irqsave(&desc->lock, flags);
407 write_icu2(BCUINTR, MBCUINTREG);
408 spin_unlock_irqrestore(&desc->lock, flags);
409 }
410}
411
412EXPORT_SYMBOL(vr41xx_enable_bcuint);
413
414void vr41xx_disable_bcuint(void)
415{
416 irq_desc_t *desc = irq_desc + BCU_IRQ;
417 unsigned long flags;
418
419 if (current_cpu_data.cputype == CPU_VR4122 ||
420 current_cpu_data.cputype == CPU_VR4131 ||
421 current_cpu_data.cputype == CPU_VR4133) {
422 spin_lock_irqsave(&desc->lock, flags);
423 write_icu2(0, MBCUINTREG);
424 spin_unlock_irqrestore(&desc->lock, flags);
425 }
426}
427
428EXPORT_SYMBOL(vr41xx_disable_bcuint);
429
430/*=======================================================================*/
431
432static unsigned int startup_sysint1_irq(unsigned int irq)
433{
434 set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
435
436 return 0; /* never anything pending */
437}
438
439static void shutdown_sysint1_irq(unsigned int irq)
440{
441 clear_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
442}
443
444static void enable_sysint1_irq(unsigned int irq)
445{
446 set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
447}
448
449#define disable_sysint1_irq shutdown_sysint1_irq
450#define ack_sysint1_irq shutdown_sysint1_irq
451
452static void end_sysint1_irq(unsigned int irq)
453{
454 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
455 set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
456}
457
458static struct hw_interrupt_type sysint1_irq_type = {
459 .typename = "SYSINT1",
460 .startup = startup_sysint1_irq,
461 .shutdown = shutdown_sysint1_irq,
462 .enable = enable_sysint1_irq,
463 .disable = disable_sysint1_irq,
464 .ack = ack_sysint1_irq,
465 .end = end_sysint1_irq,
466};
467
468/*=======================================================================*/
469
470static unsigned int startup_sysint2_irq(unsigned int irq)
471{
472 set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
473
474 return 0; /* never anything pending */
475}
476
477static void shutdown_sysint2_irq(unsigned int irq)
478{
479 clear_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
480}
481
482static void enable_sysint2_irq(unsigned int irq)
483{
484 set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
485}
486
487#define disable_sysint2_irq shutdown_sysint2_irq
488#define ack_sysint2_irq shutdown_sysint2_irq
489
490static void end_sysint2_irq(unsigned int irq)
491{
492 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
493 set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
494}
495
496static struct hw_interrupt_type sysint2_irq_type = {
497 .typename = "SYSINT2",
498 .startup = startup_sysint2_irq,
499 .shutdown = shutdown_sysint2_irq,
500 .enable = enable_sysint2_irq,
501 .disable = disable_sysint2_irq,
502 .ack = ack_sysint2_irq,
503 .end = end_sysint2_irq,
504};
505
506/*=======================================================================*/
507
508static inline int set_sysint1_assign(unsigned int irq, unsigned char assign)
509{
510 irq_desc_t *desc = irq_desc + irq;
511 uint16_t intassign0, intassign1;
512 unsigned int pin;
513
514 pin = SYSINT1_IRQ_TO_PIN(irq);
515
516 spin_lock_irq(&desc->lock);
517
518 intassign0 = read_icu1(INTASSIGN0);
519 intassign1 = read_icu1(INTASSIGN1);
520
521 switch (pin) {
522 case 0:
523 intassign0 &= ~INTASSIGN_MASK;
524 intassign0 |= (uint16_t)assign;
525 break;
526 case 1:
527 intassign0 &= ~(INTASSIGN_MASK << 3);
528 intassign0 |= (uint16_t)assign << 3;
529 break;
530 case 2:
531 intassign0 &= ~(INTASSIGN_MASK << 6);
532 intassign0 |= (uint16_t)assign << 6;
533 break;
534 case 3:
535 intassign0 &= ~(INTASSIGN_MASK << 9);
536 intassign0 |= (uint16_t)assign << 9;
537 break;
538 case 8:
539 intassign0 &= ~(INTASSIGN_MASK << 12);
540 intassign0 |= (uint16_t)assign << 12;
541 break;
542 case 9:
543 intassign1 &= ~INTASSIGN_MASK;
544 intassign1 |= (uint16_t)assign;
545 break;
546 case 11:
547 intassign1 &= ~(INTASSIGN_MASK << 6);
548 intassign1 |= (uint16_t)assign << 6;
549 break;
550 case 12:
551 intassign1 &= ~(INTASSIGN_MASK << 9);
552 intassign1 |= (uint16_t)assign << 9;
553 break;
554 default:
555 return -EINVAL;
556 }
557
558 sysint1_assign[pin] = assign;
559 write_icu1(intassign0, INTASSIGN0);
560 write_icu1(intassign1, INTASSIGN1);
561
562 spin_unlock_irq(&desc->lock);
563
564 return 0;
565}
566
567static inline int set_sysint2_assign(unsigned int irq, unsigned char assign)
568{
569 irq_desc_t *desc = irq_desc + irq;
570 uint16_t intassign2, intassign3;
571 unsigned int pin;
572
573 pin = SYSINT2_IRQ_TO_PIN(irq);
574
575 spin_lock_irq(&desc->lock);
576
577 intassign2 = read_icu1(INTASSIGN2);
578 intassign3 = read_icu1(INTASSIGN3);
579
580 switch (pin) {
581 case 0:
582 intassign2 &= ~INTASSIGN_MASK;
583 intassign2 |= (uint16_t)assign;
584 break;
585 case 1:
586 intassign2 &= ~(INTASSIGN_MASK << 3);
587 intassign2 |= (uint16_t)assign << 3;
588 break;
589 case 3:
590 intassign2 &= ~(INTASSIGN_MASK << 6);
591 intassign2 |= (uint16_t)assign << 6;
592 break;
593 case 4:
594 intassign2 &= ~(INTASSIGN_MASK << 9);
595 intassign2 |= (uint16_t)assign << 9;
596 break;
597 case 5:
598 intassign2 &= ~(INTASSIGN_MASK << 12);
599 intassign2 |= (uint16_t)assign << 12;
600 break;
601 case 6:
602 intassign3 &= ~INTASSIGN_MASK;
603 intassign3 |= (uint16_t)assign;
604 break;
605 case 7:
606 intassign3 &= ~(INTASSIGN_MASK << 3);
607 intassign3 |= (uint16_t)assign << 3;
608 break;
609 case 8:
610 intassign3 &= ~(INTASSIGN_MASK << 6);
611 intassign3 |= (uint16_t)assign << 6;
612 break;
613 case 9:
614 intassign3 &= ~(INTASSIGN_MASK << 9);
615 intassign3 |= (uint16_t)assign << 9;
616 break;
617 case 10:
618 intassign3 &= ~(INTASSIGN_MASK << 12);
619 intassign3 |= (uint16_t)assign << 12;
620 break;
621 default:
622 return -EINVAL;
623 }
624
625 sysint2_assign[pin] = assign;
626 write_icu1(intassign2, INTASSIGN2);
627 write_icu1(intassign3, INTASSIGN3);
628
629 spin_unlock_irq(&desc->lock);
630
631 return 0;
632}
633
634int vr41xx_set_intassign(unsigned int irq, unsigned char intassign)
635{
636 int retval = -EINVAL;
637
638 if (current_cpu_data.cputype != CPU_VR4133)
639 return -EINVAL;
640
641 if (intassign > INTASSIGN_MAX)
642 return -EINVAL;
643
644 if (irq >= SYSINT1_IRQ_BASE && irq <= SYSINT1_IRQ_LAST)
645 retval = set_sysint1_assign(irq, intassign);
646 else if (irq >= SYSINT2_IRQ_BASE && irq <= SYSINT2_IRQ_LAST)
647 retval = set_sysint2_assign(irq, intassign);
648
649 return retval;
650}
651
652EXPORT_SYMBOL(vr41xx_set_intassign);
653
654/*=======================================================================*/
655
656asmlinkage void irq_dispatch(unsigned char intnum, struct pt_regs *regs)
657{
658 uint16_t pend1, pend2;
659 uint16_t mask1, mask2;
660 int i;
661
662 pend1 = read_icu1(SYSINT1REG);
663 mask1 = read_icu1(MSYSINT1REG);
664
665 pend2 = read_icu2(SYSINT2REG);
666 mask2 = read_icu2(MSYSINT2REG);
667
668 mask1 &= pend1;
669 mask2 &= pend2;
670
671 if (mask1) {
672 for (i = 0; i < 16; i++) {
673 if (intnum == sysint1_assign[i] &&
674 (mask1 & ((uint16_t)1 << i))) {
675 if (i == 8)
676 giuint_irq_dispatch(regs);
677 else
678 do_IRQ(SYSINT1_IRQ(i), regs);
679 return;
680 }
681 }
682 }
683
684 if (mask2) {
685 for (i = 0; i < 16; i++) {
686 if (intnum == sysint2_assign[i] &&
687 (mask2 & ((uint16_t)1 << i))) {
688 do_IRQ(SYSINT2_IRQ(i), regs);
689 return;
690 }
691 }
692 }
693
694 printk(KERN_ERR "spurious ICU interrupt: %04x,%04x\n", pend1, pend2);
695
696 atomic_inc(&irq_err_count);
697}
698
699/*=======================================================================*/
700
701static int __init vr41xx_icu_init(void)
702{
703 switch (current_cpu_data.cputype) {
704 case CPU_VR4111:
705 case CPU_VR4121:
706 icu1_base = SYSINT1REG_TYPE1;
707 icu2_base = SYSINT2REG_TYPE1;
708 break;
709 case CPU_VR4122:
710 case CPU_VR4131:
711 case CPU_VR4133:
712 icu1_base = SYSINT1REG_TYPE2;
713 icu2_base = SYSINT2REG_TYPE2;
714 break;
715 default:
716 printk(KERN_ERR "ICU: Unexpected CPU of NEC VR4100 series\n");
717 return -EINVAL;
718 }
719
720 write_icu1(0, MSYSINT1REG);
721 write_icu1(0xffff, MGIUINTLREG);
722
723 write_icu2(0, MSYSINT2REG);
724 write_icu2(0xffff, MGIUINTHREG);
725
726 return 0;
727}
728
729early_initcall(vr41xx_icu_init);
730
731/*=======================================================================*/
732
733static inline void init_vr41xx_icu_irq(void)
734{
735 int i;
736
737 for (i = SYSINT1_IRQ_BASE; i <= SYSINT1_IRQ_LAST; i++)
738 irq_desc[i].handler = &sysint1_irq_type;
739
740 for (i = SYSINT2_IRQ_BASE; i <= SYSINT2_IRQ_LAST; i++)
741 irq_desc[i].handler = &sysint2_irq_type;
742
743 setup_irq(INT0_CASCADE_IRQ, &icu_cascade);
744 setup_irq(INT1_CASCADE_IRQ, &icu_cascade);
745 setup_irq(INT2_CASCADE_IRQ, &icu_cascade);
746 setup_irq(INT3_CASCADE_IRQ, &icu_cascade);
747 setup_irq(INT4_CASCADE_IRQ, &icu_cascade);
748}
749
750void __init arch_init_irq(void)
751{
752 mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);
753 init_vr41xx_icu_irq();
754 init_vr41xx_giuint_irq();
755
756 set_except_vector(0, vr41xx_handle_interrupt);
757}