1 /* cpu.c: Dinky routines to look for the kind of Sparc cpu 2 * we are on. 3 * 4 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) 5 */ 6 7 #include <linux/kernel.h> 8 #include <linux/module.h> 9 #include <linux/init.h> 10 #include <linux/smp.h> 11 #include <linux/threads.h> 12 13 #include <asm/spitfire.h> 14 #include <asm/oplib.h> 15 #include <asm/page.h> 16 #include <asm/head.h> 17 #include <asm/psr.h> 18 #include <asm/mbus.h> 19 #include <asm/cpudata.h> 20 21 #include "kernel.h" 22 23 DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; 24 EXPORT_PER_CPU_SYMBOL(__cpu_data); 25 26 struct cpu_info { 27 int psr_vers; 28 const char *name; 29 }; 30 31 struct fpu_info { 32 int fp_vers; 33 const char *name; 34 }; 35 36 #define NOCPU 8 37 #define NOFPU 8 38 39 struct manufacturer_info { 40 int psr_impl; 41 struct cpu_info cpu_info[NOCPU]; 42 struct fpu_info fpu_info[NOFPU]; 43 }; 44 45 #define CPU(ver, _name) \ 46 { .psr_vers = ver, .name = _name } 47 48 #define FPU(ver, _name) \ 49 { .fp_vers = ver, .name = _name } 50 51 static const struct manufacturer_info __initconst manufacturer_info[] = { 52 { 53 0, 54 /* Sun4/100, 4/200, SLC */ 55 .cpu_info = { 56 CPU(0, "Fujitsu MB86900/1A or LSI L64831 SparcKIT-40"), 57 /* borned STP1012PGA */ 58 CPU(4, "Fujitsu MB86904"), 59 CPU(5, "Fujitsu TurboSparc MB86907"), 60 CPU(-1, NULL) 61 }, 62 .fpu_info = { 63 FPU(0, "Fujitsu MB86910 or Weitek WTL1164/5"), 64 FPU(1, "Fujitsu MB86911 or Weitek WTL1164/5 or LSI L64831"), 65 FPU(2, "LSI Logic L64802 or Texas Instruments ACT8847"), 66 /* SparcStation SLC, SparcStation1 */ 67 FPU(3, "Weitek WTL3170/2"), 68 /* SPARCstation-5 */ 69 FPU(4, "Lsi Logic/Meiko L64804 or compatible"), 70 FPU(-1, NULL) 71 } 72 },{ 73 1, 74 .cpu_info = { 75 /* SparcStation2, SparcServer 490 & 690 */ 76 CPU(0, "LSI Logic Corporation - L64811"), 77 /* SparcStation2 */ 78 CPU(1, "Cypress/ROSS CY7C601"), 79 /* Embedded controller */ 80 CPU(3, "Cypress/ROSS CY7C611"), 81 /* Ross Technologies HyperSparc */ 82 CPU(0xf, "ROSS HyperSparc RT620"), 83 CPU(0xe, "ROSS HyperSparc RT625 or RT626"), 84 CPU(-1, NULL) 85 }, 86 .fpu_info = { 87 FPU(0, "ROSS HyperSparc combined IU/FPU"), 88 FPU(1, "Lsi Logic L64814"), 89 FPU(2, "Texas Instruments TMS390-C602A"), 90 FPU(3, "Cypress CY7C602 FPU"), 91 FPU(-1, NULL) 92 } 93 },{ 94 2, 95 .cpu_info = { 96 /* ECL Implementation, CRAY S-MP Supercomputer... AIEEE! */ 97 /* Someone please write the code to support this beast! ;) */ 98 CPU(0, "Bipolar Integrated Technology - B5010"), 99 CPU(-1, NULL) 100 }, 101 .fpu_info = { 102 FPU(-1, NULL) 103 } 104 },{ 105 3, 106 .cpu_info = { 107 CPU(0, "LSI Logic Corporation - unknown-type"), 108 CPU(-1, NULL) 109 }, 110 .fpu_info = { 111 FPU(-1, NULL) 112 } 113 },{ 114 4, 115 .cpu_info = { 116 CPU(0, "Texas Instruments, Inc. - SuperSparc-(II)"), 117 /* SparcClassic -- borned STP1010TAB-50*/ 118 CPU(1, "Texas Instruments, Inc. - MicroSparc"), 119 CPU(2, "Texas Instruments, Inc. - MicroSparc II"), 120 CPU(3, "Texas Instruments, Inc. - SuperSparc 51"), 121 CPU(4, "Texas Instruments, Inc. - SuperSparc 61"), 122 CPU(5, "Texas Instruments, Inc. - unknown"), 123 CPU(-1, NULL) 124 }, 125 .fpu_info = { 126 /* SuperSparc 50 module */ 127 FPU(0, "SuperSparc on-chip FPU"), 128 /* SparcClassic */ 129 FPU(4, "TI MicroSparc on chip FPU"), 130 FPU(-1, NULL) 131 } 132 },{ 133 5, 134 .cpu_info = { 135 CPU(0, "Matsushita - MN10501"), 136 CPU(-1, NULL) 137 }, 138 .fpu_info = { 139 FPU(0, "Matsushita MN10501"), 140 FPU(-1, NULL) 141 } 142 },{ 143 6, 144 .cpu_info = { 145 CPU(0, "Philips Corporation - unknown"), 146 CPU(-1, NULL) 147 }, 148 .fpu_info = { 149 FPU(-1, NULL) 150 } 151 },{ 152 7, 153 .cpu_info = { 154 CPU(0, "Harvest VLSI Design Center, Inc. - unknown"), 155 CPU(-1, NULL) 156 }, 157 .fpu_info = { 158 FPU(-1, NULL) 159 } 160 },{ 161 8, 162 .cpu_info = { 163 CPU(0, "Systems and Processes Engineering Corporation (SPEC)"), 164 CPU(-1, NULL) 165 }, 166 .fpu_info = { 167 FPU(-1, NULL) 168 } 169 },{ 170 9, 171 .cpu_info = { 172 /* Gallium arsenide 200MHz, BOOOOGOOOOMIPS!!! */ 173 CPU(0, "Fujitsu or Weitek Power-UP"), 174 CPU(1, "Fujitsu or Weitek Power-UP"), 175 CPU(2, "Fujitsu or Weitek Power-UP"), 176 CPU(3, "Fujitsu or Weitek Power-UP"), 177 CPU(-1, NULL) 178 }, 179 .fpu_info = { 180 FPU(3, "Fujitsu or Weitek on-chip FPU"), 181 FPU(-1, NULL) 182 } 183 },{ 184 0x17, 185 .cpu_info = { 186 CPU(0x10, "TI UltraSparc I (SpitFire)"), 187 CPU(0x11, "TI UltraSparc II (BlackBird)"), 188 CPU(0x12, "TI UltraSparc IIi (Sabre)"), 189 CPU(0x13, "TI UltraSparc IIe (Hummingbird)"), 190 CPU(-1, NULL) 191 }, 192 .fpu_info = { 193 FPU(0x10, "UltraSparc I integrated FPU"), 194 FPU(0x11, "UltraSparc II integrated FPU"), 195 FPU(0x12, "UltraSparc IIi integrated FPU"), 196 FPU(0x13, "UltraSparc IIe integrated FPU"), 197 FPU(-1, NULL) 198 } 199 },{ 200 0x22, 201 .cpu_info = { 202 CPU(0x10, "TI UltraSparc I (SpitFire)"), 203 CPU(-1, NULL) 204 }, 205 .fpu_info = { 206 FPU(0x10, "UltraSparc I integrated FPU"), 207 FPU(-1, NULL) 208 } 209 },{ 210 0x3e, 211 .cpu_info = { 212 CPU(0x14, "TI UltraSparc III (Cheetah)"), 213 CPU(0x15, "TI UltraSparc III+ (Cheetah+)"), 214 CPU(0x16, "TI UltraSparc IIIi (Jalapeno)"), 215 CPU(0x18, "TI UltraSparc IV (Jaguar)"), 216 CPU(0x19, "TI UltraSparc IV+ (Panther)"), 217 CPU(0x22, "TI UltraSparc IIIi+ (Serrano)"), 218 CPU(-1, NULL) 219 }, 220 .fpu_info = { 221 FPU(0x14, "UltraSparc III integrated FPU"), 222 FPU(0x15, "UltraSparc III+ integrated FPU"), 223 FPU(0x16, "UltraSparc IIIi integrated FPU"), 224 FPU(0x18, "UltraSparc IV integrated FPU"), 225 FPU(0x19, "UltraSparc IV+ integrated FPU"), 226 FPU(0x22, "UltraSparc IIIi+ integrated FPU"), 227 FPU(-1, NULL) 228 } 229 }}; 230 231 /* In order to get the fpu type correct, you need to take the IDPROM's 232 * machine type value into consideration too. I will fix this. 233 */ 234 235 const char *sparc_cpu_type; 236 const char *sparc_fpu_type; 237 238 unsigned int fsr_storage; 239 240 static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers) 241 { 242 const struct manufacturer_info *manuf; 243 int i; 244 245 sparc_cpu_type = NULL; 246 sparc_fpu_type = NULL; 247 manuf = NULL; 248 249 for (i = 0; i < ARRAY_SIZE(manufacturer_info); i++) 250 { 251 if (psr_impl == manufacturer_info[i].psr_impl) { 252 manuf = &manufacturer_info[i]; 253 break; 254 } 255 } 256 if (manuf != NULL) 257 { 258 const struct cpu_info *cpu; 259 const struct fpu_info *fpu; 260 261 cpu = &manuf->cpu_info[0]; 262 while (cpu->psr_vers != -1) 263 { 264 if (cpu->psr_vers == psr_vers) { 265 sparc_cpu_type = cpu->name; 266 sparc_fpu_type = "No FPU"; 267 break; 268 } 269 cpu++; 270 } 271 fpu = &manuf->fpu_info[0]; 272 while (fpu->fp_vers != -1) 273 { 274 if (fpu->fp_vers == fpu_vers) { 275 sparc_fpu_type = fpu->name; 276 break; 277 } 278 fpu++; 279 } 280 } 281 if (sparc_cpu_type == NULL) 282 { 283 printk(KERN_ERR "CPU: Unknown chip, impl[0x%x] vers[0x%x]\n", 284 psr_impl, psr_vers); 285 sparc_cpu_type = "Unknown CPU"; 286 } 287 if (sparc_fpu_type == NULL) 288 { 289 printk(KERN_ERR "FPU: Unknown chip, impl[0x%x] vers[0x%x]\n", 290 psr_impl, fpu_vers); 291 sparc_fpu_type = "Unknown FPU"; 292 } 293 } 294 295 #ifdef CONFIG_SPARC32 296 void __cpuinit cpu_probe(void) 297 { 298 int psr_impl, psr_vers, fpu_vers; 299 int psr; 300 301 psr_impl = ((get_psr() >> 28) & 0xf); 302 psr_vers = ((get_psr() >> 24) & 0xf); 303 304 psr = get_psr(); 305 put_psr(psr | PSR_EF); 306 fpu_vers = ((get_fsr() >> 17) & 0x7); 307 put_psr(psr); 308 309 set_cpu_and_fpu(psr_impl, psr_vers, fpu_vers); 310 } 311 #else 312 static void __init sun4v_cpu_probe(void) 313 { 314 switch (sun4v_chip_type) { 315 case SUN4V_CHIP_NIAGARA1: 316 sparc_cpu_type = "UltraSparc T1 (Niagara)"; 317 sparc_fpu_type = "UltraSparc T1 integrated FPU"; 318 break; 319 320 case SUN4V_CHIP_NIAGARA2: 321 sparc_cpu_type = "UltraSparc T2 (Niagara2)"; 322 sparc_fpu_type = "UltraSparc T2 integrated FPU"; 323 break; 324 325 default: 326 printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n", 327 prom_cpu_compatible); 328 sparc_cpu_type = "Unknown SUN4V CPU"; 329 sparc_fpu_type = "Unknown SUN4V FPU"; 330 break; 331 } 332 } 333 334 static int __init cpu_type_probe(void) 335 { 336 if (tlb_type == hypervisor) { 337 sun4v_cpu_probe(); 338 } else { 339 unsigned long ver; 340 int manuf, impl; 341 342 __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver)); 343 344 manuf = ((ver >> 48) & 0xffff); 345 impl = ((ver >> 32) & 0xffff); 346 set_cpu_and_fpu(manuf, impl, impl); 347 } 348 return 0; 349 } 350 351 arch_initcall(cpu_type_probe); 352 #endif 353