aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/cobalt
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2005-02-21 11:18:36 -0500
committerRalf Baechle <ralf@linux-mips.org>2005-10-29 14:30:42 -0400
commitc4ed38a0c6e2e5c4906296758f816ee71373792f (patch)
tree65ebab9ca61ea6d03109c53acd2989b626dce52a /arch/mips/cobalt
parent049b13c358f0187cf3c5003d5fb9848dbcb28bc3 (diff)
Resurrect Cobalt support for 2.6.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/cobalt')
-rw-r--r--arch/mips/cobalt/Makefile2
-rw-r--r--arch/mips/cobalt/int-handler.S4
-rw-r--r--arch/mips/cobalt/irq.c111
-rw-r--r--arch/mips/cobalt/promcon.c87
-rw-r--r--arch/mips/cobalt/reset.c59
-rw-r--r--arch/mips/cobalt/setup.c100
6 files changed, 175 insertions, 188 deletions
diff --git a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile
index a5e6554b2326..3b6b7579d1de 100644
--- a/arch/mips/cobalt/Makefile
+++ b/arch/mips/cobalt/Makefile
@@ -2,6 +2,6 @@
2# Makefile for the Cobalt micro systems family specific parts of the kernel 2# Makefile for the Cobalt micro systems family specific parts of the kernel
3# 3#
4 4
5obj-y := irq.o int-handler.o reset.o setup.o promcon.o 5obj-y := irq.o int-handler.o reset.o setup.o
6 6
7EXTRA_AFLAGS := $(CFLAGS) 7EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/cobalt/int-handler.S b/arch/mips/cobalt/int-handler.S
index 1a21dec1b3ca..f92608e8d84f 100644
--- a/arch/mips/cobalt/int-handler.S
+++ b/arch/mips/cobalt/int-handler.S
@@ -18,8 +18,8 @@
18 SAVE_ALL 18 SAVE_ALL
19 CLI 19 CLI
20 20
21 la ra, ret_from_irq 21 PTR_LA ra, ret_from_irq
22 move a1, sp 22 move a0, sp
23 j cobalt_irq 23 j cobalt_irq
24 24
25 END(cobalt_handle_int) 25 END(cobalt_handle_int)
diff --git a/arch/mips/cobalt/irq.c b/arch/mips/cobalt/irq.c
index 6d2a81581397..0d90851f925e 100644
--- a/arch/mips/cobalt/irq.c
+++ b/arch/mips/cobalt/irq.c
@@ -10,6 +10,8 @@
10#include <linux/kernel.h> 10#include <linux/kernel.h>
11#include <linux/init.h> 11#include <linux/init.h>
12#include <linux/irq.h> 12#include <linux/irq.h>
13#include <linux/interrupt.h>
14#include <linux/pci.h>
13 15
14#include <asm/i8259.h> 16#include <asm/i8259.h>
15#include <asm/irq_cpu.h> 17#include <asm/irq_cpu.h>
@@ -25,8 +27,8 @@ extern void cobalt_handle_int(void);
25 * the CPU interrupt lines, and ones that come in on the via chip. The CPU 27 * the CPU interrupt lines, and ones that come in on the via chip. The CPU
26 * mappings are: 28 * mappings are:
27 * 29 *
28 * 16, - Software interrupt 0 (unused) IE_SW0 30 * 16 - Software interrupt 0 (unused) IE_SW0
29 * 17 - Software interrupt 1 (unused) IE_SW0 31 * 17 - Software interrupt 1 (unused) IE_SW1
30 * 18 - Galileo chip (timer) IE_IRQ0 32 * 18 - Galileo chip (timer) IE_IRQ0
31 * 19 - Tulip 0 + NCR SCSI IE_IRQ1 33 * 19 - Tulip 0 + NCR SCSI IE_IRQ1
32 * 20 - Tulip 1 IE_IRQ2 34 * 20 - Tulip 1 IE_IRQ2
@@ -42,61 +44,94 @@ extern void cobalt_handle_int(void);
42 * 15 - IDE1 44 * 15 - IDE1
43 */ 45 */
44 46
45asmlinkage void cobalt_irq(struct pt_regs *regs) 47static inline void galileo_irq(struct pt_regs *regs)
46{ 48{
47 unsigned int pending = read_c0_status() & read_c0_cause(); 49 unsigned int mask, pending, devfn;
48
49 if (pending & CAUSEF_IP2) { /* int 18 */
50 unsigned long irq_src = GALILEO_INL(GT_INTRCAUSE_OFS);
51
52 /* Check for timer irq ... */
53 if (irq_src & GALILEO_T0EXP) {
54 /* Clear the int line */
55 GALILEO_OUTL(0, GT_INTRCAUSE_OFS);
56 do_IRQ(COBALT_TIMER_IRQ, regs);
57 }
58 return;
59 }
60 50
61 if (pending & CAUSEF_IP6) { /* int 22 */ 51 mask = GALILEO_INL(GT_INTRMASK_OFS);
62 int irq = i8259_irq(); 52 pending = GALILEO_INL(GT_INTRCAUSE_OFS) & mask;
63 53
64 if (irq >= 0) 54 if (pending & GALILEO_INTR_T0EXP) {
65 do_IRQ(irq, regs);
66 return;
67 }
68 55
69 if (pending & CAUSEF_IP3) { /* int 19 */ 56 GALILEO_OUTL(~GALILEO_INTR_T0EXP, GT_INTRCAUSE_OFS);
70 do_IRQ(COBALT_ETH0_IRQ, regs); 57 do_IRQ(COBALT_GALILEO_IRQ, regs);
71 return;
72 }
73 58
74 if (pending & CAUSEF_IP4) { /* int 20 */ 59 } else if (pending & GALILEO_INTR_RETRY_CTR) {
75 do_IRQ(COBALT_ETH1_IRQ, regs);
76 return;
77 }
78 60
79 if (pending & CAUSEF_IP5) { /* int 21 */ 61 devfn = GALILEO_INL(GT_PCI0_CFGADDR_OFS) >> 8;
80 do_IRQ(COBALT_SERIAL_IRQ, regs); 62 GALILEO_OUTL(~GALILEO_INTR_RETRY_CTR, GT_INTRCAUSE_OFS);
81 return; 63 printk(KERN_WARNING "Galileo: PCI retry count exceeded (%02x.%u)\n",
82 } 64 PCI_SLOT(devfn), PCI_FUNC(devfn));
65
66 } else {
83 67
84 if (pending & CAUSEF_IP7) { /* int 23 */ 68 GALILEO_OUTL(mask & ~pending, GT_INTRMASK_OFS);
85 do_IRQ(COBALT_QUBE_SLOT_IRQ, regs); 69 printk(KERN_WARNING "Galileo: masking unexpected interrupt %08x\n", pending);
86 return;
87 } 70 }
88} 71}
89 72
73static inline void via_pic_irq(struct pt_regs *regs)
74{
75 int irq;
76
77 irq = i8259_irq();
78 if (irq >= 0)
79 do_IRQ(irq, regs);
80}
81
82asmlinkage void cobalt_irq(struct pt_regs *regs)
83{
84 unsigned pending;
85
86 pending = read_c0_status() & read_c0_cause();
87
88 if (pending & CAUSEF_IP2) /* COBALT_GALILEO_IRQ (18) */
89
90 galileo_irq(regs);
91
92 else if (pending & CAUSEF_IP6) /* COBALT_VIA_IRQ (22) */
93
94 via_pic_irq(regs);
95
96 else if (pending & CAUSEF_IP3) /* COBALT_ETH0_IRQ (19) */
97
98 do_IRQ(COBALT_CPU_IRQ + 3, regs);
99
100 else if (pending & CAUSEF_IP4) /* COBALT_ETH1_IRQ (20) */
101
102 do_IRQ(COBALT_CPU_IRQ + 4, regs);
103
104 else if (pending & CAUSEF_IP5) /* COBALT_SERIAL_IRQ (21) */
105
106 do_IRQ(COBALT_CPU_IRQ + 5, regs);
107
108 else if (pending & CAUSEF_IP7) /* IRQ 23 */
109
110 do_IRQ(COBALT_CPU_IRQ + 7, regs);
111}
112
113static struct irqaction irq_via = {
114 no_action, 0, { { 0, } }, "cascade", NULL, NULL
115};
116
90void __init arch_init_irq(void) 117void __init arch_init_irq(void)
91{ 118{
119 /*
120 * Mask all Galileo interrupts. The Galileo
121 * handler is set in cobalt_timer_setup()
122 */
123 GALILEO_OUTL(0, GT_INTRMASK_OFS);
124
92 set_except_vector(0, cobalt_handle_int); 125 set_except_vector(0, cobalt_handle_int);
93 126
94 init_i8259_irqs(); /* 0 ... 15 */ 127 init_i8259_irqs(); /* 0 ... 15 */
95 mips_cpu_irq_init(16); /* 16 ... 23 */ 128 mips_cpu_irq_init(COBALT_CPU_IRQ); /* 16 ... 23 */
96 129
97 /* 130 /*
98 * Mask all cpu interrupts 131 * Mask all cpu interrupts
99 * (except IE4, we already masked those at VIA level) 132 * (except IE4, we already masked those at VIA level)
100 */ 133 */
101 change_c0_status(ST0_IM, IE_IRQ4); 134 change_c0_status(ST0_IM, IE_IRQ4);
135
136 setup_irq(COBALT_VIA_IRQ, &irq_via);
102} 137}
diff --git a/arch/mips/cobalt/promcon.c b/arch/mips/cobalt/promcon.c
deleted file mode 100644
index f03df761e9f1..000000000000
--- a/arch/mips/cobalt/promcon.c
+++ /dev/null
@@ -1,87 +0,0 @@
1/*
2 * PROM console for Cobalt Raq2
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
9 * Copyright (C) 2001 by Liam Davies (ldavies@agile.tv)
10 *
11 */
12
13#include <linux/init.h>
14#include <linux/console.h>
15#include <linux/kdev_t.h>
16#include <linux/serial_reg.h>
17
18#include <asm/delay.h>
19#include <asm/serial.h>
20#include <asm/io.h>
21
22static unsigned long port = 0xc800000;
23
24static __inline__ void ns16550_cons_put_char(char ch, unsigned long ioaddr)
25{
26 char lsr;
27
28 do {
29 lsr = inb(ioaddr + UART_LSR);
30 } while ((lsr & (UART_LSR_TEMT | UART_LSR_THRE)) != (UART_LSR_TEMT | UART_LSR_THRE));
31 outb(ch, ioaddr + UART_TX);
32}
33
34static __inline__ char ns16550_cons_get_char(unsigned long ioaddr)
35{
36 while ((inb(ioaddr + UART_LSR) & UART_LSR_DR) == 0)
37 udelay(1);
38 return inb(ioaddr + UART_RX);
39}
40
41void ns16550_console_write(struct console *co, const char *s, unsigned count)
42{
43 char lsr, ier;
44 unsigned i;
45
46 ier = inb(port + UART_IER);
47 outb(0x00, port + UART_IER);
48 for (i=0; i < count; i++, s++) {
49
50 if(*s == '\n')
51 ns16550_cons_put_char('\r', port);
52 ns16550_cons_put_char(*s, port);
53 }
54
55 do {
56 lsr = inb(port + UART_LSR);
57 } while ((lsr & (UART_LSR_TEMT | UART_LSR_THRE)) != (UART_LSR_TEMT | UART_LSR_THRE));
58
59 outb(ier, port + UART_IER);
60}
61
62char getDebugChar(void)
63{
64 return ns16550_cons_get_char(port);
65}
66
67void putDebugChar(char kgdb_char)
68{
69 ns16550_cons_put_char(kgdb_char, port);
70}
71
72static struct console ns16550_console = {
73 .name = "prom",
74 .setup = NULL,
75 .write = ns16550_console_write,
76 .flags = CON_PRINTBUFFER,
77 .index = -1,
78};
79
80static int __init ns16550_setup_console(void)
81{
82 register_console(&ns16550_console);
83
84 return 0;
85}
86
87console_initcall(ns16550_setup_console);
diff --git a/arch/mips/cobalt/reset.c b/arch/mips/cobalt/reset.c
index 084c8e59f42c..805a0e88507b 100644
--- a/arch/mips/cobalt/reset.c
+++ b/arch/mips/cobalt/reset.c
@@ -16,48 +16,45 @@
16#include <asm/reboot.h> 16#include <asm/reboot.h>
17#include <asm/system.h> 17#include <asm/system.h>
18#include <asm/mipsregs.h> 18#include <asm/mipsregs.h>
19#include <asm/cobalt/cobalt.h>
19 20
20void cobalt_machine_restart(char *command) 21void cobalt_machine_halt(void)
21{ 22{
22 *(volatile char *)0xbc000000 = 0x0f; 23 int state, last, diff;
24 unsigned long mark;
23 25
24 /* 26 /*
25 * Ouch, we're still alive ... This time we take the silver bullet ... 27 * turn off bar on Qube, flash power off LED on RaQ (0.5Hz)
26 * ... and find that we leave the hardware in a state in which the 28 *
27 * kernel in the flush locks up somewhen during of after the PCI 29 * restart if ENTER and SELECT are pressed
28 * detection stuff.
29 */ 30 */
30 set_c0_status(ST0_BEV | ST0_ERL);
31 change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
32 flush_cache_all();
33 write_c0_wired(0);
34 __asm__ __volatile__(
35 "jr\t%0"
36 :
37 : "r" (0xbfc00000));
38}
39 31
40extern int led_state; 32 last = COBALT_KEY_PORT;
41#define kLED 0xBC000000
42#define LEDSet(x) (*(volatile unsigned char *) kLED) = (( unsigned char)x)
43 33
44void cobalt_machine_halt(void) 34 for (state = 0;;) {
45{ 35
46 int mark; 36 state ^= COBALT_LED_POWER_OFF;
37 COBALT_LED_PORT = state;
38
39 diff = COBALT_KEY_PORT ^ last;
40 last ^= diff;
47 41
48 /* Blink our cute? little LED (number 3)... */ 42 if((diff & (COBALT_KEY_ENTER | COBALT_KEY_SELECT)) && !(~last & (COBALT_KEY_ENTER | COBALT_KEY_SELECT)))
49 while (1) { 43 COBALT_LED_PORT = COBALT_LED_RESET;
50 led_state = led_state | ( 1 << 3 ); 44
51 LEDSet(led_state); 45 for (mark = jiffies; jiffies - mark < HZ;)
52 mark = jiffies; 46 ;
53 while (jiffies<(mark+HZ));
54 led_state = led_state & ~( 1 << 3 );
55 LEDSet(led_state);
56 mark = jiffies;
57 while (jiffies<(mark+HZ));
58 } 47 }
59} 48}
60 49
50void cobalt_machine_restart(char *command)
51{
52 COBALT_LED_PORT = COBALT_LED_RESET;
53
54 /* we should never get here */
55 cobalt_machine_halt();
56}
57
61/* 58/*
62 * This triggers the luser mode device driver for the power switch ;-) 59 * This triggers the luser mode device driver for the power switch ;-)
63 */ 60 */
diff --git a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c
index f8138c15a535..d358a118fa31 100644
--- a/arch/mips/cobalt/setup.c
+++ b/arch/mips/cobalt/setup.c
@@ -13,6 +13,8 @@
13#include <linux/interrupt.h> 13#include <linux/interrupt.h>
14#include <linux/pci.h> 14#include <linux/pci.h>
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/serial.h>
17#include <linux/serial_core.h>
16 18
17#include <asm/bootinfo.h> 19#include <asm/bootinfo.h>
18#include <asm/time.h> 20#include <asm/time.h>
@@ -21,6 +23,7 @@
21#include <asm/processor.h> 23#include <asm/processor.h>
22#include <asm/reboot.h> 24#include <asm/reboot.h>
23#include <asm/gt64120.h> 25#include <asm/gt64120.h>
26#include <asm/serial.h>
24 27
25#include <asm/cobalt/cobalt.h> 28#include <asm/cobalt/cobalt.h>
26 29
@@ -30,45 +33,44 @@ extern void cobalt_machine_power_off(void);
30 33
31int cobalt_board_id; 34int cobalt_board_id;
32 35
33static char my_cmdline[CL_SIZE] = {
34 "console=ttyS0,115200 "
35#ifdef CONFIG_IP_PNP
36 "ip=on "
37#endif
38#ifdef CONFIG_ROOT_NFS
39 "root=/dev/nfs "
40#else
41 "root=/dev/hda1 "
42#endif
43 };
44
45const char *get_system_type(void) 36const char *get_system_type(void)
46{ 37{
38 switch (cobalt_board_id) {
39 case COBALT_BRD_ID_QUBE1:
40 return "Cobalt Qube";
41 case COBALT_BRD_ID_RAQ1:
42 return "Cobalt RaQ";
43 case COBALT_BRD_ID_QUBE2:
44 return "Cobalt Qube2";
45 case COBALT_BRD_ID_RAQ2:
46 return "Cobalt RaQ2";
47 }
47 return "MIPS Cobalt"; 48 return "MIPS Cobalt";
48} 49}
49 50
50static void __init cobalt_timer_setup(struct irqaction *irq) 51static void __init cobalt_timer_setup(struct irqaction *irq)
51{ 52{
52 /* Load timer value for 150 Hz */ 53 /* Load timer value for 1KHz (TCLK is 50MHz) */
53 GALILEO_OUTL(500000, GT_TC0_OFS); 54 GALILEO_OUTL(50*1000*1000 / 1000, GT_TC0_OFS);
54 55
55 /* Register our timer interrupt */ 56 /* Enable timer */
56 setup_irq(COBALT_TIMER_IRQ, irq); 57 GALILEO_OUTL(GALILEO_ENTC0 | GALILEO_SELTC0, GT_TC_CONTROL_OFS);
57 58
58 /* Enable timer ints */ 59 /* Register interrupt */
59 GALILEO_OUTL((GALILEO_ENTC0 | GALILEO_SELTC0), GT_TC_CONTROL_OFS); 60 setup_irq(COBALT_GALILEO_IRQ, irq);
60 /* Unmask timer int */ 61
61 GALILEO_OUTL(0x100, GT_INTRMASK_OFS); 62 /* Enable interrupt */
63 GALILEO_OUTL(GALILEO_INTR_T0EXP | GALILEO_INL(GT_INTRMASK_OFS), GT_INTRMASK_OFS);
62} 64}
63 65
64extern struct pci_ops gt64111_pci_ops; 66extern struct pci_ops gt64111_pci_ops;
65 67
66static struct resource cobalt_mem_resource = { 68static struct resource cobalt_mem_resource = {
67 "GT64111 PCI MEM", GT64111_IO_BASE, 0xffffffffUL, IORESOURCE_MEM 69 "PCI memory", GT64111_MEM_BASE, GT64111_MEM_END, IORESOURCE_MEM
68}; 70};
69 71
70static struct resource cobalt_io_resource = { 72static struct resource cobalt_io_resource = {
71 "GT64111 IO MEM", 0x00001000UL, 0x0fffffffUL, IORESOURCE_IO 73 "PCI I/O", 0x1000, 0xffff, IORESOURCE_IO
72}; 74};
73 75
74static struct resource cobalt_io_resources[] = { 76static struct resource cobalt_io_resources[] = {
@@ -86,11 +88,12 @@ static struct pci_controller cobalt_pci_controller = {
86 .mem_resource = &cobalt_mem_resource, 88 .mem_resource = &cobalt_mem_resource,
87 .mem_offset = 0, 89 .mem_offset = 0,
88 .io_resource = &cobalt_io_resource, 90 .io_resource = &cobalt_io_resource,
89 .io_offset = 0x00001000UL - GT64111_IO_BASE 91 .io_offset = 0 - GT64111_IO_BASE
90}; 92};
91 93
92void __init plat_setup(void) 94void __init plat_setup(void)
93{ 95{
96 static struct uart_port uart;
94 unsigned int devfn = PCI_DEVFN(COBALT_PCICONF_VIA, 0); 97 unsigned int devfn = PCI_DEVFN(COBALT_PCICONF_VIA, 0);
95 int i; 98 int i;
96 99
@@ -100,7 +103,10 @@ void __init plat_setup(void)
100 103
101 board_timer_setup = cobalt_timer_setup; 104 board_timer_setup = cobalt_timer_setup;
102 105
103 set_io_port_base(KSEG1ADDR(GT64111_IO_BASE)); 106 set_io_port_base(CKSEG1ADDR(GT64111_IO_BASE));
107
108 /* I/O port resource must include UART and LCD/buttons */
109 ioport_resource.end = 0x0fffffff;
104 110
105 /* 111 /*
106 * This is a prom style console. We just poke at the 112 * This is a prom style console. We just poke at the
@@ -120,25 +126,61 @@ void __init plat_setup(void)
120 cobalt_board_id >>= ((VIA_COBALT_BRD_ID_REG & 3) * 8); 126 cobalt_board_id >>= ((VIA_COBALT_BRD_ID_REG & 3) * 8);
121 cobalt_board_id = VIA_COBALT_BRD_REG_to_ID(cobalt_board_id); 127 cobalt_board_id = VIA_COBALT_BRD_REG_to_ID(cobalt_board_id);
122 128
129 printk("Cobalt board ID: %d\n", cobalt_board_id);
130
123#ifdef CONFIG_PCI 131#ifdef CONFIG_PCI
124 register_pci_controller(&cobalt_pci_controller); 132 register_pci_controller(&cobalt_pci_controller);
125#endif 133#endif
134
135#ifdef CONFIG_SERIAL_8250
136 if (cobalt_board_id > COBALT_BRD_ID_RAQ1) {
137
138 uart.line = 0;
139 uart.type = PORT_UNKNOWN;
140 uart.uartclk = 18432000;
141 uart.irq = COBALT_SERIAL_IRQ;
142 uart.flags = STD_COM_FLAGS;
143 uart.iobase = 0xc800000;
144 uart.iotype = UPIO_PORT;
145
146 early_serial_setup(&uart);
147 }
148#endif
126} 149}
127 150
128/* 151/*
129 * Prom init. We read our one and only communication with the firmware. 152 * Prom init. We read our one and only communication with the firmware.
130 * Grab the amount of installed memory 153 * Grab the amount of installed memory.
154 * Better boot loaders (CoLo) pass a command line too :-)
131 */ 155 */
132 156
133void __init prom_init(void) 157void __init prom_init(void)
134{ 158{
135 int argc = fw_arg0; 159 int narg, indx, posn, nchr;
136 160 unsigned long memsz;
137 strcpy(arcs_cmdline, my_cmdline); 161 char **argv;
138 162
139 mips_machgroup = MACH_GROUP_COBALT; 163 mips_machgroup = MACH_GROUP_COBALT;
140 164
141 add_memory_region(0x0, argc & 0x7fffffff, BOOT_MEM_RAM); 165 memsz = fw_arg0 & 0x7fff0000;
166 narg = fw_arg0 & 0x0000ffff;
167
168 if (narg) {
169 arcs_cmdline[0] = '\0';
170 argv = (char **) fw_arg1;
171 posn = 0;
172 for (indx = 1; indx < narg; ++indx) {
173 nchr = strlen(argv[indx]);
174 if (posn + 1 + nchr + 1 > sizeof(arcs_cmdline))
175 break;
176 if (posn)
177 arcs_cmdline[posn++] = ' ';
178 strcpy(arcs_cmdline + posn, argv[indx]);
179 posn += nchr;
180 }
181 }
182
183 add_memory_region(0x0, memsz, BOOT_MEM_RAM);
142} 184}
143 185
144unsigned long __init prom_free_prom_memory(void) 186unsigned long __init prom_free_prom_memory(void)