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
5 +/**************************************************************************
7 + * BRIEF MODULE DESCRIPTION
8 + * Intterrupt dispatcher code for IDT boards
10 + * Copyright 2004 IDT Inc. (rischelp@idt.com)
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.
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.
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.
33 + **************************************************************************
40 + **************************************************************************
45 +#include <asm/mipsregs.h>
46 +#include <asm/regdef.h>
47 +#include <asm/stackframe.h>
53 + NESTED(idtIRQ, PT_SIZE, sp)
61 + /* Get the pending interrupts */
65 + /* Isolate the allowed ones by anding the irq mask */
67 + move a1, sp /* need a nop here, hence we anticipate */
71 + /* check for r4k counter/timer IRQ. */
73 + andi t1, t0, CAUSEF_IP7
77 + jal aruba_timer_interrupt
84 + jal aruba_irqdispatch
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
96 +/**************************************************************************
98 + * BRIEF MODULE DESCRIPTION
99 + * Interrupt routines for IDT EB434 boards / Atheros boards
100 + * Modified by Aruba Networks
102 + * Copyright 2004 IDT Inc. (rischelp@idt.com)
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.
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.
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.
125 + **************************************************************************
126 + * May 2004 rkt, neb
132 + **************************************************************************
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>
149 +#include <asm/bitops.h>
150 +#include <asm/bootinfo.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>
157 +#include <asm/irq.h>
161 +/* note: prints function name for you */
162 +#define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
164 +#define DPRINTK(fmt, args...)
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);
174 +extern void __init init_generic_irq(void);
178 + volatile u32 *base_addr;
181 +static const intr_group_t intr_group_merlot[NUM_INTR_GROUPS] = {
182 + {0xffffffff, (u32 *) KSEG1ADDR(IC_GROUP0_PEND + 0)},
185 +#define READ_PEND_MERLOT(base) (*((volatile unsigned long *)(0xbc003010)))
186 +#define READ_MASK_MERLOT(base) (*((volatile unsigned long *)(0xbc003010 + 4)))
187 +#define WRITE_MASK_MERLOT(base, val) ((*((volatile unsigned long *)((0xbc003010) + 4))) = (val))
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)}
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))
201 +static inline int irq_to_group(unsigned int irq_nr)
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:
213 +static inline int group_to_ip(unsigned int group)
215 + switch (mips_machtype) {
216 + case MACH_ARUBA_AP70:
218 + case MACH_ARUBA_AP65:
219 + case MACH_ARUBA_AP60:
225 +static inline void enable_local_irq(unsigned int ip)
227 + int ipnum = 0x100 << ip;
228 + clear_c0_cause(ipnum);
229 + set_c0_status(ipnum);
232 +static inline void disable_local_irq(unsigned int ip)
234 + int ipnum = 0x100 << ip;
235 + clear_c0_status(ipnum);
238 +static inline void ack_local_irq(unsigned int ip)
240 + int ipnum = 0x100 << ip;
241 + clear_c0_cause(ipnum);
244 +static void aruba_enable_irq(unsigned int irq_nr)
246 + unsigned long flags;
247 + int ip = irq_nr - GROUP0_IRQ_BASE;
248 + unsigned int group, intr_bit;
249 + volatile unsigned int *addr;
252 + local_irq_save(flags);
255 + enable_local_irq(irq_nr);
258 + switch (mips_machtype) {
259 + case MACH_ARUBA_AP70:
262 + case MACH_ARUBA_AP65:
263 + case MACH_ARUBA_AP60:
269 + // calc interrupt bit within group
270 + ip -= (group << 5);
271 + intr_bit = 1 << ip;
273 + // first enable the IP mapped to this IRQ
274 + enable_local_irq(group_to_ip(group));
276 + switch (mips_machtype) {
277 + case MACH_ARUBA_AP70:
278 + addr = intr_group_muscat[group].base_addr;
279 + WRITE_MASK_MUSCAT(addr, READ_MASK_MUSCAT(addr) & ~intr_bit);
281 + case MACH_ARUBA_AP65:
282 + case MACH_ARUBA_AP60:
284 + addr = intr_group_merlot[group].base_addr;
285 + WRITE_MASK_MERLOT(addr, READ_MASK_MERLOT(addr) | intr_bit);
290 + local_irq_restore(flags);
294 +static void aruba_disable_irq(unsigned int irq_nr)
296 + unsigned long flags;
297 + int ip = irq_nr - GROUP0_IRQ_BASE;
298 + unsigned int group, intr_bit, mask;
299 + volatile unsigned int *addr;
301 + local_irq_save(flags);
304 + disable_local_irq(irq_nr);
307 + switch (mips_machtype) {
308 + case MACH_ARUBA_AP70:
311 + case MACH_ARUBA_AP65:
312 + case MACH_ARUBA_AP60:
318 + // calc interrupt bit within group
320 + intr_bit = 1 << ip;
322 + switch (mips_machtype) {
323 + case MACH_ARUBA_AP70:
324 + addr = intr_group_muscat[group].base_addr;
325 + // mask intr within group
326 + mask = READ_MASK_MUSCAT(addr);
328 + WRITE_MASK_MUSCAT(addr, mask);
331 + if there are no more interrupts enabled in this
332 + group, disable corresponding IP
334 + if (mask == intr_group_muscat[group].mask)
335 + disable_local_irq(group_to_ip(group));
337 + case MACH_ARUBA_AP65:
338 + case MACH_ARUBA_AP60:
340 + addr = intr_group_merlot[group].base_addr;
341 + // mask intr within group
342 + mask = READ_MASK_MERLOT(addr);
344 + WRITE_MASK_MERLOT(addr, mask);
345 + if (READ_MASK_MERLOT(addr))
346 + disable_local_irq(group_to_ip(group));
351 + local_irq_restore(flags);
355 +static unsigned int startup_irq(unsigned int irq_nr)
357 + aruba_enable_irq(irq_nr);
361 +static void shutdown_irq(unsigned int irq_nr)
363 + aruba_disable_irq(irq_nr);
367 +static void mask_and_ack_irq(unsigned int irq_nr)
369 + aruba_disable_irq(irq_nr);
370 + ack_local_irq(group_to_ip(irq_to_group(irq_nr)));
373 +static void end_irq(unsigned int irq_nr)
376 + unsigned long flags;
377 + int ip = irq_nr - GROUP0_IRQ_BASE;
378 + unsigned int intr_bit, group;
379 + volatile unsigned int *addr;
382 + local_irq_save(flags);
383 + if (irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS)) {
384 + printk("warning: end_irq %d did not enable (%x)\n",
385 + irq_nr, irq_desc[irq_nr].status);
387 + enable_local_irq(irq_nr);
390 + switch (mips_machtype) {
391 + case MACH_ARUBA_AP70:
392 + if (irq_nr == GROUP4_IRQ_BASE + 9) idt_gpio->gpioistat &= 0xfffffdff;
393 + else if (irq_nr == GROUP4_IRQ_BASE + 10) idt_gpio->gpioistat &= 0xfffffbff;
394 + else if (irq_nr == GROUP4_IRQ_BASE + 11) idt_gpio->gpioistat &= 0xfffff7ff;
395 + else if (irq_nr == GROUP4_IRQ_BASE + 12) idt_gpio->gpioistat &= 0xffffefff;
399 + // calc interrupt bit within group
400 + ip -= (group << 5);
401 + intr_bit = 1 << ip;
403 + // first enable the IP mapped to this IRQ
404 + enable_local_irq(group_to_ip(group));
406 + addr = intr_group_muscat[group].base_addr;
407 + // unmask intr within group
408 + WRITE_MASK_MUSCAT(addr, READ_MASK_MUSCAT(addr) & ~intr_bit);
411 + case MACH_ARUBA_AP65:
412 + case MACH_ARUBA_AP60:
415 + // calc interrupt bit within group
416 + intr_bit = 1 << ip;
418 + // first enable the IP mapped to this IRQ
419 + enable_local_irq(group_to_ip(group));
421 + addr = intr_group_merlot[group].base_addr;
422 + // unmask intr within group
423 + WRITE_MASK_MERLOT(addr, READ_MASK_MERLOT(addr) | intr_bit);
427 + local_irq_restore(flags);
430 +static struct hw_interrupt_type aruba_irq_type = {
431 + .typename = "IDT434",
432 + .startup = startup_irq,
433 + .shutdown = shutdown_irq,
434 + .enable = aruba_enable_irq,
435 + .disable = aruba_disable_irq,
436 + .ack = mask_and_ack_irq,
440 +void __init arch_init_irq(void)
443 + printk("Initializing IRQ's: %d out of %d\n", RC32434_NR_IRQS, NR_IRQS);
444 + memset(irq_desc, 0, sizeof(irq_desc));
445 + set_except_vector(0, idtIRQ);
448 + set_c0_status(0xFF00);
450 + for (i = 0; i < RC32434_NR_IRQS; i++) {
451 + irq_desc[i].status = IRQ_DISABLED;
452 + irq_desc[i].action = NULL;
453 + irq_desc[i].depth = 1;
454 + irq_desc[i].handler = &aruba_irq_type;
455 + spin_lock_init(&irq_desc[i].lock);
458 + switch (mips_machtype) {
459 + case MACH_ARUBA_AP70:
461 + case MACH_ARUBA_AP65:
462 + case MACH_ARUBA_AP60:
464 + WRITE_MASK_MERLOT(intr_group_merlot[0].base_addr, 0);
465 + *((volatile unsigned long *)0xbc003014) = 0x10;
470 +/* Main Interrupt dispatcher */
471 +void aruba_irqdispatch(unsigned long cp0_cause, struct pt_regs *regs)
473 + unsigned int pend, group, ip;
474 + volatile unsigned int *addr;
476 + if(cp0_cause == 0) {
477 + printk("INTERRUPT(S) FIRED WHILE MASKED\n");
479 + // debuging use -- figure out which interrupt(s) fired
480 + cp0_cause = read_c0_cause() & CAUSEF_IP;
481 + while (cp0_cause) {
482 + unsigned long intr_bit;
483 + unsigned int irq_nr;
484 + intr_bit = (31 - rc32434_clz(cp0_cause));
485 + irq_nr = intr_bit - GROUP0_IRQ_BASE;
486 + printk(" ---> MASKED IRQ %d\n",irq_nr);
487 + cp0_cause &= ~(1 << intr_bit);
494 + switch (mips_machtype) {
495 + case MACH_ARUBA_AP70:
496 + if ((ip = (cp0_cause & 0x7c00))) {
497 + group = 21 - rc32434_clz(ip);
499 + addr = intr_group_muscat[group].base_addr;
501 + pend = READ_PEND_MUSCAT(addr);
502 + pend &= ~READ_MASK_MUSCAT(addr); // only unmasked interrupts
503 + pend = 39 - rc32434_clz(pend);
504 + do_IRQ((group << 5) + pend, regs);
507 + case MACH_ARUBA_AP65:
508 + case MACH_ARUBA_AP60:
510 + if (cp0_cause & 0x4000) { // 1 << (8 +6) == irq 6
513 + addr = intr_group_merlot[group].base_addr;
514 + pend = READ_PEND_MERLOT(addr);
515 + pend &= READ_MASK_MERLOT(addr); // only unmasked interrupts
516 + /* handle one misc interrupt at a time */
518 + unsigned long intr_bit;
519 + unsigned int irq_nr;
521 + intr_bit = (31 - rc32434_clz(pend));
522 + irq_nr = intr_bit + GROUP0_IRQ_BASE;
524 + do_IRQ(irq_nr, regs);
525 + pend &= ~(1 << intr_bit);
528 + if (cp0_cause & 0x3c00) { // irq 2-5
529 + while (cp0_cause) {
530 + unsigned long intr_bit;
531 + unsigned int irq_nr;
533 + intr_bit = (31 - rc32434_clz(cp0_cause));
534 + irq_nr = intr_bit - GROUP0_IRQ_BASE;
536 + do_IRQ(irq_nr, regs);
537 + cp0_cause &= ~(1 << intr_bit);