tomahawk.c (550491B)
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: tomahawk.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 #endif 22 #include <soc/bradley.h> 23 #include <soc/drv.h> 24 #include <soc/error.h> 25 #include <soc/debug.h> 26 #include <soc/mem.h> 27 #include <soc/i2c.h> 28 #include <soc/l2x.h> 29 #include <soc/soc_ser_log.h> 30 31 #ifdef BCM_TOMAHAWK_SUPPORT 32 33 #ifdef ALPM_ENABLE 34 #include <soc/lpm.h> 35 #include <soc/alpm.h> 36 #include <soc/esw/alpm_int.h> 37 #endif /* ALPM_ENABLE */ 38 39 #include <soc/mmu_config.h> 40 #include <soc/tomahawk.h> 41 #include <soc/trident2.h> 42 43 #ifdef BCM_TOMAHAWK2_SUPPORT 44 #include <soc/tomahawk2.h> 45 #endif 46 47 #ifdef BCM_TOMAHAWK3_SUPPORT 48 #include <soc/tomahawk3.h> 49 #endif 50 51 #include <soc/drv.h> 52 #ifdef BCM_IPROC_SUPPORT 53 #include <soc/iproc.h> 54 #endif 55 56 57 #define PORT_BLOCK_BASE_PORT(port) \ 58 (1 + ((SOC_INFO(unit).port_l2p_mapping[port] - 1) & ~0x3)); 59 60 #define _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(ptype) \ 61 si->ptype.num = 0; \ 62 si->ptype.min = si->ptype.max = -1; \ 63 PBMP_ITER(si->ptype.bitmap, it_port) { \ 64 si->ptype.port[si->ptype.num++] = it_port; \ 65 if (si->ptype.min < 0) { \ 66 si->ptype.min = it_port; \ 67 } \ 68 if (it_port > si->ptype.max) { \ 69 si->ptype.max = it_port; \ 70 } \ 71 } 72 73 #define _TH_SUBS_ACC_TYPE_DUPLICATE 9 74 75 static const soc_reg_t idb_grp_tbl_regs[] = { 76 IS_OVR_SUB_GRP0_TBLr, IS_OVR_SUB_GRP1_TBLr, 77 IS_OVR_SUB_GRP2_TBLr, IS_OVR_SUB_GRP3_TBLr, 78 IS_OVR_SUB_GRP4_TBLr, IS_OVR_SUB_GRP5_TBLr 79 }; 80 81 static const soc_reg_t mmu_grp_tbl_regs[] = { 82 OVR_SUB_GRP0_TBLr, OVR_SUB_GRP1_TBLr, 83 OVR_SUB_GRP2_TBLr, OVR_SUB_GRP3_TBLr, 84 OVR_SUB_GRP4_TBLr, OVR_SUB_GRP5_TBLr 85 }; 86 87 static soc_speed_group_info_t soc_speed_group_info[] = { 88 {SOC_TH_SPEED_CLASS_10G, SOC_TH_PORT_MODE_QUAD, 4, 3, "10G_SPEED_CLASS"}, 89 {SOC_TH_SPEED_CLASS_20G, SOC_TH_PORT_MODE_DUAL, 2, 6, "20G_SPEED_CLASS"}, 90 {SOC_TH_SPEED_CLASS_25G, SOC_TH_PORT_MODE_QUAD, 4, 3, "25G_SPEED_CLASS"}, 91 {SOC_TH_SPEED_CLASS_40G, SOC_TH_PORT_MODE_DUAL, 2, 6, "40Gd_SPEED_CLASS"}, 92 {SOC_TH_SPEED_CLASS_40G, SOC_TH_PORT_MODE_SINGLE, 1, 12, "40Gs_SPEED_CLASS"}, 93 {SOC_TH_SPEED_CLASS_50G, SOC_TH_PORT_MODE_DUAL, 2, 6, "50G_SPEED_CLASS"}, 94 {SOC_TH_SPEED_CLASS_100G, SOC_TH_PORT_MODE_SINGLE, 1, 12, "100G_SPEED_CLASS"} 95 }; 96 97 static int soc_speed_group_info_size = sizeof(soc_speed_group_info) / sizeof(soc_speed_group_info_t); 98 99 static int num_shared_alpm_banks[SOC_MAX_NUM_DEVICES] = {0}; 100 101 static soc_mem_t *_soc_th_alpm_bkt_view_map[SOC_MAX_NUM_DEVICES]; 102 static soc_mem_t *_soc_th_lpm_view_map[SOC_MAX_NUM_DEVICES]; 103 104 105 static uint32 _soc_th_iss_log_to_phy_bank_map_shadow[SOC_MAX_NUM_DEVICES]; 106 107 soc_pbmp_t loopback_disable[SOC_MAX_NUM_DEVICES]; 108 109 typedef void (*soc_mmu_config_buf_default_f)(int unit, _soc_mmu_cfg_buf_t *buf, 110 _soc_mmu_device_info_t *devcfg, 111 int lossless); 112 STATIC soc_error_t 113 _soc_tomahawk_flexed_port_speed_get(int unit, soc_th_port_lanes_t *lanes_ctrl, 114 uint32 *port_speed); 115 STATIC int 116 soc_th_port_lanes_ctrl_info_diag(int unit, soc_th_port_lanes_t *lanes_ctrl); 117 STATIC int 118 soc_tomahawk_oversub_group_find(int unit, soc_th_port_lanes_t *lanes_ctrl); 119 STATIC int 120 _soc_tomahawk_port_lanes_update_tdm(int unit, soc_th_port_lanes_t *lanes_ctrl); 121 STATIC int 122 _soc_th_default_pg_headroom(int unit, soc_port_t port, int lossless); 123 STATIC soc_error_t 124 soc_th_os_mixed_sister_port_mode_get(int unit, int initTime, soc_th_port_lanes_t *lanes_ctrl); 125 STATIC int 126 _soc_tomahawk_obm_thresholds_reconfigure(int unit, soc_port_t port_conf); 127 STATIC int 128 soc_th_speed_group_consolidate_check(int unit, soc_th_port_lanes_t *lanes_ctrl, int flag); 129 STATIC int 130 soc_th_speed_group_migrate(int unit, soc_th_port_lanes_t *lanes_ctrl, int flag); 131 132 STATIC int 133 _soc_tomahawk_mmu_port_empty_check(int unit, soc_port_t port, int *empty) 134 { 135 soc_reg_t status_reg = Q_SCHED_PORT_EMPTY_STATUSr; 136 soc_info_t *si = &SOC_INFO(unit); 137 int pipe, phy_port, mmu_port; 138 uint64 rval64; 139 140 pipe = si->port_pipe[port]; 141 phy_port = si->port_l2p_mapping[port]; 142 mmu_port = si->port_p2m_mapping[phy_port]; 143 COMPILER_64_ZERO(rval64); 144 SOC_IF_ERROR_RETURN 145 (soc_reg_get(unit, status_reg, pipe, 0, &rval64)); 146 147 /* Reg config is per pipe */ 148 mmu_port %= SOC_TH_MMU_PORT_STRIDE; 149 150 if (mmu_port < 32) { 151 *empty = COMPILER_64_LO(rval64) & (1 << mmu_port) ? TRUE : FALSE; 152 } else { 153 *empty = COMPILER_64_HI(rval64) & (1 << (mmu_port - 32)) ? 154 TRUE : FALSE; 155 } 156 157 return SOC_E_NONE; 158 } 159 160 int 161 soc_tomahawk_mmu_port_flush_hw(int unit, soc_port_t port, uint32 drain_timeout) 162 { 163 soc_info_t *si; 164 uint64 rval64; 165 uint64 temp64; 166 uint32 rval; 167 int pipe; 168 int empty; 169 soc_timeout_t to; 170 int phy_port, mmu_port; 171 soc_field_t initiate_val; 172 173 COMPILER_64_ZERO(rval64); 174 COMPILER_64_ZERO(temp64); 175 si = &SOC_INFO(unit); 176 pipe = si->port_pipe[port]; 177 178 phy_port = si->port_l2p_mapping[port]; 179 mmu_port = si->port_p2m_mapping[phy_port]; 180 181 /* Reg config is per pipe */ 182 mmu_port %= SOC_TH_MMU_PORT_STRIDE; 183 184 if (mmu_port < 32) { 185 COMPILER_64_SET(temp64, 0, (1 << mmu_port)); 186 } else { 187 COMPILER_64_SET(temp64, (1 << (mmu_port - 32)), 0); 188 } 189 190 SOC_IF_ERROR_RETURN 191 (_soc_tomahawk_mmu_port_empty_check(unit, port, &empty)); 192 193 if (empty) { 194 return SOC_E_NONE; 195 } 196 197 /* Read the Port flush Register */ 198 SOC_IF_ERROR_RETURN 199 (soc_reg_get(unit, Q_SCHED_PORT_FLUSHr, pipe, 0, &rval64)); 200 201 COMPILER_64_OR(rval64, temp64); 202 203 /* Port Not Empty - Initiate Flush */ 204 /* ENABLEf is the only field in FLUSH reg. Hence writing it directly */ 205 SOC_IF_ERROR_RETURN 206 (soc_reg_set(unit, Q_SCHED_PORT_FLUSHr, pipe, 0, rval64)); 207 208 /* Disable Shaper Updates */ 209 SOC_IF_ERROR_RETURN 210 (soc_reg_get(unit, MTRO_PORT_ENTITY_DISABLEr, pipe, 0, &rval64)); 211 212 COMPILER_64_OR(rval64, temp64); 213 214 /* METERING_DISABLEf is the only field in reg. Hence writing it directly */ 215 SOC_IF_ERROR_RETURN 216 (soc_reg_set(unit, MTRO_PORT_ENTITY_DISABLEr, pipe, 0, rval64)); 217 218 /* Initiate RQE FIFO Flush */ 219 SOC_IF_ERROR_RETURN 220 (soc_reg32_get(unit, Q_SCHED_RQE_SNAPSHOTr, pipe, 0, &rval)); 221 initiate_val = 0x1; 222 soc_reg_field_set(unit, Q_SCHED_RQE_SNAPSHOTr, &rval, INITIATEf, initiate_val); 223 SOC_IF_ERROR_RETURN 224 (soc_reg32_set(unit, Q_SCHED_RQE_SNAPSHOTr, pipe, 0, rval)); 225 226 /* Restart timeout */ 227 soc_timeout_init(&to, drain_timeout, 0); 228 for (;;) { 229 if (soc_timeout_check(&to)) { 230 SOC_IF_ERROR_RETURN 231 (soc_reg32_get(unit, Q_SCHED_RQE_SNAPSHOTr, pipe, 0, &rval)); 232 initiate_val = soc_reg_field_get(unit, Q_SCHED_RQE_SNAPSHOTr, 233 rval, INITIATEf); 234 if (initiate_val == 0) { 235 /* Completion of Snapshot Process */ 236 break; 237 } else { 238 LOG_ERROR(BSL_LS_SOC_COMMON, 239 (BSL_META_U(unit, 240 "MacDrainTimeOut:port %d,%s, " 241 "Unable to drain packets from MMU\n"), 242 unit, SOC_PORT_NAME(unit, port))); 243 return SOC_E_INTERNAL; 244 } 245 } 246 } 247 248 COMPILER_64_NOT(temp64); 249 /* Reenable Shaper Updates */ 250 SOC_IF_ERROR_RETURN 251 (soc_reg_get(unit, MTRO_PORT_ENTITY_DISABLEr, pipe, 0, &rval64)); 252 COMPILER_64_AND(rval64, temp64); 253 /* METERING_DISABLEf is the only field in reg. Hence writing it directly */ 254 SOC_IF_ERROR_RETURN 255 (soc_reg_set(unit, MTRO_PORT_ENTITY_DISABLEr, pipe, 0, rval64)); 256 257 /* Read the Port flush Register */ 258 SOC_IF_ERROR_RETURN 259 (soc_reg_get(unit, Q_SCHED_PORT_FLUSHr, pipe, 0, &rval64)); 260 COMPILER_64_AND(rval64, temp64); 261 /* Port Empty - Disable Flush */ 262 /* ENABLEf is the only field in FLUSH reg. Hence writing it directly */ 263 SOC_IF_ERROR_RETURN 264 (soc_reg_set(unit, Q_SCHED_PORT_FLUSHr, pipe, 0, rval64)); 265 266 SOC_IF_ERROR_RETURN 267 (_soc_tomahawk_mmu_port_empty_check(unit, port, &empty)); 268 if (empty) { 269 LOG_VERBOSE(BSL_LS_SOC_COMMON, 270 (BSL_META_U(unit, 271 "MacDrain:port %d,%s, " 272 "Drained successfully\n"), 273 unit, SOC_PORT_NAME(unit, port))); 274 } else { 275 LOG_ERROR(BSL_LS_SOC_COMMON, 276 (BSL_META_U(unit, 277 "MacDrainError:port %d,%s, " 278 "Unable to drain packets from MMU\n"), 279 unit, SOC_PORT_NAME(unit, port))); 280 return SOC_E_INTERNAL; 281 } 282 return SOC_E_NONE; 283 } 284 285 soc_th_latency_table_cfg_t 286 soc_th_tbl_cfg[SOC_MAX_NUM_DEVICES] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; 287 288 STATIC int 289 soc_bcm56168_mem_config(int unit) 290 { 291 soc_persist_t *sop; 292 293 sop = SOC_PERSIST(unit); 294 sop->memState[VFIm].index_max = 4095; 295 sop->memState[VFI_1m].index_max = 4095; 296 sop->memState[EGR_VFIm].index_max = 4095; 297 sop->memState[L2MCm].index_max = 4095; 298 sop->memState[L3_IPMCm].index_max = 2047; 299 sop->memState[L3_IPMC_REMAPm].index_max = 2047; 300 sop->memState[EGR_IPMCm].index_max = 2047; 301 sop->memState[EGR_L3_NEXT_HOPm].index_max = 4095; 302 sop->memState[ING_L3_NEXT_HOPm].index_max = 4095; 303 sop->memState[INITIAL_ING_L3_NEXT_HOPm].index_max = 4095; 304 305 return SOC_E_NONE; 306 } 307 308 int 309 soc_tomahawk_mem_config(int unit) 310 { 311 #define _SOC_TH_DEFIP_MAX_TCAMS 8 312 #define _SOC_TH_DEFIP_REDUCED_TCAMS 3 313 #define _SOC_TH_DEFIP_TCAM_DEPTH SOC_IS_TOMAHAWK2(unit) ? 2048 : 1024 314 #define _SOC_TH_FIXED_TBL_SZ (8 * 1024) 315 soc_persist_t *sop; 316 int l2_entries, fixed_l2_entries = 0, shared_l2_banks = 0; 317 int num_ipv6_128b_entries = 0; 318 int config_v6_entries = 0; 319 int defip_config = 0; 320 int l3_entries, fixed_l3_entries = 0, shared_l3_banks = 0; 321 int fpem_entries, shared_fpem_banks = 0; 322 int num_share_banks_enabled = 4; 323 int share_banks_bitmap_enabled = 0xf; 324 int alpm_enable; 325 int latency; 326 int max_tcams = _SOC_TH_DEFIP_MAX_TCAMS; 327 int tcam_depth = _SOC_TH_DEFIP_TCAM_DEPTH; 328 uint16 dev_id = 0; 329 uint8 rev_id = 0; 330 331 soc_cm_get_id(unit, &dev_id, &rev_id); 332 333 sop = SOC_PERSIST(unit); 334 335 l2_entries = soc_property_get(unit, spn_L2_MEM_ENTRIES, _SOC_TH_FIXED_TBL_SZ); 336 l3_entries = soc_property_get(unit, spn_L3_MEM_ENTRIES, _SOC_TH_FIXED_TBL_SZ); 337 fpem_entries = soc_property_get(unit, spn_FPEM_MEM_ENTRIES, 0); 338 alpm_enable = soc_property_get(unit, spn_L3_ALPM_ENABLE, 0); 339 340 if ((dev_id == BCM56168_DEVICE_ID) || (dev_id == BCM56169_DEVICE_ID)) { 341 max_tcams = _SOC_TH_DEFIP_REDUCED_TCAMS; 342 } 343 344 /* switch latency bypass */ 345 SOC_IF_ERROR_RETURN(soc_th_latency_get(unit, &latency)); 346 347 switch(latency) { 348 case SOC_SWITCH_BYPASS_MODE_NONE: 349 /* 350 * bank 0-1 are dedicated L2 banks (4k entries per bank) 351 * bank 6-9 are dedicated L3 banks (2k entries per bank) 352 * bank 2-5 are shared banks (32k L2/L3 or ALPM(uses all 4 or banks 2,3) 353 * or 16k FPEM entres per bank) 354 */ 355 fixed_l2_entries = _SOC_TH_FIXED_TBL_SZ; /* 8k dedicated L2 entries */ 356 if (l2_entries < fixed_l2_entries) { 357 l2_entries = fixed_l2_entries; 358 shared_l2_banks = 0; 359 } else { 360 l2_entries -= fixed_l2_entries; 361 #if defined(BCM_TOMAHAWK2_SUPPORT) 362 if (SOC_IS_TOMAHAWK2(unit)) { 363 shared_l2_banks = (l2_entries + (64 * 1024 - 1)) / (64 * 1024); 364 l2_entries = fixed_l2_entries + shared_l2_banks * 64 * 1024; 365 } else 366 #endif 367 { 368 shared_l2_banks = (l2_entries + (32 * 1024 - 1)) / (32 * 1024); 369 l2_entries = fixed_l2_entries + shared_l2_banks * 32 * 1024; 370 } 371 } 372 373 fixed_l3_entries = _SOC_TH_FIXED_TBL_SZ; /* 8k dedicated L3 entries */ 374 if (l3_entries < fixed_l3_entries) { 375 l3_entries = fixed_l3_entries; 376 shared_l3_banks = 0; 377 } else { 378 l3_entries -= fixed_l3_entries; 379 #if defined(BCM_TOMAHAWK2_SUPPORT) 380 if (SOC_IS_TOMAHAWK2(unit)) { 381 shared_l3_banks = (l3_entries + (64 * 1024 - 1)) / (64 * 1024); 382 l3_entries = fixed_l3_entries + shared_l3_banks * 64 * 1024; 383 } else 384 #endif 385 if ((dev_id == BCM56168_DEVICE_ID) || (dev_id == BCM56169_DEVICE_ID)) { 386 shared_l3_banks = 0; 387 l3_entries = fixed_l3_entries; 388 } else { 389 shared_l3_banks = (l3_entries + (32 * 1024 - 1)) / (32 * 1024); 390 l3_entries = fixed_l3_entries + shared_l3_banks * 32 * 1024; 391 } 392 } 393 394 #if defined(BCM_TOMAHAWK2_SUPPORT) 395 if (SOC_IS_TOMAHAWK2(unit)) { 396 shared_fpem_banks = (fpem_entries + (32 * 1024 - 1)) / (32 * 1024); 397 fpem_entries = shared_fpem_banks * 32 * 1024; 398 } else 399 #endif 400 { 401 shared_fpem_banks = (fpem_entries + (16 * 1024 - 1)) / (16 * 1024); 402 fpem_entries = shared_fpem_banks * 16 * 1024; 403 } 404 405 if ((dev_id == BCM56168_DEVICE_ID) || (dev_id == BCM56169_DEVICE_ID)) { 406 if (shared_l2_banks + shared_fpem_banks > 1) { 407 return SOC_E_PARAM; 408 } 409 } 410 411 #ifdef BCM_TOMAHAWK2_SUPPORT 412 if (soc_feature(unit, soc_feature_untethered_otp)) { 413 soc_th2_uft_otp_info_get(unit, &num_share_banks_enabled, 414 &share_banks_bitmap_enabled); 415 } 416 #endif 417 418 if (shared_l2_banks + shared_l3_banks + shared_fpem_banks 419 > num_share_banks_enabled) { 420 return SOC_E_PARAM; 421 } 422 423 if (alpm_enable && soc_feature(unit, soc_feature_alpm)) { 424 if (((shared_l2_banks + shared_l3_banks + shared_fpem_banks + 2) 425 > num_share_banks_enabled) 426 /* If any of B2, B3 banks is disabled */ 427 || (~share_banks_bitmap_enabled & 0x3)) { 428 return SOC_E_PARAM; 429 } 430 } 431 432 break; 433 434 case SOC_SWITCH_BYPASS_MODE_LOW: 435 if (l2_entries > _SOC_TH_FIXED_TBL_SZ) { 436 LOG_CLI(("ERROR: Unsupported L2 table size specified in " 437 "config.bcm\n")); 438 LOG_CLI(("INFO : L2 table size reduced to 8K in " 439 "low (L2) latency mode\n")); 440 } 441 if (l3_entries) { 442 LOG_CLI(("ERROR: L3 tables unsupported in " 443 "low (L2) latency mode\n")); 444 LOG_CLI(("INFO : Ignored L3 table config specified " 445 "in config.bcm\n")); 446 } 447 if (alpm_enable) { 448 LOG_CLI(("ERROR: ALPM unsupported in " 449 "low (L2) latency mode\n")); 450 LOG_CLI(("INFO : Ignored ALPM config specified " 451 "in config.bcm\n")); 452 } 453 454 l2_entries = _SOC_TH_FIXED_TBL_SZ; 455 fixed_l2_entries = _SOC_TH_FIXED_TBL_SZ; 456 l3_entries = 0; 457 fixed_l3_entries = 0; 458 max_tcams = tcam_depth = 0; 459 460 fpem_entries = 0; 461 shared_l2_banks = 0; 462 shared_l3_banks = 0; 463 shared_fpem_banks = 0; 464 465 alpm_enable = 0; 466 467 sop->memState[VLAN_MPLSm].index_max = -1; 468 SOC_MEM_PTR(unit, VLAN_MPLSm) = 0; 469 break; 470 471 case SOC_SWITCH_BYPASS_MODE_BALANCED: 472 if (l2_entries > _SOC_TH_FIXED_TBL_SZ) { 473 LOG_CLI(("ERROR: Unsupported L2 table size specified in " 474 "config.bcm\n")); 475 LOG_CLI(("INFO : L2 table size reduced to 8K in " 476 "balanced (L2/L3) latency mode\n")); 477 } 478 if (l3_entries > _SOC_TH_FIXED_TBL_SZ) { 479 480 LOG_CLI(("ERROR: Unsupported L3 table size specified in" 481 "config.bcm\n")); 482 LOG_CLI(("INFO : L3 table size reduced to 8K in " 483 "balanced (L2/L3) latency mode\n")); 484 } 485 if (alpm_enable) { 486 LOG_CLI(("ERROR: ALPM unsupported in " 487 "balanced (L2/L3) latency mode\n")); 488 LOG_CLI(("INFO : Ignored ALPM config specified " 489 "in config.bcm\n")); 490 } 491 492 l2_entries = _SOC_TH_FIXED_TBL_SZ; 493 fixed_l2_entries = _SOC_TH_FIXED_TBL_SZ; 494 l3_entries = _SOC_TH_FIXED_TBL_SZ; 495 fixed_l3_entries = _SOC_TH_FIXED_TBL_SZ; 496 497 fpem_entries = 0; 498 shared_l2_banks = 0; 499 shared_l3_banks = 0; 500 shared_fpem_banks = 0; 501 502 alpm_enable = 0; 503 504 /* In balanced latency mode, only first half of ecmp tables are active */ 505 sop->memState[L3_ECMPm].index_max = 506 sop->memState[L3_ECMPm].index_max/2; 507 sop->memState[L3_ECMP_COUNTm].index_max = 508 sop->memState[L3_ECMP_COUNTm].index_max/2; 509 sop->memState[INITIAL_L3_ECMP_COUNTm].index_max = 510 sop->memState[INITIAL_L3_ECMP_COUNTm].index_max/2; 511 sop->memState[INITIAL_L3_ECMPm].index_max = 512 sop->memState[INITIAL_L3_ECMPm].index_max/2; 513 break; 514 515 default: 516 return SOC_E_INTERNAL; 517 } 518 519 if (soc_feature(unit, soc_feature_alpm)) { 520 _soc_alpm_mode[unit] = alpm_enable; 521 } 522 523 if (SAL_BOOT_QUICKTURN) { 524 sop->memState[MY_STATION_TCAMm].index_max = 7; 525 } 526 527 /* Adjust L2 table size */ 528 sop->memState[L2Xm].index_max = l2_entries - 1; 529 sop->memState[L2_ENTRY_TILEm].index_max = l2_entries - 1; 530 sop->memState[L2_ENTRY_ONLY_TILEm].index_max = l2_entries - 1; 531 sop->memState[L2_ENTRY_ONLY_ECCm].index_max = l2_entries - 1; 532 sop->memState[L2_HITDA_ONLYm].index_max = l2_entries / 4 - 1; 533 sop->memState[L2_HITSA_ONLYm].index_max = l2_entries / 4 - 1; 534 sop->memState[L2_ENTRY_ISS_LPm].index_max = 535 (l2_entries - fixed_l2_entries) / 4 - 1; 536 537 /* Adjust L3 table size */ 538 sop->memState[L3_ENTRY_ONLYm].index_max = l3_entries - 1; 539 sop->memState[L3_ENTRY_IPV4_UNICASTm].index_max = l3_entries - 1; 540 sop->memState[L3_ENTRY_IPV4_MULTICASTm].index_max = l3_entries / 2 - 1; 541 sop->memState[L3_ENTRY_IPV6_UNICASTm].index_max = l3_entries/ 2 - 1; 542 sop->memState[L3_ENTRY_IPV6_MULTICASTm].index_max = l3_entries / 4 - 1; 543 sop->memState[L3_ENTRY_ONLY_ECCm].index_max = l3_entries - 1; 544 sop->memState[L3_ENTRY_HIT_ONLYm].index_max = l3_entries / 4 - 1; 545 sop->memState[L3_ENTRY_ISS_LPm].index_max = 546 (l3_entries - fixed_l3_entries) / 4 - 1; 547 548 /* Adjust FP exact match table size */ 549 sop->memState[EXACT_MATCH_2m].index_max = fpem_entries - 1; 550 sop->memState[EXACT_MATCH_2_PIPE0m].index_max = fpem_entries - 1; 551 sop->memState[EXACT_MATCH_2_PIPE1m].index_max = fpem_entries - 1; 552 sop->memState[EXACT_MATCH_2_PIPE2m].index_max = fpem_entries - 1; 553 sop->memState[EXACT_MATCH_2_PIPE3m].index_max = fpem_entries - 1; 554 sop->memState[EXACT_MATCH_2_ENTRY_ONLYm].index_max = fpem_entries - 1; 555 sop->memState[EXACT_MATCH_2_ENTRY_ONLY_PIPE0m].index_max = 556 fpem_entries - 1; 557 sop->memState[EXACT_MATCH_2_ENTRY_ONLY_PIPE1m].index_max = 558 fpem_entries - 1; 559 sop->memState[EXACT_MATCH_2_ENTRY_ONLY_PIPE2m].index_max = 560 fpem_entries - 1; 561 sop->memState[EXACT_MATCH_2_ENTRY_ONLY_PIPE3m].index_max = 562 fpem_entries - 1; 563 sop->memState[EXACT_MATCH_4m].index_max = fpem_entries / 2 - 1; 564 sop->memState[EXACT_MATCH_4_PIPE0m].index_max = fpem_entries / 2 - 1; 565 sop->memState[EXACT_MATCH_4_PIPE1m].index_max = fpem_entries / 2 - 1; 566 sop->memState[EXACT_MATCH_4_PIPE2m].index_max = fpem_entries / 2 - 1; 567 sop->memState[EXACT_MATCH_4_PIPE3m].index_max = fpem_entries / 2 - 1; 568 sop->memState[EXACT_MATCH_4_ENTRY_ONLYm].index_max = fpem_entries / 2 - 1; 569 sop->memState[EXACT_MATCH_4_ENTRY_ONLY_PIPE0m].index_max = 570 fpem_entries / 2 - 1; 571 sop->memState[EXACT_MATCH_4_ENTRY_ONLY_PIPE1m].index_max = 572 fpem_entries / 2 - 1; 573 sop->memState[EXACT_MATCH_4_ENTRY_ONLY_PIPE2m].index_max = 574 fpem_entries / 2 - 1; 575 sop->memState[EXACT_MATCH_4_ENTRY_ONLY_PIPE3m].index_max = 576 fpem_entries / 2 - 1; 577 sop->memState[EXACT_MATCH_HIT_ONLYm].index_max = fpem_entries / 2 - 1; 578 sop->memState[FPEM_LPm].index_max = fpem_entries / 2 - 1; 579 sop->memState[FPEM_ECCm].index_max = fpem_entries * 2 - 1; 580 sop->memState[FPEM_ECC_PIPE0m].index_max = fpem_entries * 2 - 1; 581 sop->memState[FPEM_ECC_PIPE1m].index_max = fpem_entries * 2 - 1; 582 sop->memState[FPEM_ECC_PIPE2m].index_max = fpem_entries * 2 - 1; 583 sop->memState[FPEM_ECC_PIPE3m].index_max = fpem_entries * 2 - 1; 584 585 SOC_CONTROL(unit)->l3_defip_max_tcams = max_tcams; 586 SOC_CONTROL(unit)->l3_defip_tcam_size = tcam_depth; 587 588 if (SOC_SWITCH_BYPASS_MODE_LOW == latency) { 589 sop->memState[L3_DEFIP_PAIR_128m].index_max = -1; 590 sop->memState[L3_DEFIP_PAIR_128_ONLYm].index_max = -1; 591 sop->memState[L3_DEFIP_PAIR_128_DATA_ONLYm].index_max = -1; 592 sop->memState[L3_DEFIP_PAIR_128_HIT_ONLYm].index_max = -1; 593 sop->memState[L3_DEFIPm].index_max = -1; 594 sop->memState[L3_DEFIP_ONLYm].index_max = -1; 595 sop->memState[L3_DEFIP_DATA_ONLYm].index_max = -1; 596 sop->memState[L3_DEFIP_HIT_ONLYm].index_max = -1; 597 } else { 598 if (soc_property_get(unit, "l3_defip_sizing", TRUE)) { 599 if (!(soc_feature(unit, soc_feature_alpm) && 600 soc_property_get(unit, spn_L3_ALPM_ENABLE, 0))) { 601 defip_config = soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 1); 602 603 if (SOC_IS_TOMAHAWK2(unit)) { 604 num_ipv6_128b_entries = soc_property_get(unit, 605 spn_NUM_IPV6_LPM_128B_ENTRIES, 606 (defip_config ? 4096 : 0)); 607 } else if ((dev_id == BCM56168_DEVICE_ID) || (dev_id == BCM56169_DEVICE_ID)) { 608 num_ipv6_128b_entries = soc_property_get(unit, 609 spn_NUM_IPV6_LPM_128B_ENTRIES, 610 (defip_config ? 512 : 0)); 611 if (num_ipv6_128b_entries > 512) { 612 num_ipv6_128b_entries = 512; 613 } 614 } else { 615 num_ipv6_128b_entries = soc_property_get(unit, 616 spn_NUM_IPV6_LPM_128B_ENTRIES, 617 (defip_config ? 2048 : 0)); 618 } 619 num_ipv6_128b_entries = num_ipv6_128b_entries + 620 (num_ipv6_128b_entries % 2); 621 622 config_v6_entries = num_ipv6_128b_entries; 623 if (soc_property_get(unit, spn_LPM_SCALING_ENABLE, 0)) { 624 num_ipv6_128b_entries = 0; 625 if (!soc_property_get(unit, spn_LPM_IPV6_128B_RESERVED, 1)) { 626 config_v6_entries = ((config_v6_entries / 627 SOC_CONTROL(unit)->l3_defip_tcam_size) + 628 ((config_v6_entries % 629 SOC_CONTROL(unit)->l3_defip_tcam_size) 630 ? 1 : 0)) * SOC_CONTROL(unit)->l3_defip_tcam_size; 631 } 632 } 633 sop->memState[L3_DEFIP_PAIR_128m].index_max = 634 num_ipv6_128b_entries - 1; 635 sop->memState[L3_DEFIP_PAIR_128_ONLYm].index_max = 636 num_ipv6_128b_entries - 1; 637 sop->memState[L3_DEFIP_PAIR_128_DATA_ONLYm].index_max = 638 num_ipv6_128b_entries - 1; 639 sop->memState[L3_DEFIP_PAIR_128_HIT_ONLYm].index_max = 640 num_ipv6_128b_entries - 1; 641 sop->memState[L3_DEFIPm].index_max = 642 (SOC_CONTROL(unit)->l3_defip_max_tcams * 643 SOC_CONTROL(unit)->l3_defip_tcam_size) - 644 (num_ipv6_128b_entries * 2) - 1; 645 646 if (soc_feature(unit, soc_feature_l3_1k_defip_table)) { 647 sop->memState[L3_DEFIPm].index_max = 1023; 648 } 649 650 sop->memState[L3_DEFIP_ONLYm].index_max = 651 sop->memState[L3_DEFIPm].index_max; 652 sop->memState[L3_DEFIP_DATA_ONLYm].index_max = 653 sop->memState[L3_DEFIPm].index_max; 654 sop->memState[L3_DEFIP_HIT_ONLYm].index_max = 655 sop->memState[L3_DEFIPm].index_max; 656 SOC_CONTROL(unit)->l3_defip_index_remap = num_ipv6_128b_entries; 657 } else { 658 if (soc_property_get(unit, spn_IPV6_LPM_128B_ENABLE, 1)) { 659 /* slightly different processing for v6-128 */ 660 if (SOC_IS_TOMAHAWK2(unit)) { 661 num_ipv6_128b_entries = soc_property_get(unit, 662 spn_NUM_IPV6_LPM_128B_ENTRIES, 663 4096); 664 } else { 665 num_ipv6_128b_entries = soc_property_get(unit, 666 spn_NUM_IPV6_LPM_128B_ENTRIES, 667 2048); 668 } 669 num_ipv6_128b_entries = num_ipv6_128b_entries + 670 (num_ipv6_128b_entries % 2); 671 if (soc_tomahawk_alpm_mode_get(unit) == 1 || 672 soc_tomahawk_alpm_mode_get(unit) == 3) { 673 num_ipv6_128b_entries = (num_ipv6_128b_entries + 3) / 4 * 4; 674 } 675 config_v6_entries = num_ipv6_128b_entries; 676 sop->memState[L3_DEFIP_PAIR_128m].index_max = 677 num_ipv6_128b_entries - 1; 678 sop->memState[L3_DEFIP_PAIR_128_ONLYm].index_max = 679 num_ipv6_128b_entries - 1; 680 sop->memState[L3_DEFIP_PAIR_128_DATA_ONLYm].index_max = 681 num_ipv6_128b_entries - 1; 682 sop->memState[L3_DEFIP_PAIR_128_HIT_ONLYm].index_max = 683 num_ipv6_128b_entries - 1; 684 sop->memState[L3_DEFIPm].index_max = 685 (SOC_CONTROL(unit)->l3_defip_max_tcams * 686 SOC_CONTROL(unit)->l3_defip_tcam_size) - 687 (num_ipv6_128b_entries * 2) - 1; 688 689 sop->memState[L3_DEFIP_ONLYm].index_max = 690 sop->memState[L3_DEFIPm].index_max; 691 sop->memState[L3_DEFIP_DATA_ONLYm].index_max = 692 sop->memState[L3_DEFIPm].index_max; 693 sop->memState[L3_DEFIP_HIT_ONLYm].index_max = 694 sop->memState[L3_DEFIPm].index_max; 695 SOC_CONTROL(unit)->l3_defip_index_remap = 696 (num_ipv6_128b_entries / 2) * 2; 697 } else { 698 sop->memState[L3_DEFIP_PAIR_128m].index_max = -1; 699 sop->memState[L3_DEFIP_PAIR_128_ONLYm].index_max = -1; 700 sop->memState[L3_DEFIP_PAIR_128_DATA_ONLYm].index_max = -1; 701 sop->memState[L3_DEFIP_PAIR_128_HIT_ONLYm].index_max = -1; 702 } 703 } 704 soc_l3_defip_indexes_init(unit, config_v6_entries); 705 } 706 }/* switch latency bypass */ 707 708 /* Adjust ALPM table size */ 709 if ((SOC_SWITCH_BYPASS_MODE_NONE == latency) && 710 soc_feature(unit, soc_feature_alpm) && 711 soc_property_get(unit, spn_L3_ALPM_ENABLE, 0)) { 712 /* The check below is sufficient because if ALPM mode is enabled 713 * and number of shared banks used is > 2 we return SOC_E_PARAM 714 * in code at the top of this function. 715 */ 716 if ((shared_l2_banks + shared_l3_banks + shared_fpem_banks > 0) 717 /* If any of B4, B5 banks is disabled, ALPM can only use Bank B2, B3 */ 718 || (~share_banks_bitmap_enabled & 0xc)){ 719 sop->memState[L3_DEFIP_ALPM_RAWm].index_max = 720 sop->memState[L3_DEFIP_ALPM_RAWm].index_max/2; 721 sop->memState[L3_DEFIP_ALPM_IPV4m].index_max = 722 sop->memState[L3_DEFIP_ALPM_IPV4m].index_max/2; 723 sop->memState[L3_DEFIP_ALPM_IPV4_1m].index_max = 724 sop->memState[L3_DEFIP_ALPM_IPV4_1m].index_max/2; 725 sop->memState[L3_DEFIP_ALPM_IPV6_64m].index_max = 726 sop->memState[L3_DEFIP_ALPM_IPV6_64m].index_max/2; 727 sop->memState[L3_DEFIP_ALPM_IPV6_64_1m].index_max = 728 sop->memState[L3_DEFIP_ALPM_IPV6_64_1m].index_max/2; 729 sop->memState[L3_DEFIP_ALPM_IPV6_128m].index_max = 730 sop->memState[L3_DEFIP_ALPM_IPV6_128m].index_max/2; 731 sop->memState[L3_DEFIP_ALPM_HIT_ONLYm].index_max = 732 sop->memState[L3_DEFIP_ALPM_HIT_ONLYm].index_max/2; 733 sop->memState[L3_DEFIP_ALPM_ECCm].index_max = 734 sop->memState[L3_DEFIP_ALPM_ECCm].index_max/2; 735 } 736 } else { 737 sop->memState[L3_DEFIP_ALPM_RAWm].index_max = -1; 738 sop->memState[L3_DEFIP_ALPM_IPV4m].index_max = -1; 739 sop->memState[L3_DEFIP_ALPM_IPV4_1m].index_max = -1; 740 sop->memState[L3_DEFIP_ALPM_IPV6_64m].index_max = -1; 741 sop->memState[L3_DEFIP_ALPM_IPV6_64_1m].index_max = -1; 742 sop->memState[L3_DEFIP_ALPM_IPV6_128m].index_max = -1; 743 sop->memState[L3_DEFIP_ALPM_HIT_ONLYm].index_max = -1; 744 sop->memState[L3_DEFIP_ALPM_ECCm].index_max = -1; 745 } 746 747 if (_soc_th_alpm_bkt_view_map[unit] != NULL) { 748 sal_free(_soc_th_alpm_bkt_view_map[unit]); 749 _soc_th_alpm_bkt_view_map[unit] = NULL; 750 } 751 752 if (NULL == _soc_th_alpm_bkt_view_map[unit]) { 753 if ((_soc_th_alpm_bkt_view_map[unit] = 754 sal_alloc(sizeof(soc_mem_t) * SOC_TH_ALPM_MAX_BKTS(unit), 755 "alpm_bkt_map")) == NULL) { 756 return SOC_E_MEMORY; 757 } 758 } 759 760 sal_memset(_soc_th_alpm_bkt_view_map[unit], INVALIDm, 761 sizeof(soc_mem_t) * SOC_TH_ALPM_MAX_BKTS(unit)); 762 763 if (_soc_th_lpm_view_map[unit] != NULL) { 764 sal_free(_soc_th_lpm_view_map[unit]); 765 _soc_th_lpm_view_map[unit] = NULL; 766 } 767 768 if (NULL == _soc_th_lpm_view_map[unit]) { 769 if ((_soc_th_lpm_view_map[unit] = 770 sal_alloc(sizeof(soc_mem_t) * 771 SOC_L3_DEFIP_MAX_TCAMS_GET(unit) * 772 SOC_L3_DEFIP_TCAM_DEPTH_GET(unit), 773 "lpm_view_map")) == NULL) { 774 return SOC_E_MEMORY; 775 } 776 } 777 778 sal_memset(_soc_th_lpm_view_map[unit], INVALIDm, 779 sizeof(soc_mem_t) * 780 SOC_L3_DEFIP_MAX_TCAMS_GET(unit) * 781 SOC_L3_DEFIP_TCAM_DEPTH_GET(unit)); 782 if ((dev_id == BCM56168_DEVICE_ID) || (dev_id == BCM56169_DEVICE_ID)) { 783 soc_bcm56168_mem_config(unit); 784 } 785 786 /* update tbl cfg to latency subsystem for diag purposes */ 787 soc_th_tbl_cfg[unit].l2_entries = l2_entries; 788 soc_th_tbl_cfg[unit].fixed_l2_entries = fixed_l2_entries; 789 soc_th_tbl_cfg[unit].shared_l2_banks = shared_l2_banks; 790 soc_th_tbl_cfg[unit].l3_entries = l3_entries; 791 soc_th_tbl_cfg[unit].fixed_l3_entries = fixed_l3_entries; 792 soc_th_tbl_cfg[unit].shared_l3_banks = shared_l3_banks; 793 soc_th_tbl_cfg[unit].fpem_entries = fpem_entries; 794 soc_th_tbl_cfg[unit].shared_fpem_banks = shared_fpem_banks; 795 soc_th_tbl_cfg[unit].alpm_enable = alpm_enable; 796 soc_th_tbl_cfg[unit].max_tcams = max_tcams; 797 soc_th_tbl_cfg[unit].tcam_depth = tcam_depth; 798 799 return SOC_E_NONE; 800 } 801 802 int 803 soc_tomahawk_mem_cpu_write_control(int unit, soc_mem_t mem, int copyno, 804 int enable, int *orig_enable) 805 { 806 soc_reg_t reg; 807 soc_field_t field; 808 uint32 rval, fval; 809 int blk, port, block_info_index; 810 uint32 orig_fval, enable_fval, disable_fval; 811 812 enable_fval = 1; 813 disable_fval = 0; 814 815 switch (mem) { 816 case CLPORT_WC_UCMEM_DATAm: 817 reg = CLPORT_WC_UCMEM_CTRLr; 818 field = ACCESS_MODEf; 819 SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) { 820 port = SOC_BLOCK_PORT(unit, blk); 821 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 822 /* It will use the setting from the last block */ 823 *orig_enable = soc_reg_field_get(unit, reg, rval, field); 824 soc_reg_field_set(unit, reg, &rval, field, enable ? 1 : 0); 825 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval)); 826 } 827 return SOC_E_NONE; 828 default: 829 block_info_index = SOC_MEM_BLOCK_ANY(unit, mem); 830 if ((SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_XPE) || 831 #if defined(BCM_TOMAHAWK2_SUPPORT) 832 (SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_SED) || 833 #endif 834 (SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_SC)){ 835 reg = MMU_GCFG_MISCCONFIGr; 836 field = REFRESH_ENf; 837 enable_fval = 0; 838 disable_fval = 1; 839 SOC_IF_ERROR_RETURN 840 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 841 orig_fval = soc_reg_field_get(unit, reg, rval, field); 842 fval = enable ? enable_fval : disable_fval; 843 *orig_enable = orig_fval == enable_fval; 844 if (fval != orig_fval) { 845 soc_reg_field_set(unit, reg, &rval, field, fval); 846 SOC_IF_ERROR_RETURN 847 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 848 } 849 } 850 return _soc_trident2_mem_cpu_write_control(unit, mem, copyno, 851 enable, orig_enable); 852 } 853 return SOC_E_NONE; 854 } 855 856 int 857 soc_tomahawk_reg_cpu_write_control(int unit, int enable) 858 { 859 uint32 intfo_dis = 0; 860 861 if (enable) { 862 /* Disable HW updates */ 863 soc_reg_field_set(unit, INTFO_HW_UPDATE_DISr, &intfo_dis, 864 EG_SPf, 1); 865 soc_reg_field_set(unit, INTFO_HW_UPDATE_DISr, &intfo_dis, 866 ING_SPf, 1); 867 soc_reg_field_set(unit, INTFO_HW_UPDATE_DISr, &intfo_dis, 868 CONGST_STf, 1); 869 } 870 SOC_IF_ERROR_RETURN(WRITE_INTFO_HW_UPDATE_DISr(unit, intfo_dis)); 871 872 return SOC_E_NONE; 873 } 874 875 uint32 _soc_th_mmu_port(int unit, int port) 876 { 877 soc_info_t *si = &SOC_INFO(unit); 878 return si->port_p2m_mapping[si->port_l2p_mapping[port]]; 879 } 880 881 /* 882 * CPU port (mmu port 32): 48 MC queues 883 * Loopback port (mmu port 33,97,161,225): 10 MC queues 884 * Mgmt port (mmu port 96,160): 10 UC, 10 MC queues 885 */ 886 int 887 soc_tomahawk_num_cosq_init_port(int unit, int port) 888 { 889 #define CPU_MCQ_BASE 330 /* CPU port MC queue base index */ 890 #define LB_MCQ_BASE 320 /* LB ports MC queue base index */ 891 #define MGMT_UCQ_BASE 320 /* Mgmt ports UC queue base index */ 892 #define MGMT_MCQ_BASE 330 /* Mgmt ports MC queue base index */ 893 soc_info_t *si; 894 int mmu_port; 895 896 si = &SOC_INFO(unit); 897 mmu_port = SOC_TH_MMU_PORT(unit, port); 898 899 if (IS_CPU_PORT(unit, port)) { 900 si->port_num_cosq[port] = 48; 901 si->port_cosq_base[port] = CPU_MCQ_BASE; 902 } else if (IS_LB_PORT(unit, port)) { 903 si->port_num_cosq[port] = 10; 904 si->port_cosq_base[port] = LB_MCQ_BASE; 905 } else if (SOC_PBMP_MEMBER(si->management_pbm, port)) { 906 si->port_num_cosq[port] = 10; 907 si->port_cosq_base[port] = MGMT_MCQ_BASE; 908 si->port_num_uc_cosq[port] = 10; 909 si->port_uc_cosq_base[port] = MGMT_UCQ_BASE; 910 } else { 911 if (mmu_port == -1) { 912 return SOC_E_INTERNAL; 913 } 914 915 si->port_num_cosq[port] = 10; 916 si->port_cosq_base[port] = 917 (mmu_port % SOC_TH_MMU_PORT_STRIDE) * 10; 918 si->port_num_uc_cosq[port] = 10; 919 si->port_uc_cosq_base[port] = 920 (mmu_port % SOC_TH_MMU_PORT_STRIDE) * 10; 921 si->port_num_ext_cosq[port] = 0; 922 } 923 924 return SOC_E_NONE; 925 } 926 927 928 /* 929 * CPU port (mmu port 32): 48 MC queues 930 * Loopback port (mmu port 33,97,161,225): 10 MC queues 931 * Mgmt port (mmu port 96,160): 10 UC, 10 MC queues 932 */ 933 int 934 soc_tomahawk_num_cosq_init(int unit) 935 { 936 int port; 937 938 PBMP_ALL_ITER(unit, port) { 939 SOC_IF_ERROR_RETURN 940 (soc_tomahawk_num_cosq_init_port(unit, port)); 941 } 942 943 return SOC_E_NONE; 944 } 945 946 STATIC int 947 soc_tomahawk_max_frequency_get(int unit, uint16 dev_id, uint8 rev_id, 948 int skew_id, int *frequency) 949 { 950 switch (dev_id) { 951 default: 952 *frequency = 850; 953 } 954 955 return SOC_E_NONE; 956 } 957 958 void 959 soc_tomahawk_tsc_map_get(int unit, uint32 *tsc_map) 960 { 961 *tsc_map = 0xffffffff; 962 } 963 964 void 965 soc_tomahawk_pipe_map_get(int unit, uint32 *pipe_map) 966 { 967 soc_info_t *si; 968 int port; 969 970 si = &SOC_INFO(unit); 971 972 *pipe_map = 0; 973 PBMP_LB_ITER(unit, port) { 974 *pipe_map |= 1 << si->port_pipe[port]; 975 } 976 } 977 978 /* 979 * #1 single: 100 - x - x - x SOC_TH_PORT_RATIO_SINGLE 980 * #2 single: 40 - x - x - x SOC_TH_PORT_RATIO_TRI_023_2_1_1 981 * #3 dual: 50 - x - 50 - x SOC_TH_PORT_RATIO_DUAL_1_1 982 * #4 dual: 40 - x - 40 - x SOC_TH_PORT_RATIO_DUAL_1_1 983 * #5 dual: 20 - x - 20 - x SOC_TH_PORT_RATIO_DUAL_1_1 984 * #6 dual: 40 - x - 20 - x SOC_TH_PORT_RATIO_DUAL_2_1 985 * #7 dual: 20 - x - 40 - x SOC_TH_PORT_RATIO_DUAL_1_2 986 * #8 tri: 50 - x - 25/x - 25/x SOC_TH_PORT_RATIO_TRI_023_2_1_1 987 * #9 tri: 20 - x - 10/x - 10/x SOC_TH_PORT_RATIO_TRI_023_2_1_1 988 * #10 tri: 40 - x - 10/x - 10/x SOC_TH_PORT_RATIO_TRI_023_4_1_1 989 * #11 tri: 25/x - 25/x - 50 - x SOC_TH_PORT_RATIO_TRI_012_1_1_2 990 * #12 tri: 10/x - 10/x - 20 - x SOC_TH_PORT_RATIO_TRI_012_1_1_2 991 * #13 tri: 10/x - 10/x - 40 - x SOC_TH_PORT_RATIO_TRI_012_1_1_4 992 * #14 quad: 25/x - 25/x - 25/x - 25/x SOC_TH_PORT_RATIO_QUAD 993 * #15 quad: 10/x - 10/x - 10/x - 10/x SOC_TH_PORT_RATIO_QUAD 994 */ 995 void 996 soc_tomahawk_port_ratio_get(int unit, int initTime, int clport, int *mode) 997 { 998 soc_info_t *si; 999 int port, phy_port_base, lane; 1000 int num_lanes[_TH_PORTS_PER_PBLK]; 1001 int speed_max[_TH_PORTS_PER_PBLK]; 1002 int cur_mode; 1003 int port_sub, port_sis; 1004 1005 si = &SOC_INFO(unit); 1006 phy_port_base = 1 + clport * _TH_PORTS_PER_PBLK; 1007 for (lane = 0; lane < _TH_PORTS_PER_PBLK; lane += 2) { 1008 port = si->port_p2l_mapping[phy_port_base + lane]; 1009 if (port == -1 || SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) { 1010 num_lanes[lane] = -1; 1011 speed_max[lane] = -1; 1012 } else { 1013 num_lanes[lane] = si->port_num_lanes[port]; 1014 /* At init time port_speed_max_max contains port init speed_max and 1015 * at run time during flex port opeartion, init_speed_max 1016 * contains current port speed_max 1017 */ 1018 speed_max[lane] = initTime ? si->port_speed_max[port] : 1019 si->port_init_speed[port]; 1020 } 1021 } 1022 1023 if (num_lanes[0] == 4) { 1024 *mode = SOC_TH_PORT_RATIO_SINGLE; 1025 } else if (num_lanes[0] == 2 && num_lanes[2] == 2) { 1026 if (speed_max[0] == speed_max[2]) { 1027 *mode = SOC_TH_PORT_RATIO_DUAL_1_1; 1028 } else if (speed_max[0] > speed_max[2]) { 1029 *mode = SOC_TH_PORT_RATIO_DUAL_2_1; 1030 } else { 1031 *mode = SOC_TH_PORT_RATIO_DUAL_1_2; 1032 } 1033 } else if (num_lanes[0] == 2) { 1034 if (num_lanes[2] == -1) { 1035 *mode = SOC_TH_PORT_RATIO_DUAL_1_1; 1036 } else { 1037 *mode = cur_mode = (speed_max[0] == 20000 || speed_max[0] == 21000 || 1038 speed_max[0] == 50000 || speed_max[0] == 53000) ? 1039 SOC_TH_PORT_RATIO_TRI_023_2_1_1 : SOC_TH_PORT_RATIO_TRI_023_4_1_1; 1040 if (initTime && si->os_mixed_sister_25_50_enable) { 1041 *mode = ((speed_max[0] == 50000 && speed_max[2] == 25000) || 1042 (speed_max[0] == 53000 && speed_max[2] == 27000)) ? 1043 SOC_TH_PORT_RATIO_DUAL_1_1 : cur_mode; 1044 } 1045 } 1046 } else if (num_lanes[2] == 2) { 1047 if (num_lanes[0] == -1) { 1048 *mode = SOC_TH_PORT_RATIO_DUAL_1_1; 1049 } else { 1050 *mode = cur_mode = (speed_max[2] == 20000 || speed_max[2] == 21000 || 1051 speed_max[2] == 50000 || speed_max[2] == 53000) ? 1052 SOC_TH_PORT_RATIO_TRI_012_1_1_2 : SOC_TH_PORT_RATIO_TRI_012_1_1_4; 1053 if (initTime && si->os_mixed_sister_25_50_enable) { 1054 *mode = ((speed_max[0] == 25000 && speed_max[2] == 50000) || 1055 (speed_max[0] == 27000 && speed_max[2] == 53000)) ? 1056 SOC_TH_PORT_RATIO_DUAL_1_1 : cur_mode; 1057 } 1058 } 1059 } else { 1060 *mode = cur_mode = SOC_TH_PORT_RATIO_QUAD; 1061 1062 if (initTime && si->os_mixed_sister_25_50_enable) { 1063 port_sub = si->port_p2l_mapping[phy_port_base + 1]; 1064 port_sis = si->port_p2l_mapping[phy_port_base + 3]; 1065 *mode = (((speed_max[0] == 25000 && speed_max[2] == 25000) || 1066 (speed_max[0] == 27000 && speed_max[2] == 27000)) && 1067 SOC_PBMP_MEMBER(si->all.disabled_bitmap, port_sub) && 1068 SOC_PBMP_MEMBER(si->all.disabled_bitmap, port_sis)) ? 1069 SOC_TH_PORT_RATIO_DUAL_1_1 : cur_mode; 1070 } 1071 } 1072 } 1073 1074 #if 0 1075 STATIC void 1076 _soc_tomahawk_pipe_bandwidth_get(int unit, int pipe, 1077 int *max_pipe_core_bandwidth, 1078 int *pipe_linerate_bandwidth, 1079 int *pipe_oversub_bandwidth) 1080 { 1081 soc_info_t *si; 1082 int port; 1083 int bandwidth; 1084 1085 si = &SOC_INFO(unit); 1086 1087 *max_pipe_core_bandwidth = si->bandwidth / 4; 1088 1089 *pipe_linerate_bandwidth = 0; 1090 *pipe_oversub_bandwidth = 0; 1091 PBMP_PORT_ITER(unit, port) { 1092 if (si->port_pipe[port] != pipe) { 1093 continue; 1094 } 1095 bandwidth = si->port_speed_max[port] >= 2500 ? 1096 si->port_speed_max[port] : 2500; 1097 if (SOC_PBMP_MEMBER(si->oversub_pbm, port)) { 1098 *pipe_oversub_bandwidth += bandwidth; 1099 } else { 1100 *pipe_linerate_bandwidth += bandwidth; 1101 } 1102 } 1103 /* 10G cpu/management, 5G loopback, 10G purge/refresh */ 1104 *pipe_linerate_bandwidth += 25; 1105 } 1106 #endif 1107 1108 /* 1109 * Oversubscription group speed class encoding 1110 * 0 - 0 1111 * 1 - 2 (10G) 1112 * 2 - 4 (20G) 1113 * 3 - 5 (25G) 1114 * 4 - 8 (40G) 1115 * 5 - 10 (50G) 1116 * 6 - 20 (100G) 1117 */ 1118 void 1119 _soc_tomahawk_speed_to_ovs_class_mapping(int unit, int speed, int *ovs_class) 1120 { 1121 if (speed >= 40000) { 1122 if (speed >= 100000) { 1123 *ovs_class = 6; 1124 } else if (speed >= 50000) { 1125 *ovs_class = 5; 1126 } else { 1127 *ovs_class = 4; 1128 } 1129 } else { 1130 if (speed >= 25000) { 1131 *ovs_class = 3; 1132 } else if (speed >= 20000) { 1133 *ovs_class = 2; 1134 } else { 1135 *ovs_class = 1; 1136 } 1137 } 1138 } 1139 1140 void 1141 _soc_tomahawk_speed_to_slot_mapping(int unit, int speed, int *slot) 1142 { 1143 if (speed >= 40000) { 1144 if (speed >= 100000) { 1145 *slot = 40; 1146 } else if (speed >= 50000) { 1147 *slot = 20; 1148 } else { 1149 *slot = 16; 1150 } 1151 } else { 1152 if (speed >= 25000) { 1153 *slot = 10; 1154 } else if (speed >= 20000) { 1155 *slot = 8; 1156 } else if (speed >= 10000) { 1157 *slot = 4; 1158 } else { 1159 *slot = 1; 1160 } 1161 } 1162 } 1163 1164 static int _soc_th_port_speed_cap[SOC_MAX_NUM_DEVICES][132] = {{ 0 }}; 1165 1166 STATIC int 1167 _soc_th_post_mmu_init_update(int unit) 1168 { 1169 int port; 1170 soc_info_t *si = &SOC_INFO(unit); 1171 1172 #ifdef BCM_TOMAHAWK2_SUPPORT 1173 if (SOC_IS_TOMAHAWK2(unit)) { 1174 return soc_th2_post_mmu_init_update(unit); 1175 } 1176 #endif 1177 1178 PBMP_ALL_ITER(unit, port) { 1179 /* Set init speed to max speed by default */ 1180 si->port_init_speed[port] = si->port_speed_max[port]; 1181 if (_soc_th_port_speed_cap[unit][port]) { 1182 /* If cap speed is available then adjust max speed for further use */ 1183 si->port_speed_max[port] = _soc_th_port_speed_cap[unit][port]; 1184 } 1185 } 1186 return SOC_E_NONE; 1187 } 1188 1189 /* 1190 * FUNCTION : soc_th_bypass_unused_pm 1191 * ARGS: 1192 * unit - IN, unit number 1193 * Description : 1194 * Bypass unused port blocks, by programming TOP_TSC_ENABLEr 1195 * appropriately. 1196 */ 1197 soc_error_t 1198 soc_th_bypass_unused_pm(int unit) 1199 { 1200 int port, phy_port, pm, block, bn; 1201 uint32 rval = 0, orval, xrval; 1202 soc_info_t *si = &SOC_INFO(unit); 1203 uint8 used_pm_map[_TH_PBLKS_PER_DEV + 1]; /* #CLPORT + #XLPORT */ 1204 soc_reg_t reg = TOP_TSC_ENABLEr; 1205 soc_field_t reg_field[_TH_PBLKS_PER_DEV] = { 1206 TSC_0_ENABLEf, TSC_1_ENABLEf, TSC_2_ENABLEf, TSC_3_ENABLEf, 1207 TSC_4_ENABLEf, TSC_5_ENABLEf, TSC_6_ENABLEf, TSC_7_ENABLEf, 1208 TSC_8_ENABLEf, TSC_9_ENABLEf, TSC_10_ENABLEf, TSC_11_ENABLEf, 1209 TSC_12_ENABLEf, TSC_13_ENABLEf, TSC_14_ENABLEf, TSC_15_ENABLEf, 1210 TSC_16_ENABLEf, TSC_17_ENABLEf, TSC_18_ENABLEf, TSC_19_ENABLEf, 1211 TSC_20_ENABLEf, TSC_21_ENABLEf, TSC_22_ENABLEf, TSC_23_ENABLEf, 1212 TSC_24_ENABLEf, TSC_25_ENABLEf, TSC_26_ENABLEf, TSC_27_ENABLEf, 1213 TSC_28_ENABLEf, TSC_29_ENABLEf, TSC_30_ENABLEf, TSC_31_ENABLEf 1214 }; 1215 1216 sal_memset(used_pm_map, 0, sizeof(used_pm_map)); 1217 for (phy_port = 1; phy_port <= _TH_PORTS_PER_DEV; phy_port++) { 1218 port = si->port_p2l_mapping[phy_port]; 1219 pm = si->port_serdes[port]; 1220 if ((-1 != pm) && (0 == used_pm_map[pm])) { 1221 used_pm_map[pm] = 1; 1222 } 1223 } 1224 SOC_IF_ERROR_RETURN(READ_TOP_TSC_ENABLEr(unit, &rval)); 1225 orval = rval; 1226 /* Upper loop bound omits XLPORT block intentionally */ 1227 for (pm = 0; pm < _TH_PBLKS_PER_DEV; pm++) { 1228 /* If PM is not used, bypass it */ 1229 if (0 == used_pm_map[pm]) { 1230 soc_reg_field_set(unit, reg, &rval, reg_field[pm], 0); 1231 phy_port = 1 + (pm * _TH_PORTS_PER_PBLK); 1232 block = SOC_PORT_BLOCK(unit, phy_port); 1233 /* Invalidate port block in soc info */ 1234 if (SOC_BLK_CLPORT == SOC_BLOCK_INFO(unit, block).type) { 1235 si->block_valid[block] = 0; 1236 } 1237 } 1238 } 1239 if (rval != orval) { 1240 /*Calculate different bits number between old and new*/ 1241 xrval = rval ^ orval; 1242 for (bn = 0; xrval != 0; bn++) { 1243 xrval &= (xrval - 1); 1244 } 1245 1246 /*Do two steps configuration change for the case of different bits number beyond 10*/ 1247 if (bn > 10) { 1248 /*Change half of those different bits to new at first*/ 1249 bn /= 2; 1250 xrval = rval ^ orval; 1251 do { 1252 xrval &= (xrval-1); 1253 } while (bn-- > 0); 1254 xrval ^= rval; 1255 SOC_IF_ERROR_RETURN(WRITE_TOP_TSC_ENABLEr(unit, xrval)); 1256 sal_usleep(100000); 1257 } 1258 SOC_IF_ERROR_RETURN(WRITE_TOP_TSC_ENABLEr(unit, rval)); 1259 sal_usleep(100000); 1260 } 1261 1262 return SOC_E_NONE; 1263 } 1264 1265 #ifdef BCM_TOMAHAWKX_SUPPORT 1266 static int 1267 _soc_tomahawk_phy_dev_port_check(int unit, int phy_port, int dev_port) 1268 { 1269 int num_phy_port = 136; 1270 1271 if( phy_port < 0 || phy_port >= num_phy_port) { 1272 return FALSE; 1273 } else if ( phy_port >= 1 && phy_port <= 32) { 1274 return ( dev_port >= 1 && dev_port <=32 ); 1275 } else if ( phy_port >= 33 && phy_port <= 64) { 1276 return ( dev_port >= 34 && dev_port <= 66 ); 1277 } else if ( phy_port >= 65 && phy_port <= 96) { 1278 return ( dev_port >= 68 && dev_port <= 100 ); 1279 } else if ( phy_port >= 97 && phy_port <= 128) { 1280 return ( dev_port >= 102 && dev_port <= 133 ); 1281 } else if ( phy_port == 129) { 1282 return ( dev_port >= 34 && dev_port <= 66 ); 1283 } else if ( phy_port == 131) { 1284 return ( dev_port >= 68 && dev_port <= 100 ); 1285 } else { 1286 /*skip LBPORT(132,133,134,135) , CPU port(0) and hole (130)*/ 1287 return TRUE; 1288 } 1289 1290 } 1291 #endif 1292 1293 /* 1294 * Tomahawk port mapping 1295 * 1296 * physical idb/ device mmu 1297 * port idb port port port 1298 * CMIC 0 0/32 0 32 1299 * CLPORT0-7 1-32 0/0-31 1-32 0-31 1300 * CLPORT8-15 33-64 1/0-31 34-66 64-95 1301 * CLPORT16-23 65-96 2/0-31 68-100 128-159 1302 * CLPORT24-31 97-128 3/0-31 102-133 192-223 1303 * XLPORT0/0 129 1/32 34-66 96 1304 * hole 130 3/32 134 224 1305 * XLPORT0/2 131 2/32 68-100 160 1306 * LBPORT0 132 0/33 33 33 1307 * LBPORT1 133 1/33 67 97 1308 * LBPORT2 134 2/33 101 161 1309 * LBPORT3 135 3/33 135 225 1310 * Software uses device port 135 for LBPORT3 although it can be 134 1311 * Device port number is flexible within the above range 1312 * Although MMU port number is flexible within the above range, it is 1313 * configured as a fixed mapped to physical port number 1314 */ 1315 int 1316 soc_tomahawk_port_config_init(int unit, uint16 dev_id) 1317 { 1318 #ifdef BCM_TOMAHAWKX_SUPPORT 1319 soc_info_t *si; 1320 char *config_str, *sub_str, *sub_str_end; 1321 static const char str_2p5[] = "2.5"; 1322 char str_buf[8]; 1323 int rv, oversub_mode, frequency, os_mixed_sister_25_50_enable; 1324 int num_port, num_phy_port, num_mmu_port; 1325 int port, phy_port, mmu_port, idb_port; 1326 int pipe, xpe, sc, index, bandwidth_cap; 1327 int port_bandwidth, freq_list_len; 1328 char option1, option2; 1329 uint32 pipe_map, xpe_map, sc_map, ipipe_map, epipe_map; 1330 soc_pbmp_t oversub_pbm; 1331 static const int freq_list[] = { 850, 765, 672, 645, 545 }; 1332 static const struct { 1333 int port; 1334 int phy_port; 1335 int pipe; 1336 int idb_port; 1337 int mmu_port; 1338 } fixed_ports[] = { 1339 { 0, 0, 0, 32, 32 }, /* cpu port */ 1340 { 33, 132, 0, 33, 33 }, /* loopback port 0 */ 1341 { 67, 133, 1, 33, 97 }, /* loopback port 1 */ 1342 { 101, 134, 2, 33, 161 }, /* loopback port 2 */ 1343 { 135, 135, 3, 33, 225 } /* loopback port 3 */ 1344 }; 1345 1346 si = &SOC_INFO(unit); 1347 1348 si->flex_eligible = FALSE; 1349 1350 num_phy_port = 136; 1351 num_port = 136; 1352 num_mmu_port = 226; 1353 1354 /* Can't read TOP register at this point */ 1355 soc_tomahawk_max_frequency_get(unit, dev_id, -1, -1, &si->frequency); 1356 frequency = soc_property_get(unit, spn_CORE_CLOCK_FREQUENCY, -1); 1357 /*frequency = rev_id == BCM56965_A0_REV_ID ? 545 : frequency;*/ 1358 1359 si->bandwidth = /*rev_id == BCM56965_A0_REV_ID ? 1024000 :*/ 2048000; 1360 1361 if (frequency != -1 && frequency < si->frequency) { 1362 freq_list_len = COUNTOF(freq_list); 1363 for (index = 1; index < freq_list_len; index++) { /* skip index 0 */ 1364 if (freq_list[index] < si->frequency && 1365 frequency == freq_list[index]) { 1366 break; 1367 } 1368 } 1369 1370 if (index < freq_list_len) { 1371 si->frequency = frequency; 1372 } else { 1373 LOG_CLI((BSL_META_U(unit, 1374 "*** Input core clock frequency %dMHz is not " 1375 "supported!\n"), frequency)); 1376 } 1377 } else if (frequency > si->frequency) { 1378 LOG_CLI((BSL_META_U(unit, 1379 "*** Input core clock frequency %dMHz is not supported!\n"), 1380 frequency)); 1381 } 1382 1383 1384 SOC_PBMP_CLEAR(oversub_pbm); 1385 oversub_mode = soc_property_get(unit, spn_OVERSUBSCRIBE_MODE, 0); 1386 oversub_pbm = soc_property_get_pbmp(unit, spn_PBMP_OVERSUBSCRIBE, 0); 1387 oversub_mode = oversub_mode || SOC_PBMP_NOT_NULL(oversub_pbm); 1388 si->oversub_mode = oversub_mode; 1389 os_mixed_sister_25_50_enable = soc_property_get(unit, spn_OVERSUBSCRIBE_MIXED_SISTER_25_50_ENABLE, 0); 1390 if (oversub_mode) { 1391 si->os_mixed_sister_25_50_enable = os_mixed_sister_25_50_enable; 1392 } else { 1393 si->os_mixed_sister_25_50_enable = 0; 1394 } 1395 1396 for (phy_port = 0; phy_port < num_phy_port; phy_port++) { 1397 si->port_p2l_mapping[phy_port] = -1; 1398 si->port_p2m_mapping[phy_port] = -1; 1399 } 1400 for (port = 0; port < num_port; port++) { 1401 si->port_l2p_mapping[port] = -1; 1402 si->port_l2i_mapping[port] = -1; 1403 si->port_speed_max[port] = -1; 1404 si->port_group[port] = -1; 1405 si->port_serdes[port] = -1; 1406 si->port_pipe[port] = -1; 1407 si->port_num_lanes[port] = -1; 1408 } 1409 for (mmu_port = 0; mmu_port < num_mmu_port; mmu_port++) { 1410 si->port_m2p_mapping[mmu_port] = -1; 1411 } 1412 SOC_PBMP_CLEAR(si->eq_pbm); 1413 SOC_PBMP_CLEAR(si->management_pbm); 1414 for (pipe = 0; pipe < SOC_MAX_NUM_PIPES; pipe++) { 1415 SOC_PBMP_CLEAR(si->pipe_pbm[pipe]); 1416 }; 1417 SOC_PBMP_CLEAR(si->oversub_pbm); 1418 SOC_PBMP_CLEAR(si->all.disabled_bitmap); 1419 1420 /* Populate the fixed mapped ports */ 1421 for (index = 0; index < COUNTOF(fixed_ports); index++) { 1422 port = fixed_ports[index].port; 1423 phy_port = fixed_ports[index].phy_port; 1424 pipe = fixed_ports[index].pipe;; 1425 1426 si->port_l2p_mapping[port] = phy_port; 1427 si->port_l2i_mapping[port] = fixed_ports[index].idb_port; 1428 si->port_p2l_mapping[phy_port] = port; 1429 si->port_p2m_mapping[phy_port] = fixed_ports[index].mmu_port; 1430 si->port_pipe[port] = pipe; 1431 } 1432 1433 rv = SOC_E_NONE; 1434 for (port = 1; port < num_port; port++) { 1435 if (si->port_l2p_mapping[port] != -1) { /* fixed mapped port */ 1436 continue; 1437 } 1438 if (port == 134) { /* SDK uses device port 135 for loopback port 3 */ 1439 continue; 1440 } 1441 1442 config_str = soc_property_port_get_str(unit, port, spn_PORTMAP); 1443 if (config_str == NULL) { 1444 continue; 1445 } 1446 1447 /* 1448 * portmap_<port>=<physical port number>:<bandwidth in Gb>[:<bandwidth cap in Gb/i(inactive)/1/2/4(num lanes)>][:<i>] 1449 * eg: portmap_1=1:100 1450 * or portmap_1=1:40 1451 * or portmap_1=1:40:i 1452 * or portmap_1=1:40:2 1453 * or portmap_1=1:40:2:i 1454 * or portmap_1=1:10:100 1455 */ 1456 sub_str = config_str; 1457 1458 /* Parse physical port number */ 1459 phy_port = sal_ctoi(sub_str, &sub_str_end); 1460 if (sub_str == sub_str_end) { 1461 LOG_CLI((BSL_META_U(unit, 1462 "Port %d: Missing physical port information \"%s\"\n"), 1463 port, config_str)); 1464 rv = SOC_E_FAIL; 1465 continue; 1466 } 1467 if (phy_port < 0 || phy_port >= num_phy_port) { 1468 LOG_CLI((BSL_META_U(unit, 1469 "Port %d: Invalid physical port number %d\n"), 1470 port, phy_port)); 1471 rv = SOC_E_FAIL; 1472 continue; 1473 } 1474 if (!_soc_tomahawk_phy_dev_port_check(unit, phy_port, port)) { 1475 LOG_CLI((BSL_META_U(unit, 1476 "Port %d: Invalid mapping physical port number %d\n"), 1477 port, phy_port)); 1478 rv = SOC_E_FAIL; 1479 continue; 1480 } 1481 /* coverity[check_after_sink : FALSE] */ 1482 if (si->port_p2l_mapping[phy_port] != -1) { 1483 LOG_CLI((BSL_META_U(unit, 1484 "Port %d: Physical port %d is used by port %d\n"), 1485 port, phy_port, si->port_p2l_mapping[phy_port])); 1486 rv = SOC_E_FAIL; 1487 continue; 1488 } 1489 1490 /* Skip ':' between physical port number and bandwidth */ 1491 sub_str = sub_str_end; 1492 if (*sub_str != '\0') { 1493 if (*sub_str != ':') { 1494 LOG_CLI((BSL_META_U(unit, 1495 "Port %d: Bad config string \"%s\"\n"), 1496 port, config_str)); 1497 rv = SOC_E_FAIL; 1498 continue; 1499 } 1500 sub_str++; 1501 } 1502 1503 /* Parse bandwidth */ 1504 for (index = 0; index < sizeof(str_2p5) - 1; index++) { 1505 if (sub_str[index] == '\0') { 1506 break; 1507 } 1508 str_buf[index] = sub_str[index]; 1509 } 1510 str_buf[index] = '\0'; 1511 if (!sal_strcmp(str_buf, str_2p5)) { 1512 port_bandwidth = 2500; 1513 sub_str_end = &sub_str[sizeof(str_2p5) - 1]; 1514 } else { 1515 port_bandwidth = sal_ctoi(sub_str, &sub_str_end) * 1000; 1516 if (sub_str == sub_str_end) { 1517 LOG_CLI((BSL_META_U(unit, 1518 "Port %d: Missing bandwidth information \"%s\"\n"), 1519 port, config_str)); 1520 rv = SOC_E_FAIL; 1521 continue; 1522 } 1523 switch (port_bandwidth) { 1524 case 1000: 1525 case 10000: 1526 case 11000: 1527 case 20000: 1528 case 21000: 1529 case 25000: 1530 case 27000: 1531 case 40000: 1532 case 42000: 1533 case 50000: 1534 case 53000: 1535 case 100000: 1536 case 106000: 1537 break; 1538 default: 1539 LOG_CLI((BSL_META_U(unit, 1540 "Port %d: Invalid bandwidth %d Gb\n"), 1541 port, port_bandwidth / 1000)); 1542 rv = SOC_E_FAIL; 1543 continue; 1544 } 1545 } 1546 1547 /* Check if option presents */ 1548 option1 = 0; option2 = 0; 1549 sub_str = sub_str_end; 1550 if (*sub_str != '\0') { 1551 /* Skip ':' between bandwidth and cap or options */ 1552 if (*sub_str != ':') { 1553 LOG_CLI((BSL_META_U(unit, 1554 "Port %d: Bad config string \"%s\"\n"), 1555 port, config_str)); 1556 rv = SOC_E_FAIL; 1557 continue; 1558 } 1559 sub_str++; 1560 1561 if (*sub_str != '\0') { 1562 /* Parse bandwidth cap or options */ 1563 bandwidth_cap = sal_ctoi(sub_str, &sub_str_end) * 1000; 1564 /* For distinguish 1G cap or lane 1, left-to-right */ 1565 if ((bandwidth_cap == 1000) && 1566 (bandwidth_cap < port_bandwidth)) { 1567 bandwidth_cap = 0; 1568 } 1569 switch (bandwidth_cap) { 1570 case 1000: 1571 case 10000: 1572 case 11000: 1573 case 20000: 1574 case 21000: 1575 case 25000: 1576 case 27000: 1577 case 40000: 1578 case 42000: 1579 case 50000: 1580 case 53000: 1581 case 100000: 1582 case 106000: 1583 sub_str = sub_str_end; 1584 _soc_th_port_speed_cap[unit][port] = bandwidth_cap; 1585 /* Flex config detected, port speed cap specified */ 1586 si->flex_eligible = TRUE; 1587 break; 1588 default: 1589 if (!(*sub_str == 'i' || *sub_str == '1' || *sub_str == '2' || 1590 *sub_str == '4')) { 1591 LOG_CLI((BSL_META_U(unit, 1592 "Port %d: Bad config string \"%s\"\n"), 1593 port, config_str)); 1594 rv = SOC_E_FAIL; 1595 continue; 1596 } else { 1597 option1 = *sub_str; 1598 sub_str++; 1599 } 1600 } 1601 /* Check if more options present */ 1602 if (*sub_str != '\0') { 1603 /* Skip ':' between options */ 1604 if (*sub_str != ':') { 1605 LOG_CLI((BSL_META_U(unit, 1606 "Port %d: Bad config string \"%s\"\n"), 1607 port, config_str)); 1608 rv = SOC_E_FAIL; 1609 continue; 1610 } 1611 sub_str++; 1612 1613 if (*sub_str != 'i') { 1614 LOG_CLI((BSL_META_U(unit, 1615 "Port %d: Bad config string \"%s\"\n"), 1616 port, config_str)); 1617 rv = SOC_E_FAIL; 1618 continue; 1619 } 1620 option2 = *sub_str; 1621 sub_str++; 1622 } 1623 } 1624 } 1625 1626 /* Check trailing string */ 1627 if (*sub_str != '\0') { 1628 LOG_CLI((BSL_META_U(unit, 1629 "Port %d: Bad config string \"%s\"\n"), 1630 port, config_str)); 1631 rv = SOC_E_FAIL; 1632 continue; 1633 } 1634 1635 /* Update soc_info */ 1636 si->port_l2p_mapping[port] = phy_port; 1637 si->port_p2l_mapping[phy_port] = port; 1638 if (phy_port == 129) { /* management port 0 */ 1639 pipe = 1; 1640 si->port_l2i_mapping[port] = 32; 1641 si->port_p2m_mapping[phy_port] = 96; 1642 si->port_serdes[port] = 32; 1643 SOC_PBMP_PORT_ADD(si->management_pbm, port); 1644 } else if (phy_port == 131) { /* management port 1 */ 1645 pipe = 2; 1646 si->port_l2i_mapping[port] = 32; 1647 si->port_p2m_mapping[phy_port] = 160; 1648 si->port_serdes[port] = 32; 1649 SOC_PBMP_PORT_ADD(si->management_pbm, port); 1650 } else { 1651 idb_port = (phy_port - 1) % _TH_PORTS_PER_PIPE; 1652 pipe = (phy_port - 1) / _TH_PORTS_PER_PIPE; 1653 si->port_l2i_mapping[port] = idb_port; 1654 si->port_p2m_mapping[phy_port] = 1655 (pipe << 6) | ((idb_port & 0x1) << 4) | (idb_port >> 1); 1656 si->port_serdes[port] = (phy_port - 1) / _TH_PORTS_PER_PBLK; 1657 } 1658 si->port_pipe[port] = pipe; 1659 SOC_PBMP_PORT_ADD(si->pipe_pbm[pipe], port); 1660 si->port_speed_max[port] = port_bandwidth; 1661 if (option1 == 'i') { 1662 SOC_PBMP_PORT_ADD(si->all.disabled_bitmap, port); 1663 } else { 1664 switch (option1) { 1665 case '1': si->port_num_lanes[port] = 1; break; 1666 case '2': si->port_num_lanes[port] = 2; break; 1667 case '4': si->port_num_lanes[port] = 4; break; 1668 default: break; 1669 } 1670 } 1671 if (option2 == 'i') { 1672 SOC_PBMP_PORT_ADD(si->all.disabled_bitmap, port); 1673 } 1674 if (oversub_mode) { 1675 SOC_PBMP_PORT_ADD(si->oversub_pbm, port); 1676 } 1677 } 1678 /* Flex config detected, disabled ports in config */ 1679 if (SOC_PBMP_NOT_NULL(SOC_PORT_DISABLED_BITMAP(unit, all))) { 1680 si->flex_eligible = TRUE; 1681 } 1682 1683 for (index = 1; index < COUNTOF(fixed_ports); index++) { 1684 pipe = fixed_ports[index].pipe; 1685 port = fixed_ports[index].port; 1686 phy_port = fixed_ports[index].phy_port; 1687 if (SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) { 1688 /* Remove loopback port if the entire pipe is not in use */ 1689 si->port_l2p_mapping[port] = -1; 1690 si->port_l2i_mapping[port] = -1; 1691 si->port_p2l_mapping[phy_port] = -1; 1692 si->port_p2m_mapping[phy_port] = -1; 1693 si->port_pipe[port] = -1; 1694 } else { 1695 SOC_PBMP_PORT_ADD(si->pipe_pbm[pipe], port); 1696 } 1697 } 1698 1699 /* Since in tomahawk, CPU port's Queues and Scheduling nodes are bound to 1700 pipeline 0, add CPU Port to PIPE_PBM of PIPE 0 */ 1701 SOC_PBMP_PORT_ADD(si->pipe_pbm[0], CMIC_PORT(unit)); 1702 1703 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 1704 LOG_CLI((BSL_META_U(unit, 1705 "physical to logical mapping:"))); 1706 for (index = 0; index < num_phy_port; index++) { 1707 if (index % 16 == 0) { 1708 LOG_CLI((BSL_META_U(unit, 1709 "\n "))); 1710 } 1711 LOG_CLI((BSL_META_U(unit, 1712 " %3d"), si->port_p2l_mapping[index])); 1713 } 1714 LOG_CLI((BSL_META_U(unit, 1715 "\n"))); 1716 LOG_CLI((BSL_META_U(unit, 1717 "physical port bandwidth:"))); 1718 for (index = 0; index < num_phy_port; index++) { 1719 if (index % 16 == 0) { 1720 LOG_CLI((BSL_META_U(unit, 1721 "\n "))); 1722 } 1723 port = si->port_p2l_mapping[index]; 1724 if (port == -1) { 1725 LOG_CLI((BSL_META_U(unit, 1726 " -1"))); 1727 } else if (si->port_speed_max[port] == 2500) { 1728 LOG_CLI((BSL_META_U(unit, 1729 " 2.5"))); 1730 } else { 1731 LOG_CLI((BSL_META_U(unit, 1732 " %3d"), si->port_speed_max[port] / 1000)); 1733 } 1734 } 1735 LOG_CLI((BSL_META_U(unit, 1736 "\n"))); 1737 1738 LOG_CLI((BSL_META_U(unit, 1739 "physical to mmu mapping:"))); 1740 for (index = 0; index < num_phy_port; index++) { 1741 if (index % 16 == 0) { 1742 LOG_CLI((BSL_META_U(unit, 1743 "\n "))); 1744 } 1745 LOG_CLI((BSL_META_U(unit, 1746 " %3d"), si->port_p2m_mapping[index])); 1747 } 1748 LOG_CLI((BSL_META_U(unit, 1749 "\n"))); 1750 } 1751 1752 1753 1754 /* Setup port_num_lanes */ 1755 for (port = 0; port < num_port; port++) { 1756 if (si->port_speed_max[port] > 53000) { 1757 si->port_num_lanes[port] = 4; 1758 } else if (si->port_speed_max[port] == 40000 || 1759 si->port_speed_max[port] == 42000) { 1760 /* Note: 40G, HG[42] can operate either in dual or quad lane mode 1761 Check if adjacent ports exist to set dual lane mode */ 1762 phy_port = si->port_l2p_mapping[port]; 1763 if (phy_port >= 1 && phy_port <= 127 && phy_port != -1) { 1764 int sis_port; 1765 1766 if (phy_port % 4 == 1) { 1767 sis_port = si->port_p2l_mapping[phy_port+2]; 1768 if ((si->port_speed_max[sis_port] > 0) && 1769 !SOC_PBMP_MEMBER(si->all.disabled_bitmap, sis_port)) { 1770 si->port_num_lanes[port] = 2; 1771 } 1772 } else if (phy_port % 4 == 3) { 1773 sis_port = si->port_p2l_mapping[phy_port-2]; 1774 if ((si->port_speed_max[sis_port] > 0) && 1775 !SOC_PBMP_MEMBER(si->all.disabled_bitmap, sis_port)) { 1776 si->port_num_lanes[port] = 2; 1777 } 1778 } 1779 } 1780 /* Else set to quad lane mode by default if the user did not 1781 specify anything and no sister ports existed */ 1782 if (si->port_num_lanes[port] == -1) { 1783 si->port_num_lanes[port] = 4; 1784 } 1785 } else if ((si->port_speed_max[port] >= 20000) && 1786 !(si->port_speed_max[port] == 25000 || 1787 si->port_speed_max[port] == 27000)) { 1788 /* 50G, HG[53], 20G MLD, HG[21] use 2 lanes */ 1789 si->port_num_lanes[port] = 2; 1790 } else if (si->port_speed_max[port] > 0) { 1791 /* 10G XFI, HG[11], 25G XFI and HG[27] use 1 lane */ 1792 if (si->port_num_lanes[port] == -1) { 1793 /* But RXAUI and XAUI on mgmt ports use 2 and 4 lanes, which 1794 * can be provided via the portmap interface. 1795 */ 1796 si->port_num_lanes[port] = 1; 1797 } 1798 } 1799 } 1800 1801 /* Setup high speed port (HSP) pbm */ 1802 for (port = 0; port < num_port; port++) { 1803 phy_port = si->port_l2p_mapping[port]; 1804 if (phy_port == -1) { 1805 continue; 1806 } 1807 if (si->port_speed_max[port] >= 40000) { 1808 SOC_PBMP_PORT_ADD(si->eq_pbm, port); 1809 } 1810 } 1811 1812 /* Setup pipe/xpe mapping 1813 * XPE0 (SC_R/XPE_A): IP 0/3 EP 0/1 1814 * XPE1 (SC_S/XPE_A): IP 0/3 EP 2/3 1815 * XPE2 (SC_R/XPE_B): IP 1/2 EP 0/1 1816 * XPE3 (SC_S/XPE_B): IP 1/2 EP 2/3 1817 */ 1818 pipe_map = 0; 1819 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 1820 if (SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) { 1821 continue; 1822 } 1823 pipe_map |= 1 << pipe; 1824 } 1825 xpe_map = 0; 1826 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 1827 ipipe_map = (xpe < 2 ? 0x9 : 0x6) & pipe_map; 1828 epipe_map = (xpe & 1 ? 0xc : 0x3) & pipe_map; 1829 if (ipipe_map == 0 || epipe_map == 0) { 1830 continue; 1831 } 1832 xpe_map |= 1 << xpe; 1833 si->xpe_ipipe_map[xpe] = ipipe_map; 1834 si->xpe_epipe_map[xpe] = epipe_map; 1835 } 1836 sc_map = 0; 1837 for (sc = 0; sc < NUM_SLICE(unit); sc++) { 1838 ipipe_map = pipe_map; 1839 epipe_map = (sc & 1 ? 0xc : 0x3) & pipe_map; 1840 if (ipipe_map == 0 || epipe_map == 0) { 1841 continue; 1842 } 1843 sc_map |= 1 << sc; 1844 si->sc_ipipe_map[sc] = ipipe_map; 1845 si->sc_epipe_map[sc] = epipe_map; 1846 } 1847 for (pipe = 0; pipe < SOC_MAX_NUM_PIPES; pipe++) { 1848 /* Number of pipes is 4 in Tomahawk */ 1849 /* coverity[overrun-local : FALSE] */ 1850 if (SOC_PBMP_IS_NULL(si->pipe_pbm[pipe])) { 1851 continue; 1852 } 1853 /* coverity[overrun-local : FALSE] */ 1854 si->ipipe_xpe_map[pipe] = (pipe == 0 || pipe == 3 ? 0x3 : 0xc) & 1855 xpe_map; 1856 /* coverity[overrun-local : FALSE] */ 1857 si->epipe_xpe_map[pipe] = (pipe < 2 ? 0x5 : 0xa) & xpe_map; 1858 /* coverity[overrun-local : FALSE] */ 1859 si->ipipe_sc_map[pipe] = sc_map; 1860 /* coverity[overrun-local : FALSE] */ 1861 si->epipe_sc_map[pipe] = (pipe < 2 ? 0x1 : 0x2) & sc_map; 1862 } 1863 1864 return rv; 1865 #else 1866 return SOC_E_UNAVAIL; 1867 #endif 1868 } 1869 1870 #if defined(BCM_TOMAHAWK2_SUPPORT) 1871 /* 1872 * Function: 1873 * soc_th2_port_max_oversub_ratio_get 1874 * Purpose: 1875 * Get the max OVS ratio among all half pipes in the device. 1876 * Parameters: 1877 * unit - (IN) Unit number. 1878 * ratio - (OUT) Max OVS ratio among all half pipes in the device 1879 * Returns: 1880 * SOC_E_xxx 1881 * Notes: 1882 */ 1883 STATIC int 1884 soc_th2_port_max_oversub_ratio_get( 1885 int unit, 1886 OUT int* const ratio) 1887 { 1888 soc_info_t *si; 1889 _soc_tomahawk2_tdm_t *tdm; 1890 int pipe, hpipe, max_ovs_ratio; 1891 1892 if (!ratio) { 1893 return SOC_E_PARAM; 1894 } 1895 1896 if (SAL_BOOT_XGSSIM) { 1897 *ratio = 0; 1898 return SOC_E_NONE; 1899 } 1900 1901 si = &SOC_INFO(unit); 1902 tdm = SOC_CONTROL(unit)->tdm_info; 1903 1904 if (!si || !tdm) { 1905 return SOC_E_INTERNAL; 1906 } 1907 1908 max_ovs_ratio = 0; 1909 for (pipe = 0; pipe < _TH2_PIPES_PER_DEV; pipe++) { 1910 for (hpipe = 0; hpipe < _TH2_OVS_HPIPE_COUNT_PER_PIPE; hpipe++) { 1911 if (max_ovs_ratio < tdm->ovs_ratio_x1000[pipe][hpipe]) { 1912 max_ovs_ratio = tdm->ovs_ratio_x1000[pipe][hpipe]; 1913 } 1914 } 1915 } 1916 *ratio = max_ovs_ratio; 1917 1918 return SOC_E_NONE; 1919 } 1920 #endif 1921 soc_error_t 1922 soc_th_subsidiary_ports_get(int unit, soc_port_t port, soc_pbmp_t *pbmp) 1923 { 1924 soc_info_t *si = &SOC_INFO(unit); 1925 soc_port_t phy_port_base, phy_port; 1926 soc_pbmp_t pbm; 1927 int max_subport; 1928 1929 if (!SOC_PORT_VALID(unit, port) || IS_CPU_PORT(unit, port) || 1930 IS_LB_PORT(unit, port) || 1931 SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) { 1932 /* CPU, LB and Management ports do not support flexport */ 1933 return SOC_E_PORT; 1934 } 1935 1936 phy_port = si->port_l2p_mapping[port]; 1937 if (-1 == phy_port) { 1938 return SOC_E_PORT; 1939 } 1940 phy_port_base = PORT_BLOCK_BASE_PORT(port); 1941 1942 /* Only lane 0 and lane 2 of a PM can be controlling ports */ 1943 if ((phy_port_base != phy_port) && ((phy_port_base + 2) != phy_port)) { 1944 /* Not a controlling port */ 1945 return SOC_E_PORT; 1946 } 1947 1948 #ifdef BCM_TOMAHAWK3_SUPPORT 1949 /* Tomahawk 3 has 8 lanes per PM instead of 4 */ 1950 if (SOC_IS_TOMAHAWK3(unit)) { 1951 max_subport = phy_port + (8 - ((phy_port - 1) % 8)); 1952 } else 1953 #endif 1954 { 1955 max_subport = phy_port + (4 - ((phy_port - 1) % 4)); 1956 } 1957 SOC_PBMP_CLEAR(pbm); 1958 for (; phy_port < max_subport; phy_port++) { 1959 if (si->port_p2l_mapping[phy_port] == -1) { 1960 continue; 1961 } 1962 SOC_PBMP_PORT_ADD(pbm, si->port_p2l_mapping[phy_port]); 1963 } 1964 SOC_PBMP_ASSIGN(*pbmp, pbm); 1965 1966 return SOC_E_NONE; 1967 } 1968 1969 int 1970 soc_th_port_oversub_ratio_get( 1971 int unit, 1972 soc_port_t port, 1973 OUT int* const ratio) 1974 { 1975 soc_info_t *si; 1976 _soc_tomahawk_tdm_t *tdm; 1977 int pipe; 1978 1979 if (!ratio) { 1980 return SOC_E_PARAM; 1981 } 1982 1983 #if defined(BCM_TOMAHAWK2_SUPPORT) 1984 if (SOC_IS_TOMAHAWK2(unit)) { 1985 return soc_th2_port_max_oversub_ratio_get(unit, ratio); 1986 } 1987 #endif 1988 1989 si = &SOC_INFO(unit); 1990 tdm = SOC_CONTROL(unit)->tdm_info; 1991 1992 if (!si || !tdm) { 1993 return SOC_E_INTERNAL; 1994 } 1995 1996 pipe = si->port_pipe[port]; 1997 *ratio = tdm->ovs_ratio_x1000[pipe]; 1998 1999 return SOC_E_NONE; 2000 } 2001 2002 uint32 _soc_th_temp_mon_mask[SOC_MAX_NUM_DEVICES]; 2003 2004 static int 2005 _soc_th_freq_val_sel(int frequency) 2006 { 2007 switch (frequency) { 2008 case 850: 2009 return 1; 2010 case 765: 2011 return 2; 2012 case 672: 2013 return 3; 2014 case 645: 2015 return 4; 2016 case 545: 2017 return 5; 2018 default: 2019 return 1; 2020 } 2021 } 2022 2023 STATIC int _soc_tomahawk_clear_all_memory(int unit, int mmu_init); 2024 STATIC int _soc_tomahawk_tdm_calculation_free_memory(int unit); 2025 2026 int 2027 soc_tomahawk_chip_reset(int unit) 2028 { 2029 #define _SOC_TH_LCPLL_COUNT 4 2030 #define _SOC_TH_PLL_CFG_FIELDS 4 2031 #define _SOC_TH_DEF_TEMP_MAX 125 2032 #define _SOC_TH_NUM_PORTS 136 2033 #define _SOC_TH_LINK_DELAY_REG_BASE 0x20000700 /* EGR_1588_LINK_DELAY_64 */ 2034 #define _SOC_TH_LINK_DELAY_REG_BLK 2 /* EPIPE BLOCKNUM */ 2035 2036 soc_info_t *si; 2037 uint16 dev_id; 2038 uint8 rev_id; 2039 uint32 to_usec, temp_mask; 2040 uint32 rval, temp_thr; 2041 soc_reg_t reg; 2042 int freq_sel, freq_list_len, max_frequency; 2043 int num_banks, index, shared_bank, shared_bank_offset = 0; 2044 int num_shared_l2_banks, num_shared_l3_banks, num_shared_fpem_banks; 2045 uint32 config = 0, map = 0, fpmap = 0; 2046 soc_field_t fields[_SOC_TH_PLL_CFG_FIELDS]; 2047 uint32 values[_SOC_TH_PLL_CFG_FIELDS]; 2048 static soc_field_t l2_fields[] = { 2049 L2_ENTRY_BANK_2f, L2_ENTRY_BANK_3f, L2_ENTRY_BANK_4f, 2050 L2_ENTRY_BANK_5f 2051 }; 2052 static soc_field_t l3_fields[] = { 2053 L3_ENTRY_BANK_4f, L3_ENTRY_BANK_5f, L3_ENTRY_BANK_6f, 2054 L3_ENTRY_BANK_7f 2055 }; 2056 static soc_field_t fpem_fields[] = { 2057 FPEM_ENTRY_BANK_0f, FPEM_ENTRY_BANK_1f, FPEM_ENTRY_BANK_2f, 2058 FPEM_ENTRY_BANK_3f 2059 }; 2060 static const soc_reg_t lcpll_ctrl0_reg[] = { 2061 TOP_XG_PLL0_CTRL_0r, TOP_XG_PLL1_CTRL_0r, 2062 TOP_XG_PLL2_CTRL_0r, TOP_XG_PLL3_CTRL_0r 2063 }; 2064 static const soc_reg_t lcpll_ctrl4_reg[] = { 2065 TOP_XG_PLL0_CTRL_4r, TOP_XG_PLL1_CTRL_4r, 2066 TOP_XG_PLL2_CTRL_4r, TOP_XG_PLL3_CTRL_4r 2067 }; 2068 static const soc_reg_t lcpll_status_reg[] = { 2069 TOP_XG_PLL0_STATUSr, TOP_XG_PLL1_STATUSr, 2070 TOP_XG_PLL2_STATUSr, TOP_XG_PLL3_STATUSr 2071 }; 2072 static const soc_reg_t temp_thr_reg[] = { 2073 TOP_PVTMON_0_INTR_THRESHOLDr, TOP_PVTMON_1_INTR_THRESHOLDr, 2074 TOP_PVTMON_2_INTR_THRESHOLDr, TOP_PVTMON_3_INTR_THRESHOLDr, 2075 TOP_PVTMON_4_INTR_THRESHOLDr, TOP_PVTMON_5_INTR_THRESHOLDr, 2076 TOP_PVTMON_6_INTR_THRESHOLDr, TOP_PVTMON_7_INTR_THRESHOLDr 2077 }; 2078 static const char *temp_thr_prop[] = { 2079 "temp0_threshold", "temp1_threshold", "temp2_threshold", 2080 "temp3_threshold", "temp4_threshold", "temp5_threshold", 2081 "temp6_threshold", "temp7_threshold" 2082 }; 2083 static const int freq_list[] = { 850, 765, 672, 645, 545 }; 2084 2085 int port, acc; 2086 uint64 rval64; 2087 2088 /* Settings for 500 MHz TSPLL output clock. */ 2089 unsigned ts_ref_freq = 0; 2090 unsigned ts_idx = 0; 2091 2092 static const soc_pll_param_t ts_pll[] = { 2093 /* Fref, Ndiv_int, Ndiv_frac, Pdiv, Mdiv, Ka, Ki, Kp, VCO_div2 */ 2094 {12800000, 195, 0x50000, 1, 5, 0, 2, 3, 1}, 2095 {20000000, 125, 0, 1, 5, 0, 2, 3, 1}, 2096 {25000000, 100, 0, 1, 5, 0, 2, 3, 1}, 2097 {32000000, 78, 0x20000, 1, 5, 0, 2, 3, 1}, 2098 {50000000, 100, 0, 2, 5, 0, 2, 3, 1}, 2099 { 0, 100, 0, 2, 5, 0, 2, 3, 1} /* 50 MHz internal reference. */ 2100 }; 2101 2102 /* Settings for 20 MHz BSPLL output clock. */ 2103 unsigned bs_ref_freq = 0; 2104 unsigned bs_idx = 0; 2105 2106 static const soc_pll_param_t bs_pll[] = { 2107 /* Fref, Ndiv_int, Ndiv_frac, Pdiv, Mdiv, Ka, Ki, Kp, VCO_div2 */ 2108 {12800000, 195, 0x50000, 1, 125, 0, 2, 3, 1}, 2109 {20000000, 125, 0, 1, 125, 0, 2, 3, 1}, 2110 {25000000, 100, 0, 1, 125, 0, 2, 3, 1}, 2111 {32000000, 78, 0x20000, 1, 125, 0, 2, 3, 1}, 2112 {50000000, 100, 0, 2, 125, 0, 2, 3, 1}, 2113 { 0, 100, 0, 2, 125, 0, 2, 3, 1} /* 50 MHz internal reference. */ 2114 }; 2115 2116 si = &SOC_INFO(unit); 2117 soc_cm_get_id(unit, &dev_id, &rev_id); 2118 to_usec = SAL_BOOT_QUICKTURN ? (250 * MILLISECOND_USEC) : 2119 (10 * MILLISECOND_USEC); 2120 2121 /* 2122 * SBUS ring and block number: 2123 * ring 0: IP(1), LBPORT0(54), LBPORT1(51), LBPORT2(52), LBPORT3(53) 2124 * ring 1: EP(2) 2125 * ring 2: MMU_XPE(3), MMU_SC(4), MMU_GLB(5) 2126 * ring 3: PM7(22), PM6(21), PM5(20), PM4(19), PM3(18), PM2(17), PM1(16), 2127 * PM0(15), PM31(46), PM30(45), PM29(44), PM28(43), PM27(42), 2128 * PM26(41), PM25(40), PM24(39), CLPORT32(55) 2129 * ring 4: PM32(11), PM8(23), PM9(24), PM10(25), PM11(26), PM12(27), 2130 * PM13(28), PM14(29), PM15(30), PM16(31), PM17(32), PM18(33), 2131 * PM19(34), PM20(35), PM21(36), PM22(37), PM23(38) 2132 * ring 5: OTPC(6), AVS(59), TOP(7), SER(8) 2133 */ 2134 #ifdef BCM_CMICM_SUPPORT 2135 if (soc_feature(unit, soc_feature_cmicm)) { 2136 WRITE_CMIC_SBUS_RING_MAP_0_7r(unit, 0x55222100); 2137 WRITE_CMIC_SBUS_RING_MAP_8_15r(unit, 0x30004005); 2138 WRITE_CMIC_SBUS_RING_MAP_16_23r(unit, 0x43333333); 2139 WRITE_CMIC_SBUS_RING_MAP_24_31r(unit, 0x44444444); 2140 WRITE_CMIC_SBUS_RING_MAP_32_39r(unit, 0x34444444); 2141 WRITE_CMIC_SBUS_RING_MAP_40_47r(unit, 0x03333333); 2142 WRITE_CMIC_SBUS_RING_MAP_48_55r(unit, 0x30000000); 2143 WRITE_CMIC_SBUS_RING_MAP_56_63r(unit, 0x00005000); 2144 WRITE_CMIC_SBUS_TIMEOUTr(unit, 0x7d0); 2145 } 2146 #endif 2147 2148 #ifdef BCM_CMICX_SUPPORT 2149 if (soc_feature(unit, soc_feature_cmicx)) { 2150 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_0_7_OFFSET,0x55222100); 2151 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_8_15_OFFSET,0x30004005); 2152 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_16_23_OFFSET,0x43333333); 2153 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_24_31_OFFSET,0x44444444); 2154 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_32_39_OFFSET,0x34444444); 2155 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_40_47_OFFSET,0x03333333); 2156 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_48_55_OFFSET,0x30000000); 2157 soc_pci_write(unit, CMIC_TOP_SBUS_RING_MAP_56_63_OFFSET,0x00005000); 2158 soc_pci_write(unit, CMIC_TOP_SBUS_TIMEOUT_OFFSET,0x7d0); 2159 } 2160 #endif 2161 sal_usleep(to_usec); 2162 2163 2164 SOC_IF_ERROR_RETURN 2165 (soc_tomahawk_max_frequency_get(unit, dev_id, rev_id, -1, 2166 &max_frequency)); 2167 if ((si->frequency != max_frequency) 2168 || (si->frequency != freq_list[0])) { 2169 if (si->frequency > max_frequency) { 2170 si->frequency = max_frequency; 2171 } 2172 freq_list_len = COUNTOF(freq_list); 2173 for (freq_sel = 1; freq_sel < freq_list_len; freq_sel++) { /* skip index 0 */ 2174 if (si->frequency == freq_list[freq_sel]) { 2175 break; 2176 } 2177 } 2178 if (freq_sel < freq_list_len) { 2179 LOG_CLI((BSL_META_U(unit, 2180 "*** change core clock frequency to %dMHz\n"), 2181 si->frequency)); 2182 2183 freq_sel = _soc_th_freq_val_sel(si->frequency); 2184 fields[0] = CORE_CLK_0_FREQ_SELf; 2185 values[0] = freq_sel; 2186 fields[1] = SW_CORE_CLK_0_SEL_ENf; 2187 values[1] = 1; 2188 SOC_IF_ERROR_RETURN 2189 (soc_reg_fields32_modify(unit, TOP_CORE_CLK_FREQ_SELr, 2190 REG_PORT_ANY, 2, fields, values)); 2191 sal_usleep(to_usec); 2192 } 2193 } 2194 else { 2195 /* Set correct frequency in non OTP'd SKUs */ 2196 SOC_IF_ERROR_RETURN(READ_TOP_DEV_REV_IDr(unit, &rval)); 2197 if (!(soc_reg_field_get(unit, TOP_DEV_REV_IDr, rval, DEVICE_SKEWf) & 0x8)) { 2198 SOC_IF_ERROR_RETURN 2199 (soc_tomahawk_max_frequency_get(unit, dev_id, rev_id, -1, 2200 &max_frequency)); 2201 LOG_CLI((BSL_META_U(unit, 2202 "*** change core clock frequency to %dMHz\n"), 2203 max_frequency)); 2204 freq_sel = _soc_th_freq_val_sel(max_frequency); 2205 fields[0] = CORE_CLK_0_FREQ_SELf; 2206 values[0] = freq_sel; 2207 fields[1] = SW_CORE_CLK_0_SEL_ENf; 2208 values[1] = 1; 2209 SOC_IF_ERROR_RETURN 2210 (soc_reg_fields32_modify(unit, TOP_CORE_CLK_FREQ_SELr, 2211 REG_PORT_ANY, 2, fields, values)); 2212 sal_usleep(to_usec); 2213 } 2214 } 2215 2216 /* Power on core pll1 */ 2217 SOC_IF_ERROR_RETURN 2218 (soc_reg_field32_modify(unit, TOP_CORE_PLL1_CTRL_1r, 2219 REG_PORT_ANY, PWRONf, 0)); 2220 /* Program LCPLL frequency */ 2221 for (index = 0; index < COUNTOF(lcpll_ctrl0_reg); index++) { 2222 SOC_IF_ERROR_RETURN 2223 (soc_reg_field32_modify(unit, lcpll_ctrl4_reg[index], 2224 REG_PORT_ANY, POST_RST_SELf, 3)); 2225 SOC_IF_ERROR_RETURN 2226 (soc_reg_field32_modify(unit, lcpll_ctrl0_reg[index], 2227 REG_PORT_ANY, PDIVf, 1)); 2228 SOC_IF_ERROR_RETURN 2229 (soc_reg_field32_modify(unit, lcpll_ctrl0_reg[index], 2230 REG_PORT_ANY, NDIV_INTf, 20)); 2231 } 2232 2233 /* Configure TS PLL */ 2234 ts_ref_freq = soc_property_get(unit, spn_PTP_TS_PLL_FREF, 0); /* 0->internal reference */ 2235 2236 for (ts_idx = 0; ts_idx < sizeof(ts_pll)/sizeof(ts_pll[0]); ++ts_idx) { 2237 if (ts_pll[ts_idx].ref_freq == ts_ref_freq) { 2238 break; 2239 } 2240 } 2241 2242 if (ts_idx == sizeof(ts_pll)/sizeof(ts_pll[0])) { 2243 /* Valid configuration lookup failed. Use internal reference. */ 2244 ts_idx = 5; 2245 ts_ref_freq = 0; 2246 } 2247 2248 SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_0r(unit, &rval)); 2249 soc_reg_field_set(unit, TOP_TS_PLL_CTRL_0r, &rval, POST_RESETB_SELECTf, 3); 2250 SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_0r(unit, rval)); 2251 2252 SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_1r(unit, &rval)); 2253 soc_reg_field_set(unit, TOP_TS_PLL_CTRL_1r, & rval, FREF_SELf, (ts_ref_freq != 0)); 2254 SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_1r(unit, rval)); 2255 2256 SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_2r(unit,&rval)); 2257 soc_reg_field_set(unit, TOP_TS_PLL_CTRL_2r, &rval, PDIVf, 2258 soc_property_get(unit, spn_PTP_TS_PLL_PDIV, ts_pll[ts_idx].pdiv)); 2259 soc_reg_field_set(unit, TOP_TS_PLL_CTRL_2r, &rval, CH0_MDIVf, 2260 soc_property_get(unit, spn_PTP_TS_PLL_MNDIV, ts_pll[ts_idx].mdiv)); 2261 SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_2r(unit, rval)); 2262 2263 SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_3r(unit,&rval)); 2264 soc_reg_field_set(unit, TOP_TS_PLL_CTRL_3r, &rval, NDIV_INTf, 2265 soc_property_get(unit, spn_PTP_TS_PLL_N, ts_pll[ts_idx].ndiv_int)); 2266 soc_reg_field_set(unit, TOP_TS_PLL_CTRL_3r, &rval, NDIV_FRACf, ts_pll[ts_idx].ndiv_frac); 2267 SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_3r(unit, rval)); 2268 2269 SOC_IF_ERROR_RETURN(READ_TOP_TS_PLL_CTRL_4r(unit,&rval)); 2270 soc_reg_field_set(unit, TOP_TS_PLL_CTRL_4r, &rval, KAf, 2271 soc_property_get(unit, spn_PTP_TS_KA, ts_pll[ts_idx].ka)); 2272 soc_reg_field_set(unit, TOP_TS_PLL_CTRL_4r, &rval, KIf, 2273 soc_property_get(unit, spn_PTP_TS_KI, ts_pll[ts_idx].ki)); 2274 soc_reg_field_set(unit, TOP_TS_PLL_CTRL_4r, &rval, KPf, 2275 soc_property_get(unit, spn_PTP_TS_KP, ts_pll[ts_idx].kp)); 2276 SOC_IF_ERROR_RETURN(WRITE_TOP_TS_PLL_CTRL_4r(unit, rval)); 2277 2278 /* Set 250Mhz (implies 4ns resolution) default timesync clock to 2279 calculate assymentric delays */ 2280 SOC_TIMESYNC_PLL_CLOCK_NS(unit) = (1/250 * 1000); /* clock period in nanoseconds */ 2281 2282 2283 /* Configure BroadSync PLLs. */ 2284 bs_ref_freq = soc_property_get(unit, spn_PTP_BS_FREF, 0); /* 0->internal reference */ 2285 2286 for (bs_idx = 0; bs_idx < sizeof(bs_pll)/sizeof(bs_pll[0]); ++bs_idx) { 2287 if (bs_pll[bs_idx].ref_freq == bs_ref_freq) { 2288 break; 2289 } 2290 } 2291 2292 if (bs_idx == sizeof(bs_pll)/sizeof(bs_pll[0])) { 2293 /* Valid configuration lookup failed. Use internal reference. */ 2294 bs_idx = 5; 2295 bs_ref_freq = 0; 2296 } 2297 2298 /* Configure BS PLL0 */ 2299 SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_0r(unit, &rval)); 2300 soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_0r, &rval, POST_RESETB_SELECTf, 3); 2301 SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_0r(unit, rval)); 2302 2303 SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_1r(unit, &rval)); 2304 soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_1r, & rval, FREF_SELf, (bs_ref_freq != 0)); 2305 SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_1r(unit, rval)); 2306 2307 SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_2r(unit, &rval)); 2308 soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_2r, &rval, PDIVf, 2309 soc_property_get(unit, spn_PTP_BS_PDIV, bs_pll[bs_idx].pdiv)); 2310 soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_2r, &rval, CH0_MDIVf, 2311 soc_property_get(unit, spn_PTP_BS_MNDIV, bs_pll[bs_idx].mdiv)); 2312 SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_2r(unit, rval)); 2313 2314 SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_3r(unit, &rval)); 2315 soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_3r, &rval, NDIV_INTf, 2316 soc_property_get(unit, spn_PTP_BS_NDIV_INT, bs_pll[bs_idx].ndiv_int)); 2317 soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_3r, &rval, NDIV_FRACf, 2318 soc_property_get(unit, spn_PTP_BS_NDIV_FRAC, bs_pll[bs_idx].ndiv_frac)); 2319 SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_3r(unit, rval)); 2320 2321 SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL0_CTRL_4r(unit, &rval)); 2322 soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_4r, &rval, KAf, 2323 soc_property_get(unit, spn_PTP_BS_KA, bs_pll[bs_idx].ka)); 2324 soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_4r, &rval, KIf, 2325 soc_property_get(unit, spn_PTP_BS_KI, bs_pll[bs_idx].ki)); 2326 soc_reg_field_set(unit, TOP_BS_PLL0_CTRL_4r, &rval, KPf, 2327 soc_property_get(unit, spn_PTP_BS_KP, bs_pll[bs_idx].kp)); 2328 SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL0_CTRL_4r(unit, rval)); 2329 2330 /* Configure BS PLL1 */ 2331 SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_0r(unit, &rval)); 2332 soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_0r, &rval, POST_RESETB_SELECTf, 3); 2333 SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_0r(unit, rval)); 2334 2335 SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_1r(unit, &rval)); 2336 soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_1r, & rval, FREF_SELf, (bs_ref_freq != 0)); 2337 SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_1r(unit, rval)); 2338 2339 SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_2r(unit, &rval)); 2340 soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_2r, &rval, PDIVf, 2341 soc_property_get(unit, spn_PTP_BS_PDIV, bs_pll[bs_idx].pdiv)); 2342 soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_2r, &rval, CH0_MDIVf, 2343 soc_property_get(unit, spn_PTP_BS_MNDIV, bs_pll[bs_idx].mdiv)); 2344 SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_2r(unit, rval)); 2345 2346 SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_3r(unit, &rval)); 2347 soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_3r, &rval, NDIV_INTf, 2348 soc_property_get(unit, spn_PTP_BS_NDIV_INT, bs_pll[bs_idx].ndiv_int)); 2349 soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_3r, &rval, NDIV_FRACf, 2350 soc_property_get(unit, spn_PTP_BS_NDIV_FRAC, bs_pll[bs_idx].ndiv_frac)); 2351 SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_3r(unit, rval)); 2352 2353 SOC_IF_ERROR_RETURN(READ_TOP_BS_PLL1_CTRL_4r(unit, &rval)); 2354 soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_4r, &rval, KAf, 2355 soc_property_get(unit, spn_PTP_BS_KA, bs_pll[bs_idx].ka)); 2356 soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_4r, &rval, KIf, 2357 soc_property_get(unit, spn_PTP_BS_KI, bs_pll[bs_idx].ki)); 2358 soc_reg_field_set(unit, TOP_BS_PLL1_CTRL_4r, &rval, KPf, 2359 soc_property_get(unit, spn_PTP_BS_KP, bs_pll[bs_idx].kp)); 2360 SOC_IF_ERROR_RETURN(WRITE_TOP_BS_PLL1_CTRL_4r(unit, rval)); 2361 2362 /* Bring LCPLL, time sync PLL, BroadSync PLL, AVS out of reset */ 2363 SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval)); 2364 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL0_RST_Lf, 2365 1); 2366 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL1_RST_Lf, 2367 1); 2368 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL2_RST_Lf, 2369 1); 2370 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL3_RST_Lf, 2371 1); 2372 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_TS_PLL_RST_Lf, 1); 2373 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL0_RST_Lf, 2374 1); 2375 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL1_RST_Lf, 2376 1); 2377 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_AVS_RST_Lf, 1); 2378 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval)); 2379 2380 sal_usleep(to_usec); 2381 2382 if (!SAL_BOOT_SIMULATION) { 2383 /* Check LCPLL lock status */ 2384 for (index = 0; index < _SOC_TH_LCPLL_COUNT; index++) { 2385 reg = lcpll_status_reg[index]; 2386 SOC_IF_ERROR_RETURN 2387 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 2388 if (!soc_reg_field_get(unit, reg, rval, TOP_XGPLL_LOCKf)) { 2389 LOG_ERROR(BSL_LS_SOC_COMMON, 2390 (BSL_META_U(unit, 2391 "LCPLL %d not locked on unit %d " 2392 "status = 0x%08x\n"), index, unit, rval)); 2393 } 2394 } 2395 /* Check time sync lock status */ 2396 reg = TOP_TS_PLL_STATUSr; 2397 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 2398 if (!soc_reg_field_get(unit, reg, rval, PLL_LOCKf)) { 2399 LOG_ERROR(BSL_LS_SOC_COMMON, 2400 (BSL_META_U(unit, 2401 "TS_PLL not locked on unit %d " 2402 "status = 0x%08x\n"), unit, rval)); 2403 } 2404 /* Check BroadSync lock status */ 2405 reg = TOP_BS_PLL0_STATUSr; 2406 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 2407 if (!soc_reg_field_get(unit, reg, rval, PLL_LOCKf)) { 2408 LOG_ERROR(BSL_LS_SOC_COMMON, 2409 (BSL_META_U(unit, 2410 "BS_PLL0 not locked on unit %d " 2411 "status = 0x%08x\n"), unit, rval)); 2412 } 2413 } 2414 2415 /* De-assert LCPLL's post reset */ 2416 SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval)); 2417 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 2418 TOP_XG_PLL0_POST_RST_Lf, 1); 2419 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 2420 TOP_XG_PLL1_POST_RST_Lf, 1); 2421 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 2422 TOP_XG_PLL2_POST_RST_Lf, 1); 2423 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 2424 TOP_XG_PLL3_POST_RST_Lf, 1); 2425 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 2426 TOP_TS_PLL_POST_RST_Lf, 1); 2427 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 2428 TOP_BS_PLL0_POST_RST_Lf, 1); 2429 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 2430 TOP_BS_PLL1_POST_RST_Lf, 1); 2431 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval)); 2432 2433 sal_usleep(to_usec); 2434 2435 /* Set correct value for BG_ADJ */ 2436 SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_CTRL_0r(unit, &rval)); 2437 soc_reg_field_set(unit, TOP_PVTMON_CTRL_0r, &rval, BG_ADJf, 0); 2438 SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_0r(unit, rval)); 2439 2440 /* Enable high temperature interrupt monitoring. 2441 * Default on: pvtmon6 (close to core_plls at center of die). 2442 */ 2443 temp_mask = soc_property_get(unit, "temp_monitor_select", 1<<6); 2444 /* The above is a 9 bit mask to indicate which temp sensor to hook up to 2445 * the interrupt. 2446 */ 2447 rval = 0; 2448 for (index = 0; index <COUNTOF(temp_thr_reg); index++) { 2449 uint32 trval; 2450 2451 /* data = 410.04-(temp/0.48705) = (410040-(temp*1000))/487 2452 * Note: Since this is a high temp value we can safely assume it to 2453 * always be a +ive number. This is in degrees celcius. 2454 */ 2455 temp_thr = soc_property_get(unit, temp_thr_prop[index], _SOC_TH_DEF_TEMP_MAX); 2456 if (temp_thr > 410) { 2457 LOG_ERROR(BSL_LS_SOC_COMMON, 2458 (BSL_META_U(unit, 2459 "Unsupported temp value %d !! Max 410. Using %d.\n"), 2460 temp_thr, _SOC_TH_DEF_TEMP_MAX)); 2461 temp_thr = _SOC_TH_DEF_TEMP_MAX; 2462 } 2463 /* Convert temperature to config data */ 2464 temp_thr = (410040-(temp_thr*1000))/487; 2465 SOC_IF_ERROR_RETURN 2466 (soc_reg32_get(unit, temp_thr_reg[index], REG_PORT_ANY, 0, &trval)); 2467 soc_reg_field_set(unit, temp_thr_reg[index], &trval, MIN_THRESHOLDf, 2468 temp_thr); 2469 SOC_IF_ERROR_RETURN 2470 (soc_reg32_set(unit, temp_thr_reg[index], REG_PORT_ANY, 0, trval)); 2471 if (temp_mask & (1 << index)) { 2472 rval |= (1 << ((index * 2) + 1)); /* 2 bits per pvtmon, using min */ 2473 } 2474 } 2475 _soc_th_temp_mon_mask[unit] = temp_mask; 2476 2477 SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_INTR_MASKr(unit, rval)); 2478 /* Enable temp mon interrupt */ 2479 #ifdef BCM_CMICM_SUPPORT 2480 if (soc_feature(unit, soc_feature_cmicm)) { 2481 (void)soc_cmicm_intr3_enable(unit, 0x4); /* PVTMON_INTR bit 2 */ 2482 } 2483 #endif 2484 2485 /* Bring port blocks out of reset */ 2486 rval = 0; 2487 soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_PM32_RST_Lf, 1); 2488 soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_TS_RST_Lf, 1); 2489 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REGr(unit, rval)); 2490 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_3r(unit, 0xffffffff)); 2491 sal_usleep(to_usec); 2492 2493 /* Bring IP, EP, and MMU blocks out of reset */ 2494 SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REGr(unit, &rval)); 2495 soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_IP_RST_Lf, 1); 2496 soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_EP_RST_Lf, 1); 2497 soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_MMU_RST_Lf, 1); 2498 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REGr(unit, rval)); 2499 sal_usleep(to_usec); 2500 2501 if (!SAL_BOOT_PLISIM) { 2502 COMPILER_64_ZERO(rval64); 2503 2504 for (port = 0; port < _SOC_TH_NUM_PORTS; port++) { 2505 for (acc = 0; acc < _TH_PIPES_PER_DEV; acc++) { 2506 SOC_IF_ERROR_RETURN( 2507 _soc_reg64_set(unit, _SOC_TH_LINK_DELAY_REG_BLK, acc, 2508 (_SOC_TH_LINK_DELAY_REG_BASE + port), 2509 rval64)); 2510 } 2511 } 2512 } 2513 2514 /* Must do this before setting low-latency mode */ 2515 SOC_IF_ERROR_RETURN(_soc_tomahawk_clear_all_memory(unit, 0)); 2516 2517 /* Configure Switch Latency Bypass Mode */ 2518 SOC_IF_ERROR_RETURN(soc_th_latency_init(unit)); 2519 2520 SOC_IF_ERROR_RETURN 2521 (soc_tomahawk_hash_bank_count_get(unit, L2Xm, &num_banks)); 2522 num_shared_l2_banks = num_banks - 2; /* minus 2 dedicated L2 banks */ 2523 SOC_IF_ERROR_RETURN 2524 (soc_tomahawk_hash_bank_count_get(unit, L3_ENTRY_ONLYm, &num_banks)); 2525 num_shared_l3_banks = num_banks - 4; /* minus 4 dedicated L3 banks */ 2526 SOC_IF_ERROR_RETURN 2527 (soc_tomahawk_hash_bank_count_get(unit, EXACT_MATCH_2m, 2528 &num_shared_fpem_banks)); 2529 2530 if (soc_mem_index_count(unit, L3_DEFIP_ALPM_IPV4m)) { 2531 int non_alpm = num_shared_fpem_banks + num_shared_l3_banks + 2532 num_shared_l2_banks; 2533 if ((non_alpm) && (non_alpm <= 2)) { 2534 /* If Shared banks are used between ALPM and non-ALPM memories, 2535 * then ALPM uses Shared Bank B2, B3 and non-ALPM uses B4, B5 banks 2536 */ 2537 soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config, 2538 ALPM_ENTRY_BANK_CONFIGf, 0x3); 2539 soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map, 2540 ALPM_BANK_MODEf, 1); 2541 SOC_IF_ERROR_RETURN 2542 (soc_reg_field32_modify(unit, ISS_LOG_TO_PHY_BANK_MAP_2r, 2543 REG_PORT_ANY, ALPM_BANK_MODEf, 1)); 2544 SOC_IF_ERROR_RETURN 2545 (soc_reg_field32_modify(unit, ISS_MEMORY_CONTROL_84r, 2546 REG_PORT_ANY, BYPASS_ISS_MEMORY_LPf, 0x3)); 2547 soc_th_set_alpm_banks(unit, 2); 2548 shared_bank_offset = 2; 2549 } else { 2550 soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config, 2551 ALPM_ENTRY_BANK_CONFIGf, 0xf); 2552 soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map, 2553 ALPM_BANK_MODEf, 0); 2554 SOC_IF_ERROR_RETURN 2555 (soc_reg_field32_modify(unit, ISS_LOG_TO_PHY_BANK_MAP_2r, 2556 REG_PORT_ANY, ALPM_BANK_MODEf, 0)); 2557 SOC_IF_ERROR_RETURN 2558 (soc_reg_field32_modify(unit, ISS_MEMORY_CONTROL_84r, 2559 REG_PORT_ANY, BYPASS_ISS_MEMORY_LPf, 0xf)); 2560 soc_th_set_alpm_banks(unit, 4); 2561 } 2562 } 2563 2564 soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config, L2_ENTRY_BANK_CONFIGf, 2565 ((1 << num_shared_l2_banks) - 1) << shared_bank_offset); 2566 for (index = 0; index < num_shared_l2_banks; index++) { 2567 shared_bank = index + shared_bank_offset; 2568 soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map, 2569 l2_fields[index], shared_bank); 2570 } 2571 shared_bank_offset += num_shared_l2_banks; 2572 2573 soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config, L3_ENTRY_BANK_CONFIGf, 2574 ((1 << num_shared_l3_banks) - 1) << shared_bank_offset); 2575 for (index = 0; index < num_shared_l3_banks; index++) { 2576 shared_bank = index + shared_bank_offset;; 2577 soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map, 2578 l3_fields[index], shared_bank); 2579 } 2580 shared_bank_offset += num_shared_l3_banks; 2581 2582 soc_reg_field_set(unit, ISS_BANK_CONFIGr, &config, 2583 FPEM_ENTRY_BANK_CONFIGf, 2584 ((1 << num_shared_fpem_banks) - 1) << shared_bank_offset); 2585 for (index = 0; index < num_shared_fpem_banks; index++) { 2586 shared_bank = index + shared_bank_offset; 2587 soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, &map, 2588 fpem_fields[index], shared_bank); 2589 soc_reg_field_set(unit, ISS_LOG_TO_PHY_BANK_MAP_3r, &fpmap, 2590 fpem_fields[index], shared_bank); 2591 } 2592 2593 SOC_IF_ERROR_RETURN 2594 (soc_reg32_set(unit, ISS_BANK_CONFIGr, REG_PORT_ANY, 0, config)); 2595 SOC_IF_ERROR_RETURN 2596 (soc_reg32_set(unit, ISS_LOG_TO_PHY_BANK_MAPr, REG_PORT_ANY, 0, map)); 2597 SOC_IF_ERROR_RETURN 2598 (soc_th_iss_log_to_phy_bank_map_shadow_set(unit, map)); 2599 SOC_IF_ERROR_RETURN 2600 (soc_reg32_set(unit, ISS_LOG_TO_PHY_BANK_MAP_3r, REG_PORT_ANY, 0, fpmap)); 2601 2602 /* Bypass unused Port Blocks */ 2603 if (soc_property_get(unit, "disable_unused_port_blocks", TRUE)) { 2604 SOC_IF_ERROR_RETURN(soc_th_bypass_unused_pm(unit)); 2605 } 2606 2607 if (!(SOC_CONTROL(unit)->soc_flags & SOC_F_ALL_MODULES_INITED) && 2608 soc_feature(unit, soc_feature_turbo_boot)) { 2609 SOC_HW_RESET_START(unit); 2610 } 2611 2612 #ifdef BCM_IPROC_SUPPORT 2613 /* Reset all mHost processors */ 2614 SOC_IF_ERROR_RETURN(WRITE_MHOST_0_CR5_RST_CTRLr(unit, 0)); 2615 SOC_IF_ERROR_RETURN(WRITE_MHOST_1_CR5_RST_CTRLr(unit, 0)); 2616 /*Reset the common UARTs */ 2617 SOC_IF_ERROR_RETURN(WRITE_CHIPCOMMONG_UART0_UART_SRRr(unit, 1)); 2618 SOC_IF_ERROR_RETURN(WRITE_CHIPCOMMONG_UART1_UART_SRRr(unit, 1)); 2619 #endif 2620 2621 return SOC_E_NONE; 2622 } 2623 2624 #ifdef BCM_WARM_BOOT_SUPPORT 2625 /* 2626 * Function: 2627 * soc_tomahawk_chip_warmboot_reset 2628 * Purpose: 2629 * Special re-init sequencing for BCM56960 during warmboot 2630 */ 2631 int 2632 soc_tomahawk_chip_warmboot_reset(int unit) 2633 { 2634 uint32 map = 0; 2635 2636 SOC_IF_ERROR_RETURN 2637 (soc_reg32_get(unit, ISS_LOG_TO_PHY_BANK_MAPr, REG_PORT_ANY, 0, &map)); 2638 SOC_IF_ERROR_RETURN 2639 (soc_th_iss_log_to_phy_bank_map_shadow_set(unit, map)); 2640 2641 return SOC_E_NONE; 2642 } 2643 #endif 2644 2645 int 2646 soc_tomahawk_port_reset(int unit) 2647 { 2648 uint32 rval; 2649 int blk, port; 2650 int sleep_usec = SAL_BOOT_QUICKTURN ? 500000 : 1100; 2651 2652 #ifdef BCM_TOMAHAWK2_SUPPORT 2653 if (soc_feature(unit, soc_feature_pm_refclk_master)) { 2654 soc_info_t *si = &SOC_INFO(unit); 2655 if (!SHR_BITNULL_RANGE(si->pm_ref_master_bitmap, 0, 2656 SOC_MAX_NUM_BLKS)) { 2657 soc_xgxs_reset_master_tsc(unit); 2658 } 2659 } 2660 #endif 2661 2662 SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) { 2663 port = SOC_BLOCK_PORT(unit, blk); 2664 2665 SOC_IF_ERROR_RETURN(READ_CLPORT_MAC_CONTROLr(unit, port, &rval)); 2666 soc_reg_field_set(unit, CLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 1); 2667 SOC_IF_ERROR_RETURN(WRITE_CLPORT_MAC_CONTROLr(unit, port, rval)); 2668 sal_udelay(10); 2669 soc_reg_field_set(unit, CLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 0); 2670 /* PM interface is 16B in TH2 */ 2671 if (soc_feature(unit, soc_feature_clmac_16byte_interface_mode)) { 2672 soc_reg_field_set(unit, CLPORT_MAC_CONTROLr, &rval, 2673 SYS_16B_INTF_MODEf, 1); 2674 } 2675 SOC_IF_ERROR_RETURN(WRITE_CLPORT_MAC_CONTROLr(unit, port, rval)); 2676 } 2677 2678 SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) { 2679 port = SOC_BLOCK_PORT(unit, blk); 2680 2681 SOC_IF_ERROR_RETURN(READ_XLPORT_MAC_CONTROLr(unit, port, &rval)); 2682 soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 1); 2683 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MAC_CONTROLr(unit, port, rval)); 2684 sal_udelay(10); 2685 soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 0); 2686 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MAC_CONTROLr(unit, port, rval)); 2687 } 2688 2689 /* Power off CLPORT blocks */ 2690 SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) { 2691 port = SOC_BLOCK_PORT(unit, blk); 2692 SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 1)); 2693 } 2694 sal_usleep(sleep_usec + 10000); 2695 /* Power on CLPORT blocks */ 2696 SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) { 2697 port = SOC_BLOCK_PORT(unit, blk); 2698 SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 0)); 2699 } 2700 2701 /* Power off XLPORT blocks */ 2702 SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) { 2703 port = SOC_BLOCK_PORT(unit, blk); 2704 SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 1)); 2705 } 2706 sal_usleep(sleep_usec + 10000); 2707 /* Power off XLPORT blocks */ 2708 SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) { 2709 port = SOC_BLOCK_PORT(unit, blk); 2710 SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 0)); 2711 } 2712 2713 return SOC_E_NONE; 2714 } 2715 2716 int 2717 soc_tomahawkplus_port_reset(int unit) 2718 { 2719 uint32 rval; 2720 int blk, port; 2721 int sleep_usec = SAL_BOOT_QUICKTURN ? 500000 : 1100; 2722 2723 /* Power off CLPORT blocks */ 2724 SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) { 2725 port = SOC_BLOCK_PORT(unit, blk); 2726 SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 1)); 2727 } 2728 sal_usleep(sleep_usec + 10000); 2729 /* Power on CLPORT blocks */ 2730 SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) { 2731 port = SOC_BLOCK_PORT(unit, blk); 2732 SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 0)); 2733 } 2734 2735 /* Power off XLPORT blocks */ 2736 SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) { 2737 port = SOC_BLOCK_PORT(unit, blk); 2738 SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 1)); 2739 } 2740 sal_usleep(sleep_usec + 10000); 2741 /* Power off XLPORT blocks */ 2742 SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) { 2743 port = SOC_BLOCK_PORT(unit, blk); 2744 SOC_IF_ERROR_RETURN(soc_tsc_xgxs_power_mode(unit, port, 0, 0)); 2745 } 2746 2747 SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) { 2748 port = SOC_BLOCK_PORT(unit, blk); 2749 2750 SOC_IF_ERROR_RETURN(READ_CLPORT_MAC_CONTROLr(unit, port, &rval)); 2751 soc_reg_field_set(unit, CLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 1); 2752 SOC_IF_ERROR_RETURN(WRITE_CLPORT_MAC_CONTROLr(unit, port, rval)); 2753 sal_udelay(10); 2754 soc_reg_field_set(unit, CLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 0); 2755 SOC_IF_ERROR_RETURN(WRITE_CLPORT_MAC_CONTROLr(unit, port, rval)); 2756 } 2757 2758 SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) { 2759 port = SOC_BLOCK_PORT(unit, blk); 2760 2761 SOC_IF_ERROR_RETURN(READ_XLPORT_MAC_CONTROLr(unit, port, &rval)); 2762 soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 1); 2763 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MAC_CONTROLr(unit, port, rval)); 2764 sal_udelay(10); 2765 soc_reg_field_set(unit, XLPORT_MAC_CONTROLr, &rval, XMAC0_RESETf, 0); 2766 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MAC_CONTROLr(unit, port, rval)); 2767 } 2768 return SOC_E_NONE; 2769 } 2770 2771 2772 /* Configure HSP port multicast T2OQ setting. 2773 * Note: Caller must check if the Port is part of HSP port bitmap 2774 * HSP Port check: SOC_PBMP_MEMBER(si->eq_pbm, port) 2775 */ 2776 2777 STATIC int 2778 _soc_tomahawk_mc_toq_cfg(int unit, int port, int enable) 2779 { 2780 static soc_field_t t2oq_fields[] = { 2781 IS_MC_T2OQ_PORT0f, IS_MC_T2OQ_PORT1f 2782 }; 2783 soc_field_t field; 2784 uint32 rval, fval; 2785 int inst, pipe, mmu_port; 2786 soc_reg_t reg = MMU_SCFG_TOQ_MC_CFG1r; 2787 soc_info_t *si = &SOC_INFO(unit);; 2788 2789 pipe = si->port_pipe[port]; 2790 field = t2oq_fields[pipe & 0x01]; 2791 inst = (pipe >> 1) | SOC_REG_ADDR_INSTANCE_MASK; 2792 mmu_port = si->port_p2m_mapping[si->port_l2p_mapping[port]]; 2793 2794 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, 0, &rval)); 2795 fval = soc_reg_field_get(unit, reg, rval, field); 2796 if (enable) { 2797 fval |= 1 << (mmu_port & 0x0f); 2798 } else { 2799 fval &= ~(1 << (mmu_port & 0x0f)); 2800 } 2801 soc_reg_field_set(unit, reg, &rval, field, fval); 2802 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval)); 2803 2804 return SOC_E_NONE; 2805 } 2806 2807 /* 2808 * Utility function to update multicast initial copy count 2809 * Invoked during speed set and flexport operations. 2810 */ 2811 STATIC soc_error_t 2812 soc_tomahawk_update_icc(int unit, soc_port_t port, int port_speed) 2813 { 2814 soc_info_t *si = &SOC_INFO(unit); 2815 int phy_port, count_width; 2816 uint32 regval = 0; 2817 2818 phy_port = si->port_l2p_mapping[port]; 2819 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) || 2820 phy_port == 129 || phy_port == 131) { 2821 /* For CPU, loopback, and management ports, 2822 * the copy count width is fixed at 3 bits (encoded value of 1). 2823 * Pysical ports 129 and 131 are management ports. 2824 */ 2825 count_width = 1; 2826 } else { 2827 /* For ports with speed 40G and above the copy count width 2828 * is 3 bits (encoded value of 1) for lower speeds its 2829 * 2 bits (encoded value of 0). 2830 */ 2831 count_width = (port_speed >= 40000) ? 1 : 0; 2832 } 2833 soc_reg_field_set(unit, PORT_INITIAL_COPY_COUNT_WIDTHr, ®val, 2834 BIT_WIDTHf, count_width); 2835 SOC_IF_ERROR_RETURN(WRITE_PORT_INITIAL_COPY_COUNT_WIDTHr 2836 (unit, port, regval)); 2837 2838 return SOC_E_NONE; 2839 } 2840 2841 /* 2842 * Function to update Port PG's Headroom allocation. 2843 * Port PG needs to be updated during 2844 * 1. Flex (bcmPortControlLanes) operation 2845 * 2. Port Speed update (bcm_port_speed_set api) 2846 * Note: This function will update the Port's PG Headroom to the 2847 * updated port speed (soc_info.port_init_speed). 2848 */ 2849 STATIC 2850 int soc_tomahawk_port_pg_headroom_update(int unit, soc_port_t port) 2851 { 2852 #define DEFAULT_PG_NUM 7 /* Default Priority Group Num */ 2853 int headroom, lossless, pipe, midx; 2854 soc_mem_t mem; 2855 thdi_port_pg_config_entry_t pg_config_mem_entry; 2856 2857 lossless = SOC_INFO(unit).mmu_lossless; 2858 headroom = _soc_th_default_pg_headroom(unit, port, lossless); 2859 pipe = SOC_INFO(unit).port_pipe[port]; 2860 mem = SOC_MEM_UNIQUE_ACC(unit, THDI_PORT_PG_CONFIGm)[pipe]; 2861 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, port, THDI_PORT_PG_CONFIGm, 2862 DEFAULT_PG_NUM); 2863 SOC_IF_ERROR_RETURN 2864 (soc_mem_read(unit, mem, MEM_BLOCK_ANY, midx, &pg_config_mem_entry)); 2865 soc_mem_field32_set(unit, mem, &pg_config_mem_entry, 2866 PG_HDRM_LIMITf, headroom); 2867 SOC_IF_ERROR_RETURN 2868 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, midx, &pg_config_mem_entry)); 2869 return SOC_E_NONE; 2870 } 2871 2872 STATIC int 2873 _soc_tomahawk_port_mixed_speed_check(int unit, soc_th_port_lanes_t *lanes_ctrl) 2874 { 2875 soc_info_t *si = &SOC_INFO(unit); 2876 soc_port_t phy_port_base, phy_port; 2877 soc_port_t port_sub, port_sis; 2878 int port_sub_speed, port_sis_speed; 2879 soc_port_t port_base = lanes_ctrl->port_base; 2880 2881 phy_port = si->port_l2p_mapping[port_base]; 2882 if (-1 == phy_port) { 2883 return SOC_E_PORT; 2884 } 2885 phy_port_base = PORT_BLOCK_BASE_PORT(port_base); 2886 if ((phy_port_base != phy_port) && ((phy_port_base + 2) != phy_port)) { 2887 /* Not a controlling port, skip the checking */ 2888 return SOC_E_NONE; 2889 } 2890 2891 /* check mixed sister port mode */ 2892 port_sub = si->port_p2l_mapping[phy_port_base]; 2893 port_sis = si->port_p2l_mapping[phy_port_base + 2]; 2894 if (phy_port_base == phy_port) { 2895 port_sub_speed = lanes_ctrl->speed; 2896 } else { 2897 port_sub_speed = si->port_init_speed[port_sub]; 2898 } 2899 if ((phy_port_base + 2) == phy_port) { 2900 port_sis_speed = lanes_ctrl->speed; 2901 } else { 2902 port_sis_speed = si->port_init_speed[port_sis]; 2903 } 2904 2905 if (!SOC_PBMP_MEMBER(si->all.disabled_bitmap, si->port_p2l_mapping[phy_port_base + 1]) || 2906 !SOC_PBMP_MEMBER(si->all.disabled_bitmap, si->port_p2l_mapping[phy_port_base + 3])) { 2907 return SOC_E_PORT; 2908 } 2909 2910 if (((port_sub_speed == 50000) && (port_sis_speed == 50000)) || 2911 ((port_sub_speed == 53000) && (port_sis_speed == 53000))) { 2912 lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_50_0_50_0; 2913 } else if (((port_sub_speed == 50000) && (port_sis_speed == 25000)) || 2914 ((port_sub_speed == 53000) && (port_sis_speed == 27000))) { 2915 lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_50_0_25_0; 2916 } else if (((port_sub_speed == 25000) && (port_sis_speed == 50000)) || 2917 ((port_sub_speed == 27000) && (port_sis_speed == 53000))) { 2918 lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_25_0_50_0; 2919 } else if (((port_sub_speed == 25000) && (port_sis_speed == 25000)) || 2920 ((port_sub_speed == 27000) && (port_sis_speed == 27000))) { 2921 lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_25_0_25_0; 2922 } else if (((port_sub_speed == 40000) && (port_sis_speed == 40000)) || 2923 ((port_sub_speed == 43000) && (port_sis_speed == 43000))) { 2924 lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_40_0_40_0; 2925 } else if (((port_sub_speed == 20000) && (port_sis_speed == 20000)) || 2926 ((port_sub_speed == 21000) && (port_sis_speed == 21000))) { 2927 lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_20_0_20_0; 2928 } else { 2929 lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_0; 2930 } 2931 if (lanes_ctrl->mixed_port_mode == MIXED_DUAL_MODE_0) { 2932 return SOC_E_PORT; 2933 } 2934 2935 return SOC_E_NONE; 2936 } 2937 2938 int 2939 soc_tomahawk_port_speed_update(int unit, soc_port_t port, int speed) 2940 { 2941 uint32 rval, fval; 2942 uint32 entry[SOC_MAX_MEM_WORDS]; 2943 soc_info_t *si = &SOC_INFO(unit); 2944 soc_port_t it_port; 2945 int port_rename = 0; 2946 int rv; 2947 soc_th_port_lanes_t lanes_ctrl; 2948 2949 sal_memset(&lanes_ctrl, 0, sizeof(lanes_ctrl)); 2950 lanes_ctrl.port_base = port; 2951 lanes_ctrl.lanes = TH_FLEXPORT_SPEED_SET_NUM_LANES; 2952 lanes_ctrl.cur_lanes = TH_FLEXPORT_SPEED_SET_NUM_LANES; 2953 lanes_ctrl.speed = speed; 2954 lanes_ctrl.os_mixed_sister = si->os_mixed_sister_25_50_enable; 2955 2956 SOC_IF_ERROR_RETURN(READ_CLPORT_MODE_REGr(unit, port, &rval)); 2957 lanes_ctrl.cur_mode = soc_reg_field_get(unit, CLPORT_MODE_REGr, rval, 2958 XPORT0_CORE_PORT_MODEf); 2959 2960 /* Validate the port config under Mixed Speed */ 2961 if ((lanes_ctrl.os_mixed_sister) && 2962 (lanes_ctrl.cur_mode == SOC_TH_PORT_MODE_DUAL)) { 2963 if (!SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) { 2964 SOC_IF_ERROR_RETURN(_soc_tomahawk_port_mixed_speed_check(unit, &lanes_ctrl)); 2965 } 2966 } 2967 2968 /* 2969 * Update bitmaps and port names of Management Port 2970 * when shift b/w XE <=> GE <=> FE 2971 */ 2972 if (SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) { 2973 if (IS_XE_PORT(unit, port) && (speed < 10000) && (speed > 100)) { 2974 SOC_PBMP_PORT_REMOVE(si->xe.bitmap, port); 2975 SOC_PBMP_PORT_ADD(si->ge.bitmap, port); 2976 port_rename = 1; 2977 } else if (IS_XE_PORT(unit, port) && (speed <= 100)) { 2978 SOC_PBMP_PORT_REMOVE(si->xe.bitmap, port); 2979 SOC_PBMP_PORT_ADD(si->fe.bitmap, port); 2980 port_rename = 1; 2981 } else if (IS_GE_PORT(unit, port) && (speed == 10000)) { 2982 SOC_PBMP_PORT_REMOVE(si->ge.bitmap, port); 2983 SOC_PBMP_PORT_ADD(si->xe.bitmap, port); 2984 port_rename = 1; 2985 } else if (IS_GE_PORT(unit, port) && (speed <= 100)) { 2986 SOC_PBMP_PORT_REMOVE(si->ge.bitmap, port); 2987 SOC_PBMP_PORT_ADD(si->fe.bitmap, port); 2988 port_rename = 1; 2989 } else if (IS_FE_PORT(unit, port) && (speed == 10000)) { 2990 SOC_PBMP_PORT_REMOVE(si->fe.bitmap, port); 2991 SOC_PBMP_PORT_ADD(si->xe.bitmap, port); 2992 port_rename = 1; 2993 } else if (IS_FE_PORT(unit, port) && (speed < 10000) && (speed > 100)) { 2994 SOC_PBMP_PORT_REMOVE(si->fe.bitmap, port); 2995 SOC_PBMP_PORT_ADD(si->ge.bitmap, port); 2996 port_rename = 1; 2997 } 2998 } 2999 if (port_rename) { 3000 _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(xe); 3001 _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(ge); 3002 _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(fe); 3003 soc_dport_map_update(unit); 3004 } 3005 3006 /* 3007 * No reconfiguration is needed if new speed 3008 * matches current speed 3009 */ 3010 if (speed == si->port_init_speed[port]) { 3011 return SOC_E_NONE; 3012 } 3013 3014 /* Update HSP port multicast T2OQ setting */ 3015 if (SOC_PBMP_MEMBER(si->eq_pbm, port) && (!SOC_IS_TOMAHAWK2(unit))) { 3016 SOC_IF_ERROR_RETURN 3017 (_soc_tomahawk_mc_toq_cfg(unit, port, 3018 (speed >= 40000) ? TRUE : FALSE)); 3019 } 3020 3021 rv = soc_th_port_asf_mode_set(unit, port, speed, 3022 _SOC_TH_ASF_MODE_CFG_UPDATE); 3023 if ((SOC_E_NONE != rv) && (SOC_E_UNAVAIL != rv) && (SOC_E_PARAM != rv)) { 3024 return rv; 3025 } 3026 3027 /* OS related updates */ 3028 if (SOC_PBMP_NOT_NULL(SOC_INFO(unit).oversub_pbm)) { 3029 int factor = SOC_IS_TOMAHAWK2(unit) ? 178125 : 118750; 3030 sal_memset(entry, 0, sizeof(egr_xmit_start_count_entry_t)); 3031 fval = ((speed / 10) * factor) / 100000; 3032 soc_mem_field32_set(unit, EDB_1DBG_Bm, &entry, FIELD_Bf, fval); 3033 SOC_IF_ERROR_RETURN 3034 (soc_mem_write(unit, EDB_1DBG_Bm, MEM_BLOCK_ALL, 3035 SOC_INFO(unit).port_l2p_mapping[port], entry)); 3036 3037 rval = 0; 3038 if (speed >= 100000) { 3039 fval = 140; 3040 } else if (speed >= 40000) { 3041 fval = 60; 3042 } else if (speed >= 25000) { 3043 fval = 40; 3044 } else if (speed >= 20000) { 3045 fval = 30; 3046 } else { 3047 fval = 15; 3048 } 3049 soc_reg_field_set(unit, MMU_3DBG_Cr, &rval, FIELD_Af, 3050 fval + sal_rand() % 20); 3051 SOC_IF_ERROR_RETURN 3052 (soc_tomahawk_sc_reg32_set(unit, MMU_3DBG_Cr, -1, port, 0, rval)); 3053 } 3054 3055 if (!SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) { 3056 SOC_IF_ERROR_RETURN(soc_th_speed_set_init_ctrl(unit, &lanes_ctrl)); 3057 SOC_IF_ERROR_RETURN 3058 (soc_tomahawk_port_lanes_set(unit, &lanes_ctrl)); 3059 } 3060 3061 return SOC_E_NONE; 3062 } 3063 3064 /* 3065 * Utility routine called when converting an HiGig2 encapped port 3066 * to IEEE encap. This routine returns the IEEE speed corresponding 3067 * to the current HG speed of the port 3068 */ 3069 int 3070 soc_th_port_ie_speed_get(int unit, soc_port_t port, int *speed) 3071 { 3072 soc_info_t *si; 3073 si = &SOC_INFO(unit); 3074 3075 switch (si->port_init_speed[port]) { 3076 case 11000: 3077 *speed = 10000; 3078 break; 3079 case 21000: 3080 *speed = 20000; 3081 break; 3082 case 27000: 3083 *speed = 25000; 3084 break; 3085 case 42000: 3086 *speed = 40000; 3087 break; 3088 case 53000: 3089 *speed = 50000; 3090 break; 3091 case 106000: 3092 *speed = 100000; 3093 break; 3094 default: 3095 /* port_init_speed is already IEEE speed */ 3096 *speed = si->port_init_speed[port]; 3097 break; 3098 } 3099 3100 return SOC_E_NONE; 3101 } 3102 3103 /* 3104 * Utility routine called when converting an IEEE encapped port 3105 * to HiGig2 encap. This routine returns the HG speed corresponding 3106 * to the current ethernet speed of the port 3107 */ 3108 int 3109 soc_th_port_hg_speed_get(int unit, soc_port_t port, int *speed) 3110 { 3111 soc_info_t *si; 3112 si = &SOC_INFO(unit); 3113 3114 switch (si->port_init_speed[port]) { 3115 case 10000: 3116 *speed = 11000; 3117 break; 3118 case 20000: 3119 *speed = 21000; 3120 break; 3121 case 25000: 3122 *speed = 27000; 3123 break; 3124 case 40000: 3125 *speed = 42000; 3126 break; 3127 case 50000: 3128 *speed = 53000; 3129 break; 3130 case 100000: 3131 *speed = 106000; 3132 break; 3133 default: 3134 /* port_init_speed is already HG speed */ 3135 *speed = si->port_init_speed[port]; 3136 break; 3137 } 3138 3139 return SOC_E_NONE; 3140 } 3141 3142 int 3143 soc_tomahawk_xpe_base_index_check(int unit, int base_type, int xpe, 3144 int base_index, char *msg) 3145 { 3146 soc_info_t *si; 3147 int pipe; 3148 uint32 map; 3149 char *base_name; 3150 3151 si = &SOC_INFO(unit); 3152 3153 if (xpe == -1 || base_index == -1) { 3154 return SOC_E_NONE; 3155 } 3156 3157 if (xpe < NUM_XPE(unit) && si->xpe_ipipe_map[xpe] == 0) { 3158 if (msg) { 3159 LOG_CLI((BSL_META_U(unit, 3160 "%s: XPE%d is not in config\n"), 3161 msg, xpe)); 3162 } 3163 return SOC_E_PARAM; 3164 } 3165 3166 switch (base_type) { 3167 case 0: /* IPORT */ 3168 case 1: /* EPORT */ 3169 base_name = base_type == 0 ? "IPORT" : "EPORT"; 3170 pipe = si->port_pipe[base_index]; 3171 if (pipe == -1) { 3172 if (msg) { 3173 LOG_CLI((BSL_META_U(unit, 3174 "%s: %s%d is not in config\n"), 3175 msg, base_name, base_index)); 3176 } 3177 } else if (xpe < NUM_XPE(unit)) { /* Unique access type */ 3178 map = base_type == 0 ? 3179 si->ipipe_xpe_map[pipe] : si->epipe_xpe_map[pipe]; 3180 if (map & (1 << xpe)) { 3181 break; 3182 } 3183 if (msg != NULL) { 3184 LOG_CLI((BSL_META_U(unit, 3185 "%s: %s%d is not in XPE%d\n"), 3186 msg, base_name, base_index, xpe)); 3187 } 3188 } else { 3189 break; 3190 } 3191 return SOC_E_PARAM; 3192 case 2: /* IPIPE */ 3193 case 3: /* EPIPE */ 3194 if (base_type == 2) { 3195 base_name = "IPIPE"; 3196 map = si->ipipe_xpe_map[base_index]; 3197 } else { 3198 base_name = "EPIPE"; 3199 map = si->epipe_xpe_map[base_index]; 3200 } 3201 if (map == 0) { 3202 if (msg) { 3203 LOG_CLI((BSL_META_U(unit, 3204 "%s: %s%d is not in config\n"), 3205 msg, base_name, base_index)); 3206 } 3207 } else if (xpe < NUM_XPE(unit)) { /* Unique access type */ 3208 if (map & (1 << xpe)) { 3209 break; 3210 } 3211 if (msg != NULL) { 3212 LOG_CLI((BSL_META_U(unit, 3213 "%s: %s%d is not in XPE%d\n"), 3214 msg, base_name, base_index, xpe)); 3215 } 3216 } else { 3217 break; 3218 } 3219 return SOC_E_PARAM; 3220 case 4: /* CHIP */ 3221 break; 3222 case 5: /* XPE */ 3223 if (si->xpe_ipipe_map[base_index] != 0) { 3224 break; 3225 } 3226 if (msg != NULL) { 3227 LOG_CLI((BSL_META_U(unit, 3228 "%s: XPE%d is not in config\n"), 3229 msg, base_index)); 3230 } 3231 return SOC_E_PARAM; 3232 case 6: /* SLICE */ 3233 if (si->sc_ipipe_map[base_index] == 0) { 3234 if (msg != NULL) { 3235 LOG_CLI((BSL_META_U(unit, 3236 "%s: SLICE%d is not in config\n"), 3237 msg, base_index)); 3238 } 3239 } else if (xpe < NUM_XPE(unit)) { /* Unique access type */ 3240 if (xpe & 1) { /* XPE 1 and 3 are in slice 1 */ 3241 if (base_index == 1) { 3242 break; 3243 } 3244 } else { /* XPE 0 and 2 are in slice 0 */ 3245 if (base_index == 0) { 3246 break; 3247 } 3248 } 3249 if (msg != NULL) { 3250 LOG_CLI((BSL_META_U(unit, 3251 "%s: XPE%d is not in SLICE%d\n"), 3252 msg, xpe, base_index)); 3253 } 3254 } else { 3255 break; 3256 } 3257 return SOC_E_PARAM; 3258 case 7: /* LAYER */ 3259 if (xpe & 2) { /* XPE 2 and 3 are in layer 1 */ 3260 if (base_index == 1) { 3261 break; 3262 } 3263 } else { /* XPE 0 and 1 are in layer 0 */ 3264 if (base_index == 0) { 3265 break; 3266 } 3267 } 3268 if (msg) { 3269 LOG_CLI((BSL_META_U(unit, 3270 "%s: XPE%d is not in LAYER%d\n"), 3271 msg, xpe, base_index)); 3272 } 3273 return SOC_E_PARAM; 3274 } 3275 3276 return SOC_E_NONE; 3277 } 3278 3279 void soc_th_set_alpm_banks(int unit, int alpm_banks) 3280 { 3281 num_shared_alpm_banks[unit] = alpm_banks; 3282 return; 3283 } 3284 3285 int soc_th_get_alpm_banks(int unit) 3286 { 3287 int rv = SOC_E_NONE; 3288 uint32 bank_config = 0xf; 3289 uint32 config = 0; 3290 3291 if (num_shared_alpm_banks[unit] == 0) { 3292 rv = soc_reg32_get(unit, ISS_BANK_CONFIGr, REG_PORT_ANY, 0, &config); 3293 if (SOC_FAILURE(rv)) { 3294 num_shared_alpm_banks[unit] = 4; 3295 } else { 3296 bank_config = soc_reg_field_get(unit, ISS_BANK_CONFIGr, config, 3297 ALPM_ENTRY_BANK_CONFIGf); 3298 if (bank_config == 0x3) { 3299 num_shared_alpm_banks[unit] = 2; 3300 } else { 3301 num_shared_alpm_banks[unit] = 4; 3302 } 3303 } 3304 } 3305 3306 return num_shared_alpm_banks[unit]; 3307 } 3308 3309 int 3310 soc_tomahawk_alpm_mode_get(int unit) 3311 { 3312 return _soc_alpm_mode[unit]; 3313 } 3314 3315 void 3316 _soc_tomahawk_alpm_bkt_view_set(int unit, int index, soc_mem_t view) 3317 { 3318 int bkt = (index >> (soc_th_get_alpm_banks(unit) + 1) / 2) & SOC_TH_ALPM_BKT_MASK(unit); 3319 3320 if (view != INVALIDm) { 3321 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3322 (BSL_META_U(unit, 3323 "Unit:%d ALPM bkt set index:%d bkt:%d view:%s\n"), 3324 unit, index, bkt, SOC_MEM_NAME(unit, view))); 3325 } 3326 _soc_th_alpm_bkt_view_map[unit][bkt] = view; 3327 } 3328 3329 soc_mem_t 3330 _soc_tomahawk_alpm_bkt_view_get(int unit, int index) 3331 { 3332 soc_mem_t view; 3333 int bkt = (index >> (soc_th_get_alpm_banks(unit) + 1) / 2) & SOC_TH_ALPM_BKT_MASK(unit); 3334 3335 view = _soc_th_alpm_bkt_view_map[unit][bkt]; 3336 if (view != INVALIDm) { 3337 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3338 (BSL_META_U(unit, 3339 "Unit:%d ALPM bkt get index:%d bkt:%d view:%s\n"), 3340 unit, index, bkt, SOC_MEM_NAME(unit, view))); 3341 } 3342 return view; 3343 } 3344 3345 int soc_tomahawk_mem_basetype_get(int unit, soc_mem_t mem) 3346 { 3347 int base_type; 3348 3349 base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7; 3350 return base_type; 3351 } 3352 3353 int soc_tomahawk_mem_is_xpe(int unit, soc_mem_t mem) 3354 { 3355 int block_info_index; 3356 3357 if (!SOC_MEM_IS_VALID(unit, mem)) { 3358 return 0; 3359 } 3360 3361 block_info_index = SOC_MEM_BLOCK_ANY(unit, mem); 3362 if (SOC_BLOCK_TYPE(unit, block_info_index) == SOC_BLK_MMU_XPE) { 3363 return 1; 3364 } else { 3365 return 0; 3366 } 3367 } 3368 3369 /* Function to check if given XPE/PIPE combo matches for the given mem's base 3370 * type definition. 3371 */ 3372 int 3373 soc_tomahawk_mem_xpe_pipe_check(int unit, soc_mem_t mem, int xpe, int pipe) 3374 { 3375 int rv = SOC_E_NONE; 3376 int block_info_index, base_type; 3377 3378 block_info_index = SOC_MEM_BLOCK_ANY(unit, mem); 3379 if (SOC_BLOCK_TYPE(unit, block_info_index) != SOC_BLK_MMU_XPE) { 3380 return SOC_E_PARAM; 3381 } 3382 3383 base_type = soc_tomahawk_mem_basetype_get(unit, mem); 3384 rv = soc_tomahawk_xpe_base_index_check(unit, base_type, xpe, pipe, NULL); 3385 3386 if (rv == SOC_E_PARAM) { 3387 rv = SOC_E_UNAVAIL; 3388 } 3389 3390 return rv; 3391 } 3392 3393 STATIC int 3394 _soc_tomahawk_xpe_reg_check(int unit, soc_reg_t reg, int xpe, int base_index) 3395 { 3396 int acc_type, base_type; 3397 3398 if (!SOC_BLOCK_IN_LIST(SOC_REG_INFO(unit, reg).block, SOC_BLK_MMU_XPE)) { 3399 LOG_CLI((BSL_META_U(unit, 3400 "%s is not XPE register\n"), SOC_REG_NAME(unit, reg))); 3401 return SOC_E_PARAM; 3402 } 3403 3404 if (SOC_REG_UNIQUE_ACC(unit, reg) != NULL) { /* UNIQUE base register */ 3405 if (xpe == -1 || xpe >= NUM_XPE(unit)) { 3406 LOG_CLI((BSL_META_U(unit, 3407 "%s bad XPE value %d\n"), 3408 SOC_REG_NAME(unit, reg), xpe)); 3409 return SOC_E_PARAM; 3410 } 3411 } else { 3412 acc_type = SOC_REG_ACC_TYPE(unit, reg); 3413 if (acc_type < NUM_XPE(unit)) { /* UNIQUE per XPE register */ 3414 if (xpe != acc_type) { 3415 LOG_CLI((BSL_META_U(unit, 3416 "Ovveride XPE value %d with ACC_TYPE of %s\n"), 3417 xpe, SOC_REG_NAME(unit, reg))); 3418 } 3419 xpe = acc_type; 3420 } else { /* non-UNIQUE register */ 3421 return SOC_E_NONE; 3422 } 3423 } 3424 base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7; 3425 3426 return soc_tomahawk_xpe_base_index_check(unit, base_type, xpe, base_index, 3427 SOC_REG_NAME(unit, reg)); 3428 } 3429 3430 STATIC int 3431 _soc_tomahawk_xpe_mem_check(int unit, soc_mem_t mem, int xpe, int base_index) 3432 { 3433 int block_info_index, acc_type, base_type; 3434 3435 block_info_index = SOC_MEM_BLOCK_ANY(unit, mem); 3436 if (SOC_BLOCK_TYPE(unit, block_info_index) != SOC_BLK_MMU_XPE) { 3437 LOG_CLI((BSL_META_U(unit, 3438 "%s is not XPE register\n"), SOC_MEM_NAME(unit, mem))); 3439 return SOC_E_PARAM; 3440 } 3441 3442 if (SOC_MEM_UNIQUE_ACC(unit, mem) != NULL) { /* UNIQUE base memory */ 3443 if (xpe == -1 || xpe >= NUM_XPE(unit)) { 3444 LOG_CLI((BSL_META_U(unit, 3445 "%s bad XPE value %d\n"), 3446 SOC_MEM_NAME(unit, mem), xpe)); 3447 return SOC_E_PARAM; 3448 } 3449 } else { 3450 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 3451 if (acc_type < NUM_XPE(unit)) { /* UNIQUE per XPE memory */ 3452 if (xpe != acc_type) { 3453 LOG_CLI((BSL_META_U(unit, 3454 "Ovveride XPE value %d with ACC_TYPE of %s\n"), 3455 xpe, SOC_MEM_NAME(unit, mem))); 3456 xpe = acc_type; 3457 } 3458 } else { /* non-UNIQUE memory */ 3459 return SOC_E_NONE; 3460 } 3461 } 3462 base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7; 3463 3464 return soc_tomahawk_xpe_base_index_check(unit, base_type, xpe, base_index, 3465 SOC_MEM_NAME(unit, mem)); 3466 } 3467 3468 /* 3469 * Parameters for soc_tomahawk_xpe_reg_access and soc_tomahawk_xpe_mem_access: 3470 * 3471 * base unique reg/ xpe write action read action 3472 * index type mem 3473 * ==== ====== ===== === ================ ================= 3474 * #1 -1 no - - all XPEs/pipes first pipe in the first XPE 3475 * #2 -1 yes base -1 (same as #1) 3476 * #3 -1 yes base 0-3 all pipes in the XPE first pipe in the XPE 3477 * #4 -1 yes xpe0-3 - (same as #3) 3478 * #5 0-3 no - - applicable XPEs first XPE has the pipe 3479 * #6 0-3 yes base -1 (same as #5) 3480 * #7 0-3 yes base 0-3 the XPE/pipe the XPE/pipe 3481 * #8 0-3 yes xpe0-3 - (same as #7) 3482 * 3483 * - S/W will loop through base types (i.e. pipes) if base_index==-1 3484 * - S/W will loop through applicable XPEs if xpe==-1 on unique access type 3485 * base view (H/W will do the loop for other access types) 3486 * - base_index will be ignored if the table does not have multiple sections 3487 * for example ACC_TYPE==UNIQUE BASE_TYPE==XPE 3488 */ 3489 STATIC int 3490 _soc_tomahawk_xpe_reg_access(int unit, soc_reg_t reg, int xpe, int base_index, 3491 int index, uint64 *data, int write) 3492 { 3493 soc_info_t *si; 3494 soc_reg_t orig_reg; 3495 int port; 3496 int base_type, break_after_first, unique, accessed; 3497 int base_index_count; 3498 uint32 base_index_map, xpe_map=0, orig_xpe_map; 3499 soc_pbmp_t base_index_pbmp; 3500 uint32 inst; 3501 3502 si = &SOC_INFO(unit); 3503 orig_reg = reg; 3504 base_type = SOC_REG_BASE_TYPE(unit, reg); 3505 break_after_first = TRUE; 3506 3507 if (xpe >= 0 && base_index >= 0) { 3508 SOC_IF_ERROR_RETURN 3509 (_soc_tomahawk_xpe_reg_check(unit, reg, xpe, base_index)); 3510 } 3511 3512 switch (base_type) { 3513 case 0: /* IPORT */ 3514 case 1: /* EPORT */ 3515 if (xpe >= 0 && SOC_REG_UNIQUE_ACC(unit, reg) != NULL) { 3516 reg = SOC_REG_UNIQUE_ACC(unit, reg)[xpe]; 3517 } 3518 3519 if (base_index == -1) { 3520 SOC_PBMP_ASSIGN(base_index_pbmp, PBMP_ALL(unit)); 3521 } else { 3522 /* This argument is logical port, same as soc_reg_get/set */ 3523 SOC_PBMP_PORT_SET(base_index_pbmp, base_index); 3524 } 3525 3526 SOC_PBMP_ITER(base_index_pbmp, port) { 3527 /* Loop through XPE(s) only on UNIQUE type base register */ 3528 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) { 3529 if (base_index < -1) { 3530 return SOC_E_PARAM; 3531 } else if (base_index == -1) { 3532 xpe_map = 0xf; 3533 } else { 3534 xpe_map = base_type == 0 ? 3535 si->ipipe_xpe_map[base_index] : 3536 si->epipe_xpe_map[base_index]; 3537 } 3538 if (write) { 3539 break_after_first = FALSE; 3540 } 3541 } 3542 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 3543 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) { 3544 if (!(xpe_map & (1 << xpe))) { 3545 continue; 3546 } 3547 reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[xpe]; 3548 } 3549 if (write) { 3550 SOC_IF_ERROR_RETURN 3551 (soc_reg_set(unit, reg, port, index, *data)); 3552 } else { 3553 SOC_IF_ERROR_RETURN 3554 (soc_reg_get(unit, reg, port, index, data)); 3555 } 3556 if (break_after_first) { 3557 break; 3558 } 3559 } 3560 } 3561 break; 3562 case 2: /* IPIPE */ 3563 case 3: /* EPIPE */ 3564 if (xpe >= 0 && SOC_REG_UNIQUE_ACC(unit, reg) != NULL) { 3565 reg = SOC_REG_UNIQUE_ACC(unit, reg)[xpe]; 3566 } 3567 3568 soc_tomahawk_pipe_map_get(unit, &base_index_map); 3569 if (base_index != -1) { 3570 base_index_map &= 1 << base_index; 3571 if (base_index_map == 0) { 3572 return SOC_E_PARAM; 3573 } 3574 } 3575 3576 for (base_index = 0; base_index < NUM_PIPE(unit); base_index++) { 3577 if (!(base_index_map & (1 << base_index))) { 3578 continue; 3579 } 3580 /* Loop through XPE(s) only on UNIQUE type base register */ 3581 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) { 3582 xpe_map = base_type == 2 ? 3583 si->ipipe_xpe_map[base_index] : 3584 si->epipe_xpe_map[base_index]; 3585 if (write) { 3586 break_after_first = FALSE; 3587 } 3588 } 3589 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 3590 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) { 3591 if (!(xpe_map & (1 << xpe))) { 3592 continue; 3593 } 3594 reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[xpe]; 3595 } 3596 inst = base_index | SOC_REG_ADDR_INSTANCE_MASK; 3597 if (write) { 3598 SOC_IF_ERROR_RETURN 3599 (soc_reg_set(unit, reg, inst, index, *data)); 3600 } else { 3601 SOC_IF_ERROR_RETURN 3602 (soc_reg_get(unit, reg, inst, index, data)); 3603 } 3604 if (break_after_first) { 3605 break; 3606 } 3607 } 3608 } 3609 break; 3610 case 4: /* CHIP */ 3611 if (xpe == -1) { 3612 xpe_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1]; 3613 } else { 3614 xpe_map = (1 << xpe) & (si->ipipe_xpe_map[0]|si->ipipe_xpe_map[1]); 3615 } 3616 unique = (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL); 3617 3618 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 3619 if (!(xpe_map & (1 << xpe))) { 3620 continue; 3621 } 3622 3623 if (unique) { 3624 reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[xpe]; 3625 } 3626 if (write) { 3627 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, 0, index, *data)); 3628 } else { 3629 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, 0, index, data)); 3630 } 3631 /* only unique writing need access all xpe */ 3632 if (!(write && unique)) { 3633 break; 3634 } 3635 } 3636 break; 3637 case 5: /* XPE */ 3638 if (xpe >= 0 && SOC_REG_UNIQUE_ACC(unit, reg) != NULL) { 3639 reg = SOC_REG_UNIQUE_ACC(unit, reg)[xpe]; 3640 } 3641 3642 if (SOC_REG_UNIQUE_ACC(unit, reg) != NULL || 3643 SOC_REG_ACC_TYPE(unit, reg) < NUM_XPE(unit)) { 3644 base_index_map = 1; 3645 } else if (base_index == -1) { 3646 base_index_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1]; 3647 } else { 3648 base_index_map = 1 << base_index; 3649 } 3650 3651 /* Loop through XPE(s) only on UNIQUE type base register */ 3652 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) { 3653 xpe_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1]; 3654 break_after_first = FALSE; 3655 } 3656 3657 for (base_index = 0; base_index < NUM_XPE(unit); base_index++) { 3658 if (!(base_index_map & (1 << base_index))) { 3659 continue; 3660 } 3661 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 3662 if (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL) { 3663 if (!(xpe_map & (1 << xpe))) { 3664 continue; 3665 } 3666 reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[xpe]; 3667 } 3668 inst = base_index | SOC_REG_ADDR_INSTANCE_MASK; 3669 if (write) { 3670 SOC_IF_ERROR_RETURN 3671 (soc_reg_set(unit, reg, inst, index, *data)); 3672 } else { 3673 SOC_IF_ERROR_RETURN 3674 (soc_reg_get(unit, reg, inst, index, data)); 3675 } 3676 if (break_after_first) { 3677 break; 3678 } 3679 } 3680 } 3681 break; 3682 case 6: /* SLICE */ 3683 case 7: /* LAYER */ 3684 if (base_index == -1) { 3685 base_index_map = base_type == 6 ? si->ipipe_sc_map[0] : 0x3; 3686 } else { 3687 base_index_map = 1 << base_index; 3688 } 3689 if (xpe == -1) { 3690 orig_xpe_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1]; 3691 } else { 3692 orig_xpe_map = (1 << xpe); 3693 } 3694 unique = (SOC_REG_UNIQUE_ACC(unit, orig_reg) != NULL); 3695 accessed = 0; 3696 3697 base_index_count = base_type == 6 ? NUM_SLICE(unit) : NUM_LAYER(unit); 3698 for (base_index = 0; base_index < base_index_count; base_index++) { 3699 if (!(base_index_map & (1 << base_index))) { 3700 continue; 3701 } 3702 3703 /* Loop through XPE(s) only on UNIQUE type base register */ 3704 if (base_type == 6) { 3705 /* epipe 0 on sc 0, epipe 2 on sc 1 */ 3706 xpe_map = si->epipe_xpe_map[base_index * 2]; 3707 } else { 3708 /* ipipe 0 on layer 0, ipipe 1 on layer 1 */ 3709 xpe_map = si->ipipe_xpe_map[base_index]; 3710 } 3711 xpe_map &= orig_xpe_map; 3712 3713 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 3714 if (!(xpe_map & (1 << xpe))) { 3715 continue; 3716 } 3717 3718 if (unique) { 3719 reg = SOC_REG_UNIQUE_ACC(unit, orig_reg)[xpe]; 3720 } 3721 inst = base_index | SOC_REG_ADDR_INSTANCE_MASK; 3722 if (write) { 3723 SOC_IF_ERROR_RETURN 3724 (soc_reg_set(unit, reg, inst, index, *data)); 3725 } else { 3726 SOC_IF_ERROR_RETURN 3727 (soc_reg_get(unit, reg, inst, index, data)); 3728 } 3729 accessed = 1; 3730 /* only unique writing need access all xpe */ 3731 if (!(write && unique)) { 3732 break; 3733 } 3734 } 3735 /* reading operation breaks if accessed */ 3736 if ((!write) && (accessed)) { 3737 break; 3738 } 3739 } 3740 break; 3741 /* No default case as base_type can have value only between 0-7 */ 3742 } 3743 3744 return SOC_E_NONE; 3745 } 3746 3747 STATIC int 3748 _soc_tomahawk_xpe_mem_access(int unit, soc_mem_t mem, int xpe, int base_index, 3749 int copyno, int offset_in_section, 3750 void *entry_data, int write) 3751 { 3752 soc_info_t *si; 3753 soc_mem_t mem_list[8] = {INVALIDm}; 3754 int mem_index, mem_cnt; 3755 int index; 3756 int base_type; 3757 uint32 base_index_map, xpe_map=0, orig_xpe_map; 3758 3759 si = &SOC_INFO(unit); 3760 base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7; 3761 mem_index = 0; 3762 3763 if (xpe >= 0 && base_index >= 0) { 3764 SOC_IF_ERROR_RETURN 3765 (_soc_tomahawk_xpe_mem_check(unit, mem, xpe, base_index)); 3766 } 3767 3768 switch (base_type) { 3769 case 2: /* IPIPE */ 3770 case 3: /* EPIPE */ 3771 /* no _PIPEx */ 3772 if (SOC_MEM_UNIQUE_ACC(unit, mem) == NULL) { 3773 mem_list[mem_index++] = mem; 3774 break; 3775 } 3776 3777 soc_tomahawk_pipe_map_get(unit, &base_index_map); 3778 if (base_index != -1) { 3779 base_index_map &= (1 << base_index); 3780 if (base_index_map == 0) { 3781 return SOC_E_PARAM; 3782 } 3783 } 3784 3785 orig_xpe_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1]; 3786 if (xpe != -1) { 3787 orig_xpe_map &= (1 << xpe); 3788 if (orig_xpe_map == 0) { 3789 return SOC_E_PARAM; 3790 } 3791 } 3792 3793 for (base_index = 0; base_index < NUM_PIPE(unit); base_index++) { 3794 if (!(base_index_map & (1 << base_index))) { 3795 continue; 3796 } 3797 3798 /* no need to check each pipe, 0 is enough */ 3799 if (SOC_MEM_ACC_TYPE(unit, SOC_MEM_UNIQUE_ACC_PIPE(unit, mem, 0)) 3800 == _TH_SUBS_ACC_TYPE_DUPLICATE) { 3801 /* _PIPEx */ 3802 mem_list[mem_index++] = 3803 SOC_MEM_UNIQUE_ACC_PIPE(unit, mem, base_index); 3804 } else { 3805 /* _XPEy_PIPEx */ 3806 xpe_map = base_type == 2 ? 3807 si->ipipe_xpe_map[base_index] : 3808 si->epipe_xpe_map[base_index]; 3809 xpe_map &= orig_xpe_map; 3810 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 3811 if (!(xpe_map & (1 << xpe))) { 3812 continue; 3813 } 3814 mem_list[mem_index++] = 3815 SOC_MEM_UNIQUE_ACC_XPE_PIPE(unit, mem, xpe, base_index); 3816 } 3817 } 3818 } 3819 break; 3820 case 4: /* CHIP */ 3821 /* no _XPEx */ 3822 if (SOC_MEM_UNIQUE_ACC(unit, mem) == NULL) { 3823 mem_list[mem_index++] = mem; 3824 break; 3825 } 3826 3827 xpe_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1]; 3828 if (xpe != -1) { 3829 xpe_map &= (1 << xpe); 3830 if (xpe_map == 0) { 3831 return SOC_E_PARAM; 3832 } 3833 } 3834 3835 /* _XPEx */ 3836 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 3837 if (!(xpe_map & (1 << xpe))) { 3838 continue; 3839 } 3840 mem_list[mem_index++] = 3841 SOC_MEM_UNIQUE_ACC_XPE(unit, mem, xpe); 3842 } 3843 break; 3844 case 5: /* XPE */ 3845 /* no _XPEx */ 3846 if (SOC_MEM_UNIQUE_ACC(unit, mem) == NULL) { 3847 mem_list[mem_index++] = mem; 3848 break; 3849 } 3850 3851 xpe_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1]; 3852 if (xpe != -1) { 3853 xpe_map &= (1 << xpe); 3854 if (xpe_map == 0) { 3855 return SOC_E_PARAM; 3856 } 3857 } 3858 3859 /* _XPEx */ 3860 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 3861 if (!(xpe_map & (1 << xpe))) { 3862 continue; 3863 } 3864 mem_list[mem_index++] = 3865 SOC_MEM_UNIQUE_ACC_XPE(unit, mem, xpe); 3866 } 3867 break; 3868 case 6: /* SLICE */ 3869 /* no _SCx */ 3870 if (SOC_MEM_UNIQUE_ACC(unit, mem) == NULL) { 3871 mem_list[mem_index++] = mem; 3872 break; 3873 } 3874 3875 base_index_map = si->ipipe_sc_map[0]; 3876 if (base_index != -1) { 3877 base_index_map &= (1 << base_index); 3878 if (base_index_map == 0) { 3879 return SOC_E_PARAM; 3880 } 3881 } 3882 3883 for (base_index = 0; base_index < NUM_SLICE(unit); base_index++) { 3884 if (!(base_index_map & (1 << base_index))) { 3885 continue; 3886 } 3887 3888 /* no need to check each sc, 0 is enough */ 3889 if (SOC_MEM_ACC_TYPE(unit, SOC_MEM_UNIQUE_ACC_SC(unit, mem, 0)) 3890 == _TH_SUBS_ACC_TYPE_DUPLICATE) { 3891 /* _PIPEx */ 3892 mem_list[mem_index++] = 3893 SOC_MEM_UNIQUE_ACC_SC(unit, mem, base_index); 3894 } else { 3895 /* No unique access type for such base_type till now */ 3896 } 3897 } 3898 break; 3899 case 0: /* IPORT */ 3900 case 1: /* EPORT */ 3901 case 7: /* LAYER */ 3902 default: 3903 return SOC_E_INTERNAL; 3904 } 3905 3906 mem_cnt = write ? mem_index : 1; 3907 index = offset_in_section; 3908 for (mem_index = 0; mem_index < mem_cnt; mem_index ++) { 3909 if (write) { 3910 SOC_IF_ERROR_RETURN(soc_mem_write 3911 (unit, mem_list[mem_index], copyno, index, entry_data)); 3912 } else { 3913 SOC_IF_ERROR_RETURN(soc_mem_read 3914 (unit, mem_list[mem_index], copyno, index, entry_data)); 3915 } 3916 } 3917 3918 return SOC_E_NONE; 3919 } 3920 3921 int 3922 soc_tomahawk_sc_base_index_check(int unit, int base_type, int sc, 3923 int base_index, char *msg) 3924 { 3925 soc_info_t *si; 3926 int pipe; 3927 uint32 map; 3928 char *base_name; 3929 3930 si = &SOC_INFO(unit); 3931 3932 if (sc == -1 || base_index == -1) { 3933 return SOC_E_NONE; 3934 } 3935 3936 if (sc < NUM_SLICE(unit) && si->sc_ipipe_map[sc] == 0) { 3937 if (msg) { 3938 LOG_CLI((BSL_META_U(unit, 3939 "%s: SC%d is not in config\n"), 3940 msg, sc)); 3941 } 3942 return SOC_E_PARAM; 3943 } 3944 3945 switch (base_type) { 3946 case 0: /* IPORT */ 3947 case 1: /* EPORT */ 3948 base_name = base_type == 0 ? "IPORT" : "EPORT"; 3949 pipe = si->port_pipe[base_index]; 3950 if (pipe == -1) { 3951 if (msg) { 3952 LOG_CLI((BSL_META_U(unit, 3953 "%s: %s%d is not in config\n"), 3954 msg, base_name, base_index)); 3955 } 3956 } else if (sc < NUM_SLICE(unit)) { /* Unique access type */ 3957 map = base_type == 0 ? 3958 si->ipipe_sc_map[pipe] : si->epipe_sc_map[pipe]; 3959 if (map & (1 << sc)) { 3960 break; 3961 } 3962 if (msg != NULL) { 3963 LOG_CLI((BSL_META_U(unit, 3964 "%s: %s%d is not in SC%d\n"), 3965 msg, base_name, base_index, sc)); 3966 } 3967 } else { 3968 break; 3969 } 3970 return SOC_E_PARAM; 3971 case 2: /* IPIPE */ 3972 case 3: /* EPIPE */ 3973 if (base_type == 2) { 3974 base_name = "IPIPE"; 3975 map = si->ipipe_sc_map[base_index]; 3976 } else { 3977 base_name = "EPIPE"; 3978 map = si->epipe_sc_map[base_index]; 3979 } 3980 if (map == 0) { 3981 if (msg) { 3982 LOG_CLI((BSL_META_U(unit, 3983 "%s: %s%d is not in config\n"), 3984 msg, base_name, base_index)); 3985 } 3986 } else if (sc < NUM_SLICE(unit)) { /* Unique access type */ 3987 if (map & (1 << sc)) { 3988 break; 3989 } 3990 if (msg != NULL) { 3991 LOG_CLI((BSL_META_U(unit, 3992 "%s: %s%d is not in SC%d\n"), 3993 msg, base_name, base_index, sc)); 3994 } 3995 } else { 3996 break; 3997 } 3998 return SOC_E_PARAM; 3999 case 4: /* CHIP */ 4000 break; 4001 case 5: /* XPE */ 4002 if (si->xpe_ipipe_map[base_index] == 0) { 4003 if (msg != NULL) { 4004 LOG_CLI((BSL_META_U(unit, 4005 "%s: XPE%d is not in config\n"), 4006 msg, base_index)); 4007 } 4008 } else if (sc < NUM_SLICE(unit)) { /* Unique access type */ 4009 if (sc == 0) { /* XPE 0 and 2 are in slice 0 */ 4010 if (base_index == 0 || base_index == 2) { 4011 break; 4012 } 4013 } else { /* XPE 1 and 3 are in slice 1 */ 4014 if (base_index == 1 || base_index == 3) { 4015 break; 4016 } 4017 } 4018 if (msg != NULL) { 4019 LOG_CLI((BSL_META_U(unit, 4020 "%s: XPE%d is not in SLICE%d\n"), 4021 msg, base_index, sc)); 4022 } 4023 } else { 4024 break; 4025 } 4026 return SOC_E_PARAM; 4027 case 6: /* SLICE */ 4028 case 7: /* LAYER, not used */ 4029 break; 4030 } 4031 4032 return SOC_E_NONE; 4033 } 4034 4035 STATIC int 4036 _soc_tomahawk_sc_reg_check(int unit, soc_reg_t reg, int sc, int base_index) 4037 { 4038 int acc_type, base_type; 4039 4040 if (!SOC_BLOCK_IN_LIST(SOC_REG_INFO(unit, reg).block, SOC_BLK_MMU_SC)) { 4041 LOG_CLI((BSL_META_U(unit, 4042 "%s is not SC register\n"), SOC_REG_NAME(unit, reg))); 4043 return SOC_E_PARAM; 4044 } 4045 4046 if (SOC_REG_UNIQUE_ACC(unit, reg) != NULL) { /* UNIQUE base register */ 4047 if (sc == -1 || sc >= NUM_SLICE(unit)) { 4048 LOG_CLI((BSL_META_U(unit, 4049 "%s bad SC value %d\n"), 4050 SOC_REG_NAME(unit, reg), sc)); 4051 return SOC_E_PARAM; 4052 } 4053 } else { 4054 acc_type = SOC_REG_ACC_TYPE(unit, reg); 4055 if (acc_type < NUM_SLICE(unit)) { /* UNIQUE per SC register */ 4056 if (sc != acc_type) { 4057 LOG_CLI((BSL_META_U(unit, 4058 "Ovveride SC value %d with ACC_TYPE of %s\n"), 4059 sc, SOC_REG_NAME(unit, reg))); 4060 } 4061 sc = acc_type; 4062 } else { /* non-UNIQUE register */ 4063 return SOC_E_NONE; 4064 } 4065 } 4066 base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7; 4067 4068 return soc_tomahawk_sc_base_index_check(unit, base_type, sc, base_index, 4069 SOC_REG_NAME(unit, reg)); 4070 } 4071 4072 #if 0 4073 STATIC int 4074 _soc_tomahawk_sc_mem_check(int unit, soc_mem_t mem, int sc, int base_index) 4075 { 4076 int block_info_index, acc_type, base_type; 4077 4078 block_info_index = SOC_MEM_BLOCK_ANY(unit, mem); 4079 if (SOC_BLOCK_TYPE(unit, block_info_index) != SOC_BLK_MMU_SC) { 4080 LOG_CLI((BSL_META_U(unit, 4081 "%s is not SC register\n"), SOC_MEM_NAME(unit, mem))); 4082 return SOC_E_PARAM; 4083 } 4084 4085 if (SOC_MEM_UNIQUE_ACC(unit, mem) != NULL) { /* UNIQUE base memory */ 4086 if (sc == -1 || sc >= NUM_SLICE(unit)) { 4087 LOG_CLI((BSL_META_U(unit, 4088 "%s bad SC value %d\n"), 4089 SOC_MEM_NAME(unit, mem), sc)); 4090 return SOC_E_PARAM; 4091 } 4092 } else { 4093 acc_type = SOC_MEM_ACC_TYPE(unit, mem); 4094 if (acc_type < NUM_SLICE(unit)) { /* UNIQUE per SC memory */ 4095 if (sc != acc_type) { 4096 LOG_CLI((BSL_META_U(unit, 4097 "Ovveride SC value %d with ACC_TYPE of %s\n"), 4098 sc, SOC_MEM_NAME(unit, mem))); 4099 sc = acc_type; 4100 } 4101 } else { /* non-UNIQUE memory */ 4102 return SOC_E_NONE; 4103 } 4104 } 4105 base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7; 4106 4107 return soc_tomahawk_sc_base_index_check(unit, base_type, sc, base_index, 4108 SOC_MEM_NAME(unit, mem)); 4109 } 4110 #endif 4111 4112 STATIC int 4113 _soc_tomahawk_sc_reg_access(int unit, soc_reg_t reg, int sc, int base_index, 4114 int index, uint64 *data, int write) 4115 { 4116 soc_info_t *si; 4117 int port; 4118 int base_type; 4119 uint32 base_index_map; 4120 soc_pbmp_t base_index_pbmp; 4121 uint32 inst; 4122 4123 si = &SOC_INFO(unit); 4124 base_type = ((SOC_REG_INFO(unit, reg).offset) >> 23) & 0x7; 4125 4126 if (sc >= 0 && base_index >= 0) { 4127 SOC_IF_ERROR_RETURN 4128 (_soc_tomahawk_sc_reg_check(unit, reg, sc, base_index)); 4129 } 4130 4131 switch (base_type) { 4132 case 0: /* IPORT */ 4133 case 1: /* EPORT */ 4134 /* No unique access type for such base_type */ 4135 if (base_index == -1) { 4136 SOC_PBMP_ASSIGN(base_index_pbmp, PBMP_ALL(unit)); 4137 } else { 4138 /* This argument is logical port, same as soc_reg_get/set */ 4139 SOC_PBMP_PORT_SET(base_index_pbmp, base_index); 4140 } 4141 4142 SOC_PBMP_ITER(base_index_pbmp, port) { 4143 if (write) { 4144 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, index, *data)); 4145 } else { 4146 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, index, data)); 4147 } 4148 } 4149 break; 4150 case 2: /* IPIPE */ 4151 case 3: /* EPIPE */ 4152 /* No unique access type for such base_type */ 4153 soc_tomahawk_pipe_map_get(unit, &base_index_map); 4154 if (base_index != -1) { 4155 base_index_map &= 1 << base_index; 4156 if (base_index_map == 0) { 4157 return SOC_E_PARAM; 4158 } 4159 } 4160 4161 for (base_index = 0; base_index < NUM_PIPE(unit); base_index++) { 4162 if (!(base_index_map & (1 << base_index))) { 4163 continue; 4164 } 4165 inst = base_index | SOC_REG_ADDR_INSTANCE_MASK; 4166 if (write) { 4167 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, inst, index, *data)); 4168 } else { 4169 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, inst, index, data)); 4170 } 4171 } 4172 break; 4173 case 4: /* CHIP */ 4174 if (write) { 4175 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, 0, index, *data)); 4176 } else { 4177 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, 0, index, data)); 4178 } 4179 break; 4180 case 5: /* XPE */ 4181 /* No unique access type for such base_type */ 4182 if (base_index == -1) { 4183 base_index_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1]; 4184 } else { 4185 base_index_map = 1 << base_index; 4186 } 4187 4188 for (base_index = 0; base_index < NUM_XPE(unit); base_index++) { 4189 if (!(base_index_map & (1 << base_index))) { 4190 continue; 4191 } 4192 inst = base_index | SOC_REG_ADDR_INSTANCE_MASK; 4193 if (write) { 4194 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, inst, index, *data)); 4195 } else { 4196 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, inst, index, data)); 4197 } 4198 } 4199 break; 4200 case 6: /* SLICE */ 4201 /* No unique access type for such base_type */ 4202 if (base_index == -1) { 4203 base_index_map = si->ipipe_sc_map[0];; 4204 } else { 4205 base_index_map = 1 << base_index; 4206 } 4207 for (base_index = 0; base_index < NUM_SLICE(unit); base_index++) { 4208 if (!(base_index_map & (1 << base_index))) { 4209 continue; 4210 } 4211 inst = base_index | SOC_REG_ADDR_INSTANCE_MASK; 4212 if (write) { 4213 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, inst, index, *data)); 4214 } else { 4215 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, inst, index, data)); 4216 } 4217 } 4218 break; 4219 case 7: /* LAYER */ 4220 default: 4221 return SOC_E_INTERNAL; 4222 } 4223 4224 return SOC_E_NONE; 4225 } 4226 #if 0 4227 STATIC int 4228 _soc_tomahawk_sc_mem_access(int unit, soc_mem_t mem, int sc, int base_index, 4229 int copyno, int offset_in_section, void *entry_data, 4230 int write) 4231 { 4232 soc_info_t *si; 4233 soc_mem_t orig_mem; 4234 int index, section_size; 4235 int base_type, break_after_first; 4236 uint32 base_index_map, sc_map=0; 4237 4238 si = &SOC_INFO(unit); 4239 orig_mem = mem; 4240 base_type = ((SOC_MEM_INFO(unit, mem).base) >> 23) & 0x7; 4241 section_size = SOC_MEM_INFO(unit, mem).section_size; 4242 break_after_first = TRUE; 4243 4244 if (sc >= 0 && base_index >= 0) { 4245 SOC_IF_ERROR_RETURN 4246 (_soc_tomahawk_sc_mem_check(unit, mem, sc, base_index)); 4247 } 4248 4249 switch (base_type) { 4250 case 2: /* IPIPE */ 4251 case 3: /* EPIPE */ 4252 if (sc >= 0 && SOC_MEM_UNIQUE_ACC(unit, mem) != NULL) { 4253 mem = SOC_MEM_UNIQUE_ACC(unit, mem)[sc]; 4254 } 4255 4256 /* All tables with such base_type should have multiple sections */ 4257 soc_tomahawk_pipe_map_get(unit, &base_index_map); 4258 if (base_index != -1) { 4259 base_index_map &= 1 << base_index; 4260 if (base_index_map == 0) { 4261 return SOC_E_PARAM; 4262 } 4263 } 4264 4265 for (base_index = 0; base_index < NUM_PIPE(unit); base_index++) { 4266 if (!(base_index_map & (1 << base_index))) { 4267 continue; 4268 } 4269 /* Loop through SC(s) only on UNIQUE type base memory */ 4270 if (SOC_MEM_UNIQUE_ACC(unit, orig_mem) != NULL) { 4271 sc_map = base_type == 2 ? 4272 si->ipipe_sc_map[base_index] : 4273 si->epipe_sc_map[base_index]; 4274 if (write) { 4275 break_after_first = FALSE; 4276 } 4277 } 4278 for (sc = 0; sc < NUM_SLICE(unit); sc++) { 4279 if (SOC_MEM_UNIQUE_ACC(unit, orig_mem) != NULL) { 4280 if (!(sc_map & (1 << sc))) { 4281 continue; 4282 } 4283 mem = SOC_MEM_UNIQUE_ACC(unit, orig_mem)[sc]; 4284 } 4285 index = base_index * section_size + offset_in_section; 4286 if (write) { 4287 SOC_IF_ERROR_RETURN 4288 (soc_mem_write(unit, mem, copyno, index, entry_data)); 4289 } else { 4290 SOC_IF_ERROR_RETURN 4291 (soc_mem_read(unit, mem, copyno, index, entry_data)); 4292 } 4293 if (break_after_first) { 4294 break; 4295 } 4296 } 4297 } 4298 break; 4299 case 5: /* XPE */ 4300 /* No unique access type for such base_type */ 4301 if (base_index == -1) { 4302 base_index_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1]; 4303 } else { 4304 base_index_map = 1 << base_index; 4305 } 4306 4307 for (base_index = 0; base_index < NUM_SLICE(unit); base_index++) { 4308 if (!(base_index_map & (1 << base_index))) { 4309 continue; 4310 } 4311 index = base_index * section_size + offset_in_section; 4312 if (write) { 4313 SOC_IF_ERROR_RETURN 4314 (soc_mem_write(unit, mem, copyno, index, entry_data)); 4315 } else { 4316 SOC_IF_ERROR_RETURN 4317 (soc_mem_read(unit, mem, copyno, index, entry_data)); 4318 } 4319 } 4320 break; 4321 case 6: /* SLICE */ 4322 /* No unique access type for such base_type */ 4323 if (base_index == -1) { 4324 base_index_map = si->ipipe_sc_map[0]; 4325 } else { 4326 base_index_map = 1 << base_index; 4327 } 4328 for (base_index = 0; base_index < NUM_SLICE(unit); base_index++) { 4329 if (!(base_index_map & (1 << base_index))) { 4330 continue; 4331 } 4332 index = base_index * section_size + offset_in_section; 4333 if (write) { 4334 SOC_IF_ERROR_RETURN 4335 (soc_mem_write(unit, mem, copyno, index, entry_data)); 4336 } else { 4337 SOC_IF_ERROR_RETURN 4338 (soc_mem_read(unit, mem, copyno, index, entry_data)); 4339 } 4340 } 4341 break; 4342 case 0: /* IPORT */ 4343 case 1: /* EPORT */ 4344 case 4: /* CHIP */ 4345 case 7: /* LAYER */ 4346 default: 4347 return SOC_E_INTERNAL; 4348 } 4349 4350 return SOC_E_NONE; 4351 } 4352 #endif 4353 4354 /*About layer concept, you can refer to 1.3.3 chapter in MMUuA_overview.pdf*/ 4355 int 4356 soc_tomahawk_mmu_layer_get(int unit, int pipe, int *layer) 4357 { 4358 if( layer == NULL ) { 4359 return SOC_E_PARAM; 4360 } 4361 if ( pipe >= 0 && pipe < NUM_PIPE(unit)) { 4362 if ( pipe == 0 || pipe == 3 ) { /* pipe 0 and 3 are in layer 0 */ 4363 *layer = 0; 4364 } else { /* pipe 1 and 2 are in layer 1 */ 4365 *layer = 1; 4366 } 4367 return SOC_E_NONE; 4368 } 4369 return SOC_E_PARAM; 4370 } 4371 4372 int 4373 soc_tomahawk_xpe_reg32_set(int unit, soc_reg_t reg, int xpe, int base_index, 4374 int index, uint32 data) 4375 { 4376 uint64 data64; 4377 4378 COMPILER_64_SET(data64, 0, data); 4379 SOC_IF_ERROR_RETURN(_soc_tomahawk_xpe_reg_access(unit, reg, xpe, base_index, 4380 index, &data64, TRUE)); 4381 4382 return SOC_E_NONE; 4383 } 4384 4385 int 4386 soc_tomahawk_xpe_reg32_get(int unit, soc_reg_t reg, int xpe, int base_index, 4387 int index, uint32 *data) 4388 { 4389 uint64 data64; 4390 4391 COMPILER_64_SET(data64, 0, *data); 4392 SOC_IF_ERROR_RETURN(_soc_tomahawk_xpe_reg_access(unit, reg, xpe, base_index, 4393 index, &data64, FALSE)); 4394 *data = COMPILER_64_LO(data64); 4395 4396 return SOC_E_NONE; 4397 } 4398 4399 int 4400 soc_tomahawk_xpe_reg_set(int unit, soc_reg_t reg, int xpe, int base_index, 4401 int index, uint64 data) 4402 { 4403 return _soc_tomahawk_xpe_reg_access(unit, reg, xpe, base_index, 4404 index, &data, TRUE); 4405 } 4406 4407 int 4408 soc_tomahawk_xpe_reg_get(int unit, soc_reg_t reg, int xpe, int base_index, 4409 int index, uint64 *data) 4410 { 4411 return _soc_tomahawk_xpe_reg_access(unit, reg, xpe, base_index, 4412 index, data, FALSE); 4413 } 4414 4415 int 4416 soc_tomahawk_xpe_mem_write(int unit, soc_mem_t mem, int xpe, int base_index, 4417 int copyno, int offset_in_section, void *entry_data) 4418 { 4419 return _soc_tomahawk_xpe_mem_access(unit, mem, xpe, base_index, copyno, 4420 offset_in_section, entry_data, TRUE); 4421 } 4422 4423 int 4424 soc_tomahawk_xpe_mem_read(int unit, soc_mem_t mem, int xpe, int base_index, 4425 int copyno, int offset_in_section, void *entry_data) 4426 { 4427 return _soc_tomahawk_xpe_mem_access(unit, mem, xpe, base_index, copyno, 4428 offset_in_section, entry_data, FALSE); 4429 } 4430 4431 int 4432 soc_tomahawk_sc_reg32_set(int unit, soc_reg_t reg, int sc, int base_index, 4433 int index, uint32 data) 4434 { 4435 uint64 data64; 4436 4437 COMPILER_64_SET(data64, 0, data); 4438 SOC_IF_ERROR_RETURN(_soc_tomahawk_sc_reg_access(unit, reg, sc, base_index, 4439 index, &data64, TRUE)); 4440 4441 return SOC_E_NONE; 4442 } 4443 4444 int 4445 soc_tomahawk_sc_reg32_get(int unit, soc_reg_t reg, int sc, int base_index, 4446 int index, uint32 *data) 4447 { 4448 uint64 data64; 4449 4450 COMPILER_64_SET(data64, 0, *data); 4451 SOC_IF_ERROR_RETURN(_soc_tomahawk_sc_reg_access(unit, reg, sc, base_index, 4452 index, &data64, FALSE)); 4453 *data = COMPILER_64_LO(data64); 4454 4455 return SOC_E_NONE; 4456 } 4457 4458 int 4459 soc_tomahawk_sc_reg_set(int unit, soc_reg_t reg, int sc, int base_index, 4460 int index, uint64 data) 4461 { 4462 return _soc_tomahawk_sc_reg_access(unit, reg, sc, base_index, 4463 index, &data, TRUE); 4464 } 4465 4466 int 4467 soc_tomahawk_sc_reg_get(int unit, soc_reg_t reg, int sc, int base_index, 4468 int index, uint64 *data) 4469 { 4470 return _soc_tomahawk_sc_reg_access(unit, reg, sc, base_index, 4471 index, data, FALSE); 4472 } 4473 4474 int 4475 soc_tomahawk_port_traffic_egr_enable_set(int unit, soc_port_t port, 4476 int enable) 4477 { 4478 uint64 rval64; 4479 int mmu_port, phy_port, i; 4480 soc_info_t *si = &SOC_INFO(unit); 4481 soc_reg_t reg[3] = { 4482 THDU_OUTPUT_PORT_RX_ENABLE_64r, 4483 MMU_THDM_DB_PORT_RX_ENABLE_64r, 4484 MMU_THDM_MCQE_PORT_RX_ENABLE_64r 4485 }; 4486 int pipe; 4487 uint32 mmu_inst_map; 4488 int xpe; 4489 4490 phy_port = si->port_l2p_mapping[port]; 4491 mmu_port = si->port_p2m_mapping[phy_port]; 4492 mmu_port %= SOC_TH_MMU_PORT_STRIDE; 4493 SOC_IF_ERROR_RETURN(soc_port_pipe_get(unit, port, &pipe)); 4494 mmu_inst_map = si->epipe_xpe_map[pipe]; 4495 for (xpe = 0; xpe < NUM_XPE(unit); xpe++) { 4496 if (!(mmu_inst_map & (1 << xpe))) { 4497 continue; 4498 } 4499 4500 for (i = 0; i < 3; i++) { 4501 COMPILER_64_ZERO(rval64); 4502 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg_get(unit, reg[i], 4503 xpe, pipe, 0, &rval64)); 4504 if (enable) { 4505 COMPILER_64_BITSET(rval64, mmu_port); 4506 } else { 4507 COMPILER_64_BITCLR(rval64, mmu_port); 4508 } 4509 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg_set(unit, reg[i], 4510 xpe, pipe, 0, rval64)); 4511 } 4512 } 4513 4514 return SOC_E_NONE; 4515 } 4516 4517 #if 0 4518 int 4519 soc_tomahawk_sc_mem_write(int unit, soc_mem_t mem, int sc, int base_index, 4520 int copyno, int offset_in_section, void *entry_data) 4521 { 4522 return _soc_tomahawk_sc_mem_access(unit, mem, sc, base_index, copyno, 4523 offset_in_section, entry_data, TRUE); 4524 } 4525 4526 int 4527 soc_tomahawk_sc_mem_read(int unit, soc_mem_t mem, int sc, int base_index, 4528 int copyno, int offset_in_section, void *entry_data) 4529 { 4530 return _soc_tomahawk_sc_mem_access(unit, mem, sc, base_index, copyno, 4531 offset_in_section, entry_data, FALSE); 4532 } 4533 #endif 4534 4535 int 4536 soc_tomahawk_clear_mmu_memory(int unit) 4537 { 4538 #define SOC_MMU_BASE_TYPE_IPORT 0 4539 #define SOC_MMU_BASE_TYPE_EPORT 1 4540 #define SOC_MMU_BASE_TYPE_IPIPE 2 4541 #define SOC_MMU_BASE_TYPE_EPIPE 3 4542 #define SOC_MMU_BASE_TYPE_CHIP 4 4543 #define SOC_MMU_BASE_TYPE_XPE 5 4544 #define SOC_MMU_BASE_TYPE_SC 6 4545 #define SOC_MMU_BASE_TYPE_LAYER 7 4546 int i, j, use_base_type_views, base_type, index, num_views; 4547 uint32 entry[SOC_MAX_MEM_WORDS]; 4548 soc_mem_t mem; 4549 static struct { 4550 soc_mem_t mem; /* base view */ 4551 int use_base_type_views; /* 1 means use xpe/sc/etc views */ 4552 int index; /* -1 means clear entire mem */ 4553 } mem_list[] = { 4554 { MMU_CBPDATA0m, 1, 0 }, 4555 { MMU_CBPDATA15m, 1, 0 }, 4556 { MMU_CBPDATA30m, 1, 0 }, 4557 { MMU_CBPDATA45m, 1, 0 }, 4558 { INVALIDm, 0, -1 } 4559 }; 4560 4561 #ifdef BCM_TOMAHAWKPLUS_SUPPORT 4562 /* adjust CBPDATA for resetting on TH+ */ 4563 if (SOC_IS_TOMAHAWKPLUS(unit)) { 4564 mem_list[0].mem = MMU_CBPDATA0m; 4565 mem_list[1].mem = MMU_CBPDATA19m; 4566 mem_list[2].mem = MMU_CBPDATA38m; 4567 mem_list[3].mem = MMU_CBPDATA57m; 4568 } 4569 #endif 4570 4571 for (i = 0; mem_list[i].mem != INVALIDm; i++) { 4572 mem = mem_list[i].mem; 4573 index = mem_list[i].index; 4574 use_base_type_views = mem_list[i].use_base_type_views; 4575 if (use_base_type_views) { 4576 base_type = soc_tomahawk_mem_basetype_get(unit, mem); 4577 switch (base_type) { 4578 case SOC_MMU_BASE_TYPE_XPE: 4579 num_views = NUM_XPE(unit); 4580 break; 4581 case SOC_MMU_BASE_TYPE_SC: 4582 num_views = NUM_SLICE(unit); 4583 break; 4584 case SOC_MMU_BASE_TYPE_LAYER: 4585 num_views = NUM_LAYER(unit); 4586 break; 4587 case SOC_MMU_BASE_TYPE_IPIPE: 4588 case SOC_MMU_BASE_TYPE_EPIPE: 4589 num_views = NUM_PIPE(unit); 4590 break; 4591 default: 4592 num_views = -1; /* not supported */ 4593 break; 4594 } 4595 if (num_views < 0) { 4596 LOG_ERROR(BSL_LS_SOC_COMMON, 4597 (BSL_META_U(unit, 4598 "mmu_mem %s, base_type %d will not be" 4599 "cleared \n"), 4600 SOC_MEM_NAME(unit,mem), base_type)); 4601 continue; 4602 } 4603 } else { 4604 num_views = 0; /* dont_care */ 4605 } 4606 4607 sal_memset(entry, 0x0, 4608 soc_mem_entry_words(unit, mem) * sizeof(uint32)); 4609 if (use_base_type_views) { 4610 for (j = 0; j < num_views; j++) { 4611 LOG_VERBOSE(BSL_LS_SOC_COMMON, 4612 (BSL_META_U(unit, 4613 "mmu_mem %s, index %d will be " 4614 "cleared \n"), 4615 SOC_MEM_NAME(unit, SOC_MEM_UNIQUE_ACC(unit, mem)[j]), 4616 index)); 4617 if (index >= 0) { 4618 SOC_IF_ERROR_RETURN 4619 (soc_mem_write(unit, 4620 SOC_MEM_UNIQUE_ACC(unit, mem)[j], 4621 MEM_BLOCK_ALL, index, entry)); 4622 } else { 4623 SOC_IF_ERROR_RETURN 4624 (soc_mem_clear(unit, 4625 SOC_MEM_UNIQUE_ACC(unit, mem)[j], 4626 COPYNO_ALL, TRUE)); 4627 } 4628 } 4629 } else { 4630 LOG_VERBOSE(BSL_LS_SOC_COMMON, 4631 (BSL_META_U(unit, 4632 "mmu_mem %s, index %d will be " 4633 "cleared \n"), 4634 SOC_MEM_NAME(unit, mem), index)); 4635 if (index >= 0) { 4636 SOC_IF_ERROR_RETURN 4637 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, index, 4638 entry)); 4639 } else { 4640 SOC_IF_ERROR_RETURN 4641 (soc_mem_clear(unit, mem, COPYNO_ALL, TRUE)); 4642 } 4643 } 4644 } 4645 return SOC_E_NONE; 4646 } 4647 4648 /* Function to Clear all Memories. 4649 * Param 4650 * mmu_init - bool val to indicate whether to initialize mmu or not. 4651 */ 4652 STATIC int 4653 _soc_tomahawk_clear_all_memory(int unit, int mmu_init) 4654 { 4655 uint32 pipe_map; 4656 soc_reg_t reg; 4657 int pipe, count; 4658 uint32 rval, in_progress; 4659 int pipe_init_usec; 4660 soc_timeout_t to; 4661 4662 soc_tomahawk_pipe_map_get(unit, &pipe_map); 4663 4664 /* Initial IPIPE memory */ 4665 rval = 0; 4666 SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_1r(unit, rval)); 4667 soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, RESET_ALLf, 1); 4668 soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, VALIDf, 1); 4669 /* Set count to # entries of largest IPIPE table */ 4670 count = soc_mem_index_count(unit, ING_L3_NEXT_HOPm); 4671 if (count < soc_mem_index_count(unit, L2Xm)) { 4672 count = soc_mem_index_count(unit, L2Xm); 4673 } 4674 if (count < soc_mem_index_count(unit, L3_ENTRY_ONLYm)) { 4675 count = soc_mem_index_count(unit, L3_ENTRY_ONLYm); 4676 } 4677 if (count < soc_mem_index_count(unit, FPEM_ECCm)) { 4678 count = soc_mem_index_count(unit, FPEM_ECCm); 4679 } 4680 if (count < soc_mem_index_count(unit, L3_DEFIP_ALPM_IPV4m)) { 4681 count = soc_mem_index_count(unit, L3_DEFIP_ALPM_IPV4m); 4682 } 4683 soc_reg_field_set(unit, ING_HW_RESET_CONTROL_2r, &rval, COUNTf, count); 4684 SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval)); 4685 4686 /* Initial L2_MGT memories */ 4687 rval = 0; 4688 SOC_IF_ERROR_RETURN(WRITE_L2_MGMT_HW_RESET_CONTROL_0r(unit, rval)); 4689 soc_reg_field_set(unit, L2_MGMT_HW_RESET_CONTROL_1r, &rval, RESET_ALLf, 1); 4690 soc_reg_field_set(unit, L2_MGMT_HW_RESET_CONTROL_1r, &rval, VALIDf, 1); 4691 count = soc_mem_index_count(unit, L2_MOD_FIFOm); 4692 if (count < soc_mem_index_count(unit, L2_MGMT_SER_FIFOm)) { 4693 count = soc_mem_index_count(unit, L2_MGMT_SER_FIFOm); 4694 } 4695 soc_reg_field_set(unit, L2_MGMT_HW_RESET_CONTROL_1r, &rval, COUNTf, count); 4696 SOC_IF_ERROR_RETURN(WRITE_L2_MGMT_HW_RESET_CONTROL_1r(unit, rval)); 4697 4698 /* Initial EPIPE memory */ 4699 rval = 0; 4700 SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_0r(unit, rval)); 4701 soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, RESET_ALLf, 1); 4702 soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, VALIDf, 1); 4703 /* Set count to # entries in largest EPIPE table (EGR_L3_NEXT_HOP) */ 4704 count = SOC_MEM_INFO(unit, EGR_L3_NEXT_HOPm).index_max + 1; 4705 soc_reg_field_set(unit, EGR_HW_RESET_CONTROL_1r, &rval, COUNTf, count); 4706 SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1r(unit, rval)); 4707 4708 /* For simulation, set timeout to 10 sec. Otherwise, timeout = 50 ms */ 4709 if (SAL_BOOT_SIMULATION) { 4710 pipe_init_usec = 10000000; 4711 } else { 4712 pipe_init_usec = 50000; 4713 } 4714 soc_timeout_init(&to, pipe_init_usec, 0); 4715 4716 /* Wait for IPIPE memory initialization done */ 4717 in_progress = pipe_map; 4718 do { 4719 sal_usleep(1000); 4720 for (pipe = 0; pipe < _TH_PIPES_PER_DEV && in_progress; pipe++) { 4721 if (in_progress & (1 << pipe)) { /* not done yet */ 4722 reg = SOC_REG_UNIQUE_ACC(unit, ING_HW_RESET_CONTROL_2r)[pipe]; 4723 SOC_IF_ERROR_RETURN 4724 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 4725 if (soc_reg_field_get(unit, reg, rval, DONEf)) { 4726 in_progress ^= 1 << pipe; 4727 } 4728 } 4729 } 4730 if (soc_timeout_check(&to)) { 4731 LOG_WARN(BSL_LS_SOC_COMMON, 4732 (BSL_META_U(unit, 4733 "unit %d : ING_HW_RESET timeout\n"), unit)); 4734 break; 4735 } 4736 } while (in_progress != 0); 4737 4738 /* Wait for EPIPE memory initialization done */ 4739 in_progress = pipe_map; 4740 do { 4741 for (pipe = 0; pipe < _TH_PIPES_PER_DEV && in_progress; pipe++) { 4742 if (in_progress & (1 << pipe)) { /* not done yet */ 4743 reg = SOC_REG_UNIQUE_ACC(unit, EGR_HW_RESET_CONTROL_1r)[pipe]; 4744 SOC_IF_ERROR_RETURN 4745 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 4746 if (soc_reg_field_get(unit, reg, rval, DONEf)) { 4747 in_progress ^= 1 << pipe; 4748 } 4749 } 4750 } 4751 if (in_progress != 0) { 4752 sal_usleep(1000); 4753 } 4754 if (soc_timeout_check(&to)) { 4755 LOG_WARN(BSL_LS_SOC_COMMON, 4756 (BSL_META_U(unit, 4757 "unit %d : EGR_HW_RESET timeout\n"), unit)); 4758 break; 4759 } 4760 } while (in_progress != 0); 4761 4762 /* Make sure L2_MGMT memories are all clean */ 4763 reg = L2_MGMT_HW_RESET_CONTROL_1r; 4764 SOC_IF_ERROR_RETURN 4765 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 4766 if (!soc_reg_field_get(unit, reg, rval, DONEf)) { 4767 LOG_WARN(BSL_LS_SOC_COMMON, (BSL_META_U(unit, 4768 "unit %d : L2_MGMT_HW_RESET not done (reg val: 0x%x) !! \n"), 4769 unit, rval)); 4770 } else { 4771 SOC_IF_ERROR_RETURN(WRITE_L2_MGMT_HW_RESET_CONTROL_1r(unit, 0)); 4772 } 4773 4774 rval = 0; 4775 SOC_IF_ERROR_RETURN(WRITE_ING_HW_RESET_CONTROL_2r(unit, rval)); 4776 rval = SOC_REG_INFO(unit, EGR_HW_RESET_CONTROL_1r).rst_val_lo; 4777 SOC_IF_ERROR_RETURN(WRITE_EGR_HW_RESET_CONTROL_1r(unit, rval)); 4778 4779 /* Initialize IDB memory */ 4780 SOC_IF_ERROR_RETURN(WRITE_IDB_HW_CONTROLr(unit, 0)); 4781 rval = 0; 4782 soc_reg_field_set(unit, IDB_HW_CONTROLr, &rval, IS_MEM_INITf, 1); 4783 SOC_IF_ERROR_RETURN(WRITE_IDB_HW_CONTROLr(unit, rval)); 4784 SOC_IF_ERROR_RETURN(WRITE_IDB_HW_CONTROLr(unit, 0)); 4785 4786 if (mmu_init) { 4787 /* Initialize MMU memory */ 4788 SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_MISCCONFIGr(unit, 0)); 4789 rval = 0; 4790 soc_reg_field_set(unit, MMU_GCFG_MISCCONFIGr, &rval, INIT_MEMf, 1); 4791 SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_MISCCONFIGr(unit, rval)); 4792 SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_MISCCONFIGr(unit, 0)); 4793 } 4794 4795 return SOC_E_NONE; 4796 } 4797 4798 STATIC int 4799 _soc_tomahawk_port_mapping_init(int unit) 4800 { 4801 soc_info_t *si; 4802 int port, phy_port, idb_port; 4803 int num_port, num_phy_port; 4804 soc_reg_t reg; 4805 soc_mem_t mem; 4806 uint32 rval; 4807 uint32 entry[SOC_MAX_MEM_WORDS]; 4808 int pipe; 4809 int i; 4810 uint16 dev_id = 0; 4811 uint8 rev_id = 0; 4812 4813 /* 4814 * 96 entries MMU_CHFC_SYSPORT_MAPPINGm.SYS_PORT 4815 * 256 entries SYS_PORTMAPm.DEVICE_PORT_NUMBER 4816 */ 4817 4818 si = &SOC_INFO(unit); 4819 soc_cm_get_id(unit, &dev_id, &rev_id); 4820 4821 num_port = soc_mem_index_count(unit, PORT_TABm) - 1; 4822 num_phy_port = 136; 4823 4824 /* Ingress physical to device port mapping */ 4825 sal_memset(&entry, 0, 4826 sizeof(ing_idb_to_device_port_number_mapping_table_entry_t)); 4827 for (phy_port = 0; phy_port < num_phy_port; phy_port++) { 4828 port = si->port_p2l_mapping[phy_port]; 4829 if (port != -1) { 4830 pipe = si->port_pipe[port]; 4831 idb_port = si->port_l2i_mapping[port]; 4832 } else if (phy_port >= 132) { /* loopback port */ 4833 pipe = phy_port - 132; 4834 idb_port = 33; 4835 } else if (phy_port == 129) { /* management port 0 (if not in use) */ 4836 pipe = 1; 4837 idb_port = 32; 4838 } else if (phy_port == 130) { /* undefined physical port */ 4839 pipe = 3; 4840 idb_port = 32; 4841 } else if (phy_port == 131) { /* management port 1 (if not in use) */ 4842 pipe = 2; 4843 idb_port = 32; 4844 } else { 4845 pipe = (phy_port - 1) / _TH_PORTS_PER_PIPE; 4846 idb_port = (phy_port -1 ) % _TH_PORTS_PER_PIPE; 4847 } 4848 mem = SOC_MEM_UNIQUE_ACC 4849 (unit, ING_IDB_TO_DEVICE_PORT_NUMBER_MAPPING_TABLEm)[pipe]; 4850 soc_mem_field32_set(unit, mem, &entry, DEVICE_PORT_NUMBERf, 4851 port == -1 ? 0xff : port); 4852 SOC_IF_ERROR_RETURN 4853 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, idb_port, &entry)); 4854 } 4855 4856 /* Ingress GPP port to device port mapping */ 4857 mem = SYS_PORTMAPm; 4858 sal_memset(&entry, 0, sizeof(sys_portmap_entry_t)); 4859 for (port = 0; port < num_port; port++) { 4860 soc_mem_field32_set(unit, mem, &entry, DEVICE_PORT_NUMBERf, port); 4861 SOC_IF_ERROR_RETURN 4862 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, port, &entry)); 4863 } 4864 4865 /* Ingress device port to GPP port mapping 4866 * PORT_TAB.SRC_SYS_PORT_ID is programmed in the general port config 4867 * init routine _bcm_fb_port_cfg_init() 4868 */ 4869 4870 /* Egress device port to physical port mapping */ 4871 rval = 0; 4872 reg = EGR_DEVICE_TO_PHYSICAL_PORT_NUMBER_MAPPINGr; 4873 PBMP_ALL_ITER(unit, port) { 4874 soc_reg_field_set(unit, reg, &rval, PHYSICAL_PORT_NUMBERf, 4875 si->port_l2p_mapping[port]); 4876 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval)); 4877 } 4878 4879 /* MMU port to device port mapping */ 4880 rval = 0; 4881 reg = MMU_PORT_TO_DEVICE_PORT_MAPPINGr; 4882 PBMP_ALL_ITER(unit, port) { 4883 soc_reg_field_set(unit, reg, &rval, DEVICE_PORTf, port); 4884 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval)); 4885 } 4886 4887 /* MMU port to physical port mapping */ 4888 rval = 0; 4889 reg = MMU_PORT_TO_PHY_PORT_MAPPINGr; 4890 PBMP_ALL_ITER(unit, port) { 4891 soc_reg_field_set(unit, reg, &rval, PHY_PORTf, 4892 si->port_l2p_mapping[port]); 4893 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval)); 4894 } 4895 4896 /* MMU port to system port mapping */ 4897 rval = 0; 4898 reg = MMU_PORT_TO_SYSTEM_PORT_MAPPINGr; 4899 PBMP_ALL_ITER(unit, port) { 4900 soc_reg_field_set(unit, reg, &rval, SYSTEM_PORTf, port); 4901 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval)); 4902 } 4903 4904 if ((BCM56963_DEVICE_ID == dev_id) || (BCM56967_DEVICE_ID == dev_id)) { 4905 const int phy_pbmp_lb_disable[] = { 4906 13,14,15,16,17,18,19,20,25,26,27,28,29,30,31,32,45,46,47,48, 4907 57,58,59,60,61,62,63,64,73,74,75,76,77,78,79,80,89,90,91,92, 4908 93,94,95,96,113,114,115,116,121,122,123,124,125,126,127,128}; 4909 for (i = 0; i < COUNTOF(phy_pbmp_lb_disable); i++) { 4910 phy_port = phy_pbmp_lb_disable[i]; 4911 port = si->port_p2l_mapping[phy_port]; 4912 if (port != -1) { 4913 SOC_PBMP_PORT_ADD(loopback_disable[unit],port); 4914 } 4915 } 4916 } 4917 return SOC_E_NONE; 4918 } 4919 4920 STATIC int 4921 _soc_tomahawk_tdm_idb_calendar_set(int unit, int calendar_id, int in_pipe) 4922 { 4923 soc_info_t *si; 4924 _soc_tomahawk_tdm_t *tdm; 4925 uint32 pipe_map; 4926 soc_mem_t mem; 4927 soc_reg_t reg; 4928 soc_field_t field; 4929 int pipe, slot, id, length; 4930 int port, phy_port, idb_port; 4931 uint32 rval = 0; 4932 uint32 entry[SOC_MAX_MEM_WORDS]; 4933 static const soc_mem_t calendar_mems[] = { 4934 IS_TDM_CALENDAR0m, IS_TDM_CALENDAR1m 4935 }; 4936 static const soc_field_t calendar_end_fields[] = { 4937 CAL0_ENDf, CAL1_ENDf 4938 }; 4939 4940 si = &SOC_INFO(unit); 4941 tdm = SOC_CONTROL(unit)->tdm_info; 4942 4943 soc_tomahawk_pipe_map_get(unit, &pipe_map); 4944 4945 for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) { 4946 if (!(pipe_map & (1 << pipe)) || 4947 ((UPDATE_ALL_PIPES != in_pipe) && (pipe != in_pipe))) { 4948 continue; 4949 } 4950 4951 for (length = _TDM_LENGTH; length > 0; length--) { 4952 if (tdm->idb_tdm[pipe][length - 1] != TH_NUM_EXT_PORTS) { 4953 break; 4954 } 4955 } 4956 4957 reg = SOC_REG_UNIQUE_ACC(unit, IS_TDM_CONFIGr)[pipe]; 4958 if (calendar_id == -1) { /* choose "the other one" */ 4959 SOC_IF_ERROR_RETURN 4960 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 4961 calendar_id = soc_reg_field_get(unit, reg, rval, CURR_CALf) ^ 1; 4962 } 4963 mem = SOC_MEM_UNIQUE_ACC(unit, calendar_mems[calendar_id])[pipe]; 4964 field = calendar_end_fields[calendar_id]; 4965 sal_memset(entry, 0, soc_mem_entry_words(unit, mem) * sizeof(uint32)); 4966 for (slot = 0; slot < length; slot += 2) { 4967 phy_port = tdm->idb_tdm[pipe][slot]; 4968 id = -1; 4969 if (phy_port == TH_OVSB_TOKEN) { 4970 idb_port = _SOC_TH_TDM_OVERSUB_TOKEN; 4971 } else if (phy_port == TH_IDL1_TOKEN) { 4972 idb_port = _SOC_TH_TDM_IDL1_TOKEN; 4973 } else if (phy_port == TH_IDL2_TOKEN) { 4974 idb_port = _SOC_TH_TDM_IDL2_TOKEN; 4975 } else if (phy_port == NULL_TOKEN) { 4976 idb_port = _SOC_TH_TDM_NULL_TOKEN; 4977 } else if (phy_port >= TH_NUM_EXT_PORTS) { 4978 idb_port = _SOC_TH_TDM_UNUSED_TOKEN; 4979 } else { 4980 /* TDM code always allocates slots for management ports. 4981 * If mgmgt ports are omitted from config, this mapping 4982 * is not set up. 4983 */ 4984 if ((phy_port == 129) || (phy_port == 131)){ 4985 idb_port = 32; 4986 id = 0xf; 4987 } 4988 else { 4989 port = si->port_p2l_mapping[phy_port]; 4990 idb_port = si->port_l2i_mapping[port]; 4991 id = si->port_serdes[port]; 4992 } 4993 } 4994 soc_mem_field32_set(unit, mem, entry, PORT_NUM_EVENf, idb_port); 4995 soc_mem_field32_set(unit, mem, entry, PHY_PORT_ID_EVENf, id & 0xf); 4996 phy_port = tdm->idb_tdm[pipe][slot + 1]; 4997 id = -1; 4998 if (phy_port == TH_OVSB_TOKEN) { 4999 idb_port = _SOC_TH_TDM_OVERSUB_TOKEN; 5000 } else if (phy_port == TH_IDL1_TOKEN) { 5001 idb_port = _SOC_TH_TDM_IDL1_TOKEN; 5002 } else if (phy_port == TH_IDL2_TOKEN) { 5003 idb_port = _SOC_TH_TDM_IDL2_TOKEN; 5004 } else if (phy_port == NULL_TOKEN) { 5005 idb_port = _SOC_TH_TDM_NULL_TOKEN; 5006 } else if (phy_port >= TH_NUM_EXT_PORTS) { 5007 idb_port = _SOC_TH_TDM_UNUSED_TOKEN; 5008 } else { 5009 /* TDM code always allocates slots for management ports. 5010 * If mgmgt ports are omitted from config, this mapping 5011 * is not set up. 5012 */ 5013 if ((phy_port == 129) || (phy_port == 131)){ 5014 idb_port = 32; 5015 id = 0xf; 5016 } 5017 else { 5018 port = si->port_p2l_mapping[phy_port]; 5019 idb_port = si->port_l2i_mapping[port]; 5020 id = si->port_serdes[port]; 5021 } 5022 } 5023 soc_mem_field32_set(unit, mem, entry, PORT_NUM_ODDf, idb_port); 5024 soc_mem_field32_set(unit, mem, entry, PHY_PORT_ID_ODDf, id & 0xf); 5025 SOC_IF_ERROR_RETURN 5026 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, slot / 2, entry)); 5027 if (tdm->idb_tdm[pipe][slot + 2] == TH_NUM_EXT_PORTS) { 5028 soc_reg_field_set(unit, reg, &rval, field, 5029 phy_port == TH_NUM_EXT_PORTS ? slot : slot + 1); 5030 break; 5031 } 5032 } 5033 soc_reg_field_set(unit, reg, &rval, CURR_CALf, calendar_id); 5034 soc_reg_field_set(unit, reg, &rval, ENABLEf, 1); 5035 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 5036 } 5037 5038 return SOC_E_NONE; 5039 } 5040 5041 STATIC int 5042 _soc_tomahawk_tdm_idb_oversub_group_set(int unit) 5043 { 5044 soc_info_t *si; 5045 _soc_tomahawk_tdm_t *tdm; 5046 uint32 pipe_map; 5047 int block_info_idx; 5048 soc_reg_t reg, reg1; 5049 int pipe, clport, group, lane, slot, id, mode, ovs_class; 5050 int port, phy_port, phy_port_base, idb_port; 5051 int speed_max; 5052 uint32 rval; 5053 static const soc_reg_t grp_tbl_regs[] = { 5054 IS_OVR_SUB_GRP0_TBLr, IS_OVR_SUB_GRP1_TBLr, 5055 IS_OVR_SUB_GRP2_TBLr, IS_OVR_SUB_GRP3_TBLr, 5056 IS_OVR_SUB_GRP4_TBLr, IS_OVR_SUB_GRP5_TBLr 5057 }; 5058 static const soc_reg_t pblk_calendar_regs[] ={ 5059 IS_PBLK0_CALENDARr, IS_PBLK1_CALENDARr, 5060 IS_PBLK2_CALENDARr, IS_PBLK3_CALENDARr, 5061 IS_PBLK4_CALENDARr, IS_PBLK5_CALENDARr, 5062 IS_PBLK6_CALENDARr, IS_PBLK7_CALENDARr 5063 }; 5064 static int pblk_slots[SOC_TH_PORT_RATIO_COUNT][7] = { 5065 { 0, -1, 0, 0, -1, 0, -1 }, /* SOC_TH_PORT_RATIO_SINGLE */ 5066 { 0, -1, 2, 0, -1, 2, -1 }, /* SOC_TH_PORT_RATIO_DUAL_1_1 */ 5067 { 0, 0, 2, 0, 0, 2, -1 }, /* SOC_TH_PORT_RATIO_DUAL_2_1 */ 5068 { 0, 2, 2, 0, 2, 2, -1 }, /* SOC_TH_PORT_RATIO_DUAL_1_2 */ 5069 { 0, -1, 2, 0, -1, 3, -1 }, /* SOC_TH_PORT_RATIO_TRI_023_2_1_1 */ 5070 { 0, 0, 2, 0, 0, 3, -1 }, /* SOC_TH_PORT_RATIO_TRI_023_4_1_1 */ 5071 { 0, -1, 2, 1, -1, 2, -1 }, /* SOC_TH_PORT_RATIO_TRI_012_1_1_2 */ 5072 { 0, 2, 2, 1, 2, 2, -1 }, /* SOC_TH_PORT_RATIO_TRI_012_1_1_4 */ 5073 { 0, -1, 2, 1, -1, 3, -1 } /* SOC_TH_PORT_RATIO_QUAD */ 5074 }; 5075 5076 si = &SOC_INFO(unit); 5077 tdm = SOC_CONTROL(unit)->tdm_info; 5078 5079 soc_tomahawk_pipe_map_get(unit, &pipe_map); 5080 5081 for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) { 5082 if (!(pipe_map & (1 << pipe))) { 5083 continue; 5084 } 5085 5086 reg1 = SOC_REG_UNIQUE_ACC(unit, IS_OVR_SUB_GRP_CFGr)[pipe]; 5087 for (group = 0; group < _OVS_GROUP_COUNT; group++) { 5088 reg = SOC_REG_UNIQUE_ACC(unit, grp_tbl_regs[group])[pipe]; 5089 rval = 0; 5090 for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) { 5091 phy_port = tdm->idb_ovs_tdm[pipe][group][slot]; 5092 if (phy_port >= TH_NUM_EXT_PORTS) { 5093 idb_port = 0x3f; 5094 id = 0; 5095 } else { 5096 port = si->port_p2l_mapping[phy_port]; 5097 idb_port = si->port_l2i_mapping[port]; 5098 id = si->port_serdes[port]; 5099 } 5100 soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, id & 0x7); 5101 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, idb_port); 5102 SOC_IF_ERROR_RETURN 5103 (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval)); 5104 } 5105 /* Handle the case where the first element in the group 5106 * is invalid but other valid ports exist in the group. 5107 */ 5108 for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) { 5109 phy_port = tdm->idb_ovs_tdm[pipe][group][slot]; 5110 if (phy_port < TH_NUM_EXT_PORTS) { 5111 break; 5112 } 5113 } 5114 /* No valid ports found, skip group */ 5115 if (_OVS_GROUP_TDM_LENGTH == slot) { 5116 continue; 5117 } 5118 if (si->os_mixed_sister_25_50_enable == 0) { 5119 port = si->port_p2l_mapping[phy_port]; 5120 speed_max = 25000 * si->port_num_lanes[port]; 5121 if (speed_max > si->port_speed_max[port]) { 5122 speed_max = si->port_speed_max[port]; 5123 } 5124 } else { 5125 speed_max = tdm->speed[phy_port]; 5126 } 5127 _soc_tomahawk_speed_to_ovs_class_mapping(unit, speed_max, 5128 &ovs_class); 5129 rval = 0; 5130 soc_reg_field_set(unit, reg1, &rval, SAME_SPACINGf, 4); 5131 soc_reg_field_set(unit, reg1, &rval, SISTER_SPACINGf, 4); 5132 soc_reg_field_set(unit, reg1, &rval, SPEEDf, ovs_class); 5133 SOC_IF_ERROR_RETURN 5134 (soc_reg32_set(unit, reg1, REG_PORT_ANY, group, rval)); 5135 } 5136 } 5137 5138 SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) { 5139 port = SOC_BLOCK_PORT(unit, block_info_idx); 5140 phy_port_base = PORT_BLOCK_BASE_PORT(port); 5141 pipe = si->port_pipe[port]; 5142 clport = SOC_BLOCK_NUMBER(unit, block_info_idx); 5143 5144 mode = tdm->port_ratio[clport]; 5145 reg = SOC_REG_UNIQUE_ACC(unit, pblk_calendar_regs[clport & 0x7])[pipe]; 5146 rval = 0; 5147 soc_reg_field_set(unit, reg, &rval, VALIDf, 1); 5148 soc_reg_field_set(unit, reg, &rval, SPACINGf, 4); 5149 for (slot = 0; slot < 7; slot++) { 5150 lane = pblk_slots[mode][slot]; 5151 if (lane == -1) { 5152 SOC_IF_ERROR_RETURN 5153 (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, 0)); 5154 continue; 5155 } 5156 port = si->port_p2l_mapping[phy_port_base + lane]; 5157 idb_port = si->port_l2i_mapping[port]; 5158 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, idb_port); 5159 SOC_IF_ERROR_RETURN 5160 (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval)); 5161 } 5162 } 5163 5164 return SOC_E_NONE; 5165 } 5166 5167 int 5168 _soc_tomahawk_tdm_idb_opportunistic_set(int unit, int enable) 5169 { 5170 soc_reg_t reg; 5171 uint32 pipe_map; 5172 int pipe; 5173 uint32 rval; 5174 5175 soc_tomahawk_pipe_map_get(unit, &pipe_map); 5176 5177 for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) { 5178 if (!(pipe_map & (1 << pipe))) { 5179 continue; 5180 } 5181 5182 reg = SOC_REG_UNIQUE_ACC(unit, IS_CPU_LB_OPP_CFGr)[pipe]; 5183 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 5184 soc_reg_field_set(unit, reg, &rval, CPU_OPP_ENf, enable ? 1 : 0); 5185 soc_reg_field_set(unit, reg, &rval, LB_OPP_ENf, enable ? 1 : 0); 5186 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 5187 5188 reg = SOC_REG_UNIQUE_ACC(unit, IS_OPP_SCHED_CFGr)[pipe]; 5189 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 5190 soc_reg_field_set(unit, reg, &rval, OPP1_PORT_ENf, enable ? 1 : 0); 5191 soc_reg_field_set(unit, reg, &rval, OPP2_PORT_ENf, enable ? 1 : 0); 5192 soc_reg_field_set(unit, reg, &rval, OPP_OVR_SUB_ENf, enable ? 1 : 0); 5193 soc_reg_field_set(unit, reg, &rval, DISABLE_PORT_NUMf, 35); 5194 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 5195 } 5196 5197 return SOC_E_NONE; 5198 } 5199 5200 int 5201 _soc_tomahawk_tdm_idb_hsp_set(int unit, int all_pipes) 5202 { 5203 soc_info_t *si; 5204 soc_reg_t reg; 5205 uint32 pipe_map; 5206 int pipe; 5207 int port, idb_port; 5208 uint32 port_map[_TH_PIPES_PER_DEV]; 5209 uint32 rval = 0x0; 5210 5211 si = &SOC_INFO(unit); 5212 5213 soc_tomahawk_pipe_map_get(unit, &pipe_map); 5214 5215 for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) { 5216 port_map[pipe] = 0; 5217 } 5218 SOC_PBMP_ITER(si->eq_pbm, port) { 5219 pipe = si->port_pipe[port]; 5220 idb_port = si->port_l2i_mapping[port]; 5221 port_map[pipe] |= 1 << idb_port; 5222 } 5223 5224 for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) { 5225 if (!(pipe_map & (1 << pipe))) { 5226 continue; 5227 } 5228 if ((UPDATE_ALL_PIPES == all_pipes) || (pipe == all_pipes)) { 5229 reg = SOC_REG_UNIQUE_ACC(unit, IS_TDM_HSPr)[pipe]; 5230 soc_reg_field_set(unit, reg, &rval, PORT_BMPf, port_map[pipe]); 5231 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 5232 } 5233 } 5234 5235 return SOC_E_NONE; 5236 } 5237 5238 STATIC int 5239 _soc_tomahawk_tdm_mmu_calendar_set(int unit, int calendar_id, int in_pipe) 5240 { 5241 soc_info_t *si; 5242 _soc_tomahawk_tdm_t *tdm; 5243 uint32 pipe_map; 5244 soc_mem_t mem; 5245 soc_reg_t reg; 5246 soc_field_t field; 5247 int pipe, slot, id, length; 5248 int port, phy_port, mmu_port, inst; 5249 uint32 rval = 0; 5250 uint32 entry[SOC_MAX_MEM_WORDS]; 5251 static const soc_mem_t calendar_mems[] = { 5252 TDM_CALENDAR0m, TDM_CALENDAR1m 5253 }; 5254 static const soc_field_t calendar_end_fields[] = { 5255 CAL0_ENDf, CAL1_ENDf 5256 }; 5257 5258 si = &SOC_INFO(unit); 5259 tdm = SOC_CONTROL(unit)->tdm_info; 5260 5261 soc_tomahawk_pipe_map_get(unit, &pipe_map); 5262 5263 for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) { 5264 if (!(pipe_map & (1 << pipe)) || 5265 ((UPDATE_ALL_PIPES != in_pipe) && (pipe != in_pipe))) { 5266 continue; 5267 } 5268 5269 for (length = _TDM_LENGTH; length > 0; length--) { 5270 if (tdm->mmu_tdm[pipe][length - 1] != TH_NUM_EXT_PORTS) { 5271 break; 5272 } 5273 } 5274 5275 reg = TDM_CONFIGr; 5276 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 5277 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, 0, &rval)); 5278 if (calendar_id == -1) { /* choose "the other one" */ 5279 calendar_id = soc_reg_field_get(unit, reg, rval, CURR_CALf) ^ 1; 5280 } 5281 mem = SOC_MEM_UNIQUE_ACC(unit, calendar_mems[calendar_id])[pipe]; 5282 field = calendar_end_fields[calendar_id]; 5283 sal_memset(entry, 0, soc_mem_entry_words(unit, mem) * sizeof(uint32)); 5284 for (slot = 0; slot < length; slot += 2) { 5285 phy_port = tdm->mmu_tdm[pipe][slot]; 5286 id = -1; 5287 if (phy_port == TH_OVSB_TOKEN) { 5288 mmu_port = _SOC_TH_TDM_OVERSUB_TOKEN; 5289 } else if (phy_port == TH_IDL1_TOKEN) { 5290 mmu_port = _SOC_TH_TDM_IDL1_TOKEN; 5291 } else if (phy_port == TH_IDL2_TOKEN) { 5292 mmu_port = _SOC_TH_TDM_IDL2_TOKEN; 5293 } else if (phy_port == NULL_TOKEN) { 5294 mmu_port = _SOC_TH_TDM_NULL_TOKEN; 5295 } else if (phy_port >= TH_NUM_EXT_PORTS) { 5296 mmu_port = _SOC_TH_TDM_UNUSED_TOKEN; 5297 } else { 5298 /* TDM code always allocates slots for management ports. 5299 * If mgmgt ports are omitted from config, this mapping 5300 * is not set up. 5301 */ 5302 id = 0xf; 5303 if (phy_port == 129) { 5304 mmu_port = 96; 5305 } else if (phy_port == 131){ 5306 mmu_port = 160; 5307 } else { 5308 mmu_port = si->port_p2m_mapping[phy_port]; 5309 port = si->port_p2l_mapping[phy_port]; 5310 id = si->port_serdes[port]; 5311 } 5312 } 5313 soc_mem_field32_set(unit, mem, entry, PORT_NUM_EVENf, 5314 mmu_port & 0x3f); 5315 soc_mem_field32_set(unit, mem, entry, PHY_PORT_ID_EVENf, id & 0xf); 5316 phy_port = tdm->mmu_tdm[pipe][slot + 1]; 5317 id = -1; 5318 if (phy_port == TH_OVSB_TOKEN) { 5319 mmu_port = _SOC_TH_TDM_OVERSUB_TOKEN; 5320 } else if (phy_port == TH_IDL1_TOKEN) { 5321 mmu_port = _SOC_TH_TDM_IDL1_TOKEN; 5322 } else if (phy_port == TH_IDL2_TOKEN) { 5323 mmu_port = _SOC_TH_TDM_IDL2_TOKEN; 5324 } else if (phy_port == NULL_TOKEN) { 5325 mmu_port = _SOC_TH_TDM_NULL_TOKEN; 5326 } else if (phy_port >= TH_NUM_EXT_PORTS) { 5327 mmu_port = _SOC_TH_TDM_UNUSED_TOKEN; 5328 } else { 5329 /* TDM code always allocates slots for management ports. 5330 * If mgmgt ports are omitted from config, this mapping 5331 * is not set up. 5332 */ 5333 id = 0xf; 5334 if (phy_port == 129) { 5335 mmu_port = 96; 5336 } else if (phy_port == 131){ 5337 mmu_port = 160; 5338 } else { 5339 mmu_port = si->port_p2m_mapping[phy_port]; 5340 port = si->port_p2l_mapping[phy_port]; 5341 id = si->port_serdes[port]; 5342 } 5343 } 5344 soc_mem_field32_set(unit, mem, entry, PORT_NUM_ODDf, 5345 mmu_port & 0x3f); 5346 soc_mem_field32_set(unit, mem, entry, PHY_PORT_ID_ODDf, id & 0xf); 5347 SOC_IF_ERROR_RETURN 5348 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, slot / 2, entry)); 5349 if (tdm->mmu_tdm[pipe][slot + 2] == TH_NUM_EXT_PORTS) { 5350 soc_reg_field_set(unit, reg, &rval, field, 5351 phy_port == TH_NUM_EXT_PORTS ? slot : slot + 1); 5352 break; 5353 } 5354 } 5355 soc_reg_field_set(unit, reg, &rval, CURR_CALf, calendar_id); 5356 soc_reg_field_set(unit, reg, &rval, ENABLEf, 1); 5357 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval)); 5358 } 5359 5360 return SOC_E_NONE; 5361 } 5362 5363 STATIC int 5364 _soc_tomahawk_tdm_mmu_oversub_group_set(int unit) 5365 { 5366 soc_info_t *si; 5367 _soc_tomahawk_tdm_t *tdm; 5368 uint32 pipe_map; 5369 int block_info_idx; 5370 soc_reg_t reg, reg1; 5371 int pipe, clport, group, lane, slot, id, mode, ovs_class; 5372 int port, phy_port, phy_port_base, mmu_port, inst; 5373 int speed_max; 5374 uint32 rval; 5375 static const soc_reg_t grp_tbl_regs[] = { 5376 OVR_SUB_GRP0_TBLr, OVR_SUB_GRP1_TBLr, 5377 OVR_SUB_GRP2_TBLr, OVR_SUB_GRP3_TBLr, 5378 OVR_SUB_GRP4_TBLr, OVR_SUB_GRP5_TBLr 5379 }; 5380 static const soc_reg_t pblk_calendar_regs[] = { 5381 PBLK0_CALENDARr, PBLK1_CALENDARr, PBLK2_CALENDARr, PBLK3_CALENDARr, 5382 PBLK4_CALENDARr, PBLK5_CALENDARr, PBLK6_CALENDARr, PBLK7_CALENDARr 5383 }; 5384 static const int pblk_slots[SOC_TH_PORT_RATIO_COUNT][7] = { 5385 { 0, -1, 0, 0, -1, 0, -1 }, /* SOC_TH_PORT_RATIO_SINGLE */ 5386 { 0, -1, 2, 0, -1, 2, -1 }, /* SOC_TH_PORT_RATIO_DUAL_1_1 */ 5387 { 0, 0, 2, 0, 0, 2, -1 }, /* SOC_TH_PORT_RATIO_DUAL_2_1 */ 5388 { 0, 2, 2, 0, 2, 2, -1 }, /* SOC_TH_PORT_RATIO_DUAL_1_2 */ 5389 { 0, -1, 2, 0, -1, 3, -1 }, /* SOC_TH_PORT_RATIO_TRI_023_2_1_1 */ 5390 { 0, 0, 2, 0, 0, 3, -1 }, /* SOC_TH_PORT_RATIO_TRI_023_4_1_1 */ 5391 { 0, -1, 2, 1, -1, 2, -1 }, /* SOC_TH_PORT_RATIO_TRI_012_1_1_2 */ 5392 { 0, 2, 2, 1, 2, 2, -1 }, /* SOC_TH_PORT_RATIO_TRI_012_1_1_4 */ 5393 { 0, -1, 2, 1, -1, 3, -1 } /* SOC_TH_PORT_RATIO_QUAD */ 5394 }; 5395 5396 si = &SOC_INFO(unit); 5397 tdm = SOC_CONTROL(unit)->tdm_info; 5398 5399 soc_tomahawk_pipe_map_get(unit, &pipe_map); 5400 5401 reg1 = OVR_SUB_GRP_CFGr; 5402 for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) { 5403 if (!(pipe_map & (1 << pipe))) { 5404 continue; 5405 } 5406 5407 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 5408 for (group = 0; group < _OVS_GROUP_COUNT; group++) { 5409 reg = grp_tbl_regs[group]; 5410 rval = 0; 5411 for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) { 5412 phy_port = tdm->mmu_ovs_tdm[pipe][group][slot]; 5413 if (phy_port >= TH_NUM_EXT_PORTS) { 5414 mmu_port = 0x3f; 5415 id = 0; 5416 } else { 5417 mmu_port = si->port_p2m_mapping[phy_port]; 5418 port = si->port_p2l_mapping[phy_port]; 5419 id = si->port_serdes[port]; 5420 } 5421 soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, id & 0x7); 5422 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, 5423 mmu_port & 0x3f); 5424 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval)); 5425 } 5426 /* Handle the case where the first element in the group 5427 * is invalid but other valid ports exist in the group. 5428 */ 5429 for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) { 5430 phy_port = tdm->mmu_ovs_tdm[pipe][group][slot]; 5431 if (phy_port < TH_NUM_EXT_PORTS) { 5432 break; 5433 } 5434 } 5435 /* No valid ports found, skip group */ 5436 if (_OVS_GROUP_TDM_LENGTH == slot) { 5437 continue; 5438 } 5439 if (si->os_mixed_sister_25_50_enable == 0) { 5440 port = si->port_p2l_mapping[phy_port]; 5441 speed_max = 25000 * si->port_num_lanes[port]; 5442 if (speed_max > si->port_speed_max[port]) { 5443 speed_max = si->port_speed_max[port]; 5444 } 5445 } else { 5446 speed_max = tdm->speed[phy_port]; 5447 } 5448 _soc_tomahawk_speed_to_ovs_class_mapping(unit, speed_max, 5449 &ovs_class); 5450 rval = 0; 5451 soc_reg_field_set(unit, reg1, &rval, SAME_SPACINGf, 5452 speed_max >= 40000 ? 4 : 8); 5453 soc_reg_field_set(unit, reg1, &rval, SISTER_SPACINGf, 4); 5454 soc_reg_field_set(unit, reg1, &rval, SPEEDf, ovs_class); 5455 SOC_IF_ERROR_RETURN 5456 (soc_reg32_set(unit, reg1, inst, group, rval)); 5457 } 5458 } 5459 5460 SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) { 5461 port = SOC_BLOCK_PORT(unit, block_info_idx); 5462 phy_port_base = PORT_BLOCK_BASE_PORT(port); 5463 if (si->os_mixed_sister_25_50_enable == 0) { 5464 speed_max = 25000 * si->port_num_lanes[port]; 5465 if (speed_max > si->port_speed_max[port]) { 5466 speed_max = si->port_speed_max[port]; 5467 } 5468 } else { 5469 phy_port = si->port_l2p_mapping[port]; 5470 speed_max = tdm->speed[phy_port]; 5471 } 5472 pipe = si->port_pipe[port]; 5473 clport = SOC_BLOCK_NUMBER(unit, block_info_idx); 5474 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 5475 5476 mode = tdm->port_ratio[clport]; 5477 reg = pblk_calendar_regs[clport & 0x7]; 5478 rval = 0; 5479 soc_reg_field_set(unit, reg, &rval, VALIDf, 1); 5480 soc_reg_field_set(unit, reg, &rval, SPACINGf, 5481 speed_max >= 40000 ? 4 : 8); 5482 for (slot = 0; slot < 7; slot++) { 5483 lane = pblk_slots[mode][slot]; 5484 if (lane == -1) { 5485 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, 0)); 5486 continue; 5487 } 5488 mmu_port = si->port_p2m_mapping[phy_port_base + lane]; 5489 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, mmu_port & 0x3f); 5490 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval)); 5491 } 5492 } 5493 5494 return SOC_E_NONE; 5495 } 5496 5497 int 5498 _soc_tomahawk_tdm_mmu_opportunistic_set(int unit, int enable) 5499 { 5500 uint32 pipe_map; 5501 soc_reg_t reg; 5502 int pipe; 5503 int inst; 5504 uint32 rval; 5505 5506 soc_tomahawk_pipe_map_get(unit, &pipe_map); 5507 5508 for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) { 5509 if (!(pipe_map & (1 << pipe))) { 5510 continue; 5511 } 5512 5513 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 5514 5515 reg = CPU_LB_OPP_CFGr; 5516 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, 0, &rval)); 5517 soc_reg_field_set(unit, reg, &rval, CPU_OPP_ENf, enable ? 1 : 0); 5518 soc_reg_field_set(unit, reg, &rval, LB_OPP_ENf, enable ? 1 : 0); 5519 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval)); 5520 5521 reg = OPP_SCHED_CFGr; 5522 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, 0, &rval)); 5523 soc_reg_field_set(unit, reg, &rval, OPP1_PORT_ENf, enable ? 1 : 0); 5524 soc_reg_field_set(unit, reg, &rval, OPP2_PORT_ENf, enable ? 1 : 0); 5525 soc_reg_field_set(unit, reg, &rval, OPP_OVR_SUB_ENf, enable ? 1 : 0); 5526 soc_reg_field_set(unit, reg, &rval, DISABLE_PORT_NUMf, 35); 5527 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval)); 5528 } 5529 5530 return SOC_E_NONE; 5531 } 5532 5533 int 5534 _soc_tomahawk_tdm_mmu_hsp_set(int unit, int all_pipes) 5535 { 5536 soc_info_t *si; 5537 uint32 pipe_map; 5538 soc_reg_t reg; 5539 int pipe; 5540 int port, phy_port, mmu_port, inst; 5541 uint32 port_map[_TH_PIPES_PER_DEV]; 5542 uint32 rval = 0x0; 5543 5544 si = &SOC_INFO(unit); 5545 5546 soc_tomahawk_pipe_map_get(unit, &pipe_map); 5547 5548 for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) { 5549 port_map[pipe] = 0; 5550 } 5551 SOC_PBMP_ITER(si->eq_pbm, port) { 5552 pipe = si->port_pipe[port]; 5553 phy_port = si->port_l2p_mapping[port]; 5554 mmu_port = si->port_p2m_mapping[phy_port]; 5555 port_map[pipe] |= 1 << (mmu_port & 0x1f); 5556 } 5557 5558 for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) { 5559 if (!(pipe_map & (1 << pipe))) { 5560 continue; 5561 } 5562 5563 if ((UPDATE_ALL_PIPES == all_pipes) || (pipe == all_pipes)) { 5564 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 5565 reg = TDM_HSPr; 5566 soc_reg_field_set(unit, reg, &rval, PORT_BMPf, port_map[pipe]); 5567 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, 0, rval)); 5568 } 5569 } 5570 5571 return SOC_E_NONE; 5572 } 5573 5574 STATIC int 5575 _soc_tomahawk_tdm_calculation(int unit, int initTime, _soc_tomahawk_tdm_t *tdm) 5576 { 5577 soc_info_t *si; 5578 int port, phy_port; 5579 int pipe, clport, lane, group, block_info_idx, index, cal_id, cal_grp; 5580 int length, ovs_core_slot_count, ovs_io_slot_count, port_slot_count; 5581 int mode[_TH_PIPES_PER_DEV]; 5582 int *tdm_idb_pipe_main, *tdm_mmu_pipe_main; 5583 int **tdm_idb_pipe_group, **tdm_mmu_pipe_group; 5584 tdm_soc_t _chip_pkg; 5585 tdm_mod_t *_tdm_pkg; 5586 soc_pbmp_t pbmp; 5587 soc_th_port_lanes_t lanes_ctrl; 5588 5589 si = &SOC_INFO(unit); 5590 5591 sal_memset(tdm, 0, sizeof(_soc_tomahawk_tdm_t)); 5592 sal_memset(&_chip_pkg, 0, sizeof(tdm_soc_t)); 5593 5594 for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) { 5595 SOC_PBMP_ASSIGN(pbmp, si->pipe_pbm[pipe]); 5596 SOC_PBMP_AND(pbmp, PBMP_HG_ALL(unit)); 5597 mode[pipe] = SOC_PBMP_NOT_NULL(pbmp) ? PORT_HIGIG2 : PORT_ETHERNET; 5598 } 5599 5600 for (index = 0; index < COUNTOF(tdm->pm_encap_type); index++) { 5601 tdm->pm_encap_type[index] = PORT_ETHERNET; 5602 } 5603 PBMP_PORT_ITER(unit, port) { 5604 if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) { 5605 continue; 5606 } 5607 phy_port = si->port_l2p_mapping[port]; 5608 tdm->port_state[phy_port] = 5609 SOC_PBMP_MEMBER(si->oversub_pbm, port) ? 5610 PORT_STATE_OVERSUB : PORT_STATE_LINERATE; 5611 for (lane = 1; lane < si->port_num_lanes[port]; lane++) { 5612 tdm->port_state[phy_port + lane] = PORT_STATE_CONTINUATION; 5613 } 5614 if (initTime) { 5615 /* When invoked by init misc, use speed obtained from 5616 * config file. 5617 */ 5618 tdm->speed[phy_port] = si->port_speed_max[port]; 5619 /* bootup in normmally config */ 5620 if (si->os_mixed_sister_25_50_enable == 0) { 5621 tdm->speed[phy_port] = si->port_speed_max[port]; 5622 } else { /* bootup in mixed config */ 5623 sal_memset(&lanes_ctrl, 0, sizeof(lanes_ctrl)); 5624 lanes_ctrl.port_base = port; 5625 lanes_ctrl.os_mixed_sister = si->os_mixed_sister_25_50_enable; 5626 soc_th_os_mixed_sister_port_mode_get(unit, initTime, &lanes_ctrl); 5627 if (lanes_ctrl.mixed_port_mode == MIXED_DUAL_MODE_50_0_25_0 || 5628 lanes_ctrl.mixed_port_mode == MIXED_DUAL_MODE_25_0_50_0 || 5629 lanes_ctrl.mixed_port_mode == MIXED_DUAL_MODE_25_0_25_0) { 5630 tdm->speed[phy_port] = IS_HG_PORT(unit, port) ? 53000 : 50000; 5631 } else { 5632 tdm->speed[phy_port] = si->port_speed_max[port]; 5633 } 5634 } 5635 } else { 5636 /* When invoked as part of flexport transform use fixedup 5637 * speed. 5638 */ 5639 tdm->speed[phy_port] = si->port_init_speed[port]; 5640 } 5641 } 5642 5643 /* CLPORT */ 5644 SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) { 5645 port = SOC_BLOCK_PORT(unit, block_info_idx); 5646 clport = SOC_BLOCK_NUMBER(unit, block_info_idx); 5647 soc_tomahawk_port_ratio_get(unit, initTime, clport, &tdm->port_ratio[clport]); 5648 tdm->pm_encap_type[clport] = mode[si->port_pipe[port]]; 5649 } 5650 5651 /* Management ports */ 5652 SOC_PBMP_ITER(si->management_pbm, port) { 5653 phy_port = si->port_l2p_mapping[port]; 5654 tdm->pm_encap_type[_TH_PBLKS_PER_DEV] = mode[si->port_pipe[port]]; 5655 tdm->speed[phy_port] = si->port_speed_max[port]; 5656 } 5657 5658 if (LOG_CHECK(BSL_LS_SOC_TDM | BSL_INFO)) { 5659 LOG_CLI((BSL_META_U(unit, 5660 "frequency: %dMHz\n"), si->frequency)); 5661 LOG_CLI((BSL_META_U(unit, 5662 "port speed:"))); 5663 for (index = 0; index < TH_NUM_EXT_PORTS; index++) { 5664 if (index % 8 == 0) { 5665 LOG_CLI((BSL_META_U(unit, 5666 "\n "))); 5667 } 5668 LOG_CLI((BSL_META_U(unit, 5669 " %6d"), tdm->speed[index])); 5670 } 5671 LOG_CLI((BSL_META_U(unit, 5672 "\n"))); 5673 LOG_CLI((BSL_META_U(unit, 5674 "port state map:"))); 5675 for (index = 0; index < TH_NUM_EXT_PORTS; index++) { 5676 if (index % 16 == 0) { 5677 LOG_CLI((BSL_META_U(unit, 5678 "\n "))); 5679 } 5680 if (index == 0 || index == (TH_NUM_EXT_PORTS - 1)) { 5681 LOG_CLI((BSL_META_U(unit, 5682 " ---"))); 5683 } else { 5684 LOG_CLI((BSL_META_U(unit, 5685 " %3d"), tdm->port_state[index])); 5686 } 5687 } 5688 LOG_CLI((BSL_META_U(unit, 5689 "\n"))); 5690 LOG_CLI((BSL_META_U(unit, 5691 "pm encap type:"))); 5692 for (index = 0; index < TH_NUM_PM_MOD; index++) { 5693 if (index % 16 == 0) { 5694 LOG_CLI((BSL_META_U(unit, 5695 "\n "))); 5696 } 5697 LOG_CLI((BSL_META_U(unit, 5698 " %3d"), tdm->pm_encap_type[index])); 5699 } 5700 LOG_CLI((BSL_META_U(unit, 5701 "\n"))); 5702 } 5703 5704 for (index = 0; index < TH_NUM_EXT_PORTS; index++) { 5705 tdm->tdm_globals.speed[index] = tdm->speed[index]; 5706 } 5707 tdm->tdm_globals.clk_freq = si->frequency; 5708 for (index = 1; index < TH_NUM_EXT_PORTS; index++) { 5709 tdm->tdm_globals.port_rates_array[index-1] = tdm->port_state[index]; 5710 } 5711 for (index = 1; index < TH_NUM_PM_MOD; index++) { 5712 tdm->tdm_globals.pm_encap_type[index] = tdm->pm_encap_type[index]; 5713 } 5714 _chip_pkg.unit = unit; 5715 _chip_pkg.num_ext_ports = TH_NUM_EXT_PORTS; 5716 _chip_pkg.state=sal_alloc((_chip_pkg.num_ext_ports)*sizeof(int *), 5717 "port state list"); 5718 if (_chip_pkg.state == NULL) { 5719 return SOC_E_MEMORY; 5720 } 5721 _chip_pkg.speed=sal_alloc((_chip_pkg.num_ext_ports)*sizeof(int *), 5722 "port speed list"); 5723 if (_chip_pkg.speed == NULL) { 5724 sal_free(_chip_pkg.state); 5725 return SOC_E_MEMORY; 5726 } 5727 for (index=0; index<TH_NUM_PHY_PORTS; index++) { 5728 _chip_pkg.state[index] = tdm->pm_encap_type[((index)/TH_NUM_PM_LNS)]== 5729 PORT_HIGIG2?((tdm->tdm_globals.port_rates_array[index])| 5730 PSBMP_ENCAP_HIGIG):(tdm->tdm_globals.port_rates_array[index]); 5731 } 5732 for (index=TH_NUM_PHY_PORTS; index<TH_NUM_EXT_PORTS; index++) { 5733 _chip_pkg.state[index] = tdm->tdm_globals.port_rates_array[index]; 5734 } 5735 for (index=0; index<(_chip_pkg.num_ext_ports); index++) { 5736 _chip_pkg.speed[index] = tdm->tdm_globals.speed[index]; 5737 } 5738 _chip_pkg.soc_vars.th.cal_universal_en = si->fabric_port_enable; 5739 _chip_pkg.clk_freq = tdm->tdm_globals.clk_freq; 5740 _chip_pkg.soc_vars.th.mgmt_pm_hg= 5741 ((tdm->tdm_globals.pm_encap_type[TH_NUM_PHY_PM]==PORT_HIGIG2)&& 5742 ((tdm->tdm_globals.speed[129]>0)|| 5743 (tdm->tdm_globals.speed[131]>0)))?(1):(0); 5744 _chip_pkg.tvec_size = 0; 5745 _tdm_pkg = _soc_set_tdm_tbl(SOC_SEL_TDM(&_chip_pkg)); 5746 sal_free(_chip_pkg.state); 5747 sal_free(_chip_pkg.speed); 5748 if (NULL == _tdm_pkg) { 5749 LOG_CLI((BSL_META_U(unit, 5750 "Unsupported config for TDM calendar generation\n"))); 5751 return SOC_E_FAIL; 5752 } 5753 else { 5754 for (cal_id = 0; cal_id < 4; cal_id++) { 5755 switch (cal_id) { 5756 case 0: 5757 tdm_idb_pipe_group=_tdm_pkg->_chip_data.cal_0.cal_grp; 5758 tdm_idb_pipe_main=_tdm_pkg->_chip_data.cal_0.cal_main; 5759 tdm_mmu_pipe_group=_tdm_pkg->_chip_data.cal_4.cal_grp; 5760 tdm_mmu_pipe_main=_tdm_pkg->_chip_data.cal_4.cal_main; 5761 break; 5762 case 1: 5763 tdm_idb_pipe_group=_tdm_pkg->_chip_data.cal_1.cal_grp; 5764 tdm_idb_pipe_main=_tdm_pkg->_chip_data.cal_1.cal_main; 5765 tdm_mmu_pipe_group=_tdm_pkg->_chip_data.cal_5.cal_grp; 5766 tdm_mmu_pipe_main=_tdm_pkg->_chip_data.cal_5.cal_main; 5767 break; 5768 case 2: 5769 tdm_idb_pipe_group=_tdm_pkg->_chip_data.cal_2.cal_grp; 5770 tdm_idb_pipe_main=_tdm_pkg->_chip_data.cal_2.cal_main; 5771 tdm_mmu_pipe_group=_tdm_pkg->_chip_data.cal_6.cal_grp; 5772 tdm_mmu_pipe_main=_tdm_pkg->_chip_data.cal_6.cal_main; 5773 break; 5774 case 3: 5775 tdm_idb_pipe_group=_tdm_pkg->_chip_data.cal_3.cal_grp; 5776 tdm_idb_pipe_main=_tdm_pkg->_chip_data.cal_3.cal_main; 5777 tdm_mmu_pipe_group=_tdm_pkg->_chip_data.cal_7.cal_grp; 5778 tdm_mmu_pipe_main=_tdm_pkg->_chip_data.cal_7.cal_main; 5779 break; 5780 default: 5781 tdm_idb_pipe_group=NULL; 5782 tdm_idb_pipe_main=NULL; 5783 tdm_mmu_pipe_group=NULL; 5784 tdm_mmu_pipe_main=NULL; 5785 } 5786 tdm->idb_tdm[cal_id] = sal_alloc(sizeof(int)*_TDM_LENGTH, 5787 "IDB TDM main calendar"); 5788 if (tdm->idb_tdm[cal_id] == NULL) { 5789 return SOC_E_MEMORY; 5790 } 5791 sal_memcpy(tdm->idb_tdm[cal_id], tdm_idb_pipe_main, 5792 sizeof(int)*_TDM_LENGTH); 5793 tdm->mmu_tdm[cal_id] = sal_alloc(sizeof(int)*_TDM_LENGTH, 5794 "MMU TDM main calendar"); 5795 if (tdm->mmu_tdm[cal_id] == NULL) { 5796 return SOC_E_MEMORY; 5797 } 5798 sal_memcpy(tdm->mmu_tdm[cal_id], tdm_mmu_pipe_main, 5799 sizeof(int)*_TDM_LENGTH); 5800 for (cal_grp = 0; cal_grp < _OVS_GROUP_COUNT; cal_grp++) { 5801 tdm->idb_ovs_tdm[cal_id][cal_grp] = sal_alloc(sizeof(int)* 5802 _OVS_GROUP_TDM_LENGTH,"IDB TDM group calendar"); 5803 if (tdm->idb_ovs_tdm[cal_id][cal_grp] == NULL) { 5804 return SOC_E_MEMORY; 5805 } 5806 sal_memcpy(tdm->idb_ovs_tdm[cal_id][cal_grp], 5807 tdm_idb_pipe_group[cal_grp], sizeof(int)*_OVS_GROUP_TDM_LENGTH); 5808 tdm->mmu_ovs_tdm[cal_id][cal_grp] = sal_alloc(sizeof(int)* 5809 _OVS_GROUP_TDM_LENGTH,"MMU TDM group calendar"); 5810 if (tdm->mmu_ovs_tdm[cal_id][cal_grp] == NULL) { 5811 return SOC_E_MEMORY; 5812 } 5813 sal_memcpy(tdm->mmu_ovs_tdm[cal_id][cal_grp], 5814 tdm_mmu_pipe_group[cal_grp], sizeof(int)*_OVS_GROUP_TDM_LENGTH); 5815 } 5816 } 5817 tdm_th_free(_tdm_pkg); 5818 sal_free(_tdm_pkg); 5819 } 5820 5821 for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) { 5822 /* Count number of TH_OVSB_TOKEN assigned by the TDM code */ 5823 for (length = _TDM_LENGTH; length > 0; length--) { 5824 if (tdm->mmu_tdm[pipe][length - 1] != TH_NUM_EXT_PORTS) { 5825 break; 5826 } 5827 } 5828 ovs_core_slot_count = 0; 5829 for (index = 0; index < length; index++) { 5830 if (tdm->mmu_tdm[pipe][index] == TH_OVSB_TOKEN) { 5831 ovs_core_slot_count++; 5832 } 5833 } 5834 5835 /* Count number of slot needed for the oversub I/O bandwidth */ 5836 ovs_io_slot_count = 0; 5837 for (group = 0; group < _OVS_GROUP_COUNT; group++) { 5838 port_slot_count = 0; 5839 for (index = 0; index < _OVS_GROUP_TDM_LENGTH; index++) { 5840 phy_port = tdm->mmu_ovs_tdm[pipe][group][index]; 5841 if (phy_port == TH_NUM_EXT_PORTS) { 5842 continue; 5843 } 5844 if (port_slot_count == 0) { 5845 _soc_tomahawk_speed_to_slot_mapping 5846 (unit, tdm->speed[phy_port], &port_slot_count); 5847 } 5848 ovs_io_slot_count += port_slot_count; 5849 } 5850 } 5851 5852 if (ovs_core_slot_count != 0) { 5853 tdm->ovs_ratio_x1000[pipe] = 5854 ovs_io_slot_count * 1000 / ovs_core_slot_count; 5855 } 5856 } 5857 5858 if (LOG_CHECK(BSL_LS_SOC_TDM | BSL_INFO)) { 5859 for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) { 5860 LOG_CLI((BSL_META_U(unit, 5861 "Pipe %d idb_tdm:"), pipe)); 5862 for (index = 0; index < _TDM_LENGTH; index++) { 5863 if (index % 16 == 0) { 5864 LOG_CLI((BSL_META_U(unit, 5865 "\n "))); 5866 } 5867 LOG_CLI((BSL_META_U(unit, 5868 " %3d"), tdm->idb_tdm[pipe][index])); 5869 } 5870 LOG_CLI((BSL_META_U(unit, 5871 "\n"))); 5872 for (group = 0; group < _OVS_GROUP_COUNT; group++) { 5873 LOG_CLI((BSL_META_U(unit, 5874 "Pipe %d group %d idb_ovs_tdm"), pipe, group)); 5875 for (index = 0; index < _OVS_GROUP_TDM_LENGTH; index++) { 5876 if (index % 16 == 0) { 5877 LOG_CLI((BSL_META_U(unit, 5878 "\n "))); 5879 } 5880 LOG_CLI((BSL_META_U(unit, 5881 " %3d"), tdm->idb_ovs_tdm[pipe][group][index])); 5882 } 5883 LOG_CLI((BSL_META_U(unit, 5884 "\n"))); 5885 } 5886 5887 LOG_CLI((BSL_META_U(unit, 5888 "Pipe %d mmu_tdm:"), pipe)); 5889 for (index = 0; index < _TDM_LENGTH; index++) { 5890 if (index % 16 == 0) { 5891 LOG_CLI((BSL_META_U(unit, 5892 "\n "))); 5893 } 5894 LOG_CLI((BSL_META_U(unit, 5895 " %3d"), tdm->mmu_tdm[pipe][index])); 5896 } 5897 LOG_CLI((BSL_META_U(unit, 5898 "\n"))); 5899 for (group = 0; group < _OVS_GROUP_COUNT; group++) { 5900 LOG_CLI((BSL_META_U(unit, 5901 "Pipe %d group %d mmu_ovs_tdm"), 5902 pipe, group)); 5903 for (index = 0; index < _OVS_GROUP_TDM_LENGTH; index++) { 5904 if (index % 16 == 0) { 5905 LOG_CLI((BSL_META_U(unit, 5906 "\n "))); 5907 } 5908 LOG_CLI((BSL_META_U(unit, 5909 " %3d"), tdm->mmu_ovs_tdm[pipe][group][index])); 5910 } 5911 LOG_CLI((BSL_META_U(unit, 5912 "\n"))); 5913 } 5914 LOG_CLI((BSL_META_U(unit, 5915 "Pipe %d oversubscribe ratio %d.%-2d\n"), 5916 pipe, tdm->ovs_ratio_x1000[pipe] / 1000, 5917 tdm->ovs_ratio_x1000[pipe] % 1000)); 5918 } 5919 } 5920 5921 return SOC_E_NONE; 5922 } 5923 5924 STATIC int 5925 _soc_tomahawk_tdm_calculation_free_memory(int unit) 5926 { 5927 int pipe, cal_grp; 5928 soc_control_t *soc; 5929 _soc_tomahawk_tdm_t *tdm; 5930 5931 soc = SOC_CONTROL(unit); 5932 tdm = NULL; 5933 if (soc!=NULL){ 5934 if(soc->tdm_info!=NULL){ 5935 tdm = soc->tdm_info; 5936 } 5937 } 5938 if (tdm!=NULL){ 5939 for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) { 5940 if (tdm->idb_tdm[pipe]!=NULL){ 5941 sal_free(tdm->idb_tdm[pipe]); 5942 } 5943 if (tdm->mmu_tdm[pipe]!=NULL){ 5944 sal_free(tdm->mmu_tdm[pipe]); 5945 } 5946 for (cal_grp = 0; cal_grp < _OVS_GROUP_COUNT; cal_grp++) { 5947 if (tdm->idb_ovs_tdm[pipe][cal_grp]!=NULL){ 5948 sal_free(tdm->idb_ovs_tdm[pipe][cal_grp]); 5949 } 5950 if (tdm->mmu_ovs_tdm[pipe][cal_grp]!=NULL){ 5951 sal_free(tdm->mmu_ovs_tdm[pipe][cal_grp]); 5952 } 5953 } 5954 } 5955 } 5956 5957 return SOC_E_NONE; 5958 } 5959 5960 STATIC int 5961 _soc_tomahawk_hash_init(int unit) 5962 { 5963 soc_field_t fields[4]; 5964 uint32 values[4]; 5965 5966 5967 /* L2 dedicated banks */ 5968 fields[0] = BANK0_HASH_OFFSETf; 5969 values[0] = 0; /* CRC32_LOWER */ 5970 fields[1] = BANK1_HASH_OFFSETf; 5971 values[1] = 16; /* CRC32_UPPER */ 5972 SOC_IF_ERROR_RETURN 5973 (soc_reg_fields32_modify(unit, L2_TABLE_HASH_CONTROLr, REG_PORT_ANY, 2, 5974 fields, values)); 5975 5976 if (soc_feature(unit, soc_feature_l3)) { 5977 /* L3 dedicated banks */ 5978 fields[0] = BANK6_HASH_OFFSETf; 5979 values[0] = 0; /* CRC32_LOWER */ 5980 fields[1] = BANK7_HASH_OFFSETf; 5981 values[1] = 8; /* CRC32 >> 8 */ 5982 fields[2] = BANK8_HASH_OFFSETf; 5983 values[2] = 16; /* CRC32_UPPER */ 5984 fields[3] = BANK9_HASH_OFFSETf; 5985 values[3] = 32; /* CRC16 */ 5986 SOC_IF_ERROR_RETURN 5987 (soc_reg_fields32_modify(unit, L3_TABLE_HASH_CONTROLr, REG_PORT_ANY, 4, 5988 fields, values)); 5989 5990 /* SHARED_TABLE_HASH_CONTROLr is not accessible in 5991 * low, balanced latency modes */ 5992 if (SOC_REG_IS_VALID(unit, SHARED_TABLE_HASH_CONTROLr)) { 5993 /* L2/L3/ALPM shared banks */ 5994 fields[0] = BANK2_HASH_OFFSETf; 5995 values[0] = 4; /* CRC32 >> 4 */ 5996 fields[1] = BANK3_HASH_OFFSETf; 5997 values[1] = 12; /* CRC32 >> 12 */ 5998 fields[2] = BANK4_HASH_OFFSETf; 5999 values[2] = 20; /* CRC32 >> 20 */ 6000 fields[3] = BANK5_HASH_OFFSETf; 6001 values[3] = 24; /* CRC32 >> 24 */ 6002 SOC_IF_ERROR_RETURN 6003 (soc_reg_fields32_modify(unit, SHARED_TABLE_HASH_CONTROLr, 6004 REG_PORT_ANY, 4, fields, values)); 6005 } 6006 } 6007 #ifdef SOC_ROBUST_HASH 6008 /* Robust Hash initialization */ 6009 if (soc_feature(unit, soc_feature_robust_hash)) { 6010 uint32 value, seed = 0; 6011 6012 if (NULL == ROBUSTHASH(unit)) { 6013 ROBUSTHASH(unit) = sal_alloc(sizeof(soc_robust_hash_db_t), 6014 "soc_robust_hash"); 6015 if (ROBUSTHASH(unit) == NULL) { 6016 return SOC_E_MEMORY; 6017 } 6018 sal_memset(ROBUSTHASH(unit), 0, sizeof(soc_robust_hash_db_t)); 6019 } 6020 6021 /* Enable Robust hashing for VLAN_XLATE table and configure corresponding 6022 remap and action tables */ 6023 if ((soc_property_get(unit, "robust_hash_disable_vlan", 0)) == 1) { 6024 /* Disable robust hashing */ 6025 SOC_IF_ERROR_RETURN 6026 (READ_VLAN_XLATE_HASH_CONTROLr(unit, &value)); 6027 soc_reg_field_set(unit, VLAN_XLATE_HASH_CONTROLr, &value, 6028 ROBUST_HASH_ENf, 0x0); 6029 SOC_IF_ERROR_RETURN 6030 (WRITE_VLAN_XLATE_HASH_CONTROLr(unit, value)); 6031 6032 ROBUSTHASH(unit)->ing_xlate.enable = 0; 6033 } else { 6034 /* Enable robust hashing */ 6035 SOC_IF_ERROR_RETURN 6036 (READ_VLAN_XLATE_HASH_CONTROLr(unit, &value)); 6037 soc_reg_field_set(unit, VLAN_XLATE_HASH_CONTROLr, &value, 6038 ROBUST_HASH_ENf, 0x1); 6039 SOC_IF_ERROR_RETURN 6040 (WRITE_VLAN_XLATE_HASH_CONTROLr(unit, value)); 6041 ROBUSTHASH(unit)->ing_xlate.enable = 1; 6042 6043 /* Fill action and remap tables with random data */ 6044 ROBUSTHASH(unit)->ing_xlate.remap_tab[0] = ING_VXLT_REMAP_TABLE_Am; 6045 ROBUSTHASH(unit)->ing_xlate.remap_tab[1] = ING_VXLT_REMAP_TABLE_Bm; 6046 ROBUSTHASH(unit)->ing_xlate.action_tab[0] = ING_VXLT_ACTION_TABLE_Am; 6047 ROBUSTHASH(unit)->ing_xlate.action_tab[1] = ING_VXLT_ACTION_TABLE_Bm; 6048 6049 seed = soc_property_get(unit, spn_ROBUST_HASH_SEED_VLAN, 16777213); 6050 6051 SOC_IF_ERROR_RETURN 6052 (soc_robust_hash_table_set(unit, 6053 &(ROBUSTHASH(unit)->ing_xlate), 6054 seed)); 6055 } 6056 6057 /* Enable Robust hashing for EGR_VLAN_XLATE table and configure corresponding 6058 remap and action tables */ 6059 if ((soc_property_get(unit, "robust_hash_disable_egress_vlan", 0)) == 1) { 6060 /* Disable robust hashing */ 6061 SOC_IF_ERROR_RETURN 6062 (READ_EGR_VLAN_XLATE_HASH_CONTROLr(unit, &value)); 6063 soc_reg_field_set(unit, EGR_VLAN_XLATE_HASH_CONTROLr, &value, 6064 ROBUST_HASH_ENf, 0x0); 6065 SOC_IF_ERROR_RETURN 6066 (WRITE_EGR_VLAN_XLATE_HASH_CONTROLr(unit, value)); 6067 6068 ROBUSTHASH(unit)->egr_xlate.enable = 0; 6069 } else { 6070 /* Enable robust hashing */ 6071 SOC_IF_ERROR_RETURN 6072 (READ_EGR_VLAN_XLATE_HASH_CONTROLr(unit, &value)); 6073 soc_reg_field_set(unit, EGR_VLAN_XLATE_HASH_CONTROLr, &value, 6074 ROBUST_HASH_ENf, 0x1); 6075 SOC_IF_ERROR_RETURN 6076 (WRITE_EGR_VLAN_XLATE_HASH_CONTROLr(unit, value)); 6077 6078 ROBUSTHASH(unit)->egr_xlate.enable = 1; 6079 6080 /* Fill action and remap tables with random data */ 6081 ROBUSTHASH(unit)->egr_xlate.remap_tab[0] = EGR_VXLT_REMAP_TABLE_Am; 6082 ROBUSTHASH(unit)->egr_xlate.remap_tab[1] = EGR_VXLT_REMAP_TABLE_Bm; 6083 ROBUSTHASH(unit)->egr_xlate.action_tab[0] = EGR_VXLT_ACTION_TABLE_Am; 6084 ROBUSTHASH(unit)->egr_xlate.action_tab[1] = EGR_VXLT_ACTION_TABLE_Bm; 6085 6086 seed = soc_property_get(unit, spn_ROBUST_HASH_SEED_EGRESS_VLAN, 6087 16777213); 6088 6089 SOC_IF_ERROR_RETURN 6090 (soc_robust_hash_table_set(unit, 6091 &(ROBUSTHASH(unit)->egr_xlate), 6092 seed)); 6093 } 6094 6095 /* Enable Robust hashing for MPLS_ENTRY table and configure corresponding 6096 remap and action tables */ 6097 if ((soc_property_get(unit, "robust_hash_disable_mpls", 0)) == 1) { 6098 /* Disable robust hashing */ 6099 SOC_IF_ERROR_RETURN 6100 (READ_MPLS_ENTRY_HASH_CONTROLr(unit, &value)); 6101 soc_reg_field_set(unit, MPLS_ENTRY_HASH_CONTROLr, &value, 6102 ROBUST_HASH_ENf, 0x0); 6103 SOC_IF_ERROR_RETURN 6104 (WRITE_MPLS_ENTRY_HASH_CONTROLr(unit, value)); 6105 ROBUSTHASH(unit)->mpls_entry.enable = 0; 6106 } else { 6107 /* Enable robust hashing */ 6108 SOC_IF_ERROR_RETURN 6109 (READ_MPLS_ENTRY_HASH_CONTROLr(unit, &value)); 6110 soc_reg_field_set(unit, MPLS_ENTRY_HASH_CONTROLr, &value, 6111 ROBUST_HASH_ENf, 0x1); 6112 SOC_IF_ERROR_RETURN 6113 (WRITE_MPLS_ENTRY_HASH_CONTROLr(unit, value)); 6114 ROBUSTHASH(unit)->mpls_entry.enable = 1; 6115 6116 /* Fill action and remap tables with random data */ 6117 ROBUSTHASH(unit)->mpls_entry.remap_tab[0] = ING_MPLS_ENTRY_REMAP_TABLE_Am; 6118 ROBUSTHASH(unit)->mpls_entry.remap_tab[1] = ING_MPLS_ENTRY_REMAP_TABLE_Bm; 6119 ROBUSTHASH(unit)->mpls_entry.action_tab[0] = ING_MPLS_ENTRY_ACTION_TABLE_Am; 6120 ROBUSTHASH(unit)->mpls_entry.action_tab[1] = ING_MPLS_ENTRY_ACTION_TABLE_Bm; 6121 6122 seed = soc_property_get(unit, spn_ROBUST_HASH_SEED_MPLS, 16777213); 6123 6124 SOC_IF_ERROR_RETURN 6125 (soc_robust_hash_table_set(unit, 6126 &(ROBUSTHASH(unit)->mpls_entry), 6127 seed)); 6128 } 6129 } 6130 #endif /* SOC_ROBUST_HASH */ 6131 6132 return SOC_E_NONE; 6133 } 6134 6135 /* For a given logical port, return the OBM id and the lane number */ 6136 int 6137 soc_tomahawk_port_obm_info_get(int unit, soc_port_t port, 6138 int *obm_id, int *lane) 6139 { 6140 soc_info_t *si; 6141 soc_port_t phy_port; 6142 int pipe, clport, port_block_base, ports_per_pblk; 6143 6144 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port) || 6145 (SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port))) { 6146 return SOC_E_PARAM; 6147 } 6148 si = &SOC_INFO(unit); 6149 pipe = si->port_pipe[port]; 6150 phy_port = si->port_l2p_mapping[port]; 6151 port_block_base = PORT_BLOCK_BASE_PORT(port); 6152 clport = si->port_serdes[port]; 6153 6154 #ifdef BCM_TOMAHAWK3_SUPPORT 6155 if (SOC_IS_TOMAHAWK3(unit)) { 6156 port_block_base = SOC_TH3_PORT_BLOCK_BASE_PORT(port); 6157 ports_per_pblk = _TH3_PORTS_PER_PBLK; 6158 /* TH3 PIPE 2/3/6/7 has reversed (mirrored) OBM number*/ 6159 *obm_id = pipe & 0x10 ? 3 - (clport & 0x3) : clport & 0x3; 6160 } else 6161 #endif 6162 #ifdef BCM_TOMAHAWK2_SUPPORT 6163 if (SOC_IS_TOMAHAWK2(unit)) { 6164 ports_per_pblk = _TH2_PBLKS_PER_PIPE; 6165 *obm_id = clport & 0xF; 6166 } else 6167 #endif 6168 { 6169 ports_per_pblk = _TH_PBLKS_PER_PIPE; 6170 /* obm number is reversed (mirrored) in odd pipe */ 6171 *obm_id = pipe & 1 ? 7 - (clport & 0x7) : clport & 0x7; 6172 } 6173 6174 *lane = (phy_port - port_block_base) % ports_per_pblk; 6175 6176 if (*obm_id >= ports_per_pblk) { 6177 return SOC_E_PARAM; 6178 } 6179 6180 return SOC_E_NONE; 6181 } 6182 6183 STATIC int 6184 _soc_tomahawk_idb_init(int unit) 6185 { 6186 #define _TH_BYTES_PER_OBM_CELL 16 6187 #define _TH_CELLS_PER_OBM 1012 6188 soc_info_t *si; 6189 _soc_tomahawk_tdm_t *tdm; 6190 soc_reg_t reg; 6191 soc_mem_t mem; 6192 soc_field_t field; 6193 int block_info_idx, pipe, clport, obm, lane; 6194 int port, phy_port_base; 6195 int lossless, i, count; 6196 uint32 rval0, rval1, fval; 6197 uint32 rval_port_cfg = 0, rval_max_usage_cfg = 0; 6198 uint64 rval64; 6199 int num_lanes, oversub_ratio_idx; 6200 uint32 entry[SOC_MAX_MEM_WORDS]; 6201 static const struct _obm_setting_s { 6202 int discard_limit; 6203 int lossless_xoff; 6204 int lossy_only_lossy_low_pri; 6205 int port_xoff[3]; /* for oversub ratio 1.5, 1.8, and above */ 6206 int lossy_low_pri[3]; /* for oversub ratio 1.5, 1.8, and above */ 6207 int lossy_discard[3]; /* for oversub ratio 1.5, 1.8, and above */ 6208 } obm_settings[2][5] = { 6209 /* LOSSY Settings */ 6210 { /* indexed by number of lanes used in the port */ 6211 { /* 0 - invalid */ 0 }, 6212 { /* 1 lane */ 6213 _TH_CELLS_PER_OBM / 4, 1023, 157, 6214 { 1023, 1023, 1023 }, /* port_xoff */ 6215 { 157, 157, 157 }, /* lossy_low_pri */ 6216 { 253, 253, 253 } /* lossy_discard */ 6217 }, 6218 { /* 2 lanes */ 6219 _TH_CELLS_PER_OBM / 2, 1023, 410, 6220 { 1023, 1023, 1023 }, /* port_xoff */ 6221 { 410, 410, 410 }, /* lossy_low_pri */ 6222 { 506, 506, 506 } /* lossy_discard */ 6223 }, 6224 { /* 3 - invalid */ 0 }, 6225 { /* 4 lanes */ 6226 _TH_CELLS_PER_OBM, 1023, 916, 6227 { 1023, 1023, 1023 }, /* port_xoff */ 6228 { 916, 916, 916 }, /* lossy_low_pri */ 6229 { 1012, 1012, 1012 } /* lossy_discard */ 6230 } 6231 }, 6232 /* LOSSLESS Settings*/ 6233 { /* indexed by number of lanes used in the port */ 6234 { /* 0 - invalid */ 0 }, 6235 { /* 1 lane */ 6236 _TH_CELLS_PER_OBM / 4, 45, 157, 6237 { 129, 87, 67 }, /* port_xoff */ 6238 { 100, 76, 56 }, /* lossy_low_pri */ 6239 { 196, 152, 112 } /* lossy_discard */ 6240 }, 6241 { /* 2 lanes */ 6242 _TH_CELLS_PER_OBM / 2, 108, 410, 6243 { 312, 248, 215 }, /* port_xoff */ 6244 { 100, 100, 100 }, /* lossy_low_pri */ 6245 { 196, 196, 196 } /* lossy_discard */ 6246 }, 6247 { /* 3 - invalid */ 0 }, 6248 { /* 4 lanes */ 6249 _TH_CELLS_PER_OBM, 258, 916, 6250 { 682, 572, 517 }, /* port_xoff */ 6251 { 100, 100, 100 }, /* lossy_low_pri */ 6252 { 196, 196, 196 } /* lossy_discard */ 6253 } 6254 } 6255 }; 6256 static const soc_reg_t obm_ctrl_regs[] = { 6257 IDB_OBM0_CONTROLr, IDB_OBM1_CONTROLr, 6258 IDB_OBM2_CONTROLr, IDB_OBM3_CONTROLr, 6259 IDB_OBM4_CONTROLr, IDB_OBM5_CONTROLr, 6260 IDB_OBM6_CONTROLr, IDB_OBM7_CONTROLr 6261 }; 6262 static const soc_reg_t obm_ca_ctrl_regs[] = { 6263 IDB_OBM0_CA_CONTROLr, IDB_OBM1_CA_CONTROLr, 6264 IDB_OBM2_CA_CONTROLr, IDB_OBM3_CA_CONTROLr, 6265 IDB_OBM4_CA_CONTROLr, IDB_OBM5_CA_CONTROLr, 6266 IDB_OBM6_CA_CONTROLr, IDB_OBM7_CA_CONTROLr 6267 }; 6268 static const soc_reg_t obm_thresh_regs[] = { 6269 IDB_OBM0_THRESHOLDr, IDB_OBM1_THRESHOLDr, 6270 IDB_OBM2_THRESHOLDr, IDB_OBM3_THRESHOLDr, 6271 IDB_OBM4_THRESHOLDr, IDB_OBM5_THRESHOLDr, 6272 IDB_OBM6_THRESHOLDr, IDB_OBM7_THRESHOLDr 6273 }; 6274 static const soc_reg_t obm_fc_thresh_regs[] = { 6275 IDB_OBM0_FC_THRESHOLDr, IDB_OBM1_FC_THRESHOLDr, 6276 IDB_OBM2_FC_THRESHOLDr, IDB_OBM3_FC_THRESHOLDr, 6277 IDB_OBM4_FC_THRESHOLDr, IDB_OBM5_FC_THRESHOLDr, 6278 IDB_OBM6_FC_THRESHOLDr, IDB_OBM7_FC_THRESHOLDr 6279 }; 6280 static const soc_reg_t obm_shared_regs[] = { 6281 IDB_OBM0_SHARED_CONFIGr, IDB_OBM1_SHARED_CONFIGr, 6282 IDB_OBM2_SHARED_CONFIGr, IDB_OBM3_SHARED_CONFIGr, 6283 IDB_OBM4_SHARED_CONFIGr, IDB_OBM5_SHARED_CONFIGr, 6284 IDB_OBM6_SHARED_CONFIGr, IDB_OBM7_SHARED_CONFIGr 6285 }; 6286 static const soc_reg_t obm_max_usage_regs[] = { 6287 IDB_OBM0_MAX_USAGE_SELECTr, IDB_OBM1_MAX_USAGE_SELECTr, 6288 IDB_OBM2_MAX_USAGE_SELECTr, IDB_OBM3_MAX_USAGE_SELECTr, 6289 IDB_OBM4_MAX_USAGE_SELECTr, IDB_OBM5_MAX_USAGE_SELECTr, 6290 IDB_OBM6_MAX_USAGE_SELECTr, IDB_OBM7_MAX_USAGE_SELECTr 6291 }; 6292 static const soc_reg_t obm_port_config_regs[] = { 6293 IDB_OBM0_PORT_CONFIGr, IDB_OBM1_PORT_CONFIGr, 6294 IDB_OBM2_PORT_CONFIGr, IDB_OBM3_PORT_CONFIGr, 6295 IDB_OBM4_PORT_CONFIGr, IDB_OBM5_PORT_CONFIGr, 6296 IDB_OBM6_PORT_CONFIGr, IDB_OBM7_PORT_CONFIGr 6297 }; 6298 static const soc_reg_t obm_fc_config_regs[] = { 6299 IDB_OBM0_FLOW_CONTROL_CONFIGr, IDB_OBM1_FLOW_CONTROL_CONFIGr, 6300 IDB_OBM2_FLOW_CONTROL_CONFIGr, IDB_OBM3_FLOW_CONTROL_CONFIGr, 6301 IDB_OBM4_FLOW_CONTROL_CONFIGr, IDB_OBM5_FLOW_CONTROL_CONFIGr, 6302 IDB_OBM6_FLOW_CONTROL_CONFIGr, IDB_OBM7_FLOW_CONTROL_CONFIGr 6303 }; 6304 static const soc_field_t obm_bypass_fields[] = { 6305 PORT0_BYPASS_ENABLEf, PORT1_BYPASS_ENABLEf, 6306 PORT2_BYPASS_ENABLEf, PORT3_BYPASS_ENABLEf 6307 }; 6308 static const soc_field_t obm_oversub_fields[] = { 6309 PORT0_OVERSUB_ENABLEf, PORT1_OVERSUB_ENABLEf, 6310 PORT2_OVERSUB_ENABLEf, PORT3_OVERSUB_ENABLEf 6311 }; 6312 static const soc_mem_t obm_pri_map_mem[][4] = { 6313 {IDB_OBM0_PRI_MAP_PORT0m, IDB_OBM0_PRI_MAP_PORT1m, 6314 IDB_OBM0_PRI_MAP_PORT2m, IDB_OBM0_PRI_MAP_PORT3m 6315 }, 6316 {IDB_OBM1_PRI_MAP_PORT0m, IDB_OBM1_PRI_MAP_PORT1m, 6317 IDB_OBM1_PRI_MAP_PORT2m, IDB_OBM1_PRI_MAP_PORT3m 6318 }, 6319 {IDB_OBM2_PRI_MAP_PORT0m, IDB_OBM2_PRI_MAP_PORT1m, 6320 IDB_OBM2_PRI_MAP_PORT2m, IDB_OBM2_PRI_MAP_PORT3m 6321 }, 6322 {IDB_OBM3_PRI_MAP_PORT0m, IDB_OBM3_PRI_MAP_PORT1m, 6323 IDB_OBM3_PRI_MAP_PORT2m, IDB_OBM3_PRI_MAP_PORT3m 6324 }, 6325 {IDB_OBM4_PRI_MAP_PORT0m, IDB_OBM4_PRI_MAP_PORT1m, 6326 IDB_OBM4_PRI_MAP_PORT2m, IDB_OBM4_PRI_MAP_PORT3m 6327 }, 6328 {IDB_OBM5_PRI_MAP_PORT0m, IDB_OBM5_PRI_MAP_PORT1m, 6329 IDB_OBM5_PRI_MAP_PORT2m, IDB_OBM5_PRI_MAP_PORT3m 6330 }, 6331 {IDB_OBM6_PRI_MAP_PORT0m, IDB_OBM6_PRI_MAP_PORT1m, 6332 IDB_OBM6_PRI_MAP_PORT2m, IDB_OBM6_PRI_MAP_PORT3m 6333 }, 6334 {IDB_OBM7_PRI_MAP_PORT0m, IDB_OBM7_PRI_MAP_PORT1m, 6335 IDB_OBM7_PRI_MAP_PORT2m, IDB_OBM7_PRI_MAP_PORT3m 6336 }, 6337 }; 6338 static const soc_field_t obm_ob_pri_fields[] = { 6339 OFFSET0_OB_PRIORITYf, OFFSET1_OB_PRIORITYf, OFFSET2_OB_PRIORITYf, 6340 OFFSET3_OB_PRIORITYf, OFFSET4_OB_PRIORITYf, OFFSET5_OB_PRIORITYf, 6341 OFFSET6_OB_PRIORITYf, OFFSET7_OB_PRIORITYf, OFFSET8_OB_PRIORITYf, 6342 OFFSET9_OB_PRIORITYf, OFFSET10_OB_PRIORITYf, OFFSET11_OB_PRIORITYf, 6343 OFFSET12_OB_PRIORITYf, OFFSET13_OB_PRIORITYf, OFFSET14_OB_PRIORITYf, 6344 OFFSET15_OB_PRIORITYf 6345 }; 6346 static const int hw_mode_values[SOC_TH_PORT_RATIO_COUNT] = { 6347 0, 1, 1, 1, 3, 5, 4, 6, 2 6348 }; 6349 6350 si = &SOC_INFO(unit); 6351 tdm = SOC_CONTROL(unit)->tdm_info; 6352 6353 if (SOC_IS_TOMAHAWKPLUS(unit)) { 6354 lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 6355 SOC_TH_MMU_LOSSLESS_DEFAULT_DISABLE); 6356 } else { 6357 lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 6358 SOC_TH_MMU_LOSSLESS_DEFAULT_ENABLE); 6359 } 6360 6361 rval_port_cfg = 0; 6362 reg = SOC_REG_UNIQUE_ACC(unit, obm_port_config_regs[0])[0]; 6363 soc_reg_field_set(unit, reg, &rval_port_cfg, PORT_PRIf, 2); 6364 6365 rval_max_usage_cfg = 0; 6366 reg = SOC_REG_UNIQUE_ACC(unit, obm_max_usage_regs[0])[0]; 6367 soc_reg_field_set(unit, reg, &rval_max_usage_cfg, PRIORITY_SELECTf, 2); 6368 6369 sal_memset(entry, 0, sizeof(idb_obm0_pri_map_port0_entry_t)); 6370 mem = SOC_MEM_UNIQUE_ACC(unit, obm_pri_map_mem[0][0])[0]; 6371 6372 count = COUNTOF(obm_ob_pri_fields); 6373 for (i = 0; i < count; i++) { 6374 soc_mem_field32_set(unit, mem, entry, obm_ob_pri_fields[i], 2); 6375 } 6376 6377 SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) { 6378 port = SOC_BLOCK_PORT(unit, block_info_idx); 6379 phy_port_base = PORT_BLOCK_BASE_PORT(port); 6380 pipe = si->port_pipe[port]; 6381 clport = SOC_BLOCK_NUMBER(unit, block_info_idx); 6382 /* obm number is reversed (mirrored) in odd pipe */ 6383 obm = pipe & 1 ? 7 - (clport & 0x7) : clport & 0x7; 6384 6385 /* Set cell assembly mode then toggle reset to send initial credit 6386 * to EP */ 6387 reg = SOC_REG_UNIQUE_ACC(unit, obm_ca_ctrl_regs[obm])[pipe]; 6388 rval0 = 0; 6389 soc_reg_field_set(unit, reg, &rval0, PORT_MODEf, 6390 hw_mode_values[tdm->port_ratio[clport]]); 6391 rval1 = rval0; 6392 soc_reg_field_set(unit, reg, &rval0, PORT0_RESETf, 1); 6393 soc_reg_field_set(unit, reg, &rval0, PORT1_RESETf, 1); 6394 soc_reg_field_set(unit, reg, &rval0, PORT2_RESETf, 1); 6395 soc_reg_field_set(unit, reg, &rval0, PORT3_RESETf, 1); 6396 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval0)); 6397 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval1)); 6398 6399 /* Enable oversub */ 6400 reg = SOC_REG_UNIQUE_ACC(unit, obm_ctrl_regs[obm])[pipe]; 6401 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval0)); 6402 for (lane = 0; lane < _TH_PORTS_PER_PBLK; lane++) { 6403 if (si->port_p2l_mapping[phy_port_base + lane] == -1) { 6404 continue; 6405 } 6406 field = obm_bypass_fields[lane]; 6407 soc_reg_field_set(unit, reg, &rval0, field, 1); 6408 field = obm_oversub_fields[lane]; 6409 soc_reg_field_set(unit, reg, &rval0, field, 1); 6410 } 6411 6412 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval0)); 6413 if (!SOC_PBMP_MEMBER(si->oversub_pbm, port)) { 6414 continue; 6415 } 6416 6417 /* Configure shared config */ 6418 reg = SOC_REG_UNIQUE_ACC(unit, obm_shared_regs[obm])[pipe]; 6419 SOC_IF_ERROR_RETURN 6420 (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64)); 6421 soc_reg64_field32_set(unit, reg, &rval64, DISCARD_THRESHOLDf, 1023); 6422 soc_reg64_field32_set(unit, reg, &rval64, SOP_THRESHOLDf, 1023); 6423 soc_reg64_field32_set(unit, reg, &rval64, SOP_DISCARD_MODEf, 1); 6424 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64)); 6425 6426 if (lossless) { 6427 if (tdm->ovs_ratio_x1000[pipe] >= 1800) { /* ratio >= 1.8 */ 6428 oversub_ratio_idx = 2; 6429 } else if (tdm->ovs_ratio_x1000[pipe] >= 1500) { /* ratio >= 1.5 */ 6430 oversub_ratio_idx = 1; 6431 } else { 6432 oversub_ratio_idx = 0; 6433 } 6434 6435 for (lane = 0; lane < _TH_PORTS_PER_PBLK; lane++) { 6436 port = si->port_p2l_mapping[phy_port_base + lane]; 6437 if (port == -1) { 6438 continue; 6439 } 6440 num_lanes = si->port_num_lanes[port]; 6441 6442 /* Configure threshold */ 6443 reg = SOC_REG_UNIQUE_ACC(unit, obm_thresh_regs[obm])[pipe]; 6444 SOC_IF_ERROR_RETURN 6445 (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64)); 6446 fval = obm_settings[1][num_lanes].discard_limit; 6447 soc_reg64_field32_set(unit, reg, &rval64, DISCARD_LIMITf, fval); 6448 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_DISCARDf, 6449 1023); 6450 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_DISCARDf, 6451 1023); 6452 fval = obm_settings[1][num_lanes].lossy_low_pri[oversub_ratio_idx]; 6453 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_LOW_PRIf, fval); 6454 fval = obm_settings[1][num_lanes].lossy_discard[oversub_ratio_idx]; 6455 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_DISCARDf, fval); 6456 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_MINf, 0); 6457 SOC_IF_ERROR_RETURN 6458 (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64)); 6459 6460 /* Configure flow control threshold */ 6461 reg = SOC_REG_UNIQUE_ACC(unit, obm_fc_thresh_regs[obm])[pipe]; 6462 SOC_IF_ERROR_RETURN 6463 (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64)); 6464 fval = obm_settings[1][num_lanes].port_xoff[oversub_ratio_idx]; 6465 soc_reg64_field32_set(unit, reg, &rval64, PORT_XOFFf, fval); 6466 soc_reg64_field32_set(unit, reg, &rval64, PORT_XONf, fval - 10); 6467 fval = obm_settings[1][num_lanes].lossless_xoff; 6468 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XOFFf, 6469 fval); 6470 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XOFFf, 6471 fval); 6472 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XONf, 6473 fval - 10); 6474 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XONf, 6475 fval - 10); 6476 SOC_IF_ERROR_RETURN 6477 (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64)); 6478 6479 /* Configure flow control config */ 6480 reg = SOC_REG_UNIQUE_ACC(unit, obm_fc_config_regs[obm])[pipe]; 6481 SOC_IF_ERROR_RETURN 6482 (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64)); 6483 soc_reg64_field32_set(unit, reg, &rval64, PORT_FC_ENf, 1); 6484 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_FC_ENf, 1); 6485 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_FC_ENf, 1); 6486 soc_reg64_field32_set(unit, reg, &rval64, 6487 LOSSLESS0_PRIORITY_PROFILEf, 0xff); 6488 soc_reg64_field32_set(unit, reg, &rval64, 6489 LOSSLESS1_PRIORITY_PROFILEf, 0xff); 6490 SOC_IF_ERROR_RETURN 6491 (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64)); 6492 6493 /* OBM Port config */ 6494 reg = SOC_REG_UNIQUE_ACC(unit, obm_port_config_regs[obm])[pipe]; 6495 SOC_IF_ERROR_RETURN 6496 (soc_reg32_set(unit, reg, REG_PORT_ANY, lane, 6497 rval_port_cfg)); 6498 6499 mem = SOC_MEM_UNIQUE_ACC 6500 (unit, obm_pri_map_mem[obm][lane])[pipe]; 6501 SOC_IF_ERROR_RETURN 6502 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, entry)); 6503 } 6504 6505 reg = SOC_REG_UNIQUE_ACC(unit, obm_max_usage_regs[obm])[pipe]; 6506 SOC_IF_ERROR_RETURN 6507 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, 6508 rval_max_usage_cfg)); 6509 6510 } else { /* lossy */ 6511 for (lane = 0; lane < _TH_PORTS_PER_PBLK; lane++) { 6512 port = si->port_p2l_mapping[phy_port_base + lane]; 6513 if (port == -1) { 6514 continue; 6515 } 6516 num_lanes = si->port_num_lanes[port]; 6517 6518 /* Configure threshold */ 6519 reg = SOC_REG_UNIQUE_ACC(unit, obm_thresh_regs[obm])[pipe]; 6520 SOC_IF_ERROR_RETURN 6521 (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64)); 6522 fval = obm_settings[0][num_lanes].discard_limit; 6523 soc_reg64_field32_set(unit, reg, &rval64, DISCARD_LIMITf, fval); 6524 /* same as DISCARD_LIMIT setting */ 6525 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_DISCARDf, fval); 6526 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_DISCARDf, 6527 1023); 6528 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_DISCARDf, 6529 1023); 6530 fval = obm_settings[0][num_lanes].lossy_only_lossy_low_pri; 6531 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_LOW_PRIf, fval); 6532 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_MINf, 0); 6533 SOC_IF_ERROR_RETURN 6534 (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64)); 6535 6536 /* Configure flow control threshold */ 6537 reg = SOC_REG_UNIQUE_ACC(unit, obm_fc_thresh_regs[obm])[pipe]; 6538 SOC_IF_ERROR_RETURN 6539 (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64)); 6540 soc_reg64_field32_set(unit, reg, &rval64, PORT_XOFFf, 1023); 6541 soc_reg64_field32_set(unit, reg, &rval64, PORT_XONf, 1023); 6542 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XOFFf, 6543 1023); 6544 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XOFFf, 6545 1023); 6546 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XONf, 1023); 6547 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XONf, 1023); 6548 SOC_IF_ERROR_RETURN 6549 (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64)); 6550 } 6551 } 6552 } 6553 6554 /* Toggle cpu port cell assembly reset to send initial credit to EP */ 6555 reg = IDB_CA_CPU_CONTROLr; 6556 rval0 = 0; 6557 soc_reg_field_set(unit, reg, &rval0, PORT_RESETf, 1); 6558 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval0)); 6559 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, 0)); 6560 6561 /* Toggle loopback port cell assembly reset to send initial credit to EP */ 6562 reg = IDB_CA_LPBK_CONTROLr; 6563 rval0 = 0; 6564 soc_reg_field_set(unit, reg, &rval0, PORT_RESETf, 1); 6565 PBMP_LB_ITER(unit, port) { 6566 reg = SOC_REG_UNIQUE_ACC(unit, IDB_CA_LPBK_CONTROLr) 6567 [si->port_pipe[port]]; 6568 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval0)); 6569 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, 0)); 6570 } 6571 6572 return SOC_E_NONE; 6573 } 6574 6575 extern int 6576 (*_phy_tsce_firmware_set_helper[SOC_MAX_NUM_DEVICES])(int, int, uint8 *, int); 6577 extern int 6578 (*_phy_tscf_firmware_set_helper[SOC_MAX_NUM_DEVICES])(int, int, uint8 *, int); 6579 6580 STATIC int 6581 _soc_tomahawk_tscx_firmware_set(int unit, int port, uint8 *array, int datalen) 6582 { 6583 soc_mem_t mem = IS_CL_PORT(unit, port) ? 6584 CLPORT_WC_UCMEM_DATAm : XLPORT_WC_UCMEM_DATAm; 6585 soc_reg_t reg = IS_CL_PORT(unit, port) ? 6586 CLPORT_WC_UCMEM_CTRLr : XLPORT_WC_UCMEM_CTRLr; 6587 6588 return soc_warpcore_firmware_set(unit, port, array, datalen, 0, mem, reg); 6589 } 6590 6591 #define TSC_REG_ADDR_TSCID_SET(_phy_reg, _phyad) \ 6592 ((_phy_reg) |= ((_phyad) & 0x1f) << 19) 6593 6594 STATIC int 6595 _soc_tomahawk_mdio_addr_to_port(uint32 phy_addr) 6596 { 6597 int bus, offset; 6598 6599 /* Must be internal MDIO address */ 6600 if ((phy_addr & 0x80) == 0) { 6601 return 0; 6602 } 6603 6604 /* 6605 * Internal phy address: 6606 * bus 0 phy 1 to 24 are mapped to Physical port 1 to 24 6607 * bus 1 phy 1 to 16 are mapped to Physical port 25 to 40 6608 * bus 2 phy 1 to 24 are mapped to Physical port 41 to 64 6609 * bus 3 phy 1 to 24 are mapped to Physical port 85 to 88 6610 * bus 4 phy 1 to 16 are mapped to Physical port 89 to 104 6611 * bus 5 phy 1 to 24 are mapped to Physical port 105 to 128 6612 * bus 6 phy 1 is mapped to Physical port 129 and 6613 * phy 3 is mapped to Physical port 131 6614 */ 6615 bus = PHY_ID_BUS_NUM(phy_addr); 6616 if (bus > 6) { 6617 return 0; 6618 } 6619 switch (bus) { 6620 case 0: offset = 0; 6621 break; 6622 case 1: offset = 24; 6623 break; 6624 case 2: offset = 40; 6625 break; 6626 case 3: offset = 64; 6627 break; 6628 case 4: offset = 88; 6629 break; 6630 case 5: offset = 104; 6631 break; 6632 case 6: offset = 128; 6633 if ((phy_addr & 0x1f) == 2 || (phy_addr & 0x1f) > 3) { 6634 return 0; 6635 } 6636 break; 6637 default: 6638 return 0; 6639 } 6640 6641 return (phy_addr & 0x1f) + offset; 6642 } 6643 6644 STATIC int 6645 _soc_tomahawk_tscx_reg_read(int unit, uint32 phy_addr, 6646 uint32 phy_reg, uint32 *phy_data) 6647 { 6648 int rv, blk, port; 6649 int phy_port = _soc_tomahawk_mdio_addr_to_port(phy_addr); 6650 6651 #ifdef BCM_TOMAHAWK2_SUPPORT 6652 if (SOC_IS_TOMAHAWK2(unit)) { 6653 phy_port = soc_tomahawk2_mdio_addr_to_port(phy_addr); 6654 } 6655 #endif 6656 6657 port = SOC_INFO(unit).port_p2l_mapping[phy_port]; 6658 blk = SOC_PORT_BLOCK(unit, phy_port); 6659 LOG_INFO(BSL_LS_SOC_MII, 6660 (BSL_META_U(unit, 6661 "soc_tomahawk_tscx_reg_read[%d]: %d/%d/%d/%d\n"), 6662 unit, phy_addr, phy_port, port, blk)); 6663 TSC_REG_ADDR_TSCID_SET(phy_reg, phy_addr); 6664 rv = soc_sbus_tsc_reg_read(unit, port, blk, phy_addr, 6665 phy_reg, phy_data); 6666 return rv; 6667 } 6668 6669 STATIC int 6670 _soc_tomahawk_tscx_reg_write(int unit, uint32 phy_addr, 6671 uint32 phy_reg, uint32 phy_data) 6672 { 6673 int rv, blk, port; 6674 int phy_port = _soc_tomahawk_mdio_addr_to_port(phy_addr); 6675 6676 #ifdef BCM_TOMAHAWK2_SUPPORT 6677 if (SOC_IS_TOMAHAWK2(unit)) { 6678 phy_port = soc_tomahawk2_mdio_addr_to_port(phy_addr); 6679 } 6680 #endif 6681 6682 port = SOC_INFO(unit).port_p2l_mapping[phy_port]; 6683 blk = SOC_PORT_BLOCK(unit, phy_port); 6684 LOG_INFO(BSL_LS_SOC_MII, 6685 (BSL_META_U(unit, 6686 "soc_tomahawk_tscx_reg_write[%d]: %d/%d/%d/%d\n"), 6687 unit, phy_addr, phy_port, port, blk)); 6688 TSC_REG_ADDR_TSCID_SET(phy_reg, phy_addr); 6689 rv = soc_sbus_tsc_reg_write(unit, port, blk, phy_addr, 6690 phy_reg, phy_data); 6691 return rv; 6692 } 6693 6694 STATIC int 6695 _soc_th_ledup_init(int unit) 6696 { 6697 uint32 rval = 0; 6698 int ix, pval1, pval2, pval_size; 6699 6700 typedef struct led_remap_s { 6701 uint32 reg_addr; 6702 uint32 port0; 6703 uint32 port1; 6704 uint32 port2; 6705 uint32 port3; 6706 } led_remap_t; 6707 6708 led_remap_t led0_remap[] = { 6709 { CMIC_LEDUP0_PORT_ORDER_REMAP_0_3r, 6710 REMAP_PORT_0f, REMAP_PORT_1f, REMAP_PORT_2f, REMAP_PORT_3f }, 6711 { CMIC_LEDUP0_PORT_ORDER_REMAP_4_7r, 6712 REMAP_PORT_4f, REMAP_PORT_5f, REMAP_PORT_6f, REMAP_PORT_7f }, 6713 { CMIC_LEDUP0_PORT_ORDER_REMAP_8_11r, 6714 REMAP_PORT_8f, REMAP_PORT_9f, REMAP_PORT_10f, REMAP_PORT_11f }, 6715 { CMIC_LEDUP0_PORT_ORDER_REMAP_12_15r, 6716 REMAP_PORT_12f, REMAP_PORT_13f, REMAP_PORT_14f, REMAP_PORT_15f }, 6717 { CMIC_LEDUP0_PORT_ORDER_REMAP_16_19r, 6718 REMAP_PORT_16f, REMAP_PORT_17f, REMAP_PORT_18f, REMAP_PORT_19f }, 6719 { CMIC_LEDUP0_PORT_ORDER_REMAP_20_23r, 6720 REMAP_PORT_20f, REMAP_PORT_21f, REMAP_PORT_22f, REMAP_PORT_23f }, 6721 { CMIC_LEDUP0_PORT_ORDER_REMAP_24_27r, 6722 REMAP_PORT_24f, REMAP_PORT_25f, REMAP_PORT_26f, REMAP_PORT_27f }, 6723 { CMIC_LEDUP0_PORT_ORDER_REMAP_28_31r, 6724 REMAP_PORT_28f, REMAP_PORT_29f, REMAP_PORT_30f, REMAP_PORT_31f }, 6725 { CMIC_LEDUP0_PORT_ORDER_REMAP_32_35r, 6726 REMAP_PORT_32f, REMAP_PORT_33f, REMAP_PORT_34f, REMAP_PORT_35f }, 6727 { CMIC_LEDUP0_PORT_ORDER_REMAP_36_39r, 6728 REMAP_PORT_36f, REMAP_PORT_37f, REMAP_PORT_38f, REMAP_PORT_39f }, 6729 { CMIC_LEDUP0_PORT_ORDER_REMAP_40_43r, 6730 REMAP_PORT_40f, REMAP_PORT_41f, REMAP_PORT_42f, REMAP_PORT_43f }, 6731 { CMIC_LEDUP0_PORT_ORDER_REMAP_44_47r, 6732 REMAP_PORT_44f, REMAP_PORT_45f, REMAP_PORT_46f, REMAP_PORT_47f }, 6733 { CMIC_LEDUP0_PORT_ORDER_REMAP_48_51r, 6734 REMAP_PORT_48f, REMAP_PORT_49f, REMAP_PORT_50f, REMAP_PORT_51f }, 6735 { CMIC_LEDUP0_PORT_ORDER_REMAP_52_55r, 6736 REMAP_PORT_52f, REMAP_PORT_53f, REMAP_PORT_54f, REMAP_PORT_55f }, 6737 { CMIC_LEDUP0_PORT_ORDER_REMAP_56_59r, 6738 REMAP_PORT_56f, REMAP_PORT_57f, REMAP_PORT_58f, REMAP_PORT_59f }, 6739 { CMIC_LEDUP0_PORT_ORDER_REMAP_60_63r, 6740 REMAP_PORT_60f, REMAP_PORT_61f, REMAP_PORT_62f, REMAP_PORT_63f } 6741 }; 6742 6743 led_remap_t led1_remap[] = { 6744 { CMIC_LEDUP1_PORT_ORDER_REMAP_0_3r, 6745 REMAP_PORT_0f, REMAP_PORT_1f, REMAP_PORT_2f, REMAP_PORT_3f }, 6746 { CMIC_LEDUP1_PORT_ORDER_REMAP_4_7r, 6747 REMAP_PORT_4f, REMAP_PORT_5f, REMAP_PORT_6f, REMAP_PORT_7f }, 6748 { CMIC_LEDUP1_PORT_ORDER_REMAP_8_11r, 6749 REMAP_PORT_8f, REMAP_PORT_9f, REMAP_PORT_10f, REMAP_PORT_11f }, 6750 { CMIC_LEDUP1_PORT_ORDER_REMAP_12_15r, 6751 REMAP_PORT_12f, REMAP_PORT_13f, REMAP_PORT_14f, REMAP_PORT_15f }, 6752 { CMIC_LEDUP1_PORT_ORDER_REMAP_16_19r, 6753 REMAP_PORT_16f, REMAP_PORT_17f, REMAP_PORT_18f, REMAP_PORT_19f }, 6754 { CMIC_LEDUP1_PORT_ORDER_REMAP_20_23r, 6755 REMAP_PORT_20f, REMAP_PORT_21f, REMAP_PORT_22f, REMAP_PORT_23f }, 6756 { CMIC_LEDUP1_PORT_ORDER_REMAP_24_27r, 6757 REMAP_PORT_24f, REMAP_PORT_25f, REMAP_PORT_26f, REMAP_PORT_27f }, 6758 { CMIC_LEDUP1_PORT_ORDER_REMAP_28_31r, 6759 REMAP_PORT_28f, REMAP_PORT_29f, REMAP_PORT_30f, REMAP_PORT_31f }, 6760 { CMIC_LEDUP1_PORT_ORDER_REMAP_32_35r, 6761 REMAP_PORT_32f, REMAP_PORT_33f, REMAP_PORT_34f, REMAP_PORT_35f }, 6762 { CMIC_LEDUP1_PORT_ORDER_REMAP_36_39r, 6763 REMAP_PORT_36f, REMAP_PORT_37f, REMAP_PORT_38f, REMAP_PORT_39f }, 6764 { CMIC_LEDUP1_PORT_ORDER_REMAP_40_43r, 6765 REMAP_PORT_40f, REMAP_PORT_41f, REMAP_PORT_42f, REMAP_PORT_43f }, 6766 { CMIC_LEDUP1_PORT_ORDER_REMAP_44_47r, 6767 REMAP_PORT_44f, REMAP_PORT_45f, REMAP_PORT_46f, REMAP_PORT_47f }, 6768 { CMIC_LEDUP1_PORT_ORDER_REMAP_48_51r, 6769 REMAP_PORT_48f, REMAP_PORT_49f, REMAP_PORT_50f, REMAP_PORT_51f }, 6770 { CMIC_LEDUP1_PORT_ORDER_REMAP_52_55r, 6771 REMAP_PORT_52f, REMAP_PORT_53f, REMAP_PORT_54f, REMAP_PORT_55f }, 6772 { CMIC_LEDUP1_PORT_ORDER_REMAP_56_59r, 6773 REMAP_PORT_56f, REMAP_PORT_57f, REMAP_PORT_58f, REMAP_PORT_59f }, 6774 { CMIC_LEDUP1_PORT_ORDER_REMAP_60_63r, 6775 REMAP_PORT_60f, REMAP_PORT_61f, REMAP_PORT_62f, REMAP_PORT_63f } 6776 }; 6777 6778 led_remap_t led2_remap[] = { 6779 { CMIC_LEDUP2_PORT_ORDER_REMAP_0_3r, 6780 REMAP_PORT_0f, REMAP_PORT_1f, REMAP_PORT_2f, REMAP_PORT_3f }, 6781 { CMIC_LEDUP2_PORT_ORDER_REMAP_4_7r, 6782 REMAP_PORT_4f, REMAP_PORT_5f, REMAP_PORT_6f, REMAP_PORT_7f }, 6783 { CMIC_LEDUP2_PORT_ORDER_REMAP_8_11r, 6784 REMAP_PORT_8f, REMAP_PORT_9f, REMAP_PORT_10f, REMAP_PORT_11f }, 6785 { CMIC_LEDUP2_PORT_ORDER_REMAP_12_15r, 6786 REMAP_PORT_12f, REMAP_PORT_13f, REMAP_PORT_14f, REMAP_PORT_15f }, 6787 { CMIC_LEDUP2_PORT_ORDER_REMAP_16_19r, 6788 REMAP_PORT_16f, REMAP_PORT_17f, REMAP_PORT_18f, REMAP_PORT_19f }, 6789 { CMIC_LEDUP2_PORT_ORDER_REMAP_20_23r, 6790 REMAP_PORT_20f, REMAP_PORT_21f, REMAP_PORT_22f, REMAP_PORT_23f }, 6791 { CMIC_LEDUP2_PORT_ORDER_REMAP_24_27r, 6792 REMAP_PORT_24f, REMAP_PORT_25f, REMAP_PORT_26f, REMAP_PORT_27f }, 6793 { CMIC_LEDUP2_PORT_ORDER_REMAP_28_31r, 6794 REMAP_PORT_28f, REMAP_PORT_29f, REMAP_PORT_30f, REMAP_PORT_31f }, 6795 { CMIC_LEDUP2_PORT_ORDER_REMAP_32_35r, 6796 REMAP_PORT_32f, REMAP_PORT_33f, REMAP_PORT_34f, REMAP_PORT_35f }, 6797 { CMIC_LEDUP2_PORT_ORDER_REMAP_36_39r, 6798 REMAP_PORT_36f, REMAP_PORT_37f, REMAP_PORT_38f, REMAP_PORT_39f }, 6799 { CMIC_LEDUP2_PORT_ORDER_REMAP_40_43r, 6800 REMAP_PORT_40f, REMAP_PORT_41f, REMAP_PORT_42f, REMAP_PORT_43f }, 6801 { CMIC_LEDUP2_PORT_ORDER_REMAP_44_47r, 6802 REMAP_PORT_44f, REMAP_PORT_45f, REMAP_PORT_46f, REMAP_PORT_47f }, 6803 { CMIC_LEDUP2_PORT_ORDER_REMAP_48_51r, 6804 REMAP_PORT_48f, REMAP_PORT_49f, REMAP_PORT_50f, REMAP_PORT_51f }, 6805 { CMIC_LEDUP2_PORT_ORDER_REMAP_52_55r, 6806 REMAP_PORT_52f, REMAP_PORT_53f, REMAP_PORT_54f, REMAP_PORT_55f }, 6807 { CMIC_LEDUP2_PORT_ORDER_REMAP_56_59r, 6808 REMAP_PORT_56f, REMAP_PORT_57f, REMAP_PORT_58f, REMAP_PORT_59f }, 6809 { CMIC_LEDUP2_PORT_ORDER_REMAP_60_63r, 6810 REMAP_PORT_60f, REMAP_PORT_61f, REMAP_PORT_62f, REMAP_PORT_63f } 6811 }; 6812 6813 6814 pval_size = COUNTOF(led0_remap); 6815 pval2 = (pval_size >> 1) - 1; 6816 6817 /* Configure LED-0 remap register settings. 6818 * LED-0 chain provides port status for tile0 (ports 1-32) 6819 * and tile 3 (ports 97-128). 6820 * Scan chain order: 32, 31, ...., 1, 128, 127, ...., 97 6821 * LED port status for port 32 arrives first at the CMIC block and 6822 * port 97's LED status arrives last. 6823 */ 6824 for (ix = 0; ix < pval_size ; ix++) { 6825 if (ix == pval_size >> 1) { 6826 pval2 = pval_size -1; 6827 } 6828 6829 pval1 = ix << 2; 6830 6831 rval = 0; 6832 soc_reg_field_set(unit, led0_remap[pval2].reg_addr, &rval, 6833 led0_remap[pval2].port3, pval1); 6834 soc_reg_field_set(unit, led0_remap[pval2].reg_addr, &rval, 6835 led0_remap[pval2].port2, pval1 + 1); 6836 soc_reg_field_set(unit, led0_remap[pval2].reg_addr, &rval, 6837 led0_remap[pval2].port1, pval1 + 2); 6838 soc_reg_field_set(unit, led0_remap[pval2].reg_addr, &rval, 6839 led0_remap[pval2].port0, pval1 + 3); 6840 soc_pci_write(unit, soc_reg_addr(unit, 6841 led0_remap[pval2].reg_addr, REG_PORT_ANY, 0), rval); 6842 pval2--; 6843 } 6844 6845 /* Configure LED-1 remap register settings. 6846 * LED-1 chain provides port status for tile1 (ports 33-64) 6847 * and tile 2 (ports 65-96). 6848 * Scan chain order: 33, 34, 35, ...., 96 6849 * LED port status for port 33 arrives first at the CMIC block and 6850 * port 96's LED status arrives last. 6851 */ 6852 for (ix = 0; ix < pval_size ; ix++) { 6853 pval1 = ix << 2; 6854 6855 rval = 0; 6856 soc_reg_field_set(unit, led1_remap[ix].reg_addr, &rval, 6857 led1_remap[ix].port3, pval1); 6858 soc_reg_field_set(unit, led1_remap[ix].reg_addr, &rval, 6859 led1_remap[ix].port2, pval1 + 1); 6860 soc_reg_field_set(unit, led1_remap[ix].reg_addr, &rval, 6861 led1_remap[ix].port1, pval1 + 2); 6862 soc_reg_field_set(unit, led1_remap[ix].reg_addr, &rval, 6863 led1_remap[ix].port0, pval1 + 3); 6864 soc_pci_write(unit, soc_reg_addr(unit, 6865 led1_remap[ix].reg_addr, REG_PORT_ANY, 0), rval); 6866 } 6867 6868 /* Configure LED-2 remap register settings. 6869 * LED-2 chain provides port status for management ports (129-132). 6870 * Scan chain port order is - 132 (unused), 131, 130 (unused), 129. 6871 * Unused remapping port registers are programmed to a larger value. 6872 */ 6873 for (ix = 0; ix < pval_size ; ix++) { 6874 rval = 0; 6875 soc_reg_field_set(unit, led2_remap[ix].reg_addr, &rval, 6876 led2_remap[ix].port0, 0x3F); 6877 soc_reg_field_set(unit, led2_remap[ix].reg_addr, &rval, 6878 led2_remap[ix].port1, 0x3F); 6879 soc_reg_field_set(unit, led2_remap[ix].reg_addr, &rval, 6880 led2_remap[ix].port2, 0x3F); 6881 soc_reg_field_set(unit, led2_remap[ix].reg_addr, &rval, 6882 led2_remap[ix].port3, 0x3F); 6883 6884 if (ix == 0) { 6885 soc_reg_field_set(unit, led2_remap[ix].reg_addr, &rval, 6886 led2_remap[ix].port1, 1); 6887 soc_reg_field_set(unit, led2_remap[ix].reg_addr, &rval, 6888 led2_remap[ix].port3, 0); 6889 } 6890 6891 soc_pci_write(unit, soc_reg_addr(unit, led2_remap[ix].reg_addr, 6892 REG_PORT_ANY, 0), rval); 6893 } 6894 6895 /* initialize the LED processors data ram */ 6896 rval = 0; 6897 for (ix = 0; ix < 256; ix++) { 6898 WRITE_CMIC_LEDUP0_DATA_RAMr(unit,ix, rval); 6899 WRITE_CMIC_LEDUP1_DATA_RAMr(unit,ix, rval); 6900 soc_pci_write(unit, 6901 soc_reg_addr(unit, CMIC_LEDUP2_DATA_RAMr, REG_PORT_ANY, ix), 6902 rval); 6903 } 6904 6905 return SOC_E_NONE; 6906 } 6907 6908 static const soc_reg_t pvtmon_result_reg[] = { 6909 TOP_PVTMON_RESULT_0r, TOP_PVTMON_RESULT_1r, 6910 TOP_PVTMON_RESULT_2r, TOP_PVTMON_RESULT_3r, 6911 TOP_PVTMON_RESULT_4r, TOP_PVTMON_RESULT_5r, 6912 TOP_PVTMON_RESULT_6r, TOP_PVTMON_RESULT_7r 6913 }; 6914 6915 STATIC int 6916 soc_th_port_config_validate(int unit) 6917 { 6918 int encap, ovs, lport, blk; 6919 int port_sister_speed[4] = {-1, -1, -1, -1}; 6920 int port_status[4] = {0}; 6921 int port_base, port_base_speed = 0; 6922 soc_info_t *si = &SOC_INFO(unit); 6923 int mixed_25_50_en = 0; 6924 int i = 0, idx = 0; 6925 6926 ovs = si->oversub_mode; 6927 mixed_25_50_en = si->os_mixed_sister_25_50_enable; 6928 6929 if (!ovs) { 6930 return SOC_E_NONE; 6931 } 6932 6933 for (blk = 0; blk < SOC_MAX_NUM_BLKS; blk++) { 6934 if (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_CLPORT) { 6935 encap = SOC_ENCAP_COUNT; 6936 i = 0; 6937 for (idx = 0; idx < 4; idx++) { 6938 port_sister_speed[idx] = -1; 6939 port_status[idx] = 0; 6940 } 6941 6942 SOC_PBMP_ITER(si->block_bitmap[blk], lport) { 6943 if (encap == SOC_ENCAP_COUNT) { 6944 encap = IS_HG_PORT(unit, lport) ? 6945 SOC_ENCAP_HIGIG2 : SOC_ENCAP_IEEE; 6946 port_base = lport; 6947 port_base_speed = si->port_speed_max[port_base]; 6948 ovs = SOC_PBMP_MEMBER(si->oversub_pbm, port_base) ? 1 : 0; 6949 } 6950 6951 port_sister_speed[i] = si->port_speed_max[lport]; 6952 port_status[i] = (!SOC_PBMP_MEMBER(si->all.disabled_bitmap, lport)) ? 1 : 0; 6953 i++; 6954 } 6955 6956 /* 6957 * The port config was restricted. 6958 * portmap_1.0=1:100 6959 * portmap_2.0=2:25:i 6960 * portmap_3.0=3:50:i 6961 * portmap_4.0=4:25:i 6962 */ 6963 if (((port_base_speed == 100000) && (port_sister_speed[1] == 25000) && 6964 (port_sister_speed[2] == 50000) && (port_sister_speed[3] == 25000) && 6965 (port_status[0]) && (!port_status[1]) && (!port_status[2]) && (!port_status[3])) || 6966 ((port_sister_speed[0] == 25000) && (port_sister_speed[1] == 25000) && 6967 (port_sister_speed[2] == 50000) && (port_status[0]) && (port_status[1]) && 6968 (port_status[2]))) { 6969 LOG_ERROR(BSL_LS_SOC_PORT, 6970 (BSL_META_U(unit, 6971 "Unsupported port config in oversub mode on port macro %d\n"), 6972 SOC_BLOCK_NUMBER(unit, blk))); 6973 return SOC_E_CONFIG; 6974 } 6975 if (!mixed_25_50_en && 6976 (((port_sister_speed[0] == 25000) && 6977 (port_sister_speed[2] == 50000) && 6978 (port_status[0]) && (port_status[2])) || 6979 ((port_sister_speed[0] == 50000) && 6980 (port_sister_speed[2] == 25000) && 6981 (port_status[0]) && port_status[2]))) { 6982 LOG_ERROR(BSL_LS_SOC_PORT, 6983 (BSL_META_U(unit, 6984 "Unsupported port config in mixed mode on port macro %d\n"), 6985 SOC_BLOCK_NUMBER(unit, blk))); 6986 return SOC_E_CONFIG; 6987 } 6988 } 6989 } 6990 6991 return SOC_E_NONE; 6992 } 6993 6994 STATIC int 6995 _soc_tomahawk_misc_init(int unit) 6996 { 6997 #ifdef BCM_TOMAHAWKX_SUPPORT 6998 static int rtag7_field_width[] = { 16, 16, 4, 16, 8, 8, 16, 16 }; 6999 soc_mem_t mem; 7000 soc_reg_t reg; 7001 uint32 rval, rval1, fval; 7002 uint64 rval64; 7003 int rv, pipe = 0; 7004 soc_pbmp_t pbmp; 7005 uint8 rev_id; 7006 uint16 dev_id; 7007 int port_chk, num_port = 136; 7008 int port, phy_port_base, lport; 7009 _soc_tomahawk_tdm_t *tdm; 7010 uint32 entry[SOC_MAX_MEM_WORDS]; 7011 int block_info_idx, parity_enable; 7012 int clport, lane, mode, class, index; 7013 int count, sub_sel, offset; 7014 int freq, target_freq, divisor, dividend, delay; 7015 soc_control_t *soc = SOC_CONTROL(unit); 7016 soc_info_t *si = &SOC_INFO(unit); 7017 int ecmp_mode = 0; 7018 int fabric_port_enable = 1; 7019 static soc_field_t port_fields[_TH_PORTS_PER_PBLK] = { 7020 PORT0f, PORT1f, PORT2f, PORT3f 7021 }; 7022 static const int mode_encodings[SOC_TH_PORT_RATIO_COUNT] = { 7023 4, 3, 3, 3, 2, 2, 1, 1, 0 7024 }; 7025 int phy_port_mgmt0, phy_port_mgmt1; 7026 #if defined(BCM_TOMAHAWK2_SUPPORT) 7027 egr_mmu_cell_credit_entry_t credit_entry; 7028 char *board_name; 7029 #endif 7030 7031 soc_cm_get_id(unit, &dev_id, &rev_id); 7032 7033 /* Stop the mem scan task before all of the parity init takes place */ 7034 SOC_IF_ERROR_RETURN(soc_generic_ser_mem_scan_stop(unit)); 7035 SOC_IF_ERROR_RETURN(soc_generic_sram_mem_scan_stop(unit)); 7036 7037 /* Prevent ASF from accessing phy */ 7038 SOC_IF_ERROR_RETURN(soc_th_asf_deinit(unit)); 7039 7040 parity_enable = soc_property_get(unit, spn_PARITY_ENABLE, TRUE); 7041 if (parity_enable) { 7042 if ((!SAL_BOOT_SIMULATION || SAL_BOOT_QUICKTURN) && 7043 !SOC_WARM_BOOT(unit)) { 7044 7045 /* Initialize PORT MIB counter */ 7046 rval = 0; 7047 SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) { 7048 port = SOC_BLOCK_PORT(unit, block_info_idx); 7049 soc_reg_field_set(unit, CLPORT_MIB_RESETr, &rval, CLR_CNTf, 0xf); 7050 SOC_IF_ERROR_RETURN(WRITE_CLPORT_MIB_RESETr(unit, port, rval)); 7051 SOC_IF_ERROR_RETURN(WRITE_CLPORT_MIB_RESETr(unit, port, 0)); 7052 } 7053 rval = 0; 7054 SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_XLPORT) { 7055 port = SOC_BLOCK_PORT(unit, block_info_idx); 7056 soc_reg_field_set(unit, XLPORT_MIB_RESETr, &rval, CLR_CNTf, 0xf); 7057 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MIB_RESETr(unit, port, rval)); 7058 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MIB_RESETr(unit, port, 0)); 7059 } 7060 /* Certain mems/regs need to be cleared before enabling SER */ 7061 if (SOC_IS_TOMAHAWK(unit)) { 7062 SOC_IF_ERROR_RETURN(soc_tomahawk_clear_mmu_memory(unit)); 7063 } 7064 #ifdef BCM_TOMAHAWK2_SUPPORT 7065 else if (SOC_IS_TOMAHAWK2(unit)) { 7066 SOC_IF_ERROR_RETURN(soc_tomahawk2_clear_mmu_memory(unit)); 7067 } 7068 #endif 7069 } 7070 7071 /* Check the whether the alpm tables use cache to recover*/ 7072 soc_ser_alpm_cache_check(unit); 7073 7074 /* Enable logging of SER events */ 7075 soc_ser_log_init(unit, NULL, 0); 7076 7077 /* Enable l2_mgmt interrupt */ 7078 SOC_IF_ERROR_RETURN 7079 (soc_reg_field32_modify(unit, L2_MGMT_INTR_MASKr, REG_PORT_ANY, 7080 SER_FIFO_NOT_EMPTYf, 1)); 7081 #ifdef BCM_CMICM_SUPPORT 7082 if (soc_feature(unit, soc_feature_cmicm)) { 7083 (void)soc_cmicm_intr3_enable(unit, 0x2); /* L2_MGMT_TO_CMIC_INTR bit 1 */ 7084 } 7085 #endif 7086 #ifdef BCM_TOMAHAWK2_SUPPORT 7087 if (SOC_IS_TOMAHAWK2(unit)) { 7088 SOC_IF_ERROR_RETURN(soc_tomahawk2_clear_enabled_port_data(unit)); 7089 } 7090 #endif 7091 SOC_IF_ERROR_RETURN(soc_tomahawk_tcam_ser_init(unit)); 7092 7093 SOC_IF_ERROR_RETURN(soc_tomahawk_ser_enable_all(unit, TRUE)); 7094 7095 soc_tomahawk_ser_register(unit); 7096 #if defined(SER_TR_TEST_SUPPORT) 7097 /*Initialize chip-specific functions for SER testing*/ 7098 soc_th_ser_test_register(unit); 7099 #endif /*defined(SER_TR_TEST_SUPPORT*/ 7100 } 7101 7102 if (!SOC_IS_RELOADING(unit) && !SOC_WARM_BOOT(unit)) { 7103 #ifdef BCM_TOMAHAWK2_SUPPORT 7104 if (SOC_IS_TOMAHAWK2(unit)) { 7105 SOC_IF_ERROR_RETURN(soc_tomahawk2_init_mmu_memory(unit)); 7106 } else 7107 #endif 7108 { 7109 SOC_IF_ERROR_RETURN(_soc_tomahawk_clear_all_memory(unit, 1)); 7110 } 7111 7112 /* Dummy call to clear garbage h/w values */ 7113 SOC_IF_ERROR_RETURN 7114 (soc_tomahawk_temperature_monitor_get(unit, COUNTOF(pvtmon_result_reg), 7115 NULL, NULL)); 7116 } 7117 7118 #ifdef BCM_TOMAHAWK2_SUPPORT 7119 if (SOC_IS_TOMAHAWK2(unit)) { 7120 int latency; 7121 int lmode = SOC_SWITCH_BYPASS_MODE_NONE; 7122 7123 SOC_IF_ERROR_RETURN(soc_th_latency_get(unit, &lmode)); 7124 7125 /* Set the latency in Slot Pipeline config register, need to be 7126 * programmed before any traffic going through the IP */ 7127 latency = soc_th2_slot_pipeline_latency_get(si->dpp_clk_ratio_x10, lmode); 7128 reg = SLOT_PIPELINE_CONFIGr; 7129 rval = 0; 7130 soc_reg_field_set(unit, reg, &rval, LATENCYf, latency); 7131 soc_reg_field_set(unit, reg, &rval, WR_ENf, 1); 7132 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 7133 } 7134 #endif 7135 7136 #ifdef BCM_TOMAHAWK2_SUPPORT 7137 if (SOC_IS_TOMAHAWK2(unit)) { 7138 SOC_IF_ERROR_RETURN(_soc_tomahawk2_port_mapping_init(unit)); 7139 } else 7140 #endif 7141 { 7142 SOC_IF_ERROR_RETURN(_soc_tomahawk_port_mapping_init(unit)); 7143 } 7144 7145 /* 7146 * Parse config at init time and cache property value for use at 7147 * run time 7148 */ 7149 if (SOC_PBMP_NOT_NULL(PBMP_HG_ALL(unit))) { 7150 fabric_port_enable = 1; 7151 } else { 7152 fabric_port_enable = soc_property_get(unit, spn_FABRIC_PORT_ENABLE, 1); 7153 } 7154 SOC_CONTROL_LOCK(unit); 7155 si->fabric_port_enable = fabric_port_enable; 7156 SOC_CONTROL_UNLOCK(unit); 7157 7158 if (dev_id == BCM56968_DEVICE_ID) { 7159 if ((soc_property_get(unit, spn_SWITCH_BYPASS_MODE, 7160 SOC_SWITCH_BYPASS_MODE_NONE)) != SOC_SWITCH_BYPASS_MODE_NONE) { 7161 LOG_ERROR(BSL_LS_SOC_COMMON, 7162 (BSL_META_U(unit, 7163 "Low latency and Balanced latency modes not" 7164 "supported on BCM56968 \n"))); 7165 return SOC_E_CONFIG; 7166 } 7167 if (SOC_PBMP_NEQ(si->ether.bitmap, si->management_pbm) && 7168 !SOC_PBMP_MEMBER(si->hg.bitmap, si->port_p2l_mapping[129]) && 7169 !SOC_PBMP_MEMBER(si->hg.bitmap, si->port_p2l_mapping[131])) { 7170 LOG_ERROR(BSL_LS_SOC_COMMON, 7171 (BSL_META_U(unit, 7172 "Port config error!! The MGMT/CPU ports support " 7173 "Eth/HiGig encap and the General ports only " 7174 "support HiGig encap on BCM56968.\n"))); 7175 return SOC_E_CONFIG; 7176 } 7177 } 7178 7179 for(port_chk = 0; port_chk < num_port; port_chk++) { 7180 if (si->port_speed_max[port_chk] > 0 && 7181 SOC_PBMP_MEMBER(PBMP_ALL(unit), port_chk)) { 7182 rv = soc_th_port_speed_supported(unit, port_chk, 7183 si->port_speed_max[port_chk]); 7184 if (SOC_FAILURE(rv)) { 7185 LOG_ERROR(BSL_LS_SOC_COMMON, 7186 (BSL_META_U(unit, 7187 "Unsupported port speed : port - %d, " 7188 "speed - %d\n"), port_chk, 7189 si->port_speed_max[port_chk])); 7190 return rv; 7191 } 7192 } 7193 } 7194 7195 #if defined(BCM_TOMAHAWK_SUPPORT) 7196 if (SOC_IS_TOMAHAWK(unit)) { 7197 SOC_IF_ERROR_RETURN(soc_th_port_config_validate(unit)); 7198 } 7199 #endif /* BCM_TOMAHAWK_SUPPORT */ 7200 7201 #if defined(BCM_TOMAHAWK2_SUPPORT) 7202 if (SOC_IS_TOMAHAWK2(unit)) { 7203 /* Check sister ports */ 7204 SOC_IF_ERROR_RETURN(soc_port_sister_validate(unit, _TH2_PORTS_PER_PBLK)); 7205 7206 /* Check if speed and encap mode matched */ 7207 SOC_IF_ERROR_RETURN(soc_port_speed_encap_validate(unit)); 7208 7209 /* Check line rate bandwidth for each pipe */ 7210 SOC_IF_ERROR_RETURN(soc_th2_max_lr_bandwidth_validate(unit)); 7211 7212 /* Check the speed classes */ 7213 SOC_IF_ERROR_RETURN(soc_th2_speed_class_validate(unit)); 7214 } 7215 #endif /* BCM_TOMAHAWK2_SUPPORT */ 7216 7217 if (!SAL_BOOT_XGSSIM) { 7218 if (SOC_IS_TOMAHAWK(unit)) { 7219 if (soc->tdm_info == NULL) { 7220 soc->tdm_info = sal_alloc(sizeof(_soc_tomahawk_tdm_t), 7221 "Tomahakw TDM info"); 7222 if (soc->tdm_info == NULL) { 7223 return SOC_E_MEMORY; 7224 } 7225 } 7226 tdm = soc->tdm_info; 7227 /* Calculate TDM calendars */ 7228 rv = _soc_tomahawk_tdm_calculation(unit, TRUE, tdm); 7229 if (SOC_FAILURE(rv)){ 7230 LOG_ERROR(BSL_LS_SOC_COMMON, 7231 (BSL_META_U(unit, 7232 "FAILED in" 7233 "_soc_tomahawk_tdm_calculation\n"))); 7234 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit)); 7235 return rv; 7236 } 7237 /* Set IDB calendars */ 7238 rv = _soc_tomahawk_tdm_idb_calendar_set(unit, 0, UPDATE_ALL_PIPES); 7239 if (SOC_FAILURE(rv)){ 7240 LOG_ERROR(BSL_LS_SOC_COMMON, 7241 (BSL_META_U(unit, 7242 "FAILED in" 7243 "_soc_tomahawk_tdm_idb_calendar_set\n"))); 7244 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit)); 7245 return rv; 7246 } 7247 rv = _soc_tomahawk_tdm_idb_oversub_group_set(unit); 7248 if (SOC_FAILURE(rv)){ 7249 LOG_ERROR(BSL_LS_SOC_COMMON, 7250 (BSL_META_U(unit, 7251 "FAILED in" 7252 "_soc_tomahawk_tdm_idb_oversub_group_set\n"))); 7253 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit)); 7254 return rv; 7255 } 7256 rv = _soc_tomahawk_tdm_idb_opportunistic_set(unit, TRUE); 7257 if (SOC_FAILURE(rv)){ 7258 LOG_ERROR(BSL_LS_SOC_COMMON, 7259 (BSL_META_U(unit, 7260 "FAILED in" 7261 "_soc_tomahawk_tdm_idb_opportunistic_set\n"))); 7262 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit)); 7263 return rv; 7264 } 7265 rv = _soc_tomahawk_tdm_idb_hsp_set(unit, UPDATE_ALL_PIPES); 7266 if (SOC_FAILURE(rv)){ 7267 LOG_ERROR(BSL_LS_SOC_COMMON, 7268 (BSL_META_U(unit, 7269 "FAILED in" 7270 "_soc_tomahawk_tdm_idb_hsp_set\n"))); 7271 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit)); 7272 return rv; 7273 } 7274 /* Set MMU calendars */ 7275 rv = _soc_tomahawk_tdm_mmu_calendar_set(unit, 0, UPDATE_ALL_PIPES); 7276 if (SOC_FAILURE(rv)){ 7277 LOG_ERROR(BSL_LS_SOC_COMMON, 7278 (BSL_META_U(unit, 7279 "FAILED in" 7280 "_soc_tomahawk_tdm_mmu_calendar_set\n"))); 7281 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit)); 7282 return rv; 7283 } 7284 rv = _soc_tomahawk_tdm_mmu_oversub_group_set(unit); 7285 if (SOC_FAILURE(rv)){ 7286 LOG_ERROR(BSL_LS_SOC_COMMON, 7287 (BSL_META_U(unit, 7288 "FAILED in" 7289 "_soc_tomahawk_tdm_mmu_oversub_group_set\n"))); 7290 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit)); 7291 return rv; 7292 } 7293 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit)); 7294 rv = _soc_tomahawk_tdm_mmu_opportunistic_set(unit, TRUE); 7295 if (SOC_FAILURE(rv)){ 7296 LOG_ERROR(BSL_LS_SOC_COMMON, 7297 (BSL_META_U(unit, 7298 "FAILED in" 7299 "_soc_tomahawk_tdm_mmu_opportunistic_set\n"))); 7300 return rv; 7301 } 7302 rv = _soc_tomahawk_tdm_mmu_hsp_set(unit, UPDATE_ALL_PIPES); 7303 if (SOC_FAILURE(rv)){ 7304 LOG_ERROR(BSL_LS_SOC_COMMON, 7305 (BSL_META_U(unit, 7306 "FAILED in" 7307 "_soc_tomahawk_tdm_mmu_hsp_set\n"))); 7308 return rv; 7309 } 7310 /* Initialize IDB */ 7311 rv = _soc_tomahawk_idb_init(unit); 7312 if (SOC_FAILURE(rv)){ 7313 LOG_ERROR(BSL_LS_SOC_COMMON, 7314 (BSL_META_U(unit, 7315 "FAILED in" 7316 "_soc_tomahawk_idb_init\n"))); 7317 return rv; 7318 } 7319 #ifdef BCM_TOMAHAWK2_SUPPORT 7320 } else if (SOC_IS_TOMAHAWK2(unit)) { 7321 SOC_IF_ERROR_RETURN(_soc_tomahawk2_tdm_init(unit)); 7322 SOC_IF_ERROR_RETURN(_soc_tomahawk2_idb_init(unit)); 7323 #endif 7324 } 7325 } 7326 7327 sal_memset(entry, 0, sizeof(cpu_pbm_entry_t)); 7328 soc_mem_pbmp_field_set(unit, CPU_PBMm, entry, BITMAPf, &PBMP_CMIC(unit)); 7329 SOC_IF_ERROR_RETURN 7330 (soc_mem_write(unit, CPU_PBMm, MEM_BLOCK_ALL, 0, entry)); 7331 7332 sal_memset(entry, 0, sizeof(cpu_pbm_2_entry_t)); 7333 soc_mem_pbmp_field_set(unit, CPU_PBM_2m, entry, BITMAPf, &PBMP_CMIC(unit)); 7334 SOC_IF_ERROR_RETURN 7335 (soc_mem_write(unit, CPU_PBM_2m, MEM_BLOCK_ALL, 0, entry)); 7336 7337 #if __GNUC__ > 6 7338 #pragma GCC diagnostic push 7339 #pragma GCC diagnostic ignored "-Wmemset-elt-size" 7340 #endif 7341 /* 7342 * We are NOT doing a sal_memset(entry,0,sizeof(entry)) for 7343 * performance reasons, because the actual soc_mem_field_set() 7344 * will only write sizeof(device_loopback_ports_bitmap_entry_t)=17 7345 * bytes while sizeof(entry)=SOC_MAX_MEM_BYTES can be up to 651 7346 * depending on which devices are compiled in. 7347 */ 7348 sal_memset(entry, 0, sizeof(device_loopback_ports_bitmap_entry_t)); 7349 #if __GNUC__ > 6 7350 #pragma GCC diagnostic pop 7351 #endif 7352 soc_mem_pbmp_field_set(unit, DEVICE_LOOPBACK_PORTS_BITMAPm, entry, BITMAPf, 7353 &PBMP_LB(unit)); 7354 SOC_IF_ERROR_RETURN 7355 (soc_mem_write(unit, DEVICE_LOOPBACK_PORTS_BITMAPm, MEM_BLOCK_ALL, 0, 7356 entry)); 7357 7358 PBMP_LB_ITER(unit, port) { 7359 mem = SOC_MEM_UNIQUE_ACC(unit, MULTIPASS_LOOPBACK_BITMAPm) 7360 [si->port_pipe[port]]; 7361 sal_memset(entry, 0, sizeof(multipass_loopback_bitmap_entry_t)); 7362 SOC_PBMP_PORT_SET(pbmp, port); 7363 soc_mem_pbmp_field_set(unit, mem, &entry, BITMAPf, &pbmp); 7364 SOC_IF_ERROR_RETURN 7365 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, 0, entry)); 7366 } 7367 7368 sal_memset(entry, 0, sizeof(egr_ing_port_entry_t)); 7369 soc_mem_field32_set(unit, EGR_ING_PORTm, entry, PORT_TYPEf, 1); 7370 PBMP_HG_ITER(unit, port) { 7371 SOC_IF_ERROR_RETURN 7372 (soc_mem_write(unit, EGR_ING_PORTm, MEM_BLOCK_ALL, port, entry)); 7373 } 7374 SOC_IF_ERROR_RETURN 7375 (soc_mem_write(unit, EGR_ING_PORTm, MEM_BLOCK_ALL, si->cpu_hg_index, 7376 entry)); 7377 soc_mem_field32_set(unit, EGR_ING_PORTm, entry, PORT_TYPEf, 2); 7378 PBMP_LB_ITER(unit, port) { 7379 SOC_IF_ERROR_RETURN 7380 (soc_mem_write(unit, EGR_ING_PORTm, MEM_BLOCK_ALL, port, entry)); 7381 } 7382 7383 SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) { 7384 port = SOC_BLOCK_PORT(unit, block_info_idx); 7385 clport = SOC_BLOCK_NUMBER(unit, block_info_idx); 7386 phy_port_base = PORT_BLOCK_BASE_PORT(port); 7387 7388 /* Assert CLPORT soft reset */ 7389 rval = 0; 7390 for (lane = 0; lane < _TH_PORTS_PER_PBLK; lane++) { 7391 if (si->port_p2l_mapping[phy_port_base + lane] != -1) { 7392 soc_reg_field_set(unit, CLPORT_SOFT_RESETr, &rval, 7393 port_fields[lane], 1); 7394 } 7395 } 7396 SOC_IF_ERROR_RETURN(WRITE_CLPORT_SOFT_RESETr(unit, port, rval)); 7397 7398 /* Set port mode */ 7399 soc_tomahawk_port_ratio_get(unit, 1 /*initTime*/, clport, &mode); 7400 rval = 0; 7401 soc_reg_field_set(unit, CLPORT_MODE_REGr, &rval, XPORT0_CORE_PORT_MODEf, 7402 mode_encodings[mode]); 7403 soc_reg_field_set(unit, CLPORT_MODE_REGr, &rval, XPORT0_PHY_PORT_MODEf, 7404 mode_encodings[mode]); 7405 SOC_IF_ERROR_RETURN(WRITE_CLPORT_MODE_REGr(unit, port, rval)); 7406 7407 /* De-assert XLPORT soft reset */ 7408 SOC_IF_ERROR_RETURN(WRITE_CLPORT_SOFT_RESETr(unit, port, 0)); 7409 7410 /* Enable CLPORT */ 7411 rval = 0; 7412 rval1 = 0; 7413 soc_reg_field_set(unit, CLPORT_FLOW_CONTROL_CONFIGr, &rval1, 7414 MERGE_MODE_ENf, 1); 7415 for (lane = 0; lane < _TH_PORTS_PER_PBLK; lane++) { 7416 lport = si->port_p2l_mapping[phy_port_base + lane]; 7417 if (lport != -1) { 7418 soc_reg_field_set(unit, CLPORT_ENABLE_REGr, &rval, 7419 port_fields[lane], 1); 7420 SOC_IF_ERROR_RETURN 7421 (WRITE_CLPORT_FLOW_CONTROL_CONFIGr(unit, lport, rval1)); 7422 } 7423 } 7424 SOC_IF_ERROR_RETURN(WRITE_CLPORT_ENABLE_REGr(unit, port, rval)); 7425 } 7426 #ifdef BCM_TOMAHAWK2_SUPPORT 7427 if (SOC_IS_TOMAHAWK2(unit)) { 7428 phy_port_mgmt0 = _TH2_PHY_PORT_MNG0; 7429 phy_port_mgmt1 = _TH2_PHY_PORT_MNG1; 7430 } else 7431 #endif /* BCM_TOMAHAWK2_SUPPORT */ 7432 { 7433 phy_port_mgmt0 = 129; 7434 phy_port_mgmt1 = 131; 7435 } 7436 7437 SOC_PBMP_ITER(si->management_pbm, port) { 7438 /* Assert XLPORT soft reset */ 7439 rval = 0; 7440 if (si->port_p2l_mapping[phy_port_mgmt0] != -1) { /* management port 0 */ 7441 soc_reg_field_set(unit, XLPORT_SOFT_RESETr, &rval, PORT0f, 1); 7442 } 7443 if (si->port_p2l_mapping[phy_port_mgmt1] != -1) { /* management port 1 */ 7444 soc_reg_field_set(unit, XLPORT_SOFT_RESETr, &rval, PORT2f, 1); 7445 } 7446 SOC_IF_ERROR_RETURN(WRITE_XLPORT_SOFT_RESETr(unit, port, rval)); 7447 7448 /* Set port mode based upon lanes config */ 7449 rval = 0; 7450 /* Note - this is a special h/w requirement to use dual lane mode */ 7451 fval = 3; 7452 soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, XPORT0_CORE_PORT_MODEf, 7453 fval); 7454 soc_reg_field_set(unit, XLPORT_MODE_REGr, &rval, XPORT0_PHY_PORT_MODEf, 7455 fval); 7456 SOC_IF_ERROR_RETURN(WRITE_XLPORT_MODE_REGr(unit, port, rval)); 7457 7458 /* De-assert XLPORT soft reset */ 7459 SOC_IF_ERROR_RETURN(WRITE_XLPORT_SOFT_RESETr(unit, port, 0)); 7460 7461 /* Enable XLPORT */ 7462 rval = 0; 7463 if (si->port_p2l_mapping[phy_port_mgmt0] != -1) { /* management port 0 */ 7464 soc_reg_field_set(unit, XLPORT_ENABLE_REGr, &rval, PORT0f, 1); 7465 } 7466 if (si->port_p2l_mapping[phy_port_mgmt1] != -1) { /* management port 1 */ 7467 soc_reg_field_set(unit, XLPORT_ENABLE_REGr, &rval, PORT2f, 1); 7468 } 7469 SOC_IF_ERROR_RETURN(WRITE_XLPORT_ENABLE_REGr(unit, port, rval)); 7470 7471 rval = 0; 7472 soc_reg_field_set(unit, XLPORT_FLOW_CONTROL_CONFIGr, &rval, 7473 MERGE_MODE_ENf, 1); 7474 SOC_IF_ERROR_RETURN 7475 (WRITE_XLPORT_FLOW_CONTROL_CONFIGr(unit, port, rval)); 7476 } 7477 7478 SOC_IF_ERROR_RETURN(READ_MMU_GCFG_MISCCONFIGr(unit, &rval)); 7479 soc_reg_field_set(unit, MMU_GCFG_MISCCONFIGr, &rval, REFRESH_ENf, 1); 7480 SOC_IF_ERROR_RETURN(WRITE_MMU_GCFG_MISCCONFIGr(unit, rval)); 7481 7482 /* Enable dual hash tables */ 7483 SOC_IF_ERROR_RETURN(_soc_tomahawk_hash_init(unit)); 7484 7485 /* Configure EP credit */ 7486 freq = si->frequency; 7487 #if defined(BCM_TOMAHAWK2_SUPPORT) 7488 if (soc_feature(unit, soc_feature_egr_mmu_cell_credit_is_memory)) { 7489 PBMP_ALL_ITER(unit, port) { 7490 SOC_IF_ERROR_RETURN( 7491 soc_th_port_asf_speed_to_mmu_cell_credit(unit, port, 7492 si->port_speed_max[port], &fval)); 7493 SOC_IF_ERROR_RETURN(READ_EGR_MMU_CELL_CREDITm(unit, MEM_BLOCK_ANY, 7494 si->port_l2p_mapping[port], &credit_entry)); 7495 soc_EGR_MMU_CELL_CREDITm_field32_set(unit, &credit_entry, 7496 CREDITf, fval); 7497 SOC_IF_ERROR_RETURN(WRITE_EGR_MMU_CELL_CREDITm(unit, MEM_BLOCK_ALL, 7498 si->port_l2p_mapping[port], &credit_entry)); 7499 } 7500 } else 7501 #endif 7502 { 7503 reg = EGR_MMU_CELL_CREDITr; 7504 rval = 0; 7505 PBMP_ALL_ITER(unit, port) { 7506 SOC_IF_ERROR_RETURN( 7507 soc_th_port_asf_speed_to_mmu_cell_credit(unit, port, 7508 si->port_speed_max[port], &fval)); 7509 soc_reg_field_set(unit, reg, &rval, CREDITf, fval); 7510 SOC_IF_ERROR_RETURN(WRITE_EGR_MMU_CELL_CREDITr(unit, port, rval)); 7511 } 7512 } 7513 7514 /* Configure egress transmit start count */ 7515 mem = EGR_XMIT_START_COUNTm; 7516 sal_memset(entry, 0, sizeof(egr_xmit_start_count_entry_t)); 7517 soc_mem_field32_set(unit, EGR_XMIT_START_COUNTm, entry, THRESHOLDf, 18); 7518 PBMP_ALL_ITER(unit, port) { 7519 for (class = 0; class < 13; class++) { 7520 index = (port % 34) * 16 + class; 7521 pipe = si->port_pipe[port]; 7522 SOC_IF_ERROR_RETURN 7523 (soc_mem_write(unit, SOC_MEM_UNIQUE_ACC(unit, mem)[pipe], 7524 MEM_BLOCK_ALL, index, entry)); 7525 } 7526 7527 /* Update HSP port multicast T2OQ setting, and this is not supported on TH2 */ 7528 if (SOC_PBMP_MEMBER(si->eq_pbm, port) && !SOC_IS_TOMAHAWK2(unit)) { 7529 SOC_IF_ERROR_RETURN(_soc_tomahawk_mc_toq_cfg(unit, port, TRUE)); 7530 } 7531 } 7532 rval = 0; 7533 SOC_IF_ERROR_RETURN(READ_MMU_SCFG_TOQ_MC_CFG0r(unit, &rval)); 7534 soc_reg_field_set(unit, MMU_SCFG_TOQ_MC_CFG0r, &rval, 7535 MCQE_FULL_THRESHOLDf, 0); 7536 SOC_IF_ERROR_RETURN(WRITE_MMU_SCFG_TOQ_MC_CFG0r(unit, rval)); 7537 7538 /* Ingress Force SAF */ 7539 #ifdef BCM_TOMAHAWK2_SUPPORT 7540 if (SOC_IS_TOMAHAWK2(unit)) { 7541 SOC_IF_ERROR_RETURN(_soc_tomahawk2_ing_fsaf_init(unit)); 7542 } 7543 #endif 7544 7545 /* Egress Force SAF */ 7546 if (SOC_PBMP_NOT_NULL(si->oversub_pbm)) { 7547 uint32 cd = 0, dd = si->frequency; 7548 int factor = SOC_IS_TOMAHAWK2(unit) ? 178125 : 118750; 7549 mem = EDB_1DBG_Bm; 7550 7551 sal_memset(entry, 0, sizeof(edb_1dbg_b_entry_t)); 7552 7553 PBMP_ALL_ITER(unit, port) { 7554 fval = ((si->port_speed_max[port] / 10) * factor) / 100000; 7555 soc_mem_field32_set(unit, mem, &entry, FIELD_Bf, fval); 7556 SOC_IF_ERROR_RETURN 7557 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, 7558 si->port_l2p_mapping[port], entry)); 7559 } 7560 7561 for (index = 0; index < NUM_PIPE(unit); index++) { 7562 if (SOC_PBMP_IS_NULL(si->pipe_pbm[index])) { 7563 continue; 7564 } 7565 reg = SOC_REG_UNIQUE_ACC(unit, EDB_1DBG_Ar)[index]; 7566 if (SOC_IS_TOMAHAWK2(unit)) { 7567 SOC_IF_ERROR_RETURN 7568 (soc_reg_get(unit, reg, REG_PORT_ANY, 0, &rval64)); 7569 cd = 135 * si->frequency / 10; 7570 dd = 15 * si->frequency / 10; 7571 soc_reg64_field32_set(unit, EDB_1DBG_Ar, &rval64, FIELD_Af, dd); 7572 soc_reg64_field32_set(unit, EDB_1DBG_Ar, &rval64, FIELD_Bf, cd); 7573 soc_reg64_field32_set(unit, EDB_1DBG_Ar, &rval64, FIELD_Cf, 25); 7574 SOC_IF_ERROR_RETURN 7575 (soc_reg_set(unit, reg, REG_PORT_ANY, 0, rval64)); 7576 } else { 7577 SOC_IF_ERROR_RETURN 7578 (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 7579 switch (si->frequency) { 7580 case 850: cd = 7650; 7581 break; 7582 case 765: cd = 6885; 7583 break; 7584 case 672: cd = 6048; 7585 break; 7586 case 645: cd = 5805; 7587 break; 7588 case 545: cd = 4905; 7589 break; 7590 default: 7591 break; 7592 } 7593 soc_reg_field_set(unit, EDB_1DBG_Ar, &rval, FIELD_Af, dd); 7594 soc_reg_field_set(unit, EDB_1DBG_Ar, &rval, FIELD_Bf, cd); 7595 soc_reg_field_set(unit, EDB_1DBG_Ar, &rval, FIELD_Cf, 8); 7596 SOC_IF_ERROR_RETURN 7597 (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 7598 } 7599 } 7600 } 7601 7602 /* Enable egress */ 7603 sal_memset(entry, 0, sizeof(egr_enable_entry_t)); 7604 soc_mem_field32_set(unit, EGR_ENABLEm, entry, PRT_ENABLEf, 1); 7605 PBMP_ALL_ITER(unit, port) { 7606 if (SOC_IS_TOMAHAWK2(unit)) { 7607 SOC_IF_ERROR_RETURN 7608 (WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, 7609 si->port_l2p_mapping[port], entry)); 7610 } else { 7611 SOC_IF_ERROR_RETURN 7612 (WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, port, entry)); 7613 } 7614 } 7615 7616 sal_memset(entry, 0, sizeof(epc_link_bmap_entry_t)); 7617 soc_mem_pbmp_field_set(unit, EPC_LINK_BMAPm, entry, PORT_BITMAPf, 7618 &PBMP_CMIC(unit)); 7619 if (soc_mem_field_valid(unit, EPC_LINK_BMAPm, ENABLE_SOBMH_BLOCKINGf)) { 7620 soc_mem_field32_set(unit, EPC_LINK_BMAPm, entry, ENABLE_SOBMH_BLOCKINGf, 7621 soc_property_get(unit, "epc_sobmh_block", 0)); 7622 } 7623 SOC_IF_ERROR_RETURN(WRITE_EPC_LINK_BMAPm(unit, MEM_BLOCK_ALL, 0, entry)); 7624 7625 #ifdef BCM_TOMAHAWK2_SUPPORT 7626 if (SOC_IS_TOMAHAWK2(unit)) { 7627 /* enable all ports */ 7628 ing_dest_port_enable_entry_t ingr_entry; 7629 7630 sal_memset(&ingr_entry, 0, sizeof(ingr_entry)); 7631 soc_mem_pbmp_field_set(unit, ING_DEST_PORT_ENABLEm, &ingr_entry, 7632 PORT_BITMAPf, &PBMP_ALL(unit)); 7633 SOC_IF_ERROR_RETURN(WRITE_ING_DEST_PORT_ENABLEm(unit, MEM_BLOCK_ALL, 0, 7634 &ingr_entry)); 7635 } 7636 #endif 7637 SOC_IF_ERROR_RETURN(READ_ING_CONFIG_64r(unit, &rval64)); 7638 soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64, 7639 L3SRC_HIT_ENABLEf, 1); 7640 soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64, 7641 L2DST_HIT_ENABLEf, 1); 7642 soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64, 7643 APPLY_EGR_MASK_ON_L2f, 1); 7644 soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64, 7645 APPLY_EGR_MASK_ON_L3f, 1); 7646 soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64, 7647 ARP_RARP_TO_FPf, 0x3); /* enable both ARP & RARP */ 7648 soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64, 7649 ARP_VALIDATION_ENf, 1); 7650 if (soc_feature(unit, soc_feature_port_lag_failover)) { 7651 soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64, 7652 IGNORE_HG_HDR_LAG_FAILOVERf, 0); 7653 } else { 7654 soc_reg64_field32_set(unit, ING_CONFIG_64r, &rval64, 7655 IGNORE_HG_HDR_LAG_FAILOVERf, 1); 7656 } 7657 SOC_IF_ERROR_RETURN(WRITE_ING_CONFIG_64r(unit, rval64)); 7658 7659 SOC_IF_ERROR_RETURN 7660 (soc_reg_field32_modify(unit, EGR_CONFIG_1r, REG_PORT_ANY, RING_MODEf, 7661 1)); 7662 /* This bit controls MAC_DA format on MPB bus used for L3UC extended view packet flow */ 7663 if (soc_property_get(unit, spn_EMBEDDED_NH_VP_SUPPORT, 0)) { 7664 SOC_IF_ERROR_RETURN 7665 (soc_reg_field32_modify(unit, EGR_CONFIG_1r, REG_PORT_ANY, 7666 MACDA_OUI_PROFILE_ENABLEf, 1)); 7667 } 7668 7669 /* The HW defaults for EGR_VLAN_CONTROL_1.VT_MISS_UNTAG == 1, which 7670 * causes the outer tag to be removed from packets that don't have 7671 * a hit in the egress vlan tranlation table. Set to 0 to disable this. 7672 */ 7673 rval = 0; 7674 soc_reg_field_set(unit, EGR_VLAN_CONTROL_1r, &rval, VT_MISS_UNTAGf, 0); 7675 7676 /* Enable pri/cfi remarking on egress ports. */ 7677 soc_reg_field_set(unit, EGR_VLAN_CONTROL_1r, &rval, REMARK_OUTER_DOT1Pf, 7678 1); 7679 PBMP_ALL_ITER(unit, port) { 7680 SOC_IF_ERROR_RETURN(WRITE_EGR_VLAN_CONTROL_1r(unit, port, rval)); 7681 } 7682 7683 SOC_PBMP_ASSIGN(pbmp, PBMP_ALL(unit)); 7684 SOC_PBMP_REMOVE(pbmp, PBMP_LB(unit)); 7685 SOC_IF_ERROR_RETURN(soc_mem_read(unit, ING_EN_EFILTER_BITMAPm, 7686 MEM_BLOCK_ANY, 0, &entry)); 7687 soc_mem_pbmp_field_set(unit, ING_EN_EFILTER_BITMAPm, &entry, BITMAPf, 7688 &pbmp); 7689 SOC_IF_ERROR_RETURN(soc_mem_write(unit, ING_EN_EFILTER_BITMAPm, 7690 MEM_BLOCK_ANY, 0, &entry)); 7691 7692 /* Multicast range initialization */ 7693 SOC_IF_ERROR_RETURN 7694 (soc_hbx_higig2_mcast_sizes_set(unit, 7695 soc_property_get(unit, spn_HIGIG2_MULTICAST_VLAN_RANGE, 7696 SOC_HBX_MULTICAST_RANGE_DEFAULT), 7697 soc_property_get(unit, spn_HIGIG2_MULTICAST_L2_RANGE, 7698 soc_mem_index_count(unit, L2MCm) / 2), 7699 soc_property_get(unit, spn_HIGIG2_MULTICAST_L3_RANGE, 7700 soc_mem_index_count(unit, L2MCm) / 2))); 7701 SOC_IF_ERROR_RETURN 7702 (soc_hbx_mcast_size_set(unit, soc_property_get(unit, 7703 spn_MULTICAST_L2_RANGE, soc_mem_index_count(unit, L2MCm) / 2))); 7704 SOC_IF_ERROR_RETURN 7705 (soc_hbx_ipmc_size_set(unit, soc_property_get(unit, 7706 spn_MULTICAST_L3_RANGE, soc_mem_index_count(unit, L2MCm) / 2))); 7707 7708 #if 0 7709 7710 if (SAL_BOOT_QUICKTURN && SOC_IS_TOMAHAWK(unit)) { 7711 PBMP_PORT_ITER(unit, port) { 7712 if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) { 7713 continue; 7714 } 7715 SOC_IF_ERROR_RETURN 7716 (soc_tomahawk_port_speed_update(unit, port, 7717 si->port_speed_max[port])); 7718 } 7719 } 7720 #endif 7721 7722 freq = si->frequency; 7723 /* 7724 * Set external MDIO freq to around 2MHz 7725 * target_freq = core_clock_freq * DIVIDEND / DIVISOR / 2 7726 */ 7727 target_freq = 2; 7728 divisor = (freq + (target_freq * 2 - 1)) / (target_freq * 2); 7729 divisor = soc_property_get(unit, spn_RATE_EXT_MDIO_DIVISOR, divisor); 7730 dividend = soc_property_get(unit, spn_RATE_EXT_MDIO_DIVIDEND, 1); 7731 rval = 0; 7732 7733 if (soc_feature(unit, soc_feature_cmicm)) { 7734 soc_reg_field_set(unit, CMIC_RATE_ADJUSTr, &rval, DIVISORf, divisor); 7735 soc_reg_field_set(unit, CMIC_RATE_ADJUSTr, &rval, DIVIDENDf, dividend); 7736 WRITE_CMIC_RATE_ADJUSTr(unit, rval); 7737 7738 /* 7739 * Set internal MDIO freq to around 12MHz 7740 * Valid range is from 2.5MHz to 20MHz 7741 * target_freq = core_clock_freq * DIVIDEND / DIVISOR / 2 7742 * or 7743 * DIVISOR = core_clock_freq * DIVIDENT / (target_freq * 2) 7744 */ 7745 target_freq = 12; 7746 divisor = (freq + (target_freq * 2 - 1)) / (target_freq * 2); 7747 divisor = soc_property_get(unit, spn_RATE_INT_MDIO_DIVISOR, divisor); 7748 dividend = soc_property_get(unit, spn_RATE_INT_MDIO_DIVIDEND, 1); 7749 rval = 0; 7750 soc_reg_field_set (unit, CMIC_RATE_ADJUST_INT_MDIOr, &rval, DIVISORf, 7751 divisor); 7752 soc_reg_field_set (unit, CMIC_RATE_ADJUST_INT_MDIOr, &rval, DIVIDENDf, 7753 dividend); 7754 WRITE_CMIC_RATE_ADJUST_INT_MDIOr(unit, rval); 7755 7756 delay = soc_property_get(unit, spn_MDIO_OUTPUT_DELAY, 10); 7757 if (delay >= 1 && delay <= 15) { 7758 READ_CMIC_MIIM_CONFIGr(unit, &rval); 7759 soc_reg_field_set(unit, CMIC_MIIM_CONFIGr, &rval, MDIO_OUT_DELAYf, 7760 delay); 7761 WRITE_CMIC_MIIM_CONFIGr(unit, rval); 7762 } 7763 7764 if (!SOC_WARM_BOOT(unit)) { 7765 #ifdef BCM_TOMAHAWK2_SUPPORT 7766 if (SOC_IS_TOMAHAWK2(unit)) { 7767 SOC_IF_ERROR_RETURN(soc_th2_ledup_init(unit)); 7768 } else 7769 #endif 7770 { 7771 SOC_IF_ERROR_RETURN(_soc_th_ledup_init(unit)); 7772 } 7773 } 7774 } 7775 7776 _phy_tsce_firmware_set_helper[unit] = _soc_tomahawk_tscx_firmware_set; 7777 _phy_tscf_firmware_set_helper[unit] = _soc_tomahawk_tscx_firmware_set; 7778 7779 rval = 0; 7780 soc_reg32_get(unit, MMU_SCFG_TOQ_MC_CFG2r, REG_PORT_ANY, 0, &rval); 7781 soc_reg_field_set(unit, MMU_SCFG_TOQ_MC_CFG2r, &rval, 7782 EPRG_KILL_TIMEOUTf, 512); 7783 SOC_IF_ERROR_RETURN 7784 (soc_tomahawk_sc_reg32_set(unit, MMU_SCFG_TOQ_MC_CFG2r, 7785 -1, -1, 0, rval)); 7786 7787 SOC_IF_ERROR_RETURN 7788 (soc_counter_tomahawk_status_enable(unit, TRUE)); 7789 7790 /* Check if Hierarchical ECMP mode is set */ 7791 rval = 0; 7792 SOC_IF_ERROR_RETURN(READ_ECMP_CONFIGr(unit, &rval)); 7793 /* 7794 * If ecmp mode is Fast ECMP (low latency), ecmp mode cannot be changed 7795 * to Hierarchical or Single 7796 */ 7797 if (rval != 0) { 7798 if (soc_property_get(unit, spn_L3_ECMP_LEVELS, 1) == 2) { 7799 ecmp_mode = 3; 7800 soc_reg_field_set(unit, ECMP_CONFIGr, &rval, ECMP_MODEf, ecmp_mode); 7801 SOC_IF_ERROR_RETURN(WRITE_ECMP_CONFIGr(unit, rval)); 7802 } 7803 } 7804 7805 /* Populate and enable RTAG7 Macro flow offset table */ 7806 if (soc_mem_is_valid(unit, RTAG7_FLOW_BASED_HASHm)) { 7807 count = soc_mem_index_max(unit, RTAG7_FLOW_BASED_HASHm); 7808 sal_memset(entry, 0, sizeof(rtag7_flow_based_hash_entry_t)); 7809 for (index = 0; index < count; ) { 7810 for (sub_sel = 0; sub_sel < 8 && index < count; sub_sel++) { 7811 for (offset = 0; 7812 offset < rtag7_field_width[sub_sel] && index < count; 7813 offset++) { 7814 if (ecmp_mode == 3) { 7815 soc_mem_field32_set(unit, RTAG7_FLOW_BASED_HASHm, &entry, 7816 SUB_SEL_ECMP_LEVEL2f, sub_sel); 7817 soc_mem_field32_set(unit, RTAG7_FLOW_BASED_HASHm, &entry, 7818 OFFSET_ECMP_LEVEL2f, offset); 7819 } 7820 soc_mem_field32_set(unit, RTAG7_FLOW_BASED_HASHm, &entry, 7821 SUB_SEL_ECMPf, sub_sel); 7822 soc_mem_field32_set(unit, RTAG7_FLOW_BASED_HASHm, &entry, 7823 OFFSET_ECMPf, offset); 7824 SOC_IF_ERROR_RETURN 7825 (soc_mem_write(unit, RTAG7_FLOW_BASED_HASHm, 7826 MEM_BLOCK_ANY, index, &entry)); 7827 index++; 7828 } 7829 } 7830 } 7831 rval = 0; 7832 soc_reg_field_set(unit, RTAG7_HASH_SELr, &rval, USE_FLOW_SEL_ECMPf, 1); 7833 soc_reg_field_set(unit, RTAG7_HASH_SELr, &rval, 7834 USE_FLOW_SEL_TRILL_ECMPf, 1); 7835 SOC_IF_ERROR_RETURN(WRITE_RTAG7_HASH_SELr(unit, rval)); 7836 } 7837 #ifdef INCLUDE_AVS 7838 /* Register tomahawk related functions */ 7839 #ifdef BCM_TOMAHAWK2_SUPPORT 7840 if (SOC_IS_TOMAHAWK2(unit)) { 7841 soc_th2_avs_init(unit); 7842 } else 7843 #endif /* BCM_TOMAHAWK2_SUPPORT */ 7844 { 7845 soc_th_avs_init(unit); 7846 } 7847 #endif /* INCLUDE_AVS */ 7848 7849 #ifdef BCM_TOMAHAWK2_SUPPORT 7850 if (SOC_IS_TOMAHAWK2(unit)) { 7851 /* Add board properity which can be used in rc.soc */ 7852 board_name = soc_property_get_str(unit, spn_BOARD_NAME); 7853 if (board_name) { 7854 if (soc_mem_config_set == NULL) { 7855 LOG_WARN(BSL_LS_SOC_COMMON, 7856 (BSL_META_U(unit, "unit %d : soc_mem_config_set() is NULL\n"), 7857 unit)); 7858 } else { 7859 if (sal_strcmp(board_name, "BCM956970K64") == 0) { 7860 soc_mem_config_set("bcm956970k64", "1"); 7861 } else if (sal_strcmp(board_name, "BCM956970K32") == 0) { 7862 soc_mem_config_set("bcm956970k32", "1"); 7863 } else if (sal_strcmp(board_name, "BCM956970S") == 0) { 7864 soc_mem_config_set("bcm956970s", "1"); 7865 } 7866 } 7867 } 7868 } 7869 #endif 7870 7871 /* Mem Scan thread start should be the last step in Misc init */ 7872 if (parity_enable) { 7873 SOC_IF_ERROR_RETURN(soc_generic_ser_mem_scan_start(unit)); 7874 SOC_IF_ERROR_RETURN(soc_generic_sram_mem_scan_start(unit)); 7875 } 7876 7877 LOG_VERBOSE(BSL_LS_SOC_COMMON, 7878 (BSL_META_U(unit, 7879 "MISC Init completed (u=%d)\n"), unit)); 7880 return SOC_E_NONE; 7881 #else 7882 return SOC_E_UNAVAIL; 7883 #endif 7884 } 7885 7886 /* 7887 * Function used for index calculation of certain memories, 7888 * where index is derived from more than one key. 7889 * Eg. (Port, SP) or (Port, PG) 7890 * Defined as Macro: SOC_TH_MMU_PIPED_MEM_INDEX 7891 * Note: If no special indexig required, return the same index. 7892 */ 7893 uint32 _soc_th_piped_mem_index(int unit, soc_port_t port, 7894 soc_mem_t mem, int arr_off) 7895 { 7896 int mmu_port, index; 7897 7898 mmu_port = SOC_TH_MMU_PORT(unit, port); 7899 7900 switch (mem) { 7901 case MMU_THDM_DB_PORTSP_CONFIGm: 7902 case MMU_THDM_MCQE_PORTSP_CONFIGm: 7903 index = (_TH_MMU_PORTS_PER_PIPE * arr_off) + (mmu_port & 0x3f); 7904 break; 7905 case THDI_PORT_SP_CONFIGm: 7906 case MMU_THDU_CONFIG_PORTm: 7907 case MMU_THDU_RESUME_PORTm: 7908 case MMU_THDU_COUNTER_PORTm: 7909 index = ((mmu_port & 0x3f) * _TH_MMU_NUM_POOL) + arr_off; 7910 break; 7911 case THDI_PORT_PG_CONFIGm: 7912 index = ((mmu_port & 0x3f) * _TH_MMU_NUM_PG) + arr_off; 7913 break; 7914 default: 7915 return arr_off; 7916 } 7917 7918 return index; 7919 } 7920 7921 STATIC void 7922 _soc_th_mmu_init_dev_config(int unit, _soc_mmu_device_info_t *devcfg, 7923 int lossless) 7924 { 7925 #define _TH_TDM_MCQE_RSVD_OVERSHOOT 12 7926 #define _TH_MCQE_RSVD_PER_MCQ 6 7927 uint32 total_rsvd_mcq = 0; 7928 int port; 7929 soc_info_t *si = &SOC_INFO(unit);; 7930 sal_memset(devcfg, 0, sizeof(_soc_mmu_device_info_t)); 7931 7932 devcfg->max_pkt_byte = _TH_MMU_MAX_PACKET_BYTES; 7933 devcfg->mmu_hdr_byte = _TH_MMU_PACKET_HEADER_BYTES; 7934 devcfg->jumbo_pkt_size = _TH_MMU_JUMBO_FRAME_BYTES; 7935 devcfg->default_mtu_size = _TH_MMU_DEFAULT_MTU_BYTES; 7936 devcfg->mmu_cell_size = _TH_MMU_BYTES_PER_CELL; 7937 devcfg->mmu_total_cell = _TH_MMU_TOTAL_CELLS_PER_XPE; 7938 #ifdef BCM_TOMAHAWKPLUS_SUPPORT 7939 if (SOC_IS_TOMAHAWKPLUS(unit)) { 7940 devcfg->mmu_total_cell = _THP_MMU_TOTAL_CELLS_PER_XPE; 7941 } 7942 #endif 7943 devcfg->num_pg = _TH_MMU_NUM_PG; 7944 devcfg->num_service_pool = _TH_MMU_NUM_POOL; 7945 devcfg->flags = SOC_MMU_CFG_F_PORT_MIN | SOC_MMU_CFG_F_PORT_POOL_MIN | 7946 SOC_MMU_CFG_F_RQE | SOC_MMU_CFG_F_EGR_MCQ_ENTRY; 7947 devcfg->total_mcq_entry = _TH_MMU_TOTAL_MCQ_ENTRY(unit); 7948 /* Device reservation for MCQ Entry - 6 cells for each MC queue */ 7949 PBMP_ALL_ITER(unit, port) { 7950 if (IS_CPU_PORT(unit, port)) { 7951 continue; 7952 } 7953 total_rsvd_mcq += (si->port_num_cosq[port] * _TH_MCQE_RSVD_PER_MCQ); 7954 } 7955 total_rsvd_mcq >>= 1; /* Converting it to per XPE */ 7956 total_rsvd_mcq += ((SOC_TH_NUM_CPU_QUEUES * _TH_MCQE_RSVD_PER_MCQ) + 7957 _TH_TDM_MCQE_RSVD_OVERSHOOT); 7958 devcfg->total_mcq_entry -= total_rsvd_mcq; 7959 devcfg->total_rqe_queue_entry = _TH_MMU_TOTAL_RQE_ENTRY(unit) - 7960 SOC_TH_MMU_RQE_ENTRY_RSVD_PER_XPE; 7961 devcfg->rqe_queue_num = _TH_MMU_NUM_RQE_QUEUES; 7962 } 7963 7964 STATIC int 7965 _soc_th_default_pg_headroom(int unit, soc_port_t port, 7966 int lossless) 7967 { 7968 int speed = 1000, hdrm = 0; 7969 uint8 port_oversub = 0; 7970 7971 if (IS_CPU_PORT(unit, port)) { 7972 return 77; 7973 } else if (!lossless) { 7974 return 0; 7975 } else if (SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) { 7976 return 166; 7977 } else if (IS_LB_PORT(unit, port)) { 7978 return 150; 7979 } 7980 7981 speed = SOC_INFO(unit).port_init_speed[port] ? 7982 SOC_INFO(unit).port_init_speed[port] : 7983 SOC_INFO(unit).port_speed_max[port]; 7984 7985 if (SOC_PBMP_NOT_NULL(PBMP_OVERSUB(unit))) { 7986 port_oversub = 1; 7987 } 7988 7989 if ((speed >= 1000) && (speed < 20000)) { 7990 hdrm = port_oversub ? 189 : 166; 7991 } else if ((speed >= 20000) && (speed <= 30000)) { 7992 hdrm = port_oversub ? 217 : 194; 7993 } else if ((speed >= 30000) && (speed <= 42000)) { 7994 hdrm = port_oversub ? 340 : 286; 7995 } else if ((speed >= 50000) && (speed < 100000)) { 7996 hdrm = port_oversub ? 358 : 304; 7997 } else if (speed >= 100000) { 7998 hdrm = port_oversub ? 648 : 519; 7999 } else { 8000 hdrm = port_oversub ? 189 : 166; 8001 } 8002 return hdrm; 8003 } 8004 8005 /* Function to get the number of ports present in a given Port Macro */ 8006 int 8007 soc_th_ports_per_pm_get(int unit, int pm_id) 8008 { 8009 soc_info_t *si; 8010 int phy_port_base, num_ports = 0; 8011 8012 si = &SOC_INFO(unit); 8013 if (pm_id >= _TH_PBLKS_PER_DEV) { 8014 return SOC_E_PARAM; 8015 } 8016 phy_port_base = 1 + (pm_id * _TH_PORTS_PER_PBLK); 8017 8018 if (si->port_p2l_mapping[phy_port_base] != -1) { 8019 num_ports = 1; 8020 if ((si->port_num_lanes[phy_port_base] == 2) && 8021 (si->port_p2l_mapping[phy_port_base + 2] != -1)) { 8022 /* for cases when num_lanes is given in the config (40g). 8023 */ 8024 num_ports = 2; 8025 } 8026 8027 /* When phy_port_base + 1 is valid, 8028 * All 4 ports of the PM(port macro) are valid. 8029 * When phy_port_base + 2 is valid, 8030 * The PM is operating in Dual lane mode 8031 */ 8032 if (si->port_p2l_mapping[phy_port_base + 1] != -1) { 8033 num_ports = 4; 8034 if (si->port_p2l_mapping[phy_port_base + 2] == -1) { 8035 num_ports = 2; 8036 } 8037 } else if (si->port_p2l_mapping[phy_port_base + 2] != -1) { 8038 num_ports = 2; 8039 } 8040 } 8041 return num_ports; 8042 } 8043 8044 /* Function to reserve cells for CutThru(CT) and Flex ports 8045 * Parameters: 8046 * unit - (IN) Unit number. 8047 * pipe - (IN) Pipe number 8048 * flex - (IN) Config has Flex ports or Not 8049 * lossless - (IN) MMU Lossless or Lossy 8050 * asf_profile - (IN) ASF profile configuration 8051 * rsvd_buffer - (OUT) Buffers reserved per resource (Ing/Egr/ASF) 8052 * Returns: 8053 * SOC_E_xxx 8054 */ 8055 int 8056 soc_th_mmu_additional_buffer_reserve(int unit, int pipe, int flex, 8057 int lossless, int asf_profile, 8058 _soc_mmu_rsvd_buffer_t *rsvd_buffer) 8059 { 8060 /* array indexed by num_ports/pm 1, 2, 4 */ 8061 int similar_speed_asf_cells_lr[] = {20, 40, 80}; /* Line Rate */ 8062 int extreme_speed_asf_cells_lr[] = {46, 92, 184}; /* Line Rate */ 8063 int similar_speed_asf_cells_ob[] = {48, 96, 168}; /* Oversub mode */ 8064 int extreme_speed_asf_cells_ob[] = {56, 112, 224}; /* Oversub mode */ 8065 int hdrm_lossless_cells[] = {648, 358, 217}; 8066 int zero_cells[] = {0, 0, 0}; 8067 int *rsvd_asf_cells_p, *headroom_cells_p; 8068 int id, min_pm_id = 0, max_pm_id = 0, oversub_mode = FALSE; 8069 int pg_min_cells = 0, qgrp_min_cells = 0, hdrm_cells = 0, asf_cells = 0; 8070 int total_reserve = 0, num_ports = 0; 8071 uint8 two_port_pm = FALSE, four_port_pm = FALSE; 8072 soc_info_t *si; 8073 8074 si = &SOC_INFO(unit); 8075 8076 if ((pipe >= NUM_PIPE(unit)) || (!rsvd_buffer)) { 8077 return SOC_E_PARAM; 8078 } 8079 8080 sal_memset(rsvd_buffer, 0, sizeof(_soc_mmu_rsvd_buffer_t)); 8081 8082 if (SOC_PBMP_NOT_NULL(si->oversub_pbm)) { 8083 oversub_mode = TRUE; 8084 } 8085 8086 rsvd_asf_cells_p = zero_cells; 8087 8088 if (oversub_mode == TRUE) { 8089 if (asf_profile == 1) { 8090 rsvd_asf_cells_p = similar_speed_asf_cells_ob; 8091 } else if (asf_profile == 2) { 8092 rsvd_asf_cells_p = extreme_speed_asf_cells_ob; 8093 } 8094 } else { 8095 if (asf_profile == 1) { 8096 rsvd_asf_cells_p = similar_speed_asf_cells_lr; 8097 } else if (asf_profile == 2) { 8098 rsvd_asf_cells_p = extreme_speed_asf_cells_lr; 8099 } 8100 } 8101 8102 headroom_cells_p = zero_cells; 8103 if (flex && (lossless != 0)) { 8104 headroom_cells_p = hdrm_lossless_cells; 8105 } 8106 8107 min_pm_id = pipe * _TH_PBLKS_PER_PIPE; 8108 max_pm_id = min_pm_id + _TH_PBLKS_PER_PIPE; 8109 8110 for (id = min_pm_id; id < max_pm_id; id++) { 8111 num_ports = soc_th_ports_per_pm_get(unit, id); 8112 switch (num_ports) { 8113 case 1: 8114 hdrm_cells = headroom_cells_p[0]; 8115 asf_cells = rsvd_asf_cells_p[0]; 8116 break; 8117 case 2: 8118 hdrm_cells = headroom_cells_p[1]; 8119 asf_cells = rsvd_asf_cells_p[1]; 8120 two_port_pm = TRUE; 8121 break; 8122 case 4: 8123 hdrm_cells = headroom_cells_p[2]; 8124 asf_cells = rsvd_asf_cells_p[2]; 8125 four_port_pm = TRUE; 8126 break; 8127 default: 8128 continue; 8129 } 8130 if (flex) { 8131 8132 pg_min_cells = 0; /*(lossless[unit]) ? 8 : 0; */ 8133 } 8134 qgrp_min_cells = (lossless) ? 0 : 16; 8135 if (lossless) { 8136 rsvd_buffer->ing_rsvd_cells += (hdrm_cells + pg_min_cells + 8137 qgrp_min_cells) * num_ports; 8138 } else { 8139 rsvd_buffer->ing_rsvd_cells += (hdrm_cells + pg_min_cells) * num_ports; 8140 } 8141 rsvd_buffer->egr_rsvd_cells += qgrp_min_cells * num_ports; 8142 rsvd_buffer->asf_rsvd_cells += asf_cells; 8143 } 8144 8145 if (asf_profile == 1) { 8146 /* In Similar speed CT profile, cap limits in bytes are as follows 8147 * 150K for 1 port/pm case 8148 * 200K for 2 port/pm case 8149 * 250K for 3/4 port/pm case 8150 */ 8151 int cap_limit = 0; 8152 if (four_port_pm == TRUE) { 8153 cap_limit = 250; 8154 } else if (two_port_pm == TRUE) { 8155 cap_limit = 200; 8156 } else { 8157 cap_limit = 150; 8158 } 8159 /* calculating the cap_limit in cells */ 8160 cap_limit = ((cap_limit * 1024) + (_TH_MMU_BYTES_PER_CELL - 1)) / 8161 _TH_MMU_BYTES_PER_CELL; 8162 cap_limit = (cap_limit + 1) / 2; /* Each pipe belongs to 2 XPEs. 8163 * Hence half the value */ 8164 if (rsvd_buffer->asf_rsvd_cells > cap_limit) { 8165 rsvd_buffer->asf_rsvd_cells = cap_limit; 8166 } 8167 } 8168 8169 total_reserve = rsvd_buffer->ing_rsvd_cells; 8170 total_reserve += rsvd_buffer->egr_rsvd_cells; 8171 total_reserve += rsvd_buffer->asf_rsvd_cells; 8172 8173 LOG_VERBOSE(BSL_LS_SOC_MMU, 8174 (BSL_META_U(unit, 8175 "MMU config: Cells rsvd for Pipe %d," 8176 " Flex/ASF per XPE: %d, Ing: %d," 8177 " Egr: %d, ASF: %d\n"), 8178 pipe, total_reserve, rsvd_buffer->ing_rsvd_cells, 8179 rsvd_buffer->egr_rsvd_cells, 8180 rsvd_buffer->asf_rsvd_cells)); 8181 return SOC_E_NONE; 8182 } 8183 8184 #define DEFAULT_VALUE_MAGIC (0xFFFFFF) 8185 8186 STATIC void 8187 _soc_th_mmu_config_buf_default_v5_0(int unit, _soc_mmu_cfg_buf_t *buf, 8188 _soc_mmu_device_info_t *devcfg, 8189 int lossless) 8190 { 8191 #define DEFAULT_PG_NUM 7 /* Default Priority Group Num */ 8192 #define DEFAULT_POOL_ID 0 /* Default Service/Shared Pool Id */ 8193 soc_info_t *si; 8194 _soc_mmu_cfg_buf_pool_t *buf_pool; 8195 _soc_mmu_cfg_buf_port_t *buf_port; 8196 _soc_mmu_cfg_buf_port_pool_t *buf_port_pool; 8197 _soc_mmu_cfg_buf_prigroup_t *buf_prigroup; 8198 _soc_mmu_cfg_buf_queue_t *buf_queue; 8199 _soc_mmu_cfg_buf_mcengine_queue_t *buf_rqe_queue; 8200 int max_packet_cells, default_mtu_cells; 8201 int port, idx; 8202 int total_pool_size = 0, egr_shared_total = 0; 8203 int in_reserved = 0; 8204 uint32 color_limit = 0; 8205 int rqe_entry_shared_total, asf_rsvd = 0, ing_rsvd = 0, egr_rsvd = 0; 8206 _soc_mmu_cfg_buf_qgroup_t *queue_grp; 8207 int asf_profile; 8208 8209 si = &SOC_INFO(unit); 8210 8211 asf_profile = soc_property_get(unit, spn_ASF_MEM_PROFILE, 8212 _SOC_TH_ASF_MEM_PROFILE_SIMILAR); 8213 8214 LOG_VERBOSE(BSL_LS_SOC_MMU, 8215 (BSL_META_U(unit, 8216 "Initializing default MMU config(v5.3). (u=%d), " 8217 "Lossless %s, Flex %s, ASF profile %d\n"), 8218 unit, lossless ? "YES": "NO", 8219 si->flex_eligible ? "YES": "NO", asf_profile)); 8220 max_packet_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->max_pkt_byte + 8221 devcfg->mmu_hdr_byte, 8222 devcfg->mmu_cell_size); 8223 default_mtu_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->default_mtu_size + 8224 devcfg->mmu_hdr_byte, 8225 devcfg->mmu_cell_size); 8226 8227 total_pool_size = devcfg->mmu_total_cell; /* per XPE limit */ 8228 8229 8230 for (idx = 0; idx < NUM_PIPE(unit); idx++) { 8231 soc_th_mmu_additional_buffer_reserve(unit, idx, si->flex_eligible, 8232 lossless, asf_profile, 8233 &buf->rsvd_buffers[idx]); 8234 if (asf_rsvd < buf->rsvd_buffers[idx].asf_rsvd_cells) { 8235 asf_rsvd = buf->rsvd_buffers[idx].asf_rsvd_cells; 8236 } 8237 if (egr_rsvd < buf->rsvd_buffers[idx].egr_rsvd_cells) { 8238 egr_rsvd = buf->rsvd_buffers[idx].egr_rsvd_cells; 8239 } 8240 if (ing_rsvd < buf->rsvd_buffers[idx].ing_rsvd_cells) { 8241 ing_rsvd = buf->rsvd_buffers[idx].ing_rsvd_cells; 8242 } 8243 } 8244 8245 buf->headroom = 2 * max_packet_cells; 8246 8247 in_reserved += buf->headroom; 8248 8249 egr_shared_total = total_pool_size - ((lossless) ? 88 : 0) - 8250 ((asf_rsvd + egr_rsvd) << 1); 8251 LOG_VERBOSE(BSL_LS_SOC_MMU, 8252 (BSL_META_U(unit, 8253 "MMU config: Total Shared size: %d\n"), 8254 egr_shared_total)); 8255 8256 rqe_entry_shared_total = devcfg->total_rqe_queue_entry - 88; 8257 8258 for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) { 8259 buf_pool = &buf->pools[idx]; 8260 8261 if (idx == 0) { /* 100% scale up by 100 */ 8262 buf_pool->size = 10000 | _MMU_CFG_BUF_PERCENT_FLAG; 8263 buf_pool->yellow_size = 10000 | _MMU_CFG_BUF_PERCENT_FLAG; 8264 buf_pool->red_size = 10000 | _MMU_CFG_BUF_PERCENT_FLAG; 8265 buf_pool->total_mcq_entry = 10000 | _MMU_CFG_BUF_PERCENT_FLAG; 8266 buf_pool->total_rqe_entry = rqe_entry_shared_total; 8267 } else { 8268 buf_pool->size = 0; 8269 buf_pool->yellow_size = 0; 8270 buf_pool->red_size = 0; 8271 buf_pool->total_mcq_entry = 0; 8272 buf_pool->total_rqe_entry = 0; 8273 } 8274 } 8275 8276 color_limit = 0 | _MMU_CFG_BUF_DYNAMIC_FLAG; 8277 for (idx = 0; idx < SOC_TH_MMU_CFG_QGROUP_MAX; idx++) { 8278 /* Default Settings: QGRP min will be used by Lossy Queues only */ 8279 queue_grp = &buf->qgroups[idx]; 8280 queue_grp->guarantee = 0; 8281 queue_grp->pool_resume = 16; 8282 queue_grp->yellow_resume = 16; 8283 queue_grp->red_resume = 16; 8284 if (lossless) { 8285 queue_grp->pool_scale = -1; 8286 queue_grp->guarantee = 0; 8287 queue_grp->pool_limit = 0; 8288 queue_grp->discard_enable = 1; 8289 queue_grp->red_limit = 0; 8290 queue_grp->yellow_limit = 0; 8291 } else { 8292 /* resume limits - accounted for 8 cell granularity */ 8293 queue_grp->guarantee = 16; 8294 queue_grp->pool_limit = 0; 8295 queue_grp->discard_enable = 1; 8296 queue_grp->pool_scale = 8; 8297 queue_grp->red_limit = color_limit; 8298 queue_grp->yellow_limit = color_limit; 8299 } 8300 } 8301 8302 PBMP_ALL_ITER(unit, port) { 8303 if (port >= SOC_MMU_CFG_PORT_MAX) { 8304 break; 8305 } 8306 buf_port = &buf->ports[port]; 8307 8308 /* internal priority to priority group mapping */ 8309 for (idx = 0; idx < _TH_MMU_NUM_INT_PRI; idx++) { 8310 buf_port->pri_to_prigroup[idx] = DEFAULT_PG_NUM; 8311 } 8312 8313 /* priority group to pool mapping */ 8314 for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) { 8315 buf_port->prigroups[idx].pool_idx = DEFAULT_POOL_ID; 8316 } 8317 8318 for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) { 8319 buf_port_pool = &buf_port->pools[idx]; 8320 buf_port_pool->guarantee = 0; 8321 buf_port_pool->pool_limit = 0; 8322 buf_port_pool->pool_resume = 0; 8323 if (idx == DEFAULT_POOL_ID) { 8324 buf_port_pool->pool_limit = total_pool_size; 8325 buf_port_pool->pool_resume = total_pool_size - 16; 8326 } 8327 in_reserved += buf_port_pool->guarantee; 8328 } 8329 8330 buf_port->pkt_size = max_packet_cells; 8331 8332 /* priority group */ 8333 for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) { 8334 buf_prigroup = &buf_port->prigroups[idx]; 8335 buf_prigroup->guarantee = 0; 8336 buf_prigroup->user_delay = -1; 8337 buf_prigroup->switch_delay = -1; 8338 buf_prigroup->pkt_size = max_packet_cells; 8339 buf_prigroup->device_headroom_enable = 0; 8340 buf_prigroup->pool_limit = 0; 8341 buf_prigroup->pool_floor = 0; 8342 buf_prigroup->pool_scale = -1; 8343 buf_prigroup->headroom = 0; 8344 buf_prigroup->pool_resume = 0; 8345 buf_prigroup->flow_control_enable = 0; 8346 if (idx == DEFAULT_PG_NUM) { 8347 buf_prigroup->device_headroom_enable = 1; 8348 buf_prigroup->flow_control_enable = lossless; 8349 /* Init pool_limit to DEFAULT_VALUE_MAGIC to check if user 8350 have pool_limit setting in config file. */ 8351 buf_prigroup->pool_limit = DEFAULT_VALUE_MAGIC; 8352 if (lossless) { 8353 buf_prigroup->guarantee = default_mtu_cells; 8354 buf_prigroup->headroom = 8355 _soc_th_default_pg_headroom(unit, port, lossless); 8356 buf_prigroup->pool_scale = 8; 8357 } else if (IS_CPU_PORT(unit, port)) { 8358 buf_prigroup->headroom = 8359 _soc_th_default_pg_headroom(unit, port, lossless); 8360 } 8361 } 8362 } 8363 8364 /* multicast queue */ 8365 for (idx = 0; idx < si->port_num_cosq[port]; idx++) { 8366 buf_queue = &buf_port->queues[idx]; 8367 8368 buf_queue->qgroup_id = -1; 8369 buf_queue->mcq_entry_guarantee = 4; 8370 color_limit = 0 | _MMU_CFG_BUF_DYNAMIC_FLAG 8371 | _MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1;; 8372 if (lossless) { 8373 buf_queue->guarantee = 0; 8374 buf_queue->discard_enable = 0; 8375 buf_queue->pool_scale = -1; 8376 buf_queue->pool_limit = egr_shared_total; 8377 buf_queue->yellow_limit = egr_shared_total; 8378 buf_queue->red_limit = egr_shared_total; 8379 buf_queue->color_discard_enable = 0; 8380 buf_queue->pool_resume = 16; 8381 } else { 8382 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) { 8383 buf_queue->guarantee = 8; 8384 } else { 8385 buf_queue->guarantee = 0; 8386 } 8387 buf_queue->discard_enable = 1; 8388 buf_queue->pool_scale = 8; 8389 buf_queue->pool_limit = 0; 8390 buf_queue->yellow_limit = color_limit; 8391 buf_queue->red_limit = color_limit; 8392 buf_queue->color_discard_enable = 0; 8393 /* pool_resume - accounted for 8 cell granularity */ 8394 buf_queue->pool_resume = 16; 8395 } 8396 } 8397 8398 /* unicast queue */ 8399 for (idx = 0; idx < si->port_num_uc_cosq[port]; idx++) { 8400 buf_queue = &buf_port->queues[si->port_num_cosq[port] + idx]; 8401 8402 buf_queue->qgroup_id = -1; 8403 color_limit = 0 | _MMU_CFG_BUF_DYNAMIC_FLAG 8404 | _MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1; 8405 if (lossless) { 8406 buf_queue->guarantee = 0; 8407 buf_queue->discard_enable = 0; 8408 buf_queue->pool_scale = -1; 8409 buf_queue->pool_limit = egr_shared_total; 8410 buf_queue->red_limit = egr_shared_total; 8411 buf_queue->yellow_limit = egr_shared_total; 8412 buf_queue->color_discard_enable = 0; 8413 /* resume limits - accounted for 8 cell granularity */ 8414 buf_queue->pool_resume = 16; 8415 buf_queue->yellow_resume = 16; 8416 buf_queue->red_resume = 16; 8417 } else { 8418 buf_queue->guarantee = 0; 8419 buf_queue->discard_enable = 1; 8420 buf_queue->pool_scale = 8; 8421 buf_queue->pool_limit = 0; 8422 buf_queue->red_limit = color_limit; 8423 buf_queue->yellow_limit = color_limit; 8424 buf_queue->color_discard_enable = 0; 8425 /* resume limits - accounted for 8 cell granularity */ 8426 buf_queue->pool_resume = 16; 8427 buf_queue->yellow_resume = 16; 8428 buf_queue->red_resume = 16; 8429 8430 /* Enable QGROUP in LOSSY MODE */ 8431 buf_queue->qgroup_id = 0; 8432 buf_queue->qgroup_min_enable = 1; 8433 } 8434 } 8435 8436 /* queue to pool mapping */ 8437 for (idx = 0; 8438 idx < si->port_num_cosq[port] + si->port_num_uc_cosq[port]; idx++) { 8439 buf_port->queues[idx].pool_idx = DEFAULT_POOL_ID; 8440 } 8441 } 8442 8443 /* RQE */ 8444 for (idx = 0; idx < _TH_MMU_NUM_RQE_QUEUES; idx++) { 8445 buf_rqe_queue = &buf->rqe_queues[idx]; 8446 buf_rqe_queue->pool_idx = DEFAULT_POOL_ID; 8447 buf_rqe_queue->guarantee = 8; 8448 color_limit = 0 | _MMU_CFG_BUF_DYNAMIC_FLAG; 8449 if (lossless) { 8450 buf_rqe_queue->discard_enable = 0; 8451 buf_rqe_queue->pool_scale = -1; 8452 buf_rqe_queue->pool_limit = egr_shared_total; 8453 buf_rqe_queue->red_limit = egr_shared_total; 8454 buf_rqe_queue->yellow_limit = egr_shared_total; 8455 } else { 8456 buf_rqe_queue->discard_enable = 1; 8457 buf_rqe_queue->pool_scale = 8; 8458 buf_rqe_queue->pool_limit = 0; 8459 buf_rqe_queue->red_limit = color_limit; 8460 buf_rqe_queue->yellow_limit = color_limit; 8461 } 8462 } 8463 } 8464 STATIC int 8465 _soc_th_pool_scale_to_limit(int size, int scale) 8466 { 8467 int factor = 1000; 8468 8469 switch (scale) { 8470 case 7: factor = 875; break; 8471 case 6: factor = 750; break; 8472 case 5: factor = 625; break; 8473 case 4: factor = 500; break; 8474 case 3: factor = 375; break; 8475 case 2: factor = 250; break; 8476 case 1: factor = 125; break; 8477 case 0: 8478 default: 8479 factor = 1000; break; 8480 } 8481 return (size * factor)/1000; 8482 } 8483 8484 STATIC int 8485 _soc_th_mmu_config_buf_set_hw(int unit, _soc_mmu_cfg_buf_t *buf, 8486 _soc_mmu_device_info_t *devcfg, int lossless) 8487 { 8488 #define DEFAULT_PG_NUM 7 /* Default Priority Group Num */ 8489 soc_info_t *si; 8490 _soc_mmu_cfg_buf_pool_t *buf_pool; 8491 _soc_mmu_cfg_buf_port_t *buf_port; 8492 _soc_mmu_cfg_buf_qgroup_t *queue_grp; 8493 mmu_thdo_config_qgroup_entry_t cfg_qgrp; 8494 mmu_thdo_offset_qgroup_entry_t offset_qgrp; 8495 _soc_mmu_cfg_buf_port_pool_t *buf_port_pool; 8496 thdi_port_sp_config_entry_t thdi_sp_config; 8497 thdi_port_pg_config_entry_t pg_config_mem; 8498 _soc_mmu_cfg_buf_prigroup_t *buf_prigroup; 8499 _soc_mmu_cfg_buf_queue_t *buf_queue; 8500 _soc_mmu_cfg_buf_mcengine_queue_t *buf_rqe_queue; 8501 uint32 entry0[SOC_MAX_MEM_WORDS], entry1[SOC_MAX_MEM_WORDS]; 8502 soc_reg_t reg = INVALIDr; 8503 soc_mem_t mem0, mem1, mem2, mem3; 8504 uint32 fval, rval, rval2, rval3; 8505 int base, numq, qbase, rqlen; 8506 int port, idx, midx, pval, pri, index1; 8507 int jumbo_frame_cells, default_mtu_cells; 8508 int limit, ing_limit = 0, egr_limit, rlimit; 8509 int pipe; 8510 uint32 mgmt_hdrm, mgmt_pg_min, lb_hdrm, cpu_hdrm; 8511 uint32 mgmt_q_min, lb_q_min, cpu_q_min, cpu_pg_min; 8512 uint32 total_mcqe_rsvd, cpu_mcqe_rsvd; 8513 uint32 rqe_rsvd = _TH_MMU_NUM_RQE_QUEUES * 8; 8514 static const soc_mem_t mmu_thdi_port_mem[] = { 8515 THDI_PORT_SP_CONFIGm, 8516 THDI_PORT_PG_CONFIGm 8517 }; 8518 static const soc_mem_t mmu_thdo_q_uc_mem[] = { 8519 MMU_THDU_CONFIG_QUEUEm, 8520 MMU_THDU_OFFSET_QUEUEm, 8521 MMU_THDU_Q_TO_QGRP_MAPm 8522 }; 8523 static const soc_mem_t mmu_thdo_qgrp_uc_mem[] = { 8524 MMU_THDU_CONFIG_QGROUPm, 8525 MMU_THDU_OFFSET_QGROUPm 8526 }; 8527 static const soc_mem_t mmu_thdo_port_uc_mem[] = { 8528 MMU_THDU_CONFIG_PORTm, 8529 MMU_THDU_RESUME_PORTm 8530 }; 8531 static const soc_mem_t mmu_thdo_q_mc_mem[] = { 8532 MMU_THDM_DB_QUEUE_CONFIGm, 8533 MMU_THDM_DB_QUEUE_OFFSETm, 8534 MMU_THDM_MCQE_QUEUE_CONFIGm, 8535 MMU_THDM_MCQE_QUEUE_OFFSETm 8536 }; 8537 8538 static const soc_mem_t mmu_thdo_port_mc_mem[] = { 8539 MMU_THDM_DB_PORTSP_CONFIGm, 8540 MMU_THDM_MCQE_PORTSP_CONFIGm 8541 }; 8542 8543 static const soc_field_t prigroup_reg[] = { 8544 THDI_PORT_PRI_GRP0r, THDI_PORT_PRI_GRP1r 8545 }; 8546 static const soc_field_t prigroup_field[] = { 8547 PRI0_GRPf, PRI1_GRPf, PRI2_GRPf, PRI3_GRPf, 8548 PRI4_GRPf, PRI5_GRPf, PRI6_GRPf, PRI7_GRPf, 8549 PRI8_GRPf, PRI9_GRPf, PRI10_GRPf, PRI11_GRPf, 8550 PRI12_GRPf, PRI13_GRPf, PRI14_GRPf, PRI15_GRPf 8551 }; 8552 static const soc_field_t prigroup_spid_field[] = { 8553 PG0_SPIDf, PG1_SPIDf, PG2_SPIDf, PG3_SPIDf, 8554 PG4_SPIDf, PG5_SPIDf, PG6_SPIDf, PG7_SPIDf 8555 }; 8556 int pool_resume = 0; 8557 uint16 dev_id; 8558 uint8 rev_id; 8559 int ing_rsvd = 0, egr_rsvd = 0, asf_rsvd = 0; 8560 int pool_pg_headroom = 0, queue_guarantee = 0; 8561 8562 soc_cm_get_id(unit, &dev_id, &rev_id); 8563 si = &SOC_INFO(unit); 8564 jumbo_frame_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->jumbo_pkt_size + 8565 devcfg->mmu_hdr_byte, 8566 devcfg->mmu_cell_size); 8567 default_mtu_cells = _MMU_CFG_MMU_BYTES_TO_CELLS(devcfg->default_mtu_size + 8568 devcfg->mmu_hdr_byte, 8569 devcfg->mmu_cell_size); 8570 pool_resume = 2 * jumbo_frame_cells; 8571 8572 rval = 0; 8573 fval = _TH_MMU_PHYSICAL_CELLS_PER_XPE - _TH_MMU_RSVD_CELLS_CFAP_PER_XPE; 8574 #ifdef BCM_TOMAHAWKPLUS_SUPPORT 8575 if (SOC_IS_TOMAHAWKPLUS(unit)) { 8576 fval = _THP_MMU_PHYSICAL_CELLS_PER_XPE - _THP_MMU_RSVD_CELLS_CFAP_PER_XPE; 8577 } 8578 #endif 8579 soc_reg_field_set(unit, CFAPFULLTHRESHOLDSETr, &rval, CFAPFULLSETPOINTf, 8580 fval); 8581 SOC_IF_ERROR_RETURN( 8582 soc_tomahawk_xpe_reg32_set(unit, CFAPFULLTHRESHOLDSETr, -1, -1, 8583 -1, rval)); 8584 8585 rval = 0; 8586 soc_reg_field_set(unit, CFAPFULLTHRESHOLDRESETr, &rval, 8587 CFAPFULLRESETPOINTf, fval - (2 * jumbo_frame_cells)); 8588 SOC_IF_ERROR_RETURN( 8589 soc_tomahawk_xpe_reg32_set(unit, CFAPFULLTHRESHOLDRESETr, -1, -1, 8590 -1, rval)); 8591 8592 rval = 0; 8593 soc_reg_field_set(unit, CFAPBANKFULLr, &rval, LIMITf, 767); 8594 for (idx = 0; idx < SOC_REG_NUMELS(unit, CFAPBANKFULLr); idx++) { 8595 SOC_IF_ERROR_RETURN( 8596 soc_tomahawk_xpe_reg32_set(unit, CFAPBANKFULLr, -1, -1, idx, rval)); 8597 } 8598 8599 for (idx = 0; idx < NUM_PIPE(unit); idx++) { 8600 if (asf_rsvd < buf->rsvd_buffers[idx].asf_rsvd_cells) { 8601 asf_rsvd = buf->rsvd_buffers[idx].asf_rsvd_cells; 8602 } 8603 if (egr_rsvd < buf->rsvd_buffers[idx].egr_rsvd_cells) { 8604 egr_rsvd = buf->rsvd_buffers[idx].egr_rsvd_cells; 8605 } 8606 if (ing_rsvd < buf->rsvd_buffers[idx].ing_rsvd_cells) { 8607 ing_rsvd = buf->rsvd_buffers[idx].ing_rsvd_cells; 8608 } 8609 } 8610 /* Converting 1 pipe value to 2 pipe (1 XPE handles 2 pipes) */ 8611 ing_rsvd <<= 1; 8612 egr_rsvd <<= 1; 8613 asf_rsvd <<= 1; 8614 asf_rsvd -= 1; /* To offset approximation */ 8615 8616 LOG_VERBOSE(BSL_LS_SOC_MMU, 8617 (BSL_META_U(unit, 8618 "MMU config set HW: Cells rsvd per XPE: %d\n"), 8619 (ing_rsvd + egr_rsvd + asf_rsvd))); 8620 8621 mgmt_hdrm = 0; 8622 mgmt_q_min = (lossless) ? 0 : 16; 8623 mgmt_pg_min = 0; 8624 SOC_PBMP_ITER(si->management_pbm, port) { 8625 mgmt_hdrm += _soc_th_default_pg_headroom(unit, port, lossless); 8626 } 8627 lb_hdrm = 0; 8628 lb_q_min = 0; 8629 SOC_PBMP_ITER(si->lb_pbm, port) { 8630 lb_hdrm += _soc_th_default_pg_headroom(unit, port, lossless); 8631 if (!lossless) { 8632 lb_q_min += (10 * 8) >> 1; /* Taking half, 2 pipe = 1 xpe */ 8633 } 8634 } 8635 cpu_hdrm = _soc_th_default_pg_headroom(unit, CMIC_PORT(unit), lossless); 8636 cpu_q_min = (lossless) ? 0 : (48 * 8); 8637 cpu_pg_min = 8638 buf->ports[CMIC_PORT(unit)].prigroups[DEFAULT_PG_NUM].guarantee; 8639 /* internal priority to priority group mapping */ 8640 PBMP_ALL_ITER(unit, port) { 8641 buf_port = &buf->ports[port]; 8642 8643 if (SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) { 8644 buf_prigroup = &buf_port->prigroups[DEFAULT_PG_NUM]; 8645 mgmt_pg_min += buf_prigroup->guarantee; 8646 } 8647 for (idx = 0; idx < 16; idx++) { 8648 if (idx % 8 == 0) { /* 8 fields per register */ 8649 reg = prigroup_reg[idx / 8]; 8650 rval = 0; 8651 } 8652 soc_reg_field_set(unit, reg, &rval, prigroup_field[idx], 8653 buf_port->pri_to_prigroup[idx]); 8654 if (idx % 8 == 7) { /* 8 fields per register */ 8655 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval)); 8656 } 8657 } 8658 } 8659 8660 /* Input thresholds */ 8661 rval = 0; 8662 soc_reg_field_set(unit, THDI_GLOBAL_HDRM_LIMITr, 8663 &rval, GLOBAL_HDRM_LIMITf, buf->headroom / 2); 8664 /* Per XPE register */ 8665 SOC_IF_ERROR_RETURN( 8666 soc_tomahawk_xpe_reg32_set(unit, THDI_GLOBAL_HDRM_LIMITr, 8667 -1, -1, 0, rval)); 8668 8669 for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) { 8670 buf_pool = &buf->pools[idx]; 8671 if (((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) == 0) 8672 || (buf_pool->prigroup_headroom == 0)) { 8673 continue; 8674 } 8675 8676 if (FALSE == si->flex_eligible) { 8677 int temp_headroom = 0; 8678 if (lossless) { 8679 /* Calculate PG headroom for Layer A. CPU, No Mgmt*/ 8680 pool_pg_headroom = ((buf_pool->prigroup_headroom - 8681 (cpu_hdrm + mgmt_hdrm)) >> 1) + cpu_hdrm; 8682 /* Calculate PG headroom for Layer B. No CPU, Mgmt */ 8683 temp_headroom = ((buf_pool->prigroup_headroom - 8684 (cpu_hdrm + mgmt_hdrm)) >> 1) + mgmt_hdrm; 8685 if (temp_headroom > pool_pg_headroom) { 8686 pool_pg_headroom = temp_headroom; 8687 } 8688 } else { 8689 pool_pg_headroom = cpu_hdrm; 8690 } 8691 } else { 8692 int temp_headroom = 0; 8693 /* Calculate PG headroom for Layer A. CPU, No Mgmt */ 8694 pool_pg_headroom = ing_rsvd + (lb_hdrm >> 1) + cpu_hdrm; 8695 8696 /* Calculate PG headroom for Layer B. No CPU, Mgmt */ 8697 temp_headroom = ing_rsvd + (lb_hdrm >> 1) + mgmt_hdrm; 8698 if (temp_headroom > pool_pg_headroom) { 8699 pool_pg_headroom = temp_headroom; 8700 } 8701 } 8702 8703 limit = buf_pool->total - 8704 (((buf_pool->prigroup_guarantee - mgmt_pg_min - cpu_pg_min) >> 1) + 8705 mgmt_pg_min + asf_rsvd + pool_pg_headroom + buf->headroom) - 8706 (lossless ? (rqe_rsvd + cpu_q_min + mgmt_q_min) : 0); 8707 ing_limit = limit; 8708 8709 if (limit > 0) { 8710 rval = 0; 8711 soc_reg_field_set(unit, THDI_BUFFER_CELL_LIMIT_SPr, &rval, LIMITf, 8712 limit); 8713 SOC_IF_ERROR_RETURN( 8714 soc_tomahawk_xpe_reg32_set(unit, THDI_BUFFER_CELL_LIMIT_SPr, 8715 -1, -1, idx, rval)); 8716 } 8717 8718 rval = 0; 8719 soc_reg_field_set(unit, THDI_CELL_RESET_LIMIT_OFFSET_SPr, &rval, 8720 OFFSETf, pool_resume); 8721 SOC_IF_ERROR_RETURN( 8722 soc_tomahawk_xpe_reg32_set(unit, THDI_CELL_RESET_LIMIT_OFFSET_SPr, 8723 -1, -1, idx, rval)); 8724 8725 rval = 0; 8726 soc_reg_field_set(unit, THDI_HDRM_BUFFER_CELL_LIMIT_HPr, &rval, 8727 LIMITf, pool_pg_headroom); 8728 SOC_IF_ERROR_RETURN( 8729 soc_tomahawk_xpe_reg32_set(unit, THDI_HDRM_BUFFER_CELL_LIMIT_HPr, 8730 -1, -1, idx, rval)); 8731 } 8732 rval = 0; 8733 SOC_IF_ERROR_RETURN( 8734 soc_tomahawk_xpe_reg32_set(unit, THDI_BUFFER_CELL_LIMIT_PUBLIC_POOLr, 8735 -1, -1, 0, rval)); 8736 8737 /* Input port per port settings */ 8738 PBMP_ALL_ITER(unit, port) { 8739 pipe = si->port_pipe[port]; 8740 buf_port = &buf->ports[port]; 8741 8742 rval = 0; 8743 for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) { 8744 soc_reg_field_set(unit, THDI_PORT_PG_SPIDr, &rval, 8745 prigroup_spid_field[idx], 8746 buf_port->prigroups[idx].pool_idx); 8747 } 8748 SOC_IF_ERROR_RETURN(WRITE_THDI_PORT_PG_SPIDr(unit, port, rval)); 8749 8750 /* Per port per pool settings */ 8751 mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdi_port_mem[0])[pipe]; 8752 if (mem0 == INVALIDm) { 8753 continue; 8754 } 8755 for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) { 8756 buf_port_pool = &buf_port->pools[idx]; 8757 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, port, mmu_thdi_port_mem[0], 8758 idx); 8759 sal_memset(&thdi_sp_config, 0, sizeof(thdi_sp_config)); 8760 soc_mem_field32_set(unit, mem0, &thdi_sp_config, 8761 PORT_SP_MIN_LIMITf, buf_port_pool->guarantee); 8762 soc_mem_field32_set(unit, mem0, &thdi_sp_config, 8763 PORT_SP_RESUME_LIMITf, buf_port_pool->pool_resume); 8764 soc_mem_field32_set(unit, mem0, &thdi_sp_config, 8765 PORT_SP_MAX_LIMITf, buf_port_pool->pool_limit); 8766 SOC_IF_ERROR_RETURN 8767 (soc_mem_write(unit, mem0, MEM_BLOCK_ALL, 8768 midx, &thdi_sp_config)); 8769 } 8770 8771 fval = 0; 8772 for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) { 8773 if (buf_port->prigroups[idx].flow_control_enable != 0) { 8774 for (pri=0; pri < 16; pri++) { 8775 if (buf_port->pri_to_prigroup[pri] == idx) { 8776 fval |= 1 << pri; 8777 } 8778 } 8779 } 8780 } 8781 8782 rval = 0; 8783 soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval, 8784 INPUT_PORT_RX_ENABLEf, 1); 8785 soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval, 8786 PORT_PRI_XON_ENABLEf, fval); 8787 soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval, 8788 PORT_PAUSE_ENABLEf, fval ? 1 : 0); 8789 SOC_IF_ERROR_RETURN(WRITE_THDI_INPUT_PORT_XON_ENABLESr(unit, 8790 port, rval)); 8791 8792 rval = 0; 8793 soc_reg_field_set(unit, THDI_PORT_MAX_PKT_SIZEr, &rval, 8794 PORT_MAX_PKT_SIZEf, buf_port->pkt_size); 8795 SOC_IF_ERROR_RETURN(WRITE_THDI_PORT_MAX_PKT_SIZEr(unit, rval)); 8796 8797 /* Input port per port per priority group settings */ 8798 mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdi_port_mem[1])[pipe]; 8799 if (mem1 == INVALIDm) { 8800 continue; 8801 } 8802 for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) 8803 { 8804 buf_prigroup = &buf->ports[port].prigroups[idx]; 8805 8806 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, port, mmu_thdi_port_mem[1], 8807 idx); 8808 sal_memset(&pg_config_mem, 0, sizeof(pg_config_mem)); 8809 soc_mem_field32_set(unit, mem1, &pg_config_mem, 8810 PG_MIN_LIMITf, buf_prigroup->guarantee); 8811 8812 if (buf_prigroup->pool_scale != -1) { 8813 soc_mem_field32_set(unit, mem1, &pg_config_mem, 8814 PG_SHARED_DYNAMICf, 1); 8815 soc_mem_field32_set(unit, mem1, &pg_config_mem, 8816 PG_SHARED_LIMITf, 8817 buf_prigroup->pool_scale); 8818 } else { 8819 if (buf_prigroup->pool_limit == DEFAULT_VALUE_MAGIC) { 8820 soc_mem_field32_set(unit, mem1, &pg_config_mem, 8821 PG_SHARED_LIMITf, 8822 ing_limit); 8823 } else { 8824 soc_mem_field32_set(unit, mem1, &pg_config_mem, 8825 PG_SHARED_LIMITf, 8826 buf_prigroup->pool_limit); 8827 } 8828 } 8829 8830 soc_mem_field32_set(unit, mem1, &pg_config_mem, 8831 PG_GBL_HDRM_ENf, 8832 buf_prigroup->device_headroom_enable); 8833 soc_mem_field32_set(unit, mem1, &pg_config_mem, 8834 PG_HDRM_LIMITf, buf_prigroup->headroom); 8835 8836 soc_mem_field32_set(unit, mem1, &pg_config_mem, 8837 PG_RESET_OFFSETf, buf_prigroup->pool_resume / 8); 8838 8839 soc_mem_field32_set(unit, mem1, &pg_config_mem, 8840 PG_RESET_FLOORf, buf_prigroup->pool_floor); 8841 8842 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem1, 8843 MEM_BLOCK_ALL, midx, 8844 &pg_config_mem)); 8845 } 8846 } 8847 8848 8849 /*********************************** 8850 * THDO 8851 */ 8852 /* output thresholds */ 8853 SOC_IF_ERROR_RETURN(READ_OP_THDU_CONFIGr(unit, &rval)); 8854 soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval, 8855 ENABLE_QUEUE_AND_GROUP_TICKETf, 1); 8856 soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval, 8857 ENABLE_UPDATE_COLOR_RESUMEf, 0); 8858 soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval, MOP_POLICY_1Bf, 1); 8859 soc_reg_field_set(unit, OP_THDU_CONFIGr, &rval, MOP_POLICY_1Af, 0); 8860 SOC_IF_ERROR_RETURN(WRITE_OP_THDU_CONFIGr(unit, rval)); 8861 8862 rval = 0; 8863 SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, &rval)); 8864 soc_reg_field_set(unit, MMU_THDM_DB_DEVICE_THR_CONFIGr, &rval, 8865 MOP_POLICYf, 1); 8866 SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, rval)); 8867 8868 /* Output port per port per queue setting for regular multicast queue */ 8869 cpu_mcqe_rsvd = 0; 8870 total_mcqe_rsvd = 0; 8871 egr_limit = 0; 8872 8873 port = CMIC_PORT(unit); 8874 numq = si->port_num_cosq[port]; 8875 for (idx = 0; idx < numq; idx++) { 8876 buf_queue = &buf->ports[port].queues[idx]; 8877 cpu_mcqe_rsvd += buf_queue->mcq_entry_guarantee; 8878 } 8879 8880 /* per service pool settings */ 8881 for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) { 8882 buf_pool = &buf->pools[idx]; 8883 if ((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) == 0) { 8884 continue; 8885 } 8886 8887 queue_guarantee = egr_rsvd; 8888 if (lossless == 0) { 8889 queue_guarantee += (lb_q_min + cpu_q_min + mgmt_q_min); 8890 } 8891 limit = buf_pool->total - (queue_guarantee + asf_rsvd + rqe_rsvd); 8892 8893 if (limit <= 0) { 8894 limit = 0; 8895 } 8896 egr_limit = limit; 8897 8898 rval = 0; 8899 soc_reg_field_set(unit, MMU_THDM_DB_POOL_SHARED_LIMITr, &rval, 8900 SHARED_LIMITf, limit); 8901 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 8902 MMU_THDM_DB_POOL_SHARED_LIMITr, -1, -1, idx, rval)); 8903 8904 rval = 0; 8905 soc_reg_field_set(unit, MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr, 8906 &rval, YELLOW_SHARED_LIMITf, sal_ceil_func(limit, 8)); 8907 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 8908 MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr, -1, -1, idx, rval)); 8909 8910 rval = 0; 8911 soc_reg_field_set(unit, MMU_THDM_DB_POOL_RED_SHARED_LIMITr, 8912 &rval, RED_SHARED_LIMITf, sal_ceil_func(limit, 8)); 8913 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 8914 MMU_THDM_DB_POOL_RED_SHARED_LIMITr, -1, -1, idx, rval)); 8915 8916 rval = 0; 8917 soc_reg_field_set(unit, MMU_THDM_DB_POOL_RESUME_LIMITr, 8918 &rval, RESUME_LIMITf, sal_ceil_func(limit, 8)); 8919 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 8920 MMU_THDM_DB_POOL_RESUME_LIMITr, -1, -1, idx, rval)); 8921 8922 rval = 0; 8923 soc_reg_field_set(unit, MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr, 8924 &rval, YELLOW_RESUME_LIMITf, sal_ceil_func(limit, 8)); 8925 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 8926 MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr, -1, -1, idx, rval)); 8927 8928 rval = 0; 8929 soc_reg_field_set(unit, MMU_THDM_DB_POOL_RED_RESUME_LIMITr, 8930 &rval, RED_RESUME_LIMITf, sal_ceil_func(limit, 8)); 8931 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 8932 MMU_THDM_DB_POOL_RED_RESUME_LIMITr, -1, -1, idx, rval)); 8933 8934 /* mcq entries */ 8935 total_mcqe_rsvd = ((buf_pool->mcq_entry_reserved - 8936 cpu_mcqe_rsvd) >> 1) + cpu_mcqe_rsvd; 8937 limit = buf_pool->total_mcq_entry - total_mcqe_rsvd; 8938 if (limit <= 0) { 8939 continue; 8940 } 8941 8942 rval = 0; 8943 soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_SHARED_LIMITr, 8944 &rval, SHARED_LIMITf, limit/4); 8945 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 8946 MMU_THDM_MCQE_POOL_SHARED_LIMITr, -1, -1, idx, rval)); 8947 8948 rval = 0; 8949 soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_YELLOW_SHARED_LIMITr, 8950 &rval, YELLOW_SHARED_LIMITf, limit/8); 8951 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 8952 MMU_THDM_MCQE_POOL_YELLOW_SHARED_LIMITr, -1, -1, idx, rval)); 8953 8954 rval = 0; 8955 soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_RED_SHARED_LIMITr, 8956 &rval, RED_SHARED_LIMITf, limit/8); 8957 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 8958 MMU_THDM_MCQE_POOL_RED_SHARED_LIMITr, -1, -1, idx, rval)); 8959 8960 rval = 0; 8961 soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_RESUME_LIMITr, 8962 &rval, RESUME_LIMITf, limit/8); 8963 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 8964 MMU_THDM_MCQE_POOL_RESUME_LIMITr, -1, -1, idx, rval)); 8965 8966 rval = 0; 8967 soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_YELLOW_RESUME_LIMITr, 8968 &rval, YELLOW_RESUME_LIMITf, limit/8); 8969 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 8970 MMU_THDM_MCQE_POOL_YELLOW_RESUME_LIMITr, -1, -1, idx, rval)); 8971 8972 rval = 0; 8973 soc_reg_field_set(unit, MMU_THDM_MCQE_POOL_RED_RESUME_LIMITr, 8974 &rval, RED_RESUME_LIMITf, limit/8); 8975 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 8976 MMU_THDM_MCQE_POOL_RED_RESUME_LIMITr, -1, -1, idx, rval)); 8977 } 8978 8979 8980 PBMP_ALL_ITER(unit, port) { 8981 pipe = si->port_pipe[port]; 8982 numq = si->port_num_cosq[port]; 8983 qbase = si->port_cosq_base[port]; 8984 if (numq == 0) { 8985 continue; 8986 } 8987 8988 mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_mc_mem[0])[pipe]; 8989 mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_mc_mem[1])[pipe]; 8990 if ((mem0 == INVALIDm) || (mem1 == INVALIDm)) { 8991 continue; 8992 } 8993 base = qbase; 8994 for (idx = 0; idx < numq; idx++) { 8995 buf_queue = &buf->ports[port].queues[idx]; 8996 sal_memset(entry0, 0, sizeof(mmu_thdm_db_queue_config_0_entry_t)); 8997 8998 soc_mem_field32_set(unit, mem0, entry0, 8999 Q_MIN_LIMITf, buf_queue->guarantee); 9000 if (buf_queue->discard_enable) { 9001 soc_mem_field32_set(unit, mem0, entry0, Q_LIMIT_ENABLEf, 1); 9002 } 9003 if (buf_queue->color_discard_enable) { 9004 soc_mem_field32_set(unit, mem0, entry0, Q_COLOR_LIMIT_ENABLEf, 9005 1); 9006 } 9007 if (buf_queue->pool_scale != -1) { 9008 soc_mem_field32_set(unit, mem0, entry0, Q_LIMIT_DYNAMICf, 1); 9009 soc_mem_field32_set(unit, mem0, entry0, 9010 Q_SHARED_ALPHAf, buf_queue->pool_scale); 9011 } else { 9012 /* Q_LIMIT_DYNAMIC_CELLf is 0 */ 9013 soc_mem_field32_set(unit, mem0, entry0, 9014 Q_SHARED_LIMITf, egr_limit); 9015 } 9016 if ((buf_queue->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) || 9017 (buf_queue->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) { 9018 soc_mem_field32_set(unit, mem0, entry0, 9019 Q_COLOR_LIMIT_DYNAMICf, 1); 9020 soc_mem_field32_set(unit, mem0, entry0, YELLOW_SHARED_LIMITf, 9021 buf_queue->yellow_limit 9022 & ~_MMU_CFG_BUF_DYNAMIC_FLAG 9023 & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1); 9024 soc_mem_field32_set(unit, mem0, entry0, RED_SHARED_LIMITf, 9025 buf_queue->red_limit 9026 & ~_MMU_CFG_BUF_DYNAMIC_FLAG 9027 & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1); 9028 } else { 9029 /* Q_COLOR_LIMIT_DYNAMIC_CELLf is 0 */ 9030 soc_mem_field32_set(unit, mem0, entry0, YELLOW_SHARED_LIMITf, 9031 sal_ceil_func(egr_limit, 8)); 9032 soc_mem_field32_set(unit, mem0, entry0, RED_SHARED_LIMITf, 9033 sal_ceil_func(egr_limit, 8)); 9034 } 9035 9036 soc_mem_field32_set(unit, mem0, entry0, 9037 Q_SPIDf, buf_queue->pool_idx); 9038 9039 SOC_IF_ERROR_RETURN 9040 (soc_mem_write(unit, mem0, MEM_BLOCK_ALL, base + idx, entry0)); 9041 9042 sal_memset(entry0, 0, sizeof(mmu_thdm_db_queue_offset_entry_t)); 9043 9044 soc_mem_field32_set(unit, mem1, entry0, RESUME_OFFSETf, 2); 9045 soc_mem_field32_set(unit, mem1, entry0, 9046 YELLOW_RESUME_OFFSET_PROFILE_SELf, 0); 9047 soc_mem_field32_set(unit, mem1, entry0, 9048 RED_RESUME_OFFSET_PROFILE_SELf, 0); 9049 SOC_IF_ERROR_RETURN 9050 (soc_mem_write(unit, mem1, MEM_BLOCK_ALL, base + idx, 9051 entry0)); 9052 9053 rval = 0; 9054 SOC_IF_ERROR_RETURN( 9055 WRITE_MMU_THDM_DB_QUEUE_RESUME_OFFSET_PROFILE_YELLOWr(unit, 0, 9056 2)); 9057 9058 rval = 0; 9059 SOC_IF_ERROR_RETURN( 9060 WRITE_MMU_THDM_DB_QUEUE_RESUME_OFFSET_PROFILE_REDr(unit, 0, 2)); 9061 } 9062 9063 mem2 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_mc_mem[2])[pipe]; 9064 mem3 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_mc_mem[3])[pipe]; 9065 if ((mem2 == INVALIDm) || (mem3 == INVALIDm)) { 9066 continue; 9067 } 9068 9069 for (idx = 0; idx < numq; idx++) { 9070 buf_queue = &buf->ports[port].queues[idx]; 9071 buf_pool = &buf->pools[buf_queue->pool_idx]; 9072 if (buf_pool->total == 0) { 9073 continue; 9074 } 9075 total_mcqe_rsvd = ((buf_pool->mcq_entry_reserved - 9076 cpu_mcqe_rsvd) >> 1) + cpu_mcqe_rsvd; 9077 limit = buf_pool->total_mcq_entry - total_mcqe_rsvd; 9078 if (limit <= 0) { 9079 continue; 9080 } 9081 9082 sal_memset(entry0, 0, sizeof(mmu_thdm_mcqe_queue_config_entry_t)); 9083 9084 soc_mem_field32_set(unit, mem2, entry0, 9085 Q_MIN_LIMITf, 9086 buf_queue->mcq_entry_guarantee/4); 9087 9088 if (buf_queue->discard_enable) { 9089 soc_mem_field32_set(unit, mem2, entry0, Q_LIMIT_ENABLEf, 1); 9090 } 9091 if (buf_queue->color_discard_enable) { 9092 soc_mem_field32_set(unit, mem2, entry0, Q_COLOR_LIMIT_ENABLEf, 9093 1); 9094 } 9095 if (buf_queue->pool_scale != -1) { 9096 soc_mem_field32_set(unit, mem2, entry0, Q_LIMIT_DYNAMICf, 1); 9097 soc_mem_field32_set(unit, mem2, entry0, 9098 Q_SHARED_ALPHAf, 9099 buf_queue->pool_scale); 9100 } else { 9101 /* Q_LIMIT_DYNAMIC_CELLf is 0 */ 9102 soc_mem_field32_set(unit, mem2, entry0, 9103 Q_SHARED_LIMITf, limit/4); 9104 } 9105 if ((buf_queue->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) || 9106 (buf_queue->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) { 9107 soc_mem_field32_set(unit, mem2, entry0, 9108 Q_COLOR_LIMIT_DYNAMICf, 1); 9109 soc_mem_field32_set(unit, mem2, entry0, YELLOW_SHARED_LIMITf, 9110 buf_queue->yellow_limit 9111 & ~_MMU_CFG_BUF_DYNAMIC_FLAG 9112 & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1); 9113 soc_mem_field32_set(unit, mem2, entry0, RED_SHARED_LIMITf, 9114 buf_queue->red_limit 9115 & ~_MMU_CFG_BUF_DYNAMIC_FLAG 9116 & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1); 9117 } else { 9118 /* Q_COLOR_LIMIT_DYNAMIC_CELLf is 0 */ 9119 soc_mem_field32_set(unit, mem2, entry0, YELLOW_SHARED_LIMITf, 9120 limit / 8); 9121 soc_mem_field32_set(unit, mem2, entry0, RED_SHARED_LIMITf, 9122 limit / 8); 9123 9124 } 9125 9126 soc_mem_field32_set(unit, mem2, entry0, 9127 Q_SPIDf, buf_queue->pool_idx); 9128 9129 SOC_IF_ERROR_RETURN 9130 (soc_mem_write(unit, mem2, MEM_BLOCK_ALL, base + idx, entry0)); 9131 9132 sal_memset(entry0, 0, sizeof(mmu_thdm_mcqe_queue_offset_entry_t)); 9133 9134 soc_mem_field32_set(unit, mem3, entry0, RESUME_OFFSETf, 1); 9135 soc_mem_field32_set(unit, mem3, entry0, 9136 YELLOW_RESUME_OFFSET_PROFILE_SELf, 0); 9137 soc_mem_field32_set(unit, mem3, entry0, 9138 RED_RESUME_OFFSET_PROFILE_SELf, 0); 9139 SOC_IF_ERROR_RETURN 9140 (soc_mem_write(unit, mem3, MEM_BLOCK_ALL, base + idx, entry0)); 9141 9142 rval = 0; 9143 SOC_IF_ERROR_RETURN( 9144 WRITE_MMU_THDM_MCQE_QUEUE_RESUME_OFFSET_PROFILE_YELLOWr(unit, 0, 9145 1)); 9146 9147 rval = 0; 9148 SOC_IF_ERROR_RETURN( 9149 WRITE_MMU_THDM_MCQE_QUEUE_RESUME_OFFSET_PROFILE_REDr(unit, 0, 9150 1)); 9151 } 9152 9153 /* Per port per pool */ 9154 for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) { 9155 buf_port_pool = &buf->ports[port].pools[idx]; 9156 if (buf_port_pool->pool_limit == 0) { 9157 continue; 9158 } 9159 9160 limit = buf_port_pool->pool_limit; 9161 rlimit = limit - (default_mtu_cells * 2); 9162 9163 mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_port_mc_mem[0])[pipe]; 9164 if (mem0 == INVALIDm) { 9165 continue; 9166 } 9167 9168 index1 = SOC_TH_MMU_PIPED_MEM_INDEX(unit, port, 9169 mmu_thdo_port_mc_mem[0], 9170 idx); 9171 sal_memset(entry0, 0, sizeof(mmu_thdm_db_portsp_config_entry_t)); 9172 9173 soc_mem_field32_set(unit, mem0, entry0, SHARED_LIMITf, limit); 9174 soc_mem_field32_set(unit, mem0, entry0, RED_SHARED_LIMITf, 9175 limit/8); 9176 soc_mem_field32_set(unit, mem0, entry0, YELLOW_SHARED_LIMITf, 9177 limit/8); 9178 9179 soc_mem_field32_set(unit, mem0, entry0, SHARED_LIMIT_ENABLEf, 9180 !lossless); 9181 9182 soc_mem_field32_set(unit, mem0, entry0, SHARED_RESUME_LIMITf, 9183 rlimit/8); 9184 soc_mem_field32_set(unit, mem0, entry0, YELLOW_RESUME_LIMITf, 9185 rlimit/8); 9186 soc_mem_field32_set(unit, mem0, entry0, RED_RESUME_LIMITf, 9187 rlimit/8); 9188 9189 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem0, MEM_BLOCK_ALL, 9190 index1, entry0)); 9191 9192 mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_port_mc_mem[1])[pipe]; 9193 if (mem1 == INVALIDm) { 9194 continue; 9195 } 9196 buf_pool = &buf->pools[idx]; 9197 sal_memset(entry0, 0, sizeof(mmu_thdm_mcqe_portsp_config_entry_t)); 9198 9199 /* Use the Sky high value of MCQE, not the limit after reservation */ 9200 limit = _TH_MMU_TOTAL_MCQ_ENTRY(unit); 9201 if (limit <= 0) { 9202 continue; 9203 } 9204 9205 soc_mem_field32_set(unit, mem1, entry0, SHARED_LIMITf, (limit/4) - 1); 9206 soc_mem_field32_set(unit, mem1, entry0, YELLOW_SHARED_LIMITf, 9207 (limit/8) - 1); 9208 soc_mem_field32_set(unit, mem1, entry0, RED_SHARED_LIMITf, 9209 (limit/8) - 1); 9210 9211 soc_mem_field32_set(unit, mem1, entry0, SHARED_LIMIT_ENABLEf, 9212 !lossless); 9213 9214 soc_mem_field32_set(unit, mem1, entry0, SHARED_RESUME_LIMITf, 9215 (limit/8) - 2); 9216 soc_mem_field32_set(unit, mem1, entry0, YELLOW_RESUME_LIMITf, 9217 (limit/8) - 2); 9218 soc_mem_field32_set(unit, mem1, entry0, RED_RESUME_LIMITf, 9219 (limit/8) - 2); 9220 9221 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem1, MEM_BLOCK_ALL, 9222 index1, entry0)); 9223 } 9224 } 9225 9226 /* Output port per port per queue setting for regular unicast queue */ 9227 PBMP_ALL_ITER(unit, port) { 9228 pipe = si->port_pipe[port]; 9229 /* Per port per pool unicast */ 9230 for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) { 9231 buf_pool = &buf->pools[idx]; 9232 9233 if (buf_pool->total == 0) { 9234 continue; 9235 } 9236 9237 limit = buf_pool->total; 9238 9239 mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_port_uc_mem[0])[pipe]; 9240 mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_port_uc_mem[1])[pipe]; 9241 if ((mem0 == INVALIDm) || (mem1 == INVALIDm)) { 9242 continue; 9243 } 9244 index1 = SOC_TH_MMU_PIPED_MEM_INDEX(unit, port, 9245 mmu_thdo_port_uc_mem[0], 9246 idx); 9247 sal_memset(entry0, 0, sizeof(mmu_thdu_config_port_entry_t)); 9248 sal_memset(entry1, 0, sizeof(mmu_thdu_resume_port_entry_t)); 9249 9250 soc_mem_field32_set(unit, mem0, entry0, SHARED_LIMITf, limit); 9251 soc_mem_field32_set(unit, mem1, entry1, 9252 SHARED_RESUMEf, 9253 (limit - (default_mtu_cells * 2))/8); 9254 9255 soc_mem_field32_set(unit, mem0, entry0, YELLOW_LIMITf, limit/8); 9256 soc_mem_field32_set(unit, mem1, entry1, 9257 YELLOW_RESUMEf, 9258 (limit - (default_mtu_cells*2))/8); 9259 9260 soc_mem_field32_set(unit, mem0, entry0, RED_LIMITf, limit/8); 9261 soc_mem_field32_set(unit, mem1, entry1, 9262 RED_RESUMEf, 9263 (limit - (default_mtu_cells * 2))/8); 9264 9265 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem0, MEM_BLOCK_ALL, 9266 index1, entry0)); 9267 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem1, MEM_BLOCK_ALL, 9268 index1, entry1)); 9269 } 9270 9271 /* per port regular unicast queue */ 9272 numq = si->port_num_uc_cosq[port]; 9273 qbase = si->port_uc_cosq_base[port]; 9274 9275 if (numq == 0) { 9276 continue; 9277 } 9278 base = qbase; 9279 9280 mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_uc_mem[0])[pipe]; 9281 mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_uc_mem[1])[pipe]; 9282 mem2 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_q_uc_mem[2])[pipe]; 9283 if ((mem0 == INVALIDm) || (mem1 == INVALIDm) || (mem2 == INVALIDm)) { 9284 continue; 9285 } 9286 for (idx = 0; idx < numq; idx++) { 9287 buf_queue = &buf->ports[port].queues[si->port_num_cosq[port] + idx]; 9288 9289 sal_memset(entry0, 0, sizeof(mmu_thdu_config_queue_entry_t)); 9290 sal_memset(entry1, 0, sizeof(mmu_thdu_offset_queue_entry_t)); 9291 9292 soc_mem_field32_set(unit, mem0, entry0, 9293 Q_MIN_LIMIT_CELLf, buf_queue->guarantee); 9294 if (buf_queue->pool_scale != -1) { 9295 soc_mem_field32_set(unit, mem0, entry0, Q_LIMIT_DYNAMIC_CELLf, 9296 1); 9297 soc_mem_field32_set(unit, mem0, entry0, 9298 Q_SHARED_ALPHA_CELLf, 9299 buf_queue->pool_scale); 9300 } else { 9301 /* Q_LIMIT_DYNAMIC_CELLf is 0 */ 9302 soc_mem_field32_set(unit, mem0, entry0, 9303 Q_SHARED_LIMIT_CELLf, egr_limit); 9304 } 9305 soc_mem_field32_set(unit, mem1, entry1, RESET_OFFSET_CELLf, 9306 buf_queue->pool_resume / 8); 9307 9308 if ((buf_queue->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) || 9309 (buf_queue->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) { 9310 soc_mem_field32_set(unit, mem0, entry0, 9311 Q_COLOR_LIMIT_DYNAMIC_CELLf, 1); 9312 soc_mem_field32_set(unit, mem0, entry0, LIMIT_YELLOW_CELLf, 9313 buf_queue->yellow_limit 9314 & ~_MMU_CFG_BUF_DYNAMIC_FLAG 9315 & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1); 9316 soc_mem_field32_set(unit, mem0, entry0, LIMIT_RED_CELLf, 9317 buf_queue->red_limit 9318 & ~_MMU_CFG_BUF_DYNAMIC_FLAG 9319 & ~_MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1); 9320 } else { 9321 /* Q_COLOR_LIMIT_DYNAMIC_CELLf is 0 */ 9322 soc_mem_field32_set(unit, mem0, entry0, LIMIT_YELLOW_CELLf, 9323 sal_ceil_func(egr_limit, 8)); 9324 soc_mem_field32_set(unit, mem0, entry0, LIMIT_RED_CELLf, 9325 sal_ceil_func(egr_limit, 8)); 9326 } 9327 soc_mem_field32_set(unit, mem1, entry1, RESET_OFFSET_YELLOW_CELLf, 9328 buf_queue->yellow_resume / 8); 9329 soc_mem_field32_set(unit, mem1, entry1, RESET_OFFSET_RED_CELLf, 9330 buf_queue->red_resume / 8); 9331 SOC_IF_ERROR_RETURN 9332 (soc_mem_write(unit, mem0, MEM_BLOCK_ALL, base + idx, entry0)); 9333 9334 SOC_IF_ERROR_RETURN 9335 (soc_mem_write(unit, mem1, MEM_BLOCK_ALL, base + idx, entry1)); 9336 9337 sal_memset(entry0, 0, sizeof(mmu_thdo_q_to_qgrp_map_entry_t)); 9338 soc_mem_field32_set(unit, mem2, entry0, 9339 Q_SPIDf, buf_queue->pool_idx); 9340 9341 if (buf_queue->discard_enable) { 9342 soc_mem_field32_set(unit, mem2, entry0, 9343 Q_LIMIT_ENABLEf, 1); 9344 } 9345 if (buf_queue->color_discard_enable) { 9346 soc_mem_field32_set(unit, mem2, entry0, 9347 Q_COLOR_ENABLE_CELLf, 1); 9348 } 9349 9350 9351 if (buf_queue->qgroup_id >= 0) { 9352 soc_mem_field32_set(unit, mem2, entry0, QGROUP_VALIDf, 1); 9353 if (buf_queue->qgroup_min_enable) { 9354 soc_mem_field32_set(unit, mem2, entry0, USE_QGROUP_MINf, 1); 9355 } 9356 } 9357 9358 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem2, MEM_BLOCK_ALL, 9359 base + idx, entry0)); 9360 } 9361 9362 } 9363 9364 /* configure Q-groups */ 9365 for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) { 9366 for (idx = 0; idx < SOC_TH_MMU_CFG_QGROUP_MAX; idx++) { 9367 mem0 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_qgrp_uc_mem[0])[pipe]; 9368 mem1 = SOC_MEM_UNIQUE_ACC(unit, mmu_thdo_qgrp_uc_mem[1])[pipe]; 9369 if ((mem0 == INVALIDm) || (mem1 == INVALIDm)) { 9370 continue; 9371 } 9372 queue_grp = &buf->qgroups[idx]; 9373 9374 sal_memset(&cfg_qgrp, 0, sizeof(cfg_qgrp)); 9375 sal_memset(&offset_qgrp, 0, sizeof(offset_qgrp)); 9376 9377 soc_mem_field32_set(unit, mem0, &cfg_qgrp, 9378 Q_MIN_LIMIT_CELLf, queue_grp->guarantee); 9379 9380 if (queue_grp->pool_scale != -1) { 9381 soc_mem_field32_set(unit, mem0, &cfg_qgrp, 9382 Q_SHARED_ALPHA_CELLf, 9383 queue_grp->pool_scale); 9384 soc_mem_field32_set(unit, mem0, &cfg_qgrp, 9385 Q_LIMIT_DYNAMIC_CELLf, 1); 9386 } else { 9387 soc_mem_field32_set(unit, mem0, &cfg_qgrp, 9388 Q_SHARED_LIMIT_CELLf, egr_limit); 9389 } 9390 9391 if ((queue_grp->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) || 9392 (queue_grp->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) { 9393 soc_mem_field32_set(unit, mem0, &cfg_qgrp, 9394 Q_COLOR_LIMIT_DYNAMIC_CELLf, 1); 9395 } 9396 9397 if (queue_grp->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) { 9398 pval = _soc_th_pool_scale_to_limit(queue_grp->pool_limit, 9399 queue_grp->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG); 9400 soc_mem_field32_set(unit, mem0, &cfg_qgrp, 9401 LIMIT_RED_CELLf, pval/8); 9402 9403 } else { 9404 soc_mem_field32_set(unit, mem0, &cfg_qgrp, 9405 LIMIT_RED_CELLf, egr_limit / 8); 9406 } 9407 9408 if (queue_grp->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) { 9409 pval = _soc_th_pool_scale_to_limit(queue_grp->pool_limit, 9410 queue_grp->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG); 9411 soc_mem_field32_set(unit, mem0, &cfg_qgrp, 9412 LIMIT_YELLOW_CELLf, pval/8); 9413 9414 } else { 9415 soc_mem_field32_set(unit, mem0, &cfg_qgrp, 9416 LIMIT_YELLOW_CELLf, egr_limit / 8); 9417 } 9418 9419 soc_mem_field32_set(unit, mem1, &offset_qgrp, 9420 RESET_OFFSET_CELLf, 9421 queue_grp->pool_resume / 8); 9422 soc_mem_field32_set(unit, mem1, &offset_qgrp, 9423 RESET_OFFSET_YELLOW_CELLf, 9424 queue_grp->pool_resume / 8); 9425 soc_mem_field32_set(unit, mem1, &offset_qgrp, 9426 RESET_OFFSET_RED_CELLf, 9427 queue_grp->pool_resume / 8); 9428 SOC_IF_ERROR_RETURN 9429 (soc_mem_write(unit, mem0, MEM_BLOCK_ALL, idx, &cfg_qgrp)); 9430 SOC_IF_ERROR_RETURN 9431 (soc_mem_write(unit, mem1, MEM_BLOCK_ALL, idx, &offset_qgrp)); 9432 } 9433 } 9434 9435 9436 /* RQE */ 9437 for (idx = 0; idx < _TH_MMU_NUM_RQE_QUEUES; idx++) { 9438 buf_rqe_queue = &buf->rqe_queues[idx]; 9439 9440 rval = 0; 9441 soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_MIN_PRIQr, 9442 &rval, MIN_LIMITf, buf_rqe_queue->guarantee); 9443 SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_LIMIT_MIN_PRIQr(unit, idx, rval)); 9444 9445 rval = 0; 9446 rval2 = 0; 9447 rval3 = 0; 9448 soc_reg_field_set(unit, MMU_THDR_DB_CONFIG1_PRIQr, 9449 &rval, SPIDf, buf_rqe_queue->pool_idx); 9450 9451 if ((buf_rqe_queue->red_limit & _MMU_CFG_BUF_DYNAMIC_FLAG) || 9452 (buf_rqe_queue->yellow_limit & _MMU_CFG_BUF_DYNAMIC_FLAG)) { 9453 soc_reg_field_set(unit, MMU_THDR_DB_CONFIG1_PRIQr, 9454 &rval, COLOR_LIMIT_DYNAMICf, 1); 9455 soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_COLOR_PRIQr, &rval3, 9456 SHARED_RED_LIMITf, 9457 buf_rqe_queue->red_limit & ~_MMU_CFG_BUF_DYNAMIC_FLAG); 9458 soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_COLOR_PRIQr, &rval3, 9459 SHARED_YELLOW_LIMITf, 9460 buf_rqe_queue->yellow_limit & ~_MMU_CFG_BUF_DYNAMIC_FLAG); 9461 } else { 9462 soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_COLOR_PRIQr, &rval3, 9463 SHARED_RED_LIMITf, buf_rqe_queue->red_limit / 8); 9464 9465 soc_reg_field_set(unit, MMU_THDR_DB_LIMIT_COLOR_PRIQr, &rval3, 9466 SHARED_YELLOW_LIMITf, buf_rqe_queue->yellow_limit / 8); 9467 } 9468 9469 soc_reg_field_set(unit, MMU_THDR_DB_CONFIG1_PRIQr, &rval, LIMIT_ENABLEf, 9470 (buf_rqe_queue->discard_enable ? 1 : 0)); 9471 9472 if (buf_rqe_queue->pool_scale != -1) { 9473 soc_reg_field_set(unit, MMU_THDR_DB_CONFIG1_PRIQr, 9474 &rval, DYNAMIC_ENABLEf, 1); 9475 soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_PRIQr, &rval2, 9476 SHARED_ALPHAf, buf_rqe_queue->pool_scale); 9477 } else { 9478 soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_PRIQr, &rval2, 9479 SHARED_LIMITf, buf_rqe_queue->pool_limit); 9480 } 9481 soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_PRIQr, &rval2, 9482 RESET_OFFSETf, 2); 9483 9484 SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_CONFIG1_PRIQr(unit, idx, rval)); 9485 SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_CONFIG_PRIQr_REG32(unit, idx, rval2)); 9486 SOC_IF_ERROR_RETURN 9487 (WRITE_MMU_THDR_DB_LIMIT_COLOR_PRIQr(unit, idx, rval3)); 9488 9489 rval = 0; 9490 soc_reg_field_set(unit, MMU_THDR_DB_RESET_OFFSET_COLOR_PRIQr, 9491 &rval, RESET_OFFSET_REDf, 2); 9492 soc_reg_field_set(unit, MMU_THDR_DB_RESET_OFFSET_COLOR_PRIQr, 9493 &rval, RESET_OFFSET_YELLOWf, 2); 9494 SOC_IF_ERROR_RETURN 9495 (WRITE_MMU_THDR_DB_RESET_OFFSET_COLOR_PRIQr(unit, idx, rval)); 9496 9497 /* queue entry */ 9498 buf_pool = &buf->pools[buf_rqe_queue->pool_idx]; 9499 fval = (buf_pool->total_rqe_entry + 8 * 11 - 1) / (8 * 11); 9500 rval = 0; 9501 soc_reg_field_set(unit, MMU_THDR_QE_LIMIT_MIN_PRIQr, 9502 &rval, MIN_LIMITf, buf_rqe_queue->guarantee/8); 9503 SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_LIMIT_MIN_PRIQr(unit, idx, rval)); 9504 9505 rval = 0; 9506 rval2 = 0; 9507 rval3 = 0; 9508 soc_reg_field_set(unit, MMU_THDR_QE_CONFIG1_PRIQr, 9509 &rval, SPIDf, buf_rqe_queue->pool_idx); 9510 9511 9512 soc_reg_field_set(unit, MMU_THDR_QE_CONFIG1_PRIQr, &rval, LIMIT_ENABLEf, 9513 (buf_rqe_queue->discard_enable ? 1 : 0)); 9514 9515 if (buf_rqe_queue->pool_scale != -1) { 9516 soc_reg_field_set(unit, MMU_THDR_DB_CONFIG1_PRIQr, 9517 &rval, DYNAMIC_ENABLEf, 1); 9518 soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_PRIQr, &rval2, 9519 SHARED_ALPHAf, buf_rqe_queue->pool_scale); 9520 soc_reg_field_set(unit, MMU_THDR_QE_LIMIT_COLOR_PRIQr, 9521 &rval3, SHARED_RED_LIMITf, 0); 9522 soc_reg_field_set(unit, MMU_THDR_QE_LIMIT_COLOR_PRIQr, 9523 &rval3, SHARED_YELLOW_LIMITf, 0); 9524 soc_reg_field_set(unit, MMU_THDR_QE_CONFIG1_PRIQr, 9525 &rval, COLOR_LIMIT_DYNAMICf, 1); 9526 } else { 9527 soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_PRIQr, &rval2, 9528 SHARED_LIMITf, fval); 9529 soc_reg_field_set(unit, MMU_THDR_QE_LIMIT_COLOR_PRIQr, 9530 &rval3, SHARED_RED_LIMITf, fval); 9531 soc_reg_field_set(unit, MMU_THDR_QE_LIMIT_COLOR_PRIQr, 9532 &rval3, SHARED_YELLOW_LIMITf, fval); 9533 soc_reg_field_set(unit, MMU_THDR_QE_CONFIG1_PRIQr, 9534 &rval, COLOR_LIMIT_DYNAMICf, 0); 9535 } 9536 soc_reg_field_set(unit, MMU_THDR_QE_CONFIG_PRIQr, &rval2, 9537 RESET_OFFSETf, 1); 9538 9539 SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_CONFIG1_PRIQr(unit, idx, rval)); 9540 SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_CONFIG_PRIQr(unit, idx, rval2)); 9541 SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_LIMIT_COLOR_PRIQr(unit, idx, rval3)); 9542 9543 rval = 0; 9544 soc_reg_field_set(unit, MMU_THDR_QE_RESET_OFFSET_COLOR_PRIQr, 9545 &rval, RESET_OFFSET_REDf, default_mtu_cells/8); 9546 soc_reg_field_set(unit, MMU_THDR_QE_RESET_OFFSET_COLOR_PRIQr, 9547 &rval, RESET_OFFSET_YELLOWf, default_mtu_cells/8); 9548 SOC_IF_ERROR_RETURN 9549 (WRITE_MMU_THDR_QE_RESET_OFFSET_COLOR_PRIQr(unit, idx, rval)); 9550 } 9551 9552 /* per pool RQE settings */ 9553 for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) { 9554 buf_pool = &buf->pools[idx]; 9555 if (((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) == 0) || 9556 (buf_pool->total == 0)) { 9557 continue; 9558 } 9559 9560 limit = egr_limit; 9561 if (!lossless) { 9562 limit -= (buf->headroom + cpu_hdrm); 9563 } 9564 9565 rval = 0; 9566 soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_SPr, 9567 &rval, SHARED_LIMITf, limit); 9568 soc_reg_field_set(unit, MMU_THDR_DB_CONFIG_SPr, &rval, RESUME_LIMITf, 9569 (limit - (default_mtu_cells * 2) + 7)/8); 9570 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 9571 MMU_THDR_DB_CONFIG_SPr, -1, -1, idx, rval)); 9572 9573 rval = 0; 9574 soc_reg_field_set(unit, MMU_THDR_DB_SP_SHARED_LIMITr, &rval, 9575 SHARED_RED_LIMITf, (limit + 7)/8); 9576 soc_reg_field_set(unit, MMU_THDR_DB_SP_SHARED_LIMITr, &rval, 9577 SHARED_YELLOW_LIMITf, (limit+7)/8); 9578 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 9579 MMU_THDR_DB_SP_SHARED_LIMITr, -1, -1, idx, rval)); 9580 9581 rval = 0; 9582 soc_reg_field_set(unit, MMU_THDR_DB_RESUME_COLOR_LIMIT_SPr, &rval, 9583 RESUME_RED_LIMITf, 9584 (limit - (default_mtu_cells * 2) + 7)/8); 9585 soc_reg_field_set(unit, MMU_THDR_DB_RESUME_COLOR_LIMIT_SPr, &rval, 9586 RESUME_YELLOW_LIMITf, 9587 (limit - (default_mtu_cells * 2) + 7)/8); 9588 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 9589 MMU_THDR_DB_RESUME_COLOR_LIMIT_SPr, -1, -1, idx, rval)); 9590 9591 rqlen = buf_pool->total_rqe_entry/8; 9592 if (rqlen <= 0) { 9593 continue; 9594 } 9595 9596 rval = 0; 9597 soc_reg_field_set(unit, MMU_THDR_QE_CONFIG_SPr, &rval, 9598 SHARED_LIMITf, rqlen); 9599 soc_reg_field_set(unit, MMU_THDR_QE_CONFIG_SPr, &rval, 9600 RESUME_LIMITf, rqlen - 1); 9601 SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_QE_CONFIG_SPr(unit, idx, rval)); 9602 9603 rval = 0; 9604 soc_reg_field_set(unit, MMU_THDR_QE_SHARED_COLOR_LIMIT_SPr, &rval, 9605 SHARED_RED_LIMITf, rqlen); 9606 soc_reg_field_set(unit, MMU_THDR_QE_SHARED_COLOR_LIMIT_SPr, &rval, 9607 SHARED_YELLOW_LIMITf, rqlen); 9608 SOC_IF_ERROR_RETURN 9609 (WRITE_MMU_THDR_QE_SHARED_COLOR_LIMIT_SPr(unit, idx, rval)); 9610 9611 rval = 0; 9612 soc_reg_field_set(unit, MMU_THDR_QE_RESUME_COLOR_LIMIT_SPr, &rval, 9613 RESUME_RED_LIMITf, rqlen - 1); 9614 soc_reg_field_set(unit, MMU_THDR_QE_RESUME_COLOR_LIMIT_SPr, &rval, 9615 RESUME_YELLOW_LIMITf, rqlen - 1); 9616 SOC_IF_ERROR_RETURN 9617 (WRITE_MMU_THDR_QE_RESUME_COLOR_LIMIT_SPr(unit, idx, rval)); 9618 } 9619 9620 /* Device level config setting */ 9621 if (soc_property_get(unit, spn_PORT_UC_MC_ACCOUNTING_COMBINE, 0)) { 9622 SOC_IF_ERROR_RETURN(READ_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, &rval)); 9623 soc_reg_field_set(unit, MMU_THDM_DB_DEVICE_THR_CONFIGr, &rval, 9624 UC_MC_PORTSP_COMB_ACCT_ENABLEf, 1); 9625 SOC_IF_ERROR_RETURN(WRITE_MMU_THDM_DB_DEVICE_THR_CONFIGr(unit, rval)); 9626 } 9627 9628 rval = 0; 9629 SOC_IF_ERROR_RETURN(READ_MMU_THDR_DB_CONFIGr(unit, &rval)); 9630 soc_reg_field_set(unit, MMU_THDR_DB_CONFIGr, &rval, MOP_POLICY_1Bf, 1); 9631 SOC_IF_ERROR_RETURN(WRITE_MMU_THDR_DB_CONFIGr(unit, rval)); 9632 9633 return SOC_E_NONE; 9634 } 9635 9636 STATIC int 9637 soc_th_mmu_config_init(int unit, int test_only) 9638 { 9639 int rv; 9640 int lossless = 1; 9641 _soc_mmu_cfg_buf_t *buf; 9642 _soc_mmu_device_info_t devcfg; 9643 soc_mmu_config_buf_default_f soc_mmu_config_buf_default = NULL; 9644 9645 buf = soc_mmu_cfg_alloc(unit); 9646 if (!buf) { 9647 return SOC_E_MEMORY; 9648 } 9649 9650 soc_mmu_config_buf_default = _soc_th_mmu_config_buf_default_v5_0; 9651 9652 if (SOC_IS_TOMAHAWKPLUS(unit)) { 9653 lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 9654 SOC_TH_MMU_LOSSLESS_DEFAULT_DISABLE); 9655 } else { 9656 lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 9657 SOC_TH_MMU_LOSSLESS_DEFAULT_ENABLE); 9658 } 9659 9660 /* Update the soc_info mmu_lossless to the updated value */ 9661 SOC_INFO(unit).mmu_lossless = lossless; 9662 9663 _soc_th_mmu_init_dev_config(unit, &devcfg, lossless); 9664 soc_mmu_config_buf_default(unit, buf, &devcfg, lossless); 9665 9666 if (soc_property_get(unit, spn_MMU_CONFIG_OVERRIDE, 1) == 0) { 9667 /* Override default config */ 9668 _soc_mmu_cfg_buf_read(unit, buf, &devcfg); 9669 } 9670 rv = _soc_mmu_cfg_buf_check(unit, buf, &devcfg); 9671 if (!test_only) { 9672 if (SOC_FAILURE(rv)) { 9673 LOG_VERBOSE(BSL_LS_SOC_COMMON, 9674 (BSL_META_U(unit, 9675 "MMU config: Use default setting\n"))); 9676 soc_mmu_config_buf_default(unit, buf, &devcfg, lossless); 9677 SOC_IF_ERROR_RETURN 9678 (_soc_mmu_cfg_buf_calculate(unit, buf, &devcfg)); 9679 } 9680 rv = _soc_th_mmu_config_buf_set_hw(unit, buf, &devcfg, lossless); 9681 } 9682 9683 soc_mmu_cfg_free(unit, buf); 9684 9685 LOG_VERBOSE(BSL_LS_SOC_COMMON, 9686 (BSL_META_U(unit, 9687 "MMU THDI/THDO init done\n"))); 9688 return rv; 9689 } 9690 9691 STATIC int 9692 _soc_tomahawk_mmu_init(int unit) 9693 { 9694 soc_info_t *si; 9695 uint32 pipe_map; 9696 int pipe, oversub_mode = FALSE; 9697 uint32 rval = 0; 9698 uint32 fval = 0; 9699 int port, phy_port, mmu_port; 9700 uint64 enable[_TH_PIPES_PER_DEV]; 9701 int test_only; 9702 #ifdef BCM_TOMAHAWK2_SUPPORT 9703 pbmp_t pbmp_mmu; 9704 9705 SOC_PBMP_CLEAR(pbmp_mmu); 9706 #endif 9707 9708 si = &SOC_INFO(unit); 9709 9710 soc_tomahawk_pipe_map_get(unit, &pipe_map); 9711 9712 test_only = soc_property_get(unit, "simple_simulation_only", 9713 (SAL_BOOT_BCMSIM || SAL_BOOT_XGSSIM)) ? TRUE : FALSE; 9714 #ifdef BCM_TOMAHAWK2_SUPPORT 9715 if (SOC_IS_TOMAHAWK2(unit)) { 9716 SOC_IF_ERROR_RETURN(soc_th2_mmu_config_init(unit, test_only)); 9717 } else 9718 #endif 9719 { 9720 SOC_IF_ERROR_RETURN(soc_th_mmu_config_init(unit, test_only)); 9721 } 9722 9723 if (SOC_PBMP_NOT_NULL(si->oversub_pbm)) { 9724 oversub_mode = TRUE; 9725 SOC_IF_ERROR_RETURN 9726 (soc_tomahawk_sc_reg32_get(unit, MMU_1DBG_Cr, -1, -1, 0, &rval)); 9727 soc_reg_field_set(unit, MMU_1DBG_Cr, &rval, FIELD_Af, 1); 9728 SOC_IF_ERROR_RETURN 9729 (soc_tomahawk_sc_reg32_set(unit, MMU_1DBG_Cr, -1, -1, 0, rval)); 9730 rval = 0xffffffff; 9731 SOC_IF_ERROR_RETURN 9732 (soc_tomahawk_sc_reg32_set(unit, MMU_1DBG_Ar, -1, -1, 0, rval)); 9733 } 9734 9735 sal_memset(enable, 0, sizeof(enable)); 9736 PBMP_ALL_ITER(unit, port) { 9737 pipe = si->port_pipe[port]; 9738 phy_port = si->port_l2p_mapping[port]; 9739 mmu_port = si->port_p2m_mapping[phy_port]; 9740 #ifdef BCM_TOMAHAWK2_SUPPORT 9741 SOC_PBMP_PORT_ADD(pbmp_mmu, mmu_port); 9742 #endif 9743 if (mmu_port & 0x20) { 9744 u64_H(enable[pipe]) |= 1 << (mmu_port & 0x1f); 9745 } else { 9746 u64_L(enable[pipe]) |= 1 << (mmu_port & 0x1f); 9747 } 9748 if (oversub_mode) { 9749 rval = 0; 9750 if (si->port_speed_max[port] >= 100000) { 9751 fval = 140; 9752 } else if (si->port_speed_max[port] >= 40000) { 9753 fval = 60; 9754 } else if (si->port_speed_max[port] >= 25000) { 9755 fval = 40; 9756 } else if (si->port_speed_max[port] >= 20000) { 9757 fval = 30; 9758 } else { 9759 fval = 15; 9760 } 9761 soc_reg_field_set(unit, MMU_3DBG_Cr, &rval, FIELD_Af, 9762 fval + sal_rand() % 20); 9763 SOC_IF_ERROR_RETURN 9764 (soc_tomahawk_sc_reg32_set(unit, MMU_3DBG_Cr, -1, port, 0, rval)); 9765 } 9766 } 9767 9768 #ifdef BCM_TOMAHAWK2_SUPPORT 9769 if (SOC_IS_TOMAHAWK2(unit)) { 9770 /* 9771 * THDU_OUTPUT_PORT_RX_ENABLE_64, 9772 * MMU_THDM_DB_PORT_RX_ENABLE_64, 9773 * MMU_THDM_MCQE_PORT_RX_ENABLE_64, 9774 * THDI_INPUT_PORT_XON_ENABLES.INPUT_PORT_RX_ENABLE, 9775 * MMU RX_ENABLE registers listed above shouldn't be changed during 9776 * run-time. Enable RX for all MMU ports that flex eligible. 9777 */ 9778 if (si->flex_eligible) { 9779 for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) { 9780 if (!(pipe_map & (1 << pipe))) { 9781 continue; 9782 } 9783 for (mmu_port = 0; mmu_port < _TH2_MMU_GPORTS_PER_PIPE; 9784 mmu_port++) { 9785 u64_L(enable[pipe]) |= 1 << mmu_port; 9786 SOC_PBMP_PORT_ADD(pbmp_mmu, 9787 (mmu_port + pipe * _TH2_MMU_PORTS_OFFSET_PER_PIPE)); 9788 } 9789 } 9790 } 9791 9792 SOC_PBMP_ITER(pbmp_mmu, mmu_port) { 9793 SOC_IF_ERROR_RETURN 9794 (soc_reg32_rawport_get(unit, THDI_INPUT_PORT_XON_ENABLESr, 9795 mmu_port,0, &rval)); 9796 soc_reg_field_set(unit, THDI_INPUT_PORT_XON_ENABLESr, &rval, 9797 INPUT_PORT_RX_ENABLEf, 1); 9798 SOC_IF_ERROR_RETURN 9799 (soc_reg32_rawport_set(unit, THDI_INPUT_PORT_XON_ENABLESr, 9800 mmu_port, 0, rval)); 9801 } 9802 9803 /* enable WRED refresh */ 9804 SOC_IF_ERROR_RETURN(READ_WRED_REFRESH_CONTROLr(unit, &rval)); 9805 soc_reg_field_set(unit, WRED_REFRESH_CONTROLr, &rval, 9806 REFRESH_DISABLEf, 0); 9807 SOC_IF_ERROR_RETURN(WRITE_WRED_REFRESH_CONTROLr(unit, rval)); 9808 9809 } 9810 #endif /* BCM_TOMAHAWK2_SUPPORT */ 9811 9812 #ifdef BCM_WARM_BOOT_SUPPORT 9813 if (!SOC_WARM_BOOT(unit)) 9814 #endif 9815 { 9816 for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) { 9817 if (!(pipe_map & (1 << pipe))) { 9818 continue; 9819 } 9820 SOC_IF_ERROR_RETURN 9821 (soc_tomahawk_xpe_reg_set(unit, THDU_OUTPUT_PORT_RX_ENABLE_64r, 9822 -1, pipe, 0, enable[pipe])); 9823 } 9824 9825 for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) { 9826 if (!(pipe_map & (1 << pipe))) { 9827 continue; 9828 } 9829 SOC_IF_ERROR_RETURN 9830 (soc_tomahawk_xpe_reg_set(unit, MMU_THDM_DB_PORT_RX_ENABLE_64r, 9831 -1, pipe, 0, enable[pipe])); 9832 } 9833 9834 for (pipe = 0; pipe < _TH_PIPES_PER_DEV; pipe++) { 9835 if (!(pipe_map & (1 << pipe))) { 9836 continue; 9837 } 9838 SOC_IF_ERROR_RETURN 9839 (soc_tomahawk_xpe_reg_set(unit, MMU_THDM_MCQE_PORT_RX_ENABLE_64r, 9840 -1, pipe, 0, enable[pipe])); 9841 } 9842 } 9843 SOC_IF_ERROR_RETURN(_soc_th_post_mmu_init_update(unit)); 9844 return SOC_E_NONE; 9845 } 9846 9847 STATIC int 9848 _soc_tomahawk_age_timer_get(int unit, int *age_seconds, int *enabled) 9849 { 9850 soc_control_t *soc = SOC_CONTROL(unit); 9851 9852 *enabled = soc->l2x_age_pid != SAL_THREAD_ERROR && 9853 soc->l2x_age_enable ? 9854 1 : 0; 9855 *age_seconds = soc->l2x_age_pid != SAL_THREAD_ERROR && 9856 soc->l2x_age_enable ? 9857 soc->l2x_age_interval : 0; 9858 9859 return SOC_E_NONE; 9860 } 9861 9862 STATIC int 9863 _soc_tomahawk_age_timer_max_get(int unit, int *max_seconds) 9864 { 9865 *max_seconds = 0x7fffffff; 9866 return SOC_E_NONE; 9867 } 9868 9869 STATIC int 9870 _soc_tomahawk_age_timer_set(int unit, int age_seconds, int enable) 9871 { 9872 soc_control_t *soc = SOC_CONTROL(unit); 9873 sal_usecs_t interval = soc->l2x_age_interval; 9874 9875 if (soc->l2x_age_interval) { 9876 if (!enable) { 9877 soc->l2x_age_enable = 0; 9878 } else { 9879 if (age_seconds) { 9880 SOC_CONTROL_LOCK(unit); 9881 soc->l2x_age_interval = age_seconds; 9882 SOC_CONTROL_UNLOCK(unit); 9883 } 9884 soc->l2x_age_enable = 1; 9885 if (interval != age_seconds) { 9886 sal_sem_give(soc->l2x_age_notify); 9887 } 9888 } 9889 } else { 9890 if (enable) { 9891 soc->l2x_age_enable = 1; 9892 SOC_IF_ERROR_RETURN 9893 (soc_th_l2_bulk_age_start(unit, age_seconds)); 9894 } 9895 } 9896 9897 return SOC_E_NONE; 9898 } 9899 9900 STATIC int 9901 _soc_tomahawk_bond_info_init(int unit) 9902 { 9903 soc_chip_types type = SOC_DRIVER(unit)->type; 9904 9905 switch (type) { 9906 #ifdef BCM_TOMAHAWK2_SUPPORT 9907 case SOC_CHIP_BCM56970_A0: 9908 return soc_tomahawk2_bond_info_init(unit); 9909 #endif 9910 default: 9911 return SOC_E_NONE; 9912 } 9913 } 9914 9915 soc_error_t 9916 soc_th_port_speed_supported(int unit, soc_port_t port, int speed) 9917 { 9918 uint8 rev_id; 9919 uint16 dev_id; 9920 int num_lanes; 9921 soc_info_t *si = &SOC_INFO(unit); 9922 int phy_port; 9923 9924 #ifdef BCM_TOMAHAWK2_SUPPORT 9925 if (SOC_IS_TOMAHAWK2(unit)) { 9926 return soc_th2_port_speed_supported(unit, port, speed); 9927 } 9928 #endif 9929 9930 /* 9931 * If Universal calendar was not selected at init time then 9932 * disallow speed change to HG2 speeds. 9933 */ 9934 if (FALSE == si->fabric_port_enable) { 9935 if (IS_HG2_SPEED(speed)) { 9936 /* 9937 * Intentionally returning SOC_E_CONFIG as this is a case 9938 * of incorrect configuration 9939 */ 9940 return SOC_E_CONFIG; 9941 } 9942 } 9943 9944 /* 9945 * Management ports only support 1G, 2.5G and 10G. Flexport 9946 * on management ports is not supported. Management ports 9947 * are guaranteed 10G bandwidth. 9948 */ 9949 if (SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) { 9950 if ((1000 == speed) || (2500 == speed) || (10000 == speed)) { 9951 return SOC_E_NONE; 9952 } else { 9953 return SOC_E_PARAM; 9954 } 9955 } 9956 9957 soc_cm_get_id(unit, &dev_id, &rev_id); 9958 num_lanes = si->port_num_lanes[port]; 9959 phy_port = si->port_l2p_mapping[port]; 9960 9961 /* 9962 * Check if Core Clock Frequency supports Port Speed 9963 */ 9964 9965 switch (speed) { 9966 /* 1G, 10G, 20G, 40G, HG11, HG21, HG 42 */ 9967 case 1000: 9968 case 10000: 9969 case 20000: 9970 case 40000: 9971 case 11000: 9972 case 21000: 9973 case 42000: 9974 break; 9975 9976 /* 25G, 50G, 100G */ 9977 case 25000: 9978 case 50000: 9979 case 100000: 9980 /* HG27, HG 53, HG 106 */ 9981 case 27000: 9982 case 53000: 9983 case 106000: 9984 /* Universal Calendar */ 9985 if (si->fabric_port_enable) { 9986 if (si->frequency < 672) { 9987 return SOC_E_PARAM; 9988 } 9989 /* Ethernet Optimized Calendar */ 9990 } else { 9991 if (si->frequency < 645) { 9992 return SOC_E_PARAM; 9993 } 9994 } 9995 break; 9996 9997 default: 9998 return SOC_E_PARAM; 9999 } 10000 10001 /* 10002 * Laying down the framework to handle SKU differences. This is 10003 * needed because some SKUs have speed caps on certain PMs. 10004 */ 10005 switch (dev_id) { 10006 case BCM56168_DEVICE_ID: 10007 /* 10008 * The specification of FC Max lanes speed on BCM56168 as below 10009 * FC[0:2] FC[3:7] FC[8:9] FC[10:15] FC[16:21] FC[22:23] FC[24:29] FC[30:31] 10010 * 4x25 4x10 4x25 4x10 4x10 4x25 4x10 4x25 10011 */ 10012 if (((phy_port >= 13) && (phy_port <= 32)) || \ 10013 ((phy_port >= 41) && (phy_port <= 88)) || \ 10014 ((phy_port >= 97) && (phy_port <= 120))) { 10015 if ((10000 != speed) && (11000 != speed) && \ 10016 (20000 != speed) && (21000 != speed) && \ 10017 (40000 != speed) && (42000 != speed)) 10018 return SOC_E_PARAM; 10019 } 10020 break; 10021 10022 case BCM56961_DEVICE_ID: 10023 case BCM56969_DEVICE_ID: 10024 /* SERDES VCO capped at 21.875Ghz */ 10025 if ((25000 == speed) || (27000 == speed) || (speed >= 50000)) { 10026 return SOC_E_PARAM; 10027 } 10028 /* Fall through to default case */ 10029 10030 default: 10031 if (speed >= 100000) { /* 100G, HG106 */ 10032 if (4 != num_lanes) { 10033 return SOC_E_PARAM; 10034 } 10035 } else if (speed >= 50000) { /* 50G, HG53 */ 10036 if (2 != num_lanes) { 10037 return SOC_E_PARAM; 10038 } 10039 } else if (speed >= 40000) { /* 40G, HG42 */ 10040 if ((2 != num_lanes) && (4 != num_lanes)) { 10041 return SOC_E_PARAM; 10042 } 10043 } else if ((speed == 20000) || ( speed == 21000)) { /* 20G, HG21 */ 10044 if (2 != num_lanes) { 10045 return SOC_E_PARAM; 10046 } 10047 } else { /* 10G, HG11, 25G, HG27 */ 10048 if (1 != num_lanes) { 10049 return SOC_E_PARAM; 10050 } 10051 } 10052 } 10053 return SOC_E_NONE; 10054 } 10055 10056 STATIC int 10057 soc_th_port_lanes_ctrl_info_diag(int unit, soc_th_port_lanes_t *lanes_ctrl) 10058 { 10059 soc_info_t *si = &SOC_INFO(unit); 10060 int port_base, phy_port_base; 10061 int pipe, i; 10062 10063 static char *mode_name[] = { 10064 "QUAD", "TRI_012", "TRI_023", "DUAL", "SINGLE" 10065 }; 10066 10067 port_base = lanes_ctrl->port_base; 10068 phy_port_base = si->port_l2p_mapping[port_base]; 10069 if (phy_port_base == -1) { 10070 return SOC_E_PORT; 10071 } 10072 10073 pipe = si->port_pipe[port_base]; 10074 10075 LOG_CLI((BSL_META_U(unit, 10076 ">>>> The current port lanes control info\n"))); 10077 LOG_CLI((BSL_META_U(unit, 10078 "oversub mode:%s mixed sister mode:%s mixed sister port mode:%d\n"), 10079 lanes_ctrl->oversub ? "enable" : "disable", 10080 lanes_ctrl->os_mixed_sister ? "enable" : "disable", 10081 lanes_ctrl->mixed_port_mode)); 10082 LOG_CLI((BSL_META_U(unit, 10083 "pipe:%d logical port:%d physical port:%d bindex:%d\n"), 10084 pipe, port_base, phy_port_base, lanes_ctrl->bindex)); 10085 LOG_CLI((BSL_META_U(unit, 10086 " mode(cur:%s ==>> new:%s) lanes(cur:%d ==>> new:%d)\n"), 10087 mode_name[lanes_ctrl->cur_mode], 10088 mode_name[lanes_ctrl->mode], 10089 lanes_ctrl->cur_lanes, lanes_ctrl->lanes)); 10090 LOG_CLI((BSL_META_U(unit, 10091 " speed class(cur:%d ==>> new:%d)\n"), 10092 lanes_ctrl->cur_class, lanes_ctrl->class)); 10093 for (i = 0; i < lanes_ctrl->phy_ports_len; i++) { 10094 LOG_CLI((BSL_META_U(unit, 10095 " %s physical port:%d (logical port:%d)\n"), 10096 lanes_ctrl->lanes > lanes_ctrl->cur_lanes ? 10097 "del" : "add", 10098 lanes_ctrl->phy_ports[i], 10099 si->port_p2l_mapping[lanes_ctrl->phy_ports[i]])); 10100 } 10101 if (lanes_ctrl->idb_group != -1) { 10102 LOG_CLI((BSL_META_U(unit, 10103 "new idb group:%d slot:%d"), 10104 lanes_ctrl->idb_group, lanes_ctrl->idb_slots[0])); 10105 if (lanes_ctrl->lanes < lanes_ctrl->cur_lanes && 10106 lanes_ctrl->idb_slots[0] != -1) { 10107 LOG_CLI((BSL_META_U(unit, 10108 " add:"))); 10109 for (i = 1; i < lanes_ctrl->phy_ports_len; i++) { 10110 LOG_CLI((BSL_META_U(unit, 10111 " slot:%d"), lanes_ctrl->idb_slots[i])); 10112 } 10113 } 10114 LOG_CLI((BSL_META_U(unit, 10115 "\n"))); 10116 } 10117 LOG_CLI((BSL_META_U(unit, 10118 "cur idb group:%d slot:%d"), 10119 lanes_ctrl->cur_idb_group, lanes_ctrl->cur_idb_slots[0])); 10120 if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) { 10121 LOG_CLI((BSL_META_U(unit, 10122 " del:"))); 10123 /* port(s) to be removed */ 10124 for (i = 1; i < lanes_ctrl->phy_ports_len; i++) { 10125 LOG_CLI((BSL_META_U(unit, 10126 " slot:%d"), lanes_ctrl->cur_idb_slots[i])); 10127 } 10128 } 10129 LOG_CLI((BSL_META_U(unit, 10130 "\n"))); 10131 10132 if (lanes_ctrl->mmu_group != -1) { 10133 LOG_CLI((BSL_META_U(unit, 10134 "new mmu group:%d slot:%d"), 10135 lanes_ctrl->mmu_group, lanes_ctrl->mmu_slots[0])); 10136 if (lanes_ctrl->lanes < lanes_ctrl->cur_lanes && 10137 lanes_ctrl->mmu_slots[0] != -1) { 10138 LOG_CLI((BSL_META_U(unit, 10139 " add:"))); 10140 /* port(s) to be added */ 10141 for (i = 1; i < lanes_ctrl->phy_ports_len; i++) { 10142 LOG_CLI((BSL_META_U(unit, 10143 " slot:%d"), lanes_ctrl->mmu_slots[i])); 10144 } 10145 } 10146 LOG_CLI((BSL_META_U(unit, 10147 "\n"))); 10148 } 10149 LOG_CLI((BSL_META_U(unit, 10150 "cur mmu group:%d slot:%d"), 10151 lanes_ctrl->cur_mmu_group, lanes_ctrl->cur_mmu_slots[0])); 10152 if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) { 10153 LOG_CLI((BSL_META_U(unit, 10154 " del:"))); 10155 /* port(s) to be removed */ 10156 for (i = 1; i < lanes_ctrl->phy_ports_len; i++) { 10157 LOG_CLI((BSL_META_U(unit, 10158 " slot:%d"), lanes_ctrl->mmu_slots[i])); 10159 } 10160 } 10161 LOG_CLI((BSL_META_U(unit, 10162 "\n"))); 10163 return SOC_E_NONE; 10164 } 10165 10166 STATIC int 10167 soc_th_port_lanes_migrate(int unit, soc_th_port_lanes_t *lanes_ctrl) 10168 { 10169 soc_info_t *si; 10170 int port_base, phy_port, idb_port, mmu_port; 10171 int group, pipe, slot, id; 10172 soc_reg_t reg; 10173 uint32 rval; 10174 uint32 inst; 10175 10176 si = &SOC_INFO(unit); 10177 port_base = lanes_ctrl->port_base; 10178 phy_port = si->port_l2p_mapping[port_base]; 10179 pipe = si->port_pipe[port_base]; 10180 id = si->port_serdes[port_base] & 7; 10181 10182 /* Migrate only one group/slot to the destination */ 10183 if ((-1 != lanes_ctrl->cur_idb_group) && 10184 (-1 != lanes_ctrl->cur_mmu_group) && 10185 (-1 != lanes_ctrl->idb_group) && 10186 (-1 != lanes_ctrl->mmu_group)) { 10187 /* Remove idb port(s) from current group */ 10188 group = lanes_ctrl->cur_idb_group; 10189 reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[group])[pipe]; 10190 rval = 0; 10191 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, 0x3f); 10192 slot = lanes_ctrl->cur_idb_slots[0]; 10193 if (slot < 0) { 10194 return SOC_E_INTERNAL; 10195 } 10196 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval)); 10197 10198 /* Add idb port(s) to new group */ 10199 group = lanes_ctrl->idb_group; 10200 reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[group])[pipe]; 10201 rval = 0; 10202 soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, id); 10203 idb_port = si->port_l2i_mapping[port_base]; 10204 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, idb_port); 10205 slot = lanes_ctrl->idb_slots[0]; 10206 if (slot < 0) { 10207 return SOC_E_INTERNAL; 10208 } 10209 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval)); 10210 10211 /* Remove mmu port(s) from current group */ 10212 group = lanes_ctrl->cur_mmu_group; 10213 reg = mmu_grp_tbl_regs[group]; 10214 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 10215 rval = 0; 10216 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, 0x3f); 10217 slot = lanes_ctrl->cur_mmu_slots[0]; 10218 if (slot < 0) { 10219 return SOC_E_INTERNAL; 10220 } 10221 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval)); 10222 10223 /* Add mmu port(s) to new group */ 10224 group = lanes_ctrl->mmu_group; 10225 reg = mmu_grp_tbl_regs[group]; 10226 rval = 0; 10227 soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, id); 10228 mmu_port = si->port_p2m_mapping[phy_port]; 10229 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, mmu_port & 0x3f); 10230 slot = lanes_ctrl->mmu_slots[0]; 10231 if (slot < 0) { 10232 return SOC_E_INTERNAL; 10233 } 10234 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval)); 10235 10236 } else { 10237 return SOC_E_INTERNAL; 10238 } 10239 10240 return SOC_E_NONE; 10241 } 10242 10243 STATIC int 10244 soc_tomahawk_oversub_group_find(int unit, soc_th_port_lanes_t *lanes_ctrl) 10245 { 10246 soc_info_t *si = &SOC_INFO(unit); 10247 soc_th_port_lanes_t re_lanes_ctrl; 10248 soc_reg_t reg; 10249 int port_base, phy_port_base, idb_port_base, mmu_port_base; 10250 int port, mmu_port, id, inst; 10251 uint32 rval, fval; 10252 int pipe, group, slot, i; 10253 int cur_ids[4], cur_ids_len; 10254 int ids_len; 10255 int cur_mmu_ids[4]; 10256 int slots[4], slots_len; 10257 uint32 speed_max = 0, cur_speed_max; 10258 int sp_group1 = -1, sp_group2 = -1; 10259 int cnt_idb[_OVS_GROUP_COUNT] = {0,0,0,0,0,0}; 10260 int cnt_mmu[_OVS_GROUP_COUNT] = {0,0,0,0,0,0}; 10261 typedef struct { 10262 int group; 10263 int slot; 10264 int port; 10265 int free_slot; 10266 } cur_group_info_t; 10267 cur_group_info_t cur_idb[_OVS_GROUP_COUNT]; 10268 cur_group_info_t cur_mmu[_OVS_GROUP_COUNT]; 10269 10270 port_base = lanes_ctrl->port_base; 10271 phy_port_base = si->port_l2p_mapping[port_base]; 10272 idb_port_base = si->port_l2i_mapping[port_base]; 10273 mmu_port_base = si->port_p2m_mapping[phy_port_base]; 10274 pipe = si->port_pipe[port_base]; 10275 sal_memset(cur_idb, -1, sizeof(cur_idb)); 10276 sal_memset(cur_mmu, -1, sizeof(cur_mmu)); 10277 10278 /* Figure out the new speed group */ 10279 _soc_tomahawk_flexed_port_speed_get(unit, lanes_ctrl, &speed_max); 10280 _soc_tomahawk_speed_to_ovs_class_mapping(unit, speed_max, 10281 &lanes_ctrl->class); 10282 10283 /* Figure out the current speed group */ 10284 cur_speed_max = si->port_init_speed[port_base]; 10285 _soc_tomahawk_speed_to_ovs_class_mapping(unit, cur_speed_max, 10286 &lanes_ctrl->cur_class); 10287 10288 /* Construct new and old idb port list for oversub group replacement */ 10289 cur_idb[0].port = cur_ids[0] = idb_port_base; 10290 ids_len = cur_ids_len = 1; 10291 10292 if (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes) { 10293 if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) { 10294 /* idb port(s) to be removed */ 10295 for (i = 0; i < lanes_ctrl->phy_ports_len; i++) { 10296 port = si->port_p2l_mapping[lanes_ctrl->phy_ports[i]]; 10297 cur_idb[1 + i].port = cur_ids[1 + i] = si->port_l2i_mapping[port]; 10298 } 10299 cur_ids_len += lanes_ctrl->phy_ports_len; 10300 } else { /* idb port(s) to be added */ 10301 ids_len += lanes_ctrl->phy_ports_len; 10302 } 10303 } 10304 10305 lanes_ctrl->idb_group = -1; 10306 lanes_ctrl->idb_slots[0] = -1; 10307 lanes_ctrl->cur_idb_slots[0] = -1; 10308 for (group = 0; group < _OVS_GROUP_COUNT; group++) { 10309 reg = SOC_REG_UNIQUE_ACC(unit, IS_OVR_SUB_GRP_CFGr)[pipe]; 10310 SOC_IF_ERROR_RETURN 10311 (soc_reg32_get(unit, reg, REG_PORT_ANY, group, &rval)); 10312 fval = soc_reg_field_get(unit, reg, rval, SPEEDf); 10313 if (fval == 0) { /* unused idb port oversub group */ 10314 if (lanes_ctrl->idb_group == -1) { 10315 lanes_ctrl->idb_group = group; 10316 } 10317 continue; 10318 } else { 10319 if (fval == lanes_ctrl->class) { 10320 if (lanes_ctrl->idb_slots[0] == -1) { /* hasn't found the group */ 10321 /* Find slot(s) for new idb port oversub group */ 10322 reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[group])[pipe]; 10323 slots_len = 0; 10324 for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) { 10325 SOC_IF_ERROR_RETURN 10326 (soc_reg32_get(unit, reg, REG_PORT_ANY, slot, &rval)); 10327 if (soc_reg_field_get(unit, reg, rval, PORT_NUMf) != 0x3f) { 10328 continue; 10329 } 10330 slots[slots_len] = slot; 10331 slots_len++; 10332 if (slots_len == ids_len) { 10333 /* Enough free slots in an existing group */ 10334 lanes_ctrl->idb_group = group; 10335 for (i = 0; i < slots_len; i++) { 10336 lanes_ctrl->idb_slots[i] = slots[i]; 10337 } 10338 break; 10339 } 10340 } 10341 } 10342 } 10343 if (fval == lanes_ctrl->cur_class) { 10344 if (lanes_ctrl->cur_idb_slots[0] == -1) { 10345 /* Find slot(s) used by the current idb port oversub group */ 10346 reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[group])[pipe]; 10347 slots_len = 0; 10348 lanes_ctrl->cur_idb_empty = TRUE; 10349 for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) { 10350 SOC_IF_ERROR_RETURN 10351 (soc_reg32_get(unit, reg, REG_PORT_ANY, slot, &rval)); 10352 id = soc_reg_field_get(unit, reg, rval, PORT_NUMf); 10353 if (id == 0x3f) { 10354 continue; 10355 } 10356 for (i = 0; i < cur_ids_len; i++) { 10357 if (id == cur_idb[i].port) { 10358 cur_idb[i].group = group; 10359 cur_idb[i].slot = slot; 10360 } 10361 if (id == cur_ids[i]) { 10362 slots[slots_len] = slot; 10363 slots_len++; 10364 break; 10365 } 10366 } 10367 if (i == cur_ids_len) { 10368 lanes_ctrl->cur_idb_empty = FALSE; 10369 } else if (slots_len == cur_ids_len) { 10370 lanes_ctrl->cur_idb_group = group; 10371 for (i = 0; i < slots_len; i++) { 10372 lanes_ctrl->cur_idb_slots[i] = slots[i]; 10373 } 10374 } 10375 if (lanes_ctrl->cur_idb_slots[0] != -1 && 10376 !lanes_ctrl->cur_idb_empty) { 10377 break; 10378 } 10379 } 10380 } 10381 } 10382 } 10383 if (lanes_ctrl->idb_slots[0] != -1 && 10384 lanes_ctrl->cur_idb_slots[0] != -1) { 10385 break; 10386 } 10387 } 10388 10389 if (lanes_ctrl->idb_group == -1) { 10390 LOG_VERBOSE(BSL_LS_SOC_COMMON, 10391 (BSL_META_U(unit, 10392 "IDB Speed Group is Full\n"))); 10393 return SOC_E_FULL; 10394 } 10395 10396 /* Construct new and old mmu port list for oversub group replacement */ 10397 cur_mmu[0].port = cur_mmu_ids[0] = mmu_port_base & 0x3f; 10398 ids_len = cur_ids_len = 1; 10399 if (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes) { 10400 if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) { 10401 /* mmu port(s) to be removed */ 10402 for (i = 0; i < lanes_ctrl->phy_ports_len; i++) { 10403 mmu_port = si->port_p2m_mapping[lanes_ctrl->phy_ports[i]]; 10404 cur_mmu[1 + i].port = cur_mmu_ids[1 + i] = mmu_port & 0x3f; 10405 } 10406 cur_ids_len += lanes_ctrl->phy_ports_len; 10407 } else { /* mmu port(s) to be added */ 10408 for (i = 0; i < lanes_ctrl->phy_ports_len; i++) { 10409 mmu_port = si->port_p2m_mapping[lanes_ctrl->phy_ports[i]]; 10410 } 10411 ids_len += lanes_ctrl->phy_ports_len; 10412 } 10413 } 10414 10415 lanes_ctrl->mmu_group = -1; 10416 lanes_ctrl->mmu_slots[0] = -1; 10417 lanes_ctrl->cur_mmu_slots[0] = -1; 10418 for (group = 0; group < _OVS_GROUP_COUNT; group++) { 10419 reg = OVR_SUB_GRP_CFGr; 10420 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 10421 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, group, &rval)); 10422 fval = soc_reg_field_get(unit, reg, rval, SPEEDf); 10423 if (fval == 0) { /* unused mmu port oversub group */ 10424 if (lanes_ctrl->mmu_group == -1) { 10425 lanes_ctrl->mmu_group = group; 10426 } 10427 continue; 10428 } else { 10429 if (fval == lanes_ctrl->class) { 10430 if (lanes_ctrl->mmu_slots[0] == -1) { /* hasn't found the group */ 10431 /* Find slot(s) for new mmu port oversub group */ 10432 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 10433 reg = mmu_grp_tbl_regs[group]; 10434 slots_len = 0; 10435 for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) { 10436 SOC_IF_ERROR_RETURN 10437 (soc_reg32_get(unit, reg, inst, slot, &rval)); 10438 if (soc_reg_field_get(unit, reg, rval, PORT_NUMf) != 0x3f) { 10439 continue; 10440 } 10441 slots[slots_len] = slot; 10442 slots_len++; 10443 if (slots_len == ids_len) { 10444 /* Enough free slots in an existing group */ 10445 lanes_ctrl->mmu_group = group; 10446 for (i = 0; i < slots_len; i++) { 10447 lanes_ctrl->mmu_slots[i] = slots[i]; 10448 } 10449 break; 10450 } 10451 } 10452 } 10453 } 10454 if (fval == lanes_ctrl->cur_class) { 10455 if (lanes_ctrl->cur_mmu_slots[0] == -1) { 10456 /* Find slot(s) used by the currnet mmu port oversub group */ 10457 reg = mmu_grp_tbl_regs[group]; 10458 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 10459 slots_len = 0; 10460 lanes_ctrl->cur_mmu_empty = TRUE; 10461 for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) { 10462 SOC_IF_ERROR_RETURN 10463 (soc_reg32_get(unit, reg, inst, slot, &rval)); 10464 id = soc_reg_field_get(unit, reg, rval, PORT_NUMf); 10465 if (id == 0x3f) { 10466 continue; 10467 } 10468 for (i = 0; i < cur_ids_len; i++) { 10469 if (id == cur_mmu[i].port) { 10470 cur_mmu[i].group = group; 10471 cur_mmu[i].slot = slot; 10472 } 10473 if (id == cur_mmu_ids[i]) { 10474 slots[slots_len] = slot; 10475 slots_len++; 10476 break; 10477 } 10478 } 10479 if (i == cur_ids_len) { 10480 lanes_ctrl->cur_mmu_empty = FALSE; 10481 } else if (slots_len == cur_ids_len) { 10482 lanes_ctrl->cur_mmu_group = group; 10483 for (i = 0; i < slots_len; i++) { 10484 lanes_ctrl->cur_mmu_slots[i] = slots[i]; 10485 } 10486 } 10487 if (lanes_ctrl->cur_mmu_slots[0] != -1 && 10488 !lanes_ctrl->cur_mmu_empty) { 10489 break; 10490 } 10491 } 10492 } 10493 } 10494 } 10495 if (lanes_ctrl->mmu_slots[0] != -1 && 10496 lanes_ctrl->cur_mmu_slots[0] != -1) { 10497 break; 10498 } 10499 } 10500 10501 if (lanes_ctrl->mmu_group == -1) { 10502 LOG_VERBOSE(BSL_LS_SOC_COMMON, 10503 (BSL_META_U(unit, 10504 "MMU Speed Group is Full\n"))); 10505 return SOC_E_FULL; 10506 } 10507 10508 /* Peform validation of OS group/slots */ 10509 if (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes) { 10510 if ((-1 == lanes_ctrl->cur_idb_group) || 10511 (-1 == lanes_ctrl->cur_mmu_group) || 10512 (-1 == lanes_ctrl->idb_group) || 10513 (-1 == lanes_ctrl->mmu_group)) { 10514 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 10515 SOC_IF_ERROR_RETURN(soc_th_port_lanes_ctrl_info_diag(unit, lanes_ctrl)); 10516 10517 for (i = 0; i < _OVS_GROUP_COUNT; i++) { 10518 LOG_CLI((BSL_META_U(unit, 10519 "cur_idb[%d]: %d %d %d %d\n"), 10520 i, cur_idb[i].group, cur_idb[i].slot, cur_idb[i].port, cur_idb[i].free_slot)); 10521 LOG_CLI((BSL_META_U(unit, 10522 "cur_mmu[%d]: %d %d %d %d\n"), 10523 i, cur_mmu[i].group, cur_mmu[i].slot, cur_mmu[i].port, cur_mmu[i].free_slot)); 10524 } 10525 } 10526 10527 /* Peform adjusting the group/slots which is splitted into different groups */ 10528 if (lanes_ctrl->lanes == 4 && lanes_ctrl->cur_lanes == 1 && 10529 lanes_ctrl->class == 4 && lanes_ctrl->cur_class == 1) { 10530 /* figure out the number of same group id */ 10531 for (i = 0; i < _OVS_GROUP_COUNT; i++) { 10532 cnt_idb[cur_idb[i].group]++; 10533 cnt_mmu[cur_mmu[i].group]++; 10534 } 10535 /* figure out one group is different with the others */ 10536 for (i = 0; i < _OVS_GROUP_COUNT; i++) { 10537 if (cnt_idb[i] == 1) { 10538 sp_group1 = i; 10539 } 10540 if (cnt_idb[i] == 3) { 10541 sp_group2 = i; 10542 } 10543 if ((sp_group1 > 0) && (sp_group2 > 0)) 10544 break; 10545 } 10546 if (sp_group1 < 0 || sp_group2 < 0) { 10547 LOG_VERBOSE(BSL_LS_SOC_COMMON, 10548 (BSL_META_U(unit, 10549 "FAILED in search the number of speed group\n"))); 10550 return SOC_E_INTERNAL; 10551 } 10552 10553 if (lanes_ctrl->idb_slots[0] == -1) { 10554 reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[sp_group2])[pipe]; 10555 for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) { 10556 SOC_IF_ERROR_RETURN 10557 (soc_reg32_get(unit, reg, REG_PORT_ANY, slot, &rval)); 10558 if (soc_reg_field_get(unit, reg, rval, PORT_NUMf) != 0x3f) { 10559 continue; 10560 } 10561 lanes_ctrl->idb_group = sp_group2; 10562 lanes_ctrl->idb_slots[0] = slot; 10563 break; 10564 } 10565 if (slot == _OVS_GROUP_TDM_LENGTH) { 10566 LOG_VERBOSE(BSL_LS_SOC_COMMON, 10567 (BSL_META_U(unit, 10568 "FAILED in search the empty speed group slot\n"))); 10569 return SOC_E_INTERNAL; 10570 } 10571 } 10572 if (lanes_ctrl->cur_idb_slots[0] == -1) { 10573 for (i = 0; i < _OVS_GROUP_COUNT; i++) { 10574 if(cur_idb[i].group == sp_group1) { 10575 lanes_ctrl->cur_idb_group = cur_idb[i].group; 10576 lanes_ctrl->cur_idb_slots[0] = cur_idb[i].slot; 10577 } 10578 } 10579 } 10580 10581 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 10582 SOC_IF_ERROR_RETURN(soc_th_port_lanes_ctrl_info_diag(unit, lanes_ctrl)); 10583 } 10584 10585 for (i = 0; i < _OVS_GROUP_COUNT; i++) { 10586 if (cnt_mmu[i] == 1) 10587 sp_group1 = i; 10588 if (cnt_mmu[i] == 3) 10589 sp_group2 = i; 10590 if ((sp_group1 > 0) && (sp_group2 > 0)) 10591 break; 10592 } 10593 if (sp_group1 < 0 || sp_group2 < 0) { 10594 LOG_VERBOSE(BSL_LS_SOC_COMMON, 10595 (BSL_META_U(unit, 10596 "FAILED in search the number of mmu\n"))); 10597 return SOC_E_INTERNAL; 10598 } 10599 if (lanes_ctrl->mmu_slots[0] == -1) { 10600 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 10601 reg = mmu_grp_tbl_regs[sp_group2]; 10602 for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) { 10603 SOC_IF_ERROR_RETURN 10604 (soc_reg32_get(unit, reg, inst, slot, &rval)); 10605 if (soc_reg_field_get(unit, reg, rval, PORT_NUMf) != 0x3f) { 10606 continue; 10607 } 10608 lanes_ctrl->mmu_group = sp_group2; 10609 lanes_ctrl->mmu_slots[0] = slot; 10610 break; 10611 } 10612 if (slot == _OVS_GROUP_TDM_LENGTH) { 10613 LOG_VERBOSE(BSL_LS_SOC_COMMON, 10614 (BSL_META_U(unit, 10615 "FAILED in search the empty mmu slot\n"))); 10616 return SOC_E_INTERNAL; 10617 } 10618 } 10619 if (lanes_ctrl->cur_mmu_slots[0] == -1) { 10620 for (i = 0; i < _OVS_GROUP_COUNT; i++) { 10621 if(cur_mmu[i].group == sp_group1) { 10622 lanes_ctrl->cur_mmu_group = cur_mmu[i].group; 10623 lanes_ctrl->cur_mmu_slots[0] = cur_mmu[i].slot; 10624 } 10625 } 10626 } 10627 10628 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 10629 SOC_IF_ERROR_RETURN(soc_th_port_lanes_ctrl_info_diag(unit, lanes_ctrl)); 10630 } 10631 10632 /* Perform migrating to new group/slot */ 10633 SOC_IF_ERROR_RETURN(soc_th_port_lanes_migrate(unit, lanes_ctrl)); 10634 10635 /* Re-structure the lanes control */ 10636 sal_memset(&re_lanes_ctrl, 0, sizeof(re_lanes_ctrl)); 10637 re_lanes_ctrl.port_base = lanes_ctrl->port_base; 10638 re_lanes_ctrl.lanes = lanes_ctrl->lanes; 10639 SOC_IF_ERROR_RETURN 10640 (soc_tomahawk_port_lanes_validate(unit, &re_lanes_ctrl)); 10641 sal_memcpy(lanes_ctrl, &re_lanes_ctrl, sizeof(re_lanes_ctrl)); 10642 return SOC_E_NONE; 10643 } else { 10644 LOG_VERBOSE(BSL_LS_SOC_COMMON, 10645 (BSL_META_U(unit, 10646 "FAILED in search lanes group\n"))); 10647 return SOC_E_INTERNAL; 10648 } 10649 } 10650 10651 if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) { 10652 /* ports being removed */ 10653 for (i = 0; i <= lanes_ctrl->phy_ports_len; i++) { 10654 if ((-1 == lanes_ctrl->cur_idb_slots[i]) || 10655 (-1 == lanes_ctrl->cur_mmu_slots[i])) { 10656 LOG_VERBOSE(BSL_LS_SOC_COMMON, 10657 (BSL_META_U(unit, 10658 "FAILED in search ports slots remove\n"))); 10659 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 10660 SOC_IF_ERROR_RETURN(soc_th_port_lanes_ctrl_info_diag(unit, lanes_ctrl)); 10661 } 10662 return SOC_E_INTERNAL; 10663 } 10664 } 10665 } else { 10666 /* ports being added */ 10667 if ((-1 == lanes_ctrl->cur_idb_slots[0]) || 10668 (-1 == lanes_ctrl->cur_mmu_slots[0])) { 10669 LOG_VERBOSE(BSL_LS_SOC_COMMON, 10670 (BSL_META_U(unit, 10671 "FAILED in search ports slots added\n"))); 10672 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 10673 SOC_IF_ERROR_RETURN(soc_th_port_lanes_ctrl_info_diag(unit, lanes_ctrl)); 10674 } 10675 return SOC_E_INTERNAL; 10676 } 10677 } 10678 } 10679 return SOC_E_NONE; 10680 } 10681 10682 soc_error_t 10683 soc_th_speed_set_init_ctrl(int unit, soc_th_port_lanes_t *lanes_ctrl) 10684 { 10685 soc_info_t *si = &SOC_INFO(unit); 10686 soc_port_t port_base = lanes_ctrl->port_base; 10687 10688 lanes_ctrl->oversub = SOC_PBMP_MEMBER(si->oversub_pbm, port_base); 10689 if (lanes_ctrl->oversub) { 10690 SOC_IF_ERROR_RETURN( 10691 soc_tomahawk_oversub_group_find(unit, lanes_ctrl)); 10692 } 10693 10694 return SOC_E_NONE; 10695 } 10696 10697 STATIC soc_error_t 10698 soc_th_os_mixed_sister_port_mode_get(int unit, int initTime, soc_th_port_lanes_t *lanes_ctrl) 10699 { 10700 soc_info_t *si = &SOC_INFO(unit); 10701 soc_port_t phy_port_base, phy_port; 10702 soc_port_t port_sub, port_sis; 10703 int port_sub_speed, port_sis_speed; 10704 soc_port_t port_base = lanes_ctrl->port_base; 10705 10706 if (lanes_ctrl->os_mixed_sister == 0) { 10707 return SOC_E_FAIL; 10708 } 10709 10710 phy_port = si->port_l2p_mapping[port_base]; 10711 if (-1 == phy_port) { 10712 return SOC_E_PORT; 10713 } 10714 phy_port_base = PORT_BLOCK_BASE_PORT(port_base); 10715 if ((phy_port_base != phy_port) && ((phy_port_base + 2) != phy_port)) { 10716 /* Not a controlling port */ 10717 return SOC_E_PORT; 10718 } 10719 10720 /* check mixed sister port mode */ 10721 port_sub = si->port_p2l_mapping[phy_port_base]; 10722 port_sis = si->port_p2l_mapping[phy_port_base + 2]; 10723 port_sub_speed = initTime ? si->port_speed_max[port_sub] : si->port_init_speed[port_sub]; 10724 port_sis_speed = initTime ? si->port_speed_max[port_sis] : si->port_init_speed[port_sis]; 10725 10726 if (!SOC_PBMP_MEMBER(si->all.disabled_bitmap, si->port_p2l_mapping[phy_port_base + 1]) || 10727 !SOC_PBMP_MEMBER(si->all.disabled_bitmap, si->port_p2l_mapping[phy_port_base + 3])) { 10728 return SOC_E_PORT; 10729 } 10730 10731 if (((port_sub_speed == 50000) && (port_sis_speed == 50000)) || 10732 ((port_sub_speed == 53000) && (port_sis_speed == 53000))) { 10733 lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_50_0_50_0; 10734 } else if (((port_sub_speed == 50000) && (port_sis_speed == 25000)) || 10735 ((port_sub_speed == 53000) && (port_sis_speed == 27000))) { 10736 lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_50_0_25_0; 10737 } else if (((port_sub_speed == 25000) && (port_sis_speed == 50000)) || 10738 ((port_sub_speed == 27000) && (port_sis_speed == 53000))) { 10739 lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_25_0_50_0; 10740 } else if (((port_sub_speed == 25000) && (port_sis_speed == 25000)) || 10741 ((port_sub_speed == 27000) && (port_sis_speed == 27000))) { 10742 lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_25_0_25_0; 10743 } else if (((port_sub_speed == 40000) && (port_sis_speed == 40000)) || 10744 ((port_sub_speed == 43000) && (port_sis_speed == 43000))) { 10745 lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_40_0_40_0; 10746 } else if (((port_sub_speed == 20000) && (port_sis_speed == 20000)) || 10747 ((port_sub_speed == 21000) && (port_sis_speed == 21000))) { 10748 lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_20_0_20_0; 10749 } else { 10750 lanes_ctrl->mixed_port_mode = MIXED_DUAL_MODE_0; 10751 } 10752 if (initTime == FALSE) { 10753 if ((si->port_init_speed[port_base] == 25000) || 10754 (si->port_init_speed[port_base] == 27000)) { 10755 lanes_ctrl->cur_lanes = 1; 10756 } else if ((si->port_init_speed[port_base] == 50000) || 10757 (si->port_init_speed[port_base] == 40000) || 10758 (si->port_init_speed[port_base] == 53000) || 10759 (si->port_init_speed[port_base] == 42000) || 10760 (si->port_init_speed[port_base] == 20000) || 10761 (si->port_init_speed[port_base] == 21000)) { 10762 lanes_ctrl->cur_lanes = 2; 10763 } else { 10764 return SOC_E_PORT; 10765 } 10766 } 10767 10768 return SOC_E_NONE; 10769 } 10770 10771 /* 10772 * Function: 10773 * soc_tomahawk_port_lanes_validate 10774 * Description: 10775 * Validate if the specified number of lanes can be configured on a port, 10776 * If the request can be done, fill in the control structure which will 10777 * be used by the routines programming the hardware. 10778 * Parameters: 10779 * unit - Device number 10780 * lanes_ctrl - Control structure 10781 * 10782 * Each TSC can be configured into following 5 mode: 10783 * Lane number 0 1 2 3 10784 * ------------ ----------- -------- ------------ -------- 10785 * single port 100G/40G x x x 10786 * dual port 50G/d40G/20G x 50G/d40G/20G x 10787 * tri_023 port 50G/d40g/20G x 25G/10G 25G/10G 10788 * tri_012 port 25G/10G 25G/10G 50G/d40G/20G x 10789 * quad port 25G/10G 25G/10G 25G/10G 25G/10G 10790 * 10791 * (Note: All of the above apply to equivalent HG line rate speeds as well) 10792 * 10793 * lanes mode valid lane index 10794 * ------------ ---------------- ---------------- 10795 * new current new current 10796 * --- ------- ------- ------- 10797 * #1 4 1 single quad 0 10798 * #2 4 1 single tri_012 0 10799 * #3 4 2 single tri_023 0 10800 * #4 4 2 single dual 0 10801 * #5 2 1 tri_023 quad 0 10802 * #6 2 1 tri_012 quad 2 10803 * #7 2 1 dual tri_023 2 10804 * #8 2 1 dual tri_012 0 10805 * #9 2 4 dual single 0 10806 * #10 1 2 tri_023 dual 2 10807 * #11 1 2 tri_012 dual 0 10808 * #12 1 2 quad tri_023 0 10809 * #13 1 2 quad tri_012 2 10810 * #14 1 4 quad single 0 10811 * Following mode change requires 2 transition 10812 * - from single to tri_023: #9 + #10 10813 * - from single to tri_012: #9 + #11 10814 * Following mode change are the result of lane change on multiple ports 10815 * - from quad to dual: #12 + #7 or #13 + #8 10816 * - from dual to quad: #10 + #12 or #11 + # 13 10817 * - from tri_023 to tri_012: #7 + #11 or #12 + #6 10818 * - from tri_012 to tri_023: #8 + #10 or #13 + #5 10819 * 10820 * Logical port number will stay the same after conversion, for example 10821 * converting single port to dual port, the logical port number of lane 0 10822 * will be changed. 10823 */ 10824 int 10825 soc_tomahawk_port_lanes_validate(int unit, soc_th_port_lanes_t *lanes_ctrl) 10826 { 10827 soc_info_t *si = &SOC_INFO(unit); 10828 int port_base, phy_port_base; 10829 uint32 rval; 10830 int i; 10831 int chk_mixed_sister = 0; 10832 10833 lanes_ctrl->os_mixed_sister = si->os_mixed_sister_25_50_enable; 10834 10835 /* Find physical and mmu port number for the specified port */ 10836 port_base = lanes_ctrl->port_base; 10837 phy_port_base = si->port_l2p_mapping[port_base]; 10838 if (phy_port_base == -1) { 10839 return SOC_E_PORT; 10840 } 10841 lanes_ctrl->oversub = SOC_PBMP_MEMBER(si->oversub_pbm, port_base); 10842 10843 /* Find lane index for the specified port (base port) */ 10844 lanes_ctrl->bindex = SOC_PORT_BINDEX(unit, phy_port_base); 10845 10846 /* Get the current mode */ 10847 SOC_IF_ERROR_RETURN(READ_CLPORT_MODE_REGr(unit, port_base, &rval)); 10848 lanes_ctrl->cur_mode = soc_reg_field_get(unit, CLPORT_MODE_REGr, rval, 10849 XPORT0_CORE_PORT_MODEf); 10850 10851 /* Figure out the current number of lanes */ 10852 switch (lanes_ctrl->cur_mode) { 10853 case SOC_TH_PORT_MODE_QUAD: 10854 lanes_ctrl->cur_lanes = 1; 10855 break; 10856 case SOC_TH_PORT_MODE_TRI_012: 10857 lanes_ctrl->cur_lanes = lanes_ctrl->bindex == 0 ? 1 : 2; 10858 break; 10859 case SOC_TH_PORT_MODE_TRI_023: 10860 lanes_ctrl->cur_lanes = lanes_ctrl->bindex == 0 ? 2 : 1; 10861 break; 10862 case SOC_TH_PORT_MODE_DUAL: 10863 if (lanes_ctrl->os_mixed_sister == 0) { 10864 lanes_ctrl->cur_lanes = 2; 10865 } else { 10866 chk_mixed_sister = 1; 10867 } 10868 break; 10869 case SOC_TH_PORT_MODE_SINGLE: 10870 lanes_ctrl->cur_lanes = 4; 10871 break; 10872 default: 10873 return SOC_E_FAIL; 10874 } 10875 10876 /* check the mixed sister port mode */ 10877 if (chk_mixed_sister) { 10878 SOC_IF_ERROR_RETURN(soc_th_os_mixed_sister_port_mode_get(unit, FALSE, lanes_ctrl)); 10879 } 10880 10881 /* Validate new number of lanes */ 10882 if (lanes_ctrl->lanes == 4 || lanes_ctrl->cur_lanes == 4) { 10883 if (lanes_ctrl->bindex & 0x3) { 10884 return SOC_E_PARAM; 10885 } 10886 } else if (lanes_ctrl->lanes == 2 || lanes_ctrl->cur_lanes == 2) { 10887 if (lanes_ctrl->bindex & 0x1) { 10888 return SOC_E_PARAM; 10889 } 10890 } else if (lanes_ctrl->lanes != 1) { 10891 return SOC_E_PARAM; 10892 } 10893 10894 /* No change to number of lanes */ 10895 if (lanes_ctrl->lanes == lanes_ctrl->cur_lanes) { 10896 return SOC_E_NONE; 10897 } 10898 10899 /* Figure out new mode */ 10900 if (lanes_ctrl->lanes == 4) { 10901 lanes_ctrl->mode = SOC_TH_PORT_MODE_SINGLE; 10902 } else if (lanes_ctrl->lanes == 2) { 10903 if (lanes_ctrl->cur_mode == SOC_TH_PORT_MODE_QUAD) { 10904 lanes_ctrl->mode = lanes_ctrl->bindex == 0 ? 10905 SOC_TH_PORT_MODE_TRI_023 : SOC_TH_PORT_MODE_TRI_012; 10906 } else { 10907 lanes_ctrl->mode = SOC_TH_PORT_MODE_DUAL; 10908 } 10909 } else{ 10910 if (lanes_ctrl->cur_mode == SOC_TH_PORT_MODE_DUAL) { 10911 if (lanes_ctrl->os_mixed_sister && 10912 (lanes_ctrl->mixed_port_mode != MIXED_DUAL_MODE_40_0_40_0)) { 10913 lanes_ctrl->mode = SOC_TH_PORT_MODE_DUAL; 10914 } else { 10915 lanes_ctrl->mode = lanes_ctrl->bindex == 0 ? 10916 SOC_TH_PORT_MODE_TRI_012 : SOC_TH_PORT_MODE_TRI_023; 10917 } 10918 } else { 10919 lanes_ctrl->mode = SOC_TH_PORT_MODE_QUAD; 10920 } 10921 } 10922 if (lanes_ctrl->oversub) { 10923 if (SOC_TH_PORT_MODE_TRI_012 == lanes_ctrl->mode || 10924 SOC_TH_PORT_MODE_TRI_023 == lanes_ctrl->mode) { 10925 return SOC_E_PARAM; 10926 } 10927 } 10928 if (lanes_ctrl->os_mixed_sister) { 10929 if ((lanes_ctrl->mixed_port_mode == MIXED_DUAL_MODE_50_0_25_0) && 10930 (SOC_TH_PORT_MODE_SINGLE == lanes_ctrl->mode) && 10931 (SOC_TH_PORT_MODE_DUAL == lanes_ctrl->cur_mode)) { 10932 return SOC_E_PARAM; 10933 } 10934 } 10935 10936 lanes_ctrl->phy_ports_len = 0; 10937 if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) { 10938 /* Figure out which port(s) to be removed */ 10939 if (lanes_ctrl->lanes == 4) { 10940 if (lanes_ctrl->cur_mode == SOC_TH_PORT_MODE_TRI_012 || 10941 lanes_ctrl->cur_mode == SOC_TH_PORT_MODE_QUAD) { 10942 if (si->port_p2l_mapping[phy_port_base + 1] != -1) { 10943 lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] = 10944 phy_port_base + 1; 10945 } 10946 } 10947 if (si->port_p2l_mapping[phy_port_base + 2] != -1) { 10948 lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] = 10949 phy_port_base + 2; 10950 } 10951 if (lanes_ctrl->cur_mode == SOC_TH_PORT_MODE_TRI_023 || 10952 lanes_ctrl->cur_mode == SOC_TH_PORT_MODE_QUAD) { 10953 if (si->port_p2l_mapping[phy_port_base + 3] != -1) { 10954 lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] = 10955 phy_port_base + 3; 10956 } 10957 } 10958 } else { 10959 if (si->port_p2l_mapping[phy_port_base + 1] != -1) { 10960 lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] = 10961 phy_port_base + 1; 10962 } 10963 } 10964 } else { /* Figure out which port(s) to be added */ 10965 if (lanes_ctrl->lanes == 2) { 10966 if (si->port_p2l_mapping[phy_port_base + 2] != -1) { 10967 lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] = 10968 phy_port_base + 2; 10969 } 10970 } else { 10971 if (lanes_ctrl->os_mixed_sister == 0) { 10972 if (si->port_p2l_mapping[phy_port_base + 1] != -1) { 10973 lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] = 10974 phy_port_base + 1; 10975 } 10976 } else { 10977 if (((lanes_ctrl->lanes != 2) && (lanes_ctrl->cur_lanes != 1)) && 10978 ((lanes_ctrl->lanes != 1) && (lanes_ctrl->cur_lanes != 2))) { 10979 lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] = 10980 phy_port_base + 1; 10981 } /* 1x25G+1x50G,1x50G+1x25G,2x25G don't need to change number of port */ 10982 if ((lanes_ctrl->lanes == 1) && (lanes_ctrl->cur_lanes == 4)) { 10983 lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] = 10984 phy_port_base + 1; 10985 } /* 1x100G --> 4x25G */ 10986 } 10987 10988 if (lanes_ctrl->cur_mode == SOC_TH_PORT_MODE_SINGLE) { 10989 if (si->port_p2l_mapping[phy_port_base + 2] != -1) { 10990 lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] = 10991 phy_port_base + 2; 10992 } 10993 if (si->port_p2l_mapping[phy_port_base + 3] != -1) { 10994 lanes_ctrl->phy_ports[lanes_ctrl->phy_ports_len++] = 10995 phy_port_base + 3; 10996 } 10997 } 10998 } 10999 } 11000 11001 /* Initialize all OS group/slot info to -1 */ 11002 lanes_ctrl->cur_idb_group = lanes_ctrl->idb_group = -1; 11003 lanes_ctrl->cur_mmu_group = lanes_ctrl->mmu_group = -1; 11004 for (i = 0; i <= lanes_ctrl->phy_ports_len; i++) { 11005 lanes_ctrl->idb_slots[i] = -1; 11006 lanes_ctrl->mmu_slots[i] = -1; 11007 lanes_ctrl->cur_idb_slots[i] = -1; 11008 lanes_ctrl->cur_mmu_slots[i] = -1; 11009 } 11010 11011 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 11012 SOC_IF_ERROR_RETURN(soc_th_port_lanes_ctrl_info_diag(unit, lanes_ctrl)); 11013 } 11014 if (lanes_ctrl->os_mixed_sister == 0) { 11015 if (lanes_ctrl->oversub) { 11016 SOC_IF_ERROR_RETURN(soc_tomahawk_oversub_group_find(unit, lanes_ctrl)); 11017 } 11018 } else { 11019 if (((lanes_ctrl->lanes == 1) && (lanes_ctrl->cur_lanes == 4)) || 11020 ((lanes_ctrl->lanes == 4) && (lanes_ctrl->cur_lanes == 1)) || 11021 ((lanes_ctrl->lanes == 4) && (lanes_ctrl->cur_lanes == 2)) || 11022 ((lanes_ctrl->lanes == 2) && (lanes_ctrl->cur_lanes == 4)) || 11023 (((lanes_ctrl->lanes != 2) && (lanes_ctrl->cur_lanes != 1)) && 11024 ((lanes_ctrl->lanes != 1) && (lanes_ctrl->cur_lanes != 2)))) { 11025 SOC_IF_ERROR_RETURN(soc_tomahawk_oversub_group_find(unit, lanes_ctrl)); 11026 } 11027 } 11028 11029 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 11030 SOC_IF_ERROR_RETURN(soc_th_port_lanes_ctrl_info_diag(unit, lanes_ctrl)); 11031 } 11032 11033 return SOC_E_NONE; 11034 } 11035 11036 STATIC soc_error_t 11037 _soc_tomahawk_flexed_port_speed_get(int unit, soc_th_port_lanes_t *lanes_ctrl, 11038 uint32 *port_speed) 11039 { 11040 uint32 vco; 11041 soc_error_t rc; 11042 int port = lanes_ctrl->port_base; 11043 int higigPort = IS_HG_PORT(unit, port); 11044 soc_info_t *si = &SOC_INFO(unit); 11045 11046 if (TH_FLEXPORT_SPEED_SET_NUM_LANES == lanes_ctrl->lanes) { 11047 if (((lanes_ctrl->speed >= 100000) && (si->port_speed_max[port] < 100000)) || 11048 ((lanes_ctrl->speed >= 50000) && (si->port_speed_max[port] < 50000)) || 11049 ((lanes_ctrl->speed >= 40000) && (si->port_speed_max[port] < 40000)) || 11050 ((lanes_ctrl->speed >= 25000) && (si->port_speed_max[port] < 25000)) || 11051 ((lanes_ctrl->speed >= 20000) && (si->port_speed_max[port] < 20000)) || 11052 ((lanes_ctrl->speed >= 10000) && (si->port_speed_max[port] < 10000))) { 11053 return SOC_E_CONFIG; 11054 } else { 11055 *port_speed = lanes_ctrl->speed; 11056 return SOC_E_NONE; 11057 } 11058 } 11059 /* Determine new port speed based on vco frequency of the PM and number of 11060 * lanes in the flexed port. 11061 */ 11062 rc = soc_phyctrl_redirect_control_get(unit, port, 0, 0, 0, SOC_PHY_CONTROL_VCO_FREQ, &vco); 11063 rc = soc_phyctrl_control_get(unit, port, 11064 SOC_PHY_CONTROL_VCO_FREQ, 11065 &vco); 11066 if (SOC_E_NONE != rc) { 11067 /* Set default vco, phyctrl may not exist, for e.x. ext phy */ 11068 if (si->port_init_speed[port] >= 50000) { 11069 vco = 25781; 11070 } else if (si->port_init_speed[port] >= 40000) { 11071 vco = 20625; 11072 } else if (si->port_init_speed[port] >= 25000) { 11073 vco = 25781; 11074 } else { 11075 vco = 20625; 11076 } 11077 } 11078 if (lanes_ctrl->lanes == 1) { 11079 /* Possibilities are 25G/10G */ 11080 if (vco >= 25781) { 11081 *port_speed = higigPort ? 27000 : 25000; 11082 } else { 11083 *port_speed = higigPort ? 11000 : 10000; 11084 } 11085 } else if (lanes_ctrl->lanes == 2) { 11086 if (vco >= 25781) { 11087 *port_speed = higigPort ? 53000 : 50000; 11088 } else { 11089 *port_speed = higigPort ? 42000 : 40000; 11090 } 11091 } else { 11092 /* Possibilities are 100G/40G */ 11093 if (vco >= 25781) { 11094 *port_speed = higigPort ? 106000 : 100000; 11095 } else { 11096 *port_speed = higigPort ? 42000 : 40000; 11097 } 11098 } 11099 if (*port_speed > SOC_INFO(unit).port_speed_max[port]) { 11100 return SOC_E_CONFIG; 11101 } 11102 return SOC_E_NONE; 11103 } 11104 11105 STATIC int 11106 _soc_tomahawk_xmt_start_cnt_update(int unit, int extra_delay) 11107 { 11108 int port; 11109 int port_speed; 11110 soc_th_asf_mode_e mode = _SOC_TH_ASF_MODE_SAF; 11111 soc_info_t *si; 11112 11113 si = &SOC_INFO(unit); 11114 PBMP_ALL_ITER(unit, port) { 11115 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) { 11116 continue; 11117 } 11118 port_speed = si->port_init_speed[port]; 11119 if (!SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), port)) { 11120 SOC_IF_ERROR_RETURN( 11121 soc_th_port_asf_mode_get(unit, port, port_speed, &mode)); 11122 } 11123 SOC_IF_ERROR_RETURN( 11124 soc_th_port_asf_xmit_start_count_set(unit, port, port_speed, 11125 mode, extra_delay)); 11126 } 11127 11128 return SOC_E_NONE; 11129 } 11130 11131 STATIC int 11132 _soc_tomahawk_port_lanes_update_tdm(int unit, soc_th_port_lanes_t *lanes_ctrl) 11133 { 11134 soc_control_t *soc; 11135 soc_info_t *si; 11136 _soc_tomahawk_tdm_t *tdm; 11137 int port_base, port, phy_port, idb_port, mmu_port; 11138 int group, pipe, slot, id, i, clport, mode, lane, port_block_base; 11139 int rv; 11140 soc_reg_t reg; 11141 uint32 rval; 11142 uint32 inst; 11143 11144 static const soc_reg_t pblk_calendar_regs[] ={ 11145 IS_PBLK0_CALENDARr, IS_PBLK1_CALENDARr, 11146 IS_PBLK2_CALENDARr, IS_PBLK3_CALENDARr, 11147 IS_PBLK4_CALENDARr, IS_PBLK5_CALENDARr, 11148 IS_PBLK6_CALENDARr, IS_PBLK7_CALENDARr 11149 }; 11150 static const soc_reg_t mmu_pblk_calendar_regs[] = { 11151 PBLK0_CALENDARr, PBLK1_CALENDARr, PBLK2_CALENDARr, PBLK3_CALENDARr, 11152 PBLK4_CALENDARr, PBLK5_CALENDARr, PBLK6_CALENDARr, PBLK7_CALENDARr 11153 }; 11154 static int pblk_slots[SOC_TH_PORT_RATIO_COUNT][7] = { 11155 { 0, -1, 0, 0, -1, 0, -1 }, /* SOC_TH_PORT_RATIO_SINGLE */ 11156 { 0, -1, 2, 0, -1, 2, -1 }, /* SOC_TH_PORT_RATIO_DUAL_1_1 */ 11157 { 0, 0, 2, 0, 0, 2, -1 }, /* SOC_TH_PORT_RATIO_DUAL_2_1 */ 11158 { 0, 2, 2, 0, 2, 2, -1 }, /* SOC_TH_PORT_RATIO_DUAL_1_2 */ 11159 { 0, -1, 2, 0, -1, 3, -1 }, /* SOC_TH_PORT_RATIO_TRI_023_2_1_1 */ 11160 { 0, 0, 2, 0, 0, 3, -1 }, /* SOC_TH_PORT_RATIO_TRI_023_4_1_1 */ 11161 { 0, -1, 2, 1, -1, 2, -1 }, /* SOC_TH_PORT_RATIO_TRI_012_1_1_2 */ 11162 { 0, 2, 2, 1, 2, 2, -1 }, /* SOC_TH_PORT_RATIO_TRI_012_1_1_4 */ 11163 { 0, -1, 2, 1, -1, 3, -1 } /* SOC_TH_PORT_RATIO_QUAD */ 11164 }; 11165 11166 soc = SOC_CONTROL(unit); 11167 si = &SOC_INFO(unit); 11168 tdm = soc->tdm_info; 11169 port_base = lanes_ctrl->port_base; 11170 phy_port = si->port_l2p_mapping[port_base]; 11171 pipe = si->port_pipe[port_base]; 11172 id = si->port_serdes[port_base] & 7; 11173 clport = si->port_serdes[port_base]; 11174 11175 if (!SOC_PBMP_MEMBER(si->oversub_pbm, port_base)) { 11176 rv = _soc_tomahawk_xmt_start_cnt_update(unit, 9); 11177 if (SOC_FAILURE(rv)){ 11178 LOG_ERROR(BSL_LS_SOC_COMMON, 11179 (BSL_META_U(unit, 11180 "FAILED in" 11181 "_soc_tomahawk_xmt_start_cnt_update\n"))); 11182 return rv; 11183 } 11184 11185 rv = _soc_tomahawk_tdm_calculation(unit, FALSE, tdm); 11186 if (SOC_FAILURE(rv)){ 11187 LOG_ERROR(BSL_LS_SOC_COMMON, 11188 (BSL_META_U(unit, 11189 "FAILED in" 11190 "_soc_tomahawk_tdm_calculation\n"))); 11191 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit)); 11192 return rv; 11193 } 11194 11195 rv = _soc_tomahawk_tdm_idb_calendar_set(unit, -1, pipe); 11196 if (SOC_FAILURE(rv)){ 11197 LOG_ERROR(BSL_LS_SOC_COMMON, 11198 (BSL_META_U(unit, 11199 "FAILED in" 11200 "_soc_tomahawk_tdm_idb_calendar_set\n"))); 11201 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit)); 11202 return rv; 11203 } 11204 11205 rv = _soc_tomahawk_tdm_mmu_calendar_set(unit, -1, pipe); 11206 if (SOC_FAILURE(rv)){ 11207 LOG_ERROR(BSL_LS_SOC_COMMON, 11208 (BSL_META_U(unit, 11209 "FAILED in" 11210 "_soc_tomahawk_tdm_mmu_calendar_set\n"))); 11211 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit)); 11212 return rv; 11213 } 11214 11215 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_calculation_free_memory(unit)); 11216 11217 rv = _soc_tomahawk_xmt_start_cnt_update(unit, 0); 11218 if (SOC_FAILURE(rv)){ 11219 LOG_ERROR(BSL_LS_SOC_COMMON, 11220 (BSL_META_U(unit, 11221 "FAILED in" 11222 "_soc_tomahawk_xmt_start_cnt_update\n"))); 11223 return rv; 11224 } 11225 } else if ((lanes_ctrl->class != lanes_ctrl->cur_class) || 11226 ((SOC_TH_SPEED_CLASS_40G == lanes_ctrl->class) && 11227 (-1 != lanes_ctrl->cur_idb_group) && 11228 (-1 != lanes_ctrl->cur_mmu_group) && 11229 (-1 != lanes_ctrl->idb_group) && 11230 (-1 != lanes_ctrl->mmu_group))) { 11231 /* Update CLPORT details in tdm structure*/ 11232 soc_tomahawk_port_ratio_get(unit, 0 /*initTime*/, clport, &tdm->port_ratio[clport]); 11233 11234 /* Remove idb port(s) from current group */ 11235 group = lanes_ctrl->cur_idb_group; 11236 reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[group])[pipe]; 11237 rval = 0; 11238 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, 0x3f); 11239 soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, 0); 11240 slot = lanes_ctrl->cur_idb_slots[0]; 11241 if (slot < 0) { 11242 return SOC_E_INTERNAL; 11243 } 11244 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval)); 11245 if ((lanes_ctrl->lanes > lanes_ctrl->cur_lanes) && 11246 (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes)) { 11247 /* port(s) to be removed */ 11248 for (i = 0; i < lanes_ctrl->phy_ports_len; i++) { 11249 slot = lanes_ctrl->cur_idb_slots[i + 1]; 11250 if (slot < 0) { 11251 return SOC_E_INTERNAL; 11252 } 11253 SOC_IF_ERROR_RETURN 11254 (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval)); 11255 } 11256 } 11257 if (lanes_ctrl->cur_idb_empty && 11258 (lanes_ctrl->idb_group != lanes_ctrl->cur_idb_group)) { /* old group become empty */ 11259 reg = SOC_REG_UNIQUE_ACC(unit, IS_OVR_SUB_GRP_CFGr)[pipe]; 11260 SOC_IF_ERROR_RETURN 11261 (soc_reg32_set(unit, reg, REG_PORT_ANY, group, 0)); 11262 } 11263 11264 /* Add idb port(s) to new group */ 11265 group = lanes_ctrl->idb_group; 11266 reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[group])[pipe]; 11267 rval = 0; 11268 soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, id & 0x7); 11269 idb_port = si->port_l2i_mapping[port_base]; 11270 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, idb_port); 11271 slot = lanes_ctrl->idb_slots[0] != -1 ? lanes_ctrl->idb_slots[0] : 0; 11272 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval)); 11273 if ((lanes_ctrl->lanes < lanes_ctrl->cur_lanes) && 11274 (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes)) { 11275 /* port(s) to be added */ 11276 for (i = 0; i < lanes_ctrl->phy_ports_len; i++) { 11277 port = si->port_p2l_mapping[lanes_ctrl->phy_ports[i]]; 11278 idb_port = si->port_l2i_mapping[port]; 11279 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, idb_port); 11280 slot = lanes_ctrl->idb_slots[0] != -1 ? 11281 lanes_ctrl->idb_slots[i + 1] : i + 1; 11282 SOC_IF_ERROR_RETURN 11283 (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval)); 11284 } 11285 } 11286 if (lanes_ctrl->idb_slots[0] == -1) { /* new group */ 11287 reg = SOC_REG_UNIQUE_ACC(unit, IS_OVR_SUB_GRP_CFGr)[pipe]; 11288 rval = 0; 11289 soc_reg_field_set(unit, reg, &rval, SAME_SPACINGf, 4); 11290 soc_reg_field_set(unit, reg, &rval, SISTER_SPACINGf, 4); 11291 soc_reg_field_set(unit, reg, &rval, SPEEDf, lanes_ctrl->class); 11292 SOC_IF_ERROR_RETURN 11293 (soc_reg32_set(unit, reg, REG_PORT_ANY, group, rval)); 11294 } 11295 11296 /* Remove mmu port(s) from current group */ 11297 group = lanes_ctrl->cur_mmu_group; 11298 reg = mmu_grp_tbl_regs[group]; 11299 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 11300 rval = 0; 11301 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, 0x3f); 11302 soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, 0); 11303 slot = lanes_ctrl->cur_mmu_slots[0]; 11304 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval)); 11305 if ((lanes_ctrl->lanes > lanes_ctrl->cur_lanes) && 11306 (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes)) { 11307 /* port(s) to be removed */ 11308 for (i = 0; i < lanes_ctrl->phy_ports_len; i++) { 11309 slot = lanes_ctrl->cur_mmu_slots[i + 1]; 11310 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval)); 11311 } 11312 } 11313 if (lanes_ctrl->cur_idb_empty && 11314 (lanes_ctrl->idb_group != lanes_ctrl->cur_idb_group)) { /* old group became empty */ 11315 reg = OVR_SUB_GRP_CFGr; 11316 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, group, 0)); 11317 } 11318 11319 /* Add mmu port(s) to new group */ 11320 group = lanes_ctrl->mmu_group; 11321 reg = mmu_grp_tbl_regs[group]; 11322 rval = 0; 11323 soc_reg_field_set(unit, reg, &rval, PHY_PORT_IDf, id & 0x7); 11324 mmu_port = si->port_p2m_mapping[phy_port]; 11325 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, mmu_port & 0x3f); 11326 slot = lanes_ctrl->mmu_slots[0] != -1 ? lanes_ctrl->mmu_slots[0] : 0; 11327 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval)); 11328 if ((lanes_ctrl->lanes < lanes_ctrl->cur_lanes) && 11329 (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes)) { 11330 /* port(s) to be added */ 11331 for (i = 0; i < lanes_ctrl->phy_ports_len; i++) { 11332 mmu_port = si->port_p2m_mapping[lanes_ctrl->phy_ports[i]]; 11333 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, mmu_port & 0x3f); 11334 slot = lanes_ctrl->mmu_slots[0] != -1 ? 11335 lanes_ctrl->mmu_slots[i + 1] : i + 1; 11336 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval)); 11337 } 11338 } 11339 if (lanes_ctrl->mmu_slots[0] == -1) { /* new group */ 11340 reg = OVR_SUB_GRP_CFGr; 11341 rval = 0; 11342 soc_reg_field_set(unit, reg, &rval, SAME_SPACINGf, 11343 lanes_ctrl->class >= 4 ? 4 : 8); 11344 soc_reg_field_set(unit, reg, &rval, SISTER_SPACINGf, 4); 11345 soc_reg_field_set(unit, reg, &rval, SPEEDf, lanes_ctrl->class); 11346 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, group, rval)); 11347 } 11348 } 11349 11350 if ((TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes) || 11351 ((TH_FLEXPORT_SPEED_SET_NUM_LANES == lanes_ctrl->lanes) && 11352 ((lanes_ctrl->class < 4 && lanes_ctrl->cur_class >= 4) || 11353 (lanes_ctrl->class >= 4 && lanes_ctrl->cur_class < 4)))) { 11354 mode = tdm->port_ratio[clport]; 11355 port_block_base = PORT_BLOCK_BASE_PORT(port_base); 11356 /* Reprogram IS port block calendar */ 11357 reg = SOC_REG_UNIQUE_ACC(unit, pblk_calendar_regs[id])[pipe]; 11358 rval = 0; 11359 soc_reg_field_set(unit, reg, &rval, VALIDf, 1); 11360 soc_reg_field_set(unit, reg, &rval, SPACINGf, 4); 11361 for (slot = 0; slot < 7; slot++) { 11362 lane = pblk_slots[mode][slot]; 11363 if (lane == -1) { 11364 SOC_IF_ERROR_RETURN 11365 (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, 0)); 11366 continue; 11367 } 11368 port = si->port_p2l_mapping[port_block_base + lane]; 11369 idb_port = si->port_l2i_mapping[port]; 11370 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, idb_port); 11371 SOC_IF_ERROR_RETURN 11372 (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval)); 11373 } 11374 11375 /* Reprogram MMU port block calendar */ 11376 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 11377 reg = mmu_pblk_calendar_regs[id]; 11378 rval = 0; 11379 soc_reg_field_set(unit, reg, &rval, VALIDf, 1); 11380 soc_reg_field_set(unit, reg, &rval, SPACINGf, 11381 lanes_ctrl->class >= 4 ? 4 : 8); 11382 for (slot = 0; slot < 7; slot++) { 11383 lane = pblk_slots[mode][slot]; 11384 if (lane == -1) { 11385 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, 0)); 11386 continue; 11387 } 11388 mmu_port = si->port_p2m_mapping[port_block_base + lane]; 11389 soc_reg_field_set(unit, reg, &rval, PORT_NUMf, mmu_port & 0x3f); 11390 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, inst, slot, rval)); 11391 } 11392 } 11393 11394 return SOC_E_NONE; 11395 } 11396 11397 STATIC soc_error_t 11398 _soc_tomahawk_obm_counters_reset(int unit, soc_port_t port) 11399 { 11400 int idx = 0; 11401 soc_ctr_control_info_t ctrl_info; 11402 soc_reg_t obm_counter_regs[] = { 11403 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_LO, 11404 SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_LO, 11405 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSY_HI, 11406 SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSY_HI, 11407 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS0, 11408 SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS0, 11409 SOC_COUNTER_NON_DMA_PORT_DROP_PKT_OBM_LOSSLESS1, 11410 SOC_COUNTER_NON_DMA_PORT_DROP_BYTE_OBM_LOSSLESS1 11411 }; 11412 uint64 my_zero; 11413 11414 ctrl_info.instance_type = SOC_CTR_INSTANCE_TYPE_PORT; 11415 ctrl_info.instance = port; 11416 COMPILER_64_ZERO(my_zero); 11417 for (idx = 0; idx < COUNTOF(obm_counter_regs); idx++) { 11418 SOC_IF_ERROR_RETURN 11419 (soc_counter_generic_set(unit, obm_counter_regs[idx], ctrl_info, 0, 11420 0, my_zero)); 11421 } 11422 11423 return SOC_E_NONE; 11424 } 11425 11426 soc_error_t 11427 soc_tomahawk_edb_buf_reset(int unit, soc_port_t port, int reset) 11428 { 11429 uint32 entry[SOC_MAX_MEM_WORDS]; 11430 soc_info_t *si = &SOC_INFO(unit); 11431 int phy_port, index; 11432 11433 phy_port = si->port_l2p_mapping[port]; 11434 11435 /* In Tomahawk2, EGR_PER_PORT_BUFFER_SFT_RESETm, EGR_ENABLEm are indexed 11436 * by physical port num */ 11437 index = SOC_IS_TOMAHAWK2(unit) ? phy_port : port; 11438 11439 if (reset) { 11440 soc_reg_t reg; 11441 soc_timeout_t to; 11442 int pipe; 11443 uint32 rval, level; 11444 11445 pipe = si->port_pipe[port]; 11446 reg = SOC_REG_UNIQUE_ACC(unit, EGR_EDB_MISC_CTRLr)[pipe]; 11447 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 11448 soc_reg_field_set(unit, reg, &rval, SELECT_CURRENT_USED_ENTRIESf, 1); 11449 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 11450 11451 soc_timeout_init(&to, 250000, 0); 11452 /* Poll until EDB buffer is empty */ 11453 for (;;) { 11454 SOC_IF_ERROR_RETURN 11455 (READ_EGR_MAX_USED_ENTRIESm(unit, MEM_BLOCK_ALL, 11456 phy_port, entry)); 11457 level = soc_mem_field32_get(unit, EGR_MAX_USED_ENTRIESm, 11458 entry, LEVELf); 11459 if (!level) { 11460 break; 11461 } 11462 if (soc_timeout_check(&to)) { 11463 LOG_ERROR(BSL_LS_SOC_COMMON, 11464 (BSL_META_U(unit, 11465 "EDBBufferDrainTimeOut:port %d,%s, timeout" 11466 "(pending: %d)\n"), 11467 unit, SOC_PORT_NAME(unit, port), level)); 11468 return SOC_E_INTERNAL; 11469 } 11470 } 11471 SOC_IF_ERROR_RETURN(READ_EGR_ENABLEm(unit, MEM_BLOCK_ALL, index, entry)); 11472 soc_mem_field32_set(unit, EGR_ENABLEm, entry, PRT_ENABLEf, !reset); 11473 SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, index, entry)); 11474 SOC_IF_ERROR_RETURN 11475 (READ_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL, 11476 index, entry)); 11477 soc_mem_field32_set(unit, EGR_PER_PORT_BUFFER_SFT_RESETm, 11478 entry, ENABLEf, reset); 11479 SOC_IF_ERROR_RETURN 11480 (WRITE_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL, 11481 index, entry)); 11482 } else { 11483 uint32 rval = 0; 11484 /* 11485 * Initialize EP credits in MMU so EP is in charge of distributing 11486 * the correct number of credits 11487 */ 11488 soc_reg_field_set(unit, MMU_PORT_CREDITr, &rval, INITIALIZEf, 1); 11489 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, MMU_PORT_CREDITr, port, 0, rval)); 11490 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, MMU_PORT_CREDITr, port, 0, 0)); 11491 11492 /* Release EDB port buffer reset and enable cell request generation in EP */ 11493 SOC_IF_ERROR_RETURN 11494 (READ_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL, 11495 index, entry)); 11496 soc_mem_field32_set(unit, EGR_PER_PORT_BUFFER_SFT_RESETm, 11497 entry, ENABLEf, reset); 11498 SOC_IF_ERROR_RETURN 11499 (WRITE_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL, 11500 index, entry)); 11501 SOC_IF_ERROR_RETURN(READ_EGR_ENABLEm(unit, MEM_BLOCK_ALL, index, entry)); 11502 soc_mem_field32_set(unit, EGR_ENABLEm, entry, PRT_ENABLEf, !reset); 11503 SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, index, entry)); 11504 } 11505 return SOC_E_NONE; 11506 } 11507 11508 soc_error_t 11509 soc_tomahawk_idb_buf_reset(int unit, soc_port_t port, int reset) 11510 { 11511 soc_reg_t reg, reg1; 11512 int port_block_base, phy_port, lane; 11513 int pipe, obm, clport, obm_usage_count = ~0, ca_empty = 0; 11514 uint32 rval; 11515 uint64 rval1, rval2; 11516 soc_info_t *si = &SOC_INFO(unit); 11517 11518 static const soc_reg_t idb_obm_usage_regs[] = { 11519 IDB_OBM0_USAGEr, IDB_OBM1_USAGEr, 11520 IDB_OBM2_USAGEr, IDB_OBM3_USAGEr, 11521 IDB_OBM4_USAGEr, IDB_OBM5_USAGEr, 11522 IDB_OBM6_USAGEr, IDB_OBM7_USAGEr 11523 }; 11524 static const soc_reg_t idb_obm_ca_status_regs[] = { 11525 IDB_OBM0_CA_HW_STATUSr, IDB_OBM1_CA_HW_STATUSr, 11526 IDB_OBM2_CA_HW_STATUSr, IDB_OBM3_CA_HW_STATUSr, 11527 IDB_OBM4_CA_HW_STATUSr, IDB_OBM5_CA_HW_STATUSr, 11528 IDB_OBM6_CA_HW_STATUSr, IDB_OBM7_CA_HW_STATUSr 11529 }; 11530 static const soc_reg_t obm_ctrl_regs[] = { 11531 IDB_OBM0_CONTROLr, IDB_OBM1_CONTROLr, 11532 IDB_OBM2_CONTROLr, IDB_OBM3_CONTROLr, 11533 IDB_OBM4_CONTROLr, IDB_OBM5_CONTROLr, 11534 IDB_OBM6_CONTROLr, IDB_OBM7_CONTROLr 11535 }; 11536 static const soc_reg_t obm_ca_ctrl_regs[] = { 11537 IDB_OBM0_CA_CONTROLr, IDB_OBM1_CA_CONTROLr, 11538 IDB_OBM2_CA_CONTROLr, IDB_OBM3_CA_CONTROLr, 11539 IDB_OBM4_CA_CONTROLr, IDB_OBM5_CA_CONTROLr, 11540 IDB_OBM6_CA_CONTROLr, IDB_OBM7_CA_CONTROLr 11541 }; 11542 static const soc_field_t fifo_empty_port_fields[] = { 11543 FIFO_EMPTY_PORT0f, FIFO_EMPTY_PORT1f, FIFO_EMPTY_PORT2f, 11544 FIFO_EMPTY_PORT3f 11545 }; 11546 static const soc_field_t port_reset_fields[] = { 11547 PORT0_RESETf, PORT1_RESETf, PORT2_RESETf, PORT3_RESETf 11548 }; 11549 11550 phy_port = si->port_l2p_mapping[port]; 11551 port_block_base = PORT_BLOCK_BASE_PORT(port); 11552 lane = phy_port - port_block_base; 11553 pipe = si->port_pipe[port]; 11554 clport = si->port_serdes[port]; 11555 /* obm number is reversed (mirrored) in odd pipe */ 11556 obm = pipe & 1 ? 7 - (clport & 0x7) : clport & 0x7; 11557 11558 if (reset && !SAL_BOOT_SIMULATION) { 11559 soc_timeout_t to; 11560 11561 reg = SOC_REG_UNIQUE_ACC(unit, idb_obm_usage_regs[obm])[pipe]; 11562 reg1 = SOC_REG_UNIQUE_ACC(unit, idb_obm_ca_status_regs[obm])[pipe]; 11563 11564 soc_timeout_init(&to, 250000, 0); 11565 /* Poll until IDB buffer is empty */ 11566 for (;;) { 11567 if (0 != obm_usage_count) { 11568 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, REG_PORT_ANY, lane, 11569 &rval1)); 11570 obm_usage_count = soc_reg64_field32_get(unit, reg, rval1, 11571 TOTAL_COUNTf); 11572 } 11573 if (0 == ca_empty) { 11574 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg1, REG_PORT_ANY, 0, 11575 &rval2)); 11576 ca_empty = soc_reg64_field32_get(unit, reg1, rval2, 11577 fifo_empty_port_fields[lane]); 11578 } 11579 if ((0 == obm_usage_count) && (1 == ca_empty)) { 11580 break; 11581 } 11582 if (soc_timeout_check(&to)) { 11583 LOG_ERROR(BSL_LS_SOC_COMMON, 11584 (BSL_META_U(unit, 11585 "IDBBufferDrainTimeOut:port %d,%s, timeout" 11586 "(idb_obm_usage: %d) " 11587 "(ca_fifo_empty: %d)\n"), 11588 unit, SOC_PORT_NAME(unit, port), obm_usage_count, 11589 ca_empty)); 11590 return SOC_E_INTERNAL; 11591 } 11592 } 11593 } 11594 11595 if (reset) { 11596 /* OBM counters will be cleared by IDB reset. 11597 * Clear in counter thread accordingly. 11598 */ 11599 SOC_IF_ERROR_RETURN(_soc_tomahawk_obm_counters_reset(unit, port)); 11600 } 11601 11602 reg = SOC_REG_UNIQUE_ACC(unit, obm_ctrl_regs[obm])[pipe]; 11603 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 11604 soc_reg_field_set(unit, reg, &rval, port_reset_fields[lane], reset); 11605 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 11606 11607 reg = SOC_REG_UNIQUE_ACC(unit, obm_ca_ctrl_regs[obm])[pipe]; 11608 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 11609 soc_reg_field_set(unit, reg, &rval, port_reset_fields[lane], reset); 11610 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 11611 11612 return SOC_E_NONE; 11613 } 11614 11615 STATIC int 11616 _soc_tomahawk_obm_thresholds_reconfigure(int unit, soc_port_t port_conf) 11617 { 11618 #define _TH_BYTES_PER_OBM_CELL 16 11619 #define _TH_CELLS_PER_OBM 1012 11620 soc_info_t *si; 11621 _soc_tomahawk_tdm_t *tdm; 11622 soc_reg_t reg; 11623 int block_info_idx, pipe, clport, obm, lane; 11624 int port, phy_port_base; 11625 int lossless; 11626 uint32 fval; 11627 uint64 rval64; 11628 int num_lanes, oversub_ratio_idx; 11629 static const struct _obm_setting_s { 11630 int discard_limit; 11631 int lossless_xoff; 11632 int lossy_only_lossy_low_pri; 11633 int port_xoff[3]; /* for oversub ratio 1.5, 1.8, and above */ 11634 int lossy_low_pri[3]; /* for oversub ratio 1.5, 1.8, and above */ 11635 int lossy_discard[3]; /* for oversub ratio 1.5, 1.8, and above */ 11636 } obm_settings[2][5] = { 11637 /* LOSSY Settings */ 11638 { /* indexed by number of lanes used in the port */ 11639 { /* 0 - invalid */ 0 }, 11640 { /* 1 lane */ 11641 _TH_CELLS_PER_OBM / 4, 1023, 157, 11642 { 1023, 1023, 1023 }, /* port_xoff */ 11643 { 157, 157, 157 }, /* lossy_low_pri */ 11644 { 253, 253, 253 } /* lossy_discard */ 11645 }, 11646 { /* 2 lanes */ 11647 _TH_CELLS_PER_OBM / 2, 1023, 410, 11648 { 1023, 1023, 1023 }, /* port_xoff */ 11649 { 410, 410, 410 }, /* lossy_low_pri */ 11650 { 506, 506, 506 } /* lossy_discard */ 11651 }, 11652 { /* 3 - invalid */ 0 }, 11653 { /* 4 lanes */ 11654 _TH_CELLS_PER_OBM, 1023, 916, 11655 { 1023, 1023, 1023 }, /* port_xoff */ 11656 { 916, 916, 916 }, /* lossy_low_pri */ 11657 { 1012, 1012, 1012 } /* lossy_discard */ 11658 } 11659 }, 11660 /* LOSSLESS Settings*/ 11661 { /* indexed by number of lanes used in the port */ 11662 { /* 0 - invalid */ 0 }, 11663 { /* 1 lane */ 11664 _TH_CELLS_PER_OBM / 4, 45, 157, 11665 { 129, 87, 67 }, /* port_xoff */ 11666 { 100, 76, 56 }, /* lossy_low_pri */ 11667 { 196, 152, 112 } /* lossy_discard */ 11668 }, 11669 { /* 2 lanes */ 11670 _TH_CELLS_PER_OBM / 2, 108, 410, 11671 { 312, 248, 215 }, /* port_xoff */ 11672 { 100, 100, 100 }, /* lossy_low_pri */ 11673 { 196, 196, 196 } /* lossy_discard */ 11674 }, 11675 { /* 3 - invalid */ 0 }, 11676 { /* 4 lanes */ 11677 _TH_CELLS_PER_OBM, 258, 916, 11678 { 682, 572, 517 }, /* port_xoff */ 11679 { 100, 100, 100 }, /* lossy_low_pri */ 11680 { 196, 196, 196 } /* lossy_discard */ 11681 } 11682 } 11683 }; 11684 static const soc_reg_t obm_thresh_regs[] = { 11685 IDB_OBM0_THRESHOLDr, IDB_OBM1_THRESHOLDr, 11686 IDB_OBM2_THRESHOLDr, IDB_OBM3_THRESHOLDr, 11687 IDB_OBM4_THRESHOLDr, IDB_OBM5_THRESHOLDr, 11688 IDB_OBM6_THRESHOLDr, IDB_OBM7_THRESHOLDr 11689 }; 11690 static const soc_reg_t obm_fc_thresh_regs[] = { 11691 IDB_OBM0_FC_THRESHOLDr, IDB_OBM1_FC_THRESHOLDr, 11692 IDB_OBM2_FC_THRESHOLDr, IDB_OBM3_FC_THRESHOLDr, 11693 IDB_OBM4_FC_THRESHOLDr, IDB_OBM5_FC_THRESHOLDr, 11694 IDB_OBM6_FC_THRESHOLDr, IDB_OBM7_FC_THRESHOLDr 11695 }; 11696 11697 si = &SOC_INFO(unit); 11698 tdm = SOC_CONTROL(unit)->tdm_info; 11699 11700 if (SOC_IS_TOMAHAWKPLUS(unit)) { 11701 lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 11702 SOC_TH_MMU_LOSSLESS_DEFAULT_DISABLE); 11703 } else { 11704 lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 11705 SOC_TH_MMU_LOSSLESS_DEFAULT_ENABLE); 11706 } 11707 11708 SOC_BLOCK_ITER(unit, block_info_idx, SOC_BLK_CLPORT) { 11709 port = SOC_BLOCK_PORT(unit, block_info_idx); 11710 if (port != port_conf) { 11711 continue; 11712 } 11713 11714 phy_port_base = PORT_BLOCK_BASE_PORT(port); 11715 pipe = si->port_pipe[port]; 11716 clport = SOC_BLOCK_NUMBER(unit, block_info_idx); 11717 /* obm number is reversed (mirrored) in odd pipe */ 11718 obm = pipe & 1 ? 7 - (clport & 0x7) : clport & 0x7; 11719 11720 if (!SOC_PBMP_MEMBER(si->oversub_pbm, port)) { 11721 continue; 11722 } 11723 11724 if (lossless) { 11725 if (tdm->ovs_ratio_x1000[pipe] >= 1800) { /* ratio >= 1.8 */ 11726 oversub_ratio_idx = 2; 11727 } else if (tdm->ovs_ratio_x1000[pipe] >= 1500) { /* ratio >= 1.5 */ 11728 oversub_ratio_idx = 1; 11729 } else { 11730 oversub_ratio_idx = 0; 11731 } 11732 11733 for (lane = 0; lane < _TH_PORTS_PER_PBLK; lane++) { 11734 port = si->port_p2l_mapping[phy_port_base + lane]; 11735 if (port == -1) { 11736 continue; 11737 } 11738 num_lanes = si->port_num_lanes[port]; 11739 11740 /* Configure threshold */ 11741 reg = SOC_REG_UNIQUE_ACC(unit, obm_thresh_regs[obm])[pipe]; 11742 SOC_IF_ERROR_RETURN 11743 (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64)); 11744 fval = obm_settings[1][num_lanes].discard_limit; 11745 soc_reg64_field32_set(unit, reg, &rval64, DISCARD_LIMITf, fval); 11746 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_DISCARDf, 11747 1023); 11748 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_DISCARDf, 11749 1023); 11750 fval = obm_settings[1][num_lanes].lossy_low_pri[oversub_ratio_idx]; 11751 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_LOW_PRIf, fval); 11752 fval = obm_settings[1][num_lanes].lossy_discard[oversub_ratio_idx]; 11753 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_DISCARDf, fval); 11754 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_MINf, 0); 11755 SOC_IF_ERROR_RETURN 11756 (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64)); 11757 11758 /* Configure flow control threshold */ 11759 reg = SOC_REG_UNIQUE_ACC(unit, obm_fc_thresh_regs[obm])[pipe]; 11760 SOC_IF_ERROR_RETURN 11761 (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64)); 11762 fval = obm_settings[1][num_lanes].port_xoff[oversub_ratio_idx]; 11763 soc_reg64_field32_set(unit, reg, &rval64, PORT_XOFFf, fval); 11764 soc_reg64_field32_set(unit, reg, &rval64, PORT_XONf, fval - 10); 11765 fval = obm_settings[1][num_lanes].lossless_xoff; 11766 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XOFFf, 11767 fval); 11768 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XOFFf, 11769 fval); 11770 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XONf, 11771 fval - 10); 11772 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XONf, 11773 fval - 10); 11774 SOC_IF_ERROR_RETURN 11775 (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64)); 11776 } 11777 } else { /* lossy */ 11778 for (lane = 0; lane < _TH_PORTS_PER_PBLK; lane++) { 11779 port = si->port_p2l_mapping[phy_port_base + lane]; 11780 if (port == -1) { 11781 continue; 11782 } 11783 num_lanes = si->port_num_lanes[port]; 11784 11785 /* Configure threshold */ 11786 reg = SOC_REG_UNIQUE_ACC(unit, obm_thresh_regs[obm])[pipe]; 11787 SOC_IF_ERROR_RETURN 11788 (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64)); 11789 fval = obm_settings[0][num_lanes].discard_limit; 11790 soc_reg64_field32_set(unit, reg, &rval64, DISCARD_LIMITf, fval); 11791 /* same as DISCARD_LIMIT setting */ 11792 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_DISCARDf, fval); 11793 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_DISCARDf, 11794 1023); 11795 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_DISCARDf, 11796 1023); 11797 fval = obm_settings[0][num_lanes].lossy_only_lossy_low_pri; 11798 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_LOW_PRIf, fval); 11799 soc_reg64_field32_set(unit, reg, &rval64, LOSSY_MINf, 0); 11800 SOC_IF_ERROR_RETURN 11801 (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64)); 11802 11803 /* Configure flow control threshold */ 11804 reg = SOC_REG_UNIQUE_ACC(unit, obm_fc_thresh_regs[obm])[pipe]; 11805 SOC_IF_ERROR_RETURN 11806 (soc_reg_get(unit, reg, REG_PORT_ANY, lane, &rval64)); 11807 soc_reg64_field32_set(unit, reg, &rval64, PORT_XOFFf, 1023); 11808 soc_reg64_field32_set(unit, reg, &rval64, PORT_XONf, 1023); 11809 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XOFFf, 11810 1023); 11811 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XOFFf, 11812 1023); 11813 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS0_XONf, 1023); 11814 soc_reg64_field32_set(unit, reg, &rval64, LOSSLESS1_XONf, 1023); 11815 SOC_IF_ERROR_RETURN 11816 (soc_reg_set(unit, reg, REG_PORT_ANY, lane, rval64)); 11817 } 11818 } 11819 } 11820 11821 return SOC_E_NONE; 11822 } 11823 11824 /* 11825 * Function: 11826 * soc_tomahawk_port_lanes_set 11827 * Description: 11828 * Configure number of lanes used by a port 11829 * Parameters: 11830 * unit - Device number 11831 * lanes_ctrl - Control structure 11832 * Notes: Caller needs to call soc_tomahawk_port_lanes_validate to fill 11833 * in the control structure. 11834 */ 11835 int 11836 soc_tomahawk_port_lanes_set(int unit, soc_th_port_lanes_t *lanes_ctrl) 11837 { 11838 uint32 rval; 11839 soc_reg_t reg; 11840 uint32 values[2]; 11841 soc_port_t it_port; 11842 soc_field_t fields[2]; 11843 soc_info_t *si = &SOC_INFO(unit); 11844 int i, pipe, port_base, phy_port_base, port, port_rename = 0; 11845 int clport, obm; 11846 uint32 port_speed = 0, cur_port_speed = 0; 11847 int save_port_speed = 0; 11848 _soc_tomahawk_tdm_t *tdm; 11849 static const soc_reg_t obm_ca_ctrl_regs[] = { 11850 IDB_OBM0_CA_CONTROLr, IDB_OBM1_CA_CONTROLr, 11851 IDB_OBM2_CA_CONTROLr, IDB_OBM3_CA_CONTROLr, 11852 IDB_OBM4_CA_CONTROLr, IDB_OBM5_CA_CONTROLr, 11853 IDB_OBM6_CA_CONTROLr, IDB_OBM7_CA_CONTROLr 11854 }; 11855 static const int hw_mode_values[SOC_TH_PORT_RATIO_COUNT] = { 11856 0, 1, 1, 1, 3, 5, 4, 6, 2 11857 }; 11858 11859 /* Find physical port number and lane index of the specified port */ 11860 port_base = lanes_ctrl->port_base; 11861 phy_port_base = si->port_l2p_mapping[port_base]; 11862 if (phy_port_base == -1) { 11863 return SOC_E_PORT; 11864 } 11865 pipe = si->port_pipe[port_base]; 11866 11867 /* Update port_init_max info which is used by SerDes driver */ 11868 SOC_IF_ERROR_RETURN 11869 (_soc_tomahawk_flexed_port_speed_get(unit, lanes_ctrl, &port_speed)); 11870 11871 /* Update soc_control information */ 11872 SOC_CONTROL_LOCK(unit); 11873 /* No need to update lanes information during speed change */ 11874 if (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes) { 11875 if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) { 11876 /* port(s) to be removed */ 11877 for (i = 0; i < lanes_ctrl->phy_ports_len; i++) { 11878 port = si->port_p2l_mapping[lanes_ctrl->phy_ports[i]]; 11879 SOC_PBMP_PORT_ADD(si->all.disabled_bitmap, port); 11880 } 11881 } else { /* port(s) to be added */ 11882 for (i = 0; i < lanes_ctrl->phy_ports_len; i++) { 11883 port = si->port_p2l_mapping[lanes_ctrl->phy_ports[i]]; 11884 SOC_PBMP_PORT_REMOVE(si->all.disabled_bitmap, port); 11885 } 11886 } 11887 11888 /* Update num of lanes info which is used by SerDes driver */ 11889 si->port_num_lanes[port_base] = lanes_ctrl->lanes; 11890 for (i = 0; i < lanes_ctrl->phy_ports_len; i++) { 11891 port = si->port_p2l_mapping[lanes_ctrl->phy_ports[i]]; 11892 si->port_num_lanes[port] = 11893 lanes_ctrl->lanes > lanes_ctrl->cur_lanes ? 11894 (si->port_speed_max[port] == 50000 ? 2 : 11895 (si->port_speed_max[port] == 25000 ? 1 : 0)) : 11896 lanes_ctrl->lanes; 11897 } 11898 } 11899 11900 si->port_init_speed[port_base] = port_speed; 11901 if (si->port_init_speed[port_base] >= 40000) { 11902 SOC_PBMP_PORT_ADD(si->eq_pbm, port_base); 11903 /* Update HSP port multicast T2OQ setting */ 11904 SOC_IF_ERROR_RETURN(_soc_tomahawk_mc_toq_cfg(unit, port_base, TRUE)); 11905 } else { 11906 SOC_PBMP_PORT_REMOVE(si->eq_pbm, port_base); 11907 /* Update HSP port multicast T2OQ setting */ 11908 SOC_IF_ERROR_RETURN(_soc_tomahawk_mc_toq_cfg(unit, port_base, FALSE)); 11909 } 11910 if (lanes_ctrl->os_mixed_sister) { 11911 cur_port_speed = port_speed; 11912 /* figure out 25G/50G mixed sister port mode */ 11913 if ((lanes_ctrl->mixed_port_mode > MIXED_DUAL_MODE_40_0_40_0) && 11914 ((lanes_ctrl->lanes == 1) || 11915 (lanes_ctrl->lanes == 2))) { 11916 port_speed = 50000; 11917 save_port_speed = 1; 11918 } 11919 } 11920 SOC_IF_ERROR_RETURN 11921 (soc_tomahawk_update_icc(unit, port_base, port_speed)); 11922 if (lanes_ctrl->os_mixed_sister) { 11923 port_speed = cur_port_speed; 11924 } 11925 for (i = 0; i < lanes_ctrl->phy_ports_len; i += 1) { 11926 port = si->port_p2l_mapping[lanes_ctrl->phy_ports[i]]; 11927 if (lanes_ctrl->lanes > lanes_ctrl->cur_lanes) { 11928 /* port(s) to be removed */ 11929 /* Update pbm of HSP */ 11930 if (si->port_init_speed[port] >= 40000) { 11931 SOC_PBMP_PORT_REMOVE(si->eq_pbm, port); 11932 /* Update HSP port multicast T2OQ setting */ 11933 SOC_IF_ERROR_RETURN(_soc_tomahawk_mc_toq_cfg(unit, port, 11934 FALSE)); 11935 } 11936 } else { /* port(s) to be added */ 11937 si->port_init_speed[port] = port_speed; 11938 /* Update pbm of HSP */ 11939 if (si->port_init_speed[port] >= 40000) { 11940 SOC_PBMP_PORT_ADD(si->eq_pbm, port); 11941 /* Update HSP port multicast T2OQ setting */ 11942 SOC_IF_ERROR_RETURN(_soc_tomahawk_mc_toq_cfg(unit, port, TRUE)); 11943 } 11944 if (lanes_ctrl->os_mixed_sister && save_port_speed) { 11945 port_speed = 50000; 11946 } 11947 SOC_IF_ERROR_RETURN 11948 (soc_tomahawk_update_icc(unit, port, port_speed)); 11949 if (lanes_ctrl->os_mixed_sister && save_port_speed) { 11950 port_speed = cur_port_speed; 11951 } 11952 } 11953 } 11954 11955 /* Update TDM config for HSP */ 11956 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_idb_hsp_set(unit, pipe)); 11957 SOC_IF_ERROR_RETURN(_soc_tomahawk_tdm_mmu_hsp_set(unit, pipe)); 11958 11959 /* OBM setting reconfigure */ 11960 if (TH_FLEXPORT_SPEED_SET_NUM_LANES == lanes_ctrl->lanes) { 11961 SOC_IF_ERROR_RETURN(_soc_tomahawk_obm_thresholds_reconfigure(unit, port_base)); 11962 } 11963 11964 /* 11965 * Update bitmaps and port names when switching b/w CE <=> XE ports. 11966 * Or b/w XE <=> GE ports. 11967 * Conditions tested include : 11968 * - Port is a CE port and we are flexing to a port with < 4 lanes 11969 * - Port is a CE port and we are setting speed to < 100G 11970 * - Port is a XE port and we are setting speed to 1G 11971 */ 11972 if (((lanes_ctrl->cur_lanes == 4) && IS_CE_PORT(unit, port_base)) || 11973 ((TH_FLEXPORT_SPEED_SET_NUM_LANES == lanes_ctrl->lanes) && 11974 IS_CE_PORT(unit, port_base) && (port_speed < 100000))) { 11975 11976 /* Convert to XE ports */ 11977 SOC_PBMP_PORT_REMOVE(si->ce.bitmap, port_base); 11978 SOC_PBMP_PORT_ADD(si->xe.bitmap, 11979 si->port_p2l_mapping[phy_port_base]); 11980 port_rename = 1; 11981 } else if (((lanes_ctrl->lanes == 4) && IS_XE_PORT(unit, port_base) && 11982 (port_speed == 100000)) || 11983 ((TH_FLEXPORT_SPEED_SET_NUM_LANES == lanes_ctrl->lanes) && 11984 (IS_XE_PORT(unit, port_base) && (port_speed == 100000)))) { 11985 11986 /* Convert to CE ports */ 11987 SOC_PBMP_PORT_ADD(si->ce.bitmap, port_base); 11988 SOC_PBMP_PORT_REMOVE(si->xe.bitmap, 11989 si->port_p2l_mapping[phy_port_base]); 11990 port_rename = 1; 11991 } else if ((TH_FLEXPORT_SPEED_SET_NUM_LANES == lanes_ctrl->lanes) && 11992 (IS_XE_PORT(unit, port_base) && (port_speed == 1000))) { 11993 SOC_PBMP_PORT_REMOVE(si->xe.bitmap, port_base); 11994 SOC_PBMP_PORT_ADD(si->ge.bitmap, port_base); 11995 port_rename = 1; 11996 } else if ((TH_FLEXPORT_SPEED_SET_NUM_LANES == lanes_ctrl->lanes) && 11997 (IS_GE_PORT(unit, port_base) && ((port_speed == 10000) || 11998 (port_speed == 25000)))) { 11999 SOC_PBMP_PORT_REMOVE(si->ge.bitmap, port_base); 12000 SOC_PBMP_PORT_ADD(si->xe.bitmap, port_base); 12001 port_rename = 1; 12002 } 12003 12004 if (port_rename) { 12005 _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(xe); 12006 _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(ce); 12007 _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(ge); 12008 soc_dport_map_update(unit); 12009 } 12010 SOC_CONTROL_UNLOCK(unit); 12011 12012 /* No need to change CLPORT mode during speed set */ 12013 if (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes) { 12014 /* Change CLPORT mode */ 12015 fields[0] = XPORT0_CORE_PORT_MODEf; 12016 values[0] = lanes_ctrl->mode; 12017 fields[1] = XPORT0_PHY_PORT_MODEf; 12018 values[1] = lanes_ctrl->mode; 12019 SOC_IF_ERROR_RETURN(soc_reg_fields32_modify(unit, CLPORT_MODE_REGr, 12020 port_base, 2, fields, 12021 values)); 12022 } 12023 12024 /* Update TDM */ 12025 SOC_IF_ERROR_RETURN 12026 (_soc_tomahawk_port_lanes_update_tdm(unit, lanes_ctrl)); 12027 12028 SOC_IF_ERROR_RETURN 12029 (soc_tomahawk_port_pg_headroom_update(unit, port_base)); 12030 /* No need to change CA mode during speed set */ 12031 if (TH_FLEXPORT_SPEED_SET_NUM_LANES != lanes_ctrl->lanes) { 12032 /* Reconfigure cell assembly port mode */ 12033 tdm = SOC_CONTROL(unit)->tdm_info; 12034 pipe = si->port_pipe[port_base]; 12035 clport = si->port_serdes[port_base]; 12036 /* obm number is reversed (mirrored) in odd pipe */ 12037 obm = pipe & 1 ? 7 - (clport & 0x7) : clport & 0x7; 12038 reg = SOC_REG_UNIQUE_ACC(unit, obm_ca_ctrl_regs[obm])[pipe]; 12039 rval = 0; 12040 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 12041 soc_reg_field_set(unit, reg, &rval, PORT_MODEf, 12042 hw_mode_values[tdm->port_ratio[clport]]); 12043 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 12044 } 12045 12046 return SOC_E_NONE; 12047 } 12048 12049 STATIC int 12050 _soc_th_speed_group_sort(soc_th_speed_group_count_t *min_group_array, int len) 12051 { 12052 int i, j; 12053 soc_th_speed_group_count_t tmp; 12054 12055 sal_memset(&tmp, 0, sizeof(soc_th_speed_group_count_t)); 12056 12057 for (i = 1; i < len; i ++) { 12058 sal_memcpy(&tmp, &min_group_array[i], sizeof(soc_th_speed_group_count_t)); 12059 for (j = i - 1 ; j >= 0 && min_group_array[j].count_ports > tmp.count_ports; j --) { 12060 sal_memcpy(&min_group_array[j + 1], &min_group_array[j], sizeof(soc_th_speed_group_count_t)); 12061 } 12062 sal_memcpy(&min_group_array[j + 1], &tmp, sizeof(soc_th_speed_group_count_t)); 12063 } 12064 return SOC_E_NONE; 12065 } 12066 12067 STATIC int 12068 soc_th_speed_group_consolidate_check(int unit, soc_th_port_lanes_t *lanes_ctrl, int flag) 12069 { 12070 soc_info_t *si = &SOC_INFO(unit); 12071 soc_reg_t reg; 12072 int port_base; 12073 int inst; 12074 uint32 rval, fval; 12075 int pipe, group, slot, i; 12076 int speed_id, port_mode; 12077 int count_ports = 0; 12078 int idb_sum_count_ports = 0, mmu_sum_count_ports = 0; 12079 int idb_count_group = 0, mmu_count_group = 0; 12080 int idb_speed_group_ratio, mmu_speed_group_ratio; 12081 int tmp, pass1 = 0, pass2 = 0; 12082 12083 soc_th_speed_group_count_t idb_min_group[_OVS_GROUP_COUNT]; 12084 soc_th_speed_group_count_t mmu_min_group[_OVS_GROUP_COUNT]; 12085 12086 speed_id = flag ? lanes_ctrl->cur_class : lanes_ctrl->class; 12087 port_mode = flag ? lanes_ctrl->cur_mode : lanes_ctrl->mode; 12088 port_base = lanes_ctrl->port_base; 12089 pipe = si->port_pipe[port_base]; 12090 12091 for (group = 0; group < _OVS_GROUP_COUNT; group++) { 12092 reg = SOC_REG_UNIQUE_ACC(unit, IS_OVR_SUB_GRP_CFGr)[pipe]; 12093 SOC_IF_ERROR_RETURN 12094 (soc_reg32_get(unit, reg, REG_PORT_ANY, group, &rval)); 12095 fval = soc_reg_field_get(unit, reg, rval, SPEEDf); 12096 if (speed_id == fval) { 12097 reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[group])[pipe]; 12098 for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) { 12099 SOC_IF_ERROR_RETURN 12100 (soc_reg32_get(unit, reg, REG_PORT_ANY, slot, &rval)); 12101 if (soc_reg_field_get(unit, reg, rval, PORT_NUMf) != 0x3f) { 12102 count_ports ++; 12103 } 12104 } 12105 12106 idb_min_group[idb_count_group].group_id = group; 12107 idb_min_group[idb_count_group].count_ports = count_ports; 12108 idb_sum_count_ports += count_ports; 12109 idb_count_group ++; 12110 } 12111 count_ports = 0; 12112 } 12113 12114 /* Sort the element of speed group and calculate the ratio of speed group */ 12115 _soc_th_speed_group_sort(idb_min_group, idb_count_group); 12116 idb_speed_group_ratio = (idb_sum_count_ports - 1) / _OVS_GROUP_TDM_LENGTH + 1; 12117 tmp = idb_min_group[0].count_ports + idb_min_group[1].count_ports; 12118 12119 if ((idb_speed_group_ratio < idb_count_group) && 12120 (tmp <= _OVS_GROUP_TDM_LENGTH)) { 12121 /* Determine the source and destination of group for migration */ 12122 lanes_ctrl->pipe = pipe; 12123 lanes_ctrl->speed_id = speed_id; 12124 lanes_ctrl->port_mode = port_mode; 12125 lanes_ctrl->src_idb_group = idb_min_group[0].group_id; 12126 lanes_ctrl->dst_idb_group = idb_min_group[1].group_id; 12127 pass1 = 1; 12128 } 12129 12130 count_ports = 0; 12131 for (group = 0; group < _OVS_GROUP_COUNT; group++) { 12132 reg = OVR_SUB_GRP_CFGr; 12133 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 12134 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, inst, group, &rval)); 12135 fval = soc_reg_field_get(unit, reg, rval, SPEEDf); 12136 if (speed_id == fval) { 12137 reg = mmu_grp_tbl_regs[group]; 12138 for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) { 12139 SOC_IF_ERROR_RETURN 12140 (soc_reg32_get(unit, reg, inst, slot, &rval)); 12141 if (soc_reg_field_get(unit, reg, rval, PORT_NUMf) != 0x3f) { 12142 count_ports ++; 12143 } 12144 } 12145 12146 mmu_min_group[mmu_count_group].group_id = group; 12147 mmu_min_group[mmu_count_group].count_ports = count_ports; 12148 mmu_sum_count_ports += count_ports; 12149 mmu_count_group ++; 12150 } 12151 count_ports = 0; 12152 } 12153 12154 _soc_th_speed_group_sort(mmu_min_group, mmu_count_group); 12155 mmu_speed_group_ratio = (mmu_sum_count_ports - 1) / _OVS_GROUP_TDM_LENGTH + 1; 12156 tmp = mmu_min_group[0].count_ports + mmu_min_group[1].count_ports; 12157 12158 if ((mmu_speed_group_ratio < mmu_count_group) && 12159 (tmp <= _OVS_GROUP_TDM_LENGTH)) { 12160 lanes_ctrl->src_mmu_group = mmu_min_group[0].group_id; 12161 lanes_ctrl->dst_mmu_group = mmu_min_group[1].group_id; 12162 pass2 = 1; 12163 } 12164 12165 if (pass1 && pass2) { 12166 lanes_ctrl->action_id = ACT_MIGRATE; 12167 } 12168 12169 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 12170 LOG_CLI((BSL_META_U(unit, 12171 ">>>> The idb min group info in pipe %d\n"), pipe)); 12172 for (i=0; i < idb_count_group; i++) { 12173 LOG_CLI((BSL_META_U(unit, 12174 "idb_min_group[%d]: g_id=%d c_ports=%d\n"), 12175 i, idb_min_group[i].group_id, idb_min_group[i].count_ports)); 12176 } 12177 LOG_CLI((BSL_META_U(unit, "min ratio: %d, cur ratio: %d\n"), 12178 idb_speed_group_ratio, idb_count_group)); 12179 if (idb_speed_group_ratio < idb_count_group) { 12180 LOG_CLI((BSL_META_U(unit, "speed group %d should consolidate\n"), speed_id)); 12181 if (pass1) { 12182 LOG_CLI((BSL_META_U(unit, "speed group %d has sufficient empty slots\n"), speed_id)); 12183 } 12184 } else { 12185 LOG_CLI((BSL_META_U(unit, "speed group %d need not consolidate\n"), speed_id)); 12186 } 12187 12188 LOG_CLI((BSL_META_U(unit, 12189 ">>>> The mmu min group info in pipe %d\n"), pipe)); 12190 for (i=0; i < mmu_count_group; i++) { 12191 LOG_CLI((BSL_META_U(unit, 12192 "mmu_min_group[%d]: g_id=%d c_ports=%d\n"), 12193 i, mmu_min_group[i].group_id, mmu_min_group[i].count_ports)); 12194 } 12195 LOG_CLI((BSL_META_U(unit, "min ratio: %d, cur ratio: %d\n"), 12196 mmu_speed_group_ratio, mmu_count_group)); 12197 if (mmu_speed_group_ratio < mmu_count_group) { 12198 LOG_CLI((BSL_META_U(unit, "speed group %d should consolidate\n"), speed_id)); 12199 if (pass2) { 12200 LOG_CLI((BSL_META_U(unit, "speed group %d has sufficient empty slots\n"), speed_id)); 12201 } 12202 } else { 12203 LOG_CLI((BSL_META_U(unit, "speed group %d need not consolidate\n"), speed_id)); 12204 } 12205 } 12206 12207 return SOC_E_NONE; 12208 } 12209 12210 STATIC int 12211 soc_th_speed_group_migrate(int unit, soc_th_port_lanes_t *lanes_ctrl, int flag) 12212 { 12213 int i; 12214 int p_pm = 0, speed_id, port_mode, pm_id = -1; 12215 int src_g, dst_g; 12216 int slot, src_slot, dst_slot; 12217 int pipe, inst; 12218 soc_reg_t src_reg, dst_reg; 12219 uint32 rval; 12220 int no_empty; 12221 soc_th_speed_group_slot_t entry[4]; 12222 static char *flag_name[] = {"MMU", "IDB"}; 12223 12224 pipe = lanes_ctrl->pipe; 12225 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 12226 speed_id = lanes_ctrl->speed_id; 12227 port_mode = lanes_ctrl->port_mode; 12228 12229 src_g = flag ? lanes_ctrl->src_idb_group : lanes_ctrl->src_mmu_group; 12230 dst_g = flag ? lanes_ctrl->dst_idb_group : lanes_ctrl->dst_mmu_group; 12231 12232 for (i = 0; i < soc_speed_group_info_size; i++) { 12233 if ((soc_speed_group_info[i].speed_id == speed_id) && 12234 (soc_speed_group_info[i].port_mode == port_mode)) { 12235 p_pm = soc_speed_group_info[i].p_pm; 12236 } 12237 } 12238 12239 /* Figure out each port in the PM */ 12240 src_reg = flag ? SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[src_g])[pipe] : mmu_grp_tbl_regs[src_g]; 12241 for (slot = 0, src_slot = 0; src_slot < _OVS_GROUP_TDM_LENGTH; src_slot ++) { 12242 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, src_reg, flag ? REG_PORT_ANY : inst, src_slot, &rval)); 12243 if (soc_reg_field_get(unit, src_reg, rval, PORT_NUMf) != 0x3f) { 12244 entry[slot].slot = src_slot; 12245 entry[slot].pm_id = soc_reg_field_get(unit, src_reg, rval, PHY_PORT_IDf); 12246 entry[slot].port_id = soc_reg_field_get(unit, src_reg, rval, PORT_NUMf); 12247 12248 /* Checking all ports belonging to a PM */ 12249 if (slot == 0) { 12250 pm_id = entry[0].pm_id; 12251 } 12252 if ((slot > 0) && (pm_id != entry[slot].pm_id)) { 12253 slot --; 12254 continue; 12255 } 12256 slot ++; 12257 } 12258 if (slot >= p_pm) { 12259 break; 12260 } 12261 } 12262 12263 if (slot < p_pm) { 12264 lanes_ctrl->action_id = ACT_NONE; 12265 return SOC_E_NONE; 12266 } 12267 12268 /* Configure the destination of group to contain all ports */ 12269 rval = 0; 12270 slot = 0; 12271 dst_reg = flag ? SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[dst_g])[pipe] : mmu_grp_tbl_regs[dst_g]; 12272 for (dst_slot = 0; dst_slot < _OVS_GROUP_TDM_LENGTH; dst_slot ++) { 12273 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, dst_reg, flag ? REG_PORT_ANY : inst, dst_slot, &rval)); 12274 if (soc_reg_field_get(unit, dst_reg, rval, PORT_NUMf) == 0x3f) { 12275 soc_reg_field_set(unit, dst_reg, &rval, PORT_NUMf, entry[slot].port_id); 12276 soc_reg_field_set(unit, dst_reg, &rval, PHY_PORT_IDf, entry[slot].pm_id); 12277 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, dst_reg, flag ? REG_PORT_ANY : inst, dst_slot, rval)); 12278 slot ++; 12279 } 12280 if (slot >= p_pm) { 12281 break; 12282 } 12283 } 12284 12285 /* Remove all ports from source group and reset the resource of slot */ 12286 rval = 0; 12287 for (i = 0; i < p_pm; i++) { 12288 soc_reg_field_set(unit, src_reg, &rval, PORT_NUMf, 0x3f); 12289 soc_reg_field_set(unit, src_reg, &rval, PHY_PORT_IDf, 0); 12290 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, src_reg, flag ? REG_PORT_ANY : inst, entry[i].slot, rval)); 12291 } 12292 12293 /* Reset the resource of speed group */ 12294 rval = 0; 12295 no_empty = 0; 12296 for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot ++) { 12297 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, src_reg, flag ? REG_PORT_ANY : inst, slot, &rval)); 12298 if (soc_reg_field_get(unit, src_reg, rval, PORT_NUMf) != 0x3f) { 12299 no_empty = 1; 12300 } 12301 } 12302 if (!no_empty) { 12303 src_reg = flag ? SOC_REG_UNIQUE_ACC(unit, IS_OVR_SUB_GRP_CFGr)[pipe] : OVR_SUB_GRP_CFGr; 12304 rval = 0; 12305 soc_reg_field_set(unit, src_reg, &rval, SAME_SPACINGf, 8); 12306 soc_reg_field_set(unit, src_reg, &rval, SISTER_SPACINGf, 4); 12307 soc_reg_field_set(unit, src_reg, &rval, SPEEDf, 0); 12308 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, src_reg, flag ? REG_PORT_ANY : inst, src_g, rval)); 12309 } 12310 12311 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 12312 LOG_CLI((BSL_META_U(unit, 12313 "Migration on %s sp_id=%d port_mode=%d src_g=%d dst_g=%d DONE.\n"), 12314 flag_name[flag], speed_id, port_mode, src_g, dst_g)); 12315 for (i=0; i < p_pm; i++) { 12316 LOG_CLI((BSL_META_U(unit, 12317 "slot[%d] {%d, %d} \n"), 12318 entry[i].slot, entry[i].pm_id, entry[i].port_id)); 12319 } 12320 } 12321 12322 return SOC_E_NONE; 12323 } 12324 12325 int 12326 soc_tomahawk_port_lanes_consolidation(int unit, soc_th_port_lanes_t *lanes_ctrl) 12327 { 12328 #define _TH_IDB_GROUP 1 12329 #define _TH_MMU_GROUP 0 12330 #define _TH_CUR_GROUP 1 12331 #define _TH_NEW_GROUP 0 12332 int speed_id, port_mode, lanes; 12333 int co_enable; 12334 int oversub_mode; 12335 12336 if (SOC_IS_TOMAHAWK(unit)) { 12337 oversub_mode = lanes_ctrl->oversub; 12338 speed_id = lanes_ctrl->cur_class; 12339 port_mode = lanes_ctrl->cur_mode; 12340 lanes = lanes_ctrl->lanes; 12341 12342 if (speed_id == -1 || port_mode == -1 || lanes == -1) { 12343 return SOC_E_PARAM; 12344 } 12345 12346 co_enable = soc_property_get(unit, 12347 spn_OVERSUB_SPEED_GROUP_CONSOLIDATION_ENABLE, 12348 0); 12349 if (!oversub_mode) { 12350 co_enable = 0; 12351 } 12352 12353 if(co_enable) { 12354 /* Check whether the speed group requires consolidation */ 12355 lanes_ctrl->action_id = ACT_CONSOLIDATE; 12356 SOC_IF_ERROR_RETURN 12357 (soc_th_speed_group_consolidate_check(unit, 12358 lanes_ctrl, 12359 _TH_CUR_GROUP)); 12360 12361 /* Migrate all ports to different OS group */ 12362 if (lanes_ctrl->action_id == ACT_MIGRATE) { 12363 SOC_IF_ERROR_RETURN 12364 (soc_th_speed_group_migrate(unit, 12365 lanes_ctrl, 12366 _TH_IDB_GROUP)); 12367 SOC_IF_ERROR_RETURN 12368 (soc_th_speed_group_migrate(unit, 12369 lanes_ctrl, 12370 _TH_MMU_GROUP)); 12371 } 12372 } else { 12373 lanes_ctrl->action_id = ACT_NONE; 12374 } 12375 } 12376 12377 return SOC_E_NONE; 12378 } 12379 12380 soc_error_t 12381 soc_th_port_speed_recover(int unit, soc_port_t port) 12382 { 12383 soc_info_t *si = &SOC_INFO(unit); 12384 mac_driver_t *macdp; 12385 int port_speed = 0; 12386 int port_rename = 0; 12387 soc_port_t it_port; 12388 12389 if (!IS_HG_PORT(unit, port) && !IS_CE_PORT(unit, port) && !IS_XE_PORT(unit, port)) { 12390 return SOC_E_NONE; 12391 } 12392 12393 SOC_IF_ERROR_RETURN(soc_mac_probe(unit, port, &macdp)); 12394 SOC_IF_ERROR_RETURN(MAC_SPEED_GET(macdp, unit, port, &port_speed)); 12395 SOC_CONTROL_LOCK(unit); 12396 12397 si->port_init_speed[port] = port_speed; 12398 /* Update bitmap of high speed ports */ 12399 if (port_speed >= 40000) { 12400 SOC_PBMP_PORT_ADD(si->eq_pbm, port); 12401 } else { 12402 SOC_PBMP_PORT_REMOVE(si->eq_pbm, port); 12403 } 12404 /* Adjust XE/CE port name */ 12405 if (IS_E_PORT(unit, port)) { 12406 if(port_speed < 100000) { 12407 SOC_PBMP_PORT_REMOVE(si->ce.bitmap, port); 12408 SOC_PBMP_PORT_ADD(si->xe.bitmap, port); 12409 } else { 12410 SOC_PBMP_PORT_ADD(si->ce.bitmap, port); 12411 SOC_PBMP_PORT_REMOVE(si->xe.bitmap, port); 12412 } 12413 port_rename = 1; 12414 } 12415 if (port_rename) { 12416 _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(xe); 12417 _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(ce); 12418 soc_dport_map_update(unit); 12419 } 12420 12421 SOC_CONTROL_UNLOCK(unit); 12422 return SOC_E_NONE; 12423 } 12424 12425 /* 12426 * Function: 12427 * soc_th_flexport_recover 12428 * Description: 12429 * Add port to xe/ce and high speed port bitmap by reading 12430 * port speed. 12431 * Parameters: 12432 * unit - Device number 12433 * port - logical port number 12434 */ 12435 soc_error_t 12436 soc_th_flexport_recover(int unit, soc_port_t port) 12437 { 12438 soc_info_t *si = &SOC_INFO(unit); 12439 soc_port_t it_port; 12440 mac_driver_t *macdp; 12441 int port_speed = 0, port_rename = 0; 12442 12443 SOC_IF_ERROR_RETURN(soc_mac_probe(unit, port, &macdp)); 12444 SOC_IF_ERROR_RETURN(MAC_SPEED_GET(macdp, unit, port, &port_speed)); 12445 SOC_CONTROL_LOCK(unit); 12446 si->port_init_speed[port] = port_speed; 12447 /* Update bitmap of high speed ports */ 12448 if (port_speed >= 40000) { 12449 SOC_PBMP_PORT_ADD(si->eq_pbm, port); 12450 } else { 12451 SOC_PBMP_PORT_REMOVE(si->eq_pbm, port); 12452 } 12453 /* Adjust XE/CE port bitmaps */ 12454 if (IS_E_PORT(unit, port)) { 12455 if (port_speed < 100000) { 12456 SOC_PBMP_PORT_REMOVE(si->ce.bitmap, port); 12457 SOC_PBMP_PORT_ADD(si->xe.bitmap, port); 12458 port_rename = 1; 12459 } else { 12460 SOC_PBMP_PORT_ADD(si->ce.bitmap, port); 12461 SOC_PBMP_PORT_REMOVE(si->xe.bitmap, port); 12462 port_rename = 1; 12463 } 12464 } 12465 if (port_rename) { 12466 _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(xe); 12467 _SOC_TH_RECONFIGURE_PORT_TYPE_INFO(ce); 12468 soc_dport_map_update(unit); 12469 } 12470 SOC_CONTROL_UNLOCK(unit); 12471 12472 return SOC_E_NONE; 12473 } 12474 12475 soc_error_t 12476 soc_th_granular_speed_get(int unit, soc_port_t port, int *speed) 12477 { 12478 uint32 fval, rval; 12479 12480 #if defined(BCM_TOMAHAWK2_SUPPORT) 12481 egr_mmu_cell_credit_entry_t credit_entry; 12482 if (soc_feature(unit, soc_feature_egr_mmu_cell_credit_is_memory)) { 12483 SOC_IF_ERROR_RETURN(READ_EGR_MMU_CELL_CREDITm(unit, MEM_BLOCK_ANY, 12484 SOC_INFO(unit).port_l2p_mapping[port], &credit_entry)); 12485 fval = soc_EGR_MMU_CELL_CREDITm_field32_get(unit, &credit_entry, CREDITf); 12486 } else 12487 #endif 12488 { 12489 SOC_IF_ERROR_RETURN(READ_EGR_MMU_CELL_CREDITr(unit, port, &rval)); 12490 fval = soc_reg_field_get(unit, EGR_MMU_CELL_CREDITr, rval, CREDITf); 12491 } 12492 SOC_IF_ERROR_RETURN(soc_th_port_asf_mmu_cell_credit_to_speed 12493 (unit, port, (uint8) fval, speed)); 12494 return SOC_E_NONE; 12495 } 12496 12497 void 12498 soc_tomahawk_temperature_intr(void *unit_vp, void *d1, void *d2, 12499 void *d3, void *d4) 12500 { 12501 uint32 rval, trval; 12502 int i, rv, unit = PTR_TO_INT(unit_vp); 12503 soc_port_t port; 12504 soc_block_t blk; 12505 12506 if ((rv = READ_TOP_PVTMON_INTR_STATUSr(unit, &rval)) != SOC_E_NONE) { 12507 LOG_ERROR(BSL_LS_SOC_COMMON, 12508 (BSL_META_U(unit, 12509 "TH Temp Intr, Reg access error.\n"))); 12510 } 12511 LOG_ERROR(BSL_LS_SOC_COMMON, 12512 (BSL_META_U(unit, 12513 "High temp interrupt: 0x%08x\n"), rval)); 12514 /* Raise event to app for it to take further graceful actions */ 12515 for (i = 0; i < COUNTOF(pvtmon_result_reg); i++) { 12516 if ((0x1 << i) & _soc_th_temp_mon_mask[unit]) { 12517 if ((rv = soc_reg32_get(unit, pvtmon_result_reg[i], REG_PORT_ANY, 0, 12518 &trval)) != SOC_E_NONE) { 12519 LOG_ERROR(BSL_LS_SOC_COMMON, 12520 (BSL_META_U(unit, 12521 "TH Temp Intr, Reg access error.\n"))); 12522 } 12523 trval = soc_reg_field_get(unit, pvtmon_result_reg[i], trval, 12524 PVT_DATAf); 12525 #ifdef BCM_TOMAHAWK2_SUPPORT 12526 if (SOC_IS_TOMAHAWK2(unit)) { 12527 /* Temp = 434.10 - o_ADC_data * 0.53504 12528 * data = (434.10 - temp)/0.53504 = (434100-(temp*1000))/535 12529 * Note: Since this is a high temp value we can safely assume it to 12530 * always be a +ive number. This is in degrees celcius. 12531 */ 12532 trval = (434100-(trval*535))/1000; 12533 } else 12534 #endif /* BCM_TOMAHAWK2_SUPPORT */ 12535 { 12536 /* Convert data to temperature. 12537 * temp = 410.04-(data*0.48705) = (410040-(data*487))/1000 12538 * Note: Since this is a high temp interrupt we can safely assume 12539 * that this will end up being a +ive value. 12540 */ 12541 trval = (410040-(trval*487))/1000; 12542 } 12543 LOG_ERROR(BSL_LS_SOC_COMMON, 12544 (BSL_META_U(unit, 12545 "TempMon %d: %d deg C.\n"), i, trval)); 12546 (void)soc_event_generate(unit, SOC_SWITCH_EVENT_ALARM, 12547 SOC_SWITCH_EVENT_ALARM_HIGH_TEMP, i, trval); 12548 } 12549 } 12550 /* Optionally hold system in reset. TH2 will skip as it has HW overtemp protection. 12551 * Note: The main intention is to stop the chip from getting fried and halt 12552 * all schan accesses as the h/w will not respond anymore. 12553 * We are not implementing a gracefull recovery, the unit needs to be 12554 * rebooted after this. 12555 */ 12556 if ((!SOC_IS_TOMAHAWK2(unit))&& 12557 (soc_property_get(unit, "temp_monitor_shutdown", 1))) { 12558 if ((rv = WRITE_TOP_PVTMON_INTR_MASKr(unit, 0)) != SOC_E_NONE) { 12559 LOG_ERROR(BSL_LS_SOC_COMMON, 12560 (BSL_META_U(unit, 12561 "TH Temp Intr, Reg access error.\n"))); 12562 } 12563 12564 /* Stop all schan transactions on this unit */ 12565 #ifdef INCLUDE_I2C 12566 if ((rv = soc_i2c_detach(unit)) != SOC_E_NONE) { 12567 LOG_ERROR(BSL_LS_SOC_COMMON, 12568 (BSL_META_U(unit, 12569 "TH Temp Intr, i2c detach error.\n"))); 12570 } 12571 #endif 12572 if (!SOC_IS_RCPU_ONLY(unit)) { 12573 /* Free up DMA memory */ 12574 if ((rv = soc_dma_detach(unit)) != SOC_E_NONE) { 12575 LOG_ERROR(BSL_LS_SOC_COMMON, 12576 (BSL_META_U(unit, 12577 "TH Temp Intr, dma detach error.\n"))); 12578 } 12579 } 12580 #ifdef INCLUDE_MEM_SCAN 12581 if ((rv = soc_mem_scan_stop(unit)) != SOC_E_NONE) { 12582 LOG_ERROR(BSL_LS_SOC_COMMON, 12583 (BSL_META_U(unit, 12584 "TH Temp Intr, mem scan stop error.\n"))); 12585 } 12586 #endif /* INCLUDE_MEM_SCAN */ 12587 /* Terminate counter module */ 12588 if ((rv = soc_counter_stop(unit)) != SOC_E_NONE) { 12589 LOG_ERROR(BSL_LS_SOC_COMMON, 12590 (BSL_META_U(unit, 12591 "TH Temp Intr, counter stop error.\n"))); 12592 } 12593 if (SOC_SBUSDMA_DM_INFO(unit)) { 12594 if ((rv = soc_sbusdma_desc_detach(unit)) != SOC_E_NONE) { 12595 LOG_ERROR(BSL_LS_SOC_COMMON, 12596 (BSL_META_U(unit, 12597 "TH Temp Intr, sbusdma stop error.\n"))); 12598 } 12599 } 12600 if (soc_feature(unit, soc_feature_arl_hashed)) { 12601 /* Stop L2X thread */ 12602 if ((rv = soc_l2x_stop(unit)) != SOC_E_NONE) { 12603 LOG_ERROR(BSL_LS_SOC_COMMON, 12604 (BSL_META_U(unit, 12605 "TH Temp Intr, L2x stop error.\n"))); 12606 } 12607 12608 } 12609 if ((rv = soc_th_l2_bulk_age_stop(unit)) != SOC_E_NONE) { 12610 LOG_ERROR(BSL_LS_SOC_COMMON, 12611 (BSL_META_U(unit, 12612 "TH Temp Intr, L2 age stop error.\n"))); 12613 } 12614 12615 rv = READ_TOP_SOFT_RESET_REGr(unit, &rval); 12616 if (SOC_E_NONE != rv) { 12617 LOG_ERROR(BSL_LS_SOC_COMMON, 12618 (BSL_META_U(unit, 12619 "TH Temp Intr, Reg access error.\n"))); 12620 } 12621 soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_TS_RST_Lf, 0); 12622 soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_MMU_RST_Lf, 0); 12623 soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_EP_RST_Lf, 0); 12624 soc_reg_field_set(unit, TOP_SOFT_RESET_REGr, &rval, TOP_IP_RST_Lf, 0); 12625 rv = WRITE_TOP_SOFT_RESET_REGr(unit, rval); 12626 if (SOC_E_NONE != rv) { 12627 LOG_ERROR(BSL_LS_SOC_COMMON, 12628 (BSL_META_U(unit, 12629 "TH Temp Intr, Reg access error.\n"))); 12630 } 12631 12632 if ((rv = READ_TOP_SOFT_RESET_REG_2r(unit, &rval)) != SOC_E_NONE) { 12633 LOG_ERROR(BSL_LS_SOC_COMMON, 12634 (BSL_META_U(unit, 12635 "TH Temp Intr, Reg access error.\n"))); 12636 } 12637 12638 #ifdef BCM_TOMAHAWK2_SUPPORT 12639 if (SOC_IS_TOMAHAWK2(unit)) { 12640 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL0_RST_Lf, 12641 0); 12642 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_TS_PLL_RST_Lf, 12643 1); 12644 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL0_RST_Lf, 12645 0); 12646 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL1_RST_Lf, 12647 0); 12648 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_AVS_RST_Lf, 1); 12649 } else 12650 #endif /* BCM_TOMAHAWK2_SUPPORT */ 12651 { 12652 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL0_RST_Lf, 12653 0); 12654 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL1_RST_Lf, 12655 0); 12656 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL2_RST_Lf, 12657 0); 12658 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_XG_PLL3_RST_Lf, 12659 0); 12660 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_TS_PLL_RST_Lf, 12661 1); 12662 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL0_RST_Lf, 12663 0); 12664 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_BS_PLL1_RST_Lf, 12665 0); 12666 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_AVS_RST_Lf, 1); 12667 } 12668 12669 if ((rv = WRITE_TOP_SOFT_RESET_REG_2r(unit, rval)) != SOC_E_NONE) { 12670 LOG_ERROR(BSL_LS_SOC_COMMON, 12671 (BSL_META_U(unit, 12672 "TH Temp Intr, Reg access error.\n"))); 12673 } 12674 /* Powerdown Falcon analog cores */ 12675 SOC_BLOCK_ITER(unit, blk, SOC_BLK_CLPORT) { 12676 port = SOC_BLOCK_PORT(unit, blk); 12677 rv = READ_CLPORT_XGXS0_CTRL_REGr(unit, port, &rval); 12678 if (SOC_E_NONE != rv) { 12679 LOG_ERROR(BSL_LS_SOC_COMMON, 12680 (BSL_META_U(unit, 12681 "TH Temp Intr, Reg access error.\n"))); 12682 } 12683 soc_reg_field_set(unit, CLPORT_XGXS0_CTRL_REGr, &rval, IDDQf, 1); 12684 soc_reg_field_set(unit, CLPORT_XGXS0_CTRL_REGr, &rval, PWRDWNf, 1); 12685 soc_reg_field_set(unit, CLPORT_XGXS0_CTRL_REGr, &rval, RSTB_HWf, 0); 12686 rv = WRITE_CLPORT_XGXS0_CTRL_REGr(unit, port, rval); 12687 if (SOC_E_NONE != rv) { 12688 LOG_ERROR(BSL_LS_SOC_COMMON, 12689 (BSL_META_U(unit, 12690 "TH Temp Intr, Reg access error.\n"))); 12691 } 12692 } 12693 /* Powerdown Eagle analog cores */ 12694 SOC_BLOCK_ITER(unit, blk, SOC_BLK_XLPORT) { 12695 port = SOC_BLOCK_PORT(unit, blk); 12696 rv = READ_XLPORT_XGXS0_CTRL_REGr(unit, port, &rval); 12697 if (SOC_E_NONE != rv) { 12698 LOG_ERROR(BSL_LS_SOC_COMMON, 12699 (BSL_META_U(unit, 12700 "TH Temp Intr, Reg access error.\n"))); 12701 } 12702 soc_reg_field_set(unit, XLPORT_XGXS0_CTRL_REGr, &rval, IDDQf, 1); 12703 soc_reg_field_set(unit, XLPORT_XGXS0_CTRL_REGr, &rval, PWRDWNf, 1); 12704 soc_reg_field_set(unit, XLPORT_XGXS0_CTRL_REGr, &rval, RSTB_HWf, 0); 12705 rv = WRITE_XLPORT_XGXS0_CTRL_REGr(unit, port, rval); 12706 if (SOC_E_NONE != rv) { 12707 LOG_ERROR(BSL_LS_SOC_COMMON, 12708 (BSL_META_U(unit, 12709 "TH Temp Intr, Reg access error.\n"))); 12710 } 12711 } 12712 12713 /* Disable all interrupts */ 12714 #ifdef BCM_CMICM_SUPPORT 12715 if (soc_feature(unit, soc_feature_cmicm)) { 12716 soc_cmicm_intr0_disable(unit, ~0); 12717 soc_cmicm_intr1_disable(unit, ~0); 12718 soc_cmicm_intr2_disable(unit, ~0); 12719 soc_cmicm_intr3_disable(unit, ~0); 12720 soc_cmicm_intr4_disable(unit, ~0); 12721 soc_cmicm_intr5_disable(unit, ~0); 12722 } 12723 #endif 12724 12725 #ifdef BCM_CMICDV4_SUPPORT 12726 if (soc_feature(unit, soc_feature_cmicd_v4)) { 12727 soc_cmicm_intr6_disable(unit, ~0); 12728 } 12729 #endif /* BCM_CMICDV4_SUPPORT */ 12730 12731 /* Power down core PLL, once this is done all SCHAN accesses 12732 * will fail. 12733 */ 12734 #ifdef BCM_TOMAHAWK2_SUPPORT 12735 if (SOC_IS_TOMAHAWK2(unit)) { 12736 rv = READ_TOP_CORE_PLL0_CTRL_6r(unit, &rval); 12737 if (SOC_E_NONE != rv) { 12738 LOG_ERROR(BSL_LS_SOC_COMMON, 12739 (BSL_META_U(unit, 12740 "TH2 Temp Intr, Reg access error.\n"))); 12741 } 12742 soc_reg_field_set(unit, TOP_CORE_PLL0_CTRL_6r, &rval, ISO_INANDOUT_AONf, 1); 12743 soc_reg_field_set(unit, TOP_CORE_PLL0_CTRL_6r, &rval, PWRON_PLL_AONf, 0); 12744 soc_reg_field_set(unit, TOP_CORE_PLL0_CTRL_6r, &rval, PWRON_LDO_ANALOG_AONf, 0); 12745 WRITE_TOP_CORE_PLL0_CTRL_6r(unit, rval); 12746 } else 12747 #endif /* BCM_TOMAHAWK2_SUPPORT */ 12748 { 12749 rv = READ_TOP_CORE_PLL0_CTRL_1r(unit, &rval); 12750 if (SOC_E_NONE != rv) { 12751 LOG_ERROR(BSL_LS_SOC_COMMON, 12752 (BSL_META_U(unit, 12753 "TH Temp Intr, Reg access error.\n"))); 12754 } 12755 soc_reg_field_set(unit, TOP_CORE_PLL0_CTRL_1r, &rval, ISO_INf, 1); 12756 soc_reg_field_set(unit, TOP_CORE_PLL0_CTRL_1r, &rval, PWRONf, 0); 12757 soc_reg_field_set(unit, TOP_CORE_PLL0_CTRL_1r, &rval, PWRON_LDOf, 0); 12758 WRITE_TOP_CORE_PLL0_CTRL_1r(unit, rval); 12759 } 12760 SCHAN_LOCK(unit); 12761 12762 /* Clear all outstanding DPCs owned by this unit */ 12763 sal_dpc_cancel(INT_TO_PTR(unit)); 12764 LOG_ERROR(BSL_LS_SOC_COMMON, 12765 (BSL_META_U(unit, 12766 "\nReboot the system.."))); 12767 } 12768 } 12769 12770 int 12771 soc_tomahawk_temperature_monitor_get(int unit, int temperature_max, 12772 soc_switch_temperature_monitor_t *temperature_array, int *temperature_count) 12773 { 12774 soc_reg_t reg; 12775 int index; 12776 uint32 rval; 12777 int fval, cur, peak; 12778 int num_entries_out; 12779 12780 if (temperature_count) { 12781 *temperature_count = 0; 12782 } 12783 if (COUNTOF(pvtmon_result_reg) > temperature_max) { 12784 num_entries_out = temperature_max; 12785 } else { 12786 num_entries_out = COUNTOF(pvtmon_result_reg); 12787 } 12788 SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_CTRL_1r(unit, &rval)); 12789 if ((soc_reg_field_get(unit, TOP_PVTMON_CTRL_1r, rval, PVTMON_RESET_Nf) == 0) || 12790 (soc_reg_field_get(unit, TOP_PVTMON_CTRL_1r, rval, PVTMON_SELECTf) != 0)) { 12791 soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_RESET_Nf, 0); 12792 SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_1r(unit, rval)); 12793 soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_RESET_Nf, 1); 12794 soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_SELECTf, 0); 12795 SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_1r(unit, rval)); 12796 sal_usleep(1000); 12797 } 12798 12799 for (index = 0; index < num_entries_out; index++) { 12800 reg = pvtmon_result_reg[index]; 12801 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 12802 fval = soc_reg_field_get(unit, reg, rval, PVT_DATAf); 12803 #if defined(BCM_TOMAHAWK2_SUPPORT) 12804 if (SOC_IS_TOMAHAWK2(unit)) { 12805 cur = (4341000-(fval*5350))/1000; 12806 } else 12807 #endif /* BCM_TOMAHAWK2_SUPPORT */ 12808 { 12809 cur = (4100400-(fval*4870))/1000; 12810 } 12811 fval = soc_reg_field_get(unit, reg, rval, MIN_PVT_DATAf); 12812 #if defined(BCM_TOMAHAWK2_SUPPORT) 12813 if (SOC_IS_TOMAHAWK2(unit)) { 12814 peak = (4341000-(fval*5350))/1000; 12815 } else 12816 #endif /* BCM_TOMAHAWK2_SUPPORT */ 12817 { 12818 peak = (4100400-(fval*4870))/1000; 12819 } 12820 if (temperature_array) { 12821 (temperature_array + index)->curr = cur; 12822 (temperature_array + index)->peak = peak; 12823 } 12824 } 12825 SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval)); 12826 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 12827 TOP_PVT_MON_MIN_RST_Lf, 0); 12828 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval)); 12829 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, 12830 TOP_PVT_MON_MIN_RST_Lf, 1); 12831 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval)); 12832 12833 if (temperature_count) { 12834 *temperature_count = num_entries_out; 12835 } 12836 return SOC_E_NONE; 12837 } 12838 12839 int 12840 soc_tomahawk_show_voltage(int unit) 12841 { 12842 soc_reg_t reg; 12843 int index; 12844 uint32 rval, fval, avg; 12845 12846 if (!SOC_IS_TOMAHAWK3(unit)) { 12847 SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_CTRL_1r(unit, &rval)); 12848 if ((soc_reg_field_get(unit, TOP_PVTMON_CTRL_1r, rval, PVTMON_RESET_Nf) == 0) || 12849 (soc_reg_field_get(unit, TOP_PVTMON_CTRL_1r, rval, PVTMON_SELECTf) != 4)) { 12850 soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_RESET_Nf, 0); 12851 SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_1r(unit, rval)); 12852 soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_RESET_Nf, 1); 12853 soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_SELECTf, 4); 12854 SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_1r(unit, rval)); 12855 sal_usleep(1000); 12856 } 12857 } 12858 12859 avg = 0; 12860 12861 /* Read Voltages. */ 12862 for (index = 0; index < COUNTOF(pvtmon_result_reg); index++) { 12863 reg = pvtmon_result_reg[index]; 12864 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 12865 fval = soc_reg_field_get(unit, reg, rval, PVT_DATAf); 12866 #ifdef BCM_TOMAHAWK2_SUPPORT 12867 if (SOC_IS_TOMAHAWK2(unit) || SOC_IS_TOMAHAWK3(unit)) { 12868 /* (PVT_DATA * 950) / (1024 * 0.8) */ 12869 fval = (fval * 950 * 10) / (1024 * 8); 12870 } else 12871 #endif /* BCM_TOMAHAWK2_SUPPORT */ 12872 { 12873 LOG_CLI((BSL_META_U(unit, 12874 "Voltage monitor fail: Need to add formula for current device.\n"))); 12875 return SOC_E_UNAVAIL; 12876 } 12877 avg += fval; 12878 LOG_CLI((BSL_META_U(unit, 12879 "Voltage monitor %d: voltage = %d.%03dV\n"), 12880 index, (fval/1000), (fval %1000))); 12881 } 12882 12883 avg /= (COUNTOF(pvtmon_result_reg)); 12884 LOG_CLI((BSL_META_U(unit, 12885 "Average voltage is = %d.%03dV\n"), 12886 (avg/1000), (avg %1000))); 12887 12888 return SOC_E_NONE; 12889 } 12890 12891 int 12892 soc_tomahawk_show_ring_osc(int unit) 12893 { 12894 static const struct { 12895 int osc_sel; 12896 soc_field_t field0; 12897 int value0; 12898 soc_field_t field1; 12899 int value1; 12900 char *name; 12901 } osc_tbl[] = { 12902 { 2, IROSC_SELf, 0, INVALIDf, -1, "Core ring 0 five stages" }, 12903 { 2, IROSC_SELf, 1, INVALIDf, -1, "Core ring 0 nine stages" }, 12904 { 3, IROSC_SELf, 0, INVALIDf, -1, "Core ring 1 five stages" }, 12905 { 3, IROSC_SELf, 1, INVALIDf, -1, "Core ring 1 nine stages" }, 12906 { 4, SRAM_OSC_0_PENf, 0, SRAM_OSC_0_NENf, 1, "SRAM ring 0 NMOS" }, 12907 { 5, SRAM_OSC_0_PENf, 1, SRAM_OSC_0_NENf, 0, "SRAM ring 0 PMOS" }, 12908 { 6, SRAM_OSC_1_PENf, 0, SRAM_OSC_1_NENf, 1, "SRAM ring 1 NMOS" }, 12909 { 7, SRAM_OSC_1_PENf, 1, SRAM_OSC_1_NENf, 0, "SRAM ring 1 PMOS" }, 12910 { 8, SRAM_OSC_2_PENf, 0, SRAM_OSC_2_NENf, 1, "SRAM ring 2 NMOS" }, 12911 { 9, SRAM_OSC_2_PENf, 1, SRAM_OSC_2_NENf, 0, "SRAM ring 2 PMOS" }, 12912 { 10, SRAM_OSC_3_PENf, 0, SRAM_OSC_3_NENf, 1, "SRAM ring 3 NMOS" }, 12913 { 11, SRAM_OSC_3_PENf, 1, SRAM_OSC_3_NENf, 0, "SRAM ring 3 PMOS" } 12914 }; 12915 soc_reg_t ctrl_reg, stat_reg; 12916 uint32 rval, fval; 12917 int index, core_clk, quo, rem, frac, retry; 12918 12919 core_clk = SOC_INFO(unit).frequency * 1024; 12920 ctrl_reg = TOP_RING_OSC_CTRLr; 12921 stat_reg = TOP_OSC_COUNT_STATr; 12922 12923 for (index = 0; index < COUNTOF(osc_tbl); index++) { 12924 rval = 0; 12925 12926 #if defined(BCM_TOMAHAWK2_SUPPORT) || defined(BCM_TOMAHAWK3_SUPPORT) 12927 if (SOC_IS_TOMAHAWK2(unit) || (SOC_IS_TOMAHAWK3(unit))) { 12928 if (SRAM_OSC_1_PENf == osc_tbl[index].field0 || 12929 SRAM_OSC_2_PENf == osc_tbl[index].field0 || 12930 SRAM_OSC_3_PENf == osc_tbl[index].field0) { 12931 continue; 12932 } 12933 } 12934 #endif 12935 12936 /* 12937 * set OSC_CNT_RSTBf to 0 to do softreset 12938 * set OSC_CNT_START to 0 to hold the counter until it selects 12939 * the input signal 12940 */ 12941 SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval)); 12942 soc_reg_field_set(unit, ctrl_reg, &rval, OSC_ENABLEf, 1); 12943 soc_reg_field_set(unit, ctrl_reg, &rval, IROSC_ENf, 1); 12944 soc_reg_field_set(unit, ctrl_reg, &rval, osc_tbl[index].field0, 12945 osc_tbl[index].value0); 12946 if (osc_tbl[index].field1 != INVALIDf) { 12947 soc_reg_field_set(unit, ctrl_reg, &rval, osc_tbl[index].field1, 12948 osc_tbl[index].value1); 12949 } 12950 soc_reg_field_set(unit, ctrl_reg, &rval, OSC_SELf, 12951 osc_tbl[index].osc_sel); 12952 SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval)); 12953 soc_reg_field_set(unit, ctrl_reg, &rval, OSC_CNT_RSTBf, 1); 12954 SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval)); 12955 soc_reg_field_set(unit, ctrl_reg, &rval, OSC_CNT_STARTf, 1); 12956 SOC_IF_ERROR_RETURN(WRITE_TOP_RING_OSC_CTRLr(unit, rval)); 12957 12958 for (retry = 0; retry < 10; retry++) { 12959 sal_usleep(1000); 12960 SOC_IF_ERROR_RETURN(READ_TOP_OSC_COUNT_STATr(unit, &rval)); 12961 if (!soc_reg_field_get(unit, stat_reg, rval, OSC_CNT_DONEf)) { 12962 continue; 12963 } 12964 12965 fval = soc_reg_field_get(unit, stat_reg, rval, OSC_CNT_VALUEf); 12966 quo = core_clk / fval; 12967 rem = core_clk - quo * fval; 12968 frac = (rem * 10000) / fval; 12969 LOG_CLI((BSL_META_U(unit, 12970 "%s: %d.%04d Mhz\n"), 12971 osc_tbl[index].name, quo, frac)); 12972 break; 12973 } 12974 } 12975 12976 return SOC_E_NONE; 12977 } 12978 12979 STATIC _soc_th_bst_hw_cb th_bst_cb; 12980 12981 int 12982 _soc_th_process_mmu_bst(int unit, int xpe, soc_field_t field) 12983 { 12984 int rv = SOC_E_NONE; 12985 if (th_bst_cb != NULL) { 12986 rv = th_bst_cb(unit); 12987 } 12988 return rv; 12989 } 12990 12991 int soc_th_set_bst_callback(int unit, _soc_th_bst_hw_cb cb) 12992 { 12993 th_bst_cb = cb; 12994 return SOC_E_NONE; 12995 } 12996 12997 void 12998 soc_tomahawk_process_func_intr(void *unit_vp, void *d1, void *d2, void *d3, void *d4) 12999 { 13000 int rv = SOC_E_NONE; 13001 int unit = PTR_TO_INT(unit_vp); 13002 uint32 rval; 13003 char prefix_str[10]; 13004 sal_sprintf(prefix_str, "Unit: %d \n", unit); 13005 13006 rv = READ_L2_MGMT_INTRr(unit, &rval); 13007 if (SOC_FAILURE(rv)) { 13008 LOG_ERROR(BSL_LS_SOC_COMMON, 13009 (BSL_META_U(unit, "Error reading %s reg !!\n"), 13010 SOC_REG_NAME(unit, L2_MGMT_INTRr))); 13011 return; 13012 } 13013 13014 if (soc_reg_field_get(unit, L2_MGMT_INTRr, rval, SER_FIFO_NOT_EMPTYf)) { 13015 (void) soc_tomahawk_process_ser_fifo(unit, SOC_BLK_IPIPE, 13016 0, /* pipe */ 13017 prefix_str, 13018 1, 0, 0); /* l2_mgmt_ser_fifo */ 13019 } 13020 13021 if (soc_feature(unit, soc_feature_l2_overflow)) { 13022 if (soc_reg_field_get(unit, L2_MGMT_INTRr, rval, L2_LEARN_INSERT_FAILUREf)) { 13023 soc_td2_l2_overflow_interrupt_handler(unit); 13024 } 13025 } 13026 13027 sal_usleep(SAL_BOOT_QUICKTURN ? 100000 : 1000); /* Don't reenable too soon */ 13028 if (d1 != NULL) { 13029 #ifdef BCM_CMICM_SUPPORT 13030 if (soc_feature(unit, soc_feature_cmicm)) { 13031 (void) soc_cmicm_intr3_enable(unit, PTR_TO_INT(d1)); 13032 } 13033 #endif 13034 } 13035 } 13036 13037 /* 13038 * All non-parity related interrupts must be handled in this function. 13039 * All unserviced intr_status bits must either be serviced or disabled. 13040 * 13041 * Note: 13042 * 1. MEM_PAR_ERR_STATf is handled by tomahawk/ser.c, so ignore this 13043 * 2. blocktype (in) can only be SOC_BLK_MMU_XPE/SC 13044 */ 13045 int 13046 soc_th_mmu_non_ser_intr_handler(int unit, soc_block_t blocktype, 13047 int mmu_base_index, 13048 uint32 rval_intr_status_reg) 13049 { 13050 int i; 13051 uint32 rval = 0; 13052 soc_reg_t intr_stat_reg, intr_clr_reg; 13053 static soc_field_t xpe_intr_field_list[] = { 13054 MEM_PAR_ERR_STATf, /* handled by tomahawk/ser.c, so ignore this */ 13055 BST_THDI_INT_STATf, 13056 BST_THDO_INT_STATf, 13057 DEQ0_NOT_IP_ERR_STATf, 13058 DEQ1_NOT_IP_ERR_STATf, 13059 INVALIDf 13060 }; 13061 static soc_field_t sc_intr_field_list[] = { 13062 CFAP_A_MEM_FAIL_STATf, 13063 CFAP_B_MEM_FAIL_STATf, 13064 MEM_PAR_ERR_STATf, /* handled by tomahawk/ser.c, so ignore this */ 13065 BST_CFAP_A_INT_STATf, 13066 BST_CFAP_B_INT_STATf, 13067 ES_X_DEADLOCK_DET_INT_STATf, 13068 ES_Y_DEADLOCK_DET_INT_STATf, 13069 START_BY_START_ERR_STATf, 13070 ES_X_1IN4_ERR_INT_STATf, 13071 ES_Y_1IN4_ERR_INT_STATf, 13072 INVALIDf 13073 }; 13074 13075 if (blocktype == SOC_BLK_MMU_XPE) { 13076 intr_stat_reg = MMU_XCFG_XPE_CPU_INT_STATr; 13077 intr_clr_reg = MMU_XCFG_XPE_CPU_INT_CLEARr; 13078 for (i = 0; xpe_intr_field_list[i] != INVALIDf; i++) { 13079 if (!soc_reg_field_get(unit, intr_stat_reg, 13080 rval_intr_status_reg, 13081 xpe_intr_field_list[i])) { 13082 continue; 13083 } 13084 switch (xpe_intr_field_list[i]) { 13085 case BST_THDI_INT_STATf: 13086 case BST_THDO_INT_STATf: 13087 /* interrupt processing */ 13088 LOG_VERBOSE(BSL_LS_SOC_COMMON, 13089 (BSL_META_U(unit, "Unit: %0d -- Serviced %s intr " 13090 "from xpe = %0d \n"), 13091 unit, SOC_FIELD_NAME(unit, xpe_intr_field_list[i]), 13092 mmu_base_index)); 13093 13094 /* clear the interrupt */ 13095 SOC_IF_ERROR_RETURN 13096 (soc_tomahawk_xpe_reg32_get(unit, intr_clr_reg, 13097 mmu_base_index, mmu_base_index, 13098 0, &rval)); 13099 rval |= (1 << i); 13100 SOC_IF_ERROR_RETURN 13101 (soc_tomahawk_xpe_reg32_set(unit, intr_clr_reg, 13102 mmu_base_index, mmu_base_index, 13103 0, rval)); 13104 SOC_IF_ERROR_RETURN 13105 (_soc_th_process_mmu_bst(unit, mmu_base_index, 13106 xpe_intr_field_list[i])); 13107 break; 13108 default: 13109 LOG_ERROR(BSL_LS_SOC_COMMON, 13110 (BSL_META_U(unit, "Unit: %0d -- Could not service %s " 13111 "intr from xpe = %0d \n"), 13112 unit, SOC_FIELD_NAME(unit, xpe_intr_field_list[i]), 13113 mmu_base_index)); 13114 break; 13115 } 13116 } 13117 return SOC_E_NONE; 13118 } 13119 13120 if (blocktype == SOC_BLK_MMU_SC) { 13121 intr_stat_reg = MMU_SCFG_SC_CPU_INT_STATr; 13122 intr_clr_reg = MMU_SCFG_SC_CPU_INT_CLEARr; 13123 for (i = 0; sc_intr_field_list[i] != INVALIDf; i++) { 13124 if (!soc_reg_field_get(unit, intr_stat_reg, 13125 rval_intr_status_reg, 13126 sc_intr_field_list[i])) { 13127 continue; 13128 } 13129 switch (sc_intr_field_list[i]) { 13130 case BST_CFAP_A_INT_STATf: 13131 case BST_CFAP_B_INT_STATf: 13132 /* interrupt processing */ 13133 LOG_VERBOSE(BSL_LS_SOC_COMMON, 13134 (BSL_META_U(unit, "Unit: %0d -- Serviced %s intr " 13135 "from sc = %0d \n"), 13136 unit, SOC_FIELD_NAME(unit, sc_intr_field_list[i]), 13137 mmu_base_index)); 13138 13139 13140 /* clear the interrupt */ 13141 SOC_IF_ERROR_RETURN 13142 (soc_tomahawk_sc_reg32_get(unit, intr_clr_reg, 13143 mmu_base_index, mmu_base_index, 13144 0, &rval)); 13145 rval |= (1 << i); 13146 SOC_IF_ERROR_RETURN 13147 (soc_tomahawk_sc_reg32_set(unit, intr_clr_reg, 13148 mmu_base_index, mmu_base_index, 13149 0, rval)); 13150 SOC_IF_ERROR_RETURN 13151 (_soc_th_process_mmu_bst(unit, mmu_base_index, 13152 sc_intr_field_list[i])); 13153 13154 break; 13155 case CFAP_A_MEM_FAIL_STATf: 13156 case CFAP_B_MEM_FAIL_STATf: 13157 /* interrupt processing */ 13158 LOG_VERBOSE(BSL_LS_SOC_COMMON, 13159 (BSL_META_U(unit, "Unit: %0d -- Serviced %s intr " 13160 "from sc = %0d \n"), 13161 unit, SOC_FIELD_NAME(unit, sc_intr_field_list[i]), 13162 mmu_base_index)); 13163 13164 soc_event_generate(unit, SOC_SWITCH_EVENT_PARITY_ERROR, 13165 SOC_SWITCH_EVENT_DATA_ERROR_CFAP_MEM_FAIL, -1, -1); 13166 13167 /* clear the interrupt */ 13168 SOC_IF_ERROR_RETURN 13169 (soc_tomahawk_sc_reg32_get(unit, intr_clr_reg, 13170 mmu_base_index, mmu_base_index, 13171 0, &rval)); 13172 rval |= (1 << i); 13173 SOC_IF_ERROR_RETURN 13174 (soc_tomahawk_sc_reg32_set(unit, intr_clr_reg, 13175 mmu_base_index, mmu_base_index, 13176 0, rval)); 13177 break; 13178 default: 13179 LOG_ERROR(BSL_LS_SOC_COMMON, 13180 (BSL_META_U(unit, "Unit: %0d -- Could not service %s " 13181 "intr from sc = %0d \n"), 13182 unit, SOC_FIELD_NAME(unit, sc_intr_field_list[i]), 13183 mmu_base_index)); 13184 break; 13185 } 13186 } 13187 return SOC_E_NONE; 13188 } 13189 13190 /* cannot be here for any other blocktype */ 13191 return SOC_E_FAIL; 13192 } 13193 13194 STATIC int 13195 _soc_th_mmu_config_shared_update_check(int val1, int val2, int flags) 13196 { 13197 int rv = 0; 13198 if (flags == 1) { 13199 if (val1 > val2) { 13200 rv = 1; 13201 } 13202 } else { 13203 if (val1 < val2) { 13204 rv = 1; 13205 } 13206 } 13207 return rv; 13208 } 13209 13210 #define TH_MMU_SHARED_LIMIT_CHK(val1, val2, flags) \ 13211 _soc_th_mmu_config_shared_update_check((val1), (val2), (flags)) 13212 13213 int 13214 soc_th_mmu_config_shared_buf_recalc(int unit, int res, 13215 int *thdi_shd, int *thdo_db_shd, int *thdo_qe_shd, 13216 int post_update) 13217 { 13218 soc_info_t *si; 13219 int pipe, xpe, xpe_map; 13220 uint32 entry0[SOC_MAX_MEM_WORDS], cur_limit, rval = 0, rval2 = 0; 13221 thdi_port_pg_config_entry_t pg_config_mem; 13222 mmu_thdo_config_qgroup_entry_t cfg_qgrp; 13223 int port, base, numq, idx, midx; 13224 soc_mem_t base_mem = INVALIDm; 13225 soc_mem_t mem = INVALIDm; 13226 soc_reg_t reg = INVALIDr; 13227 soc_field_t field = INVALIDf; 13228 int granularity; 13229 int thdi_shd_min, thdo_db_shd_min, thdo_qe_shd_min; 13230 13231 si = &SOC_INFO(unit); 13232 13233 xpe_map = si->ipipe_xpe_map[0] | si->ipipe_xpe_map[1]; 13234 13235 _TH_ARRAY_MIN(thdi_shd, NUM_XPE(unit), xpe_map, thdi_shd_min); 13236 _TH_ARRAY_MIN(thdo_db_shd, NUM_XPE(unit), xpe_map, thdo_db_shd_min); 13237 _TH_ARRAY_MIN(thdo_qe_shd, NUM_XPE(unit), xpe_map, thdo_qe_shd_min); 13238 13239 /*********************************** 13240 * THDI 13241 */ 13242 if (res & 0x1) { /* if (res & THDI) */ 13243 13244 /* THDI SP entries */ 13245 rval = 0; 13246 reg = THDI_BUFFER_CELL_LIMIT_SPr; 13247 field = LIMITf; 13248 granularity = 1; 13249 for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) { 13250 if (!(xpe_map & (1 << xpe))) { 13251 continue; 13252 } 13253 13254 for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) { 13255 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 13256 reg, xpe, -1, idx, &rval)); 13257 cur_limit = soc_reg_field_get(unit, reg, rval, field); 13258 if ((cur_limit != 0) && 13259 TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdi_shd[xpe]/granularity, 13260 post_update)) { 13261 soc_reg_field_set(unit, reg, &rval, field, (thdi_shd[xpe]/granularity)); 13262 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 13263 reg, xpe, -1, idx, rval)); 13264 } 13265 } 13266 } 13267 13268 /* Input per port settings */ 13269 base_mem = THDI_PORT_PG_CONFIGm; 13270 PBMP_ALL_ITER(unit, port) { 13271 pipe = si->port_pipe[port]; 13272 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 13273 field = PG_SHARED_LIMITf; 13274 granularity = 1; 13275 /* Input port per Port-PG settings */ 13276 for (idx = 0; idx < _TH_MMU_NUM_PG; idx++) { 13277 midx = SOC_TH_MMU_PIPED_MEM_INDEX(unit, port, base_mem, idx); 13278 sal_memset(&pg_config_mem, 0, sizeof(pg_config_mem)); 13279 SOC_IF_ERROR_RETURN 13280 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, 13281 midx, &pg_config_mem)); 13282 if (!soc_mem_field32_get(unit, mem, &pg_config_mem, 13283 PG_SHARED_DYNAMICf)) { 13284 cur_limit = soc_mem_field32_get(unit, mem, &pg_config_mem, 13285 field); 13286 if ((cur_limit != 0) && 13287 TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdi_shd_min/granularity, 13288 post_update)) { 13289 soc_mem_field32_set(unit, mem, &pg_config_mem, 13290 field, thdi_shd_min/granularity); 13291 } 13292 } 13293 13294 SOC_IF_ERROR_RETURN 13295 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, 13296 midx, &pg_config_mem)); 13297 } 13298 } 13299 } 13300 13301 /*********************************** 13302 * THDO 13303 */ 13304 if (res & 0x2) { /* if (res & THDO) */ 13305 /* Per SP settings */ 13306 for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) { 13307 if (!(xpe_map & (1 << xpe))) { 13308 continue; 13309 } 13310 13311 for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) { 13312 /* DB entries */ 13313 rval = 0; 13314 reg = MMU_THDM_DB_POOL_SHARED_LIMITr; 13315 field = SHARED_LIMITf; 13316 granularity = 1; 13317 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 13318 reg, xpe, -1, idx, &rval)); 13319 cur_limit = soc_reg_field_get(unit, reg, rval, field); 13320 if ((cur_limit != 0) && 13321 TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_db_shd[xpe]/granularity, 13322 post_update)) { 13323 soc_reg_field_set(unit, reg, &rval, field, (thdo_db_shd[xpe]/granularity)); 13324 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 13325 reg, xpe, -1, idx, rval)); 13326 } 13327 13328 rval = 0; 13329 reg = MMU_THDM_DB_POOL_YELLOW_SHARED_LIMITr; 13330 field = YELLOW_SHARED_LIMITf; 13331 granularity = 8; 13332 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 13333 reg, xpe, -1, idx, &rval)); 13334 cur_limit = soc_reg_field_get(unit, reg, rval, field); 13335 if ((cur_limit != 0) && 13336 TH_MMU_SHARED_LIMIT_CHK(cur_limit, sal_ceil_func(thdo_db_shd[xpe], granularity), 13337 post_update)) { 13338 soc_reg_field_set(unit, reg, &rval, field, sal_ceil_func(thdo_db_shd[xpe], granularity)); 13339 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 13340 reg, xpe, -1, idx, rval)); 13341 } 13342 13343 rval = 0; 13344 reg = MMU_THDM_DB_POOL_RED_SHARED_LIMITr; 13345 field = RED_SHARED_LIMITf; 13346 granularity = 8; 13347 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 13348 reg, xpe, -1, idx, &rval)); 13349 cur_limit = soc_reg_field_get(unit, reg, rval, field); 13350 if ((cur_limit != 0) && 13351 TH_MMU_SHARED_LIMIT_CHK(cur_limit, sal_ceil_func(thdo_db_shd[xpe], granularity), 13352 post_update)) { 13353 soc_reg_field_set(unit, reg, &rval, field, sal_ceil_func(thdo_db_shd[xpe], granularity)); 13354 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 13355 reg, xpe, -1, idx, rval)); 13356 } 13357 13358 rval = 0; 13359 reg = MMU_THDM_DB_POOL_RESUME_LIMITr; 13360 field = RESUME_LIMITf; 13361 granularity = 8; 13362 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 13363 reg, xpe, -1, idx, &rval)); 13364 cur_limit = soc_reg_field_get(unit, reg, rval, field); 13365 if ((cur_limit != 0) && 13366 TH_MMU_SHARED_LIMIT_CHK(cur_limit, sal_ceil_func(thdo_db_shd[xpe], granularity), 13367 post_update)) { 13368 soc_reg_field_set(unit, reg, &rval, field, sal_ceil_func(thdo_db_shd[xpe], granularity)); 13369 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 13370 reg, xpe, -1, idx, rval)); 13371 } 13372 13373 rval = 0; 13374 reg = MMU_THDM_DB_POOL_YELLOW_RESUME_LIMITr; 13375 field = YELLOW_RESUME_LIMITf; 13376 granularity = 8; 13377 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 13378 reg, xpe, -1, idx, &rval)); 13379 cur_limit = soc_reg_field_get(unit, reg, rval, field); 13380 if ((cur_limit != 0) && 13381 TH_MMU_SHARED_LIMIT_CHK(cur_limit, sal_ceil_func(thdo_db_shd[xpe], granularity), 13382 post_update)) { 13383 soc_reg_field_set(unit, reg, &rval, field, sal_ceil_func(thdo_db_shd[xpe], granularity)); 13384 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 13385 reg, xpe, -1, idx, rval)); 13386 } 13387 13388 rval = 0; 13389 reg = MMU_THDM_DB_POOL_RED_RESUME_LIMITr; 13390 field = RED_RESUME_LIMITf; 13391 granularity = 8; 13392 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 13393 reg, xpe, -1, idx, &rval)); 13394 cur_limit = soc_reg_field_get(unit, reg, rval, field); 13395 if ((cur_limit != 0) && 13396 TH_MMU_SHARED_LIMIT_CHK(cur_limit, sal_ceil_func(thdo_db_shd[xpe], granularity), 13397 post_update)) { 13398 soc_reg_field_set(unit, reg, &rval, field, sal_ceil_func(thdo_db_shd[xpe], granularity)); 13399 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 13400 reg, xpe, -1, idx, rval)); 13401 } 13402 13403 /* MCQE */ 13404 rval = 0; 13405 reg = MMU_THDM_MCQE_POOL_SHARED_LIMITr; 13406 field = SHARED_LIMITf; 13407 granularity = 4; 13408 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 13409 reg, xpe, -1, idx, &rval)); 13410 cur_limit = soc_reg_field_get(unit, reg, rval, field); 13411 if ((cur_limit != 0) && 13412 TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_qe_shd[xpe]/granularity, 13413 post_update)) { 13414 soc_reg_field_set(unit, reg, &rval, field, 13415 (thdo_qe_shd[xpe]/granularity)); 13416 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 13417 reg, xpe, -1, idx, rval)); 13418 } 13419 13420 rval = 0; 13421 reg = MMU_THDM_MCQE_POOL_YELLOW_SHARED_LIMITr; 13422 field = YELLOW_SHARED_LIMITf; 13423 granularity = 8; 13424 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 13425 reg, xpe, -1, idx, &rval)); 13426 cur_limit = soc_reg_field_get(unit, reg, rval, field); 13427 if ((cur_limit != 0) && 13428 TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_qe_shd[xpe]/granularity, 13429 post_update)) { 13430 soc_reg_field_set(unit, reg, &rval, field, 13431 (thdo_qe_shd[xpe]/granularity)); 13432 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 13433 reg, xpe, -1, idx, rval)); 13434 } 13435 13436 rval = 0; 13437 reg = MMU_THDM_MCQE_POOL_RED_SHARED_LIMITr; 13438 field = RED_SHARED_LIMITf; 13439 granularity = 8; 13440 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 13441 reg, xpe, -1, idx, &rval)); 13442 cur_limit = soc_reg_field_get(unit, reg, rval, field); 13443 if ((cur_limit != 0) && 13444 TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_qe_shd[xpe]/granularity, 13445 post_update)) { 13446 soc_reg_field_set(unit, reg, &rval, field, 13447 (thdo_qe_shd[xpe]/granularity)); 13448 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 13449 reg, xpe, -1, idx, rval)); 13450 } 13451 } 13452 } 13453 13454 /* configure Q-groups */ 13455 base_mem = MMU_THDU_CONFIG_QGROUPm; 13456 for (pipe = 0; pipe < NUM_PIPE(unit); pipe++) { 13457 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 13458 for (idx = 0; idx < SOC_TH_MMU_CFG_QGROUP_MAX; idx++) { 13459 sal_memset(&cfg_qgrp, 0, sizeof(cfg_qgrp)); 13460 13461 SOC_IF_ERROR_RETURN 13462 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, idx, &cfg_qgrp)); 13463 13464 field = Q_SHARED_LIMIT_CELLf; 13465 granularity = 1; 13466 if (!soc_mem_field32_get(unit, mem, &cfg_qgrp, Q_LIMIT_DYNAMIC_CELLf)) { 13467 cur_limit = soc_mem_field32_get(unit, mem, &cfg_qgrp, field); 13468 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_db_shd_min/granularity, 13469 post_update)) { 13470 soc_mem_field32_set(unit, mem, &cfg_qgrp, 13471 field, thdo_db_shd_min/granularity); 13472 } 13473 } 13474 13475 granularity = 8; 13476 if (!soc_mem_field32_get(unit, mem, &cfg_qgrp, 13477 Q_COLOR_LIMIT_DYNAMIC_CELLf)) { 13478 field = LIMIT_RED_CELLf; 13479 cur_limit = soc_mem_field32_get(unit, mem, &cfg_qgrp, field); 13480 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_db_shd_min/granularity, 13481 post_update)) { 13482 soc_mem_field32_set(unit, mem, &cfg_qgrp, 13483 field, thdo_db_shd_min/granularity); 13484 } 13485 13486 field = LIMIT_YELLOW_CELLf; 13487 cur_limit = soc_mem_field32_get(unit, mem, &cfg_qgrp, field); 13488 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_db_shd_min/granularity, 13489 post_update)) { 13490 soc_mem_field32_set(unit, mem, &cfg_qgrp, 13491 field, thdo_db_shd_min/granularity); 13492 } 13493 } 13494 13495 SOC_IF_ERROR_RETURN 13496 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx, &cfg_qgrp)); 13497 } 13498 } 13499 13500 /* Output port per port per queue setting for UC queue */ 13501 PBMP_PORT_ITER(unit, port) { 13502 base_mem = MMU_THDU_CONFIG_QUEUEm; 13503 pipe = si->port_pipe[port]; 13504 13505 /* per port UC queue */ 13506 numq = si->port_num_uc_cosq[port]; 13507 base = si->port_uc_cosq_base[port]; 13508 13509 if (numq == 0) { 13510 continue; 13511 } 13512 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 13513 for (idx = 0; idx < numq; idx++) { 13514 sal_memset(entry0, 0, sizeof(mmu_thdu_config_queue_entry_t)); 13515 13516 SOC_IF_ERROR_RETURN 13517 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, base + idx, entry0)); 13518 13519 field = Q_SHARED_LIMIT_CELLf; 13520 granularity = 1; 13521 if (!soc_mem_field32_get(unit, mem, entry0, Q_LIMIT_DYNAMIC_CELLf)) { 13522 cur_limit = soc_mem_field32_get(unit, mem, entry0, field); 13523 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, thdo_db_shd_min/granularity, 13524 post_update)) { 13525 soc_mem_field32_set(unit, mem, entry0, 13526 field, thdo_db_shd_min/granularity); 13527 } 13528 } 13529 13530 granularity = 8; 13531 if (!soc_mem_field32_get(unit, mem, entry0, Q_COLOR_LIMIT_DYNAMIC_CELLf)) { 13532 field = LIMIT_YELLOW_CELLf; 13533 cur_limit = soc_mem_field32_get(unit, mem, entry0, field); 13534 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, sal_ceil_func(thdo_db_shd_min, granularity), 13535 post_update)) { 13536 soc_mem_field32_set(unit, mem, entry0, 13537 field, sal_ceil_func(thdo_db_shd_min, granularity)); 13538 } 13539 field = LIMIT_RED_CELLf; 13540 cur_limit = soc_mem_field32_get(unit, mem, entry0, field); 13541 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, 13542 sal_ceil_func(thdo_db_shd_min, granularity), post_update)) { 13543 soc_mem_field32_set(unit, mem, entry0, 13544 field, sal_ceil_func(thdo_db_shd_min, granularity)); 13545 } 13546 } 13547 SOC_IF_ERROR_RETURN 13548 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, base + idx, entry0)); 13549 } 13550 } 13551 13552 /* Output port per port per queue setting for MC queue */ 13553 PBMP_PORT_ITER(unit, port) { 13554 /* DB entries - Queue */ 13555 numq = si->port_num_cosq[port]; 13556 base = si->port_cosq_base[port]; 13557 if (numq == 0) { 13558 continue; 13559 } 13560 13561 base_mem = MMU_THDM_DB_QUEUE_CONFIGm; 13562 pipe = si->port_pipe[port]; 13563 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 13564 13565 for (idx = 0; idx < numq; idx++) { 13566 sal_memset(entry0, 0, sizeof(mmu_thdm_db_queue_config_entry_t)); 13567 13568 SOC_IF_ERROR_RETURN 13569 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, base + idx, entry0)); 13570 13571 field = Q_SHARED_LIMITf; 13572 granularity = 1; 13573 if (!soc_mem_field32_get(unit, mem, entry0, Q_LIMIT_DYNAMICf)) { 13574 cur_limit = soc_mem_field32_get(unit, mem, entry0, field); 13575 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, 13576 thdo_db_shd_min/granularity, post_update)) { 13577 soc_mem_field32_set(unit, mem, entry0, 13578 field, thdo_db_shd_min/granularity); 13579 } 13580 } 13581 13582 granularity = 8; 13583 if (!soc_mem_field32_get(unit, mem, entry0, Q_COLOR_LIMIT_DYNAMICf)) { 13584 field = YELLOW_SHARED_LIMITf; 13585 cur_limit = soc_mem_field32_get(unit, mem, entry0, field); 13586 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, 13587 sal_ceil_func(thdo_db_shd_min, granularity), post_update)) { 13588 soc_mem_field32_set(unit, mem, entry0, 13589 field, sal_ceil_func(thdo_db_shd_min, granularity)); 13590 } 13591 field = RED_SHARED_LIMITf; 13592 cur_limit = soc_mem_field32_get(unit, mem, entry0, field); 13593 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, 13594 sal_ceil_func(thdo_db_shd_min, granularity), post_update)) { 13595 soc_mem_field32_set(unit, mem, entry0, 13596 field, sal_ceil_func(thdo_db_shd_min, granularity)); 13597 } 13598 } 13599 SOC_IF_ERROR_RETURN 13600 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, base + idx, 13601 entry0)); 13602 } 13603 13604 /* MCQE - Queue */ 13605 base_mem = MMU_THDM_MCQE_QUEUE_CONFIGm; 13606 mem = SOC_MEM_UNIQUE_ACC(unit, base_mem)[pipe]; 13607 for (idx = 0; idx < numq; idx++) { 13608 sal_memset(entry0, 0, sizeof(mmu_thdm_mcqe_queue_config_entry_t)); 13609 13610 SOC_IF_ERROR_RETURN 13611 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, base + idx, entry0)); 13612 13613 field = Q_SHARED_LIMITf; 13614 granularity = 4; 13615 if (!soc_mem_field32_get(unit, mem, entry0, Q_LIMIT_DYNAMICf)) { 13616 cur_limit = soc_mem_field32_get(unit, mem, entry0, field); 13617 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, 13618 thdo_qe_shd_min/granularity, post_update)) { 13619 soc_mem_field32_set(unit, mem, entry0, 13620 field, thdo_qe_shd_min/granularity); 13621 } 13622 } 13623 13624 granularity = 8; 13625 if (!soc_mem_field32_get(unit, mem, entry0, Q_COLOR_LIMIT_DYNAMICf)) { 13626 field = YELLOW_SHARED_LIMITf; 13627 cur_limit = soc_mem_field32_get(unit, mem, entry0, field); 13628 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, 13629 thdo_qe_shd_min/granularity, post_update)) { 13630 soc_mem_field32_set(unit, mem, entry0, 13631 field, thdo_qe_shd_min/granularity); 13632 } 13633 field = RED_SHARED_LIMITf; 13634 cur_limit = soc_mem_field32_get(unit, mem, entry0, field); 13635 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, 13636 thdo_qe_shd_min/granularity, post_update)) { 13637 soc_mem_field32_set(unit, mem, entry0, 13638 field, thdo_qe_shd_min/granularity); 13639 } 13640 } 13641 SOC_IF_ERROR_RETURN 13642 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, base + idx, 13643 entry0)); 13644 } 13645 } 13646 13647 /* RQE */ 13648 for (idx = 0; idx < 11; idx++) { 13649 rval = 0; 13650 rval2 = 0; 13651 13652 SOC_IF_ERROR_RETURN 13653 (READ_MMU_THDR_DB_CONFIG1_PRIQr(unit, idx, &rval)); 13654 13655 reg = MMU_THDR_DB_CONFIG_PRIQr; 13656 field = SHARED_LIMITf; 13657 granularity = 1; 13658 SOC_IF_ERROR_RETURN 13659 (soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval2)); 13660 if (!soc_reg_field_get(unit, MMU_THDR_DB_CONFIG1_PRIQr, rval, 13661 DYNAMIC_ENABLEf)) { 13662 cur_limit = soc_reg_field_get(unit, reg, rval2, field); 13663 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, 13664 thdo_db_shd_min/granularity, post_update)) { 13665 soc_reg_field_set(unit, reg, &rval2, field, 13666 (thdo_db_shd_min/granularity)); 13667 SOC_IF_ERROR_RETURN 13668 (soc_reg32_set(unit, reg, REG_PORT_ANY, idx, rval2)); 13669 } 13670 } 13671 13672 rval2 = 0; 13673 reg = MMU_THDR_DB_LIMIT_COLOR_PRIQr; 13674 granularity = 8; 13675 SOC_IF_ERROR_RETURN 13676 (soc_reg32_get(unit, reg, REG_PORT_ANY, idx, &rval2)); 13677 13678 if (!soc_reg_field_get(unit, MMU_THDR_DB_CONFIG1_PRIQr, rval, 13679 COLOR_LIMIT_DYNAMICf)) { 13680 field = SHARED_RED_LIMITf; 13681 cur_limit = soc_reg_field_get(unit, reg, rval2, field); 13682 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, 13683 thdo_db_shd_min/granularity, post_update)) { 13684 soc_reg_field_set(unit, reg, &rval2, field, (thdo_db_shd_min/granularity)); 13685 } 13686 13687 field = SHARED_YELLOW_LIMITf; 13688 cur_limit = soc_reg_field_get(unit, reg, rval2, field); 13689 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, 13690 thdo_db_shd_min/granularity, post_update)) { 13691 soc_reg_field_set(unit, reg, &rval2, field, (thdo_db_shd_min/granularity)); 13692 } 13693 SOC_IF_ERROR_RETURN 13694 (soc_reg32_set(unit, reg, REG_PORT_ANY, idx, rval2)); 13695 } 13696 13697 } 13698 /* per pool RQE settings */ 13699 for (xpe = 0; xpe < NUM_XPE(unit); xpe ++) { 13700 if (!(xpe_map & (1 << xpe))) { 13701 continue; 13702 } 13703 13704 for (idx = 0; idx < _TH_MMU_NUM_POOL; idx++) { 13705 reg = MMU_THDR_DB_CONFIG_SPr; 13706 field = SHARED_LIMITf; 13707 granularity = 1; 13708 13709 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 13710 reg, xpe, -1, idx, &rval)); 13711 cur_limit = soc_reg_field_get(unit, reg, rval, field); 13712 13713 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, 13714 thdo_db_shd[xpe]/granularity, post_update)) { 13715 soc_reg_field_set 13716 (unit, reg, &rval, field, (thdo_db_shd[xpe]/granularity)); 13717 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 13718 reg, xpe, -1, idx, rval)); 13719 } 13720 13721 reg = MMU_THDR_DB_SP_SHARED_LIMITr; 13722 granularity = 8; 13723 13724 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_get(unit, 13725 reg, xpe, -1, idx, &rval)); 13726 13727 field = SHARED_YELLOW_LIMITf; 13728 cur_limit = soc_reg_field_get(unit, reg, rval, field); 13729 13730 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, 13731 thdo_db_shd[xpe]/granularity, post_update)) { 13732 soc_reg_field_set 13733 (unit, reg, &rval, field, (thdo_db_shd[xpe]/granularity)); 13734 } 13735 13736 field = SHARED_RED_LIMITf; 13737 cur_limit = soc_reg_field_get(unit, reg, rval, field); 13738 13739 if (TH_MMU_SHARED_LIMIT_CHK(cur_limit, 13740 thdo_db_shd[xpe]/granularity, post_update)) { 13741 soc_reg_field_set 13742 (unit, reg, &rval, field, (thdo_db_shd[xpe]/granularity)); 13743 } 13744 SOC_IF_ERROR_RETURN(soc_tomahawk_xpe_reg32_set(unit, 13745 reg, xpe, -1, idx, rval)); 13746 } 13747 } 13748 } 13749 return SOC_E_NONE; 13750 } 13751 13752 int soc_th_iss_log_to_phy_bank_map_shadow_get(int unit, uint32 *shadow_val) 13753 { 13754 if (shadow_val == NULL) { 13755 return SOC_E_PARAM; 13756 } 13757 13758 *shadow_val = _soc_th_iss_log_to_phy_bank_map_shadow[unit]; 13759 return SOC_E_NONE; 13760 } 13761 13762 int soc_th_iss_log_to_phy_bank_map_shadow_set(int unit, uint32 shadow_val) 13763 { 13764 _soc_th_iss_log_to_phy_bank_map_shadow[unit] = shadow_val; 13765 return SOC_E_NONE; 13766 } 13767 13768 int soc_th_reset_serdes(int unit, soc_port_t port, int reset_delay_us) 13769 { 13770 uint32 rval = 0; 13771 int rv = SOC_E_NONE; 13772 13773 SOC_IF_ERROR_RETURN(READ_CLPORT_XGXS0_CTRL_REGr(unit, port, &rval)); 13774 soc_reg_field_set(unit, CLPORT_XGXS0_CTRL_REGr, &rval, RSTB_HWf, 0 ); 13775 SOC_IF_ERROR_RETURN(WRITE_CLPORT_XGXS0_CTRL_REGr(unit, port, rval)); 13776 sal_usleep((reset_delay_us == 0) ? 10 : reset_delay_us ); 13777 soc_reg_field_set(unit, CLPORT_XGXS0_CTRL_REGr, &rval, RSTB_HWf, 1 ); 13778 SOC_IF_ERROR_RETURN(WRITE_CLPORT_XGXS0_CTRL_REGr(unit, port, rval)); 13779 sal_usleep((reset_delay_us == 0) ? 10 : reset_delay_us ); 13780 13781 return rv; 13782 } 13783 13784 void 13785 _soc_th_lpm_view_set(int unit, int index, soc_mem_t view, int pair_lpm) 13786 { 13787 int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit); 13788 13789 if (!_soc_th_lpm_view_map[unit]) { 13790 return; 13791 } 13792 13793 if (pair_lpm) { 13794 index = (index % tcam_depth) + 13795 (index / tcam_depth) * 2 * tcam_depth; 13796 _soc_th_lpm_view_map[unit][index] = view; 13797 _soc_th_lpm_view_map[unit][index + tcam_depth] = view; 13798 } else { 13799 _soc_th_lpm_view_map[unit][index] = view; 13800 } 13801 } 13802 13803 soc_mem_t 13804 _soc_th_lpm_view_get(int unit, int index, int pair_lpm) 13805 { 13806 soc_mem_t view; 13807 int tcam_depth = SOC_L3_DEFIP_TCAM_DEPTH_GET(unit); 13808 13809 if (!_soc_th_lpm_view_map[unit]) { 13810 return INVALIDm; 13811 } 13812 13813 if (pair_lpm) { 13814 index = (index % tcam_depth) + 13815 (index / tcam_depth) * 2 * tcam_depth; 13816 view = _soc_th_lpm_view_map[unit][index]; 13817 if (view == INVALIDm) { 13818 view = _soc_th_lpm_view_map[unit][index + tcam_depth]; 13819 } 13820 } else { 13821 view = _soc_th_lpm_view_map[unit][index]; 13822 } 13823 return view; 13824 } 13825 13826 #if defined(INCLUDE_FLOWTRACKER) 13827 STATIC soc_th_ft_em_ser_handler_t th_ft_em_ser_handler[SOC_MAX_NUM_DEVICES] = {NULL}; 13828 13829 void 13830 soc_th_ft_em_ser_handler_register(int unit, soc_th_ft_em_ser_handler_t handler) 13831 { 13832 th_ft_em_ser_handler[unit] = handler; 13833 } 13834 13835 int 13836 soc_th_ft_em_ser_process(int unit, int pipe, soc_mem_t mem, int index) 13837 { 13838 if (th_ft_em_ser_handler[unit]) { 13839 return th_ft_em_ser_handler[unit](unit, pipe, mem, index); 13840 } else { 13841 return SOC_E_UNAVAIL; 13842 } 13843 } 13844 #endif /* INCLUDE_FLOWTRACKER */ 13845 13846 #ifndef BCM_SW_STATE_DUMP_DISABLE 13847 void 13848 soc_th_flexport_sw_dump(int unit) 13849 { 13850 int port, phy_port, mmu_port, pipe, pm, cosq, numq, uc_cosq, uc_numq; 13851 int max_speed, init_speed, num_lanes; 13852 char pfmt[SOC_PBMP_FMT_LEN]; 13853 13854 LOG_CLI((BSL_META_U(unit, 13855 " port(log/phy/mmu) pipe pm lanes " 13856 "speed(Max) uc_Qbase/Numq mc_Qbase/Numq\n"))); 13857 PBMP_ALL_ITER(unit, port) { 13858 pipe = SOC_INFO(unit).port_pipe[port]; 13859 phy_port = SOC_INFO(unit).port_l2p_mapping[port]; 13860 mmu_port = SOC_INFO(unit).port_p2m_mapping[phy_port]; 13861 num_lanes = SOC_INFO(unit).port_num_lanes[port]; 13862 pm = SOC_INFO(unit).port_serdes[port]; 13863 max_speed = SOC_INFO(unit).port_speed_max[port]; 13864 init_speed = SOC_INFO(unit).port_init_speed[port]; 13865 cosq = SOC_INFO(unit).port_cosq_base[port]; 13866 numq = SOC_INFO(unit).port_num_cosq[port]; 13867 uc_cosq = SOC_INFO(unit).port_uc_cosq_base[port]; 13868 uc_numq = SOC_INFO(unit).port_num_uc_cosq[port]; 13869 13870 LOG_CLI((BSL_META_U(unit, 13871 " %4s(%3d/%3d/%3d) %4d %2d %5d %7d(%7d) " 13872 "%6d/%-6d %6d/%-6d\n"), 13873 SOC_INFO(unit).port_name[port], port, phy_port, mmu_port, 13874 pipe, pm, num_lanes, init_speed, max_speed, 13875 uc_cosq, uc_numq, cosq, numq)); 13876 } 13877 13878 LOG_CLI((BSL_META_U(unit, 13879 "\n Oversub Bitmap: %s"), 13880 SOC_PBMP_FMT(SOC_INFO(unit).oversub_pbm, pfmt))); 13881 LOG_CLI((BSL_META_U(unit, 13882 "\n Disabled Bitmap: %s \n"), 13883 SOC_PBMP_FMT(SOC_INFO(unit).all.disabled_bitmap, pfmt))); 13884 } 13885 13886 void 13887 soc_th_flexport_sw_pipe_speed_group_dump(int unit, int pipe, int speed_id) 13888 { 13889 int rv; 13890 soc_reg_t reg; 13891 int port_id, pm_id, inst; 13892 uint32 rval, fval; 13893 int speed, group, slot; 13894 13895 static char *speed_id_name[] = { 13896 "NONE", "10G", "20G", "25G", "40G", "50G", "100G" 13897 }; 13898 13899 speed = speed_id; 13900 13901 if (pipe < 0 || pipe > 3) { 13902 LOG_CLI((BSL_META_U(unit, 13903 "\n Error: pipe %d not valid for chip %s.\n"), 13904 pipe, SOC_UNIT_NAME(unit))); 13905 return; 13906 } 13907 if (speed < 0 || speed > SOC_TH_SPEED_CLASS_100G) { 13908 LOG_CLI((BSL_META_U(unit, 13909 "\n Error: speed class %d not valid for chip %s.\n"), 13910 speed, SOC_UNIT_NAME(unit))); 13911 return; 13912 } 13913 13914 LOG_CLI((BSL_META_U(unit, 13915 "\n pipe %d OverSub Scheduler IDB & MMU Table\n"), 13916 pipe)); 13917 for (group = 0; group < _OVS_GROUP_COUNT; group++) { 13918 reg = SOC_REG_UNIQUE_ACC(unit, IS_OVR_SUB_GRP_CFGr)[pipe]; 13919 rv = soc_reg32_get(unit, reg, REG_PORT_ANY, group, &rval); 13920 if (rv < 0) { 13921 LOG_CLI((BSL_META_U(unit, " FAILED: Register read.\n"))); 13922 } 13923 fval = soc_reg_field_get(unit, reg, rval, SPEEDf); 13924 if (fval == speed) { 13925 LOG_CLI((BSL_META_U(unit, 13926 "\n SPEED %s in IDB SPEED GROUP\n"), 13927 speed_id_name[fval])); 13928 reg = SOC_REG_UNIQUE_ACC(unit, idb_grp_tbl_regs[group])[pipe]; 13929 for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) { 13930 rv = soc_reg32_get(unit, reg, REG_PORT_ANY, slot, &rval); 13931 if (rv <0) { 13932 continue; 13933 } 13934 port_id = soc_reg_field_get(unit, reg, rval, PORT_NUMf); 13935 if (port_id != 0x3f) { 13936 pm_id = soc_reg_field_get(unit, reg, rval, PHY_PORT_IDf); 13937 LOG_CLI((BSL_META_U(unit, 13938 "{%d, %d} "), 13939 pm_id, port_id)); 13940 } 13941 } 13942 LOG_CLI((BSL_META_U(unit, "\n"))); 13943 } 13944 } 13945 13946 for (group = 0; group < _OVS_GROUP_COUNT; group++) { 13947 reg = OVR_SUB_GRP_CFGr; 13948 inst = pipe | SOC_REG_ADDR_INSTANCE_MASK; 13949 rv = soc_reg32_get(unit, reg, inst, group, &rval); 13950 if (rv <0) { 13951 continue; 13952 } 13953 fval = soc_reg_field_get(unit, reg, rval, SPEEDf); 13954 if (fval == speed) { 13955 LOG_CLI((BSL_META_U(unit, 13956 "\n SPEED %s in MMU SPEED GROUP\n"), 13957 speed_id_name[fval])); 13958 reg = mmu_grp_tbl_regs[group]; 13959 for (slot = 0; slot < _OVS_GROUP_TDM_LENGTH; slot++) { 13960 rv = soc_reg32_get(unit, reg, inst, slot, &rval); 13961 if (rv < 0) { 13962 continue; 13963 } 13964 port_id = soc_reg_field_get(unit, reg, rval, PORT_NUMf); 13965 if (port_id != 0x3f) { 13966 pm_id = soc_reg_field_get(unit, reg, rval, PHY_PORT_IDf); 13967 LOG_CLI((BSL_META_U(unit, 13968 "{%d, %d} "), 13969 pm_id, port_id)); 13970 } 13971 } 13972 LOG_CLI((BSL_META_U(unit, "\n"))); 13973 } 13974 } 13975 13976 LOG_CLI((BSL_META_U(unit, "\n"))); 13977 } 13978 13979 #endif /* BCM_SW_STATE_DUMP_DISABLE */ 13980 13981 /* 13982 * Tomahawk chip driver functions. 13983 * Pls keep at the end of this file for easy access. 13984 */ 13985 soc_functions_t soc_tomahawk_drv_funs = { 13986 _soc_tomahawk_misc_init, 13987 _soc_tomahawk_mmu_init, 13988 _soc_tomahawk_age_timer_get, 13989 _soc_tomahawk_age_timer_max_get, 13990 _soc_tomahawk_age_timer_set, 13991 _soc_tomahawk_tscx_firmware_set, 13992 _soc_tomahawk_tscx_reg_read, 13993 _soc_tomahawk_tscx_reg_write, 13994 _soc_tomahawk_bond_info_init 13995 }; 13996 #endif /* BCM_TOMAHAWK_SUPPORT */