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 sparc_cpu_type = NULL; 243 sparc_fpu_type = NULL; 244 if (psr_impl < ARRAY_SIZE(manufacturer_info)) 245 { 246 const struct cpu_info *cpu; 247 const struct fpu_info *fpu; 248 249 cpu = &manufacturer_info[psr_impl].cpu_info[0]; 250 while (cpu->psr_vers != -1) 251 { 252 if (cpu->psr_vers == psr_vers) { 253 sparc_cpu_type = cpu->name; 254 sparc_fpu_type = "No FPU"; 255 break; 256 } 257 cpu++; 258 } 259 fpu = &manufacturer_info[psr_impl].fpu_info[0]; 260 while (fpu->fp_vers != -1) 261 { 262 if (fpu->fp_vers == fpu_vers) { 263 sparc_fpu_type = fpu->name; 264 break; 265 } 266 fpu++; 267 } 268 } 269 if (sparc_cpu_type == NULL) 270 { 271 printk(KERN_ERR "CPU: Unknown chip, impl[0x%x] vers[0x%x]\n", 272 psr_impl, psr_vers); 273 sparc_cpu_type = "Unknown CPU"; 274 } 275 if (sparc_fpu_type == NULL) 276 { 277 printk(KERN_ERR "FPU: Unknown chip, impl[0x%x] vers[0x%x]\n", 278 psr_impl, fpu_vers); 279 sparc_fpu_type = "Unknown FPU"; 280 } 281 } 282 283 #ifdef CONFIG_SPARC32 284 void __cpuinit cpu_probe(void) 285 { 286 int psr_impl, psr_vers, fpu_vers; 287 int psr; 288 289 psr_impl = ((get_psr() >> 28) & 0xf); 290 psr_vers = ((get_psr() >> 24) & 0xf); 291 292 psr = get_psr(); 293 put_psr(psr | PSR_EF); 294 fpu_vers = ((get_fsr() >> 17) & 0x7); 295 put_psr(psr); 296 297 set_cpu_and_fpu(psr_impl, psr_vers, fpu_vers); 298 } 299 #else 300 static void __init sun4v_cpu_probe(void) 301 { 302 switch (sun4v_chip_type) { 303 case SUN4V_CHIP_NIAGARA1: 304 sparc_cpu_type = "UltraSparc T1 (Niagara)"; 305 sparc_fpu_type = "UltraSparc T1 integrated FPU"; 306 break; 307 308 case SUN4V_CHIP_NIAGARA2: 309 sparc_cpu_type = "UltraSparc T2 (Niagara2)"; 310 sparc_fpu_type = "UltraSparc T2 integrated FPU"; 311 break; 312 313 default: 314 printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n", 315 prom_cpu_compatible); 316 sparc_cpu_type = "Unknown SUN4V CPU"; 317 sparc_fpu_type = "Unknown SUN4V FPU"; 318 break; 319 } 320 } 321 322 static int __init cpu_type_probe(void) 323 { 324 if (tlb_type == hypervisor) { 325 sun4v_cpu_probe(); 326 } else { 327 unsigned long ver; 328 int manuf, impl; 329 330 __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver)); 331 332 manuf = ((ver >> 48) & 0xffff); 333 impl = ((ver >> 32) & 0xffff); 334 set_cpu_and_fpu(manuf, impl, impl); 335 } 336 return 0; 337 } 338 339 arch_initcall(cpu_type_probe); 340 #endif 341