[MIPS] Rewrite all the assembler interrupt handlers to C.

Saves like 1,600 lines of code, is way easier to debug, compilers
frequently do a better job than the cut and paste type of handlers many
boards had.  And finally having all the stuff done in a single place
also means alot of bug potencial for the MT ASE is gone.

The only surviving handler in assembler is the DECstation one; I hope
Maciej will rewrite it.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
diff --git a/arch/mips/ddb5xxx/ddb5074/Makefile b/arch/mips/ddb5xxx/ddb5074/Makefile
index 488206b..304c021 100644
--- a/arch/mips/ddb5xxx/ddb5074/Makefile
+++ b/arch/mips/ddb5xxx/ddb5074/Makefile
@@ -3,6 +3,6 @@
 # under Linux.
 #
 
-obj-y			+= setup.o irq.o int-handler.o nile4_pic.o
+obj-y			+= setup.o irq.o nile4_pic.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5074/int-handler.S b/arch/mips/ddb5xxx/ddb5074/int-handler.S
deleted file mode 100644
index a786441..0000000
--- a/arch/mips/ddb5xxx/ddb5074/int-handler.S
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *  arch/mips/ddb5074/int-handler.S -- NEC DDB Vrc-5074 interrupt handler
- *
- *  Based on arch/mips/sgi/kernel/indyIRQ.S
- *
- *  Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
- *
- *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Software Development Center Europe (SDCE), Brussels
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/* A lot of complication here is taken away because:
- *
- * 1) We handle one interrupt and return, sitting in a loop and moving across
- *    all the pending IRQ bits in the cause register is _NOT_ the answer, the
- *    common case is one pending IRQ so optimize in that direction.
- *
- * 2) We need not check against bits in the status register IRQ mask, that
- *    would make this routine slow as hell.
- *
- * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
- *    between like BSD spl() brain-damage.
- *
- * Furthermore, the IRQs on the INDY look basically (barring software IRQs
- * which we don't use at all) like:
- *
- *	MIPS IRQ	Source
- *      --------        ------
- *             0	Software (ignored)
- *             1        Software (ignored)
- *             2        Local IRQ level zero
- *             3        Local IRQ level one
- *             4        8254 Timer zero
- *             5        8254 Timer one
- *             6        Bus Error
- *             7        R4k timer (what we use)
- *
- * We handle the IRQ according to _our_ priority which is:
- *
- * Highest ----     R4k Timer
- *                  Local IRQ zero
- *                  Local IRQ one
- *                  Bus Error
- *                  8254 Timer zero
- * Lowest  ----     8254 Timer one
- *
- * then we just return, if multiple IRQs are pending then we will just take
- * another exception, big deal.
- */
-
-	.text
-	.set	noreorder
-	.set	noat
-	.align	5
-	NESTED(ddbIRQ, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-	.set	at
-	mfc0	s0, CP0_CAUSE		# get irq mask
-
-#if 1
-	mfc0	t2,CP0_STATUS		# get enabled interrupts
-	and	s0,t2			# isolate allowed ones
-#endif
-	/* First we check for r4k counter/timer IRQ. */
-	andi	a0, s0, CAUSEF_IP2	# delay slot, check local level zero
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP3	# delay slot, check local level one
-
-	/* Wheee, local level zero interrupt. */
-	jal	ddb_local0_irqdispatch
-	 move	a0, sp			# delay slot
-
-	j	ret_from_irq
-	 nop				# delay slot
-
-1:
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP6	# delay slot, check bus error
-
-	/* Wheee, local level one interrupt. */
-	move	a0, sp
-	jal	ddb_local1_irqdispatch
-	 nop
-
-	j	ret_from_irq
-	 nop
-
-1:
-	beq	a0, zero, 1f
-	 nop
-
-	/* Wheee, an asynchronous bus error... */
-	move	a0, sp
-	jal	ddb_buserror_irq
-	 nop
-
-	j	ret_from_irq
-	 nop
-
-1:
-	/* Here by mistake?  This is possible, what can happen
-	 * is that by the time we take the exception the IRQ
-	 * pin goes low, so just leave if this is the case.
-	 */
-	andi	a0, s0, (CAUSEF_IP4 | CAUSEF_IP5)
-	beq	a0, zero, 1f
-
-	/* Must be one of the 8254 timers... */
-	move	a0, sp
-	jal	ddb_8254timer_irq
-	 nop
-1:
-	j	ret_from_irq
-	 nop
-	END(ddbIRQ)
diff --git a/arch/mips/ddb5xxx/ddb5074/irq.c b/arch/mips/ddb5xxx/ddb5074/irq.c
index 45088a1..60c087b 100644
--- a/arch/mips/ddb5xxx/ddb5074/irq.c
+++ b/arch/mips/ddb5xxx/ddb5074/irq.c
@@ -21,8 +21,6 @@
 #include <asm/ddb5xxx/ddb5074.h>
 
 
-extern asmlinkage void ddbIRQ(void);
-
 static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
 
 #define M1543_PNP_CONFIG	0x03f0	/* PnP Config Port */
@@ -90,7 +88,7 @@
 
 }
 
