octeon-model.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. /***********************license start***************
  2. * Author: Cavium Networks
  3. *
  4. * Contact: support@caviumnetworks.com
  5. * This file is part of the OCTEON SDK
  6. *
  7. * Copyright (c) 2003-2010 Cavium Networks
  8. *
  9. * This file is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License, Version 2, as
  11. * published by the Free Software Foundation.
  12. *
  13. * This file is distributed in the hope that it will be useful, but
  14. * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
  15. * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
  16. * NONINFRINGEMENT. See the GNU General Public License for more
  17. * details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this file; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  22. * or visit http://www.gnu.org/licenses/.
  23. *
  24. * This file may also be available under a different license from Cavium.
  25. * Contact Cavium Networks for more information
  26. ***********************license end**************************************/
  27. #include <asm/octeon/octeon.h>
  28. enum octeon_feature_bits __octeon_feature_bits __read_mostly;
  29. EXPORT_SYMBOL_GPL(__octeon_feature_bits);
  30. /**
  31. * Read a byte of fuse data
  32. * @byte_addr: address to read
  33. *
  34. * Returns fuse value: 0 or 1
  35. */
  36. static uint8_t __init cvmx_fuse_read_byte(int byte_addr)
  37. {
  38. union cvmx_mio_fus_rcmd read_cmd;
  39. read_cmd.u64 = 0;
  40. read_cmd.s.addr = byte_addr;
  41. read_cmd.s.pend = 1;
  42. cvmx_write_csr(CVMX_MIO_FUS_RCMD, read_cmd.u64);
  43. while ((read_cmd.u64 = cvmx_read_csr(CVMX_MIO_FUS_RCMD))
  44. && read_cmd.s.pend)
  45. ;
  46. return read_cmd.s.dat;
  47. }
  48. /*
  49. * Version of octeon_model_get_string() that takes buffer as argument,
  50. * as running early in u-boot static/global variables don't work when
  51. * running from flash.
  52. */
  53. static const char *__init octeon_model_get_string_buffer(uint32_t chip_id,
  54. char *buffer)
  55. {
  56. const char *family;
  57. const char *core_model;
  58. char pass[4];
  59. int clock_mhz;
  60. const char *suffix;
  61. union cvmx_l2d_fus3 fus3;
  62. int num_cores;
  63. union cvmx_mio_fus_dat2 fus_dat2;
  64. union cvmx_mio_fus_dat3 fus_dat3;
  65. char fuse_model[10];
  66. uint32_t fuse_data = 0;
  67. fus3.u64 = 0;
  68. if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX))
  69. fus3.u64 = cvmx_read_csr(CVMX_L2D_FUS3);
  70. fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2);
  71. fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3);
  72. num_cores = cvmx_octeon_num_cores();
  73. /* Make sure the non existent devices look disabled */
  74. switch ((chip_id >> 8) & 0xff) {
  75. case 6: /* CN50XX */
  76. case 2: /* CN30XX */
  77. fus_dat3.s.nodfa_dte = 1;
  78. fus_dat3.s.nozip = 1;
  79. break;
  80. case 4: /* CN57XX or CN56XX */
  81. fus_dat3.s.nodfa_dte = 1;
  82. break;
  83. default:
  84. break;
  85. }
  86. /* Make a guess at the suffix */
  87. /* NSP = everything */
  88. /* EXP = No crypto */
  89. /* SCP = No DFA, No zip */
  90. /* CP = No DFA, No crypto, No zip */
  91. if (fus_dat3.s.nodfa_dte) {
  92. if (fus_dat2.s.nocrypto)
  93. suffix = "CP";
  94. else
  95. suffix = "SCP";
  96. } else if (fus_dat2.s.nocrypto)
  97. suffix = "EXP";
  98. else
  99. suffix = "NSP";
  100. if (!fus_dat2.s.nocrypto)
  101. __octeon_feature_bits |= OCTEON_HAS_CRYPTO;
  102. /*
  103. * Assume pass number is encoded using <5:3><2:0>. Exceptions
  104. * will be fixed later.
  105. */
  106. sprintf(pass, "%d.%d", (int)((chip_id >> 3) & 7) + 1, (int)chip_id & 7);
  107. /*
  108. * Use the number of cores to determine the last 2 digits of
  109. * the model number. There are some exceptions that are fixed
  110. * later.
  111. */
  112. switch (num_cores) {
  113. case 48:
  114. core_model = "90";
  115. break;
  116. case 44:
  117. core_model = "88";
  118. break;
  119. case 40:
  120. core_model = "85";
  121. break;
  122. case 32:
  123. core_model = "80";
  124. break;
  125. case 24:
  126. core_model = "70";
  127. break;
  128. case 16:
  129. core_model = "60";
  130. break;
  131. case 15:
  132. core_model = "58";
  133. break;
  134. case 14:
  135. core_model = "55";
  136. break;
  137. case 13:
  138. core_model = "52";
  139. break;
  140. case 12:
  141. core_model = "50";
  142. break;
  143. case 11:
  144. core_model = "48";
  145. break;
  146. case 10:
  147. core_model = "45";
  148. break;
  149. case 9:
  150. core_model = "42";
  151. break;
  152. case 8:
  153. core_model = "40";
  154. break;
  155. case 7:
  156. core_model = "38";
  157. break;
  158. case 6:
  159. core_model = "34";
  160. break;
  161. case 5:
  162. core_model = "32";
  163. break;
  164. case 4:
  165. core_model = "30";
  166. break;
  167. case 3:
  168. core_model = "25";
  169. break;
  170. case 2:
  171. core_model = "20";
  172. break;
  173. case 1:
  174. core_model = "10";
  175. break;
  176. default:
  177. core_model = "XX";
  178. break;
  179. }
  180. /* Now figure out the family, the first two digits */
  181. switch ((chip_id >> 8) & 0xff) {
  182. case 0: /* CN38XX, CN37XX or CN36XX */
  183. if (fus3.cn38xx.crip_512k) {
  184. /*
  185. * For some unknown reason, the 16 core one is
  186. * called 37 instead of 36.
  187. */
  188. if (num_cores >= 16)
  189. family = "37";
  190. else
  191. family = "36";
  192. } else
  193. family = "38";
  194. /*
  195. * This series of chips didn't follow the standard
  196. * pass numbering.
  197. */
  198. switch (chip_id & 0xf) {
  199. case 0:
  200. strcpy(pass, "1.X");
  201. break;
  202. case 1:
  203. strcpy(pass, "2.X");
  204. break;
  205. case 3:
  206. strcpy(pass, "3.X");
  207. break;
  208. default:
  209. strcpy(pass, "X.X");
  210. break;
  211. }
  212. break;
  213. case 1: /* CN31XX or CN3020 */
  214. if ((chip_id & 0x10) || fus3.cn31xx.crip_128k)
  215. family = "30";
  216. else
  217. family = "31";
  218. /*
  219. * This series of chips didn't follow the standard
  220. * pass numbering.
  221. */
  222. switch (chip_id & 0xf) {
  223. case 0:
  224. strcpy(pass, "1.0");
  225. break;
  226. case 2:
  227. strcpy(pass, "1.1");
  228. break;
  229. default:
  230. strcpy(pass, "X.X");
  231. break;
  232. }
  233. break;
  234. case 2: /* CN3010 or CN3005 */
  235. family = "30";
  236. /* A chip with half cache is an 05 */
  237. if (fus3.cn30xx.crip_64k)
  238. core_model = "05";
  239. /*
  240. * This series of chips didn't follow the standard
  241. * pass numbering.
  242. */
  243. switch (chip_id & 0xf) {
  244. case 0:
  245. strcpy(pass, "1.0");
  246. break;
  247. case 2:
  248. strcpy(pass, "1.1");
  249. break;
  250. default:
  251. strcpy(pass, "X.X");
  252. break;
  253. }
  254. break;
  255. case 3: /* CN58XX */
  256. family = "58";
  257. /* Special case. 4 core, half cache (CP with half cache) */
  258. if ((num_cores == 4) && fus3.cn58xx.crip_1024k && !strncmp(suffix, "CP", 2))
  259. core_model = "29";
  260. /* Pass 1 uses different encodings for pass numbers */
  261. if ((chip_id & 0xFF) < 0x8) {
  262. switch (chip_id & 0x3) {
  263. case 0:
  264. strcpy(pass, "1.0");
  265. break;
  266. case 1:
  267. strcpy(pass, "1.1");
  268. break;
  269. case 3:
  270. strcpy(pass, "1.2");
  271. break;
  272. default:
  273. strcpy(pass, "1.X");
  274. break;
  275. }
  276. }
  277. break;
  278. case 4: /* CN57XX, CN56XX, CN55XX, CN54XX */
  279. if (fus_dat2.cn56xx.raid_en) {
  280. if (fus3.cn56xx.crip_1024k)
  281. family = "55";
  282. else
  283. family = "57";
  284. if (fus_dat2.cn56xx.nocrypto)
  285. suffix = "SP";
  286. else
  287. suffix = "SSP";
  288. } else {
  289. if (fus_dat2.cn56xx.nocrypto)
  290. suffix = "CP";
  291. else {
  292. suffix = "NSP";
  293. if (fus_dat3.s.nozip)
  294. suffix = "SCP";
  295. if (fus_dat3.cn56xx.bar2_en)
  296. suffix = "NSPB2";
  297. }
  298. if (fus3.cn56xx.crip_1024k)
  299. family = "54";
  300. else
  301. family = "56";
  302. }
  303. break;
  304. case 6: /* CN50XX */
  305. family = "50";
  306. break;
  307. case 7: /* CN52XX */
  308. if (fus3.cn52xx.crip_256k)
  309. family = "51";
  310. else
  311. family = "52";
  312. break;
  313. case 0x93: /* CN61XX */
  314. family = "61";
  315. if (fus_dat2.cn61xx.nocrypto && fus_dat2.cn61xx.dorm_crypto)
  316. suffix = "AP";
  317. if (fus_dat2.cn61xx.nocrypto)
  318. suffix = "CP";
  319. else if (fus_dat2.cn61xx.dorm_crypto)
  320. suffix = "DAP";
  321. else if (fus_dat3.cn61xx.nozip)
  322. suffix = "SCP";
  323. break;
  324. case 0x90: /* CN63XX */
  325. family = "63";
  326. if (fus_dat3.s.l2c_crip == 2)
  327. family = "62";
  328. if (num_cores == 6) /* Other core counts match generic */
  329. core_model = "35";
  330. if (fus_dat2.cn63xx.nocrypto)
  331. suffix = "CP";
  332. else if (fus_dat2.cn63xx.dorm_crypto)
  333. suffix = "DAP";
  334. else if (fus_dat3.cn63xx.nozip)
  335. suffix = "SCP";
  336. else
  337. suffix = "AAP";
  338. break;
  339. case 0x92: /* CN66XX */
  340. family = "66";
  341. if (num_cores == 6) /* Other core counts match generic */
  342. core_model = "35";
  343. if (fus_dat2.cn66xx.nocrypto && fus_dat2.cn66xx.dorm_crypto)
  344. suffix = "AP";
  345. if (fus_dat2.cn66xx.nocrypto)
  346. suffix = "CP";
  347. else if (fus_dat2.cn66xx.dorm_crypto)
  348. suffix = "DAP";
  349. else if (fus_dat3.cn66xx.nozip)
  350. suffix = "SCP";
  351. else
  352. suffix = "AAP";
  353. break;
  354. case 0x91: /* CN68XX */
  355. family = "68";
  356. if (fus_dat2.cn68xx.nocrypto && fus_dat3.cn68xx.nozip)
  357. suffix = "CP";
  358. else if (fus_dat2.cn68xx.dorm_crypto)
  359. suffix = "DAP";
  360. else if (fus_dat3.cn68xx.nozip)
  361. suffix = "SCP";
  362. else if (fus_dat2.cn68xx.nocrypto)
  363. suffix = "SP";
  364. else
  365. suffix = "AAP";
  366. break;
  367. case 0x94: /* CNF71XX */
  368. family = "F71";
  369. if (fus_dat3.cnf71xx.nozip)
  370. suffix = "SCP";
  371. else
  372. suffix = "AAP";
  373. break;
  374. case 0x95: /* CN78XX */
  375. if (num_cores == 6) /* Other core counts match generic */
  376. core_model = "35";
  377. if (OCTEON_IS_MODEL(OCTEON_CN76XX))
  378. family = "76";
  379. else
  380. family = "78";
  381. if (fus_dat3.cn78xx.l2c_crip == 2)
  382. family = "77";
  383. if (fus_dat3.cn78xx.nozip
  384. && fus_dat3.cn78xx.nodfa_dte
  385. && fus_dat3.cn78xx.nohna_dte) {
  386. if (fus_dat3.cn78xx.nozip &&
  387. !fus_dat2.cn78xx.raid_en &&
  388. fus_dat3.cn78xx.nohna_dte) {
  389. suffix = "CP";
  390. } else {
  391. suffix = "SCP";
  392. }
  393. } else if (fus_dat2.cn78xx.raid_en == 0)
  394. suffix = "HCP";
  395. else
  396. suffix = "AAP";
  397. break;
  398. case 0x96: /* CN70XX */
  399. family = "70";
  400. if (cvmx_read_csr(CVMX_MIO_FUS_PDF) & (0x1ULL << 32))
  401. family = "71";
  402. if (fus_dat2.cn70xx.nocrypto)
  403. suffix = "CP";
  404. else if (fus_dat3.cn70xx.nodfa_dte)
  405. suffix = "SCP";
  406. else
  407. suffix = "AAP";
  408. break;
  409. case 0x97: /* CN73XX */
  410. if (num_cores == 6) /* Other core counts match generic */
  411. core_model = "35";
  412. family = "73";
  413. if (fus_dat3.cn73xx.l2c_crip == 2)
  414. family = "72";
  415. if (fus_dat3.cn73xx.nozip
  416. && fus_dat3.cn73xx.nodfa_dte
  417. && fus_dat3.cn73xx.nohna_dte) {
  418. if (!fus_dat2.cn73xx.raid_en)
  419. suffix = "CP";
  420. else
  421. suffix = "SCP";
  422. } else
  423. suffix = "AAP";
  424. break;
  425. case 0x98: /* CN75XX */
  426. family = "F75";
  427. if (fus_dat3.cn78xx.nozip
  428. && fus_dat3.cn78xx.nodfa_dte
  429. && fus_dat3.cn78xx.nohna_dte)
  430. suffix = "SCP";
  431. else
  432. suffix = "AAP";
  433. break;
  434. default:
  435. family = "XX";
  436. core_model = "XX";
  437. strcpy(pass, "X.X");
  438. suffix = "XXX";
  439. break;
  440. }
  441. clock_mhz = octeon_get_clock_rate() / 1000000;
  442. if (family[0] != '3') {
  443. int fuse_base = 384 / 8;
  444. if (family[0] == '6')
  445. fuse_base = 832 / 8;
  446. /* Check for model in fuses, overrides normal decode */
  447. /* This is _not_ valid for Octeon CN3XXX models */
  448. fuse_data |= cvmx_fuse_read_byte(fuse_base + 3);
  449. fuse_data = fuse_data << 8;
  450. fuse_data |= cvmx_fuse_read_byte(fuse_base + 2);
  451. fuse_data = fuse_data << 8;
  452. fuse_data |= cvmx_fuse_read_byte(fuse_base + 1);
  453. fuse_data = fuse_data << 8;
  454. fuse_data |= cvmx_fuse_read_byte(fuse_base);
  455. if (fuse_data & 0x7ffff) {
  456. int model = fuse_data & 0x3fff;
  457. int suffix = (fuse_data >> 14) & 0x1f;
  458. if (suffix && model) {
  459. /* Have both number and suffix in fuses, so both */
  460. sprintf(fuse_model, "%d%c", model, 'A' + suffix - 1);
  461. core_model = "";
  462. family = fuse_model;
  463. } else if (suffix && !model) {
  464. /* Only have suffix, so add suffix to 'normal' model number */
  465. sprintf(fuse_model, "%s%c", core_model, 'A' + suffix - 1);
  466. core_model = fuse_model;
  467. } else {
  468. /* Don't have suffix, so just use model from fuses */
  469. sprintf(fuse_model, "%d", model);
  470. core_model = "";
  471. family = fuse_model;
  472. }
  473. }
  474. }
  475. sprintf(buffer, "CN%s%sp%s-%d-%s", family, core_model, pass, clock_mhz, suffix);
  476. return buffer;
  477. }
  478. /**
  479. * Given the chip processor ID from COP0, this function returns a
  480. * string representing the chip model number. The string is of the
  481. * form CNXXXXpX.X-FREQ-SUFFIX.
  482. * - XXXX = The chip model number
  483. * - X.X = Chip pass number
  484. * - FREQ = Current frequency in Mhz
  485. * - SUFFIX = NSP, EXP, SCP, SSP, or CP
  486. *
  487. * @chip_id: Chip ID
  488. *
  489. * Returns Model string
  490. */
  491. const char *__init octeon_model_get_string(uint32_t chip_id)
  492. {
  493. static char buffer[32];
  494. return octeon_model_get_string_buffer(chip_id, buffer);
  495. }