More AP / SP bits for the 34K, the Malta bits and things.  Still wants
a little polishing.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c
index d821b13..58256ea 100644
--- a/arch/mips/mips-boards/generic/init.c
+++ b/arch/mips/mips-boards/generic/init.c
@@ -28,6 +28,8 @@
 #include <asm/gt64120.h>
 #include <asm/io.h>
 #include <asm/system.h>
+#include <asm/cacheflush.h>
+#include <asm/traps.h>
 
 #include <asm/mips-boards/prom.h>
 #include <asm/mips-boards/generic.h>
@@ -224,6 +226,30 @@
 }
 #endif
 
+void __init mips_nmi_setup (void)
+{
+	void *base;
+	extern char except_vec_nmi;
+
+	base = cpu_has_veic ?
+		(void *)(CAC_BASE + 0xa80) :
+		(void *)(CAC_BASE + 0x380);
+	memcpy(base, &except_vec_nmi, 0x80);
+	flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
+}
+
+void __init mips_ejtag_setup (void)
+{
+	void *base;
+	extern char except_vec_ejtag_debug;
+
+	base = cpu_has_veic ?
+		(void *)(CAC_BASE + 0xa00) :
+		(void *)(CAC_BASE + 0x300);
+	memcpy(base, &except_vec_ejtag_debug, 0x80);
+	flush_icache_range((unsigned long)base, (unsigned long)base + 0x80);
+}
+
 void __init prom_init(void)
 {
 	u32 start, map, mask, data;
@@ -353,6 +379,9 @@
 		while(1);   /* We die here... */
 	}
 #endif
+	board_nmi_handler_setup = mips_nmi_setup;
+	board_ejtag_handler_setup = mips_ejtag_setup;
+
 	prom_printf("\nLINUX started...\n");
 	prom_init_cmdline();
 	prom_meminit();
diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c
index 5ae2b43..2c8afd7 100644
--- a/arch/mips/mips-boards/generic/memory.c
+++ b/arch/mips/mips-boards/generic/memory.c
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
+#include <linux/string.h>
 
 #include <asm/bootinfo.h>
 #include <asm/page.h>
