18c2ecf20Sopenharmony_ci/***********************license start*************** 28c2ecf20Sopenharmony_ci * Author: Cavium Networks 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Contact: support@caviumnetworks.com 58c2ecf20Sopenharmony_ci * This file is part of the OCTEON SDK 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (c) 2003-2017 Cavium, Inc. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This file is free software; you can redistribute it and/or modify 108c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License, Version 2, as 118c2ecf20Sopenharmony_ci * published by the Free Software Foundation. 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * This file is distributed in the hope that it will be useful, but 148c2ecf20Sopenharmony_ci * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 158c2ecf20Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 168c2ecf20Sopenharmony_ci * NONINFRINGEMENT. See the GNU General Public License for more 178c2ecf20Sopenharmony_ci * details. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * You should have received a copy of the GNU General Public License 208c2ecf20Sopenharmony_ci * along with this file; if not, write to the Free Software 218c2ecf20Sopenharmony_ci * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 228c2ecf20Sopenharmony_ci * or visit http://www.gnu.org/licenses/. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * This file may also be available under a different license from Cavium. 258c2ecf20Sopenharmony_ci * Contact Cavium Networks for more information 268c2ecf20Sopenharmony_ci ***********************license end**************************************/ 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#include <asm/octeon/octeon.h> 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cienum octeon_feature_bits __octeon_feature_bits __read_mostly; 318c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(__octeon_feature_bits); 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci/** 348c2ecf20Sopenharmony_ci * Read a byte of fuse data 358c2ecf20Sopenharmony_ci * @byte_addr: address to read 368c2ecf20Sopenharmony_ci * 378c2ecf20Sopenharmony_ci * Returns fuse value: 0 or 1 388c2ecf20Sopenharmony_ci */ 398c2ecf20Sopenharmony_cistatic uint8_t __init cvmx_fuse_read_byte(int byte_addr) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci union cvmx_mio_fus_rcmd read_cmd; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci read_cmd.u64 = 0; 448c2ecf20Sopenharmony_ci read_cmd.s.addr = byte_addr; 458c2ecf20Sopenharmony_ci read_cmd.s.pend = 1; 468c2ecf20Sopenharmony_ci cvmx_write_csr(CVMX_MIO_FUS_RCMD, read_cmd.u64); 478c2ecf20Sopenharmony_ci while ((read_cmd.u64 = cvmx_read_csr(CVMX_MIO_FUS_RCMD)) 488c2ecf20Sopenharmony_ci && read_cmd.s.pend) 498c2ecf20Sopenharmony_ci ; 508c2ecf20Sopenharmony_ci return read_cmd.s.dat; 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci/* 548c2ecf20Sopenharmony_ci * Version of octeon_model_get_string() that takes buffer as argument, 558c2ecf20Sopenharmony_ci * as running early in u-boot static/global variables don't work when 568c2ecf20Sopenharmony_ci * running from flash. 578c2ecf20Sopenharmony_ci */ 588c2ecf20Sopenharmony_cistatic const char *__init octeon_model_get_string_buffer(uint32_t chip_id, 598c2ecf20Sopenharmony_ci char *buffer) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci const char *family; 628c2ecf20Sopenharmony_ci const char *core_model; 638c2ecf20Sopenharmony_ci char pass[4]; 648c2ecf20Sopenharmony_ci int clock_mhz; 658c2ecf20Sopenharmony_ci const char *suffix; 668c2ecf20Sopenharmony_ci int num_cores; 678c2ecf20Sopenharmony_ci union cvmx_mio_fus_dat2 fus_dat2; 688c2ecf20Sopenharmony_ci union cvmx_mio_fus_dat3 fus_dat3; 698c2ecf20Sopenharmony_ci char fuse_model[10]; 708c2ecf20Sopenharmony_ci uint32_t fuse_data = 0; 718c2ecf20Sopenharmony_ci uint64_t l2d_fus3 = 0; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX)) 748c2ecf20Sopenharmony_ci l2d_fus3 = (cvmx_read_csr(CVMX_L2D_FUS3) >> 34) & 0x3; 758c2ecf20Sopenharmony_ci fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2); 768c2ecf20Sopenharmony_ci fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3); 778c2ecf20Sopenharmony_ci num_cores = cvmx_octeon_num_cores(); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci /* Make sure the non existent devices look disabled */ 808c2ecf20Sopenharmony_ci switch ((chip_id >> 8) & 0xff) { 818c2ecf20Sopenharmony_ci case 6: /* CN50XX */ 828c2ecf20Sopenharmony_ci case 2: /* CN30XX */ 838c2ecf20Sopenharmony_ci fus_dat3.s.nodfa_dte = 1; 848c2ecf20Sopenharmony_ci fus_dat3.s.nozip = 1; 858c2ecf20Sopenharmony_ci break; 868c2ecf20Sopenharmony_ci case 4: /* CN57XX or CN56XX */ 878c2ecf20Sopenharmony_ci fus_dat3.s.nodfa_dte = 1; 888c2ecf20Sopenharmony_ci break; 898c2ecf20Sopenharmony_ci default: 908c2ecf20Sopenharmony_ci break; 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci /* Make a guess at the suffix */ 948c2ecf20Sopenharmony_ci /* NSP = everything */ 958c2ecf20Sopenharmony_ci /* EXP = No crypto */ 968c2ecf20Sopenharmony_ci /* SCP = No DFA, No zip */ 978c2ecf20Sopenharmony_ci /* CP = No DFA, No crypto, No zip */ 988c2ecf20Sopenharmony_ci if (fus_dat3.s.nodfa_dte) { 998c2ecf20Sopenharmony_ci if (fus_dat2.s.nocrypto) 1008c2ecf20Sopenharmony_ci suffix = "CP"; 1018c2ecf20Sopenharmony_ci else 1028c2ecf20Sopenharmony_ci suffix = "SCP"; 1038c2ecf20Sopenharmony_ci } else if (fus_dat2.s.nocrypto) 1048c2ecf20Sopenharmony_ci suffix = "EXP"; 1058c2ecf20Sopenharmony_ci else 1068c2ecf20Sopenharmony_ci suffix = "NSP"; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci if (!fus_dat2.s.nocrypto) 1098c2ecf20Sopenharmony_ci __octeon_feature_bits |= OCTEON_HAS_CRYPTO; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci /* 1128c2ecf20Sopenharmony_ci * Assume pass number is encoded using <5:3><2:0>. Exceptions 1138c2ecf20Sopenharmony_ci * will be fixed later. 1148c2ecf20Sopenharmony_ci */ 1158c2ecf20Sopenharmony_ci sprintf(pass, "%d.%d", (int)((chip_id >> 3) & 7) + 1, (int)chip_id & 7); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci /* 1188c2ecf20Sopenharmony_ci * Use the number of cores to determine the last 2 digits of 1198c2ecf20Sopenharmony_ci * the model number. There are some exceptions that are fixed 1208c2ecf20Sopenharmony_ci * later. 1218c2ecf20Sopenharmony_ci */ 1228c2ecf20Sopenharmony_ci switch (num_cores) { 1238c2ecf20Sopenharmony_ci case 48: 1248c2ecf20Sopenharmony_ci core_model = "90"; 1258c2ecf20Sopenharmony_ci break; 1268c2ecf20Sopenharmony_ci case 44: 1278c2ecf20Sopenharmony_ci core_model = "88"; 1288c2ecf20Sopenharmony_ci break; 1298c2ecf20Sopenharmony_ci case 40: 1308c2ecf20Sopenharmony_ci core_model = "85"; 1318c2ecf20Sopenharmony_ci break; 1328c2ecf20Sopenharmony_ci case 32: 1338c2ecf20Sopenharmony_ci core_model = "80"; 1348c2ecf20Sopenharmony_ci break; 1358c2ecf20Sopenharmony_ci case 24: 1368c2ecf20Sopenharmony_ci core_model = "70"; 1378c2ecf20Sopenharmony_ci break; 1388c2ecf20Sopenharmony_ci case 16: 1398c2ecf20Sopenharmony_ci core_model = "60"; 1408c2ecf20Sopenharmony_ci break; 1418c2ecf20Sopenharmony_ci case 15: 1428c2ecf20Sopenharmony_ci core_model = "58"; 1438c2ecf20Sopenharmony_ci break; 1448c2ecf20Sopenharmony_ci case 14: 1458c2ecf20Sopenharmony_ci core_model = "55"; 1468c2ecf20Sopenharmony_ci break; 1478c2ecf20Sopenharmony_ci case 13: 1488c2ecf20Sopenharmony_ci core_model = "52"; 1498c2ecf20Sopenharmony_ci break; 1508c2ecf20Sopenharmony_ci case 12: 1518c2ecf20Sopenharmony_ci core_model = "50"; 1528c2ecf20Sopenharmony_ci break; 1538c2ecf20Sopenharmony_ci case 11: 1548c2ecf20Sopenharmony_ci core_model = "48"; 1558c2ecf20Sopenharmony_ci break; 1568c2ecf20Sopenharmony_ci case 10: 1578c2ecf20Sopenharmony_ci core_model = "45"; 1588c2ecf20Sopenharmony_ci break; 1598c2ecf20Sopenharmony_ci case 9: 1608c2ecf20Sopenharmony_ci core_model = "42"; 1618c2ecf20Sopenharmony_ci break; 1628c2ecf20Sopenharmony_ci case 8: 1638c2ecf20Sopenharmony_ci core_model = "40"; 1648c2ecf20Sopenharmony_ci break; 1658c2ecf20Sopenharmony_ci case 7: 1668c2ecf20Sopenharmony_ci core_model = "38"; 1678c2ecf20Sopenharmony_ci break; 1688c2ecf20Sopenharmony_ci case 6: 1698c2ecf20Sopenharmony_ci core_model = "34"; 1708c2ecf20Sopenharmony_ci break; 1718c2ecf20Sopenharmony_ci case 5: 1728c2ecf20Sopenharmony_ci core_model = "32"; 1738c2ecf20Sopenharmony_ci break; 1748c2ecf20Sopenharmony_ci case 4: 1758c2ecf20Sopenharmony_ci core_model = "30"; 1768c2ecf20Sopenharmony_ci break; 1778c2ecf20Sopenharmony_ci case 3: 1788c2ecf20Sopenharmony_ci core_model = "25"; 1798c2ecf20Sopenharmony_ci break; 1808c2ecf20Sopenharmony_ci case 2: 1818c2ecf20Sopenharmony_ci core_model = "20"; 1828c2ecf20Sopenharmony_ci break; 1838c2ecf20Sopenharmony_ci case 1: 1848c2ecf20Sopenharmony_ci core_model = "10"; 1858c2ecf20Sopenharmony_ci break; 1868c2ecf20Sopenharmony_ci default: 1878c2ecf20Sopenharmony_ci core_model = "XX"; 1888c2ecf20Sopenharmony_ci break; 1898c2ecf20Sopenharmony_ci } 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci /* Now figure out the family, the first two digits */ 1928c2ecf20Sopenharmony_ci switch ((chip_id >> 8) & 0xff) { 1938c2ecf20Sopenharmony_ci case 0: /* CN38XX, CN37XX or CN36XX */ 1948c2ecf20Sopenharmony_ci if (l2d_fus3) { 1958c2ecf20Sopenharmony_ci /* 1968c2ecf20Sopenharmony_ci * For some unknown reason, the 16 core one is 1978c2ecf20Sopenharmony_ci * called 37 instead of 36. 1988c2ecf20Sopenharmony_ci */ 1998c2ecf20Sopenharmony_ci if (num_cores >= 16) 2008c2ecf20Sopenharmony_ci family = "37"; 2018c2ecf20Sopenharmony_ci else 2028c2ecf20Sopenharmony_ci family = "36"; 2038c2ecf20Sopenharmony_ci } else 2048c2ecf20Sopenharmony_ci family = "38"; 2058c2ecf20Sopenharmony_ci /* 2068c2ecf20Sopenharmony_ci * This series of chips didn't follow the standard 2078c2ecf20Sopenharmony_ci * pass numbering. 2088c2ecf20Sopenharmony_ci */ 2098c2ecf20Sopenharmony_ci switch (chip_id & 0xf) { 2108c2ecf20Sopenharmony_ci case 0: 2118c2ecf20Sopenharmony_ci strcpy(pass, "1.X"); 2128c2ecf20Sopenharmony_ci break; 2138c2ecf20Sopenharmony_ci case 1: 2148c2ecf20Sopenharmony_ci strcpy(pass, "2.X"); 2158c2ecf20Sopenharmony_ci break; 2168c2ecf20Sopenharmony_ci case 3: 2178c2ecf20Sopenharmony_ci strcpy(pass, "3.X"); 2188c2ecf20Sopenharmony_ci break; 2198c2ecf20Sopenharmony_ci default: 2208c2ecf20Sopenharmony_ci strcpy(pass, "X.X"); 2218c2ecf20Sopenharmony_ci break; 2228c2ecf20Sopenharmony_ci } 2238c2ecf20Sopenharmony_ci break; 2248c2ecf20Sopenharmony_ci case 1: /* CN31XX or CN3020 */ 2258c2ecf20Sopenharmony_ci if ((chip_id & 0x10) || l2d_fus3) 2268c2ecf20Sopenharmony_ci family = "30"; 2278c2ecf20Sopenharmony_ci else 2288c2ecf20Sopenharmony_ci family = "31"; 2298c2ecf20Sopenharmony_ci /* 2308c2ecf20Sopenharmony_ci * This series of chips didn't follow the standard 2318c2ecf20Sopenharmony_ci * pass numbering. 2328c2ecf20Sopenharmony_ci */ 2338c2ecf20Sopenharmony_ci switch (chip_id & 0xf) { 2348c2ecf20Sopenharmony_ci case 0: 2358c2ecf20Sopenharmony_ci strcpy(pass, "1.0"); 2368c2ecf20Sopenharmony_ci break; 2378c2ecf20Sopenharmony_ci case 2: 2388c2ecf20Sopenharmony_ci strcpy(pass, "1.1"); 2398c2ecf20Sopenharmony_ci break; 2408c2ecf20Sopenharmony_ci default: 2418c2ecf20Sopenharmony_ci strcpy(pass, "X.X"); 2428c2ecf20Sopenharmony_ci break; 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci break; 2458c2ecf20Sopenharmony_ci case 2: /* CN3010 or CN3005 */ 2468c2ecf20Sopenharmony_ci family = "30"; 2478c2ecf20Sopenharmony_ci /* A chip with half cache is an 05 */ 2488c2ecf20Sopenharmony_ci if (l2d_fus3) 2498c2ecf20Sopenharmony_ci core_model = "05"; 2508c2ecf20Sopenharmony_ci /* 2518c2ecf20Sopenharmony_ci * This series of chips didn't follow the standard 2528c2ecf20Sopenharmony_ci * pass numbering. 2538c2ecf20Sopenharmony_ci */ 2548c2ecf20Sopenharmony_ci switch (chip_id & 0xf) { 2558c2ecf20Sopenharmony_ci case 0: 2568c2ecf20Sopenharmony_ci strcpy(pass, "1.0"); 2578c2ecf20Sopenharmony_ci break; 2588c2ecf20Sopenharmony_ci case 2: 2598c2ecf20Sopenharmony_ci strcpy(pass, "1.1"); 2608c2ecf20Sopenharmony_ci break; 2618c2ecf20Sopenharmony_ci default: 2628c2ecf20Sopenharmony_ci strcpy(pass, "X.X"); 2638c2ecf20Sopenharmony_ci break; 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci break; 2668c2ecf20Sopenharmony_ci case 3: /* CN58XX */ 2678c2ecf20Sopenharmony_ci family = "58"; 2688c2ecf20Sopenharmony_ci /* Special case. 4 core, half cache (CP with half cache) */ 2698c2ecf20Sopenharmony_ci if ((num_cores == 4) && l2d_fus3 && !strncmp(suffix, "CP", 2)) 2708c2ecf20Sopenharmony_ci core_model = "29"; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci /* Pass 1 uses different encodings for pass numbers */ 2738c2ecf20Sopenharmony_ci if ((chip_id & 0xFF) < 0x8) { 2748c2ecf20Sopenharmony_ci switch (chip_id & 0x3) { 2758c2ecf20Sopenharmony_ci case 0: 2768c2ecf20Sopenharmony_ci strcpy(pass, "1.0"); 2778c2ecf20Sopenharmony_ci break; 2788c2ecf20Sopenharmony_ci case 1: 2798c2ecf20Sopenharmony_ci strcpy(pass, "1.1"); 2808c2ecf20Sopenharmony_ci break; 2818c2ecf20Sopenharmony_ci case 3: 2828c2ecf20Sopenharmony_ci strcpy(pass, "1.2"); 2838c2ecf20Sopenharmony_ci break; 2848c2ecf20Sopenharmony_ci default: 2858c2ecf20Sopenharmony_ci strcpy(pass, "1.X"); 2868c2ecf20Sopenharmony_ci break; 2878c2ecf20Sopenharmony_ci } 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci break; 2908c2ecf20Sopenharmony_ci case 4: /* CN57XX, CN56XX, CN55XX, CN54XX */ 2918c2ecf20Sopenharmony_ci if (fus_dat2.cn56xx.raid_en) { 2928c2ecf20Sopenharmony_ci if (l2d_fus3) 2938c2ecf20Sopenharmony_ci family = "55"; 2948c2ecf20Sopenharmony_ci else 2958c2ecf20Sopenharmony_ci family = "57"; 2968c2ecf20Sopenharmony_ci if (fus_dat2.cn56xx.nocrypto) 2978c2ecf20Sopenharmony_ci suffix = "SP"; 2988c2ecf20Sopenharmony_ci else 2998c2ecf20Sopenharmony_ci suffix = "SSP"; 3008c2ecf20Sopenharmony_ci } else { 3018c2ecf20Sopenharmony_ci if (fus_dat2.cn56xx.nocrypto) 3028c2ecf20Sopenharmony_ci suffix = "CP"; 3038c2ecf20Sopenharmony_ci else { 3048c2ecf20Sopenharmony_ci suffix = "NSP"; 3058c2ecf20Sopenharmony_ci if (fus_dat3.s.nozip) 3068c2ecf20Sopenharmony_ci suffix = "SCP"; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci if (fus_dat3.cn38xx.bar2_en) 3098c2ecf20Sopenharmony_ci suffix = "NSPB2"; 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci if (l2d_fus3) 3128c2ecf20Sopenharmony_ci family = "54"; 3138c2ecf20Sopenharmony_ci else 3148c2ecf20Sopenharmony_ci family = "56"; 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci break; 3178c2ecf20Sopenharmony_ci case 6: /* CN50XX */ 3188c2ecf20Sopenharmony_ci family = "50"; 3198c2ecf20Sopenharmony_ci break; 3208c2ecf20Sopenharmony_ci case 7: /* CN52XX */ 3218c2ecf20Sopenharmony_ci if (l2d_fus3) 3228c2ecf20Sopenharmony_ci family = "51"; 3238c2ecf20Sopenharmony_ci else 3248c2ecf20Sopenharmony_ci family = "52"; 3258c2ecf20Sopenharmony_ci break; 3268c2ecf20Sopenharmony_ci case 0x93: /* CN61XX */ 3278c2ecf20Sopenharmony_ci family = "61"; 3288c2ecf20Sopenharmony_ci if (fus_dat2.cn61xx.nocrypto && fus_dat2.cn61xx.dorm_crypto) 3298c2ecf20Sopenharmony_ci suffix = "AP"; 3308c2ecf20Sopenharmony_ci if (fus_dat2.cn61xx.nocrypto) 3318c2ecf20Sopenharmony_ci suffix = "CP"; 3328c2ecf20Sopenharmony_ci else if (fus_dat2.cn61xx.dorm_crypto) 3338c2ecf20Sopenharmony_ci suffix = "DAP"; 3348c2ecf20Sopenharmony_ci else if (fus_dat3.cn61xx.nozip) 3358c2ecf20Sopenharmony_ci suffix = "SCP"; 3368c2ecf20Sopenharmony_ci break; 3378c2ecf20Sopenharmony_ci case 0x90: /* CN63XX */ 3388c2ecf20Sopenharmony_ci family = "63"; 3398c2ecf20Sopenharmony_ci if (fus_dat3.s.l2c_crip == 2) 3408c2ecf20Sopenharmony_ci family = "62"; 3418c2ecf20Sopenharmony_ci if (num_cores == 6) /* Other core counts match generic */ 3428c2ecf20Sopenharmony_ci core_model = "35"; 3438c2ecf20Sopenharmony_ci if (fus_dat2.cn63xx.nocrypto) 3448c2ecf20Sopenharmony_ci suffix = "CP"; 3458c2ecf20Sopenharmony_ci else if (fus_dat2.cn63xx.dorm_crypto) 3468c2ecf20Sopenharmony_ci suffix = "DAP"; 3478c2ecf20Sopenharmony_ci else if (fus_dat3.cn61xx.nozip) 3488c2ecf20Sopenharmony_ci suffix = "SCP"; 3498c2ecf20Sopenharmony_ci else 3508c2ecf20Sopenharmony_ci suffix = "AAP"; 3518c2ecf20Sopenharmony_ci break; 3528c2ecf20Sopenharmony_ci case 0x92: /* CN66XX */ 3538c2ecf20Sopenharmony_ci family = "66"; 3548c2ecf20Sopenharmony_ci if (num_cores == 6) /* Other core counts match generic */ 3558c2ecf20Sopenharmony_ci core_model = "35"; 3568c2ecf20Sopenharmony_ci if (fus_dat2.cn66xx.nocrypto && fus_dat2.cn66xx.dorm_crypto) 3578c2ecf20Sopenharmony_ci suffix = "AP"; 3588c2ecf20Sopenharmony_ci if (fus_dat2.cn66xx.nocrypto) 3598c2ecf20Sopenharmony_ci suffix = "CP"; 3608c2ecf20Sopenharmony_ci else if (fus_dat2.cn66xx.dorm_crypto) 3618c2ecf20Sopenharmony_ci suffix = "DAP"; 3628c2ecf20Sopenharmony_ci else if (fus_dat3.cn61xx.nozip) 3638c2ecf20Sopenharmony_ci suffix = "SCP"; 3648c2ecf20Sopenharmony_ci else 3658c2ecf20Sopenharmony_ci suffix = "AAP"; 3668c2ecf20Sopenharmony_ci break; 3678c2ecf20Sopenharmony_ci case 0x91: /* CN68XX */ 3688c2ecf20Sopenharmony_ci family = "68"; 3698c2ecf20Sopenharmony_ci if (fus_dat2.cn68xx.nocrypto && fus_dat3.cn61xx.nozip) 3708c2ecf20Sopenharmony_ci suffix = "CP"; 3718c2ecf20Sopenharmony_ci else if (fus_dat2.cn68xx.dorm_crypto) 3728c2ecf20Sopenharmony_ci suffix = "DAP"; 3738c2ecf20Sopenharmony_ci else if (fus_dat3.cn61xx.nozip) 3748c2ecf20Sopenharmony_ci suffix = "SCP"; 3758c2ecf20Sopenharmony_ci else if (fus_dat2.cn68xx.nocrypto) 3768c2ecf20Sopenharmony_ci suffix = "SP"; 3778c2ecf20Sopenharmony_ci else 3788c2ecf20Sopenharmony_ci suffix = "AAP"; 3798c2ecf20Sopenharmony_ci break; 3808c2ecf20Sopenharmony_ci case 0x94: /* CNF71XX */ 3818c2ecf20Sopenharmony_ci family = "F71"; 3828c2ecf20Sopenharmony_ci if (fus_dat3.cn61xx.nozip) 3838c2ecf20Sopenharmony_ci suffix = "SCP"; 3848c2ecf20Sopenharmony_ci else 3858c2ecf20Sopenharmony_ci suffix = "AAP"; 3868c2ecf20Sopenharmony_ci break; 3878c2ecf20Sopenharmony_ci case 0x95: /* CN78XX */ 3888c2ecf20Sopenharmony_ci if (num_cores == 6) /* Other core counts match generic */ 3898c2ecf20Sopenharmony_ci core_model = "35"; 3908c2ecf20Sopenharmony_ci if (OCTEON_IS_MODEL(OCTEON_CN76XX)) 3918c2ecf20Sopenharmony_ci family = "76"; 3928c2ecf20Sopenharmony_ci else 3938c2ecf20Sopenharmony_ci family = "78"; 3948c2ecf20Sopenharmony_ci if (fus_dat3.cn78xx.l2c_crip == 2) 3958c2ecf20Sopenharmony_ci family = "77"; 3968c2ecf20Sopenharmony_ci if (fus_dat3.cn78xx.nozip 3978c2ecf20Sopenharmony_ci && fus_dat3.cn78xx.nodfa_dte 3988c2ecf20Sopenharmony_ci && fus_dat3.cn78xx.nohna_dte) { 3998c2ecf20Sopenharmony_ci if (fus_dat3.cn78xx.nozip && 4008c2ecf20Sopenharmony_ci !fus_dat2.cn78xx.raid_en && 4018c2ecf20Sopenharmony_ci fus_dat3.cn78xx.nohna_dte) { 4028c2ecf20Sopenharmony_ci suffix = "CP"; 4038c2ecf20Sopenharmony_ci } else { 4048c2ecf20Sopenharmony_ci suffix = "SCP"; 4058c2ecf20Sopenharmony_ci } 4068c2ecf20Sopenharmony_ci } else if (fus_dat2.cn78xx.raid_en == 0) 4078c2ecf20Sopenharmony_ci suffix = "HCP"; 4088c2ecf20Sopenharmony_ci else 4098c2ecf20Sopenharmony_ci suffix = "AAP"; 4108c2ecf20Sopenharmony_ci break; 4118c2ecf20Sopenharmony_ci case 0x96: /* CN70XX */ 4128c2ecf20Sopenharmony_ci family = "70"; 4138c2ecf20Sopenharmony_ci if (cvmx_read_csr(CVMX_MIO_FUS_PDF) & (0x1ULL << 32)) 4148c2ecf20Sopenharmony_ci family = "71"; 4158c2ecf20Sopenharmony_ci if (fus_dat2.cn70xx.nocrypto) 4168c2ecf20Sopenharmony_ci suffix = "CP"; 4178c2ecf20Sopenharmony_ci else if (fus_dat3.cn70xx.nodfa_dte) 4188c2ecf20Sopenharmony_ci suffix = "SCP"; 4198c2ecf20Sopenharmony_ci else 4208c2ecf20Sopenharmony_ci suffix = "AAP"; 4218c2ecf20Sopenharmony_ci break; 4228c2ecf20Sopenharmony_ci case 0x97: /* CN73XX */ 4238c2ecf20Sopenharmony_ci if (num_cores == 6) /* Other core counts match generic */ 4248c2ecf20Sopenharmony_ci core_model = "35"; 4258c2ecf20Sopenharmony_ci family = "73"; 4268c2ecf20Sopenharmony_ci if (fus_dat3.cn73xx.l2c_crip == 2) 4278c2ecf20Sopenharmony_ci family = "72"; 4288c2ecf20Sopenharmony_ci if (fus_dat3.cn73xx.nozip 4298c2ecf20Sopenharmony_ci && fus_dat3.cn73xx.nodfa_dte 4308c2ecf20Sopenharmony_ci && fus_dat3.cn73xx.nohna_dte) { 4318c2ecf20Sopenharmony_ci if (!fus_dat2.cn73xx.raid_en) 4328c2ecf20Sopenharmony_ci suffix = "CP"; 4338c2ecf20Sopenharmony_ci else 4348c2ecf20Sopenharmony_ci suffix = "SCP"; 4358c2ecf20Sopenharmony_ci } else 4368c2ecf20Sopenharmony_ci suffix = "AAP"; 4378c2ecf20Sopenharmony_ci break; 4388c2ecf20Sopenharmony_ci case 0x98: /* CN75XX */ 4398c2ecf20Sopenharmony_ci family = "F75"; 4408c2ecf20Sopenharmony_ci if (fus_dat3.cn78xx.nozip 4418c2ecf20Sopenharmony_ci && fus_dat3.cn78xx.nodfa_dte 4428c2ecf20Sopenharmony_ci && fus_dat3.cn78xx.nohna_dte) 4438c2ecf20Sopenharmony_ci suffix = "SCP"; 4448c2ecf20Sopenharmony_ci else 4458c2ecf20Sopenharmony_ci suffix = "AAP"; 4468c2ecf20Sopenharmony_ci break; 4478c2ecf20Sopenharmony_ci default: 4488c2ecf20Sopenharmony_ci family = "XX"; 4498c2ecf20Sopenharmony_ci core_model = "XX"; 4508c2ecf20Sopenharmony_ci strcpy(pass, "X.X"); 4518c2ecf20Sopenharmony_ci suffix = "XXX"; 4528c2ecf20Sopenharmony_ci break; 4538c2ecf20Sopenharmony_ci } 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci clock_mhz = octeon_get_clock_rate() / 1000000; 4568c2ecf20Sopenharmony_ci if (family[0] != '3') { 4578c2ecf20Sopenharmony_ci int fuse_base = 384 / 8; 4588c2ecf20Sopenharmony_ci if (family[0] == '6') 4598c2ecf20Sopenharmony_ci fuse_base = 832 / 8; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci /* Check for model in fuses, overrides normal decode */ 4628c2ecf20Sopenharmony_ci /* This is _not_ valid for Octeon CN3XXX models */ 4638c2ecf20Sopenharmony_ci fuse_data |= cvmx_fuse_read_byte(fuse_base + 3); 4648c2ecf20Sopenharmony_ci fuse_data = fuse_data << 8; 4658c2ecf20Sopenharmony_ci fuse_data |= cvmx_fuse_read_byte(fuse_base + 2); 4668c2ecf20Sopenharmony_ci fuse_data = fuse_data << 8; 4678c2ecf20Sopenharmony_ci fuse_data |= cvmx_fuse_read_byte(fuse_base + 1); 4688c2ecf20Sopenharmony_ci fuse_data = fuse_data << 8; 4698c2ecf20Sopenharmony_ci fuse_data |= cvmx_fuse_read_byte(fuse_base); 4708c2ecf20Sopenharmony_ci if (fuse_data & 0x7ffff) { 4718c2ecf20Sopenharmony_ci int model = fuse_data & 0x3fff; 4728c2ecf20Sopenharmony_ci int suffix = (fuse_data >> 14) & 0x1f; 4738c2ecf20Sopenharmony_ci if (suffix && model) { 4748c2ecf20Sopenharmony_ci /* Have both number and suffix in fuses, so both */ 4758c2ecf20Sopenharmony_ci sprintf(fuse_model, "%d%c", model, 'A' + suffix - 1); 4768c2ecf20Sopenharmony_ci core_model = ""; 4778c2ecf20Sopenharmony_ci family = fuse_model; 4788c2ecf20Sopenharmony_ci } else if (suffix && !model) { 4798c2ecf20Sopenharmony_ci /* Only have suffix, so add suffix to 'normal' model number */ 4808c2ecf20Sopenharmony_ci sprintf(fuse_model, "%s%c", core_model, 'A' + suffix - 1); 4818c2ecf20Sopenharmony_ci core_model = fuse_model; 4828c2ecf20Sopenharmony_ci } else { 4838c2ecf20Sopenharmony_ci /* Don't have suffix, so just use model from fuses */ 4848c2ecf20Sopenharmony_ci sprintf(fuse_model, "%d", model); 4858c2ecf20Sopenharmony_ci core_model = ""; 4868c2ecf20Sopenharmony_ci family = fuse_model; 4878c2ecf20Sopenharmony_ci } 4888c2ecf20Sopenharmony_ci } 4898c2ecf20Sopenharmony_ci } 4908c2ecf20Sopenharmony_ci sprintf(buffer, "CN%s%sp%s-%d-%s", family, core_model, pass, clock_mhz, suffix); 4918c2ecf20Sopenharmony_ci return buffer; 4928c2ecf20Sopenharmony_ci} 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci/** 4958c2ecf20Sopenharmony_ci * Given the chip processor ID from COP0, this function returns a 4968c2ecf20Sopenharmony_ci * string representing the chip model number. The string is of the 4978c2ecf20Sopenharmony_ci * form CNXXXXpX.X-FREQ-SUFFIX. 4988c2ecf20Sopenharmony_ci * - XXXX = The chip model number 4998c2ecf20Sopenharmony_ci * - X.X = Chip pass number 5008c2ecf20Sopenharmony_ci * - FREQ = Current frequency in Mhz 5018c2ecf20Sopenharmony_ci * - SUFFIX = NSP, EXP, SCP, SSP, or CP 5028c2ecf20Sopenharmony_ci * 5038c2ecf20Sopenharmony_ci * @chip_id: Chip ID 5048c2ecf20Sopenharmony_ci * 5058c2ecf20Sopenharmony_ci * Returns Model string 5068c2ecf20Sopenharmony_ci */ 5078c2ecf20Sopenharmony_ciconst char *__init octeon_model_get_string(uint32_t chip_id) 5088c2ecf20Sopenharmony_ci{ 5098c2ecf20Sopenharmony_ci static char buffer[32]; 5108c2ecf20Sopenharmony_ci return octeon_model_get_string_buffer(chip_id, buffer); 5118c2ecf20Sopenharmony_ci} 512