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 37static int *(*__prom_putchar)(int) = (int *(*)(int))PROM_ENTRY(PROM_PUTCHAR); 38 39void prom_putchar(char c) 40{ 41 __prom_putchar(c); 42} 43 44static char *(*__prom_getenv)(char *) = (char *(*)(char *))PROM_ENTRY(PROM_GETENV); 45static void (*__prom_get_memconf)(void *) = (void (*)(void *))PROM_ENTRY(PROM_GET_MEMCONF); 46 47char *prom_getenv (char *s) 48{ 49 return __prom_getenv(s); 50} 51 52void __init prom_free_prom_memory(void) 53{ 54} 55 56/* 57 * /proc/cpuinfo system type 58 * 59 */ 60static const char *systype = "Unknown"; 61const 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 74static 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 91static 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 125static 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 add_preferred_console("ttyS", port, baud ? options : NULL); 150 } 151} 152 153void __init prom_init(void) 154{ 155 int argc = fw_arg0; 156 char **argv = (void *)fw_arg1; 157 int i; 158 int cputype; 159 160 sni_brd_type = *(unsigned char *)SNI_IDPROM_BRDTYPE; 161 cputype = *(unsigned char *)SNI_IDPROM_CPUTYPE; 162 switch (sni_brd_type) { 163 case SNI_BRD_TOWER_OASIC: 164 switch (cputype) { 165 case SNI_CPU_M8030: 166 systype = "RM400-330"; 167 break; 168 case SNI_CPU_M8031: 169 systype = "RM400-430"; 170 break; 171 case SNI_CPU_M8037: 172 systype = "RM400-530"; 173 break; 174 case SNI_CPU_M8034: 175 systype = "RM400-730"; 176 break; 177 default: 178 systype = "RM400-xxx"; 179 break; 180 } 181 break; 182 case SNI_BRD_MINITOWER: 183 switch (cputype) { 184 case SNI_CPU_M8021: 185 case SNI_CPU_M8043: 186 systype = "RM400-120"; 187 break; 188 case SNI_CPU_M8040: 189 systype = "RM400-220"; 190 break; 191 case SNI_CPU_M8053: 192 systype = "RM400-225"; 193 break; 194 case SNI_CPU_M8050: 195 systype = "RM400-420"; 196 break; 197 default: 198 systype = "RM400-xxx"; 199 break; 200 } 201 break; 202 case SNI_BRD_PCI_TOWER: 203 systype = "RM400-Cxx"; 204 break; 205 case SNI_BRD_RM200: 206 systype = "RM200-xxx"; 207 break; 208 case SNI_BRD_PCI_MTOWER: 209 systype = "RM300-Cxx"; 210 break; 211 case SNI_BRD_PCI_DESKTOP: 212 switch (read_c0_prid() & 0xff00) { 213 case PRID_IMP_R4600: 214 case PRID_IMP_R4700: 215 systype = "RM200-C20"; 216 break; 217 case PRID_IMP_R5000: 218 systype = "RM200-C40"; 219 break; 220 default: 221 systype = "RM200-Cxx"; 222 break; 223 } 224 break; 225 case SNI_BRD_PCI_TOWER_CPLUS: 226 systype = "RM400-Exx"; 227 break; 228 case SNI_BRD_PCI_MTOWER_CPLUS: 229 systype = "RM300-Exx"; 230 break; 231 } 232 pr_debug("Found SNI brdtype %02x name %s\n", sni_brd_type,systype); 233 234#ifdef DEBUG 235 sni_idprom_dump(); 236#endif 237 sni_mem_init(); 238 sni_console_setup(); 239 240 /* copy prom cmdline parameters to kernel cmdline */ 241 for (i = 1; i < argc; i++) { 242 strcat(arcs_cmdline, argv[i]); 243 if (i < (argc - 1)) 244 strcat(arcs_cmdline, " "); 245 } 246} 247