summaryrefslogtreecommitdiffstats
path: root/arch/mips/mips-boards
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/mips-boards')
-rw-r--r--arch/mips/mips-boards/atlas/Makefile20
-rw-r--r--arch/mips/mips-boards/atlas/atlas_gdb.c97
-rw-r--r--arch/mips/mips-boards/atlas/atlas_int.c142
-rw-r--r--arch/mips/mips-boards/atlas/atlas_setup.c95
-rw-r--r--arch/mips/mips-boards/generic/Makefile26
-rw-r--r--arch/mips/mips-boards/generic/cmdline.c59
-rw-r--r--arch/mips/mips-boards/generic/display.c39
-rw-r--r--arch/mips/mips-boards/generic/gdb_hook.c133
-rw-r--r--arch/mips/mips-boards/generic/init.c343
-rw-r--r--arch/mips/mips-boards/generic/memory.c173
-rw-r--r--arch/mips/mips-boards/generic/mipsIRQ.S153
-rw-r--r--arch/mips/mips-boards/generic/pci.c163
-rw-r--r--arch/mips/mips-boards/generic/printf.c79
-rw-r--r--arch/mips/mips-boards/generic/reset.c73
-rw-r--r--arch/mips/mips-boards/generic/time.c167
-rw-r--r--arch/mips/mips-boards/malta/Makefile22
-rw-r--r--arch/mips/mips-boards/malta/malta_int.c187
-rw-r--r--arch/mips/mips-boards/malta/malta_setup.c231
-rw-r--r--arch/mips/mips-boards/sead/Makefile26
-rw-r--r--arch/mips/mips-boards/sead/sead_int.c51
-rw-r--r--arch/mips/mips-boards/sead/sead_setup.c84
21 files changed, 2363 insertions, 0 deletions
diff --git a/arch/mips/mips-boards/atlas/Makefile b/arch/mips/mips-boards/atlas/Makefile
new file mode 100644
index 00000000000..d8dab75906b
--- /dev/null
+++ b/arch/mips/mips-boards/atlas/Makefile
@@ -0,0 +1,20 @@
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+#
+# This program is free software; you can distribute it and/or modify it
+# under the terms of the GNU General Public License (Version 2) as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+
+obj-y := atlas_int.o atlas_setup.o
+obj-$(CONFIG_KGDB) += atlas_gdb.o
diff --git a/arch/mips/mips-boards/atlas/atlas_gdb.c b/arch/mips/mips-boards/atlas/atlas_gdb.c
new file mode 100644
index 00000000000..fb65280f178
--- /dev/null
+++ b/arch/mips/mips-boards/atlas/atlas_gdb.c
@@ -0,0 +1,97 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * This is the interface to the remote debugger stub.
+ */
+#include <asm/io.h>
+#include <asm/mips-boards/atlas.h>
+#include <asm/mips-boards/saa9730_uart.h>
+
+#define INB(a) inb((unsigned long)a)
+#define OUTB(x,a) outb(x,(unsigned long)a)
+
+/*
+ * This is the interface to the remote debugger stub
+ * if the Philips part is used for the debug port,
+ * called from the platform setup code.
+ */
+void *saa9730_base = (void *)ATLAS_SAA9730_REG;
+
+static int saa9730_kgdb_active = 0;
+
+#define SAA9730_BAUDCLOCK(baud) (((ATLAS_SAA9730_BAUDCLOCK/(baud))/16)-1)
+
+int saa9730_kgdb_hook(int speed)
+{
+ int baudclock;
+ t_uart_saa9730_regmap *kgdb_uart = (t_uart_saa9730_regmap *)(saa9730_base + SAA9730_UART_REGS_ADDR);
+
+ /*
+ * Clear all interrupts
+ */
+ (void) INB(&kgdb_uart->Lsr);
+ (void) INB(&kgdb_uart->Msr);
+ (void) INB(&kgdb_uart->Thr_Rbr);
+ (void) INB(&kgdb_uart->Iir_Fcr);
+
+ /*
+ * Now, initialize the UART
+ */
+ /* 8 data bits, one stop bit, no parity */
+ OUTB(SAA9730_LCR_DATA8, &kgdb_uart->Lcr);
+
+ baudclock = SAA9730_BAUDCLOCK(speed);
+
+ OUTB((baudclock >> 16) & 0xff, &kgdb_uart->BaudDivMsb);
+ OUTB( baudclock & 0xff, &kgdb_uart->BaudDivLsb);
+
+ /* Set RTS/DTR active */
+ OUTB(SAA9730_MCR_DTR | SAA9730_MCR_RTS, &kgdb_uart->Mcr);
+ saa9730_kgdb_active = 1;
+
+ return speed;
+}
+
+int saa9730_putDebugChar(char c)
+{
+ t_uart_saa9730_regmap *kgdb_uart = (t_uart_saa9730_regmap *)(saa9730_base + SAA9730_UART_REGS_ADDR);
+
+ if (!saa9730_kgdb_active) { /* need to init device first */
+ return 0;
+ }
+
+ while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_THRE))
+ ;
+ OUTB(c, &kgdb_uart->Thr_Rbr);
+
+ return 1;
+}
+
+char saa9730_getDebugChar(void)
+{
+ t_uart_saa9730_regmap *kgdb_uart = (t_uart_saa9730_regmap *)(saa9730_base + SAA9730_UART_REGS_ADDR);
+ char c;
+
+ if (!saa9730_kgdb_active) { /* need to init device first */
+ return 0;
+ }
+ while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_DR))
+ ;
+
+ c = INB(&kgdb_uart->Thr_Rbr);
+ return(c);
+}
diff --git a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c
new file mode 100644
index 00000000000..8f1d875217a
--- /dev/null
+++ b/arch/mips/mips-boards/atlas/atlas_int.c
@@ -0,0 +1,142 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Routines for generic manipulation of the interrupts found on the MIPS
+ * Atlas board.
+ *
+ */
+#include <linux/compiler.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/mips-boards/atlas.h>
+#include <asm/mips-boards/atlasint.h>
+#include <asm/gdb-stub.h>
+
+
+static struct atlas_ictrl_regs *atlas_hw0_icregs;
+
+extern asmlinkage void mipsIRQ(void);
+
+#if 0
+#define DEBUG_INT(x...) printk(x)
+#else
+#define DEBUG_INT(x...)
+#endif
+
+void disable_atlas_irq(unsigned int irq_nr)
+{
+ atlas_hw0_icregs->intrsten = (1 << (irq_nr-ATLASINT_BASE));
+ iob();
+}
+
+void enable_atlas_irq(unsigned int irq_nr)
+{
+ atlas_hw0_icregs->intseten = (1 << (irq_nr-ATLASINT_BASE));
+ iob();
+}
+
+static unsigned int startup_atlas_irq(unsigned int irq)
+{
+ enable_atlas_irq(irq);
+ return 0; /* never anything pending */
+}
+
+#define shutdown_atlas_irq disable_atlas_irq
+
+#define mask_and_ack_atlas_irq disable_atlas_irq
+
+static void end_atlas_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_atlas_irq(irq);
+}
+
+static struct hw_interrupt_type atlas_irq_type = {
+ "Atlas",
+ startup_atlas_irq,
+ shutdown_atlas_irq,
+ enable_atlas_irq,
+ disable_atlas_irq,
+ mask_and_ack_atlas_irq,
+ end_atlas_irq,
+ NULL
+};
+
+static inline int ls1bit32(unsigned int x)
+{
+ int b = 31, s;
+
+ s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s;
+ s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s;
+ s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s;
+ s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s;
+ s = 1; if (x << 1 == 0) s = 0; b -= s;
+
+ return b;
+}
+
+void atlas_hw0_irqdispatch(struct pt_regs *regs)
+{
+ unsigned long int_status;
+ int irq;
+
+ int_status = atlas_hw0_icregs->intstatus;
+
+ /* if int_status == 0, then the interrupt has already been cleared */
+ if (unlikely(int_status == 0))
+ return;
+
+ irq = ATLASINT_BASE + ls1bit32(int_status);
+
+ DEBUG_INT("atlas_hw0_irqdispatch: irq=%d\n", irq);
+
+ do_IRQ(irq, regs);
+}
+
+void __init arch_init_irq(void)
+{
+ int i;
+
+ atlas_hw0_icregs = (struct atlas_ictrl_regs *)ioremap (ATLAS_ICTRL_REGS_BASE, sizeof(struct atlas_ictrl_regs *));
+
+ /*
+ * Mask out all interrupt by writing "1" to all bit position in
+ * the interrupt reset reg.
+ */
+ atlas_hw0_icregs->intrsten = 0xffffffff;
+
+ /* Now safe to set the exception vector. */
+ set_except_vector(0, mipsIRQ);
+
+ for (i = ATLASINT_BASE; i <= ATLASINT_END; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &atlas_irq_type;
+ spin_lock_init(&irq_desc[i].lock);
+ }
+}
diff --git a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c
new file mode 100644
index 00000000000..0a1dd9bbc02
--- /dev/null
+++ b/arch/mips/mips-boards/atlas/atlas_setup.c
@@ -0,0 +1,95 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/atlas.h>
+#include <asm/mips-boards/atlasint.h>
+#include <asm/time.h>
+#include <asm/traps.h>
+
+extern void mips_reboot_setup(void);
+extern void mips_time_init(void);
+extern void mips_timer_setup(struct irqaction *irq);
+extern unsigned long mips_rtc_get_time(void);
+
+#ifdef CONFIG_KGDB
+extern void kgdb_config(void);
+#endif
+
+static void __init serial_init(void);
+
+const char *get_system_type(void)
+{
+ return "MIPS Atlas";
+}
+
+static int __init atlas_setup(void)
+{
+ ioport_resource.end = 0x7fffffff;
+
+ serial_init ();
+
+#ifdef CONFIG_KGDB
+ kgdb_config();
+#endif
+ mips_reboot_setup();
+
+ board_time_init = mips_time_init;
+ board_timer_setup = mips_timer_setup;
+ rtc_get_time = mips_rtc_get_time;
+
+ return 0;
+}
+
+early_initcall(atlas_setup);
+
+static void __init serial_init(void)
+{
+#ifdef CONFIG_SERIAL_8250
+ struct uart_port s;
+
+ memset(&s, 0, sizeof(s));
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+ s.iobase = ATLAS_UART_REGS_BASE;
+#else
+ s.iobase = ATLAS_UART_REGS_BASE+3;
+#endif
+ s.irq = ATLASINT_UART;
+ s.uartclk = ATLAS_BASE_BAUD * 16;
+ s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
+ s.iotype = SERIAL_IO_PORT;
+ s.regshift = 3;
+
+ if (early_serial_setup(&s) != 0) {
+ printk(KERN_ERR "Serial setup failed!\n");
+ }
+#endif
+}
diff --git a/arch/mips/mips-boards/generic/Makefile b/arch/mips/mips-boards/generic/Makefile
new file mode 100644
index 00000000000..b21bc6887fa
--- /dev/null
+++ b/arch/mips/mips-boards/generic/Makefile
@@ -0,0 +1,26 @@
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+#
+# This program is free software; you can distribute it and/or modify it
+# under the terms of the GNU General Public License (Version 2) as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# Makefile for the MIPS boards generic routines under Linux.
+#
+
+obj-y := mipsIRQ.o reset.o display.o init.o memory.o \
+ printf.o cmdline.o time.o
+obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_KGDB) += gdb_hook.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/mips-boards/generic/cmdline.c b/arch/mips/mips-boards/generic/cmdline.c
new file mode 100644
index 00000000000..1871c30ed2e
--- /dev/null
+++ b/arch/mips/mips-boards/generic/cmdline.c
@@ -0,0 +1,59 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Kernel command line creation using the prom monitor (YAMON) argc/argv.
+ */
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+
+extern int prom_argc;
+extern int *_prom_argv;
+
+/*
+ * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
+ * This macro take care of sign extension.
+ */
+#define prom_argv(index) ((char *)(long)_prom_argv[(index)])
+
+char * __init prom_getcmdline(void)
+{
+ return &(arcs_cmdline[0]);
+}
+
+
+void __init prom_init_cmdline(void)
+{
+ char *cp;
+ int actr;
+
+ actr = 1; /* Always ignore argv[0] */
+
+ cp = &(arcs_cmdline[0]);
+ while(actr < prom_argc) {
+ strcpy(cp, prom_argv(actr));
+ cp += strlen(prom_argv(actr));
+ *cp++ = ' ';
+ actr++;
+ }
+ if (cp != &(arcs_cmdline[0])) {
+ /* get rid of trailing space */
+ --cp;
+ *cp = '\0';
+ }
+}
diff --git a/arch/mips/mips-boards/generic/display.c b/arch/mips/mips-boards/generic/display.c
new file mode 100644
index 00000000000..f653946afc2
--- /dev/null
+++ b/arch/mips/mips-boards/generic/display.c
@@ -0,0 +1,39 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Display routines for display messages in MIPS boards ascii display.
+ */
+
+#include <linux/compiler.h>
+#include <asm/io.h>
+#include <asm/mips-boards/generic.h>
+
+void mips_display_message(const char *str)
+{
+ static volatile unsigned int *display = NULL;
+ int i;
+
+ if (unlikely(display == NULL))
+ display = (volatile unsigned int *)ioremap(ASCII_DISPLAY_POS_BASE, 16*sizeof(int));
+
+ for (i = 0; i <= 14; i=i+2) {
+ if (*str)
+ display[i] = *str++;
+ else
+ display[i] = ' ';
+ }
+}
diff --git a/arch/mips/mips-boards/generic/gdb_hook.c b/arch/mips/mips-boards/generic/gdb_hook.c
new file mode 100644
index 00000000000..91a2ccbe373
--- /dev/null
+++ b/arch/mips/mips-boards/generic/gdb_hook.c
@@ -0,0 +1,133 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * This is the interface to the remote debugger stub.
+ */
+#include <linux/types.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/serial_reg.h>
+
+#include <asm/serial.h>
+#include <asm/io.h>
+
+static struct serial_state rs_table[RS_TABLE_SIZE] = {
+ SERIAL_PORT_DFNS /* Defined in serial.h */
+};
+
+static struct async_struct kdb_port_info = {0};
+
+int (*generic_putDebugChar)(char);
+char (*generic_getDebugChar)(void);
+
+static __inline__ unsigned int serial_in(struct async_struct *info, int offset)
+{
+ return inb(info->port + offset);
+}
+
+static __inline__ void serial_out(struct async_struct *info, int offset,
+ int value)
+{
+ outb(value, info->port+offset);
+}
+
+int rs_kgdb_hook(int tty_no, int speed) {
+ int t;
+ struct serial_state *ser = &rs_table[tty_no];
+
+ kdb_port_info.state = ser;
+ kdb_port_info.magic = SERIAL_MAGIC;
+ kdb_port_info.port = ser->port;
+ kdb_port_info.flags = ser->flags;
+
+ /*
+ * Clear all interrupts
+ */
+ serial_in(&kdb_port_info, UART_LSR);
+ serial_in(&kdb_port_info, UART_RX);
+ serial_in(&kdb_port_info, UART_IIR);
+ serial_in(&kdb_port_info, UART_MSR);
+
+ /*
+ * Now, initialize the UART
+ */
+ serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8); /* reset DLAB */
+ if (kdb_port_info.flags & ASYNC_FOURPORT) {
+ kdb_port_info.MCR = UART_MCR_DTR | UART_MCR_RTS;
+ t = UART_MCR_DTR | UART_MCR_OUT1;
+ } else {
+ kdb_port_info.MCR
+ = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
+ t = UART_MCR_DTR | UART_MCR_RTS;
+ }
+
+ kdb_port_info.MCR = t; /* no interrupts, please */
+ serial_out(&kdb_port_info, UART_MCR, kdb_port_info.MCR);
+
+ /*
+ * and set the speed of the serial port
+ */
+ if (speed == 0)
+ speed = 9600;
+
+ t = kdb_port_info.state->baud_base / speed;
+ /* set DLAB */
+ serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8 | UART_LCR_DLAB);
+ serial_out(&kdb_port_info, UART_DLL, t & 0xff);/* LS of divisor */
+ serial_out(&kdb_port_info, UART_DLM, t >> 8); /* MS of divisor */
+ /* reset DLAB */
+ serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8);
+
+ return speed;
+}
+
+int putDebugChar(char c)
+{
+ return generic_putDebugChar(c);
+}
+
+char getDebugChar(void)
+{
+ return generic_getDebugChar();
+}
+
+int rs_putDebugChar(char c)
+{
+
+ if (!kdb_port_info.state) { /* need to init device first */
+ return 0;
+ }
+
+ while ((serial_in(&kdb_port_info, UART_LSR) & UART_LSR_THRE) == 0)
+ ;
+
+ serial_out(&kdb_port_info, UART_TX, c);
+
+ return 1;
+}
+
+char rs_getDebugChar(void)
+{
+ if (!kdb_port_info.state) { /* need to init device first */
+ return 0;
+ }
+
+ while (!(serial_in(&kdb_port_info, UART_LSR) & 1))
+ ;
+
+ return serial_in(&kdb_port_info, UART_RX);
+}
diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c
new file mode 100644
index 00000000000..31caf0603a3
--- /dev/null
+++ b/arch/mips/mips-boards/generic/init.c
@@ -0,0 +1,343 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * PROM library initialisation code.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#include <asm/io.h>
+#include <asm/bootinfo.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/generic.h>
+#ifdef CONFIG_MIPS_GT64120
+#include <asm/gt64120.h>
+#endif
+#include <asm/mips-boards/msc01_pci.h>
+#include <asm/mips-boards/bonito64.h>
+#ifdef CONFIG_MIPS_MALTA
+#include <asm/mips-boards/malta.h>
+#endif
+
+#ifdef CONFIG_KGDB
+extern int rs_kgdb_hook(int, int);
+extern int rs_putDebugChar(char);
+extern char rs_getDebugChar(void);
+extern int saa9730_kgdb_hook(int);
+extern int saa9730_putDebugChar(char);
+extern char saa9730_getDebugChar(void);
+#endif
+
+int prom_argc;
+int *_prom_argv, *_prom_envp;
+
+/*
+ * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
+ * This macro take care of sign extension, if running in 64-bit mode.
+ */
+#define prom_envp(index) ((char *)(long)_prom_envp[(index)])
+
+int init_debug = 0;
+
+unsigned int mips_revision_corid;
+
+/* Bonito64 system controller register base. */
+unsigned long _pcictrl_bonito;
+unsigned long _pcictrl_bonito_pcicfg;
+
+/* GT64120 system controller register base */
+unsigned long _pcictrl_gt64120;
+
+/* MIPS System controller register base */
+unsigned long _pcictrl_msc;
+
+char *prom_getenv(char *envname)
+{
+ /*
+ * Return a pointer to the given environment variable.
+ * In 64-bit mode: we're using 64-bit pointers, but all pointers
+ * in the PROM structures are only 32-bit, so we need some
+ * workarounds, if we are running in 64-bit mode.
+ */
+ int i, index=0;
+
+ i = strlen(envname);
+
+ while (prom_envp(index)) {
+ if(strncmp(envname, prom_envp(index), i) == 0) {
+ return(prom_envp(index+1));
+ }
+ index += 2;
+ }
+
+ return NULL;
+}
+
+static inline unsigned char str2hexnum(unsigned char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ return 0; /* foo */
+}
+
+static inline void str2eaddr(unsigned char *ea, unsigned char *str)
+{
+ int i;
+
+ for (i = 0; i < 6; i++) {
+ unsigned char num;
+
+ if((*str == '.') || (*str == ':'))
+ str++;
+ num = str2hexnum(*str++) << 4;
+ num |= (str2hexnum(*str++));
+ ea[i] = num;
+ }
+}
+
+int get_ethernet_addr(char *ethernet_addr)
+{
+ char *ethaddr_str;
+
+ ethaddr_str = prom_getenv("ethaddr");
+ if (!ethaddr_str) {
+ printk("ethaddr not set in boot prom\n");
+ return -1;
+ }
+ str2eaddr(ethernet_addr, ethaddr_str);
+
+ if (init_debug > 1) {
+ int i;
+ printk("get_ethernet_addr: ");
+ for (i=0; i<5; i++)
+ printk("%02x:", (unsigned char)*(ethernet_addr+i));
+ printk("%02x\n", *(ethernet_addr+i));
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+static void __init console_config(void)
+{
+ char console_string[40];
+ int baud = 0;
+ char parity = '\0', bits = '\0', flow = '\0';
+ char *s;
+
+ if ((strstr(prom_getcmdline(), "console=ttyS")) == NULL) {
+ s = prom_getenv("modetty0");
+ if (s) {
+ while (*s >= '0' && *s <= '9')
+ baud = baud*10 + *s++ - '0';
+ if (*s == ',') s++;
+ if (*s) parity = *s++;
+ if (*s == ',') s++;
+ if (*s) bits = *s++;
+ if (*s == ',') s++;
+ if (*s == 'h') flow = 'r';
+ }
+ if (baud == 0)
+ baud = 38400;
+ if (parity != 'n' && parity != 'o' && parity != 'e')
+ parity = 'n';
+ if (bits != '7' && bits != '8')
+ bits = '8';
+ if (flow == '\0')
+ flow = 'r';
+ sprintf (console_string, " console=ttyS0,%d%c%c%c", baud, parity, bits, flow);
+ strcat (prom_getcmdline(), console_string);
+ prom_printf("Config serial console:%s\n", console_string);
+ }
+}
+#endif
+
+#ifdef CONFIG_KGDB
+void __init kgdb_config (void)
+{
+ extern int (*generic_putDebugChar)(char);
+ extern char (*generic_getDebugChar)(void);
+ char *argptr;
+ int line, speed;
+
+ argptr = prom_getcmdline();
+ if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
+ argptr += strlen("kgdb=ttyS");
+ if (*argptr != '0' && *argptr != '1')
+ printk("KGDB: Unknown serial line /dev/ttyS%c, "
+ "falling back to /dev/ttyS1\n", *argptr);
+ line = *argptr == '0' ? 0 : 1;
+ printk("KGDB: Using serial line /dev/ttyS%d for session\n", line);
+
+ speed = 0;
+ if (*++argptr == ',')
+ {
+ int c;
+ while ((c = *++argptr) && ('0' <= c && c <= '9'))
+ speed = speed * 10 + c - '0';
+ }
+#ifdef CONFIG_MIPS_ATLAS
+ if (line == 1) {
+ speed = saa9730_kgdb_hook(speed);
+ generic_putDebugChar = saa9730_putDebugChar;
+ generic_getDebugChar = saa9730_getDebugChar;
+ }
+ else
+#endif
+ {
+ speed = rs_kgdb_hook(line, speed);
+ generic_putDebugChar = rs_putDebugChar;
+ generic_getDebugChar = rs_getDebugChar;
+ }
+
+ prom_printf("KGDB: Using serial line /dev/ttyS%d at %d for session, "
+ "please connect your debugger\n", line ? 1 : 0, speed);
+
+ {
+ char *s;
+ for (s = "Please connect GDB to this port\r\n"; *s; )
+ generic_putDebugChar (*s++);
+ }
+
+ kgdb_enabled = 1;
+ /* Breakpoint is invoked after interrupts are initialised */
+ }
+}
+#endif
+
+void __init prom_init(void)
+{
+ prom_argc = fw_arg0;
+ _prom_argv = (int *) fw_arg1;
+ _prom_envp = (int *) fw_arg2;
+
+ mips_display_message("LINUX");
+
+#ifdef CONFIG_MIPS_SEAD
+ set_io_port_base(KSEG1);
+#else
+ /*
+ * early setup of _pcictrl_bonito so that we can determine
+ * the system controller on a CORE_EMUL board
+ */
+ _pcictrl_bonito = (unsigned long)ioremap(BONITO_REG_BASE, BONITO_REG_SIZE);
+
+ mips_revision_corid = MIPS_REVISION_CORID;
+
+ if (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL) {
+ if (BONITO_PCIDID == 0x0001df53 ||
+ BONITO_PCIDID == 0x0003df53)
+ mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_BON;
+ else
+ mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_MSC;
+ }
+ switch(mips_revision_corid) {
+ case MIPS_REVISION_CORID_QED_RM5261:
+ case MIPS_REVISION_CORID_CORE_LV:
+ case MIPS_REVISION_CORID_CORE_FPGA:
+ case MIPS_REVISION_CORID_CORE_FPGAR2:
+ /*
+ * Setup the North bridge to do Master byte-lane swapping
+ * when running in bigendian.
+ */
+ _pcictrl_gt64120 = (unsigned long)ioremap(MIPS_GT_BASE, 0x2000);
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+ GT_WRITE(GT_PCI0_CMD_OFS, GT_PCI0_CMD_MBYTESWAP_BIT |
+ GT_PCI0_CMD_SBYTESWAP_BIT);
+#else
+ GT_WRITE(GT_PCI0_CMD_OFS, 0);
+#endif
+
+#ifdef CONFIG_MIPS_MALTA
+ set_io_port_base(MALTA_GT_PORT_BASE);
+#else
+ set_io_port_base((unsigned long)ioremap(0, 0x20000000));
+#endif
+ break;
+
+ case MIPS_REVISION_CORID_CORE_EMUL_BON:
+ case MIPS_REVISION_CORID_BONITO64:
+ case MIPS_REVISION_CORID_CORE_20K:
+ _pcictrl_bonito_pcicfg = (unsigned long)ioremap(BONITO_PCICFG_BASE, BONITO_PCICFG_SIZE);
+
+ /*
+ * Disable Bonito IOBC.
+ */
+ BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG &
+ ~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
+ BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
+
+ /*
+ * Setup the North bridge to do Master byte-lane swapping
+ * when running in bigendian.
+ */
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+ BONITO_BONGENCFG = BONITO_BONGENCFG &
+ ~(BONITO_BONGENCFG_MSTRBYTESWAP |
+ BONITO_BONGENCFG_BYTESWAP);
+#else
+ BONITO_BONGENCFG = BONITO_BONGENCFG |
+ BONITO_BONGENCFG_MSTRBYTESWAP |
+ BONITO_BONGENCFG_BYTESWAP;
+#endif
+
+#ifdef CONFIG_MIPS_MALTA
+ set_io_port_base(MALTA_BONITO_PORT_BASE);
+#else
+ set_io_port_base((unsigned long)ioremap(0, 0x20000000));
+#endif
+ break;
+
+ case MIPS_REVISION_CORID_CORE_MSC:
+ case MIPS_REVISION_CORID_CORE_FPGA2:
+ case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+ _pcictrl_msc = (unsigned long)ioremap(MIPS_MSC01_PCI_REG_BASE, 0x2000);
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+ MSC_WRITE(MSC01_PCI_SWAP, MSC01_PCI_SWAP_NOSWAP);
+#else
+ MSC_WRITE(MSC01_PCI_SWAP,
+ MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_IO_SHF |
+ MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_MEM_SHF |
+ MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_BAR0_SHF);
+#endif
+
+#ifdef CONFIG_MIPS_MALTA
+ set_io_port_base(MALTA_MSC_PORT_BASE);
+#else
+ set_io_port_base((unsigned long)ioremap(0, 0x20000000));
+#endif
+ break;
+
+ default:
+ /* Unknown Core card */
+ mips_display_message("CC Error");
+ while(1); /* We die here... */
+ }
+#endif
+ prom_printf("\nLINUX started...\n");
+ prom_init_cmdline();
+ prom_meminit();
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ console_config();
+#endif
+}
diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c
new file mode 100644
index 00000000000..5ae2b43e4c2
--- /dev/null
+++ b/arch/mips/mips-boards/generic/memory.c
@@ -0,0 +1,173 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * PROM library functions for acquiring/using memory descriptors given to
+ * us from the YAMON.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/bootmem.h>
+
+#include <asm/bootinfo.h>
+#include <asm/page.h>
+
+#include <asm/mips-boards/prom.h>
+
+/*#define DEBUG*/
+
+enum yamon_memtypes {
+ yamon_dontuse,
+ yamon_prom,
+ yamon_free,
+};
+struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
+
+#ifdef DEBUG
+static char *mtypes[3] = {
+ "Dont use memory",
+ "YAMON PROM memory",
+ "Free memmory",
+};
+#endif
+
+/* References to section boundaries */
+extern char _end;
+
+#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
+
+
+struct prom_pmemblock * __init prom_getmdesc(void)
+{
+ char *memsize_str;
+ unsigned int memsize;
+
+ 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;
+ mdesc[0].base = 0x00000000;
+ mdesc[0].size = 0x00001000;
+
+ mdesc[1].type = yamon_prom;
+ mdesc[1].base = 0x00001000;
+ mdesc[1].size = 0x000ef000;
+
+#ifdef CONFIG_MIPS_MALTA
+ /*
+ * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the
+ * south bridge and PCI access always forwarded to the ISA Bus and
+ * BIOSCS# is always generated.
+ * This mean that this area can't be used as DMA memory for PCI
+ * devices.
+ */
+ mdesc[2].type = yamon_dontuse;
+ mdesc[2].base = 0x000f0000;
+ mdesc[2].size = 0x00010000;
+#else
+ mdesc[2].type = yamon_prom;
+ mdesc[2].base = 0x000f0000;
+ mdesc[2].size = 0x00010000;
+#endif
+
+ mdesc[3].type = yamon_dontuse;
+ mdesc[3].base = 0x00100000;
+ mdesc[3].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[3].base;
+
+ mdesc[4].type = yamon_free;
+ mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end));
+ mdesc[4].size = memsize - mdesc[4].base;
+
+ return &mdesc[0];
+}
+
+static int __init prom_memtype_classify (unsigned int type)
+{
+ switch (type) {
+ case yamon_free:
+ return BOOT_MEM_RAM;
+ case yamon_prom:
+ return BOOT_MEM_ROM_DATA;
+ default:
+ return BOOT_MEM_RESERVED;
+ }
+}
+
+void __init prom_meminit(void)
+{
+ struct prom_pmemblock *p;
+
+#ifdef DEBUG
+ prom_printf("YAMON MEMORY DESCRIPTOR dump:\n");
+ p = prom_getmdesc();
+ while (p->size) {
+ int i = 0;
+ prom_printf("[%d,%p]: base<%08lx> size<%08lx> type<%s>\n",
+ i, p, p->base, p->size, mtypes[p->type]);
+ p++;
+ i++;
+ }
+#endif
+ p = prom_getmdesc();
+
+ while (p->size) {
+ long type;
+ unsigned long base, size;
+
+ type = prom_memtype_classify (p->type);
+ base = p->base;
+ size = p->size;
+
+ add_memory_region(base, size, type);
+ p++;
+ }
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+ unsigned long freed = 0;
+ unsigned long addr;
+ int i;
+
+ for (i = 0; i < boot_mem_map.nr_map; i++) {
+ if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
+ continue;
+
+ addr = boot_mem_map.map[i].addr;
+ while (addr < boot_mem_map.map[i].addr
+ + boot_mem_map.map[i].size) {
+ ClearPageReserved(virt_to_page(__va(addr)));
+ set_page_count(virt_to_page(__va(addr)), 1);
+ free_page((unsigned long)__va(addr));
+ addr += PAGE_SIZE;
+ freed += PAGE_SIZE;
+ }
+ }
+ printk("Freeing prom memory: %ldkb freed\n", freed >> 10);
+
+ return freed;
+}
diff --git a/arch/mips/mips-boards/generic/mipsIRQ.S b/arch/mips/mips-boards/generic/mipsIRQ.S
new file mode 100644
index 00000000000..131f49bccb2
--- /dev/null
+++ b/arch/mips/mips-boards/generic/mipsIRQ.S
@@ -0,0 +1,153 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Interrupt exception dispatch code.
+ *
+ */
+#include <linux/config.h>
+
+#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 MIPS board look basically (barring software
+ * IRQs which we don't use at all and all external interrupt sources are
+ * combined together on hardware interrupt 0 (MIPS IRQ 2)) like:
+ *
+ * MIPS IRQ Source
+ * -------- ------
+ * 0 Software (ignored)
+ * 1 Software (ignored)
+ * 2 Combined hardware interrupt (hw0)
+ * 3 Hardware (ignored)
+ * 4 Hardware (ignored)
+ * 5 Hardware (ignored)
+ * 6 Hardware (ignored)
+ * 7 R4k timer (what we use)
+ *
+ * Note: On the SEAD board thing are a little bit different.
+ * Here IRQ 2 (hw0) is wired to the UART0 and IRQ 3 (hw1) is wired
+ * wired to UART1.
+ *
+ * We handle the IRQ according to _our_ priority which is:
+ *
+ * Highest ---- R4k Timer
+ * Lowest ---- Combined hardware interrupt
+ *
+ * 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(mipsIRQ, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+ .set at
+
+ mfc0 s0, CP0_CAUSE # get irq bits
+ mfc0 s1, CP0_STATUS # get irq mask
+ 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
+#else
+ beq a0, zero, 1f # delay slot, check hw3 interrupt
+ andi a0, s0, CAUSEF_IP5
+#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
+#else
+#error "MIPS board not supported\n"
+#endif
+ move a0, sp # delay slot
+
+ j ret_from_irq
+ nop # delay slot
+
+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
+ nop
+ END(mipsIRQ)
diff --git a/arch/mips/mips-boards/generic/pci.c b/arch/mips/mips-boards/generic/pci.c
new file mode 100644
index 00000000000..92c34bda02a
--- /dev/null
+++ b/arch/mips/mips-boards/generic/pci.c
@@ -0,0 +1,163 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * MIPS boards specific PCI support.
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/mips-boards/generic.h>
+#include <asm/gt64120.h>
+#include <asm/mips-boards/bonito64.h>
+#include <asm/mips-boards/msc01_pci.h>
+#ifdef CONFIG_MIPS_MALTA
+#include <asm/mips-boards/malta.h>
+#endif
+
+static struct resource bonito64_mem_resource = {
+ .name = "Bonito PCI MEM",
+ .start = 0x10000000UL,
+ .end = 0x1bffffffUL,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource bonito64_io_resource = {
+ .name = "Bonito IO MEM",
+ .start = 0x00002000UL, /* avoid conflicts with YAMON allocated I/O addresses */
+ .end = 0x000fffffUL,
+ .flags = IORESOURCE_IO,
+};
+
+static struct resource gt64120_mem_resource = {
+ .name = "GT64120 PCI MEM",
+ .start = 0x10000000UL,
+ .end = 0x1bdfffffUL,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource gt64120_io_resource = {
+ .name = "GT64120 IO MEM",
+#ifdef CONFIG_MIPS_ATLAS
+ .start = 0x18000000UL,
+ .end = 0x181fffffUL,
+#endif
+#ifdef CONFIG_MIPS_MALTA
+ .start = 0x00002000UL,
+ .end = 0x001fffffUL,
+#endif
+ .flags = IORESOURCE_IO,
+};
+
+static struct resource msc_mem_resource = {
+ .name = "MSC PCI MEM",
+ .start = 0x10000000UL,
+ .end = 0x1fffffffUL,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource msc_io_resource = {
+ .name = "MSC IO MEM",
+ .start = 0x00002000UL,
+ .end = 0x007fffffUL,
+ .flags = IORESOURCE_IO,
+};
+
+extern struct pci_ops bonito64_pci_ops;
+extern struct pci_ops gt64120_pci_ops;
+extern struct pci_ops msc_pci_ops;
+
+static struct pci_controller bonito64_controller = {
+ .pci_ops = &bonito64_pci_ops,
+ .io_resource = &bonito64_io_resource,
+ .mem_resource = &bonito64_mem_resource,
+ .mem_offset = 0x10000000UL,
+ .io_offset = 0x00000000UL,
+};
+
+static struct pci_controller gt64120_controller = {
+ .pci_ops = &gt64120_pci_ops,
+ .io_resource = &gt64120_io_resource,
+ .mem_resource = &gt64120_mem_resource,
+ .mem_offset = 0x00000000UL,
+ .io_offset = 0x00000000UL,
+};
+
+static struct pci_controller msc_controller = {
+ .pci_ops = &msc_pci_ops,
+ .io_resource = &msc_io_resource,
+ .mem_resource = &msc_mem_resource,
+ .mem_offset = 0x10000000UL,
+ .io_offset = 0x00000000UL,
+};
+
+static int __init pcibios_init(void)
+{
+ struct pci_controller *controller;
+
+ switch (mips_revision_corid) {
+ case MIPS_REVISION_CORID_QED_RM5261:
+ case MIPS_REVISION_CORID_CORE_LV:
+ case MIPS_REVISION_CORID_CORE_FPGA:
+ case MIPS_REVISION_CORID_CORE_FPGAR2:
+ /*
+ * Due to a bug in the Galileo system controller, we need
+ * to setup the PCI BAR for the Galileo internal registers.
+ * This should be done in the bios/bootprom and will be
+ * fixed in a later revision of YAMON (the MIPS boards
+ * boot prom).
+ */
+ GT_WRITE(GT_PCI0_CFGADDR_OFS,
+ (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */
+ (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */
+ (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0*/
+ ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4*/
+ GT_PCI0_CFGADDR_CONFIGEN_BIT );
+
+ /* Perform the write */
+ GT_WRITE(GT_PCI0_CFGDATA_OFS, CPHYSADDR(MIPS_GT_BASE));
+
+ controller = &gt64120_controller;
+ break;
+
+ case MIPS_REVISION_CORID_BONITO64:
+ case MIPS_REVISION_CORID_CORE_20K:
+ case MIPS_REVISION_CORID_CORE_EMUL_BON:
+ controller = &bonito64_controller;
+ break;
+
+ case MIPS_REVISION_CORID_CORE_MSC:
+ case MIPS_REVISION_CORID_CORE_FPGA2:
+ case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+ controller = &msc_controller;
+ break;
+ default:
+ return 1;
+ }
+
+ ioport_resource.end = controller->io_resource->end;
+
+ register_pci_controller (controller);
+
+ return 0;
+}
+
+early_initcall(pcibios_init);
diff --git a/arch/mips/mips-boards/generic/printf.c b/arch/mips/mips-boards/generic/printf.c
new file mode 100644
index 00000000000..2c1ab1f19fd
--- /dev/null
+++ b/arch/mips/mips-boards/generic/printf.c
@@ -0,0 +1,79 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Putting things on the screen/serial line using YAMONs facilities.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/serial_reg.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+
+#ifdef CONFIG_MIPS_ATLAS
+#include <asm/mips-boards/atlas.h>
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+#define PORT(offset) (ATLAS_UART_REGS_BASE + ((offset)<<3))
+#else
+#define PORT(offset) (ATLAS_UART_REGS_BASE + 3 + ((offset)<<3))
+#endif
+
+#elif defined(CONFIG_MIPS_SEAD)
+
+#include <asm/mips-boards/sead.h>
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+#define PORT(offset) (SEAD_UART0_REGS_BASE + ((offset)<<3))
+#else
+#define PORT(offset) (SEAD_UART0_REGS_BASE + 3 + ((offset)<<3))
+#endif
+
+#else
+
+#define PORT(offset) (0x3f8 + (offset))
+
+#endif
+
+static inline unsigned int serial_in(int offset)
+{
+ return inb(PORT(offset));
+}
+
+static inline void serial_out(int offset, int value)
+{
+ outb(value, PORT(offset));
+}
+
+int prom_putchar(char c)
+{
+ while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0)
+ ;
+
+ serial_out(UART_TX, c);
+
+ return 1;
+}
+
+char prom_getchar(void)
+{
+ while (!(serial_in(UART_LSR) & UART_LSR_DR))
+ ;
+
+ return serial_in(UART_RX);
+}
+
diff --git a/arch/mips/mips-boards/generic/reset.c b/arch/mips/mips-boards/generic/reset.c
new file mode 100644
index 00000000000..9fdec743bd9
--- /dev/null
+++ b/arch/mips/mips-boards/generic/reset.c
@@ -0,0 +1,73 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * ########################################################################
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * Reset the MIPS boards.
+ *
+ */
+#include <linux/config.h>
+
+#include <asm/io.h>
+#include <asm/reboot.h>
+#include <asm/mips-boards/generic.h>
+#if defined(CONFIG_MIPS_ATLAS)
+#include <asm/mips-boards/atlas.h>
+#endif
+
+static void mips_machine_restart(char *command);
+static void mips_machine_halt(void);
+#if defined(CONFIG_MIPS_ATLAS)
+static void atlas_machine_power_off(void);
+#endif
+
+static void mips_machine_restart(char *command)
+{
+ volatile unsigned int *softres_reg = (unsigned int *)ioremap (SOFTRES_REG, sizeof(unsigned int));
+
+ *softres_reg = GORESET;
+}
+
+static void mips_machine_halt(void)
+{
+ volatile unsigned int *softres_reg = (unsigned int *)ioremap (SOFTRES_REG, sizeof(unsigned int));
+
+ *softres_reg = GORESET;
+}
+
+#if defined(CONFIG_MIPS_ATLAS)
+static void atlas_machine_power_off(void)
+{
+ volatile unsigned int *psustby_reg = (unsigned int *)ioremap(ATLAS_PSUSTBY_REG, sizeof(unsigned int));
+
+ *psustby_reg = ATLAS_GOSTBY;
+}
+#endif
+
+void mips_reboot_setup(void)
+{
+ _machine_restart = mips_machine_restart;
+ _machine_halt = mips_machine_halt;
+#if defined(CONFIG_MIPS_ATLAS)
+ _machine_power_off = atlas_machine_power_off;
+#endif
+#if defined(CONFIG_MIPS_MALTA) || defined(CONFIG_MIPS_SEAD)
+ _machine_power_off = mips_machine_halt;
+#endif
+}
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
new file mode 100644
index 00000000000..fe7fc17305a
--- /dev/null
+++ b/arch/mips/mips-boards/generic/time.c
@@ -0,0 +1,167 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Setting up the clock on the MIPS boards.
+ */
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/mc146818rtc.h>
+
+#include <asm/mipsregs.h>
+#include <asm/ptrace.h>
+#include <asm/div64.h>
+#include <asm/cpu.h>
+#include <asm/time.h>
+#include <asm/mc146818-time.h>
+
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.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
+#if defined(CONFIG_MIPS_MALTA)
+static char display_string[] = " LINUX ON MALTA ";
+#endif
+#if defined(CONFIG_MIPS_SEAD)
+static char display_string[] = " LINUX ON SEAD ";
+#endif
+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;
+
+void mips_timer_interrupt(struct pt_regs *regs)
+{
+ if ((timer_tick_count++ % HZ) == 0) {
+ mips_display_message(&display_string[display_count++]);
+ if (display_count == MAX_DISPLAY_COUNT)
+ display_count = 0;
+
+ }
+
+ ll_timer_interrupt(MIPS_CPU_TIMER_IRQ, regs);
+}
+
+/*
+ * Estimate CPU frequency. Sets mips_counter_frequency as a side-effect
+ */
+static unsigned int __init estimate_cpu_frequency(void)
+{
+ unsigned int prid = read_c0_prid() & 0xffff00;
+ unsigned int count;
+
+#ifdef CONFIG_MIPS_SEAD
+ /*
+ * The SEAD board doesn't have a real time clock, so we can't
+ * really calculate the timer frequency
+ * For now we hardwire the SEAD board frequency to 12MHz.
+ */
+
+ if ((prid == (PRID_COMP_MIPS | PRID_IMP_20KC)) ||
+ (prid == (PRID_COMP_MIPS | PRID_IMP_25KF)))
+ count = 12000000;
+ else
+ count = 6000000;
+#endif
+#if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_MALTA)
+ unsigned int flags;
+
+ local_irq_save(flags);
+
+ /* Start counter exactly on falling edge of update flag */
+ while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+ while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+ /* Start r4k counter. */
+ write_c0_count(0);
+
+ /* Read counter exactly on falling edge of update flag */
+ while (CMOS_READ(RTC_REG_A) & RTC_UIP);
+ while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
+
+ count = read_c0_count();
+
+ /* restore interrupts */
+ local_irq_restore(flags);
+#endif
+
+ mips_hpt_frequency = count;
+ if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
+ (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
+ count *= 2;
+
+ count += 5000; /* round */
+ count -= count%10000;
+
+ return count;
+}
+
+unsigned long __init mips_rtc_get_time(void)
+{
+ return mc146818_get_cmos_time();
+}
+
+void __init mips_time_init(void)
+{
+ unsigned int est_freq, flags;
+
+ 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 ();
+
+ printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
+ (est_freq%1000000)*100/1000000);
+
+ cpu_khz = est_freq / 1000;
+
+ local_irq_restore(flags);
+}
+
+void __init mips_timer_setup(struct irqaction *irq)
+{
+ /* 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);
+
+ /* to generate the first timer interrupt */
+ write_c0_compare (read_c0_count() + mips_hpt_frequency/HZ);
+ set_c0_status(ALLINTS);
+}
diff --git a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile
new file mode 100644
index 00000000000..fd4c143c0e2
--- /dev/null
+++ b/arch/mips/mips-boards/malta/Makefile
@@ -0,0 +1,22 @@
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+#
+# This program is free software; you can distribute it and/or modify it
+# under the terms of the GNU General Public License (Version 2) as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# Makefile for the MIPS Malta specific kernel interface routines
+# under Linux.
+#
+
+obj-y := malta_int.o malta_setup.o
diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c
new file mode 100644
index 00000000000..dd2db35966b
--- /dev/null
+++ b/arch/mips/mips-boards/malta/malta_int.c
@@ -0,0 +1,187 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc.
+ * Copyright (C) 2001 Ralf Baechle
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Routines for generic manipulation of the interrupts found on the MIPS
+ * Malta board.
+ * The interrupt controller is located in the South Bridge a PIIX4 device
+ * with two internal 82C95 interrupt controllers.
+ */
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/random.h>
+
+#include <asm/i8259.h>
+#include <asm/io.h>
+#include <asm/mips-boards/malta.h>
+#include <asm/mips-boards/maltaint.h>
+#include <asm/mips-boards/piix4.h>
+#include <asm/gt64120.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/msc01_pci.h>
+
+extern asmlinkage void mipsIRQ(void);
+
+static DEFINE_SPINLOCK(mips_irq_lock);
+
+static inline int mips_pcibios_iack(void)
+{
+ int irq;
+ u32 dummy;
+
+ /*
+ * Determine highest priority pending interrupt by performing
+ * a PCI Interrupt Acknowledge cycle.
+ */
+ switch(mips_revision_corid) {
+ case MIPS_REVISION_CORID_CORE_MSC:
+ case MIPS_REVISION_CORID_CORE_FPGA2:
+ case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+ MSC_READ(MSC01_PCI_IACK, irq);
+ irq &= 0xff;
+ break;
+ case MIPS_REVISION_CORID_QED_RM5261:
+ case MIPS_REVISION_CORID_CORE_LV:
+ case MIPS_REVISION_CORID_CORE_FPGA:
+ case MIPS_REVISION_CORID_CORE_FPGAR2:
+ irq = GT_READ(GT_PCI0_IACK_OFS);
+ irq &= 0xff;
+ break;
+ case MIPS_REVISION_CORID_BONITO64:
+ case MIPS_REVISION_CORID_CORE_20K:
+ case MIPS_REVISION_CORID_CORE_EMUL_BON:
+ /* The following will generate a PCI IACK cycle on the
+ * Bonito controller. It's a little bit kludgy, but it
+ * was the easiest way to implement it in hardware at
+ * the given time.
+ */
+ BONITO_PCIMAP_CFG = 0x20000;
+
+ /* Flush Bonito register block */
+ dummy = BONITO_PCIMAP_CFG;
+ iob(); /* sync */
+
+ irq = *(volatile u32 *)(_pcictrl_bonito_pcicfg);
+ iob(); /* sync */
+ irq &= 0xff;
+ BONITO_PCIMAP_CFG = 0;
+ break;
+ default:
+ printk("Unknown Core card, don't know the system controller.\n");
+ return -1;
+ }
+ return irq;
+}
+
+static inline int get_int(int *irq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mips_irq_lock, flags);
+
+ *irq = mips_pcibios_iack();
+
+ /*
+ * IRQ7 is used to detect spurious interrupts.
+ * The interrupt acknowledge cycle returns IRQ7, if no
+ * interrupts is requested.
+ * We can differentiate between this situation and a
+ * "Normal" IRQ7 by reading the ISR.
+ */
+ if (*irq == 7)
+ {
+ outb(PIIX4_OCW3_SEL | PIIX4_OCW3_ISR,
+ PIIX4_ICTLR1_OCW3);
+ if (!(inb(PIIX4_ICTLR1_OCW3) & (1 << 7))) {
+ spin_unlock_irqrestore(&mips_irq_lock, flags);
+ printk("We got a spurious interrupt from PIIX4.\n");
+ atomic_inc(&irq_err_count);
+ return -1; /* Spurious interrupt. */
+ }
+ }
+
+ spin_unlock_irqrestore(&mips_irq_lock, flags);
+
+ return 0;
+}
+
+void malta_hw0_irqdispatch(struct pt_regs *regs)
+{
+ int irq;
+
+ if (get_int(&irq))
+ return; /* interrupt has already been cleared */
+
+ do_IRQ(irq, regs);
+}
+
+void corehi_irqdispatch(struct pt_regs *regs)
+{
+ unsigned int data,datahi;
+
+ /* Mask out corehi interrupt. */
+ clear_c0_status(IE_IRQ3);
+
+ printk("CoreHI interrupt, shouldn't happen, so we die here!!!\n");
+ printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\nbadVaddr : %08lx\n"
+, regs->cp0_epc, regs->cp0_status, regs->cp0_cause, regs->cp0_badvaddr);
+ switch(mips_revision_corid) {
+ case MIPS_REVISION_CORID_CORE_MSC:
+ case MIPS_REVISION_CORID_CORE_FPGA2:
+ case MIPS_REVISION_CORID_CORE_EMUL_MSC:
+ break;
+ case MIPS_REVISION_CORID_QED_RM5261:
+ case MIPS_REVISION_CORID_CORE_LV:
+ case MIPS_REVISION_CORID_CORE_FPGA:
+ case MIPS_REVISION_CORID_CORE_FPGAR2:
+ data = GT_READ(GT_INTRCAUSE_OFS);
+ printk("GT_INTRCAUSE = %08x\n", data);
+ data = GT_READ(GT_CPUERR_ADDRLO_OFS);
+ datahi = GT_READ(GT_CPUERR_ADDRHI_OFS);
+ printk("GT_CPUERR_ADDR = %02x%08x\n", datahi, data);
+ break;
+ case MIPS_REVISION_CORID_BONITO64:
+ case MIPS_REVISION_CORID_CORE_20K:
+ case MIPS_REVISION_CORID_CORE_EMUL_BON:
+ data = BONITO_INTISR;
+ printk("BONITO_INTISR = %08x\n", data);
+ data = BONITO_INTEN;
+ printk("BONITO_INTEN = %08x\n", data);
+ data = BONITO_INTPOL;
+ printk("BONITO_INTPOL = %08x\n", data);
+ data = BONITO_INTEDGE;
+ printk("BONITO_INTEDGE = %08x\n", data);
+ data = BONITO_INTSTEER;
+ printk("BONITO_INTSTEER = %08x\n", data);
+ data = BONITO_PCICMD;
+ printk("BONITO_PCICMD = %08x\n", data);
+ break;
+ }
+
+ /* We die here*/
+ die("CoreHi interrupt", regs);
+}
+
+void __init arch_init_irq(void)
+{
+ set_except_vector(0, mipsIRQ);
+ init_i8259_irqs();
+}
diff --git a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c
new file mode 100644
index 00000000000..3377e66de9e
--- /dev/null
+++ b/arch/mips/mips-boards/malta/malta_setup.c
@@ -0,0 +1,231 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/tty.h>
+
+#ifdef CONFIG_MTD
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#endif
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/malta.h>
+#include <asm/mips-boards/maltaint.h>
+#include <asm/dma.h>
+#include <asm/time.h>
+#include <asm/traps.h>
+#ifdef CONFIG_VT
+#include <linux/console.h>
+#endif
+
+extern void mips_reboot_setup(void);
+extern void mips_time_init(void);
+extern void mips_timer_setup(struct irqaction *irq);
+extern unsigned long mips_rtc_get_time(void);
+
+#ifdef CONFIG_KGDB
+extern void kgdb_config(void);
+#endif
+
+struct resource standard_io_resources[] = {
+ { "dma1", 0x00, 0x1f, IORESOURCE_BUSY },
+ { "timer", 0x40, 0x5f, IORESOURCE_BUSY },
+ { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY },
+ { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY },
+ { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY },
+};
+
+#ifdef CONFIG_MTD
+static struct mtd_partition malta_mtd_partitions[] = {
+ {
+ .name = "YAMON",
+ .offset = 0x0,
+ .size = 0x100000,
+ .mask_flags = MTD_WRITEABLE
+ },
+ {
+ .name = "User FS",
+ .offset = 0x100000,
+ .size = 0x2e0000
+ },
+ {
+ .name = "Board Config",
+ .offset = 0x3e0000,
+ .size = 0x020000,
+ .mask_flags = MTD_WRITEABLE
+ }
+};
+
+#define number_partitions (sizeof(malta_mtd_partitions)/sizeof(struct mtd_partition))
+#endif
+
+const char *get_system_type(void)
+{
+ return "MIPS Malta";
+}
+
+#ifdef CONFIG_BLK_DEV_FD
+void __init fd_activate(void)
+{
+ /*
+ * Activate Floppy Controller in the SMSC FDC37M817 Super I/O
+ * Controller.
+ * Done by YAMON 2.00 onwards
+ */
+ /* Entering config state. */
+ SMSC_WRITE(SMSC_CONFIG_ENTER, SMSC_CONFIG_REG);
+
+ /* Activate floppy controller. */
+ SMSC_WRITE(SMSC_CONFIG_DEVNUM, SMSC_CONFIG_REG);
+ SMSC_WRITE(SMSC_CONFIG_DEVNUM_FLOPPY, SMSC_DATA_REG);
+ SMSC_WRITE(SMSC_CONFIG_ACTIVATE, SMSC_CONFIG_REG);
+ SMSC_WRITE(SMSC_CONFIG_ACTIVATE_ENABLE, SMSC_DATA_REG);
+
+ /* Exit config state. */
+ SMSC_WRITE(SMSC_CONFIG_EXIT, SMSC_CONFIG_REG);
+}
+#endif
+
+static int __init malta_setup(void)
+{
+ unsigned int i;
+
+ /* Request I/O space for devices used on the Malta board. */
+ for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++)
+ request_resource(&ioport_resource, standard_io_resources+i);
+
+ /*
+ * Enable DMA channel 4 (cascade channel) in the PIIX4 south bridge.
+ */
+ enable_dma(4);
+
+#ifdef CONFIG_KGDB
+ kgdb_config ();
+#endif
+
+ if ((mips_revision_corid == MIPS_REVISION_CORID_BONITO64) ||
+ (mips_revision_corid == MIPS_REVISION_CORID_CORE_20K) ||
+ (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL_BON)) {
+ char *argptr;
+
+ argptr = prom_getcmdline();
+ if (strstr(argptr, "debug")) {
+ BONITO_BONGENCFG |= BONITO_BONGENCFG_DEBUGMODE;
+ printk ("Enabled Bonito debug mode\n");
+ }
+ else
+ BONITO_BONGENCFG &= ~BONITO_BONGENCFG_DEBUGMODE;
+
+#ifdef CONFIG_DMA_COHERENT
+ if (BONITO_PCICACHECTRL & BONITO_PCICACHECTRL_CPUCOH_PRES) {
+ BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_CPUCOH_EN;
+ printk("Enabled Bonito CPU coherency\n");
+
+ argptr = prom_getcmdline();
+ if (strstr(argptr, "iobcuncached")) {
+ BONITO_PCICACHECTRL &= ~BONITO_PCICACHECTRL_IOBCCOH_EN;
+ BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG &
+ ~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
+ BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
+ printk("Disabled Bonito IOBC coherency\n");
+ }
+ else {
+ BONITO_PCICACHECTRL |= BONITO_PCICACHECTRL_IOBCCOH_EN;
+ BONITO_PCIMEMBASECFG |=
+ (BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
+ BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
+ printk("Disabled Bonito IOBC coherency\n");
+ }
+ }
+ else
+ panic("Hardware DMA cache coherency not supported");
+
+#endif
+ }
+#ifdef CONFIG_DMA_COHERENT
+ else {
+ panic("Hardware DMA cache coherency not supported");
+ }
+#endif
+
+#ifdef CONFIG_BLK_DEV_IDE
+ /* Check PCI clock */
+ {
+ int jmpr = (*((volatile unsigned int *)ioremap(MALTA_JMPRS_REG, sizeof(unsigned int))) >> 2) & 0x07;
+ static const int pciclocks[] __initdata = {
+ 33, 20, 25, 30, 12, 16, 37, 10
+ };
+ int pciclock = pciclocks[jmpr];
+ char *argptr = prom_getcmdline();
+
+ if (pciclock != 33 && !strstr (argptr, "idebus=")) {
+ printk("WARNING: PCI clock is %dMHz, setting idebus\n", pciclock);
+ argptr += strlen(argptr);
+ sprintf (argptr, " idebus=%d", pciclock);
+ if (pciclock < 20 || pciclock > 66)
+ printk ("WARNING: IDE timing calculations will be incorrect\n");
+ }
+ }
+#endif
+#ifdef CONFIG_BLK_DEV_FD
+ fd_activate ();
+#endif
+#ifdef CONFIG_VT
+#if defined(CONFIG_VGA_CONSOLE)
+ screen_info = (struct screen_info) {
+ 0, 25, /* orig-x, orig-y */
+ 0, /* unused */
+ 0, /* orig-video-page */
+ 0, /* orig-video-mode */
+ 80, /* orig-video-cols */
+ 0,0,0, /* ega_ax, ega_bx, ega_cx */
+ 25, /* orig-video-lines */
+ VIDEO_TYPE_VGAC, /* orig-video-isVGA */
+ 16 /* orig-video-points */
+ };
+#endif
+#endif
+
+#ifdef CONFIG_MTD
+ /*
+ * Support for MTD on Malta. Use the generic physmap driver
+ */
+ physmap_configure(0x1e000000, 0x400000, 4, NULL);
+ physmap_set_partitions(malta_mtd_partitions, number_partitions);
+#endif
+
+ mips_reboot_setup();
+
+ board_time_init = mips_time_init;
+ board_timer_setup = mips_timer_setup;
+ rtc_get_time = mips_rtc_get_time;
+
+ return 0;
+}
+
+early_initcall(malta_setup);
diff --git a/arch/mips/mips-boards/sead/Makefile b/arch/mips/mips-boards/sead/Makefile
new file mode 100644
index 00000000000..224bb848f16
--- /dev/null
+++ b/arch/mips/mips-boards/sead/Makefile
@@ -0,0 +1,26 @@
+#
+# Carsten Langgaard, carstenl@mips.com
+# Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved.
+#
+# ########################################################################
+#
+# This program is free software; you can distribute it and/or modify it
+# under the terms of the GNU General Public License (Version 2) as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# #######################################################################
+#
+# Makefile for the MIPS SEAD specific kernel interface routines
+# under Linux.
+#
+
+obj-y := sead_int.o sead_setup.o
diff --git a/arch/mips/mips-boards/sead/sead_int.c b/arch/mips/mips-boards/sead/sead_int.c
new file mode 100644
index 00000000000..e5109657ed5
--- /dev/null
+++ b/arch/mips/mips-boards/sead/sead_int.c
@@ -0,0 +1,51 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved.
+ * Copyright (C) 2003 Ralf Baechle (ralf@linux-mips.org)
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Routines for generic manipulation of the interrupts found on the MIPS
+ * Sead board.
+ */
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/mips-boards/seadint.h>
+
+extern asmlinkage void mipsIRQ(void);
+
+asmlinkage void sead_hw0_irqdispatch(struct pt_regs *regs)
+{
+ do_IRQ(SEADINT_UART0, regs);
+}
+
+asmlinkage void sead_hw1_irqdispatch(struct pt_regs *regs)
+{
+ do_IRQ(SEADINT_UART1, regs);
+}
+
+void __init arch_init_irq(void)
+{
+ /*
+ * Mask out all interrupt
+ */
+ clear_c0_status(0x0000ff00);
+
+ /* Now safe to set the exception vector. */
+ set_except_vector(0, mipsIRQ);
+
+ mips_cpu_irq_init(0);
+}
diff --git a/arch/mips/mips-boards/sead/sead_setup.c b/arch/mips/mips-boards/sead/sead_setup.c
new file mode 100644
index 00000000000..29892b88a4f
--- /dev/null
+++ b/arch/mips/mips-boards/sead/sead_setup.c
@@ -0,0 +1,84 @@
+/*
+ * Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved.
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * SEAD specific setup.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+
+#include <asm/cpu.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/prom.h>
+#include <asm/mips-boards/sead.h>
+#include <asm/mips-boards/seadint.h>
+#include <asm/time.h>
+
+extern void mips_reboot_setup(void);
+extern void mips_time_init(void);
+extern void mips_timer_setup(struct irqaction *irq);
+
+static void __init serial_init(void);
+
+const char *get_system_type(void)
+{
+ return "MIPS SEAD";
+}
+
+static void __init sead_setup(void)
+{
+ ioport_resource.end = 0x7fffffff;
+
+ serial_init ();
+
+ board_time_init = mips_time_init;
+ board_timer_setup = mips_timer_setup;
+
+ mips_reboot_setup();
+}
+
+early_initcall(sead_setup);
+
+static void __init serial_init(void)
+{
+#ifdef CONFIG_SERIAL_8250
+ struct uart_port s;
+
+ memset(&s, 0, sizeof(s));
+
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+ s.iobase = SEAD_UART0_REGS_BASE;
+#else
+ s.iobase = SEAD_UART0_REGS_BASE+3;
+#endif
+ s.irq = SEADINT_UART0;
+ s.uartclk = SEAD_BASE_BAUD * 16;
+ s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
+ s.iotype = 0;
+ s.regshift = 3;
+
+ if (early_serial_setup(&s) != 0) {
+ printk(KERN_ERR "Serial setup failed!\n");
+ }
+#endif
+}