port.c (18795B)
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 * StrataSwitch port control API 8 */ 9 #include <shared/bsl.h> 10 #include <sal/core/libc.h> 11 #include <shared/alloc.h> 12 #include <sal/core/spl.h> 13 14 #include <soc/drv.h> 15 #include <soc/debug.h> 16 #include <soc/portmode.h> 17 #include <soc/port_ability.h> 18 #ifdef PORTMOD_SUPPORT 19 #include <soc/esw/portctrl.h> 20 #endif /* PORTMOD_SUPPORT */ 21 22 int 23 soc_port_mode_to_ability(soc_port_mode_t mode, soc_port_ability_t *ability) 24 { 25 uint32 port_abil; 26 27 if (NULL == ability) { 28 return (SOC_E_PARAM); 29 } 30 31 /* Half duplex speeds */ 32 port_abil = 0; 33 port_abil |= (mode & SOC_PM_10MB_HD) ? SOC_PA_SPEED_10MB : 0; 34 port_abil |= (mode & SOC_PM_100MB_HD) ? SOC_PA_SPEED_100MB : 0; 35 port_abil |= (mode & SOC_PM_1000MB_HD) ? SOC_PA_SPEED_1000MB : 0; 36 port_abil |= (mode & SOC_PM_2500MB_HD) ? SOC_PA_SPEED_2500MB : 0; 37 port_abil |= (mode & SOC_PM_3000MB_HD) ? SOC_PA_SPEED_3000MB : 0; 38 port_abil |= (mode & SOC_PM_10GB_HD) ? SOC_PA_SPEED_10GB : 0; 39 port_abil |= (mode & SOC_PM_12GB_HD) ? SOC_PA_SPEED_12GB : 0; 40 port_abil |= (mode & SOC_PM_13GB_HD) ? SOC_PA_SPEED_13GB : 0; 41 port_abil |= (mode & SOC_PM_16GB_HD) ? SOC_PA_SPEED_16GB : 0; 42 ability->speed_half_duplex = port_abil; 43 44 /* Full duplex speeds */ 45 port_abil = 0; 46 port_abil |= (mode & SOC_PM_10MB_FD) ? SOC_PA_SPEED_10MB : 0; 47 port_abil |= (mode & SOC_PM_100MB_FD) ? SOC_PA_SPEED_100MB : 0; 48 port_abil |= (mode & SOC_PM_1000MB_FD) ? SOC_PA_SPEED_1000MB : 0; 49 port_abil |= (mode & SOC_PM_2500MB_FD) ? SOC_PA_SPEED_2500MB : 0; 50 port_abil |= (mode & SOC_PM_3000MB_FD) ? SOC_PA_SPEED_3000MB : 0; 51 port_abil |= (mode & SOC_PM_10GB_FD) ? SOC_PA_SPEED_10GB : 0; 52 port_abil |= (mode & SOC_PM_12GB_FD) ? SOC_PA_SPEED_12GB : 0; 53 port_abil |= (mode & SOC_PM_13GB_FD) ? SOC_PA_SPEED_13GB : 0; 54 port_abil |= (mode & SOC_PM_16GB_FD) ? SOC_PA_SPEED_16GB : 0; 55 ability->speed_full_duplex = port_abil; 56 57 /* Pause Modes */ 58 port_abil = 0; 59 port_abil |= (mode & SOC_PM_PAUSE_TX)? SOC_PA_PAUSE_TX : 0; 60 port_abil |= (mode & SOC_PM_PAUSE_RX) ? SOC_PA_PAUSE_RX : 0; 61 port_abil |= (mode & SOC_PM_PAUSE_ASYMM) ? SOC_PA_PAUSE_ASYMM : 0; 62 ability->pause = port_abil; 63 64 /* Interface Types */ 65 port_abil = 0; 66 port_abil |= (mode & SOC_PM_TBI) ? SOC_PA_INTF_TBI : 0; 67 port_abil |= (mode & SOC_PM_MII) ? SOC_PA_INTF_MII : 0; 68 port_abil |= (mode & SOC_PM_GMII) ? SOC_PA_INTF_GMII : 0; 69 port_abil |= (mode & SOC_PM_SGMII) ? SOC_PA_INTF_SGMII : 0; 70 port_abil |= (mode & SOC_PM_XGMII) ? SOC_PA_INTF_XGMII : 0; 71 ability->interface = port_abil; 72 73 /* Loopback Mode */ 74 port_abil = 0; 75 port_abil |= (mode & SOC_PM_LB_MAC) ? SOC_PA_LB_MAC : 0; 76 port_abil |= (mode & SOC_PM_LB_PHY) ? SOC_PA_LB_PHY : 0; 77 port_abil |= (mode & SOC_PM_LB_NONE) ? SOC_PA_LB_NONE : 0; 78 ability->loopback = port_abil; 79 80 /* Remaining Flags */ 81 port_abil = 0; 82 port_abil |= (mode & SOC_PM_AN) ? SOC_PA_AUTONEG : 0; 83 port_abil |= (mode & SOC_PM_COMBO) ? SOC_PA_COMBO : 0; 84 ability->flags = port_abil; 85 86 return (SOC_E_NONE); 87 } 88 89 int 90 soc_port_ability_to_mode(soc_port_ability_t *ability, soc_port_mode_t *mode) 91 { 92 uint32 port_abil; 93 soc_port_mode_t port_mode; 94 95 if ((NULL == ability) || (NULL == mode)) { 96 return (SOC_E_PARAM); 97 } 98 99 port_mode = 0; 100 101 /* Half duplex speeds */ 102 port_abil = ability->speed_half_duplex; 103 port_mode |= (port_abil & SOC_PA_SPEED_10MB) ? SOC_PM_10MB_HD : 0; 104 port_mode |= (port_abil & SOC_PA_SPEED_100MB) ? SOC_PM_100MB_HD : 0; 105 port_mode |= (port_abil & SOC_PA_SPEED_1000MB) ? SOC_PM_1000MB_HD : 0; 106 port_mode |= (port_abil & SOC_PA_SPEED_2500MB) ? SOC_PM_2500MB_HD : 0; 107 port_mode |= (port_abil & SOC_PA_SPEED_3000MB) ? SOC_PM_3000MB_HD : 0; 108 port_mode |= (port_abil & SOC_PA_SPEED_10GB) ? SOC_PM_10GB_HD : 0; 109 port_mode |= (port_abil & SOC_PA_SPEED_12GB) ? SOC_PM_12GB_HD : 0; 110 port_mode |= (port_abil & SOC_PA_SPEED_13GB) ? SOC_PM_13GB_HD : 0; 111 port_mode |= (port_abil & SOC_PA_SPEED_16GB) ? SOC_PM_16GB_HD : 0; 112 113 /* Full duplex speeds */ 114 port_abil = ability->speed_full_duplex; 115 port_mode |= (port_abil & SOC_PA_SPEED_10MB) ? SOC_PM_10MB_FD : 0; 116 port_mode |= (port_abil & SOC_PA_SPEED_100MB) ? SOC_PM_100MB_FD : 0; 117 port_mode |= (port_abil & SOC_PA_SPEED_1000MB) ? SOC_PM_1000MB_FD : 0; 118 port_mode |= (port_abil & SOC_PA_SPEED_2500MB) ? SOC_PM_2500MB_FD : 0; 119 port_mode |= (port_abil & SOC_PA_SPEED_3000MB) ? SOC_PM_3000MB_FD : 0; 120 port_mode |= (port_abil & SOC_PA_SPEED_10GB) ? SOC_PM_10GB_FD : 0; 121 port_mode |= (port_abil & SOC_PA_SPEED_12GB) ? SOC_PM_12GB_FD : 0; 122 port_mode |= (port_abil & SOC_PA_SPEED_13GB) ? SOC_PM_13GB_FD : 0; 123 port_mode |= (port_abil & SOC_PA_SPEED_16GB) ? SOC_PM_16GB_FD : 0; 124 125 /* Pause Modes */ 126 port_abil = ability->pause; 127 port_mode |= (port_abil & SOC_PA_PAUSE_TX)? SOC_PM_PAUSE_TX : 0; 128 port_mode |= (port_abil & SOC_PA_PAUSE_RX) ? SOC_PM_PAUSE_RX : 0; 129 port_mode |= (port_abil & SOC_PA_PAUSE_ASYMM) ? SOC_PM_PAUSE_ASYMM : 0; 130 131 /* Interface Types */ 132 port_abil = ability->interface; 133 port_mode |= (port_abil & SOC_PA_INTF_TBI) ? SOC_PM_TBI : 0; 134 port_mode |= (port_abil & SOC_PA_INTF_MII) ? SOC_PM_MII : 0; 135 port_mode |= (port_abil & SOC_PA_INTF_GMII) ? SOC_PM_GMII : 0; 136 port_mode |= (port_abil & SOC_PA_INTF_SGMII) ? SOC_PM_SGMII : 0; 137 port_mode |= (port_abil & SOC_PA_INTF_XGMII) ? SOC_PM_XGMII : 0; 138 139 /* Loopback port_abil */ 140 port_abil = ability->loopback; 141 port_mode |= (port_abil & SOC_PA_LB_MAC) ? SOC_PM_LB_MAC : 0; 142 port_mode |= (port_abil & SOC_PA_LB_PHY) ? SOC_PM_LB_PHY : 0; 143 port_mode |= (port_abil & SOC_PA_LB_NONE) ? SOC_PM_LB_NONE : 0; 144 145 /* Remaining Flags */ 146 port_abil = ability->flags; 147 port_mode |= (port_abil & SOC_PA_AUTONEG) ? SOC_PM_AN : 0; 148 port_mode |= (port_abil & SOC_PA_COMBO) ? SOC_PM_COMBO : 0; 149 150 *mode = port_mode; 151 return (SOC_E_NONE); 152 } 153 154 int 155 soc_port_phy_pll_os_set(int unit, soc_port_t port, uint32 vco_freq, uint32 oversample_mode, uint32 pll_divider) 156 { 157 if(!SOC_PORT_VALID(unit, port)) { 158 return SOC_E_PORT; 159 } 160 161 #if defined(PORTMOD_SUPPORT) && defined(BCM_ESW_SUPPORT) 162 if (SOC_USE_PORTCTRL(unit)) { 163 SOC_IF_ERROR_RETURN(soc_portctrl_phy_control_set(unit, port, -1, -1, 0, 164 SOC_PHY_CONTROL_VCO_FREQ, vco_freq)); 165 SOC_IF_ERROR_RETURN(soc_portctrl_phy_control_set(unit, port, -1, -1, 0, 166 SOC_PHY_CONTROL_OVERSAMPLE_MODE, oversample_mode)); 167 SOC_IF_ERROR_RETURN(soc_portctrl_phy_control_set(unit, port, -1, -1, 0, 168 SOC_PHY_CONTROL_PLL_DIVIDER, pll_divider)); 169 /* Programming of SOC_PHY_NON_CANNED_SPEED is not supported for new chips. 170 * Only Warpcore and fe1600 use it. So we do not program speed. If any 171 * future device needs it, speed should be programmed here. 172 */ 173 } else 174 #endif /* PORTMOD_SUPPORT */ 175 { 176 SOC_IF_ERROR_RETURN(soc_phyctrl_control_set(unit, port, 177 SOC_PHY_CONTROL_VCO_FREQ, vco_freq)); 178 SOC_IF_ERROR_RETURN(soc_phyctrl_control_set(unit, port, 179 SOC_PHY_CONTROL_OVERSAMPLE_MODE, oversample_mode)); 180 SOC_IF_ERROR_RETURN(soc_phyctrl_control_set(unit, port, 181 SOC_PHY_CONTROL_PLL_DIVIDER, pll_divider)); 182 SOC_IF_ERROR_RETURN(soc_phyctrl_speed_set(unit, port, 183 SOC_PHY_NON_CANNED_SPEED)); 184 } 185 186 return SOC_E_NONE; 187 } 188 189 190 int 191 soc_port_ability_mask(soc_port_ability_t *ability, soc_port_ability_t *mask) 192 { 193 if (ability == NULL || mask == NULL) { 194 return SOC_E_PARAM; 195 } 196 197 ability->flags &= mask->flags; 198 ability->loopback &= mask->loopback; 199 ability->medium &= mask->medium; 200 ability->eee &= mask->eee; 201 ability->pause &= mask->pause; 202 ability->speed_full_duplex &= mask->speed_full_duplex; 203 ability->speed_half_duplex &= mask->speed_half_duplex; 204 ability->interface &= mask->interface; 205 ability->channel &= mask->channel; 206 ability->fec &= mask->fec; 207 208 return SOC_E_NONE; 209 } 210 211 /* 212 * Function: 213 * soc_port_speed_higig2eth 214 * Purpose: 215 * Convert Higig speed into related Ethernet speed 216 * 217 * Parameters: 218 * speed - (IN) Higig speed (Mbps). 219 * Returns: 220 * Ethernet Speed 221 * Note: 222 */ 223 int 224 soc_port_speed_higig2eth(int speed) 225 { 226 switch (speed) { 227 case 11000: 228 /* 10G */ 229 return 10000; 230 case 21000: 231 /* 20G */ 232 return 20000; 233 case 27000: 234 /* 25G */ 235 return 25000; 236 case 42000: 237 /* 40G */ 238 return 40000; 239 case 53000: 240 /* 50G */ 241 return 50000; 242 case 106000: 243 /* 100G */ 244 return 100000; 245 default: 246 return speed; 247 } 248 } 249 250 /* 251 * Function: 252 * soc_port_speed_to_mask 253 * Purpose: 254 * Convert speed into bitmap mask 255 * 256 * Parameters: 257 * unit - (IN) Unit number. 258 * speed - (IN) Higig speed (Mbps). 259 * speed_mask - (OUT) bitmap for speed. 260 * is_hg_speed - (OUT) 1: Indicate Higig speed 261 * Returns: 262 * SOC_E_X 263 * Note: 264 */ 265 int 266 soc_port_speed_to_mask(int unit, int speed, uint32 *speed_mask, 267 int *is_hg_speed) 268 { 269 int is_hg = 0; 270 271 switch (speed) { 272 case 1000: 273 *speed_mask = SOC_PA_SPEED_1000MB; 274 break; 275 case 2500: 276 *speed_mask = SOC_PA_SPEED_2500MB; 277 break; 278 case 10000: 279 *speed_mask = SOC_PA_SPEED_10GB; 280 break; 281 case 11000: 282 *speed_mask = SOC_PA_SPEED_11GB; 283 is_hg = 1; 284 break; 285 case 20000: 286 *speed_mask = SOC_PA_SPEED_20GB; 287 break; 288 case 21000: 289 *speed_mask = SOC_PA_SPEED_21GB; 290 is_hg = 1; 291 break; 292 case 25000: 293 *speed_mask = SOC_PA_SPEED_25GB; 294 break; 295 case 27000: 296 *speed_mask = SOC_PA_SPEED_27GB; 297 is_hg = 1; 298 break; 299 case 40000: 300 *speed_mask = SOC_PA_SPEED_40GB; 301 break; 302 case 42000: 303 *speed_mask = SOC_PA_SPEED_42GB; 304 is_hg = 1; 305 break; 306 case 50000: 307 *speed_mask = SOC_PA_SPEED_50GB; 308 break; 309 case 53000: 310 *speed_mask = SOC_PA_SPEED_53GB; 311 is_hg = 1; 312 break; 313 case 100000: 314 *speed_mask = SOC_PA_SPEED_100GB; 315 break; 316 case 106000: 317 *speed_mask = SOC_PA_SPEED_106GB; 318 is_hg = 1; 319 break; 320 case 120000: 321 *speed_mask = SOC_PA_SPEED_120GB; 322 break; 323 case 127000: 324 *speed_mask = SOC_PA_SPEED_127GB; 325 is_hg = 1; 326 break; 327 default: 328 *speed_mask = 0; 329 LOG_ERROR(BSL_LS_SOC_PORT, 330 (BSL_META_U(unit, 331 "Invalid speed %d\n"), 332 speed)); 333 return SOC_E_PARAM; 334 } 335 336 if (is_hg_speed != NULL) { 337 *is_hg_speed = is_hg; 338 } 339 340 return SOC_E_NONE; 341 } 342 343 /* 344 * Function: 345 * soc_port_sister_validate 346 * Purpose: 347 * Check all configured sister ports: 348 * 1. has same oversub mode 349 * 2. has same speed in oversub mode 350 * Parameters: 351 * unit - (IN) Unit number. 352 * pm_port_num - (IN) Port number per Port Macro. 353 * Returns: 354 * SOC_E_XXX 355 * Note: 356 * This function is called at early stage of initialization for 357 * port configuration check. 358 */ 359 int 360 soc_port_sister_validate(int unit, uint32 pm_port_num) 361 { 362 int encap, speed, sister_speed, ovs, sister_ovs, lport, blk; 363 int phy_port, mixed_sister_25_50_en; 364 uint32 speed_mask, mix_speed_mask, pm_mixed_pbm, pm_used_pbm; 365 soc_pbmp_t pbmp_mixed_sister_25_50; 366 soc_info_t *si = &SOC_INFO(unit); 367 368 pbmp_mixed_sister_25_50 = soc_property_get_pbmp( 369 unit, spn_PBMP_OVERSUBSCRIBE_MIXED_SISTER_25_50_INIT, 0); 370 mixed_sister_25_50_en = si->os_mixed_sister_25_50_enable; 371 if (SOC_PBMP_NOT_NULL(pbmp_mixed_sister_25_50) 372 && (!mixed_sister_25_50_en)) { 373 LOG_ERROR(BSL_LS_SOC_PORT, 374 (BSL_META_U(unit, 375 "pbmp_oversubscribe_mixed_sister_25_50_init " 376 "shouldn't be defined as " 377 "oversubscribe_mixed_sister_25_50_enable " 378 "is not enabled!\n"))); 379 return SOC_E_CONFIG; 380 } 381 mix_speed_mask = SOC_PA_SPEED_50GB | SOC_PA_SPEED_25GB; 382 383 for (blk = 0; blk < SOC_MAX_NUM_BLKS; blk++) { 384 if (SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_CLPORT || 385 SOC_BLOCK_TYPE(unit, blk) == SOC_BLK_XLPORT) { 386 encap = SOC_ENCAP_COUNT; 387 speed = 0; 388 sister_speed = 0; 389 ovs = 0; 390 sister_ovs = 0; 391 speed_mask = 0; 392 pm_mixed_pbm = 0; 393 pm_used_pbm = 0; 394 SOC_PBMP_ITER(si->block_bitmap[blk], lport) { 395 if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, lport)) { 396 continue; 397 } 398 if (encap == SOC_ENCAP_COUNT) { 399 /* Encap and Speed of first port in one block */ 400 encap = IS_HG_PORT(unit, lport) ? 401 SOC_ENCAP_HIGIG2 : SOC_ENCAP_IEEE; 402 speed = si->port_speed_max[lport]; 403 if (speed == 1000) { 404 speed = 10000; 405 } 406 ovs = SOC_PBMP_MEMBER(si->oversub_pbm, lport) ? 1 : 0; 407 } 408 /* Speed of sister port in one block */ 409 sister_speed = si->port_speed_max[lport]; 410 if (sister_speed == 1000) { 411 sister_speed = 10000; 412 } 413 sister_ovs = SOC_PBMP_MEMBER(si->oversub_pbm, lport) ? 1 : 0; 414 if (sister_ovs && mixed_sister_25_50_en) { 415 speed_mask |= 416 SOC_PA_SPEED(soc_port_speed_higig2eth(sister_speed)); 417 phy_port = si->port_l2p_mapping[lport]; 418 pm_used_pbm |= 1 << ((phy_port - 1) % pm_port_num); 419 if ( SOC_PBMP_MEMBER(pbmp_mixed_sister_25_50, lport)) { 420 if (SOC_PA_SPEED(soc_port_speed_higig2eth(sister_speed)) 421 & SOC_PA_SPEED_25GB){ 422 pm_mixed_pbm |= 1 << ((phy_port - 1) % pm_port_num); 423 } else { 424 LOG_ERROR(BSL_LS_SOC_PORT, 425 (BSL_META_U(unit, 426 "Only 25G port can appear in " 427 "pbmp_oversubscribe_mixed_sister_25_50_init, " 428 "port %d with speed %d can't " 429 "appear in " 430 "pbmp_oversubscribe_mixed_sister_25_50_init!\n"), 431 lport, sister_speed)); 432 return SOC_E_CONFIG; 433 } 434 } 435 } 436 437 if (ovs != sister_ovs) { 438 LOG_ERROR(BSL_LS_SOC_PORT, 439 (BSL_META_U(unit, 440 "Mixed port oversub mode is not " 441 "acceptable on port macro %d\n"), 442 SOC_BLOCK_NUMBER(unit, blk))); 443 return SOC_E_CONFIG; 444 } 445 446 if (ovs && speed != sister_speed) { 447 /* Support 25G/50G mix sister speeds in a PM. 448 * Only include 25G and 50G speeds. 449 */ 450 if (mixed_sister_25_50_en && 451 (!(speed_mask & (~mix_speed_mask)))) { 452 continue; 453 } else { 454 LOG_ERROR(BSL_LS_SOC_PORT, 455 (BSL_META_U(unit, 456 "Mixed port speed is not acceptable " 457 "in oversub mode on port macro %d\n"), 458 SOC_BLOCK_NUMBER(unit, blk))); 459 return SOC_E_CONFIG; 460 } 461 } 462 } 463 if (ovs && mixed_sister_25_50_en) { 464 if (pm_mixed_pbm && (pm_used_pbm & 0xa)){ 465 LOG_ERROR(BSL_LS_SOC_PORT, 466 (BSL_META_U(unit, 467 "Mixed port speed configuration is wrong " 468 "on port macro %d!\n Either more than 2 " 469 "ports in this port macro or single lane " 470 "ports on 2/4th lane!\n"), 471 SOC_BLOCK_NUMBER(unit, blk))); 472 return SOC_E_CONFIG; 473 } else if (!pm_mixed_pbm && (speed_mask == mix_speed_mask) && 474 !SOC_WARM_BOOT(unit)){ 475 LOG_ERROR(BSL_LS_SOC_PORT, 476 (BSL_META_U(unit, 477 "Mixed port speed bitmap not set on " 478 "25G ports of port macro %d!\n"), 479 SOC_BLOCK_NUMBER(unit, blk))); 480 return SOC_E_CONFIG; 481 } 482 } 483 } 484 } 485 return SOC_E_NONE; 486 } 487 488 /* 489 * Function: 490 * soc_port_speed_encap_validate 491 * Purpose: 492 * Check speed and encap mode 493 * - HG speed with IEEE encap mode is not supported. 494 * Parameters: 495 * unit - (IN) Unit number. 496 * Returns: 497 * SOC_E_XXX 498 * Note: 499 * This function is called at early stage of initialization for 500 * port configuration check. 501 */ 502 int 503 soc_port_speed_encap_validate(int unit) 504 { 505 soc_info_t *si = &SOC_INFO(unit); 506 int port, speed_mask; 507 508 PBMP_PORT_ITER(unit, port) { 509 if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) { 510 continue; 511 } 512 speed_mask = SOC_PA_SPEED(si->port_speed_max[port]); 513 if (SOC_PA_IS_HG_SPEED(speed_mask) && !IS_HG_PORT(unit, port)) { 514 LOG_ERROR(BSL_LS_BCM_COMMON, 515 (BSL_META_U(unit, 516 "Unmatched speed and encapsulation " 517 "configuration for port=%d\n"), 518 port)); 519 return SOC_E_CONFIG; 520 } 521 } 522 523 return SOC_E_NONE; 524 }