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 0x17, 189 .cpu_info = { 190 CPU_PMU(0x10, "TI UltraSparc I (SpitFire)", "ultra12"), 191 CPU_PMU(0x11, "TI UltraSparc II (BlackBird)", "ultra12"), 192 CPU_PMU(0x12, "TI UltraSparc IIi (Sabre)", "ultra12"), 193 CPU_PMU(0x13, "TI UltraSparc IIe (Hummingbird)", "ultra12"), 194 CPU(-1, NULL) 195 }, 196 .fpu_info = { 197 FPU(0x10, "UltraSparc I integrated FPU"), 198 FPU(0x11, "UltraSparc II integrated FPU"), 199 FPU(0x12, "UltraSparc IIi integrated FPU"), 200 FPU(0x13, "UltraSparc IIe integrated FPU"), 201 FPU(-1, NULL) 202 } 203 },{ 204 0x22, 205 .cpu_info = { 206 CPU_PMU(0x10, "TI UltraSparc I (SpitFire)", "ultra12"), 207 CPU(-1, NULL) 208 }, 209 .fpu_info = { 210 FPU(0x10, "UltraSparc I integrated FPU"), 211 FPU(-1, NULL) 212 } 213 },{ 214 0x3e, 215 .cpu_info = { 216 CPU_PMU(0x14, "TI UltraSparc III (Cheetah)", "ultra3"), 217 CPU_PMU(0x15, "TI UltraSparc III+ (Cheetah+)", "ultra3+"), 218 CPU_PMU(0x16, "TI UltraSparc IIIi (Jalapeno)", "ultra3i"), 219 CPU_PMU(0x18, "TI UltraSparc IV (Jaguar)", "ultra3+"), 220 CPU_PMU(0x19, "TI UltraSparc IV+ (Panther)", "ultra4+"), 221 CPU_PMU(0x22, "TI UltraSparc IIIi+ (Serrano)", "ultra3i"), 222 CPU(-1, NULL) 223 }, 224 .fpu_info = { 225 FPU(0x14, "UltraSparc III integrated FPU"), 226 FPU(0x15, "UltraSparc III+ integrated FPU"), 227 FPU(0x16, "UltraSparc IIIi integrated FPU"), 228 FPU(0x18, "UltraSparc IV integrated FPU"), 229 FPU(0x19, "UltraSparc IV+ integrated FPU"), 230 FPU(0x22, "UltraSparc IIIi+ integrated FPU"), 231 FPU(-1, NULL) 232 } 233 }}; 234 235 /* In order to get the fpu type correct, you need to take the IDPROM's 236 * machine type value into consideration too. I will fix this. 237 */ 238 239 const char *sparc_cpu_type; 240 const char *sparc_fpu_type; 241 const char *sparc_pmu_type; 242 243 unsigned int fsr_storage; 244 245 static void set_cpu_and_fpu(int psr_impl, int psr_vers, int fpu_vers) 246 { 247 const struct manufacturer_info *manuf; 248 int i; 249 250 sparc_cpu_type = NULL; 251 sparc_fpu_type = NULL; 252 sparc_pmu_type = NULL; 253 manuf = NULL; 254 255 for (i = 0; i < ARRAY_SIZE(manufacturer_info); i++) 256 { 257 if (psr_impl == manufacturer_info[i].psr_impl) { 258 manuf = &manufacturer_info[i]; 259 break; 260 } 261 } 262 if (manuf != NULL) 263 { 264 const struct cpu_info *cpu; 265 const struct fpu_info *fpu; 266 267 cpu = &manuf->cpu_info[0]; 268 while (cpu->psr_vers != -1) 269 { 270 if (cpu->psr_vers == psr_vers) { 271 sparc_cpu_type = cpu->name; 272 sparc_pmu_type = cpu->pmu_name; 273 sparc_fpu_type = "No FPU"; 274 break; 275 } 276 cpu++; 277 } 278 fpu = &manuf->fpu_info[0]; 279 while (fpu->fp_vers != -1) 280 { 281 if (fpu->fp_vers == fpu_vers) { 282 sparc_fpu_type = fpu->name; 283 break; 284 } 285 fpu++; 286 } 287 } 288 if (sparc_cpu_type == NULL) 289 { 290 printk(KERN_ERR "CPU: Unknown chip, impl[0x%x] vers[0x%x]\n", 291 psr_impl, psr_vers); 292 sparc_cpu_type = "Unknown CPU"; 293 } 294 if (sparc_fpu_type == NULL) 295 { 296 printk(KERN_ERR "FPU: Unknown chip, impl[0x%x] vers[0x%x]\n", 297 psr_impl, fpu_vers); 298 sparc_fpu_type = "Unknown FPU"; 299 } 300 if (sparc_pmu_type == NULL) 301 sparc_pmu_type = "Unknown PMU"; 302 } 303 304 #ifdef CONFIG_SPARC32 305 void __cpuinit cpu_probe(void) 306 { 307 int psr_impl, psr_vers, fpu_vers; 308 int psr; 309 310 psr_impl = ((get_psr() >> 28) & 0xf); 311 psr_vers = ((get_psr() >> 24) & 0xf); 312 313 psr = get_psr(); 314 put_psr(psr | PSR_EF); 315 #ifdef CONFIG_SPARC_LEON 316 fpu_vers = 7; 317 #else 318 fpu_vers = ((get_fsr() >> 17) & 0x7); 319 #endif 320 321 put_psr(psr); 322 323 set_cpu_and_fpu(psr_impl, psr_vers, fpu_vers); 324 } 325 #else 326 static void __init sun4v_cpu_probe(void) 327 { 328 switch (sun4v_chip_type) { 329 case SUN4V_CHIP_NIAGARA1: 330 sparc_cpu_type = "UltraSparc T1 (Niagara)"; 331 sparc_fpu_type = "UltraSparc T1 integrated FPU"; 332 sparc_pmu_type = "niagara"; 333 break; 334 335 case SUN4V_CHIP_NIAGARA2: 336 sparc_cpu_type = "UltraSparc T2 (Niagara2)"; 337 sparc_fpu_type = "UltraSparc T2 integrated FPU"; 338 sparc_pmu_type = "niagara2"; 339 break; 340 341 default: 342 printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n", 343 prom_cpu_compatible); 344 sparc_cpu_type = "Unknown SUN4V CPU"; 345 sparc_fpu_type = "Unknown SUN4V FPU"; 346 break; 347 } 348 } 349 350 static int __init cpu_type_probe(void) 351 { 352 if (tlb_type == hypervisor) { 353 sun4v_cpu_probe(); 354 } else { 355 unsigned long ver; 356 int manuf, impl; 357 358 __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver)); 359 360 manuf = ((ver >> 48) & 0xffff); 361 impl = ((ver >> 32) & 0xffff); 362 set_cpu_and_fpu(manuf, impl, impl); 363 } 364 return 0; 365 } 366 367 arch_initcall(cpu_type_probe); 368 #endif 369