cpu.c 12 KB

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