2 * icu.c, Interrupt Control Unit routines for the NEC VR4100 series.
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>
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.
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.
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
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.
28 * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
29 * - Coped with INTASSIGN of NEC VR4133.
31 #include <linux/errno.h>
32 #include <linux/init.h>
33 #include <linux/interrupt.h>
34 #include <linux/irq.h>
35 #include <linux/smp.h>
36 #include <linux/types.h>
41 #include <asm/irq_cpu.h>
42 #include <asm/vr41xx/vr41xx.h>
44 extern asmlinkage void vr41xx_handle_interrupt(void);
46 extern void vr41xx_giuint_init(void);
47 extern void vr41xx_enable_giuint(int pin);
48 extern void vr41xx_disable_giuint(int pin);
49 extern void vr41xx_clear_giuint(int pin);
50 extern unsigned int giuint_do_IRQ(int pin, struct pt_regs *regs);
52 static uint32_t icu1_base;
53 static uint32_t icu2_base;
55 static unsigned char sysint1_assign[16] = {
56 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
57 static unsigned char sysint2_assign[16] = {
58 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
60 #define SYSINT1REG_TYPE1 KSEG1ADDR(0x0b000080)
61 #define SYSINT2REG_TYPE1 KSEG1ADDR(0x0b000200)
63 #define SYSINT1REG_TYPE2 KSEG1ADDR(0x0f000080)
64 #define SYSINT2REG_TYPE2 KSEG1ADDR(0x0f0000a0)
66 #define SYSINT1REG 0x00
67 #define INTASSIGN0 0x04
68 #define INTASSIGN1 0x06
69 #define GIUINTLREG 0x08
70 #define MSYSINT1REG 0x0c
71 #define MGIUINTLREG 0x14
74 #define INTASSIGN2 0x1c
75 #define INTASSIGN3 0x1e
77 #define SYSINT2REG 0x00
78 #define GIUINTHREG 0x02
79 #define MSYSINT2REG 0x06
80 #define MGIUINTHREG 0x08
82 #define MDSIUINTREG KSEG1ADDR(0x0f000096)
83 #define INTDSIU 0x0800
85 #define SYSINT1_IRQ_TO_PIN(x) ((x) - SYSINT1_IRQ_BASE) /* Pin 0-15 */
86 #define SYSINT2_IRQ_TO_PIN(x) ((x) - SYSINT2_IRQ_BASE) /* Pin 0-15 */
88 #define read_icu1(offset) readw(icu1_base + (offset))
89 #define write_icu1(val, offset) writew((val), icu1_base + (offset))
91 #define read_icu2(offset) readw(icu2_base + (offset))
92 #define write_icu2(val, offset) writew((val), icu2_base + (offset))
94 #define INTASSIGN_MAX 4
95 #define INTASSIGN_MASK 0x0007
97 static inline uint16_t set_icu1(uint8_t offset, uint16_t set)
101 res = read_icu1(offset);
103 write_icu1(res, offset);
108 static inline uint16_t clear_icu1(uint8_t offset, uint16_t clear)
112 res = read_icu1(offset);
114 write_icu1(res, offset);
119 static inline uint16_t set_icu2(uint8_t offset, uint16_t set)
123 res = read_icu2(offset);
125 write_icu2(res, offset);
130 static inline uint16_t clear_icu2(uint8_t offset, uint16_t clear)
134 res = read_icu2(offset);
136 write_icu2(res, offset);
141 /*=======================================================================*/
143 void vr41xx_enable_dsiuint(void)
145 writew(INTDSIU, MDSIUINTREG);
148 void vr41xx_disable_dsiuint(void)
150 writew(0, MDSIUINTREG);
153 /*=======================================================================*/
155 static void enable_sysint1_irq(unsigned int irq)
157 set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
160 static void disable_sysint1_irq(unsigned int irq)
162 clear_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
165 static unsigned int startup_sysint1_irq(unsigned int irq)
167 set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
169 return 0; /* never anything pending */
172 #define shutdown_sysint1_irq disable_sysint1_irq
173 #define ack_sysint1_irq disable_sysint1_irq
175 static void end_sysint1_irq(unsigned int irq)
177 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
178 set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
181 static struct hw_interrupt_type sysint1_irq_type = {
182 .typename = "SYSINT1",
183 .startup = startup_sysint1_irq,
184 .shutdown = shutdown_sysint1_irq,
185 .enable = enable_sysint1_irq,
186 .disable = disable_sysint1_irq,
187 .ack = ack_sysint1_irq,
188 .end = end_sysint1_irq,
191 /*=======================================================================*/
193 static void enable_sysint2_irq(unsigned int irq)
195 set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
198 static void disable_sysint2_irq(unsigned int irq)
200 clear_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
203 static unsigned int startup_sysint2_irq(unsigned int irq)
205 set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
207 return 0; /* never anything pending */
210 #define shutdown_sysint2_irq disable_sysint2_irq
211 #define ack_sysint2_irq disable_sysint2_irq
213 static void end_sysint2_irq(unsigned int irq)
215 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
216 set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
219 static struct hw_interrupt_type sysint2_irq_type = {
220 .typename = "SYSINT2",
221 .startup = startup_sysint2_irq,
222 .shutdown = shutdown_sysint2_irq,
223 .enable = enable_sysint2_irq,
224 .disable = disable_sysint2_irq,
225 .ack = ack_sysint2_irq,
226 .end = end_sysint2_irq,
229 /*=======================================================================*/
231 static void enable_giuint_irq(unsigned int irq)
235 pin = GIU_IRQ_TO_PIN(irq);
237 set_icu1(MGIUINTLREG, (uint16_t)1 << pin);
239 set_icu2(MGIUINTHREG, (uint16_t)1 << (pin - 16));
240 vr41xx_enable_giuint(pin);
243 static void disable_giuint_irq(unsigned int irq)
247 pin = GIU_IRQ_TO_PIN(irq);
248 vr41xx_disable_giuint(pin);
250 clear_icu1(MGIUINTLREG, (uint16_t)1 << pin);
252 clear_icu2(MGIUINTHREG, (uint16_t)1 << (pin - 16));
255 static unsigned int startup_giuint_irq(unsigned int irq)
257 vr41xx_clear_giuint(GIU_IRQ_TO_PIN(irq));
259 enable_giuint_irq(irq);
261 return 0; /* never anything pending */
264 #define shutdown_giuint_irq disable_giuint_irq
266 static void ack_giuint_irq(unsigned int irq)
268 disable_giuint_irq(irq);
270 vr41xx_clear_giuint(GIU_IRQ_TO_PIN(irq));
273 static void end_giuint_irq(unsigned int irq)
275 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
276 enable_giuint_irq(irq);
279 static struct hw_interrupt_type giuint_irq_type = {
280 .typename = "GIUINT",
281 .startup = startup_giuint_irq,
282 .shutdown = shutdown_giuint_irq,
283 .enable = enable_giuint_irq,
284 .disable = disable_giuint_irq,
285 .ack = ack_giuint_irq,
286 .end = end_giuint_irq,
289 /*=======================================================================*/
291 static struct irqaction icu_cascade = {no_action, 0, 0, "cascade", NULL, NULL};
293 static void __init vr41xx_icu_init(void)
297 switch (current_cpu_data.cputype) {
300 icu1_base = SYSINT1REG_TYPE1;
301 icu2_base = SYSINT2REG_TYPE1;
306 icu1_base = SYSINT1REG_TYPE2;
307 icu2_base = SYSINT2REG_TYPE2;
310 panic("Unexpected CPU of NEC VR4100 series");
314 write_icu1(0, MSYSINT1REG);
315 write_icu1(0, MGIUINTLREG);
317 write_icu2(0, MSYSINT2REG);
318 write_icu2(0, MGIUINTHREG);
320 for (i = SYSINT1_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
321 if (i >= SYSINT1_IRQ_BASE && i <= SYSINT1_IRQ_LAST)
322 irq_desc[i].handler = &sysint1_irq_type;
323 else if (i >= SYSINT2_IRQ_BASE && i <= SYSINT2_IRQ_LAST)
324 irq_desc[i].handler = &sysint2_irq_type;
325 else if (i >= GIU_IRQ_BASE && i <= GIU_IRQ_LAST)
326 irq_desc[i].handler = &giuint_irq_type;
329 setup_irq(INT0_CASCADE_IRQ, &icu_cascade);
330 setup_irq(INT1_CASCADE_IRQ, &icu_cascade);
331 setup_irq(INT2_CASCADE_IRQ, &icu_cascade);
332 setup_irq(INT3_CASCADE_IRQ, &icu_cascade);
333 setup_irq(INT4_CASCADE_IRQ, &icu_cascade);
336 void __init init_IRQ(void)
338 memset(irq_desc, 0, sizeof(irq_desc));
341 mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);
344 vr41xx_giuint_init();
346 set_except_vector(0, vr41xx_handle_interrupt);
349 /*=======================================================================*/
351 static inline int set_sysint1_assign(unsigned int irq, unsigned char assign)
353 irq_desc_t *desc = irq_desc + irq;
354 uint16_t intassign0, intassign1;
357 pin = SYSINT1_IRQ_TO_PIN(irq);
359 spin_lock_irq(&desc->lock);
361 intassign0 = read_icu1(INTASSIGN0);
362 intassign1 = read_icu1(INTASSIGN1);
366 intassign0 &= ~INTASSIGN_MASK;
367 intassign0 |= (uint16_t)assign;
370 intassign0 &= ~(INTASSIGN_MASK << 3);
371 intassign0 |= (uint16_t)assign << 3;
374 intassign0 &= ~(INTASSIGN_MASK << 6);
375 intassign0 |= (uint16_t)assign << 6;
378 intassign0 &= ~(INTASSIGN_MASK << 9);
379 intassign0 |= (uint16_t)assign << 9;
382 intassign0 &= ~(INTASSIGN_MASK << 12);
383 intassign0 |= (uint16_t)assign << 12;
386 intassign1 &= ~INTASSIGN_MASK;
387 intassign1 |= (uint16_t)assign;
390 intassign1 &= ~(INTASSIGN_MASK << 6);
391 intassign1 |= (uint16_t)assign << 6;
394 intassign1 &= ~(INTASSIGN_MASK << 9);
395 intassign1 |= (uint16_t)assign << 9;
401 sysint1_assign[pin] = assign;
402 write_icu1(intassign0, INTASSIGN0);
403 write_icu1(intassign1, INTASSIGN1);
405 spin_unlock_irq(&desc->lock);
410 static inline int set_sysint2_assign(unsigned int irq, unsigned char assign)
412 irq_desc_t *desc = irq_desc + irq;
413 uint16_t intassign2, intassign3;
416 pin = SYSINT2_IRQ_TO_PIN(irq);
418 spin_lock_irq(&desc->lock);
420 intassign2 = read_icu1(INTASSIGN2);
421 intassign3 = read_icu1(INTASSIGN3);
425 intassign2 &= ~INTASSIGN_MASK;
426 intassign2 |= (uint16_t)assign;
429 intassign2 &= ~(INTASSIGN_MASK << 3);
430 intassign2 |= (uint16_t)assign << 3;
433 intassign2 &= ~(INTASSIGN_MASK << 6);
434 intassign2 |= (uint16_t)assign << 6;
437 intassign2 &= ~(INTASSIGN_MASK << 9);
438 intassign2 |= (uint16_t)assign << 9;
441 intassign2 &= ~(INTASSIGN_MASK << 12);
442 intassign2 |= (uint16_t)assign << 12;
445 intassign3 &= ~INTASSIGN_MASK;
446 intassign3 |= (uint16_t)assign;
449 intassign3 &= ~(INTASSIGN_MASK << 3);
450 intassign3 |= (uint16_t)assign << 3;
453 intassign3 &= ~(INTASSIGN_MASK << 6);
454 intassign3 |= (uint16_t)assign << 6;
457 intassign3 &= ~(INTASSIGN_MASK << 9);
458 intassign3 |= (uint16_t)assign << 9;
461 intassign3 &= ~(INTASSIGN_MASK << 12);
462 intassign3 |= (uint16_t)assign << 12;
468 sysint2_assign[pin] = assign;
469 write_icu1(intassign2, INTASSIGN2);
470 write_icu1(intassign3, INTASSIGN3);
472 spin_unlock_irq(&desc->lock);
477 int vr41xx_set_intassign(unsigned int irq, unsigned char intassign)
479 int retval = -EINVAL;
481 if (current_cpu_data.cputype != CPU_VR4133)
484 if (intassign > INTASSIGN_MAX)
487 if (irq >= SYSINT1_IRQ_BASE && irq <= SYSINT1_IRQ_LAST)
488 retval = set_sysint1_assign(irq, intassign);
489 else if (irq >= SYSINT2_IRQ_BASE && irq <= SYSINT2_IRQ_LAST)
490 retval = set_sysint2_assign(irq, intassign);
495 /*=======================================================================*/
497 static inline void giuint_irq_dispatch(uint16_t pendl, uint16_t pendh,
498 struct pt_regs *regs)
503 for (i = 0; i < 16; i++) {
504 if (pendl & ((uint16_t)1 << i)) {
505 giuint_do_IRQ(i, regs);
510 for (i = 0; i < 16; i++) {
511 if (pendh & ((uint16_t)1 << i)) {
512 giuint_do_IRQ(i + 16, regs);
519 asmlinkage void irq_dispatch(unsigned char intnum, struct pt_regs *regs)
521 uint16_t pend1, pend2, pendl, pendh;
522 uint16_t mask1, mask2, maskl, maskh;
525 pend1 = read_icu1(SYSINT1REG);
526 mask1 = read_icu1(MSYSINT1REG);
528 pend2 = read_icu2(SYSINT2REG);
529 mask2 = read_icu2(MSYSINT2REG);
531 pendl = read_icu1(GIUINTLREG);
532 maskl = read_icu1(MGIUINTLREG);
534 pendh = read_icu2(GIUINTHREG);
535 maskh = read_icu2(MGIUINTHREG);
543 for (i = 0; i < 16; i++) {
544 if (intnum == sysint1_assign[i] &&
545 (mask1 & ((uint16_t)1 << i))) {
546 if (i == 8 && (maskl | maskh)) {
547 giuint_irq_dispatch(maskl, maskh, regs);
550 do_IRQ(SYSINT1_IRQ(i), regs);
558 for (i = 0; i < 16; i++) {
559 if (intnum == sysint2_assign[i] &&
560 (mask2 & ((uint16_t)1 << i))) {
561 do_IRQ(SYSINT2_IRQ(i), regs);
567 printk(KERN_ERR "spurious interrupt: %04x,%04x,%04x,%04x\n", pend1, pend2, pendl, pendh);
568 atomic_inc(&irq_err_count);