cmac.c (60228B)
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 * CMAC driver 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <sal/core/libc.h> 13 #include <shared/alloc.h> 14 #include <sal/core/spl.h> 15 #include <sal/core/boot.h> 16 17 #include <soc/drv.h> 18 #include <soc/error.h> 19 #include <soc/cmic.h> 20 #include <soc/portmode.h> 21 #include <soc/ll.h> 22 #include <soc/counter.h> 23 #include <soc/macutil.h> 24 #include <soc/phyctrl.h> 25 26 #ifdef BCM_CMAC_SUPPORT 27 28 /* 29 * CMAC Register field definitions. 30 */ 31 32 /* Transmit CRC Modes (Receive has bit field definitions in register) */ 33 #define CMAC_CRC_APPEND 0x00 /* Append CRC (Default) */ 34 #define CMAC_CRC_KEEP 0x01 /* CRC Assumed correct */ 35 #define CMAC_CRC_REGEN 0x02 /* Replace CRC with a new one */ 36 #define CMAC_CRC_PER_PKT_MODE 0x03 /* Update CRC based on h/w signal 37 from port block */ 38 39 #define JUMBO_MAXSZ 0x3fe8 /* Max legal value (per regsfile) */ 40 41 /* 42 * CMAC timestamp delay definitions 43 * From Katana/triumph3 spec, Timestamp clock period is 4ns (125Mhz) and 44 * Tx Line Clock period CMAC (341.8Mhz) is 2.9ns 45 */ 46 #define CMAC_TX_LINE_RATE_NS 0x3 47 48 49 mac_driver_t soc_mac_c; 50 51 #ifdef BROADCOM_DEBUG 52 static char *mac_c_encap_mode[] = SOC_ENCAP_MODE_NAMES_INITIALIZER; 53 static char *mac_c_port_if_names[] = SOC_PORT_IF_NAMES_INITIALIZER; 54 #endif /* BROADCOM_DEBUG */ 55 56 #define SOC_CMAC_SPEED_10 0x0 57 #define SOC_CMAC_SPEED_100 0x1 58 #define SOC_CMAC_SPEED_1000 0x2 59 #define SOC_CMAC_SPEED_2500 0x3 60 #define SOC_CMAC_SPEED_10000 0x4 61 62 63 /* Forward declarations */ 64 STATIC int mac_c_loopback_set(int unit, soc_port_t port, int lb); 65 STATIC int mac_c_loopback_get(int unit, soc_port_t port, int *lb); 66 STATIC int mac_c_frame_max_set(int unit, soc_port_t port, int size); 67 STATIC int mac_c_frame_max_get(int unit, soc_port_t port, int *size); 68 STATIC int mac_c_pause_set(int unit, soc_port_t port, int pause_tx, int pause_rx); 69 STATIC int mac_c_pause_get(int unit, soc_port_t port, int *pause_tx, int *pause_rx); 70 71 STATIC int 72 _mac_c_drain_cells(int unit, soc_port_t port) 73 { 74 int rv; 75 int pause_tx, pause_rx, pfc_rx, llfc_rx; 76 77 rv = SOC_E_NONE; 78 79 if (SOC_IS_RELOADING(unit)) { 80 return rv; 81 } 82 83 /* Drain cells in mmu/port before cells entering TX FIFO */ 84 SOC_IF_ERROR_RETURN(soc_mmu_flush_enable(unit, port, TRUE)); 85 86 /* Disable pause/pfc/llfc function */ 87 SOC_IF_ERROR_RETURN 88 (soc_mac_c.md_pause_get(unit, port, &pause_tx, &pause_rx)); 89 SOC_IF_ERROR_RETURN 90 (soc_mac_c.md_pause_set(unit, port, pause_tx, 0)); 91 92 SOC_IF_ERROR_RETURN 93 (soc_mac_c.md_control_get(unit, port, SOC_MAC_CONTROL_PFC_RX_ENABLE, 94 &pfc_rx)); 95 SOC_IF_ERROR_RETURN 96 (soc_mac_c.md_control_set(unit, port, SOC_MAC_CONTROL_PFC_RX_ENABLE, 97 0)); 98 99 SOC_IF_ERROR_RETURN 100 (soc_mac_c.md_control_get(unit, port, SOC_MAC_CONTROL_LLFC_RX_ENABLE, 101 &llfc_rx)); 102 SOC_IF_ERROR_RETURN 103 (soc_mac_c.md_control_set(unit, port, SOC_MAC_CONTROL_LLFC_RX_ENABLE, 104 0)); 105 106 /* Drain data in TX FIFO without egressing */ 107 SOC_IF_ERROR_RETURN 108 (soc_reg_field32_modify(unit, CMAC_TX_CTRLr, port, DISCARDf, 1)); 109 110 /* Notify PHY driver */ 111 SOC_IF_ERROR_RETURN 112 (soc_phyctrl_notify(unit, port, phyEventStop, PHY_STOP_DRAIN)); 113 114 /* Wait until mmu cell count is 0 */ 115 rv = soc_egress_drain_cells(unit, port, 250000); 116 if (SOC_E_NONE == rv) { 117 /* Wait until TX fifo cell count is 0 */ 118 rv = soc_txfifo_drain_cells(unit, port, 250000); 119 } 120 121 /* Notify PHY driver */ 122 SOC_IF_ERROR_RETURN 123 (soc_phyctrl_notify(unit, port, phyEventResume, PHY_STOP_DRAIN)); 124 125 /* Stop TX FIFO drainging */ 126 SOC_IF_ERROR_RETURN 127 (soc_reg_field32_modify(unit, CMAC_TX_CTRLr, port, DISCARDf, 0)); 128 129 /* Restore original pause/pfc/llfc configuration */ 130 SOC_IF_ERROR_RETURN 131 (soc_mac_c.md_pause_set(unit, port, pause_tx, pause_rx)); 132 SOC_IF_ERROR_RETURN 133 (soc_mac_c.md_control_set(unit, port, SOC_MAC_CONTROL_PFC_RX_ENABLE, 134 pfc_rx)); 135 SOC_IF_ERROR_RETURN 136 (soc_mac_c.md_control_set(unit, port, SOC_MAC_CONTROL_LLFC_RX_ENABLE, 137 llfc_rx)); 138 139 /* Stop draining cells in mmu/port */ 140 SOC_IF_ERROR_RETURN(soc_mmu_flush_enable(unit, port, FALSE)); 141 142 return rv; 143 } 144 145 /* 146 * Function: 147 * mac_c_init 148 * Purpose: 149 * Initialize Cmac into a known good state. 150 * Parameters: 151 * unit - XGS unit #. 152 * port - Port number on unit. 153 * Returns: 154 * SOC_E_XXX 155 * Notes: 156 */ 157 STATIC int 158 mac_c_init(int unit, soc_port_t port) 159 { 160 soc_info_t *si; 161 soc_reg_t reg; 162 uint64 mac_ctrl, rx_ctrl, tx_ctrl, rval; 163 int ipg; 164 int mode; 165 166 LOG_VERBOSE(BSL_LS_SOC_100G, 167 (BSL_META_U(unit, 168 "mac_c_init: unit %d port %s\n"), 169 unit, SOC_PORT_NAME(unit, port))); 170 171 si = &SOC_INFO(unit); 172 173 /* Disable Tx/Rx, assume that MAC is stable (or out of reset) */ 174 SOC_IF_ERROR_RETURN(READ_CMAC_CTRLr(unit, port, &mac_ctrl)); 175 soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, SOFT_RESETf, 0); 176 soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, RX_ENf, 0); 177 soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, TX_ENf, 0); 178 if (soc_reg_field_valid(unit, CMAC_CTRLr, XLGMII_ALIGN_ENBf)) { 179 180 if (IS_HG_PORT(unit, port) && (si->port_speed_max[port] >= 106000)) { 181 182 soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, 183 XLGMII_ALIGN_ENBf, 0); 184 185 } else { 186 soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, 187 XLGMII_ALIGN_ENBf, 1); 188 } 189 190 } 191 soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, 192 XGMII_IPG_CHECK_DISABLEf, 193 IS_HG_PORT(unit, port) ? 1 : 0); 194 195 SOC_IF_ERROR_RETURN(WRITE_CMAC_CTRLr(unit, port, mac_ctrl)); 196 197 198 if (SOC_REG_IS_VALID(unit, CPORT_MAC_MODEr)) { 199 reg = CPORT_MAC_MODEr; 200 } else { 201 reg = PORT_CMAC_MODEr; 202 } 203 SOC_IF_ERROR_RETURN 204 (soc_reg_field32_modify(unit, reg, port, CGMII_MODEf, 205 si->port_speed_max[port] > 106000 ? 1 : 0)); 206 207 SOC_IF_ERROR_RETURN(READ_CMAC_RX_CTRLr(unit, port, &rx_ctrl)); 208 soc_reg64_field32_set(unit, CMAC_RX_CTRLr, &rx_ctrl, STRIP_CRCf, 0); 209 SOC_IF_ERROR_RETURN(WRITE_CMAC_RX_CTRLr(unit, port, rx_ctrl)); 210 211 SOC_IF_ERROR_RETURN(READ_CMAC_TX_CTRLr(unit, port, &tx_ctrl)); 212 ipg = IS_HG_PORT(unit,port)? SOC_PERSIST(unit)->ipg[port].fd_hg: 213 SOC_PERSIST(unit)->ipg[port].fd_xe; 214 soc_reg64_field32_set(unit, CMAC_TX_CTRLr, &tx_ctrl, AVERAGE_IPGf, 215 (ipg / 8) & 0x1f); 216 217 soc_reg64_field32_set(unit, CMAC_TX_CTRLr, &tx_ctrl, CRC_MODEf, 218 CMAC_CRC_PER_PKT_MODE); 219 220 SOC_IF_ERROR_RETURN(WRITE_CMAC_TX_CTRLr(unit, port, tx_ctrl)); 221 222 if (IS_ST_PORT(unit, port)) { 223 soc_mac_c.md_pause_set(unit, port, FALSE, FALSE); 224 } else { 225 soc_mac_c.md_pause_set(unit, port, TRUE, TRUE); 226 } 227 228 SOC_IF_ERROR_RETURN 229 (soc_reg_field32_modify(unit, CMAC_PFC_CTRLr, port, PFC_REFRESH_ENf, 230 1)); 231 232 if (soc_property_port_get(unit, port, spn_PHY_WAN_MODE, FALSE)) { 233 /* Max speed for WAN mode is 9.294Gbps. 234 * This setting gives 10Gbps * (13/14) or 9.286 Gbps */ 235 SOC_IF_ERROR_RETURN 236 (soc_mac_c.md_control_set(unit, port, 237 SOC_MAC_CONTROL_FRAME_SPACING_STRETCH, 238 13)); 239 } 240 241 /* Set jumbo max size (8000 byte payload) */ 242 COMPILER_64_ZERO(rval); 243 #ifdef BCM_XGS_SUPPORT 244 if (SOC_IS_XGS(unit)) { 245 soc_reg64_field32_set(unit, CMAC_RX_MAX_SIZEr, &rval, RX_MAX_SIZEf, 246 SOC_INFO(unit).max_mtu); 247 } else 248 #endif 249 { 250 soc_reg64_field32_set(unit, CMAC_RX_MAX_SIZEr, &rval, RX_MAX_SIZEf, 251 JUMBO_MAXSZ); 252 } 253 SOC_IF_ERROR_RETURN(WRITE_CMAC_RX_MAX_SIZEr(unit, port, rval)); 254 255 /* Setup header mode, check for property for higig2 mode */ 256 COMPILER_64_ZERO(rval); 257 if (IS_HG_PORT(unit, port)) { 258 mode = soc_property_port_get(unit, port, spn_HIGIG2_HDR_MODE, 0) ? 259 2 : 1; 260 soc_reg64_field32_set(unit, CMAC_MODEr, &rval, HDR_MODEf, mode); 261 } 262 soc_reg64_field32_set(unit, CMAC_MODEr, &rval, SPEED_MODEf, SOC_CMAC_SPEED_10000); 263 SOC_IF_ERROR_RETURN(WRITE_CMAC_MODEr(unit, port, rval)); 264 265 /* Disable loopback and bring CMAC out of reset */ 266 soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, CORE_REMOTE_LPBKf, 0); 267 if (soc_reg_field_valid(unit, CMAC_CTRLr, LINE_REMOTE_LPBKf)) { 268 soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, LINE_REMOTE_LPBKf, 269 0); 270 } 271 soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, CORE_LOCAL_LPBKf, 0); 272 soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, LINE_LOCAL_LPBKf, 0); 273 soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, RX_ENf, 1); 274 soc_reg64_field32_set(unit, CMAC_CTRLr, &mac_ctrl, TX_ENf, 1); 275 SOC_IF_ERROR_RETURN(WRITE_CMAC_CTRLr(unit, port, mac_ctrl)); 276 277 return SOC_E_NONE; 278 } 279 280 /* 281 * Function: 282 * mac_c_enable_set 283 * Purpose: 284 * Enable or disable MAC 285 * Parameters: 286 * unit - XGS unit #. 287 * port - Port number on unit. 288 * enable - TRUE to enable, FALSE to disable 289 * Returns: 290 * SOC_E_XXX 291 */ 292 STATIC int 293 mac_c_enable_set(int unit, soc_port_t port, int enable) 294 { 295 uint64 ctrl, octrl; 296 pbmp_t mask; 297 298 LOG_VERBOSE(BSL_LS_SOC_100G, 299 (BSL_META_U(unit, 300 "mac_c_enable_set: unit %d port %s enable=%s\n"), 301 unit, SOC_PORT_NAME(unit, port), 302 enable ? "True" : "False")); 303 304 SOC_IF_ERROR_RETURN(READ_CMAC_CTRLr(unit, port, &ctrl)); 305 octrl = ctrl; 306 /* Don't disable TX since it stops egress and hangs if CPU sends */ 307 soc_reg64_field32_set(unit, CMAC_CTRLr, &ctrl, TX_ENf, 1); 308 soc_reg64_field32_set(unit, CMAC_CTRLr, &ctrl, RX_ENf, enable ? 1 : 0); 309 if (COMPILER_64_NE(ctrl, octrl)) { 310 SOC_IF_ERROR_RETURN(WRITE_CMAC_CTRLr(unit, port, ctrl)); 311 sal_udelay(10); 312 } 313 314 /* Put the CMAC in a soft reset state when disabled to allow packets to 315 * drain from the TX FIFO */ 316 soc_reg64_field32_set(unit, CMAC_CTRLr, &ctrl, SOFT_RESETf, 317 enable ? 0 : 1); 318 if (COMPILER_64_NE(ctrl, octrl)) { 319 SOC_IF_ERROR_RETURN(WRITE_CMAC_CTRLr(unit, port, ctrl)); 320 } 321 322 if (enable) { 323 soc_link_mask2_get(unit, &mask); 324 SOC_PBMP_PORT_ADD(mask, port); 325 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 326 SOC_IF_ERROR_RETURN(soc_phyctrl_notify(unit, port, phyEventResume, 327 PHY_STOP_MAC_DIS)); 328 } else { 329 soc_link_mask2_get(unit, &mask); 330 SOC_PBMP_PORT_REMOVE(mask, port); 331 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 332 SOC_IF_ERROR_RETURN(_mac_c_drain_cells(unit, port)); 333 SOC_IF_ERROR_RETURN(soc_phyctrl_notify(unit, port, phyEventStop, 334 PHY_STOP_MAC_DIS)); 335 } 336 337 return SOC_E_NONE; 338 } 339 340 /* 341 * Function: 342 * mac_c_enable_get 343 * Purpose: 344 * Get MAC enable state 345 * Parameters: 346 * unit - XGS unit #. 347 * port - Port number on unit. 348 * enable - (OUT) TRUE if enabled, FALSE if disabled 349 * Returns: 350 * SOC_E_XXX 351 */ 352 STATIC int 353 mac_c_enable_get(int unit, soc_port_t port, int *enable) 354 { 355 uint64 ctrl; 356 357 SOC_IF_ERROR_RETURN(READ_CMAC_CTRLr(unit, port, &ctrl)); 358 359 *enable = soc_reg64_field32_get(unit, CMAC_CTRLr, ctrl, RX_ENf); 360 361 LOG_VERBOSE(BSL_LS_SOC_100G, 362 (BSL_META_U(unit, 363 "mac_c_enable_get: unit %d port %s enable=%s\n"), 364 unit, SOC_PORT_NAME(unit, port), 365 *enable ? "True" : "False")); 366 367 return SOC_E_NONE; 368 } 369 370 /* 371 * Function: 372 * _mac_c_timestamp_delay_set 373 * Purpose: 374 * Set Timestamp delay for one-step to account for lane and pipeline delay. 375 * Parameters: 376 * unit - XGS unit #. 377 * port - Port number on unit. 378 * Returns: 379 * SOC_E_XXX 380 */ 381 STATIC int 382 _mac_c_timestamp_delay_set(int unit, soc_port_t port, int speed) 383 { 384 uint64 ctrl; 385 int osts_delay, tsts_delay, conversion_delay; 386 uint32 field; 387 388 LOG_VERBOSE(BSL_LS_SOC_100G, 389 (BSL_META_U(unit, 390 "mac_c_timestamp_delay_set: unit %d port %s\n"), 391 unit, SOC_PORT_NAME(unit, port))); 392 393 if (SOC_REG_IS_VALID(unit, CMAC_TIMESTAMP_ADJUSTr)) { 394 SOC_IF_ERROR_RETURN(READ_CMAC_TIMESTAMP_ADJUSTr(unit, port, &ctrl)); 395 396 /* 397 * CMAC pipeline delay is : ( as in CMAC specification) 398 * = (7.5 * TX line clock period) + (Timestamp clock period) 399 */ 400 401 402 /* 2's complement signed value of pipeline delay in ns */ 403 osts_delay = soc_property_port_get(unit, port, spn_TIMESTAMP_ADJUST(speed), 404 SOC_TIMESYNC_PLL_CLOCK_NS(unit) - 405 ((15 * CMAC_TX_LINE_RATE_NS ) / 2)); 406 407 if (SOC_E_NONE != soc_reg_signed_field_mask(unit, CMAC_TIMESTAMP_ADJUSTr, 408 TS_OSTS_ADJUSTf, osts_delay, &field)) { 409 LOG_WARN(BSL_LS_SOC_PORT, (BSL_META_U(unit, 410 "%s property out of bounds (is %d)\n"), 411 spn_TIMESTAMP_ADJUST(speed), osts_delay)); 412 field = 0; 413 } 414 415 soc_reg64_field32_set(unit, CMAC_TIMESTAMP_ADJUSTr, &ctrl, 416 TS_OSTS_ADJUSTf, field); 417 418 /* Note: TSTS delay uses same SOC property as OSTS delay, in order to allow 419 specification based on platform. However, the resulting timestamps in 420 the FIFO are only used by the application, so the application can make 421 other timestamp adjustments as required. 422 */ 423 tsts_delay = soc_property_port_get(unit, port, spn_TIMESTAMP_ADJUST(speed), 424 SOC_TIMESYNC_PLL_CLOCK_NS(unit) - 425 ((5 * CMAC_TX_LINE_RATE_NS ) / 2)); 426 427 if (SOC_E_NONE != soc_reg_signed_field_mask(unit, CMAC_TIMESTAMP_ADJUSTr, 428 TS_TSTS_ADJUSTf, tsts_delay, &field)) { 429 LOG_WARN(BSL_LS_SOC_PORT, (BSL_META_U(unit, 430 "%s property out of bounds (is %d)\n"), 431 spn_TIMESTAMP_ADJUST(speed), tsts_delay)); 432 field = 0; 433 } 434 435 soc_reg64_field32_set(unit, CMAC_TIMESTAMP_ADJUSTr, &ctrl, 436 TS_TSTS_ADJUSTf, field); 437 438 /* 5x mode delay for cmac: 1 * TX line clock period */ 439 conversion_delay = 1 * CMAC_TX_LINE_RATE_NS; 440 soc_reg64_field32_set(unit, CMAC_TIMESTAMP_ADJUSTr, &ctrl, 441 TS_OSTS_ADJUST_CONVERSION_DELAYf, conversion_delay); 442 443 SOC_IF_ERROR_RETURN(WRITE_CMAC_TIMESTAMP_ADJUSTr(unit, port, ctrl)); 444 } 445 446 return SOC_E_NONE; 447 } 448 449 /* 450 * Function: 451 * mac_c_duplex_set 452 * Purpose: 453 * Set CMAC in the specified duplex mode. 454 * Parameters: 455 * unit - XGS unit #. 456 * port - XGS port # on unit. 457 * duplex - Boolean: true --> full duplex, false --> half duplex. 458 * Returns: 459 * SOC_E_XXX 460 * Notes: 461 */ 462 STATIC int 463 mac_c_duplex_set(int unit, soc_port_t port, int duplex) 464 { 465 LOG_VERBOSE(BSL_LS_SOC_100G, 466 (BSL_META_U(unit, 467 "mac_c_duplex_set: unit %d port %s duplex=%s\n"), 468 unit, SOC_PORT_NAME(unit, port), 469 duplex ? "Full" : "Half")); 470 return SOC_E_NONE; 471 } 472 473 /* 474 * Function: 475 * mac_c_duplex_get 476 * Purpose: 477 * Get CMAC duplex mode. 478 * Parameters: 479 * unit - XGS unit #. 480 * duplex - (OUT) Boolean: true --> full duplex, false --> half duplex. 481 * Returns: 482 * SOC_E_XXX 483 */ 484 STATIC int 485 mac_c_duplex_get(int unit, soc_port_t port, int *duplex) 486 { 487 *duplex = TRUE; /* Always full duplex */ 488 489 LOG_VERBOSE(BSL_LS_SOC_100G, 490 (BSL_META_U(unit, 491 "mac_c_duplex_get: unit %d port %s duplex=%s\n"), 492 unit, SOC_PORT_NAME(unit, port), 493 *duplex ? "Full" : "Half")); 494 return SOC_E_NONE; 495 } 496 497 /* 498 * Function: 499 * mac_c_pause_set 500 * Purpose: 501 * Configure CMAC to transmit/receive pause frames. 502 * Parameters: 503 * unit - XGS unit #. 504 * port - XGS port # on unit. 505 * pause_tx - Boolean: transmit pause or -1 (don't change) 506 * pause_rx - Boolean: receive pause or -1 (don't change) 507 * Returns: 508 * SOC_E_XXX 509 */ 510 STATIC int 511 mac_c_pause_set(int unit, soc_port_t port, int pause_tx, int pause_rx) 512 { 513 soc_field_t fields[2] = { TX_PAUSE_ENf, RX_PAUSE_ENf }; 514 uint32 values[2]; 515 516 LOG_VERBOSE(BSL_LS_SOC_100G, 517 (BSL_META_U(unit, 518 "mac_c_pause_set: unit %d port %s TX=%s RX=%s\n"), 519 unit, SOC_PORT_NAME(unit, port), 520 pause_tx != FALSE ? "on" : "off", 521 pause_rx != FALSE ? "on" : "off")); 522 523 values[0] = pause_tx != FALSE ? 1 : 0; 524 values[1] = pause_rx != FALSE ? 1 : 0; 525 return soc_reg_fields32_modify(unit, CMAC_PAUSE_CTRLr, port, 2, 526 fields, values); 527 } 528 529 /* 530 * Function: 531 * mac_c_pause_get 532 * Purpose: 533 * Return the pause ability of CMAC 534 * Parameters: 535 * unit - XGS unit #. 536 * port - XGS port # on unit. 537 * pause_tx - Boolean: transmit pause 538 * pause_rx - Boolean: receive pause 539 * pause_mac - MAC address used for pause transmission. 540 * Returns: 541 * SOC_E_XXX 542 */ 543 STATIC int 544 mac_c_pause_get(int unit, soc_port_t port, int *pause_tx, int *pause_rx) 545 { 546 uint64 rval; 547 548 SOC_IF_ERROR_RETURN(READ_CMAC_PAUSE_CTRLr(unit, port, &rval)); 549 *pause_tx = 550 soc_reg64_field32_get(unit, CMAC_PAUSE_CTRLr, rval, TX_PAUSE_ENf); 551 *pause_rx = 552 soc_reg64_field32_get(unit, CMAC_PAUSE_CTRLr, rval, RX_PAUSE_ENf); 553 LOG_VERBOSE(BSL_LS_SOC_100G, 554 (BSL_META_U(unit, 555 "mac_c_pause_get: unit %d port %s TX=%s RX=%s\n"), 556 unit, SOC_PORT_NAME(unit, port), 557 *pause_tx ? "on" : "off", 558 *pause_rx ? "on" : "off")); 559 return SOC_E_NONE; 560 } 561 562 /* 563 * Function: 564 * mac_c_speed_set 565 * Purpose: 566 * Set CMAC in the specified speed. 567 * Parameters: 568 * unit - XGS unit #. 569 * port - XGS port # on unit. 570 * speed - 100000, 120000. 571 * Returns: 572 * SOC_E_XXX 573 */ 574 STATIC int 575 mac_c_speed_set(int unit, soc_port_t port, int speed) 576 { 577 soc_reg_t reg; 578 int loopback, frame_max; 579 int pause_rx, pause_tx; 580 581 LOG_VERBOSE(BSL_LS_SOC_100G, 582 (BSL_META_U(unit, 583 "mac_c_speed_set: unit %d port %s speed=%dMb\n"), 584 unit, SOC_PORT_NAME(unit, port), 585 speed)); 586 587 /* Save MAC state before reset */ 588 SOC_IF_ERROR_RETURN(mac_c_loopback_get(unit, port, &loopback)); 589 SOC_IF_ERROR_RETURN(mac_c_frame_max_get(unit, port, &frame_max)); 590 SOC_IF_ERROR_RETURN(mac_c_pause_get(unit, port, &pause_tx, &pause_rx)); 591 592 /* mac init */ 593 594 SOC_IF_ERROR_RETURN(mac_c_init(unit,port)); 595 596 /* Restore MAC state after reset */ 597 SOC_IF_ERROR_RETURN(mac_c_loopback_set(unit, port, loopback)); 598 SOC_IF_ERROR_RETURN(mac_c_frame_max_set(unit, port, frame_max)); 599 SOC_IF_ERROR_RETURN(mac_c_pause_set(unit, port, pause_tx, pause_rx)); 600 601 /* Set cmac timestamp delay */ 602 SOC_IF_ERROR_RETURN(_mac_c_timestamp_delay_set(unit,port, speed)); 603 604 /* program the XLGMII field */ 605 if (soc_reg_field_valid(unit, CMAC_CTRLr, XLGMII_ALIGN_ENBf)) { 606 if (IS_HG_PORT(unit, port) && (speed >= 106000)) { 607 SOC_IF_ERROR_RETURN 608 (soc_reg_field32_modify(unit, CMAC_CTRLr, port, 609 XLGMII_ALIGN_ENBf, 0)); 610 611 } else { 612 SOC_IF_ERROR_RETURN 613 (soc_reg_field32_modify(unit, CMAC_CTRLr, port, XLGMII_ALIGN_ENBf, 614 speed >= 100000 ? 1 : 0)); 615 } 616 } 617 618 /* And the PORT CGMII field */ 619 620 if (SOC_REG_IS_VALID(unit, CPORT_MAC_MODEr)) { 621 reg = CPORT_MAC_MODEr; 622 } else { 623 reg = PORT_CMAC_MODEr; 624 } 625 SOC_IF_ERROR_RETURN 626 (soc_reg_field32_modify(unit, reg, port, CGMII_MODEf, 627 speed > 106000 ? 1 : 0)); 628 629 return SOC_E_NONE; 630 } 631 632 /* 633 * Function: 634 * mac_c_speed_get 635 * Purpose: 636 * Get CMAC speed 637 * Parameters: 638 * unit - XGS unit #. 639 * port - XGS port # on unit. 640 * speed - (OUT) speed in Mb 641 * Returns: 642 * SOC_E_XXX 643 */ 644 STATIC int 645 mac_c_speed_get(int unit, soc_port_t port, int *speed) 646 { 647 uint64 rval; 648 649 SOC_IF_ERROR_RETURN(READ_CMAC_MODEr(unit, port, &rval)); 650 switch (soc_reg64_field32_get(unit, CMAC_MODEr, rval, SPEED_MODEf)) { 651 case SOC_CMAC_SPEED_10: 652 *speed = 10; 653 break; 654 case SOC_CMAC_SPEED_100: 655 *speed = 100; 656 break; 657 case SOC_CMAC_SPEED_1000: 658 *speed = 1000; 659 break; 660 case SOC_CMAC_SPEED_2500: 661 *speed = 2500; 662 break; 663 case SOC_CMAC_SPEED_10000: 664 default: 665 *speed = 10000; 666 } 667 668 LOG_VERBOSE(BSL_LS_SOC_100G, 669 (BSL_META_U(unit, 670 "mac_c_speed_get: unit %d port %s speed=%dMb\n"), 671 unit, SOC_PORT_NAME(unit, port), 672 *speed)); 673 return SOC_E_NONE; 674 } 675 676 /* 677 * Function: 678 * mac_c_loopback_set 679 * Purpose: 680 * Set a CMAC into/out-of loopback mode 681 * Parameters: 682 * unit - XGS unit #. 683 * port - XGS unit # on unit. 684 * loopback - Boolean: true -> loopback mode, false -> normal operation 685 * Note: 686 * On Cmac, when setting loopback, we enable the TX/RX function also. 687 * Note that to test the PHY, we use the remote loopback facility. 688 * Returns: 689 * SOC_E_XXX 690 */ 691 STATIC int 692 mac_c_loopback_set(int unit, soc_port_t port, int lb) 693 { 694 LOG_VERBOSE(BSL_LS_SOC_100G, 695 (BSL_META_U(unit, 696 "mac_c_loopback_set: unit %d port %s loopback=%s\n"), 697 unit, SOC_PORT_NAME(unit, port), 698 lb ? "local" : "no")); 699 700 /* need to enable clock compensation for applicable serdes device */ 701 (void)soc_phyctrl_notify(unit, port, phyEventMacLoopback, lb? 1: 0); 702 703 return soc_reg_field32_modify(unit, CMAC_CTRLr, port, LINE_LOCAL_LPBKf, 704 lb ? 1 : 0); 705 706 return SOC_E_NONE; 707 } 708 709 /* 710 * Function: 711 * mac_c_loopback_get 712 * Purpose: 713 * Get current CMAC loopback mode setting. 714 * Parameters: 715 * unit - XGS unit #. 716 * port - XGS port # on unit. 717 * loopback - (OUT) Boolean: true = loopback, false = normal 718 * Returns: 719 * SOC_E_XXX 720 */ 721 STATIC int 722 mac_c_loopback_get(int unit, soc_port_t port, int *lb) 723 { 724 uint64 ctrl; 725 int local, remote; 726 727 SOC_IF_ERROR_RETURN(READ_CMAC_CTRLr(unit, port, &ctrl)); 728 729 remote = soc_reg64_field32_get(unit, CMAC_CTRLr, ctrl, CORE_REMOTE_LPBKf); 730 if (soc_reg_field_valid(unit, CMAC_CTRLr, LINE_REMOTE_LPBKf)) { 731 remote |= soc_reg64_field32_get(unit, CMAC_CTRLr, ctrl, 732 LINE_REMOTE_LPBKf); 733 } 734 local = soc_reg64_field32_get(unit, CMAC_CTRLr, ctrl, CORE_LOCAL_LPBKf) | 735 soc_reg64_field32_get(unit, CMAC_CTRLr, ctrl, LINE_LOCAL_LPBKf); 736 *lb = local | remote; 737 738 LOG_VERBOSE(BSL_LS_SOC_100G, 739 (BSL_META_U(unit, 740 "mac_c_loopback_get: unit %d port %s loopback=%s\n"), 741 unit, SOC_PORT_NAME(unit, port), 742 *lb ? (remote ? "remote" : "local") : "no")); 743 return SOC_E_NONE; 744 } 745 746 /* 747 * Function: 748 * mac_c_pause_addr_set 749 * Purpose: 750 * Configure PAUSE frame source address. 751 * Parameters: 752 * unit - XGS unit #. 753 * port - XGS port # on unit. 754 * pause_mac - (OUT) MAC address used for pause transmission. 755 * Returns: 756 * SOC_E_XXX 757 */ 758 STATIC int 759 mac_c_pause_addr_set(int unit, soc_port_t port, sal_mac_addr_t m) 760 { 761 uint64 r, tmp; 762 int i; 763 764 LOG_VERBOSE(BSL_LS_SOC_100G, 765 (BSL_META_U(unit, 766 "mac_c_pause_addr_set: unit %d port %s MAC=<" 767 "%02x:%02x:%02x:%02x:%02x:%02x>\n"), 768 unit, SOC_PORT_NAME(unit, port), 769 m[0], m[1], m[2], m[3], m[4], m[5])); 770 771 COMPILER_64_ZERO(r); 772 for (i = 0; i< 6; i++) { 773 COMPILER_64_SET(tmp, 0, m[i]); 774 COMPILER_64_SHL(r, 8); 775 COMPILER_64_OR(r, tmp); 776 } 777 778 SOC_IF_ERROR_RETURN(WRITE_CMAC_TX_MAC_SAr(unit, port, r)); 779 SOC_IF_ERROR_RETURN(WRITE_CMAC_RX_MAC_SAr(unit, port, r)); 780 781 return SOC_E_NONE; 782 } 783 784 /* 785 * Function: 786 * mac_c_pause_addr_get 787 * Purpose: 788 * Retrieve PAUSE frame source address. 789 * Parameters: 790 * unit - XGS unit #. 791 * port - XGS port # on unit. 792 * pause_mac - (OUT) MAC address used for pause transmission. 793 * Returns: 794 * SOC_E_XXX 795 * NOTE: We always write the same thing to TX & RX SA 796 * so, we just return the contects on RX_MAC_SA. 797 */ 798 STATIC int 799 mac_c_pause_addr_get(int unit, soc_port_t port, sal_mac_addr_t m) 800 { 801 uint64 reg; 802 uint32 msw; 803 uint32 lsw; 804 805 SOC_IF_ERROR_RETURN(READ_CMAC_RX_MAC_SAr(unit, port, ®)); 806 COMPILER_64_TO_32_HI(msw, reg); 807 COMPILER_64_TO_32_LO(lsw, reg); 808 809 m[0] = (uint8) ( ( msw & 0x0000ff00 ) >> 8 ); 810 m[1] = (uint8) ( msw & 0x000000ff ); 811 812 m[2] = (uint8) ( ( lsw & 0xff000000) >> 24 ); 813 m[3] = (uint8) ( ( lsw & 0x00ff0000) >> 16 ); 814 m[4] = (uint8) ( ( lsw & 0x0000ff00) >> 8 ); 815 m[5] = (uint8) ( lsw & 0x000000ff ); 816 817 LOG_VERBOSE(BSL_LS_SOC_100G, 818 (BSL_META_U(unit, 819 "mac_c_pause_addr_get: unit %d port %s MAC=<" 820 "%02x:%02x:%02x:%02x:%02x:%02x>\n"), 821 unit, SOC_PORT_NAME(unit, port), 822 m[0], m[1], m[2], m[3], m[4], m[5])); 823 return SOC_E_NONE; 824 } 825 826 /* 827 * Function: 828 * mac_c_interface_set 829 * Purpose: 830 * Set a CMAC interface type 831 * Parameters: 832 * unit - XGS unit #. 833 * port - XGS port # on unit. 834 * pif - one of SOC_PORT_IF_* 835 * Returns: 836 * SOC_E_NONE 837 * SOC_E_UNAVAIL - requested mode not supported. 838 * Notes: 839 */ 840 STATIC int 841 mac_c_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 842 { 843 #ifdef BROADCOM_DEBUG 844 LOG_VERBOSE(BSL_LS_SOC_100G, 845 (BSL_META_U(unit, 846 "mac_c_interface_set: unit %d port %s interface=%s\n"), 847 unit, SOC_PORT_NAME(unit, port), 848 mac_c_port_if_names[pif])); 849 #endif 850 return SOC_E_NONE; 851 } 852 853 /* 854 * Function: 855 * mac_c_interface_get 856 * Purpose: 857 * Retrieve CMAC interface type 858 * Parameters: 859 * unit - XGS unit #. 860 * port - XGS port # on unit. 861 * pif - (OUT) one of SOC_PORT_IF_* 862 * Returns: 863 * SOC_E_NONE 864 */ 865 STATIC int 866 mac_c_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 867 { 868 COMPILER_REFERENCE(unit); 869 COMPILER_REFERENCE(port); 870 871 *pif = SOC_PORT_IF_CGMII; 872 873 #ifdef BROADCOM_DEBUG 874 LOG_VERBOSE(BSL_LS_SOC_100G, 875 (BSL_META_U(unit, 876 "mac_c_interface_get: unit %d port %s interface=%s\n"), 877 unit, SOC_PORT_NAME(unit, port), 878 mac_c_port_if_names[*pif])); 879 #endif 880 return SOC_E_NONE; 881 } 882 883 /* 884 * Function: 885 * mac_c_frame_max_set 886 * Description: 887 * Set the maximum receive frame size for the port 888 * Parameters: 889 * unit - Device number 890 * port - Port number 891 * size - Maximum frame size in bytes 892 * Return Value: 893 * BCM_E_XXX 894 */ 895 STATIC int 896 mac_c_frame_max_set(int unit, soc_port_t port, int size) 897 { 898 uint64 rval; 899 900 LOG_VERBOSE(BSL_LS_SOC_100G, 901 (BSL_META_U(unit, 902 "mac_c_frame_max_set: unit %d port %s size=%d\n"), 903 unit, SOC_PORT_NAME(unit, port), 904 size)); 905 906 if (IS_CE_PORT(unit, port)) { 907 /* For VLAN tagged packets */ 908 size += 4; 909 } 910 COMPILER_64_ZERO(rval); 911 soc_reg64_field32_set(unit, CMAC_RX_MAX_SIZEr, &rval, RX_MAX_SIZEf, size); 912 SOC_IF_ERROR_RETURN(WRITE_CMAC_RX_MAX_SIZEr(unit, port, rval)); 913 914 return SOC_E_NONE; 915 } 916 917 /* 918 * Function: 919 * mac_c_frame_max_get 920 * Description: 921 * Set the maximum receive frame size for the port 922 * Parameters: 923 * unit - Device number 924 * port - Port number 925 * size - Maximum frame size in bytes 926 * Return Value: 927 * BCM_E_XXX 928 */ 929 STATIC int 930 mac_c_frame_max_get(int unit, soc_port_t port, int *size) 931 { 932 uint64 rval; 933 934 SOC_IF_ERROR_RETURN(READ_CMAC_RX_MAX_SIZEr(unit, port, &rval)); 935 *size = soc_reg64_field32_get(unit, CMAC_RX_MAX_SIZEr, rval, RX_MAX_SIZEf); 936 if (IS_CE_PORT(unit, port)) { 937 /* For VLAN tagged packets */ 938 *size -= 4; 939 } 940 941 LOG_VERBOSE(BSL_LS_SOC_100G, 942 (BSL_META_U(unit, 943 "mac_c_frame_max_get: unit %d port %s size=%d\n"), 944 unit, SOC_PORT_NAME(unit, port), 945 *size)); 946 return SOC_E_NONE; 947 } 948 949 /* 950 * Function: 951 * mac_c_ifg_set 952 * Description: 953 * Sets the new ifg (Inter-frame gap) value 954 * Parameters: 955 * unit - Device number 956 * port - Port number 957 * speed - the speed for which the IFG is being set 958 * duplex - the duplex for which the IFG is being set 959 * ifg - number of bits to use for average inter-frame gap 960 * Return Value: 961 * BCM_E_XXX 962 * Notes: 963 * The function makes sure the IFG value makes sense and updates the 964 * IPG register in case the speed/duplex match the current settings 965 */ 966 STATIC int 967 mac_c_ifg_set(int unit, soc_port_t port, int speed, 968 soc_port_duplex_t duplex, int ifg) 969 { 970 int cur_speed; 971 int cur_duplex; 972 int real_ifg; 973 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 974 uint64 rval, orval; 975 soc_port_ability_t ability; 976 uint32 pa_flag; 977 978 LOG_VERBOSE(BSL_LS_SOC_100G, 979 (BSL_META_U(unit, 980 "mac_c_ifg_set: unit %d port %s speed=%dMb duplex=%s " 981 "ifg=%d\n"), 982 unit, SOC_PORT_NAME(unit, port), 983 speed, duplex ? "True" : "False", ifg)); 984 985 pa_flag = SOC_PA_SPEED(speed); 986 soc_mac_c.md_ability_local_get(unit, port, &ability); 987 if (!(pa_flag & ability.speed_full_duplex)) { 988 return SOC_E_PARAM; 989 } 990 991 /* Silently adjust the specified ifp bits to valid value */ 992 /* valid value: 8 to 31 bytes (i.e. multiple of 8 bits) */ 993 real_ifg = ifg < 64 ? 64 : (ifg + 7) & (0x1f << 3); 994 995 if (IS_CE_PORT(unit, port)) { 996 si->fd_xe = real_ifg; 997 } else { 998 si->fd_hg = real_ifg; 999 } 1000 1001 SOC_IF_ERROR_RETURN(mac_c_duplex_get(unit, port, &cur_duplex)); 1002 SOC_IF_ERROR_RETURN(mac_c_speed_get(unit, port, &cur_speed)); 1003 1004 if (cur_speed == speed && 1005 cur_duplex == (duplex == SOC_PORT_DUPLEX_FULL ? TRUE : FALSE)) { 1006 SOC_IF_ERROR_RETURN(READ_CMAC_TX_CTRLr(unit, port, &rval)); 1007 orval = rval; 1008 soc_reg64_field32_set(unit, CMAC_TX_CTRLr, &rval, AVERAGE_IPGf, 1009 real_ifg / 8); 1010 if (COMPILER_64_NE(rval, orval)) { 1011 SOC_IF_ERROR_RETURN(WRITE_CMAC_TX_CTRLr(unit, port, rval)); 1012 } 1013 } 1014 1015 return SOC_E_NONE; 1016 } 1017 1018 /* 1019 * Function: 1020 * mac_c_ifg_get 1021 * Description: 1022 * Sets the new ifg (Inter-frame gap) value 1023 * Parameters: 1024 * unit - Device number 1025 * port - Port number 1026 * speed - the speed for which the IFG is being set 1027 * duplex - the duplex for which the IFG is being set 1028 * size - Maximum frame size in bytes 1029 * Return Value: 1030 * BCM_E_XXX 1031 * Notes: 1032 * The function makes sure the IFG value makes sense and updates the 1033 * IPG register in case the speed/duplex match the current settings 1034 */ 1035 STATIC int 1036 mac_c_ifg_get(int unit, soc_port_t port, int speed, 1037 soc_port_duplex_t duplex, int *ifg) 1038 { 1039 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 1040 soc_port_ability_t ability; 1041 uint32 pa_flag; 1042 1043 if (!duplex) { 1044 return SOC_E_PARAM; 1045 } 1046 1047 pa_flag = SOC_PA_SPEED(speed); 1048 soc_mac_c.md_ability_local_get(unit, port, &ability); 1049 if (!(pa_flag & ability.speed_full_duplex)) { 1050 return SOC_E_PARAM; 1051 } 1052 1053 if (IS_CE_PORT(unit, port)) { 1054 *ifg = si->fd_xe; 1055 } else { 1056 *ifg = si->fd_hg; 1057 } 1058 1059 LOG_VERBOSE(BSL_LS_SOC_100G, 1060 (BSL_META_U(unit, 1061 "mac_c_ifg_get: unit %d port %s speed=%dMb duplex=%s " 1062 "ifg=%d\n"), 1063 unit, SOC_PORT_NAME(unit, port), 1064 speed, duplex ? "True" : "False", *ifg)); 1065 return SOC_E_NONE; 1066 } 1067 1068 /* 1069 * Function: 1070 * mac_c_loopback_remote_set 1071 * Purpose: 1072 * Set the CMAC into remote-loopback state. 1073 * Parameters: 1074 * unit - XGS unit #. 1075 * port - XGS port # on unit. 1076 * mode - (INT) loopback enable state 1077 * Returns: 1078 * SOC_E_XXX 1079 */ 1080 int 1081 mac_c_loopback_remote_set(int unit, soc_port_t port, int lb) 1082 { 1083 LOG_VERBOSE(BSL_LS_SOC_100G, 1084 (BSL_META_U(unit, 1085 "mac_c_loopback_remote_set: unit %d port %s loopback=%s\n"), 1086 unit, SOC_PORT_NAME(unit, port), 1087 lb ? "remote" : "no")); 1088 1089 return soc_reg_field32_modify(unit, CMAC_CTRLr, port, CORE_REMOTE_LPBKf, 1090 lb ? 1 : 0); 1091 } 1092 1093 /* 1094 * Function: 1095 * _mac_c_port_mode_update 1096 * Purpose: 1097 * Set the CMAC port encapsulation mode. 1098 * Parameters: 1099 * unit - XGS unit #. 1100 * port - XGS port # on unit. 1101 * to_hg_port - (TRUE/FALSE) 1102 * Returns: 1103 * SOC_E_XXX 1104 */ 1105 STATIC int 1106 _mac_c_port_mode_update(int unit, soc_port_t port, int to_hg_port) 1107 { 1108 uint32 rval; 1109 uint64 val64; 1110 soc_pbmp_t ctr_pbmp; 1111 int rv = SOC_E_NONE; 1112 1113 /* Pause linkscan */ 1114 soc_linkscan_pause(unit); 1115 1116 /* Pause counter collection */ 1117 COUNTER_LOCK(unit); 1118 1119 soc_xport_type_update(unit, port, to_hg_port); 1120 1121 #if defined (BCM_TRIUMPH3_SUPPORT) 1122 if (SOC_IS_TRIUMPH3(unit)) { 1123 /* no need to hard reset the Warpcore serdes device. Soft init 1124 * should be good enough. Hard reset brings 1125 * down all other ports using the same Warpcore in quad-port mode. 1126 */ 1127 } else 1128 #endif /* BCM_TRIUMPH3_SUPPORT */ 1129 { 1130 rv = soc_xgxs_reset(unit, port); 1131 } 1132 1133 if (SOC_SUCCESS(rv)) { 1134 rv = soc_phyctrl_init(unit, port); 1135 } 1136 1137 if (SOC_SUCCESS(rv)) { 1138 rv = mac_c_init(unit, port); 1139 } 1140 1141 if (SOC_SUCCESS(rv)) { 1142 rv = mac_c_enable_set(unit, port, 0); 1143 } 1144 1145 if (SOC_SUCCESS(rv)) { 1146 SOC_PBMP_CLEAR(ctr_pbmp); 1147 SOC_PBMP_PORT_SET(ctr_pbmp, port); 1148 COMPILER_64_SET(val64, 0, 0); 1149 rv = soc_counter_set_by_port(unit, ctr_pbmp, val64); 1150 } 1151 1152 COUNTER_UNLOCK(unit); 1153 soc_linkscan_continue(unit); 1154 rval = 0; 1155 SOC_IF_ERROR_RETURN(READ_PORT_CONFIGr(unit, port, &rval)); 1156 if (to_hg_port) { 1157 soc_reg_field_set(unit, PORT_CONFIGr, &rval, HIGIG_MODEf, 1); 1158 if (soc_property_port_get(unit, port, spn_HIGIG2_HDR_MODE, 0)) { 1159 soc_reg_field_set(unit, PORT_CONFIGr, &rval, HIGIG2_MODEf, 1); 1160 } 1161 } else { 1162 soc_reg_field_set(unit, PORT_CONFIGr, &rval, HIGIG_MODEf, 0); 1163 } 1164 SOC_IF_ERROR_RETURN(WRITE_PORT_CONFIGr(unit, port, rval)); 1165 return rv; 1166 } 1167 1168 /* 1169 * Function: 1170 * mac_c_encap_set 1171 * Purpose: 1172 * Set the CMAC port encapsulation mode. 1173 * Parameters: 1174 * unit - XGS unit #. 1175 * port - XGS port # on unit. 1176 * mode - (IN) encap bits (defined above) 1177 * Returns: 1178 * SOC_E_XXX 1179 */ 1180 STATIC int 1181 mac_c_encap_set(int unit, soc_port_t port, int mode) 1182 { 1183 int enable, encap, rv; 1184 1185 #ifdef BROADCOM_DEBUG 1186 LOG_VERBOSE(BSL_LS_SOC_100G, 1187 (BSL_META_U(unit, 1188 "mac_c_encap_set: unit %d port %s encapsulation=%s\n"), 1189 unit, SOC_PORT_NAME(unit, port), 1190 mac_c_encap_mode[mode])); 1191 #endif 1192 1193 switch (mode) { 1194 case SOC_ENCAP_IEEE: 1195 encap = 0; 1196 break; 1197 case SOC_ENCAP_HIGIG: 1198 encap = 1; 1199 break; 1200 case SOC_ENCAP_HIGIG2: 1201 encap = 2; 1202 break; 1203 default: 1204 return SOC_E_PARAM; 1205 } 1206 1207 if (!soc_feature(unit, soc_feature_xport_convertible)) { 1208 if ((IS_E_PORT(unit, port) && mode != SOC_ENCAP_IEEE) || 1209 (IS_ST_PORT(unit, port) && mode == SOC_ENCAP_IEEE)) { 1210 return SOC_E_PARAM; 1211 } 1212 } 1213 1214 SOC_IF_ERROR_RETURN(mac_c_enable_get(unit, port, &enable)); 1215 1216 if (enable) { 1217 /* Turn off TX/RX enable */ 1218 SOC_IF_ERROR_RETURN(mac_c_enable_set(unit, port, 0)); 1219 } 1220 1221 if (IS_E_PORT(unit, port) && mode != SOC_ENCAP_IEEE) { 1222 /* CE -> HG */ 1223 SOC_IF_ERROR_RETURN(_mac_c_port_mode_update(unit, port, TRUE)); 1224 } else if (IS_ST_PORT(unit, port) && mode == SOC_ENCAP_IEEE) { 1225 /* HG -> CE */ 1226 SOC_IF_ERROR_RETURN(_mac_c_port_mode_update(unit, port, FALSE)); 1227 } 1228 1229 /* Update the encapsulation mode */ 1230 rv = soc_reg_field32_modify(unit, CMAC_MODEr, port, HDR_MODEf, encap); 1231 1232 if (enable) { 1233 /* Re-enable transmitter and receiver */ 1234 SOC_IF_ERROR_RETURN(mac_c_enable_set(unit, port, 1)); 1235 } 1236 1237 return rv; 1238 } 1239 1240 /* 1241 * Function: 1242 * mac_c_encap_get 1243 * Purpose: 1244 * Get the CMAC port encapsulation mode. 1245 * Parameters: 1246 * unit - XGS unit #. 1247 * port - XGS port # on unit. 1248 * mode - (INT) encap bits (defined above) 1249 * Returns: 1250 * SOC_E_XXX 1251 */ 1252 STATIC int 1253 mac_c_encap_get(int unit, soc_port_t port, int *mode) 1254 { 1255 uint64 rval; 1256 1257 if (!mode) { 1258 return SOC_E_PARAM; 1259 } 1260 1261 SOC_IF_ERROR_RETURN(READ_CMAC_MODEr(unit, port, &rval)); 1262 switch (soc_reg64_field32_get(unit, CMAC_MODEr, rval, HDR_MODEf)) { 1263 case 0: 1264 *mode = SOC_ENCAP_IEEE; 1265 break; 1266 case 1: 1267 *mode = SOC_ENCAP_HIGIG; 1268 break; 1269 case 2: 1270 *mode = SOC_ENCAP_HIGIG2; 1271 break; 1272 default: 1273 *mode = SOC_ENCAP_COUNT; 1274 } 1275 1276 #ifdef BROADCOM_DEBUG 1277 LOG_VERBOSE(BSL_LS_SOC_100G, 1278 (BSL_META_U(unit, 1279 "mac_c_encap_get: unit %d port %s encapsulation=%s\n"), 1280 unit, SOC_PORT_NAME(unit, port), 1281 mac_c_encap_mode[*mode])); 1282 #endif 1283 return SOC_E_NONE; 1284 } 1285 1286 /* 1287 * Function: 1288 * mac_c_expected_rx_latency_get 1289 * Purpose: 1290 * Get the CMAC port expected Rx latency 1291 * Parameters: 1292 * unit - XGS unit #. 1293 * port - XGS port # on unit. 1294 * latency - (OUT) Latency in NS 1295 * Returns: 1296 * SOC_E_XXX 1297 */ 1298 STATIC int 1299 mac_c_expected_rx_latency_get(int unit, soc_port_t port, int *latency) 1300 { 1301 int speed = 0; 1302 SOC_IF_ERROR_RETURN(mac_c_speed_get(unit, port, &speed)); 1303 1304 1305 switch (speed) { 1306 case 1000: /* GigE */ 1307 *latency = 0; 1308 break; 1309 1310 case 10000: /* 10G */ 1311 *latency = 0; 1312 break; 1313 1314 case 100000: /* 100G */ 1315 *latency = 0; 1316 break; 1317 1318 default: 1319 *latency = 0; 1320 break; 1321 } 1322 1323 return SOC_E_NONE; 1324 } 1325 1326 /* 1327 * Function: 1328 * mac_c_control_set 1329 * Purpose: 1330 * To configure MAC control properties. 1331 * Parameters: 1332 * unit - XGS unit #. 1333 * port - XGS port # on unit. 1334 * type - MAC control property to set. 1335 * int - New setting for MAC control. 1336 * Returns: 1337 * SOC_E_XXX 1338 */ 1339 STATIC int 1340 mac_c_control_set(int unit, soc_port_t port, soc_mac_control_t type, 1341 int value) 1342 { 1343 uint64 rval, copy; 1344 uint32 fval; 1345 1346 LOG_VERBOSE(BSL_LS_SOC_100G, 1347 (BSL_META_U(unit, 1348 "mac_c_control_set: unit %d port %s type=%d value=%d\n"), 1349 unit, SOC_PORT_NAME(unit, port), 1350 type, value)); 1351 1352 switch (type) { 1353 case SOC_MAC_CONTROL_RX_SET: 1354 SOC_IF_ERROR_RETURN(READ_CMAC_CTRLr(unit, port, &rval)); 1355 copy = rval; 1356 soc_reg64_field32_set(unit, CMAC_CTRLr, &rval, RX_ENf, value ? 1 : 0); 1357 if (COMPILER_64_NE(rval, copy)) { 1358 SOC_IF_ERROR_RETURN(WRITE_CMAC_CTRLr(unit, port, rval)); 1359 } 1360 break; 1361 case SOC_MAC_CONTROL_TX_SET: 1362 SOC_IF_ERROR_RETURN(READ_CMAC_CTRLr(unit, port, &rval)); 1363 copy = rval; 1364 soc_reg64_field32_set(unit, CMAC_CTRLr, &rval, TX_ENf, value ? 1 : 0); 1365 if (COMPILER_64_NE(rval, copy)) { 1366 SOC_IF_ERROR_RETURN(WRITE_CMAC_CTRLr(unit, port, rval)); 1367 } 1368 break; 1369 case SOC_MAC_CONTROL_FRAME_SPACING_STRETCH: 1370 if (value < 0 || value > 255) { 1371 return SOC_E_PARAM; 1372 } else { 1373 SOC_IF_ERROR_RETURN(READ_CMAC_TX_CTRLr(unit, port, &rval)); 1374 if (value >= 8) { 1375 soc_reg64_field32_set(unit, CMAC_TX_CTRLr, &rval, THROT_DENOMf, 1376 value); 1377 soc_reg64_field32_set(unit, CMAC_TX_CTRLr, &rval, THROT_NUMf, 1378 1); 1379 } else { 1380 soc_reg64_field32_set(unit, CMAC_TX_CTRLr, &rval, THROT_DENOMf, 1381 0); 1382 soc_reg64_field32_set(unit, CMAC_TX_CTRLr, &rval, THROT_NUMf, 1383 0); 1384 } 1385 SOC_IF_ERROR_RETURN(WRITE_CMAC_TX_CTRLr(unit, port, rval)); 1386 } 1387 return SOC_E_NONE; 1388 1389 case SOC_MAC_PASS_CONTROL_FRAME: 1390 SOC_IF_ERROR_RETURN(READ_CMAC_RX_CTRLr(unit, port, &rval)); 1391 soc_reg64_field32_set(unit, CMAC_RX_CTRLr, &rval, RX_PASS_CTRLf, 1392 value ? 1 : 0); 1393 SOC_IF_ERROR_RETURN(WRITE_CMAC_RX_CTRLr(unit, port, rval)); 1394 break; 1395 1396 case SOC_MAC_CONTROL_PFC_TYPE: 1397 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CMAC_PFC_TYPEr, port, 1398 PFC_ETH_TYPEf, value)); 1399 break; 1400 1401 case SOC_MAC_CONTROL_PFC_OPCODE: 1402 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CMAC_PFC_OPCODEr, 1403 port, PFC_OPCODEf, value)); 1404 break; 1405 1406 case SOC_MAC_CONTROL_PFC_CLASSES: 1407 if (value != 8) { 1408 return SOC_E_PARAM; 1409 } 1410 break; 1411 1412 case SOC_MAC_CONTROL_PFC_MAC_DA_OUI: 1413 SOC_IF_ERROR_RETURN(READ_CMAC_PFC_DAr(unit, port, &rval)); 1414 fval = soc_reg64_field32_get(unit, CMAC_PFC_DAr, rval, PFC_MACDA_LOf); 1415 fval &= 0x00ffffff; 1416 fval |= (value & 0xff) << 24; 1417 soc_reg64_field32_set(unit, CMAC_PFC_DAr, &rval, PFC_MACDA_LOf, fval); 1418 1419 soc_reg64_field32_set(unit, CMAC_PFC_DAr, &rval, PFC_MACDA_HIf, 1420 value >> 8); 1421 SOC_IF_ERROR_RETURN(WRITE_CMAC_PFC_DAr(unit, port, rval)); 1422 break; 1423 1424 case SOC_MAC_CONTROL_PFC_MAC_DA_NONOUI: 1425 SOC_IF_ERROR_RETURN(READ_CMAC_PFC_DAr(unit, port, &rval)); 1426 fval = soc_reg64_field32_get(unit, CMAC_PFC_DAr, rval, PFC_MACDA_LOf); 1427 fval &= 0xff000000; 1428 fval |= value; 1429 soc_reg64_field32_set(unit, CMAC_PFC_DAr, &rval, PFC_MACDA_LOf, fval); 1430 SOC_IF_ERROR_RETURN(WRITE_CMAC_PFC_DAr(unit, port, rval)); 1431 break; 1432 1433 case SOC_MAC_CONTROL_PFC_RX_PASS: 1434 SOC_IF_ERROR_RETURN 1435 (soc_reg_field32_modify(unit, CMAC_PFC_CTRLr, port, RX_PASS_PFCf, 1436 value ? 1 : 0)); 1437 break; 1438 1439 case SOC_MAC_CONTROL_PFC_RX_ENABLE: 1440 SOC_IF_ERROR_RETURN 1441 (soc_reg_field32_modify(unit, CMAC_PFC_CTRLr, port, RX_PFC_ENf, 1442 value ? 1 : 0)); 1443 break; 1444 1445 case SOC_MAC_CONTROL_PFC_TX_ENABLE: 1446 SOC_IF_ERROR_RETURN 1447 (soc_reg_field32_modify(unit, CMAC_PFC_CTRLr, port, TX_PFC_ENf, 1448 value ? 1 : 0)); 1449 break; 1450 1451 case SOC_MAC_CONTROL_PFC_FORCE_XON: 1452 SOC_IF_ERROR_RETURN 1453 (soc_reg_field32_modify(unit, CMAC_PFC_CTRLr, port, FORCE_PFC_XONf, 1454 value ? 1 : 0)); 1455 break; 1456 1457 case SOC_MAC_CONTROL_PFC_STATS_ENABLE: 1458 SOC_IF_ERROR_RETURN 1459 (soc_reg_field32_modify(unit, CMAC_PFC_CTRLr, port, PFC_STATS_ENf, 1460 value ? 1 : 0)); 1461 break; 1462 1463 case SOC_MAC_CONTROL_PFC_REFRESH_TIME: 1464 SOC_IF_ERROR_RETURN 1465 (soc_reg_field32_modify(unit, CMAC_PFC_CTRLr, port, 1466 PFC_REFRESH_TIMERf, value)); 1467 break; 1468 1469 case SOC_MAC_CONTROL_PFC_XOFF_TIME: 1470 SOC_IF_ERROR_RETURN 1471 (soc_reg_field32_modify(unit, CMAC_PFC_CTRLr, port, 1472 PFC_XOFF_TIMERf, value)); 1473 break; 1474 1475 case SOC_MAC_CONTROL_LLFC_RX_ENABLE: 1476 SOC_IF_ERROR_RETURN 1477 (soc_reg_field32_modify(unit, CMAC_LLFC_CTRLr, port, RX_LLFC_ENf, 1478 value ? 1 : 0)); 1479 break; 1480 1481 case SOC_MAC_CONTROL_LLFC_TX_ENABLE: 1482 SOC_IF_ERROR_RETURN 1483 (soc_reg_field32_modify(unit, CMAC_LLFC_CTRLr, port, TX_LLFC_ENf, 1484 value ? 1 : 0)); 1485 break; 1486 1487 case SOC_MAC_CONTROL_EEE_ENABLE: 1488 if (!soc_feature(unit, soc_feature_eee)) { 1489 return SOC_E_UNAVAIL; 1490 } 1491 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CMAC_EEE_CTRLr, 1492 port, EEE_ENf, value)); 1493 break; 1494 1495 case SOC_MAC_CONTROL_EEE_TX_IDLE_TIME: 1496 if (!soc_feature(unit, soc_feature_eee)) { 1497 return SOC_E_UNAVAIL; 1498 } 1499 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CMAC_EEE_TIMERSr, 1500 port, EEE_DELAY_ENTRY_TIMERf, value)); 1501 break; 1502 1503 case SOC_MAC_CONTROL_EEE_TX_WAKE_TIME: 1504 if (!soc_feature(unit, soc_feature_eee)) { 1505 return SOC_E_UNAVAIL; 1506 } 1507 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CMAC_EEE_TIMERSr, 1508 port, EEE_WAKE_TIMERf, value)); 1509 break; 1510 1511 case SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE: 1512 SOC_IF_ERROR_RETURN 1513 (soc_reg_field32_modify(unit, CMAC_RX_LSS_CTRLr, port, 1514 LOCAL_FAULT_DISABLEf, value ? 0 : 1)); 1515 break; 1516 1517 case SOC_MAC_CONTROL_FAULT_REMOTE_ENABLE: 1518 SOC_IF_ERROR_RETURN 1519 (soc_reg_field32_modify(unit, CMAC_RX_LSS_CTRLr, port, 1520 REMOTE_FAULT_DISABLEf, value ? 0 : 1)); 1521 break; 1522 1523 1524 case SOC_MAC_CONTROL_FAILOVER_RX_SET: 1525 break; 1526 1527 default: 1528 return SOC_E_UNAVAIL; 1529 } 1530 1531 return SOC_E_NONE; 1532 } 1533 1534 /* 1535 * Function: 1536 * mac_c_control_get 1537 * Purpose: 1538 * To get current MAC control setting. 1539 * Parameters: 1540 * unit - XGS unit #. 1541 * port - XGS port # on unit. 1542 * type - MAC control property to set. 1543 * int - New setting for MAC control. 1544 * Returns: 1545 * SOC_E_XXX 1546 */ 1547 STATIC int 1548 mac_c_control_get(int unit, soc_port_t port, soc_mac_control_t type, 1549 int *value) 1550 { 1551 int rv; 1552 uint64 rval; 1553 uint32 fval0, fval1; 1554 1555 if (value == NULL) { 1556 return SOC_E_PARAM; 1557 } 1558 1559 rv = SOC_E_NONE; 1560 switch (type) { 1561 case SOC_MAC_CONTROL_RX_SET: 1562 SOC_IF_ERROR_RETURN(READ_CMAC_CTRLr(unit, port, &rval)); 1563 *value = soc_reg64_field32_get(unit, CMAC_CTRLr, rval, RX_ENf); 1564 break; 1565 case SOC_MAC_CONTROL_TX_SET: 1566 SOC_IF_ERROR_RETURN(READ_CMAC_CTRLr(unit, port, &rval)); 1567 *value = soc_reg64_field32_get(unit, CMAC_CTRLr, rval, TX_ENf); 1568 break; 1569 case SOC_MAC_CONTROL_SW_RESET: 1570 SOC_IF_ERROR_RETURN(READ_CMAC_CTRLr(unit, port, &rval)); 1571 *value = soc_reg64_field32_get(unit, CMAC_CTRLr, rval, SOFT_RESETf); 1572 break; 1573 case SOC_MAC_CONTROL_FRAME_SPACING_STRETCH: 1574 SOC_IF_ERROR_RETURN(READ_CMAC_TX_CTRLr(unit, port, &rval)); 1575 *value = soc_reg64_field32_get(unit, CMAC_TX_CTRLr, rval, 1576 THROT_DENOMf); 1577 rv = SOC_E_NONE; 1578 break; 1579 1580 case SOC_MAC_CONTROL_TIMESTAMP_TRANSMIT: 1581 { 1582 uint32 timestamp = 0; 1583 if (soc_feature(unit, soc_feature_timestamp_counter) && 1584 soc_property_get(unit, spn_SW_TIMESTAMP_FIFO_ENABLE, 1)) { 1585 if (soc_counter_timestamp_get(unit, port, ×tamp) != 1586 SOC_E_NOT_FOUND) { 1587 *value = (int)timestamp; 1588 break; 1589 } 1590 } 1591 1592 SOC_IF_ERROR_RETURN 1593 (READ_CMAC_TX_TIMESTAMP_FIFO_STATUSr(unit, port, &rval)); 1594 if (soc_reg64_field32_get(unit, CMAC_TX_TIMESTAMP_FIFO_STATUSr, rval, 1595 ENTRY_COUNTf) == 0) { 1596 return SOC_E_EMPTY; 1597 } 1598 SOC_IF_ERROR_RETURN 1599 (READ_CMAC_TX_TIMESTAMP_FIFO_DATAr(unit, port, &rval)); 1600 *value = soc_reg64_field32_get(unit, CMAC_TX_TIMESTAMP_FIFO_DATAr, 1601 rval, TIME_STAMPf); 1602 } 1603 break; 1604 1605 case SOC_MAC_PASS_CONTROL_FRAME: 1606 SOC_IF_ERROR_RETURN(READ_CMAC_RX_CTRLr(unit, port, &rval)); 1607 *value = soc_reg64_field32_get(unit, CMAC_RX_CTRLr, rval, 1608 RX_PASS_CTRLf); 1609 break; 1610 1611 case SOC_MAC_CONTROL_PFC_TYPE: 1612 SOC_IF_ERROR_RETURN(READ_CMAC_PFC_TYPEr(unit, port, &rval)); 1613 *value = soc_reg64_field32_get(unit, CMAC_PFC_TYPEr, rval, 1614 PFC_ETH_TYPEf); 1615 break; 1616 1617 case SOC_MAC_CONTROL_PFC_OPCODE: 1618 SOC_IF_ERROR_RETURN(READ_CMAC_PFC_OPCODEr(unit, port, &rval)); 1619 *value = soc_reg64_field32_get(unit, CMAC_PFC_OPCODEr, rval, 1620 PFC_OPCODEf); 1621 break; 1622 1623 case SOC_MAC_CONTROL_PFC_CLASSES: 1624 *value = 8; 1625 break; 1626 1627 case SOC_MAC_CONTROL_PFC_MAC_DA_OUI: 1628 SOC_IF_ERROR_RETURN(READ_CMAC_PFC_DAr(unit, port, &rval)); 1629 fval0 = soc_reg64_field32_get(unit, CMAC_PFC_DAr, rval, PFC_MACDA_LOf); 1630 fval1 = soc_reg64_field32_get(unit, CMAC_PFC_DAr, rval, PFC_MACDA_HIf); 1631 *value = (fval0 >> 24) | (fval1 << 8); 1632 break; 1633 1634 case SOC_MAC_CONTROL_PFC_MAC_DA_NONOUI: 1635 SOC_IF_ERROR_RETURN(READ_CMAC_PFC_DAr(unit, port, &rval)); 1636 *value = soc_reg64_field32_get(unit, CMAC_PFC_DAr, rval, 1637 PFC_MACDA_LOf) & 0x00ffffff; 1638 break; 1639 1640 case SOC_MAC_CONTROL_PFC_RX_PASS: 1641 SOC_IF_ERROR_RETURN(READ_CMAC_PFC_CTRLr(unit, port, &rval)); 1642 *value = soc_reg64_field32_get(unit, CMAC_PFC_CTRLr, rval, 1643 RX_PASS_PFCf); 1644 break; 1645 1646 case SOC_MAC_CONTROL_PFC_RX_ENABLE: 1647 SOC_IF_ERROR_RETURN(READ_CMAC_PFC_CTRLr(unit, port, &rval)); 1648 *value = soc_reg64_field32_get(unit, CMAC_PFC_CTRLr, rval, 1649 RX_PFC_ENf); 1650 break; 1651 1652 case SOC_MAC_CONTROL_PFC_TX_ENABLE: 1653 SOC_IF_ERROR_RETURN(READ_CMAC_PFC_CTRLr(unit, port, &rval)); 1654 *value = soc_reg64_field32_get(unit, CMAC_PFC_CTRLr, rval, 1655 TX_PFC_ENf); 1656 break; 1657 1658 case SOC_MAC_CONTROL_PFC_FORCE_XON: 1659 SOC_IF_ERROR_RETURN(READ_CMAC_PFC_CTRLr(unit, port, &rval)); 1660 *value = soc_reg64_field32_get(unit, CMAC_PFC_CTRLr, rval, 1661 FORCE_PFC_XONf); 1662 break; 1663 1664 case SOC_MAC_CONTROL_PFC_STATS_ENABLE: 1665 SOC_IF_ERROR_RETURN(READ_CMAC_PFC_CTRLr(unit, port, &rval)); 1666 *value = soc_reg64_field32_get(unit, CMAC_PFC_CTRLr, rval, 1667 PFC_STATS_ENf); 1668 break; 1669 1670 case SOC_MAC_CONTROL_PFC_REFRESH_TIME: 1671 SOC_IF_ERROR_RETURN(READ_CMAC_PFC_CTRLr(unit, port, &rval)); 1672 *value = soc_reg64_field32_get(unit, CMAC_PFC_CTRLr, rval, 1673 PFC_REFRESH_TIMERf); 1674 break; 1675 1676 case SOC_MAC_CONTROL_PFC_XOFF_TIME: 1677 SOC_IF_ERROR_RETURN(READ_CMAC_PFC_CTRLr(unit, port, &rval)); 1678 *value = soc_reg64_field32_get(unit, CMAC_PFC_CTRLr, rval, 1679 PFC_XOFF_TIMERf); 1680 break; 1681 1682 case SOC_MAC_CONTROL_LLFC_RX_ENABLE: 1683 SOC_IF_ERROR_RETURN(READ_CMAC_LLFC_CTRLr(unit, port, &rval)); 1684 *value = soc_reg64_field32_get(unit, CMAC_LLFC_CTRLr, rval, 1685 RX_LLFC_ENf); 1686 break; 1687 1688 case SOC_MAC_CONTROL_LLFC_TX_ENABLE: 1689 SOC_IF_ERROR_RETURN(READ_CMAC_LLFC_CTRLr(unit, port, &rval)); 1690 *value = soc_reg64_field32_get(unit, CMAC_LLFC_CTRLr, rval, 1691 TX_LLFC_ENf); 1692 break; 1693 1694 case SOC_MAC_CONTROL_EEE_ENABLE: 1695 if (!soc_feature(unit, soc_feature_eee)) { 1696 return SOC_E_UNAVAIL; 1697 } 1698 if (!soc_reg_field_valid(unit, CMAC_EEE_CTRLr, EEE_ENf)) { 1699 return SOC_E_UNAVAIL; 1700 } 1701 SOC_IF_ERROR_RETURN(READ_CMAC_EEE_CTRLr(unit, port, &rval)); 1702 *value = soc_reg64_field32_get(unit, CMAC_EEE_CTRLr, rval, EEE_ENf); 1703 break; 1704 1705 case SOC_MAC_CONTROL_EEE_TX_IDLE_TIME: 1706 if (!soc_feature(unit, soc_feature_eee)) { 1707 return SOC_E_UNAVAIL; 1708 } 1709 if (!soc_reg_field_valid(unit, CMAC_EEE_TIMERSr, EEE_DELAY_ENTRY_TIMERf)) { 1710 return SOC_E_UNAVAIL; 1711 } 1712 SOC_IF_ERROR_RETURN(READ_CMAC_EEE_TIMERSr(unit, port, &rval)); 1713 *value = soc_reg64_field32_get(unit, CMAC_EEE_TIMERSr, rval, 1714 EEE_DELAY_ENTRY_TIMERf); 1715 break; 1716 1717 case SOC_MAC_CONTROL_EEE_TX_WAKE_TIME: 1718 if (!soc_feature(unit, soc_feature_eee)) { 1719 return SOC_E_UNAVAIL; 1720 } 1721 if (!soc_reg_field_valid(unit, CMAC_EEE_TIMERSr, EEE_WAKE_TIMERf)) { 1722 return SOC_E_UNAVAIL; 1723 } 1724 SOC_IF_ERROR_RETURN(READ_CMAC_EEE_TIMERSr(unit, port, &rval)); 1725 *value = soc_reg64_field32_get(unit, CMAC_EEE_TIMERSr, rval, 1726 EEE_WAKE_TIMERf); 1727 break; 1728 1729 case SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE: 1730 SOC_IF_ERROR_RETURN(READ_CMAC_RX_LSS_CTRLr(unit, port, &rval)); 1731 *value = soc_reg64_field32_get(unit, CMAC_RX_LSS_CTRLr, rval, 1732 LOCAL_FAULT_DISABLEf) ? 0 : 1; 1733 break; 1734 1735 case SOC_MAC_CONTROL_FAULT_LOCAL_STATUS: 1736 SOC_IF_ERROR_RETURN(READ_CMAC_RX_LSS_STATUSr(unit, port, &rval)); 1737 *value = soc_reg64_field32_get(unit, CMAC_RX_LSS_STATUSr, rval, 1738 LOCAL_FAULT_STATUSf); 1739 break; 1740 1741 case SOC_MAC_CONTROL_FAULT_REMOTE_ENABLE: 1742 SOC_IF_ERROR_RETURN(READ_CMAC_RX_LSS_CTRLr(unit, port, &rval)); 1743 *value = soc_reg64_field32_get(unit, CMAC_RX_LSS_CTRLr, rval, 1744 REMOTE_FAULT_DISABLEf) ? 0 : 1; 1745 break; 1746 1747 case SOC_MAC_CONTROL_FAULT_REMOTE_STATUS: 1748 SOC_IF_ERROR_RETURN(READ_CMAC_RX_LSS_STATUSr(unit, port, &rval)); 1749 *value = soc_reg64_field32_get(unit, CMAC_RX_LSS_STATUSr, rval, 1750 REMOTE_FAULT_STATUSf); 1751 break; 1752 case SOC_MAC_CONTROL_EXPECTED_RX_LATENCY: 1753 SOC_IF_ERROR_RETURN(mac_c_expected_rx_latency_get(unit, port, value));; 1754 break; 1755 1756 default: 1757 return SOC_E_UNAVAIL; 1758 } 1759 1760 LOG_VERBOSE(BSL_LS_SOC_100G, 1761 (BSL_META_U(unit, 1762 "mac_c_control_get: unit %d port %s type=%d value=%d " 1763 "rv=%d\n"), 1764 unit, SOC_PORT_NAME(unit, port), 1765 type, *value, rv)); 1766 return rv; 1767 } 1768 1769 /* 1770 * Function: 1771 * mac_c_ability_local_get 1772 * Purpose: 1773 * Return the abilities of CMAC 1774 * Parameters: 1775 * unit - XGS unit #. 1776 * port - XGS port # on unit. 1777 * mode - (OUT) Supported operating modes as a mask of abilities. 1778 * Returns: 1779 * SOC_E_XXX 1780 */ 1781 STATIC int 1782 mac_c_ability_local_get(int unit, soc_port_t port, 1783 soc_port_ability_t *ability) 1784 { 1785 if (NULL == ability) { 1786 return SOC_E_PARAM; 1787 } 1788 1789 ability->speed_half_duplex = SOC_PA_ABILITY_NONE; 1790 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 1791 ability->interface = SOC_PA_INTF_MII | SOC_PA_INTF_XGMII; 1792 ability->medium = SOC_PA_ABILITY_NONE; 1793 ability->loopback = SOC_PA_LB_MAC; 1794 ability->flags = SOC_PA_ABILITY_NONE; 1795 ability->encap = SOC_PA_ENCAP_IEEE | SOC_PA_ENCAP_HIGIG | 1796 SOC_PA_ENCAP_HIGIG2; 1797 1798 if (IS_HG_PORT(unit , port)) { 1799 switch (SOC_INFO(unit).port_speed_max[port]) { 1800 case 127000: 1801 ability->speed_full_duplex |= SOC_PA_SPEED_127GB; 1802 /* fall through */ 1803 case 120000: 1804 ability->speed_full_duplex |= SOC_PA_SPEED_120GB; 1805 /* fall through */ 1806 case 106000: 1807 ability->speed_full_duplex |= SOC_PA_SPEED_106GB; 1808 /* fall through */ 1809 case 100000: 1810 ability->speed_full_duplex |= SOC_PA_SPEED_100GB; 1811 /* fall through */ 1812 default: 1813 break; 1814 } 1815 } else { 1816 switch (SOC_INFO(unit).port_speed_max[port]) { 1817 case 106000: 1818 ability->speed_full_duplex |= SOC_PA_SPEED_106GB; 1819 /* fall through */ 1820 case 100000: 1821 ability->speed_full_duplex |= SOC_PA_SPEED_100GB; 1822 /* fall through */ 1823 default: 1824 break; 1825 } 1826 } 1827 1828 LOG_VERBOSE(BSL_LS_SOC_100G, 1829 (BSL_META_U(unit, 1830 "mac_c_ability_local_get: unit %d port %s " 1831 "speed_half=0x%x speed_full=0x%x encap=0x%x pause=0x%x " 1832 "interface=0x%x medium=0x%x loopback=0x%x flags=0x%x\n"), 1833 unit, SOC_PORT_NAME(unit, port), 1834 ability->speed_half_duplex, ability->speed_full_duplex, 1835 ability->encap, ability->pause, ability->interface, 1836 ability->medium, ability->loopback, ability->flags)); 1837 return SOC_E_NONE; 1838 } 1839 1840 /* Exported CMAC driver structure */ 1841 mac_driver_t soc_mac_c = { 1842 "CMAC Driver", /* drv_name */ 1843 mac_c_init, /* md_init */ 1844 mac_c_enable_set, /* md_enable_set */ 1845 mac_c_enable_get, /* md_enable_get */ 1846 mac_c_duplex_set, /* md_duplex_set */ 1847 mac_c_duplex_get, /* md_duplex_get */ 1848 mac_c_speed_set, /* md_speed_set */ 1849 mac_c_speed_get, /* md_speed_get */ 1850 mac_c_pause_set, /* md_pause_set */ 1851 mac_c_pause_get, /* md_pause_get */ 1852 mac_c_pause_addr_set, /* md_pause_addr_set */ 1853 mac_c_pause_addr_get, /* md_pause_addr_get */ 1854 mac_c_loopback_set, /* md_lb_set */ 1855 mac_c_loopback_get, /* md_lb_get */ 1856 mac_c_interface_set, /* md_interface_set */ 1857 mac_c_interface_get, /* md_interface_get */ 1858 NULL, /* md_ability_get - Deprecated */ 1859 mac_c_frame_max_set, /* md_frame_max_set */ 1860 mac_c_frame_max_get, /* md_frame_max_get */ 1861 mac_c_ifg_set, /* md_ifg_set */ 1862 mac_c_ifg_get, /* md_ifg_get */ 1863 mac_c_encap_set, /* md_encap_set */ 1864 mac_c_encap_get, /* md_encap_get */ 1865 mac_c_control_set, /* md_control_set */ 1866 mac_c_control_get, /* md_control_get */ 1867 mac_c_ability_local_get, /* md_ability_local_get */ 1868 NULL /* md_timesync_tx_info_get */ 1869 }; 1870 1871 #endif /* BCM_CMAC_SUPPORT */