summary refs log tree commit diff
path: root/arch/mips/cobalt
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/mips/cobalt
downloadlinux-1da177e4c3f41524e886b7f1b8a0c1fc7321cac2.tar.gz
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
Diffstat (limited to 'arch/mips/cobalt')
-rw-r--r--arch/mips/cobalt/Makefile7
-rw-r--r--arch/mips/cobalt/int-handler.S25
-rw-r--r--arch/mips/cobalt/irq.c102
-rw-r--r--arch/mips/cobalt/promcon.c87
-rw-r--r--arch/mips/cobalt/reset.c68
-rw-r--r--arch/mips/cobalt/setup.c150
6 files changed, 439 insertions, 0 deletions
diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
new file mode 100644
index 000000000000..a5e6554b2326
--- /dev/null
+++ b/arch/mips/cobalt/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the Cobalt micro systems family specific parts of the kernel
+#
+
+obj-y	 := irq.o int-handler.o reset.o setup.o promcon.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/cobalt/int-handler.S b/arch/mips/cobalt/int-handler.S
new file mode 100644
index 000000000000..1a21dec1b3ca
--- /dev/null
+++ b/arch/mips/cobalt/int-handler.S
@@ -0,0 +1,25 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle
+ * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
+ */
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/cobalt/cobalt.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+
+		.text
+		.align	5
+		NESTED(cobalt_handle_int, PT_SIZE, sp)
+		SAVE_ALL
+		CLI
+
+		la	ra, ret_from_irq
+		move	a1, sp
+		j	cobalt_irq
+
+		END(cobalt_handle_int)
diff --git a/arch/mips/cobalt/irq.c b/arch/mips/cobalt/irq.c
new file mode 100644
index 000000000000..6d2a81581397
--- /dev/null
+++ b/arch/mips/cobalt/irq.c
@@ -0,0 +1,102 @@
+/*
+ * IRQ vector handles
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/i8259.h>
+#include <asm/irq_cpu.h>
+#include <asm/gt64120.h>
+#include <asm/ptrace.h>
+
+#include <asm/cobalt/cobalt.h>
+
+extern void cobalt_handle_int(void);
+
+/*
+ * We have two types of interrupts that we handle, ones that come in through
+ * the CPU interrupt lines, and ones that come in on the via chip. The CPU
+ * mappings are:
+ *
+ *    16,  - Software interrupt 0 (unused)	IE_SW0
+ *    17   - Software interrupt 1 (unused)	IE_SW0
+ *    18   - Galileo chip (timer)		IE_IRQ0
+ *    19   - Tulip 0 + NCR SCSI			IE_IRQ1
+ *    20   - Tulip 1				IE_IRQ2
+ *    21   - 16550 UART				IE_IRQ3
+ *    22   - VIA southbridge PIC		IE_IRQ4
+ *    23   - unused				IE_IRQ5
+ *
+ * The VIA chip is a master/slave 8259 setup and has the following interrupts:
+ *
+ *     8  - RTC
+ *     9  - PCI
+ *    14  - IDE0
+ *    15  - IDE1
+ */
+
+asmlinkage void cobalt_irq(struct pt_regs *regs)
+{
+	unsigned int pending = read_c0_status() & read_c0_cause();
+
+	if (pending & CAUSEF_IP2) {			/* int 18 */
+		unsigned long irq_src = GALILEO_INL(GT_INTRCAUSE_OFS);
+
+		/* Check for timer irq ... */
+		if (irq_src & GALILEO_T0EXP) {
+			/* Clear the int line */
+			GALILEO_OUTL(0, GT_INTRCAUSE_OFS);
+			do_IRQ(COBALT_TIMER_IRQ, regs);
+		}
+		return;
+	}
+
+	if (pending & CAUSEF_IP6) {			/* int 22 */
+		int irq = i8259_irq();
+
+		if (irq >= 0)
+			do_IRQ(irq, regs);
+		return;
+	}
+
+	if (pending & CAUSEF_IP3) {			/* int 19 */
+		do_IRQ(COBALT_ETH0_IRQ, regs);
+		return;
+	}
+
+	if (pending & CAUSEF_IP4) {			/* int 20 */
+		do_IRQ(COBALT_ETH1_IRQ, regs);
+		return;
+	}
+
+	if (pending & CAUSEF_IP5) {			/* int 21 */
+		do_IRQ(COBALT_SERIAL_IRQ, regs);
+		return;
+	}
+
+	if (pending & CAUSEF_IP7) {			/* int 23 */
+		do_IRQ(COBALT_QUBE_SLOT_IRQ, regs);
+		return;
+	}
+}
+
+void __init arch_init_irq(void)
+{
+	set_except_vector(0, cobalt_handle_int);
+
+	init_i8259_irqs();				/*  0 ... 15 */
+	mips_cpu_irq_init(16);				/* 16 ... 23 */
+
+	/*
+	 * Mask all cpu interrupts
+	 *  (except IE4, we already masked those at VIA level)
+	 */
+	change_c0_status(ST0_IM, IE_IRQ4);
+}
diff --git a/arch/mips/cobalt/promcon.c b/arch/mips/cobalt/promcon.c
new file mode 100644
index 000000000000..f03df761e9f1
--- /dev/null
+++ b/arch/mips/cobalt/promcon.c
@@ -0,0 +1,87 @@
+/*
+ * PROM console for Cobalt Raq2
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
+ * Copyright (C) 2001 by Liam Davies (ldavies@agile.tv)
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/kdev_t.h>
+#include <linux/serial_reg.h>
+
+#include <asm/delay.h>
+#include <asm/serial.h>
+#include <asm/io.h>
+
+static unsigned long port = 0xc800000;
+
+static __inline__ void ns16550_cons_put_char(char ch, unsigned long ioaddr)
+{
+	char lsr;
+
+	do {
+		lsr = inb(ioaddr + UART_LSR);
+	} while ((lsr & (UART_LSR_TEMT | UART_LSR_THRE)) != (UART_LSR_TEMT | UART_LSR_THRE));
+	outb(ch, ioaddr + UART_TX);
+}
+
+static __inline__ char ns16550_cons_get_char(unsigned long ioaddr)
+{
+	while ((inb(ioaddr + UART_LSR) & UART_LSR_DR) == 0)
+		udelay(1);
+	return inb(ioaddr + UART_RX);
+}
+
+void ns16550_console_write(struct console *co, const char *s, unsigned count)
+{
+	char lsr, ier;
+	unsigned i;
+
+	ier = inb(port + UART_IER);
+	outb(0x00, port + UART_IER);
+	for (i=0; i < count; i++, s++) {
+
+		if(*s == '\n')
+			ns16550_cons_put_char('\r', port);
+		ns16550_cons_put_char(*s, port);
+	}
+
+	do {
+		lsr = inb(port + UART_LSR);
+   	} while ((lsr & (UART_LSR_TEMT | UART_LSR_THRE)) != (UART_LSR_TEMT | UART_LSR_THRE));
+
+	outb(ier, port + UART_IER);
+}
+
+char getDebugChar(void)
+{
+	return ns16550_cons_get_char(port);
+}
+
+void putDebugChar(char kgdb_char)
+{
+	ns16550_cons_put_char(kgdb_char, port);
+}
+
+static struct console ns16550_console = {
+    .name	= "prom",
+    .setup	= NULL,
+    .write	= ns16550_console_write,
+    .flags	= CON_PRINTBUFFER,
+    .index	= -1,
+};
+
+static int __init ns16550_setup_console(void)
+{
+	register_console(&ns16550_console);
+
+	return 0;
+}
+
+console_initcall(ns16550_setup_console);
diff --git a/arch/mips/cobalt/reset.c b/arch/mips/cobalt/reset.c
new file mode 100644
index 000000000000..084c8e59f42c
--- /dev/null
+++ b/arch/mips/cobalt/reset.c
@@ -0,0 +1,68 @@
+/*
+ * Cobalt Reset operations
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
+ * Copyright (C) 2001 by Liam Davies (ldavies@agile.tv)
+ */
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/system.h>
+#include <asm/mipsregs.h>
+
+void cobalt_machine_restart(char *command)
+{
+	*(volatile char *)0xbc000000 = 0x0f;
+
+	/*
+	 * Ouch, we're still alive ... This time we take the silver bullet ...
+	 * ... and find that we leave the hardware in a state in which the
+	 * kernel in the flush locks up somewhen during of after the PCI
+	 * detection stuff.
+	 */
+	set_c0_status(ST0_BEV | ST0_ERL);
+	change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
+	flush_cache_all();
+	write_c0_wired(0);
+	__asm__ __volatile__(
+		"jr\t%0"
+		:
+		: "r" (0xbfc00000));
+}
+
+extern int led_state;
+#define kLED            0xBC000000
+#define LEDSet(x)       (*(volatile unsigned char *) kLED) = (( unsigned char)x)
+
+void cobalt_machine_halt(void)
+{
+	int mark;
+
+	/* Blink our cute? little LED (number 3)... */
+	while (1) {
+		led_state = led_state | ( 1 << 3 );
+		LEDSet(led_state);
+		mark = jiffies;
+		while (jiffies<(mark+HZ));
+		led_state = led_state & ~( 1 << 3 );
+		LEDSet(led_state);
+		mark = jiffies;
+		while (jiffies<(mark+HZ));
+	}
+}
+
+/*
+ * This triggers the luser mode device driver for the power switch ;-)
+ */
+void cobalt_machine_power_off(void)
+{
+	printk("You can switch the machine off now.\n");
+	cobalt_machine_halt();
+}
diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c
new file mode 100644
index 000000000000..6b4737e425ed
--- /dev/null
+++ b/arch/mips/cobalt/setup.c
@@ -0,0 +1,150 @@
+/*
+ * Setup pointers to hardware dependent routines.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1996, 1997, 2004 by Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv)
+ *
+ */
+#include <linux/config.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/bootinfo.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/processor.h>
+#include <asm/reboot.h>
+#include <asm/gt64120.h>
+
+#include <asm/cobalt/cobalt.h>
+
+extern void cobalt_machine_restart(char *command);
+extern void cobalt_machine_halt(void);
+extern void cobalt_machine_power_off(void);
+
+int cobalt_board_id;
+
+static char my_cmdline[CL_SIZE] = {
+ "console=ttyS0,115200 "
+#ifdef CONFIG_IP_PNP
+ "ip=on "
+#endif
+#ifdef CONFIG_ROOT_NFS
+ "root=/dev/nfs "
+#else
+ "root=/dev/hda1 "
+#endif
+ };
+
+const char *get_system_type(void)
+{
+	return "MIPS Cobalt";
+}
+
+static void __init cobalt_timer_setup(struct irqaction *irq)
+{
+	/* Load timer value for 150 Hz */
+	GALILEO_OUTL(500000, GT_TC0_OFS);
+
+	/* Register our timer interrupt */
+	setup_irq(COBALT_TIMER_IRQ, irq);
+
+	/* Enable timer ints */
+	GALILEO_OUTL((GALILEO_ENTC0 | GALILEO_SELTC0), GT_TC_CONTROL_OFS);
+	/* Unmask timer int */
+	GALILEO_OUTL(0x100, GT_INTRMASK_OFS);
+}
+
+extern struct pci_ops gt64111_pci_ops;
+
+static struct resource cobalt_mem_resource = {
+	"GT64111 PCI MEM", GT64111_IO_BASE, 0xffffffffUL, IORESOURCE_MEM
+};
+
+static struct resource cobalt_io_resource = {
+	"GT64111 IO MEM", 0x00001000UL, 0x0fffffffUL, IORESOURCE_IO
+};
+
+static struct resource cobalt_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 },
+};
+
+#define COBALT_IO_RESOURCES (sizeof(cobalt_io_resources)/sizeof(struct resource))
+
+static struct pci_controller cobalt_pci_controller = {
+	.pci_ops	= &gt64111_pci_ops,
+	.mem_resource	= &cobalt_mem_resource,
+	.mem_offset	= 0,
+	.io_resource	= &cobalt_io_resource,
+	.io_offset	= 0x00001000UL - GT64111_IO_BASE
+};
+
+static void __init cobalt_setup(void)
+{
+	unsigned int devfn = PCI_DEVFN(COBALT_PCICONF_VIA, 0);
+	int i;
+
+	_machine_restart = cobalt_machine_restart;
+	_machine_halt = cobalt_machine_halt;
+	_machine_power_off = cobalt_machine_power_off;
+
+	board_timer_setup = cobalt_timer_setup;
+
+        set_io_port_base(KSEG1ADDR(GT64111_IO_BASE));
+
+	/*
+	 * This is a prom style console. We just poke at the
+	 *  UART to make it talk.
+	 * Only use this console if you really screw up and can't
+	 *  get to the stage of setting up a real serial console.
+	 */
+	/*ns16550_setup_console();*/
+
+	/* request I/O space for devices used on all i[345]86 PCs */
+	for (i = 0; i < COBALT_IO_RESOURCES; i++)
+		request_resource(&ioport_resource, cobalt_io_resources + i);
+
+        /* Read the cobalt id register out of the PCI config space */
+        PCI_CFG_SET(devfn, (VIA_COBALT_BRD_ID_REG & ~0x3));
+        cobalt_board_id = GALILEO_INL(GT_PCI0_CFGDATA_OFS);
+        cobalt_board_id >>= ((VIA_COBALT_BRD_ID_REG & 3) * 8);
+        cobalt_board_id = VIA_COBALT_BRD_REG_to_ID(cobalt_board_id);
+
+#ifdef CONFIG_PCI
+	register_pci_controller(&cobalt_pci_controller);
+#endif
+}
+
+early_initcall(cobalt_setup);
+
+/*
+ * Prom init. We read our one and only communication with the firmware.
+ * Grab the amount of installed memory
+ */
+
+void __init prom_init(void)
+{
+	int argc = fw_arg0;
+
+	strcpy(arcs_cmdline, my_cmdline);
+
+	mips_machgroup = MACH_GROUP_COBALT;
+
+	add_memory_region(0x0, argc & 0x7fffffff, BOOT_MEM_RAM);
+}
+
+unsigned long __init prom_free_prom_memory(void)
+{
+	/* Nothing to do! */
+	return 0;
+}