tomahawk3.c (211045B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: tomahawk3.c 8 * Purpose: 9 * Requires: 10 */ 11 12 13 #include <shared/bsl.h> 14 15 #include <sal/core/boot.h> 16 #include <sal/core/dpc.h> 17 #include <shared/bsl.h> 18 #include <soc/tdm/core/tdm_top.h> 19 #ifdef BCM_CMICX_SUPPORT 20 #include <soc/cmicx.h> 21 #include <soc/cmicx_miim.h> 22 #endif 23 #include <soc/bradley.h> 24 #include <soc/drv.h> 25 #include <soc/error.h> 26 #include <soc/debug.h> 27 #include <soc/mem.h> 28 #include <soc/i2c.h> 29 #include <soc/l2x.h> 30 #include <soc/soc_ser_log.h> 31 #include <soc/iproc.h> 32 #include <soc/mcm/intr_iproc.h> 33 34 #ifdef BCM_TOMAHAWK3_SUPPORT 35 36 #ifdef ALPM_ENABLE 37 #include <soc/lpm.h> 38 #include <soc/alpm.h> 39 #include <soc/esw/alpm_int.h> 40 #endif /* ALPM_ENABLE */ 41 42 #include <soc/esw/portctrl.h> 43 44 #include <soc/mmu_config.h> 45 #include <soc/tomahawk.h> 46 #include <soc/tomahawk3.h> 47 #include <soc/init/tomahawk3_tdm.h> 48 #include <soc/init/tomahawk3_idb_init.h> 49 #include <soc/trident2.h> 50 #include <soc/drv.h> 51 #include <soc/pfc.h> 52 #include <soc/pstats.h> 53 54 #define NUM_READS 200 55 56 #define _SOC_TH3_HW_TEMP_MAX (125) 57 #define _SOC_TH3_SW_TEMP_MAX (110) 58 59 #define UPDATE_ALL_PIPES -1 60 61 #define _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(ptype) \ 62 si->ptype.num = 0; \ 63 si->ptype.min = si->ptype.max = -1; \ 64 PBMP_ITER(si->ptype.bitmap, it_port) { \ 65 si->ptype.port[si->ptype.num++] = it_port; \ 66 if (si->ptype.min < 0) { \ 67 si->ptype.min = it_port; \ 68 } \ 69 if (it_port > si->ptype.max) { \ 70 si->ptype.max = it_port; \ 71 } \ 72 } 73 74 static int num_shared_alpm_banks[SOC_MAX_NUM_DEVICES] = {0}; 75 static soc_mem_t *_soc_th3_lpm_view_map[SOC_MAX_NUM_DEVICES]; 76 uint32 _soc_mem_entry_reset_value[1] = {1}; 77 78 soc_th_latency_table_cfg_t 79 soc_th3_tbl_cfg[SOC_MAX_NUM_DEVICES] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; 80 81 static const soc_reg_t temp_thr_reg[] = { 82 TOP_PVTMON_0_INTR_THRESHOLDr, TOP_PVTMON_1_INTR_THRESHOLDr, 83 TOP_PVTMON_2_INTR_THRESHOLDr, TOP_PVTMON_3_INTR_THRESHOLDr, 84 TOP_PVTMON_4_INTR_THRESHOLDr, TOP_PVTMON_5_INTR_THRESHOLDr, 85 TOP_PVTMON_6_INTR_THRESHOLDr, TOP_PVTMON_7_INTR_THRESHOLDr, 86 TOP_PVTMON_8_INTR_THRESHOLDr, TOP_PVTMON_9_INTR_THRESHOLDr, 87 TOP_PVTMON_10_INTR_THRESHOLDr, TOP_PVTMON_11_INTR_THRESHOLDr, 88 TOP_PVTMON_12_INTR_THRESHOLDr, TOP_PVTMON_13_INTR_THRESHOLDr, 89 TOP_PVTMON_14_INTR_THRESHOLDr, TOP_PVTMON_15_INTR_THRESHOLDr 90 }; 91 static const soc_reg_t pvtmon_ctrl_1_reg_th3[] = { 92 TOP_PVTMON_0_CTRL_1r, TOP_PVTMON_1_CTRL_1r, 93 TOP_PVTMON_2_CTRL_1r, TOP_PVTMON_3_CTRL_1r, 94 TOP_PVTMON_4_CTRL_1r 95 }; 96 97 static const struct { 98 soc_reg_t pvtmon_reg; 99 soc_field_t pvtmon_field; 100 } temp_pvtmon_ctrl_reg[] = { 101 {TOP_PVTMON_0_CTRL_1r, TOP_PVT_MON_MIN_RST_Lf}, 102 {TOP_PVTMON_1_CTRL_1r, TOP_PVT_MON_MIN_RST_Lf}, 103 {TOP_PVTMON_2_CTRL_1r, TOP_PVT_MON_MIN_RST_Lf}, 104 {TOP_PVTMON_3_CTRL_1r, TOP_PVT_MON_MIN_RST_Lf}, 105 {TOP_PVTMON_4_CTRL_1r, TOP_PVT_MON_MIN_RST_Lf}, 106 {TOP_PVTMON_13_17_CTRL_1r, PVTMON13_TOP_PVT_MON_MIN_RST_Lf}, 107 {TOP_PVTMON_13_17_CTRL_1r, PVTMON14_TOP_PVT_MON_MIN_RST_Lf}, 108 {TOP_PVTMON_13_17_CTRL_1r, PVTMON15_TOP_PVT_MON_MIN_RST_Lf}, 109 }; 110 111 static const char *temp_thr_prop[] = { 112 "temp0_threshold", "temp1_threshold", "temp2_threshold", 113 "temp3_threshold", "temp4_threshold", "temp5_threshold", 114 "temp6_threshold", "temp7_threshold", "temp8_threshold", 115 "temp9_threshold", "temp10_threshold", "temp11_threshold", 116 "temp12_threshold", "temp13_threshold", "temp14_threshold", 117 "temp15_threshold" 118 }; 119 120 static const soc_reg_t pvtmon_result_reg_th3[] = { 121 TOP_PVTMON_RESULT_0r, TOP_PVTMON_RESULT_1r, 122 TOP_PVTMON_RESULT_2r, TOP_PVTMON_RESULT_3r, 123 TOP_PVTMON_RESULT_4r, TOP_PVTMON_RESULT_5r, 124 TOP_PVTMON_RESULT_6r, TOP_PVTMON_RESULT_7r, 125 TOP_PVTMON_RESULT_8r, TOP_PVTMON_RESULT_9r, 126 TOP_PVTMON_RESULT_10r, TOP_PVTMON_RESULT_11r, 127 TOP_PVTMON_RESULT_12r, TOP_PVTMON_RESULT_13r, 128 TOP_PVTMON_RESULT_14r, AVS_REG_RO_REGISTERS_0_PVT_TEMPERATURE_MNTR_STATUSr 129 }; 130 131 int 132 soc_tomahawk3_mem_config(int unit) 133 { 134 #define _SOC_TH3_DEFIP_MAX_TCAMS 8 135 #define _SOC_TH3_DEFIP_TCAM_DEPTH 256 136 #define _SOC_TH3_FIXED_L2_TBL_SZ (8 * 1024) 137 #define _SOC_TH3_FIXED_L3_TBL_SZ (16 * 1024) 138 soc_persist_t *sop; 139 int l2_entries, l3_entries; 140 int num_ipv6_128b_entries = 0; 141 int config_v6_entries = 0; 142 int defip_config = 0; 143 int fpem_entries = 0, shared_fpem_banks = 0; 144 int alpm_enable; 145 int max_tcams = _SOC_TH3_DEFIP_MAX_TCAMS; 146 int tcam_depth = _SOC_TH3_DEFIP_TCAM_DEPTH; 147 int def_ipv6_128b_entries = 0; 148 149 sop = SOC_PERSIST(unit); 150 151 /* TH3 Emulation has only 16 entries per TCAM slice */ 152 tcam_depth = 153 soc_property_get(unit, "l3_defip_tcam_depth", _SOC_TH3_DEFIP_TCAM_DEPTH); 154 def_ipv6_128b_entries = tcam_depth * max_tcams / 4; 155 156 /* Fetch L2 entries */ 157 l2_entries = 158 soc_property_get(unit, spn_L2_MEM_ENTRIES, _SOC_TH3_FIXED_L2_TBL_SZ); 159 if (l2_entries > _SOC_TH3_FIXED_L2_TBL_SZ) { 160 LOG_CLI(("ERROR: Unsupported L2 table size specified in config.bcm\n")); 161 LOG_CLI(("INFO : L2 table size reduced to 8K \n")); 162 } 163 l2_entries = _SOC_TH3_FIXED_L2_TBL_SZ; /* 8k dedicated L2 entries */ 164 165 /* Fetch L3 entries */ 166 l3_entries = 167 soc_property_get(unit, spn_L3_MEM_ENTRIES, _SOC_TH3_FIXED_L3_TBL_SZ); 168 if (l3_entries > _SOC_TH3_FIXED_L3_TBL_SZ) { 169 LOG_CLI(("ERROR: Unsupported L3 table size specified in config.bcm\n")); 170 LOG_CLI(("INFO : L3 table size reduced to 16K \n")); 171 } 172 l3_entries = _SOC_TH3_FIXED_L3_TBL_SZ; /* 16k dedicated L3 entries */ 173 174 /* Fetch ALPM enable mode */ 175 alpm_enable = soc_property_get(unit, spn_L3_ALPM_ENABLE, 0); 176 177 /* Fetch FPEM entries 178 * Check if config parameter fpem_mem_entries is defined in the 179 * file. If not defined then choose default based on ALPM mode 180 * requested. If ALPM is requested, then no FPEM as user wants to 181 * use 8 bank (full) mode ALPM. If ALPM is not requested then assign 182 * max(64K) for FPEM. If fpem_mem_entries is defined then use that 183 */ 184 if (NULL == soc_property_get_str(unit, spn_FPEM_MEM_ENTRIES)) { 185 fpem_entries = (alpm_enable) ? 0 : (64 * 1024); 186 } else { 187 fpem_entries = soc_property_get(unit, spn_FPEM_MEM_ENTRIES, 0); 188 } 189 /* Find out how many UFT banks are taken up by FPEM */ 190 shared_fpem_banks = (fpem_entries + (16 * 1024 - 1)) / (16 * 1024); 191 fpem_entries = shared_fpem_banks * 16 * 1024; 192 193 /* Max 4 banks from UFT Shared table can be used by FPEM */ 194 if (shared_fpem_banks > 4) { 195 LOG_CLI(("ERROR: Unsupported FPEM_MEM_ENTRIES in config.bcm\n")); 196 return SOC_E_PARAM; 197 } 198 199 /* Adjust L2 table size */ 200 sop->memState[L2Xm].index_max = l2_entries - 1; 201 sop->memState[L2_ENTRY_ECCm].index_max = l2_entries - 1; 202 sop->memState[L2_HITDA_ONLYm].index_max = l2_entries / 4 - 1; 203 sop->memState[L2_HITSA_ONLYm].index_max = l2_entries / 4 - 1; 204 205 /* Adjust L3 table size */ 206 sop->memState[L3_ENTRY_SINGLEm].index_max = l3_entries - 1; 207 sop->memState[L3_ENTRY_ECCm].index_max = l3_entries - 1; 208 sop->memState[L3_ENTRY_HIT_ONLYm].index_max = l3_entries / 4 - 1; 209 210 /* Adjust FP exact match table size */ 211 sop->memState[EXACT_MATCH_2m].index_max = fpem_entries - 1; 212 sop->memState[EXACT_MATCH_4m].index_max = fpem_entries / 2 - 1; 213 214 SOC_CONTROL(unit)->l3_defip_max_tcams = max_tcams; 215 SOC_CONTROL(unit)->l3_defip_tcam_size = tcam_depth; 216 217 if (soc_feature(unit, soc_feature_alpm)) { 218 _soc_alpm_mode[unit] = alpm_enable; 219 } 220 if (soc_property_get(unit, "l3_defip_sizing", TRUE)) { 221 if (!(soc_feature(unit, soc_feature_alpm) && alpm_enable)) { 222 defip_config = soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 1); 223 224 num_ipv6_128b_entries = 225 soc_property_get(unit, spn_NUM_IPV6_LPM_128B_ENTRIES, 226 (defip_config ? def_ipv6_128b_entries : 0)); 227 num_ipv6_128b_entries = num_ipv6_128b_entries + 228 (num_ipv6_128b_entries % 2); 229 230 config_v6_entries = num_ipv6_128b_entries; 231 if (soc_property_get(unit, spn_LPM_SCALING_ENABLE, 0)) { 232 num_ipv6_128b_entries = 0; 233 if (!soc_property_get(unit, spn_LPM_IPV6_128B_RESERVED, 1)) { 234 config_v6_entries = 235 ((config_v6_entries / 236 SOC_CONTROL(unit)->l3_defip_tcam_size) + 237 ((config_v6_entries % 238 SOC_CONTROL(unit)->l3_defip_tcam_size 239 ) ? 1 : 0) 240 ) * SOC_CONTROL(unit)->l3_defip_tcam_size; 241 } 242 } 243 sop->memState[L3_DEFIP_PAIR_LEVEL1m].index_max = 244 num_ipv6_128b_entries - 1; 245 sop->memState[L3_DEFIP_LEVEL1m].index_max = 246 (SOC_CONTROL(unit)->l3_defip_max_tcams * 247 SOC_CONTROL(unit)->l3_defip_tcam_size) - 248 (num_ipv6_128b_entries * 2) - 1; 249 250 SOC_CONTROL(unit)->l3_defip_index_remap = num_ipv6_128b_entries; 251 } else { 252 if (soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 1)) { 253 /* slightly different processing for v6-128 */ 254 num_ipv6_128b_entries = soc_property_get(unit, 255 spn_NUM_IPV6_LPM_128B_ENTRIES, 256 def_ipv6_128b_entries); 257 num_ipv6_128b_entries = num_ipv6_128b_entries + 258 (num_ipv6_128b_entries % 2); 259 if (soc_tomahawk_alpm_mode_get(unit) == 1 || 260 soc_tomahawk_alpm_mode_get(unit) == 3) { 261 num_ipv6_128b_entries = (num_ipv6_128b_entries + 3) / 4 * 4; 262 } 263 config_v6_entries = num_ipv6_128b_entries; 264 sop->memState[L3_DEFIP_PAIR_LEVEL1m].index_max = 265 num_ipv6_128b_entries - 1; 266 sop->memState[L3_DEFIP_LEVEL1m].index_max = 267 (SOC_CONTROL(unit)->l3_defip_max_tcams * 268 SOC_CONTROL(unit)->l3_defip_tcam_size) - 269 (num_ipv6_128b_entries * 2) - 1; 270 271 SOC_CONTROL(unit)->l3_defip_index_remap = 272 (num_ipv6_128b_entries / 2) * 2; 273 } else { 274 sop->memState[L3_DEFIP_PAIR_LEVEL1m].index_max = -1; 275 } 276 } 277 soc_l3_defip_indexes_init(unit, config_v6_entries); 278 } 279 280 if (fpem_entries > 0) { 281 num_shared_alpm_banks[unit] = 4; 282 } else { 283 num_shared_alpm_banks[unit] = 8; 284 } 285 286 /* update tbl cfg to latency subsystem for diag purposes */ 287 soc_th3_tbl_cfg[unit].l2_entries = l2_entries; 288 soc_th3_tbl_cfg[unit].fixed_l2_entries = l2_entries; 289 soc_th3_tbl_cfg[unit].shared_l2_banks = 0; 290 soc_th3_tbl_cfg[unit].l3_entries = l3_entries; 291 soc_th3_tbl_cfg[unit].fixed_l3_entries = l3_entries; 292 soc_th3_tbl_cfg[unit].shared_l3_banks = 0; 293 soc_th3_tbl_cfg[unit].fpem_entries = fpem_entries; 294 soc_th3_tbl_cfg[unit].shared_fpem_banks = shared_fpem_banks; 295 soc_th3_tbl_cfg[unit].alpm_enable = alpm_enable; 296 soc_th3_tbl_cfg[unit].max_tcams = max_tcams; 297 soc_th3_tbl_cfg[unit].tcam_depth = tcam_depth; 298 299 if (_soc_th3_lpm_view_map[unit] != NULL) { 300 sal_free(_soc_th3_lpm_view_map[unit]); 301 _soc_th3_lpm_view_map[unit] = NULL; 302 } 303 304 _soc_th3_lpm_view_map[unit] = sal_alloc((sizeof(soc_mem_t) * 305 SOC_L3_DEFIP_MAX_TCAMS_GET(unit) * 306 SOC_L3_DEFIP_TCAM_DEPTH_GET(unit)), 307 "lpm_view_map"); 308 if (NULL == _soc_th3_lpm_view_map[unit]) { 309 return SOC_E_MEMORY; 310 } 311 312 sal_memset(_soc_th3_lpm_view_map[unit], INVALIDm, 313 sizeof(soc_mem_t) * 314 SOC_L3_DEFIP_MAX_TCAMS_GET(unit) * 315 SOC_L3_DEFIP_TCAM_DEPTH_GET(unit)); 316 317 return SOC_E_NONE; 318 } 319 320 int 321 soc_tomahawk3_mem_cpu_write_control(int unit, soc_mem_t mem, int copyno, 322 int enable, int *orig_enable) 323 { 324 soc_reg_t reg; 325 soc_field_t field; 326 uint32 rval = 0, fval; 327 int blk, port, block_info_index; 328 uint32 orig_fval, enable_fval, disable_fval; 329 330 enable_fval = 1; 331 disable_fval = 0; 332 333 switch (mem) { 334 case CLPORT_WC_UCMEM_DATAm: 335 reg = CLPORT_WC_UCMEM_CTRLr; 336 field = ACCESS_MODEf; 337 SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) { 338 port = SOC_BLOCK_PORT(unit, blk); 339 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 340 /* It will use the setting from the last block */ 341 *orig_enable = soc_reg_field_get(unit, reg, rval, field); 342 soc_reg_field_set(unit, reg, &rval, field, enable ? 1 : 0); 343 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval)); 344 } 345 return SOC_E_NONE; 346 347 case MMU_MTRO_EGRMETERINGBUCKET_PIPE0m: 348 case MMU_MTRO_EGRMETERINGBUCKET_PIPE1m: 349 case MMU_MTRO_EGRMETERINGBUCKET_PIPE2m: 350 case MMU_MTRO_EGRMETERINGBUCKET_PIPE3m: 351 case MMU_MTRO_EGRMETERINGBUCKET_PIPE4m: 352 case MMU_MTRO_EGRMETERINGBUCKET_PIPE5m: 353 case MMU_MTRO_EGRMETERINGBUCKET_PIPE6m: 354 case MMU_MTRO_EGRMETERINGBUCKET_PIPE7m: 355 case MMU_MTRO_BUCKET_CPU_L1_PIPE0m: 356 case MMU_MTRO_BUCKET_CPU_L1_PIPE1m: 357 case MMU_MTRO_BUCKET_CPU_L1_PIPE2m: 358 case MMU_MTRO_BUCKET_CPU_L1_PIPE3m: 359 case MMU_MTRO_BUCKET_CPU_L1_PIPE4m: 360 case MMU_MTRO_BUCKET_CPU_L1_PIPE5m: 361 case MMU_MTRO_BUCKET_CPU_L1_PIPE6m: 362 case MMU_MTRO_BUCKET_CPU_L1_PIPE7m: 363 case MMU_MTRO_BUCKET_L0_PIPE0m: 364 case MMU_MTRO_BUCKET_L0_PIPE1m: 365 case MMU_MTRO_BUCKET_L0_PIPE2m: 366 case MMU_MTRO_BUCKET_L0_PIPE3m: 367 case MMU_MTRO_BUCKET_L0_PIPE4m: 368 case MMU_MTRO_BUCKET_L0_PIPE5m: 369 case MMU_MTRO_BUCKET_L0_PIPE6m: 370 case MMU_MTRO_BUCKET_L0_PIPE7m: 371 reg = MMU_MTRO_CONFIGr; 372 field = REFRESH_DISABLEf; 373 enable_fval = 1; 374 disable_fval = 0; 375 SOC_IF_ERROR_RETURN 376 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 377 orig_fval = soc_reg_field_get(unit, reg, rval, field); 378 fval = enable ? enable_fval : disable_fval; 379 *orig_enable = orig_fval == enable_fval; 380 if (fval != orig_fval) { 381 soc_reg_field_set(unit, reg, &rval, field, fval); 382 SOC_IF_ERROR_RETURN 383 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 384 } 385 return SOC_E_NONE; 386 387 case MMU_WRED_AVG_QSIZE_ITM0m: 388 case MMU_WRED_AVG_QSIZE_ITM1m: 389 case MMU_WRED_AVG_PORTSP_SIZE_ITM0m: 390 case MMU_WRED_AVG_PORTSP_SIZE_ITM1m: 391 case MMU_WRED_PORT_SP_DROP_THD_0_ITM0m: 392 case MMU_WRED_PORT_SP_DROP_THD_0_ITM1m: 393 case MMU_WRED_PORT_SP_DROP_THD_1_ITM0m: 394 case MMU_WRED_PORT_SP_DROP_THD_1_ITM1m: 395 case MMU_WRED_PORT_SP_DROP_THD_2_ITM0m: 396 case MMU_WRED_PORT_SP_DROP_THD_2_ITM1m: 397 case MMU_WRED_PORT_SP_DROP_THD_3_ITM0m: 398 case MMU_WRED_PORT_SP_DROP_THD_3_ITM1m: 399 case MMU_WRED_UC_QUEUE_DROP_THD_ITM0m: 400 case MMU_WRED_UC_QUEUE_DROP_THD_ITM1m: 401 case MMU_WRED_UC_QUEUE_DROP_THD_MARK_0_ITM0m: 402 case MMU_WRED_UC_QUEUE_DROP_THD_MARK_0_ITM1m: 403 case MMU_WRED_UC_QUEUE_DROP_THD_MARK_1_ITM0m: 404 case MMU_WRED_UC_QUEUE_DROP_THD_MARK_1_ITM1m: 405 reg = MMU_WRED_REFRESH_CONTROLr; 406 field = REFRESH_DISABLEf; 407 enable_fval = 1; 408 disable_fval = 0; 409 SOC_IF_ERROR_RETURN 410 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 411 orig_fval = soc_reg_field_get(unit, reg, rval, field); 412 fval = enable ? enable_fval : disable_fval; 413 *orig_enable = orig_fval == enable_fval; 414 if (fval != orig_fval) { 415 soc_reg_field_set(unit, reg, &rval, field, fval); 416 SOC_IF_ERROR_RETURN 417 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 418 } 419 return SOC_E_NONE; 420 421 case MMU_QSCH_L2_WEIGHT_MEM_PIPE0m: 422 case MMU_QSCH_L2_WEIGHT_MEM_PIPE1m: 423 case MMU_QSCH_L2_WEIGHT_MEM_PIPE2m: 424 case MMU_QSCH_L2_WEIGHT_MEM_PIPE3m: 425 case MMU_QSCH_L2_WEIGHT_MEM_PIPE4m: 426 case MMU_QSCH_L2_WEIGHT_MEM_PIPE5m: 427 case MMU_QSCH_L2_WEIGHT_MEM_PIPE6m: 428 case MMU_QSCH_L2_WEIGHT_MEM_PIPE7m: 429 reg = MMU_QSCH_VOQ_FAIRNESS_CONFIGr; 430 field = DYNAMIC_WEIGHT_ENABLEf; 431 enable_fval = 0; 432 disable_fval = 1; 433 SOC_IF_ERROR_RETURN 434 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 435 orig_fval = soc_reg_field_get(unit, reg, rval, field); 436 fval = enable ? enable_fval : disable_fval; 437 *orig_enable = orig_fval == enable_fval; 438 if (fval != orig_fval) { 439 soc_reg_field_set(unit, reg, &rval, field, fval); 440 SOC_IF_ERROR_RETURN 441 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 442 } 443 return SOC_E_NONE; 444 445 case MMU_EBMB_CCBE_SLICE_CPU_PIPE0m: 446 case MMU_EBMB_CCBE_SLICE_CPU_PIPE1m: 447 case MMU_EBMB_CCBE_SLICE_CPU_PIPE2m: 448 case MMU_EBMB_CCBE_SLICE_CPU_PIPE3m: 449 case MMU_EBMB_CCBE_SLICE_CPU_PIPE4m: 450 case MMU_EBMB_CCBE_SLICE_CPU_PIPE5m: 451 case MMU_EBMB_CCBE_SLICE_CPU_PIPE6m: 452 case MMU_EBMB_CCBE_SLICE_CPU_PIPE7m: 453 case MMU_EBMB_PAYLOAD_SLICE0_CPU_PIPE0m: 454 case MMU_EBMB_PAYLOAD_SLICE0_CPU_PIPE1m: 455 case MMU_EBMB_PAYLOAD_SLICE0_CPU_PIPE2m: 456 case MMU_EBMB_PAYLOAD_SLICE0_CPU_PIPE3m: 457 case MMU_EBMB_PAYLOAD_SLICE0_CPU_PIPE4m: 458 case MMU_EBMB_PAYLOAD_SLICE0_CPU_PIPE5m: 459 case MMU_EBMB_PAYLOAD_SLICE0_CPU_PIPE6m: 460 case MMU_EBMB_PAYLOAD_SLICE0_CPU_PIPE7m: 461 case MMU_EBMB_PAYLOAD_SLICE1_CPU_PIPE0m: 462 case MMU_EBMB_PAYLOAD_SLICE1_CPU_PIPE1m: 463 case MMU_EBMB_PAYLOAD_SLICE1_CPU_PIPE2m: 464 case MMU_EBMB_PAYLOAD_SLICE1_CPU_PIPE3m: 465 case MMU_EBMB_PAYLOAD_SLICE1_CPU_PIPE4m: 466 case MMU_EBMB_PAYLOAD_SLICE1_CPU_PIPE5m: 467 case MMU_EBMB_PAYLOAD_SLICE1_CPU_PIPE6m: 468 case MMU_EBMB_PAYLOAD_SLICE1_CPU_PIPE7m: 469 case MMU_EBMB_PAYLOAD_SLICE2_CPU_PIPE0m: 470 case MMU_EBMB_PAYLOAD_SLICE2_CPU_PIPE1m: 471 case MMU_EBMB_PAYLOAD_SLICE2_CPU_PIPE2m: 472 case MMU_EBMB_PAYLOAD_SLICE2_CPU_PIPE3m: 473 case MMU_EBMB_PAYLOAD_SLICE2_CPU_PIPE4m: 474 case MMU_EBMB_PAYLOAD_SLICE2_CPU_PIPE5m: 475 case MMU_EBMB_PAYLOAD_SLICE2_CPU_PIPE6m: 476 case MMU_EBMB_PAYLOAD_SLICE2_CPU_PIPE7m: 477 case MMU_EBMB_PAYLOAD_SLICE3_CPU_PIPE0m: 478 case MMU_EBMB_PAYLOAD_SLICE3_CPU_PIPE1m: 479 case MMU_EBMB_PAYLOAD_SLICE3_CPU_PIPE2m: 480 case MMU_EBMB_PAYLOAD_SLICE3_CPU_PIPE3m: 481 case MMU_EBMB_PAYLOAD_SLICE3_CPU_PIPE4m: 482 case MMU_EBMB_PAYLOAD_SLICE3_CPU_PIPE5m: 483 case MMU_EBMB_PAYLOAD_SLICE3_CPU_PIPE6m: 484 case MMU_EBMB_PAYLOAD_SLICE3_CPU_PIPE7m: 485 case MMU_EBMB_PAYLOAD_SLICE4_CPU_PIPE0m: 486 case MMU_EBMB_PAYLOAD_SLICE4_CPU_PIPE1m: 487 case MMU_EBMB_PAYLOAD_SLICE4_CPU_PIPE2m: 488 case MMU_EBMB_PAYLOAD_SLICE4_CPU_PIPE3m: 489 case MMU_EBMB_PAYLOAD_SLICE4_CPU_PIPE4m: 490 case MMU_EBMB_PAYLOAD_SLICE4_CPU_PIPE5m: 491 case MMU_EBMB_PAYLOAD_SLICE4_CPU_PIPE6m: 492 case MMU_EBMB_PAYLOAD_SLICE4_CPU_PIPE7m: 493 case MMU_EBMB_PAYLOAD_SLICE5_CPU_PIPE0m: 494 case MMU_EBMB_PAYLOAD_SLICE5_CPU_PIPE1m: 495 case MMU_EBMB_PAYLOAD_SLICE5_CPU_PIPE2m: 496 case MMU_EBMB_PAYLOAD_SLICE5_CPU_PIPE3m: 497 case MMU_EBMB_PAYLOAD_SLICE5_CPU_PIPE4m: 498 case MMU_EBMB_PAYLOAD_SLICE5_CPU_PIPE5m: 499 case MMU_EBMB_PAYLOAD_SLICE5_CPU_PIPE6m: 500 case MMU_EBMB_PAYLOAD_SLICE5_CPU_PIPE7m: 501 case MMU_EBMB_PAYLOAD_SLICE6_CPU_PIPE0m: 502 case MMU_EBMB_PAYLOAD_SLICE6_CPU_PIPE1m: 503 case MMU_EBMB_PAYLOAD_SLICE6_CPU_PIPE2m: 504 case MMU_EBMB_PAYLOAD_SLICE6_CPU_PIPE3m: 505 case MMU_EBMB_PAYLOAD_SLICE6_CPU_PIPE4m: 506 case MMU_EBMB_PAYLOAD_SLICE6_CPU_PIPE5m: 507 case MMU_EBMB_PAYLOAD_SLICE6_CPU_PIPE6m: 508 case MMU_EBMB_PAYLOAD_SLICE6_CPU_PIPE7m: 509 case MMU_EBMB_PAYLOAD_SLICE7_CPU_PIPE0m: 510 case MMU_EBMB_PAYLOAD_SLICE7_CPU_PIPE1m: 511 case MMU_EBMB_PAYLOAD_SLICE7_CPU_PIPE2m: 512 case MMU_EBMB_PAYLOAD_SLICE7_CPU_PIPE3m: 513 case MMU_EBMB_PAYLOAD_SLICE7_CPU_PIPE4m: 514 case MMU_EBMB_PAYLOAD_SLICE7_CPU_PIPE5m: 515 case MMU_EBMB_PAYLOAD_SLICE7_CPU_PIPE6m: 516 case MMU_EBMB_PAYLOAD_SLICE7_CPU_PIPE7m: 517 reg = MMU_EBPTS_CBMG_VALUEr; 518 field = MMU_NULL_SLOT_COUNTER_VALUEf; 519 enable_fval = 0; 520 disable_fval = 1; 521 SOC_IF_ERROR_RETURN 522 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 523 orig_fval = soc_reg_field_get(unit, reg, rval, field); 524 fval = enable ? enable_fval : disable_fval; 525 *orig_enable = orig_fval == enable_fval; 526 if (fval != orig_fval) { 527 soc_reg_field_set(unit, reg, &rval, field, fval); 528 SOC_IF_ERROR_RETURN 529 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 530 } 531 return SOC_E_NONE; 532 533 default: 534 block_info_index = SOC_MEM_BLOCK_ANY(unit, mem); 535 if ((SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_XPE) || 536 (SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_SC)){ 537 reg = MMU_GCFG_MISCCONFIGr; 538 field = REFRESH_ENf; 539 enable_fval = 0; 540 disable_fval = 1; 541 SOC_IF_ERROR_RETURN 542 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 543 orig_fval = soc_reg_field_get(unit, reg, rval, field); 544 fval = enable ? enable_fval : disable_fval; 545 *orig_enable = orig_fval == enable_fval; 546 if (fval != orig_fval) { 547 soc_reg_field_set(unit, reg, &rval, field, fval); 548 SOC_IF_ERROR_RETURN 549 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 550 } 551 } 552 return _soc_trident2_mem_cpu_write_control(unit, mem, copyno, 553 enable, orig_enable); 554 } 555 return SOC_E_NONE; 556 } 557 558 int 559 soc_tomahawk3_reg_cpu_write_control(int unit, int enable) 560 { 561 uint32 intfo_dis = 0; 562 563 if (enable) { 564 /* Disable HW updates */ 565 soc_reg_field_set(unit, MMU_INTFO_HW_UPDATE_DISr, &intfo_dis, 566 RQE_SPf, 1); 567 soc_reg_field_set(unit, MMU_INTFO_HW_UPDATE_DISr, &intfo_dis, 568 EG_SPf, 1); 569 soc_reg_field_set(unit, MMU_INTFO_HW_UPDATE_DISr, &intfo_dis, 570 ING_SPf, 1); 571 soc_reg_field_set(unit, MMU_INTFO_HW_UPDATE_DISr, &intfo_dis, 572 CONGST_STf, 1); 573 } 574 SOC_IF_ERROR_RETURN(WRITE_MMU_INTFO_HW_UPDATE_DISr(unit, intfo_dis)); 575 576 return SOC_E_NONE; 577 } 578 579 uint32 _soc_th3_mmu_port(int unit, int port) 580 { 581 soc_info_t *si = &SOC_INFO(unit); 582 return si->port_p2m_mapping[si->port_l2p_mapping[port]]; 583 } 584 585 STATIC int 586 soc_tomahawk3_max_frequency_get(int unit, uint16 dev_id, uint8 rev_id, 587 int skew_id, int *frequency) 588 { 589 switch (dev_id) { 590 case BCM56984_DEVICE_ID: 591 *frequency = 925; 592 break; 593 default: 594 *frequency = 1325; 595 break; 596 } 597 598 return SOC_E_NONE; 599 } 600 601 void 602 soc_tomahawk3_tsc_map_get(int unit, uint32 *tsc_map) 603 { 604 *tsc_map = 0xffffffff; 605 } 606 607 void 608 soc_tomahawk3_pipe_map_get(int unit, uint32 *pipe_map) 609 { 610 soc_info_t *si; 611 int port; 612 613 si = &SOC_INFO(unit); 614 615 *pipe_map = 0; 616 PBMP_LB_ITER(unit, port) { 617 *pipe_map |= 1 << si->port_pipe[port]; 618 } 619 } 620 621 int soc_tomahawk3_itm_valid(int unit, int itm) { 622 soc_info_t *si; 623 uint32 itm_map; 624 625 si = &SOC_INFO(unit); 626 itm_map = si->itm_map; 627 628 if (itm < 0 || itm >= NUM_ITM(unit)) { 629 return 0; 630 } 631 if (itm_map & (1U << itm)) { 632 return 1; 633 } 634 return 0; 635 } 636 637 /* Function: 638 * _soc_tomahawk3_port_flex_init 639 * Purpose: 640 * Set flexport configuration parameters from the config file. 641 * Parameters: 642 * unit - (IN) Unit number. 643 * is_any_cap - (IN) All PM can flex 644 * Returns: 645 * SOC_E_XXX 646 */ 647 STATIC int 648 _soc_tomahawk3_port_flex_init(int unit, int is_any_cap) 649 { 650 soc_info_t *si; 651 int pm, blk_idx, blk_type; 652 int flex_en, static_ports, max_ports; 653 654 si = &SOC_INFO(unit); 655 SHR_BITCLR_RANGE(si->flexible_pm_bitmap, 0, SOC_MAX_NUM_BLKS); 656 657 /* portmap_x=y:speed:i */ 658 /* portmap_x=y:speed:cap */ 659 if (SOC_PBMP_NOT_NULL(SOC_PORT_DISABLED_BITMAP(unit, all)) || is_any_cap) { 660 SHR_BITSET_RANGE(si->flexible_pm_bitmap, 1, _TH3_PBLKS_PER_DEV); 661 } else { 662 /* port_flex_enable */ 663 for (blk_idx = 0; blk_idx < SOC_MAX_NUM_BLKS; blk_idx++) { 664 blk_type = SOC_BLOCK_TYPE(unit, blk_idx); 665 pm = SOC_BLOCK_NUMBER(unit, blk_idx); 666 if (blk_type == SOC_BLK_CDPORT) { 667 /* port_flex_enable_corex=<0...1> */ 668 flex_en = soc_property_suffix_num_get_only_suffix(unit, 669 pm, spn_PORT_FLEX_ENABLE, "core", -1); 670 /* port_flex_enable{x}=<0...1> */ 671 /* port_flex_enable=<0...1> */ 672 if (flex_en == -1) { 673 flex_en = soc_property_phys_port_get(unit, 674 (pm * _TH3_PORTS_PER_PBLK + 1), 675 spn_PORT_FLEX_ENABLE, 0); 676 } 677 if (flex_en) { 678 SHR_BITSET(si->flexible_pm_bitmap, blk_idx); 679 } 680 } 681 } 682 } 683 684 /* TH3's CDPORT blocks start at 65 */ 685 si->flex_eligible = 686 (!SHR_BITNULL_RANGE(si->flexible_pm_bitmap, 65, _TH3_PBLKS_PER_DEV)); 687 688 /* port_flex_max_ports */ 689 memset(&(si->pm_max_ports), 0xff, sizeof(si->pm_max_ports)); 690 for (blk_idx = 0; blk_idx < SOC_MAX_NUM_BLKS; blk_idx++) { 691 blk_type = SOC_BLOCK_TYPE(unit, blk_idx); 692 pm = SOC_BLOCK_NUMBER(unit, blk_idx); 693 if (blk_type == SOC_BLK_CDPORT) { 694 static_ports = _soc_th3_ports_per_pm_get(unit, pm); 695 if (SHR_BITGET(si->flexible_pm_bitmap, blk_idx)) { 696 /* port_flex_max_ports_corex=y */ 697 max_ports = soc_property_suffix_num_get_only_suffix(unit, 698 pm, spn_PORT_FLEX_MAX_PORTS, "core", -1); 699 /* port_flex_max_ports{x}=y */ 700 /* port_flex_max_ports=y */ 701 if (max_ports == -1) { 702 max_ports = soc_property_phys_port_get(unit, 703 (pm * _TH3_PORTS_PER_PBLK + 1), 704 spn_PORT_FLEX_MAX_PORTS, 8); 705 } 706 /* validation check */ 707 if ((max_ports < 0) || (max_ports > 8) || (max_ports < static_ports)) { 708 LOG_CLI((BSL_META_U(unit, 709 "Core %d: Bad port_flex_max_ports %d; static ports %d"), 710 pm, max_ports, static_ports)); 711 return SOC_E_CONFIG; 712 } 713 si->pm_max_ports[blk_idx] = max_ports; 714 } else { 715 si->pm_max_ports[blk_idx] = static_ports; 716 } 717 718 } 719 } 720 721 return SOC_E_NONE; 722 } 723 /* 724 * Function: 725 * _soc_tomahwk3_port_ratio_resolve 726 * Purpose: 727 * Derive the modes each of the 4-lane macs (2 macs in TH3) is 728 * operating in. In previous devices, there was only 1 4-lane 729 * mac, so *mode only carried that information. However, there 730 * are 2 4-lane macs in each TH3 PM, so the mode needs to be 731 * derived for each of them. There's an additional bit that 732 * gets set when the PM is in 400G mode so the port will combine 733 * the two macs into one port. 734 * 735 * In single port mode, each mac is only supporting 1 port: 736 * 200G (4 x 50G in PAM-4) 737 * 100G (4 x 25G in 25G-NRZ) 738 * 40G (4 x 10G in 10G-NRZ) 739 * 740 * In Dual port mode, each mac supports 2 ports 741 * 742 * In Tri port mode, each mac supports 3 ports, but the mac needs 743 * to know which port is taking up 2 lanes, hence 744 * SOC_TH3_PORT_RATIO_TRI_023_2_1_1 and SOC_TH3_PORT_RATIO_TRI_012_1_1_2 745 * where 023 indicates lane 0 is used for one port and lanes 2 and 3 are 746 * used for the others. 747 * 748 * In Quad port mode, each mac supports 4 ports. 749 * 750 * Examples are below. 751 * 752 * Parameters: 753 * unit - (IN) Unit number 754 * num_lanes - (IN) an array containing the number of lanes occupied 755 * speed_max - (IN) an array containing the speeds of the ports 756 * mode - (OUT) an encoding of the mac modes where the 4 least 757 * significant bits are mac0, the next 4 bits are mac1 758 * and the most significant bit is whether to combine 759 * both macs into a single 400G port 760 * 761 * Returns: 762 * Nothing 763 * 764 * #1 single: 400 - x - x - x SOC_TH3_PORT_RATIO_SINGLE 765 * x - x - x - x 766 * 767 * #2 single: 200 - x - x - x SOC_TH3_PORT_RATIO_SINGLE 768 * 200 - x - x - x 769 * #3 single: 100 - x - x - x SOC_TH3_PORT_RATIO_SINGLE 770 * #4 single: 40 - x - x - x SOC_TH3_PORT_RATIO_SINGLE 771 * #5 dual: 100 - x - 100 - x SOC_TH3_PORT_RATIO_DUAL_1_1 772 * #6 dual: 50 - x - 50 - x SOC_TH3_PORT_RATIO_DUAL_1_1 773 * #7 dual: 100 - x - 50 - x SOC_TH3_PORT_RATIO_DUAL_2_1 774 * #8 dual: 50 - x - 100 - x SOC_TH3_PORT_RATIO_DUAL_1_2 775 * #9 tri: 100 - x - 50/x - 50/x SOC_TH3_PORT_RATIO_TRI_023_2_1_1 776 * #10 tri: 50 - x - 25/x - 25/x SOC_TH3_PORT_RATIO_TRI_023_2_1_1 777 * #11 tri: 50/x - 50/x - 100 - x SOC_TH3_PORT_RATIO_TRI_012_1_1_2 778 * #12 tri: 25/x - 25/x - 50 - x SOC_TH3_PORT_RATIO_TRI_012_1_1_2 779 * #13 quad: 25/x - 25/x - 25/x - 25/x SOC_TH3_PORT_RATIO_QUAD 780 * #14 quad: 50/x - 50/x - 50/x - 50/x SOC_TH3_PORT_RATIO_QUAD 781 * #15 quad: 10/x - 10/x - 10/x - 10/x SOC_TH3_PORT_RATIO_QUAD 782 */ 783 #define _TH3_MACS_PER_PM 2 784 #define _TH3_LANES_PER_MAC 4 785 786 STATIC void 787 _soc_tomahawk3_port_ratio_resolve(int unit, 788 const int * num_lanes, 789 const int * speed_max, 790 int * mode) 791 { 792 int i; 793 794 *mode = 0; 795 /* Encode Mac0 in the 4 least significant bits, 0-3, and encode Mac1 in bits 4-7 */ 796 if (num_lanes[0] == 8) { 797 /* 8 lanes means 400G port, so encode as such */ 798 *mode |= (SOC_TH3_PORT_RATIO_SINGLE | 799 (SOC_TH3_PORT_RATIO_SINGLE << 4)); 800 /* also encode that the 400G field should be set */ 801 *mode |= 1 << 8; 802 } else { 803 /* Iterate through both macs in the pm (2) */ 804 for (i = 0; i < _TH3_MACS_PER_PM; i++) { 805 /* If the port in the mac uses 4 lanes, it's a single port */ 806 if (num_lanes[i * _TH3_LANES_PER_MAC] == 4) { 807 *mode |= SOC_TH3_PORT_RATIO_SINGLE << (i * 4); 808 } else if (num_lanes[i * _TH3_LANES_PER_MAC] == 2 && 809 num_lanes[(i * _TH3_LANES_PER_MAC) + 2] == 2) { 810 /* First Port uses 2 lanes and Second Port uses 2 lanes, 811 * so Dual mode */ 812 if (speed_max[i * _TH3_LANES_PER_MAC] == 813 speed_max[(i * _TH3_LANES_PER_MAC) + 2]) { 814 *mode |= SOC_TH3_PORT_RATIO_DUAL_1_1 << (i * 4); 815 } else if (speed_max[i * _TH3_LANES_PER_MAC] > 816 speed_max[(i * _TH3_LANES_PER_MAC) + 2]) { 817 *mode |= SOC_TH3_PORT_RATIO_DUAL_2_1 << (i * 4); 818 } else { 819 *mode |= SOC_TH3_PORT_RATIO_DUAL_1_2 << (i * 4); 820 } 821 } else if (num_lanes[i * _TH3_LANES_PER_MAC] == 2) { 822 /* First Port uses 2 lanes */ 823 if (num_lanes[(i * _TH3_LANES_PER_MAC) + 2] == -1) { 824 /* Second port is not specified, so leave in Dual mode */ 825 *mode |= SOC_TH3_PORT_RATIO_DUAL_1_1 << (i * 4); 826 } else { 827 /* Second port is 1 lane (2 lanes would have been the 828 * Dual mode case in the first else if), so tri mode 829 * with the first port occupying 2 lanes */ 830 *mode |= SOC_TH3_PORT_RATIO_TRI_023_2_1_1 << (i * 4); 831 } 832 } else if (num_lanes[(i * _TH3_LANES_PER_MAC) + 2] == 2) { 833 /* Second Port uses 2 lanes */ 834 if (num_lanes[i * _TH3_LANES_PER_MAC] == -1) { 835 /* If the first port is undefined, leave in dual mode */ 836 *mode |= SOC_TH3_PORT_RATIO_DUAL_1_1 << (i * 4); 837 } else { 838 /* First port is 1 lane, indicating Tri mode */ 839 *mode |= SOC_TH3_PORT_RATIO_TRI_012_1_1_2 << (i * 4); 840 } 841 } else { 842 /* 4 ports in this mac */ 843 *mode |= SOC_TH3_PORT_RATIO_QUAD << (i * 4); 844 } 845 } 846 } 847 } 848 849 /* 850 * Function: 851 * soc_tomahwk3_port_ratio_get 852 * Purpose: 853 * Derive the modes of the cdport port macro passed in. This function 854 * calls _soc_tomahawk3_port_ratio_get after fetching the designated 855 * port macro's lane assignment and port speeds. 856 * Parameters: 857 * unit - (IN) Unit number 858 * initTime - (IN) Whether the device is being initialized 859 * cdport - (IN) Which port macro we need the mode of (0 - 31) 860 * mode - (OUT) an encoding of the mac modes where the 4 least 861 * significant bits are mac0, the next 4 bits are mac1 862 * and the most significant bit is whether to combine 863 * both macs into a single 400G port 864 * 865 * Returns: 866 * Nothing 867 */ 868 void 869 soc_tomahawk3_port_ratio_get(int unit, int initTime, int cdport, int *mode) 870 { 871 soc_info_t *si; 872 int port, phy_port_base, lane; 873 int num_lanes[_TH3_PORTS_PER_PBLK]; 874 int speed_max[_TH3_PORTS_PER_PBLK]; 875 876 si = &SOC_INFO(unit); 877 phy_port_base = 1 + cdport * _TH3_PORTS_PER_PBLK; 878 for (lane = 0; lane < _TH3_PORTS_PER_PBLK; lane += 2) { 879 port = si->port_p2l_mapping[phy_port_base + lane]; 880 if (port == -1 || SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) { 881 num_lanes[lane] = -1; 882 speed_max[lane] = -1; 883 } else { 884 num_lanes[lane] = si->port_num_lanes[port]; 885 /* At init time port_speed_max_max contains port init speed_max and 886 * at run time during flex port opeartion, init_speed_max 887 * contains current port speed_max 888 */ 889 speed_max[lane] = initTime ? si->port_speed_max[port] : 890 si->port_init_speed[port]; 891 } 892 } 893 _soc_tomahawk3_port_ratio_resolve(unit, num_lanes, speed_max, mode); 894 } 895 896 /* 897 * Function: 898 * soc_tomahwk3_port_ratio_get_schedule_state 899 * Purpose: 900 * Derive the modes of the cdport port macro passed in, but use 901 * the num_lanes and speed_max from the passed port_map. This function 902 * calls _soc_tomahawk3_port_ratio_get after fetching the designated 903 * port macro's lane assignment and port speeds. 904 * Parameters: 905 * unit - (IN) Unit number 906 * port_schedule_state - (IN) Pointer containing the num_lanes 907 * and speed_max we're to use for the PM, 908 * rather than using SOC_INFO 909 * cdport - (IN) Which port macro we need the mode of (0 - 31) 910 * mode - (OUT) an encoding of the mac modes where the 4 least 911 * significant bits are mac0, the next 4 bits are mac1 912 * and the most significant bit is whether to combine 913 * both macs into a single 400G port 914 * prev_or_new - (IN) Function looks in in_port_map or out_port_map 915 * 916 * Returns: 917 * Nothing 918 */ 919 void 920 soc_tomahawk3_port_ratio_get_schedule_state(int unit, 921 soc_port_schedule_state_t *port_schedule_state, 922 int cdport, int *mode, 923 int prev_or_new) 924 { 925 int port, phy_port_base, lane; 926 int num_lanes[_TH3_PORTS_PER_PBLK]; 927 int speed_max[_TH3_PORTS_PER_PBLK]; 928 soc_port_map_type_t *port_map; 929 930 if (prev_or_new == 1) { 931 port_map = &port_schedule_state->in_port_map; 932 } else { 933 port_map = &port_schedule_state->out_port_map; 934 } 935 936 phy_port_base = 1 + cdport * _TH3_PORTS_PER_PBLK; 937 for (lane = 0; lane < _TH3_PORTS_PER_PBLK; lane += 2) { 938 port = port_map->port_p2l_mapping[phy_port_base + lane]; 939 if (port == -1 || (port_map->log_port_speed[port]==0) ){ 940 num_lanes[lane] = -1; 941 speed_max[lane] = -1; 942 } else { 943 num_lanes[lane] = port_map->port_num_lanes[port]; 944 speed_max[lane] = port_map->log_port_speed[port]; 945 } 946 } 947 _soc_tomahawk3_port_ratio_resolve(unit, num_lanes, speed_max, mode); 948 } 949 950 #if 0 951 STATIC void 952 _soc_tomahawk3_pipe_bandwidth_get(int unit, int pipe, 953 int *max_pipe_core_bandwidth, 954 int *pipe_linerate_bandwidth, 955 int *pipe_oversub_bandwidth) 956 { 957 soc_info_t *si; 958 int port; 959 int bandwidth; 960 961 si = &SOC_INFO(unit); 962 963 *max_pipe_core_bandwidth = si->bandwidth / 4; 964 965 *pipe_linerate_bandwidth = 0; 966 *pipe_oversub_bandwidth = 0; 967 PBMP_PORT_ITER(unit, port) { 968 if (si->port_pipe[port] != pipe) { 969 continue; 970 } 971 bandwidth = si->port_speed_max[port] >= 2500 ? 972 si->port_speed_max[port] : 2500; 973 if (SOC_PBMP_MEMBER(si->oversub_pbm, port)) { 974 *pipe_oversub_bandwidth += bandwidth; 975 } else { 976 *pipe_linerate_bandwidth += bandwidth; 977 } 978 } 979 /* 10G cpu/management, 5G loopback, 10G purge/refresh */ 980 *pipe_linerate_bandwidth += 25; 981 } 982 #endif 983 984 int 985 _soc_th3_port_speed_cap[SOC_MAX_NUM_DEVICES][_TH3_DEV_PORTS_PER_DEV]; 986 987 STATIC int 988 _soc_th3_post_mmu_init_update(int unit) 989 { 990 int port; 991 soc_info_t *si = &SOC_INFO(unit); 992 993 PBMP_ALL_ITER(unit, port) { 994 /* Set init speed to max speed by default */ 995 si->port_init_speed[port] = si->port_speed_max[port]; 996 if (_soc_th3_port_speed_cap[unit][port]) { 997 /* If cap speed is available then adjust max speed for further use */ 998 si->port_speed_max[port] = _soc_th3_port_speed_cap[unit][port]; 999 } 1000 } 1001 return SOC_E_NONE; 1002 } 1003 1004 /* 1005 * FUNCTION : soc_th3_bypass_unused_pm 1006 * ARGS: 1007 * unit - IN, unit number 1008 * Description : 1009 * Bypass unused port blocks, by programming TOP_TSC_ENABLEr 1010 * appropriately. 1011 */ 1012 soc_error_t 1013 soc_th3_bypass_unused_pm(int unit) 1014 { 1015 int port, phy_port, pm, block, bn; 1016 uint32 rval = 0, orval, xrval, pipe_map; 1017 uint16 dev_id; 1018 uint8 rev_id; 1019 int is_master_pm; 1020 soc_info_t *si = &SOC_INFO(unit); 1021 uint8 used_pm_map[_TH3_PBLKS_PER_DEV + 1]; /* #CDPORT + #XLPORT */ 1022 soc_reg_t reg = TOP_TSC_ENABLEr; 1023 soc_field_t reg_field[_TH3_PBLKS_PER_DEV] = { 1024 TSC_0_ENABLEf, TSC_1_ENABLEf, TSC_2_ENABLEf, TSC_3_ENABLEf, 1025 TSC_4_ENABLEf, TSC_5_ENABLEf, TSC_6_ENABLEf, TSC_7_ENABLEf, 1026 TSC_8_ENABLEf, TSC_9_ENABLEf, TSC_10_ENABLEf, TSC_11_ENABLEf, 1027 TSC_12_ENABLEf, TSC_13_ENABLEf, TSC_14_ENABLEf, TSC_15_ENABLEf, 1028 TSC_16_ENABLEf, TSC_17_ENABLEf, TSC_18_ENABLEf, TSC_19_ENABLEf, 1029 TSC_20_ENABLEf, TSC_21_ENABLEf, TSC_22_ENABLEf, TSC_23_ENABLEf, 1030 TSC_24_ENABLEf, TSC_25_ENABLEf, TSC_26_ENABLEf, TSC_27_ENABLEf, 1031 TSC_28_ENABLEf, TSC_29_ENABLEf, TSC_30_ENABLEf, TSC_31_ENABLEf 1032 }; 1033 1034 sal_memset(used_pm_map, 0, sizeof(used_pm_map)); 1035 for (phy_port = 1; phy_port <= _TH3_PORTS_PER_DEV; phy_port++) { 1036 port = si->port_p2l_mapping[phy_port]; 1037 if (port > 0) { 1038 pm = si->port_serdes[port]; 1039 if ((-1 != pm) && (0 == used_pm_map[pm])) { 1040 used_pm_map[pm] = 1; 1041 } 1042 } 1043 } 1044 1045 SOC_IF_ERROR_RETURN( 1046 soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 1047 orval = rval; 1048 1049 soc_tomahawk3_pipe_map_get(unit, &pipe_map); 1050 1051 soc_cm_get_id(unit, &dev_id, &rev_id); 1052 1053 /* Upper loop bound omits XLPORT block intentionally */ 1054 for (pm = 0; pm < _TH3_PBLKS_PER_DEV; pm++) { 1055 1056 is_master_pm = 0; 1057 1058 /* In TH3 A0, the "inner" port macros in a pipe are the master port 1059 * macros -- they drive the "outer" port macros and act as 1060 * the refclk master. Do not shut them off 1061 */ 1062 if (rev_id == BCM56980_A0_REV_ID) { 1063 if ((pm == 1 || pm == 2 || pm == 5 || pm == 6 || 1064 pm == 9 || pm == 10 || pm == 13 || pm == 14 || 1065 pm == 17 || pm == 18 || pm == 21 || pm == 22 || 1066 pm == 25 || pm == 26 || pm == 29 || pm == 30)) { 1067 is_master_pm = 1; 1068 } 1069 } else { 1070 if ((pm == 3 || pm == 4 || pm == 11 || pm == 12 || 1071 pm == 19 || pm == 20 || pm == 27 || pm == 28)) { 1072 is_master_pm = 1; 1073 } 1074 } 1075 1076 if (is_master_pm) { 1077 /* If the pipe is active, skip turning off the master port macros */ 1078 if (pipe_map & (1 << (pm / _TH3_PBLKS_PER_PIPE))) { 1079 continue; 1080 } 1081 } 1082 1083 /* If PM is not used, bypass it */ 1084 if (0 == used_pm_map[pm]) { 1085 soc_reg_field_set(unit, reg, &rval, reg_field[pm], 0); 1086 phy_port = 1 + (pm * _TH3_PORTS_PER_PBLK); 1087 block = SOC_PORT_BLOCK(unit, phy_port); 1088 /* Invalidate port block in soc info */ 1089 if (SOC_BLK_CDPORT == SOC_BLOCK_INFO(unit, block).type) { 1090 si->block_valid[block] = 0; 1091 } 1092 } 1093 } 1094 if (rval != orval) { 1095 /*Calculate different bits number between old and new*/ 1096 xrval = rval ^ orval; 1097 for (bn = 0; xrval != 0; bn++) { 1098 xrval &= (xrval - 1); 1099 } 1100 1101 /*Do two steps configuration change for the case of different bits number beyond 10*/ 1102 if (bn > 10) { 1103 /*Change half of those different bits to new at first*/ 1104 bn /= 2; 1105 xrval = rval ^ orval; 1106 do { 1107 xrval &= (xrval-1); 1108 } while (bn-- > 0); 1109 xrval ^= rval; 1110 SOC_IF_ERROR_RETURN( 1111 soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1112 sal_usleep(100000); 1113 } 1114 SOC_IF_ERROR_RETURN( 1115 soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 1116 sal_usleep(100000); 1117 } 1118 1119 return SOC_E_NONE; 1120 } 1121 1122 #if 0 1123 static int 1124 _soc_tomahawk3_phy_dev_port_check(int unit, int phy_port, int dev_port) 1125 { 1126 int num_phy_port = 136; 1127 1128 if( phy_port < 0 || phy_port >= num_phy_port) { 1129 return FALSE; 1130 } else if ( phy_port >= 1 && phy_port <= 32) { 1131 return ( dev_port >= 1 && dev_port <=32 ); 1132 } else if ( phy_port >= 33 && phy_port <= 64) { 1133 return ( dev_port >= 34 && dev_port <= 66 ); 1134 } else if ( phy_port >= 65 && phy_port <= 96) { 1135 return ( dev_port >= 68 && dev_port <= 100 ); 1136 } else if ( phy_port >= 97 && phy_port <= 128) { 1137 return ( dev_port >= 102 && dev_port <= 133 ); 1138 } else if ( phy_port == 129) { 1139 return ( dev_port >= 34 && dev_port <= 66 ); 1140 } else if ( phy_port == 131) { 1141 return ( dev_port >= 68 && dev_port <= 100 ); 1142 } else { 1143 /*skip LBPORT(132,133,134,135) , CPU port(0) and hole (130)*/ 1144 return TRUE; 1145 } 1146 1147 } 1148 #endif 1149 1150 /* 1151 *Function: soc_tomahawk3_dpr_frequency_range_check 1152 *Purpose: Check if dpr frequency is in valid range based on the core clock 1153 * frequency. Packet Processor can have a maximum of 1000 (1G) or 1154 * the core clock frequency, whichever is less 1155 *Params: 1156 * unit: Device unit number 1157 * dpr_freq: dpr frequency value 1158 */ 1159 int 1160 soc_tomahawk3_dpr_frequency_range_check(int unit, int dpr_freq) 1161 { 1162 int dpr_freq_max, dpr_freq_min; 1163 soc_info_t *si = &SOC_INFO(unit); 1164 1165 dpr_freq_max = si->frequency; 1166 1167 /* set maximum to 1000 if si->frequency is greater than 1000 */ 1168 if (dpr_freq_max > 1000) { 1169 dpr_freq_max = 1000; 1170 } 1171 1172 dpr_freq_min = si->frequency / 2; 1173 if ((dpr_freq < dpr_freq_min) || (dpr_freq > dpr_freq_max) || 1174 dpr_freq == -1) { 1175 LOG_CLI((BSL_META_U(unit, 1176 "*** Input DPR clock frequency %dMHz is not supported!\n" 1177 "Valid range is in between %dMHz and %dMHz\n"), dpr_freq, 1178 dpr_freq_max, dpr_freq_min)); 1179 return SOC_E_PARAM; 1180 } 1181 return SOC_E_NONE; 1182 } 1183 1184 STATIC int 1185 _soc_tomahawk3_port_mapping_check(int unit) 1186 { 1187 soc_info_t *si; 1188 int port, phy_port, lanes, i; 1189 1190 si = &SOC_INFO(unit); 1191 1192 for (phy_port = 1; phy_port < _TH3_PORTS_PER_DEV;) { 1193 port = si->port_p2l_mapping[phy_port]; 1194 if (port < 0) { 1195 phy_port ++; 1196 continue; 1197 } 1198 if (port >= _TH3_DEV_PORTS_PER_DEV) { 1199 LOG_CLI((BSL_META_U(unit, "wrong logical port %d, phy %d\n"), 1200 port, phy_port)); 1201 return SOC_E_CONFIG; 1202 } 1203 lanes = si->port_num_lanes[port]; 1204 if ((lanes < 0) || (lanes > 8)) { 1205 LOG_CLI((BSL_META_U(unit, "wrong lane number, port %d, lanes %d\n"), 1206 port, lanes)); 1207 return SOC_E_CONFIG; 1208 } 1209 for (i = 1; i < lanes; i ++) { 1210 if (si->port_p2l_mapping[phy_port + i] != -1) { 1211 LOG_CLI((BSL_META_U(unit, "port overlay, port %d(%d-%d) and " 1212 "port %d(%d..)\n"), 1213 port, phy_port, phy_port + lanes - 1, 1214 si->port_p2l_mapping[phy_port + i], phy_port + i)); 1215 return SOC_E_CONFIG; 1216 } 1217 } 1218 phy_port += lanes; 1219 } 1220 1221 return SOC_E_NONE; 1222 } 1223 /* 1224 * Function: soc_tomahawk3_find_disabled_pipes 1225 * 1226 * Purpose: In the event of half chip or emulation, sometimes TH3 doesn't 1227 * have all 8 pipes. This function is meant to mark the ones that do not 1228 * exist so that calls to soc_tomahawk3_pipe_map_get will be accurate 1229 * 1230 * Parameters: 1231 * unit - Switch unit 1232 * disabled_pipes - Array of pipes indicating enabled or disabled 1233 * 1234 * Returns: 1235 * SOC_E_XXX 1236 */ 1237 STATIC int 1238 soc_tomahawk3_find_disabled_pipes(int unit, int *disabled_pipes) 1239 { 1240 uint32 reg_val; 1241 uint16 dev_id; 1242 uint8 rev_id; 1243 1244 soc_cm_get_id(unit, &dev_id, &rev_id); 1245 /* DMU_PCU_OTP_CONFIG_4.otp_config[7] tells us whether only 1246 * pipes 0, 1, 4, 5 are active */ 1247 SOC_IF_ERROR_RETURN(READ_DMU_PCU_OTP_CONFIG_4r(unit, ®_val)); 1248 if (reg_val & 0x80) { 1249 disabled_pipes[2] = 1; 1250 disabled_pipes[3] = 1; 1251 disabled_pipes[6] = 1; 1252 disabled_pipes[7] = 1; 1253 } else if (SAL_BOOT_QUICKTURN && SOC_INFO(unit).num_pipe == 4) { 1254 disabled_pipes[2] = 1; 1255 disabled_pipes[3] = 1; 1256 disabled_pipes[4] = 1; 1257 disabled_pipes[5] = 1; 1258 } else if (dev_id == BCM56983_DEVICE_ID) { 1259 disabled_pipes[2] = 1; 1260 disabled_pipes[3] = 1; 1261 disabled_pipes[4] = 1; 1262 disabled_pipes[5] = 1; 1263 } 1264 1265 return SOC_E_NONE; 1266 } 1267 /* 1268 * Tomahawk3 port mapping 1269 * 1270 * physical idb/ device mmu 1271 * port idb port port port 1272 * CMIC 0 0/19 0 19 1273 * CDPORT0-3 1-32 0/0-17 1-18 0-17 1274 * CDPORT4-7 33-64 1/0-17 20-37 39-49 1275 * CDPORT8-11 65-96 2/0-17 40-57 64-81 1276 * CDPORT12-15 97-128 3/0-17 60-77 96-113 1277 * CDPORT16-19 129-160 4/0-17 80-97 128-145 1278 * CDPORT20-23 161-192 5/0-17 100-117 160-177 1279 * CDPORT24-27 193-224 6/0-17 120-137 192-209 1280 * CDPORT28-31 225-256 7/0-17 140-157 224-241 1281 * XLPORT0/1 257 1/19 38 51 1282 * XLPORT0/5 258 5/19 118 179 1283 * LBPORT0 259 0/18 19 18 1284 * LBPORT1 260 1/18 39 50 1285 * LBPORT2 261 2/18 59 82 1286 * LBPORT3 262 3/18 79 114 1287 * LBPORT4 263 4/18 99 146 1288 * LBPORT5 264 5/18 119 178 1289 * LBPORT6 265 6/18 139 210 1290 * LBPORT7 266 7/18 159 242 1291 * Device port number is flexible within the above range 1292 * Although MMU port number is flexible within the above range, it is 1293 * configured as a fixed mapped to physical port number 1294 */ 1295 int 1296 soc_tomahawk3_port_config_init(int unit, uint16 dev_id) 1297 { 1298 #define BCM_TH3_MAX_LOGICAL_PORT_NUM (160) 1299 soc_info_t *si; 1300 char *config_str, *sub_str, *sub_str_end; 1301 static const char str_2p5[] = "2.5"; 1302 char str_buf[8]; 1303 int rv, oversub_mode, frequency; 1304 int port, phy_port, mmu_port, idb_port; 1305 int pipe, itm, index, bandwidth_cap, is_any_cap = FALSE; 1306 int port_bandwidth, freq_list_len, blk_idx; 1307 int disabled_pipe[_TH3_PIPES_PER_DEV]; 1308 int dpr_freq; 1309 uint16 dev_id_temp; 1310 uint8 rev_id; 1311 char option1, option2; 1312 uint32 pipe_map, itm_map, ipipe_map = 0; 1313 static const int freq_list[] = { 1325, 1250, 1175, 1100, 1000, 925, 1314 850, 775, 675 }; 1315 static const struct { 1316 int port; 1317 int phy_port; 1318 int pipe; 1319 int idb_port; 1320 int mmu_port; 1321 } fixed_ports[] = { 1322 { 0, 0, 0, 19, 19 }, /* cpu port */ 1323 { 19, 259, 0, 18, 18 }, /* loopback port 0 */ 1324 { 39, 260, 1, 18, 50 }, /* loopback port 1 */ 1325 { 59, 261, 2, 18, 82 }, /* loopback port 2 */ 1326 { 79, 262, 3, 18, 114 }, /* loopback port 3 */ 1327 { 99, 263, 4, 18, 146 }, /* loopback port 4 */ 1328 { 119, 264, 5, 18, 178 }, /* loopback port 5 */ 1329 { 139, 265, 6, 18, 210 }, /* loopback port 6 */ 1330 { 159, 266, 7, 18, 242 }, /* loopback port 7 */ 1331 }; 1332 portmod_speed_config_t speed_config_temp; 1333 1334 1335 si = &SOC_INFO(unit); 1336 1337 1338 /* Keep track of the pipes that are disabled */ 1339 sal_memset(disabled_pipe, 0, _TH3_PIPES_PER_DEV * sizeof(int)); 1340 SOC_IF_ERROR_RETURN(soc_tomahawk3_find_disabled_pipes(unit, disabled_pipe)); 1341 1342 /* Can't read TOP register at this point */ 1343 soc_tomahawk3_max_frequency_get(unit, dev_id, -1, -1, &si->frequency); 1344 frequency = soc_property_get(unit, spn_CORE_CLOCK_FREQUENCY, -1); 1345 1346 1347 /* Core CLK frequency */ 1348 if (frequency != -1 && frequency != si->frequency) { 1349 freq_list_len = COUNTOF(freq_list); 1350 for (index = 0; index < freq_list_len; index++) { 1351 if (freq_list[index] <= si->frequency && 1352 frequency == freq_list[index]) { 1353 break; 1354 } 1355 } 1356 1357 if (index < freq_list_len) { 1358 si->frequency = frequency; 1359 } else { 1360 LOG_CLI((BSL_META_U(unit, 1361 "*** Input core clock frequency %dMHz is not " 1362 "supported!\n"), frequency)); 1363 } 1364 } 1365 1366 1367 /*DPR frequency check*/ 1368 /*TH3 supports the DPR:clock frequency ratio between 1:2 and 1:1*/ 1369 dpr_freq = soc_property_get(unit, spn_DPR_CLOCK_FREQUENCY, -1); 1370 #if defined(PLISIM) 1371 if (SAL_BOOT_PLISIM) { 1372 dpr_freq = 0; 1373 } 1374 #endif 1375 if (dpr_freq) { 1376 /* PCID server is property agnostic */ 1377 SOC_IF_ERROR_RETURN 1378 (soc_tomahawk3_dpr_frequency_range_check(unit, dpr_freq)); 1379 } 1380 1381 /* TH3 is only oversubscribed mode */ 1382 oversub_mode = 1; 1383 si->oversub_mode = oversub_mode; 1384 1385 for (phy_port = 0; phy_port < 267; phy_port++) { 1386 si->port_p2l_mapping[phy_port] = -1; 1387 si->port_p2m_mapping[phy_port] = -1; 1388 } 1389 for (port = 0; port < BCM_TH3_MAX_LOGICAL_PORT_NUM; port++) { 1390 si->port_l2p_mapping[port] = -1; 1391 si->port_l2i_mapping[port] = -1; 1392 si->port_speed_max[port] = -1; 1393 si->port_group[port] = -1; 1394 si->port_serdes[port] = -1; 1395 si->port_pipe[port] = -1; 1396 si->port_num_lanes[port] = -1; 1397 _soc_th3_port_speed_cap[unit][port] = 0; 1398 } 1399 for (mmu_port = 0; mmu_port < _TH3_MMU_PORTS_PER_DEV; mmu_port++) { 1400 si->port_m2p_mapping[mmu_port] = -1; 1401 } 1402 SOC_PBMP_CLEAR(si->eq_pbm); 1403 SOC_PBMP_CLEAR(si->management_pbm); 1404 for (pipe = 0; pipe < si->num_pipe; pipe++) { 1405 SOC_PBMP_CLEAR(si->pipe_pbm[pipe]); 1406 } 1407 SOC_PBMP_CLEAR(si->oversub_pbm); 1408 SOC_PBMP_CLEAR(si->all.disabled_bitmap); 1409 1410 /* Populate the fixed mapped ports */ 1411 for (index = 0; index < COUNTOF(fixed_ports); index++) { 1412 port = fixed_ports[index].port; 1413 phy_port = fixed_ports[index].phy_port; 1414 pipe = fixed_ports[index].pipe;; 1415 si->port_l2p_mapping[port] = phy_port; 1416 si->port_l2i_mapping[port] = fixed_ports[index].idb_port; 1417 si->port_p2l_mapping[phy_port] = port; 1418 si->port_p2m_mapping[phy_port] = fixed_ports[index].mmu_port; 1419 si->port_pipe[port] = pipe; 1420 } 1421 1422 1423 rv = SOC_E_NONE; 1424 for (port = 1; port < BCM_TH3_MAX_LOGICAL_PORT_NUM; port++) { 1425 if (si->port_l2p_mapping[port] != -1) { /* fixed mapped port */ 1426 continue; 1427 } 1428 #if 0 1429 if (port == 134) { /* Reserved port */ 1430 continue; 1431 } 1432 #endif 1433 config_str = soc_property_port_get_str(unit, port, spn_PORTMAP); 1434 if (config_str == NULL) { 1435 continue; 1436 } 1437 1438 /* 1439 * portmap_<port>=<physical port number>:<bandwidth in Gb>[:<bandwidth cap in Gb/i(inactive)/1/2/4(num lanes)>][:<i>] 1440 * eg: portmap_1=1:100 1441 * or portmap_1=1:40 1442 * or portmap_1=1:40:i 1443 * or portmap_1=1:40:2 1444 * or portmap_1=1:40:2:i 1445 * or portmap_1=1:10:100 1446 */ 1447 sub_str = config_str; 1448 1449 /* Parse physical port number */ 1450 phy_port = sal_ctoi(sub_str, &sub_str_end); 1451 if (sub_str == sub_str_end) { 1452 LOG_CLI((BSL_META_U(unit, 1453 "Port %d: Missing physical port information " 1454 "\"%s\"\n"), 1455 port, config_str)); 1456 rv = SOC_E_FAIL; 1457 continue; 1458 } 1459 if (phy_port < 0 || phy_port >= 267) { 1460 LOG_CLI((BSL_META_U(unit, 1461 "Port %d: Invalid physical port number %d\n"), 1462 port, phy_port)); 1463 rv = SOC_E_FAIL; 1464 continue; 1465 } 1466 /* coverity[check_after_sink : FALSE] */ 1467 if (si->port_p2l_mapping[phy_port] != -1) { 1468 LOG_CLI((BSL_META_U(unit, 1469 "Port %d: Physical port %d is used by port " 1470 "%d\n"), 1471 port, phy_port, si->port_p2l_mapping[phy_port])); 1472 rv = SOC_E_FAIL; 1473 continue; 1474 } 1475 /* In order to reuse the mapping between logical and physical port 1476 * number for the mapping relationship between physical and IDB port 1477 * number, we have to make maping between IDB and logical port as fixed. 1478 * For the management ports: 1479 * phy_port IDB port => Logical port 1480 * 257 32 66 1481 * 259 32 100 1482 */ 1483 if ((phy_port == 257 && port != 38) || 1484 (phy_port == 258 && port != 118)) { 1485 LOG_CLI((BSL_META_U(unit, 1486 "Management Port %d: Invalid port number %d\n"), 1487 phy_port, port)); 1488 rv = SOC_E_FAIL; 1489 continue; 1490 } 1491 1492 pipe = port/_TH3_DEV_PORTS_PER_PIPE; 1493 if ((port != 38 && port != 118) && 1494 ((phy_port < (pipe * 32 + 1)) || 1495 (phy_port > (pipe + 1) * 32))) { 1496 LOG_CLI((BSL_META_U(unit, 1497 "Port %d, Physical port %d: " 1498 "Not in same pipeline range\n"), 1499 port, phy_port)); 1500 rv = SOC_E_FAIL; 1501 continue; 1502 } 1503 1504 1505 /* Skip ':' between physical port number and bandwidth */ 1506 sub_str = sub_str_end; 1507 if (*sub_str != '\0') { 1508 if (*sub_str != ':') { 1509 LOG_CLI((BSL_META_U(unit, 1510 "Port %d: Bad config string \"%s\"\n"), 1511 port, config_str)); 1512 rv = SOC_E_FAIL; 1513 continue; 1514 } 1515 sub_str++; 1516 } 1517 1518 /* Parse bandwidth */ 1519 for (index = 0; index < sizeof(str_2p5) - 1; index++) { 1520 if (sub_str[index] == '\0') { 1521 break; 1522 } 1523 str_buf[index] = sub_str[index]; 1524 } 1525 str_buf[index] = '\0'; 1526 if (!sal_strcmp(str_buf, str_2p5)) { 1527 port_bandwidth = 2500; 1528 sub_str_end = &sub_str[sizeof(str_2p5) - 1]; 1529 } else { 1530 port_bandwidth = sal_ctoi(sub_str, &sub_str_end) * 1000; 1531 if (sub_str == sub_str_end) { 1532 LOG_CLI((BSL_META_U(unit, 1533 "Port %d: Missing bandwidth information " 1534 "\"%s\"\n"), 1535 port, config_str)); 1536 rv = SOC_E_FAIL; 1537 continue; 1538 } 1539 switch (port_bandwidth) { 1540 case 1000: 1541 case 10000: 1542 case 25000: 1543 case 40000: 1544 case 50000: 1545 case 100000: 1546 case 200000: 1547 case 400000: 1548 break; 1549 default: 1550 LOG_CLI((BSL_META_U(unit, 1551 "Port %d: Invalid bandwidth %d Gb\n"), 1552 port, port_bandwidth / 1000)); 1553 rv = SOC_E_FAIL; 1554 continue; 1555 } 1556 } 1557 1558 /* Check if option presents */ 1559 option1 = 0; option2 = 0; 1560 sub_str = sub_str_end; 1561 if (*sub_str != '\0') { 1562 /* Skip ':' between bandwidth and cap or options */ 1563 if (*sub_str != ':') { 1564 LOG_CLI((BSL_META_U(unit, 1565 "Port %d: Bad config string \"%s\"\n"), 1566 port, config_str)); 1567 rv = SOC_E_FAIL; 1568 continue; 1569 } 1570 sub_str++; 1571 1572 if (*sub_str != '\0') { 1573 /* Parse bandwidth cap or options */ 1574 bandwidth_cap = sal_ctoi(sub_str, &sub_str_end) * 1000; 1575 switch (bandwidth_cap) { 1576 case 10000: 1577 case 25000: 1578 case 40000: 1579 case 50000: 1580 case 100000: 1581 case 200000: 1582 case 400000: 1583 sub_str = sub_str_end; 1584 _soc_th3_port_speed_cap[unit][port] = bandwidth_cap; 1585 /* Flex config detected, port speed cap specified */ 1586 is_any_cap = TRUE; 1587 break; 1588 default: 1589 if (!(*sub_str == 'i' || *sub_str == '1' || 1590 *sub_str == '2' || *sub_str == '4' || 1591 *sub_str == '8')) { 1592 LOG_CLI((BSL_META_U(unit, 1593 "Port %d: Bad config string " 1594 "\"%s\"\n"), 1595 port, config_str)); 1596 rv = SOC_E_FAIL; 1597 continue; 1598 } else { 1599 option1 = *sub_str; 1600 sub_str++; 1601 } 1602 } 1603 /* Check if more options present */ 1604 if (*sub_str != '\0') { 1605 /* Skip ':' between options */ 1606 if (*sub_str != ':') { 1607 LOG_CLI((BSL_META_U(unit, 1608 "Port %d: Bad config string " 1609 "\"%s\"\n"), 1610 port, config_str)); 1611 rv = SOC_E_FAIL; 1612 continue; 1613 } 1614 sub_str++; 1615 1616 if (*sub_str != 'i') { 1617 LOG_CLI((BSL_META_U(unit, 1618 "Port %d: Bad config string " 1619 "\"%s\"\n"), 1620 port, config_str)); 1621 rv = SOC_E_FAIL; 1622 continue; 1623 } 1624 option2 = *sub_str; 1625 sub_str++; 1626 } 1627 } 1628 } 1629 1630 /* Check trailing string */ 1631 if (*sub_str != '\0') { 1632 LOG_CLI((BSL_META_U(unit, 1633 "Port %d: Bad config string \"%s\"\n"), 1634 port, config_str)); 1635 rv = SOC_E_FAIL; 1636 continue; 1637 } 1638 1639 /* Update soc_info */ 1640 si->port_l2p_mapping[port] = phy_port; 1641 si->port_p2l_mapping[phy_port] = port; 1642 si->port_speed_max[port] = port_bandwidth; 1643 if (option1 == 'i') { 1644 SOC_PBMP_PORT_ADD(si->all.disabled_bitmap, port); 1645 } else { 1646 switch (option1) { 1647 case '1': si->port_num_lanes[port] = 1; break; 1648 case '2': si->port_num_lanes[port] = 2; break; 1649 case '4': si->port_num_lanes[port] = 4; break; 1650 case '8': si->port_num_lanes[port] = 8; break; 1651 default: break; 1652 } 1653 } 1654 if (option2 == 'i') { 1655 SOC_PBMP_PORT_ADD(si->all.disabled_bitmap, port); 1656 } 1657 } 1658 1659 /* Setup port_num_lanes */ 1660 for (port = 0; port < BCM_TH3_MAX_LOGICAL_PORT_NUM; port++) { 1661 if (si->port_speed_max[port] == 400000) { 1662 si->port_num_lanes[port] = 8; 1663 } else if (si->port_speed_max[port] == 200000) { 1664 si->port_num_lanes[port] = 4; 1665 } else if (si->port_speed_max[port] == 100000 && 1666 si->port_num_lanes[port] == -1) { 1667 /* if it's 100G and the user didn't specify the number of lanes, 1668 * choose 2 lanes (2 x 50G) */ 1669 si->port_num_lanes[port] = 2; 1670 } else if (si->port_speed_max[port] == 50000 && 1671 si->port_num_lanes[port] == -1) { 1672 /* if it's 50G and the user didn't specify the number of lanes, 1673 * choose 1 lane (1 x 50G) */ 1674 si->port_num_lanes[port] = 1; 1675 } else if (si->port_speed_max[port] == 40000 && 1676 si->port_num_lanes[port] == -1) { 1677 si->port_num_lanes[port] = 2; 1678 } else if (si->port_speed_max[port] > 0) { 1679 if (si->port_num_lanes[port] == -1) { 1680 /* But RXAUI and XAUI on mgmt ports use 2 and 4 lanes, which 1681 * can be provided via the portmap interface. 1682 */ 1683 si->port_num_lanes[port] = 1; 1684 } 1685 } 1686 1687 /* If the port is mapped, find out its fec, link training, lane config 1688 * from config file */ 1689 if (si->port_speed_max[port] > 0) { 1690 /* Fetch FEC, Link Training and Phy lane Config from Config File */ 1691 SOC_IF_ERROR_RETURN(soc_esw_portctrl_speed_config_fill(unit, port, 1692 si->port_speed_max[port], 1693 si->port_num_lanes[port], 1694 -1, 1695 -1, 1696 -1, 1697 &speed_config_temp)); 1698 si->port_fec_type[port] = speed_config_temp.fec; 1699 si->port_link_training[port] = speed_config_temp.link_training; 1700 si->port_phy_lane_config[port] = speed_config_temp.lane_config; 1701 } 1702 } 1703 1704 1705 /* check portmap */ 1706 SOC_IF_ERROR_RETURN(_soc_tomahawk3_port_mapping_check(unit)); 1707 1708 /* get flex port properties */ 1709 if (SOC_FAILURE(_soc_tomahawk3_port_flex_init(unit, is_any_cap))) { 1710 rv = SOC_E_FAIL; 1711 } 1712 1713 #if defined(BCM_WARM_BOOT_SUPPORT) 1714 if (si->flex_eligible) { 1715 if (SOC_WARM_BOOT(unit)) { 1716 SOC_IF_ERROR_RETURN( 1717 soc_th3_flexport_scache_recovery(unit)); 1718 } else { 1719 SOC_IF_ERROR_RETURN( 1720 soc_th3_flexport_scache_allocate(unit)); 1721 } 1722 } 1723 #endif 1724 1725 1726 /* Setup high speed port (HSP) pbm */ 1727 for (port = 0; port < BCM_TH3_MAX_LOGICAL_PORT_NUM; port++) { 1728 phy_port = si->port_l2p_mapping[port]; 1729 if (phy_port <= 0 || phy_port > 258) { 1730 continue; 1731 } 1732 1733 pipe = port/_TH3_DEV_PORTS_PER_PIPE; 1734 if (phy_port == 257) { 1735 si->port_l2i_mapping[port] = 19; 1736 si->port_p2m_mapping[phy_port] = 51; 1737 si->port_serdes[port] = 32; 1738 SOC_PBMP_PORT_ADD(si->management_pbm, port); 1739 } else if (phy_port == 258) { 1740 si->port_l2i_mapping[port] = 19; 1741 si->port_p2m_mapping[phy_port] = 179; 1742 si->port_serdes[port] = 32; 1743 SOC_PORT_BLOCK(unit, phy_port) = SOC_PORT_BLOCK(unit, 257); 1744 SOC_PORT_BINDEX(unit, phy_port) = 2; 1745 SOC_PBMP_PORT_ADD(si->management_pbm, port); 1746 } else { 1747 idb_port = (port % 20) - (pipe == 0 ? 1 : 0); 1748 mmu_port = pipe * 32 + idb_port; 1749 si->port_l2i_mapping[port] = idb_port; 1750 si->port_p2m_mapping[phy_port] = mmu_port; 1751 si->port_serdes[port] = (phy_port - 1) / 8; 1752 } 1753 1754 si->port_pipe[port] = pipe; 1755 SOC_PBMP_PORT_ADD(si->pipe_pbm[pipe], port); 1756 1757 if (si->port_speed_max[port] >= 40000) { 1758 SOC_PBMP_PORT_ADD(si->eq_pbm, port); 1759 } 1760 } 1761 1762 for (index = 1; index < COUNTOF(fixed_ports); index++) { 1763 pipe = fixed_ports[index].pipe; 1764 port = fixed_ports[index].port; 1765 phy_port = fixed_ports[index].phy_port; 1766 /* If this is a half chip or a SKU with disabled pipes, 1767 * remove the mappings */ 1768 if (disabled_pipe[pipe] == 1) { 1769 /* Remove loopback port if the entire pipe does not exist */ 1770 si->port_l2p_mapping[port] = -1; 1771 si->port_l2i_mapping[port] = -1; 1772 si->port_p2l_mapping[phy_port] = -1; 1773 si->port_p2m_mapping[phy_port] = -1; 1774 si->port_pipe[port] = -1; 1775 } else { 1776 SOC_PBMP_PORT_ADD(si->pipe_pbm[pipe], port); 1777 } 1778 } 1779 1780 /* Add CPU Port to PIP_PBM of PIPE 0 */ 1781 SOC_PBMP_PORT_ADD(si->pipe_pbm[0], CMIC_PORT(unit)); 1782 1783 /* Since we have the port speeds and lanes from the config file, 1784 * or WB, calculate the port macro VCOs for later PM init 1785 */ 1786 SOC_IF_ERROR_RETURN(soc_th3_portctrl_vco_soc_info_update(unit)); 1787 1788 /* Setup pipe/xpe mapping 1789 * XPE0 (SC_R/XPE_A): IP 0/3 EP 0/1 1790 * XPE1 (SC_S/XPE_A): IP 0/3 EP 2/3 1791 * XPE2 (SC_R/XPE_B): IP 1/2 EP 0/1 1792 * XPE3 (SC_S/XPE_B): IP 1/2 EP 2/3 1793 */ 1794 pipe_map = 0; 1795 for (pipe = 0; pipe < _TH3_PIPES_PER_DEV; pipe++) { 1796 if (SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) { 1797 continue; 1798 } 1799 pipe_map |= 1 << pipe; 1800 } 1801 itm_map = 0; 1802 for (itm = 0; itm < NUM_ITM(unit); itm++) { 1803 ipipe_map = (itm == 0 ? 0xc3 : 0x3c) & pipe_map; 1804 if (ipipe_map == 0) { 1805 continue; 1806 } 1807 itm_map |= 1 << itm; 1808 /* Number of ITMs is 2 in Tomahawk3 */ 1809 /* coverity[overrun-local : FALSE] */ 1810 si->itm_ipipe_map[itm] = ipipe_map; 1811 } 1812 for (pipe = 0; pipe < _TH3_PIPES_PER_DEV; pipe++) { 1813 /* Number of pipes is 8 in Tomahawk3 */ 1814 /* coverity[overrun-local : FALSE] */ 1815 if (SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) { 1816 continue; 1817 } 1818 /* coverity[overrun-local : FALSE] */ 1819 si->ipipe_itm_map[pipe] = ((pipe < 2 || pipe > 5 )? 0x1 : 0x2) ; 1820 } 1821 si->itm_map = itm_map; 1822 1823 /* Setup cdport refclk master block bitmap. 1824 * In Tomahawk3, the "inner" port macros in a pipe are the master 1825 * port macros and will drive the "outer" port macros in a pipe from the 1826 * system board and they will act as the refclk master to drive the other 1827 * instances. 1828 */ 1829 SHR_BITCLR_RANGE(si->pm_ref_master_bitmap, 0, SOC_MAX_NUM_BLKS); 1830 for (blk_idx = 0; blk_idx < SOC_MAX_NUM_BLKS; blk_idx++) { 1831 int blknum = SOC_BLOCK_NUMBER(unit, blk_idx); 1832 int blktype = SOC_BLOCK_TYPE(unit, blk_idx); 1833 if (blktype == SOC_BLK_CDPORT) { 1834 soc_cm_get_id(unit, &dev_id_temp, &rev_id); 1835 1836 /* Set Master PM bitmap for flexport purposes depending on whether 1837 * it's A0 or B0 chip */ 1838 if (rev_id == BCM56980_A0_REV_ID) { 1839 if ((blknum == 1 || blknum == 2 || blknum == 5 || blknum == 6 || 1840 blknum == 9 ||blknum == 10 || blknum == 13 || blknum == 14 || 1841 blknum == 17 || blknum == 18 || blknum == 21 || blknum == 22 || 1842 blknum == 25 || blknum == 26 || blknum == 29 || blknum == 30)) { 1843 SHR_BITSET(si->pm_ref_master_bitmap, blk_idx); 1844 } 1845 } else { 1846 if ((blknum == 3 || blknum == 4 || blknum == 11 || blknum == 12 || 1847 blknum == 19 || blknum == 20 || blknum == 27 || blknum == 28)) { 1848 SHR_BITSET(si->pm_ref_master_bitmap, blk_idx); 1849 } 1850 } 1851 } 1852 } 1853 1854 #undef BCM_TH3_MAX_LOGICAL_PORT_NUM 1855 return rv; 1856 } 1857 1858 STATIC int _soc_tomahawk3_init_ipep_memory(int unit); 1859 1860 static int 1861 _soc_th3_pp_pll_config(int unit, int freq) 1862 { 1863 uint32 rval; 1864 unsigned pp_idx; 1865 static const soc_pp_pll_param_t pp_pll[] = { 1866 /* Fref, Ndiv, Pdiv, Mdiv, pp_clk, VCO */ 1867 {110010, 80, 1, 4, 1000, 4}, 1868 {110010, 70, 1, 4, 875, 3.5}, 1869 {110010, 60, 1, 4, 750, 3}, 1870 {110010, 53, 1, 4, 662.5, 2.65}, 1871 {110010, 50, 1, 4, 625, 2.5}, 1872 {110010, 40, 1, 4, 500, 2.0} 1873 }; 1874 1875 1876 for (pp_idx = 0; pp_idx < sizeof(pp_pll)/sizeof(pp_pll[0]); ++pp_idx) { 1877 if (pp_pll[pp_idx].pp_clk == freq) { 1878 break; 1879 } 1880 } 1881 1882 SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval)); 1883 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_PP_PLL_RST_Lf, 0); 1884 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_PP_PLL_POST_RST_Lf, 0); 1885 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval)); 1886 1887 /* hold all post div channels */ 1888 SOC_IF_ERROR_RETURN(READ_TOP_PP_PLL_CTRL_1r(unit, &rval)); 1889 soc_reg_field_set(unit, TOP_PP_PLL_CTRL_1r, &rval, POST_HOLD_ALLf, 1); 1890 SOC_IF_ERROR_RETURN(WRITE_TOP_PP_PLL_CTRL_1r(unit, rval)); 1891 1892 /* Enable glitchless bypass enable */ 1893 SOC_IF_ERROR_RETURN(READ_TOP_PP_PLL_CTRL_4r(unit, &rval)); 1894 soc_reg_field_set(unit, TOP_PP_PLL_CTRL_4r, &rval, PLL_RESERVEDf, 2); 1895 SOC_IF_ERROR_RETURN(WRITE_TOP_PP_PLL_CTRL_4r(unit, rval)); 1896 1897 /* Set to normal operation instead of bypassing all post-div channels*/ 1898 SOC_IF_ERROR_RETURN(READ_TOP_PP_PLL_CTRL_1r(unit, &rval)); 1899 soc_reg_field_set(unit, TOP_PP_PLL_CTRL_1r, &rval, CH_BYP_ENf, 0); 1900 SOC_IF_ERROR_RETURN(WRITE_TOP_PP_PLL_CTRL_1r(unit, rval)); 1901 1902 /* Set ndiv_int and mdiv for target freq */ 1903 SOC_IF_ERROR_RETURN 1904 (soc_reg_field32_modify(unit, TOP_PP_PLL_CTRL_0r, 1905 REG_PORT_ANY, NDIV_INTf, 1906 pp_pll[pp_idx].ndiv_int)); 1907 SOC_IF_ERROR_RETURN 1908 (soc_reg_field32_modify(unit, TOP_PP_PLL_CTRL_3r, 1909 REG_PORT_ANY, CH_MDIVf, 1910 pp_pll[pp_idx].mdiv)); 1911 1912 /* Deassert PP_PLL_RST_L */ 1913 SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval)); 1914 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_PP_PLL_RST_Lf, 1); 1915 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval)); 1916 1917 /* Wait for 10us */ 1918 sal_usleep(10); 1919 1920 /* Deassert PP_PLL_POST_RST_L */ 1921 SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval)); 1922 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_PP_PLL_POST_RST_Lf, 1); 1923 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval)); 1924 1925 SOC_IF_ERROR_RETURN(READ_TOP_PP_PLL_CTRL_4r(unit, &rval)); 1926 soc_reg_field_set(unit, TOP_PP_PLL_CTRL_4r, &rval, PLL_RESERVEDf, 0); 1927 SOC_IF_ERROR_RETURN(WRITE_TOP_PP_PLL_CTRL_4r(unit, rval)); 1928 1929 /* Adjusting the clock phases on 2 post div channels. We set the 1930 channel#1 twice so it is shifted by 2 VCO cycles which is 1931 180 degrees */ 1932 1933 SOC_IF_ERROR_RETURN 1934 (soc_reg_field32_modify(unit, TOP_PP_PLL_CTRL_3r, 1935 REG_PORT_ANY, CH_MDELf, 0)); 1936 SOC_IF_ERROR_RETURN 1937 (soc_reg_field32_modify(unit, TOP_PP_PLL_CTRL_3r, 1938 REG_PORT_ANY, CH_MDELf, 2)); 1939 SOC_IF_ERROR_RETURN 1940 (soc_reg_field32_modify(unit, TOP_PP_PLL_CTRL_3r, 1941 REG_PORT_ANY, CH_MDELf, 0)); 1942 SOC_IF_ERROR_RETURN 1943 (soc_reg_field32_modify(unit, TOP_PP_PLL_CTRL_3r, 1944 REG_PORT_ANY, CH_MDELf, 2)); 1945 1946 /* Release all post div channels to normal operation */ 1947 SOC_IF_ERROR_RETURN(READ_TOP_PP_PLL_CTRL_1r(unit, &rval)); 1948 soc_reg_field_set(unit, TOP_PP_PLL_CTRL_1r, &rval, POST_HOLD_ALLf, 0); 1949 SOC_IF_ERROR_RETURN(WRITE_TOP_PP_PLL_CTRL_1r(unit, rval)); 1950 1951 return 0; 1952 } 1953 1954 /* 1955 * Function: 1956 * soc_tomahawk3_core_pll_bypass_prog_pre 1957 * Purpose: 1958 * Performs steps 1-3 of the CORE_PLL Programming sequence, and 1959 * is done when TH3 is operating at a different core clock frequency 1960 * Parameters: 1961 * unit - (IN) Unit number 1962 * Returns: 1963 * SOC_E_XXX 1964 */ 1965 STATIC int 1966 _soc_tomahawk3_core_pll_bypass_prog_pre(int unit) 1967 { 1968 uint32 rval; 1969 1970 /* 1 */ 1971 SOC_IF_ERROR_RETURN(READ_TOP_CORE_PLL_CTRL_1r(unit, &rval)); 1972 soc_reg_field_set(unit, TOP_CORE_PLL_CTRL_1r, &rval, AUX_POST_BYP_ENf, 1); 1973 SOC_IF_ERROR_RETURN(WRITE_TOP_CORE_PLL_CTRL_1r(unit, rval)); 1974 1975 /* 2: wait 1 us */ 1976 sal_usleep(1); 1977 1978 /* 3 */ 1979 soc_reg_field_set(unit, TOP_CORE_PLL_CTRL_1r, &rval, SW_RST_ENf, 1); 1980 SOC_IF_ERROR_RETURN(WRITE_TOP_CORE_PLL_CTRL_1r(unit, rval)); 1981 1982 SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval)); 1983 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_CORE_PLL_RST_Lf, 0); 1984 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_CORE_PLL_POST_RST_Lf, 0); 1985 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval)); 1986 1987 1988 /* To 4: Programming of PLL config parameters follows this in calling 1989 * function */ 1990 1991 return SOC_E_NONE; 1992 } 1993 1994 /* 1995 * Function: 1996 * soc_tomahawk3_core_pll_bypass_prog_post 1997 * Purpose: 1998 * Performs steps 5-9 of the CORE_PLL Programming sequence, and 1999 * is done when TH3 is operating at a different core clock frequency 2000 * Parameters: 2001 * unit - (IN) Unit number 2002 * Returns: 2003 * SOC_E_XXX 2004 */ 2005 STATIC int 2006 _soc_tomahawk3_core_pll_bypass_prog_post(int unit) 2007 { 2008 uint32 rval; 2009 2010 /* From 4: This follows the programming of the PLL config parameters from 2011 * the calling function */ 2012 2013 /* 5 */ 2014 SOC_IF_ERROR_RETURN(READ_TOP_CORE_PLL_CTRL_1r(unit, &rval)); 2015 soc_reg_field_set(unit, TOP_CORE_PLL_CTRL_1r, &rval, SW_CFG_SELf, 1); 2016 SOC_IF_ERROR_RETURN(WRITE_TOP_CORE_PLL_CTRL_1r(unit, rval)); 2017 2018 /* 6 */ 2019 SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval)); 2020 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_CORE_PLL_RST_Lf, 1); 2021 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval)); 2022 2023 /* 7: wait 10 us */ 2024 sal_usleep(10); 2025 2026 /* 8 */ 2027 SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval)); 2028 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_CORE_PLL_POST_RST_Lf, 1); 2029 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval)); 2030 2031 /* 9 */ 2032 SOC_IF_ERROR_RETURN(READ_TOP_CORE_PLL_CTRL_1r(unit, &rval)); 2033 soc_reg_field_set(unit, TOP_CORE_PLL_CTRL_1r, &rval, AUX_POST_BYP_ENf, 0); 2034 SOC_IF_ERROR_RETURN(WRITE_TOP_CORE_PLL_CTRL_1r(unit, rval)); 2035 2036 return SOC_E_NONE; 2037 } 2038 2039 /* 2040 * Function: 2041 * soc_tomahawk3_core_pll_config 2042 * Purpose: 2043 * Performs necessary steps to configure the chip for different 2044 * core frequencies. For TH3, only TOP_CORE_PLL_CTRL_0.NDIV_INT 2045 * is changed 2046 * Parameters: 2047 * unit - (IN) Unit number 2048 * Returns: 2049 * SOC_E_XXX 2050 */ 2051 STATIC int 2052 _soc_tomahawk3_core_pll_config(int unit, int frequency) 2053 { 2054 #define _SOC_TH3_PLL_CFG_FIELDS (1) 2055 2056 soc_field_t fields[_SOC_TH3_PLL_CFG_FIELDS]; 2057 uint32 values[_SOC_TH3_PLL_CFG_FIELDS]; 2058 2059 int ndiv_int = -1; 2060 int count; 2061 2062 if (frequency > 0) { 2063 switch (frequency) { 2064 case 1325: 2065 /* Don't do anything if core clock is default */ 2066 break; 2067 case 1250: 2068 ndiv_int = 100; 2069 break; 2070 case 1175: 2071 ndiv_int = 94; 2072 break; 2073 case 1100: 2074 ndiv_int = 88; 2075 break; 2076 case 1000: 2077 ndiv_int = 80; 2078 break; 2079 case 925: 2080 ndiv_int = 74; 2081 break; 2082 default: 2083 break; 2084 } 2085 } else { 2086 ndiv_int = soc_property_get(unit, "force_core_pll_ndiv_int", -1); 2087 } 2088 2089 count = 0; 2090 if (ndiv_int != -1) { 2091 LOG_INFO(BSL_LS_SOC_COMMON, 2092 (BSL_META_U(unit, 2093 "*** change NDIV_INT to %d\n"), ndiv_int)); 2094 fields[count] = NDIV_INTf; 2095 values[count] = ndiv_int; 2096 count++; 2097 } 2098 if (count > 0) { 2099 /* Call this to prepare TH3 for changing the core pll frequency */ 2100 SOC_IF_ERROR_RETURN(_soc_tomahawk3_core_pll_bypass_prog_pre(unit)); 2101 2102 SOC_IF_ERROR_RETURN 2103 (soc_reg_fields32_modify(unit, TOP_CORE_PLL_CTRL_0r, 2104 REG_PORT_ANY, count, fields, values)); 2105 /* Call this after changing the core pll frequency to bring the 2106 * core pll bypass out of reset */ 2107 SOC_IF_ERROR_RETURN(_soc_tomahawk3_core_pll_bypass_prog_post(unit)); 2108 } 2109 2110 return SOC_E_NONE; 2111 } 2112 2113 int 2114 soc_tomahawk3_chip_reset(int unit) 2115 { 2116 uint16 dev_id; 2117 uint8 rev_id; 2118 uint32 to_usec, temp_mask; 2119 uint32 rval, temp_thr; 2120 uint32 trval; 2121 uint32 val; 2122 soc_reg_t reg; 2123 int index = 0, freq = 0; 2124 int parity_enable; 2125 int frequency; 2126 2127 soc_cm_get_id(unit, &dev_id, &rev_id); 2128 to_usec = SAL_BOOT_QUICKTURN ? (250 * MILLISECOND_USEC) : 2129 (10 * MILLISECOND_USEC); 2130 2131 /* 2132 * SBUS ring and block number: 2133 * ring 0: OTPC(6,7), AVS(87), TOP(8) 2134 * ring 1: IP(1) 2135 * ring 2: EP(2) 2136 * ring 3: MMU_ITM(3), MMU_EB(4), MMU_GLB(5) 2137 * ring 4: PM0(16), PM1(17), ... , PM14(30), PM15(31) 2138 * ring 5: PM16(32), PM17(33), ... , PM30(46), PM31(47) 2139 * ring 6: CEV(88) 2140 * ring 7: PM_MGMT(12) 2141 */ 2142 #ifdef BCM_CMICX_SUPPORT 2143 if (soc_feature(unit, soc_feature_cmicx)) { 2144 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_0_7_OFFSET,0x00333210); 2145 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_8_15_OFFSET,0x00070000); 2146 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_16_23_OFFSET,0x44444444); 2147 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_24_31_OFFSET,0x44444444); 2148 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_32_39_OFFSET,0x55555555); 2149 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_40_47_OFFSET,0x55555555); 2150 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_48_55_OFFSET,0x00000000); 2151 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_56_63_OFFSET,0x00005004); 2152 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_64_71_OFFSET,0x00000000); 2153 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_72_79_OFFSET,0x00000000); 2154 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_80_87_OFFSET,0x00000000); 2155 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_88_95_OFFSET,0x00000006); 2156 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_96_103_OFFSET,0x00000000); 2157 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_104_111_OFFSET,0x00000000); 2158 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_112_119_OFFSET,0x00000000); 2159 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_120_127_OFFSET,0x00000000); 2160 /*if (!SAL_BOOT_QUICKTURN) {*/ 2161 soc_pci_write(unit, CMIC_TOP_SBUS_TIMEOUT_OFFSET,0x2700); 2162 /*}*/ 2163 } 2164 #endif 2165 sal_usleep(to_usec); 2166 2167 2168 if (!SAL_BOOT_SIMULATION) { 2169 if (soc_property_get(unit, "force_core_pll", 0)) { 2170 frequency = soc_property_get(unit, "force_core_pll_freq", -1); 2171 } else { 2172 frequency = SOC_INFO(unit).frequency; 2173 } 2174 SOC_IF_ERROR_RETURN(_soc_tomahawk3_core_pll_config(unit, frequency)); 2175 sal_usleep(to_usec); 2176 } 2177 2178 /* Set the PP_PLL */ 2179 if (!SAL_BOOT_SIMULATION) { 2180 freq = soc_property_get(unit, spn_DPR_CLOCK_FREQUENCY, 1000); 2181 SOC_IF_ERROR_RETURN(_soc_th3_pp_pll_config(unit, freq)); 2182 } 2183 2184 2185 /* PLLs are not required in simulation environments */ 2186 if (!SAL_BOOT_SIMULATION) { 2187 /* Configure TS PLL */ 2188 2189 #if 0 2190 SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_1r(unit,&rval)); 2191 soc_reg_field_set(unit, TOP_TS_PLL_CTRL_1r, &rval, PDIVf, 2192 soc_property_get(unit, spn_PTP_TS_PLL_PDIV, 2)); 2193 SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_1r(unit, rval)); 2194 2195 SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_2r(unit,&rval)); 2196 soc_reg_field_set(unit, TOP_TS_PLL_CTRL_2r, &rval, CH0_MDIVf, 2197 soc_property_get(unit, spn_PTP_TS_PLL_MNDIV, 5)); 2198 SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_2r(unit, rval)); 2199 2200 SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_0r(unit,&rval)); 2201 soc_reg_field_set(unit, TOP_TS_PLL_CTRL_0r, &rval, NDIV_INTf, 2202 soc_property_get(unit, spn_PTP_TS_PLL_N, 100)); 2203 SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_0r(unit, rval)); 2204 2205 SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_1r(unit,&rval)); 2206 soc_reg_field_set(unit, TOP_TS_PLL_CTRL_1r, &rval, KAf, 2207 soc_property_get(unit, spn_PTP_TS_KA, 10)); 2208 soc_reg_field_set(unit, TOP_TS_PLL_CTRL_1r, &rval, KIf, 2209 soc_property_get(unit, spn_PTP_TS_KI, 3)); 2210 soc_reg_field_set(unit, TOP_TS_PLL_CTRL_1r, &rval, KPf, 2211 soc_property_get(unit, spn_PTP_TS_KP, 10)); 2212 SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_1r(unit, rval)); 2213 #endif 2214 /* Set 250Mhz (implies 4ns resolution) default timesync clock to 2215 calculate assymentric delays */ 2216 SOC_TIMESYNC_PLL_CLOCK_NS(unit) = (1/250 * 1000); /* clock period in nsec */ 2217 #if 0 2218 /* Configure BS PLL0 */ 2219 SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_1r(unit, &rval)); 2220 soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_1r, &rval, PDIVf, 2221 soc_property_get(unit, spn_PTP_BS_PDIV, 2)); 2222 SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_1r(unit, rval)); 2223 2224 SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_2r(unit, &rval)); 2225 soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_2r, &rval, CH0_MDIVf, 2226 soc_property_get(unit, spn_PTP_BS_MNDIV, 125)); 2227 SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_2r(unit, rval)); 2228 2229 SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_0r(unit, &rval)); 2230 soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_0r, &rval, NDIV_INTf, 2231 soc_property_get(unit, spn_PTP_BS_NDIV_INT, 100)); 2232 SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_0r(unit, rval)); 2233 2234 SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_1r(unit, &rval)); 2235 soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_1r, &rval, KAf, 2236 soc_property_get(unit, spn_PTP_BS_KA, 10)); 2237 soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_1r, &rval, KIf, 2238 soc_property_get(unit, spn_PTP_BS_KI, 3)); 2239 soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_1r, &rval, KPf, 2240 soc_property_get(unit, spn_PTP_BS_KP, 10)); 2241 SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_1r(unit, rval)); 2242 2243 /* Configure BS PLL1 */ 2244 SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_1r(unit, &rval)); 2245 soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_1r, &rval, PDIVf, 2246 soc_property_get(unit, spn_PTP_BS_PDIV, 2)); 2247 SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_1r(unit, rval)); 2248 2249 SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_2r(unit, &rval)); 2250 soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_2r, &rval, CH0_MDIVf, 2251 soc_property_get(unit, spn_PTP_BS_MNDIV, 125)); 2252 SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_2r(unit, rval)); 2253 2254 SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_0r(unit, &rval)); 2255 soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_0r, &rval, NDIV_INTf, 2256 soc_property_get(unit, spn_PTP_BS_NDIV_INT, 100)); 2257 SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_0r(unit, rval)); 2258 2259 SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_1r(unit, &rval)); 2260 soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_1r, &rval, KAf, 2261 soc_property_get(unit, spn_PTP_BS_KA, 10)); 2262 soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_1r, &rval, KIf, 2263 soc_property_get(unit, spn_PTP_BS_KI, 3)); 2264 soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_1r, &rval, KPf, 2265 soc_property_get(unit, spn_PTP_BS_KP, 10)); 2266 SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_1r(unit, rval)); 2267 #endif 2268 2269 /* Bring LCPLL, time sync, BroadSync, IPROC, PP, CORE PLLs 2270 and AVS out of reset */ 2271 SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval)); 2272 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_TS_PLL_RST_Lf, 1); 2273 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL0_RST_Lf, 2274 1); 2275 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL1_RST_Lf, 2276 1); 2277 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_AVS_RST_Lf, 1); 2278 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 2279 TOP_IPROC_PLL_RST_Lf, 1); 2280 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 2281 TOP_PP_PLL_RST_Lf, 1); 2282 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 2283 TOP_CORE_PLL_RST_Lf, 1); 2284 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval)); 2285 2286 SOC_IF_ERROR_RETURN(READ_IDM_GENRES_S0_IDM_RESET_CONTROLr(unit, &rval)); 2287 soc_reg_field_set(unit, IDM_GENRES_S0_IDM_RESET_CONTROLr, &rval, RESETf, 1); 2288 SOC_IF_ERROR_RETURN(WRITE_IDM_GENRES_S0_IDM_RESET_CONTROLr(unit, rval)); 2289 2290 SOC_IF_ERROR_RETURN(READ_IDM_GENRES_S0_IDM_RESET_CONTROLr(unit, &rval)); 2291 soc_reg_field_set(unit, IDM_GENRES_S0_IDM_RESET_CONTROLr, &rval, RESETf, 0); 2292 SOC_IF_ERROR_RETURN(WRITE_IDM_GENRES_S0_IDM_RESET_CONTROLr(unit, rval)); 2293 2294 2295 2296 2297 sal_usleep(to_usec); 2298 2299 /* Check LCPLL lock status */ 2300 2301 #if 0 2302 reg = TOP_XG_PLL0_STATUSr; 2303 SOC_IF_ERROR_RETURN 2304 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 2305 if (!soc_reg_field_get(unit, reg, rval, TOP_XGPLL_LOCKf)) { 2306 LOG_ERROR(BSL_LS_SOC_COMMON, 2307 (BSL_META_U(unit, 2308 "LCPLL %d not locked on unit %d " 2309 "status = 0x%08x\n"), index, unit, rval)); 2310 } 2311 #endif 2312 2313 /* Check time sync lock status */ 2314 reg = TOP_TS_PLL_STATUSr; 2315 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 2316 if (!soc_reg_field_get(unit, reg, rval, LOCKf)) { 2317 LOG_ERROR(BSL_LS_SOC_COMMON, 2318 (BSL_META_U(unit, 2319 "TS_PLL not locked on unit %d " 2320 "status = 0x%08x\n"), unit, rval)); 2321 } 2322 /* Check BroadSync lock status */ 2323 reg = TOP_BS_PLL0_STATUSr; 2324 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 2325 if (!soc_reg_field_get(unit, reg, rval, LOCKf)) { 2326 LOG_ERROR(BSL_LS_SOC_COMMON, 2327 (BSL_META_U(unit, 2328 "BS_PLL0 not locked on unit %d " 2329 "status = 0x%08x\n"), unit, rval)); 2330 } 2331 2332 reg = TOP_BS_PLL1_STATUSr; 2333 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 2334 if (!soc_reg_field_get(unit, reg, rval, LOCKf)) { 2335 LOG_ERROR(BSL_LS_SOC_COMMON, 2336 (BSL_META_U(unit, 2337 "BS_PLL0 not locked on unit %d " 2338 "status = 0x%08x\n"), unit, rval)); 2339 } 2340 2341 /* Check PP lock status */ 2342 reg = TOP_PP_PLL_STATUSr; 2343 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 2344 if (!soc_reg_field_get(unit, reg, rval, LOCKf)) { 2345 LOG_ERROR(BSL_LS_SOC_COMMON, 2346 (BSL_META_U(unit, 2347 "BS_PLL0 not locked on unit %d " 2348 "status = 0x%08x\n"), unit, rval)); 2349 } 2350 2351 /* De-assert LCPLL's post reset */ 2352 SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval)); 2353 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 2354 TOP_TS_PLL_POST_RST_Lf, 1); 2355 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 2356 TOP_BS_PLL0_POST_RST_Lf, 1); 2357 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 2358 TOP_BS_PLL1_POST_RST_Lf, 1); 2359 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 2360 TOP_IPROC_PLL_POST_RST_Lf, 1); 2361 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 2362 TOP_PP_PLL_POST_RST_Lf, 1); 2363 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 2364 TOP_CORE_PLL_POST_RST_Lf, 1); 2365 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval)); 2366 } 2367 2368 sal_usleep(to_usec); 2369 2370 /* Check the the sticky bit whether HW PVTMON High Temperature Protection 2371 * happened in system's previous running or not. Halt the current bootup, print error 2372 * message, and ask for a system reboot if the sticky bit was set. */ 2373 2374 SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_RESULT_0r(unit, &rval)); 2375 if (soc_reg_field_get(unit, TOP_PVTMON_RESULT_0r, 2376 rval, PVTMON_HIGHTEMP_STATUSf)) { 2377 LOG_ERROR(BSL_LS_SOC_COMMON, 2378 (BSL_META_U(unit, 2379 "HW PVTMON High Temperature Protection " 2380 "was invoked during last system run. " 2381 "Please correct the temperature problem " 2382 "and cycle power to continue.\n"))); 2383 2384 /* Clear HIGHTEMP sticky bit on all PVTMONs */ 2385 SOC_IF_ERROR_RETURN(READ_TOP_MISC_CONTROL_1r(unit, &rval)); 2386 soc_reg_field_set(unit, TOP_MISC_CONTROL_1r, &rval, PVTMON_HIGHTEMP_STAT_CLEARf, 1); 2387 SOC_IF_ERROR_RETURN(WRITE_TOP_MISC_CONTROL_1r(unit, rval)); 2388 2389 return SOC_E_FAIL; 2390 } 2391 2392 2393 /* Set correct value for BG_ADJ */ 2394 /* TH2 leaves it to be default 2395 SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_CTRL_0r(unit, &rval)); 2396 soc_reg_field_set(unit, TOP_PVTMON_CTRL_0r, &rval, BG_ADJf, 0); 2397 SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_0r(unit, rval)); 2398 */ 2399 2400 /* Enable high temperature interrupt monitoring. 2401 */ 2402 temp_mask = soc_property_get(unit, "temp_monitor_select", ((1 << 16)-1)); 2403 /* The above is a 9 bit mask to indicate which temp sensor to hook up to 2404 * the interrupt. 2405 */ 2406 val = 0; 2407 for (index = 0; index <COUNTOF(temp_thr_reg)-1; index++) { 2408 /* AVS excluded */ 2409 2410 trval = 0; 2411 /* Temp = 434.10 - o_ADC_data * 0.53504 2412 * data = (434.10 - temp)/0.53504 = (434100-(temp*1000))/535 2413 * Note: Since this is a high temp value we can safely assume it to 2414 * always be a +ive number. This is in degrees celcius. 2415 */ 2416 temp_thr = 2417 soc_property_get(unit, temp_thr_prop[index], 2418 ((index < 5) || (index == 6) || (index == 10)) ? \ 2419 _SOC_TH3_HW_TEMP_MAX : _SOC_TH3_SW_TEMP_MAX); 2420 if (temp_thr > _SOC_TH3_HW_TEMP_MAX) { 2421 LOG_ERROR(BSL_LS_SOC_COMMON, 2422 (BSL_META_U(unit, 2423 "Unsupported temp value %d !!. " 2424 "Max %d. Using %d.\n"), 2425 temp_thr, _SOC_TH3_HW_TEMP_MAX, _SOC_TH3_HW_TEMP_MAX)); 2426 temp_thr = _SOC_TH3_HW_TEMP_MAX; 2427 } 2428 2429 /* Convert temperature to config data */ 2430 temp_thr = (434100-(temp_thr*1000))/535; 2431 2432 SOC_IF_ERROR_RETURN 2433 (soc_reg32_get(unit, temp_thr_reg[index], REG_PORT_ANY, 0, &trval)); 2434 soc_reg_field_set(unit, temp_thr_reg[index], &trval, MIN_THRESHOLDf, 2435 temp_thr); 2436 SOC_IF_ERROR_RETURN 2437 (soc_reg32_set(unit, temp_thr_reg[index], REG_PORT_ANY, 0, trval)); 2438 if (temp_mask & (1 << index)) { 2439 val |= (1 << ((index * 2) + 1)); /* 2 bits per pvtmon, using min */ 2440 } 2441 } 2442 _soc_th_temp_mon_mask[unit] = temp_mask; 2443 2444 /* Enable high temperature interrupt monitoring excluding 15 (AVS), 10, 6, 4, 3, 2, 1, 0 . */ 2445 SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_INTR_MASK_0r(unit, val & 0x3fcfcc00)); 2446 2447 /* Enable PVTMON interrupt in CMIC */ 2448 SOC_IF_ERROR_RETURN(soc_iproc_getreg(unit, 2449 soc_reg_addr(unit, ICFG_CHIP_LP_INTR_ENABLE_REG0r, 2450 REG_PORT_ANY, 0), &rval)); 2451 rval |= 0x4; 2452 SOC_IF_ERROR_RETURN(soc_iproc_setreg(unit, 2453 soc_reg_addr(unit, ICFG_CHIP_LP_INTR_ENABLE_REG0r, 2454 REG_PORT_ANY, 0), rval)); 2455 2456 2457 /* Bring the Temp monitor minimum value out of reset */ 2458 for (index = 0; index <COUNTOF(temp_pvtmon_ctrl_reg); index++) { 2459 2460 trval = 0; 2461 SOC_IF_ERROR_RETURN 2462 (soc_reg32_get(unit, temp_pvtmon_ctrl_reg[index].pvtmon_reg, 2463 REG_PORT_ANY, 0, &trval)); 2464 soc_reg_field_set(unit, temp_pvtmon_ctrl_reg[index].pvtmon_reg, &trval, 2465 temp_pvtmon_ctrl_reg[index].pvtmon_field, 1); 2466 SOC_IF_ERROR_RETURN 2467 (soc_reg32_set(unit, temp_pvtmon_ctrl_reg[index].pvtmon_reg, 2468 REG_PORT_ANY, 0, trval)); 2469 } 2470 2471 /* Enable HW PVTMON high temperature protection by setting 2472 hightemp_ctrl_en field for pvtmon 0-4, 6 and 10 */ 2473 SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_0_CTRL_1r(unit, &rval)); 2474 soc_reg_field_set(unit, TOP_PVTMON_0_CTRL_1r, &rval, PVTMON_HIGHTEMP_CTRL_ENf, 1); 2475 SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_0_CTRL_1r(unit, rval)); 2476 2477 SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_1_CTRL_1r(unit, &rval)); 2478 soc_reg_field_set(unit, TOP_PVTMON_1_CTRL_1r, &rval, PVTMON_HIGHTEMP_CTRL_ENf, 1); 2479 SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_1_CTRL_1r(unit, rval)); 2480 2481 SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_2_CTRL_1r(unit, &rval)); 2482 soc_reg_field_set(unit, TOP_PVTMON_2_CTRL_1r, &rval, PVTMON_HIGHTEMP_CTRL_ENf, 1); 2483 SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_2_CTRL_1r(unit, rval)); 2484 2485 SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_3_CTRL_1r(unit, &rval)); 2486 soc_reg_field_set(unit, TOP_PVTMON_3_CTRL_1r, &rval, PVTMON_HIGHTEMP_CTRL_ENf, 1); 2487 SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_3_CTRL_1r(unit, rval)); 2488 2489 SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_4_CTRL_1r(unit, &rval)); 2490 soc_reg_field_set(unit, TOP_PVTMON_4_CTRL_1r, &rval, PVTMON_HIGHTEMP_CTRL_ENf, 1); 2491 SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_4_CTRL_1r(unit, rval)); 2492 2493 SOC_IF_ERROR_RETURN(READ_TOP_TMON_CTRL_1r(unit, &rval)); 2494 soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_6_PVTMON_HIGHTEMP_CTRL_ENf, 1); 2495 soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_10_PVTMON_HIGHTEMP_CTRL_ENf, 1); 2496 SOC_IF_ERROR_RETURN(WRITE_TOP_TMON_CTRL_1r(unit, rval)); 2497 2498 /* Bring port blocks out of reset */ 2499 rval = 0; 2500 soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_PM_MGMT_RST_Lf, 1); 2501 soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_TS_RST_Lf, 1); 2502 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REGr(unit, rval)); 2503 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_3r(unit, 0xffffffff)); 2504 sal_usleep(to_usec); 2505 2506 /* Need set PSG/PCG to 0 before de-assert IP/EP/MMU SOFT reset */ 2507 SOC_IF_ERROR_RETURN(WRITE_TOP_CLOCKING_ENFORCE_PSGr(unit, 0)); 2508 SOC_IF_ERROR_RETURN(WRITE_TOP_CLOCKING_ENFORCE_PCGr(unit, 0)); 2509 2510 /* Bring IP, EP, and MMU blocks out of reset */ 2511 SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REGr(unit, &rval)); 2512 soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_IP_RST_Lf, 1); 2513 soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_EP_RST_Lf, 1); 2514 soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_MMU_RST_Lf, 1); 2515 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REGr(unit, rval)); 2516 sal_usleep(to_usec); 2517 2518 /* Need to enable SLOT_PIPELINE_ECC_EN before configuring slot pipeline */ 2519 parity_enable = soc_property_get(unit, spn_PARITY_ENABLE, TRUE); 2520 if (parity_enable) { 2521 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, IPOST_SER_CONTROLr, 2522 REG_PORT_ANY, 2523 SLOT_PIPELINE_ECC_ENf,1)); 2524 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, EPOST_SER_CONTROLr, 2525 REG_PORT_ANY, 2526 SLOT_PIPELINE_ECC_ENf,1)); 2527 } 2528 /* IP/EP Slot pipeline configuration */ 2529 /* Needs to be configured before accessing registers in IP/EP 2530 and also before ip/ep memories are initialized 2531 */ 2532 SOC_IF_ERROR_RETURN(soc_tomahawk3_slot_pipeline_config(unit)); 2533 2534 SOC_IF_ERROR_RETURN(_soc_tomahawk3_init_ipep_memory(unit)); 2535 2536 /* Bypass unused Port Blocks */ 2537 if (soc_property_get(unit, "disable_unused_port_blocks", TRUE)) { 2538 SOC_IF_ERROR_RETURN(soc_th3_bypass_unused_pm(unit)); 2539 } 2540 2541 return SOC_E_NONE; 2542 } 2543 2544 STATIC 2545 int _soc_tomahawk3_activate_pm8x50(int unit, int phy_port) 2546 { 2547 uint8 at; 2548 uint32 raddr, reg_val; 2549 soc_block_t block; 2550 soc_reg_t reg = CDPORT_XGXS0_CTRL_REGr; 2551 int sleep_usec = SAL_BOOT_QUICKTURN ? 500000 : 1100; 2552 2553 /* index the register by phy port to activate the PM */ 2554 raddr = soc_reg_addr_get(unit, reg, phy_port, 0, 2555 SOC_REG_ADDR_OPTION_PRESERVE_PORT, &block, &at); 2556 SOC_IF_ERROR_RETURN(_soc_reg32_get(unit, block, at, raddr, ®_val)); 2557 2558 soc_reg_field_set(unit, reg, ®_val, TSC_PWRDWNf, 0); 2559 soc_reg_field_set(unit, reg, ®_val, TSC_CLK_SELf, 1); 2560 SOC_IF_ERROR_RETURN(_soc_reg32_set(unit, block, at, raddr, reg_val)); 2561 sal_usleep(sleep_usec); 2562 2563 soc_reg_field_set(unit, reg, ®_val, TSC_RSTBf, 0); 2564 SOC_IF_ERROR_RETURN(_soc_reg32_set(unit, block, at, raddr, reg_val)); 2565 sal_usleep(sleep_usec+10000); 2566 2567 soc_reg_field_set(unit, reg, ®_val, TSC_RSTBf, 1); 2568 SOC_IF_ERROR_RETURN(_soc_reg32_set(unit, block, at, raddr, reg_val)); 2569 sal_usleep(sleep_usec); 2570 2571 return SOC_E_NONE; 2572 } 2573 2574 STATIC 2575 int soc_tomahawk3_cdport_reset(int unit) 2576 { 2577 int i, blk, pm, port, phy_port = 1; 2578 uint32 pipe_map; 2579 soc_info_t * si; 2580 int pm_reset[_TH3_PBLKS_PER_DEV]; 2581 uint16 dev_id; 2582 uint8 rev_id; 2583 2584 si = &SOC_INFO(unit); 2585 2586 sal_memset(pm_reset, 0, sizeof(pm_reset)); 2587 2588 /* reset the PMs that have mappings */ 2589 SOC_BLOCK_ITER(unit, blk, SOC_BLK_CDPORT) { 2590 port = SOC_BLOCK_PORT(unit, blk); 2591 2592 phy_port = si->port_l2p_mapping[port]; 2593 /* mark that this PM has been reset */ 2594 pm_reset[(phy_port-1)/_TH3_PORTS_PER_PBLK] = 1; 2595 2596 SOC_IF_ERROR_RETURN(soc_tsc_xgxs_reset(unit, port, 0)); 2597 } 2598 2599 soc_tomahawk3_pipe_map_get(unit, &pipe_map); 2600 2601 soc_cm_get_id(unit, &dev_id, &rev_id); 2602 2603 /* reset any master PMs that haven't been reset yet. 2604 * In TH3 A0 the master PMs are 1, 2, 5, 6, 9, 10, 13, 14, 17, 2605 * 18, 22, 22, 26, 26, 29, 30 */ 2606 if (rev_id == BCM56980_A0_REV_ID) { 2607 for (i = 0; i < 2; i++) { 2608 for (pm = 1 + i; pm < _TH3_PBLKS_PER_DEV; pm+=4) { 2609 /* skip if the pm has already been reset */ 2610 if (pm_reset[pm] == 1) { 2611 continue; 2612 } 2613 2614 /* skip a PM if the pipe it is located in is disabled */ 2615 if ((pipe_map & (1 << (pm / _TH3_PBLKS_PER_PIPE))) == 0) { 2616 continue; 2617 } 2618 2619 /* get the first phy port of the PM */ 2620 phy_port = (pm * _TH3_PORTS_PER_PBLK) + 1; 2621 2622 /* Activate the PM */ 2623 SOC_IF_ERROR_RETURN( 2624 _soc_tomahawk3_activate_pm8x50(unit, phy_port)); 2625 } 2626 } 2627 } else { 2628 /* In TH3 B0 the master PMs are 3, 4, 11, 12, 19, 20, 27, 28 */ 2629 for (pm = 0; pm < _TH3_PBLKS_PER_DEV; pm++) { 2630 /* Skip if not a master PM */ 2631 if ( !(pm == 3 || pm == 4 || pm == 11 || pm == 12 || 2632 pm == 19 || pm == 20 || pm == 27 || pm == 28) ) { 2633 continue; 2634 } 2635 2636 /* skip if the pm has already been reset */ 2637 if (pm_reset[pm] == 1) { 2638 continue; 2639 } 2640 2641 /* skip a PM if the pipe it is located in is disabled */ 2642 if ((pipe_map & (1 << (pm / _TH3_PBLKS_PER_PIPE))) == 0) { 2643 continue; 2644 } 2645 2646 /* get the first phy port of the PM */ 2647 phy_port = (pm * _TH3_PORTS_PER_PBLK) + 1; 2648 2649 /* Activate the PM */ 2650 SOC_IF_ERROR_RETURN( 2651 _soc_tomahawk3_activate_pm8x50(unit, phy_port)); 2652 2653 } 2654 } 2655 2656 return SOC_E_NONE; 2657 } 2658 2659 int 2660 soc_tomahawk3_port_reset(int unit) 2661 { 2662 uint32 rval; 2663 int blk, port; 2664 2665 /* Instead of using the generic TSC init, TH3 needs to be aware 2666 * of master port macros that need to be initialized so that the clocks 2667 * of the slaves will come up. This is why this function is needed 2668 * rather than calling soc_tsc_xgxs_reset */ 2669 SOC_IF_ERROR_RETURN(soc_tomahawk3_cdport_reset(unit)); 2670 2671 SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) { 2672 port = SOC_BLOCK_PORT(unit, blk); 2673 SOC_IF_ERROR_RETURN(soc_tsc_xgxs_reset(unit, port, 0)); 2674 } 2675 2676 2677 SOC_BLOCK_ITER(unit, blk, SOC_BLK_CDPORT) { 2678 port = SOC_BLOCK_PORT(unit, blk); 2679 2680 SOC_IF_ERROR_RETURN(READ_CDPORT_MAC_CONTROLr(unit, port, &rval)); 2681 soc_reg_field_set(unit, CDPORT_MAC_CONTROLr, &rval, CDMAC0_RESETf, 1); 2682 soc_reg_field_set(unit, CDPORT_MAC_CONTROLr, &rval, CDMAC1_RESETf, 1); 2683 SOC_IF_ERROR_RETURN(WRITE_CDPORT_MAC_CONTROLr(unit, port, rval)); 2684 sal_udelay(10); 2685 soc_reg_field_set(unit, CDPORT_MAC_CONTROLr, &rval, CDMAC0_RESETf, 0); 2686 soc_reg_field_set(unit, CDPORT_MAC_CONTROLr, &rval, CDMAC1_RESETf, 0); 2687 #if 0 2688 /* removed from latest regsfile */ 2689 soc_reg_field_set(unit, CDPORT_MAC_CONTROLr, &rval, SYS_64B_INTF_MODEf, 1); 2690 #endif 2691 2692 SOC_IF_ERROR_RETURN(WRITE_CDPORT_MAC_CONTROLr(unit, port, rval)); 2693 } 2694 2695 SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) { 2696 port = SOC_BLOCK_PORT(unit, blk); 2697 2698 SOC_IF_ERROR_RETURN(READ_XLPORT_MAC_CONTROLr(unit, port, &rval)); 2699 soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 1); 2700 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MAC_CONTROLr(unit, port, rval)); 2701 sal_udelay(10); 2702 soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 0); 2703 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MAC_CONTROLr(unit, port, rval)); 2704 } 2705 2706 return SOC_E_NONE; 2707 } 2708 2709 2710 int 2711 soc_tomahawk3_port_speed_update(int unit, soc_port_t port, int speed) 2712 { 2713 uint32 rval, fval; 2714 uint32 entry[SOC_MAX_MEM_WORDS]; 2715 soc_info_t *si = &SOC_INFO(unit); 2716 int rv; 2717 2718 /* 2719 * No reconfiguration is needed if new speed 2720 * matches current speed 2721 */ 2722 if (speed == si->port_init_speed[port]) { 2723 return SOC_E_NONE; 2724 } 2725 2726 rv = soc_th_port_asf_mode_set(unit, port, speed, 2727 _SOC_TH_ASF_MODE_CFG_UPDATE); 2728 if ((SOC_E_NONE != rv) && (SOC_E_UNAVAIL != rv) && (SOC_E_PARAM != rv)) { 2729 return rv; 2730 } 2731 2732 /* OS related updates */ 2733 if (SOC_PBMP_NOT_NULL(SOC_INFO(unit).oversub_pbm)) { 2734 sal_memset(entry, 0, sizeof(egr_xmit_start_count_entry_t)); 2735 fval = (speed * 11875)/100000; 2736 soc_mem_field32_set(unit, EDB_1DBG_Bm, &entry, FIELD_Bf, fval); 2737 SOC_IF_ERROR_RETURN 2738 (soc_mem_write(unit, EDB_1DBG_Bm, MEM_BLOCK_ALL, 2739 SOC_INFO(unit).port_l2p_mapping[port], entry)); 2740 2741 rval = 0; 2742 if (speed >= 100000) { 2743 fval = 140; 2744 } else if (speed >= 40000) { 2745 fval = 60; 2746 } else if (speed >= 25000) { 2747 fval = 40; 2748 } else if (speed >= 20000) { 2749 fval = 30; 2750 } else { 2751 fval = 15; 2752 } 2753 soc_reg_field_set(unit, MMU_3DBG_Cr, &rval, FIELD_Af, 2754 fval + sal_rand() % 20); 2755 SOC_IF_ERROR_RETURN 2756 (soc_tomahawk_sc_reg32_set(unit, MMU_3DBG_Cr, -1, port, 0, rval)); 2757 } 2758 if (!SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) { 2759 soc_th_port_lanes_t lanes_ctrl; 2760 2761 sal_memset(&lanes_ctrl, 0, sizeof(lanes_ctrl)); 2762 lanes_ctrl.port_base = port; 2763 lanes_ctrl.lanes = TH_FLEXPORT_SPEED_SET_NUM_LANES; 2764 lanes_ctrl.speed = speed; 2765 SOC_IF_ERROR_RETURN(soc_th3_speed_set_init_ctrl(unit, &lanes_ctrl)); 2766 SOC_IF_ERROR_RETURN 2767 (soc_tomahawk_port_lanes_set(unit, &lanes_ctrl)); 2768 } 2769 2770 return SOC_E_NONE; 2771 } 2772 2773 int soc_th3_get_alpm_banks(int unit) 2774 { 2775 int rv = SOC_E_NONE; 2776 uint32 bank_config; 2777 uint32 hash_control_entry[SOC_MAX_MEM_WORDS]; 2778 2779 if (num_shared_alpm_banks[unit] == 0) { 2780 rv = READ_EXACT_MATCH_HASH_CONTROLm(unit, MEM_BLOCK_ANY, 0, hash_control_entry); 2781 if (SOC_FAILURE(rv)) { 2782 num_shared_alpm_banks[unit] = 8; 2783 } else { 2784 bank_config = soc_mem_field32_get(unit, EXACT_MATCH_HASH_CONTROLm, 2785 hash_control_entry, HASH_TABLE_BANK_CONFIGf); 2786 if (bank_config & 0xF) { /* EXACT MATCH used UFT banks */ 2787 num_shared_alpm_banks[unit] = 4; /* TH3 ALPM uses only 4 or 8 UFT banks */ 2788 } else { 2789 num_shared_alpm_banks[unit] = 8; 2790 } 2791 } 2792 } 2793 2794 return num_shared_alpm_banks[unit]; 2795 } 2796 2797 int 2798 soc_tomahawk3_alpm_mode_get(int unit) 2799 { 2800 return _soc_alpm_mode[unit]; 2801 } 2802 2803 void 2804 _soc_tomahawk3_alpm_bkt_view_set(int unit, int index, soc_mem_t view) 2805 { 2806 int bkt = (index >> (soc_th3_get_alpm_banks(unit) + 1) / 2) & SOC_TH_ALPM_BKT_MASK(unit); 2807 2808 if (view != INVALIDm) { 2809 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2810 (BSL_META_U(unit, 2811 "Unit:%d ALPM bkt set index:%d bkt:%d view:%s\n"), 2812 unit, index, bkt, SOC_MEM_NAME(unit, view))); 2813 } 2814 } 2815 2816 soc_mem_t 2817 _soc_tomahawk3_alpm_bkt_view_get(int unit, int index) 2818 { 2819 soc_mem_t view = L3_DEFIP_ALPM_LEVEL3m; 2820 int bkt = (index >> (soc_th3_get_alpm_banks(unit) + 1) / 2) & SOC_TH_ALPM_BKT_MASK(unit); 2821 2822 if (view != INVALIDm) { 2823 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2824 (BSL_META_U(unit, 2825 "Unit:%d ALPM bkt get index:%d bkt:%d view:%s\n"), 2826 unit, index, bkt, SOC_MEM_NAME(unit, view))); 2827 } 2828 return view; 2829 } 2830 2831 int soc_tomahawk3_mem_basetype_get(int unit, soc_mem_t mem) 2832 { 2833 int base_type; 2834 2835 base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7; 2836 return base_type; 2837 } 2838 2839 /* Function to Clear all Memories. 2840 * Param 2841 * mmu_init - bool val to indicate whether to initialize mmu or not. 2842 */ 2843 STATIC int 2844 _soc_tomahawk3_init_ipep_memory(int unit) 2845 { 2846 uint32 pipe_map; 2847 soc_reg_t reg; 2848 int pipe; 2849 uint32 rval, in_progress; 2850 int pipe_init_usec; 2851 soc_timeout_t to; 2852 l2_entry_hash_control_entry_t l2_entry_hash_control; 2853 l3_entry_hash_control_entry_t l3_entry_hash_control; 2854 tunnel_hash_control_entry_t tunnel_hash_control; 2855 mpls_entry_hash_control_entry_t mpls_entry_hash_control; 2856 exact_match_hash_control_entry_t exact_match_hash_control; 2857 2858 soc_tomahawk3_pipe_map_get(unit, &pipe_map); 2859 2860 sal_memset(&l2_entry_hash_control, 0, sizeof(l2_entry_hash_control_entry_t)); 2861 sal_memset(&l3_entry_hash_control, 0, sizeof(l3_entry_hash_control_entry_t)); 2862 sal_memset(&tunnel_hash_control, 0, sizeof(tunnel_hash_control_entry_t)); 2863 sal_memset(&mpls_entry_hash_control, 0, sizeof(mpls_entry_hash_control_entry_t)); 2864 sal_memset(&exact_match_hash_control, 0, sizeof(exact_match_hash_control_entry_t)); 2865 2866 /* In TH3, some of the IPEP memories are hash memories and we need special settings to clear 2867 the hash memories. The settings include the configuring the reset_val of the fields in the 2868 respective hash_control memories of the hash tables. Refer TH3-3821 2869 */ 2870 soc_mem_field32_set(unit, L2_ENTRY_HASH_CONTROLm, &l2_entry_hash_control, ROBUST_HASH_ENf, 0x1); 2871 soc_mem_field32_set(unit, L2_ENTRY_HASH_CONTROLm, &l2_entry_hash_control, HASH_OFFSET_DEDICATED_BANK_1f, 0x20); 2872 soc_mem_field32_set(unit, L2_ENTRY_HASH_CONTROLm, &l2_entry_hash_control, HASH_TABLE_BANK_CONFIGf, 0x3); 2873 SOC_IF_ERROR_RETURN 2874 (WRITE_L2_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0, 2875 &l2_entry_hash_control)); 2876 2877 soc_mem_field32_set(unit, L3_ENTRY_HASH_CONTROLm, &l3_entry_hash_control, ROBUST_HASH_ENf, 0x1); 2878 soc_mem_field32_set(unit, L3_ENTRY_HASH_CONTROLm, &l3_entry_hash_control, HASH_OFFSET_DEDICATED_BANK_1f, 0x20); 2879 soc_mem_field32_set(unit, L3_ENTRY_HASH_CONTROLm, &l3_entry_hash_control, HASH_TABLE_BANK_CONFIGf, 0xf); 2880 SOC_IF_ERROR_RETURN 2881 (WRITE_L3_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0, 2882 &l3_entry_hash_control)); 2883 2884 soc_mem_field32_set(unit, L3_TUNNEL_HASH_CONTROLm, &tunnel_hash_control, ROBUST_HASH_ENf, 0x1); 2885 soc_mem_field32_set(unit, L3_TUNNEL_HASH_CONTROLm, &tunnel_hash_control, HASH_OFFSET_DEDICATED_BANK_1f, 0x20); 2886 soc_mem_field32_set(unit, L3_TUNNEL_HASH_CONTROLm, &tunnel_hash_control, HASH_TABLE_BANK_CONFIGf, 0xf); 2887 SOC_IF_ERROR_RETURN 2888 (WRITE_L3_TUNNEL_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0, 2889 &tunnel_hash_control)); 2890 2891 soc_mem_field32_set(unit, MPLS_ENTRY_HASH_CONTROLm, &mpls_entry_hash_control, ROBUST_HASH_ENf, 0x1); 2892 soc_mem_field32_set(unit, MPLS_ENTRY_HASH_CONTROLm, &mpls_entry_hash_control, HASH_OFFSET_DEDICATED_BANK_1f, 0x20); 2893 soc_mem_field32_set(unit, MPLS_ENTRY_HASH_CONTROLm, &mpls_entry_hash_control, HASH_TABLE_BANK_CONFIGf, 0x3); 2894 SOC_IF_ERROR_RETURN 2895 (WRITE_MPLS_ENTRY_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0, 2896 &mpls_entry_hash_control)); 2897 2898 soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm, &exact_match_hash_control, ROBUST_HASH_ENf, 0x1); 2899 soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm, &exact_match_hash_control, LOGICAL_BANK_1_PHYSICAL_BANK_LOCATIONf, 0x1); 2900 soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm, &exact_match_hash_control, LOGICAL_BANK_2_PHYSICAL_BANK_LOCATIONf, 0x2); 2901 soc_mem_field32_set(unit, EXACT_MATCH_HASH_CONTROLm, &exact_match_hash_control, LOGICAL_BANK_3_PHYSICAL_BANK_LOCATIONf, 0x3); 2902 SOC_IF_ERROR_RETURN 2903 (WRITE_EXACT_MATCH_HASH_CONTROLm(unit, MEM_BLOCK_ALL, 0, 2904 &exact_match_hash_control)); 2905 2906 /* Initial IPIPE memory */ 2907 rval = 0; 2908 soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, RESET_ALLf, 1); 2909 soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, VALIDf, 1); 2910 soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, COUNTf, 0x20000); 2911 SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval)); 2912 2913 /* Initial DLB memory */ 2914 rval = 0; 2915 soc_reg_field_set(unit, DLB_ECMP_HW_RESET_CONTROLr, &rval, RESET_ALLf, 1); 2916 soc_reg_field_set(unit, DLB_ECMP_HW_RESET_CONTROLr, &rval, VALIDf, 1); 2917 soc_reg_field_set(unit, DLB_ECMP_HW_RESET_CONTROLr, &rval, COUNTf, 0x1000); 2918 SOC_IF_ERROR_RETURN(WRITE_DLB_ECMP_HW_RESET_CONTROLr(unit, rval)); 2919 2920 /* Initial EPIPE memory */ 2921 rval = 0; 2922 soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, RESET_ALLf, 1); 2923 soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, VALIDf, 1); 2924 soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, COUNTf, 0xFFFF); 2925 SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1r(unit, rval)); 2926 2927 /* Initial EPIPE memory */ 2928 rval = 0; 2929 soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1_COREr, &rval, RESET_ALLf, 1); 2930 soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1_COREr, &rval, VALIDf, 1); 2931 soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1_COREr, &rval, COUNTf, 0xFFFF); 2932 SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1_COREr(unit, rval)); 2933 2934 /* For simulation, set timeout to 10 sec. Otherwise, timeout = 50 ms */ 2935 if (SAL_BOOT_SIMULATION) { 2936 pipe_init_usec = 10000000; 2937 } else { 2938 pipe_init_usec = 50000; 2939 } 2940 soc_timeout_init(&to, pipe_init_usec, 0); 2941 2942 if (!SAL_BOOT_SIMULATION || SAL_BOOT_QUICKTURN) 2943 { 2944 /* Wait for IPIPE memory initialization done */ 2945 in_progress = pipe_map; 2946 do { 2947 for (pipe = 0; pipe < _TH3_PIPES_PER_DEV && in_progress; pipe++) { 2948 if (!(pipe_map & (1 << pipe))) { 2949 continue; 2950 } 2951 reg = SOC_REG_UNIQUE_ACC(unit, ING_HW_RESET_CONTROL_2r)[pipe]; 2952 if (in_progress & (1 << pipe)) { /* not done yet */ 2953 SOC_IF_ERROR_RETURN 2954 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 2955 if (soc_reg_field_get(unit, reg, rval, DONEf)) { 2956 in_progress ^= 1 << pipe; 2957 } 2958 } 2959 } 2960 if (soc_timeout_check(&to)) { 2961 LOG_WARN(BSL_LS_SOC_COMMON, 2962 (BSL_META_U(unit, 2963 "unit %d : ING_HW_RESET timeout\n"), unit)); 2964 break; 2965 } 2966 } while (in_progress != 0); 2967 2968 /* Wait for EPIPE memory initialization done */ 2969 in_progress = pipe_map; 2970 do { 2971 for (pipe = 0; pipe < _TH3_PIPES_PER_DEV && in_progress; pipe++) { 2972 if (!(pipe_map & (1 << pipe))) { 2973 continue; 2974 } 2975 reg = SOC_REG_UNIQUE_ACC(unit, EGR_HW_RESET_CONTROL_1r)[pipe]; 2976 if (in_progress & (1 << pipe)) { /* not done yet */ 2977 SOC_IF_ERROR_RETURN 2978 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 2979 if (soc_reg_field_get(unit, reg, rval, DONEf)) { 2980 in_progress ^= 1 << pipe; 2981 } 2982 } 2983 } 2984 if (soc_timeout_check(&to)) { 2985 LOG_WARN(BSL_LS_SOC_COMMON, 2986 (BSL_META_U(unit, 2987 "unit %d : ING_HW_RESET timeout\n"), unit)); 2988 break; 2989 } 2990 } while (in_progress != 0); 2991 2992 /* Wait for DLB memory initialization done */ 2993 in_progress = 1; 2994 do { 2995 reg = DLB_ECMP_HW_RESET_CONTROLr; 2996 SOC_IF_ERROR_RETURN 2997 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 2998 if (soc_reg_field_get(unit, reg, rval, DONEf)) { 2999 in_progress = 0; 3000 } 3001 if (soc_timeout_check(&to)) { 3002 LOG_WARN(BSL_LS_SOC_COMMON, 3003 (BSL_META_U(unit, 3004 "unit %d : EGR_HW_RESET timeout\n"), unit)); 3005 break; 3006 } 3007 } while (in_progress != 0); 3008 3009 /* Wait for EPIPE memory initialization done */ 3010 /* This is a new register EGR_HW_RESET_CONTROL_1_CORE added for 3011 TH3 which would help in initializing the EPIPE memories */ 3012 in_progress = pipe_map; 3013 do { 3014 for (pipe = 0; pipe < _TH3_PIPES_PER_DEV && in_progress; pipe++) { 3015 if (!(pipe_map & (1 << pipe))) { 3016 continue; 3017 } 3018 reg = SOC_REG_UNIQUE_ACC(unit, EGR_HW_RESET_CONTROL_1_COREr)[pipe]; 3019 if (in_progress & (1 << pipe)) { /* not done yet */ 3020 SOC_IF_ERROR_RETURN 3021 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 3022 if (soc_reg_field_get(unit, reg, rval, DONEf)) { 3023 in_progress ^= 1 << pipe; 3024 } 3025 } 3026 } 3027 if (soc_timeout_check(&to)) { 3028 LOG_WARN(BSL_LS_SOC_COMMON, 3029 (BSL_META_U(unit, 3030 "unit %d : EGR_HW_RESET timeout\n"), unit)); 3031 break; 3032 } 3033 } while (in_progress != 0); 3034 } 3035 3036 rval = 0; 3037 SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval)); 3038 SOC_IF_ERROR_RETURN(WRITE_DLB_ECMP_HW_RESET_CONTROLr(unit, rval)); 3039 rval = SOC_REG_INFO(unit, EGR_HW_RESET_CONTROL_1r).rst_val_lo; 3040 SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1r(unit, rval)); 3041 rval = SOC_REG_INFO(unit, EGR_HW_RESET_CONTROL_1_COREr).rst_val_lo; 3042 SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1_COREr(unit, rval)); 3043 3044 return SOC_E_NONE; 3045 } 3046 3047 3048 STATIC int 3049 _soc_tomahawk3_port_mapping_init(int unit) 3050 { 3051 soc_info_t *si; 3052 int port, phy_port; 3053 /* int num_port, num_phy_port; */ 3054 /* uint32 entry[SOC_MAX_MEM_WORDS];*/ 3055 int i; 3056 uint16 dev_id = 0; 3057 uint8 rev_id = 0; 3058 3059 /* 3060 * 96 entries MMU_CHFC_SYSPORT_MAPPINGm.SYS_PORT 3061 * 256 entries SYS_PORTMAPm.DEVICE_PORT_NUMBER 3062 */ 3063 3064 si = &SOC_INFO(unit); 3065 soc_cm_get_id(unit, &dev_id, &rev_id); 3066 3067 /*sal_memset(&entry, 0, sizeof(entry));*/ 3068 3069 3070 3071 #if 0 3072 num_port = soc_mem_index_count(unit, PORT_TABm) - 1; 3073 num_phy_port = 136; 3074 3075 /* Ingress physical to device port mapping */ 3076 /* Ingress GPP port to device port mapping */ 3077 mem = SYS_PORTMAPm; 3078 sal_memset(&entry, 0, sizeof(sys_portmap_entry_t)); 3079 for (port = 0; port < num_port; port++) { 3080 soc_mem_field32_set(unit, mem, &entry, DEVICE_PORT_NUMBERf, port); 3081 SOC_IF_ERROR_RETURN 3082 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, port, &entry)); 3083 } 3084 3085 /* Ingress device port to GPP port mapping 3086 * PORT_TAB.SRC_SYS_PORT_ID is programmed in the general port config 3087 * init routine _bcm_fb_port_cfg_init() 3088 */ 3089 3090 #endif 3091 3092 if (BCM56963_DEVICE_ID == dev_id) { 3093 const int phy_pbmp_lb_disable[] = { 3094 13,14,15,16,17,18,19,20,25,26,27,28,29,30,31,32,45,46,47,48, 3095 57,58,59,60,61,62,63,64,73,74,75,76,77,78,79,80,89,90,91,92, 3096 93,94,95,96,113,114,115,116,121,122,123,124,125,126,127,128}; 3097 for (i = 0; i < COUNTOF(phy_pbmp_lb_disable); i++) { 3098 phy_port = phy_pbmp_lb_disable[i]; 3099 port = si->port_p2l_mapping[phy_port]; 3100 if (port != -1) { 3101 SOC_PBMP_PORT_ADD(loopback_disable[unit],port); 3102 } 3103 } 3104 } 3105 3106 /* MMU portmapping from TM */ 3107 SOC_IF_ERROR_RETURN(soc_tomahawk3_mmu_port_mapping_init(unit)); 3108 3109 return SOC_E_NONE; 3110 } 3111 3112 extern int 3113 (*_phy_tsce_firmware_set_helper[SOC_MAX_NUM_DEVICES])(int, int, uint8 *, int); 3114 extern int 3115 (*_phy_tscf_firmware_set_helper[SOC_MAX_NUM_DEVICES])(int, int, uint8 *, int); 3116 3117 STATIC int 3118 _soc_tomahawk3_tscx_firmware_set(int unit, int port, uint8 *array, int datalen) 3119 { 3120 soc_mem_t mem = IS_CL_PORT(unit, port) ? 3121 CLPORT_WC_UCMEM_DATAm : XLPORT_WC_UCMEM_DATAm; 3122 soc_reg_t reg = IS_CL_PORT(unit, port) ? 3123 CLPORT_WC_UCMEM_CTRLr : XLPORT_WC_UCMEM_CTRLr; 3124 3125 return soc_warpcore_firmware_set(unit, port, array, datalen, 0, mem, reg); 3126 } 3127 3128 #define TSC_REG_ADDR_TSCID_SET(_phy_reg, _phyad) \ 3129 ((_phy_reg) |= ((_phyad) & 0x1f) << 19) 3130 3131 STATIC int 3132 _soc_tomahawk3_mdio_addr_to_port(uint32 phy_addr) 3133 { 3134 int bus, offset; 3135 3136 /* Must be internal MDIO address */ 3137 if ((phy_addr & 0x80) == 0) { 3138 return 0; 3139 } 3140 3141 /* 3142 * Internal phy address: 3143 * bus 0 phy 1 to 24 are mapped to Physical port 1 to 24 3144 * bus 1 phy 1 to 24 are mapped to Physical port 25 to 48 3145 * bus 2 phy 1 to 24 are mapped to Physical port 49 to 72 3146 * bus 3 phy 1 to 24 are mapped to Physical port 73 to 96 3147 * bus 4 phy 1 to 24 are mapped to Physical port 97 to 120 3148 * bus 5 phy 1 to 24 are mapped to Physical port 121 to 144 3149 * bus 6 phy 1 to 24 are mapped to Physical port 145 to 168 3150 * bus 7 phy 1 to 24 are mapped to Physical port 169 to 192 3151 * bus 8 phy 1 to 24 are mapped to Physical port 193 to 216 3152 * bus 9 phy 1 to 24 are mapped to Physical port 217 to 240 3153 * bus 10 phy 1 to 16 are mapped to Physical port 241 to 256 3154 * bus 11 phy 1 is mapped to Physical port 257 and 3155 * phy 2 is mapped to Physical port 258 3156 */ 3157 bus = PHY_ID_BUS_NUM(phy_addr); 3158 if (bus > 11) { 3159 return 0; 3160 } 3161 switch (bus) { 3162 case 0: offset = 0; 3163 break; 3164 case 1: offset = 24; 3165 break; 3166 case 2: offset = 48; 3167 break; 3168 case 3: offset = 72; 3169 break; 3170 case 4: offset = 96; 3171 break; 3172 case 5: offset = 120; 3173 break; 3174 case 6: offset = 144; 3175 break; 3176 case 7: offset = 168; 3177 break; 3178 case 8: offset = 192; 3179 break; 3180 case 9: offset = 216; 3181 break; 3182 case 10: offset = 240; 3183 break; 3184 case 11: offset = 256; 3185 /* Management ports take up the first 2 ports on the 4x10G in TH3 */ 3186 if ((phy_addr & 0x1f) > 2) { 3187 return 0; 3188 } 3189 break; 3190 default: 3191 return 0; 3192 } 3193 3194 return (phy_addr & 0x1f) + offset; 3195 } 3196 3197 STATIC int 3198 _soc_tomahawk3_tscx_reg_read(int unit, uint32 phy_addr, 3199 uint32 phy_reg, uint32 *phy_data) 3200 { 3201 int rv, blk, port; 3202 int phy_port = _soc_tomahawk3_mdio_addr_to_port(phy_addr); 3203 3204 port = SOC_INFO(unit).port_p2l_mapping[phy_port]; 3205 blk = SOC_PORT_BLOCK(unit, phy_port); 3206 LOG_INFO(BSL_LS_SOC_MII, 3207 (BSL_META_U(unit, 3208 "soc_tomahawk3_tscx_reg_read[%d]: %d/%d/%d/%d\n"), 3209 unit, phy_addr, phy_port, port, blk)); 3210 rv = soc_sbus_tsc_reg_read(unit, port, blk, phy_addr, 3211 phy_reg, phy_data); 3212 return rv; 3213 } 3214 3215 STATIC int 3216 _soc_tomahawk3_tscx_reg_write(int unit, uint32 phy_addr, 3217 uint32 phy_reg, uint32 phy_data) 3218 { 3219 int rv, blk, port; 3220 int phy_port = _soc_tomahawk3_mdio_addr_to_port(phy_addr); 3221 3222 port = SOC_INFO(unit).port_p2l_mapping[phy_port]; 3223 blk = SOC_PORT_BLOCK(unit, phy_port); 3224 LOG_INFO(BSL_LS_SOC_MII, 3225 (BSL_META_U(unit, 3226 "soc_tomahawk3_tscx_reg_write[%d]: %d/%d/%d/%d\n"), 3227 unit, phy_addr, phy_port, port, blk)); 3228 rv = soc_sbus_tsc_reg_write(unit, port, blk, phy_addr, 3229 phy_reg, phy_data); 3230 return rv; 3231 } 3232 3233 #ifdef BCM_CMICX_SUPPORT 3234 STATIC int 3235 _soc_th3_ledup_init(int unit) 3236 { 3237 soc_info_t *si = &SOC_INFO(unit); 3238 int freq; 3239 uint32 rval, clk_half_period, refresh_period; 3240 3241 /* freq in KHz */ 3242 freq = (si->frequency) * 1000; 3243 3244 /* For LED refresh period = 33 ms (about 30Hz) */ 3245 3246 /* refresh period 3247 = (required refresh period in sec)*(switch clock frequency in Hz) 3248 */ 3249 refresh_period = (freq * 33); 3250 3251 rval = 0; 3252 soc_reg_field_set(unit, U0_LED_REFRESH_CTRLr, &rval, 3253 REFRESH_CYCLE_PERIODf, refresh_period); 3254 3255 SOC_IF_ERROR_RETURN(WRITE_U0_LED_REFRESH_CTRLr(unit, rval)); 3256 3257 /* For LED clock period */ 3258 /* LEDCLK_HALF_PERIOD 3259 = [(required LED clock period in sec)/2]*(M0SS clock frequency in Hz) 3260 3261 Where M0SS freqency is 858MHz and 3262 Typical LED clock period is 200ns(5MHz) = 2*10^-7 3263 */ 3264 freq = 858 * 1000000; 3265 clk_half_period = (freq + 2500000) / 5000000; 3266 clk_half_period = clk_half_period / 2; 3267 3268 rval = 0; 3269 soc_reg_field_set(unit, U0_LED_CLK_DIV_CTRLr, &rval, 3270 LEDCLK_HALF_PERIODf, clk_half_period); 3271 3272 SOC_IF_ERROR_RETURN(WRITE_U0_LED_CLK_DIV_CTRLr(unit, rval)); 3273 3274 3275 SOC_IF_ERROR_RETURN(READ_U0_LED_ACCU_CTRLr(unit, &rval)); 3276 soc_reg_field_set(unit, U0_LED_ACCU_CTRLr, &rval, 3277 LAST_PORTf, 0); 3278 SOC_IF_ERROR_RETURN(WRITE_U0_LED_ACCU_CTRLr(unit, rval)); 3279 3280 /* To initialize M0s for LED or Firmware Link Scan*/ 3281 if (soc_feature(unit, soc_feature_cmicx) && !(SAL_BOOT_PLISIM || SAL_BOOT_BCMSIM)) { 3282 SOC_IF_ERROR_RETURN(soc_iproc_m0_init(unit)); 3283 } 3284 3285 return SOC_E_NONE; 3286 } 3287 #endif /* BCM_CMICX_SUPPORT */ 3288 3289 STATIC int 3290 _soc_tomahawk3_management_port_init (int unit) { 3291 3292 int port, fval; 3293 uint32 rval; 3294 soc_info_t *si=&SOC_INFO(unit); 3295 3296 SOC_PBMP_ITER(si->management_pbm, port) { 3297 /* Assert XLPORT soft reset */ 3298 rval = 0; 3299 if (si->port_p2l_mapping[257] != -1) { /* management port 0 */ 3300 soc_reg_field_set(unit, XLPORT_SOFT_RESETr, &rval, PORT0f, 1); 3301 } 3302 if (si->port_p2l_mapping[258] != -1) { /* management port 1 */ 3303 soc_reg_field_set(unit, XLPORT_SOFT_RESETr, &rval, PORT2f, 1); 3304 } 3305 SOC_IF_ERROR_RETURN(WRITE_XLPORT_SOFT_RESETr(unit, port, rval)); 3306 3307 /* Set port mode based upon lanes config */ 3308 rval = 0; 3309 /* Note - this is a special h/w requirement to ONLY use dual lane mode */ 3310 fval = 3; 3311 soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, XPORT0_CORE_PORT_MODEf, 3312 fval); 3313 soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, XPORT0_PHY_PORT_MODEf, 3314 fval); 3315 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MODE_REGr(unit, port, rval)); 3316 3317 /* De-assert XLPORT soft reset */ 3318 SOC_IF_ERROR_RETURN(WRITE_XLPORT_SOFT_RESETr(unit, port, 0)); 3319 3320 /* Enable XLPORT */ 3321 rval = 0; 3322 if (si->port_p2l_mapping[257] != -1) { /* management port 0 */ 3323 soc_reg_field_set(unit, XLPORT_ENABLE_REGr, &rval, PORT0f, 1); 3324 } 3325 if (si->port_p2l_mapping[258] != -1) { /* management port 1 */ 3326 soc_reg_field_set(unit, XLPORT_ENABLE_REGr, &rval, PORT2f, 1); 3327 } 3328 SOC_IF_ERROR_RETURN(WRITE_XLPORT_ENABLE_REGr(unit, port, rval)); 3329 3330 rval = 0; 3331 soc_reg_field_set(unit, XLPORT_FLOW_CONTROL_CONFIGr, &rval, 3332 MERGE_MODE_ENf, 1); 3333 SOC_IF_ERROR_RETURN 3334 (WRITE_XLPORT_FLOW_CONTROL_CONFIGr(unit, port, rval)); 3335 } 3336 3337 return SOC_E_NONE; 3338 } 3339 3340 /* 3341 * Function: 3342 * _soc_tomahawk3_l2mcast_size_set 3343 * Purpose: 3344 * This function programs L2 multicast table size in hardware and sets 3345 * up soc_control structure's mc_size field value 3346 * Parameters: 3347 * unit - (IN) Unit number 3348 * mc_size - (IN) Size of L2 multicast table. Cannot exceed hardware 3349 * L2 multicast table size 3350 * Returns: 3351 * Nothing 3352 * Note: 3353 * TH3 has separate L2 and L3 multicast tables (as in TD3). Hardware 3354 * may not use value programmed in MC_CONTROL_5r's field. 3355 */ 3356 STATIC int 3357 _soc_tomahawk3_l2mcast_size_set(int unit, int mc_size) 3358 { 3359 uint32 mc_ctrl; 3360 soc_control_t *soc = SOC_CONTROL(unit); 3361 int l2mc_table_size = soc_mem_index_count(unit, L2MCm); 3362 3363 if (mc_size > l2mc_table_size) { 3364 return SOC_E_PARAM; 3365 } 3366 3367 SOC_IF_ERROR_RETURN(READ_MC_CONTROL_5r(unit, &mc_ctrl)); 3368 soc_reg_field_set(unit, MC_CONTROL_5r, &mc_ctrl, 3369 SHARED_TABLE_L2MC_SIZEf, mc_size); 3370 SOC_IF_ERROR_RETURN(WRITE_MC_CONTROL_5r(unit, mc_ctrl)); 3371 3372 soc->mcast_size = mc_size; 3373 3374 return SOC_E_NONE; 3375 } 3376 3377 /* 3378 * Function: 3379 * _soc_tomahawk3_ipmc_size_set 3380 * Purpose: 3381 * This function programs IPMC table size in hardware and sets 3382 * up soc_control structure's mc_size field value 3383 * Parameters: 3384 * unit - (IN) Unit number 3385 * mc_size - (IN) Size of IPMC table. Cannot exceed hardware 3386 * IPMC size 3387 * Returns: 3388 * Nothing 3389 * Note: 3390 * TH3 has separate L2 and L3 multicast tables (as in TD3). Hardware 3391 * may not use value programmed in MC_CONTROL_5r's field. 3392 */ 3393 STATIC int 3394 _soc_tomahawk3_ipmc_size_set(int unit, int mc_size) 3395 { 3396 uint32 mc_ctrl; 3397 soc_control_t *soc = SOC_CONTROL(unit); 3398 int ipmc_table_size = soc_mem_index_count(unit, L3_IPMCm); 3399 3400 if (mc_size > ipmc_table_size) { 3401 return SOC_E_PARAM; 3402 } 3403 3404 SOC_IF_ERROR_RETURN(READ_MC_CONTROL_5r(unit, &mc_ctrl)); 3405 soc_reg_field_set(unit, MC_CONTROL_5r, &mc_ctrl, 3406 SHARED_TABLE_IPMC_SIZEf, mc_size); 3407 SOC_IF_ERROR_RETURN(WRITE_MC_CONTROL_5r(unit, mc_ctrl)); 3408 3409 soc->ipmc_size = mc_size; 3410 3411 return SOC_E_NONE; 3412 } 3413 3414 STATIC int 3415 _soc_tomahawk3_ipep_default_init (int unit) 3416 { 3417 uint32 rval; 3418 int index, port; 3419 int count, sub_sel, offset; 3420 uint32 entry[SOC_MAX_MEM_WORDS]; 3421 int ecmp_mode = 0; 3422 soc_pbmp_t pbmp; 3423 uint64 rval64; 3424 static int rtag7_field_width[] = { 16, 16, 4, 16, 8, 8, 16, 16 }; 3425 3426 3427 SOC_IF_ERROR_RETURN(READ_ING_CONFIG_64r(unit, &rval64)); 3428 soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64, 3429 L3SRC_HIT_ENABLEf, 1); 3430 soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64, 3431 L2DST_HIT_ENABLEf, 1); 3432 soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64, 3433 APPLY_EGR_MASK_ON_L2f, 1); 3434 soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64, 3435 APPLY_EGR_MASK_ON_L3f, 1); 3436 soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64, 3437 ARP_RARP_TO_FPf, 0x3); /* enable both ARP & RARP */ 3438 soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64, 3439 ARP_VALIDATION_ENf, 1); 3440 if (soc_feature(unit, soc_feature_port_lag_failover)) { 3441 soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64, 3442 IGNORE_HG_HDR_LAG_FAILOVERf, 0); 3443 } else { 3444 soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64, 3445 IGNORE_HG_HDR_LAG_FAILOVERf, 1); 3446 } 3447 SOC_IF_ERROR_RETURN(WRITE_ING_CONFIG_64r(unit, rval64)); 3448 3449 rval = 0; 3450 /* Enable pri/cfi remarking on egress ports. */ 3451 soc_reg_field_set(unit, EGR_VLAN_CONTROL_1r, &rval, REMARK_OUTER_DOT1Pf, 3452 1); 3453 PBMP_ALL_ITER(unit, port) { 3454 SOC_IF_ERROR_RETURN(WRITE_EGR_VLAN_CONTROL_1r(unit, port, rval)); 3455 } 3456 3457 SOC_PBMP_ASSIGN(pbmp, PBMP_ALL(unit)); 3458 SOC_PBMP_REMOVE(pbmp, PBMP_LB(unit)); 3459 SOC_IF_ERROR_RETURN(soc_mem_read(unit, ING_EN_EFILTER_BITMAPm, 3460 MEM_BLOCK_ANY, 0, &entry)); 3461 soc_mem_pbmp_field_set(unit, ING_EN_EFILTER_BITMAPm, &entry, BITMAPf, 3462 &pbmp); 3463 SOC_IF_ERROR_RETURN(soc_mem_write(unit, ING_EN_EFILTER_BITMAPm, 3464 MEM_BLOCK_ANY, 0, &entry)); 3465 3466 3467 /* Multicast range initialization */ 3468 SOC_IF_ERROR_RETURN 3469 (_soc_tomahawk3_l2mcast_size_set(unit, soc_property_get(unit, 3470 spn_MULTICAST_L2_RANGE, soc_mem_index_count(unit, L2MCm)))); 3471 SOC_IF_ERROR_RETURN 3472 (_soc_tomahawk3_ipmc_size_set(unit, soc_property_get(unit, 3473 spn_MULTICAST_L3_RANGE, soc_mem_index_count(unit, L3_IPMCm)))); 3474 3475 /* Check if Hierarchical ECMP mode is set */ 3476 rval = 0; 3477 SOC_IF_ERROR_RETURN(READ_ECMP_CONFIGr(unit, &rval)); 3478 3479 if (soc_property_get(unit, spn_L3_ECMP_LEVELS, 1) == 2) { 3480 /* HW encoding for Hierarchical ECMP mode is 1.*/ 3481 ecmp_mode = 1; 3482 soc_reg_field_set(unit, ECMP_CONFIGr, &rval, ECMP_MODEf, ecmp_mode); 3483 SOC_IF_ERROR_RETURN(WRITE_ECMP_CONFIGr(unit, rval)); 3484 } 3485 /* Populate and enable RTAG7 Macro flow offset table */ 3486 if (soc_mem_is_valid(unit, RTAG7_FLOW_BASED_HASHm)) { 3487 count = soc_mem_index_max(unit, RTAG7_FLOW_BASED_HASHm); 3488 sal_memset(entry, 0, sizeof(rtag7_flow_based_hash_entry_t)); 3489 for (index = 0; index < count; ) { 3490 for (sub_sel = 0; sub_sel < 8 && index < count; sub_sel++) { 3491 for (offset = 0; 3492 offset < rtag7_field_width[sub_sel] && index < count; 3493 offset++) { 3494 if (ecmp_mode == 1) { 3495 soc_mem_field32_set(unit, RTAG7_FLOW_BASED_HASHm, &entry, 3496 SUB_SEL_ECMP_LEVEL2f, sub_sel); 3497 soc_mem_field32_set(unit, RTAG7_FLOW_BASED_HASHm, &entry, 3498 OFFSET_ECMP_LEVEL2f, offset); 3499 } 3500 soc_mem_field32_set(unit, RTAG7_FLOW_BASED_HASHm, &entry, 3501 SUB_SEL_ECMPf, sub_sel); 3502 soc_mem_field32_set(unit, RTAG7_FLOW_BASED_HASHm, &entry, 3503 OFFSET_ECMPf, offset); 3504 SOC_IF_ERROR_RETURN 3505 (soc_mem_write(unit, RTAG7_FLOW_BASED_HASHm, 3506 MEM_BLOCK_ANY, index, &entry)); 3507 index++; 3508 } 3509 } 3510 } 3511 rval = 0; 3512 soc_reg_field_set(unit, RTAG7_HASH_SELr, &rval, USE_FLOW_SEL_ECMPf, 1); 3513 3514 SOC_IF_ERROR_RETURN(WRITE_RTAG7_HASH_SELr(unit, rval)); 3515 } 3516 return SOC_E_NONE; 3517 } 3518 3519 STATIC int 3520 _soc_tomahawk3_cpu_lb_portbitmap_set (int unit) 3521 { 3522 uint32 entry[SOC_MAX_MEM_WORDS]; 3523 3524 sal_memset(entry, 0, sizeof(cpu_pbm_entry_t)); 3525 soc_mem_pbmp_field_set(unit, CPU_PBMm, entry, BITMAPf, &PBMP_CMIC(unit)); 3526 SOC_IF_ERROR_RETURN 3527 (soc_mem_write(unit, CPU_PBMm, MEM_BLOCK_ALL, 0, entry)); 3528 3529 return SOC_E_NONE; 3530 } 3531 3532 int 3533 soc_tomahawk3_clear_mmu_counters(int unit) { 3534 /* Refer to SBus BASE TYPE info structure in REGSFILE */ 3535 #define SOC_MMU_BASE_TYPE_IPORT 0 3536 #define SOC_MMU_BASE_TYPE_EPORT 1 3537 #define SOC_MMU_BASE_TYPE_IPIPE 2 3538 #define SOC_MMU_BASE_TYPE_EPIPE 3 3539 #define SOC_MMU_BASE_TYPE_CHIP 4 3540 #define SOC_MMU_BASE_TYPE_ITM 5 3541 soc_info_t *si; 3542 int i, j, use_base_type_views, base_type, index, num_views; 3543 uint32 entry[SOC_MAX_MEM_WORDS], valid_views_bmp = 0; 3544 soc_mem_t mem; 3545 static const struct { 3546 soc_mem_t mem; /* base view */ 3547 int use_base_type_views; /* 1 means use itm/sc/etc views */ 3548 int index; /* -1 means clear entire mem */ 3549 int val; /* clear with assigned value */ 3550 } mem_list[] = { 3551 { MMU_THDO_QUEUE_DROP_COUNTm, 1, -1, 0 }, 3552 { MMU_THDO_PORT_DROP_COUNT_MCm, 1, -1, 0 }, 3553 { MMU_THDO_PORT_DROP_COUNT_UCm, 1, -1, 0 }, 3554 { MMU_THDO_COUNTER_QUEUEm, 1, -1, 0 }, 3555 { MMU_THDI_PORT_PG_MIN_COUNTERm, 1, -1, 0 }, 3556 { MMU_THDI_PORT_PG_SHARED_COUNTERm, 1, -1, 0 }, 3557 { MMU_THDI_PORT_PG_HDRM_COUNTERm, 1, -1, 0 }, 3558 { MMU_THDI_PORTSP_COUNTERm, 1, -1, 0 }, 3559 { MMU_THDO_SRC_PORT_DROP_COUNTm, 1, -1, 0 }, 3560 { INVALIDm, 0, -1, 0} 3561 }; 3562 3563 si = &SOC_INFO(unit); 3564 3565 /* clear memories */ 3566 for (i = 0; mem_list[i].mem != INVALIDm; i++) { 3567 mem = mem_list[i].mem; 3568 index = mem_list[i].index; 3569 use_base_type_views = mem_list[i].use_base_type_views; 3570 if (use_base_type_views) { 3571 base_type = soc_tomahawk3_mem_basetype_get(unit, mem); 3572 switch (base_type) { 3573 case SOC_MMU_BASE_TYPE_ITM: 3574 num_views = NUM_ITM(unit); 3575 valid_views_bmp = si->itm_map; 3576 break; 3577 case SOC_MMU_BASE_TYPE_IPIPE: 3578 case SOC_MMU_BASE_TYPE_EPIPE: 3579 num_views = NUM_PIPE(unit); 3580 soc_tomahawk3_pipe_map_get(unit, &valid_views_bmp); 3581 break; 3582 default: 3583 num_views = -1; /* not supported */ 3584 break; 3585 } 3586 if (num_views < 0) { 3587 LOG_ERROR(BSL_LS_SOC_COMMON, 3588 (BSL_META_U(unit, 3589 "mmu_mem %s, base_type %d will not be" 3590 "cleared \n"), 3591 SOC_MEM_NAME(unit,mem), base_type)); 3592 continue; 3593 } 3594 } else { 3595 num_views = 0; /* dont_care */ 3596 } 3597 3598 sal_memset(entry, mem_list[i].val, 3599 soc_mem_entry_words(unit, mem) * sizeof(uint32)); 3600 if (use_base_type_views) { 3601 for (j = 0; j < num_views; j++) { 3602 if((valid_views_bmp & (1 << j)) == 0) { 3603 continue; 3604 } 3605 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3606 (BSL_META_U(unit, 3607 "mmu_mem %s, index %d will be " 3608 "cleared \n"), 3609 SOC_MEM_NAME(unit, SOC_MEM_UNIQUE_ACC(unit, mem)[j]), 3610 index)); 3611 if (index >= 0) { 3612 SOC_IF_ERROR_RETURN 3613 (soc_mem_write(unit, 3614 SOC_MEM_UNIQUE_ACC(unit, mem)[j], 3615 MEM_BLOCK_ALL, index, entry)); 3616 } else { 3617 SOC_IF_ERROR_RETURN 3618 (soc_mem_clear(unit, 3619 SOC_MEM_UNIQUE_ACC(unit, mem)[j], 3620 COPYNO_ALL, TRUE)); 3621 } 3622 } 3623 } else { 3624 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3625 (BSL_META_U(unit, 3626 "mmu_mem %s, index %d will be " 3627 "cleared \n"), 3628 SOC_MEM_NAME(unit, mem), index)); 3629 if (index >= 0) { 3630 SOC_IF_ERROR_RETURN 3631 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, 3632 entry)); 3633 } else { 3634 SOC_IF_ERROR_RETURN 3635 (soc_mem_clear(unit, mem, COPYNO_ALL, TRUE)); 3636 } 3637 } 3638 } 3639 return SOC_E_NONE; 3640 } 3641 3642 STATIC int 3643 _soc_tomahawk3_port_mib_reset (int unit) 3644 { 3645 uint32 rval=0; 3646 int lane, lport, port, phy_port_base, block_info_idx; 3647 3648 soc_info_t *si = &SOC_INFO(unit); 3649 3650 /* Reset CDMIB counters */ 3651 rval = 0; 3652 soc_reg_field_set(unit, CDMAC_MIB_COUNTER_CTRLr, &rval, CNT_CLEARf, 1); 3653 SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CDPORT) { 3654 port = SOC_BLOCK_PORT(unit, block_info_idx); 3655 phy_port_base = SOC_TH3_PORT_BLOCK_BASE_PORT(port); 3656 for (lane = 0; lane < _TH3_PORTS_PER_PBLK; lane++) { 3657 lport = si->port_p2l_mapping[phy_port_base + lane]; 3658 if (lport != -1) { 3659 SOC_IF_ERROR_RETURN(WRITE_CDMAC_MIB_COUNTER_CTRLr(unit, lport, rval)); 3660 } 3661 } 3662 } 3663 sal_usleep(1); 3664 SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CDPORT) { 3665 port = SOC_BLOCK_PORT(unit, block_info_idx); 3666 phy_port_base = SOC_TH3_PORT_BLOCK_BASE_PORT(port); 3667 for (lane = 0; lane < _TH3_PORTS_PER_PBLK; lane++) { 3668 lport = si->port_p2l_mapping[phy_port_base + lane]; 3669 if (lport != -1) { 3670 SOC_IF_ERROR_RETURN(WRITE_CDMAC_MIB_COUNTER_CTRLr(unit, lport, 0)); 3671 } 3672 } 3673 } 3674 3675 /* Reset XLMIB counters */ 3676 rval = 0; 3677 SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_XLPORT) { 3678 port = SOC_BLOCK_PORT(unit, block_info_idx); 3679 soc_reg_field_set(unit, XLPORT_MIB_RESETr, &rval, CLR_CNTf, 0xf); 3680 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MIB_RESETr(unit, port, rval)); 3681 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MIB_RESETr(unit, port, 0)); 3682 } 3683 return SOC_E_NONE; 3684 } 3685 3686 STATIC int 3687 _soc_tomahawk3_hg_lb_port_type_set (int unit) 3688 { 3689 uint32 entry[SOC_MAX_MEM_WORDS]; 3690 soc_info_t *si = &SOC_INFO(unit); 3691 int port; 3692 3693 sal_memset(entry, 0, sizeof(egr_ing_port_entry_t)); 3694 soc_mem_field32_set(unit, EGR_ING_PORTm, entry, PORT_TYPEf, 1); 3695 PBMP_HG_ITER(unit, port) { 3696 SOC_IF_ERROR_RETURN 3697 (soc_mem_write(unit, EGR_ING_PORTm, MEM_BLOCK_ALL, port, entry)); 3698 } 3699 SOC_IF_ERROR_RETURN 3700 (soc_mem_write(unit, EGR_ING_PORTm, MEM_BLOCK_ALL, si->cpu_hg_index, 3701 entry)); 3702 soc_mem_field32_set(unit, EGR_ING_PORTm, entry, PORT_TYPEf, 2); 3703 PBMP_LB_ITER(unit, port) { 3704 SOC_IF_ERROR_RETURN 3705 (soc_mem_write(unit, EGR_ING_PORTm, MEM_BLOCK_ALL, port, entry)); 3706 } 3707 return SOC_E_NONE; 3708 } 3709 3710 STATIC int 3711 _soc_tomahawk3_cmic_mdio_freq_config (int unit) 3712 { 3713 int int_divisor, ext_divisor, delay; 3714 /* spn_RATE_EXT_MDIO_DIVIDEND and spn_RATE_INT_MDIO_DIVIDEND are 3715 * NOT applicable to TH3. 3716 */ 3717 3718 /* MDIO Clock Frquency for TH3 is 250 MHz 3719 * Set external MDIO freq to around 5 MHz 3720 * Hence divisor is set to 50 3721 */ 3722 3723 ext_divisor = soc_property_get(unit, spn_RATE_EXT_MDIO_DIVISOR, 50); 3724 3725 /* 3726 * Set internal MDIO freq to around 10 MHz 3727 * Valid range is from 2.5MHz to 20MHz 3728 * Hence divisor is set to 25 3729 */ 3730 int_divisor = soc_property_get(unit, spn_RATE_INT_MDIO_DIVISOR, 25); 3731 3732 delay = soc_property_get(unit, spn_MDIO_OUTPUT_DELAY, -1); 3733 if (delay < 0 || delay > 255) { 3734 /* valid range for delay is 0-255 3735 * if outside this range, skip configuring delay 3736 */ 3737 delay = -1; 3738 } 3739 3740 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3741 (BSL_META_U(unit, 3742 "Config MIIM rings with int divisor %d, ext divisor %d, delay %d\n"), 3743 int_divisor, ext_divisor, delay)); 3744 3745 soc_cmicx_miim_divider_set_all(unit, int_divisor, ext_divisor, delay); 3746 3747 return SOC_E_NONE; 3748 } 3749 3750 /* 3751 * Function: 3752 * soc_th3_speed_class_validate 3753 * Purpose: 3754 * Check speed classes and ensure 4 speed max for device 3755 * Parameters: 3756 * unit - (IN) Unit number. 3757 * Returns: 3758 * SOC_E_XXX 3759 * Note: 3760 * This function is called at early stage of initialization for 3761 * port configuration check. 3762 */ 3763 int 3764 soc_th3_speed_class_validate(int unit) 3765 { 3766 soc_info_t *si = &SOC_INFO(unit); 3767 int port, speed; 3768 uint32 speed_mask, count; 3769 int speed_400 = 0, speed_200 = 0; 3770 3771 speed_mask = 0; 3772 PBMP_PORT_ITER(unit, port) { 3773 if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, port) || 3774 IS_MANAGEMENT_PORT(unit, port) || IS_CPU_PORT(unit, port) || 3775 IS_LB_PORT(unit, port)) { 3776 continue; 3777 } 3778 3779 /* No HG, so just take speed rather than converting from HG to eth */ 3780 speed = si->port_speed_max[port]; 3781 3782 /* 400G and 200G aren't part of SOC_PA_SPEED, so need to be counted 3783 * differently */ 3784 if (speed == 400000) { 3785 speed_400 = 1; 3786 } else if (speed == 200000) { 3787 speed_200 = 1; 3788 } else { 3789 speed_mask |= SOC_PA_SPEED(speed); 3790 } 3791 } 3792 3793 count = _shr_popcount(speed_mask); 3794 3795 /* Add 400G and 200G if they exist */ 3796 count += speed_400; 3797 count += speed_200; 3798 3799 if (count > 7) { 3800 LOG_ERROR(BSL_LS_BCM_COMMON, 3801 (BSL_META_U(unit, 3802 "No port configurations with more than 7 port " 3803 "speed classes are supported.\n"))); 3804 return SOC_E_CONFIG; 3805 } 3806 3807 return SOC_E_NONE; 3808 } 3809 3810 STATIC void 3811 _soc_tomahawk3_ser_hw_clear(int unit) 3812 { 3813 int i; 3814 uint32 entry[SOC_MAX_MEM_WORDS]; 3815 uint32 data = 0; 3816 soc_reg_t ep_ser_fifo[] = { 3817 EGR_SER_FIFO_CTRL_PIPE0r, 3818 EGR_SER_FIFO_CTRL_PIPE1r, 3819 EGR_SER_FIFO_CTRL_PIPE2r, 3820 EGR_SER_FIFO_CTRL_PIPE3r, 3821 EGR_SER_FIFO_CTRL_PIPE4r, 3822 EGR_SER_FIFO_CTRL_PIPE5r, 3823 EGR_SER_FIFO_CTRL_PIPE6r, 3824 EGR_SER_FIFO_CTRL_PIPE7r 3825 }; 3826 soc_reg_t ep_ser_fifo_2[] = { 3827 EGR_SER_FIFO_CTRL_2_PIPE0r, 3828 EGR_SER_FIFO_CTRL_2_PIPE1r, 3829 EGR_SER_FIFO_CTRL_2_PIPE2r, 3830 EGR_SER_FIFO_CTRL_2_PIPE3r, 3831 EGR_SER_FIFO_CTRL_2_PIPE4r, 3832 EGR_SER_FIFO_CTRL_2_PIPE5r, 3833 EGR_SER_FIFO_CTRL_2_PIPE6r, 3834 EGR_SER_FIFO_CTRL_2_PIPE7r 3835 }; 3836 soc_mem_t mmu_eb_fifo[] = { 3837 MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE0m, 3838 MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE1m, 3839 MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE2m, 3840 MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE3m, 3841 MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE4m, 3842 MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE5m, 3843 MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE6m, 3844 MMU_EBCFG_MEM_FAIL_ADDR_64_PIPE7m 3845 }; 3846 uint32 pipe_map; 3847 3848 soc_tomahawk3_pipe_map_get(unit, &pipe_map); 3849 /* clear mmu eb ser fifo */ 3850 for (i = 0; i < NUM_EB(unit); i++) { 3851 (void)soc_mem_pop(unit, mmu_eb_fifo[i], MEM_BLOCK_ANY, entry); 3852 } 3853 3854 /* clear EP ser fifo */ 3855 for (i = 0; i < NUM_PIPE(unit); i++) { 3856 if (!(pipe_map & (1 << i))) { 3857 continue; 3858 } 3859 (void)soc_reg_field32_modify(unit, ep_ser_fifo[i], REG_PORT_ANY, 3860 FIFO_RESETf, 1); 3861 (void)soc_reg_field32_modify(unit, ep_ser_fifo_2[i], REG_PORT_ANY, 3862 FIFO_RESETf, 1); 3863 (void)soc_reg_field32_modify(unit, ep_ser_fifo[i], REG_PORT_ANY, 3864 FIFO_RESETf, 0); 3865 (void)soc_reg_field32_modify(unit, ep_ser_fifo_2[i], REG_PORT_ANY, 3866 FIFO_RESETf, 0); 3867 } 3868 3869 /* clear MEM_PAR_ERR_INT_STAT bit in mmu EB interrupt status register, 3870 * write 1 to clear 3871 */ 3872 for (i = 0; i < NUM_PIPE(unit); i ++) { 3873 if (!(pipe_map & (1 << i))) { 3874 continue; 3875 } 3876 (void)soc_tomahawk3_eb_reg32_get(unit, MMU_EBCFG_CPU_INT_STATr, i, i, 0, &data); 3877 if(soc_reg_field_get(unit, MMU_EBCFG_CPU_INT_STATr, data, MEM_PAR_ERR_INT_STATf)) { 3878 soc_tomahawk3_eb_reg32_set(unit, MMU_EBCFG_CPU_INT_STATr, i, i, 0, 0x1); 3879 } 3880 soc_tomahawk3_eb_reg32_set(unit, MMU_EBCFG_MEM_FAIL_INT_CTRr, i, i, 0, 0x0); 3881 } 3882 /* clear EBCFGx_INT_STAT bit in GLB interrupt status register, write 1 to clear */ 3883 (void)soc_reg32_set(unit, MMU_GLBCFG_CPU_INT_STATr, REG_PORT_ANY, 0, 0x1fe); 3884 3885 } 3886 3887 /* 3888 * Function: 3889 * soc_th3_process_pm_intr 3890 * Description: 3891 * Tomahawk3 specific DPC function to service PM interrupts 3892 * Parameters: 3893 * unit_vp - Device number 3894 * d1 - IRQ4 mask 3895 * d2 - IRQ4 number (to distinguish between 3896 * different types of interrupts). 3897 */ 3898 static void 3899 soc_th3_process_pm_intr(void *unit_vp, void *d1, 3900 void *d2, void *d3, void *d4) 3901 { 3902 3903 int unit = PTR_TO_INT(unit_vp); 3904 int cmic_bit_num = PTR_TO_INT(d1); 3905 int cmic_reg_type = PTR_TO_INT(d2); 3906 int pm_id = -1; /* invalid id */ 3907 int rv = SOC_E_NONE; 3908 portmod_ecc_intr_info_t ecc_intr_info; 3909 3910 /* 3911 * Get the SW Port Macro Id from the hw 3912 * Port Macro Id(mapped to core num) 3913 */ 3914 rv = portmod_core_pm_id_get(unit, cmic_bit_num - 1, &pm_id); 3915 3916 if (rv != SOC_E_NONE) { 3917 LOG_ERROR(BSL_LS_SOC_COMMON, 3918 (BSL_META_U(unit, "soc_th3_process_pm_intr sw PM id for " 3919 "hw PM Id - %d not found!!\n" 3920 "Disabling unhandled interrupt(s)"), 3921 (cmic_bit_num - 1))); 3922 /* Disable the specific PM interrupt */ 3923 (void) soc_ser_top_intr_reg_enable(unit, cmic_reg_type, 3924 (cmic_bit_num - 1), 0); 3925 return; 3926 } 3927 3928 sal_memset(&ecc_intr_info, 0, sizeof(portmod_ecc_intr_info_t)); 3929 3930 /* Process interrupts for the specific port Macro */ 3931 rv = portmod_pm_interrupt_process(unit, pm_id, &ecc_intr_info); 3932 3933 if (rv != SOC_E_NONE) { 3934 LOG_ERROR(BSL_LS_SOC_COMMON, 3935 (BSL_META_U(unit, "soc_th3_process_pm_intr - pm_id(%d)" 3936 "Disabling unhandled interrupt(s)"), pm_id)); 3937 /* Disable the specific PM interrupt */ 3938 (void) soc_ser_top_intr_reg_enable(unit, cmic_reg_type, 3939 (cmic_bit_num - 1), 0); 3940 return; 3941 } 3942 3943 /* Report ECC errors */ 3944 if (ecc_intr_info.ecc_num_bits_err != PORTMOD_PM_ECC_NO_ERR) { 3945 3946 soc_event_generate(unit, SOC_SWITCH_EVENT_DATA_ERROR_PARITY, 3947 SOC_SWITCH_EVENT_DATA_ERROR_ECC, 0, 0); 3948 3949 if (ecc_intr_info.ecc_num_bits_err & PORTMOD_PM_ECC_1B_ERR) { 3950 3951 soc_event_generate(unit, SOC_SWITCH_EVENT_DATA_ERROR_PARITY, 3952 SOC_SWITCH_EVENT_DATA_ERROR_AUTO_CORRECTED, 0, 0); 3953 3954 LOG_ERROR(BSL_LS_SOC_COMMON, 3955 (BSL_META_U(unit, 3956 "\n%s - \n\r" 3957 "single-bit ECC error on port %s\n"), 3958 ecc_intr_info.mem_str, 3959 SOC_PORT_NAME(unit, ecc_intr_info.port))); 3960 3961 } else if (ecc_intr_info.ecc_num_bits_err & PORTMOD_PM_ECC_2B_ERR) { 3962 3963 soc_event_generate(unit, SOC_SWITCH_EVENT_DATA_ERROR_PARITY, 3964 SOC_SWITCH_EVENT_DATA_ERROR_UNCORRECTABLE, 0, 0); 3965 3966 LOG_ERROR(BSL_LS_SOC_COMMON, 3967 (BSL_META_U(unit, 3968 "\n%s - \n\r" 3969 "double-bit ECC error on port %s\n"), 3970 ecc_intr_info.mem_str, 3971 SOC_PORT_NAME(unit, ecc_intr_info.port))); 3972 3973 } else if (ecc_intr_info.ecc_num_bits_err & PORTMOD_PM_ECC_MULTIB_ERR) { 3974 3975 soc_event_generate(unit, SOC_SWITCH_EVENT_DATA_ERROR_PARITY, 3976 SOC_SWITCH_EVENT_DATA_ERROR_UNCORRECTABLE, 0, 0); 3977 3978 LOG_ERROR(BSL_LS_SOC_COMMON, 3979 (BSL_META_U(unit, 3980 "\n%s - \n\r" 3981 "multi-bit ECC error on port %s\n"), 3982 ecc_intr_info.mem_str, 3983 SOC_PORT_NAME(unit, ecc_intr_info.port))); 3984 3985 } else { 3986 LOG_ERROR(BSL_LS_SOC_COMMON, 3987 (BSL_META_U(unit, "ECC interrupt info\n" 3988 "m - %s, ecc_num_bits - %d, addr %x - error - %s\n"), 3989 SOC_MEM_NAME(unit, ecc_intr_info.err_mem_info), 3990 ecc_intr_info.ecc_num_bits_err, 3991 ecc_intr_info.err_addr, ecc_intr_info.mem_str)); 3992 } 3993 } 3994 3995 /* Enable the specific PM interrupt */ 3996 (void) soc_ser_top_intr_reg_enable(unit, cmic_reg_type, 3997 (cmic_bit_num - 1), 1); 3998 3999 /*soc_th3_ser_intr_handler(unit, PTR_TO_INT(d1), cmic_reg_type);*/ 4000 return; 4001 } 4002 4003 /* 4004 * Function: 4005 * soc_th3_process_pm_intr 4006 * Description: 4007 * Tomahawk3 specific DPC function to service PM interrupts 4008 * Parameters: 4009 * unit_vp - Device number 4010 * d1 - IRQ4 mask 4011 * d2 - IRQ4 number (to distinguish between 4012 * different types of interrupts). 4013 */ 4014 static void 4015 soc_th3_pm_intr_handler(int unit, uint32 cmic_val, int reg_num) 4016 { 4017 uint32 cmic_bit = cmic_val; 4018 uint32 cmic_bit_num = 0; 4019 4020 /* Get the bit num or the hw port macro id */ 4021 while(cmic_bit != 0) { 4022 cmic_bit >>= 1; 4023 cmic_bit_num++; 4024 } 4025 4026 /* Disable the specific PM interrupt */ 4027 (void) soc_ser_top_intr_reg_enable(unit, reg_num, 4028 (cmic_bit_num - 1), 0); 4029 4030 sal_dpc(soc_th3_process_pm_intr, INT_TO_PTR(unit), 4031 INT_TO_PTR(cmic_bit_num), INT_TO_PTR(reg_num), 0, 0); 4032 4033 return; 4034 } 4035 4036 /* 4037 * Function: 4038 * soc_th3_lp_intr_handler 4039 * Purpose: 4040 * This function is the main low priority interrupt handler. L2 learn cache 4041 * SER and other low priority interrupts should be handled by this 4042 * function. 4043 * Parameters: 4044 * unit - SOC unit # 4045 * Returns: 4046 * Nothing 4047 */ 4048 STATIC 4049 void soc_th3_lp_intr_handler(int unit, void *data) 4050 { 4051 int parity_enable = 0; 4052 uint32 regval = 0; 4053 soc_reg_t reg[] = { ICFG_CHIP_LP_INTR_RAW_STATUS_REG0r, 4054 ICFG_CHIP_LP_INTR_RAW_STATUS_REG1r, 4055 ICFG_CHIP_LP_INTR_RAW_STATUS_REG2r, 4056 ICFG_CHIP_LP_INTR_RAW_STATUS_REG3r, 4057 ICFG_CHIP_LP_INTR_STATUS_REG0r, 4058 ICFG_CHIP_LP_INTR_STATUS_REG1r, 4059 ICFG_CHIP_LP_INTR_STATUS_REG2r, 4060 ICFG_CHIP_LP_INTR_STATUS_REG3r 4061 }; 4062 4063 /* Note CHIP_INTR_LOW_PRIORITY is disabled in the calling handler function 4064 * (from CMICx layer) 4065 */ 4066 /* SER and any other modules should check the interrupt bits they will 4067 * handle, add their handlers here 4068 */ 4069 /* Check interrupts in reg[4] */ 4070 (void)soc_iproc_getreg(unit, soc_reg_addr(unit, reg[4], REG_PORT_ANY, 0), 4071 ®val); 4072 4073 /* Check for the temperature interrupt and call handler */ 4074 if (regval & 0x4) { /* PVTMON_INTR , bit 2 */ 4075 /* soc_tomahawk3_temperature_intr(INT_TO_PTR(unit), NULL, NULL, NULL, NULL); */ 4076 sal_dpc(soc_tomahawk3_temperature_intr, INT_TO_PTR(unit), 0, 0, 0, 0); 4077 } 4078 4079 parity_enable = soc_property_get(unit, spn_PARITY_ENABLE, TRUE); 4080 /* Check interrupts in reg[0] */ 4081 (void)soc_iproc_getreg(unit, soc_reg_addr(unit, reg[0], REG_PORT_ANY, 0), 4082 ®val); 4083 if ((regval & SOC_TH3_SER_REG0_INTR_MASK) && parity_enable) { 4084 soc_th3_ser_intr_handler(unit, regval, 0); 4085 } 4086 4087 regval = 0; 4088 (void)soc_iproc_getreg(unit, soc_reg_addr(unit, reg[2], REG_PORT_ANY, 0), 4089 ®val); 4090 if ((regval & SOC_TH3_SER_REG2_INTR_MASK) && parity_enable) { 4091 soc_th3_pm_intr_handler(unit, regval, 2); 4092 /*sal_dpc(soc_th3_process_pm_intr, INT_TO_PTR(unit), 4093 INT_TO_PTR(regval), INT_TO_PTR(2), 0, 0);*/ 4094 } 4095 4096 regval = 0; 4097 (void)soc_iproc_getreg(unit, soc_reg_addr(unit, reg[3], REG_PORT_ANY, 0), 4098 ®val); 4099 if ((regval & SOC_TH3_SER_REG3_INTR_MASK) && parity_enable) { 4100 soc_th3_ser_intr_handler(unit, regval, 3); 4101 } 4102 4103 regval = 0; 4104 (void)soc_iproc_getreg(unit, soc_reg_addr(unit, reg[1], REG_PORT_ANY, 0), 4105 ®val); 4106 if ((regval & SOC_TH3_SER_REG1_INTR_MASK) && parity_enable) { 4107 soc_th3_ser_intr_handler(unit, regval, 1); 4108 } 4109 /* Atleast one L2 learn cache interrupt set, call learn handler */ 4110 if (regval & SOC_TH3_L2_LEARN_CACHE_INTR_MASK) { 4111 soc_th3_lrn_cache_intr_handler(unit, data); 4112 } 4113 4114 /* Re-enable main CMICx interrupt */ 4115 soc_cmic_intr_enable(unit, CHIP_INTR_LOW_PRIORITY); 4116 } 4117 4118 4119 /* 4120 * Function: 4121 * soc_th3_lp_intr_register 4122 * Purpose: 4123 * This function registers a low priority interrupt handler for all low 4124 * priority interrupts. L2 learn cache, SER and other low priority 4125 * interrupts are handled by the handler function registered in this 4126 * function 4127 * Parameters: 4128 * unit - SOC unit # 4129 * Returns: 4130 * Nothing 4131 */ 4132 STATIC void 4133 soc_th3_lp_intr_register(int unit) 4134 { 4135 soc_cmic_intr_handler_t handle; 4136 4137 handle.num = CHIP_INTR_LOW_PRIORITY; 4138 handle.intr_fn = soc_th3_lp_intr_handler; 4139 handle.intr_data = NULL; 4140 soc_cmic_intr_register(unit, &handle, 1); 4141 4142 /* Enable main CMICx interrupt */ 4143 soc_cmic_intr_enable(unit, CHIP_INTR_LOW_PRIORITY); 4144 } 4145 4146 STATIC int 4147 _soc_tomahawk3_misc_init(int unit) 4148 { 4149 /*soc_mem_t mem;*/ 4150 int rv, i; 4151 uint8 bypass_valid = 0; 4152 uint8 rev_id; 4153 uint16 dev_id; 4154 int port_chk, num_port = 160; 4155 /* _soc_tomahawk_tdm_t *tdm; */ 4156 int parity_enable; 4157 /*int clport, lane, mode, class, index;*/ 4158 soc_info_t *si = &SOC_INFO(unit); 4159 /*static soc_field_t port_fields[_TH_PORTS_PER_PBLK] = { 4160 PORT0f, PORT1f, PORT2f, PORT3f 4161 }; 4162 */ 4163 uint64 fval_64; 4164 uint64 rval_64; 4165 int port, cnt; 4166 const static soc_reg_t cnt_reg_list[] = 4167 { 4168 RUC_64r, RPORTD_64r, RDBGC0_64r, RDBGC1_64r, 4169 RDBGC2_64r, RDBGC3_64r, RDBGC4_64r, RDBGC5_64r, 4170 RDBGC6_64r, RDBGC7_64r, RDBGC8_64r, ING_ECN_COUNTER_64r, 4171 TDBGC0_64r, TDBGC1_64r, TDBGC2_64r, TDBGC3_64r, 4172 TDBGC4_64r, TDBGC5_64r, TDBGC6_64r, TDBGC7_64r, 4173 TDBGC8_64r, TDBGC9_64r, TDBGC10_64r, TDBGC11_64r 4174 }; 4175 void *null_entry = NULL; 4176 int copyno; 4177 uint32 index = 0; 4178 soc_mem_t mem = INVALIDm; 4179 4180 uint32 pipe_map; 4181 uint8 used_pm_map[_TH3_PBLKS_PER_DEV + 1]; 4182 uint8 *buf; 4183 int phy_port, pm_num, pipe_num, size, pm; 4184 const soc_mem_t idb_obm_list[_TH3_PIPES_PER_DEV][_TH3_PBLKS_PER_PIPE] = { 4185 {IDB_OBM0_IOM_STATS_WINDOW_RESULTS_PIPE0m, 4186 IDB_OBM1_IOM_STATS_WINDOW_RESULTS_PIPE0m, 4187 IDB_OBM2_IOM_STATS_WINDOW_RESULTS_PIPE0m, 4188 IDB_OBM3_IOM_STATS_WINDOW_RESULTS_PIPE0m}, 4189 {IDB_OBM0_IOM_STATS_WINDOW_RESULTS_PIPE1m, 4190 IDB_OBM1_IOM_STATS_WINDOW_RESULTS_PIPE1m, 4191 IDB_OBM2_IOM_STATS_WINDOW_RESULTS_PIPE1m, 4192 IDB_OBM3_IOM_STATS_WINDOW_RESULTS_PIPE1m}, 4193 {IDB_OBM0_IOM_STATS_WINDOW_RESULTS_PIPE2m, 4194 IDB_OBM1_IOM_STATS_WINDOW_RESULTS_PIPE2m, 4195 IDB_OBM2_IOM_STATS_WINDOW_RESULTS_PIPE2m, 4196 IDB_OBM3_IOM_STATS_WINDOW_RESULTS_PIPE2m}, 4197 {IDB_OBM0_IOM_STATS_WINDOW_RESULTS_PIPE3m, 4198 IDB_OBM1_IOM_STATS_WINDOW_RESULTS_PIPE3m, 4199 IDB_OBM2_IOM_STATS_WINDOW_RESULTS_PIPE3m, 4200 IDB_OBM3_IOM_STATS_WINDOW_RESULTS_PIPE3m}, 4201 {IDB_OBM0_IOM_STATS_WINDOW_RESULTS_PIPE4m, 4202 IDB_OBM1_IOM_STATS_WINDOW_RESULTS_PIPE4m, 4203 IDB_OBM2_IOM_STATS_WINDOW_RESULTS_PIPE4m, 4204 IDB_OBM3_IOM_STATS_WINDOW_RESULTS_PIPE4m}, 4205 {IDB_OBM0_IOM_STATS_WINDOW_RESULTS_PIPE5m, 4206 IDB_OBM1_IOM_STATS_WINDOW_RESULTS_PIPE5m, 4207 IDB_OBM2_IOM_STATS_WINDOW_RESULTS_PIPE5m, 4208 IDB_OBM3_IOM_STATS_WINDOW_RESULTS_PIPE5m}, 4209 {IDB_OBM0_IOM_STATS_WINDOW_RESULTS_PIPE6m, 4210 IDB_OBM1_IOM_STATS_WINDOW_RESULTS_PIPE6m, 4211 IDB_OBM2_IOM_STATS_WINDOW_RESULTS_PIPE6m, 4212 IDB_OBM3_IOM_STATS_WINDOW_RESULTS_PIPE6m}, 4213 {IDB_OBM0_IOM_STATS_WINDOW_RESULTS_PIPE7m, 4214 IDB_OBM1_IOM_STATS_WINDOW_RESULTS_PIPE7m, 4215 IDB_OBM2_IOM_STATS_WINDOW_RESULTS_PIPE7m, 4216 IDB_OBM3_IOM_STATS_WINDOW_RESULTS_PIPE7m}, 4217 }; 4218 4219 sal_memset(used_pm_map, 0, sizeof(used_pm_map)); 4220 for (phy_port = 1; phy_port <= _TH3_PORTS_PER_DEV; phy_port++) { 4221 port = si->port_p2l_mapping[phy_port]; 4222 if (port > 0) { 4223 pm = si->port_serdes[port]; 4224 if ((-1 != pm) && (0 == used_pm_map[pm])) { 4225 used_pm_map[pm] = 1; 4226 } 4227 } 4228 } 4229 4230 4231 soc_cm_get_id(unit, &dev_id, &rev_id); 4232 4233 soc_tomahawk3_pipe_map_get(unit, &pipe_map); 4234 /* Stop the mem scan task before all of the parity init takes place */ 4235 SOC_IF_ERROR_RETURN(soc_generic_ser_mem_scan_stop(unit)); 4236 SOC_IF_ERROR_RETURN(soc_generic_sram_mem_scan_stop(unit)); 4237 4238 SOC_IF_ERROR_RETURN(soc_reg_field32_modify 4239 (unit, AUX_ARB_CONTROLr, REG_PORT_ANY, FP_REFRESH_ENABLEf, 1)); 4240 4241 parity_enable = soc_property_get(unit, spn_PARITY_ENABLE, TRUE); 4242 #if 0 4243 /*Slot pipeline config*/ 4244 SOC_IF_ERROR_RETURN(soc_tomahawk3_slot_pipeline_config(unit)); 4245 #endif 4246 4247 /* Reset counts on debug tx/rx debug counters */ 4248 if (SAL_BOOT_SIMULATION && !SAL_BOOT_QUICKTURN) { 4249 COMPILER_64_ZERO(fval_64); 4250 PBMP_ALL_ITER(unit, port) { 4251 for (cnt=0; cnt<COUNTOF(cnt_reg_list) ; cnt++) { 4252 COMPILER_64_ZERO(rval_64); 4253 SOC_IF_ERROR_RETURN( 4254 soc_reg_get(unit, cnt_reg_list[cnt], port, 0, &rval_64)); 4255 soc_reg64_field_set( 4256 unit, cnt_reg_list[cnt], &rval_64, COUNTf, fval_64); 4257 SOC_IF_ERROR_RETURN( 4258 soc_reg_set(unit, cnt_reg_list[cnt], port, 0, rval_64)); 4259 } 4260 } 4261 } 4262 COMPILER_64_ZERO(rval_64); 4263 /* For TH3-5414, we need to make sure the below register 4264 is cleared even for invalid ports 4265 */ 4266 for (i = 0; i < 160 ; i++) { 4267 SOC_IF_ERROR_RETURN(WRITE_EGR_1588_LINK_DELAY_64r(unit, i, rval_64)); 4268 } 4269 4270 if (!SOC_IS_RELOADING(unit) && !SOC_WARM_BOOT(unit)) { 4271 4272 SOC_IF_ERROR_RETURN(_soc_tomahawk3_port_mib_reset(unit)); 4273 4274 /* Dummy call to clear garbage h/w values */ 4275 SOC_IF_ERROR_RETURN 4276 (soc_tomahawk3_temperature_monitor_get(unit, COUNTOF(pvtmon_result_reg_th3), 4277 NULL, NULL)); 4278 4279 SOC_IF_ERROR_RETURN(soc_tomahawk3_clear_mmu_counters(unit)); 4280 SOC_IF_ERROR_RETURN(soc_tomahawk3_init_tm_memory(unit)); 4281 mem = EDB_XMIT_START_COUNTm; 4282 null_entry = soc_mem_entry_null(unit, mem); 4283 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 4284 for (index = soc_mem_index_min(unit, mem); 4285 index <= soc_mem_index_max(unit, mem); index++) { 4286 rv = soc_mem_write(unit, mem, copyno, index, null_entry); 4287 } 4288 4289 size = SOC_MEM_TABLE_BYTES(unit, idb_obm_list[0][0]); 4290 buf = soc_cm_salloc(unit, size, "IDB OBM MEMORY"); 4291 sal_memset(buf, 0, size); 4292 PBMP_PORT_ITER(unit, port) { 4293 if (SOC_PBMP_MEMBER(si->management_pbm, port)) { 4294 continue; 4295 } 4296 phy_port = si->port_l2p_mapping[port]; 4297 pipe_num = soc_tomahawk3_get_pipe_from_phy_port(phy_port); 4298 pm_num = soc_tomahawk3_get_pipe_pm_from_phy_port(phy_port); 4299 if (!(pipe_map & (1 << pipe_num))) { 4300 continue; 4301 } 4302 if (used_pm_map[pm_num] == 0) { 4303 continue; 4304 } 4305 mem = idb_obm_list[pipe_num][pm_num]; 4306 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 4307 rv = soc_mem_write_range(unit, mem, copyno, soc_mem_index_min(unit, mem), 4308 soc_mem_index_max(unit, mem), buf); 4309 if (rv != SOC_E_NONE) { 4310 soc_cm_sfree(unit, buf); 4311 return rv; 4312 } 4313 } 4314 soc_cm_sfree(unit, buf); 4315 } 4316 4317 if (parity_enable) { 4318 if ((!SAL_BOOT_SIMULATION || SAL_BOOT_QUICKTURN) && 4319 !SOC_WARM_BOOT(unit)) { 4320 4321 /* Certain mems/regs need to be cleared before enabling SER */ 4322 4323 } 4324 4325 /* Enable logging of SER events */ 4326 soc_ser_log_init(unit, NULL, 0); 4327 4328 4329 /* Enable l2_mgmt interrupt */ 4330 /* SOC_IF_ERROR_RETURN 4331 (soc_reg_field32_modify(unit, L2_MGMT_INTR_MASKr, REG_PORT_ANY, 4332 SER_FIFO_NOT_EMPTYf, 1));*/ 4333 #ifdef BCM_CMICX_SUPPORT 4334 if (soc_feature(unit, soc_feature_cmicx)) { 4335 4336 /*soc_cmicm_intr3_enable(unit, 0x2); L2_MGMT_TO_CMIC_INTR bit 1 */ 4337 } 4338 #endif 4339 4340 /* SOC_IF_ERROR_RETURN(soc_tomahawk_tcam_ser_init(unit)); */ 4341 SOC_IF_ERROR_RETURN(soc_tomahawk_ser_enable_all(unit, TRUE)); 4342 SOC_IF_ERROR_RETURN(soc_tomahawk3_ser_enable_parity_table_all(unit, TRUE)); 4343 soc_tomahawk_ser_register(unit); 4344 #if defined(SER_TR_TEST_SUPPORT) 4345 /*Initialize chip-specific functions for SER testing*/ 4346 soc_th_ser_test_register(unit); 4347 #endif /*defined(SER_TR_TEST_SUPPORT*/ 4348 } 4349 4350 /* Clear SER related fifo before enabling low priority interrupt */ 4351 if (!SAL_BOOT_SIMULATION) { 4352 _soc_tomahawk3_ser_hw_clear(unit); 4353 } 4354 4355 /* Turn on low priority interrupts for actual h/w and emulation */ 4356 /* Note the individual modules should check if they will be working in 4357 * interrupt mode, and enable/disable module level interrupts accordingly 4358 */ 4359 if ((!SAL_BOOT_SIMULATION) || (SAL_BOOT_QUICKTURN)) { 4360 if (soc_feature(unit, soc_feature_cmicx)) { 4361 soc_th3_lp_intr_register(unit); 4362 } 4363 } 4364 4365 /* Configure Switch Latency Bypass Mode */ 4366 bypass_valid = soc_property_get(unit, spn_SWITCH_BYPASS_MODE, 4367 SOC_SWITCH_BYPASS_MODE_NONE); 4368 if ((SOC_SWITCH_BYPASS_MODE_NONE != bypass_valid) && 4369 (SOC_SWITCH_BYPASS_MODE_EFP != bypass_valid)) { 4370 LOG_ERROR(BSL_LS_SOC_COMMON, 4371 (BSL_META_U(unit, 4372 "Low latency and Balanced latency modes not" 4373 "supported on BCM5698x \n"))); 4374 return SOC_E_CONFIG; 4375 } 4376 SOC_IF_ERROR_RETURN(soc_th_latency_init(unit)); 4377 4378 /*Dev_port, Phyport, MMU port, IDB port mappings*/ 4379 SOC_IF_ERROR_RETURN(_soc_tomahawk3_port_mapping_init(unit)); 4380 4381 /* No HG port support */ 4382 SOC_CONTROL_LOCK(unit); 4383 si->fabric_port_enable = 0; 4384 SOC_CONTROL_UNLOCK(unit); 4385 4386 for(port_chk = 0; port_chk < num_port; port_chk++) { 4387 if (si->port_speed_max[port_chk] > 0) { 4388 rv = soc_th3_port_speed_supported(unit, port_chk, 4389 si->port_speed_max[port_chk]); 4390 if (SOC_FAILURE(rv)) { 4391 LOG_ERROR(BSL_LS_SOC_COMMON, 4392 (BSL_META_U(unit, 4393 "Unsupported port speed : port - %d, " 4394 "speed - %d\n"), port_chk, 4395 si->port_speed_max[port_chk])); 4396 return rv; 4397 } 4398 } 4399 } 4400 4401 /* Check the speed classes, make sure only 4 speeds in the device */ 4402 SOC_IF_ERROR_RETURN(soc_th3_speed_class_validate(unit)); 4403 4404 /*DV: TDM Code*/ 4405 SOC_IF_ERROR_RETURN(soc_tomahawk3_tdm_update(unit)); 4406 4407 /* Initialize IDB */ 4408 /*DV: Integrate IDB init from DV*/ 4409 rv = soc_tomahawk3_idb_init_update(unit); 4410 if (SOC_FAILURE(rv)){ 4411 LOG_ERROR(BSL_LS_SOC_COMMON, 4412 (BSL_META_U(unit, 4413 "FAILED in" 4414 "soc_tomahawk3_idb_init_update\n"))); 4415 return rv; 4416 } 4417 4418 /*Setup CPU_PBM and Loopback port bitmap*/ 4419 SOC_IF_ERROR_RETURN(_soc_tomahawk3_cpu_lb_portbitmap_set(unit)); 4420 4421 /*Setup port_type for HG/LB ports*/ 4422 SOC_IF_ERROR_RETURN(_soc_tomahawk3_hg_lb_port_type_set(unit)); 4423 4424 #ifdef PLISIM 4425 if (SAL_BOOT_PLISIM) { 4426 /* done later, after port mapping is configured by ep_top. */ 4427 } else 4428 #endif 4429 { 4430 /*XLPORT init*/ 4431 SOC_IF_ERROR_RETURN(_soc_tomahawk3_management_port_init(unit)); 4432 } 4433 4434 /*Enable refresh in MMU*/ 4435 SOC_IF_ERROR_RETURN(soc_tomahawk3_en_mmu_refresh(unit)); 4436 4437 /* Enable dual hash tables */ 4438 SOC_IF_ERROR_RETURN(soc_tomahawk3_hash_init(unit)); 4439 4440 /*DV: integrate EP credit int and port enable from DV*/ 4441 SOC_IF_ERROR_RETURN(soc_tomahawk3_ep_top_init(unit)); 4442 4443 #if defined(PLISIM) 4444 if (SAL_BOOT_PLISIM) { 4445 /*XLPORT init*/ 4446 SOC_IF_ERROR_RETURN(_soc_tomahawk3_management_port_init(unit)); 4447 } 4448 #endif /* PLISIM */ 4449 4450 /*Enable MAC after EP enable*/ 4451 SOC_IF_ERROR_RETURN(soc_tomahawk3_cdport_init(unit)); 4452 4453 /*DV: Enable ingress forwarding */ 4454 SOC_IF_ERROR_RETURN(soc_tomahawk3_enable_ingress_forwarding(unit)); 4455 4456 4457 /*Default programming required in IPEP*/ 4458 SOC_IF_ERROR_RETURN(_soc_tomahawk3_ipep_default_init(unit)); 4459 4460 4461 4462 #if 0 4463 4464 if (SAL_BOOT_QUICKTURN) { 4465 PBMP_PORT_ITER(unit, port) { 4466 if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) { 4467 continue; 4468 } 4469 SOC_IF_ERROR_RETURN 4470 (soc_tomahawk3_port_speed_update(unit, port, 4471 si->port_speed_max[port])); 4472 } 4473 } 4474 #endif 4475 4476 /*external,internal MDIO freq config*/ 4477 SOC_IF_ERROR_RETURN(_soc_tomahawk3_cmic_mdio_freq_config(unit)); 4478 4479 4480 _phy_tsce_firmware_set_helper[unit] = _soc_tomahawk3_tscx_firmware_set; 4481 _phy_tscf_firmware_set_helper[unit] = _soc_tomahawk3_tscx_firmware_set; 4482 4483 4484 SOC_IF_ERROR_RETURN 4485 (soc_counter_tomahawk_status_enable(unit, TRUE)); 4486 4487 /* Mem Scan thread start should be the last step in Misc init */ 4488 if (parity_enable) { 4489 if ((!SAL_BOOT_SIMULATION || SAL_BOOT_QUICKTURN) && 4490 !SOC_WARM_BOOT(unit)) { 4491 SOC_IF_ERROR_RETURN(soc_generic_sram_mem_scan_start(unit)); 4492 } 4493 } 4494 4495 /* Create a mutex for s/w re-ordering */ 4496 SOC_IF_ERROR_RETURN(soc_tomahawk3_hash_mutex_init(unit)); 4497 4498 #ifdef BCM_CMICX_SUPPORT 4499 if (soc_feature(unit, soc_feature_cmicx) && 4500 !(SAL_BOOT_PLISIM || SAL_BOOT_BCMSIM)) 4501 { 4502 SOC_IF_ERROR_RETURN(_soc_th3_ledup_init(unit)); 4503 } 4504 #endif /* BCM_CMICX_SUPPORT */ 4505 4506 #ifdef INCLUDE_AVS 4507 SOC_IF_ERROR_RETURN(soc_tomahawk3_avs_init(unit)); 4508 #endif /* INCLUDE_AVS */ 4509 4510 LOG_VERBOSE(BSL_LS_SOC_COMMON, 4511 (BSL_META_U(unit, 4512 "MISC Init completed (u=%d)\n"), unit)); 4513 return SOC_E_NONE; 4514 } 4515 4516 4517 4518 /* Function to get the number of ports present in a given Port Macro */ 4519 int 4520 soc_th3_ports_per_pm_get(int unit, int pm_id) 4521 { 4522 soc_info_t *si; 4523 int phy_port_base, num_ports = 0; 4524 4525 si = &SOC_INFO(unit); 4526 if (pm_id >= _TH3_PBLKS_PER_DEV) { 4527 return SOC_E_PARAM; 4528 } 4529 phy_port_base = 1 + (pm_id * _TH3_PORTS_PER_PBLK); 4530 4531 if (si->port_p2l_mapping[phy_port_base] != -1) { 4532 num_ports = 1; 4533 if ((si->port_num_lanes[phy_port_base] == 2) && 4534 (si->port_p2l_mapping[phy_port_base + 2] != -1)) { 4535 /* for cases when num_lanes is given in the config (40g). 4536 */ 4537 num_ports = 2; 4538 } 4539 4540 /* When phy_port_base + 1 is valid, 4541 * All 4 ports of the PM(port macro) are valid. 4542 * When phy_port_base + 2 is valid, 4543 * The PM is operating in Dual lane mode 4544 */ 4545 if (si->port_p2l_mapping[phy_port_base + 1] != -1) { 4546 num_ports = 4; 4547 if (si->port_p2l_mapping[phy_port_base + 2] == -1) { 4548 num_ports = 2; 4549 } 4550 } else if (si->port_p2l_mapping[phy_port_base + 2] != -1) { 4551 num_ports = 2; 4552 } 4553 } 4554 return num_ports; 4555 } 4556 4557 void 4558 _soc_th3_lpm_view_set(int unit, int index, soc_mem_t view, int pair_lpm) 4559 { 4560 int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit); 4561 4562 if (!_soc_th3_lpm_view_map[unit]) { 4563 return; 4564 } 4565 4566 if (pair_lpm) { 4567 index = (index % tcam_depth) + 4568 (index / tcam_depth) * 2 * tcam_depth; 4569 _soc_th3_lpm_view_map[unit][index] = view; 4570 _soc_th3_lpm_view_map[unit][index + tcam_depth] = view; 4571 } else { 4572 _soc_th3_lpm_view_map[unit][index] = view; 4573 } 4574 } 4575 4576 soc_mem_t 4577 _soc_th3_lpm_view_get(int unit, int index, int pair_lpm) 4578 { 4579 soc_mem_t view; 4580 int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit); 4581 4582 if (!_soc_th3_lpm_view_map[unit]) { 4583 return INVALIDm; 4584 } 4585 4586 if (pair_lpm) { 4587 index = (index % tcam_depth) + 4588 (index / tcam_depth) * 2 * tcam_depth; 4589 view = _soc_th3_lpm_view_map[unit][index]; 4590 if (view == INVALIDm) { 4591 view = _soc_th3_lpm_view_map[unit][index + tcam_depth]; 4592 } 4593 } else { 4594 view = _soc_th3_lpm_view_map[unit][index]; 4595 } 4596 return view; 4597 } 4598 4599 STATIC int 4600 soc_tomahawk3_rqe_threshold_init(int unit) { 4601 4602 #define TH3_MMU_RQE_QUEUE_NUM 9 4603 #define TH3_THDR_QE_CONFIG1_VALUE 0x7 4604 #define TH3_THDR_QE_CONIFG_PRI_LIMIT 8 4605 #define TH3_THDR_QE_LIMIT_MIN 7 4606 #define TH3_MMU_THDR_QE_RESET_OFFSET 0xe 4607 #define TH3_THDR_QE_SP_SHARED_LIMIT 0xaa9 4608 #define TH3_THDR_QE_SP_RESUME_LIMIT 0xa9b 4609 4610 soc_reg_t reg = INVALIDr; 4611 uint32 idx, rval; 4612 for(idx = 0; idx < TH3_MMU_RQE_QUEUE_NUM; idx++) { 4613 reg = MMU_THDR_QE_CONFIG1_PRIQr; 4614 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 4615 idx, TH3_THDR_QE_CONFIG1_VALUE)); 4616 4617 reg = MMU_THDR_QE_CONFIG_PRIQr; 4618 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval)); 4619 soc_reg_field_set(unit, reg, &rval, RESET_OFFSETf, 4620 TH3_MMU_THDR_QE_RESET_OFFSET); 4621 soc_reg_field_set(unit, reg, &rval, SHARED_LIMITf, 4622 TH3_THDR_QE_CONIFG_PRI_LIMIT); 4623 soc_reg_field_set(unit, reg, &rval, SHARED_ALPHAf, 4624 TH3_THDR_QE_CONIFG_PRI_LIMIT); 4625 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 4626 idx, rval)); 4627 4628 reg = MMU_THDR_QE_LIMIT_MIN_PRIQr; 4629 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval)); 4630 soc_reg_field_set(unit, reg, &rval, MIN_LIMITf, TH3_THDR_QE_LIMIT_MIN); 4631 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 4632 idx, rval)); 4633 4634 reg = MMU_THDR_QE_RESET_OFFSET_COLOR_PRIQr; 4635 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval)); 4636 soc_reg_field_set(unit, reg, &rval, RESET_OFFSET_YELLOWf, 4637 TH3_MMU_THDR_QE_RESET_OFFSET); 4638 soc_reg_field_set(unit, reg, &rval, RESET_OFFSET_REDf, 4639 TH3_MMU_THDR_QE_RESET_OFFSET); 4640 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 4641 idx, rval)); 4642 } 4643 4644 reg = MMU_THDR_QE_CONFIGr; 4645 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval)); 4646 soc_reg_field_set(unit, reg, &rval, LAST_PKT_ACCEPT_MODEf, 1); 4647 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 4648 idx, rval)); 4649 4650 reg = MMU_THDR_QE_CONFIG_SPr; 4651 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval)); 4652 soc_reg_field_set(unit, reg, &rval, SHARED_LIMITf, 4653 TH3_THDR_QE_SP_SHARED_LIMIT); 4654 soc_reg_field_set(unit, reg, &rval, RESUME_LIMITf, 4655 TH3_THDR_QE_SP_RESUME_LIMIT); 4656 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 4657 idx, rval)); 4658 4659 reg = MMU_THDR_QE_SHARED_COLOR_LIMIT_SPr; 4660 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval)); 4661 soc_reg_field_set(unit, reg, &rval, SHARED_LIMIT_YELLOWf, 4662 TH3_THDR_QE_SP_SHARED_LIMIT); 4663 soc_reg_field_set(unit, reg, &rval, SHARED_LIMIT_REDf, 4664 TH3_THDR_QE_SP_SHARED_LIMIT); 4665 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 4666 idx, rval)); 4667 4668 reg = MMU_THDR_QE_RESUME_COLOR_LIMIT_SPr; 4669 soc_reg_field_set(unit, reg, &rval, RESUME_LIMIT_YELLOWf, 4670 TH3_THDR_QE_SP_RESUME_LIMIT); 4671 soc_reg_field_set(unit, reg, &rval, RESUME_LIMIT_REDf, 4672 TH3_THDR_QE_SP_RESUME_LIMIT); 4673 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 4674 idx, rval)); 4675 4676 4677 return SOC_E_NONE; 4678 } 4679 4680 STATIC int 4681 soc_tomahawk3_rqe_sched_shaper_init(int unit) { 4682 soc_reg_t reg = INVALIDr; 4683 uint32 idx, rval; 4684 uint64 rval_64; 4685 4686 for(idx = 0; idx < TH3_MMU_RQE_QUEUE_NUM; idx++) { 4687 reg = MMU_RQE_MAX_SHAPER_ENr; 4688 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval)); 4689 soc_reg_field_set(unit, reg, &rval, VALUEf, 0); 4690 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 4691 idx, rval)); 4692 4693 reg = MMU_RQE_PRIORITY_WERR_WEIGHTr; 4694 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval)); 4695 soc_reg_field_set(unit, reg, &rval, COUNTf, 1); 4696 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 4697 idx, rval)); 4698 } 4699 COMPILER_64_ZERO(rval_64); 4700 reg = MMU_RQE_SCH_INACTIVE_CONTROLr; 4701 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, REG_PORT_ANY, 0, &rval_64)); 4702 soc_reg64_field32_set(unit, reg, &rval_64, INTERVALf, 20); 4703 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, REG_PORT_ANY, 0, rval_64)); 4704 4705 4706 return SOC_E_NONE; 4707 } 4708 4709 STATIC int 4710 _soc_tomahawk3_mmu_init(int unit) 4711 { 4712 int test_only, parity_en; 4713 SOC_INFO(unit).mmu_lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 4714 SOC_TH3_MMU_LOSSLESS_DEFAULT_DISABLE); 4715 4716 test_only = (SAL_BOOT_BCMSIM || SAL_BOOT_XGSSIM) ? TRUE : FALSE; 4717 parity_en = soc_property_get(unit, spn_PARITY_ENABLE, TRUE); 4718 4719 SOC_IF_ERROR_RETURN(_soc_th3_post_mmu_init_update(unit)); 4720 SOC_IF_ERROR_RETURN(soc_tomahawk3_rqe_threshold_init(unit)); 4721 SOC_IF_ERROR_RETURN(soc_tomahawk3_rqe_sched_shaper_init(unit)); 4722 /*Port speed encodings to be setup in MMU diuring init*/ 4723 /*Can be re-used for port speed update as well*/ 4724 SOC_IF_ERROR_RETURN(soc_tomahawk3_tm_port_speed_encoding(unit)); 4725 SOC_IF_ERROR_RETURN(soc_tomahawk3_cell_pointer_init(unit)); 4726 SOC_IF_ERROR_RETURN(soc_tomahawk3_mmu_port_rx_enables(unit)); 4727 SOC_IF_ERROR_RETURN(soc_tomahawk3_scheduler_init(unit)); 4728 SOC_IF_ERROR_RETURN(soc_th3_mmu_config_init_thresholds(unit, test_only)); 4729 SOC_IF_ERROR_RETURN(soc_th3_mmu_rqe_queue_number_init(unit)); 4730 SOC_IF_ERROR_RETURN(soc_tomahawk3_wred_init(unit)); 4731 SOC_IF_ERROR_RETURN(soc_tomahawk3_scb_init(unit)); 4732 SOC_IF_ERROR_RETURN(soc_tomahawk3_rl_init(unit)); 4733 #ifdef INCLUDE_PSTATS 4734 soc_tomahawk3_mmu_pstats_tbl_config(unit); 4735 #endif 4736 4737 SOC_IF_ERROR_RETURN(soc_th3_pfc_rx_init_from_cfg(unit)); 4738 SOC_IF_ERROR_RETURN(soc_th3_pfc_priority_to_pg_map_init_from_cfg(unit)); 4739 if (parity_en) { 4740 SOC_IF_ERROR_RETURN(soc_th3_mmu_enable_non_func_intr(unit)); 4741 } 4742 return SOC_E_NONE; 4743 } 4744 4745 STATIC int 4746 _soc_tomahawk3_age_timer_get(int unit, int *age_seconds, int *enabled) 4747 { 4748 soc_control_t *soc = SOC_CONTROL(unit); 4749 4750 *enabled = soc->l2x_age_pid != SAL_THREAD_ERROR && 4751 soc->l2x_age_enable ? 4752 1 : 0; 4753 *age_seconds = soc->l2x_age_pid != SAL_THREAD_ERROR && 4754 soc->l2x_age_enable ? 4755 soc->l2x_age_interval : 0; 4756 4757 return SOC_E_NONE; 4758 } 4759 4760 STATIC int 4761 _soc_tomahawk3_age_timer_max_get(int unit, int *max_seconds) 4762 { 4763 *max_seconds = 0x7fffffff; 4764 return SOC_E_NONE; 4765 } 4766 4767 STATIC int 4768 _soc_tomahawk3_age_timer_set(int unit, int age_seconds, int enable) 4769 { 4770 soc_control_t *soc = SOC_CONTROL(unit); 4771 sal_usecs_t interval = soc->l2x_age_interval; 4772 4773 if (soc->l2x_age_interval) { 4774 if (!enable) { 4775 soc->l2x_age_enable = 0; 4776 } else { 4777 if (age_seconds) { 4778 SOC_CONTROL_LOCK(unit); 4779 soc->l2x_age_interval = age_seconds; 4780 SOC_CONTROL_UNLOCK(unit); 4781 } 4782 soc->l2x_age_enable = 1; 4783 if (interval != age_seconds) { 4784 sal_sem_give(soc->l2x_age_notify); 4785 } 4786 } 4787 } else { 4788 if (enable) { 4789 soc->l2x_age_enable = 1; 4790 SOC_IF_ERROR_RETURN 4791 (soc_th3_l2_age_start(unit, age_seconds)); 4792 } 4793 } 4794 4795 return SOC_E_NONE; 4796 } 4797 4798 soc_error_t 4799 soc_th3_port_speed_supported(int unit, soc_port_t port, int speed) 4800 { 4801 uint8 rev_id; 4802 uint16 dev_id; 4803 int num_lanes; 4804 soc_info_t *si = &SOC_INFO(unit); 4805 4806 /* 4807 * If Universal calendar was not selected at init time then 4808 * disallow speed change to HG2 speeds. 4809 */ 4810 if (FALSE == si->fabric_port_enable) { 4811 if (IS_HG2_SPEED(speed)) { 4812 /* 4813 * Intentionally returning SOC_E_CONFIG as this is a case 4814 * of incorrect configuration 4815 */ 4816 return SOC_E_CONFIG; 4817 } 4818 } 4819 4820 /* 4821 * Management ports only support 1G, 2.5G and 10G. Flexport 4822 * on management ports is not supported. Management ports 4823 * are guaranteed 10G bandwidth. 4824 */ 4825 if (SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) { 4826 if ((1000 == speed) || (2500 == speed) || (10000 == speed)) { 4827 return SOC_E_NONE; 4828 } else { 4829 return SOC_E_PARAM; 4830 } 4831 } 4832 4833 soc_cm_get_id(unit, &dev_id, &rev_id); 4834 num_lanes = si->port_num_lanes[port]; 4835 4836 /* 4837 * Check if Core Clock Frequency supports Port Speed 4838 */ 4839 4840 switch (speed) { 4841 /* 10G, 40G */ 4842 case 10000: 4843 case 40000: 4844 break; 4845 4846 /* 25G, 50G, 100G, 200G, 400G */ 4847 case 25000: 4848 case 50000: 4849 if (si->frequency < 300) { 4850 return SOC_E_PARAM; 4851 } 4852 break; 4853 case 100000: 4854 if (si->frequency < 600) { 4855 return SOC_E_PARAM; 4856 } 4857 break; 4858 case 200000: 4859 if (si->frequency < 600) { 4860 return SOC_E_PARAM; 4861 } 4862 break; 4863 case 400000: 4864 if (si->frequency < 1200) { 4865 return SOC_E_PARAM; 4866 } 4867 break; 4868 4869 default: 4870 return SOC_E_PARAM; 4871 } 4872 4873 /* 4874 * Laying down the framework to handle SKU differences. This is 4875 * needed because some SKUs have speed caps on certain PMs. 4876 */ 4877 switch (dev_id) { 4878 case BCM56961_DEVICE_ID: 4879 /* SERDES VCO capped at 21.875Ghz */ 4880 if ((25000 == speed) || (27000 == speed) || (speed >= 50000)) { 4881 return SOC_E_PARAM; 4882 } 4883 /* Fall through to default case */ 4884 4885 default: 4886 if (speed >= 400000) { /* 400G */ 4887 if (8 != num_lanes) { 4888 return SOC_E_PARAM; 4889 } 4890 } else if (speed >= 200000) { /* 200G */ 4891 if (4 != num_lanes) { 4892 return SOC_E_PARAM; 4893 } 4894 }else if (speed >= 100000) { /* 100G. Account for 2x50G or 4x25G*/ 4895 if ((4 != num_lanes) && (2 != num_lanes)) { 4896 return SOC_E_PARAM; 4897 } 4898 } else if (speed >= 50000) { /* 50G. Account for 1 x 50G or 2 x 25G */ 4899 if ((1 != num_lanes) && (2 != num_lanes)) { 4900 return SOC_E_PARAM; 4901 } 4902 } else if (speed >= 40000) { /* 40G 4 x 10G */ 4903 if (4 != num_lanes && (2 != num_lanes)) { 4904 return SOC_E_PARAM; 4905 } 4906 } else if (speed >= 25000) { /* 25G */ 4907 if (1 != num_lanes) { 4908 return SOC_E_PARAM; 4909 } 4910 } else { /* 10G */ 4911 if (1 != num_lanes) { 4912 return SOC_E_PARAM; 4913 } 4914 } 4915 } 4916 return SOC_E_NONE; 4917 } 4918 4919 4920 soc_error_t 4921 soc_th3_speed_set_init_ctrl(int unit, soc_th_port_lanes_t *lanes_ctrl) 4922 { 4923 #if 0 4924 soc_info_t *si = &SOC_INFO(unit); 4925 soc_port_t port_base = lanes_ctrl->port_base; 4926 4927 lanes_ctrl->oversub = SOC_PBMP_MEMBER(si->oversub_pbm, port_base); 4928 4929 if (lanes_ctrl->oversub) { 4930 SOC_IF_ERROR_RETURN(soc_tomahawk3_oversub_group_find(unit, lanes_ctrl)); 4931 } 4932 #endif 4933 4934 return SOC_E_NONE; 4935 } 4936 4937 void 4938 soc_tomahawk3_temperature_intr(void *unit_vp, void *d1, void *d2, 4939 void *d3, void *d4) 4940 { 4941 uint32 rval, trval; 4942 int i, rv, unit = PTR_TO_INT(unit_vp); 4943 4944 if ((rv = READ_TOP_PVTMON_INTR_STATUS_0r(unit, &rval)) != SOC_E_NONE) { 4945 LOG_ERROR(BSL_LS_SOC_COMMON, 4946 (BSL_META_U(unit, 4947 "TH3 Temp Intr, Reg access error.\n"))); 4948 } 4949 LOG_ERROR(BSL_LS_SOC_COMMON, 4950 (BSL_META_U(unit, 4951 "High temp interrupt: 0x%08x\n"), rval)); 4952 /* Raise event to app for it to take further graceful actions, ignore AVS */ 4953 for (i = 0; i < COUNTOF(pvtmon_result_reg_th3)-1; i++) { 4954 if ((0x1 << i) & _soc_th_temp_mon_mask[unit]) { 4955 if ((rv = soc_reg32_get(unit, pvtmon_result_reg_th3[i], REG_PORT_ANY, 0, 4956 &trval)) != SOC_E_NONE) { 4957 LOG_ERROR(BSL_LS_SOC_COMMON, 4958 (BSL_META_U(unit, 4959 "TH3 Temp Intr, Reg access error.\n"))); 4960 } 4961 trval = soc_reg_field_get(unit, pvtmon_result_reg_th3[i], trval, 4962 PVT_DATAf); 4963 /* Convert data to temperature. 4964 * temp = 434.1-(data*0.5350) = (4341000-(trval*5350))/1000; 4965 * Note: Since this is a high temp interrupt we can safely assume 4966 * that this will end up being a +ive value. 4967 */ 4968 trval = (4341000-(trval*5350))/10000; 4969 4970 LOG_ERROR(BSL_LS_SOC_COMMON, 4971 (BSL_META_U(unit, 4972 "TempMon %d: %d deg C.\n"), i, trval)); 4973 (void)soc_event_generate(unit, SOC_SWITCH_EVENT_ALARM, 4974 SOC_SWITCH_EVENT_ALARM_HIGH_TEMP, i, trval); 4975 } 4976 } 4977 4978 /* Acknowledge the interrupt */ 4979 if ((rv = WRITE_TOP_PVTMON_INTR_STATUS_0r(unit, 0xFFFFFFFF)) != SOC_E_NONE) { 4980 LOG_ERROR(BSL_LS_SOC_COMMON, 4981 (BSL_META_U(unit, 4982 "TH3 Temp Intr, Reg access error.\n"))); 4983 } 4984 4985 /* TH3 has HW overtemp protection. So no need to shutdown here. */ 4986 4987 } 4988 4989 int 4990 soc_tomahawk3_temperature_monitor_get(int unit, int temperature_max, 4991 soc_switch_temperature_monitor_t *temperature_array, int *temperature_count) 4992 { 4993 soc_reg_t reg; 4994 int index, i; 4995 uint32 rval; 4996 int cur, peak, fval, cur_fval, peak_fval; 4997 int num_entries_out; 4998 4999 if (temperature_count) { 5000 *temperature_count = 0; 5001 } 5002 if (COUNTOF(pvtmon_result_reg_th3) > temperature_max) { 5003 num_entries_out = temperature_max; 5004 } else { 5005 num_entries_out = COUNTOF(pvtmon_result_reg_th3) - 1; 5006 } 5007 5008 for (index = 0; index < num_entries_out; index++) { 5009 reg = pvtmon_result_reg_th3[index]; 5010 5011 cur_fval = 0; 5012 peak_fval = 0; 5013 5014 for(i = 0; i < NUM_READS; i++) { 5015 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 5016 5017 cur_fval += soc_reg_field_get(unit, reg, rval, PVT_DATAf); 5018 peak_fval += soc_reg_field_get(unit, reg, rval, MIN_PVT_DATAf); 5019 } 5020 cur_fval /= NUM_READS; 5021 peak_fval /= NUM_READS; 5022 5023 cur = (4341000-(cur_fval*5350))/1000; 5024 peak = (4341000-(peak_fval*5350))/1000; 5025 5026 if (temperature_array) { 5027 (temperature_array + index)->curr = cur; 5028 (temperature_array + index)->peak = peak; 5029 } 5030 } 5031 SOC_IF_ERROR_RETURN(READ_AVS_REG_RO_REGISTERS_0_PVT_TEMPERATURE_MNTR_STATUSr(unit, &rval)); 5032 if (soc_reg_field_get(unit, AVS_REG_RO_REGISTERS_0_PVT_TEMPERATURE_MNTR_STATUSr, rval, VALID_DATAf)) { 5033 fval = soc_reg_field_get(unit, AVS_REG_RO_REGISTERS_0_PVT_TEMPERATURE_MNTR_STATUSr, rval, DATAf); 5034 cur = peak = (4341000-(fval*5350))/1000; 5035 if (temperature_array) { 5036 (temperature_array + num_entries_out)->curr = cur; 5037 (temperature_array + num_entries_out)->peak = cur; 5038 } 5039 } 5040 5041 /* TOP_PVT_MON_MIN corresponds to MAX temp. */ 5042 5043 for (index = 0; index < COUNTOF(pvtmon_ctrl_1_reg_th3); index++) { 5044 reg = pvtmon_ctrl_1_reg_th3[index]; 5045 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 5046 soc_reg_field_set(unit, reg, &rval, TOP_PVT_MON_MIN_RST_Lf, 0); 5047 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 5048 soc_reg_field_set(unit, reg, &rval, TOP_PVT_MON_MIN_RST_Lf, 1); 5049 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 5050 } 5051 5052 SOC_IF_ERROR_RETURN(READ_TOP_TMON_CTRL_1r(unit, &rval)); 5053 soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_5_TOP_PVT_MON_MIN_RST_Lf, 0); 5054 soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_6_TOP_PVT_MON_MIN_RST_Lf, 0); 5055 soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_7_TOP_PVT_MON_MIN_RST_Lf, 0); 5056 soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_8_TOP_PVT_MON_MIN_RST_Lf, 0); 5057 soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_9_TOP_PVT_MON_MIN_RST_Lf, 0); 5058 soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_10_TOP_PVT_MON_MIN_RST_Lf, 0); 5059 soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_11_TOP_PVT_MON_MIN_RST_Lf, 0); 5060 soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_12_TOP_PVT_MON_MIN_RST_Lf, 0); 5061 SOC_IF_ERROR_RETURN(WRITE_TOP_TMON_CTRL_1r(unit, rval)); 5062 soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_5_TOP_PVT_MON_MIN_RST_Lf, 1); 5063 soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_6_TOP_PVT_MON_MIN_RST_Lf, 1); 5064 soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_7_TOP_PVT_MON_MIN_RST_Lf, 1); 5065 soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_8_TOP_PVT_MON_MIN_RST_Lf, 1); 5066 soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_9_TOP_PVT_MON_MIN_RST_Lf, 1); 5067 soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_10_TOP_PVT_MON_MIN_RST_Lf, 1); 5068 soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_11_TOP_PVT_MON_MIN_RST_Lf, 1); 5069 soc_reg_field_set(unit, TOP_TMON_CTRL_1r, &rval, PVTMON_12_TOP_PVT_MON_MIN_RST_Lf, 1); 5070 SOC_IF_ERROR_RETURN(WRITE_TOP_TMON_CTRL_1r(unit, rval)); 5071 5072 SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_13_17_CTRL_1r(unit, &rval)); 5073 soc_reg_field_set(unit, TOP_PVTMON_13_17_CTRL_1r, &rval, PVTMON13_TOP_PVT_MON_MIN_RST_Lf, 0); 5074 soc_reg_field_set(unit, TOP_PVTMON_13_17_CTRL_1r, &rval, PVTMON14_TOP_PVT_MON_MIN_RST_Lf, 0); 5075 SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_13_17_CTRL_1r(unit, rval)); 5076 soc_reg_field_set(unit, TOP_PVTMON_13_17_CTRL_1r, &rval, PVTMON13_TOP_PVT_MON_MIN_RST_Lf, 1); 5077 soc_reg_field_set(unit, TOP_PVTMON_13_17_CTRL_1r, &rval, PVTMON14_TOP_PVT_MON_MIN_RST_Lf, 1); 5078 SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_13_17_CTRL_1r(unit, rval)); 5079 5080 if (temperature_count) { 5081 /* *temperature_count = num_entries_out + 1; */ 5082 *temperature_count = num_entries_out; /* Avoid displaying AVS for now */ 5083 } 5084 return SOC_E_NONE; 5085 } 5086 5087 int 5088 soc_tomahawk3_show_ring_osc(int unit) 5089 { 5090 static const struct { 5091 int osc_sel; 5092 soc_field_t field0; 5093 int value0; 5094 soc_field_t field1; 5095 int value1; 5096 char *name; 5097 } osc_tbl[] = { 5098 { 2, IROSC_SELf, 0, INVALIDf, -1, "Core ring 0 five stages" }, 5099 { 2, IROSC_SELf, 1, INVALIDf, -1, "Core ring 0 nine stages" }, 5100 { 3, IROSC_SELf, 0, INVALIDf, -1, "Core ring 1 five stages" }, 5101 { 3, IROSC_SELf, 1, INVALIDf, -1, "Core ring 1 nine stages" }, 5102 { 4, SRAM_OSC_0_PENf, 0, SRAM_OSC_0_NENf, 1, "SRAM ring 0 NMOS" }, 5103 { 5, SRAM_OSC_0_PENf, 1, SRAM_OSC_0_NENf, 0, "SRAM ring 0 PMOS" }, 5104 { 6, SRAM_OSC_1_PENf, 0, SRAM_OSC_1_NENf, 1, "SRAM ring 1 NMOS" }, 5105 { 7, SRAM_OSC_1_PENf, 1, SRAM_OSC_1_NENf, 0, "SRAM ring 1 PMOS" }, 5106 { 8, SRAM_OSC_2_PENf, 0, SRAM_OSC_2_NENf, 1, "SRAM ring 2 NMOS" }, 5107 { 9, SRAM_OSC_2_PENf, 1, SRAM_OSC_2_NENf, 0, "SRAM ring 2 PMOS" }, 5108 { 10, SRAM_OSC_3_PENf, 0, SRAM_OSC_3_NENf, 1, "SRAM ring 3 NMOS" }, 5109 { 11, SRAM_OSC_3_PENf, 1, SRAM_OSC_3_NENf, 0, "SRAM ring 3 PMOS" } 5110 }; 5111 soc_reg_t ctrl_reg, stat_reg; 5112 uint32 rval, fval; 5113 int index, core_clk, quo, rem, frac, retry; 5114 5115 core_clk = SOC_INFO(unit).frequency * 1024; 5116 ctrl_reg = TOP_RING_OSC_CTRLr; 5117 stat_reg = TOP_OSC_COUNT_STATr; 5118 5119 for (index = 0; index < COUNTOF(osc_tbl); index++) { 5120 rval = 0; 5121 /* 5122 * set OSC_CNT_RSTBf to 0 to do softreset 5123 * set OSC_CNT_START to 0 to hold the counter until it selects 5124 * the input signal 5125 */ 5126 SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval)); 5127 soc_reg_field_set(unit, ctrl_reg, &rval, OSC_ENABLEf, 1); 5128 soc_reg_field_set(unit, ctrl_reg, &rval, IROSC_ENf, 1); 5129 soc_reg_field_set(unit, ctrl_reg, &rval, osc_tbl[index].field0, 5130 osc_tbl[index].value0); 5131 if (osc_tbl[index].field1 != INVALIDf) { 5132 soc_reg_field_set(unit, ctrl_reg, &rval, osc_tbl[index].field1, 5133 osc_tbl[index].value1); 5134 } 5135 soc_reg_field_set(unit, ctrl_reg, &rval, OSC_SELf, 5136 osc_tbl[index].osc_sel); 5137 SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval)); 5138 soc_reg_field_set(unit, ctrl_reg, &rval, OSC_CNT_RSTBf, 1); 5139 SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval)); 5140 soc_reg_field_set(unit, ctrl_reg, &rval, OSC_CNT_STARTf, 1); 5141 SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval)); 5142 5143 for (retry = 0; retry < 10; retry++) { 5144 sal_usleep(1000); 5145 SOC_IF_ERROR_RETURN(READ_TOP_OSC_COUNT_STATr(unit, &rval)); 5146 if (!soc_reg_field_get(unit, stat_reg, rval, OSC_CNT_DONEf)) { 5147 continue; 5148 } 5149 5150 fval = soc_reg_field_get(unit, stat_reg, rval, OSC_CNT_VALUEf); 5151 quo = core_clk / fval; 5152 rem = core_clk - quo * fval; 5153 frac = (rem * 10000) / fval; 5154 LOG_CLI((BSL_META_U(unit, 5155 "%s: %d.%04d Mhz\n"), 5156 osc_tbl[index].name, quo, frac)); 5157 break; 5158 } 5159 } 5160 5161 return SOC_E_NONE; 5162 } 5163 5164 STATIC _soc_th3_bst_hw_cb th3_bst_cb; 5165 5166 int 5167 soc_th3_process_mmu_bst(int unit, int itm, soc_field_t field) 5168 { 5169 int rv = SOC_E_NONE; 5170 if (th3_bst_cb != NULL) { 5171 rv = th3_bst_cb(unit); 5172 } 5173 return rv; 5174 } 5175 5176 int soc_th3_set_bst_callback(int unit, _soc_th_bst_hw_cb cb) 5177 { 5178 th3_bst_cb = cb; 5179 return SOC_E_NONE; 5180 } 5181 void 5182 soc_tomahawk3_process_func_intr(void *unit_vp, void *d1, void *d2, void *d3, void *d4) 5183 { 5184 int rv = SOC_E_NONE; 5185 int unit = PTR_TO_INT(unit_vp); 5186 uint32 rval; 5187 char prefix_str[10]; 5188 sal_sprintf(prefix_str, "Unit: %d \n", unit); 5189 5190 rv = READ_L2_MGMT_INTRr(unit, &rval); 5191 if (SOC_FAILURE(rv)) { 5192 LOG_ERROR(BSL_LS_SOC_COMMON, 5193 (BSL_META_U(unit, "Error reading %s reg !!\n"), 5194 SOC_REG_NAME(unit, L2_MGMT_INTRr))); 5195 return; 5196 } 5197 5198 if (soc_reg_field_get(unit, L2_MGMT_INTRr, rval, SER_FIFO_NOT_EMPTYf)) { 5199 (void) soc_tomahawk_process_ser_fifo(unit, SOC_BLK_IPIPE, 5200 0, /* pipe */ 5201 prefix_str, 5202 1, 0, 0); /* l2_mgmt_ser_fifo */ 5203 } 5204 5205 if (soc_feature(unit, soc_feature_l2_overflow)) { 5206 if (soc_reg_field_get(unit, L2_MGMT_INTRr, rval, L2_LEARN_INSERT_FAILUREf)) { 5207 soc_td2_l2_overflow_interrupt_handler(unit); 5208 } 5209 } 5210 5211 sal_usleep(SAL_BOOT_QUICKTURN ? 100000 : 1000); /* Don't reenable too soon */ 5212 if (d1 != NULL) { 5213 #ifdef BCM_CMICM_SUPPORT 5214 if (soc_feature(unit, soc_feature_cmicm)) { 5215 (void) soc_cmicm_intr3_enable(unit, PTR_TO_INT(d1)); 5216 } 5217 #endif 5218 #ifdef BCM_CMICX_SUPPORT 5219 if (soc_feature(unit, soc_feature_cmicx)) { 5220 5221 } 5222 #endif 5223 } 5224 } 5225 5226 soc_pstats_tbl_desc_t 5227 _soc_th3_pstats_tbl_desc_all = {SOC_BLK_NONE, INVALIDm, FALSE, FALSE}; 5228 soc_pstats_tbl_desc_t _soc_th3_pstats_tbl_desc[] = { 5229 /* List all the potential memories */ 5230 { 5231 SOC_BLK_MMU_ITM, 5232 MMU_THDO_BST_TOTAL_QUEUE_PKTSTATm, /* MMU_THDO_BST_TOTAL_QUEUEm,*/ 5233 FALSE, TRUE 5234 } 5235 }; 5236 5237 void 5238 soc_tomahawk3_mmu_pstats_tbl_config_all(int unit) 5239 { 5240 soc_control_t *soc = SOC_CONTROL(unit); 5241 soc_pstats_mem_desc_t *desc, *desc_all; 5242 int ti, mi, di = 0; 5243 5244 desc_all = _soc_th3_pstats_tbl_desc_all.desc; 5245 /* Check and strip invalid memories */ 5246 for (ti = 0; ti < soc->pstats_tbl_desc_count; ti++) { 5247 mi = 0; 5248 desc = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].desc; 5249 while (desc[mi].mem != INVALIDm) { 5250 desc_all[di] = desc[mi]; 5251 di++; 5252 mi++; 5253 } 5254 } 5255 desc_all[di].mem = INVALIDm; 5256 5257 soc->pstats_tbl_desc = &_soc_th3_pstats_tbl_desc_all; 5258 soc->pstats_tbl_desc_count = 1; 5259 } 5260 5261 void 5262 soc_tomahawk3_mmu_pstats_tbl_config(int unit) 5263 { 5264 soc_control_t *soc = SOC_CONTROL(unit); 5265 soc_info_t *si = &SOC_INFO(unit); 5266 soc_pstats_mem_desc_t *desc; 5267 soc_mem_t bmem; 5268 int pe, mor_dma; 5269 int ti, mi, itm, pipe; 5270 uint32 itm_map; 5271 uint32 pipe_map; 5272 5273 soc->pstats_tbl_desc = _soc_th3_pstats_tbl_desc; 5274 soc->pstats_tbl_desc_count = COUNTOF(_soc_th3_pstats_tbl_desc); 5275 soc->pstats_mode = PSTATS_MODE_NULL; 5276 5277 itm_map = si->itm_map; 5278 soc_tomahawk3_pipe_map_get(unit, &pipe_map); 5279 /* Check and strip invalid memories */ 5280 for (ti = 0; ti < soc->pstats_tbl_desc_count; ti++) { 5281 mi = 0; 5282 desc = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].desc; 5283 bmem = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].bmem; 5284 if (bmem == INVALIDm) { 5285 while (desc[mi].mem != INVALIDm) { 5286 desc[mi].width = soc_mem_entry_words(unit, desc[mi].mem); 5287 desc[mi].entries = soc_mem_index_count(unit, desc[mi].mem); 5288 mi++; 5289 } 5290 continue; 5291 } 5292 pe = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].pipe_enum; 5293 mor_dma = ((soc_pstats_tbl_desc_t *)soc->pstats_tbl_desc)[ti].mor_dma; 5294 for (itm = 0; itm < NUM_ITM(unit); itm++) { 5295 if (!(itm_map & (1U << itm))) { 5296 continue; 5297 } 5298 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 5299 if (!(pipe_map & (1 << pipe))) { 5300 continue; 5301 } 5302 desc[mi].mem = pe ? SOC_MEM_UNIQUE_ACC_ITM_PIPE(unit, bmem, itm, pipe) : 5303 SOC_MEM_UNIQUE_ACC(unit, bmem)[itm]; 5304 if (desc[mi].mem == INVALIDm) { 5305 continue; 5306 } 5307 desc[mi].width = soc_mem_entry_words(unit, desc[mi].mem); 5308 desc[mi].entries = soc_mem_index_count(unit, desc[mi].mem); 5309 if (mor_dma) { 5310 desc[mi].mor_dma = TRUE; 5311 } 5312 mi++; 5313 if (!pe) { 5314 break; 5315 } 5316 } 5317 } 5318 desc[mi].mem = INVALIDm; 5319 } 5320 5321 if (soc_property_get(unit, "pstats_desc_all", 1)) { 5322 /* Use single desc chain */ 5323 soc_tomahawk3_mmu_pstats_tbl_config_all(unit); 5324 } 5325 } 5326 5327 int 5328 soc_tomahawk3_mmu_pstats_mode_set(int unit, uint32 flags) 5329 { 5330 #define _SOC_MMU_PSTATS_BLK 2 5331 soc_control_t *soc = SOC_CONTROL(unit); 5332 int i, hwm_mode, cor_en; 5333 int pf = 0; 5334 uint32 rval; 5335 soc_reg_t reg = INVALIDr; 5336 soc_reg_t blk_regs[_SOC_MMU_PSTATS_BLK] = 5337 {MMU_THDO_BST_CONFIGr, MMU_THDI_BSTCONFIGr}; 5338 soc_field_t cor_fields[] = {HWM_CORf, HW_CORf}; 5339 soc_field_t mode_fields[] = {TRACKING_MODEf, TRACKING_MODEf}; 5340 soc_field_t track_fields[] = {BST_TRACK_EN_THDO0f, BST_TRACK_EN_THDO1f, 5341 BST_TRACK_EN_THDI0f, BST_TRACK_EN_THDI1f}; 5342 SOC_PSTATS_LOCK(unit); 5343 5344 hwm_mode = cor_en = 0; 5345 if (flags & _TH3_MMU_PSTATS_HWM_MOD) { 5346 hwm_mode = 1; 5347 pf |= _TH3_MMU_PSTATS_HWM_MOD; 5348 if (flags & _TH3_MMU_PSTATS_RESET_ON_READ) { 5349 cor_en = 1; 5350 pf |= _TH3_MMU_PSTATS_RESET_ON_READ; 5351 } 5352 } 5353 for (i = 0; i < _SOC_MMU_PSTATS_BLK; i++) { 5354 reg = blk_regs[i]; 5355 rval = 0; 5356 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 5357 soc_reg_field_set(unit, reg, &rval, mode_fields[i], hwm_mode); 5358 soc_reg_field_set(unit, reg, &rval, cor_fields[i], cor_en); 5359 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 5360 } 5361 if (flags & _TH3_MMU_PSTATS_ENABLE) { 5362 pf |= _TH3_MMU_PSTATS_ENABLE; 5363 if ((flags & _TH3_MMU_PSTATS_SYNC) || 5364 (flags & _TH3_MMU_PSTATS_HWM_MOD && 5365 flags & _TH3_MMU_PSTATS_RESET_ON_READ)) { 5366 soc->pstats_mode = PSTATS_MODE_PKT_SYNC; 5367 pf |= _TH3_MMU_PSTATS_SYNC; 5368 } 5369 /* enable BST tracking */ 5370 rval = 0; 5371 reg = MMU_GLBCFG_BST_TRACKING_ENABLEr; 5372 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 5373 for (i = 0; i < _SOC_MMU_PSTATS_BLK; i++) { 5374 soc_reg_field_set(unit, reg, &rval, track_fields[2 * i], 1); 5375 soc_reg_field_set(unit, reg, &rval, track_fields[2 * i + 1], 1); 5376 } 5377 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 5378 /* disable snapshot */ 5379 rval = 0; 5380 reg = MMU_GLBCFG_BST_SNAPSHOT_ACTION_ENr; 5381 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 5382 5383 } else { 5384 soc->pstats_mode = PSTATS_MODE_NULL; 5385 } 5386 soc->pstats_flags = pf; 5387 SOC_PSTATS_UNLOCK(unit); 5388 #undef _SOC_MMU_PSTATS_BLK 5389 return SOC_E_NONE; 5390 } 5391 5392 int 5393 soc_tomahawk3_mmu_pstats_mode_get(int unit, uint32 *flags) 5394 { 5395 int pf = 0; 5396 uint32 rval = 0; 5397 int rv; 5398 soc_reg_t reg = INVALIDr; 5399 soc_field_t track_fields[] = {BST_TRACK_EN_THDO0f, BST_TRACK_EN_THDO1f, 5400 BST_TRACK_EN_THDI0f, BST_TRACK_EN_THDI1f}; 5401 5402 SOC_PSTATS_LOCK(unit); 5403 5404 rv = READ_MMU_GLBCFG_BST_TRACKING_ENABLEr(unit, &rval); 5405 5406 if (SOC_FAILURE(rv)) { 5407 SOC_PSTATS_UNLOCK(unit); 5408 return rv; 5409 } 5410 5411 /* If one of the BST thresholds is enabled then PSTATS 5412 is enabled */ 5413 reg = MMU_GLBCFG_BST_TRACKING_ENABLEr; 5414 if (soc_reg_field_get(unit, reg, rval, track_fields[0]) || 5415 soc_reg_field_get(unit, reg, rval, track_fields[1]) || 5416 soc_reg_field_get(unit, reg, rval, track_fields[2]) || 5417 soc_reg_field_get(unit, reg, rval, track_fields[3])) { 5418 pf |= _TH3_MMU_PSTATS_ENABLE; 5419 } 5420 5421 reg = MMU_THDI_BSTCONFIGr; 5422 rval = 0; 5423 SOC_IF_ERROR_RETURN( 5424 soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 5425 5426 if (soc_reg_field_get(unit, reg, rval, TRACKING_MODEf)) { 5427 pf |= _TH3_MMU_PSTATS_HWM_MOD; 5428 if (soc_reg_field_get(unit, reg, rval, HW_CORf)) { 5429 pf |= _TH3_MMU_PSTATS_RESET_ON_READ; 5430 } 5431 } 5432 5433 reg = MMU_THDO_BST_CONFIGr; 5434 rval = 0; 5435 SOC_IF_ERROR_RETURN( 5436 soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 5437 5438 if (soc_reg_field_get(unit, reg, rval, TRACKING_MODEf)) { 5439 pf |= _TH3_MMU_PSTATS_HWM_MOD_EGR; 5440 if (soc_reg_field_get(unit, reg, rval, HWM_CORf)) { 5441 pf |= _TH3_MMU_PSTATS_RESET_ON_READ_EGR; 5442 } 5443 } 5444 5445 SOC_PSTATS_UNLOCK(unit); 5446 *flags = pf; 5447 5448 return SOC_E_NONE; 5449 } 5450 5451 int 5452 soc_tomahawk3_mmu_splitter_reset(int unit) 5453 { 5454 uint32 rval; 5455 5456 SOC_IF_ERROR_RETURN(READ_MMU_GLBCFG_SPLITTERr(unit, &rval)); 5457 soc_reg_field_set(unit, MMU_GLBCFG_SPLITTERr, &rval, RESET_SBUSf, 1); 5458 SOC_IF_ERROR_RETURN(WRITE_MMU_GLBCFG_SPLITTERr(unit, rval)); 5459 5460 return SOC_E_NONE; 5461 } 5462 5463 int 5464 soc_th3_mmu_non_ser_intr_handler(int unit, soc_block_t blocktype, 5465 int mmu_base_index, 5466 uint32 rval_intr_status_reg) 5467 { 5468 int i; 5469 soc_reg_t intr_stat_reg/*, intr_clr_reg*/; 5470 static soc_field_t itm_intr_field_list[] = { 5471 CRB_INT_STATf, 5472 THDI_INT_STATf, 5473 THDR_INT_STATf, 5474 CFAP_INT_STATf, 5475 RQE_INT_STATf, 5476 THDO_INT_STATf, 5477 INVALIDf 5478 }; 5479 static soc_field_t eb_intr_field_list[] = { 5480 EBCTM_INT_STATf, 5481 EBCFP_INT_STATf, 5482 MTRO_INT_STATf, 5483 INVALIDf 5484 }; 5485 5486 if (blocktype == SOC_BLK_MMU_ITM) { 5487 intr_stat_reg = MMU_ITMCFG_CPU_INT_STATr; 5488 /* SW is allowed to clear an interrupt by writing 1'b1 to that status bit. */ 5489 /*intr_clr_reg = MMU_ITMCFG_CPU_INT_STATr;*/ 5490 for (i = 0; itm_intr_field_list[i] != INVALIDf; i++) { 5491 if (!soc_reg_field_get(unit, intr_stat_reg, 5492 rval_intr_status_reg, 5493 itm_intr_field_list[i])) { 5494 continue; 5495 } 5496 switch (itm_intr_field_list[i]) { 5497 case CFAP_INT_STATf: 5498 SOC_IF_ERROR_RETURN(soc_th3_process_itm_cfap_int(unit, 5499 mmu_base_index, itm_intr_field_list[i])); 5500 break; 5501 case THDI_INT_STATf: 5502 SOC_IF_ERROR_RETURN(soc_th3_process_itm_thdi_int(unit, 5503 mmu_base_index, itm_intr_field_list[i])); 5504 break; 5505 case THDO_INT_STATf: 5506 SOC_IF_ERROR_RETURN(soc_th3_process_itm_thdo_int(unit, 5507 mmu_base_index, itm_intr_field_list[i])); 5508 break; 5509 case THDR_INT_STATf: 5510 SOC_IF_ERROR_RETURN(soc_th3_process_itm_thdr_int(unit, 5511 mmu_base_index, itm_intr_field_list[i])); 5512 break; 5513 case RQE_INT_STATf: 5514 SOC_IF_ERROR_RETURN(soc_th3_process_itm_rqe_int(unit, 5515 mmu_base_index, itm_intr_field_list[i])); 5516 break; 5517 case CRB_INT_STATf: 5518 SOC_IF_ERROR_RETURN(soc_th3_process_itm_crb_int(unit, 5519 mmu_base_index, itm_intr_field_list[i])); 5520 break; 5521 default: 5522 LOG_ERROR(BSL_LS_SOC_COMMON, 5523 (BSL_META_U(unit, "Unit: %0d -- Could not service %s " 5524 "intr from itm = %0d \n"), 5525 unit, SOC_FIELD_NAME(unit, itm_intr_field_list[i]), 5526 mmu_base_index)); 5527 break; 5528 } 5529 } 5530 return SOC_E_NONE; 5531 } 5532 5533 if (blocktype == SOC_BLK_MMU_EB) { 5534 intr_stat_reg = MMU_EBCFG_CPU_INT_STATr; 5535 /* SW is allowed to clear an interrupt by writing 1'b1 to that status bit. */ 5536 /*intr_clr_reg = MMU_EBCFG_CPU_INT_STATr;*/ 5537 for (i = 0; eb_intr_field_list[i] != INVALIDf; i++) { 5538 if (!soc_reg_field_get(unit, intr_stat_reg, 5539 rval_intr_status_reg, 5540 eb_intr_field_list[i])) { 5541 continue; 5542 } 5543 switch (eb_intr_field_list[i]) { 5544 case EBCTM_INT_STATf: 5545 SOC_IF_ERROR_RETURN( 5546 soc_th3_process_eb_ebctm_int(unit, mmu_base_index, 5547 eb_intr_field_list[i])); 5548 break; 5549 case EBCFP_INT_STATf: 5550 SOC_IF_ERROR_RETURN( 5551 soc_th3_process_eb_ebcfp_int(unit, mmu_base_index, 5552 eb_intr_field_list[i])); 5553 break; 5554 case MTRO_INT_STATf: 5555 SOC_IF_ERROR_RETURN( 5556 soc_th3_process_eb_mtro_int(unit, mmu_base_index, 5557 eb_intr_field_list[i])); 5558 break; 5559 default: 5560 LOG_ERROR(BSL_LS_SOC_COMMON, 5561 (BSL_META_U(unit, "Unit: %0d -- Could not service %s " 5562 "intr from sc = %0d \n"), 5563 unit, SOC_FIELD_NAME(unit, eb_intr_field_list[i]), 5564 mmu_base_index)); 5565 break; 5566 } 5567 } 5568 return SOC_E_NONE; 5569 } 5570 5571 /* cannot be here for any other blocktype */ 5572 return SOC_E_FAIL; 5573 } 5574 5575 /* 5576 * Function: 5577 * soc_th3_skip_obm_mem_if_pm_down 5578 * Purpose: 5579 * Checks the passed memory. If it's of type 5580 * IDB_OBM*_IOM_STATS_WINDOW_RESULTS*, check to see if the PM it is 5581 * associated with is disabled. If the PM is disabled, tell the calling 5582 * function to skip reading the memory 5583 * Parameters: 5584 * unit - (IN) Unit number. 5585 * mem - (IN) The mem to check 5586 * skip - (OUT) Pointer to tell whether the memory should be 5587 * skipped 5588 * Returns: 5589 * SOC_E_XXX 5590 * Note: 5591 */ 5592 int 5593 soc_th3_skip_obm_mem_if_pm_down(int unit, soc_mem_t mem, int *skip) 5594 { 5595 int i, j, pm_num; 5596 uint32 rval; 5597 soc_reg_t reg = TOP_TSC_ENABLEr; 5598 soc_field_t reg_field[_TH3_PBLKS_PER_DEV] = { 5599 TSC_0_ENABLEf, TSC_1_ENABLEf, TSC_2_ENABLEf, TSC_3_ENABLEf, 5600 TSC_4_ENABLEf, TSC_5_ENABLEf, TSC_6_ENABLEf, TSC_7_ENABLEf, 5601 TSC_8_ENABLEf, TSC_9_ENABLEf, TSC_10_ENABLEf, TSC_11_ENABLEf, 5602 TSC_12_ENABLEf, TSC_13_ENABLEf, TSC_14_ENABLEf, TSC_15_ENABLEf, 5603 TSC_16_ENABLEf, TSC_17_ENABLEf, TSC_18_ENABLEf, TSC_19_ENABLEf, 5604 TSC_20_ENABLEf, TSC_21_ENABLEf, TSC_22_ENABLEf, TSC_23_ENABLEf, 5605 TSC_24_ENABLEf, TSC_25_ENABLEf, TSC_26_ENABLEf, TSC_27_ENABLEf, 5606 TSC_28_ENABLEf, TSC_29_ENABLEf, TSC_30_ENABLEf, TSC_31_ENABLEf 5607 }; 5608 5609 soc_mem_t mem_it, mem_it_unique; 5610 soc_mem_t iom_stats_window_results[] = 5611 { IDB_OBM0_IOM_STATS_WINDOW_RESULTSm, 5612 IDB_OBM1_IOM_STATS_WINDOW_RESULTSm, 5613 IDB_OBM2_IOM_STATS_WINDOW_RESULTSm, 5614 IDB_OBM3_IOM_STATS_WINDOW_RESULTSm }; 5615 5616 5617 if (NULL == skip) { 5618 return SOC_E_PARAM; 5619 } 5620 /* start with skip == 0 */ 5621 *skip = 0; 5622 5623 /* Check if the memory passed is one that we want to check */ 5624 for (i = 0; i < COUNTOF(iom_stats_window_results); i++) { 5625 /* Must be in the range of the starting memory, plus all the 5626 * individual ones for each pipe */ 5627 if (mem >= iom_stats_window_results[i] && 5628 mem <= iom_stats_window_results[i] + _TH3_PIPES_PER_DEV) { 5629 break; 5630 } 5631 } 5632 5633 /* return if not in range */ 5634 if (i == COUNTOF(iom_stats_window_results)) { 5635 return SOC_E_NONE; 5636 } 5637 5638 for (i = 0; i < _TH3_PIPES_PER_DEV; i++) { 5639 for (j = 0; j < _TH3_PBLKS_PER_PIPE; j++) { 5640 /* Get the current port block index */ 5641 mem_it = iom_stats_window_results[j]; 5642 5643 /* Get the port block index for the pipe */ 5644 mem_it_unique = SOC_MEM_UNIQUE_ACC(unit, mem_it)[i]; 5645 5646 5647 /* if the memory is the passed one, check if the port 5648 * macro is disabled */ 5649 if (mem_it == mem || mem_it_unique == mem) { 5650 /* get the pm number associated with this mem */ 5651 pm_num = (i * _TH3_PBLKS_PER_PIPE) + j; 5652 5653 SOC_IF_ERROR_RETURN( 5654 soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 5655 5656 /* check if the PM is disabled */ 5657 if (!soc_reg_field_get(unit, reg, rval, reg_field[pm_num])) { 5658 /* if disabled, skip this memory */ 5659 *skip = 1; 5660 return SOC_E_NONE; 5661 } 5662 } 5663 } 5664 } 5665 return SOC_E_NONE; 5666 } 5667 5668 /* 5669 * Tomahawk chip driver functions. 5670 * Pls keep at the end of this file for easy access. 5671 */ 5672 soc_functions_t soc_tomahawk3_drv_funs = { 5673 _soc_tomahawk3_misc_init, 5674 _soc_tomahawk3_mmu_init, 5675 _soc_tomahawk3_age_timer_get, 5676 _soc_tomahawk3_age_timer_max_get, 5677 _soc_tomahawk3_age_timer_set, 5678 _soc_tomahawk3_tscx_firmware_set, 5679 _soc_tomahawk3_tscx_reg_read, 5680 _soc_tomahawk3_tscx_reg_write, 5681 soc_tomahawk3_bond_info_init 5682 }; 5683 #endif /* BCM_TOMAHAWK3_SUPPORT */ 5684