blob: 19c9ee9e3d0c539f8b6c261a9784ca2fb6313f32 [file] [log] [blame]
Ralf Baechle23fbee92005-07-25 22:45:45 +00001/*
Uwe Zeisbergerf30c2262006-10-03 23:01:26 +02002 * linux/arch/mips/tx4938/common/irq.c
Ralf Baechle23fbee92005-07-25 22:45:45 +00003 *
4 * Common tx4938 irq handler
5 * Copyright (C) 2000-2001 Toshiba Corporation
6 *
7 * 2003-2005 (c) MontaVista Software, Inc. This file is licensed under the
8 * terms of the GNU General Public License version 2. This program is
9 * licensed "as is" without any warranty of any kind, whether express
10 * or implied.
11 *
12 * Support for TX4938 in 2.6 - Manish Lachwani (mlachwani@mvista.com)
13 */
14#include <linux/errno.h>
15#include <linux/init.h>
16#include <linux/kernel_stat.h>
17#include <linux/module.h>
18#include <linux/signal.h>
19#include <linux/sched.h>
20#include <linux/types.h>
21#include <linux/interrupt.h>
22#include <linux/ioport.h>
23#include <linux/timex.h>
24#include <linux/slab.h>
25#include <linux/random.h>
26#include <linux/irq.h>
27#include <asm/bitops.h>
28#include <asm/bootinfo.h>
29#include <asm/io.h>
30#include <asm/irq.h>
31#include <asm/mipsregs.h>
32#include <asm/system.h>
Atsushi Nemotof5c70dd2006-08-20 22:55:52 +090033#include <asm/wbflush.h>
Ralf Baechle23fbee92005-07-25 22:45:45 +000034#include <asm/tx4938/rbtx4938.h>
35
36/**********************************************************************************/
37/* Forwad definitions for all pic's */
38/**********************************************************************************/
39
Ralf Baechle23fbee92005-07-25 22:45:45 +000040static void tx4938_irq_cp0_enable(unsigned int irq);
41static void tx4938_irq_cp0_disable(unsigned int irq);
Ralf Baechle23fbee92005-07-25 22:45:45 +000042static void tx4938_irq_cp0_end(unsigned int irq);
43
Ralf Baechle23fbee92005-07-25 22:45:45 +000044static void tx4938_irq_pic_enable(unsigned int irq);
45static void tx4938_irq_pic_disable(unsigned int irq);
Ralf Baechle23fbee92005-07-25 22:45:45 +000046static void tx4938_irq_pic_end(unsigned int irq);
47
48/**********************************************************************************/
49/* Kernel structs for all pic's */
50/**********************************************************************************/
Ralf Baechle23fbee92005-07-25 22:45:45 +000051
52#define TX4938_CP0_NAME "TX4938-CP0"
Ralf Baechle94dee172006-07-02 14:41:42 +010053static struct irq_chip tx4938_irq_cp0_type = {
Ralf Baechle23fbee92005-07-25 22:45:45 +000054 .typename = TX4938_CP0_NAME,
Atsushi Nemoto1603b5a2006-11-02 02:08:36 +090055 .ack = tx4938_irq_cp0_disable,
56 .mask = tx4938_irq_cp0_disable,
57 .mask_ack = tx4938_irq_cp0_disable,
58 .unmask = tx4938_irq_cp0_enable,
Ralf Baechle23fbee92005-07-25 22:45:45 +000059 .end = tx4938_irq_cp0_end,
Ralf Baechle23fbee92005-07-25 22:45:45 +000060};
61
62#define TX4938_PIC_NAME "TX4938-PIC"
Ralf Baechle94dee172006-07-02 14:41:42 +010063static struct irq_chip tx4938_irq_pic_type = {
Ralf Baechle23fbee92005-07-25 22:45:45 +000064 .typename = TX4938_PIC_NAME,
Atsushi Nemoto1603b5a2006-11-02 02:08:36 +090065 .ack = tx4938_irq_pic_disable,
66 .mask = tx4938_irq_pic_disable,
67 .mask_ack = tx4938_irq_pic_disable,
68 .unmask = tx4938_irq_pic_enable,
Ralf Baechle23fbee92005-07-25 22:45:45 +000069 .end = tx4938_irq_pic_end,
Ralf Baechle23fbee92005-07-25 22:45:45 +000070};
71
72static struct irqaction tx4938_irq_pic_action = {
73 .handler = no_action,
74 .flags = 0,
75 .mask = CPU_MASK_NONE,
76 .name = TX4938_PIC_NAME
77};
78
79/**********************************************************************************/
80/* Functions for cp0 */
81/**********************************************************************************/
82
83#define tx4938_irq_cp0_mask(irq) ( 1 << ( irq-TX4938_IRQ_CP0_BEG+8 ) )
84
85static void __init
86tx4938_irq_cp0_init(void)
87{
88 int i;
89
Atsushi Nemoto1603b5a2006-11-02 02:08:36 +090090 for (i = TX4938_IRQ_CP0_BEG; i <= TX4938_IRQ_CP0_END; i++)
91 set_irq_chip(i, &tx4938_irq_cp0_type);
Ralf Baechle23fbee92005-07-25 22:45:45 +000092}
93
94static void
95tx4938_irq_cp0_enable(unsigned int irq)
96{
Ralf Baechle23fbee92005-07-25 22:45:45 +000097 set_c0_status(tx4938_irq_cp0_mask(irq));
Ralf Baechle23fbee92005-07-25 22:45:45 +000098}
99
100static void
101tx4938_irq_cp0_disable(unsigned int irq)
102{
Ralf Baechle23fbee92005-07-25 22:45:45 +0000103 clear_c0_status(tx4938_irq_cp0_mask(irq));
Ralf Baechle23fbee92005-07-25 22:45:45 +0000104}
105
106static void
107tx4938_irq_cp0_end(unsigned int irq)
108{
109 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
110 tx4938_irq_cp0_enable(irq);
111 }
Ralf Baechle23fbee92005-07-25 22:45:45 +0000112}
113
114/**********************************************************************************/
115/* Functions for pic */
116/**********************************************************************************/
117
118u32
119tx4938_irq_pic_addr(int irq)
120{
121 /* MVMCP -- need to formulize this */
122 irq -= TX4938_IRQ_PIC_BEG;
123
124 switch (irq) {
125 case 17:
126 case 16:
127 case 1:
128 case 0:{
129 return (TX4938_MKA(TX4938_IRC_IRLVL0));
130 }
131 case 19:
132 case 18:
133 case 3:
134 case 2:{
135 return (TX4938_MKA(TX4938_IRC_IRLVL1));
136 }
137 case 21:
138 case 20:
139 case 5:
140 case 4:{
141 return (TX4938_MKA(TX4938_IRC_IRLVL2));
142 }
143 case 23:
144 case 22:
145 case 7:
146 case 6:{
147 return (TX4938_MKA(TX4938_IRC_IRLVL3));
148 }
149 case 25:
150 case 24:
151 case 9:
152 case 8:{
153 return (TX4938_MKA(TX4938_IRC_IRLVL4));
154 }
155 case 27:
156 case 26:
157 case 11:
158 case 10:{
159 return (TX4938_MKA(TX4938_IRC_IRLVL5));
160 }
161 case 29:
162 case 28:
163 case 13:
164 case 12:{
165 return (TX4938_MKA(TX4938_IRC_IRLVL6));
166 }
167 case 31:
168 case 30:
169 case 15:
170 case 14:{
171 return (TX4938_MKA(TX4938_IRC_IRLVL7));
172 }
173 }
174
Ralf Baechle937a8012006-10-07 19:44:33 +0100175 return 0;
Ralf Baechle23fbee92005-07-25 22:45:45 +0000176}
177
178u32
179tx4938_irq_pic_mask(int irq)
180{
181 /* MVMCP -- need to formulize this */
182 irq -= TX4938_IRQ_PIC_BEG;
183
184 switch (irq) {
185 case 31:
186 case 29:
187 case 27:
188 case 25:
189 case 23:
190 case 21:
191 case 19:
192 case 17:{
193 return (0x07000000);
194 }
195 case 30:
196 case 28:
197 case 26:
198 case 24:
199 case 22:
200 case 20:
201 case 18:
202 case 16:{
203 return (0x00070000);
204 }
205 case 15:
206 case 13:
207 case 11:
208 case 9:
209 case 7:
210 case 5:
211 case 3:
212 case 1:{
213 return (0x00000700);
214 }
215 case 14:
216 case 12:
217 case 10:
218 case 8:
219 case 6:
220 case 4:
221 case 2:
222 case 0:{
223 return (0x00000007);
224 }
225 }
Ralf Baechle937a8012006-10-07 19:44:33 +0100226 return 0x00000000;
Ralf Baechle23fbee92005-07-25 22:45:45 +0000227}
228
229static void
230tx4938_irq_pic_modify(unsigned pic_reg, unsigned clr_bits, unsigned set_bits)
231{
232 unsigned long val = 0;
233
234 val = TX4938_RD(pic_reg);
235 val &= (~clr_bits);
236 val |= (set_bits);
237 TX4938_WR(pic_reg, val);
238 mmiowb();
239 TX4938_RD(pic_reg);
Ralf Baechle23fbee92005-07-25 22:45:45 +0000240}
241
242static void __init
243tx4938_irq_pic_init(void)
244{
Ralf Baechle23fbee92005-07-25 22:45:45 +0000245 int i;
246
Atsushi Nemoto1603b5a2006-11-02 02:08:36 +0900247 for (i = TX4938_IRQ_PIC_BEG; i <= TX4938_IRQ_PIC_END; i++)
248 set_irq_chip(i, &tx4938_irq_pic_type);
Ralf Baechle23fbee92005-07-25 22:45:45 +0000249
250 setup_irq(TX4938_IRQ_NEST_PIC_ON_CP0, &tx4938_irq_pic_action);
251
Ralf Baechle23fbee92005-07-25 22:45:45 +0000252 TX4938_WR(0xff1ff640, 0x6); /* irq level mask -- only accept hightest */
253 TX4938_WR(0xff1ff600, TX4938_RD(0xff1ff600) | 0x1); /* irq enable */
Ralf Baechle23fbee92005-07-25 22:45:45 +0000254}
255
256static void
257tx4938_irq_pic_enable(unsigned int irq)
258{
Ralf Baechle23fbee92005-07-25 22:45:45 +0000259 tx4938_irq_pic_modify(tx4938_irq_pic_addr(irq), 0,
260 tx4938_irq_pic_mask(irq));
Ralf Baechle23fbee92005-07-25 22:45:45 +0000261}
262
263static void
264tx4938_irq_pic_disable(unsigned int irq)
265{
Ralf Baechle23fbee92005-07-25 22:45:45 +0000266 tx4938_irq_pic_modify(tx4938_irq_pic_addr(irq),
267 tx4938_irq_pic_mask(irq), 0);
Ralf Baechle23fbee92005-07-25 22:45:45 +0000268}
269
270static void
271tx4938_irq_pic_end(unsigned int irq)
272{
273 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
274 tx4938_irq_pic_enable(irq);
275 }
Ralf Baechle23fbee92005-07-25 22:45:45 +0000276}
277
278/**********************************************************************************/
279/* Main init functions */
280/**********************************************************************************/
281
282void __init
283tx4938_irq_init(void)
284{
Ralf Baechle23fbee92005-07-25 22:45:45 +0000285 tx4938_irq_cp0_init();
286 tx4938_irq_pic_init();
Ralf Baechle23fbee92005-07-25 22:45:45 +0000287}
288
289int
290tx4938_irq_nested(void)
291{
292 int sw_irq = 0;
293 u32 level2;
294
295 level2 = TX4938_RD(0xff1ff6a0);
296 if ((level2 & 0x10000) == 0) {
297 level2 &= 0x1f;
298 sw_irq = TX4938_IRQ_PIC_BEG + level2;
299 if (sw_irq == 26) {
300 {
301 extern int toshiba_rbtx4938_irq_nested(int sw_irq);
302 sw_irq = toshiba_rbtx4938_irq_nested(sw_irq);
303 }
304 }
305 }
306
307 wbflush();
Ralf Baechle937a8012006-10-07 19:44:33 +0100308 return sw_irq;
Ralf Baechle23fbee92005-07-25 22:45:45 +0000309}
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100310
Ralf Baechle937a8012006-10-07 19:44:33 +0100311asmlinkage void plat_irq_dispatch(void)
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100312{
313 unsigned int pending = read_c0_cause() & read_c0_status();
314
315 if (pending & STATUSF_IP7)
Ralf Baechle937a8012006-10-07 19:44:33 +0100316 do_IRQ(TX4938_IRQ_CPU_TIMER);
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100317 else if (pending & STATUSF_IP2) {
318 int irq = tx4938_irq_nested();
319 if (irq)
Ralf Baechle937a8012006-10-07 19:44:33 +0100320 do_IRQ(irq);
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100321 else
Ralf Baechle937a8012006-10-07 19:44:33 +0100322 spurious_interrupt();
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100323 } else if (pending & STATUSF_IP1)
Ralf Baechle937a8012006-10-07 19:44:33 +0100324 do_IRQ(TX4938_IRQ_USER1);
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100325 else if (pending & STATUSF_IP0)
Ralf Baechle937a8012006-10-07 19:44:33 +0100326 do_IRQ(TX4938_IRQ_USER0);
Ralf Baechlee4ac58a2006-04-03 17:56:36 +0100327}