bigmac.c (87933B)
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 * XGS 10Gigabit Media Access Controller Driver (bigmac) 8 * This file is renamed from xmac.c. 9 * 10 * This module is used for: 11 * 12 * - All ports on XGS Hercules family (10Gig x 8) 13 */ 14 15 #include <shared/bsl.h> 16 17 #include <sal/core/libc.h> 18 #include <shared/alloc.h> 19 #include <sal/core/spl.h> 20 #include <sal/core/boot.h> 21 22 #include <soc/drv.h> 23 #include <soc/error.h> 24 #include <soc/cmic.h> 25 #include <soc/portmode.h> 26 #include <soc/ll.h> 27 #include <soc/counter.h> 28 #include <soc/macutil.h> 29 #include <soc/phyctrl.h> 30 31 #ifdef BCM_BIGMAC_SUPPORT 32 33 /* 34 * BigMAC Register field definitions. 35 */ 36 37 /* Transmit CRC Modes (Receive has bit field definitions in register) */ 38 #define BIGMAC_CRC_APPEND 0x00 /* Append CRC (Default) */ 39 #define BIGMAC_CRC_KEEP 0x01 /* CRC Assumed correct */ 40 #define BIGMAC_CRC_REGEN 0x02 /* Replace CRC with a new one */ 41 #define BIGMAC_CRC_RSVP 0x03 /* Reserved (does Replace) */ 42 43 #define JUMBO_MAXSZ 0x3fe8 /* Max legal value (per regsfile) */ 44 45 /* speed to SOC_PA_SPEED flags mapping table, need to be in ascending order */ 46 struct { 47 int speed; 48 int pa_flag; 49 } mac_big_hg_speed_list[] = { 50 { 10000, SOC_PA_SPEED_10GB }, 51 { 12000, SOC_PA_SPEED_12GB }, 52 { 13000, SOC_PA_SPEED_13GB }, 53 { 16000, SOC_PA_SPEED_16GB }, 54 { 20000, SOC_PA_SPEED_20GB }, 55 { 21000, SOC_PA_SPEED_21GB }, 56 { 24000, SOC_PA_SPEED_24GB }, 57 { 25000, SOC_PA_SPEED_25GB }, 58 }; 59 60 #ifdef BROADCOM_DEBUG 61 static char *mac_big_encap_mode[] = SOC_ENCAP_MODE_NAMES_INITIALIZER; 62 static char *mac_big_port_if_names[] = SOC_PORT_IF_NAMES_INITIALIZER; 63 #endif /* BROADCOM_DEBUG */ 64 65 #if defined(BCM_XGS3_SWITCH_SUPPORT) 66 /* 67 * Returns the field in CMIC_XGXS_PLL_CONTROL_1 corresponding to 68 * a Higig port on XGS3 device 69 */ 70 static int 71 _port2pllf(int unit, soc_port_t port) 72 { 73 if (SOC_IS_FB_FX_HX(unit)) { 74 switch(port) { 75 case 24: return PLL_CONTROL_13f; 76 case 25: return PLL_CONTROL_12f; 77 case 26: return PLL_CONTROL_11f; 78 case 27: return PLL_CONTROL_10f; 79 default: return INVALIDf; 80 } 81 } 82 83 return INVALIDf; 84 } 85 86 #if defined(BCM_HELIX15_SUPPORT) || defined(BCM_FELIX15_SUPPORT) || \ 87 defined(BCM_FIREBOLT2_SUPPORT) 88 /* 89 * Check if specified speed is supported. 90 */ 91 static int 92 _mac_big_speed_support_check(int unit, soc_port_t port, int speed) 93 { 94 if (IS_LMD_ENABLED_PORT(unit, port)) { 95 if ((speed != 2500) && (speed != 3000) && (speed != 0)) { 96 return SOC_E_PARAM; 97 } 98 } else { 99 if ((speed != 10000) && (speed != 12000) && (speed != 0)) { 100 return SOC_E_PARAM; 101 } 102 } 103 104 return SOC_E_NONE; 105 } 106 107 #endif /* BCM_HELIX15_SUPPORT || BCM_FELIX15_SUPPORT || \ 108 BCM_FIREBOLT2_SUPPORT */ 109 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 110 111 void 112 _mac_big_speed_to_pa_flag(int unit, soc_port_t port, int speed, 113 uint32 *pa_flag) 114 { 115 *pa_flag = 0; 116 if (soc_feature(unit, soc_feature_xgxs_lcpll)) { 117 if (IS_LMD_ENABLED_PORT(unit, port)) { 118 if (speed == 2500) { 119 *pa_flag = SOC_PA_SPEED_2500MB; 120 } else if (speed == 3000) { 121 *pa_flag = SOC_PA_SPEED_3000MB; 122 } 123 } else { 124 if (speed == 10000) { 125 *pa_flag = SOC_PA_SPEED_10GB; 126 } else if (speed == 12000) { 127 *pa_flag = SOC_PA_SPEED_12GB; 128 } 129 } 130 } else { 131 *pa_flag = SOC_PA_SPEED(speed); 132 } 133 } 134 135 /* 136 * Function: 137 * _mac_big_drain_cells 138 * Purpose: 139 * Wait until MMU cell count reaches zero for a specified port. 140 * Parameters: 141 * unit - StrataSwitch unit #. 142 * port - Port number being examined. 143 * Returns: 144 * SOC_E_XXX 145 * Notes: 146 * Keeps polling as long as LCCCOUNT/GCCCOUNT is decrementing. 147 * If LCCCOUNT/GCCCOUNT stops decrementing without reaching zero, 148 * after a timeout period a warning message is printed 149 * and it gives up. 150 * 151 * Before calling this routine, make sure no packets are switching 152 * to the port or it might never finish draining. 153 */ 154 155 STATIC int 156 _mac_big_drain_cells(int unit, soc_port_t port) 157 { 158 int rv; 159 uint64 tx_ctrl; 160 int pause_tx, pause_rx; 161 #if defined(BCM_HURRICANE1_SUPPORT) 162 int pfc_en_rx; 163 #endif 164 165 rv = SOC_E_NONE; 166 167 if (SOC_IS_RELOADING(unit)) { 168 return rv; 169 } 170 171 /* Disable pause function */ 172 SOC_IF_ERROR_RETURN 173 (soc_mac_big.md_pause_get(unit, port, &pause_tx, &pause_rx)); 174 #if defined(BCM_HURRICANE1_SUPPORT) 175 if (SOC_IS_HURRICANE(unit)) { 176 SOC_IF_ERROR_RETURN 177 (soc_mac_big.md_control_get(unit, port, 178 SOC_MAC_CONTROL_PFC_RX_ENABLE, &pfc_en_rx)); 179 } 180 #endif 181 182 SOC_IF_ERROR_RETURN(soc_mac_big.md_pause_set(unit, port, 0, 0)); 183 #if defined(BCM_HURRICANE1_SUPPORT) 184 if (SOC_IS_HURRICANE(unit)) { 185 SOC_IF_ERROR_RETURN 186 (soc_mac_big.md_control_set(unit, port, 187 SOC_MAC_CONTROL_PFC_RX_ENABLE, 0)); 188 } 189 #endif 190 191 LOG_VERBOSE(BSL_LS_SOC_COMMON, 192 (BSL_META_U(unit, 193 "port %d bigmac saved pause and pfc state\n"), port)); 194 195 /* Notify PHY driver */ 196 SOC_IF_ERROR_RETURN 197 (soc_phyctrl_notify(unit, port, 198 phyEventStop, PHY_STOP_DRAIN)); 199 200 /* First put the port in flush state */ 201 SOC_IF_ERROR_RETURN(soc_mmu_flush_enable(unit, port, TRUE)); 202 LOG_VERBOSE(BSL_LS_SOC_COMMON, 203 (BSL_META_U(unit, 204 "port %d bigmac mmu flush enable completed\n"), port)); 205 /* Disable switch egress metering so that packet draining is not rate 206 * limited. 207 */ 208 rv = soc_egress_drain_cells(unit, port, 250000); 209 if (SOC_E_NONE == rv) { 210 LOG_VERBOSE(BSL_LS_SOC_COMMON, 211 (BSL_META_U(unit, 212 "port %d bigmac egress packet draining completed\n"), 213 port)); 214 } 215 216 /* Notify PHY driver */ 217 SOC_IF_ERROR_RETURN 218 (soc_phyctrl_notify(unit, port, phyEventResume, PHY_STOP_DRAIN)); 219 220 /* Toggle the Tx Fifo reset to erase any packets left in the 221 * BigMAC buffer. */ 222 if (soc_reg_field_valid(unit, MAC_TXCTRLr, TXFIFO_RESETf)) { 223 SOC_IF_ERROR_RETURN 224 (soc_reg_field32_modify(unit, MAC_TXCTRLr, port, 225 TXFIFO_RESETf, 1)); 226 SOC_IF_ERROR_RETURN 227 (soc_reg_field32_modify(unit, MAC_TXCTRLr, port, 228 TXFIFO_RESETf, 0)); 229 } 230 LOG_VERBOSE(BSL_LS_SOC_COMMON, 231 (BSL_META_U(unit, 232 "port %d bigmac TX fifo reset completed\n"), port)); 233 /* Restore original pause configuration */ 234 SOC_IF_ERROR_RETURN 235 (soc_mac_big.md_pause_set(unit, port, pause_tx, pause_rx)); 236 #if defined(BCM_HURRICANE1_SUPPORT) 237 if (SOC_IS_HURRICANE(unit)) { 238 SOC_IF_ERROR_RETURN 239 (soc_mac_big.md_control_set(unit, port, 240 SOC_MAC_CONTROL_PFC_RX_ENABLE, pfc_en_rx)); 241 } 242 #endif 243 LOG_VERBOSE(BSL_LS_SOC_COMMON, 244 (BSL_META_U(unit, 245 "port %d bigmac restored pause and pfc state\n"), port)); 246 /* Bring the switch MMU out of flush */ 247 SOC_IF_ERROR_RETURN(soc_mmu_flush_enable(unit, port, FALSE)); 248 LOG_VERBOSE(BSL_LS_SOC_COMMON, 249 (BSL_META_U(unit, 250 "port %d bigmac mmu flush disabled\n"), port)); 251 SOC_IF_ERROR_RETURN(READ_MAC_TXCTRLr(unit, port, &tx_ctrl)); 252 253 return rv; 254 } 255 256 /* 257 * Function: 258 * mac_big_enable_set 259 * Purpose: 260 * Enable or disable MAC 261 * Parameters: 262 * unit - XGS unit #. 263 * port - Port number on unit. 264 * enable - TRUE to enable, FALSE to disable 265 * Returns: 266 * SOC_E_XXX 267 */ 268 STATIC int 269 mac_big_enable_set(int unit, soc_port_t port, int enable) 270 { 271 uint64 ctrl, octrl; 272 pbmp_t mask; 273 274 LOG_VERBOSE(BSL_LS_SOC_10G, 275 (BSL_META_U(unit, 276 "mac_big_enable_set: unit %d port %s enable=%s\n"), 277 unit, SOC_PORT_NAME(unit, port), 278 enable ? "True" : "False")); 279 280 SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, &ctrl)); 281 octrl = ctrl; 282 /* Don't disable TX since it stops egress and hangs if CPU sends */ 283 soc_reg64_field32_set(unit, MAC_CTRLr, &ctrl, TXENf, 1); 284 soc_reg64_field32_set(unit, MAC_CTRLr, &ctrl, RXENf, enable ? 1 : 0); 285 if (COMPILER_64_NE(ctrl, octrl)) { 286 #if defined(BCM_SCORPION_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) 287 if (enable && soc_feature(unit, soc_feature_priority_flow_control)) { 288 /* Flush MMU XOFF state with toggle bit before turning on RX */ 289 if (SOC_REG_IS_VALID(unit, BMAC_PFC_CTRLr)) { 290 SOC_IF_ERROR_RETURN 291 (soc_reg_field32_modify(unit, BMAC_PFC_CTRLr, port, 292 FORCE_PFC_XONf, 1)); 293 SOC_IF_ERROR_RETURN 294 (soc_reg_field32_modify(unit, BMAC_PFC_CTRLr, port, 295 FORCE_PFC_XONf, 0)); 296 } else { 297 SOC_IF_ERROR_RETURN 298 (soc_reg_field32_modify(unit, MAC_PFC_CTRLr, port, 299 FORCE_PP_XONf, 1)); 300 SOC_IF_ERROR_RETURN 301 (soc_reg_field32_modify(unit, MAC_PFC_CTRLr, port, 302 FORCE_PP_XONf, 0)); 303 } 304 } 305 #endif /* BCM_SCORPION_SUPPORT || BCM_TRIUMPH2_SUPPORT */ 306 307 SOC_IF_ERROR_RETURN(WRITE_MAC_CTRLr(unit, port, ctrl)); 308 } 309 310 if (enable) { 311 soc_link_mask2_get(unit, &mask); 312 SOC_PBMP_PORT_ADD(mask, port); 313 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 314 } else { 315 soc_link_mask2_get(unit, &mask); 316 SOC_PBMP_PORT_REMOVE(mask, port); 317 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 318 SOC_IF_ERROR_RETURN(_mac_big_drain_cells(unit, port)); 319 } 320 321 return SOC_E_NONE; 322 } 323 324 /* This routine should go into xgxs1.c:phy_xgxs1_init and be invoked by 325 * calling soc_phyctrl_init */ 326 int 327 _fusioncore_phy_xgxs1_init(int unit, soc_port_t port) 328 { 329 uint8 phy_addr; 330 uint64 xgxs_stat; 331 int preemph, idriver, pdriver; 332 int plllock, phyrev; 333 int pll_lock_usec; 334 int locked; 335 soc_timeout_t to; 336 337 if (SOC_WARM_BOOT(unit) || SOC_IS_RELOADING(unit)){ 338 return SOC_E_NONE; 339 } 340 341 if (soc_feature(unit, soc_feature_xgxs_v1)) { 342 phyrev = 1; 343 } else if (soc_feature(unit, soc_feature_xgxs_v2)) { 344 phyrev = 2; 345 } else if (soc_feature(unit, soc_feature_xgxs_v3)) { 346 phyrev = 3; 347 } else if (soc_feature(unit, soc_feature_xgxs_v4)) { 348 phyrev = 4; 349 } else { 350 return SOC_E_NONE; 351 } 352 353 /* 354 * Allow properties to change important variables. 355 */ 356 357 plllock = soc_property_port_get(unit, port, spn_XGXS_PLLLOCK, 0x7); 358 /* NB: preemphasis, driver, pre-driver currents are bit-reversed in HW */ 359 preemph = soc_property_port_get(unit, port, spn_XGXS_PREEMPHASIS, 360 (phyrev > 2) ? 0 : 0x8); 361 preemph = _shr_bit_rev8(preemph) >> 4; 362 363 idriver = soc_property_port_get(unit, port, 364 spn_XGXS_DRIVER_CURRENT, 0xb); 365 idriver = _shr_bit_rev8(idriver) >> 4; 366 367 pdriver = soc_property_port_get(unit, port, 368 spn_XGXS_PRE_DRIVER_CURRENT, 0xb); 369 pdriver = _shr_bit_rev8(pdriver) >> 4; 370 371 phy_addr = PORT_TO_PHY_ADDR_INT(unit, port); 372 pll_lock_usec = 500000; 373 374 if (phyrev == 1) { 375 SOC_IF_ERROR_RETURN /* Select block 0x5 */ 376 (soc_miim_write(unit, phy_addr, 0x1f, 0x0050)); 377 SOC_IF_ERROR_RETURN /* PLL range select bypass */ 378 (soc_miim_write(unit, phy_addr, 0x11, 0x500e)); 379 380 SOC_IF_ERROR_RETURN /* PLL lock range */ 381 (soc_miim_write(unit, phy_addr, 0x15, 0x2e00 | (plllock & 0xf))); 382 SOC_IF_ERROR_RETURN /* PLL clock divider bias */ 383 (soc_miim_write(unit, phy_addr, 0x1b, 0x0001)); 384 SOC_IF_ERROR_RETURN /* ? */ 385 (soc_miim_write(unit, phy_addr, 0x1c, 0x0019)); 386 SOC_IF_ERROR_RETURN /* PLL bias */ 387 (soc_miim_write(unit, phy_addr, 0x1d, 0x1005)); 388 389 SOC_IF_ERROR_RETURN /* Select block 0xa */ 390 (soc_miim_write(unit, phy_addr, 0x1f, 0x00a0)); 391 SOC_IF_ERROR_RETURN /* TX pre-emphasis */ 392 (soc_miim_write(unit, phy_addr, 0x17, ((preemph & 0xf) << 12) 393 | ((idriver & 0xf) << 8) | ((pdriver & 0xf) << 4))); 394 /* Retain this for Herc A0, but not later Phys */ 395 SOC_IF_ERROR_RETURN /* Select block 0xf */ 396 (soc_miim_write(unit, phy_addr, 0x1f, 0x00f0)); 397 SOC_IF_ERROR_RETURN /* RX loop bandwidth */ 398 (soc_miim_write(unit, phy_addr, 0x16, 0x7300)); 399 SOC_IF_ERROR_RETURN /* RX integration mode */ 400 (soc_miim_write(unit, phy_addr, 0x19, 0x0110)); 401 402 SOC_IF_ERROR_RETURN /* Select block 0x5 */ 403 (soc_miim_write(unit, phy_addr, 0x1f, 0x0050)); 404 SOC_IF_ERROR_RETURN /* Turn on PLL state machine */ 405 (soc_miim_write(unit, phy_addr, 0x11, 0xd00e)); 406 407 SOC_IF_ERROR_RETURN /* Select block 0x0 */ 408 (soc_miim_write(unit, phy_addr, 0x1f, 0x0000)); 409 } else if (phyrev == 2) { 410 uint16 plldiv = (SOC_IS_HERCULES15(unit) ? 0x0000 : 0x6c33); 411 412 SOC_IF_ERROR_RETURN /* Select block 0x5 */ 413 (soc_miim_write(unit, phy_addr, 0x1f, 0x0050)); 414 SOC_IF_ERROR_RETURN /* PLL range select bypass */ 415 (soc_miim_write(unit, phy_addr, 0x11, 0x500e)); 416 417 SOC_IF_ERROR_RETURN /* Increase PLL clock divider bias */ 418 (soc_miim_write(unit, phy_addr, 0x1a, plldiv)); 419 SOC_IF_ERROR_RETURN /* Decrease VCO bias */ 420 (soc_miim_write(unit, phy_addr, 0x1d, 0x1028)); 421 422 SOC_IF_ERROR_RETURN /* Select block 0xa */ 423 (soc_miim_write(unit, phy_addr, 0x1f, 0x00a0)); 424 SOC_IF_ERROR_RETURN /* TX pre-emphasis */ 425 (soc_miim_write(unit, phy_addr, 0x17, ((preemph & 0xf) << 12) 426 | ((idriver & 0xf) << 8) | ((pdriver & 0xf) << 4))); 427 SOC_IF_ERROR_RETURN /* Select block 0x5 */ 428 (soc_miim_write(unit, phy_addr, 0x1f, 0x0050)); 429 SOC_IF_ERROR_RETURN /* Turn on PLL state machine */ 430 (soc_miim_write(unit, phy_addr, 0x11, 0xd00e)); 431 432 SOC_IF_ERROR_RETURN /* Select block 0x0 */ 433 (soc_miim_write(unit, phy_addr, 0x1f, 0x0000)); 434 } else if (phyrev == 3) { 435 SOC_IF_ERROR_RETURN /* Select block 0x5 */ 436 (soc_miim_write(unit, phy_addr, 0x1f, 0x0050)); 437 SOC_IF_ERROR_RETURN /* PLL range select bypass */ 438 (soc_miim_write(unit, phy_addr, 0x11, 0x500e)); 439 SOC_IF_ERROR_RETURN /* Enable PLL tuning */ 440 (soc_miim_write(unit, phy_addr, 0x1c, 0x0019)); 441 442 SOC_IF_ERROR_RETURN /* Select block 0xf */ 443 (soc_miim_write(unit, phy_addr, 0x1f, 0x00f0)); 444 SOC_IF_ERROR_RETURN /* Increase RX loop bandwidth */ 445 (soc_miim_write(unit, phy_addr, 0x16, 0x7300)); 446 SOC_IF_ERROR_RETURN /* Clear RX integration mode */ 447 (soc_miim_write(unit, phy_addr, 0x19, 0x0900)); 448 449 SOC_IF_ERROR_RETURN /* Select block 0x5 */ 450 (soc_miim_write(unit, phy_addr, 0x1f, 0x0050)); 451 SOC_IF_ERROR_RETURN /* Turn on PLL state machine */ 452 (soc_miim_write(unit, phy_addr, 0x11, 0xd00e)); 453 454 SOC_IF_ERROR_RETURN /* Select block 0xa */ 455 (soc_miim_write(unit, phy_addr, 0x1f, 0x00a0)); 456 SOC_IF_ERROR_RETURN /* TX pre-emphasis */ 457 (soc_miim_write(unit, phy_addr, 0x17, ((preemph & 0xf) << 12) 458 | ((idriver & 0xf) << 8) | ((pdriver & 0xf) << 4))); 459 460 SOC_IF_ERROR_RETURN /* Select block 0x0 */ 461 (soc_miim_write(unit, phy_addr, 0x1f, 0x0000)); 462 SOC_IF_ERROR_RETURN /* Set TX clk to 1/2 speed, afifo on */ 463 (soc_miim_write(unit, phy_addr, 0x10, 0x212f)); 464 if (soc_property_port_get( 465 unit, port, spn_PHY_XAUI_RX_LANE_SWAP, FALSE)) { 466 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x18, 0xa050)); 467 } 468 } else if (phyrev == 4) { 469 SOC_IF_ERROR_RETURN /* Select block 0x5 */ 470 (soc_miim_write(unit, phy_addr, 0x1f, 0x0050)); 471 SOC_IF_ERROR_RETURN /* PLL range select bypass */ 472 (soc_miim_write(unit, phy_addr, 0x11, 0x500e)); 473 SOC_IF_ERROR_RETURN /* Enable PLL tuning */ 474 (soc_miim_write(unit, phy_addr, 0x1c, 0x0019)); 475 476 SOC_IF_ERROR_RETURN /* Select block 0xf */ 477 (soc_miim_write(unit, phy_addr, 0x1f, 0x00f0)); 478 SOC_IF_ERROR_RETURN /* Set RX integration mode */ 479 (soc_miim_write(unit, phy_addr, 0x19, 0x0910)); 480 SOC_IF_ERROR_RETURN /* Set sigdet offset control */ 481 (soc_miim_write(unit, phy_addr, 0x1b, 0x0008)); 482 483 SOC_IF_ERROR_RETURN /* Select block 0x5 */ 484 (soc_miim_write(unit, phy_addr, 0x1f, 0x0050)); 485 SOC_IF_ERROR_RETURN /* Turn on PLL state machine */ 486 (soc_miim_write(unit, phy_addr, 0x11, 0xd00e)); 487 488 SOC_IF_ERROR_RETURN /* Select block 0xa */ 489 (soc_miim_write(unit, phy_addr, 0x1f, 0x00a0)); 490 SOC_IF_ERROR_RETURN /* TX pre-emphasis */ 491 (soc_miim_write(unit, phy_addr, 0x17, ((preemph & 0xf) << 12) 492 | ((idriver & 0xf) << 8) | ((pdriver & 0xf) << 4))); 493 494 SOC_IF_ERROR_RETURN /* Select block 0x0 */ 495 (soc_miim_write(unit, phy_addr, 0x1f, 0x0000)); 496 SOC_IF_ERROR_RETURN /* Set TX clk to 1/2 speed, afifo on */ 497 (soc_miim_write(unit, phy_addr, 0x10, 0x212f)); 498 if (soc_property_port_get( 499 unit, port, spn_PHY_XAUI_RX_LANE_SWAP, FALSE)) { 500 SOC_IF_ERROR_RETURN(soc_miim_write(unit, phy_addr, 0x18, 0xa050)); 501 } 502 } 503 504 if (SAL_BOOT_QUICKTURN) { 505 LOG_VERBOSE(BSL_LS_SOC_10G, 506 (BSL_META_U(unit, 507 "SIMULATION: _fusioncore_phy_xgxs1_init: unit %d " 508 "port %s: skipped waiting for pll lock\n"), 509 unit, SOC_PORT_NAME(unit, port))); 510 return SOC_E_NONE; 511 } 512 513 /* Wait up to 0.1 sec for TX PLL lock. */ 514 soc_timeout_init(&to, pll_lock_usec, 0); 515 516 locked = 0; 517 while (!soc_timeout_check(&to)) { 518 SOC_IF_ERROR_RETURN(READ_MAC_XGXS_STATr(unit, port, &xgxs_stat)); 519 locked = soc_reg64_field32_get(unit, MAC_XGXS_STATr, xgxs_stat, 520 TXPLL_LOCKf); 521 if (locked) { 522 break; 523 } 524 } 525 526 if (!locked) { 527 uint16 x_pll_stat; 528 529 SOC_IF_ERROR_RETURN /* Select block 0x5 */ 530 (soc_miim_write(unit, phy_addr, 0x1f, 0x0050)); 531 SOC_IF_ERROR_RETURN /* Read PLL status */ 532 (soc_miim_read(unit, phy_addr, 0x10, &x_pll_stat)); 533 SOC_IF_ERROR_RETURN /* Select block 0x5 */ 534 (soc_miim_write(unit, phy_addr, 0x1f, 0x0000)); 535 LOG_ERROR(BSL_LS_SOC_COMMON, 536 (BSL_META_U(unit, 537 "unit %d port %s: FusionCore PLL did not lock PLL_STAT %04x\n"), 538 unit, SOC_PORT_NAME(unit, port), x_pll_stat)); 539 } else { 540 LOG_VERBOSE(BSL_LS_SOC_10G, 541 (BSL_META_U(unit, 542 "_fusioncore_phy_xgxs1_init: unit %d port %s " 543 "FusionCore PLL locked in %d usec\n"), 544 unit, SOC_PORT_NAME(unit, port), 545 soc_timeout_elapsed(&to))); 546 } 547 548 return SOC_E_NONE; 549 } 550 551 /* 552 * Function: 553 * soc_fusioncore_reset (10(X)-Gig/Xaui/Serdes (XGXS) reset) 554 * Purpose: 555 * Reset and initialize the BigMAC and Fusion core technology. 556 * Parameters: 557 * unit - XGS unit #. 558 * port - Port number on unit. 559 * Returns: 560 * SOC_E_XXX 561 */ 562 int 563 soc_fusioncore_reset(int unit, soc_port_t port) 564 { 565 LOG_VERBOSE(BSL_LS_SOC_10G, 566 (BSL_META_U(unit, 567 "soc_fusioncore_reset: unit %d port %s\n"), 568 unit, SOC_PORT_NAME(unit, port))); 569 570 SOC_IF_ERROR_RETURN(soc_xgxs_reset(unit, port)); 571 572 SOC_IF_ERROR_RETURN(_fusioncore_phy_xgxs1_init(unit, port)); 573 return SOC_E_NONE; 574 } 575 576 STATIC int 577 _mac_big_init(int unit, soc_port_t port) 578 { 579 uint64 rx_ctrl, tx_ctrl, mac_ctrl, tmp64; 580 int encap, ipg; 581 582 LOG_VERBOSE(BSL_LS_SOC_10G, 583 (BSL_META_U(unit, 584 "_mac_big_init: unit %d port %s\n"), 585 unit, SOC_PORT_NAME(unit, port))); 586 587 /* Disable Tx/Rx, assume that MAC is stable (or out of reset) */ 588 SOC_IF_ERROR_RETURN(READ_MAC_RXCTRLr(unit, port, &rx_ctrl)); 589 SOC_IF_ERROR_RETURN(READ_MAC_TXCTRLr(unit, port, &tx_ctrl)); 590 SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, &mac_ctrl)); 591 592 if (soc_reg_field_valid(unit, MAC_CTRLr, TXRESETf)) { 593 soc_reg64_field32_set(unit, MAC_CTRLr, &mac_ctrl, TXRESETf, 0); 594 soc_reg64_field32_set(unit, MAC_CTRLr, &mac_ctrl, RXRESETf, 0); 595 } 596 597 soc_reg64_field32_set(unit, MAC_CTRLr, &mac_ctrl, RXENf, 0); 598 soc_reg64_field32_set(unit, MAC_CTRLr, &mac_ctrl, TXENf, 0); 599 if (IS_ST_PORT(unit, port)) { 600 soc_reg64_field32_set(unit, MAC_TXCTRLr, &tx_ctrl, PAUSEENf, 0); 601 soc_reg64_field32_set(unit, MAC_RXCTRLr, &rx_ctrl, RXPAUSENf, 0); 602 } else { 603 soc_reg64_field32_set(unit, MAC_TXCTRLr, &tx_ctrl, PAUSEENf, 1); 604 soc_reg64_field32_set(unit, MAC_RXCTRLr, &rx_ctrl, RXPAUSENf, 1); 605 } 606 if (IS_XE_PORT(unit, port)) { 607 ipg = SOC_PERSIST(unit)->ipg[port].fd_xe; 608 } else { 609 ipg = SOC_PERSIST(unit)->ipg[port].fd_hg; 610 } 611 soc_reg64_field32_set(unit, MAC_TXCTRLr, &tx_ctrl, AVGIPGf, ipg >> 3); 612 613 SOC_IF_ERROR_RETURN(WRITE_MAC_CTRLr(unit, port, mac_ctrl)); 614 SOC_IF_ERROR_RETURN(WRITE_MAC_TXCTRLr(unit, port, tx_ctrl)); 615 SOC_IF_ERROR_RETURN(WRITE_MAC_RXCTRLr(unit, port, rx_ctrl)); 616 617 #if defined(BCM_XGS3_SWITCH_SUPPORT) 618 if (SOC_IS_XGS3_SWITCH(unit)) { 619 int wan_mode = soc_property_port_get(unit, port, spn_PHY_WAN_MODE, 620 FALSE); 621 622 if (wan_mode) { 623 /* Max speed for WAN mode is 9.294Gbps. 624 * This setting gives 10Gbps * (13/14) or 9.286 Gbps */ 625 SOC_IF_ERROR_RETURN 626 (soc_mac_big.md_control_set(unit, port, 627 SOC_MAC_CONTROL_FRAME_SPACING_STRETCH, 13)); 628 } 629 } 630 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 631 632 /* Set jumbo max size (8000 byte payload) */ 633 COMPILER_64_SET(tmp64, 0, JUMBO_MAXSZ); 634 SOC_IF_ERROR_RETURN(WRITE_MAC_TXMAXSZr(unit, port, tmp64)); 635 SOC_IF_ERROR_RETURN(WRITE_MAC_RXMAXSZr(unit, port, tmp64)); 636 637 /* Program MAC settings */ 638 /* Setup header mode, check for property for bcm5632 mode */ 639 if (IS_XE_PORT(unit, port)) { 640 encap = SOC_ENCAP_IEEE; /* Ethernet port, so only IEEE mode */ 641 } else if (soc_property_get(unit, spn_BCM5632_MODE, 0)) { 642 encap = SOC_ENCAP_B5632; 643 } else { 644 encap = SOC_ENCAP_HIGIG; /* Default: Enable HIGIG header mode */ 645 } 646 soc_reg64_field32_set(unit, MAC_TXCTRLr, &tx_ctrl, HDRMODEf, encap); 647 soc_reg64_field32_set(unit, MAC_RXCTRLr, &rx_ctrl, HDRMODEf, encap); 648 649 #if defined(BCM_BRADLEY_SUPPORT) 650 #ifdef BCM_HIGIG2_SUPPORT 651 if (soc_feature(unit, soc_feature_higig2) && IS_HG_PORT(unit, port) && 652 soc_property_port_get(unit, port, spn_HIGIG2_HDR_MODE, 653 0)) { 654 soc_reg64_field32_set(unit, MAC_TXCTRLr, &tx_ctrl, HIGIG2MODEf, 1); 655 soc_reg64_field32_set(unit, MAC_RXCTRLr, &rx_ctrl, HIGIG2MODEf, 1); 656 } 657 #endif /* BCM_HIGIG2_SUPPORT */ 658 #endif 659 660 /* 661 * Power-up defaults are CRC_APPEND for TX and STRIPCRC for RX. 662 * Change to CRC_KEEP for Hercules, CRC_REGEN for other XGS, 663 * and turn off STRIPCRC to be compatible with other BCM56xx. 664 * 665 * To prevent an extra 4 bytes passing through the fabric, 666 */ 667 668 soc_reg64_field32_set(unit, MAC_RXCTRLr, &rx_ctrl, STRIPCRCf, 0); 669 soc_reg64_field32_set(unit, MAC_TXCTRLr, &tx_ctrl, CRC_MODEf, 670 BIGMAC_CRC_REGEN); 671 if (soc_reg_field_valid(unit, MAC_TXCTRLr, TIME_STAMP_TX_ENf)) { 672 soc_reg64_field32_set(unit, MAC_TXCTRLr, &tx_ctrl, TIME_STAMP_TX_ENf, 1); 673 } 674 if (soc_reg_field_valid(unit, MAC_RXCTRLr, TIME_STAMP_RX_ENf)) { 675 soc_reg64_field32_set(unit, MAC_RXCTRLr, &rx_ctrl, TIME_STAMP_RX_ENf, 1); 676 } 677 SOC_IF_ERROR_RETURN(WRITE_MAC_TXCTRLr(unit, port, tx_ctrl)); 678 SOC_IF_ERROR_RETURN(WRITE_MAC_RXCTRLr(unit, port, rx_ctrl)); 679 680 if (SOC_IS_XGS12_FABRIC(unit)) { 681 uint64 pse, opse; 682 683 SOC_IF_ERROR_RETURN(READ_MAC_TXPSETHRr(unit, port, &pse)); 684 opse = pse; 685 soc_reg64_field32_set(unit, MAC_TXPSETHRr, &pse, XONf, 0xff80); 686 if (COMPILER_64_NE(pse, opse)) { 687 SOC_IF_ERROR_RETURN(WRITE_MAC_TXPSETHRr(unit, port, pse)); 688 } 689 } 690 691 /* disable loopback */ 692 soc_reg64_field32_set(unit, MAC_CTRLr, &mac_ctrl, RMTLOOPf, 0); 693 soc_reg64_field32_set(unit, MAC_CTRLr, &mac_ctrl, LCLLOOPf, 0); 694 695 #if defined(BCM_SCORPION_SUPPORT) || defined(BCM_TRIUMPH2_SUPPORT) 696 if (soc_feature(unit, soc_feature_priority_flow_control)) { 697 /* Flush MMU XOFF state with toggle bit */ 698 if (SOC_REG_IS_VALID(unit, BMAC_PFC_CTRLr)) { 699 SOC_IF_ERROR_RETURN 700 (soc_reg_field32_modify(unit, BMAC_PFC_CTRLr, port, 701 FORCE_PFC_XONf, 1)); 702 SOC_IF_ERROR_RETURN 703 (soc_reg_field32_modify(unit, BMAC_PFC_CTRLr, port, 704 FORCE_PFC_XONf, 0)); 705 } else { 706 SOC_IF_ERROR_RETURN 707 (soc_reg_field32_modify(unit, MAC_PFC_CTRLr, port, 708 FORCE_PP_XONf, 1)); 709 SOC_IF_ERROR_RETURN 710 (soc_reg_field32_modify(unit, MAC_PFC_CTRLr, port, 711 FORCE_PP_XONf, 0)); 712 } 713 } 714 #endif /* BCM_SCORPION_SUPPORT || BCM_TRIUMPH2_SUPPORT */ 715 716 /* Finally, take MAC out of reset (program enables) */ 717 soc_reg64_field32_set(unit, MAC_CTRLr, &mac_ctrl, RXENf, 1); 718 soc_reg64_field32_set(unit, MAC_CTRLr, &mac_ctrl, TXENf, 1); 719 720 SOC_IF_ERROR_RETURN(WRITE_MAC_CTRLr(unit, port, mac_ctrl)); 721 722 return SOC_E_NONE; 723 } 724 725 /* 726 * Function: 727 * mac_big_init 728 * Purpose: 729 * Initialize Bigmac / FusionCore MAC into a known good state. 730 * Parameters: 731 * unit - XGS unit #. 732 * port - Port number on unit. 733 * Returns: 734 * SOC_E_XXX 735 * Notes: 736 */ 737 STATIC int 738 mac_big_init(int unit, soc_port_t port) 739 { 740 #if defined(BCM_XGS3_SWITCH_SUPPORT) 741 if (IS_HG_PORT(unit, port) && soc_feature(unit, soc_feature_xgxs_lcpll)) { 742 uint32 val, lcpll; 743 744 /* 745 * LCPLL clock speed selection 746 */ 747 lcpll = soc_property_port_get(unit, port, spn_XGXS_LCPLL_12GBPS, 0) ? 748 1 : 0, 749 READ_CMIC_XGXS_PLL_CONTROL_1r(unit, &val); 750 soc_reg_field_set(unit, CMIC_XGXS_PLL_CONTROL_1r, &val, 751 _port2pllf(unit, port), lcpll); 752 WRITE_CMIC_XGXS_PLL_CONTROL_1r(unit, val); 753 } 754 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 755 756 return _mac_big_init(unit, port); 757 } 758 759 /* 760 * Function: 761 * mac_big_enable_get 762 * Purpose: 763 * Get MAC enable state 764 * Parameters: 765 * unit - XGS unit #. 766 * port - Port number on unit. 767 * enable - (OUT) TRUE if enabled, FALSE if disabled 768 * Returns: 769 * SOC_E_XXX 770 */ 771 STATIC int 772 mac_big_enable_get(int unit, soc_port_t port, int *enable) 773 { 774 uint64 ctrl; 775 776 SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, &ctrl)); 777 778 *enable = soc_reg64_field32_get(unit, MAC_CTRLr, ctrl, RXENf); 779 780 LOG_VERBOSE(BSL_LS_SOC_10G, 781 (BSL_META_U(unit, 782 "mac_big_enable_get: unit %d port %s enable=%s\n"), 783 unit, SOC_PORT_NAME(unit, port), 784 *enable ? "True" : "False")); 785 786 return SOC_E_NONE; 787 } 788 789 /* 790 * Function: 791 * mac_big_duplex_set 792 * Purpose: 793 * Set BigMAC in the specified duplex mode. 794 * Parameters: 795 * unit - XGS unit #. 796 * port - XGS port # on unit. 797 * duplex - Boolean: true --> full duplex, false --> half duplex. 798 * Returns: 799 * SOC_E_XXX 800 * Notes: 801 */ 802 STATIC int 803 mac_big_duplex_set(int unit, soc_port_t port, int duplex) 804 { 805 LOG_VERBOSE(BSL_LS_SOC_10G, 806 (BSL_META_U(unit, 807 "mac_big_duplex_set: unit %d port %s duplex=%s\n"), 808 unit, SOC_PORT_NAME(unit, port), 809 duplex ? "Full" : "Half")); 810 return SOC_E_NONE; 811 } 812 813 /* 814 * Function: 815 * mac_big_duplex_get 816 * Purpose: 817 * Get BigMAC duplex mode. 818 * Parameters: 819 * unit - XGS unit #. 820 * duplex - (OUT) Boolean: true --> full duplex, false --> half duplex. 821 * Returns: 822 * SOC_E_XXX 823 */ 824 STATIC int 825 mac_big_duplex_get(int unit, soc_port_t port, int *duplex) 826 { 827 *duplex = TRUE; /* Always full duplex */ 828 829 LOG_VERBOSE(BSL_LS_SOC_10G, 830 (BSL_META_U(unit, 831 "mac_big_duplex_get: unit %d port %s duplex=%s\n"), 832 unit, SOC_PORT_NAME(unit, port), 833 *duplex ? "Full" : "Half")); 834 return SOC_E_NONE; 835 } 836 837 /* 838 * Function: 839 * mac_big_pause_set 840 * Purpose: 841 * Configure BigMAC to transmit/receive pause frames. 842 * Parameters: 843 * unit - XGS unit #. 844 * port - XGS port # on unit. 845 * pause_tx - Boolean: transmit pause or -1 (don't change) 846 * pause_rx - Boolean: receive pause or -1 (don't change) 847 * Returns: 848 * SOC_E_XXX 849 */ 850 STATIC int 851 mac_big_pause_set(int unit, soc_port_t port, int pause_tx, int pause_rx) 852 { 853 uint64 tmp, otmp; 854 855 LOG_VERBOSE(BSL_LS_SOC_10G, 856 (BSL_META_U(unit, 857 "mac_big_pause_set: unit %d port %s RX=%s TX=%s\n"), 858 unit, SOC_PORT_NAME(unit, port), 859 pause_rx ? "on" : "off", 860 pause_tx ? "on" : "off")); 861 862 if (pause_tx >= 0) { 863 /* Transmit Pause frame function */ 864 SOC_IF_ERROR_RETURN(READ_MAC_TXCTRLr(unit, port, &tmp)); 865 otmp = tmp; 866 soc_reg64_field32_set(unit, MAC_TXCTRLr, &tmp, PAUSEENf, 867 pause_tx ? 1 : 0); 868 if (COMPILER_64_NE(tmp, otmp)) { 869 SOC_IF_ERROR_RETURN(WRITE_MAC_TXCTRLr(unit, port, tmp)); 870 } 871 } 872 873 if (pause_rx >= 0) { 874 /* Receive Pause frame function */ 875 SOC_IF_ERROR_RETURN(READ_MAC_RXCTRLr(unit, port, &tmp)); 876 otmp = tmp; 877 soc_reg64_field32_set(unit, MAC_RXCTRLr, &tmp, RXPAUSENf, 878 pause_rx ? 1 : 0); 879 if (COMPILER_64_NE(tmp, otmp)) { 880 SOC_IF_ERROR_RETURN(WRITE_MAC_RXCTRLr(unit, port, tmp)); 881 } 882 } 883 884 return SOC_E_NONE; 885 } 886 887 /* 888 * Function: 889 * mac_big_pause_get 890 * Purpose: 891 * Return the pause ability of BigMAC 892 * Parameters: 893 * unit - XGS unit #. 894 * port - XGS port # on unit. 895 * pause_tx - Boolean: transmit pause 896 * pause_rx - Boolean: receive pause 897 * pause_mac - MAC address used for pause transmission. 898 * Returns: 899 * SOC_E_XXX 900 */ 901 STATIC int 902 mac_big_pause_get(int unit, soc_port_t port, int *pause_tx, int *pause_rx) 903 { 904 uint64 rx, tx; 905 906 SOC_IF_ERROR_RETURN(READ_MAC_RXCTRLr(unit, port, &rx)); 907 *pause_rx = soc_reg64_field32_get(unit, MAC_RXCTRLr, rx, RXPAUSENf); 908 SOC_IF_ERROR_RETURN(READ_MAC_TXCTRLr(unit, port, &tx)); 909 *pause_tx = soc_reg64_field32_get(unit, MAC_TXCTRLr, tx, PAUSEENf); 910 911 LOG_VERBOSE(BSL_LS_SOC_10G, 912 (BSL_META_U(unit, 913 "mac_big_pause_get: unit %d port %s RX=%s TX=%s\n"), 914 unit, SOC_PORT_NAME(unit, port), 915 *pause_rx ? "on" : "off", 916 *pause_tx ? "on" : "off")); 917 return SOC_E_NONE; 918 } 919 920 /* 921 * Function: 922 * mac_big_speed_set 923 * Purpose: 924 * Set BigMAC in the specified speed. 925 * Parameters: 926 * unit - XGS unit #. 927 * port - XGS port # on unit. 928 * speed - 2500, 3000, 10000, 12000 for speed. 929 * Returns: 930 * SOC_E_XXX 931 */ 932 STATIC int 933 mac_big_speed_set(int unit, soc_port_t port, int speed) 934 { 935 LOG_VERBOSE(BSL_LS_SOC_10G, 936 (BSL_META_U(unit, 937 "mac_big_speed_set: unit %d port %s speed=%dMb\n"), 938 unit, SOC_PORT_NAME(unit, port), 939 speed)); 940 941 #if defined(BCM_XGS3_SWITCH_SUPPORT) 942 if (IS_HG_PORT(unit, port) && 943 soc_feature(unit, soc_feature_xgxs_lcpll)) { 944 pbmp_t pbmp; 945 int usec, enable, cur_speed, cur_max, cur_lb; 946 uint32 flags, rval; 947 948 SOC_IF_ERROR_RETURN 949 (soc_mac_big.md_speed_get(unit, port, &cur_speed)); 950 if (speed != cur_speed) { 951 #if defined(BCM_HELIX15_SUPPORT) || defined(BCM_FELIX15_SUPPORT) || \ 952 defined(BCM_FIREBOLT2_SUPPORT) 953 SOC_IF_ERROR_RETURN 954 (_mac_big_speed_support_check(unit, port, speed)); 955 #endif /* BCM_HELIX15_SUPPORT || BCM_FELIX15_SUPPORT || 956 BCM_FIREBOLT2_SUPPORT */ 957 switch (speed) { 958 case 0: 959 /* Leave speed unchanged; */ 960 break; 961 #if defined(BCM_HELIX15_SUPPORT) || defined(BCM_FELIX15_SUPPORT) || \ 962 defined(BCM_FIREBOLT2_SUPPORT) 963 case 2500: 964 case 3000: 965 speed <<= 2; /* specified speed is div by 4 */ 966 /* FALLTHRU */ 967 #endif /* BCM_HELIX15_SUPPORT || BCM_FELIX15_SUPPORT || 968 BCM_FIREBOLT2_SUPPORT */ 969 case 10000: 970 case 12000: 971 /* Save counter DMA settings and port state */ 972 flags = SOC_CONTROL(unit)->counter_flags; 973 usec = SOC_CONTROL(unit)->counter_interval; 974 SOC_PBMP_ASSIGN(pbmp, SOC_CONTROL(unit)->counter_pbmp); 975 SOC_IF_ERROR_RETURN 976 (soc_mac_big.md_enable_get(unit, port, &enable)); 977 SOC_IF_ERROR_RETURN 978 (soc_mac_big.md_frame_max_get(unit, port, &cur_max)); 979 SOC_IF_ERROR_RETURN 980 (soc_mac_big.md_lb_get(unit, port, &cur_lb)); 981 /* Stop counter DMA and disable MAC */ 982 SOC_IF_ERROR_RETURN 983 (soc_counter_stop(unit)); 984 SOC_IF_ERROR_RETURN 985 (soc_mac_big.md_enable_set(unit, port, 0)); 986 987 READ_CMIC_XGXS_PLL_CONTROL_1r(unit, &rval); 988 soc_reg_field_set(unit, CMIC_XGXS_PLL_CONTROL_1r, &rval, 989 _port2pllf(unit, port), 990 speed == 12000 ? 1 : 0); 991 WRITE_CMIC_XGXS_PLL_CONTROL_1r(unit, rval); 992 993 /* Reset */ 994 SOC_IF_ERROR_RETURN(soc_xgxs_reset(unit, port)); 995 SOC_IF_ERROR_RETURN(_fusioncore_phy_xgxs1_init(unit, port)); 996 SOC_IF_ERROR_RETURN 997 (soc_phyctrl_init(unit, port)); 998 SOC_IF_ERROR_RETURN 999 (_mac_big_init(unit, port)); 1000 /* Restore counter DMA settings and port state */ 1001 SOC_IF_ERROR_RETURN 1002 (soc_mac_big.md_frame_max_set(unit, port, cur_max)); 1003 SOC_IF_ERROR_RETURN 1004 (soc_mac_big.md_lb_set(unit, port, cur_lb)); 1005 SOC_IF_ERROR_RETURN 1006 (soc_mac_big.md_enable_set(unit, port, enable)); 1007 SOC_IF_ERROR_RETURN 1008 (soc_counter_start(unit, flags, usec, pbmp)); 1009 break; 1010 default: 1011 return SOC_E_PARAM; 1012 } 1013 } 1014 1015 } else { 1016 /* Just update IPG */ 1017 int ipg; 1018 uint64 rval64, orval64; 1019 1020 if (IS_XE_PORT(unit, port)) { 1021 ipg = SOC_PERSIST(unit)->ipg[port].fd_xe; 1022 } else { 1023 ipg = SOC_PERSIST(unit)->ipg[port].fd_hg; 1024 } 1025 1026 SOC_IF_ERROR_RETURN(READ_MAC_TXCTRLr(unit, port, &rval64)); 1027 orval64 = rval64; 1028 soc_reg64_field32_set(unit, MAC_TXCTRLr, &rval64, AVGIPGf, ipg >> 3); 1029 if (COMPILER_64_NE(rval64, orval64)) { 1030 SOC_IF_ERROR_RETURN(WRITE_MAC_TXCTRLr(unit, port, rval64)); 1031 } 1032 } 1033 1034 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 1035 1036 return SOC_E_NONE; 1037 } 1038 1039 /* 1040 * Function: 1041 * mac_big_speed_get 1042 * Purpose: 1043 * Get BigMAC speed 1044 * Parameters: 1045 * unit - XGS unit #. 1046 * port - XGS port # on unit. 1047 * speed - (OUT) speed in Mb (2500/3000/10000/12000) 1048 * Returns: 1049 * SOC_E_XXX 1050 */ 1051 STATIC int 1052 mac_big_speed_get(int unit, soc_port_t port, int *speed) 1053 { 1054 *speed = 10000; 1055 #if defined(BCM_XGS3_SWITCH_SUPPORT) 1056 #ifdef BCM_GXPORT_SUPPORT 1057 if (soc_reg_field_valid(unit, MAC_XGXS_STATr, SPEED_10000f)) { 1058 uint64 rval64; 1059 uint32 rval32; 1060 uint32 i; 1061 static struct { 1062 soc_field_t field; 1063 int speed; 1064 } _sp_sel[] = { 1065 { SPEED_16000f, 16000 }, 1066 { SPEED_15000f, 15000 }, 1067 { SPEED_13000f, 13000 }, 1068 { SPEED_12500f, 12500 }, 1069 { SPEED_12000f, 12000 }, 1070 { SPEED_10000_CX4f, 10000 }, 1071 { SPEED_10000f, 10000 }, 1072 { SPEED_6000f, 6000 }, 1073 { SPEED_5000f, 5000 }, 1074 { SPEED_2500f, 2500 }, 1075 { SPEED_1000f, 1000 }, 1076 { SPEED_100f, 100 }, 1077 { SPEED_10f, 10 } 1078 }; 1079 1080 /* Get speed from internal PHY by reading BigMAC register */ 1081 SOC_IF_ERROR_RETURN(READ_MAC_XGXS_STATr(unit, port, &rval64)); 1082 for (i = 0; i < COUNTOF(_sp_sel); i++) { 1083 if (soc_reg64_field32_get(unit, MAC_XGXS_STATr, rval64, 1084 _sp_sel[i].field)) { 1085 *speed = _sp_sel[i].speed; 1086 break; 1087 } 1088 } 1089 if (i == COUNTOF(_sp_sel)) { 1090 if (SOC_IS_SHADOW(unit)) { 1091 SOC_IF_ERROR_RETURN(READ_XPORT_XGXS_NEWSTATUS2_REGr(unit, port, 1092 &rval32)); 1093 if (soc_reg_field_get(unit, XPORT_XGXS_NEWSTATUS2_REGr, 1094 rval32, XGXS0_SPEED20000f) & 1) { 1095 *speed = 20000; 1096 } else if (soc_reg_field_get(unit, XPORT_XGXS_NEWSTATUS2_REGr, 1097 rval32, XGXS0_SPEED25455f) & 1) { 1098 *speed = 25000; 1099 } 1100 } 1101 1102 if (SOC_IS_SC_CQ(unit)) { 1103 SOC_IF_ERROR_RETURN(READ_XPORT_XGXS_NEWSTATUS2_REGr(unit, port, 1104 &rval32)); 1105 if (soc_reg_field_get(unit, XPORT_XGXS_NEWSTATUS2_REGr, 1106 rval32, XGXS0_SPEED20000f) & 1) { 1107 *speed = 20000; 1108 } else if (soc_reg_field_get(unit, XPORT_XGXS_NEWSTATUS2_REGr, 1109 rval32, XGXS0_SPEED21000f) & 1) { 1110 *speed = 21000; 1111 } 1112 } 1113 if (!IS_XQ_PORT(unit, port) && 1114 (SOC_IS_TRIUMPH2(unit) || SOC_IS_APOLLO(unit) || 1115 SOC_IS_VALKYRIE2(unit))) { 1116 SOC_IF_ERROR_RETURN 1117 (READ_XPORT_XGXS_NEWSTATUS1_REGr(unit, port, &rval32)); 1118 if (soc_reg_field_get(unit, XPORT_XGXS_NEWSTATUS1_REGr, 1119 rval32, XGXS0_SPEED20000f)) { 1120 *speed = 20000; 1121 } else if (soc_reg_field_get(unit, XPORT_XGXS_NEWSTATUS1_REGr, 1122 rval32, XGXS0_SPEED21000f)) { 1123 *speed = 21000; 1124 } else if (soc_reg_field_get(unit, XPORT_XGXS_NEWSTATUS1_REGr, 1125 rval32, XGXS0_SPEED25455f)) { 1126 *speed = 24000; 1127 } 1128 } 1129 } 1130 1131 LOG_VERBOSE(BSL_LS_SOC_10G, 1132 (BSL_META_U(unit, 1133 "mac_big_speed_get: unit %d port %s speed=%dMb\n"), 1134 unit, SOC_PORT_NAME(unit, port), 1135 *speed)); 1136 return SOC_E_NONE; 1137 } 1138 #endif /* BCM_GXPORT_SUPPORT */ 1139 1140 if (IS_HG_PORT(unit, port)) { 1141 if (soc_feature(unit, soc_feature_xgxs_lcpll)) { 1142 uint32 val, lcpll; 1143 uint64 xgxs_ctrl; 1144 1145 /* 1146 * Check for internal/external ref clock. 1147 * If external clock is used then leave speed at 10G 1148 * even if this may be incorrect. 1149 */ 1150 SOC_IF_ERROR_RETURN(READ_MAC_XGXS_CTRLr(unit, port, &xgxs_ctrl)); 1151 if (soc_reg64_field32_get(unit, MAC_XGXS_CTRLr, 1152 xgxs_ctrl, LCREFENf) == 1) { 1153 /* Internal ref clock, get speed select */ 1154 READ_CMIC_XGXS_PLL_CONTROL_1r(unit, &val); 1155 lcpll = soc_reg_field_get(unit, CMIC_XGXS_PLL_CONTROL_1r, 1156 val, _port2pllf(unit, port)); 1157 if (lcpll == 1) { 1158 *speed = 12000; 1159 } 1160 } 1161 } 1162 } 1163 #if defined(BCM_HELIX15_SUPPORT) || defined(BCM_FELIX15_SUPPORT) || \ 1164 defined(BCM_FIREBOLT2_SUPPORT) 1165 if (soc_feature(unit, soc_feature_lmd)) { 1166 if (IS_LMD_ENABLED_PORT(unit, port)) { 1167 *speed >>= 2; /* Div by 4 */ 1168 } 1169 } 1170 #endif /* BCM_HELIX15_SUPPORT || BCM_FELIX15_SUPPORT || 1171 BCM_FIREBOLT2_SUPPORT */ 1172 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 1173 1174 LOG_VERBOSE(BSL_LS_SOC_10G, 1175 (BSL_META_U(unit, 1176 "mac_big_speed_get: unit %d port %s speed=%dMb\n"), 1177 unit, SOC_PORT_NAME(unit, port), 1178 *speed)); 1179 return SOC_E_NONE; 1180 } 1181 1182 /* 1183 * Function: 1184 * mac_big_loopback_set 1185 * Purpose: 1186 * Set a BigMAC into/out-of loopback mode 1187 * Parameters: 1188 * unit - XGS unit #. 1189 * port - XGS unit # on unit. 1190 * loopback - Boolean: true -> loopback mode, false -> normal operation 1191 * Note: 1192 * On bigmac, when setting loopback, we enable the TX/RX function also. 1193 * Note that to test the PHY, we use the remote loopback facility. 1194 * Returns: 1195 * SOC_E_XXX 1196 */ 1197 STATIC int 1198 mac_big_loopback_set(int unit, soc_port_t port, int lb) 1199 { 1200 uint64 ctrl, octrl; 1201 1202 LOG_VERBOSE(BSL_LS_SOC_10G, 1203 (BSL_META_U(unit, 1204 "mac_big_loopback_set: unit %d port %s loopback=%s\n"), 1205 unit, SOC_PORT_NAME(unit, port), 1206 lb ? "local" : "no")); 1207 1208 SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, &ctrl)); 1209 octrl = ctrl; 1210 soc_reg64_field32_set(unit, MAC_CTRLr, &ctrl, LCLLOOPf, 1211 lb ? 1 : 0); 1212 if (COMPILER_64_NE(ctrl, octrl)) { 1213 SOC_IF_ERROR_RETURN(WRITE_MAC_CTRLr(unit, port, ctrl)); 1214 } 1215 1216 return SOC_E_NONE; 1217 } 1218 1219 /* 1220 * Function: 1221 * mac_big_loopback_get 1222 * Purpose: 1223 * Get current BigMAC loopback mode setting. 1224 * Parameters: 1225 * unit - XGS unit #. 1226 * port - XGS port # on unit. 1227 * loopback - (OUT) Boolean: true = loopback, false = normal 1228 * Returns: 1229 * SOC_E_XXX 1230 */ 1231 STATIC int 1232 mac_big_loopback_get(int unit, soc_port_t port, int *lb) 1233 { 1234 uint64 ctrl; 1235 int local, remote; 1236 1237 SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, &ctrl)); 1238 1239 remote = soc_reg64_field32_get(unit, MAC_CTRLr, ctrl, RMTLOOPf); 1240 local = soc_reg64_field32_get(unit, MAC_CTRLr, ctrl, LCLLOOPf); 1241 *lb = local | remote; 1242 1243 LOG_VERBOSE(BSL_LS_SOC_10G, 1244 (BSL_META_U(unit, 1245 "mac_big_loopback_get: unit %d port %s loopback=%s\n"), 1246 unit, SOC_PORT_NAME(unit, port), 1247 *lb ? (remote ? "remote" : "local") : "no")); 1248 return SOC_E_NONE; 1249 } 1250 1251 /* 1252 * Function: 1253 * mac_big_pause_addr_set 1254 * Purpose: 1255 * Configure PAUSE frame source address. 1256 * Parameters: 1257 * unit - XGS unit #. 1258 * port - XGS port # on unit. 1259 * pause_mac - (OUT) MAC address used for pause transmission. 1260 * Returns: 1261 * SOC_E_XXX 1262 */ 1263 STATIC int 1264 mac_big_pause_addr_set(int unit, soc_port_t port, sal_mac_addr_t m) 1265 { 1266 uint64 r, tmp; 1267 int i; 1268 1269 LOG_VERBOSE(BSL_LS_SOC_10G, 1270 (BSL_META_U(unit, 1271 "mac_big_pause_addr_set: unit %d port %s MAC=<" 1272 "%02x:%02x:%02x:%02x:%02x:%02x>\n"), 1273 unit, SOC_PORT_NAME(unit, port), 1274 m[0], m[1], m[2], m[3], m[4], m[5])); 1275 1276 COMPILER_64_ZERO(r); 1277 for (i = 0; i< 6; i++) { 1278 COMPILER_64_SET(tmp, 0, m[i]); 1279 COMPILER_64_SHL(r, 8); 1280 COMPILER_64_OR(r, tmp); 1281 } 1282 1283 SOC_IF_ERROR_RETURN(WRITE_MAC_TXMACSAr(unit, port, r)); 1284 SOC_IF_ERROR_RETURN(WRITE_MAC_RXMACSAr(unit, port, r)); 1285 1286 return SOC_E_NONE; 1287 } 1288 1289 /* 1290 * Function: 1291 * mac_big_pause_addr_get 1292 * Purpose: 1293 * Retrieve PAUSE frame source address. 1294 * Parameters: 1295 * unit - XGS unit #. 1296 * port - XGS port # on unit. 1297 * pause_mac - (OUT) MAC address used for pause transmission. 1298 * Returns: 1299 * SOC_E_XXX 1300 * NOTE: We always write the same thing to TX & RX SA 1301 * so, we just return the contects on RXMACSA. 1302 */ 1303 STATIC int 1304 mac_big_pause_addr_get(int unit, soc_port_t port, sal_mac_addr_t m) 1305 { 1306 uint64 reg; 1307 uint32 msw; 1308 uint32 lsw; 1309 1310 SOC_IF_ERROR_RETURN(READ_MAC_RXMACSAr(unit, port, ®)); 1311 COMPILER_64_TO_32_HI(msw, reg); 1312 COMPILER_64_TO_32_LO(lsw, reg); 1313 1314 m[0] = (uint8) ( ( msw & 0x0000ff00 ) >> 8 ); 1315 m[1] = (uint8) ( msw & 0x000000ff ); 1316 1317 m[2] = (uint8) ( ( lsw & 0xff000000) >> 24 ); 1318 m[3] = (uint8) ( ( lsw & 0x00ff0000) >> 16 ); 1319 m[4] = (uint8) ( ( lsw & 0x0000ff00) >> 8 ); 1320 m[5] = (uint8) ( lsw & 0x000000ff ); 1321 1322 LOG_VERBOSE(BSL_LS_SOC_10G, 1323 (BSL_META_U(unit, 1324 "mac_big_pause_addr_get: unit %d port %s MAC=<" 1325 "%02x:%02x:%02x:%02x:%02x:%02x>\n"), 1326 unit, SOC_PORT_NAME(unit, port), 1327 m[0], m[1], m[2], m[3], m[4], m[5])); 1328 return SOC_E_NONE; 1329 } 1330 1331 /* 1332 * Function: 1333 * mac_big_interface_set 1334 * Purpose: 1335 * Set a BigMAC interface type 1336 * Parameters: 1337 * unit - XGS unit #. 1338 * port - XGS port # on unit. 1339 * pif - one of SOC_PORT_IF_* 1340 * Returns: 1341 * SOC_E_NONE 1342 * SOC_E_UNAVAIL - requested mode not supported. 1343 * Notes: 1344 */ 1345 STATIC int 1346 mac_big_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 1347 { 1348 #ifdef BROADCOM_DEBUG 1349 LOG_VERBOSE(BSL_LS_SOC_10G, 1350 (BSL_META_U(unit, 1351 "mac_big_interface_set: unit %d port %s interface=%s\n"), 1352 unit, SOC_PORT_NAME(unit, port), 1353 mac_big_port_if_names[pif])); 1354 #endif 1355 return SOC_E_NONE; 1356 } 1357 1358 /* 1359 * Function: 1360 * mac_big_interface_get 1361 * Purpose: 1362 * Retrieve BigMAC interface type 1363 * Parameters: 1364 * unit - XGS unit #. 1365 * port - XGS port # on unit. 1366 * pif - (OUT) one of SOC_PORT_IF_* 1367 * Returns: 1368 * SOC_E_NONE 1369 */ 1370 STATIC int 1371 mac_big_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 1372 { 1373 COMPILER_REFERENCE(unit); 1374 COMPILER_REFERENCE(port); 1375 1376 *pif = SOC_PORT_IF_MII; 1377 1378 #ifdef BROADCOM_DEBUG 1379 LOG_VERBOSE(BSL_LS_SOC_10G, 1380 (BSL_META_U(unit, 1381 "mac_big_interface_get: unit %d port %s interface=%s\n"), 1382 unit, SOC_PORT_NAME(unit, port), 1383 mac_big_port_if_names[*pif])); 1384 #endif 1385 return SOC_E_NONE; 1386 } 1387 1388 /* 1389 * Function: 1390 * mac_big_frame_max_set 1391 * Description: 1392 * Set the maximum receive frame size for the port 1393 * Parameters: 1394 * unit - Device number 1395 * port - Port number 1396 * size - Maximum frame size in bytes 1397 * Return Value: 1398 * BCM_E_XXX 1399 */ 1400 STATIC int 1401 mac_big_frame_max_set(int unit, soc_port_t port, int size) 1402 { 1403 uint64 val64; 1404 1405 LOG_VERBOSE(BSL_LS_SOC_10G, 1406 (BSL_META_U(unit, 1407 "mac_big_frame_max_set: unit %d port %s size=%d\n"), 1408 unit, SOC_PORT_NAME(unit, port), 1409 size)); 1410 1411 if (IS_XE_PORT(unit, port)) { 1412 /* For VLAN tagged packets */ 1413 size += 4; 1414 } 1415 COMPILER_64_SET(val64, 0, size); 1416 SOC_IF_ERROR_RETURN(WRITE_MAC_RXMAXSZr(unit, port, val64)); 1417 1418 if (SOC_IS_XGS12_SWITCH(unit) && IS_XE_PORT(unit, port)) { 1419 size += 8; /* Preamble included in Ethernet TX size */ 1420 } 1421 COMPILER_64_SET(val64, 0, size); 1422 SOC_IF_ERROR_RETURN(WRITE_MAC_TXMAXSZr(unit, port, val64)); 1423 1424 return SOC_E_NONE; 1425 } 1426 1427 /* 1428 * Function: 1429 * mac_big_frame_max_get 1430 * Description: 1431 * Set the maximum receive frame size for the port 1432 * Parameters: 1433 * unit - Device number 1434 * port - Port number 1435 * size - Maximum frame size in bytes 1436 * Return Value: 1437 * BCM_E_XXX 1438 */ 1439 STATIC int 1440 mac_big_frame_max_get(int unit, soc_port_t port, int *size) 1441 { 1442 int rv; 1443 uint64 val64; 1444 1445 rv = READ_MAC_TXMAXSZr(unit, port, &val64); 1446 if (rv == SOC_E_NONE) { 1447 COMPILER_64_TO_32_LO(*size, val64); 1448 if (IS_XE_PORT(unit, port)) { 1449 /* For VLAN tagged packets */ 1450 *size -= 4; 1451 } 1452 } 1453 1454 LOG_VERBOSE(BSL_LS_SOC_10G, 1455 (BSL_META_U(unit, 1456 "mac_big_frame_max_get: unit %d port %s size=%d\n"), 1457 unit, SOC_PORT_NAME(unit, port), 1458 *size)); 1459 return rv; 1460 } 1461 1462 /* 1463 * Function: 1464 * mac_big_ifg_set 1465 * Description: 1466 * Sets the new ifg (Inter-frame gap) value 1467 * Parameters: 1468 * unit - Device number 1469 * port - Port number 1470 * speed - the speed for which the IFG is being set 1471 * duplex - the duplex for which the IFG is being set 1472 * ifg - number of bits to use for average inter-frame gap 1473 * Return Value: 1474 * BCM_E_XXX 1475 * Notes: 1476 * The function makes sure the IFG value makes sense and updates the 1477 * IPG register in case the speed/duplex match the current settings 1478 */ 1479 STATIC int 1480 mac_big_ifg_set(int unit, soc_port_t port, int speed, 1481 soc_port_duplex_t duplex, int ifg) 1482 { 1483 int cur_speed; 1484 int cur_duplex; 1485 int real_ifg; 1486 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 1487 uint64 rval, orval; 1488 soc_port_ability_t ability; 1489 uint32 pa_flag; 1490 1491 LOG_VERBOSE(BSL_LS_SOC_10G, 1492 (BSL_META_U(unit, 1493 "mac_big_ifg_set: unit %d port %s speed=%dMb duplex=%s " 1494 "ifg=%d\n"), 1495 unit, SOC_PORT_NAME(unit, port), 1496 speed, duplex ? "True" : "False", ifg)); 1497 1498 if (!duplex) { 1499 return SOC_E_PARAM; 1500 } 1501 1502 _mac_big_speed_to_pa_flag(unit, port, speed, &pa_flag); 1503 soc_mac_big.md_ability_local_get(unit, port, &ability); 1504 if (!(pa_flag & ability.speed_full_duplex)) { 1505 return SOC_E_PARAM; 1506 } 1507 1508 /* Silently adjust the specified ifp bits to valid value */ 1509 /* valid value: 8 to 31 bytes (i.e. multiple of 8 bits) */ 1510 real_ifg = ifg < 64 ? 64 : (ifg > 248 ? 248 : (ifg + 7) & (0x1f << 3)); 1511 1512 if (IS_XE_PORT(unit, port)) { 1513 si->fd_xe = real_ifg; 1514 } else { 1515 si->fd_hg = real_ifg; 1516 } 1517 1518 SOC_IF_ERROR_RETURN(mac_big_duplex_get(unit, port, &cur_duplex)); 1519 SOC_IF_ERROR_RETURN(mac_big_speed_get(unit, port, &cur_speed)); 1520 1521 if (cur_speed == speed && ((soc_port_duplex_t)cur_duplex == duplex)) { 1522 SOC_IF_ERROR_RETURN(READ_MAC_TXCTRLr(unit, port, &rval)); 1523 orval = rval; 1524 soc_reg64_field32_set(unit, MAC_TXCTRLr, &rval, AVGIPGf, 1525 real_ifg >> 3); 1526 if (COMPILER_64_NE(rval, orval)) { 1527 SOC_IF_ERROR_RETURN(WRITE_MAC_TXCTRLr(unit, port, rval)); 1528 } 1529 } 1530 1531 return SOC_E_NONE; 1532 } 1533 1534 /* 1535 * Function: 1536 * mac_big_ifg_get 1537 * Description: 1538 * Sets the new ifg (Inter-frame gap) value 1539 * Parameters: 1540 * unit - Device number 1541 * port - Port number 1542 * speed - the speed for which the IFG is being set 1543 * duplex - the duplex for which the IFG is being set 1544 * size - Maximum frame size in bytes 1545 * Return Value: 1546 * BCM_E_XXX 1547 * Notes: 1548 * The function makes sure the IFG value makes sense and updates the 1549 * IPG register in case the speed/duplex match the current settings 1550 */ 1551 STATIC int 1552 mac_big_ifg_get(int unit, soc_port_t port, int speed, 1553 soc_port_duplex_t duplex, int *ifg) 1554 { 1555 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 1556 soc_port_ability_t ability; 1557 uint32 pa_flag; 1558 1559 if (!duplex) { 1560 return SOC_E_PARAM; 1561 } 1562 1563 _mac_big_speed_to_pa_flag(unit, port, speed, &pa_flag); 1564 soc_mac_big.md_ability_local_get(unit, port, &ability); 1565 if (!(pa_flag & ability.speed_full_duplex)) { 1566 return SOC_E_PARAM; 1567 } 1568 1569 if (IS_XE_PORT(unit, port)) { 1570 *ifg = si->fd_xe; 1571 } else { 1572 *ifg = si->fd_hg; 1573 } 1574 1575 LOG_VERBOSE(BSL_LS_SOC_10G, 1576 (BSL_META_U(unit, 1577 "mac_big_ifg_get: unit %d port %s speed=%dMb duplex=%s " 1578 "ifg=%d\n"), 1579 unit, SOC_PORT_NAME(unit, port), 1580 speed, duplex ? "True" : "False", *ifg)); 1581 return SOC_E_NONE; 1582 } 1583 1584 /* 1585 * Function: 1586 * mac_big_loopback_remote_set 1587 * Purpose: 1588 * Set the BigMAC into remote-loopback state. 1589 * Parameters: 1590 * unit - XGS unit #. 1591 * port - XGS port # on unit. 1592 * mode - (INT) loopback enable state 1593 * Returns: 1594 * SOC_E_XXX 1595 */ 1596 int 1597 mac_big_loopback_remote_set(int unit, soc_port_t port, int lb) 1598 { 1599 uint64 ctrl, octrl; 1600 1601 LOG_VERBOSE(BSL_LS_SOC_10G, 1602 (BSL_META_U(unit, 1603 "mac_big_loopback_remote_set: unit %d port %s loopback=%s\n"), 1604 unit, SOC_PORT_NAME(unit, port), 1605 lb ? "remote" : "no")); 1606 1607 SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, &ctrl)); 1608 octrl = ctrl; 1609 soc_reg64_field32_set(unit, MAC_CTRLr, &ctrl, RMTLOOPf, 1610 lb ? 1 : 0); 1611 if (COMPILER_64_NE(ctrl, octrl)) { 1612 SOC_IF_ERROR_RETURN(WRITE_MAC_CTRLr(unit, port, ctrl)); 1613 } 1614 1615 return SOC_E_NONE; 1616 } 1617 1618 /* 1619 * Function: 1620 * _mac_big_port_mode_update 1621 * Purpose: 1622 * Set the BigMAC port encapsulation mode. 1623 * Parameters: 1624 * unit - XGS unit #. 1625 * port - XGS port # on unit. 1626 * to_hg_port - (TRUE/FALSE) 1627 * Returns: 1628 * SOC_E_XXX 1629 */ 1630 STATIC int 1631 _mac_big_port_mode_update(int unit, soc_port_t port, int to_hg_port) 1632 { 1633 uint32 rval; 1634 uint64 val64; 1635 soc_pbmp_t ctr_pbmp; 1636 int rv = SOC_E_NONE; 1637 1638 /* Pause linkscan */ 1639 soc_linkscan_pause(unit); 1640 1641 /* Pause counter collection */ 1642 COUNTER_LOCK(unit); 1643 1644 soc_xport_type_update(unit, port, to_hg_port); 1645 1646 rv = soc_xgxs_reset(unit, port); 1647 1648 if (SOC_SUCCESS(rv)) { 1649 rv = _fusioncore_phy_xgxs1_init(unit, port); 1650 } 1651 1652 if (SOC_SUCCESS(rv)) { 1653 rv = soc_phyctrl_init(unit, port); 1654 } 1655 1656 if (SOC_SUCCESS(rv)) { 1657 rv = _mac_big_init(unit, port); 1658 } 1659 1660 if (SOC_SUCCESS(rv)) { 1661 rv = mac_big_enable_set(unit, port, 0); 1662 } 1663 1664 if (SOC_SUCCESS(rv)) { 1665 SOC_PBMP_CLEAR(ctr_pbmp); 1666 SOC_PBMP_PORT_SET(ctr_pbmp, port); 1667 COMPILER_64_SET(val64, 0, 0); 1668 rv = soc_counter_set_by_port(unit, ctr_pbmp, val64); 1669 } 1670 1671 COUNTER_UNLOCK(unit); 1672 soc_linkscan_continue(unit); 1673 1674 SOC_IF_ERROR_RETURN(READ_XPORT_CONFIGr(unit, port, &rval)); 1675 if (to_hg_port) { 1676 soc_reg_field_set(unit, XPORT_CONFIGr, &rval, HIGIG_MODEf, 1); 1677 } else { 1678 soc_reg_field_set(unit, XPORT_CONFIGr, &rval, HIGIG_MODEf, 0); 1679 } 1680 SOC_IF_ERROR_RETURN(WRITE_XPORT_CONFIGr(unit, port, rval)); 1681 return rv; 1682 } 1683 1684 /* 1685 * Function: 1686 * mac_big_encap_set 1687 * Purpose: 1688 * Set the BigMAC port encapsulation mode. 1689 * Parameters: 1690 * unit - XGS unit #. 1691 * port - XGS port # on unit. 1692 * mode - (IN) encap bits (defined above) 1693 * Returns: 1694 * SOC_E_XXX 1695 */ 1696 STATIC int 1697 mac_big_encap_set(int unit, soc_port_t port, int mode) 1698 { 1699 uint64 rval, orval; 1700 int enable, rv = SOC_E_NONE; 1701 int encap = 0; /* IEEE */ 1702 int cur_mode, higig2 = 0; 1703 1704 #ifdef BROADCOM_DEBUG 1705 LOG_VERBOSE(BSL_LS_SOC_10G, 1706 (BSL_META_U(unit, 1707 "mac_big_encap_set: unit %d port %s encapsulation=%s\n"), 1708 unit, SOC_PORT_NAME(unit, port), 1709 mac_big_encap_mode[mode])); 1710 #endif 1711 1712 SOC_IF_ERROR_RETURN(soc_mac_big.md_encap_get(unit, port, &cur_mode)); 1713 if (cur_mode == mode) { 1714 /* Nothing to do */ 1715 return SOC_E_NONE; 1716 } 1717 1718 switch (mode) { 1719 case SOC_ENCAP_IEEE: 1720 break; 1721 case SOC_ENCAP_HIGIG: 1722 encap = 1; 1723 break; 1724 case SOC_ENCAP_B5632: 1725 encap = 2; 1726 break; 1727 case SOC_ENCAP_HIGIG2: 1728 if (soc_feature(unit, soc_feature_higig2)) { 1729 higig2 = 1; 1730 encap = 1; 1731 } else { 1732 return SOC_E_PARAM; 1733 } 1734 break; 1735 default: 1736 return SOC_E_PARAM; 1737 } 1738 1739 SOC_IF_ERROR_RETURN(mac_big_enable_get(unit, port, &enable)); 1740 1741 if (enable) { 1742 /* Turn off TX/RX enable */ 1743 SOC_IF_ERROR_RETURN(mac_big_enable_set(unit, port, 0)); 1744 } 1745 1746 /* Need to test for E port and XE port because for embedded Higig 1747 * ports an XE port may not be considered an E port. */ 1748 if ((mode == SOC_ENCAP_HIGIG || mode == SOC_ENCAP_HIGIG2) && 1749 (IS_E_PORT(unit, port) || IS_XE_PORT(unit, port))) { 1750 /* XE -> HG */ 1751 if (soc_feature(unit, soc_feature_xport_convertible)) { 1752 SOC_IF_ERROR_RETURN 1753 (_mac_big_port_mode_update(unit, port, TRUE)); 1754 } else { 1755 rv = SOC_E_PARAM; 1756 } 1757 } else if ((mode == SOC_ENCAP_IEEE) && IS_ST_PORT(unit, port)) { 1758 /* HG -> XE */ 1759 if (soc_feature(unit, soc_feature_xport_convertible)) { 1760 SOC_IF_ERROR_RETURN 1761 (_mac_big_port_mode_update(unit, port, FALSE)); 1762 } else { 1763 rv = SOC_E_PARAM; 1764 } 1765 } 1766 1767 /* Update the encapsulation mode */ 1768 SOC_IF_ERROR_RETURN(READ_MAC_RXCTRLr(unit, port, &rval)); 1769 orval = rval; 1770 soc_reg64_field32_set(unit, MAC_RXCTRLr, &rval, HDRMODEf, encap); 1771 #if defined(BCM_BRADLEY_SUPPORT) 1772 if (soc_feature(unit, soc_feature_higig2)) { 1773 soc_reg64_field32_set(unit, MAC_RXCTRLr, &rval, HIGIG2MODEf, higig2); 1774 } 1775 #endif 1776 if (COMPILER_64_NE(rval, orval)) { 1777 SOC_IF_ERROR_RETURN(WRITE_MAC_RXCTRLr(unit, port, rval)); 1778 } 1779 1780 SOC_IF_ERROR_RETURN(READ_MAC_TXCTRLr(unit, port, &rval)); 1781 orval = rval; 1782 soc_reg64_field32_set(unit, MAC_TXCTRLr, &rval, HDRMODEf, encap); 1783 #if defined(BCM_BRADLEY_SUPPORT) 1784 if (soc_feature(unit, soc_feature_higig2)) { 1785 soc_reg64_field32_set(unit, MAC_TXCTRLr, &rval, HIGIG2MODEf, higig2); 1786 } 1787 #endif 1788 if (COMPILER_64_NE(rval, orval)) { 1789 SOC_IF_ERROR_RETURN(WRITE_MAC_TXCTRLr(unit, port, rval)); 1790 } 1791 1792 if (enable) { 1793 /* Re-enable transmitter and receiver */ 1794 SOC_IF_ERROR_RETURN(mac_big_enable_set(unit, port, 1)); 1795 } 1796 1797 return rv; 1798 } 1799 1800 /* 1801 * Function: 1802 * mac_big_encap_get 1803 * Purpose: 1804 * Get the BigMAC port encapsulation mode. 1805 * Parameters: 1806 * unit - XGS unit #. 1807 * port - XGS port # on unit. 1808 * mode - (INT) encap bits (defined above) 1809 * Returns: 1810 * SOC_E_XXX 1811 */ 1812 STATIC int 1813 mac_big_encap_get(int unit, soc_port_t port, int *mode) 1814 { 1815 uint64 rx_ctrl; 1816 1817 /* Bad pointer */ 1818 if (!mode) { 1819 return SOC_E_PARAM; 1820 } 1821 1822 /* 1823 * TX/RX mode should always be programmed to the same 1824 * value (or all sorts of weird things will happen). 1825 * So, for purpose of S/W state, we only need to read 1826 * one or the other and return the state. 1827 * 1828 * WARNING: The following assumes BCM_PORT_ENCAP_xxx values equal 1829 * the hardware register field values. 1830 */ 1831 1832 SOC_IF_ERROR_RETURN(READ_MAC_RXCTRLr(unit, port, &rx_ctrl)); 1833 *mode = soc_reg64_field32_get(unit, MAC_RXCTRLr, rx_ctrl, HDRMODEf); 1834 1835 #if defined(BCM_BRADLEY_SUPPORT) 1836 if (soc_feature(unit, soc_feature_higig2) && 1837 (*mode == SOC_ENCAP_HIGIG) && 1838 soc_reg64_field32_get(unit, MAC_RXCTRLr, rx_ctrl, HIGIG2MODEf)) { 1839 *mode = SOC_ENCAP_HIGIG2; 1840 } 1841 #endif 1842 1843 #ifdef BROADCOM_DEBUG 1844 LOG_VERBOSE(BSL_LS_SOC_10G, 1845 (BSL_META_U(unit, 1846 "mac_big_encap_get: unit %d port %s encapsulation=%s\n"), 1847 unit, SOC_PORT_NAME(unit, port), 1848 mac_big_encap_mode[*mode])); 1849 #endif 1850 return SOC_E_NONE; 1851 } 1852 1853 /* 1854 * Function: 1855 * mac_big_frame_spacing_stretch_set 1856 * Purpose: 1857 * Set frame spacing stretch parameters. 1858 * Parameters: 1859 * unit - XGS unit #. 1860 * port - XGS port # on unit. 1861 * Returns: 1862 * SOC_E_XXX 1863 */ 1864 STATIC int 1865 _mac_big_frame_spacing_stretch_set(int unit, soc_port_t port, int value) 1866 { 1867 #if defined(BCM_XGS3_SWITCH_SUPPORT) 1868 if (SOC_IS_XGS3_SWITCH(unit)) { 1869 int field_width, max_value; 1870 uint64 reg_val; 1871 field_width = soc_reg_field_length(unit, MAC_TXCTRLr, THROTDENOMf); 1872 max_value = (1 << (field_width + 1)) - 1; 1873 if ((value > max_value) || (value < 0)) { 1874 return SOC_E_PARAM; 1875 } 1876 1877 SOC_IF_ERROR_RETURN 1878 (READ_MAC_TXCTRLr(unit, port, ®_val)); 1879 1880 /* Set 0 will be automatically changed to 8 by ASIC; so 8 will be gotten for read */ 1881 soc_reg64_field32_set(unit, MAC_TXCTRLr, ®_val, 1882 THROTDENOMf, value); 1883 1884 if (SOC_IS_ENDURO(unit) || SOC_IS_HURRICANE(unit)) { 1885 soc_reg64_field32_set(unit, MAC_TXCTRLr, ®_val, 1886 THROTNUMERf, value ? 1 : 0); 1887 } else { 1888 soc_reg64_field32_set(unit, MAC_TXCTRLr, ®_val, 1889 THROTNUMf, value ? 1 : 0); 1890 } 1891 1892 SOC_IF_ERROR_RETURN 1893 (WRITE_MAC_TXCTRLr(unit, port, reg_val)); 1894 1895 return SOC_E_NONE; 1896 } 1897 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 1898 1899 return SOC_E_UNAVAIL; 1900 } 1901 1902 /* 1903 * Function: 1904 * mac_big_control_set 1905 * Purpose: 1906 * To configure MAC control properties. 1907 * Parameters: 1908 * unit - XGS unit #. 1909 * port - XGS port # on unit. 1910 * type - MAC control property to set. 1911 * int - New setting for MAC control. 1912 * Returns: 1913 * SOC_E_XXX 1914 */ 1915 STATIC int 1916 mac_big_control_set(int unit, soc_port_t port, soc_mac_control_t type, 1917 int value) 1918 { 1919 uint64 reg_val, copy; 1920 uint32 fval; 1921 1922 LOG_VERBOSE(BSL_LS_SOC_10G, 1923 (BSL_META_U(unit, 1924 "mac_big_control_set: unit %d port %s type=%d value=%d\n"), 1925 unit, SOC_PORT_NAME(unit, port), 1926 type, value)); 1927 1928 switch(type) { 1929 case SOC_MAC_CONTROL_RX_SET: 1930 SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, ®_val)); 1931 copy = reg_val; 1932 soc_reg64_field32_set(unit, MAC_CTRLr, ®_val, RXENf, value ? 1 : 0); 1933 if (COMPILER_64_NE(reg_val, copy)) { 1934 SOC_IF_ERROR_RETURN(WRITE_MAC_CTRLr(unit, port, reg_val)); 1935 } 1936 break; 1937 case SOC_MAC_CONTROL_FAILOVER_RX_SET: 1938 SOC_IF_ERROR_RETURN 1939 (soc_reg_field32_modify(unit, MAC_CTRLr, port, RXENf, value? 1 : 0)); 1940 break; 1941 case SOC_MAC_CONTROL_FRAME_SPACING_STRETCH: 1942 /* 'value == 0' means disable Spacing Stretch Function */ 1943 if ( value >= 8 || value == 0) { 1944 return _mac_big_frame_spacing_stretch_set(unit, port, value); 1945 } else { 1946 return SOC_E_PARAM; 1947 } 1948 break; 1949 1950 case SOC_MAC_PASS_CONTROL_FRAME: 1951 SOC_IF_ERROR_RETURN(READ_MAC_RXCTRLr(unit, port, ®_val)); 1952 soc_reg64_field32_set(unit, MAC_RXCTRLr, ®_val, RXPASSCTRLf, 1953 value ? 1 : 0); 1954 SOC_IF_ERROR_RETURN(WRITE_MAC_RXCTRLr(unit, port, reg_val)); 1955 break; 1956 1957 case SOC_MAC_CONTROL_PFC_TYPE: 1958 if (SOC_REG_IS_VALID(unit, BMAC_PFC_TYPEr)) { 1959 SOC_IF_ERROR_RETURN 1960 (soc_reg_field32_modify(unit, BMAC_PFC_TYPEr, port, 1961 PFC_ETH_TYPEf, value)); 1962 } else { 1963 SOC_IF_ERROR_RETURN 1964 (soc_reg_field32_modify(unit, MAC_PFC_FIELDr, port, 1965 ETHERTYPEf, value)); 1966 } 1967 break; 1968 1969 case SOC_MAC_CONTROL_PFC_OPCODE: 1970 if (SOC_REG_IS_VALID(unit, BMAC_PFC_OPCODEr)) { 1971 SOC_IF_ERROR_RETURN 1972 (soc_reg_field32_modify(unit, BMAC_PFC_OPCODEr, 1973 port, PFC_OPCODEf, value)); 1974 } else { 1975 SOC_IF_ERROR_RETURN 1976 (soc_reg_field32_modify(unit, MAC_PFC_FIELDr, 1977 port, OPCODEf, value)); 1978 } 1979 break; 1980 1981 case SOC_MAC_CONTROL_PFC_CLASSES: 1982 if (value == 16) { 1983 fval = 0; 1984 } else if (value == 8) { 1985 fval = 1; 1986 } else { 1987 return SOC_E_PARAM; 1988 } 1989 if (SOC_REG_IS_VALID(unit, BMAC_PFC_CTRLr)) { 1990 SOC_IF_ERROR_RETURN 1991 (soc_reg_field32_modify(unit, BMAC_PFC_CTRLr, port, 1992 PFC_EIGHT_CLASSf, fval)); 1993 } else { 1994 SOC_IF_ERROR_RETURN 1995 (soc_reg_field32_modify(unit, MAC_PFC_CTRLr, port, 1996 PP_EIGHT_CLASSf, fval)); 1997 } 1998 break; 1999 2000 case SOC_MAC_CONTROL_PFC_MAC_DA_OUI: 2001 if (SOC_REG_IS_VALID(unit, BMAC_PFC_DA_LOr)) { 2002 SOC_IF_ERROR_RETURN(READ_BMAC_PFC_DA_LOr(unit, port, ®_val)); 2003 fval = soc_reg64_field32_get(unit, BMAC_PFC_DA_LOr, reg_val, 2004 PFC_MACDA_LOf); 2005 fval &= 0x00ffffff; 2006 fval |= (value & 0xff) << 24; 2007 soc_reg64_field32_set(unit, BMAC_PFC_DA_LOr, ®_val, 2008 PFC_MACDA_LOf, fval); 2009 SOC_IF_ERROR_RETURN(WRITE_BMAC_PFC_DA_LOr(unit, port, reg_val)); 2010 2011 SOC_IF_ERROR_RETURN(READ_BMAC_PFC_DA_HIr(unit, port, ®_val)); 2012 soc_reg64_field32_set(unit, BMAC_PFC_DA_HIr, ®_val, 2013 PFC_MACDA_HIf, value >> 8); 2014 SOC_IF_ERROR_RETURN(WRITE_BMAC_PFC_DA_HIr(unit, port, reg_val)); 2015 } else { 2016 SOC_IF_ERROR_RETURN(READ_MAC_PFC_DAr(unit, port, ®_val)); 2017 fval = soc_reg64_field32_get(unit, MAC_PFC_DAr, reg_val, 2018 DA_LOf); 2019 fval &= 0x00ffffff; 2020 fval |= (value & 0xff) << 24; 2021 soc_reg64_field32_set(unit, MAC_PFC_DAr, ®_val, 2022 DA_LOf, fval); 2023 soc_reg64_field32_set(unit, MAC_PFC_DAr, ®_val, 2024 DA_HIf, value >> 8); 2025 SOC_IF_ERROR_RETURN(WRITE_MAC_PFC_DAr(unit, port, reg_val)); 2026 } 2027 break; 2028 2029 case SOC_MAC_CONTROL_PFC_MAC_DA_NONOUI: 2030 if (SOC_REG_IS_VALID(unit, BMAC_PFC_DA_LOr)) { 2031 SOC_IF_ERROR_RETURN(READ_BMAC_PFC_DA_LOr(unit, port, ®_val)); 2032 fval = soc_reg64_field32_get(unit, BMAC_PFC_DA_LOr, reg_val, 2033 PFC_MACDA_LOf); 2034 fval &= 0xff000000; 2035 fval |= value & 0x00ffffff; 2036 soc_reg64_field32_set(unit, BMAC_PFC_DA_LOr, ®_val, 2037 PFC_MACDA_LOf, fval); 2038 SOC_IF_ERROR_RETURN(WRITE_BMAC_PFC_DA_LOr(unit, port, reg_val)); 2039 } else { 2040 SOC_IF_ERROR_RETURN(READ_MAC_PFC_DAr(unit, port, ®_val)); 2041 fval = soc_reg64_field32_get(unit, MAC_PFC_DAr, reg_val, 2042 DA_LOf); 2043 fval &= 0xff000000; 2044 fval |= value & 0x00ffffff; 2045 soc_reg64_field32_set(unit, MAC_PFC_DAr, ®_val, 2046 DA_LOf, fval); 2047 SOC_IF_ERROR_RETURN(WRITE_MAC_PFC_DAr(unit, port, reg_val)); 2048 } 2049 break; 2050 2051 case SOC_MAC_CONTROL_PFC_RX_PASS: 2052 if (SOC_REG_IS_VALID(unit, BMAC_PFC_CTRLr)) { 2053 SOC_IF_ERROR_RETURN 2054 (soc_reg_field32_modify(unit, BMAC_PFC_CTRLr, port, 2055 RX_PASS_PFC_FRMf, value ? 1 : 0)); 2056 } else { 2057 SOC_IF_ERROR_RETURN 2058 (soc_reg_field32_modify(unit, MAC_RXCTRLr, port, 2059 RXPASSCTRLf, value ? 1 : 0)); 2060 } 2061 break; 2062 2063 case SOC_MAC_CONTROL_PFC_RX_ENABLE: 2064 if (soc_reg_field_valid(unit, MAC_CTRLr, PP_RX_ENABLEf)) { 2065 SOC_IF_ERROR_RETURN 2066 (soc_reg_field32_modify(unit, MAC_CTRLr, port, PP_RX_ENABLEf, 2067 value ? 1 : 0)); 2068 } else { 2069 SOC_IF_ERROR_RETURN 2070 (soc_reg_field32_modify(unit, MAC_PFC_CTRLr, port, PP_RX_ENBLf, 2071 value ? 1 : 0)); 2072 } 2073 break; 2074 2075 case SOC_MAC_CONTROL_PFC_TX_ENABLE: 2076 if (soc_reg_field_valid(unit, MAC_CTRLr, PP_TX_ENABLEf)) { 2077 SOC_IF_ERROR_RETURN 2078 (soc_reg_field32_modify(unit, MAC_CTRLr, port, PP_TX_ENABLEf, 2079 value ? 1 : 0)); 2080 } else { 2081 SOC_IF_ERROR_RETURN 2082 (soc_reg_field32_modify(unit, MAC_PFC_CTRLr, port, PP_TX_ENBLf, 2083 value ? 1 : 0)); 2084 } 2085 break; 2086 2087 case SOC_MAC_CONTROL_PFC_FORCE_XON: 2088 if (SOC_REG_IS_VALID(unit, BMAC_PFC_CTRLr)) { 2089 SOC_IF_ERROR_RETURN 2090 (soc_reg_field32_modify(unit, BMAC_PFC_CTRLr, port, 2091 FORCE_PFC_XONf, value ? 1 : 0)); 2092 } else { 2093 SOC_IF_ERROR_RETURN 2094 (soc_reg_field32_modify(unit, MAC_PFC_CTRLr, port, 2095 FORCE_PP_XONf, value ? 1 : 0)); 2096 } 2097 break; 2098 2099 case SOC_MAC_CONTROL_PFC_STATS_ENABLE: 2100 if (SOC_REG_IS_VALID(unit, BMAC_PFC_CTRLr)) { 2101 SOC_IF_ERROR_RETURN 2102 (soc_reg_field32_modify(unit, BMAC_PFC_CTRLr, port, 2103 PFC_STATS_ENf, value ? 1 : 0)); 2104 } else { 2105 SOC_IF_ERROR_RETURN 2106 (soc_reg_field32_modify(unit, MAC_PFC_CTRLr, port, 2107 PFC_STATS_ENf, value ? 1 : 0)); 2108 } 2109 break; 2110 2111 case SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE: 2112 SOC_IF_ERROR_RETURN 2113 (soc_reg_field32_modify(unit, MAC_RXLSSCTRLr, port, 2114 LOCALFAULTDISABLEf, value ? 0 : 1)); 2115 break; 2116 2117 case SOC_MAC_CONTROL_FAULT_REMOTE_ENABLE: 2118 SOC_IF_ERROR_RETURN 2119 (soc_reg_field32_modify(unit, MAC_RXLSSCTRLr, port, 2120 REMOTEFAULTDISABLEf, value ? 0 : 1)); 2121 break; 2122 2123 default: 2124 return SOC_E_UNAVAIL; 2125 } 2126 2127 return SOC_E_NONE; 2128 } 2129 2130 /* 2131 * Function: 2132 * mac_big_control_get 2133 * Purpose: 2134 * To get current MAC control setting. 2135 * Parameters: 2136 * unit - XGS unit #. 2137 * port - XGS port # on unit. 2138 * type - MAC control property to set. 2139 * int - New setting for MAC control. 2140 * Returns: 2141 * SOC_E_XXX 2142 */ 2143 STATIC int 2144 mac_big_control_get(int unit, soc_port_t port, soc_mac_control_t type, 2145 int *value) 2146 { 2147 int rv = SOC_E_NONE; 2148 uint64 reg_val; 2149 uint32 fval0, fval1; 2150 2151 if (NULL == value) { 2152 return SOC_E_PARAM; 2153 } 2154 2155 switch(type) { 2156 case SOC_MAC_CONTROL_RX_SET: 2157 SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, ®_val)); 2158 *value = soc_reg64_field32_get(unit, MAC_CTRLr, reg_val, RXENf); 2159 break; 2160 case SOC_MAC_CONTROL_FRAME_SPACING_STRETCH: 2161 if ((!SOC_REG_IS_VALID(unit, MAC_TXCTRLr)) || 2162 (!soc_reg_field_valid(unit, MAC_TXCTRLr, THROTDENOMf))){ 2163 return SOC_E_UNAVAIL; 2164 } 2165 SOC_IF_ERROR_RETURN(READ_MAC_TXCTRLr(unit, port, ®_val)); 2166 *value = soc_reg64_field32_get(unit, MAC_TXCTRLr, reg_val, 2167 THROTDENOMf); 2168 2169 /* when THROTNUMf/THROTNUMERf is 0, THROTDENOMf is not effective. 2170 * overwrite *value to 0 for the meaning of Spacing Stretch function is disabled */ 2171 if (soc_reg_field_valid(unit, MAC_TXCTRLr, THROTNUMf)) { 2172 if (0 == soc_reg64_field32_get(unit, MAC_TXCTRLr, reg_val, THROTNUMf)) { 2173 *value = 0; 2174 } 2175 } 2176 else if (soc_reg_field_valid(unit, MAC_TXCTRLr, THROTNUMERf)) { 2177 if (0 == soc_reg64_field32_get(unit, MAC_TXCTRLr, reg_val, THROTNUMERf)) { 2178 *value = 0; 2179 } 2180 } 2181 break; 2182 2183 case SOC_MAC_CONTROL_TIMESTAMP_TRANSMIT: 2184 { 2185 uint32 timestamp = 0; 2186 if (soc_feature(unit, soc_feature_timestamp_counter) && 2187 soc_property_get(unit, spn_SW_TIMESTAMP_FIFO_ENABLE, 1)) { 2188 rv = soc_counter_timestamp_get(unit, port, ×tamp); 2189 if (rv != SOC_E_NOT_FOUND) { 2190 *value = (int)timestamp; 2191 return rv; 2192 } 2193 } 2194 2195 if (!SOC_REG_IS_VALID(unit, MAC_TXTIMESTAMPFIFOSTATUSr)) { 2196 return SOC_E_UNAVAIL; 2197 } 2198 SOC_IF_ERROR_RETURN 2199 (READ_MAC_TXTIMESTAMPFIFOSTATUSr(unit, port, ®_val)); 2200 if (soc_reg64_field32_get(unit, MAC_TXTIMESTAMPFIFOSTATUSr, 2201 reg_val, ENTRY_COUNTf) == 0) { 2202 return SOC_E_EMPTY; 2203 } 2204 SOC_IF_ERROR_RETURN 2205 (READ_MAC_TXTIMESTAMPFIFOREADr(unit, port, ®_val)); 2206 timestamp = soc_reg64_field32_get(unit, MAC_TXTIMESTAMPFIFOREADr, 2207 reg_val, TIMESTAMPf); 2208 *value = (int)timestamp; 2209 rv = SOC_E_NONE; 2210 } 2211 break; 2212 2213 case SOC_MAC_PASS_CONTROL_FRAME: 2214 SOC_IF_ERROR_RETURN(READ_MAC_RXCTRLr(unit, port, ®_val)); 2215 *value = soc_reg64_field32_get(unit, MAC_RXCTRLr, reg_val, 2216 RXPASSCTRLf); 2217 break; 2218 2219 case SOC_MAC_CONTROL_PFC_TYPE: 2220 if (SOC_REG_IS_VALID(unit, BMAC_PFC_TYPEr)) { 2221 SOC_IF_ERROR_RETURN(READ_BMAC_PFC_TYPEr(unit, port, ®_val)); 2222 *value = soc_reg64_field32_get(unit, BMAC_PFC_TYPEr, reg_val, 2223 PFC_ETH_TYPEf); 2224 } else { 2225 SOC_IF_ERROR_RETURN(READ_MAC_PFC_FIELDr(unit, port, ®_val)); 2226 *value = soc_reg64_field32_get(unit, MAC_PFC_FIELDr, reg_val, 2227 ETHERTYPEf); 2228 } 2229 break; 2230 2231 case SOC_MAC_CONTROL_PFC_OPCODE: 2232 if (SOC_REG_IS_VALID(unit, BMAC_PFC_OPCODEr)) { 2233 SOC_IF_ERROR_RETURN(READ_BMAC_PFC_OPCODEr(unit, port, ®_val)); 2234 *value = soc_reg64_field32_get(unit, BMAC_PFC_OPCODEr, reg_val, 2235 PFC_OPCODEf); 2236 } else { 2237 SOC_IF_ERROR_RETURN(READ_MAC_PFC_FIELDr(unit, port, ®_val)); 2238 *value = soc_reg64_field32_get(unit, MAC_PFC_FIELDr, reg_val, 2239 OPCODEf); 2240 } 2241 break; 2242 2243 case SOC_MAC_CONTROL_PFC_CLASSES: 2244 if (SOC_REG_IS_VALID(unit, BMAC_PFC_CTRLr)) { 2245 SOC_IF_ERROR_RETURN(READ_BMAC_PFC_CTRLr(unit, port, ®_val)); 2246 *value = soc_reg64_field32_get(unit, BMAC_PFC_CTRLr, reg_val, 2247 PFC_EIGHT_CLASSf) ? 8 : 16; 2248 } else { 2249 SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr(unit, port, ®_val)); 2250 *value = soc_reg64_field32_get(unit, MAC_PFC_CTRLr, reg_val, 2251 PP_EIGHT_CLASSf) ? 8 : 16; 2252 } 2253 break; 2254 2255 case SOC_MAC_CONTROL_PFC_MAC_DA_OUI: 2256 if (SOC_REG_IS_VALID(unit, BMAC_PFC_DA_LOr)) { 2257 SOC_IF_ERROR_RETURN(READ_BMAC_PFC_DA_LOr(unit, port, ®_val)); 2258 fval0 = soc_reg64_field32_get(unit, BMAC_PFC_DA_LOr, reg_val, 2259 PFC_MACDA_LOf); 2260 SOC_IF_ERROR_RETURN(READ_BMAC_PFC_DA_HIr(unit, port, ®_val)); 2261 fval1 = soc_reg64_field32_get(unit, BMAC_PFC_DA_HIr, reg_val, 2262 PFC_MACDA_HIf); 2263 *value = (fval0 >> 24) | (fval1 << 8); 2264 } else { 2265 SOC_IF_ERROR_RETURN(READ_MAC_PFC_DAr(unit, port, ®_val)); 2266 fval0 = soc_reg64_field32_get(unit, MAC_PFC_DAr, reg_val, 2267 DA_LOf); 2268 fval1 = soc_reg64_field32_get(unit, MAC_PFC_DAr, reg_val, 2269 DA_HIf); 2270 *value = (fval0 >> 24) | (fval1 << 8); 2271 } 2272 break; 2273 2274 case SOC_MAC_CONTROL_PFC_MAC_DA_NONOUI: 2275 if (SOC_REG_IS_VALID(unit, BMAC_PFC_DA_LOr)) { 2276 SOC_IF_ERROR_RETURN(READ_BMAC_PFC_DA_LOr(unit, port, ®_val)); 2277 *value = soc_reg64_field32_get(unit, BMAC_PFC_DA_LOr, reg_val, 2278 PFC_MACDA_LOf) & 0x00ffffff; 2279 } else { 2280 SOC_IF_ERROR_RETURN(READ_MAC_PFC_DAr(unit, port, ®_val)); 2281 *value = soc_reg64_field32_get(unit, MAC_PFC_DAr, reg_val, 2282 DA_LOf) & 0x00ffffff; 2283 } 2284 break; 2285 2286 case SOC_MAC_CONTROL_PFC_RX_PASS: 2287 if (SOC_REG_IS_VALID(unit, BMAC_PFC_CTRLr)) { 2288 SOC_IF_ERROR_RETURN(READ_BMAC_PFC_CTRLr(unit, port, ®_val)); 2289 *value = soc_reg64_field32_get(unit, BMAC_PFC_CTRLr, reg_val, 2290 RX_PASS_PFC_FRMf); 2291 } else { 2292 SOC_IF_ERROR_RETURN(READ_MAC_RXCTRLr(unit, port, ®_val)); 2293 *value = soc_reg64_field32_get(unit, MAC_RXCTRLr, reg_val, 2294 RXPASSCTRLf); 2295 } 2296 break; 2297 2298 case SOC_MAC_CONTROL_PFC_RX_ENABLE: 2299 if (soc_reg_field_valid(unit, MAC_CTRLr, PP_RX_ENABLEf)) { 2300 SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, ®_val)); 2301 *value = soc_reg64_field32_get(unit, MAC_CTRLr, reg_val, 2302 PP_RX_ENABLEf); 2303 } else { 2304 SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr(unit, port, ®_val)); 2305 *value = soc_reg64_field32_get(unit, MAC_PFC_CTRLr, reg_val, 2306 PP_RX_ENBLf); 2307 } 2308 break; 2309 2310 case SOC_MAC_CONTROL_PFC_TX_ENABLE: 2311 if (soc_reg_field_valid(unit, MAC_CTRLr, PP_TX_ENABLEf)) { 2312 SOC_IF_ERROR_RETURN(READ_MAC_CTRLr(unit, port, ®_val)); 2313 *value = soc_reg64_field32_get(unit, MAC_CTRLr, reg_val, 2314 PP_TX_ENABLEf); 2315 } else { 2316 SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr(unit, port, ®_val)); 2317 *value = soc_reg64_field32_get(unit, MAC_PFC_CTRLr, reg_val, 2318 PP_TX_ENBLf); 2319 } 2320 break; 2321 2322 case SOC_MAC_CONTROL_PFC_FORCE_XON: 2323 if (SOC_REG_IS_VALID(unit, BMAC_PFC_CTRLr)) { 2324 SOC_IF_ERROR_RETURN(READ_BMAC_PFC_CTRLr(unit, port, ®_val)); 2325 *value = soc_reg64_field32_get(unit, BMAC_PFC_CTRLr, reg_val, 2326 FORCE_PFC_XONf); 2327 } else { 2328 SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr(unit, port, ®_val)); 2329 *value = soc_reg64_field32_get(unit, MAC_PFC_CTRLr, reg_val, 2330 FORCE_PP_XONf); 2331 } 2332 break; 2333 2334 case SOC_MAC_CONTROL_PFC_STATS_ENABLE: 2335 if (SOC_REG_IS_VALID(unit, BMAC_PFC_CTRLr)) { 2336 SOC_IF_ERROR_RETURN(READ_BMAC_PFC_CTRLr(unit, port, ®_val)); 2337 *value = soc_reg64_field32_get(unit, BMAC_PFC_CTRLr, reg_val, 2338 PFC_STATS_ENf); 2339 } else { 2340 SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr(unit, port, ®_val)); 2341 *value = soc_reg64_field32_get(unit, MAC_PFC_CTRLr, reg_val, 2342 PP_TX_ENBLf); 2343 } 2344 break; 2345 2346 case SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE: 2347 SOC_IF_ERROR_RETURN(READ_MAC_RXLSSCTRLr(unit, port, ®_val)); 2348 *value = soc_reg64_field32_get(unit, MAC_RXLSSCTRLr, reg_val, 2349 LOCALFAULTDISABLEf) ? 0 : 1; 2350 break; 2351 2352 case SOC_MAC_CONTROL_FAULT_LOCAL_STATUS: 2353 SOC_IF_ERROR_RETURN(READ_MAC_RXLSSSTATr(unit, port, ®_val)); 2354 *value = soc_reg64_field32_get(unit, MAC_RXLSSSTATr, reg_val, 2355 LOCALFAULTSTATf); 2356 break; 2357 2358 case SOC_MAC_CONTROL_FAULT_REMOTE_ENABLE: 2359 SOC_IF_ERROR_RETURN(READ_MAC_RXLSSCTRLr(unit, port, ®_val)); 2360 *value = soc_reg64_field32_get(unit, MAC_RXLSSCTRLr, reg_val, 2361 REMOTEFAULTDISABLEf) ? 0 : 1; 2362 break; 2363 2364 case SOC_MAC_CONTROL_FAULT_REMOTE_STATUS: 2365 SOC_IF_ERROR_RETURN(READ_MAC_RXLSSSTATr(unit, port, ®_val)); 2366 *value = soc_reg64_field32_get(unit, MAC_RXLSSSTATr, reg_val, 2367 REMOTEFAULTSTATf); 2368 break; 2369 default: 2370 return SOC_E_UNAVAIL; 2371 } 2372 2373 LOG_VERBOSE(BSL_LS_SOC_10G, 2374 (BSL_META_U(unit, 2375 "mac_big_control_get: unit %d port %s type=%d value=%d " 2376 "rv=%d\n"), 2377 unit, SOC_PORT_NAME(unit, port), 2378 type, *value, rv)); 2379 2380 return rv; 2381 } 2382 2383 /* 2384 * Function: 2385 * mac_big_ability_local_get 2386 * Purpose: 2387 * Return the abilities of BigMAC 2388 * Parameters: 2389 * unit - XGS unit #. 2390 * port - XGS port # on unit. 2391 * mode - (OUT) Supported operating modes as a mask of abilities. 2392 * Returns: 2393 * SOC_E_XXX 2394 */ 2395 STATIC int 2396 mac_big_ability_local_get(int unit, soc_port_t port, 2397 soc_port_ability_t *ability) 2398 { 2399 int idx; 2400 int port_speed_max; 2401 2402 if (NULL == ability) { 2403 return SOC_E_PARAM; 2404 } 2405 2406 ability->speed_half_duplex = SOC_PA_ABILITY_NONE; 2407 ability->speed_full_duplex = SOC_PA_ABILITY_NONE; 2408 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 2409 ability->interface = SOC_PA_INTF_MII | SOC_PA_INTF_XGMII; 2410 ability->medium = SOC_PA_ABILITY_NONE; 2411 ability->loopback = SOC_PA_LB_MAC; 2412 ability->flags = SOC_PA_ABILITY_NONE; 2413 2414 if (soc_feature(unit, soc_feature_xport_convertible)) { 2415 ability->encap = SOC_PA_ENCAP_IEEE | SOC_PA_ENCAP_HIGIG | 2416 SOC_PA_ENCAP_B5632; 2417 } else { 2418 ability->encap = 0; 2419 if (IS_E_PORT(unit, port)) { 2420 ability->encap |= SOC_PA_ENCAP_IEEE; 2421 } 2422 if (IS_ST_PORT(unit, port)) { 2423 ability->encap |= SOC_PA_ENCAP_HIGIG | SOC_PA_ENCAP_B5632; 2424 } 2425 } 2426 if (soc_feature(unit, soc_feature_higig2) && 2427 (ability->encap & SOC_PA_ENCAP_HIGIG)) { 2428 ability->encap |= SOC_PA_ENCAP_HIGIG2; 2429 } 2430 2431 if (IS_LMD_ENABLED_PORT(unit, port)) { 2432 ability->speed_full_duplex |= SOC_PA_SPEED_2500MB; 2433 } else { 2434 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 2435 } 2436 2437 if (!IS_HG_PORT(unit , port)) { 2438 LOG_VERBOSE(BSL_LS_SOC_10G, 2439 (BSL_META_U(unit, 2440 "mac_big_ability_local_get: unit %d port %s " 2441 "speed_half=0x%x speed_full=0x%x encap=0x%x pause=0x%x " 2442 "interface=0x%x medium=0x%x loopback=0x%x flags=0x%x\n"), 2443 unit, SOC_PORT_NAME(unit, port), 2444 ability->speed_half_duplex, ability->speed_full_duplex, 2445 ability->encap, ability->pause, ability->interface, 2446 ability->medium, ability->loopback, ability->flags)); 2447 return SOC_E_NONE; 2448 } 2449 2450 if (soc_feature(unit, soc_feature_xgxs_lcpll)) { 2451 if (IS_LMD_ENABLED_PORT(unit, port)) { 2452 ability->speed_full_duplex |= SOC_PA_SPEED_3000MB; 2453 } else { 2454 ability->speed_full_duplex |= SOC_PA_SPEED_12GB; 2455 } 2456 } else { 2457 port_speed_max = SOC_INFO(unit).port_speed_max[port]; 2458 for (idx = 0; idx < sizeof(mac_big_hg_speed_list) / 2459 sizeof(mac_big_hg_speed_list[0]); idx++) { 2460 if (port_speed_max < mac_big_hg_speed_list[idx].speed) { 2461 break; 2462 } 2463 ability->speed_full_duplex |= mac_big_hg_speed_list[idx].pa_flag; 2464 } 2465 } 2466 2467 LOG_VERBOSE(BSL_LS_SOC_10G, 2468 (BSL_META_U(unit, 2469 "mac_big_ability_local_get: unit %d port %s " 2470 "speed_half=0x%x speed_full=0x%x encap=0x%x pause=0x%x " 2471 "interface=0x%x medium=0x%x loopback=0x%x flags=0x%x\n"), 2472 unit, SOC_PORT_NAME(unit, port), 2473 ability->speed_half_duplex, ability->speed_full_duplex, 2474 ability->encap, ability->pause, ability->interface, 2475 ability->medium, ability->loopback, ability->flags)); 2476 return SOC_E_NONE; 2477 } 2478 2479 /* Exported BigMAC driver structure */ 2480 mac_driver_t soc_mac_big = { 2481 "BigMAC Driver", /* drv_name */ 2482 mac_big_init, /* md_init */ 2483 mac_big_enable_set, /* md_enable_set */ 2484 mac_big_enable_get, /* md_enable_get */ 2485 mac_big_duplex_set, /* md_duplex_set */ 2486 mac_big_duplex_get, /* md_duplex_get */ 2487 mac_big_speed_set, /* md_speed_set */ 2488 mac_big_speed_get, /* md_speed_get */ 2489 mac_big_pause_set, /* md_pause_set */ 2490 mac_big_pause_get, /* md_pause_get */ 2491 mac_big_pause_addr_set, /* md_pause_addr_set */ 2492 mac_big_pause_addr_get, /* md_pause_addr_get */ 2493 mac_big_loopback_set, /* md_lb_set */ 2494 mac_big_loopback_get, /* md_lb_get */ 2495 mac_big_interface_set, /* md_interface_set */ 2496 mac_big_interface_get, /* md_interface_get */ 2497 NULL, /* md_ability_get - Deprecated */ 2498 mac_big_frame_max_set, /* md_frame_max_set */ 2499 mac_big_frame_max_get, /* md_frame_max_get */ 2500 mac_big_ifg_set, /* md_ifg_set */ 2501 mac_big_ifg_get, /* md_ifg_get */ 2502 mac_big_encap_set, /* md_encap_set */ 2503 mac_big_encap_get, /* md_encap_get */ 2504 mac_big_control_set, /* md_control_set */ 2505 mac_big_control_get, /* md_control_get */ 2506 mac_big_ability_local_get, /* md_ability_local_get */ 2507 NULL /* md_timesync_tx_info_get */ 2508 }; 2509 2510 #endif /* BCM_BIGMAC_SUPPORT */