octeon-model.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  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_CN6XXX))
  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_pop(cvmx_read_csr(CVMX_CIU_FUSE));
  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 32:
  114. core_model = "80";
  115. break;
  116. case 24:
  117. core_model = "70";
  118. break;
  119. case 16:
  120. core_model = "60";
  121. break;
  122. case 15:
  123. core_model = "58";
  124. break;
  125. case 14:
  126. core_model = "55";
  127. break;
  128. case 13:
  129. core_model = "52";
  130. break;
  131. case 12:
  132. core_model = "50";
  133. break;
  134. case 11:
  135. core_model = "48";
  136. break;
  137. case 10:
  138. core_model = "45";
  139. break;
  140. case 9:
  141. core_model = "42";
  142. break;
  143. case 8:
  144. core_model = "40";
  145. break;
  146. case 7:
  147. core_model = "38";
  148. break;
  149. case 6:
  150. core_model = "34";
  151. break;
  152. case 5:
  153. core_model = "32";
  154. break;
  155. case 4:
  156. core_model = "30";
  157. break;
  158. case 3:
  159. core_model = "25";
  160. break;
  161. case 2:
  162. core_model = "20";
  163. break;
  164. case 1:
  165. core_model = "10";
  166. break;
  167. default:
  168. core_model = "XX";
  169. break;
  170. }
  171. /* Now figure out the family, the first two digits */
  172. switch ((chip_id >> 8) & 0xff) {
  173. case 0: /* CN38XX, CN37XX or CN36XX */
  174. if (fus3.cn38xx.crip_512k) {
  175. /*
  176. * For some unknown reason, the 16 core one is
  177. * called 37 instead of 36.
  178. */
  179. if (num_cores >= 16)
  180. family = "37";
  181. else
  182. family = "36";
  183. } else
  184. family = "38";
  185. /*
  186. * This series of chips didn't follow the standard
  187. * pass numbering.
  188. */
  189. switch (chip_id & 0xf) {
  190. case 0:
  191. strcpy(pass, "1.X");
  192. break;
  193. case 1:
  194. strcpy(pass, "2.X");
  195. break;
  196. case 3:
  197. strcpy(pass, "3.X");
  198. break;
  199. default:
  200. strcpy(pass, "X.X");
  201. break;
  202. }
  203. break;
  204. case 1: /* CN31XX or CN3020 */
  205. if ((chip_id & 0x10) || fus3.cn31xx.crip_128k)
  206. family = "30";
  207. else
  208. family = "31";
  209. /*
  210. * This series of chips didn't follow the standard
  211. * pass numbering.
  212. */
  213. switch (chip_id & 0xf) {
  214. case 0:
  215. strcpy(pass, "1.0");
  216. break;
  217. case 2:
  218. strcpy(pass, "1.1");
  219. break;
  220. default:
  221. strcpy(pass, "X.X");
  222. break;
  223. }
  224. break;
  225. case 2: /* CN3010 or CN3005 */
  226. family = "30";
  227. /* A chip with half cache is an 05 */
  228. if (fus3.cn30xx.crip_64k)
  229. core_model = "05";
  230. /*
  231. * This series of chips didn't follow the standard
  232. * pass numbering.
  233. */
  234. switch (chip_id & 0xf) {
  235. case 0:
  236. strcpy(pass, "1.0");
  237. break;
  238. case 2:
  239. strcpy(pass, "1.1");
  240. break;
  241. default:
  242. strcpy(pass, "X.X");
  243. break;
  244. }
  245. break;
  246. case 3: /* CN58XX */
  247. family = "58";
  248. /* Special case. 4 core, half cache (CP with half cache) */
  249. if ((num_cores == 4) && fus3.cn58xx.crip_1024k && !strncmp(suffix, "CP", 2))
  250. core_model = "29";
  251. /* Pass 1 uses different encodings for pass numbers */
  252. if ((chip_id & 0xFF) < 0x8) {
  253. switch (chip_id & 0x3) {
  254. case 0:
  255. strcpy(pass, "1.0");
  256. break;
  257. case 1:
  258. strcpy(pass, "1.1");
  259. break;
  260. case 3:
  261. strcpy(pass, "1.2");
  262. break;
  263. default:
  264. strcpy(pass, "1.X");
  265. break;
  266. }
  267. }
  268. break;
  269. case 4: /* CN57XX, CN56XX, CN55XX, CN54XX */
  270. if (fus_dat2.cn56xx.raid_en) {
  271. if (fus3.cn56xx.crip_1024k)
  272. family = "55";
  273. else
  274. family = "57";
  275. if (fus_dat2.cn56xx.nocrypto)
  276. suffix = "SP";
  277. else
  278. suffix = "SSP";
  279. } else {
  280. if (fus_dat2.cn56xx.nocrypto)
  281. suffix = "CP";
  282. else {
  283. suffix = "NSP";
  284. if (fus_dat3.s.nozip)
  285. suffix = "SCP";
  286. if (fus_dat3.s.bar2_en)
  287. suffix = "NSPB2";
  288. }
  289. if (fus3.cn56xx.crip_1024k)
  290. family = "54";
  291. else
  292. family = "56";
  293. }
  294. break;
  295. case 6: /* CN50XX */
  296. family = "50";
  297. break;
  298. case 7: /* CN52XX */
  299. if (fus3.cn52xx.crip_256k)
  300. family = "51";
  301. else
  302. family = "52";
  303. break;
  304. case 0x93: /* CN61XX */
  305. family = "61";
  306. if (fus_dat2.cn61xx.nocrypto && fus_dat2.cn61xx.dorm_crypto)
  307. suffix = "AP";
  308. if (fus_dat2.cn61xx.nocrypto)
  309. suffix = "CP";
  310. else if (fus_dat2.cn61xx.dorm_crypto)
  311. suffix = "DAP";
  312. else if (fus_dat3.cn61xx.nozip)
  313. suffix = "SCP";
  314. break;
  315. case 0x90: /* CN63XX */
  316. family = "63";
  317. if (fus_dat3.s.l2c_crip == 2)
  318. family = "62";
  319. if (num_cores == 6) /* Other core counts match generic */
  320. core_model = "35";
  321. if (fus_dat2.cn63xx.nocrypto)
  322. suffix = "CP";
  323. else if (fus_dat2.cn63xx.dorm_crypto)
  324. suffix = "DAP";
  325. else if (fus_dat3.cn63xx.nozip)
  326. suffix = "SCP";
  327. else
  328. suffix = "AAP";
  329. break;
  330. case 0x92: /* CN66XX */
  331. family = "66";
  332. if (num_cores == 6) /* Other core counts match generic */
  333. core_model = "35";
  334. if (fus_dat2.cn66xx.nocrypto && fus_dat2.cn66xx.dorm_crypto)
  335. suffix = "AP";
  336. if (fus_dat2.cn66xx.nocrypto)
  337. suffix = "CP";
  338. else if (fus_dat2.cn66xx.dorm_crypto)
  339. suffix = "DAP";
  340. else if (fus_dat3.cn66xx.nozip)
  341. suffix = "SCP";
  342. else
  343. suffix = "AAP";
  344. break;
  345. case 0x91: /* CN68XX */
  346. family = "68";
  347. if (fus_dat2.cn68xx.nocrypto && fus_dat3.cn68xx.nozip)
  348. suffix = "CP";
  349. else if (fus_dat2.cn68xx.dorm_crypto)
  350. suffix = "DAP";
  351. else if (fus_dat3.cn68xx.nozip)
  352. suffix = "SCP";
  353. else if (fus_dat2.cn68xx.nocrypto)
  354. suffix = "SP";
  355. else
  356. suffix = "AAP";
  357. break;
  358. default:
  359. family = "XX";
  360. core_model = "XX";
  361. strcpy(pass, "X.X");
  362. suffix = "XXX";
  363. break;
  364. }
  365. clock_mhz = octeon_get_clock_rate() / 1000000;
  366. if (family[0] != '3') {
  367. int fuse_base = 384 / 8;
  368. if (family[0] == '6')
  369. fuse_base = 832 / 8;
  370. /* Check for model in fuses, overrides normal decode */
  371. /* This is _not_ valid for Octeon CN3XXX models */
  372. fuse_data |= cvmx_fuse_read_byte(fuse_base + 3);
  373. fuse_data = fuse_data << 8;
  374. fuse_data |= cvmx_fuse_read_byte(fuse_base + 2);
  375. fuse_data = fuse_data << 8;
  376. fuse_data |= cvmx_fuse_read_byte(fuse_base + 1);
  377. fuse_data = fuse_data << 8;
  378. fuse_data |= cvmx_fuse_read_byte(fuse_base);
  379. if (fuse_data & 0x7ffff) {
  380. int model = fuse_data & 0x3fff;
  381. int suffix = (fuse_data >> 14) & 0x1f;
  382. if (suffix && model) {
  383. /* Have both number and suffix in fuses, so both */
  384. sprintf(fuse_model, "%d%c", model, 'A' + suffix - 1);
  385. core_model = "";
  386. family = fuse_model;
  387. } else if (suffix && !model) {
  388. /* Only have suffix, so add suffix to 'normal' model number */
  389. sprintf(fuse_model, "%s%c", core_model, 'A' + suffix - 1);
  390. core_model = fuse_model;
  391. } else {
  392. /* Don't have suffix, so just use model from fuses */
  393. sprintf(fuse_model, "%d", model);
  394. core_model = "";
  395. family = fuse_model;
  396. }
  397. }
  398. }
  399. sprintf(buffer, "CN%s%sp%s-%d-%s", family, core_model, pass, clock_mhz, suffix);
  400. return buffer;
  401. }
  402. /**
  403. * Given the chip processor ID from COP0, this function returns a
  404. * string representing the chip model number. The string is of the
  405. * form CNXXXXpX.X-FREQ-SUFFIX.
  406. * - XXXX = The chip model number
  407. * - X.X = Chip pass number
  408. * - FREQ = Current frequency in Mhz
  409. * - SUFFIX = NSP, EXP, SCP, SSP, or CP
  410. *
  411. * @chip_id: Chip ID
  412. *
  413. * Returns Model string
  414. */
  415. const char *__init octeon_model_get_string(uint32_t chip_id)
  416. {
  417. static char buffer[32];
  418. return octeon_model_get_string_buffer(chip_id, buffer);
  419. }