xref: /linux/arch/mips/jazz/irq.c (revision e4ac58afdfac792c0583af30dbd9eae53e24c78b)
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 1992 Linus Torvalds
7  * Copyright (C) 1994 - 2001, 2003 Ralf Baechle
8  */
9 #include <linux/init.h>
10 #include <linux/interrupt.h>
11 #include <linux/kernel.h>
12 #include <linux/spinlock.h>
13 
14 #include <asm/i8259.h>
15 #include <asm/io.h>
16 #include <asm/jazz.h>
17 
18 static DEFINE_SPINLOCK(r4030_lock);
19 
20 static void enable_r4030_irq(unsigned int irq)
21 {
22 	unsigned int mask = 1 << (irq - JAZZ_PARALLEL_IRQ);
23 	unsigned long flags;
24 
25 	spin_lock_irqsave(&r4030_lock, flags);
26 	mask |= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE);
27 	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask);
28 	spin_unlock_irqrestore(&r4030_lock, flags);
29 }
30 
31 static unsigned int startup_r4030_irq(unsigned int irq)
32 {
33 	enable_r4030_irq(irq);
34 	return 0; /* never anything pending */
35 }
36 
37 #define shutdown_r4030_irq	disable_r4030_irq
38 
39 void disable_r4030_irq(unsigned int irq)
40 {
41 	unsigned int mask = ~(1 << (irq - JAZZ_PARALLEL_IRQ));
42 	unsigned long flags;
43 
44 	spin_lock_irqsave(&r4030_lock, flags);
45 	mask &= r4030_read_reg16(JAZZ_IO_IRQ_ENABLE);
46 	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, mask);
47 	spin_unlock_irqrestore(&r4030_lock, flags);
48 }
49 
50 #define mask_and_ack_r4030_irq disable_r4030_irq
51 
52 static void end_r4030_irq(unsigned int irq)
53 {
54 	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
55 		enable_r4030_irq(irq);
56 }
57 
58 static struct hw_interrupt_type r4030_irq_type = {
59 	.typename = "R4030",
60 	.startup = startup_r4030_irq,
61 	.shutdown = shutdown_r4030_irq,
62 	.enable = enable_r4030_irq,
63 	.disable = disable_r4030_irq,
64 	.ack = mask_and_ack_r4030_irq,
65 	.end = end_r4030_irq,
66 };
67 
68 void __init init_r4030_ints(void)
69 {
70 	int i;
71 
72 	for (i = JAZZ_PARALLEL_IRQ; i <= JAZZ_TIMER_IRQ; i++) {
73 		irq_desc[i].status     = IRQ_DISABLED;
74 		irq_desc[i].action     = 0;
75 		irq_desc[i].depth      = 1;
76 		irq_desc[i].handler    = &r4030_irq_type;
77 	}
78 
79 	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0);
80 	r4030_read_reg16(JAZZ_IO_IRQ_SOURCE);		/* clear pending IRQs */
81 	r4030_read_reg32(JAZZ_R4030_INVAL_ADDR);	/* clear error bits */
82 }
83 
84 /*
85  * On systems with i8259-style interrupt controllers we assume for
86  * driver compatibility reasons interrupts 0 - 15 to be the i8259
87  * interrupts even if the hardware uses a different interrupt numbering.
88  */
89 void __init arch_init_irq(void)
90 {
91 	init_i8259_irqs();			/* Integrated i8259  */
92 	init_r4030_ints();
93 
94 	change_c0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1);
95 }
96 
97 static void loc_call(unsigned int irq, struct pt_regs *regs, unsigned int mask)
98 {
99 	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
100 	                  r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) & mask);
101 	do_IRQ(irq, regs);
102 	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE,
103 	                  r4030_read_reg16(JAZZ_IO_IRQ_ENABLE) | mask);
104 }
105 
106 static void ll_local_dev(struct pt_regs *regs)
107 {
108 	switch (r4030_read_reg32(JAZZ_IO_IRQ_SOURCE)) {
109 	case 0:
110 		panic("Unimplemented loc_no_irq handler");
111 		break;
112 	case 4:
113 		loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_PARALLEL);
114 		break;
115 	case 8:
116 		loc_call(JAZZ_PARALLEL_IRQ, regs, JAZZ_IE_FLOPPY);
117 		break;
118 	case 12:
119 		panic("Unimplemented loc_sound handler");
120 		break;
121 	case 16:
122 		panic("Unimplemented loc_video handler");
123 		break;
124 	case 20:
125 		loc_call(JAZZ_ETHERNET_IRQ, regs, JAZZ_IE_ETHERNET);
126 		break;
127 	case 24:
128 		loc_call(JAZZ_SCSI_IRQ, regs, JAZZ_IE_SCSI);
129 		break;
130 	case 28:
131 		loc_call(JAZZ_KEYBOARD_IRQ, regs, JAZZ_IE_KEYBOARD);
132 		break;
133 	case 32:
134 		loc_call(JAZZ_MOUSE_IRQ, regs, JAZZ_IE_MOUSE);
135 		break;
136 	case 36:
137 		loc_call(JAZZ_SERIAL1_IRQ, regs, JAZZ_IE_SERIAL1);
138 		break;
139 	case 40:
140 		loc_call(JAZZ_SERIAL2_IRQ, regs, JAZZ_IE_SERIAL2);
141 		break;
142 	}
143 }
144 
145 asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
146 {
147 	unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
148 
149 	if (pending & IE_IRQ5)
150 		write_c0_compare(0);
151 	else if (pending & IE_IRQ4) {
152 		r4030_read_reg32(JAZZ_TIMER_REGISTER);
153 		do_IRQ(JAZZ_TIMER_IRQ, regs);
154 	} else if (pending & IE_IRQ3)
155 		panic("Unimplemented ISA NMI handler");
156 	else if (pending & IE_IRQ2)
157 		do_IRQ(r4030_read_reg32(JAZZ_EISA_IRQ_ACK), regs);
158 	else if (pending & IE_IRQ1) {
159 		ll_local_dev(regs);
160 	} else if (unlikely(pending & IE_IRQ0))
161 		panic("Unimplemented local_dma handler");
162 	else if (pending & IE_SW1) {
163 		clear_c0_cause(IE_SW1);
164 		panic("Unimplemented sw1 handler");
165 	} else if (pending & IE_SW0) {
166 		clear_c0_cause(IE_SW0);
167 		panic("Unimplemented sw0 handler");
168 	}
169 }
170