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/seq_file.h> 8#include <linux/kernel.h> 9#include <linux/export.h> 10#include <linux/init.h> 11#include <linux/smp.h> 12#include <linux/threads.h> 13 14#include <asm/spitfire.h> 15#include <asm/pgtable.h> 16#include <asm/oplib.h> 17#include <asm/setup.h> 18#include <asm/page.h> 19#include <asm/head.h> 20#include <asm/psr.h> 21#include <asm/mbus.h> 22#include <asm/cpudata.h> 23 24#include "kernel.h" 25#include "entry.h" 26 27DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; 28EXPORT_PER_CPU_SYMBOL(__cpu_data); 29 30int ncpus_probed; 31unsigned int fsr_storage; 32 33struct cpu_info { 34 int psr_vers; 35 const char *name; 36 const char *pmu_name; 37}; 38 39struct fpu_info { 40 int fp_vers; 41 const char *name; 42}; 43 44#define NOCPU 8 45#define NOFPU 8 46 47struct manufacturer_info { 48 int psr_impl; 49 struct cpu_info cpu_info[NOCPU]; 50 struct fpu_info fpu_info[NOFPU]; 51}; 52 53#define CPU(ver, _name) \ 54{ .psr_vers = ver, .name = _name } 55 56#define CPU_PMU(ver, _name, _pmu_name) \ 57{ .psr_vers = ver, .name = _name, .pmu_name = _pmu_name } 58 59#define FPU(ver, _name) \ 60{ .fp_vers = ver, .name = _name } 61 62static const struct manufacturer_info __initconst manufacturer_info[] = { 63{ 64 0, 65 /* Sun4/100, 4/200, SLC */ 66 .cpu_info = { 67 CPU(0, "Fujitsu MB86900/1A or LSI L64831 SparcKIT-40"), 68 /* borned STP1012PGA */ 69 CPU(4, "Fujitsu MB86904"), 70 CPU(5, "Fujitsu TurboSparc MB86907"), 71 CPU(-1, NULL) 72 }, 73 .fpu_info = { 74 FPU(0, "Fujitsu MB86910 or Weitek WTL1164/5"), 75 FPU(1, "Fujitsu MB86911 or Weitek WTL1164/5 or LSI L64831"), 76 FPU(2, "LSI Logic L64802 or Texas Instruments ACT8847"), 77 /* SparcStation SLC, SparcStation1 */ 78 FPU(3, "Weitek WTL3170/2"), 79 /* SPARCstation-5 */ 80 FPU(4, "Lsi Logic/Meiko L64804 or compatible"), 81 FPU(-1, NULL) 82 } 83},{ 84 1, 85 .cpu_info = { 86 /* SparcStation2, SparcServer 490 & 690 */ 87 CPU(0, "LSI Logic Corporation - L64811"), 88 /* SparcStation2 */ 89 CPU(1, "Cypress/ROSS CY7C601"), 90 /* Embedded controller */ 91 CPU(3, "Cypress/ROSS CY7C611"), 92 /* Ross Technologies HyperSparc */ 93 CPU(0xf, "ROSS HyperSparc RT620"), 94 CPU(0xe, "ROSS HyperSparc RT625 or RT626"), 95 CPU(-1, NULL) 96 }, 97 .fpu_info = { 98 FPU(0, "ROSS HyperSparc combined IU/FPU"), 99 FPU(1, "Lsi Logic L64814"), 100 FPU(2, "Texas Instruments TMS390-C602A"), 101 FPU(3, "Cypress CY7C602 FPU"), 102 FPU(-1, NULL) 103 } 104},{ 105 2, 106 .cpu_info = { 107 /* ECL Implementation, CRAY S-MP Supercomputer... AIEEE! */ 108 /* Someone please write the code to support this beast! ;) */ 109 CPU(0, "Bipolar Integrated Technology - B5010"), 110 CPU(-1, NULL) 111 }, 112 .fpu_info = { 113 FPU(-1, NULL) 114 } 115},{ 116 3, 117 .cpu_info = { 118 CPU(0, "LSI Logic Corporation - unknown-type"), 119 CPU(-1, NULL) 120 }, 121 .fpu_info = { 122 FPU(-1, NULL) 123 } 124},{ 125 PSR_IMPL_TI, 126 .cpu_info = { 127 CPU(0, "Texas Instruments, Inc. - SuperSparc-(II)"), 128 /* SparcClassic -- borned STP1010TAB-50*/ 129 CPU(1, "Texas Instruments, Inc. - MicroSparc"), 130 CPU(2, "Texas Instruments, Inc. - MicroSparc II"), 131 CPU(3, "Texas Instruments, Inc. - SuperSparc 51"), 132 CPU(4, "Texas Instruments, Inc. - SuperSparc 61"), 133 CPU(5, "Texas Instruments, Inc. - unknown"), 134 CPU(-1, NULL) 135 }, 136 .fpu_info = { 137 /* SuperSparc 50 module */ 138 FPU(0, "SuperSparc on-chip FPU"), 139 /* SparcClassic */ 140 FPU(4, "TI MicroSparc on chip FPU"), 141 FPU(-1, NULL) 142 } 143},{ 144 5, 145 .cpu_info = { 146 CPU(0, "Matsushita - MN10501"), 147 CPU(-1, NULL) 148 }, 149 .fpu_info = { 150 FPU(0, "Matsushita MN10501"), 151 FPU(-1, NULL) 152 } 153},{ 154 6, 155 .cpu_info = { 156 CPU(0, "Philips Corporation - unknown"), 157 CPU(-1, NULL) 158 }, 159 .fpu_info = { 160 FPU(-1, NULL) 161 } 162},{ 163 7, 164 .cpu_info = { 165 CPU(0, "Harvest VLSI Design Center, Inc. - unknown"), 166 CPU(-1, NULL) 167 }, 168 .fpu_info = { 169 FPU(-1, NULL) 170 } 171},{ 172 8, 173 .cpu_info = { 174 CPU(0, "Systems and Processes Engineering Corporation (SPEC)"), 175 CPU(-1, NULL) 176 }, 177 .fpu_info = { 178 FPU(-1, NULL) 179 } 180},{ 181 9, 182 .cpu_info = { 183 /* Gallium arsenide 200MHz, BOOOOGOOOOMIPS!!! */ 184 CPU(0, "Fujitsu or Weitek Power-UP"), 185 CPU(1, "Fujitsu or Weitek Power-UP"), 186 CPU(2, "Fujitsu or Weitek Power-UP"), 187 CPU(3, "Fujitsu or Weitek Power-UP"), 188 CPU(-1, NULL) 189 }, 190 .fpu_info = { 191 FPU(3, "Fujitsu or Weitek on-chip FPU"), 192 FPU(-1, NULL) 193 } 194},{ 195 PSR_IMPL_LEON, /* Aeroflex Gaisler */ 196 .cpu_info = { 197 CPU(3, "LEON"), 198 CPU(-1, NULL) 199 }, 200 .fpu_info = { 201 FPU(2, "GRFPU"), 202 FPU(3, "GRFPU-Lite"), 203 FPU(-1, NULL) 204 } 205},{ 206 0x17, 207 .cpu_info = { 208 CPU_PMU(0x10, "TI UltraSparc I (SpitFire)", "ultra12"), 209 CPU_PMU(0x11, "TI UltraSparc II (BlackBird)", "ultra12"), 210 CPU_PMU(0x12, "TI UltraSparc IIi (Sabre)", "ultra12"), 211 CPU_PMU(0x13, "TI UltraSparc IIe (Hummingbird)", "ultra12"), 212 CPU(-1, NULL) 213 }, 214 .fpu_info = { 215 FPU(0x10, "UltraSparc I integrated FPU"), 216 FPU(0x11, "UltraSparc II integrated FPU"), 217 FPU(0x12, "UltraSparc IIi integrated FPU"), 218 FPU(0x13, "UltraSparc IIe integrated FPU"), 219 FPU(-1, NULL) 220 } 221},{ 222 0x22, 223 .cpu_info = { 224 CPU_PMU(0x10, "TI UltraSparc I (SpitFire)", "ultra12"), 225 CPU(-1, NULL) 226 }, 227 .fpu_info = { 228 FPU(0x10, "UltraSparc I integrated FPU"), 229 FPU(-1, NULL) 230 } 231},{ 232 0x3e, 233 .cpu_info = { 234 CPU_PMU(0x14, "TI UltraSparc III (Cheetah)", "ultra3"), 235 CPU_PMU(0x15, "TI UltraSparc III+ (Cheetah+)", "ultra3+"), 236 CPU_PMU(0x16, "TI UltraSparc IIIi (Jalapeno)", "ultra3i"), 237 CPU_PMU(0x18, "TI UltraSparc IV (Jaguar)", "ultra3+"), 238 CPU_PMU(0x19, "TI UltraSparc IV+ (Panther)", "ultra4+"), 239 CPU_PMU(0x22, "TI UltraSparc IIIi+ (Serrano)", "ultra3i"), 240 CPU(-1, NULL) 241 }, 242 .fpu_info = { 243 FPU(0x14, "UltraSparc III integrated FPU"), 244 FPU(0x15, "UltraSparc III+ integrated FPU"), 245 FPU(0x16, "UltraSparc IIIi integrated FPU"), 246 FPU(0x18, "UltraSparc IV integrated FPU"), 247 FPU(0x19, "UltraSparc IV+ integrated FPU"), 248 FPU(0x22, "UltraSparc IIIi+ integrated FPU"), 249 FPU(-1, NULL) 250 } 251}}; 252 253/* In order to get the fpu type correct, you need to take the IDPROM's 254 * machine type value into consideration too. I will fix this. 255 */ 256 257static const char *sparc_cpu_type; 258static const char *sparc_fpu_type; 259const char *sparc_pmu_type; 260 261 262static void __init set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers) 263{ 264 const struct manufacturer_info *manuf; 265 int i; 266 267 sparc_cpu_type = NULL; 268 sparc_fpu_type = NULL; 269 sparc_pmu_type = NULL; 270 manuf = NULL; 271 272 for (i = 0; i < ARRAY_SIZE(manufacturer_info); i++) 273 { 274 if (psr_impl == manufacturer_info[i].psr_impl) { 275 manuf = &manufacturer_info[i]; 276 break; 277 } 278 } 279 if (manuf != NULL) 280 { 281 const struct cpu_info *cpu; 282 const struct fpu_info *fpu; 283 284 cpu = &manuf->cpu_info[0]; 285 while (cpu->psr_vers != -1) 286 { 287 if (cpu->psr_vers == psr_vers) { 288 sparc_cpu_type = cpu->name; 289 sparc_pmu_type = cpu->pmu_name; 290 sparc_fpu_type = "No FPU"; 291 break; 292 } 293 cpu++; 294 } 295 fpu = &manuf->fpu_info[0]; 296 while (fpu->fp_vers != -1) 297 { 298 if (fpu->fp_vers == fpu_vers) { 299 sparc_fpu_type = fpu->name; 300 break; 301 } 302 fpu++; 303 } 304 } 305 if (sparc_cpu_type == NULL) 306 { 307 printk(KERN_ERR "CPU: Unknown chip, impl[0x%x] vers[0x%x]\n", 308 psr_impl, psr_vers); 309 sparc_cpu_type = "Unknown CPU"; 310 } 311 if (sparc_fpu_type == NULL) 312 { 313 printk(KERN_ERR "FPU: Unknown chip, impl[0x%x] vers[0x%x]\n", 314 psr_impl, fpu_vers); 315 sparc_fpu_type = "Unknown FPU"; 316 } 317 if (sparc_pmu_type == NULL) 318 sparc_pmu_type = "Unknown PMU"; 319} 320 321#ifdef CONFIG_SPARC32 322static int show_cpuinfo(struct seq_file *m, void *__unused) 323{ 324 seq_printf(m, 325 "cpu\t\t: %s\n" 326 "fpu\t\t: %s\n" 327 "promlib\t\t: Version %d Revision %d\n" 328 "prom\t\t: %d.%d\n" 329 "type\t\t: %s\n" 330 "ncpus probed\t: %d\n" 331 "ncpus active\t: %d\n" 332#ifndef CONFIG_SMP 333 "CPU0Bogo\t: %lu.%02lu\n" 334 "CPU0ClkTck\t: %ld\n" 335#endif 336 , 337 sparc_cpu_type, 338 sparc_fpu_type , 339 romvec->pv_romvers, 340 prom_rev, 341 romvec->pv_printrev >> 16, 342 romvec->pv_printrev & 0xffff, 343 &cputypval[0], 344 ncpus_probed, 345 num_online_cpus() 346#ifndef CONFIG_SMP 347 , cpu_data(0).udelay_val/(500000/HZ), 348 (cpu_data(0).udelay_val/(5000/HZ)) % 100, 349 cpu_data(0).clock_tick 350#endif 351 ); 352 353#ifdef CONFIG_SMP 354 smp_bogo(m); 355#endif 356 mmu_info(m); 357#ifdef CONFIG_SMP 358 smp_info(m); 359#endif 360 return 0; 361} 362#endif /* CONFIG_SPARC32 */ 363 364#ifdef CONFIG_SPARC64 365unsigned int dcache_parity_tl1_occurred; 366unsigned int icache_parity_tl1_occurred; 367 368 369static int show_cpuinfo(struct seq_file *m, void *__unused) 370{ 371 seq_printf(m, 372 "cpu\t\t: %s\n" 373 "fpu\t\t: %s\n" 374 "pmu\t\t: %s\n" 375 "prom\t\t: %s\n" 376 "type\t\t: %s\n" 377 "ncpus probed\t: %d\n" 378 "ncpus active\t: %d\n" 379 "D$ parity tl1\t: %u\n" 380 "I$ parity tl1\t: %u\n" 381#ifndef CONFIG_SMP 382 "Cpu0ClkTck\t: %016lx\n" 383#endif 384 , 385 sparc_cpu_type, 386 sparc_fpu_type, 387 sparc_pmu_type, 388 prom_version, 389 ((tlb_type == hypervisor) ? 390 "sun4v" : 391 "sun4u"), 392 ncpus_probed, 393 num_online_cpus(), 394 dcache_parity_tl1_occurred, 395 icache_parity_tl1_occurred 396#ifndef CONFIG_SMP 397 , cpu_data(0).clock_tick 398#endif 399 ); 400 cpucap_info(m); 401#ifdef CONFIG_SMP 402 smp_bogo(m); 403#endif 404 mmu_info(m); 405#ifdef CONFIG_SMP 406 smp_info(m); 407#endif 408 return 0; 409} 410#endif /* CONFIG_SPARC64 */ 411 412static void *c_start(struct seq_file *m, loff_t *pos) 413{ 414 /* The pointer we are returning is arbitrary, 415 * it just has to be non-NULL and not IS_ERR 416 * in the success case. 417 */ 418 return *pos == 0 ? &c_start : NULL; 419} 420 421static void *c_next(struct seq_file *m, void *v, loff_t *pos) 422{ 423 ++*pos; 424 return c_start(m, pos); 425} 426 427static void c_stop(struct seq_file *m, void *v) 428{ 429} 430 431const struct seq_operations cpuinfo_op = { 432 .start =c_start, 433 .next = c_next, 434 .stop = c_stop, 435 .show = show_cpuinfo, 436}; 437 438#ifdef CONFIG_SPARC32 439static int __init cpu_type_probe(void) 440{ 441 int psr_impl, psr_vers, fpu_vers; 442 int psr; 443 444 psr_impl = ((get_psr() >> PSR_IMPL_SHIFT) & PSR_IMPL_SHIFTED_MASK); 445 psr_vers = ((get_psr() >> PSR_VERS_SHIFT) & PSR_VERS_SHIFTED_MASK); 446 447 psr = get_psr(); 448 put_psr(psr | PSR_EF); 449 450 if (psr_impl == PSR_IMPL_LEON) 451 fpu_vers = get_psr() & PSR_EF ? ((get_fsr() >> 17) & 0x7) : 7; 452 else 453 fpu_vers = ((get_fsr() >> 17) & 0x7); 454 455 put_psr(psr); 456 457 set_cpu_and_fpu(psr_impl, psr_vers, fpu_vers); 458 459 return 0; 460} 461#endif /* CONFIG_SPARC32 */ 462 463#ifdef CONFIG_SPARC64 464static void __init sun4v_cpu_probe(void) 465{ 466 switch (sun4v_chip_type) { 467 case SUN4V_CHIP_NIAGARA1: 468 sparc_cpu_type = "UltraSparc T1 (Niagara)"; 469 sparc_fpu_type = "UltraSparc T1 integrated FPU"; 470 sparc_pmu_type = "niagara"; 471 break; 472 473 case SUN4V_CHIP_NIAGARA2: 474 sparc_cpu_type = "UltraSparc T2 (Niagara2)"; 475 sparc_fpu_type = "UltraSparc T2 integrated FPU"; 476 sparc_pmu_type = "niagara2"; 477 break; 478 479 case SUN4V_CHIP_NIAGARA3: 480 sparc_cpu_type = "UltraSparc T3 (Niagara3)"; 481 sparc_fpu_type = "UltraSparc T3 integrated FPU"; 482 sparc_pmu_type = "niagara3"; 483 break; 484 485 case SUN4V_CHIP_NIAGARA4: 486 sparc_cpu_type = "UltraSparc T4 (Niagara4)"; 487 sparc_fpu_type = "UltraSparc T4 integrated FPU"; 488 sparc_pmu_type = "niagara4"; 489 break; 490 491 case SUN4V_CHIP_NIAGARA5: 492 sparc_cpu_type = "UltraSparc T5 (Niagara5)"; 493 sparc_fpu_type = "UltraSparc T5 integrated FPU"; 494 sparc_pmu_type = "niagara5"; 495 break; 496 497 case SUN4V_CHIP_SPARC_M6: 498 sparc_cpu_type = "SPARC-M6"; 499 sparc_fpu_type = "SPARC-M6 integrated FPU"; 500 sparc_pmu_type = "sparc-m6"; 501 break; 502 503 case SUN4V_CHIP_SPARC_M7: 504 sparc_cpu_type = "SPARC-M7"; 505 sparc_fpu_type = "SPARC-M7 integrated FPU"; 506 sparc_pmu_type = "sparc-m7"; 507 break; 508 509 case SUN4V_CHIP_SPARC64X: 510 sparc_cpu_type = "SPARC64-X"; 511 sparc_fpu_type = "SPARC64-X integrated FPU"; 512 sparc_pmu_type = "sparc64-x"; 513 break; 514 515 default: 516 printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n", 517 prom_cpu_compatible); 518 sparc_cpu_type = "Unknown SUN4V CPU"; 519 sparc_fpu_type = "Unknown SUN4V FPU"; 520 sparc_pmu_type = "Unknown SUN4V PMU"; 521 break; 522 } 523} 524 525static int __init cpu_type_probe(void) 526{ 527 if (tlb_type == hypervisor) { 528 sun4v_cpu_probe(); 529 } else { 530 unsigned long ver; 531 int manuf, impl; 532 533 __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver)); 534 535 manuf = ((ver >> 48) & 0xffff); 536 impl = ((ver >> 32) & 0xffff); 537 set_cpu_and_fpu(manuf, impl, impl); 538 } 539 return 0; 540} 541#endif /* CONFIG_SPARC64 */ 542 543early_initcall(cpu_type_probe); 544