00a03a6e8f58a21486f69b80ce8428ad339b1c7d
[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/bootinfo.h>
23
24 /* special SNI prom calls */
25 /*
26  * This does not exist in all proms - SINIX compares
27  * the prom env variable "version" against "2.0008"
28  * or greater. If lesser it tries to probe interesting
29  * registers
30  */
31 #define PROM_GET_MEMCONF        58
32
33 #define PROM_VEC                (u64 *)CKSEG1ADDR(0x1fc00000)
34 #define PROM_ENTRY(x)           (PROM_VEC + (x))
35
36
37 static int *(*__prom_putchar)(int)        = (int *(*)(int))PROM_ENTRY(PROM_PUTCHAR);
38
39 void prom_putchar(char c)
40 {
41         __prom_putchar(c);
42 }
43
44 static char *(*__prom_getenv)(char *)     = (char *(*)(char *))PROM_ENTRY(PROM_GETENV);
45 static void (*__prom_get_memconf)(void *) = (void (*)(void *))PROM_ENTRY(PROM_GET_MEMCONF);
46
47 char *prom_getenv (char *s)
48 {
49         return __prom_getenv(s);
50 }
51
52 void __init prom_free_prom_memory(void)
53 {
54 }
55
56 /*
57  * /proc/cpuinfo system type
58  *
59  */
60 static const char *systype = "Unknown";
61 const char *get_system_type(void)
62 {
63         return systype;
64 }
65
66 #define SNI_IDPROM_BASE                0xbff00000
67 #define SNI_IDPROM_MEMSIZE             (SNI_IDPROM_BASE+0x28)  /* Memsize in 16MB quantities */
68 #define SNI_IDPROM_BRDTYPE             (SNI_IDPROM_BASE+0x29)  /* Board Type */
69 #define SNI_IDPROM_CPUTYPE             (SNI_IDPROM_BASE+0x30)  /* CPU Type */
70
71 #define SNI_IDPROM_SIZE 0x1000
72
73 #ifdef DEBUG
74 static void sni_idprom_dump(void)
75 {
76         int     i;
77
78         pr_debug("SNI IDProm dump:\n");
79         for (i = 0; i < 256; i++) {
80                 if (i%16 == 0)
81                         pr_debug("%04x ", i);
82
83                 printk("%02x ", *(unsigned char *) (SNI_IDPROM_BASE + i));
84
85                 if (i % 16 == 15)
86                         printk("\n");
87         }
88 }
89 #endif
90
91 static void sni_mem_init(void )
92 {
93         int i, memsize;
94         struct membank {
95                 u32             size;
96                 u32             base;
97                 u32             size2;
98                 u32             pad1;
99                 u32             pad2;
100         } memconf[8];
101
102         /* MemSIZE from prom in 16MByte chunks */
103         memsize = *((unsigned char *) SNI_IDPROM_MEMSIZE) * 16;
104
105         pr_debug("IDProm memsize: %lu MByte\n", memsize);
106
107         /* get memory bank layout from prom */
108         __prom_get_memconf(&memconf);
109
110         pr_debug("prom_get_mem_conf memory configuration:\n");
111         for (i = 0;i < 8 && memconf[i].size; i++) {
112                 if (sni_brd_type == SNI_BRD_PCI_TOWER ||
113                     sni_brd_type == SNI_BRD_PCI_TOWER_CPLUS) {
114                         if (memconf[i].base >= 0x20000000 &&
115                             memconf[i].base <  0x30000000) {
116                                 memconf[i].base -= 0x20000000;
117                         }
118         }
119                 pr_debug("Bank%d: %08x @ %08x\n", i,
120                         memconf[i].size, memconf[i].base);
121                 add_memory_region(memconf[i].base, memconf[i].size, BOOT_MEM_RAM);
122         }
123 }
124
125 static void __init sni_console_setup(void)
126 {
127         char *ctype;
128         char *cdev;
129         char *baud;
130         int port;
131         static char options[8];
132
133         cdev = prom_getenv ("console_dev");
134         if (strncmp (cdev, "tty", 3) == 0) {
135                 ctype = prom_getenv ("console");
136                 switch (*ctype) {
137                 default:
138                 case 'l':
139                         port = 0;
140                         baud = prom_getenv("lbaud");
141                         break;
142                 case 'r':
143                         port = 1;
144                         baud = prom_getenv("rbaud");
145                         break;
146                 }
147                 if (baud)
148                         strcpy(options, baud);
149                 if (strncmp (cdev, "tty552", 6) == 0)
150                         add_preferred_console("ttyS", port, baud ? options : NULL);
151                 else
152                         add_preferred_console("ttySC", port, baud ? options : NULL);
153         }
154 }
155
156 void __init prom_init(void)
157 {
158         int argc = fw_arg0;
159         char **argv = (void *)fw_arg1;
160         int i;
161         int cputype;
162
163         sni_brd_type = *(unsigned char *)SNI_IDPROM_BRDTYPE;
164         cputype = *(unsigned char *)SNI_IDPROM_CPUTYPE;
165         switch (sni_brd_type) {
166         case SNI_BRD_TOWER_OASIC:
167                 switch (cputype) {
168                 case SNI_CPU_M8030:
169                         systype = "RM400-330";
170                         break;
171                 case SNI_CPU_M8031:
172                         systype = "RM400-430";
173                         break;
174                 case SNI_CPU_M8037:
175                         systype = "RM400-530";
176                         break;
177                 case SNI_CPU_M8034:
178                         systype = "RM400-730";
179                         break;
180                 default:
181                         systype = "RM400-xxx";
182                         break;
183                 }
184                 break;
185         case SNI_BRD_MINITOWER:
186                 switch (cputype) {
187                 case SNI_CPU_M8021:
188                 case SNI_CPU_M8043:
189                         systype = "RM400-120";
190                         break;
191                 case SNI_CPU_M8040:
192                         systype = "RM400-220";
193                         break;
194                 case SNI_CPU_M8053:
195                         systype = "RM400-225";
196                         break;
197                 case SNI_CPU_M8050:
198                         systype = "RM400-420";
199                         break;
200                 default:
201                         systype = "RM400-xxx";
202                         break;
203                 }
204                 break;
205         case SNI_BRD_PCI_TOWER:
206                 systype = "RM400-Cxx";
207                 break;
208         case SNI_BRD_RM200:
209                 systype = "RM200-xxx";
210                 break;
211         case SNI_BRD_PCI_MTOWER:
212                 systype = "RM300-Cxx";
213                 break;
214         case SNI_BRD_PCI_DESKTOP:
215                 switch (read_c0_prid() & 0xff00) {
216                 case PRID_IMP_R4600:
217                 case PRID_IMP_R4700:
218                         systype = "RM200-C20";
219                         break;
220                 case PRID_IMP_R5000:
221                         systype = "RM200-C40";
222                         break;
223                 default:
224                         systype = "RM200-Cxx";
225                         break;
226                 }
227                 break;
228         case SNI_BRD_PCI_TOWER_CPLUS:
229                 systype = "RM400-Exx";
230                 break;
231         case SNI_BRD_PCI_MTOWER_CPLUS:
232                 systype = "RM300-Exx";
233                 break;
234         }
235         pr_debug("Found SNI brdtype %02x name %s\n", sni_brd_type,systype);
236
237 #ifdef DEBUG
238         sni_idprom_dump();
239 #endif
240         sni_mem_init();
241         sni_console_setup();
242
243         /* copy prom cmdline parameters to kernel cmdline */
244         for (i = 1; i < argc; i++) {
245                 strcat(arcs_cmdline, argv[i]);
246                 if (i < (argc - 1))
247                         strcat(arcs_cmdline, " ");
248         }
249 }
250