aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/mips-boards/generic
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/mips-boards/generic')
-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
11 files changed, 1408 insertions, 0 deletions
diff --git a/arch/mips/mips-boards/generic/Makefile b/arch/mips/mips-boards/generic/Makefile
new file mode 100644
index 000000000000..b21bc6887fa8
--- /dev/null
+++ b/arch/mips/mips-boards/generic/Makefile
@@ -0,0 +1,26 @@
1#
2# Carsten Langgaard, carstenl@mips.com
3# Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
4#
5# This program is free software; you can distribute it and/or modify it
6# under the terms of the GNU General Public License (Version 2) as
7# published by the Free Software Foundation.
8#
9# This program is distributed in the hope it will be useful, but WITHOUT
10# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12# for more details.
13#
14# You should have received a copy of the GNU General Public License along
15# with this program; if not, write to the Free Software Foundation, Inc.,
16# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
17#
18# Makefile for the MIPS boards generic routines under Linux.
19#
20
21obj-y := mipsIRQ.o reset.o display.o init.o memory.o \
22 printf.o cmdline.o time.o
23obj-$(CONFIG_PCI) += pci.o
24obj-$(CONFIG_KGDB) += gdb_hook.o
25
26EXTRA_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 000000000000..1871c30ed2eb
--- /dev/null
+++ b/arch/mips/mips-boards/generic/cmdline.c
@@ -0,0 +1,59 @@
1/*
2 * Carsten Langgaard, carstenl@mips.com
3 * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
4 *
5 * This program is free software; you can distribute it and/or modify it
6 * under the terms of the GNU General Public License (Version 2) as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
17 *
18 * Kernel command line creation using the prom monitor (YAMON) argc/argv.
19 */
20#include <linux/init.h>
21#include <linux/string.h>
22
23#include <asm/bootinfo.h>
24
25extern int prom_argc;
26extern int *_prom_argv;
27
28/*
29 * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
30 * This macro take care of sign extension.
31 */
32#define prom_argv(index) ((char *)(long)_prom_argv[(index)])
33
34char * __init prom_getcmdline(void)
35{
36 return &(arcs_cmdline[0]);
37}
38
39
40void __init prom_init_cmdline(void)
41{
42 char *cp;
43 int actr;
44
45 actr = 1; /* Always ignore argv[0] */
46
47 cp = &(arcs_cmdline[0]);
48 while(actr < prom_argc) {
49 strcpy(cp, prom_argv(actr));
50 cp += strlen(prom_argv(actr));
51 *cp++ = ' ';
52 actr++;
53 }
54 if (cp != &(arcs_cmdline[0])) {
55 /* get rid of trailing space */
56 --cp;
57 *cp = '\0';
58 }
59}
diff --git a/arch/mips/mips-boards/generic/display.c b/arch/mips/mips-boards/generic/display.c
new file mode 100644
index 000000000000..f653946afc23
--- /dev/null
+++ b/arch/mips/mips-boards/generic/display.c
@@ -0,0 +1,39 @@
1/*
2 * Carsten Langgaard, carstenl@mips.com
3 * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
4 *
5 * This program is free software; you can distribute it and/or modify it
6 * under the terms of the GNU General Public License (Version 2) as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
17 *
18 * Display routines for display messages in MIPS boards ascii display.
19 */
20
21#include <linux/compiler.h>
22#include <asm/io.h>
23#include <asm/mips-boards/generic.h>
24
25void mips_display_message(const char *str)
26{
27 static volatile unsigned int *display = NULL;
28 int i;
29
30 if (unlikely(display == NULL))
31 display = (volatile unsigned int *)ioremap(ASCII_DISPLAY_POS_BASE, 16*sizeof(int));
32
33 for (i = 0; i <= 14; i=i+2) {
34 if (*str)
35 display[i] = *str++;
36 else
37 display[i] = ' ';
38 }
39}
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 000000000000..91a2ccbe3730
--- /dev/null
+++ b/arch/mips/mips-boards/generic/gdb_hook.c
@@ -0,0 +1,133 @@
1/*
2 * Carsten Langgaard, carstenl@mips.com
3 * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
4 *
5 * This program is free software; you can distribute it and/or modify it
6 * under the terms of the GNU General Public License (Version 2) as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
17 *
18 * This is the interface to the remote debugger stub.
19 */
20#include <linux/types.h>
21#include <linux/serial.h>
22#include <linux/serialP.h>
23#include <linux/serial_reg.h>
24
25#include <asm/serial.h>
26#include <asm/io.h>
27
28static struct serial_state rs_table[RS_TABLE_SIZE] = {
29 SERIAL_PORT_DFNS /* Defined in serial.h */
30};
31
32static struct async_struct kdb_port_info = {0};
33
34int (*generic_putDebugChar)(char);
35char (*generic_getDebugChar)(void);
36
37static __inline__ unsigned int serial_in(struct async_struct *info, int offset)
38{
39 return inb(info->port + offset);
40}
41
42static __inline__ void serial_out(struct async_struct *info, int offset,
43 int value)
44{
45 outb(value, info->port+offset);
46}
47
48int rs_kgdb_hook(int tty_no, int speed) {
49 int t;
50 struct serial_state *ser = &rs_table[tty_no];
51
52 kdb_port_info.state = ser;
53 kdb_port_info.magic = SERIAL_MAGIC;
54 kdb_port_info.port = ser->port;
55 kdb_port_info.flags = ser->flags;
56
57 /*
58 * Clear all interrupts
59 */
60 serial_in(&kdb_port_info, UART_LSR);
61 serial_in(&kdb_port_info, UART_RX);
62 serial_in(&kdb_port_info, UART_IIR);
63 serial_in(&kdb_port_info, UART_MSR);
64
65 /*
66 * Now, initialize the UART
67 */
68 serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8); /* reset DLAB */
69 if (kdb_port_info.flags & ASYNC_FOURPORT) {
70 kdb_port_info.MCR = UART_MCR_DTR | UART_MCR_RTS;
71 t = UART_MCR_DTR | UART_MCR_OUT1;
72 } else {
73 kdb_port_info.MCR
74 = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
75 t = UART_MCR_DTR | UART_MCR_RTS;
76 }
77
78 kdb_port_info.MCR = t; /* no interrupts, please */
79 serial_out(&kdb_port_info, UART_MCR, kdb_port_info.MCR);
80
81 /*
82 * and set the speed of the serial port
83 */
84 if (speed == 0)
85 speed = 9600;
86
87 t = kdb_port_info.state->baud_base / speed;
88 /* set DLAB */
89 serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8 | UART_LCR_DLAB);
90 serial_out(&kdb_port_info, UART_DLL, t & 0xff);/* LS of divisor */
91 serial_out(&kdb_port_info, UART_DLM, t >> 8); /* MS of divisor */
92 /* reset DLAB */
93 serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8);
94
95 return speed;
96}
97
98int putDebugChar(char c)
99{
100 return generic_putDebugChar(c);
101}
102
103char getDebugChar(void)
104{
105 return generic_getDebugChar();
106}
107
108int rs_putDebugChar(char c)
109{
110
111 if (!kdb_port_info.state) { /* need to init device first */
112 return 0;
113 }
114
115 while ((serial_in(&kdb_port_info, UART_LSR) & UART_LSR_THRE) == 0)
116 ;
117
118 serial_out(&kdb_port_info, UART_TX, c);
119
120 return 1;
121}
122
123char rs_getDebugChar(void)
124{
125 if (!kdb_port_info.state) { /* need to init device first */
126 return 0;
127 }
128
129 while (!(serial_in(&kdb_port_info, UART_LSR) & 1))
130 ;
131
132 return serial_in(&kdb_port_info, UART_RX);
133}
diff --git a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c
new file mode 100644
index 000000000000..31caf0603a3f
--- /dev/null
+++ b/arch/mips/mips-boards/generic/init.c
@@ -0,0 +1,343 @@
1/*
2 * Carsten Langgaard, carstenl@mips.com
3 * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
4 *
5 * This program is free software; you can distribute it and/or modify it
6 * under the terms of the GNU General Public License (Version 2) as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
17 *
18 * PROM library initialisation code.
19 */
20#include <linux/config.h>
21#include <linux/init.h>
22#include <linux/string.h>
23#include <linux/kernel.h>
24
25#include <asm/io.h>
26#include <asm/bootinfo.h>
27#include <asm/mips-boards/prom.h>
28#include <asm/mips-boards/generic.h>
29#ifdef CONFIG_MIPS_GT64120
30#include <asm/gt64120.h>
31#endif
32#include <asm/mips-boards/msc01_pci.h>
33#include <asm/mips-boards/bonito64.h>
34#ifdef CONFIG_MIPS_MALTA
35#include <asm/mips-boards/malta.h>
36#endif
37
38#ifdef CONFIG_KGDB
39extern int rs_kgdb_hook(int, int);
40extern int rs_putDebugChar(char);
41extern char rs_getDebugChar(void);
42extern int saa9730_kgdb_hook(int);
43extern int saa9730_putDebugChar(char);
44extern char saa9730_getDebugChar(void);
45#endif
46
47int prom_argc;
48int *_prom_argv, *_prom_envp;
49
50/*
51 * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer.
52 * This macro take care of sign extension, if running in 64-bit mode.
53 */
54#define prom_envp(index) ((char *)(long)_prom_envp[(index)])
55
56int init_debug = 0;
57
58unsigned int mips_revision_corid;
59
60/* Bonito64 system controller register base. */
61unsigned long _pcictrl_bonito;
62unsigned long _pcictrl_bonito_pcicfg;
63
64/* GT64120 system controller register base */
65unsigned long _pcictrl_gt64120;
66
67/* MIPS System controller register base */
68unsigned long _pcictrl_msc;
69
70char *prom_getenv(char *envname)
71{
72 /*
73 * Return a pointer to the given environment variable.
74 * In 64-bit mode: we're using 64-bit pointers, but all pointers
75 * in the PROM structures are only 32-bit, so we need some
76 * workarounds, if we are running in 64-bit mode.
77 */
78 int i, index=0;
79
80 i = strlen(envname);
81
82 while (prom_envp(index)) {
83 if(strncmp(envname, prom_envp(index), i) == 0) {
84 return(prom_envp(index+1));
85 }
86 index += 2;
87 }
88
89 return NULL;
90}
91
92static inline unsigned char str2hexnum(unsigned char c)
93{
94 if (c >= '0' && c <= '9')
95 return c - '0';
96 if (c >= 'a' && c <= 'f')
97 return c - 'a' + 10;
98 return 0; /* foo */
99}
100
101static inline void str2eaddr(unsigned char *ea, unsigned char *str)
102{
103 int i;
104
105 for (i = 0; i < 6; i++) {
106 unsigned char num;
107
108 if((*str == '.') || (*str == ':'))
109 str++;
110 num = str2hexnum(*str++) << 4;
111 num |= (str2hexnum(*str++));
112 ea[i] = num;
113 }
114}
115
116int get_ethernet_addr(char *ethernet_addr)
117{
118 char *ethaddr_str;
119
120 ethaddr_str = prom_getenv("ethaddr");
121 if (!ethaddr_str) {
122 printk("ethaddr not set in boot prom\n");
123 return -1;
124 }
125 str2eaddr(ethernet_addr, ethaddr_str);
126
127 if (init_debug > 1) {
128 int i;
129 printk("get_ethernet_addr: ");
130 for (i=0; i<5; i++)
131 printk("%02x:", (unsigned char)*(ethernet_addr+i));
132 printk("%02x\n", *(ethernet_addr+i));
133 }
134
135 return 0;
136}
137
138#ifdef CONFIG_SERIAL_8250_CONSOLE
139static void __init console_config(void)
140{
141 char console_string[40];
142 int baud = 0;
143 char parity = '\0', bits = '\0', flow = '\0';
144 char *s;
145
146 if ((strstr(prom_getcmdline(), "console=ttyS")) == NULL) {
147 s = prom_getenv("modetty0");
148 if (s) {
149 while (*s >= '0' && *s <= '9')
150 baud = baud*10 + *s++ - '0';
151 if (*s == ',') s++;
152 if (*s) parity = *s++;
153 if (*s == ',') s++;
154 if (*s) bits = *s++;
155 if (*s == ',') s++;
156 if (*s == 'h') flow = 'r';
157 }
158 if (baud == 0)
159 baud = 38400;
160 if (parity != 'n' && parity != 'o' && parity != 'e')
161 parity = 'n';
162 if (bits != '7' && bits != '8')
163 bits = '8';
164 if (flow == '\0')
165 flow = 'r';
166 sprintf (console_string, " console=ttyS0,%d%c%c%c", baud, parity, bits, flow);
167 strcat (prom_getcmdline(), console_string);
168 prom_printf("Config serial console:%s\n", console_string);
169 }
170}
171#endif
172
173#ifdef CONFIG_KGDB
174void __init kgdb_config (void)
175{
176 extern int (*generic_putDebugChar)(char);
177 extern char (*generic_getDebugChar)(void);
178 char *argptr;
179 int line, speed;
180
181 argptr = prom_getcmdline();
182 if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) {
183 argptr += strlen("kgdb=ttyS");
184 if (*argptr != '0' && *argptr != '1')
185 printk("KGDB: Unknown serial line /dev/ttyS%c, "
186 "falling back to /dev/ttyS1\n", *argptr);
187 line = *argptr == '0' ? 0 : 1;
188 printk("KGDB: Using serial line /dev/ttyS%d for session\n", line);
189
190 speed = 0;
191 if (*++argptr == ',')
192 {
193 int c;
194 while ((c = *++argptr) && ('0' <= c && c <= '9'))
195 speed = speed * 10 + c - '0';
196 }
197#ifdef CONFIG_MIPS_ATLAS
198 if (line == 1) {
199 speed = saa9730_kgdb_hook(speed);
200 generic_putDebugChar = saa9730_putDebugChar;
201 generic_getDebugChar = saa9730_getDebugChar;
202 }
203 else
204#endif
205 {
206 speed = rs_kgdb_hook(line, speed);
207 generic_putDebugChar = rs_putDebugChar;
208 generic_getDebugChar = rs_getDebugChar;
209 }
210
211 prom_printf("KGDB: Using serial line /dev/ttyS%d at %d for session, "
212 "please connect your debugger\n", line ? 1 : 0, speed);
213
214 {
215 char *s;
216 for (s = "Please connect GDB to this port\r\n"; *s; )
217 generic_putDebugChar (*s++);
218 }
219
220 kgdb_enabled = 1;
221 /* Breakpoint is invoked after interrupts are initialised */
222 }
223}
224#endif
225
226void __init prom_init(void)
227{
228 prom_argc = fw_arg0;
229 _prom_argv = (int *) fw_arg1;
230 _prom_envp = (int *) fw_arg2;
231
232 mips_display_message("LINUX");
233
234#ifdef CONFIG_MIPS_SEAD
235 set_io_port_base(KSEG1);
236#else
237 /*
238 * early setup of _pcictrl_bonito so that we can determine
239 * the system controller on a CORE_EMUL board
240 */
241 _pcictrl_bonito = (unsigned long)ioremap(BONITO_REG_BASE, BONITO_REG_SIZE);
242
243 mips_revision_corid = MIPS_REVISION_CORID;
244
245 if (mips_revision_corid == MIPS_REVISION_CORID_CORE_EMUL) {
246 if (BONITO_PCIDID == 0x0001df53 ||
247 BONITO_PCIDID == 0x0003df53)
248 mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_BON;
249 else
250 mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_MSC;
251 }
252 switch(mips_revision_corid) {
253 case MIPS_REVISION_CORID_QED_RM5261:
254 case MIPS_REVISION_CORID_CORE_LV:
255 case MIPS_REVISION_CORID_CORE_FPGA:
256 case MIPS_REVISION_CORID_CORE_FPGAR2:
257 /*
258 * Setup the North bridge to do Master byte-lane swapping
259 * when running in bigendian.
260 */
261 _pcictrl_gt64120 = (unsigned long)ioremap(MIPS_GT_BASE, 0x2000);
262
263#ifdef CONFIG_CPU_LITTLE_ENDIAN
264 GT_WRITE(GT_PCI0_CMD_OFS, GT_PCI0_CMD_MBYTESWAP_BIT |
265 GT_PCI0_CMD_SBYTESWAP_BIT);
266#else
267 GT_WRITE(GT_PCI0_CMD_OFS, 0);
268#endif
269
270#ifdef CONFIG_MIPS_MALTA
271 set_io_port_base(MALTA_GT_PORT_BASE);
272#else
273 set_io_port_base((unsigned long)ioremap(0, 0x20000000));
274#endif
275 break;
276
277 case MIPS_REVISION_CORID_CORE_EMUL_BON:
278 case MIPS_REVISION_CORID_BONITO64:
279 case MIPS_REVISION_CORID_CORE_20K:
280 _pcictrl_bonito_pcicfg = (unsigned long)ioremap(BONITO_PCICFG_BASE, BONITO_PCICFG_SIZE);
281
282 /*
283 * Disable Bonito IOBC.
284 */
285 BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG &
286 ~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
287 BONITO_PCIMEMBASECFG_MEMBASE1_CACHED);
288
289 /*
290 * Setup the North bridge to do Master byte-lane swapping
291 * when running in bigendian.
292 */
293#ifdef CONFIG_CPU_LITTLE_ENDIAN
294 BONITO_BONGENCFG = BONITO_BONGENCFG &
295 ~(BONITO_BONGENCFG_MSTRBYTESWAP |
296 BONITO_BONGENCFG_BYTESWAP);
297#else
298 BONITO_BONGENCFG = BONITO_BONGENCFG |
299 BONITO_BONGENCFG_MSTRBYTESWAP |
300 BONITO_BONGENCFG_BYTESWAP;
301#endif
302
303#ifdef CONFIG_MIPS_MALTA
304 set_io_port_base(MALTA_BONITO_PORT_BASE);
305#else
306 set_io_port_base((unsigned long)ioremap(0, 0x20000000));
307#endif
308 break;
309
310 case MIPS_REVISION_CORID_CORE_MSC:
311 case MIPS_REVISION_CORID_CORE_FPGA2:
312 case MIPS_REVISION_CORID_CORE_EMUL_MSC:
313 _pcictrl_msc = (unsigned long)ioremap(MIPS_MSC01_PCI_REG_BASE, 0x2000);
314
315#ifdef CONFIG_CPU_LITTLE_ENDIAN
316 MSC_WRITE(MSC01_PCI_SWAP, MSC01_PCI_SWAP_NOSWAP);
317#else
318 MSC_WRITE(MSC01_PCI_SWAP,
319 MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_IO_SHF |
320 MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_MEM_SHF |
321 MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_BAR0_SHF);
322#endif
323
324#ifdef CONFIG_MIPS_MALTA
325 set_io_port_base(MALTA_MSC_PORT_BASE);
326#else
327 set_io_port_base((unsigned long)ioremap(0, 0x20000000));
328#endif
329 break;
330
331 default:
332 /* Unknown Core card */
333 mips_display_message("CC Error");
334 while(1); /* We die here... */
335 }
336#endif
337 prom_printf("\nLINUX started...\n");
338 prom_init_cmdline();
339 prom_meminit();
340#ifdef CONFIG_SERIAL_8250_CONSOLE
341 console_config();
342#endif
343}
diff --git a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c
new file mode 100644
index 000000000000..5ae2b43e4c2e
--- /dev/null
+++ b/arch/mips/mips-boards/generic/memory.c
@@ -0,0 +1,173 @@
1/*
2 * Carsten Langgaard, carstenl@mips.com
3 * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
4 *
5 * This program is free software; you can distribute it and/or modify it
6 * under the terms of the GNU General Public License (Version 2) as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
17 *
18 * PROM library functions for acquiring/using memory descriptors given to
19 * us from the YAMON.
20 */
21#include <linux/config.h>
22#include <linux/init.h>
23#include <linux/mm.h>
24#include <linux/bootmem.h>
25
26#include <asm/bootinfo.h>
27#include <asm/page.h>
28
29#include <asm/mips-boards/prom.h>
30
31/*#define DEBUG*/
32
33enum yamon_memtypes {
34 yamon_dontuse,
35 yamon_prom,
36 yamon_free,
37};
38struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS];
39
40#ifdef DEBUG
41static char *mtypes[3] = {
42 "Dont use memory",
43 "YAMON PROM memory",
44 "Free memmory",
45};
46#endif
47
48/* References to section boundaries */
49extern char _end;
50
51#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK)
52
53
54struct prom_pmemblock * __init prom_getmdesc(void)
55{
56 char *memsize_str;
57 unsigned int memsize;
58
59 memsize_str = prom_getenv("memsize");
60 if (!memsize_str) {
61 prom_printf("memsize not set in boot prom, set to default (32Mb)\n");
62 memsize = 0x02000000;
63 } else {
64#ifdef DEBUG
65 prom_printf("prom_memsize = %s\n", memsize_str);
66#endif
67 memsize = simple_strtol(memsize_str, NULL, 0);
68 }
69
70 memset(mdesc, 0, sizeof(mdesc));
71
72 mdesc[0].type = yamon_dontuse;
73 mdesc[0].base = 0x00000000;
74 mdesc[0].size = 0x00001000;
75
76 mdesc[1].type = yamon_prom;
77 mdesc[1].base = 0x00001000;
78 mdesc[1].size = 0x000ef000;
79
80#ifdef CONFIG_MIPS_MALTA
81 /*
82 * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the
83 * south bridge and PCI access always forwarded to the ISA Bus and
84 * BIOSCS# is always generated.
85 * This mean that this area can't be used as DMA memory for PCI
86 * devices.
87 */
88 mdesc[2].type = yamon_dontuse;
89 mdesc[2].base = 0x000f0000;
90 mdesc[2].size = 0x00010000;
91#else
92 mdesc[2].type = yamon_prom;
93 mdesc[2].base = 0x000f0000;
94 mdesc[2].size = 0x00010000;
95#endif
96
97 mdesc[3].type = yamon_dontuse;
98 mdesc[3].base = 0x00100000;
99 mdesc[3].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[3].base;
100
101 mdesc[4].type = yamon_free;
102 mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end));
103 mdesc[4].size = memsize - mdesc[4].base;
104
105 return &mdesc[0];
106}
107
108static int __init prom_memtype_classify (unsigned int type)
109{
110 switch (type) {
111 case yamon_free:
112 return BOOT_MEM_RAM;
113 case yamon_prom:
114 return BOOT_MEM_ROM_DATA;
115 default:
116 return BOOT_MEM_RESERVED;
117 }
118}
119
120void __init prom_meminit(void)
121{
122 struct prom_pmemblock *p;
123
124#ifdef DEBUG
125 prom_printf("YAMON MEMORY DESCRIPTOR dump:\n");
126 p = prom_getmdesc();
127 while (p->size) {
128 int i = 0;
129 prom_printf("[%d,%p]: base<%08lx> size<%08lx> type<%s>\n",
130 i, p, p->base, p->size, mtypes[p->type]);
131 p++;
132 i++;
133 }
134#endif
135 p = prom_getmdesc();
136
137 while (p->size) {
138 long type;
139 unsigned long base, size;
140
141 type = prom_memtype_classify (p->type);
142 base = p->base;
143 size = p->size;
144
145 add_memory_region(base, size, type);
146 p++;
147 }
148}
149
150unsigned long __init prom_free_prom_memory(void)
151{
152 unsigned long freed = 0;
153 unsigned long addr;
154 int i;
155
156 for (i = 0; i < boot_mem_map.nr_map; i++) {
157 if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA)
158 continue;
159
160 addr = boot_mem_map.map[i].addr;
161 while (addr < boot_mem_map.map[i].addr
162 + boot_mem_map.map[i].size) {
163 ClearPageReserved(virt_to_page(__va(addr)));
164 set_page_count(virt_to_page(__va(addr)), 1);
165 free_page((unsigned long)__va(addr));
166 addr += PAGE_SIZE;
167 freed += PAGE_SIZE;
168 }
169 }
170 printk("Freeing prom memory: %ldkb freed\n", freed >> 10);
171
172 return freed;
173}
diff --git a/arch/mips/mips-boards/generic/mipsIRQ.S b/arch/mips/mips-boards/generic/mipsIRQ.S
new file mode 100644
index 000000000000..131f49bccb20
--- /dev/null
+++ b/arch/mips/mips-boards/generic/mipsIRQ.S
@@ -0,0 +1,153 @@
1/*
2 * Carsten Langgaard, carstenl@mips.com
3 * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved.
4 *
5 * ########################################################################
6 *
7 * This program is free software; you can distribute it and/or modify it
8 * under the terms of the GNU General Public License (Version 2) as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
19 *
20 * ########################################################################
21 *
22 * Interrupt exception dispatch code.
23 *
24 */
25#include <linux/config.h>
26
27#include <asm/asm.h>
28#include <asm/mipsregs.h>
29#include <asm/regdef.h>
30#include <asm/stackframe.h>
31
32/* A lot of complication here is taken away because:
33 *
34 * 1) We handle one interrupt and return, sitting in a loop and moving across
35 * all the pending IRQ bits in the cause register is _NOT_ the answer, the
36 * common case is one pending IRQ so optimize in that direction.
37 *
38 * 2) We need not check against bits in the status register IRQ mask, that
39 * would make this routine slow as hell.
40 *
41 * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in
42 * between like BSD spl() brain-damage.
43 *
44 * Furthermore, the IRQs on the MIPS board look basically (barring software
45 * IRQs which we don't use at all and all external interrupt sources are
46 * combined together on hardware interrupt 0 (MIPS IRQ 2)) like:
47 *
48 * MIPS IRQ Source
49 * -------- ------
50 * 0 Software (ignored)
51 * 1 Software (ignored)
52 * 2 Combined hardware interrupt (hw0)
53 * 3 Hardware (ignored)
54 * 4 Hardware (ignored)
55 * 5 Hardware (ignored)
56 * 6 Hardware (ignored)
57 * 7 R4k timer (what we use)
58 *
59 * Note: On the SEAD board thing are a little bit different.
60 * Here IRQ 2 (hw0) is wired to the UART0 and IRQ 3 (hw1) is wired
61 * wired to UART1.
62 *
63 * We handle the IRQ according to _our_ priority which is:
64 *
65 * Highest ---- R4k Timer
66 * Lowest ---- Combined hardware interrupt
67 *
68 * then we just return, if multiple IRQs are pending then we will just take
69 * another exception, big deal.
70 */
71
72 .text
73 .set noreorder
74 .set noat
75 .align 5
76 NESTED(mipsIRQ, PT_SIZE, sp)
77 SAVE_ALL
78 CLI
79 .set at
80
81 mfc0 s0, CP0_CAUSE # get irq bits
82 mfc0 s1, CP0_STATUS # get irq mask
83 and s0, s1
84
85 /* First we check for r4k counter/timer IRQ. */
86 andi a0, s0, CAUSEF_IP7
87 beq a0, zero, 1f
88 andi a0, s0, CAUSEF_IP2 # delay slot, check hw0 interrupt
89
90 /* Wheee, a timer interrupt. */
91 move a0, sp
92 jal mips_timer_interrupt
93 nop
94
95 j ret_from_irq
96 nop
97
981:
99#if defined(CONFIG_MIPS_SEAD)
100 beq a0, zero, 1f
101 andi a0, s0, CAUSEF_IP3 # delay slot, check hw1 interrupt
102#else
103 beq a0, zero, 1f # delay slot, check hw3 interrupt
104 andi a0, s0, CAUSEF_IP5
105#endif
106
107 /* Wheee, combined hardware level zero interrupt. */
108#if defined(CONFIG_MIPS_ATLAS)
109 jal atlas_hw0_irqdispatch
110#elif defined(CONFIG_MIPS_MALTA)
111 jal malta_hw0_irqdispatch
112#elif defined(CONFIG_MIPS_SEAD)
113 jal sead_hw0_irqdispatch
114#else
115#error "MIPS board not supported\n"
116#endif
117 move a0, sp # delay slot
118
119 j ret_from_irq
120 nop # delay slot
121
1221:
123#if defined(CONFIG_MIPS_SEAD)
124 beq a0, zero, 1f
125 andi a0, s0, CAUSEF_IP5 # delay slot, check hw3 interrupt
126 jal sead_hw1_irqdispatch
127 move a0, sp # delay slot
128 j ret_from_irq
129 nop # delay slot
1301:
131#endif
132#if defined(CONFIG_MIPS_MALTA)
133 beq a0, zero, 1f # check hw3 (coreHI) interrupt
134 nop
135 jal corehi_irqdispatch
136 move a0, sp
137 j ret_from_irq
138 nop
1391:
140#endif
141 /*
142 * Here by mistake? This is possible, what can happen is that by the
143 * time we take the exception the IRQ pin goes low, so just leave if
144 * this is the case.
145 */
146 move a1,s0
147 PRINT("Got interrupt: c0_cause = %08x\n")
148 mfc0 a1, CP0_EPC
149 PRINT("c0_epc = %08x\n")
150
151 j ret_from_irq
152 nop
153 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 000000000000..92c34bda02ae
--- /dev/null
+++ b/arch/mips/mips-boards/generic/pci.c
@@ -0,0 +1,163 @@
1/*
2 * Carsten Langgaard, carstenl@mips.com
3 * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved.
4 *
5 * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
6 *
7 * This program is free software; you can distribute it and/or modify it
8 * under the terms of the GNU General Public License (Version 2) as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
19 *
20 * MIPS boards specific PCI support.
21 */
22#include <linux/config.h>
23#include <linux/types.h>
24#include <linux/pci.h>
25#include <linux/kernel.h>
26#include <linux/init.h>
27
28#include <asm/mips-boards/generic.h>
29#include <asm/gt64120.h>
30#include <asm/mips-boards/bonito64.h>
31#include <asm/mips-boards/msc01_pci.h>
32#ifdef CONFIG_MIPS_MALTA
33#include <asm/mips-boards/malta.h>
34#endif
35
36static struct resource bonito64_mem_resource = {
37 .name = "Bonito PCI MEM",
38 .start = 0x10000000UL,
39 .end = 0x1bffffffUL,
40 .flags = IORESOURCE_MEM,
41};
42
43static struct resource bonito64_io_resource = {
44 .name = "Bonito IO MEM",
45 .start = 0x00002000UL, /* avoid conflicts with YAMON allocated I/O addresses */
46 .end = 0x000fffffUL,
47 .flags = IORESOURCE_IO,
48};
49
50static struct resource gt64120_mem_resource = {
51 .name = "GT64120 PCI MEM",
52 .start = 0x10000000UL,
53 .end = 0x1bdfffffUL,
54 .flags = IORESOURCE_MEM,
55};
56
57static struct resource gt64120_io_resource = {
58 .name = "GT64120 IO MEM",
59#ifdef CONFIG_MIPS_ATLAS
60 .start = 0x18000000UL,
61 .end = 0x181fffffUL,
62#endif
63#ifdef CONFIG_MIPS_MALTA
64 .start = 0x00002000UL,
65 .end = 0x001fffffUL,
66#endif
67 .flags = IORESOURCE_IO,
68};
69
70static struct resource msc_mem_resource = {
71 .name = "MSC PCI MEM",
72 .start = 0x10000000UL,
73 .end = 0x1fffffffUL,
74 .flags = IORESOURCE_MEM,
75};
76
77static struct resource msc_io_resource = {
78 .name = "MSC IO MEM",
79 .start = 0x00002000UL,
80 .end = 0x007fffffUL,
81 .flags = IORESOURCE_IO,
82};
83
84extern struct pci_ops bonito64_pci_ops;
85extern struct pci_ops gt64120_pci_ops;
86extern struct pci_ops msc_pci_ops;
87
88static struct pci_controller bonito64_controller = {
89 .pci_ops = &bonito64_pci_ops,
90 .io_resource = &bonito64_io_resource,
91 .mem_resource = &bonito64_mem_resource,
92 .mem_offset = 0x10000000UL,
93 .io_offset = 0x00000000UL,
94};
95
96static struct pci_controller gt64120_controller = {
97 .pci_ops = &gt64120_pci_ops,
98 .io_resource = &gt64120_io_resource,
99 .mem_resource = &gt64120_mem_resource,
100 .mem_offset = 0x00000000UL,
101 .io_offset = 0x00000000UL,
102};
103
104static struct pci_controller msc_controller = {
105 .pci_ops = &msc_pci_ops,
106 .io_resource = &msc_io_resource,
107 .mem_resource = &msc_mem_resource,
108 .mem_offset = 0x10000000UL,
109 .io_offset = 0x00000000UL,
110};
111
112static int __init pcibios_init(void)
113{
114 struct pci_controller *controller;
115
116 switch (mips_revision_corid) {
117 case MIPS_REVISION_CORID_QED_RM5261:
118 case MIPS_REVISION_CORID_CORE_LV:
119 case MIPS_REVISION_CORID_CORE_FPGA:
120 case MIPS_REVISION_CORID_CORE_FPGAR2:
121 /*
122 * Due to a bug in the Galileo system controller, we need
123 * to setup the PCI BAR for the Galileo internal registers.
124 * This should be done in the bios/bootprom and will be
125 * fixed in a later revision of YAMON (the MIPS boards
126 * boot prom).
127 */
128 GT_WRITE(GT_PCI0_CFGADDR_OFS,
129 (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */
130 (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */
131 (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0*/
132 ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4*/
133 GT_PCI0_CFGADDR_CONFIGEN_BIT );
134
135 /* Perform the write */
136 GT_WRITE(GT_PCI0_CFGDATA_OFS, CPHYSADDR(MIPS_GT_BASE));
137
138 controller = &gt64120_controller;
139 break;
140
141 case MIPS_REVISION_CORID_BONITO64:
142 case MIPS_REVISION_CORID_CORE_20K:
143 case MIPS_REVISION_CORID_CORE_EMUL_BON:
144 controller = &bonito64_controller;
145 break;
146
147 case MIPS_REVISION_CORID_CORE_MSC:
148 case MIPS_REVISION_CORID_CORE_FPGA2:
149 case MIPS_REVISION_CORID_CORE_EMUL_MSC:
150 controller = &msc_controller;
151 break;
152 default:
153 return 1;
154 }
155
156 ioport_resource.end = controller->io_resource->end;
157
158 register_pci_controller (controller);
159
160 return 0;
161}
162
163early_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 000000000000..2c1ab1f19fdc
--- /dev/null
+++ b/arch/mips/mips-boards/generic/printf.c
@@ -0,0 +1,79 @@
1/*
2 * Carsten Langgaard, carstenl@mips.com
3 * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
4 *
5 * This program is free software; you can distribute it and/or modify it
6 * under the terms of the GNU General Public License (Version 2) as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
17 *
18 * Putting things on the screen/serial line using YAMONs facilities.
19 */
20#include <linux/config.h>
21#include <linux/init.h>
22#include <linux/kernel.h>
23#include <linux/serial_reg.h>
24#include <linux/spinlock.h>
25#include <asm/io.h>
26
27#ifdef CONFIG_MIPS_ATLAS
28#include <asm/mips-boards/atlas.h>
29
30#ifdef CONFIG_CPU_LITTLE_ENDIAN
31#define PORT(offset) (ATLAS_UART_REGS_BASE + ((offset)<<3))
32#else
33#define PORT(offset) (ATLAS_UART_REGS_BASE + 3 + ((offset)<<3))
34#endif
35
36#elif defined(CONFIG_MIPS_SEAD)
37
38#include <asm/mips-boards/sead.h>
39
40#ifdef CONFIG_CPU_LITTLE_ENDIAN
41#define PORT(offset) (SEAD_UART0_REGS_BASE + ((offset)<<3))
42#else
43#define PORT(offset) (SEAD_UART0_REGS_BASE + 3 + ((offset)<<3))
44#endif
45
46#else
47
48#define PORT(offset) (0x3f8 + (offset))
49
50#endif
51
52static inline unsigned int serial_in(int offset)
53{
54 return inb(PORT(offset));
55}
56
57static inline void serial_out(int offset, int value)
58{
59 outb(value, PORT(offset));
60}
61
62int prom_putchar(char c)
63{
64 while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0)
65 ;
66
67 serial_out(UART_TX, c);
68
69 return 1;
70}
71
72char prom_getchar(void)
73{
74 while (!(serial_in(UART_LSR) & UART_LSR_DR))
75 ;
76
77 return serial_in(UART_RX);
78}
79
diff --git a/arch/mips/mips-boards/generic/reset.c b/arch/mips/mips-boards/generic/reset.c
new file mode 100644
index 000000000000..9fdec743bd95
--- /dev/null
+++ b/arch/mips/mips-boards/generic/reset.c
@@ -0,0 +1,73 @@
1/*
2 * Carsten Langgaard, carstenl@mips.com
3 * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
4 *
5 * ########################################################################
6 *
7 * This program is free software; you can distribute it and/or modify it
8 * under the terms of the GNU General Public License (Version 2) as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
19 *
20 * ########################################################################
21 *
22 * Reset the MIPS boards.
23 *
24 */
25#include <linux/config.h>
26
27#include <asm/io.h>
28#include <asm/reboot.h>
29#include <asm/mips-boards/generic.h>
30#if defined(CONFIG_MIPS_ATLAS)
31#include <asm/mips-boards/atlas.h>
32#endif
33
34static void mips_machine_restart(char *command);
35static void mips_machine_halt(void);
36#if defined(CONFIG_MIPS_ATLAS)
37static void atlas_machine_power_off(void);
38#endif
39
40static void mips_machine_restart(char *command)
41{
42 volatile unsigned int *softres_reg = (unsigned int *)ioremap (SOFTRES_REG, sizeof(unsigned int));
43
44 *softres_reg = GORESET;
45}
46
47static void mips_machine_halt(void)
48{
49 volatile unsigned int *softres_reg = (unsigned int *)ioremap (SOFTRES_REG, sizeof(unsigned int));
50
51 *softres_reg = GORESET;
52}
53
54#if defined(CONFIG_MIPS_ATLAS)
55static void atlas_machine_power_off(void)
56{
57 volatile unsigned int *psustby_reg = (unsigned int *)ioremap(ATLAS_PSUSTBY_REG, sizeof(unsigned int));
58
59 *psustby_reg = ATLAS_GOSTBY;
60}
61#endif
62
63void mips_reboot_setup(void)
64{
65 _machine_restart = mips_machine_restart;
66 _machine_halt = mips_machine_halt;
67#if defined(CONFIG_MIPS_ATLAS)
68 _machine_power_off = atlas_machine_power_off;
69#endif
70#if defined(CONFIG_MIPS_MALTA) || defined(CONFIG_MIPS_SEAD)
71 _machine_power_off = mips_machine_halt;
72#endif
73}
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
new file mode 100644
index 000000000000..fe7fc17305a6
--- /dev/null
+++ b/arch/mips/mips-boards/generic/time.c
@@ -0,0 +1,167 @@
1/*
2 * Carsten Langgaard, carstenl@mips.com
3 * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved.
4 *
5 * This program is free software; you can distribute it and/or modify it
6 * under the terms of the GNU General Public License (Version 2) as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
17 *
18 * Setting up the clock on the MIPS boards.
19 */
20
21#include <linux/types.h>
22#include <linux/config.h>
23#include <linux/init.h>
24#include <linux/kernel_stat.h>
25#include <linux/sched.h>
26#include <linux/spinlock.h>
27#include <linux/interrupt.h>
28#include <linux/time.h>
29#include <linux/timex.h>
30#include <linux/mc146818rtc.h>
31
32#include <asm/mipsregs.h>
33#include <asm/ptrace.h>
34#include <asm/div64.h>
35#include <asm/cpu.h>
36#include <asm/time.h>
37#include <asm/mc146818-time.h>
38
39#include <asm/mips-boards/generic.h>
40#include <asm/mips-boards/prom.h>
41
42unsigned long cpu_khz;
43
44#if defined(CONFIG_MIPS_SEAD)
45#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ5)
46#else
47#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5)
48#endif
49
50#if defined(CONFIG_MIPS_ATLAS)
51static char display_string[] = " LINUX ON ATLAS ";
52#endif
53#if defined(CONFIG_MIPS_MALTA)
54static char display_string[] = " LINUX ON MALTA ";
55#endif
56#if defined(CONFIG_MIPS_SEAD)
57static char display_string[] = " LINUX ON SEAD ";
58#endif
59static unsigned int display_count = 0;
60#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8)
61
62#define MIPS_CPU_TIMER_IRQ (NR_IRQS-1)
63
64static unsigned int timer_tick_count=0;
65
66void mips_timer_interrupt(struct pt_regs *regs)
67{
68 if ((timer_tick_count++ % HZ) == 0) {
69 mips_display_message(&display_string[display_count++]);
70 if (display_count == MAX_DISPLAY_COUNT)
71 display_count = 0;
72
73 }
74
75 ll_timer_interrupt(MIPS_CPU_TIMER_IRQ, regs);
76}
77
78/*
79 * Estimate CPU frequency. Sets mips_counter_frequency as a side-effect
80 */
81static unsigned int __init estimate_cpu_frequency(void)
82{
83 unsigned int prid = read_c0_prid() & 0xffff00;
84 unsigned int count;
85
86#ifdef CONFIG_MIPS_SEAD
87 /*
88 * The SEAD board doesn't have a real time clock, so we can't
89 * really calculate the timer frequency
90 * For now we hardwire the SEAD board frequency to 12MHz.
91 */
92
93 if ((prid == (PRID_COMP_MIPS | PRID_IMP_20KC)) ||
94 (prid == (PRID_COMP_MIPS | PRID_IMP_25KF)))
95 count = 12000000;
96 else
97 count = 6000000;
98#endif
99#if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_MALTA)
100 unsigned int flags;
101
102 local_irq_save(flags);
103
104 /* Start counter exactly on falling edge of update flag */
105 while (CMOS_READ(RTC_REG_A) & RTC_UIP);
106 while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
107
108 /* Start r4k counter. */
109 write_c0_count(0);
110
111 /* Read counter exactly on falling edge of update flag */
112 while (CMOS_READ(RTC_REG_A) & RTC_UIP);
113 while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));
114
115 count = read_c0_count();
116
117 /* restore interrupts */
118 local_irq_restore(flags);
119#endif
120
121 mips_hpt_frequency = count;
122 if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
123 (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
124 count *= 2;
125
126 count += 5000; /* round */
127 count -= count%10000;
128
129 return count;
130}
131
132unsigned long __init mips_rtc_get_time(void)
133{
134 return mc146818_get_cmos_time();
135}
136
137void __init mips_time_init(void)
138{
139 unsigned int est_freq, flags;
140
141 local_irq_save(flags);
142
143#if defined(CONFIG_MIPS_ATLAS) || defined(CONFIG_MIPS_MALTA)
144 /* Set Data mode - binary. */
145 CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);
146#endif
147
148 est_freq = estimate_cpu_frequency ();
149
150 printk("CPU frequency %d.%02d MHz\n", est_freq/1000000,
151 (est_freq%1000000)*100/1000000);
152
153 cpu_khz = est_freq / 1000;
154
155 local_irq_restore(flags);
156}
157
158void __init mips_timer_setup(struct irqaction *irq)
159{
160 /* we are using the cpu counter for timer interrupts */
161 irq->handler = no_action; /* we use our own handler */
162 setup_irq(MIPS_CPU_TIMER_IRQ, irq);
163
164 /* to generate the first timer interrupt */
165 write_c0_compare (read_c0_count() + mips_hpt_frequency/HZ);
166 set_c0_status(ALLINTS);
167}