octeon-model.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  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-2008 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. /*
  28. * File defining functions for working with different Octeon
  29. * models.
  30. */
  31. #include <asm/octeon/octeon.h>
  32. /**
  33. * Given the chip processor ID from COP0, this function returns a
  34. * string representing the chip model number. The string is of the
  35. * form CNXXXXpX.X-FREQ-SUFFIX.
  36. * - XXXX = The chip model number
  37. * - X.X = Chip pass number
  38. * - FREQ = Current frequency in Mhz
  39. * - SUFFIX = NSP, EXP, SCP, SSP, or CP
  40. *
  41. * @chip_id: Chip ID
  42. *
  43. * Returns Model string
  44. */
  45. const char *octeon_model_get_string(uint32_t chip_id)
  46. {
  47. static char buffer[32];
  48. return octeon_model_get_string_buffer(chip_id, buffer);
  49. }
  50. /*
  51. * Version of octeon_model_get_string() that takes buffer as argument,
  52. * as running early in u-boot static/global variables don't work when
  53. * running from flash.
  54. */
  55. const char *octeon_model_get_string_buffer(uint32_t chip_id, char *buffer)
  56. {
  57. const char *family;
  58. const char *core_model;
  59. char pass[4];
  60. int clock_mhz;
  61. const char *suffix;
  62. union cvmx_l2d_fus3 fus3;
  63. int num_cores;
  64. union cvmx_mio_fus_dat2 fus_dat2;
  65. union cvmx_mio_fus_dat3 fus_dat3;
  66. char fuse_model[10];
  67. uint32_t fuse_data = 0;
  68. fus3.u64 = cvmx_read_csr(CVMX_L2D_FUS3);
  69. fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2);
  70. fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3);
  71. num_cores = cvmx_octeon_num_cores();
  72. /* Make sure the non existant devices look disabled */
  73. switch ((chip_id >> 8) & 0xff) {
  74. case 6: /* CN50XX */
  75. case 2: /* CN30XX */
  76. fus_dat3.s.nodfa_dte = 1;
  77. fus_dat3.s.nozip = 1;
  78. break;
  79. case 4: /* CN57XX or CN56XX */
  80. fus_dat3.s.nodfa_dte = 1;
  81. break;
  82. default:
  83. break;
  84. }
  85. /* Make a guess at the suffix */
  86. /* NSP = everything */
  87. /* EXP = No crypto */
  88. /* SCP = No DFA, No zip */
  89. /* CP = No DFA, No crypto, No zip */
  90. if (fus_dat3.s.nodfa_dte) {
  91. if (fus_dat2.s.nocrypto)
  92. suffix = "CP";
  93. else
  94. suffix = "SCP";
  95. } else if (fus_dat2.s.nocrypto)
  96. suffix = "EXP";
  97. else
  98. suffix = "NSP";
  99. /*
  100. * Assume pass number is encoded using <5:3><2:0>. Exceptions
  101. * will be fixed later.
  102. */
  103. sprintf(pass, "%u.%u", ((chip_id >> 3) & 7) + 1, chip_id & 7);
  104. /*
  105. * Use the number of cores to determine the last 2 digits of
  106. * the model number. There are some exceptions that are fixed
  107. * later.
  108. */
  109. switch (num_cores) {
  110. case 16:
  111. core_model = "60";
  112. break;
  113. case 15:
  114. core_model = "58";
  115. break;
  116. case 14:
  117. core_model = "55";
  118. break;
  119. case 13:
  120. core_model = "52";
  121. break;
  122. case 12:
  123. core_model = "50";
  124. break;
  125. case 11:
  126. core_model = "48";
  127. break;
  128. case 10:
  129. core_model = "45";
  130. break;
  131. case 9:
  132. core_model = "42";
  133. break;
  134. case 8:
  135. core_model = "40";
  136. break;
  137. case 7:
  138. core_model = "38";
  139. break;
  140. case 6:
  141. core_model = "34";
  142. break;
  143. case 5:
  144. core_model = "32";
  145. break;
  146. case 4:
  147. core_model = "30";
  148. break;
  149. case 3:
  150. core_model = "25";
  151. break;
  152. case 2:
  153. core_model = "20";
  154. break;
  155. case 1:
  156. core_model = "10";
  157. break;
  158. default:
  159. core_model = "XX";
  160. break;
  161. }
  162. /* Now figure out the family, the first two digits */
  163. switch ((chip_id >> 8) & 0xff) {
  164. case 0: /* CN38XX, CN37XX or CN36XX */
  165. if (fus3.cn38xx.crip_512k) {
  166. /*
  167. * For some unknown reason, the 16 core one is
  168. * called 37 instead of 36.
  169. */
  170. if (num_cores >= 16)
  171. family = "37";
  172. else
  173. family = "36";
  174. } else
  175. family = "38";
  176. /*
  177. * This series of chips didn't follow the standard
  178. * pass numbering.
  179. */
  180. switch (chip_id & 0xf) {
  181. case 0:
  182. strcpy(pass, "1.X");
  183. break;
  184. case 1:
  185. strcpy(pass, "2.X");
  186. break;
  187. case 3:
  188. strcpy(pass, "3.X");
  189. break;
  190. default:
  191. strcpy(pass, "X.X");
  192. break;
  193. }
  194. break;
  195. case 1: /* CN31XX or CN3020 */
  196. if ((chip_id & 0x10) || fus3.cn31xx.crip_128k)
  197. family = "30";
  198. else
  199. family = "31";
  200. /*
  201. * This series of chips didn't follow the standard
  202. * pass numbering.
  203. */
  204. switch (chip_id & 0xf) {
  205. case 0:
  206. strcpy(pass, "1.0");
  207. break;
  208. case 2:
  209. strcpy(pass, "1.1");
  210. break;
  211. default:
  212. strcpy(pass, "X.X");
  213. break;
  214. }
  215. break;
  216. case 2: /* CN3010 or CN3005 */
  217. family = "30";
  218. /* A chip with half cache is an 05 */
  219. if (fus3.cn30xx.crip_64k)
  220. core_model = "05";
  221. /*
  222. * This series of chips didn't follow the standard
  223. * pass numbering.
  224. */
  225. switch (chip_id & 0xf) {
  226. case 0:
  227. strcpy(pass, "1.0");
  228. break;
  229. case 2:
  230. strcpy(pass, "1.1");
  231. break;
  232. default:
  233. strcpy(pass, "X.X");
  234. break;
  235. }
  236. break;
  237. case 3: /* CN58XX */
  238. family = "58";
  239. /* Special case. 4 core, no crypto */
  240. if ((num_cores == 4) && fus_dat2.cn38xx.nocrypto)
  241. core_model = "29";
  242. /* Pass 1 uses different encodings for pass numbers */
  243. if ((chip_id & 0xFF) < 0x8) {
  244. switch (chip_id & 0x3) {
  245. case 0:
  246. strcpy(pass, "1.0");
  247. break;
  248. case 1:
  249. strcpy(pass, "1.1");
  250. break;
  251. case 3:
  252. strcpy(pass, "1.2");
  253. break;
  254. default:
  255. strcpy(pass, "1.X");
  256. break;
  257. }
  258. }
  259. break;
  260. case 4: /* CN57XX, CN56XX, CN55XX, CN54XX */
  261. if (fus_dat2.cn56xx.raid_en) {
  262. if (fus3.cn56xx.crip_1024k)
  263. family = "55";
  264. else
  265. family = "57";
  266. if (fus_dat2.cn56xx.nocrypto)
  267. suffix = "SP";
  268. else
  269. suffix = "SSP";
  270. } else {
  271. if (fus_dat2.cn56xx.nocrypto)
  272. suffix = "CP";
  273. else {
  274. suffix = "NSP";
  275. if (fus_dat3.s.nozip)
  276. suffix = "SCP";
  277. }
  278. if (fus3.cn56xx.crip_1024k)
  279. family = "54";
  280. else
  281. family = "56";
  282. }
  283. break;
  284. case 6: /* CN50XX */
  285. family = "50";
  286. break;
  287. case 7: /* CN52XX */
  288. if (fus3.cn52xx.crip_256k)
  289. family = "51";
  290. else
  291. family = "52";
  292. break;
  293. default:
  294. family = "XX";
  295. core_model = "XX";
  296. strcpy(pass, "X.X");
  297. suffix = "XXX";
  298. break;
  299. }
  300. clock_mhz = octeon_get_clock_rate() / 1000000;
  301. if (family[0] != '3') {
  302. /* Check for model in fuses, overrides normal decode */
  303. /* This is _not_ valid for Octeon CN3XXX models */
  304. fuse_data |= cvmx_fuse_read_byte(51);
  305. fuse_data = fuse_data << 8;
  306. fuse_data |= cvmx_fuse_read_byte(50);
  307. fuse_data = fuse_data << 8;
  308. fuse_data |= cvmx_fuse_read_byte(49);
  309. fuse_data = fuse_data << 8;
  310. fuse_data |= cvmx_fuse_read_byte(48);
  311. if (fuse_data & 0x7ffff) {
  312. int model = fuse_data & 0x3fff;
  313. int suffix = (fuse_data >> 14) & 0x1f;
  314. if (suffix && model) {
  315. /*
  316. * Have both number and suffix in
  317. * fuses, so both
  318. */
  319. sprintf(fuse_model, "%d%c",
  320. model, 'A' + suffix - 1);
  321. core_model = "";
  322. family = fuse_model;
  323. } else if (suffix && !model) {
  324. /*
  325. * Only have suffix, so add suffix to
  326. * 'normal' model number.
  327. */
  328. sprintf(fuse_model, "%s%c", core_model,
  329. 'A' + suffix - 1);
  330. core_model = fuse_model;
  331. } else {
  332. /*
  333. * Don't have suffix, so just use
  334. * model from fuses.
  335. */
  336. sprintf(fuse_model, "%d", model);
  337. core_model = "";
  338. family = fuse_model;
  339. }
  340. }
  341. }
  342. sprintf(buffer, "CN%s%sp%s-%d-%s",
  343. family, core_model, pass, clock_mhz, suffix);
  344. return buffer;
  345. }