blob: db544a6e23f33a448a6b14bd08f3cfec35e0baf4 [file] [log] [blame]
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +02001/*
2 * Big Endian PROM code for SNI RM machines
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) 2005-2006 Florian Lohoff (flo@rfc822.org)
9 * Copyright (C) 2005-2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
10 */
11
Ralf Baechle36a88532007-03-01 11:56:43 +000012#define DEBUG
13
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +020014#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/string.h>
Thomas Bogendoerferc066a322006-12-28 18:22:32 +010017#include <linux/console.h>
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +020018
19#include <asm/addrspace.h>
20#include <asm/sni.h>
21#include <asm/mipsprom.h>
Thomas Bogendoerfercbe7b452007-07-24 03:49:27 +020022#include <asm/mipsregs.h>
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +020023#include <asm/bootinfo.h>
24
25/* special SNI prom calls */
26/*
27 * This does not exist in all proms - SINIX compares
28 * the prom env variable "version" against "2.0008"
29 * or greater. If lesser it tries to probe interesting
30 * registers
31 */
32#define PROM_GET_MEMCONF 58
33
34#define PROM_VEC (u64 *)CKSEG1ADDR(0x1fc00000)
35#define PROM_ENTRY(x) (PROM_VEC + (x))
36
37
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +020038static int *(*__prom_putchar)(int) = (int *(*)(int))PROM_ENTRY(PROM_PUTCHAR);
Ralf Baechle36a88532007-03-01 11:56:43 +000039
40void prom_putchar(char c)
41{
42 __prom_putchar(c);
43}
44
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +020045static char *(*__prom_getenv)(char *) = (char *(*)(char *))PROM_ENTRY(PROM_GETENV);
46static void (*__prom_get_memconf)(void *) = (void (*)(void *))PROM_ENTRY(PROM_GET_MEMCONF);
47
48char *prom_getenv (char *s)
49{
50 return __prom_getenv(s);
51}
52
Atsushi Nemotoc44e8d52006-12-30 00:43:59 +090053void __init prom_free_prom_memory(void)
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +020054{
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +020055}
56
57/*
58 * /proc/cpuinfo system type
59 *
60 */
61static const char *systype = "Unknown";
62const char *get_system_type(void)
63{
64 return systype;
65}
66
67#define SNI_IDPROM_BASE 0xbff00000
68#define SNI_IDPROM_MEMSIZE (SNI_IDPROM_BASE+0x28) /* Memsize in 16MB quantities */
69#define SNI_IDPROM_BRDTYPE (SNI_IDPROM_BASE+0x29) /* Board Type */
70#define SNI_IDPROM_CPUTYPE (SNI_IDPROM_BASE+0x30) /* CPU Type */
71
72#define SNI_IDPROM_SIZE 0x1000
73
74#ifdef DEBUG
Thomas Bogendoerfercbe7b452007-07-24 03:49:27 +020075static void __init sni_idprom_dump(void)
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +020076{
77 int i;
78
Ralf Baechle36a88532007-03-01 11:56:43 +000079 pr_debug("SNI IDProm dump:\n");
Thomas Bogendoerferc066a322006-12-28 18:22:32 +010080 for (i = 0; i < 256; i++) {
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +020081 if (i%16 == 0)
Ralf Baechle36a88532007-03-01 11:56:43 +000082 pr_debug("%04x ", i);
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +020083
Ralf Baechle36a88532007-03-01 11:56:43 +000084 printk("%02x ", *(unsigned char *) (SNI_IDPROM_BASE + i));
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +020085
Thomas Bogendoerferc066a322006-12-28 18:22:32 +010086 if (i % 16 == 15)
Ralf Baechle36a88532007-03-01 11:56:43 +000087 printk("\n");
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +020088 }
89}
90#endif
91
Thomas Bogendoerfercbe7b452007-07-24 03:49:27 +020092static void __init sni_mem_init(void )
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +020093{
94 int i, memsize;
95 struct membank {
96 u32 size;
97 u32 base;
98 u32 size2;
99 u32 pad1;
100 u32 pad2;
101 } memconf[8];
102
103 /* MemSIZE from prom in 16MByte chunks */
Thomas Bogendoerferc066a322006-12-28 18:22:32 +0100104 memsize = *((unsigned char *) SNI_IDPROM_MEMSIZE) * 16;
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +0200105
Ralf Baechle36a88532007-03-01 11:56:43 +0000106 pr_debug("IDProm memsize: %lu MByte\n", memsize);
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +0200107
108 /* get memory bank layout from prom */
109 __prom_get_memconf(&memconf);
110
Ralf Baechle36a88532007-03-01 11:56:43 +0000111 pr_debug("prom_get_mem_conf memory configuration:\n");
Thomas Bogendoerferc066a322006-12-28 18:22:32 +0100112 for (i = 0;i < 8 && memconf[i].size; i++) {
113 if (sni_brd_type == SNI_BRD_PCI_TOWER ||
114 sni_brd_type == SNI_BRD_PCI_TOWER_CPLUS) {
115 if (memconf[i].base >= 0x20000000 &&
116 memconf[i].base < 0x30000000) {
117 memconf[i].base -= 0x20000000;
118 }
119 }
Ralf Baechle36a88532007-03-01 11:56:43 +0000120 pr_debug("Bank%d: %08x @ %08x\n", i,
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +0200121 memconf[i].size, memconf[i].base);
122 add_memory_region(memconf[i].base, memconf[i].size, BOOT_MEM_RAM);
123 }
124}
125
Thomas Bogendoerferc066a322006-12-28 18:22:32 +0100126static void __init sni_console_setup(void)
127{
128 char *ctype;
129 char *cdev;
130 char *baud;
131 int port;
132 static char options[8];
133
134 cdev = prom_getenv ("console_dev");
135 if (strncmp (cdev, "tty", 3) == 0) {
136 ctype = prom_getenv ("console");
137 switch (*ctype) {
138 default:
139 case 'l':
140 port = 0;
141 baud = prom_getenv("lbaud");
142 break;
143 case 'r':
144 port = 1;
145 baud = prom_getenv("rbaud");
146 break;
147 }
148 if (baud)
149 strcpy(options, baud);
Thomas Bogendoerfer06cf5582007-06-20 23:36:47 +0200150 if (strncmp (cdev, "tty552", 6) == 0)
151 add_preferred_console("ttyS", port, baud ? options : NULL);
152 else
153 add_preferred_console("ttySC", port, baud ? options : NULL);
Thomas Bogendoerferc066a322006-12-28 18:22:32 +0100154 }
155}
156
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +0200157void __init prom_init(void)
158{
159 int argc = fw_arg0;
160 char **argv = (void *)fw_arg1;
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +0200161 int i;
Thomas Bogendoerferc066a322006-12-28 18:22:32 +0100162 int cputype;
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +0200163
Thomas Bogendoerferc066a322006-12-28 18:22:32 +0100164 sni_brd_type = *(unsigned char *)SNI_IDPROM_BRDTYPE;
165 cputype = *(unsigned char *)SNI_IDPROM_CPUTYPE;
166 switch (sni_brd_type) {
167 case SNI_BRD_TOWER_OASIC:
168 switch (cputype) {
169 case SNI_CPU_M8030:
170 systype = "RM400-330";
171 break;
172 case SNI_CPU_M8031:
173 systype = "RM400-430";
174 break;
175 case SNI_CPU_M8037:
176 systype = "RM400-530";
177 break;
178 case SNI_CPU_M8034:
179 systype = "RM400-730";
180 break;
181 default:
182 systype = "RM400-xxx";
183 break;
184 }
185 break;
186 case SNI_BRD_MINITOWER:
187 switch (cputype) {
188 case SNI_CPU_M8021:
189 case SNI_CPU_M8043:
190 systype = "RM400-120";
191 break;
192 case SNI_CPU_M8040:
193 systype = "RM400-220";
194 break;
195 case SNI_CPU_M8053:
196 systype = "RM400-225";
197 break;
198 case SNI_CPU_M8050:
199 systype = "RM400-420";
200 break;
201 default:
202 systype = "RM400-xxx";
203 break;
204 }
205 break;
206 case SNI_BRD_PCI_TOWER:
207 systype = "RM400-Cxx";
208 break;
209 case SNI_BRD_RM200:
210 systype = "RM200-xxx";
211 break;
212 case SNI_BRD_PCI_MTOWER:
213 systype = "RM300-Cxx";
214 break;
215 case SNI_BRD_PCI_DESKTOP:
216 switch (read_c0_prid() & 0xff00) {
217 case PRID_IMP_R4600:
218 case PRID_IMP_R4700:
219 systype = "RM200-C20";
220 break;
221 case PRID_IMP_R5000:
222 systype = "RM200-C40";
223 break;
224 default:
225 systype = "RM200-Cxx";
226 break;
227 }
228 break;
229 case SNI_BRD_PCI_TOWER_CPLUS:
230 systype = "RM400-Exx";
231 break;
232 case SNI_BRD_PCI_MTOWER_CPLUS:
233 systype = "RM300-Exx";
234 break;
235 }
Ralf Baechle36a88532007-03-01 11:56:43 +0000236 pr_debug("Found SNI brdtype %02x name %s\n", sni_brd_type,systype);
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +0200237
238#ifdef DEBUG
239 sni_idprom_dump();
240#endif
241 sni_mem_init();
Thomas Bogendoerferc066a322006-12-28 18:22:32 +0100242 sni_console_setup();
Thomas Bogendoerfer4a0312fc2006-06-13 13:59:01 +0200243
244 /* copy prom cmdline parameters to kernel cmdline */
245 for (i = 1; i < argc; i++) {
246 strcat(arcs_cmdline, argv[i]);
247 if (i < (argc - 1))
248 strcat(arcs_cmdline, " ");
249 }
250}
251