162306a36Sopenharmony_ci/***********************license start*************** 262306a36Sopenharmony_ci * Author: Cavium Networks 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Contact: support@caviumnetworks.com 562306a36Sopenharmony_ci * This file is part of the OCTEON SDK 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (c) 2003-2017 Cavium, Inc. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * This file is free software; you can redistribute it and/or modify 1062306a36Sopenharmony_ci * it under the terms of the GNU General Public License, Version 2, as 1162306a36Sopenharmony_ci * published by the Free Software Foundation. 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * This file is distributed in the hope that it will be useful, but 1462306a36Sopenharmony_ci * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 1562306a36Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 1662306a36Sopenharmony_ci * NONINFRINGEMENT. See the GNU General Public License for more 1762306a36Sopenharmony_ci * details. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * You should have received a copy of the GNU General Public License 2062306a36Sopenharmony_ci * along with this file; if not, write to the Free Software 2162306a36Sopenharmony_ci * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 2262306a36Sopenharmony_ci * or visit http://www.gnu.org/licenses/. 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * This file may also be available under a different license from Cavium. 2562306a36Sopenharmony_ci * Contact Cavium Networks for more information 2662306a36Sopenharmony_ci ***********************license end**************************************/ 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#include <asm/octeon/octeon.h> 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cienum octeon_feature_bits __octeon_feature_bits __read_mostly; 3162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__octeon_feature_bits); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/** 3462306a36Sopenharmony_ci * Read a byte of fuse data 3562306a36Sopenharmony_ci * @byte_addr: address to read 3662306a36Sopenharmony_ci * 3762306a36Sopenharmony_ci * Returns fuse value: 0 or 1 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_cistatic uint8_t __init cvmx_fuse_read_byte(int byte_addr) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci union cvmx_mio_fus_rcmd read_cmd; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci read_cmd.u64 = 0; 4462306a36Sopenharmony_ci read_cmd.s.addr = byte_addr; 4562306a36Sopenharmony_ci read_cmd.s.pend = 1; 4662306a36Sopenharmony_ci cvmx_write_csr(CVMX_MIO_FUS_RCMD, read_cmd.u64); 4762306a36Sopenharmony_ci while ((read_cmd.u64 = cvmx_read_csr(CVMX_MIO_FUS_RCMD)) 4862306a36Sopenharmony_ci && read_cmd.s.pend) 4962306a36Sopenharmony_ci ; 5062306a36Sopenharmony_ci return read_cmd.s.dat; 5162306a36Sopenharmony_ci} 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci/* 5462306a36Sopenharmony_ci * Version of octeon_model_get_string() that takes buffer as argument, 5562306a36Sopenharmony_ci * as running early in u-boot static/global variables don't work when 5662306a36Sopenharmony_ci * running from flash. 5762306a36Sopenharmony_ci */ 5862306a36Sopenharmony_cistatic const char *__init octeon_model_get_string_buffer(uint32_t chip_id, 5962306a36Sopenharmony_ci char *buffer) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci const char *family; 6262306a36Sopenharmony_ci const char *core_model; 6362306a36Sopenharmony_ci char pass[4]; 6462306a36Sopenharmony_ci int clock_mhz; 6562306a36Sopenharmony_ci const char *suffix; 6662306a36Sopenharmony_ci int num_cores; 6762306a36Sopenharmony_ci union cvmx_mio_fus_dat2 fus_dat2; 6862306a36Sopenharmony_ci union cvmx_mio_fus_dat3 fus_dat3; 6962306a36Sopenharmony_ci char fuse_model[10]; 7062306a36Sopenharmony_ci uint32_t fuse_data = 0; 7162306a36Sopenharmony_ci uint64_t l2d_fus3 = 0; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX)) 7462306a36Sopenharmony_ci l2d_fus3 = (cvmx_read_csr(CVMX_L2D_FUS3) >> 34) & 0x3; 7562306a36Sopenharmony_ci fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2); 7662306a36Sopenharmony_ci fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3); 7762306a36Sopenharmony_ci num_cores = cvmx_octeon_num_cores(); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci /* Make sure the non existent devices look disabled */ 8062306a36Sopenharmony_ci switch ((chip_id >> 8) & 0xff) { 8162306a36Sopenharmony_ci case 6: /* CN50XX */ 8262306a36Sopenharmony_ci case 2: /* CN30XX */ 8362306a36Sopenharmony_ci fus_dat3.s.nodfa_dte = 1; 8462306a36Sopenharmony_ci fus_dat3.s.nozip = 1; 8562306a36Sopenharmony_ci break; 8662306a36Sopenharmony_ci case 4: /* CN57XX or CN56XX */ 8762306a36Sopenharmony_ci fus_dat3.s.nodfa_dte = 1; 8862306a36Sopenharmony_ci break; 8962306a36Sopenharmony_ci default: 9062306a36Sopenharmony_ci break; 9162306a36Sopenharmony_ci } 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci /* Make a guess at the suffix */ 9462306a36Sopenharmony_ci /* NSP = everything */ 9562306a36Sopenharmony_ci /* EXP = No crypto */ 9662306a36Sopenharmony_ci /* SCP = No DFA, No zip */ 9762306a36Sopenharmony_ci /* CP = No DFA, No crypto, No zip */ 9862306a36Sopenharmony_ci if (fus_dat3.s.nodfa_dte) { 9962306a36Sopenharmony_ci if (fus_dat2.s.nocrypto) 10062306a36Sopenharmony_ci suffix = "CP"; 10162306a36Sopenharmony_ci else 10262306a36Sopenharmony_ci suffix = "SCP"; 10362306a36Sopenharmony_ci } else if (fus_dat2.s.nocrypto) 10462306a36Sopenharmony_ci suffix = "EXP"; 10562306a36Sopenharmony_ci else 10662306a36Sopenharmony_ci suffix = "NSP"; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci if (!fus_dat2.s.nocrypto) 10962306a36Sopenharmony_ci __octeon_feature_bits |= OCTEON_HAS_CRYPTO; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci /* 11262306a36Sopenharmony_ci * Assume pass number is encoded using <5:3><2:0>. Exceptions 11362306a36Sopenharmony_ci * will be fixed later. 11462306a36Sopenharmony_ci */ 11562306a36Sopenharmony_ci sprintf(pass, "%d.%d", (int)((chip_id >> 3) & 7) + 1, (int)chip_id & 7); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* 11862306a36Sopenharmony_ci * Use the number of cores to determine the last 2 digits of 11962306a36Sopenharmony_ci * the model number. There are some exceptions that are fixed 12062306a36Sopenharmony_ci * later. 12162306a36Sopenharmony_ci */ 12262306a36Sopenharmony_ci switch (num_cores) { 12362306a36Sopenharmony_ci case 48: 12462306a36Sopenharmony_ci core_model = "90"; 12562306a36Sopenharmony_ci break; 12662306a36Sopenharmony_ci case 44: 12762306a36Sopenharmony_ci core_model = "88"; 12862306a36Sopenharmony_ci break; 12962306a36Sopenharmony_ci case 40: 13062306a36Sopenharmony_ci core_model = "85"; 13162306a36Sopenharmony_ci break; 13262306a36Sopenharmony_ci case 32: 13362306a36Sopenharmony_ci core_model = "80"; 13462306a36Sopenharmony_ci break; 13562306a36Sopenharmony_ci case 24: 13662306a36Sopenharmony_ci core_model = "70"; 13762306a36Sopenharmony_ci break; 13862306a36Sopenharmony_ci case 16: 13962306a36Sopenharmony_ci core_model = "60"; 14062306a36Sopenharmony_ci break; 14162306a36Sopenharmony_ci case 15: 14262306a36Sopenharmony_ci core_model = "58"; 14362306a36Sopenharmony_ci break; 14462306a36Sopenharmony_ci case 14: 14562306a36Sopenharmony_ci core_model = "55"; 14662306a36Sopenharmony_ci break; 14762306a36Sopenharmony_ci case 13: 14862306a36Sopenharmony_ci core_model = "52"; 14962306a36Sopenharmony_ci break; 15062306a36Sopenharmony_ci case 12: 15162306a36Sopenharmony_ci core_model = "50"; 15262306a36Sopenharmony_ci break; 15362306a36Sopenharmony_ci case 11: 15462306a36Sopenharmony_ci core_model = "48"; 15562306a36Sopenharmony_ci break; 15662306a36Sopenharmony_ci case 10: 15762306a36Sopenharmony_ci core_model = "45"; 15862306a36Sopenharmony_ci break; 15962306a36Sopenharmony_ci case 9: 16062306a36Sopenharmony_ci core_model = "42"; 16162306a36Sopenharmony_ci break; 16262306a36Sopenharmony_ci case 8: 16362306a36Sopenharmony_ci core_model = "40"; 16462306a36Sopenharmony_ci break; 16562306a36Sopenharmony_ci case 7: 16662306a36Sopenharmony_ci core_model = "38"; 16762306a36Sopenharmony_ci break; 16862306a36Sopenharmony_ci case 6: 16962306a36Sopenharmony_ci core_model = "34"; 17062306a36Sopenharmony_ci break; 17162306a36Sopenharmony_ci case 5: 17262306a36Sopenharmony_ci core_model = "32"; 17362306a36Sopenharmony_ci break; 17462306a36Sopenharmony_ci case 4: 17562306a36Sopenharmony_ci core_model = "30"; 17662306a36Sopenharmony_ci break; 17762306a36Sopenharmony_ci case 3: 17862306a36Sopenharmony_ci core_model = "25"; 17962306a36Sopenharmony_ci break; 18062306a36Sopenharmony_ci case 2: 18162306a36Sopenharmony_ci core_model = "20"; 18262306a36Sopenharmony_ci break; 18362306a36Sopenharmony_ci case 1: 18462306a36Sopenharmony_ci core_model = "10"; 18562306a36Sopenharmony_ci break; 18662306a36Sopenharmony_ci default: 18762306a36Sopenharmony_ci core_model = "XX"; 18862306a36Sopenharmony_ci break; 18962306a36Sopenharmony_ci } 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci /* Now figure out the family, the first two digits */ 19262306a36Sopenharmony_ci switch ((chip_id >> 8) & 0xff) { 19362306a36Sopenharmony_ci case 0: /* CN38XX, CN37XX or CN36XX */ 19462306a36Sopenharmony_ci if (l2d_fus3) { 19562306a36Sopenharmony_ci /* 19662306a36Sopenharmony_ci * For some unknown reason, the 16 core one is 19762306a36Sopenharmony_ci * called 37 instead of 36. 19862306a36Sopenharmony_ci */ 19962306a36Sopenharmony_ci if (num_cores >= 16) 20062306a36Sopenharmony_ci family = "37"; 20162306a36Sopenharmony_ci else 20262306a36Sopenharmony_ci family = "36"; 20362306a36Sopenharmony_ci } else 20462306a36Sopenharmony_ci family = "38"; 20562306a36Sopenharmony_ci /* 20662306a36Sopenharmony_ci * This series of chips didn't follow the standard 20762306a36Sopenharmony_ci * pass numbering. 20862306a36Sopenharmony_ci */ 20962306a36Sopenharmony_ci switch (chip_id & 0xf) { 21062306a36Sopenharmony_ci case 0: 21162306a36Sopenharmony_ci strcpy(pass, "1.X"); 21262306a36Sopenharmony_ci break; 21362306a36Sopenharmony_ci case 1: 21462306a36Sopenharmony_ci strcpy(pass, "2.X"); 21562306a36Sopenharmony_ci break; 21662306a36Sopenharmony_ci case 3: 21762306a36Sopenharmony_ci strcpy(pass, "3.X"); 21862306a36Sopenharmony_ci break; 21962306a36Sopenharmony_ci default: 22062306a36Sopenharmony_ci strcpy(pass, "X.X"); 22162306a36Sopenharmony_ci break; 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci break; 22462306a36Sopenharmony_ci case 1: /* CN31XX or CN3020 */ 22562306a36Sopenharmony_ci if ((chip_id & 0x10) || l2d_fus3) 22662306a36Sopenharmony_ci family = "30"; 22762306a36Sopenharmony_ci else 22862306a36Sopenharmony_ci family = "31"; 22962306a36Sopenharmony_ci /* 23062306a36Sopenharmony_ci * This series of chips didn't follow the standard 23162306a36Sopenharmony_ci * pass numbering. 23262306a36Sopenharmony_ci */ 23362306a36Sopenharmony_ci switch (chip_id & 0xf) { 23462306a36Sopenharmony_ci case 0: 23562306a36Sopenharmony_ci strcpy(pass, "1.0"); 23662306a36Sopenharmony_ci break; 23762306a36Sopenharmony_ci case 2: 23862306a36Sopenharmony_ci strcpy(pass, "1.1"); 23962306a36Sopenharmony_ci break; 24062306a36Sopenharmony_ci default: 24162306a36Sopenharmony_ci strcpy(pass, "X.X"); 24262306a36Sopenharmony_ci break; 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci break; 24562306a36Sopenharmony_ci case 2: /* CN3010 or CN3005 */ 24662306a36Sopenharmony_ci family = "30"; 24762306a36Sopenharmony_ci /* A chip with half cache is an 05 */ 24862306a36Sopenharmony_ci if (l2d_fus3) 24962306a36Sopenharmony_ci core_model = "05"; 25062306a36Sopenharmony_ci /* 25162306a36Sopenharmony_ci * This series of chips didn't follow the standard 25262306a36Sopenharmony_ci * pass numbering. 25362306a36Sopenharmony_ci */ 25462306a36Sopenharmony_ci switch (chip_id & 0xf) { 25562306a36Sopenharmony_ci case 0: 25662306a36Sopenharmony_ci strcpy(pass, "1.0"); 25762306a36Sopenharmony_ci break; 25862306a36Sopenharmony_ci case 2: 25962306a36Sopenharmony_ci strcpy(pass, "1.1"); 26062306a36Sopenharmony_ci break; 26162306a36Sopenharmony_ci default: 26262306a36Sopenharmony_ci strcpy(pass, "X.X"); 26362306a36Sopenharmony_ci break; 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci break; 26662306a36Sopenharmony_ci case 3: /* CN58XX */ 26762306a36Sopenharmony_ci family = "58"; 26862306a36Sopenharmony_ci /* Special case. 4 core, half cache (CP with half cache) */ 26962306a36Sopenharmony_ci if ((num_cores == 4) && l2d_fus3 && !strncmp(suffix, "CP", 2)) 27062306a36Sopenharmony_ci core_model = "29"; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci /* Pass 1 uses different encodings for pass numbers */ 27362306a36Sopenharmony_ci if ((chip_id & 0xFF) < 0x8) { 27462306a36Sopenharmony_ci switch (chip_id & 0x3) { 27562306a36Sopenharmony_ci case 0: 27662306a36Sopenharmony_ci strcpy(pass, "1.0"); 27762306a36Sopenharmony_ci break; 27862306a36Sopenharmony_ci case 1: 27962306a36Sopenharmony_ci strcpy(pass, "1.1"); 28062306a36Sopenharmony_ci break; 28162306a36Sopenharmony_ci case 3: 28262306a36Sopenharmony_ci strcpy(pass, "1.2"); 28362306a36Sopenharmony_ci break; 28462306a36Sopenharmony_ci default: 28562306a36Sopenharmony_ci strcpy(pass, "1.X"); 28662306a36Sopenharmony_ci break; 28762306a36Sopenharmony_ci } 28862306a36Sopenharmony_ci } 28962306a36Sopenharmony_ci break; 29062306a36Sopenharmony_ci case 4: /* CN57XX, CN56XX, CN55XX, CN54XX */ 29162306a36Sopenharmony_ci if (fus_dat2.cn56xx.raid_en) { 29262306a36Sopenharmony_ci if (l2d_fus3) 29362306a36Sopenharmony_ci family = "55"; 29462306a36Sopenharmony_ci else 29562306a36Sopenharmony_ci family = "57"; 29662306a36Sopenharmony_ci if (fus_dat2.cn56xx.nocrypto) 29762306a36Sopenharmony_ci suffix = "SP"; 29862306a36Sopenharmony_ci else 29962306a36Sopenharmony_ci suffix = "SSP"; 30062306a36Sopenharmony_ci } else { 30162306a36Sopenharmony_ci if (fus_dat2.cn56xx.nocrypto) 30262306a36Sopenharmony_ci suffix = "CP"; 30362306a36Sopenharmony_ci else { 30462306a36Sopenharmony_ci suffix = "NSP"; 30562306a36Sopenharmony_ci if (fus_dat3.s.nozip) 30662306a36Sopenharmony_ci suffix = "SCP"; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci if (fus_dat3.cn38xx.bar2_en) 30962306a36Sopenharmony_ci suffix = "NSPB2"; 31062306a36Sopenharmony_ci } 31162306a36Sopenharmony_ci if (l2d_fus3) 31262306a36Sopenharmony_ci family = "54"; 31362306a36Sopenharmony_ci else 31462306a36Sopenharmony_ci family = "56"; 31562306a36Sopenharmony_ci } 31662306a36Sopenharmony_ci break; 31762306a36Sopenharmony_ci case 6: /* CN50XX */ 31862306a36Sopenharmony_ci family = "50"; 31962306a36Sopenharmony_ci break; 32062306a36Sopenharmony_ci case 7: /* CN52XX */ 32162306a36Sopenharmony_ci if (l2d_fus3) 32262306a36Sopenharmony_ci family = "51"; 32362306a36Sopenharmony_ci else 32462306a36Sopenharmony_ci family = "52"; 32562306a36Sopenharmony_ci break; 32662306a36Sopenharmony_ci case 0x93: /* CN61XX */ 32762306a36Sopenharmony_ci family = "61"; 32862306a36Sopenharmony_ci if (fus_dat2.cn61xx.nocrypto && fus_dat2.cn61xx.dorm_crypto) 32962306a36Sopenharmony_ci suffix = "AP"; 33062306a36Sopenharmony_ci if (fus_dat2.cn61xx.nocrypto) 33162306a36Sopenharmony_ci suffix = "CP"; 33262306a36Sopenharmony_ci else if (fus_dat2.cn61xx.dorm_crypto) 33362306a36Sopenharmony_ci suffix = "DAP"; 33462306a36Sopenharmony_ci else if (fus_dat3.cn61xx.nozip) 33562306a36Sopenharmony_ci suffix = "SCP"; 33662306a36Sopenharmony_ci break; 33762306a36Sopenharmony_ci case 0x90: /* CN63XX */ 33862306a36Sopenharmony_ci family = "63"; 33962306a36Sopenharmony_ci if (fus_dat3.s.l2c_crip == 2) 34062306a36Sopenharmony_ci family = "62"; 34162306a36Sopenharmony_ci if (num_cores == 6) /* Other core counts match generic */ 34262306a36Sopenharmony_ci core_model = "35"; 34362306a36Sopenharmony_ci if (fus_dat2.cn63xx.nocrypto) 34462306a36Sopenharmony_ci suffix = "CP"; 34562306a36Sopenharmony_ci else if (fus_dat2.cn63xx.dorm_crypto) 34662306a36Sopenharmony_ci suffix = "DAP"; 34762306a36Sopenharmony_ci else if (fus_dat3.cn61xx.nozip) 34862306a36Sopenharmony_ci suffix = "SCP"; 34962306a36Sopenharmony_ci else 35062306a36Sopenharmony_ci suffix = "AAP"; 35162306a36Sopenharmony_ci break; 35262306a36Sopenharmony_ci case 0x92: /* CN66XX */ 35362306a36Sopenharmony_ci family = "66"; 35462306a36Sopenharmony_ci if (num_cores == 6) /* Other core counts match generic */ 35562306a36Sopenharmony_ci core_model = "35"; 35662306a36Sopenharmony_ci if (fus_dat2.cn66xx.nocrypto && fus_dat2.cn66xx.dorm_crypto) 35762306a36Sopenharmony_ci suffix = "AP"; 35862306a36Sopenharmony_ci if (fus_dat2.cn66xx.nocrypto) 35962306a36Sopenharmony_ci suffix = "CP"; 36062306a36Sopenharmony_ci else if (fus_dat2.cn66xx.dorm_crypto) 36162306a36Sopenharmony_ci suffix = "DAP"; 36262306a36Sopenharmony_ci else if (fus_dat3.cn61xx.nozip) 36362306a36Sopenharmony_ci suffix = "SCP"; 36462306a36Sopenharmony_ci else 36562306a36Sopenharmony_ci suffix = "AAP"; 36662306a36Sopenharmony_ci break; 36762306a36Sopenharmony_ci case 0x91: /* CN68XX */ 36862306a36Sopenharmony_ci family = "68"; 36962306a36Sopenharmony_ci if (fus_dat2.cn68xx.nocrypto && fus_dat3.cn61xx.nozip) 37062306a36Sopenharmony_ci suffix = "CP"; 37162306a36Sopenharmony_ci else if (fus_dat2.cn68xx.dorm_crypto) 37262306a36Sopenharmony_ci suffix = "DAP"; 37362306a36Sopenharmony_ci else if (fus_dat3.cn61xx.nozip) 37462306a36Sopenharmony_ci suffix = "SCP"; 37562306a36Sopenharmony_ci else if (fus_dat2.cn68xx.nocrypto) 37662306a36Sopenharmony_ci suffix = "SP"; 37762306a36Sopenharmony_ci else 37862306a36Sopenharmony_ci suffix = "AAP"; 37962306a36Sopenharmony_ci break; 38062306a36Sopenharmony_ci case 0x94: /* CNF71XX */ 38162306a36Sopenharmony_ci family = "F71"; 38262306a36Sopenharmony_ci if (fus_dat3.cn61xx.nozip) 38362306a36Sopenharmony_ci suffix = "SCP"; 38462306a36Sopenharmony_ci else 38562306a36Sopenharmony_ci suffix = "AAP"; 38662306a36Sopenharmony_ci break; 38762306a36Sopenharmony_ci case 0x95: /* CN78XX */ 38862306a36Sopenharmony_ci if (num_cores == 6) /* Other core counts match generic */ 38962306a36Sopenharmony_ci core_model = "35"; 39062306a36Sopenharmony_ci if (OCTEON_IS_MODEL(OCTEON_CN76XX)) 39162306a36Sopenharmony_ci family = "76"; 39262306a36Sopenharmony_ci else 39362306a36Sopenharmony_ci family = "78"; 39462306a36Sopenharmony_ci if (fus_dat3.cn78xx.l2c_crip == 2) 39562306a36Sopenharmony_ci family = "77"; 39662306a36Sopenharmony_ci if (fus_dat3.cn78xx.nozip 39762306a36Sopenharmony_ci && fus_dat3.cn78xx.nodfa_dte 39862306a36Sopenharmony_ci && fus_dat3.cn78xx.nohna_dte) { 39962306a36Sopenharmony_ci if (fus_dat3.cn78xx.nozip && 40062306a36Sopenharmony_ci !fus_dat2.cn78xx.raid_en && 40162306a36Sopenharmony_ci fus_dat3.cn78xx.nohna_dte) { 40262306a36Sopenharmony_ci suffix = "CP"; 40362306a36Sopenharmony_ci } else { 40462306a36Sopenharmony_ci suffix = "SCP"; 40562306a36Sopenharmony_ci } 40662306a36Sopenharmony_ci } else if (fus_dat2.cn78xx.raid_en == 0) 40762306a36Sopenharmony_ci suffix = "HCP"; 40862306a36Sopenharmony_ci else 40962306a36Sopenharmony_ci suffix = "AAP"; 41062306a36Sopenharmony_ci break; 41162306a36Sopenharmony_ci case 0x96: /* CN70XX */ 41262306a36Sopenharmony_ci family = "70"; 41362306a36Sopenharmony_ci if (cvmx_read_csr(CVMX_MIO_FUS_PDF) & (0x1ULL << 32)) 41462306a36Sopenharmony_ci family = "71"; 41562306a36Sopenharmony_ci if (fus_dat2.cn70xx.nocrypto) 41662306a36Sopenharmony_ci suffix = "CP"; 41762306a36Sopenharmony_ci else if (fus_dat3.cn70xx.nodfa_dte) 41862306a36Sopenharmony_ci suffix = "SCP"; 41962306a36Sopenharmony_ci else 42062306a36Sopenharmony_ci suffix = "AAP"; 42162306a36Sopenharmony_ci break; 42262306a36Sopenharmony_ci case 0x97: /* CN73XX */ 42362306a36Sopenharmony_ci if (num_cores == 6) /* Other core counts match generic */ 42462306a36Sopenharmony_ci core_model = "35"; 42562306a36Sopenharmony_ci family = "73"; 42662306a36Sopenharmony_ci if (fus_dat3.cn73xx.l2c_crip == 2) 42762306a36Sopenharmony_ci family = "72"; 42862306a36Sopenharmony_ci if (fus_dat3.cn73xx.nozip 42962306a36Sopenharmony_ci && fus_dat3.cn73xx.nodfa_dte 43062306a36Sopenharmony_ci && fus_dat3.cn73xx.nohna_dte) { 43162306a36Sopenharmony_ci if (!fus_dat2.cn73xx.raid_en) 43262306a36Sopenharmony_ci suffix = "CP"; 43362306a36Sopenharmony_ci else 43462306a36Sopenharmony_ci suffix = "SCP"; 43562306a36Sopenharmony_ci } else 43662306a36Sopenharmony_ci suffix = "AAP"; 43762306a36Sopenharmony_ci break; 43862306a36Sopenharmony_ci case 0x98: /* CN75XX */ 43962306a36Sopenharmony_ci family = "F75"; 44062306a36Sopenharmony_ci if (fus_dat3.cn78xx.nozip 44162306a36Sopenharmony_ci && fus_dat3.cn78xx.nodfa_dte 44262306a36Sopenharmony_ci && fus_dat3.cn78xx.nohna_dte) 44362306a36Sopenharmony_ci suffix = "SCP"; 44462306a36Sopenharmony_ci else 44562306a36Sopenharmony_ci suffix = "AAP"; 44662306a36Sopenharmony_ci break; 44762306a36Sopenharmony_ci default: 44862306a36Sopenharmony_ci family = "XX"; 44962306a36Sopenharmony_ci core_model = "XX"; 45062306a36Sopenharmony_ci strcpy(pass, "X.X"); 45162306a36Sopenharmony_ci suffix = "XXX"; 45262306a36Sopenharmony_ci break; 45362306a36Sopenharmony_ci } 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci clock_mhz = octeon_get_clock_rate() / 1000000; 45662306a36Sopenharmony_ci if (family[0] != '3') { 45762306a36Sopenharmony_ci int fuse_base = 384 / 8; 45862306a36Sopenharmony_ci if (family[0] == '6') 45962306a36Sopenharmony_ci fuse_base = 832 / 8; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci /* Check for model in fuses, overrides normal decode */ 46262306a36Sopenharmony_ci /* This is _not_ valid for Octeon CN3XXX models */ 46362306a36Sopenharmony_ci fuse_data |= cvmx_fuse_read_byte(fuse_base + 3); 46462306a36Sopenharmony_ci fuse_data = fuse_data << 8; 46562306a36Sopenharmony_ci fuse_data |= cvmx_fuse_read_byte(fuse_base + 2); 46662306a36Sopenharmony_ci fuse_data = fuse_data << 8; 46762306a36Sopenharmony_ci fuse_data |= cvmx_fuse_read_byte(fuse_base + 1); 46862306a36Sopenharmony_ci fuse_data = fuse_data << 8; 46962306a36Sopenharmony_ci fuse_data |= cvmx_fuse_read_byte(fuse_base); 47062306a36Sopenharmony_ci if (fuse_data & 0x7ffff) { 47162306a36Sopenharmony_ci int model = fuse_data & 0x3fff; 47262306a36Sopenharmony_ci int suffix = (fuse_data >> 14) & 0x1f; 47362306a36Sopenharmony_ci if (suffix && model) { 47462306a36Sopenharmony_ci /* Have both number and suffix in fuses, so both */ 47562306a36Sopenharmony_ci sprintf(fuse_model, "%d%c", model, 'A' + suffix - 1); 47662306a36Sopenharmony_ci core_model = ""; 47762306a36Sopenharmony_ci family = fuse_model; 47862306a36Sopenharmony_ci } else if (suffix && !model) { 47962306a36Sopenharmony_ci /* Only have suffix, so add suffix to 'normal' model number */ 48062306a36Sopenharmony_ci sprintf(fuse_model, "%s%c", core_model, 'A' + suffix - 1); 48162306a36Sopenharmony_ci core_model = fuse_model; 48262306a36Sopenharmony_ci } else { 48362306a36Sopenharmony_ci /* Don't have suffix, so just use model from fuses */ 48462306a36Sopenharmony_ci sprintf(fuse_model, "%d", model); 48562306a36Sopenharmony_ci core_model = ""; 48662306a36Sopenharmony_ci family = fuse_model; 48762306a36Sopenharmony_ci } 48862306a36Sopenharmony_ci } 48962306a36Sopenharmony_ci } 49062306a36Sopenharmony_ci sprintf(buffer, "CN%s%sp%s-%d-%s", family, core_model, pass, clock_mhz, suffix); 49162306a36Sopenharmony_ci return buffer; 49262306a36Sopenharmony_ci} 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci/** 49562306a36Sopenharmony_ci * Given the chip processor ID from COP0, this function returns a 49662306a36Sopenharmony_ci * string representing the chip model number. The string is of the 49762306a36Sopenharmony_ci * form CNXXXXpX.X-FREQ-SUFFIX. 49862306a36Sopenharmony_ci * - XXXX = The chip model number 49962306a36Sopenharmony_ci * - X.X = Chip pass number 50062306a36Sopenharmony_ci * - FREQ = Current frequency in Mhz 50162306a36Sopenharmony_ci * - SUFFIX = NSP, EXP, SCP, SSP, or CP 50262306a36Sopenharmony_ci * 50362306a36Sopenharmony_ci * @chip_id: Chip ID 50462306a36Sopenharmony_ci * 50562306a36Sopenharmony_ci * Returns Model string 50662306a36Sopenharmony_ci */ 50762306a36Sopenharmony_ciconst char *__init octeon_model_get_string(uint32_t chip_id) 50862306a36Sopenharmony_ci{ 50962306a36Sopenharmony_ci static char buffer[32]; 51062306a36Sopenharmony_ci return octeon_model_get_string_buffer(chip_id, buffer); 51162306a36Sopenharmony_ci} 512