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