clmac.c (80018B)
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 * CLMAC driver 8 */ 9 10 #include <sal/core/libc.h> 11 #include <shared/alloc.h> 12 #include <sal/core/spl.h> 13 #include <sal/core/boot.h> 14 #include <shared/bsl.h> 15 #include <soc/drv.h> 16 #include <soc/error.h> 17 #include <soc/cmic.h> 18 #include <soc/portmode.h> 19 #include <soc/ll.h> 20 #include <soc/macutil.h> 21 #include <soc/phyctrl.h> 22 #include <soc/debug.h> 23 #ifdef BCM_GREYHOUND2_SUPPORT 24 #include <soc/greyhound2.h> 25 #endif 26 #ifdef BCM_TOMAHAWK_SUPPORT 27 #include <soc/tomahawk.h> 28 #endif 29 30 #ifdef BCM_CLMAC_SUPPORT 31 32 /* Gen version of PM4x25G 33 * Gen1:0xA023 include TH, TD2P, Apache, Jericho, Jericho+, QAX, QMX 34 * Gen2:0xA030 include TH+, TH2, 35 */ 36 enum clmac_version_e { 37 CLMAC_VERSION_A023 = 0xA023, 38 CLMAC_VERSION_A030 = 0xA030 39 }; 40 41 #define CLMAC_RUNT_THRESHOLD_IEEE 0x40 /* Runt threshold value for XE ports */ 42 #define CLMAC_RUNT_THRESHOLD_HG1 0x48 /* Runt threshold value for HG1 ports */ 43 #define CLMAC_RUNT_THRESHOLD_HG2 0x4c /* Runt threshold value for HG2 ports */ 44 45 /* 46 * CLMAC Register field definitions. 47 */ 48 49 #define JUMBO_MAXSZ 0x3fe8 /* Max legal value (per regsfile) */ 50 51 #define SOC_CLMAC_SPEED_1000 0x2 52 #define SOC_CLMAC_SPEED_100000 0x4 53 54 /* 55 * CLMAC timestamp delay definitions 56 */ 57 #define CLMAC_TX_LINE_RATE_NS 0x3 /* TSC CLK FREQ is 644MHz */ 58 #define CLMAC_TSC_CLK_NS 4 59 60 /* Transmit CRC Modes */ 61 #define CLMAC_CRC_APPEND 0x0 62 #define CLMAC_CRC_KEEP 0x1 63 #define CLMAC_CRC_REPLACE 0x2 64 #define CLMAC_CRC_PER_PKT_MODE 0x3 65 66 /* 67 * WAN mode throttling 68 * THROT_10G_TO_5G: throt_num=21 throt_denom=21 69 * THROT_10G_TO_2P5G: throt_num=63 throt_denom=21 70 */ 71 #define CLMAC_THROT_10G_TO_5G 256 72 #define CLMAC_THROT_10G_TO_2P5G 257 73 74 mac_driver_t soc_mac_cl; 75 76 #ifdef BROADCOM_DEBUG 77 static char *mac_cl_encap_mode[] = SOC_ENCAP_MODE_NAMES_INITIALIZER; 78 static char *mac_cl_port_if_names[] = SOC_PORT_IF_NAMES_INITIALIZER; 79 #endif /* BROADCOM_DEBUG */ 80 81 STATIC int 82 _mac_cl_timestamp_delay_set(int unit, soc_port_t port, int speed); 83 STATIC int 84 mac_cl_speed_get(int unit, soc_port_t port, int *speed); 85 86 STATIC int 87 _clmac_gen_version_get(int unit, soc_port_t port, int *ver) 88 { 89 int rv; 90 uint64 reg_val; 91 rv = SOC_E_NONE; 92 93 if (!SOC_REG_IS_VALID(unit, CLMAC_VERSION_IDr)) { 94 *ver = -1; 95 } else { 96 SOC_IF_ERROR_RETURN(READ_CLMAC_VERSION_IDr(unit, port, ®_val)); 97 *ver = soc_reg64_field32_get(unit, CLMAC_VERSION_IDr, reg_val, CLMAC_VERSIONf); 98 } 99 100 return rv; 101 } 102 103 STATIC int 104 _mac_cl_drain_cells(int unit, soc_port_t port, int notify_phy) 105 { 106 int rv; 107 int pause_tx = 0, pause_rx = 0, pfc_rx = 0, llfc_rx = 0; 108 soc_field_t fields[2]; 109 uint32 values[2], fval, drain_timeout; 110 uint64 mac_ctrl, rval64; 111 soc_timeout_t to; 112 113 rv = SOC_E_NONE; 114 115 if (SOC_IS_RELOADING(unit)) { 116 return rv; 117 } 118 119 drain_timeout = SAL_BOOT_QUICKTURN ? 250000000 : 250000; 120 if (!soc_feature(unit, soc_feature_mmu_hw_flush)) { 121 /* Drain cells in mmu/port before cells entering TX FIFO */ 122 SOC_IF_ERROR_RETURN(soc_mmu_flush_enable(unit, port, TRUE)); 123 124 /* Disable pause/pfc/llfc function */ 125 SOC_IF_ERROR_RETURN 126 (soc_mac_cl.md_pause_get(unit, port, &pause_tx, &pause_rx)); 127 SOC_IF_ERROR_RETURN 128 (soc_mac_cl.md_pause_set(unit, port, pause_tx, 0)); 129 130 SOC_IF_ERROR_RETURN 131 (soc_mac_cl.md_control_get(unit, port, SOC_MAC_CONTROL_PFC_RX_ENABLE, 132 &pfc_rx)); 133 SOC_IF_ERROR_RETURN 134 (soc_mac_cl.md_control_set(unit, port, SOC_MAC_CONTROL_PFC_RX_ENABLE, 135 0)); 136 137 SOC_IF_ERROR_RETURN 138 (soc_mac_cl.md_control_get(unit, port, SOC_MAC_CONTROL_LLFC_RX_ENABLE, 139 &llfc_rx)); 140 SOC_IF_ERROR_RETURN 141 (soc_mac_cl.md_control_set(unit, port, SOC_MAC_CONTROL_LLFC_RX_ENABLE, 142 0)); 143 } 144 145 if (!soc_feature(unit, soc_feature_mmu_hw_flush)) { 146 /* Assert SOFT_RESET before DISCARD just in case there is no credit left */ 147 SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &mac_ctrl)); 148 soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl, SOFT_RESETf, 1); 149 /* Drain data in TX FIFO without egressing */ 150 SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, mac_ctrl)); 151 } 152 153 fields[0] = DISCARDf; 154 values[0] = 1; 155 fields[1] = EP_DISCARDf; 156 values[1] = 1; 157 SOC_IF_ERROR_RETURN(soc_reg_fields32_modify(unit, CLMAC_TX_CTRLr, port, 2, 158 fields, values)); 159 160 /* Reset EP credit before de-assert SOFT_RESET */ 161 SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port)); 162 163 if (!soc_feature(unit, soc_feature_mmu_hw_flush)) { 164 /* De-assert SOFT_RESET to let the drain start */ 165 soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl, SOFT_RESETf, 0); 166 SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, mac_ctrl)); 167 } 168 169 if (notify_phy == 1) { 170 /* Notify PHY driver */ 171 SOC_IF_ERROR_RETURN 172 (soc_phyctrl_notify(unit, port, phyEventStop, PHY_STOP_DRAIN)); 173 } 174 175 /* Wait until mmu cell count is 0 */ 176 rv = soc_egress_drain_cells(unit, port, drain_timeout); 177 if (SOC_E_NONE == rv) { 178 /* Wait until TX fifo cell count is 0 */ 179 soc_timeout_init(&to, drain_timeout, 0); 180 for (;;) { 181 rv = READ_CLMAC_TXFIFO_CELL_CNTr(unit, port, &rval64); 182 if (SOC_E_NONE != rv) { 183 break; 184 } 185 fval = soc_reg64_field32_get(unit, CLMAC_TXFIFO_CELL_CNTr, rval64, 186 CELL_CNTf); 187 if (fval == 0) { 188 break; 189 } 190 if (soc_timeout_check(&to)) { 191 LOG_VERBOSE(BSL_LS_SOC_COMMON, 192 (BSL_META_U(unit, 193 "mac_cl_drain_cells: unit %d " 194 "ERROR: port %s: " 195 "timeout draining TX FIFO (%d cells remain)\n"), 196 unit, SOC_PORT_NAME(unit, port), fval)); 197 rv = SOC_E_INTERNAL; 198 break; 199 } 200 } 201 } 202 203 if (notify_phy == 1) { 204 /* Notify PHY driver */ 205 SOC_IF_ERROR_RETURN 206 (soc_phyctrl_notify(unit, port, phyEventResume, PHY_STOP_DRAIN)); 207 } 208 209 /* Stop TX FIFO draining */ 210 values[0] = 0; 211 values[1] = 0; 212 SOC_IF_ERROR_RETURN(soc_reg_fields32_modify(unit, CLMAC_TX_CTRLr, port, 2, 213 fields, values)); 214 /* Restore config below only if modified above, i.e. h/w flush not used */ 215 if (!soc_feature(unit, soc_feature_mmu_hw_flush)) { 216 /* Restore original pause/pfc/llfc configuration */ 217 SOC_IF_ERROR_RETURN 218 (soc_mac_cl.md_pause_set(unit, port, pause_tx, pause_rx)); 219 SOC_IF_ERROR_RETURN 220 (soc_mac_cl.md_control_set(unit, port, 221 SOC_MAC_CONTROL_PFC_RX_ENABLE, 222 pfc_rx)); 223 SOC_IF_ERROR_RETURN 224 (soc_mac_cl.md_control_set(unit, port, 225 SOC_MAC_CONTROL_LLFC_RX_ENABLE, 226 llfc_rx)); 227 228 /* Stop draining cells in mmu/port */ 229 SOC_IF_ERROR_RETURN(soc_mmu_flush_enable(unit, port, FALSE)); 230 } 231 232 return rv; 233 } 234 235 /* 236 * Function: 237 * mac_cl_init 238 * Purpose: 239 * Initialize Clmac into a known good state. 240 * Parameters: 241 * unit - XGS unit #. 242 * port - Port number on unit. 243 * Returns: 244 * SOC_E_XXX 245 * Notes: 246 */ 247 STATIC int 248 mac_cl_init(int unit, soc_port_t port) 249 { 250 soc_info_t *si; 251 uint64 mac_ctrl, rx_ctrl, tx_ctrl, rval; 252 int ipg, runt; 253 int mode; 254 int encap = SOC_ENCAP_IEEE; 255 256 257 si = &SOC_INFO(unit); 258 259 /* Disable Tx/Rx, assume that MAC is stable (or out of reset) */ 260 SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &mac_ctrl)); 261 262 /* Reset EP credit before de-assert SOFT_RESET */ 263 if (soc_reg64_field32_get(unit, CLMAC_CTRLr, mac_ctrl, SOFT_RESETf)) { 264 SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port)); 265 } 266 267 soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl, SOFT_RESETf, 0); 268 soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl, RX_ENf, 0); 269 soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl, TX_ENf, 0); 270 if (soc_reg_field_valid(unit, CLMAC_CTRLr, XLGMII_ALIGN_ENBf)) { 271 soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl, XLGMII_ALIGN_ENBf, 272 1); 273 } 274 soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl, 275 XGMII_IPG_CHECK_DISABLEf, 276 IS_HG_PORT(unit, port) ? 1 : 0); 277 SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, mac_ctrl)); 278 279 SOC_IF_ERROR_RETURN(READ_CLMAC_TX_CTRLr(unit, port, &tx_ctrl)); 280 ipg = IS_HG_PORT(unit,port)? SOC_PERSIST(unit)->ipg[port].fd_hg: 281 SOC_PERSIST(unit)->ipg[port].fd_xe; 282 soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &tx_ctrl, AVERAGE_IPGf, 283 (ipg / 8) & 0x1f); 284 soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &tx_ctrl, CRC_MODEf, 285 CLMAC_CRC_PER_PKT_MODE); 286 SOC_IF_ERROR_RETURN(WRITE_CLMAC_TX_CTRLr(unit, port, tx_ctrl)); 287 288 if (IS_ST_PORT(unit, port)) { 289 soc_mac_cl.md_pause_set(unit, port, FALSE, FALSE); 290 } else { 291 soc_mac_cl.md_pause_set(unit, port, TRUE, TRUE); 292 } 293 294 SOC_IF_ERROR_RETURN 295 (soc_reg_field32_modify(unit, CLMAC_PFC_CTRLr, port, PFC_REFRESH_ENf, 296 1)); 297 298 if (soc_property_port_get(unit, port, spn_PHY_WAN_MODE, FALSE)) { 299 /* Max speed for WAN mode is 9.294Gbps. 300 * This setting gives 10Gbps * (13/14) or 9.286 Gbps */ 301 SOC_IF_ERROR_RETURN 302 (soc_mac_cl.md_control_set(unit, port, 303 SOC_MAC_CONTROL_FRAME_SPACING_STRETCH, 304 13)); 305 } 306 307 /* Set jumbo max size (8000 byte payload) */ 308 COMPILER_64_ZERO(rval); 309 #ifdef BCM_XGS_SUPPORT 310 if (SOC_IS_XGS3_SWITCH(unit)) { 311 uint32 rval; 312 soc_reg_t reg; 313 314 reg = SOC_REG_IS_VALID(unit, EGR_MTUr) ? EGR_MTUr : EGR_MTU_SIZEr; 315 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, port, 0, &rval)); 316 soc_reg_field_set(unit, reg, &rval, MTU_SIZEf, SOC_INFO(unit).max_mtu); 317 if (soc_reg_field_valid(unit, reg, MTU_ENABLEf)) { 318 soc_reg_field_set(unit, reg, &rval, MTU_ENABLEf, 1); 319 } 320 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, port, 0, rval)); 321 } 322 323 if (SOC_IS_XGS(unit)) { 324 soc_reg64_field32_set(unit, CLMAC_RX_MAX_SIZEr, &rval, RX_MAX_SIZEf, 325 SOC_INFO(unit).max_mtu); 326 } else 327 #endif 328 { 329 soc_reg64_field32_set(unit, CLMAC_RX_MAX_SIZEr, &rval, RX_MAX_SIZEf, 330 JUMBO_MAXSZ); 331 } 332 SOC_IF_ERROR_RETURN(WRITE_CLMAC_RX_MAX_SIZEr(unit, port, rval)); 333 334 /* Setup header mode, check for property for higig2 mode */ 335 SOC_IF_ERROR_RETURN(READ_CLMAC_MODEr(unit, port, &rval)); 336 if (IS_HG_PORT(unit, port)) { 337 mode = soc_property_port_get(unit, port, spn_HIGIG2_HDR_MODE, 338 soc_feature(unit, soc_feature_no_higig_plus) ? 1 : 0) ? 2 : 1; 339 encap = (mode == 2) ? SOC_ENCAP_HIGIG2 : SOC_ENCAP_HIGIG; 340 soc_reg64_field32_set(unit, CLMAC_MODEr, &rval, HDR_MODEf, mode); 341 } 342 SOC_IF_ERROR_RETURN(WRITE_CLMAC_MODEr(unit, port, rval)); 343 344 SOC_IF_ERROR_RETURN(READ_CLMAC_RX_CTRLr(unit, port, &rx_ctrl)); 345 soc_reg64_field32_set(unit, CLMAC_RX_CTRLr, &rx_ctrl, STRIP_CRCf, 0); 346 soc_reg64_field32_set(unit, CLMAC_RX_CTRLr, &rx_ctrl, STRICT_PREAMBLEf, 347 si->port_speed_max[port] >= 10000 && 348 IS_CL_PORT(unit, port) && 349 !IS_HG_PORT(unit, port) ? 1 : 0); 350 /* assigning RUNT_THRESHOLD per header mode setting */ 351 runt = (encap == SOC_ENCAP_HIGIG2) ? CLMAC_RUNT_THRESHOLD_HG2 : 352 ((encap == SOC_ENCAP_HIGIG) ? CLMAC_RUNT_THRESHOLD_HG1 : 353 CLMAC_RUNT_THRESHOLD_IEEE); 354 soc_reg64_field32_set(unit, CLMAC_RX_CTRLr, &rx_ctrl, RUNT_THRESHOLDf, 355 runt); 356 SOC_IF_ERROR_RETURN(WRITE_CLMAC_RX_CTRLr(unit, port, rx_ctrl)); 357 358 SOC_IF_ERROR_RETURN(READ_CLMAC_RX_LSS_CTRLr(unit, port, &rval)); 359 soc_reg64_field32_set(unit, CLMAC_RX_LSS_CTRLr, &rval, 360 DROP_TX_DATA_ON_LOCAL_FAULTf, 1); 361 soc_reg64_field32_set(unit, CLMAC_RX_LSS_CTRLr, &rval, 362 DROP_TX_DATA_ON_REMOTE_FAULTf, 1); 363 soc_reg64_field32_set(unit, CLMAC_RX_LSS_CTRLr, &rval, 364 DROP_TX_DATA_ON_LINK_INTERRUPTf, 1); 365 SOC_IF_ERROR_RETURN(WRITE_CLMAC_RX_LSS_CTRLr(unit, port, rval)); 366 367 /* Disable loopback and bring CLMAC out of reset */ 368 soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl, LOCAL_LPBKf, 0); 369 soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl, RX_ENf, 1); 370 soc_reg64_field32_set(unit, CLMAC_CTRLr, &mac_ctrl, TX_ENf, 1); 371 SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, mac_ctrl)); 372 373 return SOC_E_NONE; 374 } 375 376 /* 377 * Function: 378 * mac_cl_egress_queue_drain 379 * Purpose: 380 * Drain the egress queues with out bringing down the port 381 * Parameters: 382 * unit - XGS unit #. 383 * port - Port number on unit. 384 * Returns: 385 * SOC_E_XXX 386 */ 387 STATIC int 388 mac_cl_egress_queue_drain(int unit, soc_port_t port) 389 { 390 uint64 ctrl, octrl; 391 pbmp_t mask; 392 int rx_enable = 0; 393 int is_active = 0; 394 395 LOG_VERBOSE(BSL_LS_SOC_10G, 396 (BSL_META_U(unit, 397 "mac_cl_egress_queue_drain: unit %d port %s \n"), 398 unit, SOC_PORT_NAME(unit, port))); 399 400 SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &ctrl)); 401 octrl = ctrl; 402 403 rx_enable = soc_reg64_field32_get(unit, CLMAC_CTRLr, ctrl, RX_ENf); 404 /* Don't disable TX since it stops egress and hangs if CPU sends */ 405 soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, TX_ENf, 1); 406 soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, RX_ENf, 0); 407 /* Disable RX */ 408 SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, ctrl)); 409 410 /* Remove port from EPC_LINK */ 411 soc_link_mask2_get(unit, &mask); 412 if (SOC_PBMP_MEMBER(mask, port)) { 413 is_active = 1; 414 SOC_PBMP_PORT_REMOVE(mask, port); 415 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 416 } 417 418 /* Drain cells */ 419 SOC_IF_ERROR_RETURN(_mac_cl_drain_cells(unit, port, 0)); 420 421 /* Put port into SOFT_RESET */ 422 soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, SOFT_RESETf, 1); 423 SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, ctrl)); 424 425 /* Reset EP credit before de-assert SOFT_RESET */ 426 SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port)); 427 SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &ctrl)); 428 soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, RX_ENf, rx_enable ? 1 : 0); 429 430 /* Enable both TX and RX, deassert SOFT_RESET */ 431 soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, SOFT_RESETf, 0); 432 SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, ctrl)); 433 434 /* Restore CLMAC_CTRL to original value */ 435 SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, octrl)); 436 437 /* Add port to EPC_LINK */ 438 if(is_active) { 439 soc_link_mask2_get(unit, &mask); 440 SOC_PBMP_PORT_ADD(mask, port); 441 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 442 } 443 444 return SOC_E_NONE; 445 } 446 447 /* 448 * Function: 449 * mac_cl_enable_set 450 * Purpose: 451 * Enable or disable MAC 452 * Parameters: 453 * unit - XGS unit #. 454 * port - Port number on unit. 455 * enable - TRUE to enable, FALSE to disable 456 * Returns: 457 * SOC_E_XXX 458 */ 459 STATIC int 460 mac_cl_enable_set(int unit, soc_port_t port, int enable) 461 { 462 uint64 ctrl, octrl; 463 pbmp_t mask; 464 int speed = 1000; 465 466 LOG_VERBOSE(BSL_LS_SOC_COMMON, 467 (BSL_META_U(unit, 468 "mac_cl_enable_set: unit %d port %s enable=%s\n"), 469 unit, SOC_PORT_NAME(unit, port), 470 enable ? "True" : "False")); 471 472 SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &ctrl)); 473 octrl = ctrl; 474 /* Don't disable TX since it stops egress and hangs if CPU sends */ 475 soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, TX_ENf, 1); 476 soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, RX_ENf, enable ? 1 : 0); 477 478 if (COMPILER_64_EQ(ctrl, octrl)) { 479 if (enable) { 480 return SOC_E_NONE; 481 } else { 482 if (soc_reg64_field32_get(unit, CLMAC_CTRLr, ctrl, SOFT_RESETf)) { 483 return SOC_E_NONE; 484 } 485 } 486 } 487 488 489 if (enable) { 490 /* Reset EP credit before de-assert SOFT_RESET */ 491 SOC_IF_ERROR_RETURN(soc_port_credit_reset(unit, port)); 492 /* Deassert SOFT_RESET */ 493 soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, SOFT_RESETf, 0); 494 /* Deassert EGR_XLPORT_BUFFER_SFT_RESET */ 495 SOC_IF_ERROR_RETURN(soc_port_egress_buffer_sft_reset(unit, port, 0)); 496 /* Release Ingress buffers from reset */ 497 SOC_IF_ERROR_RETURN(soc_port_ingress_buffer_reset(unit, port, 0)); 498 SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, ctrl)); 499 500 #if defined(BCM_TOMAHAWKPLUS_SUPPORT) || defined(BCM_GREYHOUND2_SUPPORT) 501 /* Special handling for new mac version for TH+. Internally MAC loopback looks for rising */ 502 /* edge on MAC loopback configuration to enter loopback state */ 503 if (SOC_IS_TOMAHAWKPLUS(unit) || SOC_IS_GREYHOUND2(unit)) { 504 uint32 ctrl_32; 505 COMPILER_64_TO_32_LO(ctrl_32, ctrl); 506 if (ctrl_32 & 0x4) { /* Do only if loopback bit is intented to be set */ 507 soc_reg_field32_modify(unit, CLMAC_CTRLr, port, LOCAL_LPBKf, 0); 508 sal_usleep(10); /* Wait 10usec as suggested by MAC designer */ 509 soc_reg_field32_modify(unit, CLMAC_CTRLr, port, LOCAL_LPBKf, 1); 510 } 511 } 512 #endif /* TOMAHAWKPLUS || GREYHOUHD2 */ 513 514 /* Enable MMU port */ 515 SOC_IF_ERROR_RETURN(soc_port_mmu_buffer_enable(unit, port, TRUE)); 516 517 soc_link_mask2_get(unit, &mask); 518 SOC_PBMP_PORT_ADD(mask, port); 519 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 520 SOC_IF_ERROR_RETURN(soc_phyctrl_notify(unit, port, phyEventResume, 521 PHY_STOP_MAC_DIS)); 522 523 /* set timestamp adjust delay */ 524 SOC_IF_ERROR_RETURN(mac_cl_speed_get(unit, port, &speed)); 525 SOC_IF_ERROR_RETURN(_mac_cl_timestamp_delay_set(unit, port, speed)); 526 527 } else { 528 /* Disable MAC RX */ 529 SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, ctrl)); 530 soc_link_mask2_get(unit, &mask); 531 SOC_PBMP_PORT_REMOVE(mask, port); 532 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 533 /* 534 * Disable MMU port 535 * for some devices where EPC_LINK can not block the SOBMH from cpu and 536 * no mechanism is avalible to reset EDATABUF. 537 */ 538 SOC_IF_ERROR_RETURN(soc_port_mmu_buffer_enable(unit, port, FALSE)); 539 540 /* Delay to ensure EOP is received at Ingress */ 541 sal_udelay(1000); 542 /* Reset Ingress buffers */ 543 SOC_IF_ERROR_RETURN(soc_port_ingress_buffer_reset(unit, port, 1)); 544 SOC_IF_ERROR_RETURN(_mac_cl_drain_cells(unit, port, 1)); 545 /* Reset egress_buffer */ 546 SOC_IF_ERROR_RETURN(soc_port_egress_buffer_sft_reset(unit, port, 1)); 547 /* Put port into SOFT_RESET */ 548 soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, SOFT_RESETf, 1); 549 SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, ctrl)); 550 SOC_IF_ERROR_RETURN(soc_phyctrl_notify(unit, port, phyEventStop, 551 PHY_STOP_MAC_DIS)); 552 } 553 554 return SOC_E_NONE; 555 } 556 557 /* 558 * Function: 559 * mac_cl_enable_get 560 * Purpose: 561 * Get MAC enable state 562 * Parameters: 563 * unit - XGS unit #. 564 * port - Port number on unit. 565 * enable - (OUT) TRUE if enabled, FALSE if disabled 566 * Returns: 567 * SOC_E_XXX 568 */ 569 STATIC int 570 mac_cl_enable_get(int unit, soc_port_t port, int *enable) 571 { 572 uint64 ctrl; 573 574 SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &ctrl)); 575 576 *enable = soc_reg64_field32_get(unit, CLMAC_CTRLr, ctrl, RX_ENf); 577 578 LOG_VERBOSE(BSL_LS_SOC_COMMON, 579 (BSL_META_U(unit, 580 "mac_cl_enable_get: unit %d port %s enable=%s\n"), 581 unit, SOC_PORT_NAME(unit, port), 582 *enable ? "True" : "False")); 583 584 return SOC_E_NONE; 585 } 586 587 /* 588 * Function: 589 * _mac_cl_timestamp_delay_set 590 * Purpose: 591 * Set Timestamp delay for one-step to account for lane and pipeline delay. 592 * Parameters: 593 * unit - XGS unit #. 594 * port - Port number on unit. 595 * speed - New port speed 596 * Returns: 597 * SOC_E_XXX 598 */ 599 STATIC int 600 _mac_cl_timestamp_delay_set(int unit, soc_port_t port, int speed) 601 { 602 uint64 ctrl; 603 int osts_delay = 0; 604 uint32 tsts_delay = 0; 605 uint32 field; 606 607 LOG_VERBOSE(BSL_LS_SOC_10G, 608 (BSL_META_U(unit, 609 "mac_cl_timestamp_delay_set: unit %d port %s speed %d\n"), 610 unit, SOC_PORT_NAME(unit, port), speed)); 611 612 if (SOC_REG_IS_VALID(unit, CLMAC_TIMESTAMP_ADJUSTr)) { 613 SOC_IF_ERROR_RETURN(READ_CLMAC_TIMESTAMP_ADJUSTr(unit, port, &ctrl)); 614 615 /* 616 * CLMAC pipeline latency is : ( as in CLMAC specification) 617 * = (6 * TX line clock period + Timestamp clock period) 618 */ 619 620 621 /* This is a signed value of pipeline delay in ns */ 622 osts_delay = soc_property_port_get(unit, port, spn_TIMESTAMP_ADJUST(speed), 623 CLMAC_TSC_CLK_NS + 624 (3 * CLMAC_TX_LINE_RATE_NS)); 625 626 if (SOC_E_NONE != soc_reg_signed_field_mask(unit, CLMAC_TIMESTAMP_ADJUSTr, 627 TS_OSTS_ADJUSTf, osts_delay, &field)) { 628 LOG_WARN(BSL_LS_SOC_PORT, (BSL_META_U(unit, 629 "%s osts property out of bounds (is %d)\n"), 630 spn_TIMESTAMP_ADJUST(speed), osts_delay)); 631 field = 0; 632 } 633 soc_reg64_field32_set(unit, CLMAC_TIMESTAMP_ADJUSTr, &ctrl, 634 TS_OSTS_ADJUSTf, field); 635 636 /* Note: 637 TSTS delay uses different SOC property as OSTS delay, in order to 638 allow specification based on platform. However, the resulting timestamps 639 in the FIFO are only used by the application, so the application can make 640 other timestamp adjustments as required. 641 CLMAC CDC FIFO latency is : 642 = (2.5 * TX line clock period + Timestamp clock period) 643 This is an unsigned value and the range is 0~63. 644 */ 645 tsts_delay = soc_property_port_get(unit, port, spn_TIMESTAMP_TSTS_ADJUST(speed), 646 CLMAC_TSC_CLK_NS + 647 ((5 * CLMAC_TX_LINE_RATE_NS) / 4)); 648 649 if (SOC_E_NONE != soc_reg_unsigned_field_mask(unit, CLMAC_TIMESTAMP_ADJUSTr, 650 TS_TSTS_ADJUSTf, tsts_delay, &field)) { 651 LOG_WARN(BSL_LS_SOC_PORT, (BSL_META_U(unit, 652 "%s tsts property out of bounds (is %d)\n"), 653 spn_TIMESTAMP_TSTS_ADJUST(speed), tsts_delay)); 654 field = 0; 655 } 656 soc_reg64_field32_set(unit, CLMAC_TIMESTAMP_ADJUSTr, &ctrl, 657 TS_TSTS_ADJUSTf, field); 658 659 660 SOC_IF_ERROR_RETURN(WRITE_CLMAC_TIMESTAMP_ADJUSTr(unit, port, ctrl)); 661 } 662 663 return SOC_E_NONE; 664 } 665 666 /* 667 * Function: 668 * mac_cl_duplex_set 669 * Purpose: 670 * Set CLMAC in the specified duplex mode. 671 * Parameters: 672 * unit - XGS unit #. 673 * port - XGS port # on unit. 674 * duplex - Boolean: true --> full duplex, false --> half duplex. 675 * Returns: 676 * SOC_E_XXX 677 * Notes: 678 */ 679 STATIC int 680 mac_cl_duplex_set(int unit, soc_port_t port, int duplex) 681 { 682 LOG_VERBOSE(BSL_LS_SOC_COMMON, 683 (BSL_META_U(unit, 684 "mac_cl_duplex_set: unit %d port %s duplex=%s\n"), 685 unit, SOC_PORT_NAME(unit, port), 686 duplex ? "Full" : "Half")); 687 return SOC_E_NONE; 688 } 689 690 /* 691 * Function: 692 * mac_cl_duplex_get 693 * Purpose: 694 * Get CLMAC duplex mode. 695 * Parameters: 696 * unit - XGS unit #. 697 * duplex - (OUT) Boolean: true --> full duplex, false --> half duplex. 698 * Returns: 699 * SOC_E_XXX 700 */ 701 STATIC int 702 mac_cl_duplex_get(int unit, soc_port_t port, int *duplex) 703 { 704 *duplex = TRUE; /* Always full duplex */ 705 706 LOG_VERBOSE(BSL_LS_SOC_COMMON, 707 (BSL_META_U(unit, 708 "mac_cl_duplex_get: unit %d port %s duplex=%s\n"), 709 unit, SOC_PORT_NAME(unit, port), 710 *duplex ? "Full" : "Half")); 711 return SOC_E_NONE; 712 } 713 714 /* 715 * Function: 716 * mac_cl_pause_set 717 * Purpose: 718 * Configure CLMAC to transmit/receive pause frames. 719 * Parameters: 720 * unit - XGS unit #. 721 * port - XGS port # on unit. 722 * pause_tx - Boolean: transmit pause or -1 (don't change) 723 * pause_rx - Boolean: receive pause or -1 (don't change) 724 * Returns: 725 * SOC_E_XXX 726 */ 727 STATIC int 728 mac_cl_pause_set(int unit, soc_port_t port, int pause_tx, int pause_rx) 729 { 730 soc_field_t fields[2] = { TX_PAUSE_ENf, RX_PAUSE_ENf }; 731 uint32 values[2]; 732 733 LOG_VERBOSE(BSL_LS_SOC_COMMON, 734 (BSL_META_U(unit, 735 "mac_cl_pause_set: unit %d port %s TX=%s RX=%s\n"), 736 unit, SOC_PORT_NAME(unit, port), 737 pause_tx != FALSE ? "on" : "off", 738 pause_rx != FALSE ? "on" : "off")); 739 740 values[0] = pause_tx != FALSE ? 1 : 0; 741 values[1] = pause_rx != FALSE ? 1 : 0; 742 return soc_reg_fields32_modify(unit, CLMAC_PAUSE_CTRLr, port, 2, 743 fields, values); 744 } 745 746 /* 747 * Function: 748 * mac_cl_pause_get 749 * Purpose: 750 * Return the pause ability of CLMAC 751 * Parameters: 752 * unit - XGS unit #. 753 * port - XGS port # on unit. 754 * pause_tx - Boolean: transmit pause 755 * pause_rx - Boolean: receive pause 756 * pause_mac - MAC address used for pause transmission. 757 * Returns: 758 * SOC_E_XXX 759 */ 760 STATIC int 761 mac_cl_pause_get(int unit, soc_port_t port, int *pause_tx, int *pause_rx) 762 { 763 uint64 rval; 764 765 SOC_IF_ERROR_RETURN(READ_CLMAC_PAUSE_CTRLr(unit, port, &rval)); 766 *pause_tx = 767 soc_reg64_field32_get(unit, CLMAC_PAUSE_CTRLr, rval, TX_PAUSE_ENf); 768 *pause_rx = 769 soc_reg64_field32_get(unit, CLMAC_PAUSE_CTRLr, rval, RX_PAUSE_ENf); 770 LOG_VERBOSE(BSL_LS_SOC_COMMON, 771 (BSL_META_U(unit, 772 "mac_cl_pause_get: unit %d port %s TX=%s RX=%s\n"), 773 unit, SOC_PORT_NAME(unit, port), 774 *pause_tx ? "on" : "off", 775 *pause_rx ? "on" : "off")); 776 return SOC_E_NONE; 777 } 778 779 /* 780 * Function: 781 * mac_cl_speed_set 782 * Purpose: 783 * Set CLMAC in the specified speed. 784 * Parameters: 785 * unit - XGS unit #. 786 * port - XGS port # on unit. 787 * speed - 100000, 120000. 788 * Returns: 789 * SOC_E_XXX 790 */ 791 STATIC int 792 mac_cl_speed_set(int unit, soc_port_t port, int speed) 793 { 794 int enable; 795 uint32 rval; 796 uint32 fault; 797 798 LOG_VERBOSE(BSL_LS_SOC_COMMON, 799 (BSL_META_U(unit, 800 "mac_cl_speed_set: unit %d port %s speed=%dMb\n"), 801 unit, SOC_PORT_NAME(unit, port), 802 speed)); 803 804 SOC_IF_ERROR_RETURN(mac_cl_enable_get(unit, port, &enable)); 805 806 if (enable) { 807 /* Turn off TX/RX enable */ 808 SOC_IF_ERROR_RETURN(mac_cl_enable_set(unit, port, 0)); 809 } 810 811 SOC_IF_ERROR_RETURN 812 (soc_reg_field32_modify(unit, CLMAC_RX_CTRLr, port, STRICT_PREAMBLEf, 813 speed >= 10000 && 814 IS_CL_PORT(unit, port) && 815 !IS_HG_PORT(unit, port) ? 1 : 0)); 816 /* 817 * Set REMOTE_FAULT/LOCAL_FAULT for CL ports, 818 * else HW Linkscan interrupt would be suppressed. 819 */ 820 if (SOC_REG_IS_VALID(unit, CLPORT_FAULT_LINK_STATUSr)) { 821 rval = 0; 822 fault = speed <= 1000 ? 0 : 1; 823 824 soc_reg_field_set(unit, CLPORT_FAULT_LINK_STATUSr, &rval, 825 REMOTE_FAULTf, fault); 826 soc_reg_field_set(unit, CLPORT_FAULT_LINK_STATUSr, &rval, 827 LOCAL_FAULTf, fault); 828 SOC_IF_ERROR_RETURN(WRITE_CLPORT_FAULT_LINK_STATUSr(unit, 829 port, rval)); 830 } 831 832 /* Update port speed related setting in components other than MAC/SerDes*/ 833 SOC_IF_ERROR_RETURN(soc_port_speed_update(unit, port, speed)); 834 835 /* 836 * Notify internal PHY driver of speed change in case it is being 837 * used as pass-through to an external PHY. 838 */ 839 if (!PHY_REPEATER(unit, port)) { 840 SOC_IF_ERROR_RETURN 841 (soc_phyctrl_notify(unit, port, phyEventSpeed, speed)); 842 } 843 844 if (enable) { 845 /* Re-enable transmitter and receiver */ 846 SOC_IF_ERROR_RETURN(mac_cl_enable_set(unit, port, 1)); 847 } 848 849 /* Set Timestamp Mac Delays */ 850 SOC_IF_ERROR_RETURN(_mac_cl_timestamp_delay_set(unit, port, speed)); 851 852 return SOC_E_NONE; 853 } 854 855 /* 856 * Function: 857 * mac_cl_speed_get 858 * Purpose: 859 * Get CLMAC speed 860 * Parameters: 861 * unit - XGS unit #. 862 * port - XGS port # on unit. 863 * speed - (OUT) speed in Mb 864 * Returns: 865 * SOC_E_XXX 866 */ 867 STATIC int 868 mac_cl_speed_get(int unit, soc_port_t port, int *speed) 869 { 870 uint64 rval64; 871 soc_error_t rc; 872 873 SOC_IF_ERROR_RETURN(READ_CLMAC_MODEr(unit, port, &rval64)); 874 switch (soc_reg64_field32_get(unit, CLMAC_MODEr, rval64, SPEED_MODEf)) { 875 case SOC_CLMAC_SPEED_1000: 876 *speed = 1000; 877 break; 878 case SOC_CLMAC_SPEED_100000: 879 default: 880 /* Obtain fine grained port speed, since 881 * SOC_CLMAC_SPEED_1000000 implies >= 10Gbps 882 */ 883 rc = soc_granular_speed_get(unit, port, speed); 884 if (SOC_FAILURE(rc)) { 885 /* Error determining speed, set default value */ 886 *speed = 100000; 887 } 888 break; 889 } 890 891 LOG_VERBOSE(BSL_LS_SOC_COMMON, 892 (BSL_META_U(unit, 893 "mac_cl_speed_get: unit %d port %s speed=%dMb\n"), 894 unit, SOC_PORT_NAME(unit, port), 895 *speed)); 896 return SOC_E_NONE; 897 } 898 899 /* 900 * Function: 901 * mac_cl_loopback_set 902 * Purpose: 903 * Set a CLMAC into/out-of loopback mode 904 * Parameters: 905 * unit - XGS unit #. 906 * port - XGS unit # on unit. 907 * loopback - Boolean: true -> loopback mode, false -> normal operation 908 * Note: 909 * On Clmac, when setting loopback, we enable the TX/RX function also. 910 * Note that to test the PHY, we use the remote loopback facility. 911 * Returns: 912 * SOC_E_XXX 913 */ 914 STATIC int 915 mac_cl_loopback_set(int unit, soc_port_t port, int lb) 916 { 917 LOG_VERBOSE(BSL_LS_SOC_COMMON, 918 (BSL_META_U(unit, 919 "mac_cl_loopback_set: unit %d port %s loopback=%s\n"), 920 unit, SOC_PORT_NAME(unit, port), 921 lb ? "local" : "no")); 922 923 /* need to enable clock compensation for applicable serdes device */ 924 (void)soc_phyctrl_notify(unit, port, phyEventMacLoopback, lb? 1: 0); 925 926 return soc_reg_field32_modify(unit, CLMAC_CTRLr, port, LOCAL_LPBKf, 927 lb ? 1 : 0); 928 929 return SOC_E_NONE; 930 } 931 932 /* 933 * Function: 934 * mac_cl_loopback_get 935 * Purpose: 936 * Get current CLMAC loopback mode setting. 937 * Parameters: 938 * unit - XGS unit #. 939 * port - XGS port # on unit. 940 * loopback - (OUT) Boolean: true = loopback, false = normal 941 * Returns: 942 * SOC_E_XXX 943 */ 944 STATIC int 945 mac_cl_loopback_get(int unit, soc_port_t port, int *lb) 946 { 947 uint64 ctrl; 948 949 SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &ctrl)); 950 951 *lb = soc_reg64_field32_get(unit, CLMAC_CTRLr, ctrl, LOCAL_LPBKf); 952 953 LOG_VERBOSE(BSL_LS_SOC_COMMON, 954 (BSL_META_U(unit, 955 "mac_cl_loopback_get: unit %d port %s loopback=%s\n"), 956 unit, SOC_PORT_NAME(unit, port), 957 *lb ? "local" : "no")); 958 return SOC_E_NONE; 959 } 960 961 /* 962 * Function: 963 * mac_cl_pause_addr_set 964 * Purpose: 965 * Configure PAUSE frame source address. 966 * Parameters: 967 * unit - XGS unit #. 968 * port - XGS port # on unit. 969 * pause_mac - (OUT) MAC address used for pause transmission. 970 * Returns: 971 * SOC_E_XXX 972 */ 973 STATIC int 974 mac_cl_pause_addr_set(int unit, soc_port_t port, sal_mac_addr_t mac) 975 { 976 static soc_field_t fields[2] = { SA_HIf, SA_LOf }; 977 uint32 values[2]; 978 979 LOG_VERBOSE(BSL_LS_SOC_COMMON, 980 (BSL_META_U(unit, 981 "mac_cl_pause_addr_set: unit %d port %s MAC=<" 982 "%02x:%02x:%02x:%02x:%02x:%02x>\n"), 983 unit, SOC_PORT_NAME(unit, port), 984 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])); 985 986 values[0] = (mac[0] << 8) | mac[1]; 987 values[1] = (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5]; 988 989 SOC_IF_ERROR_RETURN 990 (soc_reg_fields32_modify(unit, CLMAC_TX_MAC_SAr, port, 2, fields, 991 values)); 992 SOC_IF_ERROR_RETURN 993 (soc_reg_fields32_modify(unit, CLMAC_RX_MAC_SAr, port, 2, fields, 994 values)); 995 996 return SOC_E_NONE; 997 } 998 999 /* 1000 * Function: 1001 * mac_cl_pause_addr_get 1002 * Purpose: 1003 * Retrieve PAUSE frame source address. 1004 * Parameters: 1005 * unit - XGS unit #. 1006 * port - XGS port # on unit. 1007 * pause_mac - (OUT) MAC address used for pause transmission. 1008 * Returns: 1009 * SOC_E_XXX 1010 * NOTE: We always write the same thing to TX & RX SA 1011 * so, we just return the contects on RX_MAC_SA. 1012 */ 1013 STATIC int 1014 mac_cl_pause_addr_get(int unit, soc_port_t port, sal_mac_addr_t mac) 1015 { 1016 uint64 rval64; 1017 uint32 values[2]; 1018 1019 SOC_IF_ERROR_RETURN(READ_CLMAC_RX_MAC_SAr(unit, port, &rval64)); 1020 values[0] = soc_reg64_field32_get(unit, CLMAC_RX_MAC_SAr, rval64, SA_HIf); 1021 values[1] = soc_reg64_field32_get(unit, CLMAC_RX_MAC_SAr, rval64, SA_LOf); 1022 1023 mac[0] = (values[0] & 0x0000ff00) >> 8; 1024 mac[1] = values[0] & 0x000000ff; 1025 mac[2] = (values[1] & 0xff000000) >> 24; 1026 mac[3] = (values[1] & 0x00ff0000) >> 16; 1027 mac[4] = (values[1] & 0x0000ff00) >> 8; 1028 mac[5] = values[1] & 0x000000ff; 1029 1030 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1031 (BSL_META_U(unit, 1032 "mac_cl_pause_addr_get: unit %d port %s MAC=<" 1033 "%02x:%02x:%02x:%02x:%02x:%02x>\n"), 1034 unit, SOC_PORT_NAME(unit, port), 1035 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])); 1036 return SOC_E_NONE; 1037 } 1038 1039 /* 1040 * Function: 1041 * mac_cl_interface_set 1042 * Purpose: 1043 * Set a CLMAC interface type 1044 * Parameters: 1045 * unit - XGS unit #. 1046 * port - XGS port # on unit. 1047 * pif - one of SOC_PORT_IF_* 1048 * Returns: 1049 * SOC_E_NONE 1050 * SOC_E_UNAVAIL - requested mode not supported. 1051 * Notes: 1052 */ 1053 STATIC int 1054 mac_cl_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 1055 { 1056 #ifdef BROADCOM_DEBUG 1057 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1058 (BSL_META_U(unit, 1059 "mac_cl_interface_set: unit %d port %s interface=%s\n"), 1060 unit, SOC_PORT_NAME(unit, port), 1061 mac_cl_port_if_names[pif])); 1062 #endif 1063 return SOC_E_NONE; 1064 } 1065 1066 /* 1067 * Function: 1068 * mac_cl_interface_get 1069 * Purpose: 1070 * Retrieve CLMAC interface type 1071 * Parameters: 1072 * unit - XGS unit #. 1073 * port - XGS port # on unit. 1074 * pif - (OUT) one of SOC_PORT_IF_* 1075 * Returns: 1076 * SOC_E_NONE 1077 */ 1078 STATIC int 1079 mac_cl_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 1080 { 1081 COMPILER_REFERENCE(unit); 1082 COMPILER_REFERENCE(port); 1083 1084 *pif = SOC_PORT_IF_CGMII; 1085 1086 #ifdef BROADCOM_DEBUG 1087 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1088 (BSL_META_U(unit, 1089 "mac_cl_interface_get: unit %d port %s interface=%s\n"), 1090 unit, SOC_PORT_NAME(unit, port), 1091 mac_cl_port_if_names[*pif])); 1092 #endif 1093 return SOC_E_NONE; 1094 } 1095 1096 /* 1097 * Function: 1098 * mac_cl_frame_max_set 1099 * Description: 1100 * Set the maximum receive frame size for the port 1101 * Parameters: 1102 * unit - Device number 1103 * port - Port number 1104 * size - Maximum frame size in bytes 1105 * Return Value: 1106 * BCM_E_XXX 1107 */ 1108 STATIC int 1109 mac_cl_frame_max_set(int unit, soc_port_t port, int size) 1110 { 1111 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1112 (BSL_META_U(unit, 1113 "mac_cl_frame_max_set: unit %d port %s size=%d\n"), 1114 unit, SOC_PORT_NAME(unit, port), 1115 size)); 1116 1117 if (IS_CE_PORT(unit, port) || IS_XE_PORT(unit, port) || IS_GE_PORT(unit, port)) { 1118 /* For VLAN tagged packets */ 1119 size += 4; 1120 } 1121 return soc_reg_field32_modify(unit, CLMAC_RX_MAX_SIZEr, port, RX_MAX_SIZEf, 1122 size); 1123 } 1124 1125 /* 1126 * Function: 1127 * mac_cl_frame_max_get 1128 * Description: 1129 * Set the maximum receive frame size for the port 1130 * Parameters: 1131 * unit - Device number 1132 * port - Port number 1133 * size - Maximum frame size in bytes 1134 * Return Value: 1135 * BCM_E_XXX 1136 */ 1137 STATIC int 1138 mac_cl_frame_max_get(int unit, soc_port_t port, int *size) 1139 { 1140 uint64 rval; 1141 1142 SOC_IF_ERROR_RETURN(READ_CLMAC_RX_MAX_SIZEr(unit, port, &rval)); 1143 *size = soc_reg64_field32_get(unit, CLMAC_RX_MAX_SIZEr, rval, RX_MAX_SIZEf); 1144 if (IS_CE_PORT(unit, port) || IS_XE_PORT(unit, port) || IS_GE_PORT(unit, port)) { 1145 /* For VLAN tagged packets */ 1146 *size -= 4; 1147 } 1148 1149 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1150 (BSL_META_U(unit, 1151 "mac_cl_frame_max_get: unit %d port %s size=%d\n"), 1152 unit, SOC_PORT_NAME(unit, port), 1153 *size)); 1154 return SOC_E_NONE; 1155 } 1156 1157 /* 1158 * Function: 1159 * mac_cl_ifg_set 1160 * Description: 1161 * Sets the new ifg (Inter-frame gap) value 1162 * Parameters: 1163 * unit - Device number 1164 * port - Port number 1165 * speed - the speed for which the IFG is being set 1166 * duplex - the duplex for which the IFG is being set 1167 * ifg - number of bits to use for average inter-frame gap 1168 * Return Value: 1169 * BCM_E_XXX 1170 * Notes: 1171 * The function makes sure the IFG value makes sense and updates the 1172 * IPG register in case the speed/duplex match the current settings 1173 */ 1174 STATIC int 1175 mac_cl_ifg_set(int unit, soc_port_t port, int speed, 1176 soc_port_duplex_t duplex, int ifg) 1177 { 1178 int cur_speed; 1179 int cur_duplex; 1180 int real_ifg; 1181 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 1182 uint64 rval, orval; 1183 soc_port_ability_t ability; 1184 uint32 pa_flag; 1185 1186 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1187 (BSL_META_U(unit, 1188 "mac_cl_ifg_set: unit %d port %s speed=%dMb duplex=%s " 1189 "ifg=%d\n"), 1190 unit, SOC_PORT_NAME(unit, port), 1191 speed, duplex ? "True" : "False", ifg)); 1192 1193 pa_flag = SOC_PA_SPEED(speed); 1194 sal_memset(&ability, 0, sizeof(ability)); 1195 soc_mac_cl.md_ability_local_get(unit, port, &ability); 1196 if (!(pa_flag & ability.speed_full_duplex)) { 1197 return SOC_E_PARAM; 1198 } 1199 1200 /* Silently adjust the specified ifp bits to valid value */ 1201 /* valid value: 8 to 64 bytes (i.e. multiple of 8 bits) */ 1202 real_ifg = ifg < 64 ? 64 : (ifg > 512 ? 512 : (ifg + 7) & (0x7f << 3)); 1203 1204 if (IS_CE_PORT(unit, port) || IS_XE_PORT(unit, port)) { 1205 si->fd_xe = real_ifg; 1206 } else { 1207 si->fd_hg = real_ifg; 1208 } 1209 1210 SOC_IF_ERROR_RETURN(mac_cl_duplex_get(unit, port, &cur_duplex)); 1211 SOC_IF_ERROR_RETURN(mac_cl_speed_get(unit, port, &cur_speed)); 1212 1213 /* CLMAC_MODE supports only 4 speeds with 4 being max as LINK_10G_PLUS */ 1214 /* Unlike the corresponding XLMAC function call, mac_cl_speed_get() 1215 * returns a fine grained speed value when CLMAC_MODE.SPEEDf=LINK_10G_PLUS 1216 * Hence the check below uses cur_speed >= 10000, unlike the 1217 * cur_speed == 10000 check used in xlmac */ 1218 if ((speed >= 10000) && (cur_speed >= 10000)) { 1219 cur_speed = speed; 1220 } 1221 1222 if (cur_speed == speed && 1223 cur_duplex == (duplex == SOC_PORT_DUPLEX_FULL ? TRUE : FALSE)) { 1224 SOC_IF_ERROR_RETURN(READ_CLMAC_TX_CTRLr(unit, port, &rval)); 1225 orval = rval; 1226 soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &rval, AVERAGE_IPGf, 1227 real_ifg / 8); 1228 if (COMPILER_64_NE(rval, orval)) { 1229 SOC_IF_ERROR_RETURN(WRITE_CLMAC_TX_CTRLr(unit, port, rval)); 1230 } 1231 } 1232 1233 return SOC_E_NONE; 1234 } 1235 1236 /* 1237 * Function: 1238 * mac_cl_ifg_get 1239 * Description: 1240 * Sets the new ifg (Inter-frame gap) value 1241 * Parameters: 1242 * unit - Device number 1243 * port - Port number 1244 * speed - the speed for which the IFG is being set 1245 * duplex - the duplex for which the IFG is being set 1246 * size - Maximum frame size in bytes 1247 * Return Value: 1248 * BCM_E_XXX 1249 * Notes: 1250 * The function makes sure the IFG value makes sense and updates the 1251 * IPG register in case the speed/duplex match the current settings 1252 */ 1253 STATIC int 1254 mac_cl_ifg_get(int unit, soc_port_t port, int speed, 1255 soc_port_duplex_t duplex, int *ifg) 1256 { 1257 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 1258 soc_port_ability_t ability; 1259 uint32 pa_flag; 1260 1261 if (!duplex) { 1262 return SOC_E_PARAM; 1263 } 1264 1265 pa_flag = SOC_PA_SPEED(speed); 1266 sal_memset(&ability, 0, sizeof(ability)); 1267 soc_mac_cl.md_ability_local_get(unit, port, &ability); 1268 if (!(pa_flag & ability.speed_full_duplex)) { 1269 return SOC_E_PARAM; 1270 } 1271 1272 if (IS_CE_PORT(unit, port) || IS_XE_PORT(unit, port)) { 1273 *ifg = si->fd_xe; 1274 } else { 1275 *ifg = si->fd_hg; 1276 } 1277 1278 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1279 (BSL_META_U(unit, 1280 "mac_cl_ifg_get: unit %d port %s speed=%dMb duplex=%s " 1281 "ifg=%d\n"), 1282 unit, SOC_PORT_NAME(unit, port), 1283 speed, duplex ? "True" : "False", *ifg)); 1284 return SOC_E_NONE; 1285 } 1286 1287 /* 1288 * Function: 1289 * _mac_cl_port_mode_update 1290 * Purpose: 1291 * Set the CLMAC port encapsulation mode. 1292 * Parameters: 1293 * unit - XGS unit #. 1294 * port - XGS port # on unit. 1295 * hg_mode - SOC HG encap modes. value={HG/HG2/HG2-LITE} 1296 * Returns: 1297 * SOC_E_XXX 1298 */ 1299 STATIC int 1300 _mac_cl_port_mode_update(int unit, soc_port_t port, int hg_mode) 1301 { 1302 uint32 rval; 1303 uint64 val64, rval64, ctrl; 1304 soc_pbmp_t ctr_pbmp; 1305 int speed = 0; 1306 int rv = SOC_E_NONE; 1307 int to_hg_port = 0 ; 1308 int phy_enable = 0; 1309 int encap_mode = 0; 1310 int en_able = 0; 1311 1312 /* The current encap mode */ 1313 SOC_IF_ERROR_RETURN(READ_CLMAC_MODEr(unit, port, &rval64)); 1314 encap_mode = soc_reg64_field32_get(unit, CLMAC_MODEr, rval64, HDR_MODEf); 1315 1316 /* The current port enable status */ 1317 SOC_IF_ERROR_RETURN(mac_cl_enable_get(unit, port, &en_able)); 1318 1319 /* Pause linkscan */ 1320 soc_linkscan_pause(unit); 1321 1322 /* Pause counter collection */ 1323 COUNTER_LOCK(unit); 1324 1325 /* for original hg_mode parameter is at value={TRUE|FALSE} */ 1326 to_hg_port = (hg_mode != SOC_ENCAP_IEEE) ? TRUE : FALSE; 1327 if (soc_feature(unit, soc_feature_hg2_light_in_portmacro)) { 1328 soc_xport_type_mode_update(unit, port, hg_mode); 1329 } else { 1330 soc_xport_type_update(unit, port, to_hg_port); 1331 } 1332 1333 if (to_hg_port) { 1334 SOC_IF_ERROR_RETURN(soc_port_hg_speed_get(unit, port, &speed)); 1335 SOC_IF_ERROR_RETURN(soc_phyctrl_set_speed_max(unit, port, speed)); 1336 } else { 1337 speed = SOC_INFO(unit).port_init_speed[port]; 1338 #ifdef BCM_TOMAHAWK_SUPPORT 1339 if (SOC_IS_TOMAHAWKX(unit)) { 1340 SOC_IF_ERROR_RETURN(soc_th_port_ie_speed_get(unit, port, &speed)); 1341 } 1342 #endif 1343 SOC_IF_ERROR_RETURN(soc_phyctrl_set_speed_max(unit, port, speed)); 1344 } 1345 rv = soc_phyctrl_enable_get(unit, port, &phy_enable); 1346 1347 if (SOC_SUCCESS(rv)) { 1348 rv = soc_phyctrl_init(unit, port); 1349 } 1350 1351 if (soc_feature(unit, soc_feature_port_enable_encap_restore)){ 1352 if (SOC_SUCCESS(rv)) { 1353 rv = soc_phyctrl_enable_set(unit, port, phy_enable); 1354 } 1355 } 1356 1357 if (SOC_SUCCESS(rv)) { 1358 rv = mac_cl_init(unit, port); 1359 } else { 1360 goto _failed; 1361 } 1362 1363 if (SOC_SUCCESS(rv)) { 1364 if (soc_feature(unit, soc_feature_disable_rx_on_port) && (0 == en_able)) { 1365 SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &ctrl)); 1366 /* Enable MAC TX if CPU sends packet out */ 1367 soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, TX_ENf, 1); 1368 /* Disable MAC RX */ 1369 soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, RX_ENf, 0); 1370 /* Put port into SOFT_RESET */ 1371 soc_reg64_field32_set(unit, CLMAC_CTRLr, &ctrl, SOFT_RESETf, 1); 1372 SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, ctrl)); 1373 } else { 1374 rv = mac_cl_enable_set(unit, port, 0); 1375 } 1376 } else { 1377 goto _failed; 1378 } 1379 1380 if (SOC_SUCCESS(rv)) { 1381 SOC_PBMP_CLEAR(ctr_pbmp); 1382 SOC_PBMP_PORT_SET(ctr_pbmp, port); 1383 COMPILER_64_SET(val64, 0, 0); 1384 rv = soc_counter_set_by_port(unit, ctr_pbmp, val64); 1385 } else { 1386 goto _failed; 1387 } 1388 1389 COUNTER_UNLOCK(unit); 1390 soc_linkscan_continue(unit); 1391 rval = 0; 1392 1393 if (SOC_REG_IS_VALID(unit, CLPORT_CONFIGr)) { 1394 1395 SOC_IF_ERROR_RETURN(READ_CLPORT_CONFIGr(unit, port, &rval)); 1396 #ifdef BCM_GREYHOUND2_SUPPORT 1397 if (SOC_IS_GREYHOUND2(unit)) { 1398 uint32 clp_hg_mode; 1399 1400 /* 1401 * CLPORT and PGW register 1402 * - for HIGIG_MODEf : 1403 * will be '1' for HG/HG+ setting only and '0' for other 1404 * encap modes{IEEE/HG2/HG2-LITE} 1405 * - for HGIGIG2_MODEf : 1406 * will be 1 for HG2 and will be 0 for other 1407 * encap modes{IEEE/HG/HG+/HG2-LITE} 1408 */ 1409 clp_hg_mode = (hg_mode == SOC_ENCAP_HIGIG) ? 1 : 0; 1410 SOC_IF_ERROR_RETURN 1411 (soc_greyhound2_pgw_encap_field_modify(unit, port, 1412 HIGIG_MODEf, 1413 clp_hg_mode)); 1414 1415 soc_reg_field_set(unit, CLPORT_CONFIGr, &rval, HIGIG_MODEf, 1416 clp_hg_mode); 1417 1418 clp_hg_mode = (hg_mode == SOC_ENCAP_HIGIG2) ? 1 : 0; 1419 soc_reg_field_set(unit, CLPORT_CONFIGr, &rval, HIGIG2_MODEf, 1420 clp_hg_mode); 1421 } else 1422 #endif /* GREYHOUND2 */ 1423 { 1424 soc_reg_field_set(unit, CLPORT_CONFIGr, &rval, HIGIG2_MODEf, 1425 to_hg_port); 1426 } 1427 1428 SOC_IF_ERROR_RETURN(WRITE_CLPORT_CONFIGr(unit, port, rval)); 1429 } 1430 1431 _failed: 1432 if (SOC_FAILURE(rv)) { 1433 COUNTER_UNLOCK(unit); 1434 soc_linkscan_continue(unit); 1435 if (soc_feature(unit, soc_feature_hg2_light_in_portmacro)) { 1436 soc_xport_type_mode_update(unit, port, encap_mode); 1437 } else { 1438 soc_xport_type_update(unit, port, encap_mode); 1439 } 1440 SOC_IF_ERROR_RETURN(READ_CLMAC_MODEr(unit, port, &rval64)); 1441 soc_reg64_field32_set(unit, CLMAC_MODEr, &rval64, HDR_MODEf, encap_mode); 1442 SOC_IF_ERROR_RETURN(WRITE_CLMAC_MODEr(unit, port, rval64)); 1443 } 1444 1445 return rv; 1446 } 1447 1448 /* 1449 * Function: 1450 * mac_cl_encap_set 1451 * Purpose: 1452 * Set the CLMAC port encapsulation mode. 1453 * Parameters: 1454 * unit - XGS unit #. 1455 * port - XGS port # on unit. 1456 * mode - (IN) encap bits (defined above) 1457 * Returns: 1458 * SOC_E_XXX 1459 */ 1460 STATIC int 1461 mac_cl_encap_set(int unit, soc_port_t port, int mode) 1462 { 1463 int enable, encap, rv = SOC_E_NONE; 1464 int runt; 1465 1466 #ifdef BROADCOM_DEBUG 1467 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1468 (BSL_META_U(unit, 1469 "mac_cl_encap_set: unit %d port %s encapsulation=%s\n"), 1470 unit, SOC_PORT_NAME(unit, port), 1471 mac_cl_encap_mode[mode])); 1472 #endif 1473 1474 switch (mode) { 1475 case SOC_ENCAP_IEEE: 1476 case SOC_ENCAP_HIGIG2_LITE: 1477 encap = 0; 1478 break; 1479 case SOC_ENCAP_HIGIG: 1480 encap = 1; 1481 break; 1482 case SOC_ENCAP_HIGIG2: 1483 encap = 2; 1484 break; 1485 default: 1486 return SOC_E_PARAM; 1487 } 1488 1489 if (!soc_feature(unit, soc_feature_xport_convertible)) { 1490 if ((IS_E_PORT(unit, port) && mode != SOC_ENCAP_IEEE) || 1491 (IS_ST_PORT(unit, port) && mode == SOC_ENCAP_IEEE)) { 1492 return SOC_E_PARAM; 1493 } 1494 } 1495 1496 SOC_IF_ERROR_RETURN(mac_cl_enable_get(unit, port, &enable)); 1497 if (enable) { 1498 /* Turn off TX/RX enable */ 1499 SOC_IF_ERROR_RETURN(mac_cl_enable_set(unit, port, 0)); 1500 } 1501 1502 if (soc_feature(unit, soc_feature_hg2_light_in_portmacro)) { 1503 /* mode update for all encap mode change! */ 1504 SOC_IF_ERROR_RETURN(_mac_cl_port_mode_update(unit, port, mode)); 1505 } else if ((IS_E_PORT(unit, port) && mode != SOC_ENCAP_IEEE) || 1506 (IS_ST_PORT(unit, port) && mode == SOC_ENCAP_IEEE)) { 1507 /* IEEE -> HG or HG -> IEEE */ 1508 SOC_IF_ERROR_RETURN(_mac_cl_port_mode_update(unit, port, mode)); 1509 } 1510 1511 /* Update the encapsulation mode */ 1512 rv = soc_reg_field32_modify(unit, CLMAC_MODEr, port, HDR_MODEf, encap); 1513 1514 runt = (mode == SOC_ENCAP_HIGIG2) ? CLMAC_RUNT_THRESHOLD_HG2 : 1515 ((mode == SOC_ENCAP_HIGIG) ? CLMAC_RUNT_THRESHOLD_HG1 : 1516 CLMAC_RUNT_THRESHOLD_IEEE); 1517 SOC_IF_ERROR_RETURN 1518 (soc_reg_field32_modify(unit, CLMAC_RX_CTRLr, port, RUNT_THRESHOLDf, runt)); 1519 1520 SOC_IF_ERROR_RETURN 1521 (soc_reg_field32_modify(unit, CLMAC_RX_CTRLr, port, STRICT_PREAMBLEf, 1522 mode == SOC_ENCAP_IEEE ? 1 : 0)); 1523 1524 if (enable) { 1525 /* Re-enable transmitter and receiver */ 1526 SOC_IF_ERROR_RETURN(mac_cl_enable_set(unit, port, 1)); 1527 } 1528 1529 return rv; 1530 } 1531 1532 /* 1533 * Function: 1534 * mac_cl_encap_get 1535 * Purpose: 1536 * Get the CLMAC port encapsulation mode. 1537 * Parameters: 1538 * unit - XGS unit #. 1539 * port - XGS port # on unit. 1540 * mode - (INT) encap bits (defined above) 1541 * Returns: 1542 * SOC_E_XXX 1543 */ 1544 STATIC int 1545 mac_cl_encap_get(int unit, soc_port_t port, int *mode) 1546 { 1547 uint64 rval; 1548 1549 if (!mode) { 1550 return SOC_E_PARAM; 1551 } 1552 1553 SOC_IF_ERROR_RETURN(READ_CLMAC_MODEr(unit, port, &rval)); 1554 switch (soc_reg64_field32_get(unit, CLMAC_MODEr, rval, HDR_MODEf)) { 1555 case 0: 1556 *mode = SOC_ENCAP_IEEE; 1557 break; 1558 case 1: 1559 *mode = SOC_ENCAP_HIGIG; 1560 break; 1561 case 2: 1562 *mode = SOC_ENCAP_HIGIG2; 1563 break; 1564 default: 1565 *mode = SOC_ENCAP_COUNT; 1566 } 1567 1568 #ifdef BROADCOM_DEBUG 1569 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1570 (BSL_META_U(unit, 1571 "mac_cl_encap_get: unit %d port %s encapsulation=%s\n"), 1572 unit, SOC_PORT_NAME(unit, port), 1573 mac_cl_encap_mode[*mode])); 1574 #endif 1575 return SOC_E_NONE; 1576 } 1577 1578 /* 1579 * Function: 1580 * mac_cl_expected_rx_latency_get 1581 * Purpose: 1582 * Get the CLMAC port expected Rx latency 1583 * Parameters: 1584 * unit - XGS unit #. 1585 * port - XGS port # on unit. 1586 * latency - (OUT) Latency in NS 1587 * Returns: 1588 * SOC_E_XXX 1589 */ 1590 STATIC int 1591 mac_cl_expected_rx_latency_get(int unit, soc_port_t port, int *latency) 1592 { 1593 int speed = 0; 1594 SOC_IF_ERROR_RETURN(mac_cl_speed_get(unit, port, &speed)); 1595 1596 1597 switch (speed) { 1598 case 1000: /* GigE */ 1599 *latency = 0; 1600 break; 1601 1602 case 10000: /* 10G */ 1603 *latency = 0; 1604 break; 1605 1606 default: 1607 *latency = 0; 1608 break; 1609 } 1610 1611 return SOC_E_NONE; 1612 } 1613 1614 /* 1615 * Function: 1616 * mac_cl_control_set 1617 * Purpose: 1618 * To configure MAC control properties. 1619 * Parameters: 1620 * unit - XGS unit #. 1621 * port - XGS port # on unit. 1622 * type - MAC control property to set. 1623 * int - New setting for MAC control. 1624 * Returns: 1625 * SOC_E_XXX 1626 */ 1627 STATIC int 1628 mac_cl_control_set(int unit, soc_port_t port, soc_mac_control_t type, 1629 int value) 1630 { 1631 uint64 rval, copy; 1632 uint32 fval; 1633 int ver; 1634 1635 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1636 (BSL_META_U(unit, 1637 "mac_cl_control_set: unit %d port %s type=%d value=%d\n"), 1638 unit, SOC_PORT_NAME(unit, port), 1639 type, value)); 1640 1641 switch (type) { 1642 case SOC_MAC_CONTROL_RX_SET: 1643 SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &rval)); 1644 copy = rval; 1645 soc_reg64_field32_set(unit, CLMAC_CTRLr, &rval, RX_ENf, value ? 1 : 0); 1646 if (COMPILER_64_NE(rval, copy)) { 1647 SOC_IF_ERROR_RETURN(WRITE_CLMAC_CTRLr(unit, port, rval)); 1648 } 1649 break; 1650 case SOC_MAC_CONTROL_FRAME_SPACING_STRETCH: 1651 if (value < 0 || value > CLMAC_THROT_10G_TO_2P5G) { 1652 return SOC_E_PARAM; 1653 } else { 1654 SOC_IF_ERROR_RETURN(READ_CLMAC_TX_CTRLr(unit, port, &rval)); 1655 if (value == CLMAC_THROT_10G_TO_5G) { 1656 soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &rval, THROT_DENOMf, 21); 1657 soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &rval, THROT_NUMf, 21); 1658 } else if (value == CLMAC_THROT_10G_TO_2P5G) { 1659 soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &rval, THROT_DENOMf, 21); 1660 soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &rval, THROT_NUMf, 63); 1661 } else if (value >= 8) { 1662 soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &rval, THROT_DENOMf, 1663 value); 1664 soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &rval, THROT_NUMf, 1665 1); 1666 } else { 1667 soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &rval, THROT_DENOMf, 1668 0); 1669 soc_reg64_field32_set(unit, CLMAC_TX_CTRLr, &rval, THROT_NUMf, 1670 0); 1671 } 1672 SOC_IF_ERROR_RETURN(WRITE_CLMAC_TX_CTRLr(unit, port, rval)); 1673 } 1674 return SOC_E_NONE; 1675 1676 case SOC_MAC_PASS_CONTROL_FRAME: 1677 SOC_IF_ERROR_RETURN(_clmac_gen_version_get(unit, port, &ver)); 1678 if (ver == CLMAC_VERSION_A030) { 1679 SOC_IF_ERROR_RETURN(READ_CLMAC_RX_CTRLr(unit, port, &rval)); 1680 soc_reg64_field32_set (unit, CLMAC_RX_CTRLr, &rval, 1681 RX_PASS_PAUSEf, (value? 1:0)); 1682 SOC_IF_ERROR_RETURN(WRITE_CLMAC_RX_CTRLr(unit, port, rval)); 1683 } 1684 break; 1685 1686 case SOC_MAC_CONTROL_PFC_TYPE: 1687 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CLMAC_PFC_TYPEr, port, 1688 PFC_ETH_TYPEf, value)); 1689 break; 1690 1691 case SOC_MAC_CONTROL_PFC_OPCODE: 1692 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CLMAC_PFC_OPCODEr, 1693 port, PFC_OPCODEf, value)); 1694 break; 1695 1696 case SOC_MAC_CONTROL_PFC_CLASSES: 1697 if (value != 8) { 1698 return SOC_E_PARAM; 1699 } 1700 break; 1701 1702 case SOC_MAC_CONTROL_PFC_MAC_DA_OUI: 1703 SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_DAr(unit, port, &rval)); 1704 fval = soc_reg64_field32_get(unit, CLMAC_PFC_DAr, rval, PFC_MACDA_LOf); 1705 fval &= 0x00ffffff; 1706 fval |= (value & 0xff) << 24; 1707 soc_reg64_field32_set(unit, CLMAC_PFC_DAr, &rval, PFC_MACDA_LOf, fval); 1708 1709 soc_reg64_field32_set(unit, CLMAC_PFC_DAr, &rval, PFC_MACDA_HIf, 1710 value >> 8); 1711 SOC_IF_ERROR_RETURN(WRITE_CLMAC_PFC_DAr(unit, port, rval)); 1712 break; 1713 1714 case SOC_MAC_CONTROL_PFC_MAC_DA_NONOUI: 1715 SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_DAr(unit, port, &rval)); 1716 fval = soc_reg64_field32_get(unit, CLMAC_PFC_DAr, rval, PFC_MACDA_LOf); 1717 fval &= 0xff000000; 1718 fval |= value; 1719 soc_reg64_field32_set(unit, CLMAC_PFC_DAr, &rval, PFC_MACDA_LOf, fval); 1720 SOC_IF_ERROR_RETURN(WRITE_CLMAC_PFC_DAr(unit, port, rval)); 1721 break; 1722 1723 case SOC_MAC_CONTROL_PFC_RX_PASS: 1724 if (!SOC_REG_FIELD_VALID(unit, CLMAC_PFC_CTRLr, RX_PASS_PFCf)) { 1725 return SOC_E_UNAVAIL; 1726 } 1727 1728 SOC_IF_ERROR_RETURN 1729 (soc_reg_field32_modify(unit, CLMAC_PFC_CTRLr, port, RX_PASS_PFCf, 1730 value ? 1 : 0)); 1731 break; 1732 1733 case SOC_MAC_CONTROL_PFC_RX_ENABLE: 1734 SOC_IF_ERROR_RETURN 1735 (soc_reg_field32_modify(unit, CLMAC_PFC_CTRLr, port, RX_PFC_ENf, 1736 value ? 1 : 0)); 1737 break; 1738 1739 case SOC_MAC_CONTROL_PFC_TX_ENABLE: 1740 SOC_IF_ERROR_RETURN 1741 (soc_reg_field32_modify(unit, CLMAC_PFC_CTRLr, port, TX_PFC_ENf, 1742 value ? 1 : 0)); 1743 break; 1744 1745 case SOC_MAC_CONTROL_PFC_FORCE_XON: 1746 SOC_IF_ERROR_RETURN 1747 (soc_reg_field32_modify(unit, CLMAC_PFC_CTRLr, port, FORCE_PFC_XONf, 1748 value ? 1 : 0)); 1749 break; 1750 1751 case SOC_MAC_CONTROL_PFC_STATS_ENABLE: 1752 SOC_IF_ERROR_RETURN 1753 (soc_reg_field32_modify(unit, CLMAC_PFC_CTRLr, port, PFC_STATS_ENf, 1754 value ? 1 : 0)); 1755 break; 1756 1757 case SOC_MAC_CONTROL_PFC_REFRESH_TIME: 1758 SOC_IF_ERROR_RETURN 1759 (soc_reg_field32_modify(unit, CLMAC_PFC_CTRLr, port, 1760 PFC_REFRESH_TIMERf, value)); 1761 break; 1762 1763 case SOC_MAC_CONTROL_PFC_XOFF_TIME: 1764 SOC_IF_ERROR_RETURN 1765 (soc_reg_field32_modify(unit, CLMAC_PFC_CTRLr, port, 1766 PFC_XOFF_TIMERf, value)); 1767 break; 1768 1769 case SOC_MAC_CONTROL_LLFC_RX_ENABLE: 1770 SOC_IF_ERROR_RETURN 1771 (soc_reg_field32_modify(unit, CLMAC_LLFC_CTRLr, port, RX_LLFC_ENf, 1772 value ? 1 : 0)); 1773 1774 /* Feature check inside the soc_llfc_xon_set() should take care 1775 * of devices supporting this functionality. 1776 */ 1777 SOC_IF_ERROR_RETURN 1778 (soc_llfc_xon_set(unit, port, value ? 1 : 0)); 1779 break; 1780 1781 case SOC_MAC_CONTROL_LLFC_TX_ENABLE: 1782 SOC_IF_ERROR_RETURN 1783 (soc_reg_field32_modify(unit, CLMAC_LLFC_CTRLr, port, TX_LLFC_ENf, 1784 value ? 1 : 0)); 1785 break; 1786 1787 case SOC_MAC_CONTROL_EEE_ENABLE: 1788 if (!soc_feature(unit, soc_feature_eee)) { 1789 return SOC_E_UNAVAIL; 1790 } 1791 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CLMAC_EEE_CTRLr, 1792 port, EEE_ENf, value)); 1793 break; 1794 1795 case SOC_MAC_CONTROL_EEE_TX_IDLE_TIME: 1796 if (!soc_feature(unit, soc_feature_eee)) { 1797 return SOC_E_UNAVAIL; 1798 } 1799 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CLMAC_EEE_TIMERSr, 1800 port, EEE_DELAY_ENTRY_TIMERf, value)); 1801 break; 1802 1803 case SOC_MAC_CONTROL_EEE_TX_WAKE_TIME: 1804 if (!soc_feature(unit, soc_feature_eee)) { 1805 return SOC_E_UNAVAIL; 1806 } 1807 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, CLMAC_EEE_TIMERSr, 1808 port, EEE_WAKE_TIMERf, value)); 1809 break; 1810 1811 case SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE: 1812 SOC_IF_ERROR_RETURN 1813 (soc_reg_field32_modify(unit, CLMAC_RX_LSS_CTRLr, port, 1814 LOCAL_FAULT_DISABLEf, value ? 0 : 1)); 1815 break; 1816 1817 case SOC_MAC_CONTROL_FAULT_REMOTE_ENABLE: 1818 SOC_IF_ERROR_RETURN 1819 (soc_reg_field32_modify(unit, CLMAC_RX_LSS_CTRLr, port, 1820 REMOTE_FAULT_DISABLEf, value ? 0 : 1)); 1821 break; 1822 1823 case SOC_MAC_CONTROL_EGRESS_DRAIN: 1824 SOC_IF_ERROR_RETURN(mac_cl_egress_queue_drain(unit, port)); 1825 break; 1826 1827 case SOC_MAC_CONTROL_FAILOVER_RX_SET: 1828 break; 1829 1830 default: 1831 return SOC_E_UNAVAIL; 1832 } 1833 1834 return SOC_E_NONE; 1835 } 1836 1837 /* 1838 * Function: 1839 * mac_cl_control_get 1840 * Purpose: 1841 * To get current MAC control setting. 1842 * Parameters: 1843 * unit - XGS unit #. 1844 * port - XGS port # on unit. 1845 * type - MAC control property to set. 1846 * int - New setting for MAC control. 1847 * Returns: 1848 * SOC_E_XXX 1849 */ 1850 STATIC int 1851 mac_cl_control_get(int unit, soc_port_t port, soc_mac_control_t type, 1852 int *value) 1853 { 1854 int rv; 1855 uint64 rval; 1856 uint32 fval0, fval1; 1857 int ver; 1858 1859 if (value == NULL) { 1860 return SOC_E_PARAM; 1861 } 1862 1863 rv = SOC_E_NONE; 1864 switch (type) { 1865 case SOC_MAC_CONTROL_RX_SET: 1866 SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &rval)); 1867 *value = soc_reg64_field32_get(unit, CLMAC_CTRLr, rval, RX_ENf); 1868 break; 1869 case SOC_MAC_CONTROL_SW_RESET: 1870 SOC_IF_ERROR_RETURN(READ_CLMAC_CTRLr(unit, port, &rval)); 1871 *value = soc_reg64_field32_get(unit, CLMAC_CTRLr, rval, SOFT_RESETf); 1872 break; 1873 case SOC_MAC_CONTROL_FRAME_SPACING_STRETCH: 1874 SOC_IF_ERROR_RETURN(READ_CLMAC_TX_CTRLr(unit, port, &rval)); 1875 *value = soc_reg64_field32_get(unit, CLMAC_TX_CTRLr, rval, 1876 THROT_DENOMf); 1877 rv = SOC_E_NONE; 1878 break; 1879 1880 case SOC_MAC_CONTROL_TIMESTAMP_TRANSMIT: 1881 { 1882 uint32 timestamp = 0; 1883 if (soc_feature(unit, soc_feature_timestamp_counter) && 1884 soc_property_get(unit, spn_SW_TIMESTAMP_FIFO_ENABLE, 1)) { 1885 if (soc_counter_timestamp_get(unit, port, ×tamp) != 1886 SOC_E_NOT_FOUND) { 1887 *value = (int)timestamp; 1888 break; 1889 } 1890 } 1891 1892 SOC_IF_ERROR_RETURN 1893 (READ_CLMAC_TX_TIMESTAMP_FIFO_STATUSr(unit, port, &rval)); 1894 if (soc_reg64_field32_get(unit, CLMAC_TX_TIMESTAMP_FIFO_STATUSr, rval, 1895 ENTRY_COUNTf) == 0) { 1896 return SOC_E_EMPTY; 1897 } 1898 SOC_IF_ERROR_RETURN 1899 (READ_CLMAC_TX_TIMESTAMP_FIFO_DATAr(unit, port, &rval)); 1900 *value = soc_reg64_field32_get(unit, CLMAC_TX_TIMESTAMP_FIFO_DATAr, 1901 rval, TIME_STAMPf); 1902 } 1903 break; 1904 1905 case SOC_MAC_PASS_CONTROL_FRAME: 1906 *value = TRUE; 1907 SOC_IF_ERROR_RETURN(_clmac_gen_version_get(unit, port, &ver)); 1908 if (ver == CLMAC_VERSION_A030) { 1909 SOC_IF_ERROR_RETURN(READ_CLMAC_RX_CTRLr(unit, port, &rval)); 1910 *value = soc_reg64_field32_get(unit, CLMAC_RX_CTRLr, rval, RX_PASS_CTRLf); 1911 } 1912 break; 1913 1914 case SOC_MAC_CONTROL_PFC_TYPE: 1915 SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_TYPEr(unit, port, &rval)); 1916 *value = soc_reg64_field32_get(unit, CLMAC_PFC_TYPEr, rval, 1917 PFC_ETH_TYPEf); 1918 break; 1919 1920 case SOC_MAC_CONTROL_PFC_OPCODE: 1921 SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_OPCODEr(unit, port, &rval)); 1922 *value = soc_reg64_field32_get(unit, CLMAC_PFC_OPCODEr, rval, 1923 PFC_OPCODEf); 1924 break; 1925 1926 case SOC_MAC_CONTROL_PFC_CLASSES: 1927 *value = 8; 1928 break; 1929 1930 case SOC_MAC_CONTROL_PFC_MAC_DA_OUI: 1931 SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_DAr(unit, port, &rval)); 1932 fval0 = soc_reg64_field32_get(unit, CLMAC_PFC_DAr, rval, PFC_MACDA_LOf); 1933 fval1 = soc_reg64_field32_get(unit, CLMAC_PFC_DAr, rval, PFC_MACDA_HIf); 1934 *value = (fval0 >> 24) | (fval1 << 8); 1935 break; 1936 1937 case SOC_MAC_CONTROL_PFC_MAC_DA_NONOUI: 1938 SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_DAr(unit, port, &rval)); 1939 *value = soc_reg64_field32_get(unit, CLMAC_PFC_DAr, rval, 1940 PFC_MACDA_LOf) & 0x00ffffff; 1941 break; 1942 1943 case SOC_MAC_CONTROL_PFC_RX_PASS: 1944 SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_CTRLr(unit, port, &rval)); 1945 *value = soc_reg64_field32_get(unit, CLMAC_PFC_CTRLr, rval, 1946 RX_PASS_PFCf); 1947 break; 1948 1949 case SOC_MAC_CONTROL_PFC_RX_ENABLE: 1950 SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_CTRLr(unit, port, &rval)); 1951 *value = soc_reg64_field32_get(unit, CLMAC_PFC_CTRLr, rval, 1952 RX_PFC_ENf); 1953 break; 1954 1955 case SOC_MAC_CONTROL_PFC_TX_ENABLE: 1956 SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_CTRLr(unit, port, &rval)); 1957 *value = soc_reg64_field32_get(unit, CLMAC_PFC_CTRLr, rval, 1958 TX_PFC_ENf); 1959 break; 1960 1961 case SOC_MAC_CONTROL_PFC_FORCE_XON: 1962 SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_CTRLr(unit, port, &rval)); 1963 *value = soc_reg64_field32_get(unit, CLMAC_PFC_CTRLr, rval, 1964 FORCE_PFC_XONf); 1965 break; 1966 1967 case SOC_MAC_CONTROL_PFC_STATS_ENABLE: 1968 SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_CTRLr(unit, port, &rval)); 1969 *value = soc_reg64_field32_get(unit, CLMAC_PFC_CTRLr, rval, 1970 PFC_STATS_ENf); 1971 break; 1972 1973 case SOC_MAC_CONTROL_PFC_REFRESH_TIME: 1974 SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_CTRLr(unit, port, &rval)); 1975 *value = soc_reg64_field32_get(unit, CLMAC_PFC_CTRLr, rval, 1976 PFC_REFRESH_TIMERf); 1977 break; 1978 1979 case SOC_MAC_CONTROL_PFC_XOFF_TIME: 1980 SOC_IF_ERROR_RETURN(READ_CLMAC_PFC_CTRLr(unit, port, &rval)); 1981 *value = soc_reg64_field32_get(unit, CLMAC_PFC_CTRLr, rval, 1982 PFC_XOFF_TIMERf); 1983 break; 1984 1985 case SOC_MAC_CONTROL_LLFC_RX_ENABLE: 1986 SOC_IF_ERROR_RETURN(READ_CLMAC_LLFC_CTRLr(unit, port, &rval)); 1987 *value = soc_reg64_field32_get(unit, CLMAC_LLFC_CTRLr, rval, 1988 RX_LLFC_ENf); 1989 break; 1990 1991 case SOC_MAC_CONTROL_LLFC_TX_ENABLE: 1992 SOC_IF_ERROR_RETURN(READ_CLMAC_LLFC_CTRLr(unit, port, &rval)); 1993 *value = soc_reg64_field32_get(unit, CLMAC_LLFC_CTRLr, rval, 1994 TX_LLFC_ENf); 1995 break; 1996 1997 case SOC_MAC_CONTROL_EEE_ENABLE: 1998 if (!soc_feature(unit, soc_feature_eee)) { 1999 return SOC_E_UNAVAIL; 2000 } 2001 if (!soc_reg_field_valid(unit, CLMAC_EEE_CTRLr, EEE_ENf)) { 2002 return SOC_E_UNAVAIL; 2003 } 2004 SOC_IF_ERROR_RETURN(READ_CLMAC_EEE_CTRLr(unit, port, &rval)); 2005 *value = soc_reg64_field32_get(unit, CLMAC_EEE_CTRLr, rval, EEE_ENf); 2006 break; 2007 2008 case SOC_MAC_CONTROL_EEE_TX_IDLE_TIME: 2009 if (!soc_feature(unit, soc_feature_eee)) { 2010 return SOC_E_UNAVAIL; 2011 } 2012 if (!soc_reg_field_valid(unit, CLMAC_EEE_TIMERSr, EEE_DELAY_ENTRY_TIMERf)) { 2013 return SOC_E_UNAVAIL; 2014 } 2015 SOC_IF_ERROR_RETURN(READ_CLMAC_EEE_TIMERSr(unit, port, &rval)); 2016 *value = soc_reg64_field32_get(unit, CLMAC_EEE_TIMERSr, rval, 2017 EEE_DELAY_ENTRY_TIMERf); 2018 break; 2019 2020 case SOC_MAC_CONTROL_EEE_TX_WAKE_TIME: 2021 if (!soc_feature(unit, soc_feature_eee)) { 2022 return SOC_E_UNAVAIL; 2023 } 2024 if (!soc_reg_field_valid(unit, CLMAC_EEE_TIMERSr, EEE_WAKE_TIMERf)) { 2025 return SOC_E_UNAVAIL; 2026 } 2027 SOC_IF_ERROR_RETURN(READ_CLMAC_EEE_TIMERSr(unit, port, &rval)); 2028 *value = soc_reg64_field32_get(unit, CLMAC_EEE_TIMERSr, rval, 2029 EEE_WAKE_TIMERf); 2030 break; 2031 2032 case SOC_MAC_CONTROL_FAULT_LOCAL_ENABLE: 2033 SOC_IF_ERROR_RETURN(READ_CLMAC_RX_LSS_CTRLr(unit, port, &rval)); 2034 *value = soc_reg64_field32_get(unit, CLMAC_RX_LSS_CTRLr, rval, 2035 LOCAL_FAULT_DISABLEf) ? 0 : 1; 2036 break; 2037 2038 case SOC_MAC_CONTROL_FAULT_LOCAL_STATUS: 2039 SOC_IF_ERROR_RETURN(READ_CLMAC_RX_LSS_STATUSr(unit, port, &rval)); 2040 *value = soc_reg64_field32_get(unit, CLMAC_RX_LSS_STATUSr, rval, 2041 LOCAL_FAULT_STATUSf); 2042 break; 2043 2044 case SOC_MAC_CONTROL_FAULT_REMOTE_ENABLE: 2045 SOC_IF_ERROR_RETURN(READ_CLMAC_RX_LSS_CTRLr(unit, port, &rval)); 2046 *value = soc_reg64_field32_get(unit, CLMAC_RX_LSS_CTRLr, rval, 2047 REMOTE_FAULT_DISABLEf) ? 0 : 1; 2048 break; 2049 2050 case SOC_MAC_CONTROL_FAULT_REMOTE_STATUS: 2051 SOC_IF_ERROR_RETURN(READ_CLMAC_RX_LSS_STATUSr(unit, port, &rval)); 2052 *value = soc_reg64_field32_get(unit, CLMAC_RX_LSS_STATUSr, rval, 2053 REMOTE_FAULT_STATUSf); 2054 break; 2055 case SOC_MAC_CONTROL_EXPECTED_RX_LATENCY: 2056 SOC_IF_ERROR_RETURN(mac_cl_expected_rx_latency_get(unit, port, value)); 2057 break; 2058 2059 default: 2060 return SOC_E_UNAVAIL; 2061 } 2062 2063 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2064 (BSL_META_U(unit, 2065 "mac_cl_control_get: unit %d port %s type=%d value=%d " 2066 "rv=%d\n"), 2067 unit, SOC_PORT_NAME(unit, port), 2068 type, *value, rv)); 2069 return rv; 2070 } 2071 2072 /* 2073 * Function: 2074 * mac_cl_ability_local_get 2075 * Purpose: 2076 * Return the abilities of CLMAC 2077 * Parameters: 2078 * unit - XGS unit #. 2079 * port - XGS port # on unit. 2080 * mode - (OUT) Supported operating modes as a mask of abilities. 2081 * Returns: 2082 * SOC_E_XXX 2083 */ 2084 STATIC int 2085 mac_cl_ability_local_get(int unit, soc_port_t port, 2086 soc_port_ability_t *ability) 2087 { 2088 soc_info_t *si = &SOC_INFO(unit); 2089 int port_speed_max, use_hg_port_speeds = FALSE; 2090 2091 if (NULL == ability) { 2092 return SOC_E_PARAM; 2093 } 2094 2095 ability->speed_half_duplex = SOC_PA_ABILITY_NONE; 2096 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 2097 ability->interface = SOC_PA_INTF_MII | SOC_PA_INTF_XGMII; 2098 ability->medium = SOC_PA_ABILITY_NONE; 2099 ability->loopback = SOC_PA_LB_MAC; 2100 ability->flags = SOC_PA_ABILITY_NONE; 2101 ability->encap = SOC_PA_ENCAP_IEEE | SOC_PA_ENCAP_HIGIG | 2102 SOC_PA_ENCAP_HIGIG2; 2103 2104 /* 2105 * portmap_* config variables allow users to specifiy a HG speed as the max 2106 * speed for a port that initializes as an ethernet port. This allows the user 2107 * to optionally set the port speed to a HG speed after an encap change is 2108 * performed. Under such situations allow HG speeds to be part of the MAC 2109 * ability mask for the ethernet port. 2110 */ 2111 if (soc_feature(unit, soc_feature_flexport_based_speed_set)) { 2112 use_hg_port_speeds = TRUE; 2113 } 2114 /* Adjust port_speed_max according to the port config */ 2115 port_speed_max = si->port_speed_max[port]; 2116 /* Use current number of lanes per port to determine the supported speeds */ 2117 if (use_hg_port_speeds || IS_HG_PORT(unit , port)) { 2118 switch (port_speed_max) { 2119 case 127000: 2120 ability->speed_full_duplex |= SOC_PA_SPEED_127GB; 2121 /* fall through */ 2122 case 120000: 2123 ability->speed_full_duplex |= SOC_PA_SPEED_120GB; 2124 /* fall through */ 2125 case 106000: 2126 if (si->port_num_lanes[port] == 4) { 2127 ability->speed_full_duplex |= SOC_PA_SPEED_106GB; 2128 } 2129 /* fall through */ 2130 case 100000: 2131 if (si->port_num_lanes[port] == 4) { 2132 ability->speed_full_duplex |= SOC_PA_SPEED_100GB; 2133 } 2134 /* fall through */ 2135 case 53000: 2136 if (si->port_num_lanes[port] == 2) { 2137 ability->speed_full_duplex |= SOC_PA_SPEED_53GB; 2138 } 2139 /* fall through */ 2140 case 50000: 2141 if (si->port_num_lanes[port] == 2) { 2142 ability->speed_full_duplex |= SOC_PA_SPEED_50GB; 2143 } 2144 /* fall through */ 2145 case 42000: 2146 if (si->port_num_lanes[port] != 1) { 2147 ability->speed_full_duplex |= SOC_PA_SPEED_42GB; 2148 } 2149 /* fall through */ 2150 case 40000: 2151 if (si->port_num_lanes[port] != 1) { 2152 ability->speed_full_duplex |= SOC_PA_SPEED_40GB; 2153 if(soc_feature(unit, soc_feature_higig_misc_speed_support)) { 2154 ability->speed_full_duplex |= SOC_PA_SPEED_42GB; 2155 } 2156 } 2157 /* fall through */ 2158 case 30000: 2159 if (!SOC_IS_TOMAHAWKX(unit)) { 2160 ability->speed_full_duplex |= SOC_PA_SPEED_30GB; 2161 } 2162 /* fall through */ 2163 case 27000: 2164 if (si->port_num_lanes[port] == 1) { 2165 ability->speed_full_duplex |= SOC_PA_SPEED_27GB; 2166 } 2167 /* fall through */ 2168 case 25000: 2169 if (si->port_num_lanes[port] == 1) { 2170 ability->speed_full_duplex |= SOC_PA_SPEED_25GB; 2171 } 2172 /* fall through */ 2173 case 21000: 2174 if (si->port_num_lanes[port] == 2) { 2175 ability->speed_full_duplex |= SOC_PA_SPEED_21GB; 2176 } 2177 /* fall through */ 2178 case 20000: 2179 if (si->port_num_lanes[port] == 2) { 2180 ability->speed_full_duplex |= SOC_PA_SPEED_20GB; 2181 } 2182 /* fall through */ 2183 case 16000: 2184 if (!SOC_IS_TOMAHAWKX(unit)) { 2185 ability->speed_full_duplex |= SOC_PA_SPEED_16GB; 2186 } 2187 /* fall through */ 2188 case 15000: 2189 if (!SOC_IS_TOMAHAWKX(unit)) { 2190 ability->speed_full_duplex |= SOC_PA_SPEED_15GB; 2191 } 2192 /* fall through */ 2193 case 13000: 2194 if (!SOC_IS_TOMAHAWKX(unit)) { 2195 ability->speed_full_duplex |= SOC_PA_SPEED_13GB; 2196 } 2197 /* fall through */ 2198 case 12000: 2199 if (!SOC_IS_TOMAHAWKX(unit)) { 2200 ability->speed_full_duplex |= SOC_PA_SPEED_12GB; 2201 } 2202 /* fall through */ 2203 case 11000: 2204 if (si->port_num_lanes[port] == 1) { 2205 ability->speed_full_duplex |= SOC_PA_SPEED_11GB; 2206 } 2207 /* fall through */ 2208 case 10000: 2209 if (si->port_num_lanes[port] == 1) { 2210 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 2211 } 2212 /* fall through */ 2213 case 1000: 2214 if (si->port_num_lanes[port] == 1) { 2215 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 2216 } 2217 break; 2218 default: 2219 break; 2220 } 2221 } else { 2222 switch (port_speed_max) { 2223 case 106000: 2224 ability->speed_full_duplex |= SOC_PA_SPEED_106GB; 2225 /* fall through */ 2226 case 100000: 2227 if (si->port_num_lanes[port] == 4) { 2228 ability->speed_full_duplex |= SOC_PA_SPEED_100GB; 2229 } 2230 /* fall through */ 2231 case 53000: 2232 case 50000: 2233 if (si->port_num_lanes[port] == 2) { 2234 ability->speed_full_duplex |= SOC_PA_SPEED_50GB; 2235 } 2236 /* fall through */ 2237 case 42000: 2238 case 40000: 2239 2240 if (si->port_num_lanes[port] != 1) { 2241 ability->speed_full_duplex |= SOC_PA_SPEED_40GB; 2242 } 2243 /* fall through */ 2244 case 25000: 2245 if (si->port_num_lanes[port] == 1) { 2246 ability->speed_full_duplex |= SOC_PA_SPEED_25GB; 2247 } 2248 /* fall through */ 2249 case 21000: 2250 case 20000: 2251 if (si->port_num_lanes[port] == 2) { 2252 ability->speed_full_duplex |= SOC_PA_SPEED_20GB; 2253 } 2254 /* fall through */ 2255 case 11000: 2256 case 10000: 2257 if (si->port_num_lanes[port] == 1) { 2258 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 2259 } 2260 /* fall through */ 2261 case 1000: 2262 if (si->port_num_lanes[port] == 1) { 2263 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 2264 } 2265 default: 2266 break; 2267 } 2268 } 2269 2270 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2271 (BSL_META_U(unit, 2272 "mac_cl_ability_local_get: unit %d port %s " 2273 "speed_half=0x%x speed_full=0x%x encap=0x%x pause=0x%x " 2274 "interface=0x%x medium=0x%x loopback=0x%x flags=0x%x\n"), 2275 unit, SOC_PORT_NAME(unit, port), 2276 ability->speed_half_duplex, ability->speed_full_duplex, 2277 ability->encap, ability->pause, ability->interface, 2278 ability->medium, ability->loopback, ability->flags)); 2279 return SOC_E_NONE; 2280 } 2281 2282 static int 2283 mac_cl_timesync_tx_info_get (int unit, soc_port_t port, 2284 soc_port_timesync_tx_info_t *tx_info) 2285 { 2286 uint64 rval; 2287 2288 SOC_IF_ERROR_RETURN 2289 (READ_CLMAC_TX_TIMESTAMP_FIFO_STATUSr(unit, port, &rval)); 2290 if (soc_reg64_field32_get(unit, CLMAC_TX_TIMESTAMP_FIFO_STATUSr, rval, 2291 ENTRY_COUNTf) == 0) { 2292 return SOC_E_EMPTY; 2293 } 2294 2295 SOC_IF_ERROR_RETURN 2296 (READ_CLMAC_TX_TIMESTAMP_FIFO_DATAr(unit, port, &rval)); 2297 tx_info->timestamps_in_fifo = soc_reg64_field32_get(unit, 2298 CLMAC_TX_TIMESTAMP_FIFO_DATAr, rval, TIME_STAMPf); 2299 2300 tx_info->timestamps_in_fifo_hi = 0; 2301 2302 tx_info->sequence_id = soc_reg64_field32_get(unit, 2303 CLMAC_TX_TIMESTAMP_FIFO_DATAr, rval, SEQUENCE_IDf); 2304 2305 return (SOC_E_NONE); 2306 } 2307 2308 2309 /* Exported CLMAC driver structure */ 2310 mac_driver_t soc_mac_cl = { 2311 "CLMAC Driver", /* drv_name */ 2312 mac_cl_init, /* md_init */ 2313 mac_cl_enable_set, /* md_enable_set */ 2314 mac_cl_enable_get, /* md_enable_get */ 2315 mac_cl_duplex_set, /* md_duplex_set */ 2316 mac_cl_duplex_get, /* md_duplex_get */ 2317 mac_cl_speed_set, /* md_speed_set */ 2318 mac_cl_speed_get, /* md_speed_get */ 2319 mac_cl_pause_set, /* md_pause_set */ 2320 mac_cl_pause_get, /* md_pause_get */ 2321 mac_cl_pause_addr_set, /* md_pause_addr_set */ 2322 mac_cl_pause_addr_get, /* md_pause_addr_get */ 2323 mac_cl_loopback_set, /* md_lb_set */ 2324 mac_cl_loopback_get, /* md_lb_get */ 2325 mac_cl_interface_set, /* md_interface_set */ 2326 mac_cl_interface_get, /* md_interface_get */ 2327 NULL, /* md_ability_get - Deprecated */ 2328 mac_cl_frame_max_set, /* md_frame_max_set */ 2329 mac_cl_frame_max_get, /* md_frame_max_get */ 2330 mac_cl_ifg_set, /* md_ifg_set */ 2331 mac_cl_ifg_get, /* md_ifg_get */ 2332 mac_cl_encap_set, /* md_encap_set */ 2333 mac_cl_encap_get, /* md_encap_get */ 2334 mac_cl_control_set, /* md_control_set */ 2335 mac_cl_control_get, /* md_control_get */ 2336 mac_cl_ability_local_get, /* md_ability_local_get */ 2337 mac_cl_timesync_tx_info_get /* md_timesync_tx_info_get */ 2338 }; 2339 2340 #endif /* BCM_CLMAC_SUPPORT */