xlmac.c (96517B)
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 * XLMAC driver 8 */ 9 10 #include <shared/bsl.h> 11 #include <bcm/types.h> 12 #include <sal/core/libc.h> 13 #include <shared/alloc.h> 14 #include <sal/core/spl.h> 15 #include <sal/core/boot.h> 16 #include <soc/drv.h> 17 #include <soc/error.h> 18 #include <soc/cmic.h> 19 #include <soc/portmode.h> 20 #include <soc/ll.h> 21 #include <soc/counter.h> 22 #include <soc/macutil.h> 23 #include <soc/phyctrl.h> 24 #ifdef BCM_GREYHOUND_SUPPORT 25 #include <soc/greyhound.h> 26 #endif 27 #ifdef BCM_SABER2_SUPPORT 28 #include <soc/saber2.h> 29 #endif 30 #ifdef BCM_GREYHOUND2_SUPPORT 31 #include <soc/greyhound2.h> 32 #endif 33 34 #ifdef BCM_XLMAC_SUPPORT 35 36 #define XLMAC_RUNT_THRESHOLD_IEEE 0x40 /* Runt threshold value for IEEE ports */ 37 #define XLMAC_RUNT_THRESHOLD_HG1 0x48 /* Runt threshold value for HG1 ports */ 38 #define XLMAC_RUNT_THRESHOLD_HG2 0x4c /* Runt threshold value for HG2 ports */ 39 40 /* 41 * XLMAC Register field definitions. 42 */ 43 44 #define JUMBO_MAXSZ 0x3fe8 /* Max legal value (per regsfile) */ 45 46 mac_driver_t soc_mac_xl; 47 48 #ifdef BROADCOM_DEBUG 49 static char *mac_xl_encap_mode[] = SOC_ENCAP_MODE_NAMES_INITIALIZER; 50 static char *mac_xl_port_if_names[] = SOC_PORT_IF_NAMES_INITIALIZER; 51 #endif /* BROADCOM_DEBUG */ 52 53 #define SOC_XLMAC_SPEED_10 0x0 54 #define SOC_XLMAC_SPEED_100 0x1 55 #define SOC_XLMAC_SPEED_1000 0x2 56 #define SOC_XLMAC_SPEED_2500 0x3 57 #define SOC_XLMAC_SPEED_10000 0x4 58 59 #define SOC_XLMAC_XLPORT_MODE_SINGLE 4 60 #define SOC_XLMAC_XLPORT_MODE_QUAD 0 61 62 /* Transmit CRC Modes */ 63 #define XLMAC_CRC_APPEND 0x0 64 #define XLMAC_CRC_KEEP 0x1 65 #define XLMAC_CRC_REPLACE 0x2 66 #define XLMAC_CRC_PER_PKT_MODE 0x3 67 68 #ifdef BCM_SABER2_SUPPORT 69 typedef struct { 70 uint64 mac_ctrl; 71 uint64 rx_ctrl; 72 uint64 tx_ctrl; 73 uint64 pfc_ctrl; 74 uint64 pfc_type; 75 uint64 pfc_opcode; 76 uint64 pfc_da; 77 uint64 rx_max_size; 78 uint64 mac_mode; 79 uint64 pause_ctrl; 80 uint64 rx_mac_sa; 81 uint64 tx_mac_sa; 82 uint64 llfc_ctrl; 83 uint64 eee_ctrl; 84 uint64 eee_timers; 85 uint64 rx_lss_ctrl; 86 uint64 rx_vlan_tag; 87 uint64 e2e_ctrl; 88 } _xlmac_x_cfg_t; 89 #endif 90 91 struct { 92 int speed; 93 uint32 clock_rate; 94 }_mac_xl_clock_rate[] = { 95 { 40000, 312 }, 96 { 20000, 156 }, 97 { 10000, 78 }, 98 { 5000, 78 }, 99 { 2500, 312 }, 100 { 1000, 125 }, 101 { 0, 25 }, 102 }; 103 104 /* 105 * WAN mode throttling 106 * THROT_10G_TO_5G: throt_num=21 throt_denom=21 107 * THROT_10G_TO_2P5G: throt_num=63 throt_denom=21 108 */ 109 #define XLMAC_THROT_10G_TO_5G 256 110 #define XLMAC_THROT_10G_TO_2P5G 257 111 112 STATIC int 113 _mac_xl_timestamp_delay_set(int unit, soc_port_t port, int speed); 114 STATIC int 115 mac_xl_speed_get(int unit, soc_port_t port, int *speed); 116 STATIC int 117 mac_xl_encap_get(int unit, soc_port_t port, int *mode); 118 void 119 _mac_xl_speed_to_clock_rate(int unit, soc_port_t port, int speed, 120 uint32 *clock_rate) 121 { 122 int idx; 123 124 125 for (idx = 0; 126 idx < sizeof(_mac_xl_clock_rate) / sizeof(_mac_xl_clock_rate[0]); 127 idx++) { 128 if (speed >=_mac_xl_clock_rate[idx].speed) { 129 *clock_rate = _mac_xl_clock_rate[idx].clock_rate; 130 return; 131 } 132 } 133 *clock_rate = 0; 134 } 135 136 STATIC int 137 _mac_xl_drain_cells(int unit, soc_port_t port, int notify_phy, int queue_enable) 138 { 139 int rv; 140 int pause_tx, pause_rx, pfc_rx, llfc_rx; 141 soc_field_t fields[2]; 142 uint32 values[2], fval; 143 uint64 mac_ctrl, rval64; 144 soc_timeout_t to; 145 #ifdef BCM_GREYHOUND_SUPPORT 146 uint32 mmu_fc = 0; 147 #endif 148 149 rv = SOC_E_NONE; 150 151 if (SOC_IS_RELOADING(unit)) { 152 return rv; 153 } 154 155 #ifdef BCM_GREYHOUND_SUPPORT 156 if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit)) { 157 SOC_IF_ERROR_RETURN 158 (soc_mmu_flush_enable(unit, port, TRUE)); 159 LOG_VERBOSE(BSL_LS_SOC_COMMON, 160 (BSL_META_U(unit, 161 "port %d xlmac mmu flush enable completed\n"), 162 port)); 163 /* clear the MMU pause state*/ 164 SOC_IF_ERROR_RETURN( 165 READ_MMU_FC_RX_ENr(unit, port, &mmu_fc)); 166 SOC_IF_ERROR_RETURN( 167 WRITE_MMU_FC_RX_ENr(unit, port, 0)); 168 } 169 #endif 170 171 #if defined(BCM_SABER2_SUPPORT) 172 if(SOC_IS_SABER2(unit)) { 173 SOC_IF_ERROR_RETURN(soc_mmu_flush_enable(unit, port, TRUE)); 174 LOG_VERBOSE(BSL_LS_SOC_COMMON, 175 (BSL_META_U(unit, 176 "port %d xlmac mmu flush enable completed\n"), 177 port)); 178 } 179 #endif 180 181 /* Disable pause/pfc function */ 182 SOC_IF_ERROR_RETURN 183 (soc_mac_xl.md_pause_get(unit, port, &pause_tx, &pause_rx)); 184 SOC_IF_ERROR_RETURN 185 (soc_mac_xl.md_pause_set(unit, port, pause_tx, 0)); 186 187 SOC_IF_ERROR_RETURN 188 (soc_mac_xl.md_control_get(unit, port, SOC_MAC_CONTROL_PFC_RX_ENABLE, 189 &pfc_rx)); 190 SOC_IF_ERROR_RETURN 191 (soc_mac_xl.md_control_set(unit, port, SOC_MAC_CONTROL_PFC_RX_ENABLE, 192 0)); 193 194 SOC_IF_ERROR_RETURN 195 (soc_mac_xl.md_control_get(unit, port, SOC_MAC_CONTROL_LLFC_RX_ENABLE, 196 &llfc_rx)); 197 SOC_IF_ERROR_RETURN 198 (soc_mac_xl.md_control_set(unit, port, SOC_MAC_CONTROL_LLFC_RX_ENABLE, 199 0)); 200 201 /* Assert SOFT_RESET before DISCARD just in case there is no credit left */ 202 SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &mac_ctrl)); 203 soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, SOFT_RESETf, 1); 204 205 /* Drain data in TX FIFO without egressing at packet boundary */ 206 SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, mac_ctrl)); 207 fields[0] = DISCARDf; 208 values[0] = 1; 209 fields[1] = EP_DISCARDf; 210 values[1] = 1; 211 SOC_IF_ERROR_RETURN(soc_reg_fields32_modify(unit, XLMAC_TX_CTRLr, port, 2, 212 fields, values)); 213 214 /* Reset EP credit before de-assert SOFT_RESET */ 215 if (!SOC_IS_HURRICANE2(unit)) { 216 SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port)); 217 } 218 219 /* De-assert SOFT_RESET to let the drain start */ 220 soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, SOFT_RESETf, 0); 221 SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, mac_ctrl)); 222 223 if (notify_phy == 1) 224 { 225 /* Notify PHY driver */ 226 SOC_IF_ERROR_RETURN 227 (soc_phyctrl_notify(unit, port, phyEventStop, PHY_STOP_DRAIN)); 228 } 229 230 /* Wait until mmu cell count is 0 */ 231 rv = soc_egress_drain_cells(unit, port, 250000); 232 if (SOC_E_NONE == rv) { 233 /* Wait until TX fifo cell count is 0 */ 234 soc_timeout_init(&to, 250000, 0); 235 for (;;) { 236 rv = READ_XLMAC_TXFIFO_CELL_CNTr(unit, port, &rval64); 237 if (SOC_E_NONE != rv) { 238 break; 239 } 240 fval = soc_reg64_field32_get(unit, XLMAC_TXFIFO_CELL_CNTr, rval64, 241 CELL_CNTf); 242 if (fval == 0) { 243 break; 244 } 245 if (soc_timeout_check(&to)) { 246 LOG_ERROR(BSL_LS_SOC_XLMAC, 247 (BSL_META_U(unit, 248 "ERROR: port %d:%s: " 249 "timeout draining TX FIFO (%d cells remain)\n"), 250 unit, SOC_PORT_NAME(unit, port), fval)); 251 rv = SOC_E_INTERNAL; 252 break; 253 } 254 } 255 } 256 257 if (notify_phy == 1) 258 { /* Notify PHY driver */ 259 SOC_IF_ERROR_RETURN 260 (soc_phyctrl_notify(unit, port, phyEventResume, PHY_STOP_DRAIN)); 261 } 262 263 /* Stop TX FIFO drainging */ 264 values[0] = 0; 265 values[1] = 0; 266 SOC_IF_ERROR_RETURN(soc_reg_fields32_modify(unit, XLMAC_TX_CTRLr, port, 2, 267 fields, values)); 268 269 #ifdef BCM_GREYHOUND_SUPPORT 270 if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit)) { 271 SOC_IF_ERROR_RETURN 272 (soc_mmu_flush_enable(unit, port, FALSE)); 273 LOG_VERBOSE(BSL_LS_SOC_COMMON, 274 (BSL_META_U(unit, 275 "port %d xlmac mmu flush disabled\n"), 276 port)); 277 /* restore the MMU pause state*/ 278 SOC_IF_ERROR_RETURN( 279 WRITE_MMU_FC_RX_ENr(unit, port, mmu_fc)); 280 } 281 #endif 282 283 #if defined(BCM_SABER2_SUPPORT) 284 if (SOC_IS_SABER2(unit) && queue_enable) { 285 SOC_IF_ERROR_RETURN(soc_mmu_flush_enable(unit, port, FALSE)); 286 LOG_VERBOSE(BSL_LS_SOC_COMMON, 287 (BSL_META_U(unit, 288 "port %d xlmac mmu flush disabled\n"), 289 port)); 290 } 291 #endif 292 293 /* Restore original pause/pfc/llfc configuration */ 294 SOC_IF_ERROR_RETURN 295 (soc_mac_xl.md_pause_set(unit, port, pause_tx, pause_rx)); 296 SOC_IF_ERROR_RETURN 297 (soc_mac_xl.md_control_set(unit, port, SOC_MAC_CONTROL_PFC_RX_ENABLE, 298 pfc_rx)); 299 SOC_IF_ERROR_RETURN 300 (soc_mac_xl.md_control_set(unit, port, SOC_MAC_CONTROL_LLFC_RX_ENABLE, 301 llfc_rx)); 302 303 return rv; 304 } 305 306 /* 307 * Function: 308 * _mac_xl_timestamp_byte_adjust_set 309 * Purpose: 310 * Set timestamp byte adjust values. 311 * Parameters: 312 * unit - XGS unit #. 313 * port - Port number on unit. 314 * Returns: 315 * SOC_E_XXX 316 */ 317 STATIC int 318 _mac_xl_timestamp_byte_adjust_set(int unit, soc_port_t port) 319 { 320 uint64 ctrl; 321 uint32 ctrl32; 322 323 if (SOC_REG_PORT_VALID(unit, MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr, port) && 324 (IS_GE_PORT(unit, port)) ) { 325 /* for viper ports on SB2 A0 */ 326 SOC_IF_ERROR_RETURN(READ_MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, &ctrl32)); 327 soc_reg_field_set(unit, MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr, &ctrl32, 328 TX_TIMER_BYTE_ADJUSTf, 8); 329 SOC_IF_ERROR_RETURN(WRITE_MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, ctrl32)); 330 331 SOC_IF_ERROR_RETURN(READ_MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, &ctrl32)); 332 soc_reg_field_set(unit, MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr, &ctrl32, 333 TX_TIMER_BYTE_ADJUST_ENf, 1); 334 SOC_IF_ERROR_RETURN(WRITE_MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, ctrl32)); 335 336 SOC_IF_ERROR_RETURN(READ_MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, &ctrl32)); 337 soc_reg_field_set(unit, MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr, &ctrl32, 338 RX_TIMER_BYTE_ADJUSTf, 8); 339 SOC_IF_ERROR_RETURN(WRITE_MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, ctrl32)); 340 341 SOC_IF_ERROR_RETURN(READ_MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, &ctrl32)); 342 soc_reg_field_set(unit, MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr, &ctrl32, 343 RX_TIMER_BYTE_ADJUST_ENf, 1); 344 SOC_IF_ERROR_RETURN(WRITE_MXQ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, ctrl32)); 345 } 346 347 if (SOC_REG_PORT_VALID(unit, XLMAC_TIMESTAMP_BYTE_ADJUSTr, port) && 348 (IS_GE_PORT(unit, port)) ) { 349 /* for viper and eagle ports on SB2 B0 */ 350 SOC_IF_ERROR_RETURN(READ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, &ctrl)); 351 soc_reg64_field32_set(unit, XLMAC_TIMESTAMP_BYTE_ADJUSTr, &ctrl, 352 TX_TIMER_BYTE_ADJUSTf, 8); 353 SOC_IF_ERROR_RETURN(WRITE_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, ctrl)); 354 355 SOC_IF_ERROR_RETURN(READ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, &ctrl)); 356 soc_reg64_field32_set(unit, XLMAC_TIMESTAMP_BYTE_ADJUSTr, &ctrl, 357 TX_TIMER_BYTE_ADJUST_ENf, 1); 358 SOC_IF_ERROR_RETURN(WRITE_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, ctrl)); 359 360 SOC_IF_ERROR_RETURN(READ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, &ctrl)); 361 soc_reg64_field32_set(unit, XLMAC_TIMESTAMP_BYTE_ADJUSTr, &ctrl, 362 RX_TIMER_BYTE_ADJUSTf, 8); 363 SOC_IF_ERROR_RETURN(WRITE_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, ctrl)); 364 365 SOC_IF_ERROR_RETURN(READ_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, &ctrl)); 366 soc_reg64_field32_set(unit, XLMAC_TIMESTAMP_BYTE_ADJUSTr, &ctrl, 367 RX_TIMER_BYTE_ADJUST_ENf, 1); 368 SOC_IF_ERROR_RETURN(WRITE_XLMAC_TIMESTAMP_BYTE_ADJUSTr(unit, port, ctrl)); 369 } 370 371 return SOC_E_NONE; 372 } 373 374 /* 375 * Function: 376 * mac_xl_init 377 * Purpose: 378 * Initialize Xlmac into a known good state. 379 * Parameters: 380 * unit - XGS unit #. 381 * port - Port number on unit. 382 * Returns: 383 * SOC_E_XXX 384 * Notes: 385 */ 386 STATIC int 387 mac_xl_init(int unit, soc_port_t port) 388 { 389 soc_info_t *si; 390 uint64 mac_ctrl, rx_ctrl, tx_ctrl, rval; 391 uint32 ipg; 392 int mode; 393 int encap = 0; 394 int runt; 395 #if defined(BCM_SABER2_SUPPORT) 396 int sgn_det = 0; 397 uint32 sgn_crs; 398 #endif 399 400 401 402 LOG_VERBOSE(BSL_LS_SOC_10G, 403 (BSL_META_U(unit, 404 "mac_xl_init: unit %d port %s\n"), 405 unit, SOC_PORT_NAME(unit, port))); 406 407 si = &SOC_INFO(unit); 408 409 /* Disable Tx/Rx, assume that MAC is stable (or out of reset) */ 410 SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &mac_ctrl)); 411 412 /* Reset EP credit before de-assert SOFT_RESET */ 413 if (soc_reg64_field32_get(unit, XLMAC_CTRLr, mac_ctrl, SOFT_RESETf)) { 414 SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port)); 415 } 416 417 soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, SOFT_RESETf, 0); 418 soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, RX_ENf, 0); 419 soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, TX_ENf, 0); 420 soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, 421 XGMII_IPG_CHECK_DISABLEf, 422 IS_HG_PORT(unit, port) ? 1 : 0); 423 SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, mac_ctrl)); 424 425 if (IS_ST_PORT(unit, port)) { 426 soc_mac_xl.md_pause_set(unit, port, FALSE, FALSE); 427 } else { 428 soc_mac_xl.md_pause_set(unit, port, TRUE, TRUE); 429 } 430 431 SOC_IF_ERROR_RETURN 432 (soc_reg_field32_modify(unit, XLMAC_PFC_CTRLr, port, PFC_REFRESH_ENf, 433 1)); 434 435 if (soc_property_port_get(unit, port, spn_PHY_WAN_MODE, FALSE)) { 436 SOC_IF_ERROR_RETURN 437 (soc_mac_xl.md_control_set(unit, port, 438 SOC_MAC_CONTROL_FRAME_SPACING_STRETCH, 439 13)); 440 } 441 442 /* Set jumbo max size (8000 byte payload) */ 443 COMPILER_64_ZERO(rval); 444 #ifdef BCM_XGS_SUPPORT 445 if (SOC_IS_XGS3_SWITCH(unit)) { 446 uint32 rval; 447 soc_reg_t reg; 448 reg = SOC_REG_IS_VALID(unit, EGR_MTUr) ? EGR_MTUr : EGR_MTU_SIZEr; 449 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 450 soc_reg_field_set(unit, reg, &rval, MTU_SIZEf, SOC_INFO(unit).max_mtu); 451 if (soc_reg_field_valid(unit, reg, MTU_ENABLEf)) { 452 soc_reg_field_set(unit, reg, &rval, MTU_ENABLEf, 1); 453 } 454 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval)); 455 } 456 457 if (SOC_IS_XGS(unit)) { 458 soc_reg64_field32_set(unit, XLMAC_RX_MAX_SIZEr, &rval, RX_MAX_SIZEf, 459 SOC_INFO(unit).max_mtu); 460 } else 461 #endif 462 { 463 soc_reg64_field32_set(unit, XLMAC_RX_MAX_SIZEr, &rval, RX_MAX_SIZEf, 464 JUMBO_MAXSZ); 465 } 466 SOC_IF_ERROR_RETURN(WRITE_XLMAC_RX_MAX_SIZEr(unit, port, rval)); 467 468 /* Setup header mode, check for property for higig2 mode */ 469 COMPILER_64_ZERO(rval); 470 if (!IS_XE_PORT(unit, port) && !IS_GE_PORT(unit, port)) { 471 mode = soc_property_port_get(unit, port, spn_HIGIG2_HDR_MODE, 472 soc_feature(unit, soc_feature_no_higig_plus) ? 1 : 0) ? 2 : 1; 473 soc_reg64_field32_set(unit, XLMAC_MODEr, &rval, HDR_MODEf, mode); 474 encap = mode; 475 } 476 switch (si->port_speed_max[port]) { 477 case 10: 478 mode = SOC_XLMAC_SPEED_10; 479 break; 480 case 100: 481 mode = SOC_XLMAC_SPEED_100; 482 break; 483 case 1000: 484 mode = SOC_XLMAC_SPEED_1000; 485 break; 486 case 2500: 487 mode = SOC_XLMAC_SPEED_2500; 488 break; 489 default: 490 mode = SOC_XLMAC_SPEED_10000; 491 break; 492 } 493 soc_reg64_field32_set(unit, XLMAC_MODEr, &rval, SPEED_MODEf, mode); 494 SOC_IF_ERROR_RETURN(WRITE_XLMAC_MODEr(unit, port, rval)); 495 496 /* init IPG and RUNT_THRESHOLD after port encap mode been established. */ 497 if (encap == 1) { 498 ipg = SOC_PERSIST(unit)->ipg[port].fd_hg; 499 runt = XLMAC_RUNT_THRESHOLD_HG1; 500 } else if (encap == 2) { 501 ipg = SOC_PERSIST(unit)->ipg[port].fd_hg2; 502 runt = XLMAC_RUNT_THRESHOLD_HG2; 503 } else { 504 ipg = SOC_PERSIST(unit)->ipg[port].fd_xe; 505 runt = XLMAC_RUNT_THRESHOLD_IEEE; 506 } 507 508 SOC_IF_ERROR_RETURN(READ_XLMAC_TX_CTRLr(unit, port, &tx_ctrl)); 509 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &tx_ctrl, AVERAGE_IPGf, 510 (ipg / 8) & 0x1f); 511 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &tx_ctrl, CRC_MODEf, 512 XLMAC_CRC_PER_PKT_MODE); 513 SOC_IF_ERROR_RETURN(WRITE_XLMAC_TX_CTRLr(unit, port, tx_ctrl)); 514 515 SOC_IF_ERROR_RETURN(READ_XLMAC_RX_CTRLr(unit, port, &rx_ctrl)); 516 soc_reg64_field32_set(unit, XLMAC_RX_CTRLr, &rx_ctrl, STRIP_CRCf, 0); 517 soc_reg64_field32_set(unit, XLMAC_RX_CTRLr, &rx_ctrl, STRICT_PREAMBLEf, 518 si->port_speed_max[port] >= 10000 && 519 IS_XE_PORT(unit, port) ? 1 : 0); 520 521 /* assigning RUNT_THRESHOLD (per encap mode) */ 522 soc_reg64_field32_set(unit, XLMAC_RX_CTRLr, &rx_ctrl, RUNT_THRESHOLDf, 523 runt); 524 SOC_IF_ERROR_RETURN(WRITE_XLMAC_RX_CTRLr(unit, port, rx_ctrl)); 525 526 /* assigning proper init setting for EEE feature per speed */ 527 if (soc_feature(unit, soc_feature_eee)) { 528 SOC_IF_ERROR_RETURN(soc_port_eee_timers_init(unit, 529 port, si->port_speed_max[port])); 530 } 531 532 SOC_IF_ERROR_RETURN(READ_XLMAC_RX_LSS_CTRLr(unit, port, &rval)); 533 soc_reg64_field32_set(unit, XLMAC_RX_LSS_CTRLr, &rval, 534 DROP_TX_DATA_ON_LOCAL_FAULTf, 1); 535 soc_reg64_field32_set(unit, XLMAC_RX_LSS_CTRLr, &rval, 536 DROP_TX_DATA_ON_REMOTE_FAULTf, 1); 537 soc_reg64_field32_set(unit, XLMAC_RX_LSS_CTRLr, &rval, 538 DROP_TX_DATA_ON_LINK_INTERRUPTf, 1); 539 SOC_IF_ERROR_RETURN(WRITE_XLMAC_RX_LSS_CTRLr(unit, port, rval)); 540 541 if (SOC_REG_IS_VALID(unit, XLMAC_MACSEC_CTRLr)) { 542 /* Enable Tx CRC corruption */ 543 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XLMAC_MACSEC_CTRLr, port, 544 MACSEC_TX_CRC_CORRUPT_ENf, 1)); 545 } 546 #if defined(BCM_SABER2_SUPPORT) 547 if (SOC_IS_SABER2(unit)){ 548 SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &mac_ctrl)); 549 soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, EXTENDED_HIG2_ENf, 1); 550 soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, SW_LINK_STATUSf, 1); 551 SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, mac_ctrl)); 552 553 sgn_det = soc_property_port_get(unit, port, spn_SERDES_RX_LOS, 0); 554 SOC_IF_ERROR_RETURN(READ_X_GPORT_SGNDET_EARLYCRSr(unit, port, &sgn_crs)); 555 soc_reg_field_set(unit, X_GPORT_SGNDET_EARLYCRSr, &sgn_crs, SGN_DETf, sgn_det); 556 SOC_IF_ERROR_RETURN(WRITE_X_GPORT_SGNDET_EARLYCRSr(unit, port, sgn_crs)); 557 } 558 559 #endif 560 561 /* Disable loopback and bring XLMAC out of reset */ 562 SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &mac_ctrl)); 563 soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, LOCAL_LPBKf, 0); 564 soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, RX_ENf, 1); 565 soc_reg64_field32_set(unit, XLMAC_CTRLr, &mac_ctrl, TX_ENf, 1); 566 SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, mac_ctrl)); 567 568 SOC_IF_ERROR_RETURN(_mac_xl_timestamp_byte_adjust_set(unit, port)); 569 return SOC_E_NONE; 570 } 571 572 /* 573 * Function: 574 * mac_xl_egress_queue_drain 575 * Purpose: 576 * Drain the egress queues with out bringing down the port 577 * Parameters: 578 * unit - XGS unit #. 579 * port - Port number on unit. 580 * Returns: 581 * SOC_E_XXX 582 */ 583 STATIC int 584 mac_xl_egress_queue_drain(int unit, soc_port_t port) 585 { 586 uint64 ctrl, octrl; 587 pbmp_t mask; 588 int rx_enable = 0; 589 int is_active = 0; 590 591 LOG_VERBOSE(BSL_LS_SOC_10G, 592 (BSL_META_U(unit, 593 "mac_xl_egress_queue_drain: unit %d port %s \n"), 594 unit, SOC_PORT_NAME(unit, port))); 595 596 SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &ctrl)); 597 octrl = ctrl; 598 599 rx_enable = soc_reg64_field32_get(unit, XLMAC_CTRLr, ctrl, RX_ENf); 600 /* Don't disable TX since it stops egress and hangs if CPU sends */ 601 soc_reg64_field32_set(unit, XLMAC_CTRLr, &ctrl, TX_ENf, 1); 602 soc_reg64_field32_set(unit, XLMAC_CTRLr, &ctrl, RX_ENf, 0); 603 /* Disable RX */ 604 SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, ctrl)); 605 606 /* Remove port from EPC_LINK */ 607 soc_link_mask2_get(unit, &mask); 608 if (SOC_PBMP_MEMBER(mask, port)) { 609 is_active = 1; 610 SOC_PBMP_PORT_REMOVE(mask, port); 611 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 612 } 613 614 /* Drain cells */ 615 SOC_IF_ERROR_RETURN(_mac_xl_drain_cells(unit, port, 0, TRUE)); 616 617 /* Reset port FIFO */ 618 SOC_IF_ERROR_RETURN(soc_port_fifo_reset(unit, port)); 619 620 /* Put port into SOFT_RESET */ 621 soc_reg64_field32_set(unit, XLMAC_CTRLr, &ctrl, SOFT_RESETf, 1); 622 SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, ctrl)); 623 624 /* Reset EP credit before de-assert SOFT_RESET */ 625 SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port)); 626 SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &ctrl)); 627 soc_reg64_field32_set(unit, XLMAC_CTRLr, &ctrl, RX_ENf, rx_enable ? 1 : 0); 628 629 /* Enable both TX and RX, deassert SOFT_RESET */ 630 soc_reg64_field32_set(unit, XLMAC_CTRLr, &ctrl, SOFT_RESETf, 0); 631 SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, ctrl)); 632 633 /* Restore XLMAC_CTRL to original value */ 634 SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, octrl)); 635 636 /* Add port to EPC_LINK */ 637 if(is_active) { 638 soc_link_mask2_get(unit, &mask); 639 SOC_PBMP_PORT_ADD(mask, port); 640 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 641 } 642 643 return SOC_E_NONE; 644 } 645 646 #if defined(BCM_SABER2_SUPPORT) 647 648 STATIC int _xlmac_x_register_store(int unit, soc_port_t port, _xlmac_x_cfg_t *port_cfg) 649 { 650 SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &port_cfg->mac_ctrl)); 651 SOC_IF_ERROR_RETURN(READ_XLMAC_RX_CTRLr(unit, port, &port_cfg->rx_ctrl)); 652 SOC_IF_ERROR_RETURN(READ_XLMAC_TX_CTRLr(unit, port, &port_cfg->tx_ctrl)); 653 SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_CTRLr(unit, port, &port_cfg->pfc_ctrl)); 654 SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_TYPEr(unit, port, &port_cfg->pfc_type)); 655 SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_OPCODEr(unit, port, &port_cfg->pfc_opcode)); 656 SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_DAr(unit, port, &port_cfg->pfc_da)); 657 SOC_IF_ERROR_RETURN(READ_XLMAC_RX_MAX_SIZEr(unit, port, &port_cfg->rx_max_size)); 658 SOC_IF_ERROR_RETURN(READ_XLMAC_MODEr(unit, port, &port_cfg->mac_mode)); 659 SOC_IF_ERROR_RETURN(READ_XLMAC_PAUSE_CTRLr(unit, port, &port_cfg->pause_ctrl)); 660 SOC_IF_ERROR_RETURN(READ_XLMAC_RX_MAC_SAr(unit, port, &port_cfg->rx_mac_sa)); 661 SOC_IF_ERROR_RETURN(READ_XLMAC_TX_MAC_SAr(unit, port, &port_cfg->tx_mac_sa)); 662 SOC_IF_ERROR_RETURN(READ_XLMAC_LLFC_CTRLr(unit, port, &port_cfg->llfc_ctrl)); 663 SOC_IF_ERROR_RETURN(READ_XLMAC_EEE_CTRLr(unit, port, &port_cfg->eee_ctrl)); 664 SOC_IF_ERROR_RETURN(READ_XLMAC_EEE_TIMERSr(unit, port, &port_cfg->eee_timers)); 665 SOC_IF_ERROR_RETURN(READ_XLMAC_RX_LSS_CTRLr(unit, port, &port_cfg->rx_lss_ctrl)); 666 SOC_IF_ERROR_RETURN(READ_XLMAC_RX_VLAN_TAGr(unit, port, &port_cfg->rx_vlan_tag)); 667 SOC_IF_ERROR_RETURN(READ_XLMAC_E2E_CTRLr(unit, port, &port_cfg->e2e_ctrl)); 668 return SOC_E_NONE; 669 } 670 671 STATIC int _xlmac_x_register_restore(int unit, soc_port_t port, _xlmac_x_cfg_t *port_cfg) 672 { 673 SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, port_cfg->mac_ctrl)); 674 SOC_IF_ERROR_RETURN(WRITE_XLMAC_RX_CTRLr(unit, port, port_cfg->rx_ctrl)); 675 SOC_IF_ERROR_RETURN(WRITE_XLMAC_TX_CTRLr(unit, port, port_cfg->tx_ctrl)); 676 SOC_IF_ERROR_RETURN(WRITE_XLMAC_PFC_CTRLr(unit, port, port_cfg->pfc_ctrl)); 677 SOC_IF_ERROR_RETURN(WRITE_XLMAC_PFC_TYPEr(unit, port, port_cfg->pfc_type)); 678 SOC_IF_ERROR_RETURN(WRITE_XLMAC_PFC_OPCODEr(unit, port, port_cfg->pfc_opcode)); 679 SOC_IF_ERROR_RETURN(WRITE_XLMAC_PFC_DAr(unit, port, port_cfg->pfc_da)); 680 SOC_IF_ERROR_RETURN(WRITE_XLMAC_RX_MAX_SIZEr(unit, port, port_cfg->rx_max_size)); 681 SOC_IF_ERROR_RETURN(WRITE_XLMAC_MODEr(unit, port, port_cfg->mac_mode)); 682 SOC_IF_ERROR_RETURN(WRITE_XLMAC_PAUSE_CTRLr(unit, port, port_cfg->pause_ctrl)); 683 SOC_IF_ERROR_RETURN(WRITE_XLMAC_RX_MAC_SAr(unit, port, port_cfg->rx_mac_sa)); 684 SOC_IF_ERROR_RETURN(WRITE_XLMAC_TX_MAC_SAr(unit, port, port_cfg->tx_mac_sa)); 685 SOC_IF_ERROR_RETURN(WRITE_XLMAC_LLFC_CTRLr(unit, port, port_cfg->llfc_ctrl)); 686 SOC_IF_ERROR_RETURN(WRITE_XLMAC_EEE_CTRLr(unit, port, port_cfg->eee_ctrl)); 687 SOC_IF_ERROR_RETURN(WRITE_XLMAC_EEE_TIMERSr(unit, port, port_cfg->eee_timers)); 688 SOC_IF_ERROR_RETURN(WRITE_XLMAC_RX_LSS_CTRLr(unit, port, port_cfg->rx_lss_ctrl)); 689 SOC_IF_ERROR_RETURN(WRITE_XLMAC_RX_VLAN_TAGr(unit, port, port_cfg->rx_vlan_tag)); 690 SOC_IF_ERROR_RETURN(WRITE_XLMAC_E2E_CTRLr(unit, port, port_cfg->e2e_ctrl)); 691 return SOC_E_NONE; 692 } 693 694 int _xlmac_sb2_shim_war(int unit, soc_port_t port) 695 { 696 uint32 soft_reset; 697 uint32 rval; 698 int p, index; 699 uint64 ctrl; 700 pbmp_t block_pbmp; 701 _xlmac_x_cfg_t *pcfg; 702 int speed = 1000; 703 704 BCM_PBMP_ASSIGN(block_pbmp, SOC_BLOCK_BITMAP(unit, SOC_PORT_BLOCK(unit, port))); 705 706 SOC_PBMP_ITER(block_pbmp, p) { 707 if (SOC_PBMP_MEMBER((PBMP_ALL(unit)), p)) { 708 SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, p, &ctrl)); 709 soft_reset = soc_reg64_field32_get(unit, 710 XLMAC_CTRLr, ctrl, SOFT_RESETf); 711 /* If any of the port in block is active, dont apply war */ 712 if(soft_reset != 1) { 713 return SOC_E_NONE; 714 } 715 } 716 } 717 /* Come here only when there is active war */ 718 pcfg = (_xlmac_x_cfg_t *) sal_alloc( 719 sizeof(_xlmac_x_cfg_t) * SB2_MAX_PORTS_PER_BLOCK,"XLMAC config"); 720 if (pcfg == NULL) { 721 return SOC_E_MEMORY; 722 } 723 724 index = 0; 725 SOC_PBMP_ITER(block_pbmp, p) { 726 if (SOC_PBMP_MEMBER((PBMP_ALL(unit)), p)) { 727 if(index >= SB2_MAX_PORTS_PER_BLOCK) { 728 sal_free(pcfg); 729 return SOC_E_INTERNAL; 730 } 731 SOC_IF_ERROR_CLEAN_RETURN 732 (_xlmac_x_register_store(unit, p, &pcfg[index]),sal_free(pcfg)); 733 index++; 734 } 735 } 736 p = SOC_BLOCK_PORT(unit, SOC_PORT_BLOCK(unit, port)); 737 SOC_IF_ERROR_CLEAN_RETURN(READ_XPORT_XMAC_CONTROLr(unit, p, &rval), sal_free(pcfg)); 738 soc_reg_field_set(unit, XPORT_XMAC_CONTROLr, &rval, XMAC_RESETf, 1); 739 SOC_IF_ERROR_CLEAN_RETURN(WRITE_XPORT_XMAC_CONTROLr(unit, p, rval), sal_free(pcfg)); 740 soc_reg_field_set(unit, XPORT_XMAC_CONTROLr, &rval, XMAC_RESETf, 0); 741 SOC_IF_ERROR_CLEAN_RETURN(WRITE_XPORT_XMAC_CONTROLr(unit, p, rval), sal_free(pcfg)); 742 743 index = 0; 744 SOC_PBMP_ITER(block_pbmp, p) { 745 if (SOC_PBMP_MEMBER((PBMP_ALL(unit)), p)) { 746 SOC_IF_ERROR_CLEAN_RETURN 747 (_xlmac_x_register_restore(unit, p, &pcfg[index]), 748 sal_free(pcfg)); 749 index++; 750 } 751 } 752 sal_free(pcfg); 753 754 /* reconfigure timestamp adjust after port block reset */ 755 index = 0; 756 SOC_PBMP_ITER(block_pbmp, p) { 757 if (SOC_PBMP_MEMBER((PBMP_ALL(unit)), p)) { 758 mac_xl_speed_get(unit, p, &speed); 759 _mac_xl_timestamp_delay_set(unit, p, speed); 760 index++; 761 } 762 } 763 return SOC_E_NONE; 764 } 765 #endif 766 767 /* 768 * Function: 769 * mac_xl_enable_set 770 * Purpose: 771 * Enable or disable MAC 772 * Parameters: 773 * unit - XGS unit #. 774 * port - Port number on unit. 775 * enable - TRUE to enable, FALSE to disable 776 * Returns: 777 * SOC_E_XXX 778 */ 779 STATIC int 780 mac_xl_enable_set(int unit, soc_port_t port, int enable) 781 { 782 uint64 ctrl, octrl; 783 pbmp_t mask; 784 uint32 soft_reset = 0; 785 int speed = 1000; 786 uint64 version, merge_config; 787 int xlmac_version; 788 789 LOG_VERBOSE(BSL_LS_SOC_10G, 790 (BSL_META_U(unit, 791 "mac_xl_enable_set: unit %d port %s enable=%s\n"), 792 unit, SOC_PORT_NAME(unit, port), 793 enable ? "True" : "False")); 794 795 SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &ctrl)); 796 octrl = ctrl; 797 /* Don't disable TX since it stops egress and hangs if CPU sends */ 798 soc_reg64_field32_set(unit, XLMAC_CTRLr, &ctrl, TX_ENf, 1); 799 soc_reg64_field32_set(unit, XLMAC_CTRLr, &ctrl, RX_ENf, enable ? 1 : 0); 800 801 if (COMPILER_64_EQ(ctrl, octrl)) { 802 /* SDK-49952 fix soluition : 803 * >> to avoid the unexpected early return to prevent this problem. 804 * 1. Problem occurred for disabling process only. 805 * 2. To comply origianl designing senario, XLMAC_CTRLr.SOFT_RESETf is 806 * used to early check to see if this port is at disabled state 807 * already. 808 */ 809 soft_reset = soc_reg64_field32_get(unit, 810 XLMAC_CTRLr, ctrl, SOFT_RESETf); 811 if ((enable) || (!enable && soft_reset)){ 812 return SOC_E_NONE; 813 } 814 } 815 816 if (enable) { 817 /* Reset EP credit before de-assert SOFT_RESET */ 818 SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port)); 819 820 #if defined(BCM_SABER2_SUPPORT) 821 if (SOC_IS_SABER2(unit)) { 822 SOC_IF_ERROR_RETURN(soc_mmu_flush_enable(unit, port, FALSE)); 823 } 824 #endif 825 826 /* Deassert SOFT_RESET */ 827 soc_reg64_field32_set(unit, XLMAC_CTRLr, &ctrl, SOFT_RESETf, 0); 828 829 /* Deassert EGR_XLPORT_BUFFER_SFT_RESET */ 830 SOC_IF_ERROR_RETURN(soc_port_egress_buffer_sft_reset(unit, port, 0)); 831 832 /* Enable both TX and RX */ 833 SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, ctrl)); 834 835 /* Enable MMU port */ 836 SOC_IF_ERROR_RETURN(soc_port_mmu_buffer_enable(unit, port, TRUE)); 837 838 /* Add port to EPC_LINK */ 839 soc_link_mask2_get(unit, &mask); 840 SOC_PBMP_PORT_ADD(mask, port); 841 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 842 843 /* Enable output threshold RX */ 844 SOC_IF_ERROR_RETURN 845 (soc_port_thdo_rx_enable_set(unit, port, 1)); 846 847 /* set timestamp adjust delay */ 848 mac_xl_speed_get(unit, port, &speed); 849 _mac_xl_timestamp_delay_set(unit, port, speed); 850 } else { 851 /* Disable RX */ 852 SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, ctrl)); 853 854 /* Remove port from EPC_LINK */ 855 soc_link_mask2_get(unit, &mask); 856 SOC_PBMP_PORT_REMOVE(mask, port); 857 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 858 sal_udelay(1000); 859 860 /* 861 * Disable MMU port 862 * for some devices where EPC_LINK can not block the SOBMH from cpu and 863 * no mechanism is avalible to reset EDATABUF. 864 */ 865 SOC_IF_ERROR_RETURN(soc_port_mmu_buffer_enable(unit, port, FALSE)); 866 867 /* Drain cells */ 868 SOC_IF_ERROR_RETURN(_mac_xl_drain_cells(unit, port, 1, FALSE)); 869 /* Reset egress_buffer */ 870 SOC_IF_ERROR_RETURN(soc_port_egress_buffer_sft_reset(unit, port, 1)); 871 872 /* Reset port FIFO */ 873 SOC_IF_ERROR_RETURN(soc_port_fifo_reset(unit, port)); 874 875 /* Put port into SOFT_RESET */ 876 soc_reg64_field32_set(unit, XLMAC_CTRLr, &ctrl, SOFT_RESETf, 1); 877 SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, ctrl)); 878 #if defined(BCM_SABER2_SUPPORT) 879 if(SOC_IS_SABER2(unit) && IS_MXQ_PORT(unit, port)) { 880 SOC_IF_ERROR_RETURN(_xlmac_sb2_shim_war(unit, port)); 881 } 882 #endif 883 /* Disable output threshold RX */ 884 SOC_IF_ERROR_RETURN 885 (soc_port_thdo_rx_enable_set(unit, port, 0)); 886 887 /* Forces rx_lost_eop sequence */ 888 if (SOC_REG_IS_VALID(unit, XLMAC_VERSION_IDr) && 889 SOC_REG_IS_VALID(unit, XLMAC_MERGE_CONFIGr)) { 890 891 SOC_IF_ERROR_RETURN(READ_XLMAC_VERSION_IDr(unit, port, &version)); 892 xlmac_version = 893 soc_reg64_field32_get( 894 unit, XLMAC_VERSION_IDr, version, XLMAC_VERSIONf); 895 if (xlmac_version >= 0xA043) { 896 /* Set SW force */ 897 SOC_IF_ERROR_RETURN( 898 READ_XLMAC_MERGE_CONFIGr(unit, port, &merge_config)); 899 soc_reg64_field32_set( 900 unit, XLMAC_MERGE_CONFIGr, &merge_config, 901 SW_FORCE_RX_LOST_EOPf, 1); 902 SOC_IF_ERROR_RETURN( 903 WRITE_XLMAC_MERGE_CONFIGr(unit, port, merge_config)); 904 905 /* Clear SW force */ 906 SOC_IF_ERROR_RETURN( 907 READ_XLMAC_MERGE_CONFIGr(unit, port, &merge_config)); 908 soc_reg64_field32_set( 909 unit, XLMAC_MERGE_CONFIGr, &merge_config, 910 SW_FORCE_RX_LOST_EOPf, 0); 911 SOC_IF_ERROR_RETURN( 912 WRITE_XLMAC_MERGE_CONFIGr(unit, port, merge_config)); 913 } 914 } 915 916 } 917 918 return SOC_E_NONE; 919 } 920 921 /* 922 * Function: 923 * mac_xl_enable_get 924 * Purpose: 925 * Get MAC enable state 926 * Parameters: 927 * unit - XGS unit #. 928 * port - Port number on unit. 929 * enable - (OUT) TRUE if enabled, FALSE if disabled 930 * Returns: 931 * SOC_E_XXX 932 */ 933 STATIC int 934 mac_xl_enable_get(int unit, soc_port_t port, int *enable) 935 { 936 uint64 ctrl; 937 938 SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &ctrl)); 939 940 *enable = soc_reg64_field32_get(unit, XLMAC_CTRLr, ctrl, RX_ENf); 941 942 LOG_VERBOSE(BSL_LS_SOC_10G, 943 (BSL_META_U(unit, 944 "mac_xl_enable_get: unit %d port %s enable=%s\n"), 945 unit, SOC_PORT_NAME(unit, port), 946 *enable ? "True" : "False")); 947 948 return SOC_E_NONE; 949 } 950 951 952 953 /* 954 * Function: 955 * _mac_xl_timestamp_delay_set 956 * Purpose: 957 * Set Timestamp delay for one-step to account for lane and pipeline delay. 958 * Parameters: 959 * unit - XGS unit #. 960 * port - Port number on unit. 961 * speed - Speed 962 * phy_mode - single/dual/quad phy mode 963 * Returns: 964 * SOC_E_XXX 965 */ 966 STATIC int 967 _mac_xl_timestamp_delay_set(int unit, soc_port_t port, int speed) 968 { 969 uint64 ctrl; 970 uint32 clk_rate, tx_clk_ns; 971 int osts_delay; 972 uint32 field; 973 int divisor; 974 975 LOG_VERBOSE(BSL_LS_SOC_10G, 976 (BSL_META_U(unit, 977 "mac_xl_timestamp_delay_set: unit %d speed=%dMb port %s\n"), 978 unit, speed, SOC_PORT_NAME(unit, port))); 979 980 if (SOC_REG_IS_VALID(unit, XLMAC_TIMESTAMP_ADJUSTr)) { 981 SOC_IF_ERROR_RETURN(READ_XLMAC_TIMESTAMP_ADJUSTr(unit, port, &ctrl)); 982 983 _mac_xl_speed_to_clock_rate(unit, port, speed, &clk_rate); 984 /* Tx clock rate for single/dual/quad phy mode */ 985 if ((speed >= 5000) && (speed <= 40000)) { 986 divisor = speed > 20000 ? 1 : speed > 10000 ? 2 : 4; 987 /* tx clock rate in ns */ 988 tx_clk_ns = ((1000 / clk_rate) / divisor); 989 } else { 990 /* Same tx clk rate for < 10G for all phy modes*/ 991 tx_clk_ns = 1000 / clk_rate; 992 } 993 994 995 996 /* 997 * MAC pipeline delay for XGMII/XGMII mode is: 998 * = (5.5 * TX line clock period) + (Timestamp clock period) 999 */ 1000 /* signed value of pipeline delay in ns */ 1001 osts_delay = soc_property_port_get(unit, port, spn_TIMESTAMP_ADJUST(speed), 1002 SOC_TIMESYNC_PLL_CLOCK_NS(unit) - 1003 ((11 * tx_clk_ns ) / 2)); 1004 1005 if (SOC_E_NONE != soc_reg_signed_field_mask(unit, XLMAC_TIMESTAMP_ADJUSTr, 1006 TS_OSTS_ADJUSTf, osts_delay, &field)) { 1007 LOG_WARN(BSL_LS_SOC_PORT, (BSL_META_U(unit, 1008 "%s property out of bounds (is %d)\n"), 1009 spn_TIMESTAMP_ADJUST(speed), osts_delay)); 1010 field = 0; 1011 } 1012 1013 soc_reg64_field32_set(unit, XLMAC_TIMESTAMP_ADJUSTr, &ctrl, 1014 TS_OSTS_ADJUSTf, field); 1015 1016 #if 0 1017 /* 1018 * Lane delay for xlmac lanes 1019 * Lane_0(0-3) : 1 * TX line clock period 1020 * Lane_1(4-7) : 2 * TX line clock period 1021 * Lane_2(8-11) : 3 * TX line clock period 1022 * Lane_3(12-15): 4 * TX line clock period 1023 */ 1024 /* unsigned value of lane delay in ns */ 1025 delay = 1 * tx_clk_ns; 1026 soc_reg64_field32_set(unit, XLMAC_OSTS_TIMESTAMP_ADJUSTr, &ctrl, 1027 TS_ADJUST_DEMUX_DELAY_0f, delay ); 1028 delay = 2 * tx_clk_ns; 1029 soc_reg64_field32_set(unit, XLMAC_OSTS_TIMESTAMP_ADJUSTr, &ctrl, 1030 TS_ADJUST_DEMUX_DELAY_1f, delay ); 1031 delay = 3 * tx_clk_ns; 1032 soc_reg64_field32_set(unit, XLMAC_OSTS_TIMESTAMP_ADJUSTr, &ctrl, 1033 TS_ADJUST_DEMUX_DELAY_2f, delay ); 1034 delay = 4 * tx_clk_ns; 1035 soc_reg64_field32_set(unit, XLMAC_OSTS_TIMESTAMP_ADJUSTr, &ctrl, 1036 TS_ADJUST_DEMUX_DELAY_3f, delay ); 1037 #endif 1038 SOC_IF_ERROR_RETURN(WRITE_XLMAC_TIMESTAMP_ADJUSTr(unit, port, ctrl)); 1039 } 1040 1041 /* Set Timestamp byte adjust values */ 1042 SOC_IF_ERROR_RETURN(_mac_xl_timestamp_byte_adjust_set(unit, port)); 1043 1044 return SOC_E_NONE; 1045 } 1046 1047 /* 1048 * Function: 1049 * mac_xl_duplex_set 1050 * Purpose: 1051 * Set XLMAC in the specified duplex mode. 1052 * Parameters: 1053 * unit - XGS unit #. 1054 * port - XGS port # on unit. 1055 * duplex - Boolean: true --> full duplex, false --> half duplex. 1056 * Returns: 1057 * SOC_E_XXX 1058 * Notes: 1059 */ 1060 STATIC int 1061 mac_xl_duplex_set(int unit, soc_port_t port, int duplex) 1062 { 1063 LOG_VERBOSE(BSL_LS_SOC_10G, 1064 (BSL_META_U(unit, 1065 "mac_xl_duplex_set: unit %d port %s duplex=%s\n"), 1066 unit, SOC_PORT_NAME(unit, port), 1067 duplex ? "Full" : "Half")); 1068 return SOC_E_NONE; 1069 } 1070 1071 /* 1072 * Function: 1073 * mac_xl_duplex_get 1074 * Purpose: 1075 * Get XLMAC duplex mode. 1076 * Parameters: 1077 * unit - XGS unit #. 1078 * duplex - (OUT) Boolean: true --> full duplex, false --> half duplex. 1079 * Returns: 1080 * SOC_E_XXX 1081 */ 1082 STATIC int 1083 mac_xl_duplex_get(int unit, soc_port_t port, int *duplex) 1084 { 1085 *duplex = TRUE; /* Always full duplex */ 1086 1087 LOG_VERBOSE(BSL_LS_SOC_10G, 1088 (BSL_META_U(unit, 1089 "mac_xl_duplex_get: unit %d port %s duplex=%s\n"), 1090 unit, SOC_PORT_NAME(unit, port), 1091 *duplex ? "Full" : "Half")); 1092 return SOC_E_NONE; 1093 } 1094 1095 /* 1096 * Function: 1097 * mac_xl_pause_set 1098 * Purpose: 1099 * Configure XLMAC to transmit/receive pause frames. 1100 * Parameters: 1101 * unit - XGS unit #. 1102 * port - XGS port # on unit. 1103 * pause_tx - Boolean: transmit pause or -1 (don't change) 1104 * pause_rx - Boolean: receive pause or -1 (don't change) 1105 * Returns: 1106 * SOC_E_XXX 1107 */ 1108 STATIC int 1109 mac_xl_pause_set(int unit, soc_port_t port, int pause_tx, int pause_rx) 1110 { 1111 static soc_field_t fields[2] = { TX_PAUSE_ENf, RX_PAUSE_ENf }; 1112 uint32 values[2]; 1113 1114 LOG_VERBOSE(BSL_LS_SOC_10G, 1115 (BSL_META_U(unit, 1116 "mac_xl_pause_set: unit %d port %s TX=%s RX=%s\n"), 1117 unit, SOC_PORT_NAME(unit, port), 1118 pause_tx != FALSE ? "on" : "off", 1119 pause_rx != FALSE ? "on" : "off")); 1120 1121 values[0] = pause_tx != FALSE ? 1 : 0; 1122 values[1] = pause_rx != FALSE ? 1 : 0; 1123 return soc_reg_fields32_modify(unit, XLMAC_PAUSE_CTRLr, port, 2, 1124 fields, values); 1125 } 1126 1127 /* 1128 * Function: 1129 * mac_xl_pause_get 1130 * Purpose: 1131 * Return the pause ability of XLMAC 1132 * Parameters: 1133 * unit - XGS unit #. 1134 * port - XGS port # on unit. 1135 * pause_tx - Boolean: transmit pause 1136 * pause_rx - Boolean: receive pause 1137 * pause_mac - MAC address used for pause transmission. 1138 * Returns: 1139 * SOC_E_XXX 1140 */ 1141 STATIC int 1142 mac_xl_pause_get(int unit, soc_port_t port, int *pause_tx, int *pause_rx) 1143 { 1144 uint64 rval; 1145 1146 SOC_IF_ERROR_RETURN(READ_XLMAC_PAUSE_CTRLr(unit, port, &rval)); 1147 *pause_tx = 1148 soc_reg64_field32_get(unit, XLMAC_PAUSE_CTRLr, rval, TX_PAUSE_ENf); 1149 *pause_rx = 1150 soc_reg64_field32_get(unit, XLMAC_PAUSE_CTRLr, rval, RX_PAUSE_ENf); 1151 LOG_VERBOSE(BSL_LS_SOC_10G, 1152 (BSL_META_U(unit, 1153 "mac_xl_pause_get: unit %d port %s TX=%s RX=%s\n"), 1154 unit, SOC_PORT_NAME(unit, port), 1155 *pause_tx ? "on" : "off", 1156 *pause_rx ? "on" : "off")); 1157 return SOC_E_NONE; 1158 } 1159 1160 /* 1161 * Function: 1162 * mac_xl_speed_set 1163 * Purpose: 1164 * Set XLMAC in the specified speed. 1165 * Parameters: 1166 * unit - XGS unit #. 1167 * port - XGS port # on unit. 1168 * speed - 10, 100, 1000, 2500, 10000, ... 1169 * Returns: 1170 * SOC_E_XXX 1171 */ 1172 STATIC int 1173 mac_xl_speed_set(int unit, soc_port_t port, int speed) 1174 { 1175 uint32 mode; 1176 int enable; 1177 static soc_field_t fields[2] = { 1178 LOCAL_FAULT_DISABLEf, REMOTE_FAULT_DISABLEf 1179 }; 1180 uint32 values[2]; 1181 uint32 rval = 0; 1182 1183 #ifdef BCM_GREYHOUND2_SUPPORT 1184 /* SDK-141840 Workaround for TSCE core connecting to Aquantia PHY */ 1185 if (SOC_IS_GREYHOUND2(unit)) { 1186 SOC_IF_ERROR_RETURN 1187 (soc_reg_field32_modify(unit, XLMAC_TX_CTRLr, port, TX_ANY_STARTf, 1188 0)); 1189 } 1190 #endif 1191 1192 LOG_VERBOSE(BSL_LS_SOC_10G, 1193 (BSL_META_U(unit, 1194 "mac_xl_speed_set: unit %d port %s speed=%dMb\n"), 1195 unit, SOC_PORT_NAME(unit, port), 1196 speed)); 1197 1198 switch (speed) { 1199 case 10: 1200 mode = SOC_XLMAC_SPEED_10; 1201 break; 1202 case 100: 1203 mode = SOC_XLMAC_SPEED_100; 1204 break; 1205 case 1000: 1206 mode = SOC_XLMAC_SPEED_1000; 1207 break; 1208 case 2500: 1209 #ifdef BCM_GREYHOUND2_SUPPORT 1210 /* SDK-141840 Workaround for TSCE core connecting to Aquantia PHY */ 1211 if (SOC_IS_GREYHOUND2(unit)) { 1212 SOC_IF_ERROR_RETURN 1213 (soc_reg_field32_modify(unit, XLMAC_TX_CTRLr, port, 1214 TX_ANY_STARTf, 1)); 1215 } 1216 #endif 1217 mode = SOC_XLMAC_SPEED_2500; 1218 break; 1219 case 5000: 1220 mode = SOC_XLMAC_SPEED_10000; 1221 break; 1222 case 0: 1223 return SOC_E_NONE; /* Support NULL PHY */ 1224 default: 1225 if (speed < 10000) { 1226 return SOC_E_PARAM; 1227 } 1228 mode = SOC_XLMAC_SPEED_10000; 1229 break; 1230 } 1231 1232 SOC_IF_ERROR_RETURN(mac_xl_enable_get(unit, port, &enable)); 1233 1234 if (enable) { 1235 /* Turn off TX/RX enable */ 1236 SOC_IF_ERROR_RETURN(mac_xl_enable_set(unit, port, 0)); 1237 } 1238 1239 /* Update the speed */ 1240 SOC_IF_ERROR_RETURN 1241 (soc_reg_field32_modify(unit, XLMAC_MODEr, port, SPEED_MODEf, mode)); 1242 1243 values[0] = values[1] = speed < 5000 ? 1 : 0; 1244 if (speed < 5000) { 1245 SOC_IF_ERROR_RETURN 1246 (soc_reg_fields32_modify(unit, XLMAC_RX_LSS_CTRLr, port, 2, fields, 1247 values)); 1248 } 1249 1250 /* 1251 * Not set REMOTE_FAULT/LOCAL_FAULT for 1G ports, 1252 * else HW Linkscan interrupt would be suppressed. 1253 */ 1254 if (SOC_IS_SABER2(unit) && IS_MXQ_PORT(unit, port)) { 1255 /* XLPORT_FAULT_LINK_STATUS is NA for MXQ ports on Saber2*/ 1256 } else { 1257 values[0] = values[1] = speed <= 1000 ? 0 : 1; 1258 soc_reg_field_set(unit, XLPORT_FAULT_LINK_STATUSr, &rval, 1259 REMOTE_FAULTf, values[0]); 1260 soc_reg_field_set(unit, XLPORT_FAULT_LINK_STATUSr, &rval, 1261 LOCAL_FAULTf, values[1]); 1262 SOC_IF_ERROR_RETURN(WRITE_XLPORT_FAULT_LINK_STATUSr(unit, port, rval)); 1263 } 1264 1265 /* Update port speed related setting in components other than MAC/SerDes*/ 1266 SOC_IF_ERROR_RETURN(soc_port_speed_update(unit, port, speed)); 1267 1268 /* Update port strict preamble */ 1269 SOC_IF_ERROR_RETURN 1270 (soc_reg_field32_modify(unit, XLMAC_RX_CTRLr, port, STRICT_PREAMBLEf, 1271 speed >= 10000 && IS_XE_PORT(unit, port) ? 1272 1 : 0)); 1273 /* 1274 * Notify internal PHY driver of speed change in case it is being 1275 * used as pass-through to an external PHY. 1276 */ 1277 if (!PHY_REPEATER(unit, port)) { 1278 SOC_IF_ERROR_RETURN 1279 (soc_phyctrl_notify(unit, port, phyEventSpeed, speed)); 1280 } 1281 1282 if (enable) { 1283 /* Re-enable transmitter and receiver */ 1284 SOC_IF_ERROR_RETURN(mac_xl_enable_set(unit, port, 1)); 1285 } 1286 1287 /* Set Timestamp Mac Delays */ 1288 SOC_IF_ERROR_RETURN(_mac_xl_timestamp_delay_set(unit, port, speed)); 1289 1290 /* assigning proper setting for Native EEE per speed */ 1291 if (soc_feature(unit, soc_feature_eee)) { 1292 SOC_IF_ERROR_RETURN(soc_port_eee_timers_setup(unit, port, speed)); 1293 } 1294 1295 return SOC_E_NONE; 1296 } 1297 1298 /* 1299 * Function: 1300 * mac_xl_speed_get 1301 * Purpose: 1302 * Get XLMAC speed 1303 * Parameters: 1304 * unit - XGS unit #. 1305 * port - XGS port # on unit. 1306 * speed - (OUT) speed in Mb 1307 * Returns: 1308 * SOC_E_XXX 1309 */ 1310 STATIC int 1311 mac_xl_speed_get(int unit, soc_port_t port, int *speed) 1312 { 1313 uint64 rval; 1314 #ifdef BCM_GREYHOUND2_SUPPORT 1315 int val = 0; 1316 #endif 1317 1318 SOC_IF_ERROR_RETURN(READ_XLMAC_MODEr(unit, port, &rval)); 1319 switch (soc_reg64_field32_get(unit, XLMAC_MODEr, rval, SPEED_MODEf)) { 1320 case SOC_XLMAC_SPEED_10: 1321 *speed = 10; 1322 break; 1323 case SOC_XLMAC_SPEED_100: 1324 *speed = 100; 1325 break; 1326 case SOC_XLMAC_SPEED_1000: 1327 *speed = 1000; 1328 break; 1329 case SOC_XLMAC_SPEED_2500: 1330 *speed = 2500; 1331 break; 1332 case SOC_XLMAC_SPEED_10000: 1333 default: 1334 *speed = 10000; 1335 break; 1336 } 1337 #ifdef BCM_GREYHOUND2_SUPPORT 1338 if (soc_feature(unit, soc_feature_xlmac_speed_display_above_10g)) { 1339 if (SOC_SUCCESS(soc_granular_speed_get(unit, port, &val))) { 1340 *speed = val; 1341 } 1342 } 1343 #endif 1344 LOG_VERBOSE(BSL_LS_SOC_10G, 1345 (BSL_META_U(unit, 1346 "mac_xl_speed_get: unit %d port %s speed=%dMb\n"), 1347 unit, SOC_PORT_NAME(unit, port), 1348 *speed)); 1349 return SOC_E_NONE; 1350 } 1351 1352 /* 1353 * Function: 1354 * mac_xl_loopback_set 1355 * Purpose: 1356 * Set a XLMAC into/out-of loopback mode 1357 * Parameters: 1358 * unit - XGS unit #. 1359 * port - XGS unit # on unit. 1360 * loopback - Boolean: true -> loopback mode, false -> normal operation 1361 * Note: 1362 * On Xlmac, when setting loopback, we enable the TX/RX function also. 1363 * Note that to test the PHY, we use the remote loopback facility. 1364 * Returns: 1365 * SOC_E_XXX 1366 */ 1367 STATIC int 1368 mac_xl_loopback_set(int unit, soc_port_t port, int lb) 1369 { 1370 LOG_VERBOSE(BSL_LS_SOC_10G, 1371 (BSL_META_U(unit, 1372 "mac_xl_loopback_set: unit %d port %s loopback=%s\n"), 1373 unit, SOC_PORT_NAME(unit, port), 1374 lb ? "local" : "no")); 1375 1376 /* need to enable clock compensation for applicable serdes device */ 1377 (void)soc_phyctrl_notify(unit, port, phyEventMacLoopback, lb ? 1 : 0); 1378 1379 SOC_IF_ERROR_RETURN 1380 (soc_mac_xl.md_control_set(unit, port, 1381 SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE, 1382 lb ? 0 : 1)); 1383 SOC_IF_ERROR_RETURN 1384 (soc_mac_xl.md_control_set(unit, port, 1385 SOC_MAC_CONTROL_FAULT_REMOTE_ENABLE, 1386 lb ? 0 : 1)); 1387 1388 return soc_reg_field32_modify(unit, XLMAC_CTRLr, port, LOCAL_LPBKf, 1389 lb ? 1 : 0); 1390 1391 return SOC_E_NONE; 1392 } 1393 1394 /* 1395 * Function: 1396 * mac_xl_loopback_get 1397 * Purpose: 1398 * Get current XLMAC loopback mode setting. 1399 * Parameters: 1400 * unit - XGS unit #. 1401 * port - XGS port # on unit. 1402 * loopback - (OUT) Boolean: true = loopback, false = normal 1403 * Returns: 1404 * SOC_E_XXX 1405 */ 1406 STATIC int 1407 mac_xl_loopback_get(int unit, soc_port_t port, int *lb) 1408 { 1409 uint64 ctrl; 1410 1411 SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &ctrl)); 1412 1413 *lb = soc_reg64_field32_get(unit, XLMAC_CTRLr, ctrl, LOCAL_LPBKf); 1414 1415 LOG_VERBOSE(BSL_LS_SOC_10G, 1416 (BSL_META_U(unit, 1417 "mac_xl_loopback_get: unit %d port %s loopback=%s\n"), 1418 unit, SOC_PORT_NAME(unit, port), 1419 *lb ? "True" : "False")); 1420 return SOC_E_NONE; 1421 } 1422 1423 /* 1424 * Function: 1425 * mac_xl_pause_addr_set 1426 * Purpose: 1427 * Configure PAUSE frame source address. 1428 * Parameters: 1429 * unit - XGS unit #. 1430 * port - XGS port # on unit. 1431 * pause_mac - (OUT) MAC address used for pause transmission. 1432 * Returns: 1433 * SOC_E_XXX 1434 */ 1435 STATIC int 1436 mac_xl_pause_addr_set(int unit, soc_port_t port, sal_mac_addr_t mac) 1437 { 1438 static soc_field_t fields[2] = { SA_HIf, SA_LOf }; 1439 uint32 values[2]; 1440 1441 LOG_VERBOSE(BSL_LS_SOC_10G, 1442 (BSL_META_U(unit, 1443 "mac_xl_pause_addr_set: unit %d port %s MAC=<" 1444 "%02x:%02x:%02x:%02x:%02x:%02x>\n"), 1445 unit, SOC_PORT_NAME(unit, port), 1446 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])); 1447 1448 values[0] = (mac[0] << 8) | mac[1]; 1449 values[1] = (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5]; 1450 1451 SOC_IF_ERROR_RETURN 1452 (soc_reg_fields32_modify(unit, XLMAC_TX_MAC_SAr, port, 2, fields, 1453 values)); 1454 SOC_IF_ERROR_RETURN 1455 (soc_reg_fields32_modify(unit, XLMAC_RX_MAC_SAr, port, 2, fields, 1456 values)); 1457 1458 return SOC_E_NONE; 1459 } 1460 1461 /* 1462 * Function: 1463 * mac_xl_pause_addr_get 1464 * Purpose: 1465 * Retrieve PAUSE frame source address. 1466 * Parameters: 1467 * unit - XGS unit #. 1468 * port - XGS port # on unit. 1469 * pause_mac - (OUT) MAC address used for pause transmission. 1470 * Returns: 1471 * SOC_E_XXX 1472 * NOTE: We always write the same thing to TX & RX SA 1473 * so, we just return the contects on RX_MAC_SA. 1474 */ 1475 STATIC int 1476 mac_xl_pause_addr_get(int unit, soc_port_t port, sal_mac_addr_t mac) 1477 { 1478 uint64 rval64; 1479 uint32 values[2]; 1480 1481 SOC_IF_ERROR_RETURN(READ_XLMAC_RX_MAC_SAr(unit, port, &rval64)); 1482 values[0] = soc_reg64_field32_get(unit, XLMAC_RX_MAC_SAr, rval64, SA_HIf); 1483 values[1] = soc_reg64_field32_get(unit, XLMAC_RX_MAC_SAr, rval64, SA_LOf); 1484 1485 mac[0] = (values[0] & 0x0000ff00) >> 8; 1486 mac[1] = values[0] & 0x000000ff; 1487 mac[2] = (values[1] & 0xff000000) >> 24; 1488 mac[3] = (values[1] & 0x00ff0000) >> 16; 1489 mac[4] = (values[1] & 0x0000ff00) >> 8; 1490 mac[5] = values[1] & 0x000000ff; 1491 1492 LOG_VERBOSE(BSL_LS_SOC_10G, 1493 (BSL_META_U(unit, 1494 "mac_xl_pause_addr_get: unit %d port %s MAC=<" 1495 "%02x:%02x:%02x:%02x:%02x:%02x>\n"), 1496 unit, SOC_PORT_NAME(unit, port), 1497 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])); 1498 return SOC_E_NONE; 1499 } 1500 1501 /* 1502 * Function: 1503 * mac_xl_interface_set 1504 * Purpose: 1505 * Set a XLMAC interface type 1506 * Parameters: 1507 * unit - XGS unit #. 1508 * port - XGS port # on unit. 1509 * pif - one of SOC_PORT_IF_* 1510 * Returns: 1511 * SOC_E_NONE 1512 * SOC_E_UNAVAIL - requested mode not supported. 1513 * Notes: 1514 */ 1515 STATIC int 1516 mac_xl_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 1517 { 1518 #ifdef BROADCOM_DEBUG 1519 LOG_VERBOSE(BSL_LS_SOC_10G, 1520 (BSL_META_U(unit, 1521 "mac_xl_interface_set: unit %d port %s interface=%s\n"), 1522 unit, SOC_PORT_NAME(unit, port), 1523 mac_xl_port_if_names[pif])); 1524 #endif 1525 return SOC_E_NONE; 1526 } 1527 1528 /* 1529 * Function: 1530 * mac_xl_interface_get 1531 * Purpose: 1532 * Retrieve XLMAC interface type 1533 * Parameters: 1534 * unit - XGS unit #. 1535 * port - XGS port # on unit. 1536 * pif - (OUT) one of SOC_PORT_IF_* 1537 * Returns: 1538 * SOC_E_NONE 1539 */ 1540 STATIC int 1541 mac_xl_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 1542 { 1543 *pif = SOC_PORT_IF_MII; 1544 1545 #ifdef BROADCOM_DEBUG 1546 LOG_VERBOSE(BSL_LS_SOC_10G, 1547 (BSL_META_U(unit, 1548 "mac_xl_interface_get: unit %d port %s interface=%s\n"), 1549 unit, SOC_PORT_NAME(unit, port), 1550 mac_xl_port_if_names[*pif])); 1551 #endif 1552 return SOC_E_NONE; 1553 } 1554 1555 /* 1556 * Function: 1557 * mac_xl_frame_max_set 1558 * Description: 1559 * Set the maximum receive frame size for the port 1560 * Parameters: 1561 * unit - Device number 1562 * port - Port number 1563 * size - Maximum frame size in bytes 1564 * Return Value: 1565 * SOC_E_XXX 1566 */ 1567 STATIC int 1568 mac_xl_frame_max_set(int unit, soc_port_t port, int size) 1569 { 1570 LOG_VERBOSE(BSL_LS_SOC_10G, 1571 (BSL_META_U(unit, 1572 "mac_xl_frame_max_set: unit %d port %s size=%d\n"), 1573 unit, SOC_PORT_NAME(unit, port), 1574 size)); 1575 1576 if (IS_XE_PORT(unit, port) || IS_GE_PORT(unit, port)) { 1577 /* For VLAN tagged packets */ 1578 size += 4; 1579 } 1580 return soc_reg_field32_modify(unit, XLMAC_RX_MAX_SIZEr, port, RX_MAX_SIZEf, 1581 size); 1582 } 1583 1584 /* 1585 * Function: 1586 * mac_xl_frame_max_get 1587 * Description: 1588 * Set the maximum receive frame size for the port 1589 * Parameters: 1590 * unit - Device number 1591 * port - Port number 1592 * size - Maximum frame size in bytes 1593 * Return Value: 1594 * SOC_E_XXX 1595 */ 1596 STATIC int 1597 mac_xl_frame_max_get(int unit, soc_port_t port, int *size) 1598 { 1599 uint64 rval; 1600 1601 SOC_IF_ERROR_RETURN(READ_XLMAC_RX_MAX_SIZEr(unit, port, &rval)); 1602 *size = soc_reg64_field32_get(unit, XLMAC_RX_MAX_SIZEr, rval, 1603 RX_MAX_SIZEf); 1604 if (IS_XE_PORT(unit, port) || IS_GE_PORT(unit, port)) { 1605 /* For VLAN tagged packets */ 1606 *size -= 4; 1607 } 1608 1609 LOG_VERBOSE(BSL_LS_SOC_10G, 1610 (BSL_META_U(unit, 1611 "mac_xl_frame_max_get: unit %d port %s size=%d\n"), 1612 unit, SOC_PORT_NAME(unit, port), 1613 *size)); 1614 return SOC_E_NONE; 1615 } 1616 1617 /* 1618 * Function: 1619 * mac_xl_ifg_set 1620 * Description: 1621 * Sets the new ifg (Inter-frame gap) value 1622 * Parameters: 1623 * unit - Device number 1624 * port - Port number 1625 * speed - the speed for which the IFG is being set 1626 * duplex - the duplex for which the IFG is being set 1627 * ifg - number of bits to use for average inter-frame gap 1628 * Return Value: 1629 * SOC_E_XXX 1630 * Notes: 1631 * The function makes sure the IFG value makes sense and updates the 1632 * IPG register in case the speed/duplex match the current settings 1633 */ 1634 STATIC int 1635 mac_xl_ifg_set(int unit, soc_port_t port, int speed, 1636 soc_port_duplex_t duplex, int ifg) 1637 { 1638 int cur_speed; 1639 int cur_duplex; 1640 int real_ifg; 1641 int encap = 0; 1642 1643 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 1644 uint64 rval, orval; 1645 soc_port_ability_t ability; 1646 uint32 pa_flag; 1647 1648 LOG_VERBOSE(BSL_LS_SOC_10G, 1649 (BSL_META_U(unit, 1650 "mac_xl_ifg_set: unit %d port %s speed=%dMb duplex=%s " 1651 "ifg=%d\n"), 1652 unit, SOC_PORT_NAME(unit, port), 1653 speed, duplex ? "True" : "False", ifg)); 1654 1655 pa_flag = SOC_PA_SPEED(speed); 1656 sal_memset(&ability, 0, sizeof(soc_port_ability_t)); 1657 soc_mac_xl.md_ability_local_get(unit, port, &ability); 1658 if (!(pa_flag & ability.speed_full_duplex)) { 1659 return SOC_E_PARAM; 1660 } 1661 1662 /* Silently adjust the specified ifp bits to valid value */ 1663 /* valid value: 8 to 64 bytes (i.e. multiple of 8 bits) */ 1664 real_ifg = ifg < 64 ? 64 : (ifg > 512 ? 512 : (ifg + 7) & (0x7f << 3)); 1665 1666 SOC_IF_ERROR_RETURN(mac_xl_encap_get(unit, port, &encap)); 1667 if (encap == SOC_ENCAP_HIGIG) { 1668 si->fd_hg = real_ifg; 1669 } else if (encap == SOC_ENCAP_HIGIG2) { 1670 si->fd_hg2 = real_ifg; 1671 } else { 1672 /* for encap == IEEE */ 1673 si->fd_xe = real_ifg; 1674 } 1675 1676 SOC_IF_ERROR_RETURN(mac_xl_duplex_get(unit, port, &cur_duplex)); 1677 SOC_IF_ERROR_RETURN(mac_xl_speed_get(unit, port, &cur_speed)); 1678 1679 /* XLMAC_MODE supports only 4 speeds with 4 being max as LINK_10G_PLUS */ 1680 if ((speed > 10000) && (cur_speed == 10000)) { 1681 cur_speed = speed; 1682 } 1683 1684 if (cur_speed == speed && 1685 cur_duplex == (duplex == SOC_PORT_DUPLEX_FULL ? TRUE : FALSE)) { 1686 SOC_IF_ERROR_RETURN(READ_XLMAC_TX_CTRLr(unit, port, &rval)); 1687 orval = rval; 1688 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &rval, AVERAGE_IPGf, 1689 real_ifg / 8); 1690 if (COMPILER_64_NE(rval, orval)) { 1691 SOC_IF_ERROR_RETURN(WRITE_XLMAC_TX_CTRLr(unit, port, rval)); 1692 } 1693 } 1694 1695 return SOC_E_NONE; 1696 } 1697 1698 /* 1699 * Function: 1700 * mac_xl_ifg_get 1701 * Description: 1702 * Sets the new ifg (Inter-frame gap) value 1703 * Parameters: 1704 * unit - Device number 1705 * port - Port number 1706 * speed - the speed for which the IFG is being set 1707 * duplex - the duplex for which the IFG is being set 1708 * size - Maximum frame size in bytes 1709 * Return Value: 1710 * SOC_E_XXX 1711 * Notes: 1712 * The function makes sure the IFG value makes sense and updates the 1713 * IPG register in case the speed/duplex match the current settings 1714 */ 1715 STATIC int 1716 mac_xl_ifg_get(int unit, soc_port_t port, int speed, 1717 soc_port_duplex_t duplex, int *ifg) 1718 { 1719 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 1720 soc_port_ability_t ability; 1721 uint32 pa_flag; 1722 int encap = 0; 1723 1724 if (!duplex) { 1725 return SOC_E_PARAM; 1726 } 1727 1728 pa_flag = SOC_PA_SPEED(speed); 1729 sal_memset(&ability, 0, sizeof(soc_port_ability_t)); 1730 soc_mac_xl.md_ability_local_get(unit, port, &ability); 1731 if (!(pa_flag & ability.speed_full_duplex)) { 1732 return SOC_E_PARAM; 1733 } 1734 1735 SOC_IF_ERROR_RETURN(mac_xl_encap_get(unit, port, &encap)); 1736 if (encap == SOC_ENCAP_HIGIG) { 1737 *ifg = si->fd_hg; 1738 } else if (encap == SOC_ENCAP_HIGIG2) { 1739 *ifg = si->fd_hg2; 1740 } else { 1741 /* for encap == IEEE */ 1742 *ifg = si->fd_xe; 1743 } 1744 1745 LOG_VERBOSE(BSL_LS_SOC_10G, 1746 (BSL_META_U(unit, 1747 "mac_xl_ifg_get: unit %d port %s speed=%dMb duplex=%s " 1748 "ifg=%d\n"), 1749 unit, SOC_PORT_NAME(unit, port), 1750 speed, duplex ? "True" : "False", *ifg)); 1751 return SOC_E_NONE; 1752 } 1753 1754 /* 1755 * Function: 1756 * _mac_xl_port_mode_update 1757 * Purpose: 1758 * Set the XLMAC port encapsulation mode. 1759 * Parameters: 1760 * unit - XGS unit #. 1761 * port - XGS port # on unit. 1762 * hg_mode - SOC HG encap modes. value={HG/HG2/HG2-LITE} 1763 * Returns: 1764 * SOC_E_XXX 1765 */ 1766 STATIC int 1767 _mac_xl_port_mode_update(int unit, soc_port_t port, int hg_mode) 1768 { 1769 uint32 rval; 1770 uint64 val64; 1771 soc_pbmp_t ctr_pbmp; 1772 int rv = SOC_E_NONE; 1773 int to_hg_port = 0 ; 1774 int phy_enable = 0; 1775 int speed = 0; 1776 1777 /* Pause linkscan */ 1778 soc_linkscan_pause(unit); 1779 1780 /* Pause counter collection */ 1781 COUNTER_LOCK(unit); 1782 1783 /* for original hg_mode parameter is at value={TRUE|FALSE} */ 1784 to_hg_port = (hg_mode != SOC_ENCAP_IEEE) ? TRUE : FALSE; 1785 if (soc_feature(unit, soc_feature_hg2_light_in_portmacro)) { 1786 soc_xport_type_mode_update(unit, port, hg_mode); 1787 } else { 1788 soc_xport_type_update(unit, port, to_hg_port); 1789 } 1790 1791 if (soc_feature(unit, soc_feature_port_encap_speed_max_config)) { 1792 if (to_hg_port) { 1793 SOC_IF_ERROR_RETURN(soc_port_hg_speed_get(unit, port, &speed)); 1794 SOC_IF_ERROR_RETURN(soc_phyctrl_set_speed_max(unit, port, speed)); 1795 } else { 1796 speed = SOC_INFO(unit).port_init_speed[port]; 1797 SOC_IF_ERROR_RETURN(soc_phyctrl_set_speed_max(unit, port, speed)); 1798 } 1799 } 1800 rv = soc_phyctrl_enable_get(unit, port, &phy_enable); 1801 1802 if (SOC_SUCCESS(rv)) { 1803 rv = soc_phyctrl_init(unit, port); 1804 } 1805 1806 if (soc_feature(unit, soc_feature_port_enable_encap_restore)){ 1807 if (SOC_SUCCESS(rv)) { 1808 rv = soc_phyctrl_enable_set(unit, port, phy_enable); 1809 } 1810 } else { 1811 /* Re-enable phy after init.*/ 1812 if (SOC_SUCCESS(rv) && phy_enable) { 1813 rv = soc_phyctrl_enable_set(unit, port, phy_enable); 1814 } 1815 } 1816 1817 if (SOC_SUCCESS(rv)) { 1818 rv = mac_xl_init(unit, port); 1819 } 1820 1821 if (SOC_SUCCESS(rv)) { 1822 rv = mac_xl_enable_set(unit, port, 0); 1823 } 1824 1825 if (SOC_SUCCESS(rv)) { 1826 SOC_PBMP_CLEAR(ctr_pbmp); 1827 SOC_PBMP_PORT_SET(ctr_pbmp, port); 1828 COMPILER_64_SET(val64, 0, 0); 1829 rv = soc_counter_set_by_port(unit, ctr_pbmp, val64); 1830 } 1831 1832 COUNTER_UNLOCK(unit); 1833 soc_linkscan_continue(unit); 1834 1835 if (SOC_REG_IS_VALID(unit, XLPORT_CONFIGr)) { 1836 uint32 xlp_hg_mode; 1837 1838 xlp_hg_mode = (to_hg_port) ? 1 : 0; 1839 #ifdef BCM_GREYHOUND_SUPPORT 1840 /* GH specific design is to apply HG setting PGW interface */ 1841 if (SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE3(unit) || 1842 SOC_IS_GREYHOUND2(unit)) { 1843 1844 /* XLPORT and PGW register for HIGIG_MODEf is confirmed 1845 * will be '1' for HG/HG+ setting only and '0' for other 1846 * encap mode{IEEE/HG2/HG2-LITE} 1847 */ 1848 xlp_hg_mode = (hg_mode == SOC_ENCAP_HIGIG) ? 1 : 0; 1849 1850 /* only port in XLMAC allows PGW encap setting below */ 1851 #ifdef BCM_GREYHOUND2_SUPPORT 1852 if (SOC_IS_GREYHOUND2(unit)) { 1853 SOC_IF_ERROR_RETURN 1854 (soc_greyhound2_pgw_encap_field_modify(unit, port, 1855 HIGIG_MODEf, xlp_hg_mode)); 1856 } else 1857 #endif /* GREYHOUND2 */ 1858 { 1859 SOC_IF_ERROR_RETURN 1860 (soc_greyhound_pgw_encap_field_modify(unit, port, 1861 HIGIG_MODEf, xlp_hg_mode)); 1862 } 1863 } 1864 #endif /* BCM_GREYHOUND_SUPPORT */ 1865 SOC_IF_ERROR_RETURN(READ_XLPORT_CONFIGr(unit, port, &rval)); 1866 soc_reg_field_set(unit, XLPORT_CONFIGr, &rval, HIGIG_MODEf, 1867 xlp_hg_mode); 1868 if (soc_feature(unit, soc_feature_no_higig_plus)) { 1869 soc_reg_field_set(unit, XLPORT_CONFIGr, &rval, HIGIG2_MODEf, 1870 xlp_hg_mode); 1871 } 1872 SOC_IF_ERROR_RETURN(WRITE_XLPORT_CONFIGr(unit, port, rval)); 1873 } 1874 if (SOC_REG_IS_VALID(unit, PORT_CONFIGr)) { 1875 SOC_IF_ERROR_RETURN(READ_PORT_CONFIGr(unit, port, &rval)); 1876 soc_reg_field_set(unit, PORT_CONFIGr, &rval, HIGIG_MODEf, 1877 to_hg_port); 1878 SOC_IF_ERROR_RETURN(WRITE_XPORT_CONFIGr(unit, port, rval)); 1879 } 1880 return rv; 1881 } 1882 1883 /* 1884 * Function: 1885 * mac_xl_encap_set 1886 * Purpose: 1887 * Set the XLMAC port encapsulation mode. 1888 * Parameters: 1889 * unit - XGS unit #. 1890 * port - XGS port # on unit. 1891 * mode - (IN) encap bits (defined above) 1892 * Returns: 1893 * SOC_E_XXX 1894 */ 1895 STATIC int 1896 mac_xl_encap_set(int unit, soc_port_t port, int mode) 1897 { 1898 int enable, encap, rv; 1899 int runt; 1900 1901 #ifdef BROADCOM_DEBUG 1902 LOG_VERBOSE(BSL_LS_SOC_10G, 1903 (BSL_META_U(unit, 1904 "mac_xl_encap_set: unit %d port %s encapsulation=%s\n"), 1905 unit, SOC_PORT_NAME(unit, port), 1906 mac_xl_encap_mode[mode])); 1907 #endif 1908 1909 switch (mode) { 1910 case SOC_ENCAP_IEEE: 1911 case SOC_ENCAP_HIGIG2_LITE: 1912 encap = 0; 1913 break; 1914 case SOC_ENCAP_HIGIG: 1915 encap = 1; 1916 break; 1917 case SOC_ENCAP_HIGIG2: 1918 encap = 2; 1919 break; 1920 default: 1921 return SOC_E_PARAM; 1922 } 1923 1924 if (!soc_feature(unit, soc_feature_xport_convertible)) { 1925 if ((IS_E_PORT(unit, port) && mode != SOC_ENCAP_IEEE) || 1926 (IS_ST_PORT(unit, port) && mode == SOC_ENCAP_IEEE)) { 1927 return SOC_E_PARAM; 1928 } 1929 } 1930 1931 SOC_IF_ERROR_RETURN(mac_xl_enable_get(unit, port, &enable)); 1932 1933 if (enable) { 1934 /* Turn off TX/RX enable */ 1935 SOC_IF_ERROR_RETURN(mac_xl_enable_set(unit, port, 0)); 1936 } 1937 1938 if (soc_feature(unit, soc_feature_hg2_light_in_portmacro)) { 1939 /* mode update for all encap mode change! */ 1940 SOC_IF_ERROR_RETURN(_mac_xl_port_mode_update(unit, port, mode)); 1941 } else if ((IS_E_PORT(unit, port) && mode != SOC_ENCAP_IEEE) || 1942 (IS_ST_PORT(unit, port) && mode == SOC_ENCAP_IEEE)) { 1943 /* IEEE -> HG or HG -> IEEE */ 1944 SOC_IF_ERROR_RETURN(_mac_xl_port_mode_update(unit, port, mode)); 1945 } 1946 1947 /* apply encap setting */ 1948 rv = soc_reg_field32_modify(unit, XLMAC_MODEr, port, HDR_MODEf, encap); 1949 1950 /* assigning runt value per encap setting */ 1951 if ((mode == SOC_ENCAP_HIGIG2) || (mode == SOC_ENCAP_HIGIG2_LITE)) { 1952 runt = XLMAC_RUNT_THRESHOLD_HG2; 1953 } else if (mode == SOC_ENCAP_HIGIG) { 1954 runt = XLMAC_RUNT_THRESHOLD_HG1; 1955 } else { 1956 runt = XLMAC_RUNT_THRESHOLD_IEEE; 1957 } 1958 SOC_IF_ERROR_RETURN 1959 (soc_reg_field32_modify(unit, XLMAC_RX_CTRLr, port, RUNT_THRESHOLDf, 1960 runt)); 1961 1962 SOC_IF_ERROR_RETURN 1963 (soc_reg_field32_modify(unit, XLMAC_RX_CTRLr, port, STRICT_PREAMBLEf, 1964 mode == SOC_ENCAP_IEEE ? 1 : 0)); 1965 1966 if (enable) { 1967 /* Re-enable transmitter and receiver */ 1968 SOC_IF_ERROR_RETURN(mac_xl_enable_set(unit, port, 1)); 1969 } 1970 1971 return rv; 1972 } 1973 1974 /* 1975 * Function: 1976 * mac_xl_encap_get 1977 * Purpose: 1978 * Get the XLMAC port encapsulation mode. 1979 * Parameters: 1980 * unit - XGS unit #. 1981 * port - XGS port # on unit. 1982 * mode - (INT) encap bits (defined above) 1983 * Returns: 1984 * SOC_E_XXX 1985 */ 1986 STATIC int 1987 mac_xl_encap_get(int unit, soc_port_t port, int *mode) 1988 { 1989 uint64 rval; 1990 1991 if (!mode) { 1992 return SOC_E_PARAM; 1993 } 1994 1995 SOC_IF_ERROR_RETURN(READ_XLMAC_MODEr(unit, port, &rval)); 1996 switch (soc_reg64_field32_get(unit, XLMAC_MODEr, rval, HDR_MODEf)) { 1997 case 0: 1998 *mode = SOC_ENCAP_IEEE; 1999 break; 2000 case 1: 2001 *mode = SOC_ENCAP_HIGIG; 2002 break; 2003 case 2: 2004 *mode = SOC_ENCAP_HIGIG2; 2005 break; 2006 default: 2007 *mode = SOC_ENCAP_COUNT; 2008 } 2009 2010 #ifdef BROADCOM_DEBUG 2011 LOG_VERBOSE(BSL_LS_SOC_10G, 2012 (BSL_META_U(unit, 2013 "mac_xl_encap_get: unit %d port %s encapsulation=%s\n"), 2014 unit, SOC_PORT_NAME(unit, port), 2015 mac_xl_encap_mode[*mode])); 2016 #endif 2017 return SOC_E_NONE; 2018 } 2019 2020 /* 2021 * Function: 2022 * mac_xl_expected_rx_latency_get 2023 * Purpose: 2024 * Get the XLMAC port expected Rx latency 2025 * Parameters: 2026 * unit - XGS unit #. 2027 * port - XGS port # on unit. 2028 * latency - (OUT) Latency in NS 2029 * Returns: 2030 * SOC_E_XXX 2031 */ 2032 STATIC int 2033 mac_xl_expected_rx_latency_get(int unit, soc_port_t port, int *latency) 2034 { 2035 int speed = 0; 2036 SOC_IF_ERROR_RETURN(mac_xl_speed_get(unit, port, &speed)); 2037 2038 switch (speed) { 2039 case 1000: /* GigE */ 2040 *latency = 510; /* From SDK-69340 */ 2041 break; 2042 2043 case 10000: /* 10G */ 2044 *latency = 230; /* From SDK-69340 */ 2045 break; 2046 2047 default: 2048 *latency = 0; 2049 break; 2050 } 2051 2052 return SOC_E_NONE; 2053 } 2054 2055 /* 2056 * Function: 2057 * mac_xl_control_set 2058 * Purpose: 2059 * To configure MAC control properties. 2060 * Parameters: 2061 * unit - XGS unit #. 2062 * port - XGS port # on unit. 2063 * type - MAC control property to set. 2064 * int - New setting for MAC control. 2065 * Returns: 2066 * SOC_E_XXX 2067 */ 2068 STATIC int 2069 mac_xl_control_set(int unit, soc_port_t port, soc_mac_control_t type, 2070 int value) 2071 { 2072 uint64 rval, copy; 2073 uint32 fval; 2074 2075 LOG_VERBOSE(BSL_LS_SOC_10G, 2076 (BSL_META_U(unit, 2077 "mac_xl_control_set: unit %d port %s type=%d value=%d\n"), 2078 unit, SOC_PORT_NAME(unit, port), 2079 type, value)); 2080 2081 switch (type) { 2082 case SOC_MAC_CONTROL_RX_SET: 2083 SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &rval)); 2084 copy = rval; 2085 soc_reg64_field32_set(unit, XLMAC_CTRLr, &rval, RX_ENf, value ? 1 : 0); 2086 if (COMPILER_64_NE(rval, copy)) { 2087 SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, rval)); 2088 } 2089 break; 2090 case SOC_MAC_CONTROL_TX_SET: 2091 SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &rval)); 2092 copy = rval; 2093 soc_reg64_field32_set(unit, XLMAC_CTRLr, &rval, TX_ENf, value ? 1 : 0); 2094 if (COMPILER_64_NE(rval, copy)) { 2095 SOC_IF_ERROR_RETURN(WRITE_XLMAC_CTRLr(unit, port, rval)); 2096 } 2097 break; 2098 case SOC_MAC_CONTROL_FRAME_SPACING_STRETCH: 2099 if (value < 0 || value > XLMAC_THROT_10G_TO_2P5G) { 2100 return SOC_E_PARAM; 2101 } else { 2102 SOC_IF_ERROR_RETURN(READ_XLMAC_TX_CTRLr(unit, port, &rval)); 2103 if ( value == XLMAC_THROT_10G_TO_5G ) { 2104 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &rval, THROT_DENOMf, 21); 2105 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &rval, THROT_NUMf, 21); 2106 } else if (value == XLMAC_THROT_10G_TO_2P5G) { 2107 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &rval, THROT_DENOMf, 21); 2108 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &rval, THROT_NUMf, 63); 2109 } else if (value >= 8) { 2110 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &rval, 2111 THROT_DENOMf, value); 2112 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &rval, THROT_NUMf, 2113 1); 2114 } else { 2115 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &rval, 2116 THROT_DENOMf, 0); 2117 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &rval, THROT_NUMf, 2118 0); 2119 } 2120 SOC_IF_ERROR_RETURN(WRITE_XLMAC_TX_CTRLr(unit, port, rval)); 2121 } 2122 return SOC_E_NONE; 2123 2124 case SOC_MAC_PASS_CONTROL_FRAME: 2125 if (SOC_REG_IS_VALID(unit, XLMAC_PAUSE_CTRLr)) { 2126 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XLMAC_PAUSE_CTRLr, port, 2127 RX_PAUSE_ENf, value ? 0 : 1)); 2128 2129 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XLMAC_PAUSE_CTRLr, port, 2130 TX_PAUSE_ENf, value ? 0 : 1)); 2131 } 2132 break; 2133 2134 case SOC_MAC_CONTROL_PFC_TYPE: 2135 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XLMAC_PFC_TYPEr, port, 2136 PFC_ETH_TYPEf, value)); 2137 break; 2138 2139 case SOC_MAC_CONTROL_PFC_OPCODE: 2140 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XLMAC_PFC_OPCODEr, 2141 port, PFC_OPCODEf, value)); 2142 break; 2143 2144 case SOC_MAC_CONTROL_PFC_CLASSES: 2145 if (value != 8) { 2146 return SOC_E_PARAM; 2147 } 2148 break; 2149 2150 case SOC_MAC_CONTROL_PFC_MAC_DA_OUI: 2151 SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_DAr(unit, port, &rval)); 2152 fval = soc_reg64_field32_get(unit, XLMAC_PFC_DAr, rval, PFC_MACDA_LOf); 2153 fval &= 0x00ffffff; 2154 fval |= (value & 0xff) << 24; 2155 soc_reg64_field32_set(unit, XLMAC_PFC_DAr, &rval, PFC_MACDA_LOf, fval); 2156 2157 soc_reg64_field32_set(unit, XLMAC_PFC_DAr, &rval, PFC_MACDA_HIf, 2158 value >> 8); 2159 SOC_IF_ERROR_RETURN(WRITE_XLMAC_PFC_DAr(unit, port, rval)); 2160 break; 2161 2162 case SOC_MAC_CONTROL_PFC_MAC_DA_NONOUI: 2163 SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_DAr(unit, port, &rval)); 2164 fval = soc_reg64_field32_get(unit, XLMAC_PFC_DAr, rval, PFC_MACDA_LOf); 2165 fval &= 0xff000000; 2166 fval |= value; 2167 soc_reg64_field32_set(unit, XLMAC_PFC_DAr, &rval, PFC_MACDA_LOf, fval); 2168 SOC_IF_ERROR_RETURN(WRITE_XLMAC_PFC_DAr(unit, port, rval)); 2169 break; 2170 2171 case SOC_MAC_CONTROL_PFC_RX_PASS: 2172 /* this is always true */ 2173 break; 2174 2175 case SOC_MAC_CONTROL_PFC_RX_ENABLE: 2176 SOC_IF_ERROR_RETURN 2177 (soc_reg_field32_modify(unit, XLMAC_PFC_CTRLr, port, RX_PFC_ENf, 2178 value ? 1 : 0)); 2179 break; 2180 2181 case SOC_MAC_CONTROL_PFC_TX_ENABLE: 2182 SOC_IF_ERROR_RETURN 2183 (soc_reg_field32_modify(unit, XLMAC_PFC_CTRLr, port, TX_PFC_ENf, 2184 value ? 1 : 0)); 2185 break; 2186 2187 case SOC_MAC_CONTROL_PFC_FORCE_XON: 2188 SOC_IF_ERROR_RETURN 2189 (soc_reg_field32_modify(unit, XLMAC_PFC_CTRLr, port, FORCE_PFC_XONf, 2190 value ? 1 : 0)); 2191 break; 2192 2193 case SOC_MAC_CONTROL_PFC_STATS_ENABLE: 2194 SOC_IF_ERROR_RETURN 2195 (soc_reg_field32_modify(unit, XLMAC_PFC_CTRLr, port, PFC_STATS_ENf, 2196 value ? 1 : 0)); 2197 break; 2198 2199 case SOC_MAC_CONTROL_PFC_REFRESH_TIME: 2200 SOC_IF_ERROR_RETURN 2201 (soc_reg_field32_modify(unit, XLMAC_PFC_CTRLr, port, 2202 PFC_REFRESH_TIMERf, value)); 2203 break; 2204 2205 case SOC_MAC_CONTROL_PFC_XOFF_TIME: 2206 SOC_IF_ERROR_RETURN 2207 (soc_reg_field32_modify(unit, XLMAC_PFC_CTRLr, port, 2208 PFC_XOFF_TIMERf, value)); 2209 break; 2210 2211 case SOC_MAC_CONTROL_LLFC_RX_ENABLE: 2212 SOC_IF_ERROR_RETURN 2213 (soc_reg_field32_modify(unit, XLMAC_LLFC_CTRLr, port, RX_LLFC_ENf, 2214 value ? 1 : 0)); 2215 SOC_IF_ERROR_RETURN 2216 (soc_llfc_xon_set(unit, port, value ? 1 : 0)); 2217 break; 2218 2219 case SOC_MAC_CONTROL_LLFC_TX_ENABLE: 2220 SOC_IF_ERROR_RETURN 2221 (soc_reg_field32_modify(unit, XLMAC_LLFC_CTRLr, port, TX_LLFC_ENf, 2222 value ? 1 : 0)); 2223 break; 2224 2225 case SOC_MAC_CONTROL_EEE_ENABLE: 2226 if (!soc_feature(unit, soc_feature_eee)) { 2227 return SOC_E_UNAVAIL; 2228 } 2229 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XLMAC_EEE_CTRLr, 2230 port, EEE_ENf, value)); 2231 break; 2232 2233 case SOC_MAC_CONTROL_EEE_TX_IDLE_TIME: 2234 if (!soc_feature(unit, soc_feature_eee)) { 2235 return SOC_E_UNAVAIL; 2236 } 2237 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XLMAC_EEE_TIMERSr, 2238 port, EEE_DELAY_ENTRY_TIMERf, value)); 2239 break; 2240 2241 case SOC_MAC_CONTROL_EEE_TX_WAKE_TIME: 2242 if (!soc_feature(unit, soc_feature_eee)) { 2243 return SOC_E_UNAVAIL; 2244 } 2245 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, XLMAC_EEE_TIMERSr, 2246 port, EEE_WAKE_TIMERf, value)); 2247 break; 2248 2249 case SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE: 2250 SOC_IF_ERROR_RETURN 2251 (soc_reg_field32_modify(unit, XLMAC_RX_LSS_CTRLr, port, 2252 LOCAL_FAULT_DISABLEf, value ? 0 : 1)); 2253 break; 2254 2255 case SOC_MAC_CONTROL_FAULT_REMOTE_ENABLE: 2256 SOC_IF_ERROR_RETURN 2257 (soc_reg_field32_modify(unit, XLMAC_RX_LSS_CTRLr, port, 2258 REMOTE_FAULT_DISABLEf, value ? 0 : 1)); 2259 break; 2260 case SOC_MAC_CONTROL_FAILOVER_RX_SET: 2261 break; 2262 case SOC_MAC_CONTROL_EGRESS_DRAIN: 2263 SOC_IF_ERROR_RETURN(mac_xl_egress_queue_drain(unit, port)); 2264 break; 2265 case SOC_MAC_CONTROL_RX_VLAN_TAG_OUTER_TPID: 2266 SOC_IF_ERROR_RETURN 2267 (soc_reg_field32_modify(unit, XLMAC_RX_VLAN_TAGr, port, 2268 OUTER_VLAN_TAGf, value)); 2269 SOC_IF_ERROR_RETURN 2270 (soc_reg_field32_modify(unit, XLMAC_RX_VLAN_TAGr, port, 2271 OUTER_VLAN_TAG_ENABLEf, value ? 1 : 0)); 2272 break; 2273 case SOC_MAC_CONTROL_RX_VLAN_TAG_INNER_TPID: 2274 SOC_IF_ERROR_RETURN 2275 (soc_reg_field32_modify(unit, XLMAC_RX_VLAN_TAGr, port, 2276 INNER_VLAN_TAGf, value)); 2277 SOC_IF_ERROR_RETURN 2278 (soc_reg_field32_modify(unit, XLMAC_RX_VLAN_TAGr, port, 2279 INNER_VLAN_TAG_ENABLEf, value ? 1 : 0)); 2280 break; 2281 default: 2282 return SOC_E_UNAVAIL; 2283 } 2284 2285 return SOC_E_NONE; 2286 } 2287 2288 /* 2289 * Function: 2290 * mac_xl_control_get 2291 * Purpose: 2292 * To get current MAC control setting. 2293 * Parameters: 2294 * unit - XGS unit #. 2295 * port - XGS port # on unit. 2296 * type - MAC control property to set. 2297 * int - New setting for MAC control. 2298 * Returns: 2299 * SOC_E_XXX 2300 */ 2301 STATIC int 2302 mac_xl_control_get(int unit, soc_port_t port, soc_mac_control_t type, 2303 int *value) 2304 { 2305 int rv; 2306 uint64 rval; 2307 uint32 fval0, fval1; 2308 2309 if (value == NULL) { 2310 return SOC_E_PARAM; 2311 } 2312 2313 rv = SOC_E_NONE; 2314 switch (type) { 2315 case SOC_MAC_CONTROL_RX_SET: 2316 SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &rval)); 2317 *value = soc_reg64_field32_get(unit, XLMAC_CTRLr, rval, RX_ENf); 2318 break; 2319 case SOC_MAC_CONTROL_TX_SET: 2320 SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &rval)); 2321 *value = soc_reg64_field32_get(unit, XLMAC_CTRLr, rval, TX_ENf); 2322 break; 2323 case SOC_MAC_CONTROL_SW_RESET: 2324 SOC_IF_ERROR_RETURN(READ_XLMAC_CTRLr(unit, port, &rval)); 2325 *value = soc_reg64_field32_get(unit, XLMAC_CTRLr, rval, SOFT_RESETf); 2326 break; 2327 case SOC_MAC_CONTROL_FRAME_SPACING_STRETCH: 2328 SOC_IF_ERROR_RETURN(READ_XLMAC_TX_CTRLr(unit, port, &rval)); 2329 *value = soc_reg64_field32_get(unit, XLMAC_TX_CTRLr, rval, 2330 THROT_DENOMf); 2331 break; 2332 2333 case SOC_MAC_CONTROL_TIMESTAMP_TRANSMIT: 2334 { 2335 uint32 timestamp = 0; 2336 if (soc_feature(unit, soc_feature_timestamp_counter) && 2337 soc_property_get(unit, spn_SW_TIMESTAMP_FIFO_ENABLE, 1)) { 2338 if (soc_counter_timestamp_get(unit, port, 2339 ×tamp) != SOC_E_NOT_FOUND) { 2340 *value = (int)timestamp; 2341 break; 2342 } 2343 } 2344 SOC_IF_ERROR_RETURN 2345 (READ_XLMAC_TX_TIMESTAMP_FIFO_STATUSr(unit, port, &rval)); 2346 if (soc_reg64_field32_get(unit, XLMAC_TX_TIMESTAMP_FIFO_STATUSr, rval, 2347 ENTRY_COUNTf) == 0) { 2348 return SOC_E_EMPTY; 2349 } 2350 SOC_IF_ERROR_RETURN 2351 (READ_XLMAC_TX_TIMESTAMP_FIFO_DATAr(unit, port, &rval)); 2352 *value = soc_reg64_field32_get(unit, XLMAC_TX_TIMESTAMP_FIFO_DATAr, 2353 rval, TIME_STAMPf); 2354 } 2355 break; 2356 2357 case SOC_MAC_PASS_CONTROL_FRAME: 2358 *value = TRUE; 2359 break; 2360 2361 case SOC_MAC_CONTROL_PFC_TYPE: 2362 SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_TYPEr(unit, port, &rval)); 2363 *value = soc_reg64_field32_get(unit, XLMAC_PFC_TYPEr, rval, 2364 PFC_ETH_TYPEf); 2365 break; 2366 2367 case SOC_MAC_CONTROL_PFC_OPCODE: 2368 SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_OPCODEr(unit, port, &rval)); 2369 *value = soc_reg64_field32_get(unit, XLMAC_PFC_OPCODEr, rval, 2370 PFC_OPCODEf); 2371 break; 2372 2373 case SOC_MAC_CONTROL_PFC_CLASSES: 2374 *value = 8; 2375 break; 2376 2377 case SOC_MAC_CONTROL_PFC_MAC_DA_OUI: 2378 SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_DAr(unit, port, &rval)); 2379 fval0 = soc_reg64_field32_get(unit, XLMAC_PFC_DAr, rval, 2380 PFC_MACDA_LOf); 2381 fval1 = soc_reg64_field32_get(unit, XLMAC_PFC_DAr, rval, 2382 PFC_MACDA_HIf); 2383 *value = (fval0 >> 24) | (fval1 << 8); 2384 break; 2385 2386 case SOC_MAC_CONTROL_PFC_MAC_DA_NONOUI: 2387 SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_DAr(unit, port, &rval)); 2388 *value = soc_reg64_field32_get(unit, XLMAC_PFC_DAr, rval, 2389 PFC_MACDA_LOf) & 0x00ffffff; 2390 break; 2391 2392 case SOC_MAC_CONTROL_PFC_RX_PASS: 2393 *value = TRUE; 2394 break; 2395 2396 case SOC_MAC_CONTROL_PFC_RX_ENABLE: 2397 SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_CTRLr(unit, port, &rval)); 2398 *value = soc_reg64_field32_get(unit, XLMAC_PFC_CTRLr, rval, 2399 RX_PFC_ENf); 2400 break; 2401 2402 case SOC_MAC_CONTROL_PFC_TX_ENABLE: 2403 SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_CTRLr(unit, port, &rval)); 2404 *value = soc_reg64_field32_get(unit, XLMAC_PFC_CTRLr, rval, 2405 TX_PFC_ENf); 2406 break; 2407 2408 case SOC_MAC_CONTROL_PFC_FORCE_XON: 2409 SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_CTRLr(unit, port, &rval)); 2410 *value = soc_reg64_field32_get(unit, XLMAC_PFC_CTRLr, rval, 2411 FORCE_PFC_XONf); 2412 break; 2413 2414 case SOC_MAC_CONTROL_PFC_STATS_ENABLE: 2415 SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_CTRLr(unit, port, &rval)); 2416 *value = soc_reg64_field32_get(unit, XLMAC_PFC_CTRLr, rval, 2417 PFC_STATS_ENf); 2418 break; 2419 2420 case SOC_MAC_CONTROL_PFC_REFRESH_TIME: 2421 SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_CTRLr(unit, port, &rval)); 2422 *value = soc_reg64_field32_get(unit, XLMAC_PFC_CTRLr, rval, 2423 PFC_REFRESH_TIMERf); 2424 break; 2425 2426 case SOC_MAC_CONTROL_PFC_XOFF_TIME: 2427 SOC_IF_ERROR_RETURN(READ_XLMAC_PFC_CTRLr(unit, port, &rval)); 2428 *value = soc_reg64_field32_get(unit, XLMAC_PFC_CTRLr, rval, 2429 PFC_XOFF_TIMERf); 2430 break; 2431 2432 case SOC_MAC_CONTROL_LLFC_RX_ENABLE: 2433 SOC_IF_ERROR_RETURN(READ_XLMAC_LLFC_CTRLr(unit, port, &rval)); 2434 *value = soc_reg64_field32_get(unit, XLMAC_LLFC_CTRLr, rval, 2435 RX_LLFC_ENf); 2436 break; 2437 2438 case SOC_MAC_CONTROL_LLFC_TX_ENABLE: 2439 SOC_IF_ERROR_RETURN(READ_XLMAC_LLFC_CTRLr(unit, port, &rval)); 2440 *value = soc_reg64_field32_get(unit, XLMAC_LLFC_CTRLr, rval, 2441 TX_LLFC_ENf); 2442 break; 2443 2444 case SOC_MAC_CONTROL_EEE_ENABLE: 2445 if (!soc_feature(unit, soc_feature_eee)) { 2446 return SOC_E_UNAVAIL; 2447 } 2448 SOC_IF_ERROR_RETURN(READ_XLMAC_EEE_CTRLr(unit, port, &rval)); 2449 *value = soc_reg64_field32_get(unit, XLMAC_EEE_CTRLr, rval, EEE_ENf); 2450 break; 2451 2452 case SOC_MAC_CONTROL_EEE_TX_IDLE_TIME: 2453 if (!soc_feature(unit, soc_feature_eee)) { 2454 return SOC_E_UNAVAIL; 2455 } 2456 SOC_IF_ERROR_RETURN(READ_XLMAC_EEE_TIMERSr(unit, port, &rval)); 2457 *value = soc_reg64_field32_get(unit, XLMAC_EEE_TIMERSr, rval, 2458 EEE_DELAY_ENTRY_TIMERf); 2459 break; 2460 2461 case SOC_MAC_CONTROL_EEE_TX_WAKE_TIME: 2462 if (!soc_feature(unit, soc_feature_eee)) { 2463 return SOC_E_UNAVAIL; 2464 } 2465 SOC_IF_ERROR_RETURN(READ_XLMAC_EEE_TIMERSr(unit, port, &rval)); 2466 *value = soc_reg64_field32_get(unit, XLMAC_EEE_TIMERSr, rval, 2467 EEE_WAKE_TIMERf); 2468 break; 2469 2470 case SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE: 2471 SOC_IF_ERROR_RETURN(READ_XLMAC_RX_LSS_CTRLr(unit, port, &rval)); 2472 *value = soc_reg64_field32_get(unit, XLMAC_RX_LSS_CTRLr, rval, 2473 LOCAL_FAULT_DISABLEf) ? 0 : 1; 2474 break; 2475 2476 case SOC_MAC_CONTROL_FAULT_LOCAL_STATUS: 2477 SOC_IF_ERROR_RETURN(READ_XLMAC_RX_LSS_CTRLr(unit, port, &rval)); 2478 if (soc_reg64_field32_get(unit, XLMAC_RX_LSS_CTRLr, rval, 2479 LOCAL_FAULT_DISABLEf) == 1) { 2480 *value = 0; 2481 } else { 2482 SOC_IF_ERROR_RETURN(READ_XLMAC_RX_LSS_STATUSr(unit, port, &rval)); 2483 *value = soc_reg64_field32_get(unit, XLMAC_RX_LSS_STATUSr, rval, 2484 LOCAL_FAULT_STATUSf); 2485 } 2486 break; 2487 2488 case SOC_MAC_CONTROL_FAULT_REMOTE_ENABLE: 2489 SOC_IF_ERROR_RETURN(READ_XLMAC_RX_LSS_CTRLr(unit, port, &rval)); 2490 *value = soc_reg64_field32_get(unit, XLMAC_RX_LSS_CTRLr, rval, 2491 REMOTE_FAULT_DISABLEf) ? 0 : 1; 2492 break; 2493 2494 case SOC_MAC_CONTROL_FAULT_REMOTE_STATUS: 2495 SOC_IF_ERROR_RETURN(READ_XLMAC_RX_LSS_CTRLr(unit, port, &rval)); 2496 if (soc_reg64_field32_get(unit, XLMAC_RX_LSS_CTRLr, rval, 2497 REMOTE_FAULT_DISABLEf) == 1) { 2498 *value = 0; 2499 } else { 2500 SOC_IF_ERROR_RETURN(READ_XLMAC_RX_LSS_STATUSr(unit, port, &rval)); 2501 *value = soc_reg64_field32_get(unit, XLMAC_RX_LSS_STATUSr, rval, 2502 REMOTE_FAULT_STATUSf); 2503 } 2504 break; 2505 case SOC_MAC_CONTROL_RX_VLAN_TAG_OUTER_TPID: 2506 SOC_IF_ERROR_RETURN(READ_XLMAC_RX_VLAN_TAGr(unit, port, &rval)); 2507 *value = soc_reg64_field32_get(unit, XLMAC_RX_VLAN_TAGr, 2508 rval, OUTER_VLAN_TAGf); 2509 break; 2510 case SOC_MAC_CONTROL_RX_VLAN_TAG_INNER_TPID: 2511 SOC_IF_ERROR_RETURN(READ_XLMAC_RX_VLAN_TAGr(unit, port, &rval)); 2512 *value = soc_reg64_field32_get(unit, XLMAC_RX_VLAN_TAGr, 2513 rval, INNER_VLAN_TAGf); 2514 break; 2515 case SOC_MAC_CONTROL_EXPECTED_RX_LATENCY: 2516 SOC_IF_ERROR_RETURN(mac_xl_expected_rx_latency_get(unit, port, value)); 2517 break; 2518 2519 default: 2520 return SOC_E_UNAVAIL; 2521 } 2522 2523 LOG_VERBOSE(BSL_LS_SOC_10G, 2524 (BSL_META_U(unit, 2525 "mac_xl_control_get: unit %d port %s type=%d value=%d " 2526 "rv=%d\n"), 2527 unit, SOC_PORT_NAME(unit, port), 2528 type, *value, rv)); 2529 return rv; 2530 } 2531 2532 /* 2533 * Function: 2534 * mac_xl_ability_local_get 2535 * Purpose: 2536 * Return the abilities of XLMAC 2537 * Parameters: 2538 * unit - XGS unit #. 2539 * port - XGS port # on unit. 2540 * mode - (OUT) Supported operating modes as a mask of abilities. 2541 * Returns: 2542 * SOC_E_XXX 2543 */ 2544 STATIC int 2545 mac_xl_ability_local_get(int unit, soc_port_t port, 2546 soc_port_ability_t *ability) 2547 { 2548 soc_info_t *si = &SOC_INFO(unit); 2549 int blk, bindex, port_speed_max, i; 2550 int phy_port, active_port; 2551 uint32 active_mask; 2552 #ifdef BCM_METROLITE_SUPPORT 2553 uint32 rval = 0; 2554 uint32 port_mode = 0xF; 2555 #endif 2556 2557 if (NULL == ability) { 2558 return SOC_E_PARAM; 2559 } 2560 2561 ability->speed_half_duplex = SOC_PA_ABILITY_NONE; 2562 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 2563 ability->interface = SOC_PA_INTF_MII | SOC_PA_INTF_XGMII; 2564 ability->medium = SOC_PA_ABILITY_NONE; 2565 ability->loopback = SOC_PA_LB_MAC; 2566 ability->flags = SOC_PA_ABILITY_NONE; 2567 ability->encap = SOC_PA_ENCAP_IEEE | SOC_PA_ENCAP_HIGIG | 2568 SOC_PA_ENCAP_HIGIG2; 2569 2570 #ifdef BCM_SABER2_SUPPORT 2571 if (SOC_IS_SABER2(unit) && IS_XL_PORT(unit,port)) { 2572 ability->encap |= SOC_PA_ENCAP_HIGIG2_LITE; 2573 ability->speed_full_duplex = SOC_PA_ABILITY_NONE; 2574 } 2575 #endif 2576 2577 /* Adjust port_speed_max according to the port config */ 2578 port_speed_max = SOC_INFO(unit).port_speed_max[port]; 2579 if (soc_feature(unit, soc_feature_logical_port_num) && 2580 !soc_feature(unit, soc_feature_tsce)) { 2581 phy_port = si->port_l2p_mapping[port]; 2582 bindex = -1; 2583 for (i = 0; i < SOC_DRIVER(unit)->port_num_blktype; i++) { 2584 blk = SOC_PORT_IDX_BLOCK(unit, phy_port, i); 2585 if (SOC_BLOCK_INFO(unit, blk).type == SOC_BLK_XLPORT) { 2586 bindex = SOC_PORT_IDX_BINDEX(unit, phy_port, i); 2587 break; 2588 } 2589 } 2590 if (port_speed_max > 10000) { 2591 active_mask = 0; 2592 for (i = bindex + 1; i <= 3; i++) { 2593 active_port = si->port_p2l_mapping[phy_port - bindex + i]; 2594 if (active_port != -1 && 2595 !SOC_PBMP_MEMBER(SOC_PORT_DISABLED_BITMAP(unit, all), 2596 active_port)) { 2597 active_mask |= 1 << i; 2598 } 2599 } 2600 if (bindex == 0) { /* Lanes 0 */ 2601 if (active_mask & 0x2) { /* lane 1 is in use */ 2602 port_speed_max = 10000; 2603 } else if (port_speed_max > 20000 && active_mask & 0xc) { 2604 /* Lane 1 isn't in use, lane 2 or 3 (or both) is (are) in use */ 2605 port_speed_max = 20000; 2606 } 2607 } else { /* (Must be) lanes 2 */ 2608 if (active_mask & 0x8) { /* lane 3 is in use */ 2609 port_speed_max = 10000; 2610 } 2611 } 2612 } 2613 } 2614 if (IS_HL_PORT(unit , port)) { 2615 if (SOC_INFO(unit).port_speed_max[port]) { 2616 ability->speed_full_duplex |= SOC_PA_SPEED_2500MB; 2617 if (SOC_IS_HURRICANE2(unit)) { 2618 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 2619 } 2620 #ifdef BCM_METROLITE_SUPPORT 2621 /* HL is supported in 4x1G */ 2622 if (SOC_IS_METROLITE(unit)) { 2623 if (SOC_REG_PORT_VALID(unit, XLPORT_MODE_REGr, port)) { 2624 SOC_IF_ERROR_RETURN(READ_XLPORT_MODE_REGr(unit, port, &rval)); 2625 port_mode = soc_reg_field_get(unit, XLPORT_MODE_REGr, rval, 2626 XPORT0_CORE_PORT_MODEf); 2627 /* Quad Port Mode. Lanes 0..3 individually active */ 2628 if (port_mode == 0x0){ 2629 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 2630 } 2631 } 2632 } 2633 #endif 2634 } 2635 } else if (IS_HG_PORT(unit , port)) { 2636 switch (port_speed_max) { 2637 case 42000: 2638 ability->speed_full_duplex |= SOC_PA_SPEED_42GB; 2639 /* fall through */ 2640 case 40000: 2641 ability->speed_full_duplex |= SOC_PA_SPEED_40GB; 2642 if(soc_feature(unit, soc_feature_higig_misc_speed_support)) { 2643 ability->speed_full_duplex |= SOC_PA_SPEED_42GB; 2644 } 2645 /* fall through */ 2646 case 32000: 2647 ability->speed_full_duplex |= SOC_PA_SPEED_32GB; 2648 /* fall through */ 2649 case 30000: 2650 ability->speed_full_duplex |= SOC_PA_SPEED_30GB; 2651 /* fall through */ 2652 case 25000: 2653 ability->speed_full_duplex |= SOC_PA_SPEED_25GB; 2654 /* fall through */ 2655 case 21000: 2656 ability->speed_full_duplex |= SOC_PA_SPEED_21GB; 2657 /* fall through */ 2658 case 20000: 2659 ability->speed_full_duplex |= SOC_PA_SPEED_20GB; 2660 if(soc_feature(unit, soc_feature_higig_misc_speed_support)) { 2661 ability->speed_full_duplex |= SOC_PA_SPEED_21GB; 2662 } 2663 /* fall through */ 2664 case 16000: 2665 ability->speed_full_duplex |= SOC_PA_SPEED_16GB; 2666 /* fall through */ 2667 case 15000: 2668 ability->speed_full_duplex |= SOC_PA_SPEED_15GB; 2669 /* fall through */ 2670 case 13000: 2671 ability->speed_full_duplex |= SOC_PA_SPEED_13GB; 2672 /* fall through */ 2673 case 12000: 2674 ability->speed_full_duplex |= SOC_PA_SPEED_12GB; 2675 /* fall through */ 2676 case 11000: 2677 ability->speed_full_duplex |= SOC_PA_SPEED_11GB; 2678 /* fall through */ 2679 case 10000: 2680 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 2681 if(soc_feature(unit, soc_feature_higig_misc_speed_support)) { 2682 ability->speed_full_duplex |= SOC_PA_SPEED_11GB; 2683 ability->speed_full_duplex |= SOC_PA_SPEED_5000MB; 2684 /* For 11G and 5G speeds, MAC should be in 10G */ 2685 } 2686 break; 2687 case 5000: 2688 if(soc_feature(unit, soc_feature_higig_misc_speed_support)) { 2689 ability->speed_full_duplex |= SOC_PA_SPEED_5000MB; 2690 /* For 5G speed, MAC will actually be set to 10G */ 2691 } 2692 break; 2693 default: 2694 break; 2695 } 2696 } else { 2697 if (port_speed_max >= 40000) { 2698 ability->speed_full_duplex |= SOC_PA_SPEED_40GB; 2699 } 2700 if (port_speed_max >= 20000) { 2701 ability->speed_full_duplex |= SOC_PA_SPEED_20GB; 2702 } 2703 if (port_speed_max >= 10000) { 2704 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 2705 } 2706 if (port_speed_max >= 5000) { 2707 ability->speed_full_duplex |= SOC_PA_SPEED_5000MB; 2708 /* For 5G speed, MAC will actually be set to 10G */ 2709 } 2710 /* Temp fix running regression, saber2 check 2711 * In Saber2, the xlmac is used for MXQ ports as well. 2712 */ 2713 if (soc_feature(unit, soc_feature_unified_port) || (SOC_IS_SABER2(unit))) { 2714 if (port_speed_max >= 2500) { 2715 ability->speed_full_duplex |= SOC_PA_SPEED_2500MB; 2716 } 2717 if (port_speed_max >= 1000) { 2718 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 2719 } 2720 if (port_speed_max >= 100) { 2721 ability->speed_full_duplex |= SOC_PA_SPEED_100MB; 2722 } 2723 if (port_speed_max >= 10) { 2724 ability->speed_full_duplex |= SOC_PA_SPEED_10MB; 2725 } 2726 } 2727 } 2728 2729 LOG_VERBOSE(BSL_LS_SOC_10G, 2730 (BSL_META_U(unit, 2731 "mac_xl_ability_local_get: unit %d port %s " 2732 "speed_half=0x%x speed_full=0x%x encap=0x%x pause=0x%x " 2733 "interface=0x%x medium=0x%x loopback=0x%x flags=0x%x\n"), 2734 unit, SOC_PORT_NAME(unit, port), 2735 ability->speed_half_duplex, ability->speed_full_duplex, 2736 ability->encap, ability->pause, ability->interface, 2737 ability->medium, ability->loopback, ability->flags)); 2738 return SOC_E_NONE; 2739 } 2740 2741 static int 2742 mac_xl_timesync_tx_info_get (int unit, soc_port_t port, 2743 soc_port_timesync_tx_info_t *tx_info) 2744 { 2745 uint64 rval; 2746 2747 SOC_IF_ERROR_RETURN 2748 (READ_XLMAC_TX_TIMESTAMP_FIFO_STATUSr(unit, port, &rval)); 2749 if (soc_reg64_field32_get(unit, XLMAC_TX_TIMESTAMP_FIFO_STATUSr, rval, 2750 ENTRY_COUNTf) == 0) { 2751 return SOC_E_EMPTY; 2752 } 2753 SOC_IF_ERROR_RETURN 2754 (READ_XLMAC_TX_TIMESTAMP_FIFO_DATAr(unit, port, &rval)); 2755 tx_info->timestamps_in_fifo = soc_reg64_field32_get(unit, XLMAC_TX_TIMESTAMP_FIFO_DATAr, 2756 rval, TIME_STAMPf); 2757 tx_info->timestamps_in_fifo_hi = 0; 2758 tx_info->sequence_id = soc_reg64_field32_get(unit, 2759 XLMAC_TX_TIMESTAMP_FIFO_DATAr, rval, SEQUENCE_IDf); 2760 2761 return (SOC_E_NONE); 2762 } 2763 2764 /* Exported XLMAC driver structure */ 2765 mac_driver_t soc_mac_xl = { 2766 "XLMAC Driver", /* drv_name */ 2767 mac_xl_init, /* md_init */ 2768 mac_xl_enable_set, /* md_enable_set */ 2769 mac_xl_enable_get, /* md_enable_get */ 2770 mac_xl_duplex_set, /* md_duplex_set */ 2771 mac_xl_duplex_get, /* md_duplex_get */ 2772 mac_xl_speed_set, /* md_speed_set */ 2773 mac_xl_speed_get, /* md_speed_get */ 2774 mac_xl_pause_set, /* md_pause_set */ 2775 mac_xl_pause_get, /* md_pause_get */ 2776 mac_xl_pause_addr_set, /* md_pause_addr_set */ 2777 mac_xl_pause_addr_get, /* md_pause_addr_get */ 2778 mac_xl_loopback_set, /* md_lb_set */ 2779 mac_xl_loopback_get, /* md_lb_get */ 2780 mac_xl_interface_set, /* md_interface_set */ 2781 mac_xl_interface_get, /* md_interface_get */ 2782 NULL, /* md_ability_get - Deprecated */ 2783 mac_xl_frame_max_set, /* md_frame_max_set */ 2784 mac_xl_frame_max_get, /* md_frame_max_get */ 2785 mac_xl_ifg_set, /* md_ifg_set */ 2786 mac_xl_ifg_get, /* md_ifg_get */ 2787 mac_xl_encap_set, /* md_encap_set */ 2788 mac_xl_encap_get, /* md_encap_get */ 2789 mac_xl_control_set, /* md_control_set */ 2790 mac_xl_control_get, /* md_control_get */ 2791 mac_xl_ability_local_get, /* md_ability_local_get */ 2792 mac_xl_timesync_tx_info_get /* md_timesync_tx_info_get */ 2793 }; 2794 2795 #endif /* BCM_XLMAC_SUPPORT */