cpu.c 12 KB

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