db544a6e23f33a448a6b14bd08f3cfec35e0baf4
[linux-2.6.git] / arch / mips / sni / sniprom.c
1 /*
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
12 #define DEBUG
13
14 #include <linux/kernel.h>
15 #include <linux/init.h>
16 #include <linux/string.h>
17 #include <linux/console.h>
18
19 #include <asm/addrspace.h>
20 #include <asm/sni.h>
21 #include <asm/mipsprom.h>
22 #include <asm/mipsregs.h>
23 #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
38 static int *(*__prom_putchar)(int)        = (int *(*)(int))PROM_ENTRY(PROM_PUTCHAR);
39
40 void prom_putchar(char c)
41 {
42         __prom_putchar(c);
43 }
44
45 static char *(*__prom_getenv)(char *)     = (char *(*)(char *))PROM_ENTRY(PROM_GETENV);
46 static void (*__prom_get_memconf)(void *) = (void (*)(void *))PROM_ENTRY(PROM_GET_MEMCONF);
47
48 char *prom_getenv (char *s)
49 {
50         return __prom_getenv(s);
51 }
52
53 void __init prom_free_prom_memory(void)
54 {
55 }
56
57 /*
58  * /proc/cpuinfo system type
59  *
60  */
61 static const char *systype = "Unknown";
62 const 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
75 static void __init sni_idprom_dump(void)
76 {
77         int     i;
78
79         pr_debug("SNI IDProm dump:\n");
80         for (i = 0; i < 256; i++) {
81                 if (i%16 == 0)
82                         pr_debug("%04x ", i);
83
84                 printk("%02x ", *(unsigned char *) (SNI_IDPROM_BASE + i));
85
86                 if (i % 16 == 15)
87                         printk("\n");
88         }
89 }
90 #endif
91
92 static void __init sni_mem_init(void )
93 {
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 */
104         memsize = *((unsigned char *) SNI_IDPROM_MEMSIZE) * 16;
105
106         pr_debug("IDProm memsize: %lu MByte\n", memsize);
107
108         /* get memory bank layout from prom */
109         __prom_get_memconf(&memconf);
110
111         pr_debug("prom_get_mem_conf memory configuration:\n");
112         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         }
120                 pr_debug("Bank%d: %08x @ %08x\n", i,
121                         memconf[i].size, memconf[i].base);
122                 add_memory_region(memconf[i].base, memconf[i].size, BOOT_MEM_RAM);
123         }
124 }
125
126 static 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);
150                 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);
154         }
155 }
156
157 void __init prom_init(void)
158 {
159         int argc = fw_arg0;
160         char **argv = (void *)fw_arg1;
161         int i;
162         int cputype;
163
164         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         }
236         pr_debug("Found SNI brdtype %02x name %s\n", sni_brd_type,systype);
237
238 #ifdef DEBUG
239         sni_idprom_dump();
240 #endif
241         sni_mem_init();
242         sni_console_setup();
243
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