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