-void ddb_local0_irqdispatch(struct pt_regs *regs)
+static void ddb_local0_irqdispatch(struct pt_regs *regs)
 {
 	u32 mask;
 	int nile4_irq;
@@ -118,29 +116,41 @@
 		}
 }
 
-void ddb_local1_irqdispatch(void)
+static void ddb_local1_irqdispatch(void)
 {
 	printk("ddb_local1_irqdispatch called\n");
 }
 
-void ddb_buserror_irq(void)
+static void ddb_buserror_irq(void)
 {
 	printk("ddb_buserror_irq called\n");
 }
 
-void ddb_8254timer_irq(void)
+static void ddb_8254timer_irq(void)
 {
 	printk("ddb_8254timer_irq called\n");
 }
 
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status();
+
+	if (pending & CAUSEF_IP2)
+		ddb_local0_irqdispatch(regs);
+	else if (pending & CAUSEF_IP3)
+		ddb_local1_irqdispatch();
+	else if (pending & CAUSEF_IP6)
+		ddb_buserror_irq();
+	else if (pending & (CAUSEF_IP4 | CAUSEF_IP5))
+		ddb_8254timer_irq();
+}
+
 void __init arch_init_irq(void)
 {
 	/* setup cascade interrupts */
 	setup_irq(NILE4_IRQ_BASE  + NILE4_INT_INTE, &irq_cascade);
 	setup_irq(CPU_IRQ_BASE + CPU_NILE4_CASCADE, &irq_cascade);
 
-	set_except_vector(0, ddbIRQ);
-
 	nile4_irq_setup(NILE4_IRQ_BASE);
 	m1543_irq_setup();
 	init_i8259_irqs();
diff --git a/arch/mips/ddb5xxx/ddb5476/Makefile b/arch/mips/ddb5xxx/ddb5476/Makefile
index 61eec36..ab0312c 100644
--- a/arch/mips/ddb5xxx/ddb5476/Makefile
+++ b/arch/mips/ddb5xxx/ddb5476/Makefile
@@ -3,7 +3,7 @@
 # under Linux.
 #
 
-obj-y			+= setup.o irq.o int-handler.o nile4_pic.o vrc5476_irq.o
+obj-y			+= setup.o irq.o nile4_pic.o vrc5476_irq.o
 obj-$(CONFIG_KGDB)	+= dbg_io.o
 
 EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/ddb5xxx/ddb5476/int-handler.S b/arch/mips/ddb5xxx/ddb5476/int-handler.S
deleted file mode 100644
index 0c2bdae..0000000
--- a/arch/mips/ddb5xxx/ddb5476/int-handler.S
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ddb5476
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-#include <asm/ddb5xxx/ddb5476.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
-	.align	5
-	NESTED(ddb5476_handle_int, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-	.set	at
-	.set	noreorder
-	mfc0	t0, CP0_CAUSE
-	mfc0	t2, CP0_STATUS
-
-	and	t0, t2
-
-        andi    t1, t0, STATUSF_IP7     /* cpu timer */
-        bnez    t1, ll_cpu_ip7
-        andi    t1, t0, STATUSF_IP2	/* vrc5476 & i8259 */
-        bnez    t1, ll_cpu_ip2
-        andi    t1, t0, STATUSF_IP3
-        bnez    t1, ll_cpu_ip3
-        andi    t1, t0, STATUSF_IP4
-        bnez    t1, ll_cpu_ip4
-        andi    t1, t0, STATUSF_IP5
-        bnez    t1, ll_cpu_ip5
-        andi    t1, t0, STATUSF_IP6
-        bnez    t1, ll_cpu_ip6
-        andi    t1, t0, STATUSF_IP0     /* software int 0 */
-        bnez    t1, ll_cpu_ip0
-        andi    t1, t0, STATUSF_IP1     /* software int 1 */
-        bnez    t1, ll_cpu_ip1
-        nop
-
-	.set	reorder
-
-	/* wrong alarm or masked ... */
-	// jal	spurious_interrupt
-	// j	ret_from_irq
-	move 	a0, sp
-	jal	vrc5476_irq_dispatch
-	j	ret_from_irq
-	nop
-
-	.align	5
-
-ll_cpu_ip0:
-	li	a0, CPU_IRQ_BASE + 0
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip1:
-	li	a0, CPU_IRQ_BASE + 1
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip2:		/* jump to second-level dispatching */
-	move	a0, sp
-	jal	vrc5476_irq_dispatch
-	j	ret_from_irq
-
-ll_cpu_ip3:
-	li	a0, CPU_IRQ_BASE + 3
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip4:
-	li	a0, CPU_IRQ_BASE + 4
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip5:
-	li	a0, CPU_IRQ_BASE + 5
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip6:
-	li	a0, CPU_IRQ_BASE + 6
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip7:
-	li	a0, CPU_IRQ_BASE + 7
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-	END(ddb5476_handle_int)
diff --git a/arch/mips/ddb5xxx/ddb5476/irq.c b/arch/mips/ddb5xxx/ddb5476/irq.c
index 5388b58..7583a1f 100644
--- a/arch/mips/ddb5xxx/ddb5476/irq.c
+++ b/arch/mips/ddb5xxx/ddb5476/irq.c
@@ -110,11 +110,36 @@
 static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
 static struct irqaction irq_error = { no_action, 0, CPU_MASK_NONE, "error", NULL, NULL };
 
-extern asmlinkage void ddb5476_handle_int(void);
 extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
 extern void mips_cpu_irq_init(u32 irq_base);
 extern void vrc5476_irq_init(u32 irq_base);
 
+extern void vrc5476_irq_dispatch(struct pt_regs *regs);
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status();
+
+	if (pending & STATUSF_IP7)
+		do_IRQ(CPU_IRQ_BASE + 7, regs);
+	else if (pending & STATUSF_IP2)
+		vrc5476_irq_dispatch(regs);
+	else if (pending & STATUSF_IP3)
+		do_IRQ(CPU_IRQ_BASE + 3, regs);
+	else if (pending & STATUSF_IP4)
+		do_IRQ(CPU_IRQ_BASE + 4, regs);
+	else if (pending & STATUSF_IP5)
+		do_IRQ(CPU_IRQ_BASE + 5, regs);
+	else if (pending & STATUSF_IP6)
+		do_IRQ(CPU_IRQ_BASE + 6, regs);
+	else if (pending & STATUSF_IP0)
+		do_IRQ(CPU_IRQ_BASE, regs);
+	else if (pending & STATUSF_IP1)
+		do_IRQ(CPU_IRQ_BASE + 1, regs);
+
+	vrc5476_irq_dispatch(regs);
+}
+
 void __init arch_init_irq(void)
 {
 	/* hardware initialization */
@@ -137,7 +162,4 @@
 	setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_LBRT, &irq_error);
 	setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCIS, &irq_error);
 	setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCI, &irq_error);
