more irq patches and cleanups
[openwrt.git] / openwrt / target / linux / aruba-2.6 / patches / 002-irq.patch
1 diff -Nur linux-2.6.15/arch/mips/aruba/idtIRQ.S linux-2.6.15-openwrt/arch/mips/aruba/idtIRQ.S
2 --- linux-2.6.15/arch/mips/aruba/idtIRQ.S 1970-01-01 01:00:00.000000000 +0100
3 +++ linux-2.6.15-openwrt/arch/mips/aruba/idtIRQ.S 2006-01-10 00:32:32.000000000 +0100
4 @@ -0,0 +1,87 @@
5 +/**************************************************************************
6 + *
7 + * BRIEF MODULE DESCRIPTION
8 + * Intterrupt dispatcher code for IDT boards
9 + *
10 + * Copyright 2004 IDT Inc. (rischelp@idt.com)
11 + *
12 + * This program is free software; you can redistribute it and/or modify it
13 + * under the terms of the GNU General Public License as published by the
14 + * Free Software Foundation; either version 2 of the License, or (at your
15 + * option) any later version.
16 + *
17 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
20 + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 + *
28 + * You should have received a copy of the GNU General Public License along
29 + * with this program; if not, write to the Free Software Foundation, Inc.,
30 + * 675 Mass Ave, Cambridge, MA 02139, USA.
31 + *
32 + *
33 + **************************************************************************
34 + * May 2004 rkt, neb
35 + *
36 + * Initial Release
37 + *
38 + *
39 + *
40 + **************************************************************************
41 + */
42 +
43 +
44 +#include <asm/asm.h>
45 +#include <asm/mipsregs.h>
46 +#include <asm/regdef.h>
47 +#include <asm/stackframe.h>
48 +
49 + .text
50 + .set noreorder
51 + .set noat
52 + .align 5
53 + NESTED(idtIRQ, PT_SIZE, sp)
54 + .set noat
55 + SAVE_ALL
56 + CLI
57 +
58 + .set at
59 + .set noreorder
60 +
61 + /* Get the pending interrupts */
62 + mfc0 t0, CP0_CAUSE
63 + nop
64 +
65 + /* Isolate the allowed ones by anding the irq mask */
66 + mfc0 t2, CP0_STATUS
67 + move a1, sp /* need a nop here, hence we anticipate */
68 + andi t0, CAUSEF_IP
69 + and t0, t2
70 +
71 + /* check for r4k counter/timer IRQ. */
72 +
73 + andi t1, t0, CAUSEF_IP7
74 + beqz t1, 1f
75 + nop
76 +
77 + jal aruba_timer_interrupt
78 +
79 + li a0, 7
80 +
81 + j ret_from_irq
82 + nop
83 +1:
84 + jal aruba_irqdispatch
85 + move a0, t0
86 + j ret_from_irq
87 + nop
88 +
89 + END(idtIRQ)
90 +
91 +
92 diff -Nur linux-2.6.15/arch/mips/aruba/irq.c linux-2.6.15-openwrt/arch/mips/aruba/irq.c
93 --- linux-2.6.15/arch/mips/aruba/irq.c 1970-01-01 01:00:00.000000000 +0100
94 +++ linux-2.6.15-openwrt/arch/mips/aruba/irq.c 2006-01-10 00:32:32.000000000 +0100
95 @@ -0,0 +1,429 @@
96 +/**************************************************************************
97 + *
98 + * BRIEF MODULE DESCRIPTION
99 + * Interrupt routines for IDT EB434 boards / Atheros boards
100 + * Modified by Aruba Networks
101 + *
102 + * Copyright 2004 IDT Inc. (rischelp@idt.com)
103 + *
104 + * This program is free software; you can redistribute it and/or modify it
105 + * under the terms of the GNU General Public License as published by the
106 + * Free Software Foundation; either version 2 of the License, or (at your
107 + * option) any later version.
108 + *
109 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
110 + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
111 + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
112 + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
113 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
114 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
115 + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
116 + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
117 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
118 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
119 + *
120 + * You should have received a copy of the GNU General Public License along
121 + * with this program; if not, write to the Free Software Foundation, Inc.,
122 + * 675 Mass Ave, Cambridge, MA 02139, USA.
123 + *
124 + *
125 + **************************************************************************
126 + * May 2004 rkt, neb
127 + *
128 + * Initial Release
129 + *
130 + *
131 + *
132 + **************************************************************************
133 + */
134 +
135 +#include <linux/errno.h>
136 +#include <linux/init.h>
137 +#include <linux/kernel_stat.h>
138 +#include <linux/module.h>
139 +#include <linux/signal.h>
140 +#include <linux/sched.h>
141 +#include <linux/types.h>
142 +#include <linux/interrupt.h>
143 +#include <linux/ioport.h>
144 +#include <linux/timex.h>
145 +#include <linux/slab.h>
146 +#include <linux/random.h>
147 +#include <linux/delay.h>
148 +
149 +#include <asm/bitops.h>
150 +#include <asm/bootinfo.h>
151 +#include <asm/io.h>
152 +#include <asm/mipsregs.h>
153 +#include <asm/system.h>
154 +#include <asm/idt-boards/rc32434/rc32434.h>
155 +#include <asm/idt-boards/rc32434/rc32434_gpio.h>
156 +
157 +#include <asm/irq.h>
158 +
159 +#undef DEBUG_IRQ
160 +#ifdef DEBUG_IRQ
161 +/* note: prints function name for you */
162 +#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
163 +#else
164 +#define DPRINTK(fmt, args...)
165 +#endif
166 +
167 +extern asmlinkage void idtIRQ(void);
168 +static unsigned int startup_irq(unsigned int irq);
169 +static void end_irq(unsigned int irq_nr);
170 +static void mask_and_ack_irq(unsigned int irq_nr);
171 +static void aruba_enable_irq(unsigned int irq_nr);
172 +static void aruba_disable_irq(unsigned int irq_nr);
173 +
174 +extern void __init init_generic_irq(void);
175 +
176 +typedef struct {
177 + u32 mask;
178 + volatile u32 *base_addr;
179 +} intr_group_t;
180 +
181 +static const intr_group_t intr_group_merlot[NUM_INTR_GROUPS] = {
182 + {0xffffffff, (u32 *) KSEG1ADDR(IC_GROUP0_PEND + 0)},
183 +};
184 +
185 +#define READ_PEND_MERLOT(base) (*((volatile unsigned long *)(0xbc003010)))
186 +#define READ_MASK_MERLOT(base) (*((volatile unsigned long *)(0xbc003014)))
187 +#define WRITE_MASK_MERLOT(base, val) ((*((volatile unsigned long *)(0xbc003014))) = (val), READ_MASK_MERLOT())
188 +
189 +static const intr_group_t intr_group_muscat[NUM_INTR_GROUPS] = {
190 + {0x0000efff, (u32 *) KSEG1ADDR(IC_GROUP0_PEND + 0 * IC_GROUP_OFFSET)},
191 + {0x00001fff, (u32 *) KSEG1ADDR(IC_GROUP0_PEND + 1 * IC_GROUP_OFFSET)},
192 + {0x00000007, (u32 *) KSEG1ADDR(IC_GROUP0_PEND + 2 * IC_GROUP_OFFSET)},
193 + {0x0003ffff, (u32 *) KSEG1ADDR(IC_GROUP0_PEND + 3 * IC_GROUP_OFFSET)},
194 + {0xffffffff, (u32 *) KSEG1ADDR(IC_GROUP0_PEND + 4 * IC_GROUP_OFFSET)}
195 +};
196 +
197 +#define READ_PEND_MUSCAT(base) (*(base))
198 +#define READ_MASK_MUSCAT(base) (*(base + 2))
199 +#define WRITE_MASK_MUSCAT(base, val) (*(base + 2) = (val))
200 +
201 +static inline int irq_to_group(unsigned int irq_nr)
202 +{
203 + switch (mips_machtype) {
204 + case MACH_ARUBA_AP70:
205 + return ((irq_nr - GROUP0_IRQ_BASE) >> 5);
206 + case MACH_ARUBA_AP65:
207 + case MACH_ARUBA_AP60:
208 + default:
209 + return 0;
210 + }
211 +}
212 +
213 +static inline int group_to_ip(unsigned int group)
214 +{
215 + switch (mips_machtype) {
216 + case MACH_ARUBA_AP70:
217 + return group + 2;
218 + case MACH_ARUBA_AP65:
219 + case MACH_ARUBA_AP60:
220 + default:
221 + return 6;
222 + }
223 +}
224 +
225 +static inline void enable_local_irq(unsigned int ip)
226 +{
227 + set_c0_status(0x100 << ip);
228 + irq_enable_hazard();
229 +}
230 +
231 +static inline void disable_local_irq(unsigned int ip)
232 +{
233 + clear_c0_status(0x100 << ip);
234 + irq_disable_hazard();
235 +}
236 +
237 +static void aruba_enable_irq(unsigned int irq_nr)
238 +{
239 + unsigned long flags;
240 + int ip = irq_nr - GROUP0_IRQ_BASE;
241 + unsigned int group, intr_bit;
242 + volatile unsigned int *addr;
243 +
244 +
245 + local_irq_save(flags);
246 +
247 + if (ip < 0) {
248 + enable_local_irq(irq_nr);
249 + } else {
250 + // calculate group
251 + switch (mips_machtype) {
252 + case MACH_ARUBA_AP70:
253 + group = ip >> 5;
254 + break;
255 + case MACH_ARUBA_AP65:
256 + case MACH_ARUBA_AP60:
257 + default:
258 + group = 0;
259 + break;
260 + }
261 +
262 + // calc interrupt bit within group
263 + ip -= (group << 5);
264 + intr_bit = 1 << ip;
265 +
266 + switch (mips_machtype) {
267 + case MACH_ARUBA_AP70:
268 + addr = intr_group_muscat[group].base_addr;
269 + WRITE_MASK_MUSCAT(addr, READ_MASK_MUSCAT(addr) & ~intr_bit);
270 + break;
271 + case MACH_ARUBA_AP65:
272 + case MACH_ARUBA_AP60:
273 + default:
274 + addr = intr_group_merlot[group].base_addr;
275 + WRITE_MASK_MERLOT(addr, READ_MASK_MERLOT(addr) | intr_bit);
276 + break;
277 + }
278 + enable_local_irq(group_to_ip(group));
279 + }
280 +
281 + back_to_back_c0_hazard();
282 + local_irq_restore(flags);
283 +
284 +}
285 +
286 +static void aruba_disable_irq(unsigned int irq_nr)
287 +{
288 + unsigned long flags;
289 + int ip = irq_nr - GROUP0_IRQ_BASE;
290 + unsigned int group, intr_bit, mask;
291 + volatile unsigned int *addr;
292 +
293 + local_irq_save(flags);
294 +
295 + if (ip < 0) {
296 + disable_local_irq(irq_nr);
297 + } else {
298 + // calculate group
299 + switch (mips_machtype) {
300 + case MACH_ARUBA_AP70:
301 + group = ip >> 5;
302 + break;
303 + case MACH_ARUBA_AP65:
304 + case MACH_ARUBA_AP60:
305 + default:
306 + group = 0;
307 + break;
308 + }
309 +
310 + // calc interrupt bit within group
311 + ip -= group << 5;
312 + intr_bit = 1 << ip;
313 +
314 + switch (mips_machtype) {
315 + case MACH_ARUBA_AP70:
316 + addr = intr_group_muscat[group].base_addr;
317 + // mask intr within group
318 + mask = READ_MASK_MUSCAT(addr);
319 + mask |= intr_bit;
320 + WRITE_MASK_MUSCAT(addr, mask);
321 +
322 + /*
323 + if there are no more interrupts enabled in this
324 + group, disable corresponding IP
325 + */
326 + if (mask == intr_group_muscat[group].mask)
327 + disable_local_irq(group_to_ip(group));
328 + break;
329 + case MACH_ARUBA_AP65:
330 + case MACH_ARUBA_AP60:
331 + default:
332 + addr = intr_group_merlot[group].base_addr;
333 + // mask intr within group
334 + mask = READ_MASK_MERLOT(addr);
335 + mask &= ~intr_bit;
336 + if (!mask)
337 + disable_local_irq(group_to_ip(group));
338 + WRITE_MASK_MERLOT(addr, mask);
339 + break;
340 + }
341 + }
342 +
343 + back_to_back_c0_hazard();
344 + local_irq_restore(flags);
345 +}
346 +
347 +static unsigned int startup_irq(unsigned int irq_nr)
348 +{
349 + aruba_enable_irq(irq_nr);
350 + return 0;
351 +}
352 +
353 +static void shutdown_irq(unsigned int irq_nr)
354 +{
355 + aruba_disable_irq(irq_nr);
356 +}
357 +
358 +static void mask_and_ack_irq(unsigned int irq_nr)
359 +{
360 + aruba_disable_irq(irq_nr);
361 +}
362 +
363 +static void end_irq(unsigned int irq_nr)
364 +{
365 +
366 + int ip = irq_nr - GROUP0_IRQ_BASE;
367 + unsigned int intr_bit, group;
368 + volatile unsigned int *addr;
369 +
370 +
371 + if (irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS)) {
372 + printk("warning: end_irq %d did not enable (%x)\n",
373 + irq_nr, irq_desc[irq_nr].status);
374 + /* fall through; enable the interrupt
375 + * -- It'll get stuck otherwise
376 + */
377 +
378 + }
379 +
380 + if (ip<0) {
381 + enable_local_irq(irq_nr);
382 + } else {
383 +
384 + switch (mips_machtype) {
385 + case MACH_ARUBA_AP70:
386 + if (irq_nr == GROUP4_IRQ_BASE + 9) idt_gpio->gpioistat &= 0xfffffdff;
387 + else if (irq_nr == GROUP4_IRQ_BASE + 10) idt_gpio->gpioistat &= 0xfffffbff;
388 + else if (irq_nr == GROUP4_IRQ_BASE + 11) idt_gpio->gpioistat &= 0xfffff7ff;
389 + else if (irq_nr == GROUP4_IRQ_BASE + 12) idt_gpio->gpioistat &= 0xffffefff;
390 +
391 + group = ip >> 5;
392 +
393 + // calc interrupt bit within group
394 + ip -= (group << 5);
395 + intr_bit = 1 << ip;
396 +
397 + // first enable the IP mapped to this IRQ
398 + enable_local_irq(group_to_ip(group));
399 +
400 + addr = intr_group_muscat[group].base_addr;
401 + // unmask intr within group
402 + WRITE_MASK_MUSCAT(addr, READ_MASK_MUSCAT(addr) & ~intr_bit);
403 + break;
404 +
405 + case MACH_ARUBA_AP65:
406 + case MACH_ARUBA_AP60:
407 + default:
408 + group = 0;
409 +
410 + // calc interrupt bit within group
411 + intr_bit = 1 << ip;
412 +
413 + // first enable the IP mapped to this IRQ
414 + enable_local_irq(group_to_ip(group));
415 +
416 + addr = intr_group_merlot[group].base_addr;
417 + // unmask intr within group
418 + WRITE_MASK_MERLOT(addr, READ_MASK_MERLOT(addr) | intr_bit);
419 + break;
420 + }
421 + }
422 +}
423 +
424 +static struct hw_interrupt_type aruba_irq_type = {
425 + .typename = "ARUBA",
426 + .startup = startup_irq,
427 + .shutdown = shutdown_irq,
428 + .enable = aruba_enable_irq,
429 + .disable = aruba_disable_irq,
430 + .ack = mask_and_ack_irq,
431 + .end = end_irq,
432 +};
433 +
434 +void __init arch_init_irq(void)
435 +{
436 + int i;
437 + printk("Initializing IRQ's: %d out of %d\n", RC32434_NR_IRQS, NR_IRQS);
438 + memset(irq_desc, 0, sizeof(irq_desc));
439 + set_except_vector(0, idtIRQ);
440 +
441 + set_c0_status(0xFF00);
442 +
443 + for (i = 0; i < RC32434_NR_IRQS; i++) {
444 + irq_desc[i].status = IRQ_DISABLED;
445 + irq_desc[i].action = NULL;
446 + irq_desc[i].depth = 1;
447 + irq_desc[i].handler = &aruba_irq_type;
448 + spin_lock_init(&irq_desc[i].lock);
449 + }
450 +}
451 +
452 +/* Main Interrupt dispatcher */
453 +void aruba_irqdispatch(unsigned long cp0_cause, struct pt_regs *regs)
454 +{
455 + unsigned int pend, group, ip;
456 + volatile unsigned int *addr;
457 +
458 + if(cp0_cause == 0) {
459 + printk("INTERRUPT(S) FIRED WHILE MASKED\n");
460 +#ifdef ARUBA_DEBUG
461 + // debuging use -- figure out which interrupt(s) fired
462 + cp0_cause = read_c0_cause() & CAUSEF_IP;
463 + while (cp0_cause) {
464 + unsigned long intr_bit;
465 + unsigned int irq_nr;
466 + intr_bit = (31 - rc32434_clz(cp0_cause));
467 + irq_nr = intr_bit - GROUP0_IRQ_BASE;
468 + printk(" ---> MASKED IRQ %d\n",irq_nr);
469 + cp0_cause &= ~(1 << intr_bit);
470 + }
471 +#endif
472 + return;
473 + }
474 +
475 + switch (mips_machtype) {
476 + case MACH_ARUBA_AP70:
477 + if ((ip = (cp0_cause & 0x7c00))) {
478 + group = 21 - rc32434_clz(ip);
479 +
480 + addr = intr_group_muscat[group].base_addr;
481 +
482 + pend = READ_PEND_MUSCAT(addr);
483 + pend &= ~READ_MASK_MUSCAT(addr); // only unmasked interrupts
484 + pend = 39 - rc32434_clz(pend);
485 + do_IRQ((group << 5) + pend, regs);
486 + }
487 + break;
488 + case MACH_ARUBA_AP65:
489 + case MACH_ARUBA_AP60:
490 + default:
491 + if (cp0_cause & 0x4000) { // 1 << (8 +6) == irq 6
492 + // Misc Interrupt
493 + group = 0;
494 + addr = intr_group_merlot[group].base_addr;
495 + pend = READ_PEND_MERLOT(addr);
496 + pend &= READ_MASK_MERLOT(addr); // only unmasked interrupts
497 + /* handle one misc interrupt at a time */
498 + while (pend)
499 + {
500 + unsigned long intr_bit;
501 + unsigned int irq_nr;
502 +
503 + intr_bit = (31 - rc32434_clz(pend));
504 + irq_nr = intr_bit + GROUP0_IRQ_BASE;
505 +
506 + do_IRQ(irq_nr, regs);
507 + pend &= ~(1 << intr_bit);
508 + }
509 + } else if (cp0_cause & 0x3c00) { // irq 2-5
510 + while (cp0_cause)
511 + {
512 + unsigned long intr_bit;
513 + unsigned int irq_nr;
514 +
515 + intr_bit = (31 - rc32434_clz(cp0_cause));
516 + irq_nr = intr_bit - GROUP0_IRQ_BASE;
517 +
518 + do_IRQ(irq_nr, regs);
519 + cp0_cause &= ~(1 << intr_bit);
520 + }
521 + }
522 + break;
523 + }
524 +}
This page took 0.076341 seconds and 5 git commands to generate.