unimac.c (89278B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * XGS 10/100/1000/2500 Megabit Media Access Controller Driver (unimac) 8 * 9 * This module is used for: 10 * 11 * - Gigabit ports on some XGS3 systems. 12 */ 13 14 #include <shared/bsl.h> 15 16 #include <sal/core/libc.h> 17 18 #include <soc/drv.h> 19 #include <soc/ll.h> 20 #include <soc/error.h> 21 #include <soc/portmode.h> 22 #include <soc/macutil.h> 23 #include <soc/phyctrl.h> 24 25 26 #ifdef BCM_UNIMAC_SUPPORT 27 28 #define JUMBO_MAXSZ 0x3fe8 29 30 /* 31 * Forward Declarations 32 */ 33 mac_driver_t soc_mac_uni; 34 35 #define SOC_UNIMAC_SPEED_10 0x0 36 #define SOC_UNIMAC_SPEED_100 0x1 37 #define SOC_UNIMAC_SPEED_1000 0x2 38 #define SOC_UNIMAC_SPEED_2500 0x3 39 40 /* EEE related defination */ 41 #define SOC_UNIMAC_MAX_EEE_SPEED 1000 42 43 /* Config value of LCCDRAIN_TIMEOUT_USEC. Default is 250000 usec. */ 44 STATIC int lcc_drain_timeout[SOC_MAX_NUM_DEVICES]; 45 46 #ifdef BROADCOM_DEBUG 47 static char *mac_uni_encap_mode[] = SOC_ENCAP_MODE_NAMES_INITIALIZER; 48 static char *mac_uni_port_if_names[] = SOC_PORT_IF_NAMES_INITIALIZER; 49 #endif /* BROADCOM_DEBUG */ 50 51 /* 52 * Function: 53 * _mac_uni_drain_cells 54 * Purpose: 55 * Wait until MMU cell count reaches zero for a specified port. 56 * Parameters: 57 * unit - StrataSwitch unit #. 58 * port - Port number being examined. 59 * Returns: 60 * SOC_E_XXX 61 * Notes: 62 * Keeps polling as long as LCCCOUNT/GCCCOUNT is decrementing. 63 * If LCCCOUNT/GCCCOUNT stops decrementing without reaching zero, 64 * after a timeout period a warning message is printed 65 * and it gives up. 66 * 67 * Before calling this routine, make sure no packets are switching 68 * to the port or it might never finish draining. 69 */ 70 71 STATIC int 72 _mac_uni_drain_cells(int unit, soc_port_t port) 73 { 74 int rv; 75 uint32 flush_ctrl; 76 int pause_tx, pause_rx; 77 #ifdef BCM_GREYHOUND_SUPPORT 78 uint32 mmu_fc = 0; 79 #endif 80 rv = SOC_E_NONE; 81 82 if (SOC_IS_RELOADING(unit)) { 83 return rv; 84 } 85 #if defined(BCM_KATANA_SUPPORT) 86 if (SOC_IS_KATANA(unit)) { 87 /* Drop out all packets in TX FIFO without egressing any packets */ 88 SOC_IF_ERROR_RETURN 89 (READ_FLUSH_CONTROLr(unit, port, &flush_ctrl)); 90 soc_reg_field_set(unit, FLUSH_CONTROLr, &flush_ctrl, FLUSHf, 1); 91 SOC_IF_ERROR_RETURN 92 (WRITE_FLUSH_CONTROLr(unit, port, flush_ctrl)); 93 LOG_VERBOSE(BSL_LS_SOC_COMMON, 94 (BSL_META_U(unit, 95 "port %d unimac TX fifo FLUSH_CONTROL.FLUSH set to 1\n"), port)); 96 } 97 #endif /* BCM_KATANA_SUPPORT */ 98 99 /* First put the port in flush state - the packets from the XQ of the 100 * port are purged after dequeue. */ 101 SOC_IF_ERROR_RETURN 102 (soc_mmu_flush_enable(unit, port, TRUE)); 103 LOG_VERBOSE(BSL_LS_SOC_COMMON, 104 (BSL_META_U(unit, 105 "port %d unimac mmu flush enable completed\n"), port)); 106 #ifdef BCM_GREYHOUND_SUPPORT 107 /* clear the MMU pause state*/ 108 if (SOC_REG_IS_VALID(unit, MMU_FC_RX_ENr)) { 109 SOC_IF_ERROR_RETURN( 110 READ_MMU_FC_RX_ENr(unit, port, &mmu_fc)); 111 SOC_IF_ERROR_RETURN( 112 WRITE_MMU_FC_RX_ENr(unit,port,0)); 113 } 114 #endif 115 /* Disable pause function */ 116 SOC_IF_ERROR_RETURN 117 (soc_mac_uni.md_pause_get(unit, port, &pause_tx, &pause_rx)); 118 SOC_IF_ERROR_RETURN 119 (soc_mac_uni.md_pause_set(unit, port, 0, 0)); 120 121 LOG_VERBOSE(BSL_LS_SOC_COMMON, 122 (BSL_META_U(unit, 123 "port %d unimac saved pause and pfc state\n"), port)); 124 125 if (!SOC_IS_KATANA(unit)) { 126 /* Drop out all packets in TX FIFO without egressing any packets */ 127 SOC_IF_ERROR_RETURN 128 (READ_FLUSH_CONTROLr(unit, port, &flush_ctrl)); 129 soc_reg_field_set(unit, FLUSH_CONTROLr, &flush_ctrl, FLUSHf, 1); 130 SOC_IF_ERROR_RETURN 131 (WRITE_FLUSH_CONTROLr(unit, port, flush_ctrl)); 132 LOG_VERBOSE(BSL_LS_SOC_COMMON, 133 (BSL_META_U(unit, 134 "port %d unimac TX fifo FLUSH_CONTROL.FLUSH set to 1\n"), port)); 135 } 136 /* Notify PHY driver */ 137 SOC_IF_ERROR_RETURN 138 (soc_phyctrl_notify(unit, port, 139 phyEventStop, PHY_STOP_DRAIN)); 140 141 /* Disable switch egress metering so that packet draining is not rate 142 * limited. 143 */ 144 rv = soc_egress_drain_cells(unit, port, lcc_drain_timeout[unit]); 145 if (SOC_E_NONE == rv) { 146 LOG_VERBOSE(BSL_LS_SOC_COMMON, 147 (BSL_META_U(unit, 148 "port %d unimac egress packet draining completed\n"), 149 port)); 150 } 151 152 /* Notify PHY driver */ 153 SOC_IF_ERROR_RETURN 154 (soc_phyctrl_notify(unit, port, 155 phyEventResume, PHY_STOP_DRAIN)); 156 157 /* Soft-reset is recommended here. 158 * SOC_IF_ERROR_RETURN 159 * (soc_mac_uni.md_control_set(unit, port, SOC_MAC_CONTROL_SW_RESET, 160 * TRUE)); 161 * SOC_IF_ERROR_RETURN 162 * (soc_mac_uni.md_control_set(unit, port, SOC_MAC_CONTROL_SW_RESET, 163 * FALSE)); 164 */ 165 166 /* Bring the TxFifo out of flush */ 167 soc_reg_field_set(unit, FLUSH_CONTROLr, &flush_ctrl, FLUSHf, 0); 168 SOC_IF_ERROR_RETURN 169 (WRITE_FLUSH_CONTROLr(unit, port, flush_ctrl)); 170 LOG_VERBOSE(BSL_LS_SOC_COMMON, 171 (BSL_META_U(unit, 172 "port %d unimac TX fifo FLUSH_CONTROL.FLUSH set to 0\n"), port)); 173 174 175 #ifdef BCM_GREYHOUND_SUPPORT 176 /* restore the MMU pause state*/ 177 if (SOC_REG_IS_VALID(unit, MMU_FC_RX_ENr)) { 178 SOC_IF_ERROR_RETURN( 179 WRITE_MMU_FC_RX_ENr(unit, port, mmu_fc)); 180 } 181 #endif 182 183 /* Restore original pause configuration */ 184 SOC_IF_ERROR_RETURN 185 (soc_mac_uni.md_pause_set(unit, port, pause_tx, pause_rx)); 186 187 #if defined(BCM_KATANA_SUPPORT) 188 if (SOC_IS_KATANA(unit)) { 189 LOG_VERBOSE(BSL_LS_SOC_COMMON, 190 (BSL_META_U(unit, 191 "KATANA port %d mmu flush disable will be invoked during port re-enable"), 192 port)); 193 } else 194 #endif 195 { 196 /* Bring the switch MMU out of flush */ 197 SOC_IF_ERROR_RETURN 198 (soc_mmu_flush_enable(unit, port, FALSE)); 199 LOG_VERBOSE(BSL_LS_SOC_COMMON, 200 (BSL_META_U(unit, 201 "port %d unimac mmu flush disabled\n"), port)); 202 } 203 return rv; 204 } 205 206 /* 207 * Function: 208 * mac_uni_init 209 * Purpose: 210 * Initialize UniMAC into a known good state. 211 * Parameters: 212 * unit - StrataSwitch unit #. 213 * port - StrataSwitch port # on unit. 214 * Returns: 215 * SOC_E_XXX 216 * Notes: 217 * The initialization speed/duplex is arbitrary and must be 218 * updated by linkscan before enabling the MAC. 219 */ 220 221 STATIC int 222 mac_uni_init(int unit, soc_port_t port) 223 { 224 uint32 command_config, ocommand_config, speed, rval32; 225 int frame_max; 226 int ignore_pause; 227 228 LOG_VERBOSE(BSL_LS_SOC_GE, 229 (BSL_META_U(unit, 230 "mac_uni_init: unit %d port %s\n"), 231 unit, SOC_PORT_NAME(unit, port))); 232 233 /* Get MAC configurations from config settings. */ 234 lcc_drain_timeout[unit] = soc_property_get(unit, spn_LCCDRAIN_TIMEOUT_USEC, 235 250000); 236 SOC_IF_ERROR_RETURN 237 (soc_port_blk_init(unit, port)); 238 239 frame_max = IS_ST_PORT(unit, port) ? JUMBO_MAXSZ : 1518; 240 241 soc_mac_uni.md_frame_max_set(unit, port, frame_max); 242 243 /* First put the MAC in reset and sleep */ 244 SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port, 245 SOC_MAC_CONTROL_SW_RESET, 246 TRUE)); 247 248 /* Do the initialization */ 249 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 250 ocommand_config = command_config; 251 252 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, TX_ENAf, 0); 253 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ENAf, 0); 254 speed = IS_FE_PORT(unit, port) ? SOC_UNIMAC_SPEED_100 : SOC_UNIMAC_SPEED_1000; 255 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, ETH_SPEEDf, 256 speed); 257 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PROMIS_ENf, 1); 258 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PAD_ENf, 0); 259 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, CRC_FWDf, 1); 260 #ifdef BCM_SHADOW_SUPPORT 261 if (SOC_IS_SHADOW(unit)) { 262 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PAD_ENf, 1); 263 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, CRC_FWDf, 0); 264 /* Quickfix - Enable external config for SGMII mode in shadow */ 265 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, 266 ENA_EXT_CONFIGf, 1); 267 } 268 #endif 269 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PAUSE_FWDf, 0); 270 271 /* Ignore pause if using as stack port */ 272 ignore_pause = IS_ST_PORT(unit, port) ? 1 : 0; 273 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PAUSE_IGNOREf, 274 ignore_pause); 275 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, IGNORE_TX_PAUSEf, 276 ignore_pause); 277 278 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, TX_ADDR_INSf, 0); 279 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, HD_ENAf, 0); 280 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, LOOP_ENAf, 0); 281 282 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, CNTL_FRM_ENAf, 0); 283 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, NO_LGTH_CHECKf, 284 1); 285 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, LINE_LOOPBACKf, 286 0); 287 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ERR_DISCf, 0); 288 if (soc_reg_field_valid(unit, COMMAND_CONFIGr, PRBL_ENAf)) { 289 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, PRBL_ENAf, 0); 290 } 291 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, CNTL_FRM_ENAf, 1); 292 293 /* For Hawkeye, let the bit ENA_EXT_CONFIG to stay the default value 294 * without changing by S/W. 295 * It is same as unmanaged mode and suggested by design team during 296 * bringup. 297 */ 298 if(!SOC_IS_HAWKEYE(unit)) { 299 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, 300 ENA_EXT_CONFIGf, 301 PHY_SGMII_AUTONEG_MODE(unit, port) ? 1 : 0); 302 } 303 304 if (PHY_SGMII_AUTONEG_MODE(unit, port) && 305 soc_reg_field_valid(unit,COMMAND_CONFIGr,SW_OVERRIDE_RXf) && 306 soc_reg_field_valid(unit,COMMAND_CONFIGr,SW_OVERRIDE_TXf)) { 307 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, 308 SW_OVERRIDE_RXf, 1); 309 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, 310 SW_OVERRIDE_TXf, 1); 311 } 312 313 if (ocommand_config != command_config) { 314 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config)); 315 } 316 317 /* Initialize mask for purging packet data received from the MAC */ 318 SOC_IF_ERROR_RETURN(soc_packet_purge_control_init(unit, port)); 319 320 /* Bring the UniMAC out of reset */ 321 SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port, 322 SOC_MAC_CONTROL_SW_RESET, 323 FALSE)); 324 325 /* Pulse the Serdes AN if using auto_cfg mode */ 326 if (PHY_SGMII_AUTONEG_MODE(unit, port)) { 327 SOC_IF_ERROR_RETURN 328 (soc_phyctrl_notify(unit, port, phyEventAutoneg, 0)); 329 SOC_IF_ERROR_RETURN 330 (soc_phyctrl_notify(unit, port, phyEventAutoneg, 1)); 331 } 332 333 rval32 = 0; 334 soc_reg_field_set(unit, PAUSE_CONTROLr, &rval32, ENABLEf, 1); 335 336 if (soc_feature(unit, soc_feature_pause_control_update)) { 337 soc_reg_field_set(unit, PAUSE_CONTROLr, &rval32, VALUEf, 0xc000); 338 } else { 339 soc_reg_field_set(unit, PAUSE_CONTROLr, &rval32, VALUEf, 0x1ffff); 340 } 341 342 SOC_IF_ERROR_RETURN(WRITE_PAUSE_CONTROLr(unit, port, rval32)); 343 344 SOC_IF_ERROR_RETURN(WRITE_PAUSE_QUANTr(unit, port, 0xffff)); 345 346 if (SOC_REG_IS_VALID(unit, MAC_PFC_REFRESH_CTRLr)) { 347 soc_field_t fields[] = { PFC_REFRESH_ENf, PFC_REFRESH_TIMERf }; 348 uint32 values[] = { 1, 0xc000 }; 349 SOC_IF_ERROR_RETURN 350 (soc_reg_fields32_modify(unit, MAC_PFC_REFRESH_CTRLr, port, 2, 351 fields, values)); 352 } 353 354 SOC_IF_ERROR_RETURN(WRITE_TX_IPG_LENGTHr(unit, port, 12)); 355 356 /* Set egress enable */ 357 SOC_IF_ERROR_RETURN 358 (soc_egress_enable(unit, port, TRUE)); 359 360 /* assigning proper setting for EEE feature : 361 * Note : 362 * - GE speed force assigned for timer setting 363 */ 364 if (soc_feature(unit, soc_feature_eee)) { 365 SOC_IF_ERROR_RETURN(soc_port_eee_timers_init(unit, 366 port, SOC_UNIMAC_MAX_EEE_SPEED)); 367 } 368 369 return SOC_E_NONE; 370 } 371 372 /* 373 * Function: 374 * mac_uni_enable_set 375 * Purpose: 376 * Enable or disable MAC 377 * Parameters: 378 * unit - StrataSwitch unit #. 379 * port - Port number on unit. 380 * enable - TRUE to enable, FALSE to disable 381 * Returns: 382 * SOC_E_XXX 383 */ 384 385 STATIC int 386 mac_uni_enable_set(int unit, soc_port_t port, int enable) 387 { 388 uint32 command_config, tx_ena, rx_ena; 389 pbmp_t mask; 390 uint32 version, merge_config; 391 int unimac_version; 392 393 LOG_VERBOSE(BSL_LS_SOC_GE, 394 (BSL_META_U(unit, 395 "mac_uni_enable_set: unit %d port %s enable=%s\n"), 396 unit, SOC_PORT_NAME(unit, port), 397 enable ? "True" : "False")); 398 399 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 400 tx_ena = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, TX_ENAf); 401 rx_ena = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, RX_ENAf); 402 403 /* We have seen instances when there are a flurry of disable/enable calls 404 where the TX_ENA and RX_ENA are set, but the mask2 bit is clear for the port. 405 This resulted in the MAC not actually being enabled for the port. The logic 406 below ensures that we consider the membership of the mask2 bitmap before 407 returning early. */ 408 soc_link_mask2_get(unit, &mask); 409 if ((tx_ena == rx_ena) && 410 (tx_ena == (enable ? 1 : 0)) && 411 (enable ? SOC_PBMP_MEMBER(mask, port) : !SOC_PBMP_MEMBER(mask, port))) { 412 return SOC_E_NONE; 413 } 414 415 /* First put the MAC in reset */ 416 SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port, 417 SOC_MAC_CONTROL_SW_RESET, 418 TRUE)); 419 420 /* de-assert RX_ENA and TX_ENA */ 421 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_RESETf, 1); 422 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, TX_ENAf, 0); 423 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ENAf, 0); 424 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config)); 425 sal_udelay(2); 426 427 /* Bring the MAC out of reset */ 428 SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port, 429 SOC_MAC_CONTROL_SW_RESET, 430 FALSE)); 431 432 if (!enable) { 433 if (soc_feature(unit, soc_feature_unimac_reset_wo_clock)) { 434 SOC_IF_ERROR_RETURN 435 (soc_pgw_rx_fifo_reset(unit, port, TRUE)); 436 } 437 438 soc_link_mask2_get(unit, &mask); 439 SOC_PBMP_PORT_REMOVE(mask, port); 440 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 441 /* 442 * Disable MMU port 443 * for some devices where EPC_LINK can not block the SOBMH from cpu and 444 * no mechanism is avalible to reset EDATABUF. 445 */ 446 SOC_IF_ERROR_RETURN(soc_port_mmu_buffer_enable(unit, port, FALSE)); 447 448 SOC_IF_ERROR_RETURN(_mac_uni_drain_cells(unit, port)); 449 SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port, 450 SOC_MAC_CONTROL_SW_RESET, 451 TRUE)); 452 SOC_IF_ERROR_RETURN(soc_phyctrl_notify(unit, port, phyEventStop, 453 PHY_STOP_MAC_DIS)); 454 /* Drop incoming packets from this port in the ingress pipeline */ 455 if (SOC_REG_IS_VALID(unit, PKT_DROP_ENABLEr) && 456 !(SOC_IS_SC_CQ(unit) && 457 (SOC_PORT_BLOCK_TYPE(unit, port) == SOC_BLK_QGPORT)) && 458 !(SOC_IS_ENDURO(unit) && 459 (SOC_PORT_BLOCK_TYPE(unit, port) == SOC_BLK_GPORT)) && 460 !(SOC_IS_HURRICANE(unit) && 461 (SOC_PORT_BLOCK_TYPE(unit, port) == SOC_BLK_GPORT))) { 462 SOC_IF_ERROR_RETURN(WRITE_PKT_DROP_ENABLEr(unit, port, 1)); 463 } 464 465 /* Forces rx_lost_eop sequence */ 466 if (SOC_REG_IS_VALID(unit, UMAC_REV_IDr) && 467 SOC_REG_IS_VALID(unit, MAC_MERGE_CONFIGr)) { 468 469 SOC_IF_ERROR_RETURN(READ_UMAC_REV_IDr(unit, port, &version)); 470 unimac_version = 471 soc_reg_field_get( 472 unit, UMAC_REV_IDr, version, REVISION_ID_MAJORf); 473 if (unimac_version == 4) { 474 /* Set SW force */ 475 SOC_IF_ERROR_RETURN( 476 READ_MAC_MERGE_CONFIGr(unit, port, &merge_config)); 477 soc_reg_field_set( 478 unit, MAC_MERGE_CONFIGr, &merge_config, 479 SW_FORCE_RX_LOST_EOPf, 1); 480 SOC_IF_ERROR_RETURN( 481 WRITE_MAC_MERGE_CONFIGr(unit, port, merge_config)); 482 483 /* Clear SW force */ 484 SOC_IF_ERROR_RETURN( 485 READ_MAC_MERGE_CONFIGr(unit, port, &merge_config)); 486 soc_reg_field_set( 487 unit, MAC_MERGE_CONFIGr, &merge_config, 488 SW_FORCE_RX_LOST_EOPf, 0); 489 SOC_IF_ERROR_RETURN( 490 WRITE_MAC_MERGE_CONFIGr(unit, port, merge_config)); 491 } 492 } 493 } else { 494 /* Stop the ingress pipeline from dropping packets from this port */ 495 #if defined(BCM_KATANA_SUPPORT) 496 if (SOC_IS_KATANA(unit)) { 497 SOC_IF_ERROR_RETURN 498 (soc_mmu_flush_enable(unit, port, FALSE)); 499 } 500 #endif 501 if (SOC_REG_IS_VALID(unit, PKT_DROP_ENABLEr) && 502 !(SOC_IS_SC_CQ(unit) && 503 (SOC_PORT_BLOCK_TYPE(unit, port) == SOC_BLK_QGPORT)) && 504 !(SOC_IS_ENDURO(unit) && 505 (SOC_PORT_BLOCK_TYPE(unit, port) == SOC_BLK_GPORT)) && 506 !(SOC_IS_HURRICANE(unit) && 507 (SOC_PORT_BLOCK_TYPE(unit, port) == SOC_BLK_GPORT))) { 508 SOC_IF_ERROR_RETURN(WRITE_PKT_DROP_ENABLEr(unit, port, 0)); 509 } 510 #if defined(BCM_SCORPION_SUPPORT) 511 if (soc_feature(unit, soc_feature_priority_flow_control)) { 512 /* Flush MMU XOFF state with toggle bit */ 513 if (SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) { 514 SOC_IF_ERROR_RETURN 515 (soc_reg_field32_modify(unit, UNIMAC_PFC_CTRLr, port, 516 FORCE_PFC_XONf, 1)); 517 SOC_IF_ERROR_RETURN 518 (soc_reg_field32_modify(unit, UNIMAC_PFC_CTRLr, port, 519 FORCE_PFC_XONf, 0)); 520 } 521 } 522 #endif /* BCM_SCORPION_SUPPORT */ 523 /* if it is to enable, assert RX_ENA and TX_ENA */ 524 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_RESETf, 525 0); 526 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, TX_ENAf, 1); 527 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ENAf, 1); 528 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config)); 529 sal_udelay(2); 530 531 /* Enable MMU port */ 532 SOC_IF_ERROR_RETURN(soc_port_mmu_buffer_enable(unit, port, TRUE)); 533 534 soc_link_mask2_get(unit, &mask); 535 SOC_PBMP_PORT_ADD(mask, port); 536 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 537 SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port, 538 SOC_MAC_CONTROL_SW_RESET, 539 TRUE)); 540 SOC_IF_ERROR_RETURN(soc_phyctrl_notify(unit, port, phyEventResume, 541 PHY_STOP_MAC_DIS)); 542 SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port, 543 SOC_MAC_CONTROL_SW_RESET, 544 FALSE)); 545 546 if (soc_feature(unit, soc_feature_unimac_reset_wo_clock)) { 547 SOC_IF_ERROR_RETURN 548 (soc_pgw_rx_fifo_reset(unit, port, FALSE)); 549 } 550 } 551 552 return SOC_E_NONE; 553 } 554 555 /* 556 * Function: 557 * mac_uni_enable_get 558 * Purpose: 559 * Get UniMAC enable state 560 * Parameters: 561 * unit - StrataSwitch unit #. 562 * port - Port number on unit. 563 * enable - (OUT) TRUE if enabled, FALSE if disabled 564 * Returns: 565 * SOC_E_XXX 566 */ 567 568 STATIC int 569 mac_uni_enable_get(int unit, soc_port_t port, int *enable) 570 { 571 uint32 command_config; 572 573 SOC_IF_ERROR_RETURN 574 (READ_COMMAND_CONFIGr(unit, port, &command_config)); 575 576 *enable = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, 577 RX_ENAf); 578 579 LOG_VERBOSE(BSL_LS_SOC_GE, 580 (BSL_META_U(unit, 581 "mac_uni_enable_get: unit %d port %s enable=%s\n"), 582 unit, SOC_PORT_NAME(unit, port), 583 *enable ? "True" : "False")); 584 return SOC_E_NONE; 585 } 586 587 588 #if defined(BCM_KATANA_SUPPORT) 589 /* 590 * Function: 591 * _mac_uni_timestamp_delay_set 592 * Purpose: 593 * Set Timestamp delay for one-step to account for lane and pipeline delay. 594 * Parameters: 595 * unit - Switch unit #. 596 * port - Port number on unit. 597 * Returns: 598 * SOC_E_XXX 599 */ 600 STATIC int 601 _mac_uni_timestamp_delay_set(int unit, soc_port_t port, int speed) 602 { 603 uint32 ctrl; 604 int ts_adjust; 605 uint32 field; 606 LOG_VERBOSE(BSL_LS_SOC_GE, 607 (BSL_META_U(unit, 608 "mac_uni_timestamp_delay_set: unit %d port %s speed %d\n"), 609 unit, SOC_PORT_NAME(unit, port), speed)); 610 /* 611 * KT-1379 : UniMAC Rx pipeline delay accounting on Tx path 612 * can cause issue for asymmetric paths/ speeds 613 * UMAC_TIMESTAMP_ADJUST.AUTO_ADJUST programmed to 0. 614 * Per-ingress port EGR_1588_LINK_DELAY.LINK_DELAY registers. 615 * - MACRxPipelineDelay(1000M ingress speed) = 232ns 616 * - MACRxPipelineDelay(100M ingress speed) = 2320ns 617 * - MACRxPipelineDelay(10M ingress speed) = 23200ns 618 */ 619 620 if (SOC_REG_IS_VALID(unit, UMAC_TIMESTAMP_ADJUSTr)) { 621 ts_adjust = soc_property_port_get(unit, port, spn_TIMESTAMP_ADJUST(speed), 0); 622 623 if (SOC_E_NONE != soc_reg_signed_field_mask(unit, UMAC_TIMESTAMP_ADJUSTr, 624 ADJUSTf, ts_adjust, &field)) { 625 LOG_WARN(BSL_LS_SOC_PORT, (BSL_META_U(unit, 626 "%s property out of bounds (is %d)\n"), 627 spn_TIMESTAMP_ADJUST(speed), ts_adjust)); 628 field = 0; 629 } 630 SOC_IF_ERROR_RETURN(READ_UMAC_TIMESTAMP_ADJUSTr(unit, port, &ctrl)); 631 soc_reg_field_set(unit, UMAC_TIMESTAMP_ADJUSTr, &ctrl, 632 AUTO_ADJUSTf, 0 ); 633 soc_reg_field_set(unit, UMAC_TIMESTAMP_ADJUSTr, &ctrl, 634 ADJUSTf, ts_adjust); 635 SOC_IF_ERROR_RETURN(WRITE_UMAC_TIMESTAMP_ADJUSTr(unit, port, ctrl)); 636 } 637 638 return SOC_E_NONE; 639 } 640 #endif /* defined(BCM_KATANA_SUPPORT) */ 641 642 /* 643 * Function: 644 * mac_uni_ifg_to_ipg 645 * Description: 646 * Converts the inter-frame gap specified in bit-times into a value 647 * suitable to be programmed into the IPG register 648 * Parameters: 649 * unit - Device number 650 * port - Port number 651 * speed - the speed for which the IFG is being set 652 * duplex - the duplex for which the IFG is being set 653 * ifg - Inter-frame gap in bit-times 654 * ipg - (OUT) the value to be written into IPG 655 * Return Value: 656 * BCM_E_XXX 657 * Notes: 658 * The function makes sure the calculated IPG value will not cause 659 * hardware to fail. If the requested ifg value cannot be supported in 660 * hardware, the function will choose a value that approximates the 661 * requested value as best as possible. 662 * 663 * Specifically: 664 * -- Current chips only support ifg which is divisible by 8. If 665 * the specified ifg is not divisible by 8, it will be rounded 666 * to the next multiplier of 8 (65 will result in 72). 667 * -- ifg < 64 are not supported 668 * 669 * This function supports only GE portion of GE MAC (FE portion is 670 * supported by mac_fe_ipg_* functions 671 */ 672 STATIC int 673 mac_uni_ifg_to_ipg(int unit, soc_port_t port, int speed, int duplex, 674 int ifg, int *ipg) 675 { 676 int real_ifg; 677 678 /* 679 * Silently adjust the specified ifp bits to valid value 680 * - valid value: 8 to 64 bytes (i.e. multiple of 8 bits) 681 */ 682 real_ifg = ifg < 64 ? 64 : (ifg > 512 ? 512 : (ifg + 7) & (0x7f << 3)); 683 *ipg = real_ifg / 8; 684 685 return SOC_E_NONE; 686 } 687 688 /* 689 * Function: 690 * mac_uni_ipg_to_ifg 691 * Description: 692 * Converts the IPG register value into the inter-frame gap expressed in 693 * bit-times 694 * Parameters: 695 * unit - Device number 696 * port - Port number 697 * speed - the speed for which the IFG is being set 698 * duplex - the duplex for which the IFG is being set 699 * ipg - the value in the IPG register 700 * ifg - Inter-frame gap in bit-times 701 * Return Value: 702 * BCM_E_XXX 703 * Notes: 704 * This function supports only GE portion of GE MAC (FE portion is 705 * supported by mac_fe_ipg_* functions 706 */ 707 STATIC int 708 mac_uni_ipg_to_ifg(int unit, soc_port_t port, int speed, int duplex, 709 int ipg, int *ifg) 710 { 711 /* 712 * Now we need to convert the value according to various chips' 713 * peculiarities (there are none as of now) 714 */ 715 *ifg = ipg * 8; 716 717 return SOC_E_NONE; 718 } 719 720 /* 721 * Function: 722 * mac_uni_ipg_update 723 * Purpose: 724 * Set the IPG appropriate for current duplex 725 * Parameters: 726 * unit - StrataSwitch unit #. 727 * port - Port number on unit. 728 * Notes: 729 * The current duplex is read from the hardware registers. 730 */ 731 732 STATIC int 733 mac_uni_ipg_update(int unit, int port) 734 { 735 int fd, speed, ipg, ifg; 736 uint32 rval; 737 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 738 739 SOC_IF_ERROR_RETURN(soc_mac_uni.md_duplex_get(unit, port, &fd)); 740 SOC_IF_ERROR_RETURN(soc_mac_uni.md_speed_get(unit, port, &speed)); 741 742 if (fd) { 743 switch (speed) { 744 case 10: 745 ifg = si->fd_10; 746 break; 747 case 100: 748 ifg = si->fd_100; 749 break; 750 case 1000: 751 ifg = si->fd_1000; 752 break; 753 case 2500: 754 ifg = si->fd_2500; 755 break; 756 default: 757 return SOC_E_INTERNAL; 758 break; 759 } 760 } else { 761 switch (speed) { 762 case 10: 763 ifg = si->hd_10; 764 break; 765 case 100: 766 ifg = si->hd_100; 767 break; 768 default: 769 return SOC_E_INTERNAL; 770 break; 771 } 772 } 773 774 /* 775 * Convert the ifg value from bit-times into IPG register-specific value 776 */ 777 SOC_IF_ERROR_RETURN(mac_uni_ifg_to_ipg(unit, port, speed, fd, ifg, &ipg)); 778 779 /* 780 * Program the appropriate register 781 */ 782 SOC_IF_ERROR_RETURN 783 (WRITE_TX_IPG_LENGTHr(unit, port, ipg)); 784 785 /* Do not process any packets that have less than 8 bytes IPG */ 786 SOC_IF_ERROR_RETURN(READ_IPG_HD_BKP_CNTLr(unit, port, &rval)); 787 soc_reg_field_set(unit, IPG_HD_BKP_CNTLr, &rval, IPG_CONFIG_RXf, 788 speed > 1000 ? 5 : speed == 1000 ? 6 : 12); 789 SOC_IF_ERROR_RETURN(WRITE_IPG_HD_BKP_CNTLr(unit, port, rval)); 790 791 return SOC_E_NONE; 792 } 793 794 /* 795 * Function: 796 * mac_uni_duplex_set 797 * Purpose: 798 * Set UniMAC in the specified duplex mode. 799 * Parameters: 800 * unit - StrataSwitch unit #. 801 * port - StrataSwitch port # on unit. 802 * duplex - Boolean: true --> full duplex, false --> half duplex. 803 * Returns: 804 * SOC_E_XXX 805 * Notes: 806 * Programs an IFG time appropriate to speed and duplex. 807 */ 808 809 STATIC int 810 mac_uni_duplex_set(int unit, soc_port_t port, int duplex) 811 { 812 uint32 command_config, ocommand_config; 813 int speed; 814 815 LOG_VERBOSE(BSL_LS_SOC_GE, 816 (BSL_META_U(unit, 817 "mac_uni_duplex_set: unit %d port %s duplex=%s\n"), 818 unit, SOC_PORT_NAME(unit, port), 819 duplex ? "Full" : "Half")); 820 821 if (PHY_SGMII_AUTONEG_MODE(unit, port)) { 822 return SOC_E_NONE; 823 } 824 825 SOC_IF_ERROR_RETURN(soc_mac_uni.md_speed_get(unit, port, &speed)); 826 827 if (speed >= 1000) { 828 /* 829 * program the bit full-duplex for speed 1000 or 2500Mbps. 830 */ 831 duplex = 1; 832 } 833 834 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 835 ocommand_config = command_config; 836 837 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, HD_ENAf, 838 duplex ? 0 : 1); 839 if (command_config == ocommand_config) { 840 return SOC_E_NONE; 841 } 842 843 /* First put the MAC in reset */ 844 SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port, 845 SOC_MAC_CONTROL_SW_RESET, 846 TRUE)); 847 848 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_RESETf, 1); 849 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config)); 850 851 /* Set IPG to match new duplex */ 852 SOC_IF_ERROR_RETURN(mac_uni_ipg_update(unit, port)); 853 854 /* 855 * Notify internal PHY driver of duplex change in case it is being 856 * used as pass-through to an external PHY. 857 */ 858 SOC_IF_ERROR_RETURN 859 (soc_phyctrl_notify(unit, port, phyEventDuplex, duplex)); 860 861 /* Bring the MAC out of reset */ 862 SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port, 863 SOC_MAC_CONTROL_SW_RESET, 864 FALSE)); 865 866 return SOC_E_NONE; 867 } 868 869 /* 870 * Function: 871 * mac_uni_duplex_get 872 * Purpose: 873 * Get UniMAC duplex mode. 874 * Parameters: 875 * unit - StrataSwitch unit #. 876 * port - StrataSwitch port # on unit. 877 * duplex - (OUT) Boolean: true --> full duplex, false --> half duplex. 878 * Returns: 879 * SOC_E_XXX 880 */ 881 882 STATIC int 883 mac_uni_duplex_get(int unit, soc_port_t port, int *duplex) 884 { 885 uint32 command_config; 886 int speed; 887 888 SOC_IF_ERROR_RETURN(soc_mac_uni.md_speed_get(unit, port, &speed)); 889 890 if ((1000 == speed) || (2500 == speed)) { 891 *duplex = TRUE; 892 } else { 893 SOC_IF_ERROR_RETURN 894 (READ_COMMAND_CONFIGr(unit, port, &command_config)); 895 896 *duplex = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, 897 HD_ENAf) ? FALSE : TRUE; 898 } 899 900 LOG_VERBOSE(BSL_LS_SOC_GE, 901 (BSL_META_U(unit, 902 "mac_uni_duplex_get: unit %d port %s duplex=%s\n"), 903 unit, SOC_PORT_NAME(unit, port), 904 *duplex ? "Full" : "Half")); 905 return SOC_E_NONE; 906 } 907 908 /* 909 * Function: 910 * mac_uni_speed_set 911 * Purpose: 912 * Set UniMAC in the specified speed. 913 * Parameters: 914 * unit - StrataSwitch unit #. 915 * port - Port number on unit. 916 * speed - 10,100,1000, 2500 for speed. 917 * Returns: 918 * SOC_E_XXX 919 * Notes: 920 * Programs an IFG time appropriate to speed and duplex. 921 */ 922 923 STATIC int 924 mac_uni_speed_set(int unit, soc_port_t port, int speed) 925 { 926 uint32 command_config; 927 int speed_select; 928 uint32 cur_speed; 929 930 LOG_VERBOSE(BSL_LS_SOC_GE, 931 (BSL_META_U(unit, 932 "mac_uni_speed_set: unit %d port %s speed=%dMb\n"), 933 unit, SOC_PORT_NAME(unit, port), 934 speed)); 935 936 if (PHY_SGMII_AUTONEG_MODE(unit, port)) { 937 return SOC_E_NONE; 938 } 939 940 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 941 cur_speed = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, 942 ETH_SPEEDf); 943 944 switch (speed) { 945 case 10: 946 speed_select = SOC_UNIMAC_SPEED_10; 947 break; 948 /* support non-standard speed in Broadreach mode */ 949 case 20: 950 case 25: 951 case 33: 952 case 50: 953 /* fall through to case 100 */ 954 case 100: 955 speed_select = SOC_UNIMAC_SPEED_100; 956 break; 957 case 1000: 958 speed_select = SOC_UNIMAC_SPEED_1000; 959 break; 960 case 2500: 961 speed_select = SOC_UNIMAC_SPEED_2500; 962 break; 963 case 0: 964 return (SOC_E_NONE); /* Support NULL PHY */ 965 default: 966 return (SOC_E_CONFIG); 967 } 968 969 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, 970 ETH_SPEEDf, speed_select); 971 972 /* First reset the MAC */ 973 SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port, 974 SOC_MAC_CONTROL_SW_RESET, 975 TRUE)); 976 977 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_RESETf, 1); 978 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config)); 979 980 /* 981 * Notify internal PHY driver of speed change in case it is being 982 * used as pass-through to an external PHY. 983 */ 984 if (! PHY_REPEATER(unit, port)) { 985 SOC_IF_ERROR_RETURN 986 (soc_phyctrl_notify(unit, port, phyEventSpeed, speed)); 987 } 988 989 /* Set IPG to match new speed */ 990 SOC_IF_ERROR_RETURN(mac_uni_ipg_update(unit, port)); 991 992 993 /* Bring the MAC out of reset */ 994 SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port, 995 SOC_MAC_CONTROL_SW_RESET, 996 FALSE)); 997 998 /* MAC speed switch results in a tx clock glitch to the serdes in 100fx mode. 999 * reset serdes txfifo clears this condition. However this reset triggers 1000 * a link transition. Do not apply this reset if speed is already in 100M 1001 */ 1002 if ((speed == 100) && (cur_speed != SOC_UNIMAC_SPEED_100)) { 1003 (void)soc_phyctrl_notify(unit, port, phyEventTxFifoReset, 100); 1004 } 1005 1006 #if defined(BCM_KATANA_SUPPORT) 1007 /* Set unimac timestamp delay */ 1008 if (SOC_IS_KATANAX(unit)) { 1009 SOC_IF_ERROR_RETURN(_mac_uni_timestamp_delay_set(unit,port,speed)); 1010 } 1011 #endif 1012 return (SOC_E_NONE); 1013 } 1014 1015 /* 1016 * Function: 1017 * mac_uni_speed_get 1018 * Purpose: 1019 * Get GE MAC speed 1020 * Parameters: 1021 * unit - StrataSwitch unit #. 1022 * port - Port number on unit. 1023 * speed - (OUT) speed in Mb (10/100/1000) 1024 * Returns: 1025 * SOC_E_NONE 1026 */ 1027 1028 STATIC int 1029 mac_uni_speed_get(int unit, soc_port_t port, int *speed) 1030 { 1031 uint32 command_config, uni_speed; 1032 int rv = SOC_E_NONE; 1033 1034 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 1035 1036 uni_speed = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, 1037 ETH_SPEEDf); 1038 1039 switch(uni_speed) { 1040 case SOC_UNIMAC_SPEED_10: 1041 *speed = 10; 1042 break; 1043 case SOC_UNIMAC_SPEED_100: 1044 *speed = 100; 1045 break; 1046 case SOC_UNIMAC_SPEED_1000: 1047 *speed = 1000; 1048 break; 1049 case SOC_UNIMAC_SPEED_2500: 1050 *speed = 2500; 1051 break; 1052 default: 1053 rv = SOC_E_INTERNAL; 1054 } 1055 1056 LOG_VERBOSE(BSL_LS_SOC_GE, 1057 (BSL_META_U(unit, 1058 "mac_uni_speed_get: unit %d port %s speed=%dMb\n"), 1059 unit, SOC_PORT_NAME(unit, port), 1060 *speed)); 1061 return(rv); 1062 } 1063 1064 /* 1065 * Function: 1066 * mac_uni_pause_set 1067 * Purpose: 1068 * Configure UniMAC to transmit/receive pause frames. 1069 * Parameters: 1070 * unit - StrataSwitch unit #. 1071 * port - StrataSwitch port # on unit. 1072 * pause_tx - Boolean: transmit pause, or -1 (don't change) 1073 * pause_rx - Boolean: receive pause, or -1 (don't change) 1074 * Returns: 1075 * SOC_E_XXX 1076 */ 1077 1078 STATIC int 1079 mac_uni_pause_set(int unit, soc_port_t port, int pause_tx, int pause_rx) 1080 { 1081 uint32 command_config, ocommand_config; 1082 1083 LOG_VERBOSE(BSL_LS_SOC_GE, 1084 (BSL_META_U(unit, 1085 "mac_uni_pause_set: unit %d port %s RX=%s TX=%s\n"), 1086 unit, SOC_PORT_NAME(unit, port), 1087 pause_rx ? "on" : "off", 1088 pause_tx ? "on" : "off")); 1089 1090 if (pause_tx < 0 && pause_rx < 0) { 1091 return SOC_E_NONE; 1092 } 1093 1094 if (IS_ST_PORT(unit, port)) { 1095 if ((pause_tx == 0) && (pause_rx == 0)) { 1096 return SOC_E_NONE; 1097 } else { 1098 /* Flow control cannot be enabled in HiGL mode */ 1099 return SOC_E_CONFIG; 1100 } 1101 } 1102 1103 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 1104 ocommand_config = command_config; 1105 1106 if (pause_rx >= 0) { 1107 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, 1108 PAUSE_IGNOREf, pause_rx ? 0 : 1); 1109 } 1110 if (pause_tx >= 0) { 1111 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, 1112 IGNORE_TX_PAUSEf, pause_tx ? 0 : 1); 1113 } 1114 1115 if (command_config == ocommand_config) { 1116 return SOC_E_NONE; 1117 } 1118 1119 /* First put the MAC in reset */ 1120 SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port, 1121 SOC_MAC_CONTROL_SW_RESET, 1122 TRUE)); 1123 1124 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_RESETf, 1); 1125 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config)); 1126 1127 /* Add 2usec delay before deasserting SW_RESET */ 1128 sal_udelay(2); 1129 1130 /* Bring the MAC out of reset */ 1131 SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port, 1132 SOC_MAC_CONTROL_SW_RESET, 1133 FALSE)); 1134 1135 return SOC_E_NONE; 1136 } 1137 1138 /* 1139 * Function: 1140 * mac_uni_pause_get 1141 * Purpose: 1142 * Return current GE MAC transmit/receive pause frame configuration. 1143 * Parameters: 1144 * unit - StrataSwitch unit #. 1145 * port - StrataSwitch port # on unit. 1146 * pause_tx - (OUT) TRUE is TX pause enabled. 1147 * pause_rx - (OUT) TRUE if obey RX pause enabled. 1148 * Returns: 1149 * SOC_E_XXX 1150 */ 1151 1152 STATIC int 1153 mac_uni_pause_get(int unit, soc_port_t port, int *pause_tx, int *pause_rx) 1154 { 1155 uint32 command_config; 1156 1157 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 1158 1159 *pause_rx = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, 1160 PAUSE_IGNOREf) ? FALSE : TRUE; 1161 *pause_tx = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, 1162 IGNORE_TX_PAUSEf) ? FALSE : TRUE; 1163 1164 LOG_VERBOSE(BSL_LS_SOC_GE, 1165 (BSL_META_U(unit, 1166 "mac_uni_pause_get: unit %d port %s RX=%s TX=%s\n"), 1167 unit, SOC_PORT_NAME(unit, port), 1168 *pause_rx ? "on" : "off", 1169 *pause_tx ? "on" : "off")); 1170 return SOC_E_NONE; 1171 } 1172 1173 /* 1174 * Function: 1175 * mac_uni_pause_addr_set 1176 * Purpose: 1177 * Set GE MAC source address for transmitted PAUSE frame 1178 * Parameters: 1179 * unit - StrataSwitch unit #. 1180 * port - StrataSwitch port # on unit. 1181 * pause_mac - MAC address used for pause transmission. 1182 * Returns: 1183 * SOC_E_XXX 1184 */ 1185 1186 STATIC int 1187 mac_uni_pause_addr_set(int unit, soc_port_t port, sal_mac_addr_t pause_mac) 1188 { 1189 uint32 mac_0, mac_1; 1190 1191 mac_0 = pause_mac[0] << 24 | 1192 pause_mac[1] << 16 | 1193 pause_mac[2] << 8 | 1194 pause_mac[3] << 0; 1195 mac_1 = pause_mac[4] << 8 | 1196 pause_mac[5]; 1197 1198 SOC_IF_ERROR_RETURN(WRITE_MAC_0r(unit, port, mac_0)); 1199 SOC_IF_ERROR_RETURN(WRITE_MAC_1r(unit, port, mac_1)); 1200 1201 LOG_VERBOSE(BSL_LS_SOC_GE, 1202 (BSL_META_U(unit, 1203 "mac_uni_pause_addr_set: unit %d port %s " 1204 "MAC=<%02x:%02x:%02x:%02x:%02x:%02x>\n"), 1205 unit, SOC_PORT_NAME(unit, port), 1206 pause_mac[0], pause_mac[1], pause_mac[2], 1207 pause_mac[3], pause_mac[4], pause_mac[5])); 1208 return SOC_E_NONE; 1209 } 1210 1211 /* 1212 * Function: 1213 * mac_uni_pause_addr_get 1214 * Purpose: 1215 * Return current GE MAC source address for transmitted PAUSE frames 1216 * Parameters: 1217 * unit - StrataSwitch unit #. 1218 * port - StrataSwitch port # on unit. 1219 * pause_mac - (OUT) MAC address used for pause transmission. 1220 * Returns: 1221 * SOC_E_XXX 1222 */ 1223 1224 STATIC int 1225 mac_uni_pause_addr_get(int unit, soc_port_t port, sal_mac_addr_t pause_mac) 1226 { 1227 uint32 mac_0, mac_1; 1228 1229 SOC_IF_ERROR_RETURN(READ_MAC_0r(unit, port, &mac_0)); 1230 SOC_IF_ERROR_RETURN(READ_MAC_1r(unit, port, &mac_1)); 1231 1232 pause_mac[0] = (uint8)(mac_0 >> 24); 1233 pause_mac[1] = (uint8)(mac_0 >> 16); 1234 pause_mac[2] = (uint8)(mac_0 >> 8); 1235 pause_mac[3] = (uint8)(mac_0 >> 0); 1236 pause_mac[4] = (uint8)(mac_1 >> 8); 1237 pause_mac[5] = (uint8)(mac_1 >> 0); 1238 1239 LOG_VERBOSE(BSL_LS_SOC_GE, 1240 (BSL_META_U(unit, 1241 "mac_uni_pause_addr_get: unit %d port %s " 1242 "MAC=<%02x:%02x:%02x:%02x:%02x:%02x>\n"), 1243 unit, SOC_PORT_NAME(unit, port), 1244 pause_mac[0], pause_mac[1], pause_mac[2], 1245 pause_mac[3], pause_mac[4], pause_mac[5])); 1246 return SOC_E_NONE; 1247 } 1248 1249 /* 1250 * Function: 1251 * mac_uni_loopback_set 1252 * Purpose: 1253 * Set GE MAC into/out-of loopback mode 1254 * Parameters: 1255 * unit - StrataSwitch unit #. 1256 * port - Port number on unit. 1257 * loopback - Boolean: true -> loopback mode, false -> normal operation 1258 * Returns: 1259 * SOC_E_XXX 1260 */ 1261 1262 STATIC int 1263 mac_uni_loopback_set(int unit, soc_port_t port, int loopback) 1264 { 1265 uint32 command_config, ocommand_config; 1266 int phy_lb = 0; 1267 1268 LOG_VERBOSE(BSL_LS_SOC_GE, 1269 (BSL_META_U(unit, 1270 "mac_uni_loopback_set: unit %d port %s loopback=%s\n"), 1271 unit, SOC_PORT_NAME(unit, port), 1272 loopback ? "True" : "False")); 1273 1274 /* The MAC loopback will not work when ENA_EXT_CONFIGf=1 because hardware puts MAC 1275 * in reset state if link is down. 1276 * A simple workaround is to put PHY in loopback mode to get the link. This brings 1277 * MAC out of reset state, and then clears ENA_EXT_CONFIGf. 1278 */ 1279 if (PHY_SGMII_AUTONEG_MODE(unit, port) && (!SOC_IS_HAWKEYE(unit))) { 1280 SOC_IF_ERROR_RETURN(soc_phyctrl_loopback_get(unit, port, &phy_lb)); 1281 1282 SOC_IF_ERROR_RETURN(soc_phyctrl_loopback_set(unit,port,TRUE, TRUE)); 1283 sal_usleep(40000); 1284 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 1285 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, 1286 ENA_EXT_CONFIGf, loopback? 0 : 1); 1287 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config)); 1288 SOC_IF_ERROR_RETURN(soc_phyctrl_loopback_set(unit,port,phy_lb, TRUE)); 1289 } 1290 1291 SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port, 1292 SOC_MAC_CONTROL_SW_RESET, 1293 TRUE)); 1294 1295 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 1296 ocommand_config = command_config; 1297 1298 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, LOOP_ENAf, 1299 loopback ? 1 : 0); 1300 1301 if (command_config != ocommand_config) { 1302 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, command_config)); 1303 } 1304 1305 #ifdef BCM_GREYHOUND2_SUPPORT 1306 if (SOC_IS_GREYHOUND2(unit) && loopback) { 1307 /* GH2's QTCE ports need phy linkup signal to active MAC loopback */ 1308 SOC_IF_ERROR_RETURN(soc_phyctrl_loopback_get(unit, port, &phy_lb)); 1309 SOC_IF_ERROR_RETURN(soc_phyctrl_loopback_set(unit, port, TRUE, TRUE)); 1310 sal_usleep(1000); 1311 SOC_IF_ERROR_RETURN(soc_phyctrl_loopback_set(unit, port, phy_lb, TRUE)); 1312 LOG_VERBOSE(BSL_LS_SOC_PORT, (BSL_META_U(unit, 1313 "port %s need raise phy linkup signal for mac loopback!\n"), 1314 SOC_PORT_NAME(unit, port))); 1315 } 1316 #endif /* BCM_GREYHOUND2_SUPPORT */ 1317 1318 SOC_IF_ERROR_RETURN(soc_mac_uni.md_control_set(unit, port, 1319 SOC_MAC_CONTROL_SW_RESET, 1320 FALSE)); 1321 1322 return SOC_E_NONE; 1323 } 1324 1325 /* 1326 * Function: 1327 * mac_uni_loopback_get 1328 * Purpose: 1329 * Get current GE MAC loopback mode setting. 1330 * Parameters: 1331 * unit - StrataSwitch unit #. 1332 * port - StrataSwitch port # on unit 1333 * loopback - (OUT) Boolean: true = loopback, false = normal 1334 * Returns: 1335 * SOC_E_XXX 1336 */ 1337 1338 STATIC int 1339 mac_uni_loopback_get(int unit, soc_port_t port, int *loopback) 1340 { 1341 uint32 command_config; 1342 1343 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 1344 1345 *loopback = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, 1346 LOOP_ENAf); 1347 1348 LOG_VERBOSE(BSL_LS_SOC_GE, 1349 (BSL_META_U(unit, 1350 "mac_uni_loopback_get: unit %d port %s loopback=%s\n"), 1351 unit, SOC_PORT_NAME(unit, port), 1352 *loopback ? "True" : "False")); 1353 return SOC_E_NONE; 1354 } 1355 1356 /* 1357 * Function: 1358 * mac_uni_ability_get 1359 * Purpose: 1360 * Return the UniMAC abilities 1361 * Parameters: 1362 * unit - StrataSwitch Unit #. 1363 * port - StrataSwitch Port # on unit. 1364 * mode - (OUT) Mask of MAC abilities returned. 1365 * Returns: 1366 * SOC_E_NONE 1367 */ 1368 1369 STATIC int 1370 mac_uni_ability_get(int unit, soc_port_t port, soc_port_mode_t *mode) 1371 { 1372 COMPILER_REFERENCE(unit); 1373 COMPILER_REFERENCE(port); 1374 1375 if (SOC_IS_SC_CQ(unit) && 1376 (SOC_PORT_BLOCK_TYPE(unit, port) == SOC_BLK_QGPORT)) { 1377 /* 5682x/72x GE-only ports are fixed at 1G speed */ 1378 *mode = (SOC_PM_10MB_FD | SOC_PM_100MB_FD | SOC_PM_1000MB_FD | 1379 SOC_PM_SGMII | SOC_PM_LB_MAC | SOC_PM_PAUSE); 1380 } else if (IS_ST_PORT(unit, port)) { 1381 *mode = (SOC_PM_1000MB_FD | SOC_PM_2500MB_FD | SOC_PM_LB_MAC | 1382 SOC_PM_MII | SOC_PM_GMII); 1383 1384 } else { 1385 *mode = (SOC_PM_10MB | SOC_PM_100MB | SOC_PM_1000MB_FD | 1386 SOC_PM_2500MB_FD | SOC_PM_MII | SOC_PM_GMII | 1387 SOC_PM_LB_MAC | SOC_PM_PAUSE); 1388 } 1389 1390 LOG_VERBOSE(BSL_LS_SOC_GE, 1391 (BSL_META_U(unit, 1392 "mac_uni_ability_get: unit %d port %s mode=0x%x\n"), 1393 unit, SOC_PORT_NAME(unit, port), 1394 *mode)); 1395 return SOC_E_NONE; 1396 } 1397 1398 /* 1399 * Function: 1400 * mac_uni_frame_max_set 1401 * Description: 1402 * Set the maximum receive frame size for the GE port 1403 * Parameters: 1404 * unit - Device number 1405 * port - Port number 1406 * size - Maximum frame size in bytes 1407 * Return Value: 1408 * BCM_E_XXX 1409 */ 1410 1411 STATIC int 1412 mac_uni_frame_max_set(int unit, soc_port_t port, int size) 1413 { 1414 uint32 command_config, rx_ena; 1415 int speed = 0; 1416 LOG_VERBOSE(BSL_LS_SOC_GE, 1417 (BSL_META_U(unit, 1418 "mac_uni_frame_max_set: unit %d port %s size=%d\n"), 1419 unit, SOC_PORT_NAME(unit, port), 1420 size)); 1421 1422 if (IS_ST_PORT(unit, port)) { 1423 size += 16; /* Account for 16 bytes of Higig2 header */ 1424 } 1425 1426 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &command_config)); 1427 rx_ena = soc_reg_field_get(unit, COMMAND_CONFIGr, command_config, RX_ENAf); 1428 1429 /* If Rx is enabled then disable RX */ 1430 if (rx_ena) { 1431 /* Disable RX */ 1432 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ENAf, 0); 1433 SOC_IF_ERROR_RETURN 1434 (WRITE_COMMAND_CONFIGr(unit, port, command_config)); 1435 1436 /* Wait for maximum frame receiption time(for 16K) based on speed */ 1437 SOC_IF_ERROR_RETURN(soc_mac_uni.md_speed_get(unit, port, &speed)); 1438 switch (speed) { 1439 case 2500: 1440 sal_usleep(55); 1441 break; 1442 case 1000: 1443 sal_usleep(131); 1444 break; 1445 case 100: 1446 sal_usleep(1310); 1447 break; 1448 case 10: 1449 sal_usleep(13100); 1450 break; 1451 default: 1452 break; 1453 } 1454 } 1455 1456 SOC_IF_ERROR_RETURN(WRITE_FRM_LENGTHr(unit, port, size)); 1457 1458 /* if Rx was enabled before, restore it */ 1459 if (rx_ena) { 1460 /* Enable RX */ 1461 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, RX_ENAf, 1); 1462 SOC_IF_ERROR_RETURN 1463 (WRITE_COMMAND_CONFIGr(unit, port, command_config)); 1464 } 1465 1466 return SOC_E_NONE; 1467 } 1468 1469 /* 1470 * Function: 1471 * mac_uni_frame_max_get 1472 * Description: 1473 * Set the maximum receive frame size for the GE port 1474 * Parameters: 1475 * unit - Device number 1476 * port - Port number 1477 * size - Maximum frame size in bytes 1478 * Return Value: 1479 * BCM_E_XXX 1480 * Notes: 1481 * Depending on chip or port type the actual maximum receive frame size 1482 * might be slightly higher. 1483 */ 1484 STATIC int 1485 mac_uni_frame_max_get(int unit, soc_port_t port, int *size) 1486 { 1487 uint32 frame_length; 1488 1489 SOC_IF_ERROR_RETURN(READ_FRM_LENGTHr(unit, port, &frame_length)); 1490 1491 *size = (int) frame_length; 1492 if (IS_ST_PORT(unit, port)) { 1493 *size -= 16; /* Account for 16 bytes of Higig2 header */ 1494 } 1495 1496 LOG_VERBOSE(BSL_LS_SOC_GE, 1497 (BSL_META_U(unit, 1498 "mac_uni_frame_max_get: unit %d port %s size=%d\n"), 1499 unit, SOC_PORT_NAME(unit, port), 1500 *size)); 1501 return SOC_E_NONE; 1502 } 1503 1504 /* 1505 * Function: 1506 * mac_uni_ifg_set 1507 * Description: 1508 * Sets the new ifg (Inter-frame gap) value 1509 * Parameters: 1510 * unit - Device number 1511 * port - Port number 1512 * speed - the speed for which the IFG is being set 1513 * duplex - the duplex for which the IFG is being set 1514 * ifg - Inter-frame gap in bit-times 1515 * Return Value: 1516 * BCM_E_XXX 1517 * Notes: 1518 * The function makes sure the IFG value makes sense and updates the 1519 * IPG register in case the speed/duplex match the current settings 1520 */ 1521 STATIC int 1522 mac_uni_ifg_set(int unit, soc_port_t port, int speed, 1523 soc_port_duplex_t duplex, int ifg) 1524 { 1525 int cur_speed = 0; 1526 int cur_duplex; 1527 int ipg, real_ifg; 1528 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 1529 1530 LOG_VERBOSE(BSL_LS_SOC_GE, 1531 (BSL_META_U(unit, 1532 "mac_uni_ifg_set: unit %d port %s speed=%dMb duplex=%s " 1533 "ifg=%d\n"), 1534 unit, SOC_PORT_NAME(unit, port), 1535 speed, duplex == SOC_PORT_DUPLEX_FULL ? "Full" : "Half", 1536 ifg)); 1537 1538 /* Get IPG, check range of IFG */ 1539 SOC_IF_ERROR_RETURN(mac_uni_ifg_to_ipg(unit, port, speed, duplex, 1540 ifg, &ipg)); 1541 SOC_IF_ERROR_RETURN(mac_uni_ipg_to_ifg(unit, port, speed, duplex, 1542 ipg, &real_ifg)); 1543 1544 if (duplex == SOC_PORT_DUPLEX_FULL) { 1545 if((speed != 10) && (speed != 100) && 1546 (speed != 1000) && (speed != 2500)) { 1547 return SOC_E_PARAM; 1548 } 1549 } else { 1550 if((speed != 10) && (speed != 100)) { 1551 return SOC_E_PARAM; 1552 } 1553 } 1554 1555 SOC_IF_ERROR_RETURN(mac_uni_duplex_get(unit, port, &cur_duplex)); 1556 SOC_IF_ERROR_RETURN(mac_uni_speed_get(unit, port, &cur_speed)); 1557 1558 if (cur_speed == speed && 1559 cur_duplex == (duplex == SOC_PORT_DUPLEX_FULL ? TRUE : FALSE)) { 1560 /* First put the MAC in reset */ 1561 SOC_IF_ERROR_RETURN 1562 (soc_mac_uni.md_control_set(unit, port, SOC_MAC_CONTROL_SW_RESET, 1563 TRUE)); 1564 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, TX_IPG_LENGTHr, port, 1565 TX_IPG_LENGTHf, ipg)); 1566 /* Bring the MAC out of reset */ 1567 SOC_IF_ERROR_RETURN 1568 (soc_mac_uni.md_control_set(unit, port, SOC_MAC_CONTROL_SW_RESET, 1569 FALSE)); 1570 1571 /* HW update success. Update the SI */ 1572 if (duplex == SOC_PORT_DUPLEX_FULL) { 1573 switch (speed) { 1574 case 10: 1575 si->fd_10 = real_ifg; 1576 break; 1577 case 100: 1578 si->fd_100 = real_ifg; 1579 break; 1580 case 1000: 1581 si->fd_1000 = real_ifg; 1582 break; 1583 case 2500: 1584 si->fd_2500 = real_ifg; 1585 break; 1586 /* coverity[dead_error_begin] */ 1587 default: 1588 /* Should not reach */ 1589 break; 1590 } 1591 } else { 1592 switch (speed) { 1593 case 10: 1594 si->hd_10 = real_ifg; 1595 break; 1596 case 100: 1597 si->hd_100 = real_ifg; 1598 break; 1599 /* coverity[dead_error_begin] */ 1600 default: 1601 /* Should not reach */ 1602 break; 1603 } 1604 } 1605 } 1606 1607 return SOC_E_NONE; 1608 } 1609 1610 /* 1611 * Function: 1612 * mac_uni_ifg_get 1613 * Description: 1614 * Gets the ifg (Inter-frame gap) value for a specific speed/duplex 1615 * combination 1616 * Parameters: 1617 * unit - Device number 1618 * port - Port number 1619 * speed - the speed for which the IFG is being set 1620 * duplex - the duplex for which the IFG is being set 1621 * ifg - Inter-frame gap in bit-times 1622 * Return Value: 1623 * BCM_E_XXX 1624 * Notes: 1625 * The function returns the REAL ifg value that will be (or is currently) 1626 * used by the chip, which might be different from the value initially 1627 * set by the ifg_set() call. The reason for that is that only certain 1628 * values are allowed. 1629 */ 1630 STATIC int 1631 mac_uni_ifg_get(int unit, soc_port_t port, int speed, 1632 soc_port_duplex_t duplex, int *ifg) 1633 { 1634 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 1635 1636 if (duplex == SOC_PORT_DUPLEX_FULL) { 1637 switch (speed) { 1638 case 10: 1639 *ifg = si->fd_10; 1640 break; 1641 case 100: 1642 *ifg = si->fd_100; 1643 break; 1644 case 1000: 1645 *ifg = si->fd_1000; 1646 break; 1647 case 2500: 1648 *ifg = si->fd_2500; 1649 break; 1650 default: 1651 return SOC_E_PARAM; 1652 break; 1653 } 1654 } else { 1655 switch (speed) { 1656 case 10: 1657 *ifg = si->hd_10; 1658 break; 1659 case 100: 1660 *ifg = si->hd_100; 1661 break; 1662 default: 1663 return SOC_E_PARAM; 1664 break; 1665 } 1666 } 1667 1668 LOG_VERBOSE(BSL_LS_SOC_GE, 1669 (BSL_META_U(unit, 1670 "mac_uni_ifg_get: unit %d port %s speed=%dMb duplex=%s " 1671 "ifg=%d\n"), 1672 unit, SOC_PORT_NAME(unit, port), 1673 speed, duplex == SOC_PORT_DUPLEX_FULL ? "Full" : "Half", 1674 *ifg)); 1675 return SOC_E_NONE; 1676 } 1677 1678 /* 1679 * Function: 1680 * mac_uni_interface_set 1681 * Purpose: 1682 * Set GE MAC interface type 1683 * Parameters: 1684 * unit - StrataSwitch unit #. 1685 * port - Port number on unit. 1686 * pif - one of SOC_PORT_IF_* 1687 * Returns: 1688 * SOC_E_XXX 1689 */ 1690 1691 STATIC int 1692 mac_uni_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 1693 { 1694 #ifdef BROADCOM_DEBUG 1695 LOG_VERBOSE(BSL_LS_SOC_GE, 1696 (BSL_META_U(unit, 1697 "mac_uni_interface_set: unit %d port %s interface=%s\n"), 1698 unit, SOC_PORT_NAME(unit, port), 1699 mac_uni_port_if_names[pif])); 1700 #endif 1701 1702 switch (pif) { 1703 case SOC_PORT_IF_MII: 1704 case SOC_PORT_IF_GMII: 1705 case SOC_PORT_IF_SGMII: 1706 return SOC_E_NONE; 1707 default: 1708 return SOC_E_UNAVAIL; 1709 } 1710 } 1711 1712 /* 1713 * Function: 1714 * mac_uni_interface_get 1715 * Purpose: 1716 * Retrieve GE MAC interface type 1717 * Parameters: 1718 * unit - StrataSwitch unit #. 1719 * port - StrataSwitch port # on unit. 1720 * pif - (OUT) one of SOC_PORT_IF_* 1721 * Returns: 1722 * SOC_E_XXX 1723 */ 1724 1725 STATIC int 1726 mac_uni_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 1727 { 1728 *pif = SOC_PORT_IF_GMII; 1729 1730 #ifdef BROADCOM_DEBUG 1731 LOG_VERBOSE(BSL_LS_SOC_GE, 1732 (BSL_META_U(unit, 1733 "mac_uni_interface_get: unit %d port %s interface=%s\n"), 1734 unit, SOC_PORT_NAME(unit, port), 1735 mac_uni_port_if_names[*pif])); 1736 #endif 1737 return SOC_E_NONE; 1738 } 1739 1740 /* 1741 * Function: 1742 * mac_uni_encap_set 1743 * Purpose: 1744 * Set the port encapsulation mode. 1745 * Parameters: 1746 * unit - XGS unit #. 1747 * port - XGS port # on unit. 1748 * mode - encapsulation mode 1749 * Returns: 1750 * SOC_E_XXX 1751 */ 1752 STATIC int 1753 mac_uni_encap_set(int unit, soc_port_t port, int mode) 1754 { 1755 #ifdef BROADCOM_DEBUG 1756 LOG_VERBOSE(BSL_LS_SOC_GE, 1757 (BSL_META_U(unit, 1758 "mac_uni_encap_set: unit %d port %s encapsulation=%s\n"), 1759 unit, SOC_PORT_NAME(unit, port), 1760 mac_uni_encap_mode[mode])); 1761 #endif 1762 1763 if (mode == SOC_ENCAP_IEEE) { 1764 return SOC_E_NONE; 1765 } 1766 return SOC_E_PARAM; 1767 } 1768 1769 /* 1770 * Function: 1771 * mac_uni_encap_get 1772 * Purpose: 1773 * Get the port encapsulation mode. 1774 * Parameters: 1775 * unit - XGS unit #. 1776 * port - XGS port # on unit. 1777 * mode - (INT) encapsulation mode 1778 * Returns: 1779 * SOC_E_XXX 1780 */ 1781 STATIC int 1782 mac_uni_encap_get(int unit, soc_port_t port, int *mode) 1783 { 1784 *mode = SOC_ENCAP_IEEE; 1785 1786 #ifdef BROADCOM_DEBUG 1787 LOG_VERBOSE(BSL_LS_SOC_GE, 1788 (BSL_META_U(unit, 1789 "mac_uni_encap_get: unit %d port %s encapsulation=%s\n"), 1790 unit, SOC_PORT_NAME(unit, port), 1791 mac_uni_encap_mode[*mode])); 1792 #endif 1793 return SOC_E_NONE; 1794 } 1795 1796 STATIC int 1797 _mac_uni_sw_reset(int unit, soc_port_t port, int reset_assert) 1798 { 1799 uint32 command_config; 1800 int reset_sleep_usec; 1801 1802 if (SAL_BOOT_QUICKTURN) { 1803 reset_sleep_usec = 50000; 1804 } else { 1805 /* Minimum of 5 clocks period with the slowest clock is required 1806 * between each reset step. 1807 * 10Mbps (2.5MHz) = 2000ns 1808 * 100Mbps (25MHz) = 200ns 1809 * 1000Mbps (125MHz) = 40ns 1810 * 2500Mbps (133MHz) = 37.5ns 1811 */ 1812 reset_sleep_usec = 2; /* choose max delay */ 1813 } 1814 1815 SOC_IF_ERROR_RETURN 1816 (READ_COMMAND_CONFIGr(unit, port, &command_config)); 1817 if (reset_assert) { 1818 /* SIDE EFFECT: TX and RX are enabled when SW_RESET is set. */ 1819 /* Assert SW_RESET */ 1820 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_RESETf, 1); 1821 } else { 1822 /* Deassert SW_RESET */ 1823 soc_reg_field_set(unit, COMMAND_CONFIGr, &command_config, SW_RESETf, 0); 1824 } 1825 1826 if (soc_feature(unit, soc_feature_unimac_reset_wo_clock)) { 1827 if (reset_assert) 1828 SOC_IF_ERROR_RETURN 1829 (soc_pgw_rx_fifo_reset(unit, port, TRUE)); 1830 } 1831 1832 SOC_IF_ERROR_RETURN 1833 (WRITE_COMMAND_CONFIGr(unit, port, command_config)); 1834 1835 sal_udelay(reset_sleep_usec); 1836 1837 if (soc_feature(unit, soc_feature_unimac_reset_wo_clock)) { 1838 if (!reset_assert) 1839 SOC_IF_ERROR_RETURN 1840 (soc_pgw_rx_fifo_reset(unit, port, FALSE)); 1841 } 1842 1843 return SOC_E_NONE; 1844 } 1845 1846 /* 1847 * Function: 1848 * mac_uni_expected_rx_latency_get 1849 * Purpose: 1850 * Get the UniMAC port expected Rx latency, part of determining LINK_DELAY 1851 * Parameters: 1852 * unit - XGS unit #. 1853 * port - XGS port # on unit. 1854 * latency - (OUT) Latency in NS 1855 * Returns: 1856 * SOC_E_XXX 1857 */ 1858 STATIC int 1859 mac_uni_expected_rx_latency_get(int unit, soc_port_t port, int *latency) 1860 { 1861 int speed = 0; 1862 SOC_IF_ERROR_RETURN(mac_uni_speed_get(unit, port, &speed)); 1863 1864 switch (speed) { 1865 case 10: 1866 /* 10M value from KT-1370 */ 1867 *latency = 23200; 1868 break; 1869 case 100: 1870 /* 100M value from KT-1370 */ 1871 *latency = 2320; 1872 break; 1873 case 1000: /* GigE */ 1874 /* 1G value from KT-1370: 232ns */ 1875 /* 1G value from SDK-84155: 275ns */ 1876 *latency = 275; 1877 break; 1878 1879 default: 1880 *latency = 0; 1881 break; 1882 } 1883 1884 return SOC_E_NONE; 1885 } 1886 1887 /* 1888 * Function: 1889 * mac_uni_control_set 1890 * Purpose: 1891 * To configure MAC control properties. 1892 * Parameters: 1893 * unit - XGS unit #. 1894 * port - XGS port # on unit. 1895 * type - MAC control property to set. 1896 * int - New setting for MAC control. 1897 * Returns: 1898 * SOC_E_XXX 1899 */ 1900 STATIC int 1901 mac_uni_control_set(int unit, soc_port_t port, soc_mac_control_t type, 1902 int value) 1903 { 1904 uint32 rval, fval, copy; 1905 1906 LOG_VERBOSE(BSL_LS_SOC_GE, 1907 (BSL_META_U(unit, 1908 "mac_uni_control_set: unit %d port %s type=%d value=%d\n"), 1909 unit, SOC_PORT_NAME(unit, port), 1910 type, value)); 1911 1912 switch(type) { 1913 case SOC_MAC_CONTROL_RX_SET: 1914 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &rval)); 1915 copy = rval; 1916 soc_reg_field_set(unit, COMMAND_CONFIGr, &rval, RX_ENAf, value ? 1 : 0); 1917 if (copy != rval) { 1918 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, rval)); 1919 } 1920 break; 1921 case SOC_MAC_CONTROL_TX_SET: 1922 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &rval)); 1923 copy = rval; 1924 soc_reg_field_set(unit, COMMAND_CONFIGr, &rval, TX_ENAf, value ? 1 : 0); 1925 if (copy != rval) { 1926 SOC_IF_ERROR_RETURN(WRITE_COMMAND_CONFIGr(unit, port, rval)); 1927 } 1928 break; 1929 case SOC_MAC_CONTROL_SW_RESET: 1930 case SOC_MAC_CONTROL_DISABLE_PHY: 1931 return _mac_uni_sw_reset(unit, port, value); 1932 1933 case SOC_MAC_CONTROL_PFC_TYPE: 1934 if (!SOC_REG_IS_VALID(unit, MAC_PFC_TYPEr)) { 1935 return SOC_E_UNAVAIL; 1936 } 1937 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, MAC_PFC_TYPEr, port, 1938 PFC_ETH_TYPEf, value)); 1939 break; 1940 1941 case SOC_MAC_CONTROL_PFC_OPCODE: 1942 if (!SOC_REG_IS_VALID(unit, MAC_PFC_OPCODEr)) { 1943 return SOC_E_UNAVAIL; 1944 } 1945 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, MAC_PFC_OPCODEr, 1946 port, PFC_OPCODEf, value)); 1947 break; 1948 1949 case SOC_MAC_CONTROL_PFC_CLASSES: 1950 if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) { 1951 return SOC_E_UNAVAIL; 1952 } 1953 if (soc_reg_field_valid(unit, UNIMAC_PFC_CTRLr, PFC_EIGHT_CLASSf)) { 1954 if (value == 16) { 1955 fval = 0; 1956 } else if (value == 8) { 1957 fval = 1; 1958 } else { 1959 return SOC_E_PARAM; 1960 } 1961 SOC_IF_ERROR_RETURN 1962 (soc_reg_field32_modify(unit, UNIMAC_PFC_CTRLr, port, 1963 PFC_EIGHT_CLASSf, fval)); 1964 } else if (value != 8) { 1965 return SOC_E_PARAM; 1966 } 1967 break; 1968 1969 case SOC_MAC_CONTROL_PFC_MAC_DA_OUI: 1970 if (!SOC_REG_IS_VALID(unit, MAC_PFC_DA_0r)) { 1971 return SOC_E_UNAVAIL; 1972 } 1973 SOC_IF_ERROR_RETURN(READ_MAC_PFC_DA_0r(unit, port, &rval)); 1974 rval &= 0x00ffffff; 1975 rval |= (value & 0x0000ff) << 24; 1976 SOC_IF_ERROR_RETURN(WRITE_MAC_PFC_DA_0r(unit, port, rval)); 1977 1978 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, MAC_PFC_DA_1r, port, 1979 PFC_MACDA_1f, value >> 8)); 1980 break; 1981 1982 case SOC_MAC_CONTROL_PFC_MAC_DA_NONOUI: 1983 if (!SOC_REG_IS_VALID(unit, MAC_PFC_DA_0r)) { 1984 return SOC_E_UNAVAIL; 1985 } 1986 SOC_IF_ERROR_RETURN(READ_MAC_PFC_DA_0r(unit, port, &rval)); 1987 rval &= 0xff000000; 1988 rval |= value & 0x00ffffff; 1989 SOC_IF_ERROR_RETURN(WRITE_MAC_PFC_DA_0r(unit, port, rval)); 1990 break; 1991 1992 case SOC_MAC_CONTROL_PFC_RX_PASS: 1993 if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) 1994 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) { 1995 SOC_IF_ERROR_RETURN 1996 (soc_reg_field32_modify(unit, MAC_PFC_CTRLr, port, 1997 RX_PASS_PFC_FRMf, value ? 1 : 0)); 1998 } else { 1999 if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) { 2000 return SOC_E_UNAVAIL; 2001 } 2002 SOC_IF_ERROR_RETURN 2003 (soc_reg_field32_modify(unit, UNIMAC_PFC_CTRLr, port, 2004 RX_PASS_PFC_FRMf, value ? 1 : 0)); 2005 } 2006 break; 2007 2008 case SOC_MAC_CONTROL_PFC_RX_ENABLE: 2009 if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) 2010 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) { 2011 SOC_IF_ERROR_RETURN 2012 (soc_reg_field32_modify(unit, MAC_PFC_CTRLr, port, PFC_RX_ENBLf, 2013 value ? 1 : 0)); 2014 } else { 2015 if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) { 2016 return SOC_E_UNAVAIL; 2017 } 2018 SOC_IF_ERROR_RETURN 2019 (soc_reg_field32_modify(unit, UNIMAC_PFC_CTRLr, port, PFC_RX_ENBLf, 2020 value ? 1 : 0)); 2021 } 2022 break; 2023 2024 case SOC_MAC_CONTROL_PFC_TX_ENABLE: 2025 if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) 2026 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) { 2027 SOC_IF_ERROR_RETURN 2028 (soc_reg_field32_modify(unit, MAC_PFC_CTRLr, port, PFC_TX_ENBLf, 2029 value ? 1 : 0)); 2030 } else { 2031 if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) { 2032 return SOC_E_UNAVAIL; 2033 } 2034 SOC_IF_ERROR_RETURN 2035 (soc_reg_field32_modify(unit, UNIMAC_PFC_CTRLr, port, PFC_TX_ENBLf, 2036 value ? 1 : 0)); 2037 } 2038 break; 2039 2040 case SOC_MAC_CONTROL_PFC_FORCE_XON: 2041 if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) 2042 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) { 2043 SOC_IF_ERROR_RETURN 2044 (soc_reg_field32_modify(unit, MAC_PFC_CTRLr, port, 2045 FORCE_PFC_XONf, value ? 1 : 0)); 2046 } else { 2047 if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) { 2048 return SOC_E_UNAVAIL; 2049 } 2050 SOC_IF_ERROR_RETURN 2051 (soc_reg_field32_modify(unit, UNIMAC_PFC_CTRLr, port, 2052 FORCE_PFC_XONf, value ? 1 : 0)); 2053 } 2054 break; 2055 2056 case SOC_MAC_CONTROL_PFC_STATS_ENABLE: 2057 if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) 2058 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) { 2059 SOC_IF_ERROR_RETURN 2060 (soc_reg_field32_modify(unit, MAC_PFC_CTRLr, port, 2061 PFC_STATS_ENf, value ? 1 : 0)); 2062 } else { 2063 if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) { 2064 return SOC_E_UNAVAIL; 2065 } 2066 SOC_IF_ERROR_RETURN 2067 (soc_reg_field32_modify(unit, UNIMAC_PFC_CTRLr, port, 2068 PFC_STATS_ENf, value ? 1 : 0)); 2069 } 2070 break; 2071 2072 case SOC_MAC_CONTROL_PFC_REFRESH_TIME: 2073 if (!SOC_REG_IS_VALID(unit, MAC_PFC_REFRESH_CTRLr)) { 2074 return SOC_E_UNAVAIL; 2075 } 2076 SOC_IF_ERROR_RETURN 2077 (soc_reg_field32_modify(unit, MAC_PFC_REFRESH_CTRLr, 2078 port, PFC_REFRESH_TIMERf, value)); 2079 break; 2080 2081 case SOC_MAC_CONTROL_PFC_XOFF_TIME: 2082 if (!SOC_REG_IS_VALID(unit, PFC_XOFF_TIMERr)) { 2083 return SOC_E_UNAVAIL; 2084 } 2085 SOC_IF_ERROR_RETURN 2086 (soc_reg_field32_modify(unit, PFC_XOFF_TIMERr, 2087 port, PFC_XOFF_TIMERf, value)); 2088 break; 2089 2090 case SOC_MAC_CONTROL_EEE_ENABLE: 2091 if (!soc_feature(unit, soc_feature_eee)) { 2092 return SOC_E_UNAVAIL; 2093 } 2094 if (!soc_reg_field_valid(unit, UMAC_EEE_CTRLr, EEE_ENf)) { 2095 return SOC_E_UNAVAIL; 2096 } 2097 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, UMAC_EEE_CTRLr, 2098 port, EEE_ENf, value)); 2099 break; 2100 2101 case SOC_MAC_CONTROL_EEE_TX_IDLE_TIME: 2102 if (!soc_feature(unit, soc_feature_eee)) { 2103 return SOC_E_UNAVAIL; 2104 } 2105 #if defined(BCM_HURRICANE2_SUPPORT) 2106 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 2107 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 2108 if (SOC_REG_PORT_VALID(unit, MII_EEE_DELAY_ENTRY_TIMERr, port)) { 2109 SOC_IF_ERROR_RETURN( 2110 soc_reg_field32_modify(unit, MII_EEE_DELAY_ENTRY_TIMERr, 2111 port, MII_EEE_LPI_TIMERf, value)); 2112 } 2113 2114 if (SOC_REG_PORT_VALID(unit, GMII_EEE_DELAY_ENTRY_TIMERr, port)) { 2115 SOC_IF_ERROR_RETURN( 2116 soc_reg_field32_modify(unit, GMII_EEE_DELAY_ENTRY_TIMERr, 2117 port, GMII_EEE_LPI_TIMERf, value)); 2118 } 2119 } else 2120 #endif 2121 { 2122 if (!soc_reg_field_valid(unit, 2123 EEE_DELAY_ENTRY_TIMERr, EEE_LPI_TIMERf)) { 2124 return SOC_E_UNAVAIL; 2125 } 2126 SOC_IF_ERROR_RETURN( 2127 soc_reg_field32_modify(unit, EEE_DELAY_ENTRY_TIMERr, 2128 port, EEE_LPI_TIMERf, value)); 2129 } 2130 break; 2131 2132 case SOC_MAC_CONTROL_EEE_TX_WAKE_TIME: 2133 if (!soc_feature(unit, soc_feature_eee)) { 2134 return SOC_E_UNAVAIL; 2135 } 2136 #if defined(BCM_HURRICANE2_SUPPORT) 2137 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 2138 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 2139 if (SOC_REG_PORT_VALID(unit, MII_EEE_WAKE_TIMERr, port)) { 2140 SOC_IF_ERROR_RETURN( 2141 soc_reg_field32_modify(unit, MII_EEE_WAKE_TIMERr, 2142 port, MII_EEE_WAKE_TIMERf, value)); 2143 } 2144 2145 if (SOC_REG_PORT_VALID(unit, GMII_EEE_WAKE_TIMERr, port)) { 2146 SOC_IF_ERROR_RETURN( 2147 soc_reg_field32_modify(unit, GMII_EEE_WAKE_TIMERr, 2148 port, GMII_EEE_WAKE_TIMERf, value)); 2149 } 2150 } else 2151 #endif 2152 { 2153 if (!soc_reg_field_valid(unit, EEE_WAKE_TIMERr, EEE_WAKE_TIMERf)) { 2154 return SOC_E_UNAVAIL; 2155 } 2156 SOC_IF_ERROR_RETURN( 2157 soc_reg_field32_modify(unit, EEE_WAKE_TIMERr, 2158 port, EEE_WAKE_TIMERf, value)); 2159 } 2160 break; 2161 2162 case SOC_MAC_CONTROL_RX_VLAN_TAG_OUTER_TPID: 2163 SOC_IF_ERROR_RETURN 2164 (soc_reg_field32_modify(unit, TAG_0r, port, 2165 FRM_TAG_0f, value)); 2166 if (soc_reg_field_valid(unit, TAG_0r, CONFIG_OUTER_TPID_ENABLEf)) { 2167 SOC_IF_ERROR_RETURN 2168 (soc_reg_field32_modify(unit, TAG_0r, port, 2169 CONFIG_OUTER_TPID_ENABLEf, value ? 1 : 0)); 2170 } 2171 break; 2172 2173 case SOC_MAC_CONTROL_RX_VLAN_TAG_INNER_TPID: 2174 SOC_IF_ERROR_RETURN 2175 (soc_reg_field32_modify(unit, TAG_1r, port, 2176 FRM_TAG_1f, value)); 2177 if (soc_reg_field_valid(unit, TAG_1r, CONFIG_INNER_TPID_ENABLEf)) { 2178 SOC_IF_ERROR_RETURN 2179 (soc_reg_field32_modify(unit, TAG_1r, port, 2180 CONFIG_INNER_TPID_ENABLEf, value ? 1 : 0)); 2181 } 2182 break; 2183 2184 default: 2185 return SOC_E_UNAVAIL; 2186 } 2187 2188 return SOC_E_NONE; 2189 } 2190 2191 /* 2192 * Function: 2193 * mac_uni_control_get 2194 * Purpose: 2195 * To get current MAC control setting. 2196 * Parameters: 2197 * unit - XGS unit #. 2198 * port - XGS port # on unit. 2199 * type - MAC control property to set. 2200 * int - New setting for MAC control. 2201 * Returns: 2202 * SOC_E_XXX 2203 */ 2204 STATIC int 2205 mac_uni_control_get(int unit, soc_port_t port, soc_mac_control_t type, 2206 int *value) 2207 { 2208 int rv; 2209 uint32 rval, fval0, fval1; 2210 2211 rv = SOC_E_NONE; 2212 2213 switch (type) { 2214 case SOC_MAC_CONTROL_RX_SET: 2215 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &rval)); 2216 *value = soc_reg_field_get(unit, COMMAND_CONFIGr, rval, RX_ENAf); 2217 break; 2218 case SOC_MAC_CONTROL_TX_SET: 2219 SOC_IF_ERROR_RETURN(READ_COMMAND_CONFIGr(unit, port, &rval)); 2220 *value = soc_reg_field_get(unit, COMMAND_CONFIGr, rval, TX_ENAf); 2221 break; 2222 case SOC_MAC_CONTROL_TIMESTAMP_TRANSMIT: 2223 { 2224 uint32 timestamp = 0; 2225 if (soc_feature(unit, soc_feature_timestamp_counter) && 2226 soc_property_get(unit, spn_SW_TIMESTAMP_FIFO_ENABLE, 1)) { 2227 rv = soc_counter_timestamp_get(unit, port, ×tamp); 2228 if (rv != SOC_E_NOT_FOUND) { 2229 *value = (int)timestamp; 2230 return rv; 2231 } 2232 } 2233 2234 if (!SOC_REG_IS_VALID(unit, TS_STATUS_CNTRLr)) { 2235 return SOC_E_UNAVAIL; 2236 } 2237 SOC_IF_ERROR_RETURN(READ_TS_STATUS_CNTRLr(unit, port, &rval)); 2238 if (soc_reg_field_get(unit, TS_STATUS_CNTRLr, rval, TX_TS_FIFO_EMPTYf)) { 2239 return SOC_E_EMPTY; 2240 } 2241 if (SOC_REG_IS_VALID(unit,TX_TS_SEQ_IDr)) { 2242 SOC_IF_ERROR_RETURN(READ_TX_TS_SEQ_IDr(unit, port, &rval)); 2243 if (!soc_reg_field_get(unit, TX_TS_SEQ_IDr, rval, TSTS_VALIDf)) { 2244 return SOC_E_EMPTY; 2245 } 2246 } 2247 SOC_IF_ERROR_RETURN(READ_TX_TS_DATAr(unit, port, &rval)); 2248 *value = (int) soc_reg_field_get(unit, TX_TS_DATAr, rval, TX_TS_DATAf); 2249 rv = SOC_E_NONE; 2250 } 2251 break; 2252 2253 case SOC_MAC_CONTROL_PFC_TYPE: 2254 if (!SOC_REG_IS_VALID(unit, MAC_PFC_TYPEr)) { 2255 return SOC_E_UNAVAIL; 2256 } 2257 SOC_IF_ERROR_RETURN(READ_MAC_PFC_TYPEr(unit, port, &rval)); 2258 *value = soc_reg_field_get(unit, MAC_PFC_TYPEr, rval, PFC_ETH_TYPEf); 2259 break; 2260 2261 case SOC_MAC_CONTROL_PFC_OPCODE: 2262 if (!SOC_REG_IS_VALID(unit, MAC_PFC_OPCODEr)) { 2263 return SOC_E_UNAVAIL; 2264 } 2265 SOC_IF_ERROR_RETURN(READ_MAC_PFC_OPCODEr(unit, port, &rval)); 2266 *value = soc_reg_field_get(unit, MAC_PFC_OPCODEr, rval, PFC_OPCODEf); 2267 break; 2268 2269 case SOC_MAC_CONTROL_PFC_CLASSES: 2270 if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) { 2271 return SOC_E_UNAVAIL; 2272 } 2273 if (soc_reg_field_valid(unit, UNIMAC_PFC_CTRLr, PFC_EIGHT_CLASSf)) { 2274 SOC_IF_ERROR_RETURN(READ_UNIMAC_PFC_CTRLr(unit, port, &rval)); 2275 *value = soc_reg_field_get(unit, UNIMAC_PFC_CTRLr, rval, 2276 PFC_EIGHT_CLASSf) ? 8 : 16; 2277 } else { 2278 *value = 8; 2279 } 2280 break; 2281 2282 case SOC_MAC_CONTROL_PFC_MAC_DA_OUI: 2283 if (!SOC_REG_IS_VALID(unit, MAC_PFC_DA_0r)) { 2284 return SOC_E_UNAVAIL; 2285 } 2286 SOC_IF_ERROR_RETURN(READ_MAC_PFC_DA_0r(unit, port, &rval)); 2287 fval0 = soc_reg_field_get(unit, MAC_PFC_DA_0r, rval, PFC_MACDA_0f); 2288 SOC_IF_ERROR_RETURN(READ_MAC_PFC_DA_1r(unit, port, &rval)); 2289 fval1 = soc_reg_field_get(unit, MAC_PFC_DA_1r, rval, PFC_MACDA_1f); 2290 *value = (fval0 >> 24) | (fval1 << 8); 2291 break; 2292 2293 case SOC_MAC_CONTROL_PFC_MAC_DA_NONOUI: 2294 if (!SOC_REG_IS_VALID(unit, MAC_PFC_DA_0r)) { 2295 return SOC_E_UNAVAIL; 2296 } 2297 SOC_IF_ERROR_RETURN(READ_MAC_PFC_DA_0r(unit, port, &rval)); 2298 *value = soc_reg_field_get(unit, MAC_PFC_DA_0r, rval, PFC_MACDA_0f) & 2299 0x00ffffff; 2300 break; 2301 2302 case SOC_MAC_CONTROL_PFC_RX_PASS: 2303 if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) 2304 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) { 2305 SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr_REG32(unit, port, &rval)); 2306 *value = soc_reg_field_get(unit, MAC_PFC_CTRLr, rval, 2307 RX_PASS_PFC_FRMf); 2308 } else { 2309 if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) { 2310 return SOC_E_UNAVAIL; 2311 } 2312 SOC_IF_ERROR_RETURN(READ_UNIMAC_PFC_CTRLr(unit, port, &rval)); 2313 *value = soc_reg_field_get(unit, UNIMAC_PFC_CTRLr, rval, 2314 RX_PASS_PFC_FRMf); 2315 } 2316 break; 2317 2318 case SOC_MAC_CONTROL_PFC_RX_ENABLE: 2319 if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) 2320 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) { 2321 SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr_REG32(unit, port, &rval)); 2322 *value = soc_reg_field_get(unit, MAC_PFC_CTRLr, rval, PFC_RX_ENBLf); 2323 } else { 2324 if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) { 2325 return SOC_E_UNAVAIL; 2326 } 2327 SOC_IF_ERROR_RETURN(READ_UNIMAC_PFC_CTRLr(unit, port, &rval)); 2328 *value = soc_reg_field_get(unit, UNIMAC_PFC_CTRLr, rval, PFC_RX_ENBLf); 2329 } 2330 break; 2331 2332 case SOC_MAC_CONTROL_PFC_TX_ENABLE: 2333 if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) 2334 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) { 2335 SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr_REG32(unit, port, &rval)); 2336 *value = soc_reg_field_get(unit, MAC_PFC_CTRLr, rval, PFC_TX_ENBLf); 2337 } else { 2338 if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) { 2339 return SOC_E_UNAVAIL; 2340 } 2341 SOC_IF_ERROR_RETURN(READ_UNIMAC_PFC_CTRLr(unit, port, &rval)); 2342 *value = soc_reg_field_get(unit, UNIMAC_PFC_CTRLr, rval, PFC_TX_ENBLf); 2343 } 2344 break; 2345 2346 case SOC_MAC_CONTROL_PFC_FORCE_XON: 2347 if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) 2348 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) { 2349 SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr_REG32(unit, port, &rval)); 2350 *value = soc_reg_field_get(unit, MAC_PFC_CTRLr, rval, 2351 FORCE_PFC_XONf); 2352 } else { 2353 if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) { 2354 return SOC_E_UNAVAIL; 2355 } 2356 SOC_IF_ERROR_RETURN(READ_UNIMAC_PFC_CTRLr(unit, port, &rval)); 2357 *value = soc_reg_field_get(unit, UNIMAC_PFC_CTRLr, rval, 2358 FORCE_PFC_XONf); 2359 } 2360 break; 2361 2362 case SOC_MAC_CONTROL_PFC_STATS_ENABLE: 2363 if ((SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) 2364 && SOC_REG_IS_VALID(unit, MAC_PFC_CTRLr)) { 2365 SOC_IF_ERROR_RETURN(READ_MAC_PFC_CTRLr_REG32(unit, port, &rval)); 2366 *value = soc_reg_field_get(unit, MAC_PFC_CTRLr, rval, 2367 PFC_STATS_ENf); 2368 } else { 2369 if (!SOC_REG_IS_VALID(unit, UNIMAC_PFC_CTRLr)) { 2370 return SOC_E_UNAVAIL; 2371 } 2372 SOC_IF_ERROR_RETURN(READ_UNIMAC_PFC_CTRLr(unit, port, &rval)); 2373 *value = soc_reg_field_get(unit, UNIMAC_PFC_CTRLr, rval, 2374 PFC_STATS_ENf); 2375 } 2376 break; 2377 2378 case SOC_MAC_CONTROL_PFC_REFRESH_TIME: 2379 if (!SOC_REG_IS_VALID(unit, MAC_PFC_REFRESH_CTRLr)) { 2380 return SOC_E_UNAVAIL; 2381 } 2382 SOC_IF_ERROR_RETURN(READ_MAC_PFC_REFRESH_CTRLr(unit, port, &rval)); 2383 *value = soc_reg_field_get(unit, MAC_PFC_REFRESH_CTRLr, rval, 2384 PFC_REFRESH_TIMERf); 2385 break; 2386 2387 case SOC_MAC_CONTROL_PFC_XOFF_TIME: 2388 if (!SOC_REG_IS_VALID(unit, PFC_XOFF_TIMERr)) { 2389 return SOC_E_UNAVAIL; 2390 } 2391 SOC_IF_ERROR_RETURN(READ_PFC_XOFF_TIMERr(unit, port, &rval)); 2392 *value = soc_reg_field_get(unit, PFC_XOFF_TIMERr, rval, 2393 PFC_XOFF_TIMERf); 2394 break; 2395 2396 case SOC_MAC_CONTROL_EEE_ENABLE: 2397 if (!soc_feature(unit, soc_feature_eee)) { 2398 return SOC_E_UNAVAIL; 2399 } 2400 if (!soc_reg_field_valid(unit, UMAC_EEE_CTRLr, EEE_ENf)) { 2401 return SOC_E_UNAVAIL; 2402 } 2403 SOC_IF_ERROR_RETURN(READ_UMAC_EEE_CTRLr(unit, port, &rval)); 2404 *value = soc_reg_field_get(unit, UMAC_EEE_CTRLr, rval, EEE_ENf); 2405 break; 2406 2407 case SOC_MAC_CONTROL_EEE_TX_IDLE_TIME: 2408 if (!soc_feature(unit, soc_feature_eee)) { 2409 return SOC_E_UNAVAIL; 2410 } 2411 #if defined(BCM_HURRICANE2_SUPPORT) 2412 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 2413 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 2414 if (SOC_REG_PORT_VALID( 2415 unit, MII_EEE_DELAY_ENTRY_TIMERr, port)) { 2416 SOC_IF_ERROR_RETURN( 2417 READ_MII_EEE_DELAY_ENTRY_TIMERr(unit, port, &rval)); 2418 *value = soc_reg_field_get(unit, MII_EEE_DELAY_ENTRY_TIMERr, 2419 rval, MII_EEE_LPI_TIMERf); 2420 } else if (SOC_REG_PORT_VALID(unit, 2421 GMII_EEE_DELAY_ENTRY_TIMERr, port)) { 2422 SOC_IF_ERROR_RETURN( 2423 READ_GMII_EEE_DELAY_ENTRY_TIMERr(unit, port, &rval)); 2424 *value = soc_reg_field_get(unit,GMII_EEE_DELAY_ENTRY_TIMERr, 2425 rval, GMII_EEE_LPI_TIMERf); 2426 } else { 2427 return SOC_E_UNAVAIL; 2428 } 2429 } else 2430 #endif 2431 { 2432 if (!soc_reg_field_valid(unit, 2433 EEE_DELAY_ENTRY_TIMERr, EEE_LPI_TIMERf)) { 2434 return SOC_E_UNAVAIL; 2435 } 2436 SOC_IF_ERROR_RETURN( 2437 READ_EEE_DELAY_ENTRY_TIMERr(unit, port, &rval)); 2438 *value = soc_reg_field_get(unit, EEE_DELAY_ENTRY_TIMERr, rval, 2439 EEE_LPI_TIMERf); 2440 } 2441 break; 2442 2443 case SOC_MAC_CONTROL_EEE_TX_WAKE_TIME: 2444 if (!soc_feature(unit, soc_feature_eee)) { 2445 return SOC_E_UNAVAIL; 2446 } 2447 #if defined(BCM_HURRICANE2_SUPPORT) 2448 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 2449 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 2450 if (SOC_REG_PORT_VALID(unit, MII_EEE_WAKE_TIMERr, port)) { 2451 SOC_IF_ERROR_RETURN( 2452 READ_MII_EEE_WAKE_TIMERr(unit, port, &rval)); 2453 *value = soc_reg_field_get(unit, MII_EEE_WAKE_TIMERr, 2454 rval, MII_EEE_WAKE_TIMERf); 2455 } else if ( 2456 SOC_REG_PORT_VALID(unit, GMII_EEE_WAKE_TIMERr, port)) { 2457 SOC_IF_ERROR_RETURN( 2458 READ_GMII_EEE_WAKE_TIMERr(unit, port, &rval)); 2459 *value = soc_reg_field_get(unit, GMII_EEE_WAKE_TIMERr, 2460 rval, GMII_EEE_WAKE_TIMERf); 2461 } else { 2462 return SOC_E_UNAVAIL; 2463 } 2464 } else 2465 #endif 2466 { 2467 if (!soc_reg_field_valid(unit, 2468 EEE_WAKE_TIMERr, EEE_WAKE_TIMERf)) { 2469 return SOC_E_UNAVAIL; 2470 } 2471 SOC_IF_ERROR_RETURN(READ_EEE_WAKE_TIMERr(unit, port, &rval)); 2472 *value = soc_reg_field_get(unit, EEE_WAKE_TIMERr, rval, 2473 EEE_WAKE_TIMERf); 2474 } 2475 break; 2476 2477 case SOC_MAC_CONTROL_FAULT_LOCAL_STATUS: 2478 case SOC_MAC_CONTROL_FAULT_REMOTE_STATUS: 2479 *value = 0; 2480 break; 2481 2482 case SOC_MAC_CONTROL_EXPECTED_RX_LATENCY: 2483 SOC_IF_ERROR_RETURN(mac_uni_expected_rx_latency_get(unit, port, value)); 2484 break; 2485 2486 case SOC_MAC_CONTROL_RX_VLAN_TAG_OUTER_TPID: 2487 SOC_IF_ERROR_RETURN(READ_TAG_0r(unit, port, &rval)); 2488 *value = soc_reg_field_get(unit, TAG_0r, rval, FRM_TAG_0f); 2489 break; 2490 2491 case SOC_MAC_CONTROL_RX_VLAN_TAG_INNER_TPID: 2492 SOC_IF_ERROR_RETURN(READ_TAG_1r(unit, port, &rval)); 2493 *value = soc_reg_field_get(unit, TAG_1r, rval, FRM_TAG_1f); 2494 break; 2495 2496 default: 2497 return SOC_E_UNAVAIL; 2498 } 2499 LOG_VERBOSE(BSL_LS_SOC_GE, 2500 (BSL_META_U(unit, 2501 "mac_uni_control_get: unit %d port %s type=%d value=%d " 2502 "rv=%d\n"), 2503 unit, SOC_PORT_NAME(unit, port), 2504 type, *value, rv)); 2505 return rv; 2506 } 2507 2508 /* 2509 * Function: 2510 * mac_uni_ability_local_get 2511 * Purpose: 2512 * Return the UniMAC abilities 2513 * Parameters: 2514 * unit - StrataSwitch Unit #. 2515 * port - StrataSwitch Port # on unit. 2516 * mode - (OUT) Mask of MAC abilities returned. 2517 * Returns: 2518 * SOC_E_NONE 2519 */ 2520 2521 STATIC int 2522 mac_uni_ability_local_get(int unit, soc_port_t port, 2523 soc_port_ability_t *ability) 2524 { 2525 COMPILER_REFERENCE(unit); 2526 COMPILER_REFERENCE(port); 2527 2528 #if defined(BCM_SCORPION_SUPPORT) 2529 if (SOC_IS_SC_CQ(unit) && 2530 (SOC_PORT_BLOCK_TYPE(unit, port) == SOC_BLK_QGPORT)) { 2531 /* 5682x/72x GE-only ports are restricted */ 2532 ability->speed_half_duplex = 0; 2533 ability->speed_full_duplex = 2534 SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB | SOC_PA_SPEED_1000MB; 2535 } else 2536 #endif /* BCM_SCORPION_SUPPORT */ 2537 #if defined(BCM_TRIDENT_SUPPORT) || defined(BCM_HURRICANE3_SUPPORT) 2538 if (SOC_IS_TD_TT(unit) || SOC_IS_HURRICANE3(unit)) { 2539 ability->speed_half_duplex = 2540 SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB; 2541 ability->speed_full_duplex = 2542 SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB | SOC_PA_SPEED_1000MB; 2543 if (SOC_CONTROL(unit)->info.port_speed_max[port] > 1000) { 2544 ability->speed_full_duplex |= SOC_PA_SPEED_2500MB; 2545 } 2546 } else 2547 #endif /* BCM_TRIDENT_SUPPORT */ 2548 { 2549 ability->speed_half_duplex = 2550 SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB; 2551 ability->speed_full_duplex = 2552 SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB | 2553 SOC_PA_SPEED_1000MB | SOC_PA_SPEED_2500MB; 2554 } 2555 ability->interface = SOC_PA_INTF_MII | SOC_PA_INTF_GMII; 2556 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 2557 ability->medium = SOC_PA_ABILITY_NONE; 2558 ability->loopback = SOC_PA_LB_MAC; 2559 ability->flags = SOC_PA_ABILITY_NONE; 2560 ability->encap = SOC_PA_ENCAP_IEEE; 2561 2562 LOG_VERBOSE(BSL_LS_SOC_GE, 2563 (BSL_META_U(unit, 2564 "mac_uni_ability_local_get: unit %d port %s " 2565 "speed_half=0x%x speed_full=0x%x encap=0x%x pause=0x%x " 2566 "interface=0x%x medium=0x%x loopback=0x%x flags=0x%x\n"), 2567 unit, SOC_PORT_NAME(unit, port), 2568 ability->speed_half_duplex, ability->speed_full_duplex, 2569 ability->encap, ability->pause, ability->interface, 2570 ability->medium, ability->loopback, ability->flags)); 2571 2572 return (SOC_E_NONE); 2573 } 2574 2575 2576 /* Exported UniMAC driver structure */ 2577 mac_driver_t soc_mac_uni = { 2578 "UniMAC Driver", /* drv_name */ 2579 mac_uni_init, /* md_init */ 2580 mac_uni_enable_set, /* md_enable_set */ 2581 mac_uni_enable_get, /* md_enable_get */ 2582 mac_uni_duplex_set, /* md_duplex_set */ 2583 mac_uni_duplex_get, /* md_duplex_get */ 2584 mac_uni_speed_set, /* md_speed_set */ 2585 mac_uni_speed_get, /* md_speed_get */ 2586 mac_uni_pause_set, /* md_pause_set */ 2587 mac_uni_pause_get, /* md_pause_get */ 2588 mac_uni_pause_addr_set, /* md_pause_addr_set */ 2589 mac_uni_pause_addr_get, /* md_pause_addr_get */ 2590 mac_uni_loopback_set, /* md_lb_set */ 2591 mac_uni_loopback_get, /* md_lb_get */ 2592 mac_uni_interface_set, /* md_interface_set */ 2593 mac_uni_interface_get, /* md_interface_get */ 2594 mac_uni_ability_get, /* md_ability_get */ 2595 mac_uni_frame_max_set, /* md_frame_max_set */ 2596 mac_uni_frame_max_get, /* md_frame_max_get */ 2597 mac_uni_ifg_set, /* md_ifg_set */ 2598 mac_uni_ifg_get, /* md_ifg_get */ 2599 mac_uni_encap_set, /* md_encap_set */ 2600 mac_uni_encap_get, /* md_encap_get */ 2601 mac_uni_control_set, /* md_control_set */ 2602 mac_uni_control_get, /* md_control_get */ 2603 mac_uni_ability_local_get, /* md_ability_local_get */ 2604 NULL /* md_timesync_tx_info_get */ 2605 }; 2606 #endif /* BCM_UNIMAC_SUPPORT */