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