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