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