@@ -55,18 +56,30 @@
 {
 	char *memsize_str;
 	unsigned int memsize;
+	char cmdline[CL_SIZE], *ptr;
 
-	memsize_str = prom_getenv("memsize");
-	if (!memsize_str) {
-		prom_printf("memsize not set in boot prom, set to default (32Mb)\n");
-		memsize = 0x02000000;
-	} else {
-#ifdef DEBUG
-		prom_printf("prom_memsize = %s\n", memsize_str);
-#endif
-		memsize = simple_strtol(memsize_str, NULL, 0);
+	/* Check the command line first for a memsize directive */
+	strcpy(cmdline, arcs_cmdline);
+	ptr = strstr(cmdline, "memsize=");
+	if (ptr && (ptr != cmdline) && (*(ptr - 1) != ' '))
+		ptr = strstr(ptr, " memsize=");
+
+	if (ptr) {
+		memsize = memparse(ptr + 8, &ptr);
 	}
-
+	else {
+		/* otherwise look in the environment */
+		memsize_str = prom_getenv("memsize");
+		if (!memsize_str) {
+			prom_printf("memsize not set in boot prom, set to default (32Mb)\n");
+			memsize = 0x02000000;
+		} else {
+#ifdef DEBUG
+			prom_printf("prom_memsize = %s\n", memsize_str);
+#endif
+			memsize = simple_strtol(memsize_str, NULL, 0);
+		}
+	}
 	memset(mdesc, 0, sizeof(mdesc));
 
 	mdesc[0].type = yamon_dontuse;
diff --git a/arch/mips/mips-boards/generic/mipsIRQ.S b/arch/mips/mips-boards/generic/mipsIRQ.S
index 131f49b..a397ecb 100644
--- a/arch/mips/mips-boards/generic/mipsIRQ.S
+++ b/arch/mips/mips-boards/generic/mipsIRQ.S
@@ -29,6 +29,20 @@
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
 
+#ifdef CONFIG_MIPS_ATLAS
+#include <asm/mips-boards/atlasint.h>
+#define CASCADE_IRQ		MIPSCPU_INT_ATLAS
+#define CASCADE_DISPATCH	atlas_hw0_irqdispatch
+#endif
+#ifdef CONFIG_MIPS_MALTA
+#include <asm/mips-boards/maltaint.h>
+#define CASCADE_IRQ		MIPSCPU_INT_I8259A
+#define CASCADE_DISPATCH	malta_hw0_irqdispatch
+#endif
+#ifdef CONFIG_MIPS_SEAD
+#include <asm/mips-boards/seadint.h>
+#endif
+
 /* A lot of complication here is taken away because:
  *
  * 1) We handle one interrupt and return, sitting in a loop and moving across
@@ -80,74 +94,62 @@
 
 	mfc0	s0, CP0_CAUSE		# get irq bits
 	mfc0	s1, CP0_STATUS		# get irq mask
+	andi	s0, ST0_IM		# CAUSE.CE may be non-zero!
 	and	s0, s1
 
-	/* First we check for r4k counter/timer IRQ. */
-	andi	a0, s0, CAUSEF_IP7
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP2	# delay slot, check hw0 interrupt
-
-	/* Wheee, a timer interrupt. */
-	move	a0, sp
-	jal	mips_timer_interrupt
-	 nop
-
-	j	ret_from_irq
-	 nop
-
-1:
-#if defined(CONFIG_MIPS_SEAD)
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP3	# delay slot, check hw1 interrupt
+#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64)
+ 	.set	mips32
+	clz	a0, s0
+	.set	mips0
+	negu	a0
+	addu	a0, 31-CAUSEB_IP
+	bltz	a0, spurious
 #else
-	beq	a0, zero, 1f		# delay slot, check hw3 interrupt
- 	 andi	a0, s0, CAUSEF_IP5
+	beqz	s0, spurious
+	 li	a0, 7
+
+	and	t0, s0, 0xf000
+	sltiu	t0, t0, 1
+	sll	t0, 2
+	subu	a0, t0
+	sll	s0, t0
+
+	and	t0, s0, 0xc000
+	sltiu	t0, t0, 1
+	sll	t0, 1
+	subu	a0, t0
+	sll	s0, t0
+
+	and	t0, s0, 0x8000
+	sltiu	t0, t0, 1
+	# sll	t0, 0
+	subu	a0, t0
+	# sll	s0, t0
 #endif
 
-	/* Wheee, combined hardware level zero interrupt. */
-#if defined(CONFIG_MIPS_ATLAS)
-	jal	atlas_hw0_irqdispatch
-#elif defined(CONFIG_MIPS_MALTA)
-	jal	malta_hw0_irqdispatch
-#elif defined(CONFIG_MIPS_SEAD)
-	jal	sead_hw0_irqdispatch
+#ifdef CASCADE_IRQ
+	 li	a1, CASCADE_IRQ
+	bne	a0, a1, 1f
+	 addu	a0, MIPSCPU_INT_BASE
+
+	jal	CASCADE_DISPATCH
+	 move	 a0, sp
+
+	j	ret_from_irq
+	 nop
+1:
 #else
-#error "MIPS board not supported\n"
+	 addu	a0, MIPSCPU_INT_BASE
 #endif
-	 move	a0, sp			# delay slot
 
-	j	ret_from_irq
-	 nop				# delay slot
+	jal	do_IRQ
+	 move	a1, sp
 
-1:
-#if defined(CONFIG_MIPS_SEAD)
-	beq	a0, zero, 1f
-	 andi	a0, s0, CAUSEF_IP5	# delay slot, check hw3 interrupt
-	jal	sead_hw1_irqdispatch
-	 move	a0, sp			# delay slot
-	j	ret_from_irq
-	 nop				# delay slot
-1:
-#endif
-#if defined(CONFIG_MIPS_MALTA)
-	beq	a0, zero, 1f            # check hw3 (coreHI) interrupt
-	 nop
-	jal	corehi_irqdispatch
-	 move	a0, sp
 	j	ret_from_irq
 	 nop
-1:
-#endif
-	/*
-	 * 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.
-	 */
-	move	a1,s0
-	PRINT("Got interrupt: c0_cause = %08x\n")
-	mfc0	a1, CP0_EPC
-	PRINT("c0_epc = %08x\n")
 
-	j	ret_from_irq
+
+spurious:
+	j	spurious_interrupt
 	 nop
 	END(mipsIRQ)
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index 1631544..3a6f142 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -31,22 +31,21 @@
 
 #include <asm/mipsregs.h>
 #include <asm/ptrace.h>
+#include <asm/hardirq.h>
+#include <asm/irq.h>
 #include <asm/div64.h>
 #include <asm/cpu.h>
 #include <asm/time.h>
 #include <asm/mc146818-time.h>
+#include <asm/msc01_ic.h>
 
 #include <asm/mips-boards/generic.h>
 #include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/maltaint.h>
+#include <asm/mc146818-time.h>
 
 unsigned long cpu_khz;
 
-#if defined(CONFIG_MIPS_SEAD)
-#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ5)
-#else
-#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
-#endif
-
 #if defined(CONFIG_MIPS_ATLAS)
 static char display_string[] = "        LINUX ON ATLAS       ";
 #endif
@@ -59,20 +58,27 @@
 static unsigned int display_count = 0;
 #define MAX_DISPLAY_COUNT (sizeof(display_string) - 8)
 
-#define MIPS_CPU_TIMER_IRQ (NR_IRQS-1)
-
 static unsigned int timer_tick_count=0;
+static int mips_cpu_timer_irq;
 
-void mips_timer_interrupt(struct pt_regs *regs)
+static void mips_timer_dispatch (struct pt_regs *regs)
 {
+	do_IRQ (mips_cpu_timer_irq, regs);
+}
+
+irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	irqreturn_t r;
+
+	r = timer_interrupt(irq, dev_id, regs);
+
 	if ((timer_tick_count++ % HZ) == 0) {
 		mips_display_message(&display_string[display_count++]);
 		if (display_count == MAX_DISPLAY_COUNT)
-		        display_count = 0;
-
+			display_count = 0;
 	}
 
-	ll_timer_interrupt(MIPS_CPU_TIMER_IRQ, regs);
+	return r;
 }
 
 /*
@@ -140,10 +146,8 @@
 
 	local_irq_save(flags);
 
-#if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_MALTA)
         /* Set Data mode - binary. */
         CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
-#endif
 
 	est_freq = estimate_cpu_frequency ();
 
@@ -157,11 +161,22 @@
 
 void __init mips_timer_setup(struct irqaction *irq)
 {
+	if (cpu_has_veic) {
+		set_vi_handler (MSC01E_INT_CPUCTR, mips_timer_dispatch);
+		mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
+	}
+	else {
+		if (cpu_has_vint)
+			set_vi_handler (MIPSCPU_INT_CPUCTR, mips_timer_dispatch);
+		mips_cpu_timer_irq = MIPSCPU_INT_BASE + MIPSCPU_INT_CPUCTR;
+	}
+
+
 	/* we are using the cpu counter for timer interrupts */
-	irq->handler = no_action;     /* we use our own handler */
-	setup_irq(MIPS_CPU_TIMER_IRQ, irq);
+	irq->handler = mips_timer_interrupt;	/* we use our own handler */
+	setup_irq(mips_cpu_timer_irq, irq);
+
 
         /* to generate the first timer interrupt */
 	write_c0_compare (read_c0_count() + mips_hpt_frequency/HZ);
-	set_c0_status(ALLINTS);
 }