-
-	/* setup the grandpa intr vector */
-	set_except_vector(0, ddb5476_handle_int);
 }
diff --git a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
index 581eaba..a3c5e7b 100644
--- a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
+++ b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c
@@ -77,7 +77,7 @@
 }
 
 
-asmlinkage void
+void
 vrc5476_irq_dispatch(struct pt_regs *regs)
 {
 	u32 mask;
diff --git a/arch/mips/ddb5xxx/ddb5477/Makefile b/arch/mips/ddb5xxx/ddb5477/Makefile
index b79b43c..ea68815 100644
--- a/arch/mips/ddb5xxx/ddb5477/Makefile
+++ b/arch/mips/ddb5xxx/ddb5477/Makefile
@@ -2,7 +2,7 @@
 # Makefile for NEC DDB-Vrc5477 board
 #
 
-obj-y	 		+= int-handler.o irq.o irq_5477.o setup.o lcd44780.o
+obj-y	 		+= irq.o irq_5477.o setup.o lcd44780.o
 
 obj-$(CONFIG_RUNTIME_DEBUG) 	+= debug.o
 obj-$(CONFIG_KGDB)		+= kgdb_io.o
diff --git a/arch/mips/ddb5xxx/ddb5477/int-handler.S b/arch/mips/ddb5xxx/ddb5477/int-handler.S
deleted file mode 100644
index 9884874..0000000
--- a/arch/mips/ddb5xxx/ddb5477/int-handler.S
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2001 MontaVista Software Inc.
- * Author: jsun@mvista.com or jsun@junsun.net
- *
- * First-level interrupt dispatcher for ddb5477
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include <asm/asm.h>
-#include <asm/mipsregs.h>
-#include <asm/addrspace.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-#include <asm/ddb5xxx/ddb5477.h>
-
-/*
- * first level interrupt dispatcher for ocelot board -
- * We check for the timer first, then check PCI ints A and D.
- * Then check for serial IRQ and fall through.
- */
-	.align	5
-	NESTED(ddb5477_handle_int, PT_SIZE, sp)
-	SAVE_ALL
-	CLI
-	.set	at
-	.set	noreorder
-	mfc0	t0, CP0_CAUSE
-	mfc0	t2, CP0_STATUS
-
-	and	t0, t2
-
-	andi	t1, t0, STATUSF_IP7	/* cpu timer */
-	bnez	t1, ll_cputimer_irq
-	andi	t1, t0, (STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6 )
-	bnez	t1, ll_vrc5477_irq
-	andi	t1, t0, STATUSF_IP0	/* software int 0 */
-	bnez	t1, ll_cpu_ip0
-	andi	t1, t0, STATUSF_IP1	/* software int 1 */
-	bnez	t1, ll_cpu_ip1
-	nop
-	.set	reorder
-
-	/* wrong alarm or masked ... */
-	jal	spurious_interrupt
-	j	ret_from_irq
-	END(ddb5477_handle_int)
-
-	.align	5
-
-ll_vrc5477_irq:
-	move	a0, sp
-	jal	vrc5477_irq_dispatch
-	j	ret_from_irq
-
-ll_cputimer_irq:
-	li	a0, CPU_IRQ_BASE + 7
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-
-ll_cpu_ip0:
-	li	a0, CPU_IRQ_BASE + 0
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
-
-ll_cpu_ip1:
-	li	a0, CPU_IRQ_BASE + 1
-	move	a1, sp
-	jal	do_IRQ
-	j	ret_from_irq
diff --git a/arch/mips/ddb5xxx/ddb5477/irq.c b/arch/mips/ddb5xxx/ddb5477/irq.c
index 9ffe1a9..de433cf 100644
--- a/arch/mips/ddb5xxx/ddb5477/irq.c
+++ b/arch/mips/ddb5xxx/ddb5477/irq.c
@@ -75,7 +75,6 @@
 
 extern void vrc5477_irq_init(u32 base);
 extern void mips_cpu_irq_init(u32 base);
-extern asmlinkage void ddb5477_handle_int(void);
 extern int setup_irq(unsigned int irq, struct irqaction *irqaction);
 static struct irqaction irq_cascade = { no_action, 0, CPU_MASK_NONE, "cascade", NULL, NULL };
 
@@ -135,9 +134,6 @@
 	/* setup cascade interrupts */
 	setup_irq(VRC5477_IRQ_BASE + VRC5477_I8259_CASCADE, &irq_cascade);
 	setup_irq(CPU_IRQ_BASE + CPU_VRC5477_CASCADE, &irq_cascade);
-
-	/* hook up the first-level interrupt handler */
-	set_except_vector(0, ddb5477_handle_int);
 }
 
 u8 i8259_interrupt_ack(void)
@@ -159,7 +155,7 @@
  * the first level int-handler will jump here if it is a vrc5477 irq
  */
 #define	NUM_5477_IRQS	32
-asmlinkage void
+static void
 vrc5477_irq_dispatch(struct pt_regs *regs)
 {
 	u32 intStatus;
@@ -197,3 +193,21 @@
 		}
 	}
 }
+
+#define VR5477INTS (STATUSF_IP2|STATUSF_IP3|STATUSF_IP4|STATUSF_IP5|STATUSF_IP6)
+
+asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_cause() & read_c0_status();
+
+	if (pending & STATUSF_IP7)
+		do_IRQ(CPU_IRQ_BASE + 7, regs);
+	else if (pending & VR5477INTS)
+		vrc5477_irq_dispatch(regs);
+	else if (pending & STATUSF_IP0)
+		do_IRQ(CPU_IRQ_BASE, regs);
+	else if (pending & STATUSF_IP1)
+		do_IRQ(CPU_IRQ_BASE + 1, regs);
+	else
+		spurious_interrupt(regs);
+}