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