3 * arch/mips/vr41xx/common/icu.c
5 * BRIEF MODULE DESCRIPTION
6 * Interrupt Control Unit routines for the NEC VR4100 series.
9 * yyuasa@mvista.com or source@mvista.com
11 * Copyright 2001,2002 MontaVista Software Inc.
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * You should have received a copy of the GNU General Public License along
30 * with this program; if not, write to the Free Software Foundation, Inc.,
31 * 675 Mass Ave, Cambridge, MA 02139, USA.
35 * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
36 * - New creation, NEC VR4122 and VR4131 are supported.
37 * - Added support for NEC VR4111 and VR4121.
39 * Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
40 * - Coped with INTASSIGN of NEC VR4133.
42 #include <linux/errno.h>
43 #include <linux/init.h>
44 #include <linux/interrupt.h>
45 #include <linux/irq.h>
46 #include <linux/smp.h>
47 #include <linux/types.h>
52 #include <asm/irq_cpu.h>
53 #include <asm/vr41xx/vr41xx.h>
55 extern asmlinkage void vr41xx_handle_interrupt(void);
57 extern void vr41xx_giuint_init(void);
58 extern void vr41xx_enable_giuint(int pin);
59 extern void vr41xx_disable_giuint(int pin);
60 extern void vr41xx_clear_giuint(int pin);
61 extern unsigned int giuint_do_IRQ(int pin, struct pt_regs *regs);
63 static uint32_t icu1_base;
64 static uint32_t icu2_base;
66 static unsigned char sysint1_assign[16] = {
67 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
68 static unsigned char sysint2_assign[16] = {
69 2, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
71 #define SYSINT1REG_TYPE1 KSEG1ADDR(0x0b000080)
72 #define SYSINT2REG_TYPE1 KSEG1ADDR(0x0b000200)
74 #define SYSINT1REG_TYPE2 KSEG1ADDR(0x0f000080)
75 #define SYSINT2REG_TYPE2 KSEG1ADDR(0x0f0000a0)
77 #define SYSINT1REG 0x00
78 #define INTASSIGN0 0x04
79 #define INTASSIGN1 0x06
80 #define GIUINTLREG 0x08
81 #define MSYSINT1REG 0x0c
82 #define MGIUINTLREG 0x14
85 #define INTASSIGN2 0x1c
86 #define INTASSIGN3 0x1e
88 #define SYSINT2REG 0x00
89 #define GIUINTHREG 0x02
90 #define MSYSINT2REG 0x06
91 #define MGIUINTHREG 0x08
93 #define SYSINT1_IRQ_TO_PIN(x) ((x) - SYSINT1_IRQ_BASE) /* Pin 0-15 */
94 #define SYSINT2_IRQ_TO_PIN(x) ((x) - SYSINT2_IRQ_BASE) /* Pin 0-15 */
96 #define read_icu1(offset) readw(icu1_base + (offset))
97 #define write_icu1(val, offset) writew((val), icu1_base + (offset))
99 #define read_icu2(offset) readw(icu2_base + (offset))
100 #define write_icu2(val, offset) writew((val), icu2_base + (offset))
102 #define INTASSIGN_MAX 4
103 #define INTASSIGN_MASK 0x0007
105 static inline uint16_t set_icu1(uint8_t offset, uint16_t set)
109 res = read_icu1(offset);
111 write_icu1(res, offset);
116 static inline uint16_t clear_icu1(uint8_t offset, uint16_t clear)
120 res = read_icu1(offset);
122 write_icu1(res, offset);
127 static inline uint16_t set_icu2(uint8_t offset, uint16_t set)
131 res = read_icu2(offset);
133 write_icu2(res, offset);
138 static inline uint16_t clear_icu2(uint8_t offset, uint16_t clear)
142 res = read_icu2(offset);
144 write_icu2(res, offset);
149 /*=======================================================================*/
151 static void enable_sysint1_irq(unsigned int irq)
153 set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
156 static void disable_sysint1_irq(unsigned int irq)
158 clear_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
161 static unsigned int startup_sysint1_irq(unsigned int irq)
163 set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
165 return 0; /* never anything pending */
168 #define shutdown_sysint1_irq disable_sysint1_irq
169 #define ack_sysint1_irq disable_sysint1_irq
171 static void end_sysint1_irq(unsigned int irq)
173 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
174 set_icu1(MSYSINT1REG, (uint16_t)1 << SYSINT1_IRQ_TO_PIN(irq));
177 static struct hw_interrupt_type sysint1_irq_type = {
178 .typename = "SYSINT1",
179 .startup = startup_sysint1_irq,
180 .shutdown = shutdown_sysint1_irq,
181 .enable = enable_sysint1_irq,
182 .disable = disable_sysint1_irq,
183 .ack = ack_sysint1_irq,
184 .end = end_sysint1_irq,
187 /*=======================================================================*/
189 static void enable_sysint2_irq(unsigned int irq)
191 set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
194 static void disable_sysint2_irq(unsigned int irq)
196 clear_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
199 static unsigned int startup_sysint2_irq(unsigned int irq)
201 set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
203 return 0; /* never anything pending */
206 #define shutdown_sysint2_irq disable_sysint2_irq
207 #define ack_sysint2_irq disable_sysint2_irq
209 static void end_sysint2_irq(unsigned int irq)
211 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
212 set_icu2(MSYSINT2REG, (uint16_t)1 << SYSINT2_IRQ_TO_PIN(irq));
215 static struct hw_interrupt_type sysint2_irq_type = {
216 .typename = "SYSINT2",
217 .startup = startup_sysint2_irq,
218 .shutdown = shutdown_sysint2_irq,
219 .enable = enable_sysint2_irq,
220 .disable = disable_sysint2_irq,
221 .ack = ack_sysint2_irq,
222 .end = end_sysint2_irq,
225 /*=======================================================================*/
227 static void enable_giuint_irq(unsigned int irq)
231 pin = GIU_IRQ_TO_PIN(irq);
233 set_icu1(MGIUINTLREG, (uint16_t)1 << pin);
235 set_icu2(MGIUINTHREG, (uint16_t)1 << (pin - 16));
236 vr41xx_enable_giuint(pin);
239 static void disable_giuint_irq(unsigned int irq)
243 pin = GIU_IRQ_TO_PIN(irq);
244 vr41xx_disable_giuint(pin);
246 clear_icu1(MGIUINTLREG, (uint16_t)1 << pin);
248 clear_icu2(MGIUINTHREG, (uint16_t)1 << (pin - 16));
251 static unsigned int startup_giuint_irq(unsigned int irq)
253 vr41xx_clear_giuint(GIU_IRQ_TO_PIN(irq));
255 enable_giuint_irq(irq);
257 return 0; /* never anything pending */
260 #define shutdown_giuint_irq disable_giuint_irq
262 static void ack_giuint_irq(unsigned int irq)
264 disable_giuint_irq(irq);
266 vr41xx_clear_giuint(GIU_IRQ_TO_PIN(irq));
269 static void end_giuint_irq(unsigned int irq)
271 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
272 enable_giuint_irq(irq);
275 static struct hw_interrupt_type giuint_irq_type = {
276 .typename = "GIUINT",
277 .startup = startup_giuint_irq,
278 .shutdown = shutdown_giuint_irq,
279 .enable = enable_giuint_irq,
280 .disable = disable_giuint_irq,
281 .ack = ack_giuint_irq,
282 .end = end_giuint_irq,
285 /*=======================================================================*/
287 static struct irqaction icu_cascade = {no_action, 0, 0, "cascade", NULL, NULL};
289 static void __init vr41xx_icu_init(void)
293 switch (current_cpu_data.cputype) {
296 icu1_base = SYSINT1REG_TYPE1;
297 icu2_base = SYSINT2REG_TYPE1;
302 icu1_base = SYSINT1REG_TYPE2;
303 icu2_base = SYSINT2REG_TYPE2;
306 panic("Unexpected CPU of NEC VR4100 series");
310 write_icu1(0, MSYSINT1REG);
311 write_icu1(0, MGIUINTLREG);
313 write_icu2(0, MSYSINT2REG);
314 write_icu2(0, MGIUINTHREG);
316 for (i = SYSINT1_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
317 if (i >= SYSINT1_IRQ_BASE && i <= SYSINT1_IRQ_LAST)
318 irq_desc[i].handler = &sysint1_irq_type;
319 else if (i >= SYSINT2_IRQ_BASE && i <= SYSINT2_IRQ_LAST)
320 irq_desc[i].handler = &sysint2_irq_type;
321 else if (i >= GIU_IRQ_BASE && i <= GIU_IRQ_LAST)
322 irq_desc[i].handler = &giuint_irq_type;
325 setup_irq(INT0_CASCADE_IRQ, &icu_cascade);
326 setup_irq(INT1_CASCADE_IRQ, &icu_cascade);
327 setup_irq(INT2_CASCADE_IRQ, &icu_cascade);
328 setup_irq(INT3_CASCADE_IRQ, &icu_cascade);
329 setup_irq(INT4_CASCADE_IRQ, &icu_cascade);
332 void __init init_IRQ(void)
334 memset(irq_desc, 0, sizeof(irq_desc));
337 mips_cpu_irq_init(MIPS_CPU_IRQ_BASE);
340 vr41xx_giuint_init();
342 set_except_vector(0, vr41xx_handle_interrupt);
345 /*=======================================================================*/
347 static inline int set_sysint1_assign(unsigned int irq, unsigned char assign)
349 irq_desc_t *desc = irq_desc + irq;
350 uint16_t intassign0, intassign1;
353 pin = SYSINT1_IRQ_TO_PIN(irq);
355 spin_lock_irq(&desc->lock);
357 intassign0 = read_icu1(INTASSIGN0);
358 intassign1 = read_icu1(INTASSIGN1);
362 intassign0 &= ~INTASSIGN_MASK;
363 intassign0 |= (uint16_t)assign;
366 intassign0 &= ~(INTASSIGN_MASK << 3);
367 intassign0 |= (uint16_t)assign << 3;
370 intassign0 &= ~(INTASSIGN_MASK << 6);
371 intassign0 |= (uint16_t)assign << 6;
374 intassign0 &= ~(INTASSIGN_MASK << 9);
375 intassign0 |= (uint16_t)assign << 9;
378 intassign0 &= ~(INTASSIGN_MASK << 12);
379 intassign0 |= (uint16_t)assign << 12;
382 intassign1 &= ~INTASSIGN_MASK;
383 intassign1 |= (uint16_t)assign;
386 intassign1 &= ~(INTASSIGN_MASK << 6);
387 intassign1 |= (uint16_t)assign << 6;
390 intassign1 &= ~(INTASSIGN_MASK << 9);
391 intassign1 |= (uint16_t)assign << 9;
397 sysint1_assign[pin] = assign;
398 write_icu1(intassign0, INTASSIGN0);
399 write_icu1(intassign1, INTASSIGN1);
401 spin_unlock_irq(&desc->lock);
406 static inline int set_sysint2_assign(unsigned int irq, unsigned char assign)
408 irq_desc_t *desc = irq_desc + irq;
409 uint16_t intassign2, intassign3;
412 pin = SYSINT2_IRQ_TO_PIN(irq);
414 spin_lock_irq(&desc->lock);
416 intassign2 = read_icu1(INTASSIGN2);
417 intassign3 = read_icu1(INTASSIGN3);
421 intassign2 &= ~INTASSIGN_MASK;
422 intassign2 |= (uint16_t)assign;
425 intassign2 &= ~(INTASSIGN_MASK << 3);
426 intassign2 |= (uint16_t)assign << 3;
429 intassign2 &= ~(INTASSIGN_MASK << 6);
430 intassign2 |= (uint16_t)assign << 6;
433 intassign2 &= ~(INTASSIGN_MASK << 9);
434 intassign2 |= (uint16_t)assign << 9;
437 intassign2 &= ~(INTASSIGN_MASK << 12);
438 intassign2 |= (uint16_t)assign << 12;
441 intassign3 &= ~INTASSIGN_MASK;
442 intassign3 |= (uint16_t)assign;
445 intassign3 &= ~(INTASSIGN_MASK << 3);
446 intassign3 |= (uint16_t)assign << 3;
449 intassign3 &= ~(INTASSIGN_MASK << 6);
450 intassign3 |= (uint16_t)assign << 6;
453 intassign3 &= ~(INTASSIGN_MASK << 9);
454 intassign3 |= (uint16_t)assign << 9;
457 intassign3 &= ~(INTASSIGN_MASK << 12);
458 intassign3 |= (uint16_t)assign << 12;
464 sysint2_assign[pin] = assign;
465 write_icu1(intassign2, INTASSIGN2);
466 write_icu1(intassign3, INTASSIGN3);
468 spin_unlock_irq(&desc->lock);
473 int vr41xx_set_intassign(unsigned int irq, unsigned char intassign)
475 int retval = -EINVAL;
477 if (current_cpu_data.cputype != CPU_VR4133)
480 if (intassign > INTASSIGN_MAX)
483 if (irq >= SYSINT1_IRQ_BASE && irq <= SYSINT1_IRQ_LAST)
484 retval = set_sysint1_assign(irq, intassign);
485 else if (irq >= SYSINT2_IRQ_BASE && irq <= SYSINT2_IRQ_LAST)
486 retval = set_sysint2_assign(irq, intassign);
491 /*=======================================================================*/
493 static inline void giuint_irq_dispatch(uint16_t pendl, uint16_t pendh,
494 struct pt_regs *regs)
499 for (i = 0; i < 16; i++) {
500 if (pendl & ((uint16_t)1 << i)) {
501 giuint_do_IRQ(i, regs);
506 for (i = 0; i < 16; i++) {
507 if (pendh & ((uint16_t)1 << i)) {
508 giuint_do_IRQ(i + 16, regs);
515 asmlinkage void irq_dispatch(unsigned char intnum, struct pt_regs *regs)
517 uint16_t pend1, pend2, pendl, pendh;
518 uint16_t mask1, mask2, maskl, maskh;
521 pend1 = read_icu1(SYSINT1REG);
522 mask1 = read_icu1(MSYSINT1REG);
524 pend2 = read_icu2(SYSINT2REG);
525 mask2 = read_icu2(MSYSINT2REG);
527 pendl = read_icu1(GIUINTLREG);
528 maskl = read_icu1(MGIUINTLREG);
530 pendh = read_icu2(GIUINTHREG);
531 maskh = read_icu2(MGIUINTHREG);
539 for (i = 0; i < 16; i++) {
540 if (intnum == sysint1_assign[i] &&
541 (mask1 & ((uint16_t)1 << i))) {
542 if (i == 8 && (maskl | maskh)) {
543 giuint_irq_dispatch(maskl, maskh, regs);
546 do_IRQ(SYSINT1_IRQ(i), regs);
554 for (i = 0; i < 16; i++) {
555 if (intnum == sysint2_assign[i] &&
556 (mask2 & ((uint16_t)1 << i))) {
557 do_IRQ(SYSINT2_IRQ(i), regs);
563 printk(KERN_ERR "spurious interrupt: %04x,%04x,%04x,%04x\n", pend1, pend2, pendl, pendh);
564 atomic_inc(&irq_err_count);