mac.c (111530B)
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 * StrataSwitch Media Access Controller API 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <sal/core/libc.h> 13 #include <shared/alloc.h> 14 #include <sal/core/spl.h> 15 16 #include <soc/drv.h> 17 #include <soc/error.h> 18 #include <soc/cmic.h> 19 #include <soc/portmode.h> 20 #include <soc/ll.h> 21 #include <soc/phyctrl.h> 22 #include <soc/macutil.h> 23 24 #include <soc/mem.h> 25 26 #if defined(BCM_ESW_SUPPORT) 27 28 #define JUMBO_MAXSZ 0x3fe8 29 30 /* 31 * Forward Declarations 32 * 33 * mac_fe_xxx Routines that work on FE ports and 34 * GE ports that support 10/100 mode. 35 * mac_ge_xxx Routines that work on GE ports and 36 * GE ports that support 10/100 mode. 37 */ 38 39 STATIC int mac_fe_init(int unit, soc_port_t port); 40 STATIC int mac_fe_enable_set(int unit, soc_port_t port, int enable); 41 STATIC int mac_fe_enable_get(int unit, soc_port_t port, int *enable); 42 43 STATIC int mac_fe_duplex_set(int unit, soc_port_t port, int duplex); 44 STATIC int mac_fe_duplex_get(int unit, soc_port_t port, int *duplex); 45 STATIC int mac_fe_speed_set(int unit, soc_port_t port, int speed); 46 STATIC int mac_fe_speed_get(int unit, soc_port_t port, int *speed); 47 48 STATIC int mac_fe_pause_set(int unit, soc_port_t port, 49 int pause_tx, int pause_rx); 50 STATIC int mac_fe_pause_get(int unit, soc_port_t port, 51 int *pause_tx, int *pause_rx); 52 53 STATIC int mac_ge_init(int unit, soc_port_t port); 54 STATIC int mac_ge_enable_set(int unit, soc_port_t port, int enable); 55 STATIC int mac_ge_enable_get(int unit, soc_port_t port, int *enable); 56 57 STATIC int mac_ge_duplex_set(int unit, soc_port_t port, int duplex); 58 STATIC int mac_ge_duplex_get(int unit, soc_port_t port, int *duplex); 59 STATIC int mac_ge_speed_set(int unit, soc_port_t port, int speed); 60 STATIC int mac_ge_speed_get(int unit, soc_port_t port, int *speed); 61 STATIC int mac_ge_frame_max_set(int unit, soc_port_t port, int size); 62 63 STATIC int mac_ge_pause_set(int unit, soc_port_t port, 64 int pause_tx, int pause_rx); 65 STATIC int mac_ge_pause_get(int unit, soc_port_t port, 66 int *pause_tx, int *pause_rx); 67 STATIC int mac_ge_pause_addr_set(int unit, soc_port_t port, 68 sal_mac_addr_t); 69 STATIC int mac_ge_pause_addr_get(int unit, soc_port_t port, 70 sal_mac_addr_t); 71 STATIC int mac_ge_loopback_set(int unit, soc_port_t port, int); 72 STATIC int mac_ge_loopback_get(int unit, soc_port_t port, int *); 73 STATIC int mac_ge_interface_set(int unit, soc_port_t port, 74 soc_port_if_t pif); 75 76 /* 77 * Helper macros for PAUSE_CONTROL setting. The PAUSE_CONTROL value 78 * determines how often XOFFs must be sent. We use 75% of the maximum 79 * value to give some time for the pause to be transmitted and parsed 80 * on the far side. These are all usually counted in units of 512 bit 81 * times independent of port speed, so PAUSE_VAL(512) can be used to 82 * set the PAUSE_CONTROL register at initialization time. 83 */ 84 #define PAUSE_MAX 0x10000 /* units of 512 bit times */ 85 #define PAUSE_VAL(_bt) (PAUSE_MAX * (512/_bt) * 3 / 4) 86 87 /* 88 * Function: 89 * soc_mac_probe 90 * Purpose: 91 * Probe the specified unit/port for MAC type and return 92 * a mac_driver_t pointer used to drive the MAC. 93 * Parameters: 94 * unit - StrataSwitch/XGS Unit #. 95 * port - StrataSwitch/XGS Port # on unit. 96 * macd_ptr - (OUT) Pointer to MAC driver. 97 * Returns: 98 * SOC_E_XXX 99 */ 100 101 int 102 soc_mac_probe(int unit, soc_port_t port, mac_driver_t **macdp) 103 { 104 #if defined(BCM_SABER2_SUPPORT) 105 if (SOC_IS_SABER2(unit)) { 106 *macdp = &soc_mac_xl; 107 return SOC_E_NONE; 108 } 109 #endif 110 111 #ifdef BCM_CLMAC_SUPPORT 112 if (soc_feature(unit, soc_feature_cport_clmac)) { 113 if ((IS_CXX_PORT(unit, port) || IS_C_PORT(unit, port)) && 114 SOC_INFO(unit).port_speed_max[port] >= 100000) { 115 *macdp = &soc_mac_cl; 116 } else if ((SOC_IS_APACHE(unit) || SOC_IS_MONTEREY(unit)) && 117 (IS_CL_PORT(unit, port) || IS_CLG2_PORT(unit, port))) { 118 *macdp = &soc_mac_cl; 119 } else 120 { 121 *macdp = &soc_mac_xl; 122 } 123 return SOC_E_NONE; 124 } 125 #endif /* BCM_CLMAC_SUPPORT */ 126 127 #ifdef BCM_GREYHOUND2_SUPPORT 128 if (SOC_IS_GREYHOUND2(unit) && IS_CL_PORT(unit, port)) { 129 *macdp = &soc_mac_cl; 130 return SOC_E_NONE; 131 } 132 #endif /* BCM_GREYHOUND2_SUPPORT */ 133 134 if (IS_FE_PORT(unit, port)) { 135 #ifdef BCM_UNIMAC_SUPPORT 136 if (soc_feature(unit, soc_feature_unimac)) { 137 *macdp = &soc_mac_uni; 138 } else 139 #endif 140 { 141 *macdp = &soc_mac_fe; 142 } 143 #if defined(BCM_XMAC_SUPPORT) && defined(BCM_ESW_SUPPORT) 144 } else if (IS_MXQ_PORT(unit, port)) { 145 *macdp = &soc_mac_x; 146 #endif 147 #ifdef BCM_GXPORT_SUPPORT 148 #if defined(BCM_HUMV_SUPPORT) || defined(BCM_BRADLEY_SUPPORT) || \ 149 defined(BCM_GOLDWING_SUPPORT) 150 } else if (IS_GX_PORT(unit, port) && 151 (SOC_IS_HUMV(unit) || SOC_IS_BRADLEY(unit) || 152 SOC_IS_GOLDWING(unit))) { 153 *macdp = &soc_mac_gx; 154 #endif /* BCM_HUMV_SUPPORT || BCM_BRADLEY_SUPPORT || BCM_GOLDWING_SUPPORT */ 155 #endif /* BCM_GXPORT_SUPPORT */ 156 } else if (IS_GE_PORT(unit, port) && !SOC_IS_TD2_TT2(unit)) { 157 #ifdef BCM_HURRICANE2_SUPPORT 158 if ((SOC_IS_HURRICANE2(unit)|| SOC_IS_GREYHOUND(unit) || 159 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) && 160 IS_XL_PORT(unit,port)) { 161 *macdp = &soc_mac_xl; 162 } else 163 #endif 164 #ifdef BCM_UNIMAC_SUPPORT 165 if (soc_feature(unit, soc_feature_unimac)) { 166 *macdp = &soc_mac_uni; 167 } else 168 #endif 169 { 170 if (SOC_IS_TRIUMPH3(unit)) { /* For all GE's */ 171 *macdp = &soc_mac_x; 172 } else { 173 *macdp = &soc_mac_ge; 174 } 175 } 176 } else if (soc_feature(unit, soc_feature_unified_port)) { 177 #if defined(BCM_CMAC_SUPPORT) 178 if (IS_CL_PORT(unit, port) || IS_C_PORT(unit, port)) { 179 #if defined(BCM_CLMAC_SUPPORT) 180 if (soc_feature(unit, soc_feature_clmac)) { 181 *macdp = &soc_mac_cl; 182 return SOC_E_NONE; 183 } else 184 #endif /* BCM_CLMAC_SUPPORT */ 185 if (IS_CE_PORT(unit, port) || 186 SOC_INFO(unit).port_speed_max[port] >= 100000) { 187 *macdp = &soc_mac_c; 188 return SOC_E_NONE; 189 } else { 190 *macdp = &soc_mac_x; 191 return SOC_E_NONE; 192 } 193 } 194 #endif /* BCM_CMAC_SUPPORT */ 195 #if defined(BCM_XLMAC_SUPPORT) 196 if (soc_feature(unit, soc_feature_xlmac)) { 197 *macdp = &soc_mac_xl; 198 } 199 #endif /* BCM_XLPORT_SUPPORT */ 200 #if defined(BCM_XMAC_SUPPORT) 201 if (soc_feature(unit, soc_feature_xmac)) { 202 *macdp = &soc_mac_x; 203 } 204 #endif /* BCM_XMAC_SUPPORT */ 205 return SOC_E_NONE; 206 #if (defined(BCM_BIGMAC_SUPPORT) || defined(BCM_XMAC_SUPPORT)) && defined(BCM_UNIMAC_SUPPORT) 207 } else if (IS_GX_PORT(unit, port) || 208 (IS_XG_PORT(unit, port) && 209 soc_feature(unit, soc_feature_flexible_xgport))) { 210 #ifdef BCM_ESW_SUPPORT 211 if (IS_IL_PORT(unit, port)) { 212 *macdp = &soc_mac_il; 213 } else 214 #endif /* BCM_ESW_SUPPORT */ 215 { 216 *macdp = &soc_mac_combo; 217 } 218 #endif /* (BCM_BIGMAC_SUPPORT || BCM_XMAC_SUPPORT) && BCM_UNIMAC_SUPPORT */ 219 } else if (((IS_XE_PORT(unit, port)) || (IS_HG_PORT(unit, port))) && !SOC_IS_TRIUMPH3(unit)) { 220 #ifdef BCM_BIGMAC_SUPPORT 221 { 222 *macdp = &soc_mac_big; 223 } 224 #endif /* BCM_BIGMAC_SUPPORT */ 225 } else { 226 return SOC_E_PARAM; 227 } 228 return SOC_E_NONE; 229 } 230 231 /* 232 * Function: 233 * soc_mac_speed_get 234 * Purpose: 235 * Get the speed of a given mac 236 * Parameters: 237 * unit - Strata Switch unit # 238 * port - Strata Switch port # 239 * speed - (OUT) Speed in Mb/sec 240 * Notes: 241 * Do not add a soc_mac_speed_set function. Use the 242 * higher level MAC driver (eg in bcm/port.c) for this. 243 * Returns: 244 * SOC_E_XXX 245 */ 246 247 int 248 soc_mac_speed_get(int unit, soc_port_t port, int *speed) 249 { 250 uint32 fereg; 251 soc_mac_mode_t mode; 252 int turbo = 0; 253 254 if (speed == NULL) { 255 return SOC_E_PARAM; 256 } 257 258 if (IS_FE_PORT(unit, port)) { 259 SOC_IF_ERROR_RETURN(READ_FE_SUPPr(unit, port, &fereg)); 260 if (soc_reg_field_get(unit, FE_SUPPr, fereg, SPEEDf)) { 261 *speed = 100; 262 } else { 263 *speed = 10; 264 } 265 } else { 266 SOC_IF_ERROR_RETURN(soc_mac_mode_get(unit, port, &mode)); 267 switch (mode) { 268 case SOC_MAC_MODE_10: 269 case SOC_MAC_MODE_10_100: /* Get the speed from the mac */ 270 SOC_IF_ERROR_RETURN(FE_READ(FE_SUPPr, GTH_FE_SUPPr, 271 unit, port, &fereg)); 272 if (soc_reg_field_get(unit, FE_SUPPr, fereg, SPEEDf)) { 273 *speed = 100; 274 } else { 275 *speed = 10; 276 } 277 break; 278 case SOC_MAC_MODE_1000_T: 279 #if defined(BCM_RAPTOR1_SUPPORT) 280 if (SOC_IS_RAPTOR(unit) && IS_S_PORT(unit, port)) { 281 soc_pbmp_t pbmp_s0; 282 uint32 gport_config; 283 284 SOC_IF_ERROR_RETURN( 285 READ_GPORT_CONFIGr(unit, port, &gport_config)); 286 SOC_PBMP_WORD_SET(pbmp_s0, 0, 0x00000002); 287 if (SOC_PBMP_MEMBER(pbmp_s0, port)) { 288 turbo = soc_reg_field_get(unit, GPORT_CONFIGr, 289 gport_config, PLL_MODE_DEF_S0f); 290 } else { 291 turbo = soc_reg_field_get(unit, GPORT_CONFIGr, 292 gport_config, PLL_MODE_DEF_S1f); 293 } 294 } 295 #endif 296 /* coverity[dead_error_line] */ 297 *speed = turbo ? 2500 : 1000; 298 break; 299 case SOC_MAC_MODE_10000: 300 *speed = 10000; 301 #if defined(BCM_HELIX15_SUPPORT) || defined(BCM_FELIX15_SUPPORT) || \ 302 defined(BCM_FIREBOLT2_SUPPORT) 303 if (soc_feature(unit, soc_feature_lmd)) { 304 if (IS_LMD_ENABLED_PORT(unit, port)) { 305 *speed >>= 2; /* Div by 4 */ 306 } 307 } 308 #endif /* BCM_HELIX15_SUPPORT || BCM_FELIX15_SUPPORT || 309 BCM_FIREBOLT2_SUPPORT */ 310 break; 311 default: 312 return(SOC_E_INTERNAL); 313 } 314 } 315 return(SOC_E_NONE); 316 } 317 318 /* 319 * Function: 320 * _port_sp_sel_get/set 321 * Purpose: 322 * Get/set speed select for a port based on chip type and port 323 * Parameters: 324 * unit, port 325 * Returns: 326 * Returns < 0 on error. Otherwise, speed select value for port. 327 * Notes: 328 * These should only be called for gig ports supporting fe mode. 329 */ 330 331 STATIC int 332 _port_sp_sel_get(int unit, int port) 333 { 334 #ifdef BCM_XGS3_SWITCH_SUPPORT 335 if (soc_feature(unit, soc_feature_trimac)) { 336 /* FB/ER puts speed into GE_PORT_CONFIGr */ 337 uint32 val; 338 339 SOC_IF_ERROR_RETURN(READ_GE_PORT_CONFIGr(unit, port, &val)); 340 return soc_reg_field_get(unit, GE_PORT_CONFIGr, val, SPEED_SELECTf); 341 } 342 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 343 344 return SOC_E_INTERNAL; 345 } 346 347 STATIC int 348 _port_sp_sel_set(int unit, int port, uint32 sp_sel) 349 { 350 #ifdef BCM_XGS3_SWITCH_SUPPORT 351 if (soc_feature(unit, soc_feature_trimac)) { 352 /* FB/ER puts speed into GE_PORT_CONFIGr */ 353 uint32 val; 354 355 SOC_IF_ERROR_RETURN(READ_GE_PORT_CONFIGr(unit, port, &val)); 356 soc_reg_field_set(unit, GE_PORT_CONFIGr, &val, SPEED_SELECTf, sp_sel); 357 SOC_IF_ERROR_RETURN(WRITE_GE_PORT_CONFIGr(unit, port, val)); 358 } 359 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 360 361 return sp_sel; 362 } 363 364 365 /* 366 * Function: 367 * soc_mac_mode_get 368 * Purpose: 369 * Certain gig ports have two MACs. This function indicates which 370 * mode a gig port is in. 371 * Parameters: 372 * unit - StrataSwitch unit #. 373 * port - Port number on unit. 374 * mode - (OUT) current operating mode. 375 * Returns: 376 * SOC_E_XXX 377 * Notes: 378 * This routine is used outside of this module. 379 */ 380 381 int 382 soc_mac_mode_get(int unit, soc_port_t port, soc_mac_mode_t *mode) 383 { 384 int speed_sel; 385 uint32 rval; 386 int bits; 387 388 if(IS_GE_PORT(unit, port) && soc_feature(unit, soc_feature_unimac)) { 389 *mode = SOC_MAC_MODE_1000_T; /* Default */ 390 } else if (IS_GE_PORT(unit, port) || 391 (IS_FE_PORT(unit, port) && soc_feature(unit, soc_feature_trimac))) { 392 *mode = SOC_MAC_MODE_1000_T; /* Default */ 393 394 if (soc_feature(unit, soc_feature_fe_gig_macs)) { 395 if ((speed_sel = _port_sp_sel_get(unit, port)) < 0) { 396 return SOC_E_INTERNAL; 397 } 398 if (soc_feature(unit, soc_feature_trimac)) { 399 if (speed_sel == 1) { 400 *mode = SOC_MAC_MODE_10_100; 401 } else if (speed_sel == 2) { 402 *mode = SOC_MAC_MODE_10; 403 } 404 } else if (speed_sel != 0) { 405 *mode = SOC_MAC_MODE_10_100; 406 } 407 } 408 } else if (IS_FE_PORT(unit, port)) { 409 *mode = SOC_MAC_MODE_10_100; 410 } else if (IS_HG_PORT(unit, port) || IS_XE_PORT(unit, port)) { 411 if (IS_XQ_PORT(unit, port)) { 412 if (SOC_REG_IS_VALID(unit, XQPORT_MODE_REGr)) { 413 SOC_IF_ERROR_RETURN(READ_XQPORT_MODE_REGr(unit, port, &rval)); 414 bits = soc_reg_field_get(unit, XQPORT_MODE_REGr, rval, 415 XQPORT_MODE_BITSf); 416 if (bits == 2) { /* xport-mode */ 417 *mode = SOC_MAC_MODE_10000; 418 } else if (bits == 1) { /* gport-mode */ 419 *mode = SOC_MAC_MODE_1000_T; 420 return SOC_E_NONE; 421 } 422 } 423 } 424 *mode = SOC_MAC_MODE_10000; 425 } else { 426 return SOC_E_INTERNAL; 427 } 428 429 return SOC_E_NONE; 430 } 431 432 /* 433 * Function: 434 * soc_drain_cells 435 * Purpose: 436 * Wait until MMU cell count reaches zero for a specified port. 437 * Parameters: 438 * unit - StrataSwitch unit #. 439 * port - Port number being examined. 440 * Returns: 441 * SOC_E_XXX 442 * Notes: 443 * Keeps polling as long as LCCCOUNT/GCCCOUNT is decrementing. 444 * If LCCCOUNT/GCCCOUNT stops decrementing without reaching zero, 445 * after a timeout period a warning message is printed 446 * and it gives up. 447 * 448 * Before calling this routine, make sure no packets are switching 449 * to the port or it might never finish draining. 450 */ 451 452 int 453 soc_drain_cells(int unit, soc_port_t port) 454 { 455 soc_timeout_t to; 456 int rv, timeout_usec, loopback = -1; 457 uint32 cur_cells, new_cells; 458 soc_mac_mode_t mode; 459 uint32 egr_meter_config; 460 #ifdef BCM_XGS3_SWITCH_SUPPORT 461 uint32 pkt_drop_ctrl, pkt_drop_set; 462 int pause_tx = 0, pause_rx = 0; 463 #endif 464 465 if (SOC_IS_RELOADING(unit)) { 466 return SOC_E_NONE; 467 } 468 469 timeout_usec = soc_property_get(unit, spn_LCCDRAIN_TIMEOUT_USEC, 250000); 470 soc_timeout_init(&to, timeout_usec, 0); 471 472 #ifdef BCM_XGS3_SWITCH_SUPPORT 473 if (SOC_IS_XGS3_SWITCH(unit)) { 474 SOC_IF_ERROR_RETURN 475 (mac_ge_pause_get(unit, port, &pause_tx, &pause_rx)); 476 SOC_IF_ERROR_RETURN 477 (mac_ge_pause_set(unit, port, 0, 0)); 478 SOC_IF_ERROR_RETURN 479 (READ_GE_EGR_PKT_DROP_CTLr(unit, port, &pkt_drop_ctrl)); 480 pkt_drop_set = 0; 481 soc_reg_field_set(unit, GE_EGR_PKT_DROP_CTLr, &pkt_drop_set, FLUSHf, 1); 482 SOC_IF_ERROR_RETURN 483 (WRITE_GE_EGR_PKT_DROP_CTLr(unit, port, pkt_drop_set)); 484 if (IS_GE_PORT(unit, port) && !IS_GMII_PORT(unit, port) && 485 soc_feature(unit, soc_feature_dodeca_serdes) && 486 !PHY_SGMII_AUTONEG_MODE(unit, port)) { 487 SOC_IF_ERROR_RETURN 488 (soc_phyctrl_notify(unit, port, 489 phyEventStop, PHY_STOP_DRAIN)); 490 } 491 } 492 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 493 494 /* Disable egress metering. */ 495 if (SOC_REG_IS_VALID(unit, EGRMETERINGCONFIGr)) { 496 SOC_EGRESS_METERING_LOCK(unit); 497 rv = READ_EGRMETERINGCONFIGr(unit, port, &egr_meter_config); 498 if (rv < 0) { 499 SOC_EGRESS_METERING_UNLOCK(unit); 500 return (rv); 501 } 502 rv = WRITE_EGRMETERINGCONFIGr(unit, port, 0); 503 if (rv < 0) { 504 SOC_EGRESS_METERING_UNLOCK(unit); 505 return (rv); 506 } 507 } 508 509 if (soc_mac_mode_get(unit, port, &mode) < 0) { 510 mode = SOC_MAC_MODE_10_100; 511 } 512 513 cur_cells = 0xffffffff; 514 515 for (;;) { 516 if ((rv = soc_egress_cell_count(unit, port, &new_cells)) < 0) { 517 break; 518 } 519 520 if (new_cells == 0) { 521 rv = SOC_E_NONE; 522 break; 523 } 524 525 /* gig mac in pause state needs loopback mode to clear xoff */ 526 if (new_cells == cur_cells && loopback < 0 && 527 mode == SOC_MAC_MODE_1000_T) { 528 if (mac_ge_loopback_get(unit, port, &loopback) < 0) { 529 loopback = -1; 530 } else { 531 mac_ge_loopback_set(unit, port, 1); 532 } 533 } 534 535 if (new_cells < cur_cells) { /* Progress made */ 536 soc_timeout_init(&to, timeout_usec, 0); /* Restart timeout */ 537 cur_cells = new_cells; 538 } 539 540 if (soc_timeout_check(&to)) { 541 if ((rv = soc_egress_cell_count(unit, port, &new_cells)) < 0) { 542 break; 543 } 544 545 LOG_ERROR(BSL_LS_SOC_GE, 546 (BSL_META_U(unit, 547 "MacDrainTimeOut:port %d,%s, " 548 "timeout draining packets (%d cells remain)\n"), 549 unit, SOC_PORT_NAME(unit, port), new_cells)); 550 rv = SOC_E_INTERNAL; 551 break; 552 } 553 } 554 555 /* Reenable egres metering. */ 556 if (SOC_REG_IS_VALID(unit, EGRMETERINGCONFIGr)) { 557 rv = WRITE_EGRMETERINGCONFIGr(unit, port, egr_meter_config); 558 SOC_EGRESS_METERING_UNLOCK(unit); 559 if (rv < 0) { 560 return (rv); 561 } 562 } 563 564 if (loopback >= 0) { 565 SOC_IF_ERROR_RETURN 566 (mac_ge_loopback_set(unit, port, loopback)); 567 } 568 569 #ifdef BCM_XGS3_SWITCH_SUPPORT 570 if (SOC_IS_XGS3_SWITCH(unit)) { 571 if (IS_GE_PORT(unit, port) && !IS_GMII_PORT(unit, port) && 572 soc_feature(unit, soc_feature_dodeca_serdes) && 573 !PHY_SGMII_AUTONEG_MODE(unit, port)) { 574 SOC_IF_ERROR_RETURN 575 (soc_phyctrl_notify(unit, port, 576 phyEventResume, PHY_STOP_DRAIN)); 577 } 578 SOC_IF_ERROR_RETURN 579 (WRITE_GE_EGR_PKT_DROP_CTLr(unit, port, pkt_drop_ctrl)); 580 SOC_IF_ERROR_RETURN 581 (mac_ge_pause_set(unit, port, pause_tx, pause_rx)); 582 } 583 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 584 585 return rv; 586 } 587 588 /* 589 * Function: 590 * soc_mac_mode_set 591 * Purpose: 592 * Force GE MAC into 10/100 or 1000 mode. 593 * Parameters: 594 * unit - StrataSwitch unit #. 595 * port - Port number on unit. 596 * mode - one of SOC_MAC_MODE_* 597 * Returns: 598 * SOC_E_CONFIG - Speed not available on port 599 * SOC_E_XXX 600 * Notes: 601 * Can be used on any port; verifies parameters. 602 */ 603 604 int 605 soc_mac_mode_set(int unit, soc_port_t port, soc_mac_mode_t new_mode) 606 { 607 soc_mac_mode_t old_mode; 608 int old_mac_enable; 609 int save_duplex; 610 sal_mac_addr_t save_pause_mac; /* Pause MAC address */ 611 int save_pause_tx; /* Pause Tx enable status */ 612 int save_pause_rx; /* Pause Rx enable status */ 613 int save_lb; /* Mac LB enable status */ 614 615 LOG_INFO(BSL_LS_SOC_PHY, 616 (BSL_META_U(unit, 617 "soc_mac_mode_set: reconfiguring port=%d mode=%d\n"), 618 port, new_mode)); 619 620 switch (new_mode) { /* Check mode for validity */ 621 case SOC_MAC_MODE_10: 622 if (!soc_feature(unit, soc_feature_trimac)) { 623 return SOC_E_CONFIG; 624 } 625 break; 626 case SOC_MAC_MODE_10_100: 627 if (IS_FE_PORT(unit, port) && !soc_feature(unit, soc_feature_trimac)) { 628 return SOC_E_NONE; 629 } else if (IS_GE_PORT(unit, port)) { 630 if (!soc_feature(unit, soc_feature_fe_gig_macs)) { 631 return SOC_E_CONFIG; 632 } 633 } 634 break; 635 case SOC_MAC_MODE_1000_T: 636 if (!IS_GE_PORT(unit, port)) { 637 return SOC_E_CONFIG; 638 } 639 break; 640 case SOC_MAC_MODE_10000: 641 if (!IS_HG_PORT(unit, port) && !IS_XE_PORT(unit, port)) { 642 return SOC_E_CONFIG; 643 } else { 644 return SOC_E_NONE; 645 } 646 break; 647 default: 648 return SOC_E_INTERNAL; 649 } 650 651 /* 652 * At this point, we know the request is valid, and that we *MAY* need 653 * to take action. Cases such as setting mac on 10/100 port only OR 654 * 10G on HG port are already handled. 655 */ 656 657 SOC_IF_ERROR_RETURN(soc_mac_mode_get(unit, port, &old_mode)); 658 659 if (new_mode == old_mode) { /* Already in requested mode */ 660 return SOC_E_NONE; 661 } 662 663 /* 664 * Save some state from the current MAC that must be restored in the 665 * new MAC after the mode is switched. 666 */ 667 668 SOC_IF_ERROR_RETURN 669 (mac_ge_duplex_get(unit, port, &save_duplex)); 670 671 SOC_IF_ERROR_RETURN 672 (mac_ge_pause_get(unit, port, &save_pause_tx, &save_pause_rx)); 673 674 SOC_IF_ERROR_RETURN 675 (mac_ge_pause_addr_get(unit, port, save_pause_mac)); 676 677 SOC_IF_ERROR_RETURN 678 (mac_ge_loopback_get(unit, port, &save_lb)); 679 680 /* 681 * The currently selected MAC is quiesced before switching it out. 682 * It must not be talking to the MMU when the switch occurs. For 683 * receive, RX is disabled. For transmit, Egress is disabled. 684 */ 685 686 SOC_IF_ERROR_RETURN 687 (mac_ge_enable_get(unit, port, &old_mac_enable)); 688 SOC_IF_ERROR_RETURN 689 (mac_ge_enable_set(unit, port, FALSE)); 690 691 switch (new_mode) { 692 case SOC_MAC_MODE_10: 693 case SOC_MAC_MODE_10_100: 694 LOG_INFO(BSL_LS_SOC_PHY, 695 (BSL_META_U(unit, 696 "soc_mac_mode_set: port=%d, 10/100 mode\n"), 697 port)); 698 if (new_mode == SOC_MAC_MODE_10) { 699 _port_sp_sel_set(unit, port, 2); 700 } else { 701 _port_sp_sel_set(unit, port, 1); 702 } 703 break; 704 case SOC_MAC_MODE_1000_T: 705 LOG_INFO(BSL_LS_SOC_PHY, 706 (BSL_META_U(unit, 707 "soc_mac_mode_set: port=%d, Gig mode\n"), 708 port)); 709 _port_sp_sel_set(unit, port, 0); 710 break; 711 /* 712 * COVERITY 713 * 714 * Defensive default 715 */ 716 /* coverity[dead_error_begin] */ 717 default: 718 return SOC_E_INTERNAL; 719 } 720 721 /* 722 * Restore the saved state in the new MAC. 723 */ 724 725 SOC_IF_ERROR_RETURN 726 (mac_ge_duplex_set(unit, port, save_duplex)); 727 728 SOC_IF_ERROR_RETURN 729 (mac_ge_pause_set(unit, port, save_pause_tx, save_pause_rx)); 730 731 SOC_IF_ERROR_RETURN 732 (mac_ge_pause_addr_set(unit, port, save_pause_mac)); 733 734 SOC_IF_ERROR_RETURN 735 (mac_ge_loopback_set(unit, port, save_lb)); 736 737 /* 738 * Enable the egress and MAC, if previously enabled. 739 */ 740 741 if (old_mac_enable) { 742 if (new_mode == SOC_MAC_MODE_1000_T) { 743 SOC_IF_ERROR_RETURN(mac_ge_enable_set(unit, port, TRUE)); 744 } else { 745 SOC_IF_ERROR_RETURN(mac_fe_enable_set(unit, port, TRUE)); 746 } 747 } 748 749 return SOC_E_NONE; 750 } 751 752 /* 753 * Function: 754 * mac_fe_enable_set 755 * Purpose: 756 * Enable or disable MAC 757 * Parameters: 758 * unit - StrataSwitch unit #. 759 * port - Port number on unit. 760 * enable - TRUE to enable, FALSE to disable 761 * Returns: 762 * SOC_E_XXX 763 * Notes: 764 * The EGR_ENABLE and GEGR_ENABLE registers disable the egress, 765 * chopping any packet that is in progress and leaving part of it 766 * in the MMU. 767 * 768 * On FE ports, we can avoid using EGR_ENABLE by putting the egress 769 * single step debug mode. This will stop traffic to the egress 770 * between packets. 771 * 772 * On GE ports, egress single step is not implemented. Before 773 * setting GEGR_ENABLE to 0, we necessary to clear the port from 774 * EPC LINK to stop traffic from flowing to it, then wait for all 775 * packets to drain from the MMU to the egress. 776 * 777 * The draining approach is not used for FE because the draining 778 * takes too long. It is likely for a link to come back up before 779 * the draining is complete. 780 */ 781 782 STATIC int 783 mac_fe_enable_set(int unit, soc_port_t port, int enable) 784 { 785 uint32 regval; 786 pbmp_t mask; 787 788 #ifdef BCM_RAPTOR1_SUPPORT 789 /* Need to reset the FE MAC for Raptor before enabling RX */ 790 if (SOC_IS_RAPTOR(unit) && enable) { 791 SOC_IF_ERROR_RETURN 792 (soc_reg_field32_modify(unit, GMACC0r, port, SRSTf, 1)); 793 SOC_IF_ERROR_RETURN 794 (soc_reg_field32_modify(unit, GMACC0r, port, SRSTf, 0)); 795 } 796 #endif 797 /* 798 * Turn on/off receive enable. 799 * 800 * We do not bother then TXEN because on some chips this signal does 801 * not take effect (get latched) until traffic stops flowing. 802 */ 803 804 SOC_IF_ERROR_RETURN(FE_READ(FE_MAC1r, GTH_FE_MAC1r, unit, port, ®val)); 805 FE_SET(unit, port, FE_MAC1r, GTH_FE_MAC1r, RX_ENf, regval, enable ? 1 : 0); 806 SOC_IF_ERROR_RETURN(FE_WRITE(FE_MAC1r, GTH_FE_MAC1r, unit, port, regval)); 807 808 sal_usleep(50000); /* sleep 50ms */ 809 810 /* 811 * Use EPC_LINK to control other ports sending to this port. This 812 * blocking is independent and in addition to what Linkscan does. 813 * 814 * Single-step mode is used to stop traffic from going from the 815 * egress to the MAC. 816 */ 817 818 if (!enable) { 819 soc_link_mask2_get(unit, &mask); 820 SOC_PBMP_PORT_REMOVE(mask, port); 821 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 822 823 SOC_IF_ERROR_RETURN(soc_drain_cells(unit, port)); 824 825 #if defined(BCM_FIREBOLT2_SUPPORT) 826 if (SOC_IS_FIREBOLT2(unit)) { 827 int fd, speed; 828 829 SOC_IF_ERROR_RETURN(mac_fe_duplex_get(unit, port, &fd)); 830 SOC_IF_ERROR_RETURN(mac_fe_speed_get(unit, port, &speed)); 831 832 /* Only for 100 FX via the SerDes */ 833 if ((speed == 100) && fd && PHY_FIBER_MODE(unit, port) && 834 !PHY_EXTERNAL_MODE(unit, port)) { 835 /* Reset the MAC so that the error link state which may 836 * affect receive false carrier counter is cleared when 837 * the link is up again. */ 838 SOC_IF_ERROR_RETURN 839 (soc_reg_field32_modify(unit, GMACC0r, port, SRSTf, 1)); 840 SOC_IF_ERROR_RETURN 841 (soc_reg_field32_modify(unit, GMACC0r, port, SRSTf, 0)); 842 } 843 } 844 #endif /* BCM_FIREBOLT2_SUPPORT */ 845 } else { 846 soc_link_mask2_get(unit, &mask); 847 SOC_PBMP_PORT_ADD(mask, port); 848 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 849 } 850 851 /* 852 * The SERDES PHY is kept in reset whenever the MAC is 853 * disabled. When the link comes up, the SERDES PHY must come out 854 * of reset last, *after* the speed and duplex are programmed. If 855 * the SERDES PHY is reset after the external PHY has link, a false 856 * carrier is generated which can cause certain remote hardware to 857 * drop link. SEE ALSO: mac_ge_enable_set. 858 */ 859 860 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) 861 if (soc_feature(unit, soc_feature_dodeca_serdes)) { 862 if (enable) { 863 SOC_IF_ERROR_RETURN 864 (soc_phyctrl_notify(unit, port, 865 phyEventResume, PHY_STOP_MAC_DIS)); 866 } else { 867 SOC_IF_ERROR_RETURN 868 (soc_phyctrl_notify(unit, port, 869 phyEventStop, PHY_STOP_MAC_DIS)); 870 } 871 } 872 #endif /* BCM_FIREBOLT_SUPPORT || BCM_RAPTOR_SUPPORT */ 873 874 return SOC_E_NONE; 875 } 876 877 /* 878 * Function: 879 * mac_fe_enable_get 880 * Purpose: 881 * Get MAC enable state 882 * Parameters: 883 * unit - StrataSwitch unit #. 884 * port - Port number on unit. 885 * enable - (OUT) TRUE if enabled, FALSE if disabled 886 * Returns: 887 * SOC_E_XXX 888 */ 889 890 STATIC int 891 mac_fe_enable_get(int unit, soc_port_t port, int *enable) 892 { 893 uint32 regval; 894 895 SOC_IF_ERROR_RETURN(FE_READ(FE_MAC1r, GTH_FE_MAC1r, unit, port, ®val)); 896 897 *enable = FE_GET(unit, port, FE_MAC1r, GTH_FE_MAC1r, RX_ENf, regval); 898 899 return SOC_E_NONE; 900 } 901 902 /* 903 * Function: 904 * mac_fe_ifg_to_ipg 905 * Description: 906 * Converts the inter-frame gap specified in bit-times into a value 907 * suitable to be programmed into the IPG register 908 * Parameters: 909 * unit - Device number 910 * port - Port number 911 * speed - the speed for which the IFG is being set 912 * duplex - the duplex for which the IFG is being set 913 * ifg - Inter-frame gap in bit-times 914 * ipg - (OUT) the value to be written into IPG 915 * Return Value: 916 * BCM_E_XXX 917 * Notes: 918 * The function makes sure the calculated IPG value will not cause 919 * hardware to fail. If the requested ifg value cannot be supported in 920 * hardware, the function will choose a value that approximates the 921 * requested value as best as possible. 922 * 923 * Specifically: 924 * -- Current chips only support ifg which is divisible by 8. If 925 * the specified ifg is not divisible by 8, it will be rounded 926 * to the next multiplier of 8 (65 will result in 72). 927 * -- ifg < 64 are not supported 928 * 929 * This function support both FE and GTH_FE MACs 930 */ 931 STATIC int 932 mac_fe_ifg_to_ipg(int unit, soc_port_t port, int speed, int duplex, 933 int ifg, int *ipg) 934 { 935 /* 936 * The inter-frame gap should be a multiple of 8 bit-times. 937 */ 938 ifg = (ifg + 7) & ~7; 939 940 /* 941 * The smallest supported ifg is 64 bit-times 942 */ 943 ifg = (ifg < 64) ? 64 : ifg; 944 945 /* 946 * Now we need to convert the value according to various chips' 947 * peculiarities 948 */ 949 if (duplex) { 950 *ipg = ifg / 4 - 3; 951 } else { 952 switch (SOC_CHIP_GROUP(unit)) { 953 case SOC_CHIP_BCM56504: 954 case SOC_CHIP_BCM56102: 955 case SOC_CHIP_BCM56304: 956 case SOC_CHIP_BCM56800: 957 case SOC_CHIP_BCM56218: 958 case SOC_CHIP_BCM56112: 959 case SOC_CHIP_BCM56314: 960 case SOC_CHIP_BCM56514: 961 case SOC_CHIP_BCM56624: 962 case SOC_CHIP_BCM56820: 963 case SOC_CHIP_BCM56680: 964 case SOC_CHIP_BCM56634: 965 case SOC_CHIP_BCM56524: 966 case SOC_CHIP_BCM56685: 967 case SOC_CHIP_BCM88732: 968 switch (speed) { 969 case 10: 970 if (soc_feature(unit, soc_feature_ext_gth_hd_ipg)) { 971 *ipg = ifg / 4 - 4; 972 } else { 973 *ipg = ifg / 4 - 12; 974 } 975 break; 976 case 100: 977 if (soc_feature(unit, soc_feature_ext_gth_hd_ipg)) { 978 *ipg = ifg / 4 - 5; 979 } else { 980 *ipg = ifg / 4 - 13; 981 } 982 break; 983 default: 984 return SOC_E_INTERNAL; 985 } 986 break; 987 default: 988 *ipg = ifg / 4 - 6; 989 break; 990 } 991 } 992 993 /* 994 * Notice, that since we force the minimal ifg to be 64, then there 995 * no way ipg will be less than 0 or something like that. 996 */ 997 998 return SOC_E_NONE; 999 } 1000 1001 /* 1002 * Function: 1003 * mac_fe_ipg_to_ifg 1004 * Description: 1005 * Converts the IPG register value into the inter-frame gap expressed in 1006 * bit-times 1007 * Parameters: 1008 * unit - Device number 1009 * port - Port number 1010 * speed - the speed for which the IFG is being set 1011 * duplex - the duplex for which the IFG is being set 1012 * ipg - the value in the IPG register 1013 * ifg - Inter-frame gap in bit-times 1014 * Return Value: 1015 * BCM_E_XXX 1016 * Notes: 1017 * This function works for both FE and GTH_FE MACs 1018 */ 1019 STATIC int 1020 mac_fe_ipg_to_ifg(int unit, soc_port_t port, int speed, int duplex, 1021 int ipg, int *ifg) 1022 { 1023 /* 1024 * Now we need to convert the value according to various chips' 1025 * peculiarities 1026 */ 1027 if (duplex) { 1028 *ifg = (ipg + 3) * 4; 1029 } else { 1030 switch (SOC_CHIP_GROUP(unit)) { 1031 case SOC_CHIP_BCM56504: 1032 case SOC_CHIP_BCM56102: 1033 case SOC_CHIP_BCM56304: 1034 case SOC_CHIP_BCM56800: 1035 case SOC_CHIP_BCM56218: 1036 case SOC_CHIP_BCM56112: 1037 case SOC_CHIP_BCM56314: 1038 case SOC_CHIP_BCM56514: 1039 case SOC_CHIP_BCM56624: 1040 case SOC_CHIP_BCM56820: 1041 case SOC_CHIP_BCM56680: 1042 case SOC_CHIP_BCM56634: 1043 case SOC_CHIP_BCM56524: 1044 case SOC_CHIP_BCM56685: 1045 case SOC_CHIP_BCM88732: 1046 if (soc_feature(unit, soc_feature_ext_gth_hd_ipg)) { 1047 if (speed == 10) { 1048 *ifg = (ipg + 4) * 4; 1049 } else { 1050 *ifg = (ipg + 5) * 4; 1051 } 1052 } else { 1053 if (speed == 10) { 1054 *ifg = (ipg + 12) * 4; 1055 } else { 1056 *ifg = (ipg + 13) * 4; 1057 } 1058 } 1059 break; 1060 default: 1061 *ifg = (ipg + 6) * 4; 1062 break; 1063 } 1064 } 1065 1066 return SOC_E_NONE; 1067 } 1068 1069 /* 1070 * Function: 1071 * mac_fe_ipg_update 1072 * Purpose: 1073 * Set the IPG appropriate for current speed/duplex 1074 * Parameters: 1075 * unit - StrataSwitch unit #. 1076 * port - Port number on unit. 1077 * Notes: 1078 * The current speed/duplex are read from the hardware registers. 1079 */ 1080 1081 STATIC int 1082 mac_fe_ipg_update(int unit, int port) 1083 { 1084 int fd, speed, ifg, ipg = 0; 1085 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 1086 uint32 ipg32; 1087 1088 SOC_IF_ERROR_RETURN(mac_fe_duplex_get(unit, port, &fd)); 1089 SOC_IF_ERROR_RETURN(mac_fe_speed_get(unit, port, &speed)); 1090 1091 /* 1092 * Get the ifg value in bit-times 1093 */ 1094 if (fd) { 1095 switch (speed) { 1096 case 10: 1097 ifg = si->fd_10; 1098 break; 1099 case 100: 1100 ifg = si->fd_100; 1101 break; 1102 default: 1103 return SOC_E_INTERNAL; 1104 } 1105 if (SOC_IS_XGS3_SWITCH(unit)) { 1106 SOC_IF_ERROR_RETURN(mac_fe_ifg_to_ipg(unit, port, speed, fd, ifg, &ipg)); 1107 } 1108 } else { 1109 switch (speed) { 1110 case 10: 1111 ifg = si->hd_10; 1112 break; 1113 case 100: 1114 ifg = si->hd_100; 1115 break; 1116 default: 1117 return SOC_E_INTERNAL; 1118 } 1119 /* Deal with XGS 3 switches */ 1120 if (SOC_IS_XGS3_SWITCH(unit)) { 1121 switch (SOC_CHIP_GROUP(unit)) { 1122 case SOC_CHIP_BCM56102: 1123 case SOC_CHIP_BCM56112: 1124 ipg = 0x11; 1125 break; 1126 case SOC_CHIP_BCM56601: 1127 case SOC_CHIP_BCM56602: 1128 case SOC_CHIP_BCM56504: 1129 case SOC_CHIP_BCM56304: 1130 case SOC_CHIP_BCM56800: 1131 case SOC_CHIP_BCM56218: 1132 case SOC_CHIP_BCM56314: 1133 case SOC_CHIP_BCM56514: 1134 ipg = 0x12; 1135 break; 1136 default: 1137 return SOC_E_INTERNAL; 1138 } 1139 } 1140 } 1141 1142 /* 1143 * Convert the ifg value from bit-times into IPG register-specific value 1144 * Do only for older switches - XGS3 dealt with separately 1145 */ 1146 if (!SOC_IS_XGS3_SWITCH(unit)) { 1147 SOC_IF_ERROR_RETURN(mac_fe_ifg_to_ipg(unit, port, speed, fd, ifg, &ipg)); 1148 } 1149 1150 /* 1151 * Program the appropriate register 1152 */ 1153 ipg32 = ipg; 1154 SOC_IF_ERROR_RETURN(FE_WRITE(FE_IPGTr, GTH_FE_IPGTr, unit, port, ipg32)); 1155 1156 return SOC_E_NONE; 1157 } 1158 1159 /* 1160 * Function: 1161 * mac_fe_init 1162 * Purpose: 1163 * Initialize FE MAC into a known good state. 1164 * Parameters: 1165 * unit - StrataSwitch unit #. 1166 * port - Port number on unit. 1167 * Returns: 1168 * SOC_E_XXX 1169 * Notes: 1170 * The initialization speed/duplex is arbitrary and must be 1171 * updated by linkscan before enabling the MAC. 1172 */ 1173 1174 STATIC int 1175 mac_fe_init(int unit, soc_port_t port) 1176 { 1177 uint32 reg32; 1178 1179 #if defined(BCM_FELIX_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) 1180 if (IS_FE_PORT(unit, port) && soc_feature(unit, soc_feature_trimac)) { 1181 SOC_IF_ERROR_RETURN(soc_mac_mode_set(unit, port, 1182 SOC_MAC_MODE_10_100)); 1183 #ifdef BCM_RAPTOR1_SUPPORT 1184 /* 1185 * Do a MAC soft reset 1186 */ 1187 if (SOC_IS_RAPTOR(unit)) { 1188 SOC_IF_ERROR_RETURN 1189 (soc_reg_field32_modify(unit, GMACC0r, port, SRSTf, 1)); 1190 SOC_IF_ERROR_RETURN 1191 (soc_reg_field32_modify(unit, GMACC0r, port, SRSTf, 0)); 1192 } 1193 #endif 1194 } 1195 #endif /* BCM_FELIX_SUPPORT || BCM_RAPTOR_SUPPORT */ 1196 /* 1197 * Perform length check on Ethernet frames and do not allow huge frames 1198 */ 1199 SOC_IF_ERROR_RETURN(FE_READ(FE_MAC2r, GTH_FE_MAC2r, unit, port, ®32)); 1200 /* FULL_DUP=0 for workaround */ 1201 FE_SET(unit, port, FE_MAC2r, GTH_FE_MAC2r, FULL_DUPf, reg32, 0); 1202 FE_SET(unit, port, FE_MAC2r, GTH_FE_MAC2r, EXC_DEFf, reg32, 1); 1203 FE_SET(unit, port, FE_MAC2r, GTH_FE_MAC2r, LG_CHKf, reg32, 0); 1204 FE_SET(unit, port, FE_MAC2r, GTH_FE_MAC2r, HUGE_FRf, reg32, 0); 1205 FE_SET(unit, port, FE_MAC2r, GTH_FE_MAC2r, DEL_CRCf, reg32, 0); 1206 FE_SET(unit, port, FE_MAC2r, GTH_FE_MAC2r, CRC_ENf, reg32, 0); 1207 FE_SET(unit, port, FE_MAC2r, GTH_FE_MAC2r, PAD_ENf, reg32, 0); 1208 FE_SET(unit, port, FE_MAC2r, GTH_FE_MAC2r, VLAN_PADf, reg32, 0); 1209 FE_SET(unit, port, FE_MAC2r, GTH_FE_MAC2r, AUTO_PADf, reg32, 0); 1210 FE_SET(unit, port, FE_MAC2r, GTH_FE_MAC2r, PURE_PADf, reg32, 0); 1211 FE_SET(unit, port, FE_MAC2r, GTH_FE_MAC2r, LONG_PREf, reg32, 0); 1212 FE_SET(unit, port, FE_MAC2r, GTH_FE_MAC2r, NO_BOFFf, reg32, 0); 1213 FE_SET(unit, port, FE_MAC2r, GTH_FE_MAC2r, BP_NO_BOFFf, reg32, 0); 1214 SOC_IF_ERROR_RETURN(FE_WRITE(FE_MAC2r, GTH_FE_MAC2r, unit, port, reg32)); 1215 1216 SOC_IF_ERROR_RETURN(FE_READ(FE_CLRTr, GTH_FE_CLRTr, unit, port, ®32)); 1217 FE_SET(unit, port, FE_CLRTr, GTH_FE_CLRTr, COL_WINf, reg32, 0x37); 1218 FE_SET(unit, port, FE_CLRTr, GTH_FE_CLRTr, RETRYf, reg32, 0xf); 1219 SOC_IF_ERROR_RETURN(FE_WRITE(FE_CLRTr, GTH_FE_CLRTr, unit, port, reg32)); 1220 1221 if (soc_feature(unit, soc_feature_fe_maxframe)) { 1222 reg32 = 1518 + 1; 1223 SOC_IF_ERROR_RETURN(WRITE_FE_MAXFr(unit, port, reg32)); 1224 } 1225 1226 SOC_IF_ERROR_RETURN(FE_READ(FE_IPGRr, GTH_FE_IPGRr, unit, port, ®32)); 1227 FE_SET(unit, port, FE_IPGRr, GTH_FE_IPGRr, IPGR2f, reg32, 0x12); 1228 FE_SET(unit, port, FE_IPGRr, GTH_FE_IPGRr, IPGR1f, reg32, 0xc); 1229 SOC_IF_ERROR_RETURN(FE_WRITE(FE_IPGRr, GTH_FE_IPGRr, unit, port, reg32)); 1230 1231 SOC_IF_ERROR_RETURN(FE_READ(FE_SUPPr, GTH_FE_SUPPr, unit, port, ®32)); 1232 FE_SET(unit, port, FE_SUPPr, GTH_FE_SUPPr, SPEEDf, reg32, 1); 1233 FE_SET(unit, port, FE_SUPPr, GTH_FE_SUPPr, BIT_MODEf, reg32, 0); 1234 1235 SOC_IF_ERROR_RETURN(FE_WRITE(FE_SUPPr, GTH_FE_SUPPr, unit, port, reg32)); 1236 SOC_IF_ERROR_RETURN(FE_READ(FE_TESTr, GTH_FE_TESTr, unit, port, ®32)); 1237 FE_SET(unit, port, FE_TESTr, GTH_FE_TESTr, SHORT_QNTAf, reg32, 0); 1238 FE_SET(unit, port, FE_TESTr, GTH_FE_TESTr, TEST_PAUSEf, reg32, 0); 1239 FE_SET(unit, port, FE_TESTr, GTH_FE_TESTr, TEST_BACKf, reg32, 0); 1240 SOC_IF_ERROR_RETURN(FE_WRITE(FE_TESTr, GTH_FE_TESTr, unit, port, reg32)); 1241 1242 SOC_IF_ERROR_RETURN(FE_READ(FE_MAC1r, GTH_FE_MAC1r, unit, port, ®32)); 1243 if (!SOC_IS_XGS_SWITCH(unit)) { 1244 FE_SET(unit, port, FE_MAC1r, GTH_FE_MAC1r, SOFT_RSTf, reg32, 0); 1245 } 1246 1247 /* Enable pause on FE ports */ 1248 FE_SET(unit, port, FE_MAC1r, GTH_FE_MAC1r, TX_PAUf, reg32, 1); 1249 FE_SET(unit, port, FE_MAC1r, GTH_FE_MAC1r, RX_PAUf, reg32, 1); 1250 1251 FE_SET(unit, port, FE_MAC1r, GTH_FE_MAC1r, LBACKf, reg32, 0); 1252 FE_SET(unit, port, FE_MAC1r, GTH_FE_MAC1r, RX_ENf, reg32, 0); 1253 SOC_IF_ERROR_RETURN(FE_WRITE(FE_MAC1r, GTH_FE_MAC1r, unit, port, reg32)); 1254 1255 /* Clear station address */ 1256 reg32 = 0; 1257 SOC_IF_ERROR_RETURN(FE_WRITE(ESA0r, GTH_ESA0r, unit, port, reg32)); 1258 SOC_IF_ERROR_RETURN(FE_WRITE(ESA1r, GTH_ESA1r, unit, port, reg32)); 1259 SOC_IF_ERROR_RETURN(FE_WRITE(ESA2r, GTH_ESA2r, unit, port, reg32)); 1260 1261 /* Set IPG to match initial operating mode */ 1262 SOC_IF_ERROR_RETURN(mac_fe_ipg_update(unit, port)); 1263 1264 if (!IS_GE_PORT(unit, port)) { 1265 uint32 port_bit; 1266 1267 port_bit = (1 << (port % 8)); 1268 1269 #if defined(BCM_FELIX_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) 1270 if (IS_FE_PORT(unit, port) && soc_feature(unit, soc_feature_trimac)) { 1271 SOC_IF_ERROR_RETURN(READ_EGR_ENABLEr(unit, port, ®32)); 1272 soc_reg_field_set(unit, EGR_ENABLEr, ®32, PRT_ENABLEf, 1); 1273 SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port, reg32)); 1274 } else 1275 #endif /* BCM_FELIX_SUPPORT || BCM_RAPTOR_SUPPORT */ 1276 { 1277 /* Set egress enable */ 1278 SOC_IF_ERROR_RETURN(READ_EGR_ENABLEr(unit, port, ®32)); 1279 reg32 |= port_bit; 1280 SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port, reg32)); 1281 } 1282 } 1283 1284 return (SOC_E_NONE); 1285 } 1286 1287 /* 1288 * Function: 1289 * mac_fe_duplex_set 1290 * Purpose: 1291 * Set FE MAC in the specified duplex mode. 1292 * Parameters: 1293 * unit - StrataSwitch unit #. 1294 * port - StrataSwitch port # on unit. 1295 * duplex - Boolean: true --> full duplex, false --> half duplex. 1296 * Returns: 1297 * SOC_E_XXX 1298 * Notes: 1299 * Programs an IFG time appropriate to speed and duplex. 1300 * Also handles GTH ports (gig ports in 10/100 MAC mode). 1301 */ 1302 1303 STATIC int 1304 mac_fe_duplex_set(int unit, soc_port_t port, int duplex) 1305 { 1306 uint32 fe_mac2; 1307 int old_mac_en; 1308 1309 SOC_IF_ERROR_RETURN(mac_fe_enable_get(unit, port, &old_mac_en)); 1310 if (old_mac_en) { 1311 SOC_IF_ERROR_RETURN(mac_fe_enable_set(unit, port, FALSE)); 1312 } 1313 1314 SOC_IF_ERROR_RETURN(FE_READ(FE_MAC2r, GTH_FE_MAC2r, unit, port, &fe_mac2)); 1315 FE_SET(unit, port, FE_MAC2r, GTH_FE_MAC2r, 1316 FULL_DUPf, fe_mac2, duplex ? 1 : 0); 1317 SOC_IF_ERROR_RETURN(FE_WRITE(FE_MAC2r, GTH_FE_MAC2r, unit, port, fe_mac2)); 1318 1319 /* Set IPG to match new duplex */ 1320 SOC_IF_ERROR_RETURN(mac_fe_ipg_update(unit, port)); 1321 1322 if (old_mac_en) { 1323 SOC_IF_ERROR_RETURN(mac_fe_enable_set(unit, port, TRUE)); 1324 } 1325 1326 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) 1327 /* 1328 * Notify internal PHY driver of duplex change in case it is being 1329 * used as pass-through to an external PHY. 1330 */ 1331 if (soc_feature(unit, soc_feature_dodeca_serdes)) { 1332 if (IS_GE_PORT(unit, port)) { 1333 SOC_IF_ERROR_RETURN 1334 (soc_phyctrl_notify(unit, port, phyEventDuplex, duplex)); 1335 } 1336 } 1337 #endif /* BCM_FIREBOLT_SUPPORT || BCM_RAPTOR_SUPPORT */ 1338 1339 return (SOC_E_NONE); 1340 } 1341 1342 /* 1343 * Function: 1344 * mac_fe_duplex_get 1345 * Purpose: 1346 * Get FE MAC duplex mode. 1347 * Parameters: 1348 * unit - StrataSwitch unit #. 1349 * duplex - (OUT) Boolean: true --> full duplex, false --> half duplex. 1350 * Returns: 1351 * SOC_E_XXX 1352 */ 1353 1354 STATIC int 1355 mac_fe_duplex_get(int unit, soc_port_t port, int *duplex) 1356 { 1357 uint32 fe_mac2; 1358 1359 SOC_IF_ERROR_RETURN(FE_READ(FE_MAC2r, GTH_FE_MAC2r, unit, port, &fe_mac2)); 1360 1361 *duplex = FE_GET(unit, port, FE_MAC2r, GTH_FE_MAC2r, 1362 FULL_DUPf, fe_mac2) ? 1 : 0; 1363 1364 return (SOC_E_NONE); 1365 } 1366 1367 /* 1368 * Function: 1369 * mac_fe_speed_set 1370 * Purpose: 1371 * Set FE MAC in the specified speed. 1372 * Parameters: 1373 * unit - StrataSwitch unit #. 1374 * port - StrataSwitch port # on unit. 1375 * speed - 10,100 for speed. 1376 * Returns: 1377 * SOC_E_XXX 1378 * Notes: 1379 * On chips with a PHYMOD field: 1380 * If PHYMOD=0, the speed is hardwired to 100Mb/s. 1381 * If PHYMOD=1, the speed is obtained directly from the PHY. 1382 * In either case, FE_SUPP.SPEED is completely ignored. 1383 * Programs an IFG time appropriate to speed and duplex. 1384 */ 1385 1386 STATIC int 1387 mac_fe_speed_set(int unit, soc_port_t port, int speed) 1388 { 1389 uint32 fe_supp; 1390 1391 SOC_IF_ERROR_RETURN(FE_READ(FE_SUPPr, GTH_FE_SUPPr, unit, port, &fe_supp)); 1392 1393 switch (speed) { 1394 case 0: 1395 /* Leave speed unchanged; supports NULL PHY */ 1396 break; 1397 case 10: 1398 if (IS_FE_PORT(unit, port) && soc_feature(unit, soc_feature_trimac)) { 1399 SOC_IF_ERROR_RETURN(soc_mac_mode_set(unit, port, 1400 SOC_MAC_MODE_10)); 1401 } 1402 FE_SET(unit, port, FE_SUPPr, GTH_FE_SUPPr, SPEEDf, fe_supp, 0); 1403 break; 1404 case 100: 1405 if (IS_FE_PORT(unit, port) && soc_feature(unit, soc_feature_trimac)) { 1406 SOC_IF_ERROR_RETURN(soc_mac_mode_set(unit, port, 1407 SOC_MAC_MODE_10_100)); 1408 } 1409 FE_SET(unit, port, FE_SUPPr, GTH_FE_SUPPr, SPEEDf, fe_supp, 1); 1410 break; 1411 default: 1412 return (SOC_E_CONFIG); 1413 } 1414 1415 SOC_IF_ERROR_RETURN(FE_WRITE(FE_SUPPr, GTH_FE_SUPPr, unit, port, fe_supp)); 1416 1417 /* Set IPG to match new speed */ 1418 SOC_IF_ERROR_RETURN(mac_fe_ipg_update(unit, port)); 1419 1420 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) 1421 /* 1422 * Notify internal PHY driver of speed change in case it is being 1423 * used as pass-through to an external PHY. 1424 */ 1425 if (soc_feature(unit, soc_feature_dodeca_serdes)) { 1426 if (IS_GE_PORT(unit, port)) { 1427 SOC_IF_ERROR_RETURN 1428 (soc_phyctrl_notify(unit, port, phyEventSpeed, speed)); 1429 } 1430 } 1431 #endif /* BCM_FIREBOLT_SUPPORT || BCM_RAPTOR_SUPPORT */ 1432 1433 return (SOC_E_NONE); 1434 } 1435 1436 /* 1437 * Function: 1438 * mac_fe_speed_get 1439 * Purpose: 1440 * Get FE MAC speed 1441 * Parameters: 1442 * unit - StrataSwitch unit #. 1443 * port - StrataSwitch port # on unit. 1444 * speed - (OUT) speed in Mb (10/100) 1445 * Returns: 1446 * SOC_E_XXX 1447 * Notes: 1448 * On chips with a PHYMOD field: 1449 * If PHYMOD=0, the speed is hardwired to 100Mb/s. 1450 * If PHYMOD=1, the speed is obtained directly from the PHY. 1451 * In either case, FE_SUPP.SPEED is completely ignored. 1452 */ 1453 1454 STATIC int 1455 mac_fe_speed_get(int unit, soc_port_t port, int *speed) 1456 { 1457 uint32 fe_supp; 1458 1459 SOC_IF_ERROR_RETURN(FE_READ(FE_SUPPr, GTH_FE_SUPPr, unit, port, &fe_supp)); 1460 1461 if (FE_GET(unit, port, FE_SUPPr, GTH_FE_SUPPr, SPEEDf, fe_supp) == 1) { 1462 *speed = 100; 1463 } else { 1464 *speed = 10; 1465 } 1466 1467 return (SOC_E_NONE); 1468 } 1469 1470 /* 1471 * Function: 1472 * mac_fe_pause_set 1473 * Purpose: 1474 * Configure MAC to transmit/receive pause frames. 1475 * Parameters: 1476 * unit - StrataSwitch unit #. 1477 * port - StrataSwitch port # on unit. 1478 * pause_tx - Boolean: transmit pause, or -1 (don't change) 1479 * pause_rx - Boolean: receive pause, or -1 (don't change) 1480 * Returns: 1481 * SOC_E_XXX 1482 */ 1483 1484 STATIC int 1485 mac_fe_pause_set(int unit, soc_port_t port, int pause_tx, int pause_rx) 1486 { 1487 uint32 fe_mac1; 1488 1489 if (pause_tx < 0 && pause_rx < 0) { 1490 return SOC_E_NONE; 1491 } 1492 1493 SOC_IF_ERROR_RETURN(FE_READ(FE_MAC1r, GTH_FE_MAC1r, unit, port, &fe_mac1)); 1494 if (pause_rx >= 0) { 1495 FE_SET(unit, port, FE_MAC1r, GTH_FE_MAC1r, 1496 RX_PAUf, fe_mac1, pause_rx ? 1 : 0); 1497 } 1498 if (pause_tx >= 0) { 1499 FE_SET(unit, port, FE_MAC1r, GTH_FE_MAC1r, 1500 TX_PAUf, fe_mac1, pause_tx ? 1 : 0); 1501 } 1502 SOC_IF_ERROR_RETURN(FE_WRITE(FE_MAC1r, GTH_FE_MAC1r, unit, port, fe_mac1)); 1503 1504 return SOC_E_NONE; 1505 } 1506 1507 /* 1508 * Function: 1509 * mac_fe_pause_addr_set 1510 * Purpose: 1511 * Configure FE MAC PAUSE frame source address. 1512 * Parameters: 1513 * unit - StrataSwitch unit #. 1514 * port - StrataSwitch port # on unit. 1515 * pause_mac - MAC address used for pause transmission. 1516 * Returns: 1517 * SOC_E_XXX 1518 */ 1519 1520 STATIC int 1521 mac_fe_pause_addr_set(int unit, soc_port_t port, sal_mac_addr_t pause_mac) 1522 { 1523 uint32 esa0, esa1, esa2; 1524 1525 esa0 = 0; 1526 esa1 = 0; 1527 esa2 = 0; 1528 1529 FE_SET(unit, port, ESA0r, GTH_ESA0r, STAD0f, esa0, 1530 (pause_mac[4] << 8) | pause_mac[5]); 1531 FE_SET(unit, port, ESA1r, GTH_ESA1r, STAD0f, esa1, 1532 (pause_mac[2] << 8) | pause_mac[3]); 1533 FE_SET(unit, port, ESA2r, GTH_ESA2r, STAD0f, esa2, 1534 (pause_mac[0] << 8) | pause_mac[1]); 1535 1536 SOC_IF_ERROR_RETURN(FE_WRITE(ESA0r, GTH_ESA0r, unit, port, esa0)); 1537 SOC_IF_ERROR_RETURN(FE_WRITE(ESA1r, GTH_ESA1r, unit, port, esa1)); 1538 SOC_IF_ERROR_RETURN(FE_WRITE(ESA2r, GTH_ESA2r, unit, port, esa2)); 1539 1540 return (SOC_E_NONE); 1541 } 1542 1543 /* 1544 * Function: 1545 * mac_fe_pause_get 1546 * Purpose: 1547 * Return the ability of FE MAC 1548 * Parameters: 1549 * unit - StrataSwitch unit #. 1550 * port - StrataSwitch port # on unit. 1551 * pause_tx - Boolean: transmit pause 1552 * pause_rx - Boolean: receive pause 1553 * pause_mac - MAC address used for pause transmission. 1554 * Returns: 1555 * SOC_E_XXX 1556 */ 1557 1558 STATIC int 1559 mac_fe_pause_get(int unit, soc_port_t port, int *pause_tx, int *pause_rx) 1560 { 1561 uint32 fe_mac1; 1562 1563 SOC_IF_ERROR_RETURN(FE_READ(FE_MAC1r, GTH_FE_MAC1r, unit, port, &fe_mac1)); 1564 1565 *pause_rx = FE_GET(unit, port, FE_MAC1r, GTH_FE_MAC1r, 1566 RX_PAUf, fe_mac1) ? 1 : 0; 1567 *pause_tx = FE_GET(unit, port, FE_MAC1r, GTH_FE_MAC1r, 1568 TX_PAUf, fe_mac1) ? 1 : 0; 1569 1570 return (SOC_E_NONE); 1571 } 1572 1573 /* 1574 * Function: 1575 * mac_fe_pause_addr_set 1576 * Purpose: 1577 * Configure PAUSE frame source address. 1578 * Parameters: 1579 * unit - StrataSwitch unit #. 1580 * port - StrataSwitch port # on unit. 1581 * pause_mac - (OUT) MAC address used for pause transmission. 1582 * Returns: 1583 * SOC_E_XXX 1584 */ 1585 1586 STATIC int 1587 mac_fe_pause_addr_get(int unit, soc_port_t port, sal_mac_addr_t pause_mac) 1588 { 1589 uint32 esa0, esa1, esa2; 1590 uint32 b0_15, b16_31, b32_47; 1591 1592 SOC_IF_ERROR_RETURN(FE_READ(ESA0r, GTH_ESA0r, unit, port, &esa0)); 1593 SOC_IF_ERROR_RETURN(FE_READ(ESA1r, GTH_ESA1r, unit, port, &esa1)); 1594 SOC_IF_ERROR_RETURN(FE_READ(ESA2r, GTH_ESA2r, unit, port, &esa2)); 1595 1596 b0_15 = FE_GET(unit, port, ESA0r, GTH_ESA0r, STAD0f, esa0); 1597 b16_31 = FE_GET(unit, port, ESA1r, GTH_ESA1r, STAD0f, esa1); 1598 b32_47 = FE_GET(unit, port, ESA2r, GTH_ESA2r, STAD0f, esa2); 1599 1600 pause_mac[0] = (uint8)(b32_47 >> 8); 1601 pause_mac[1] = (uint8)(b32_47 >> 0); 1602 pause_mac[2] = (uint8)(b16_31 >> 8); 1603 pause_mac[3] = (uint8)(b16_31 >> 0); 1604 pause_mac[4] = (uint8)(b0_15 >> 8); 1605 pause_mac[5] = (uint8)(b0_15 >> 0); 1606 1607 return (SOC_E_NONE); 1608 } 1609 1610 /* 1611 * Function: 1612 * mac_fe_loopback_set 1613 * Purpose: 1614 * Set a MAC into/out-of loopback mode 1615 * Parameters: 1616 * unit - StrataSwitch unit #. 1617 * port - StrataSwitch unit # on unit. 1618 * loopback - Boolean: true -> loopback mode, false -> normal operation 1619 * Returns: 1620 * SOC_E_XXX 1621 */ 1622 1623 STATIC int 1624 mac_fe_loopback_set(int unit, soc_port_t port, int loopback) 1625 { 1626 uint32 fe_mac1; 1627 1628 SOC_IF_ERROR_RETURN(FE_READ(FE_MAC1r, GTH_FE_MAC1r, unit, port, &fe_mac1)); 1629 FE_SET(unit, port, FE_MAC1r, GTH_FE_MAC1r, 1630 LBACKf, fe_mac1, loopback ? 1 : 0); 1631 SOC_IF_ERROR_RETURN(FE_WRITE(FE_MAC1r, GTH_FE_MAC1r, unit, port, fe_mac1)); 1632 1633 return (SOC_E_NONE); 1634 } 1635 1636 /* 1637 * Function: 1638 * mac_fe_loopback_get 1639 * Purpose: 1640 * Get current FE MAC loopback mode setting. 1641 * Parameters: 1642 * unit - StrataSwitch unit #. 1643 * port - StrataSwitch port # on unit. 1644 * loopback - (OUT) Boolean: true = loopback, false = normal 1645 * Returns: 1646 * SOC_E_XXX 1647 */ 1648 1649 STATIC int 1650 mac_fe_loopback_get(int unit, soc_port_t port, int *loopback) 1651 { 1652 int rv; 1653 uint32 fe_mac1; 1654 1655 if ((rv = FE_READ(FE_MAC1r, GTH_FE_MAC1r, 1656 unit, port, &fe_mac1)) == SOC_E_NONE) { 1657 *loopback = FE_GET(unit, port, FE_MAC1r, GTH_FE_MAC1r, 1658 LBACKf, fe_mac1); 1659 } 1660 1661 return(rv); 1662 } 1663 1664 /* 1665 * Function: 1666 * mac_fe_interface_set 1667 * Purpose: 1668 * Set a FE MAC interface type 1669 * Parameters: 1670 * unit - StrataSwitch unit #. 1671 * port - StrataSwitch port # on unit. 1672 * pif - one of SOC_PORT_IF_* 1673 * Returns: 1674 * SOC_E_NONE 1675 * SOC_E_UNAVAIL - requested mode not supported. 1676 * Notes: 1677 * Only MII supported on FE ports. 1678 */ 1679 1680 STATIC int 1681 mac_fe_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 1682 { 1683 COMPILER_REFERENCE(unit); 1684 COMPILER_REFERENCE(port); 1685 1686 switch (pif) { 1687 case SOC_PORT_IF_MII: 1688 return SOC_E_NONE; 1689 default: 1690 return SOC_E_UNAVAIL; 1691 } 1692 } 1693 1694 /* 1695 * Function: 1696 * mac_fe_interface_get 1697 * Purpose: 1698 * Retrieve FE MAC interface type 1699 * Parameters: 1700 * unit - StrataSwitch unit #. 1701 * port - StrataSwitch port # on unit. 1702 * pif - (OUT) one of SOC_PORT_IF_* 1703 * Returns: 1704 * SOC_E_NONE 1705 */ 1706 1707 STATIC int 1708 mac_fe_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 1709 { 1710 COMPILER_REFERENCE(unit); 1711 COMPILER_REFERENCE(port); 1712 1713 *pif = SOC_PORT_IF_MII; 1714 1715 return (SOC_E_NONE); 1716 } 1717 1718 /* 1719 * Function: 1720 * mac_fe_ability_get 1721 * Purpose: 1722 * Return the abilities of FE MAC 1723 * Parameters: 1724 * unit - StrataSwitch unit #. 1725 * port - StrataSwitch port # on unit. 1726 * mode - (OUT) Supported operating modes as a mask of abilities. 1727 * Returns: 1728 * SOC_E_XXX 1729 */ 1730 1731 STATIC int 1732 mac_fe_ability_get(int unit, soc_port_t port, soc_port_mode_t *mode) 1733 { 1734 COMPILER_REFERENCE(unit); 1735 1736 if (IS_FE_PORT(unit, port)) { 1737 /* Asymmetric pause not available (SOC_PM_PAUSE_ASYMM) */ 1738 *mode = (SOC_PM_10MB | SOC_PM_100MB | SOC_PM_PAUSE | 1739 SOC_PM_MII | SOC_PM_LB_MAC); 1740 return (SOC_E_NONE); 1741 } else { 1742 *mode = 0; 1743 return (SOC_E_UNAVAIL); 1744 } 1745 } 1746 1747 /* 1748 * Function: 1749 * mac_fe_frame_max_set 1750 * Description: 1751 * Set the maximum receive frame size for the GE port 1752 * Parameters: 1753 * unit - Device number 1754 * port - Port number 1755 * size - Maximum frame size in bytes 1756 * Return Value: 1757 * BCM_E_XXX 1758 * Notes: 1759 * 1) Depending on chip or port type the actual maximum receive frame 1760 * size might be slightly higher. 1761 */ 1762 1763 STATIC int 1764 mac_fe_frame_max_set(int unit, soc_port_t port, int size) 1765 { 1766 uint32 val32; 1767 1768 if (soc_feature(unit, soc_feature_fe_maxframe)) { 1769 size += 1; /* XGS3 FE MAC MAX_FR is one greater than MAX len */ 1770 } 1771 1772 val32 = size; 1773 1774 return FE_WRITE(FE_MAXFr, GTH_FE_MAXFr, unit, port, val32); 1775 } 1776 1777 /* 1778 * Function: 1779 * mac_fe_frame_max_get 1780 * Description: 1781 * Set the maximum receive frame size for the GE port 1782 * Parameters: 1783 * unit - Device number 1784 * port - Port number 1785 * size - Maximum frame size in bytes 1786 * Return Value: 1787 * BCM_E_XXX 1788 * Notes: 1789 * 1) Depending on chip or port type the actual maximum receive frame 1790 * size might be slightly higher. 1791 */ 1792 STATIC int 1793 mac_fe_frame_max_get(int unit, soc_port_t port, int *size) 1794 { 1795 uint32 val32; 1796 1797 SOC_IF_ERROR_RETURN(FE_READ(FE_MAXFr, GTH_FE_MAXFr, unit, port, &val32)); 1798 *size = val32; 1799 1800 if (soc_feature(unit, soc_feature_fe_maxframe)) { 1801 *size -= 1; /* XGS3 FE MAC MAX_FR is one greater than MAX len */ 1802 } 1803 1804 return SOC_E_NONE; 1805 } 1806 1807 /* 1808 * Function: 1809 * mac_fe_ifg_set 1810 * Description: 1811 * Sets the new ifg (Inter-frame gap) value 1812 * Parameters: 1813 * unit - Device number 1814 * port - Port number 1815 * speed - the speed for which the IFG is being set 1816 * duplex - the duplex for which the IFG is being set 1817 * ifg - Inter-frame gap in bit-times 1818 * Return Value: 1819 * BCM_E_XXX 1820 * Notes: 1821 * The function makes sure the IFG value makes sense and updates the 1822 * IPG register in case the speed/duplex match the current settings 1823 */ 1824 STATIC int 1825 mac_fe_ifg_set(int unit, soc_port_t port, int speed, soc_port_duplex_t duplex, 1826 int ifg) 1827 { 1828 int cur_speed; 1829 int cur_duplex; 1830 int ipg; 1831 int real_ifg; 1832 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 1833 int rv; 1834 1835 SOC_IF_ERROR_RETURN(mac_fe_ifg_to_ipg(unit, port, speed, duplex, 1836 ifg, &ipg)); 1837 SOC_IF_ERROR_RETURN(mac_fe_ipg_to_ifg(unit, port, speed, duplex, 1838 ipg, &real_ifg)); 1839 1840 if (duplex) { 1841 switch (speed) { 1842 case 10: 1843 si->fd_10 = real_ifg; 1844 break; 1845 case 100: 1846 si->fd_100 = real_ifg; 1847 break; 1848 default: 1849 return SOC_E_PARAM; 1850 break; 1851 } 1852 } else { 1853 switch (speed) { 1854 case 10: 1855 si->hd_10 = real_ifg; 1856 /* coverity[equality_cond] */ 1857 break; 1858 case 100: 1859 si->hd_100 = real_ifg; 1860 break; 1861 default: 1862 return SOC_E_PARAM; 1863 break; 1864 } 1865 } 1866 1867 SOC_IF_ERROR_RETURN(mac_fe_duplex_get(unit, port, &cur_duplex)); 1868 SOC_IF_ERROR_RETURN(mac_fe_speed_get(unit, port, &cur_speed)); 1869 1870 if (cur_speed == speed && ((soc_port_duplex_t)cur_duplex == duplex)) { 1871 switch (speed) { 1872 case 10: 1873 case 100: 1874 rv = mac_fe_ipg_update(unit, port); 1875 break; 1876 /* coverity[dead_error_begin] */ 1877 default: 1878 rv = SOC_E_PARAM; 1879 } 1880 } else { 1881 rv = SOC_E_NONE; 1882 } 1883 1884 return (rv); 1885 } 1886 1887 /* 1888 * Function: 1889 * mac_fe_ifg_get 1890 * Description: 1891 * Gets the ifg (Inter-frame gap) value for a specific speed/duplex 1892 * combination 1893 * Parameters: 1894 * unit - Device number 1895 * port - Port number 1896 * speed - the speed for which the IFG is being set 1897 * duplex - the duplex for which the IFG is being set 1898 * ifg - Inter-frame gap in bit-times 1899 * Return Value: 1900 * BCM_E_XXX 1901 * Notes: 1902 * The function returns the REAL ifg value that will be (or is currently) 1903 * used by the chip, which might be different from the value initially 1904 * set by the ifg_set() call. The reason for that is that only certain 1905 * values are allowed. 1906 */ 1907 STATIC int 1908 mac_fe_ifg_get(int unit, soc_port_t port, int speed, soc_port_duplex_t duplex, 1909 int *ifg) 1910 { 1911 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 1912 1913 if (duplex) { 1914 switch (speed) { 1915 case 10: 1916 *ifg = si->fd_10; 1917 break; 1918 case 100: 1919 *ifg = si->fd_100; 1920 break; 1921 default: 1922 return SOC_E_PARAM; 1923 break; 1924 } 1925 } else { 1926 switch (speed) { 1927 case 10: 1928 *ifg = si->hd_10; 1929 break; 1930 case 100: 1931 *ifg = si->hd_100; 1932 break; 1933 default: 1934 return SOC_E_PARAM; 1935 break; 1936 } 1937 } 1938 1939 return SOC_E_NONE; 1940 } 1941 1942 /* 1943 * Function: 1944 * mac_fe_encap_set 1945 * Purpose: 1946 * Set the port encapsulation mode. 1947 * Parameters: 1948 * unit - XGS unit #. 1949 * port - XGS port # on unit. 1950 * mode - encapsulation mode 1951 * Returns: 1952 * SOC_E_XXX 1953 */ 1954 STATIC int 1955 mac_fe_encap_set(int unit, soc_port_t port, int mode) 1956 { 1957 if (mode == SOC_ENCAP_IEEE) { 1958 return SOC_E_NONE; 1959 } 1960 return SOC_E_PARAM; 1961 } 1962 1963 /* 1964 * Function: 1965 * mac_fe_encap_get 1966 * Purpose: 1967 * Get the port encapsulation mode. 1968 * Parameters: 1969 * unit - XGS unit #. 1970 * port - XGS port # on unit. 1971 * mode - (INT) encapsulation mode 1972 * Returns: 1973 * SOC_E_XXX 1974 */ 1975 STATIC int 1976 mac_fe_encap_get(int unit, soc_port_t port, int *mode) 1977 { 1978 *mode = SOC_ENCAP_IEEE; 1979 1980 return SOC_E_NONE; 1981 } 1982 1983 /* 1984 * Function: 1985 * mac_fe_ability_local_get 1986 * Purpose: 1987 * Return the abilities of FE MAC 1988 * Parameters: 1989 * unit - StrataSwitch unit #. 1990 * port - StrataSwitch port # on unit. 1991 * mode - (OUT) Supported operating modes as a mask of abilities. 1992 * Returns: 1993 * SOC_E_XXX 1994 */ 1995 1996 STATIC int 1997 mac_fe_ability_local_get(int unit, soc_port_t port, 1998 soc_port_ability_t *ability) 1999 { 2000 if (NULL == ability) { 2001 return (SOC_E_PARAM); 2002 } 2003 2004 if (IS_FE_PORT(unit, port)) { 2005 ability->speed_half_duplex = SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB; 2006 ability->speed_full_duplex = SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB; 2007 ability->pause = SOC_PA_PAUSE; 2008 ability->interface = SOC_PA_INTF_MII; 2009 ability->medium = SOC_PA_ABILITY_NONE; 2010 ability->loopback = SOC_PA_LB_MAC; 2011 ability->flags = SOC_PA_ABILITY_NONE; 2012 ability->encap = SOC_PA_ENCAP_IEEE; 2013 return (SOC_E_NONE); 2014 } else { 2015 return (SOC_E_UNAVAIL); 2016 } 2017 } 2018 2019 /* Exported FE MAC driver structure */ 2020 mac_driver_t soc_mac_fe = { 2021 "10Mb/100Mb MAC Driver", /* drv_name */ 2022 mac_fe_init, /* md_init */ 2023 mac_fe_enable_set, /* md_enable_set */ 2024 mac_fe_enable_get, /* md_enable_get */ 2025 mac_fe_duplex_set, /* md_duplex_set */ 2026 mac_fe_duplex_get, /* md_duplex_get */ 2027 mac_fe_speed_set, /* md_speed_set */ 2028 mac_fe_speed_get, /* md_speed_get */ 2029 mac_fe_pause_set, /* md_pause_set */ 2030 mac_fe_pause_get, /* md_pause_get */ 2031 mac_fe_pause_addr_set, /* md_pause_addr_set */ 2032 mac_fe_pause_addr_get, /* md_pause_addr_get */ 2033 mac_fe_loopback_set, /* md_lb_set */ 2034 mac_fe_loopback_get, /* md_lb_get */ 2035 mac_fe_interface_set, /* md_interface_set */ 2036 mac_fe_interface_get, /* md_interface_get */ 2037 mac_fe_ability_get, /* md_ability_get */ 2038 mac_fe_frame_max_set, /* md_frame_max_set */ 2039 mac_fe_frame_max_get, /* md_frame_max_get */ 2040 mac_fe_ifg_set, /* md_ifg_set */ 2041 mac_fe_ifg_get, /* md_ifg_get */ 2042 mac_fe_encap_set, /* md_encap_set */ 2043 mac_fe_encap_get, /* md_encap_get */ 2044 NULL, /* md_control_set */ 2045 NULL, /* md_control_get */ 2046 mac_fe_ability_local_get, /* md_ability_local_get */ 2047 NULL, /* md_timesync_tx_info_get */ 2048 }; 2049 2050 /* 2051 * Function: 2052 * mac_ge_enable_set 2053 * Purpose: 2054 * Enable or disable MAC 2055 * Parameters: 2056 * unit - StrataSwitch unit #. 2057 * port - Port number on unit. 2058 * enable - TRUE to enable, FALSE to disable 2059 * Returns: 2060 * SOC_E_XXX 2061 */ 2062 2063 STATIC int 2064 mac_ge_enable_set(int unit, soc_port_t port, int enable) 2065 { 2066 uint32 gmacc1, ogmacc1; 2067 soc_mac_mode_t mode; 2068 pbmp_t mask; 2069 2070 SOC_IF_ERROR_RETURN(soc_mac_mode_get(unit, port, &mode)); 2071 2072 if ((mode == SOC_MAC_MODE_10_100) || (mode == SOC_MAC_MODE_10)) { 2073 return (mac_fe_enable_set(unit, port, enable)); 2074 } 2075 2076 /* 2077 * Turn on/off receive enable. 2078 * 2079 * We do not bother then TXEN because on some chips this signal does 2080 * not take effect (get latched) until traffic stops flowing. 2081 */ 2082 2083 SOC_IF_ERROR_RETURN(READ_GMACC1r(unit, port, &gmacc1)); 2084 ogmacc1 = gmacc1; 2085 if (enable) { 2086 soc_reg_field_set(unit, GMACC1r, &gmacc1, TXEN0f, 1); 2087 soc_reg_field_set(unit, GMACC1r, &gmacc1, RXEN0f, 1); 2088 } else { /* Turn off Receive Enable */ 2089 soc_reg_field_set(unit, GMACC1r, &gmacc1, RXEN0f, 0); 2090 } 2091 if (gmacc1 != ogmacc1) { 2092 SOC_IF_ERROR_RETURN(WRITE_GMACC1r(unit, port, gmacc1)); 2093 } 2094 2095 /* 2096 * Use EPC_LINK to control other ports sending to this port. This 2097 * blocking is independent and in addition to what Linkscan does. 2098 * 2099 * Single-step mode is used to stop traffic from going from the 2100 * egress to the MAC. 2101 */ 2102 2103 if (!enable) { 2104 soc_link_mask2_get(unit, &mask); 2105 SOC_PBMP_PORT_REMOVE(mask, port); 2106 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 2107 2108 SOC_IF_ERROR_RETURN(soc_drain_cells(unit, port)); 2109 2110 } else { 2111 soc_link_mask2_get(unit, &mask); 2112 SOC_PBMP_PORT_ADD(mask, port); 2113 SOC_IF_ERROR_RETURN(soc_link_mask2_set(unit, mask)); 2114 } 2115 2116 /* 2117 * The SERDES PHY is kept in reset whenever the MAC is 2118 * disabled. When the link comes up, the SERDES PHY must come out 2119 * of reset last, *after* the speed and duplex are programmed. If 2120 * the SERDES PHY is reset after the external PHY has link, a false 2121 * carrier is generated which can cause certain remote hardware to 2122 * drop link. SEE ALSO: mac_fe_enable_set. 2123 */ 2124 2125 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) 2126 if (soc_feature(unit, soc_feature_dodeca_serdes)) { 2127 if (IS_GE_PORT(unit, port)) { 2128 if (enable) { 2129 SOC_IF_ERROR_RETURN 2130 (soc_phyctrl_notify(unit, port, 2131 phyEventResume, PHY_STOP_MAC_DIS)); 2132 } else { 2133 SOC_IF_ERROR_RETURN 2134 (soc_phyctrl_notify(unit, port, 2135 phyEventStop, PHY_STOP_MAC_DIS)); 2136 } 2137 } 2138 } 2139 #endif /* BCM_FIREBOLT_SUPPORT || BCM_RAPTOR_SUPPORT */ 2140 2141 return SOC_E_NONE; 2142 } 2143 2144 /* 2145 * Function: 2146 * mac_ge_enable_get 2147 * Purpose: 2148 * Get MAC enable state 2149 * Parameters: 2150 * unit - StrataSwitch unit #. 2151 * port - Port number on unit. 2152 * enable - (OUT) TRUE if enabled, FALSE if disabled 2153 * Returns: 2154 * SOC_E_XXX 2155 */ 2156 2157 STATIC int 2158 mac_ge_enable_get(int unit, soc_port_t port, int *enable) 2159 { 2160 soc_mac_mode_t mode; 2161 2162 SOC_IF_ERROR_RETURN(soc_mac_mode_get(unit, port, &mode)); 2163 2164 if ((mode == SOC_MAC_MODE_10_100) || (mode == SOC_MAC_MODE_10)) { 2165 return (mac_fe_enable_get(unit, port, enable)); 2166 } else { 2167 uint32 gmacc1; 2168 2169 SOC_IF_ERROR_RETURN(READ_GMACC1r(unit, port, &gmacc1)); 2170 2171 *enable = soc_reg_field_get(unit, GMACC1r, gmacc1, RXEN0f); 2172 } 2173 2174 return SOC_E_NONE; 2175 } 2176 2177 /* 2178 * Function: 2179 * mac_ge_ifg_to_ipg 2180 * Description: 2181 * Converts the inter-frame gap specified in bit-times into a value 2182 * suitable to be programmed into the IPG register 2183 * Parameters: 2184 * unit - Device number 2185 * port - Port number 2186 * speed - the speed for which the IFG is being set 2187 * duplex - the duplex for which the IFG is being set 2188 * ifg - Inter-frame gap in bit-times 2189 * ipg - (OUT) the value to be written into IPG 2190 * Return Value: 2191 * BCM_E_XXX 2192 * Notes: 2193 * The function makes sure the calculated IPG value will not cause 2194 * hardware to fail. If the requested ifg value cannot be supported in 2195 * hardware, the function will choose a value that approximates the 2196 * requested value as best as possible. 2197 * 2198 * Specifically: 2199 * -- Current chips only support ifg which is divisible by 8. If 2200 * the specified ifg is not divisible by 8, it will be rounded 2201 * to the next multiplier of 8 (65 will result in 72). 2202 * -- ifg < 64 are not supported 2203 * 2204 * This function supports only GE portion of GE MAC (FE portion is 2205 * supported by mac_fe_ipg_* functions 2206 */ 2207 STATIC int 2208 mac_ge_ifg_to_ipg(int unit, soc_port_t port, int speed, int duplex, 2209 int ifg, int *ipg) 2210 { 2211 /* 2212 * The inter-frame gap should be a multiple of 8 bit-times. 2213 */ 2214 ifg = (ifg + 7) & ~7; 2215 2216 /* 2217 * The smallest supported ifg is 64 bit-times 2218 */ 2219 ifg = (ifg < 64) ? 64 : ifg; 2220 2221 /* 2222 * Now we need to convert the value according to various chips' 2223 * peculiarities (there are none as of now) 2224 */ 2225 *ipg = ifg / 8; 2226 2227 return SOC_E_NONE; 2228 } 2229 2230 /* 2231 * Function: 2232 * mac_ge_ipg_to_ifg 2233 * Description: 2234 * Converts the IPG register value into the inter-frame gap expressed in 2235 * bit-times 2236 * Parameters: 2237 * unit - Device number 2238 * port - Port number 2239 * speed - the speed for which the IFG is being set 2240 * duplex - the duplex for which the IFG is being set 2241 * ipg - the value in the IPG register 2242 * ifg - Inter-frame gap in bit-times 2243 * Return Value: 2244 * BCM_E_XXX 2245 * Notes: 2246 * This function supports only GE portion of GE MAC (FE portion is 2247 * supported by mac_fe_ipg_* functions 2248 */ 2249 STATIC int 2250 mac_ge_ipg_to_ifg(int unit, soc_port_t port, int speed, int duplex, 2251 int ipg, int *ifg) 2252 { 2253 /* 2254 * Now we need to convert the value according to various chips' 2255 * peculiarities (there are none as of now) 2256 */ 2257 *ifg = ipg * 8; 2258 2259 return SOC_E_NONE; 2260 } 2261 2262 /* 2263 * Function: 2264 * mac_ge_ipg_update 2265 * Purpose: 2266 * Set the IPG appropriate for current duplex 2267 * Parameters: 2268 * unit - StrataSwitch unit #. 2269 * port - Port number on unit. 2270 * Notes: 2271 * The current duplex is read from the hardware registers. 2272 */ 2273 2274 STATIC int 2275 mac_ge_ipg_update(int unit, int port) 2276 { 2277 uint32 gmacc2, ogmacc2; 2278 int fd, speed, ipg, ifg; 2279 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 2280 2281 SOC_IF_ERROR_RETURN(mac_ge_duplex_get(unit, port, &fd)); 2282 SOC_IF_ERROR_RETURN(mac_ge_speed_get(unit, port, &speed)); 2283 2284 if (fd) { 2285 switch (speed) { 2286 case 10: 2287 case 100: 2288 return (mac_fe_ipg_update(unit, port)); 2289 break; 2290 case 1000: 2291 ifg = si->fd_1000; 2292 break; 2293 case 2500: 2294 ifg = si->fd_2500; 2295 break; 2296 default: 2297 return SOC_E_INTERNAL; 2298 break; 2299 } 2300 } else { 2301 switch (speed) { 2302 case 10: 2303 case 100: 2304 return (mac_fe_ipg_update(unit, port)); 2305 break; 2306 case 1000: 2307 ifg = si->hd_1000; 2308 break; 2309 case 2500: 2310 ifg = si->hd_2500; 2311 break; 2312 default: 2313 return SOC_E_INTERNAL; 2314 break; 2315 } 2316 } 2317 2318 /* 2319 * Convert the ifg value from bit-times into IPG register-specific value 2320 */ 2321 SOC_IF_ERROR_RETURN(mac_ge_ifg_to_ipg(unit, port, speed, fd, ifg, &ipg)); 2322 2323 /* 2324 * Program the appropriate register (if necessary) 2325 */ 2326 SOC_IF_ERROR_RETURN(READ_GMACC2r(unit, port, &gmacc2)); 2327 ogmacc2 = gmacc2; 2328 soc_reg_field_set(unit, GMACC2r, &gmacc2, IPGTf, ipg); 2329 if (gmacc2 != ogmacc2) { 2330 SOC_IF_ERROR_RETURN(WRITE_GMACC2r(unit, port, gmacc2)); 2331 } 2332 2333 return SOC_E_NONE; 2334 } 2335 2336 /* 2337 * Function: 2338 * mac_ge_init 2339 * Purpose: 2340 * Initialize the gigabit MAC into a known good state. 2341 * Parameters: 2342 * unit - StrataSwitch unit #. 2343 * port - StrataSwitch port # on unit. 2344 * Returns: 2345 * SOC_E_XXX 2346 * Notes: 2347 * Both the FE and GE MACs are initialized. 2348 * The initialization speed/duplex is arbitrary and must be 2349 * updated by linkscan before enabling the MAC. 2350 */ 2351 2352 STATIC int 2353 mac_ge_init(int unit, soc_port_t port) 2354 { 2355 uint32 gmacc0, gmacc1, gmacc2, val32; 2356 uint32 ogmacc0, ogmacc1, ogmacc2; 2357 uint32 pctrl; 2358 2359 /* 2360 * Initialize 10/100MB/s MAC if present 2361 */ 2362 if (soc_feature(unit, soc_feature_fe_gig_macs)) { 2363 SOC_IF_ERROR_RETURN(soc_mac_mode_set(unit, port, 2364 SOC_MAC_MODE_10_100)); 2365 SOC_IF_ERROR_RETURN(mac_fe_init(unit, port)); 2366 } 2367 2368 /* 2369 * Initialize 1000Mb/s MAC 2370 */ 2371 SOC_IF_ERROR_RETURN(soc_mac_mode_set(unit, port, SOC_MAC_MODE_1000_T)); 2372 2373 SOC_IF_ERROR_RETURN(READ_GMACC0r(unit, port, &gmacc0)); 2374 SOC_IF_ERROR_RETURN(READ_GMACC1r(unit, port, &gmacc1)); 2375 SOC_IF_ERROR_RETURN(READ_GMACC2r(unit, port, &gmacc2)); 2376 ogmacc0 = gmacc0; 2377 ogmacc1 = gmacc1; 2378 ogmacc2 = gmacc2; 2379 soc_reg_field_set(unit, GMACC0r, &gmacc0, SRSTf, 0); 2380 soc_reg_field_set(unit, GMACC0r, &gmacc0, L10Bf, 0); 2381 soc_reg_field_set(unit, GMACC0r, &gmacc0, L32Bf, 0); 2382 soc_reg_field_set(unit, GMACC0r, &gmacc0, TMDSf, 0); 2383 2384 soc_reg_field_set(unit, GMACC1r, &gmacc1, FULLDf, 1); /* arbitrary */ 2385 if (IS_ST_PORT(unit, port)) { 2386 /* Flow control should not be enabled in stacking mode. */ 2387 soc_reg_field_set(unit, GMACC1r, &gmacc1, FCTXf, 0); /* Flow ctl */ 2388 soc_reg_field_set(unit, GMACC1r, &gmacc1, FCRXf, 0); /* Flow ctl */ 2389 } else { 2390 soc_reg_field_set(unit, GMACC1r, &gmacc1, FCTXf, 1); /* Flow ctl */ 2391 soc_reg_field_set(unit, GMACC1r, &gmacc1, FCRXf, 1); /* Flow ctl */ 2392 } 2393 soc_reg_field_set(unit, GMACC1r, &gmacc1, LONGPf, 1); 2394 soc_reg_field_set(unit, GMACC1r, &gmacc1, MIFGf, 2); 2395 soc_reg_field_set(unit, GMACC1r, &gmacc1, GLVRf, 1); 2396 soc_reg_field_set(unit, GMACC1r, &gmacc1, TXEN0f, 0); 2397 soc_reg_field_set(unit, GMACC1r, &gmacc1, RXEN0f, 0); 2398 soc_reg_field_set(unit, GMACC1r, &gmacc1, JUMBOf, 1); /* HUGEN=0 */ 2399 2400 pctrl = 0; 2401 soc_reg_field_set(unit, PAUSE_CONTROLr, &pctrl, ENABLEf, 1); 2402 soc_reg_field_set(unit, PAUSE_CONTROLr, &pctrl, VALUEf, 2403 PAUSE_VAL(512)); 2404 2405 SOC_IF_ERROR_RETURN(WRITE_PAUSE_CONTROLr(unit, port, pctrl)); 2406 2407 val32 = 0; 2408 SOC_IF_ERROR_RETURN(WRITE_TEST2r(unit, port, val32)); 2409 2410 if (gmacc2 != ogmacc2) { 2411 SOC_IF_ERROR_RETURN(WRITE_GMACC2r(unit, port, gmacc2)); 2412 } 2413 if (gmacc1 != ogmacc1) { 2414 SOC_IF_ERROR_RETURN(WRITE_GMACC1r(unit, port, gmacc1)); 2415 } 2416 if (gmacc0 != ogmacc0) { 2417 SOC_IF_ERROR_RETURN(WRITE_GMACC0r(unit, port, gmacc0)); 2418 } 2419 2420 #if defined(BCM_RAPTOR_SUPPORT) 2421 if (IS_S_PORT(unit, port)) { 2422 soc_pbmp_t pbmp_s0; 2423 #if defined(BCM_RAPTOR1_SUPPORT) 2424 int support_2_5g = 0; 2425 #endif 2426 2427 /* Select between 2.5 and 1G mode */ 2428 if (!PHY_EXTERNAL_MODE(unit, port)) { 2429 mac_ge_frame_max_set(unit, port, JUMBO_MAXSZ); 2430 #if defined(BCM_RAPTOR1_SUPPORT) 2431 support_2_5g = 1; 2432 #endif 2433 } else { 2434 mac_ge_frame_max_set(unit, port, 1518); 2435 } 2436 2437 SOC_IF_ERROR_RETURN(READ_GPORT_CONFIGr(unit, port, &val32)); 2438 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, CLR_CNTf, 1); 2439 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, GPORT_ENf, 1); 2440 SOC_PBMP_WORD_SET(pbmp_s0, 0, 0x00000002); 2441 if (SOC_PBMP_MEMBER(pbmp_s0, port)) { 2442 /* The "SOP check enables" are not gated with "HiGig2 enables" 2443 * and "bond_disable_stacking". 2444 * Thus software need to enable/disable the SOP drop check 2445 * in HiGig2 mode as desired. 2446 */ 2447 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, 2448 DROP_ON_WRONG_SOP_EN_S0f, 0); 2449 #if defined(BCM_RAPTOR1_SUPPORT) 2450 /* Select 2.5 Gbps or 1 Gbps mode. */ 2451 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, 2452 PLL_MODE_DEF_S0f, support_2_5g); 2453 #endif 2454 /* Enable HiGig 2 */ 2455 /* Assuming that always use stacking port in HiGig mode */ 2456 /* Actually, stacking port can also be used in ethernet mode */ 2457 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, 2458 HGIG2_EN_S0f, IS_ST_PORT(unit, port) ? 1 : 0); 2459 #if defined(BCM_RAPTOR1_SUPPORT) 2460 /* Select LCPLL as reference clock */ 2461 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, 2462 SEL_LCPLL_S0f, 1); 2463 #endif 2464 } else { 2465 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, 2466 DROP_ON_WRONG_SOP_EN_S1f, 0); 2467 #if defined(BCM_RAPTOR1_SUPPORT) 2468 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, 2469 PLL_MODE_DEF_S1f, support_2_5g); 2470 #endif 2471 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, 2472 HGIG2_EN_S1f, IS_ST_PORT(unit, port) ? 1 : 0); 2473 #if defined(BCM_RAPTOR1_SUPPORT) 2474 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, 2475 SEL_LCPLL_S1f, 1); 2476 #endif 2477 } 2478 SOC_IF_ERROR_RETURN(WRITE_GPORT_CONFIGr(unit, port, val32)); 2479 2480 /* Reset the clear-count bit after 64 clocks */ 2481 SOC_IF_ERROR_RETURN(READ_GPORT_CONFIGr(unit, port, &val32)); 2482 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, CLR_CNTf, 0); 2483 SOC_IF_ERROR_RETURN(WRITE_GPORT_CONFIGr(unit, port, val32)); 2484 } 2485 #endif /* BCM_RAPTOR_SUPPORT */ 2486 2487 /* Clear station address */ 2488 val32 = 0; 2489 SOC_IF_ERROR_RETURN(WRITE_GSA0r(unit, port, val32)); 2490 SOC_IF_ERROR_RETURN(WRITE_GSA1r(unit, port, val32)); 2491 2492 /* Set IPG to match initial operating mode */ 2493 SOC_IF_ERROR_RETURN(mac_ge_ipg_update(unit, port)); 2494 2495 /* Set receive IPGs */ 2496 switch (SOC_CHIP_GROUP(unit)) { 2497 case SOC_CHIP_BCM56504: 2498 case SOC_CHIP_BCM56102: 2499 case SOC_CHIP_BCM56304: 2500 case SOC_CHIP_BCM56800: 2501 case SOC_CHIP_BCM56218: 2502 case SOC_CHIP_BCM56112: 2503 case SOC_CHIP_BCM56314: 2504 case SOC_CHIP_BCM56514: 2505 case SOC_CHIP_BCM56624: 2506 case SOC_CHIP_BCM56820: 2507 case SOC_CHIP_BCM56680: 2508 case SOC_CHIP_BCM56634: 2509 case SOC_CHIP_BCM56524: 2510 case SOC_CHIP_BCM56685: 2511 case SOC_CHIP_BCM88732: 2512 val32 = 0; 2513 soc_reg_field_set(unit, FE_IPGRr, &val32, IPGR1f, 0x6); 2514 soc_reg_field_set(unit, FE_IPGRr, &val32, IPGR2f, 0xf); 2515 SOC_IF_ERROR_RETURN(WRITE_FE_IPGRr(unit, port, val32)); 2516 break; 2517 default: 2518 break; 2519 } 2520 2521 /* Set egress enable */ 2522 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) 2523 if (SOC_IS_FBX(unit) || SOC_IS_RAPTOR(unit)) { 2524 SOC_IF_ERROR_RETURN(READ_EGR_ENABLEr(unit, port, &val32)); 2525 soc_reg_field_set(unit, EGR_ENABLEr, &val32, PRT_ENABLEf, 1); 2526 SOC_IF_ERROR_RETURN(WRITE_EGR_ENABLEr(unit, port, val32)); 2527 } 2528 #endif /* BCM_FIREBOLT_SUPPORT */ 2529 2530 /* 2531 * Firebolt ports are initialized in bcm_port_init() so as to 2532 * block control frames (PORT_TABm.PASS_CONTROL_FRAMESf = 0). 2533 */ 2534 2535 #if defined(BCM_RAPTOR1_SUPPORT) 2536 if (SOC_IS_RAPTOR(unit) && IS_S_PORT(unit, port)) { 2537 /* Must initialize the ComboSerDes after MAC is initialized. */ 2538 SOC_IF_ERROR_RETURN 2539 (soc_phyctrl_init(unit, port)); 2540 } 2541 #endif /* BCM_RAPTOR1_SUPPORT */ 2542 2543 return SOC_E_NONE; 2544 } 2545 2546 /* 2547 * Function: 2548 * mac_ge_interface_set 2549 * Purpose: 2550 * Set GE MAC interface type 2551 * Parameters: 2552 * unit - StrataSwitch unit #. 2553 * port - Port number on unit. 2554 * pif - one of SOC_PORT_IF_* 2555 * Returns: 2556 * SOC_E_XXX 2557 */ 2558 2559 STATIC int 2560 mac_ge_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 2561 { 2562 uint32 gmacc0, gpcsc; 2563 uint32 ogmacc0, ogpcsc; 2564 2565 SOC_IF_ERROR_RETURN(READ_GMACC0r(unit, port, &gmacc0)); 2566 SOC_IF_ERROR_RETURN(READ_GPCSCr(unit, port, &gpcsc)); 2567 ogmacc0 = gmacc0; 2568 ogpcsc = gpcsc; 2569 2570 switch (pif) { 2571 case SOC_PORT_IF_MII: 2572 case SOC_PORT_IF_GMII: 2573 case SOC_PORT_IF_SGMII: 2574 soc_reg_field_set(unit, GMACC0r, &gmacc0, TMDSf, 1); /* GMII */ 2575 soc_reg_field_set(unit, GPCSCr, &gpcsc, RCSELf, 1); /* 125 MHz */ 2576 break; 2577 case SOC_PORT_IF_TBI: 2578 soc_reg_field_set(unit, GMACC0r, &gmacc0, TMDSf, 0); /* TBI */ 2579 soc_reg_field_set(unit, GPCSCr, &gpcsc, RCSELf, 0); /* 62.5 MHz */ 2580 break; 2581 default: 2582 return SOC_E_UNAVAIL; 2583 } 2584 2585 if (gpcsc != ogpcsc) { 2586 SOC_IF_ERROR_RETURN(WRITE_GPCSCr(unit, port, gpcsc)); 2587 } 2588 if (gmacc0 != ogmacc0) { 2589 SOC_IF_ERROR_RETURN(WRITE_GMACC0r(unit, port, gmacc0)); 2590 } 2591 return SOC_E_NONE; 2592 } 2593 2594 /* 2595 * Function: 2596 * mac_ge_interface_get 2597 * Purpose: 2598 * Retrieve GE MAC interface type 2599 * Parameters: 2600 * unit - StrataSwitch unit #. 2601 * port - StrataSwitch port # on unit. 2602 * pif - (OUT) one of SOC_PORT_IF_* 2603 * Returns: 2604 * SOC_E_XXX 2605 */ 2606 2607 STATIC int 2608 mac_ge_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 2609 { 2610 uint32 gmacc0; 2611 2612 SOC_IF_ERROR_RETURN(READ_GMACC0r(unit, port, &gmacc0)); 2613 2614 *pif = (soc_reg_field_get(unit, GMACC0r, gmacc0, TMDSf) ? 2615 SOC_PORT_IF_GMII : 2616 SOC_PORT_IF_TBI); 2617 2618 return SOC_E_NONE; 2619 } 2620 2621 /* 2622 * Function: 2623 * mac_ge_duplex_set 2624 * Purpose: 2625 * Set GE MAC in the specified duplex mode. 2626 * Parameters: 2627 * unit - StrataSwitch unit #. 2628 * port - StrataSwitch port # on unit. 2629 * duplex - Boolean: true --> full duplex, false --> half duplex. 2630 * Returns: 2631 * SOC_E_XXX 2632 * Notes: 2633 * Programs an IFG time appropriate to speed and duplex. 2634 */ 2635 2636 STATIC int 2637 mac_ge_duplex_set(int unit, soc_port_t port, int duplex) 2638 { 2639 soc_mac_mode_t mode; 2640 2641 SOC_IF_ERROR_RETURN(soc_mac_mode_get(unit, port, &mode)); 2642 2643 if ((mode == SOC_MAC_MODE_10_100) || (mode == SOC_MAC_MODE_10)) { 2644 return (mac_fe_duplex_set(unit, port, duplex)); 2645 } else { 2646 uint32 gmacc1, ogmacc1; 2647 if (IS_S_PORT(unit, port)) { 2648 /* Full-Duplex is tied to 1 on Raptor combo SerDes */ 2649 duplex = 1; 2650 } 2651 SOC_IF_ERROR_RETURN(READ_GMACC1r(unit, port, &gmacc1)); 2652 ogmacc1 = gmacc1; 2653 soc_reg_field_set(unit, GMACC1r, &gmacc1, 2654 FULLDf, duplex ? 1 : 0); 2655 if (gmacc1 != ogmacc1) { 2656 SOC_IF_ERROR_RETURN(WRITE_GMACC1r(unit, port, gmacc1)); 2657 2658 /* Set IPG to match new duplex */ 2659 SOC_IF_ERROR_RETURN(mac_ge_ipg_update(unit, port)); 2660 } 2661 2662 } 2663 2664 #if defined(BCM_FIREBOLT_SUPPORT) || defined(BCM_RAPTOR_SUPPORT) 2665 /* 2666 * Notify internal PHY driver of duplex change in case it is being 2667 * used as pass-through to an external PHY. 2668 */ 2669 if (soc_feature(unit, soc_feature_dodeca_serdes)) { 2670 if (IS_GE_PORT(unit, port)) { 2671 SOC_IF_ERROR_RETURN 2672 (soc_phyctrl_notify(unit, port, phyEventDuplex, duplex)); 2673 } 2674 } 2675 #endif /* BCM_FIREBOLT_SUPPORT */ 2676 2677 return SOC_E_NONE; 2678 } 2679 2680 /* 2681 * Function: 2682 * mac_ge_duplex_get 2683 * Purpose: 2684 * Get GE MAC duplex mode. 2685 * Parameters: 2686 * unit - StrataSwitch unit #. 2687 * port - StrataSwitch port # on unit. 2688 * duplex - (OUT) Boolean: true --> full duplex, false --> half duplex. 2689 * Returns: 2690 * SOC_E_XXX 2691 */ 2692 2693 STATIC int 2694 mac_ge_duplex_get(int unit, soc_port_t port, int *duplex) 2695 { 2696 soc_mac_mode_t mode; 2697 2698 SOC_IF_ERROR_RETURN(soc_mac_mode_get(unit, port, &mode)); 2699 2700 if ((mode == SOC_MAC_MODE_10_100) || (mode == SOC_MAC_MODE_10)) { 2701 return mac_fe_duplex_get(unit, port, duplex); 2702 } else { 2703 uint32 gmacc1; 2704 2705 SOC_IF_ERROR_RETURN(READ_GMACC1r(unit, port, &gmacc1)); 2706 2707 *duplex = soc_reg_field_get(unit, GMACC1r, gmacc1, FULLDf); 2708 2709 return SOC_E_NONE; 2710 } 2711 } 2712 2713 #if defined(BCM_RAPTOR1_SUPPORT) 2714 STATIC int 2715 mac_se_speed_set(int unit, soc_port_t port, int speed) 2716 { 2717 int cur_speed; 2718 uint32 val32; 2719 uint32 val64; 2720 soc_pbmp_t pbmp_s0; 2721 2722 SOC_IF_ERROR_RETURN(mac_ge_speed_get(unit, port, &cur_speed)); 2723 if (cur_speed == speed) { 2724 return SOC_E_NONE; 2725 } 2726 2727 /* Make sure all packets in flight have reached destination */ 2728 2729 /* Keep Trimac in soft reset */ 2730 SOC_IF_ERROR_RETURN(READ_GMACC0r(unit, port, &val64)); 2731 soc_reg_field_set(unit, GMACC0r, &val64, SRSTf, 1); 2732 SOC_IF_ERROR_RETURN(WRITE_GMACC0r(unit, port, val64)); 2733 2734 /* Change the config bits to desired mode */ 2735 SOC_IF_ERROR_RETURN(READ_GPORT_CONFIGr(unit, port, &val32)); 2736 SOC_PBMP_WORD_SET(pbmp_s0, 0, 0x00000002); 2737 if (SOC_PBMP_MEMBER(pbmp_s0, port)) { 2738 /* Select 2.5 Gbps or 1 Gbps mode. */ 2739 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, 2740 PLL_MODE_DEF_S0f, (speed == 2500) ? 1 : 0); 2741 } else { 2742 soc_reg_field_set(unit, GPORT_CONFIGr, &val32, 2743 PLL_MODE_DEF_S1f, (speed == 2500) ? 1 : 0); 2744 } 2745 SOC_IF_ERROR_RETURN(WRITE_GPORT_CONFIGr(unit, port, val32)); 2746 2747 /* Bring Trimac out of reset */ 2748 SOC_IF_ERROR_RETURN(READ_GMACC0r(unit, port, &val64)); 2749 soc_reg_field_set(unit, GMACC0r, &val64, SRSTf, 0); 2750 SOC_IF_ERROR_RETURN(WRITE_GMACC0r(unit, port, val64)); 2751 2752 return SOC_E_NONE; 2753 } 2754 #endif /* BCM_RAPTOR1_SUPPORT */ 2755 2756 /* 2757 * Function: 2758 * mac_ge_speed_set 2759 * Purpose: 2760 * Set GE MAC in the specified speed. 2761 * Parameters: 2762 * unit - StrataSwitch unit #. 2763 * port - Port number on unit. 2764 * speed - 10,100,1000 for speed. 2765 * Returns: 2766 * SOC_E_XXX 2767 * Notes: 2768 * Programs an IFG time appropriate to speed and duplex. 2769 */ 2770 2771 STATIC int 2772 mac_ge_speed_set(int unit, soc_port_t port, int speed) 2773 { 2774 int cur_speed; 2775 2776 if (!IS_GE_PORT(unit, port)) { 2777 return SOC_E_CONFIG; 2778 } 2779 2780 SOC_IF_ERROR_RETURN(mac_ge_speed_get(unit, port, &cur_speed)); 2781 2782 #if defined(BCM_RAPTOR1_SUPPORT) 2783 if (SOC_IS_RAPTOR(unit) && IS_S_PORT(unit, port)) { 2784 if (!PHY_EXTERNAL_MODE(unit, port)) { 2785 SOC_IF_ERROR_RETURN 2786 (mac_se_speed_set(unit, port, speed)); 2787 } 2788 } 2789 #endif /* BCM_RAPTOR1_SUPPORT */ 2790 2791 switch (speed) { 2792 case 0: 2793 break; /* Support NULL PHY */ 2794 2795 case 10: 2796 case 100: 2797 if (soc_feature(unit, soc_feature_trimac)) { 2798 SOC_IF_ERROR_RETURN 2799 (soc_mac_mode_set(unit, port, 2800 (speed == 10) ? 2801 SOC_MAC_MODE_10: 2802 SOC_MAC_MODE_10_100)); 2803 } else { 2804 SOC_IF_ERROR_RETURN 2805 (soc_mac_mode_set(unit, port, SOC_MAC_MODE_10_100)); 2806 } 2807 SOC_IF_ERROR_RETURN 2808 (mac_fe_speed_set(unit, port, speed)); 2809 2810 break; 2811 2812 case 1000: 2813 SOC_IF_ERROR_RETURN 2814 (soc_mac_mode_set(unit, port, SOC_MAC_MODE_1000_T)); 2815 2816 #if defined(BCM_FIREBOLT_SUPPORT) 2817 /* 2818 * Notify internal PHY driver of speed change in case it is being 2819 * used as pass-through to an external PHY. 2820 */ 2821 2822 if (soc_feature(unit, soc_feature_dodeca_serdes)) { 2823 /* 2824 * Notify internal PHY driver of speed change in case it is being 2825 * used as pass-through to an external PHY. 2826 */ 2827 if (IS_GE_PORT(unit, port)) { 2828 SOC_IF_ERROR_RETURN(soc_phyctrl_notify(unit, port, 2829 phyEventSpeed, speed)); 2830 } 2831 } 2832 #endif /* BCM_FIREBOLT_SUPPORT */ 2833 2834 break; 2835 2836 case 2500: 2837 SOC_IF_ERROR_RETURN 2838 (soc_mac_mode_set(unit, port, SOC_MAC_MODE_1000_T)); 2839 break; 2840 2841 default: 2842 return (SOC_E_CONFIG); 2843 } 2844 2845 /* Set IPG to match new speed */ 2846 SOC_IF_ERROR_RETURN(mac_ge_ipg_update(unit, port)); 2847 2848 /* MAC speed switch results in a tx clock glitch to the serdes in 100fx mode. 2849 * reset serdes txfifo clears this condition. However this reset triggers 2850 * a link transition. Do not apply this reset if speed is already in 100M 2851 */ 2852 if ((speed == 100) && (cur_speed != 100)) { 2853 (void)soc_phyctrl_notify(unit, port, phyEventTxFifoReset, 100); 2854 } 2855 2856 return (SOC_E_NONE); 2857 } 2858 2859 /* 2860 * Function: 2861 * mac_ge_speed_get 2862 * Purpose: 2863 * Get GE MAC speed 2864 * Parameters: 2865 * unit - StrataSwitch unit #. 2866 * port - Port number on unit. 2867 * speed - (OUT) speed in Mb (10/100/1000) 2868 * Returns: 2869 * SOC_E_NONE 2870 */ 2871 2872 STATIC int 2873 mac_ge_speed_get(int unit, soc_port_t port, int *speed) 2874 { 2875 soc_mac_mode_t mode; 2876 int turbo = 0; 2877 int rv = SOC_E_NONE; 2878 2879 SOC_IF_ERROR_RETURN(soc_mac_mode_get(unit, port, &mode)); 2880 2881 switch(mode) { 2882 case SOC_MAC_MODE_10: 2883 case SOC_MAC_MODE_10_100: 2884 rv = mac_fe_speed_get(unit, port, speed); 2885 break; 2886 case SOC_MAC_MODE_1000_T: 2887 #if defined(BCM_RAPTOR1_SUPPORT) 2888 if (SOC_IS_RAPTOR(unit) && IS_S_PORT(unit, port)) { 2889 uint32 gport_config; 2890 soc_pbmp_t pbmp_s0; 2891 2892 SOC_IF_ERROR_RETURN(READ_GPORT_CONFIGr(unit, port, &gport_config)); 2893 2894 SOC_PBMP_WORD_SET(pbmp_s0, 0, 0x00000002); 2895 if (SOC_PBMP_MEMBER(pbmp_s0, port)) { 2896 turbo = soc_reg_field_get(unit, GPORT_CONFIGr, 2897 gport_config, PLL_MODE_DEF_S0f); 2898 } else { 2899 turbo = soc_reg_field_get(unit, GPORT_CONFIGr, 2900 gport_config, PLL_MODE_DEF_S1f); 2901 } 2902 } 2903 #endif 2904 /* coverity[dead_error_line] */ 2905 *speed = turbo ? 2500 : 1000; 2906 break; 2907 default: 2908 rv = SOC_E_INTERNAL; 2909 } 2910 return(rv); 2911 } 2912 2913 /* 2914 * Function: 2915 * mac_ge_pause_set 2916 * Purpose: 2917 * Configure GE MAC to transmit/receive pause frames. 2918 * Parameters: 2919 * unit - StrataSwitch unit #. 2920 * port - StrataSwitch port # on unit. 2921 * pause_tx - Boolean: transmit pause, or -1 (don't change) 2922 * pause_rx - Boolean: receive pause, or -1 (don't change) 2923 * Returns: 2924 * SOC_E_XXX 2925 */ 2926 2927 STATIC int 2928 mac_ge_pause_set(int unit, soc_port_t port, int pause_tx, int pause_rx) 2929 { 2930 soc_mac_mode_t mode; 2931 2932 if (pause_tx < 0 && pause_rx < 0) { 2933 return SOC_E_NONE; 2934 } 2935 #if defined(BCM_RAPTOR1_SUPPORT) 2936 if (SOC_IS_RAPTOR(unit) && IS_ST_PORT(unit, port)) { 2937 /* Flow control cannot be enabled in HiGL mode */ 2938 pause_tx = 0; 2939 pause_rx = 0; 2940 } 2941 #endif 2942 SOC_IF_ERROR_RETURN(soc_mac_mode_get(unit, port, &mode)); 2943 2944 if ((mode == SOC_MAC_MODE_10_100) || (mode == SOC_MAC_MODE_10)) { 2945 return (mac_fe_pause_set(unit, port, pause_tx, pause_rx)); 2946 } else { 2947 uint32 gmacc1, ogmacc1; 2948 2949 SOC_IF_ERROR_RETURN(READ_GMACC1r(unit, port, &gmacc1)); 2950 ogmacc1 = gmacc1; 2951 if (pause_tx >= 0) { 2952 soc_reg_field_set(unit, GMACC1r, &gmacc1, FCTXf, 2953 pause_tx ? 1 : 0); 2954 } 2955 if (pause_rx >= 0) { 2956 soc_reg_field_set(unit, GMACC1r, &gmacc1, FCRXf, 2957 pause_rx ? 1 : 0); 2958 } 2959 if (gmacc1 != ogmacc1) { 2960 SOC_IF_ERROR_RETURN(WRITE_GMACC1r(unit, port, gmacc1)); 2961 } 2962 2963 return SOC_E_NONE; 2964 } 2965 } 2966 2967 /* 2968 * Function: 2969 * mac_ge_pause_addr_set 2970 * Purpose: 2971 * Set GE MAC source address for transmitted PAUSE frame 2972 * Parameters: 2973 * unit - StrataSwitch unit #. 2974 * port - StrataSwitch port # on unit. 2975 * pause_mac - MAC address used for pause transmission. 2976 * Returns: 2977 * SOC_E_XXX 2978 */ 2979 2980 STATIC int 2981 mac_ge_pause_addr_set(int unit, soc_port_t port, sal_mac_addr_t pause_mac) 2982 { 2983 soc_mac_mode_t mode; 2984 2985 SOC_IF_ERROR_RETURN(soc_mac_mode_get(unit, port, &mode)); 2986 2987 if ((mode == SOC_MAC_MODE_10_100) || (mode == SOC_MAC_MODE_10)) { 2988 return (mac_fe_pause_addr_set(unit, port, pause_mac)); 2989 } else { /* mac in gig mode */ 2990 uint32 gsa0, gsa1; 2991 2992 gsa0 = 0; 2993 gsa1 = 0; 2994 2995 soc_reg_field_set(unit, GSA0r, &gsa0, STAD1f, 2996 pause_mac[0] << 24 | 2997 pause_mac[1] << 16 | 2998 pause_mac[2] << 8 | 2999 pause_mac[3] << 0); 3000 3001 soc_reg_field_set(unit, GSA1r, &gsa1, STAD2f, 3002 pause_mac[4] << 8 | 3003 pause_mac[5]); 3004 3005 SOC_IF_ERROR_RETURN(WRITE_GSA0r(unit, port, gsa0)); 3006 SOC_IF_ERROR_RETURN(WRITE_GSA1r(unit, port, gsa1)); 3007 } 3008 3009 return (SOC_E_NONE); 3010 } 3011 3012 /* 3013 * Function: 3014 * mac_ge_pause_get 3015 * Purpose: 3016 * Return current GE MAC transmit/receive pause frame configuration. 3017 * Parameters: 3018 * unit - StrataSwitch unit #. 3019 * port - StrataSwitch port # on unit. 3020 * pause_tx - (OUT) TRUE is TX pause enabled. 3021 * pause_rx - (OUT) TRUE if obey RX pause enabled. 3022 * Returns: 3023 * SOC_E_XXX 3024 */ 3025 3026 STATIC int 3027 mac_ge_pause_get(int unit, soc_port_t port, int *pause_tx, int *pause_rx) 3028 { 3029 soc_mac_mode_t mode; 3030 3031 SOC_IF_ERROR_RETURN(soc_mac_mode_get(unit, port, &mode)); 3032 3033 if ((mode == SOC_MAC_MODE_10_100) || (mode == SOC_MAC_MODE_10)) { 3034 return (mac_fe_pause_get(unit, port, pause_tx, pause_rx)); 3035 } else { /* mac in gig mode */ 3036 uint32 gmacc1; 3037 3038 SOC_IF_ERROR_RETURN(READ_GMACC1r(unit, port, &gmacc1)); 3039 3040 *pause_tx = soc_reg_field_get(unit, GMACC1r, gmacc1, FCTXf) ? 3041 TRUE : FALSE; 3042 *pause_rx = soc_reg_field_get(unit, GMACC1r, gmacc1, FCRXf) ? 3043 TRUE : FALSE; 3044 3045 return (SOC_E_NONE); 3046 } 3047 } 3048 3049 /* 3050 * Function: 3051 * mac_ge_pause_addr_get 3052 * Purpose: 3053 * Return current GE MAC source address for transmitted PAUSE frames 3054 * Parameters: 3055 * unit - StrataSwitch unit #. 3056 * port - StrataSwitch port # on unit. 3057 * pause_mac - (OUT) MAC address used for pause transmission. 3058 * Returns: 3059 * SOC_E_XXX 3060 */ 3061 3062 STATIC int 3063 mac_ge_pause_addr_get(int unit, soc_port_t port, sal_mac_addr_t pause_mac) 3064 { 3065 soc_mac_mode_t mode; 3066 3067 SOC_IF_ERROR_RETURN(soc_mac_mode_get(unit, port, &mode)); 3068 3069 if ((mode == SOC_MAC_MODE_10_100) || (mode == SOC_MAC_MODE_10)) { 3070 return (mac_fe_pause_addr_get(unit, port, pause_mac)); 3071 } else { /* mac in gig mode */ 3072 uint32 gsa0, gsa1; 3073 uint32 stad1, stad2; 3074 3075 SOC_IF_ERROR_RETURN(READ_GSA0r(unit, port, &gsa0)); 3076 SOC_IF_ERROR_RETURN(READ_GSA1r(unit, port, &gsa1)); 3077 3078 stad1 = soc_reg_field_get(unit, GSA0r, gsa0, STAD1f); 3079 stad2 = soc_reg_field_get(unit, GSA1r, gsa1, STAD2f); 3080 3081 pause_mac[0] = (uint8)(stad1 >> 24); 3082 pause_mac[1] = (uint8)(stad1 >> 16); 3083 pause_mac[2] = (uint8)(stad1 >> 8); 3084 pause_mac[3] = (uint8)(stad1 >> 0); 3085 pause_mac[4] = (uint8)(stad2 >> 8); 3086 pause_mac[5] = (uint8)(stad2 >> 0); 3087 3088 return (SOC_E_NONE); 3089 } 3090 } 3091 3092 /* 3093 * Function: 3094 * mac_ge_loopback_set 3095 * Purpose: 3096 * Set GE MAC into/out-of loopback mode 3097 * Parameters: 3098 * unit - StrataSwitch unit #. 3099 * port - Port number on unit. 3100 * loopback - Boolean: true -> loopback mode, false -> normal operation 3101 * Returns: 3102 * SOC_E_XXX 3103 */ 3104 3105 STATIC int 3106 mac_ge_loopback_set(int unit, soc_port_t port, int loopback) 3107 { 3108 soc_mac_mode_t mode; 3109 3110 SOC_IF_ERROR_RETURN(soc_mac_mode_get(unit, port, &mode)); 3111 3112 if ((mode == SOC_MAC_MODE_10_100) || (mode == SOC_MAC_MODE_10)) { 3113 return mac_fe_loopback_set(unit, port, loopback); 3114 } else { 3115 uint32 gmacc0, ogmacc0; 3116 3117 /* L10B also works, but not on Raptor so we'll use L32B */ 3118 SOC_IF_ERROR_RETURN(READ_GMACC0r(unit, port, &gmacc0)); 3119 ogmacc0 = gmacc0; 3120 soc_reg_field_set(unit, GMACC0r, &gmacc0, L32Bf, loopback ? 1 : 0); 3121 if (gmacc0 != ogmacc0) { 3122 SOC_IF_ERROR_RETURN(WRITE_GMACC0r(unit, port, gmacc0)); 3123 } 3124 3125 return (SOC_E_NONE); 3126 } 3127 } 3128 3129 /* 3130 * Function: 3131 * mac_ge_loopback_get 3132 * Purpose: 3133 * Get current GE MAC loopback mode setting. 3134 * Parameters: 3135 * unit - StrataSwitch unit #. 3136 * port - StrataSwitch port # on unit 3137 * loopback - (OUT) Boolean: true = loopback, false = normal 3138 * Returns: 3139 * SOC_E_XXX 3140 */ 3141 3142 STATIC int 3143 mac_ge_loopback_get(int unit, soc_port_t port, int *loopback) 3144 { 3145 soc_mac_mode_t mode; 3146 3147 SOC_IF_ERROR_RETURN(soc_mac_mode_get(unit, port, &mode)); 3148 3149 if ((mode == SOC_MAC_MODE_10_100) || (mode == SOC_MAC_MODE_10)) { 3150 return mac_fe_loopback_get(unit, port, loopback); 3151 } else { /* mac in gig mode */ 3152 uint32 gmacc0; 3153 3154 SOC_IF_ERROR_RETURN(READ_GMACC0r(unit, port, &gmacc0)); 3155 3156 *loopback = soc_reg_field_get(unit, GMACC0r, gmacc0, L32Bf); 3157 3158 return (SOC_E_NONE); 3159 } 3160 } 3161 3162 /* 3163 * Function: 3164 * mac_ge_ability_get 3165 * Purpose: 3166 * Return the GE MAC abilities 3167 * Parameters: 3168 * unit - StrataSwitch Unit #. 3169 * port - StrataSwitch Port # on unit. 3170 * mode - (OUT) Mask of MAC abilities returned. 3171 * Returns: 3172 * SOC_E_NONE 3173 */ 3174 3175 STATIC int 3176 mac_ge_ability_get(int unit, soc_port_t port, soc_port_mode_t *mode) 3177 { 3178 COMPILER_REFERENCE(unit); 3179 COMPILER_REFERENCE(port); 3180 3181 *mode = (SOC_PM_1000MB_FD | SOC_PM_MII | SOC_PM_GMII | SOC_PM_TBI | 3182 SOC_PM_LB_MAC | SOC_PM_PAUSE | SOC_PM_PAUSE_ASYMM); 3183 3184 if (soc_feature(unit, soc_feature_fe_gig_macs)) { 3185 *mode |= SOC_PM_100MB | SOC_PM_10MB; 3186 } 3187 3188 #if defined(BCM_RAPTOR1_SUPPORT) 3189 if (SOC_IS_RAPTOR(unit) && IS_S_PORT(unit, port)) { 3190 *mode |= SOC_PM_2500MB_FD; 3191 } 3192 #endif /* BCM_RAPTOR_SUPPORT */ 3193 3194 return (SOC_E_NONE); 3195 } 3196 3197 /* 3198 * Function: 3199 * mac_ge_frame_max_set 3200 * Description: 3201 * Set the maximum receive frame size for the GE port 3202 * Parameters: 3203 * unit - Device number 3204 * port - Port number 3205 * size - Maximum frame size in bytes 3206 * Return Value: 3207 * BCM_E_XXX 3208 * Notes: 3209 * The maximum frame size on GE port is set the same for both GE and 3210 * 10/100 mode 3211 */ 3212 3213 STATIC int 3214 mac_ge_frame_max_set(int unit, soc_port_t port, int size) 3215 { 3216 uint32 val32; 3217 3218 /* 10/100 mode first */ 3219 if (soc_feature(unit, soc_feature_fe_gig_macs)) { 3220 SOC_IF_ERROR_RETURN(mac_fe_frame_max_set(unit, port, size)); 3221 } 3222 3223 /* now 1000 mode */ 3224 3225 if (IS_ST_PORT(unit, port)) { 3226 size += 16; /* Account for 16 bytes of Higig2 header */ 3227 } 3228 3229 val32 = size; 3230 return WRITE_MAXFRr(unit, port, val32); 3231 } 3232 3233 /* 3234 * Function: 3235 * mac_ge_frame_max_get 3236 * Description: 3237 * Set the maximum receive frame size for the GE port 3238 * Parameters: 3239 * unit - Device number 3240 * port - Port number 3241 * size - Maximum frame size in bytes 3242 * Return Value: 3243 * BCM_E_XXX 3244 * Notes: 3245 * Depending on chip or port type the actual maximum receive frame size 3246 * might be slightly higher. 3247 * 3248 * For GE ports that use 2 separate MACs (one for GE and another one for 3249 * 10/100 modes) the function returns the maximum rx frame size set for 3250 * the current mode. 3251 */ 3252 STATIC int 3253 mac_ge_frame_max_get(int unit, soc_port_t port, int *size) 3254 { 3255 uint32 val32; 3256 soc_mac_mode_t mode; 3257 3258 SOC_IF_ERROR_RETURN(soc_mac_mode_get(unit, port, &mode)); 3259 3260 if ((mode == SOC_MAC_MODE_10_100) || (mode == SOC_MAC_MODE_10)) { 3261 return mac_fe_frame_max_get(unit, port, size); 3262 } else { 3263 SOC_IF_ERROR_RETURN(READ_MAXFRr(unit, port, &val32)); 3264 *size = val32; 3265 3266 if (IS_ST_PORT(unit, port)) { 3267 *size -= 16; /* Account for 16 bytes of Higig2 header */ 3268 } 3269 return SOC_E_NONE; 3270 } 3271 } 3272 3273 /* 3274 * Function: 3275 * mac_ge_ifg_set 3276 * Description: 3277 * Sets the new ifg (Inter-frame gap) value 3278 * Parameters: 3279 * unit - Device number 3280 * port - Port number 3281 * speed - the speed for which the IFG is being set 3282 * duplex - the duplex for which the IFG is being set 3283 * ifg - Inter-frame gap in bit-times 3284 * Return Value: 3285 * BCM_E_XXX 3286 * Notes: 3287 * The function makes sure the IFG value makes sense and updates the 3288 * IPG register in case the speed/duplex match the current settings 3289 */ 3290 STATIC int 3291 mac_ge_ifg_set(int unit, soc_port_t port, int speed, soc_port_duplex_t duplex, 3292 int ifg) 3293 { 3294 int cur_speed; 3295 int cur_duplex; 3296 int ipg; 3297 int real_ifg; 3298 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 3299 int rv; 3300 3301 SOC_IF_ERROR_RETURN(mac_ge_ifg_to_ipg(unit, port, speed, duplex, 3302 ifg, &ipg)); 3303 SOC_IF_ERROR_RETURN(mac_ge_ipg_to_ifg(unit, port, speed, duplex, 3304 ipg, &real_ifg)); 3305 3306 if (duplex) { 3307 switch (speed) { 3308 case 10: 3309 if (soc_feature(unit, soc_feature_fe_gig_macs)) { 3310 si->fd_10 = real_ifg; 3311 } else { 3312 return SOC_E_PARAM; 3313 } 3314 break; 3315 case 100: 3316 if (soc_feature(unit, soc_feature_fe_gig_macs)) { 3317 si->fd_100 = real_ifg; 3318 } else { 3319 return SOC_E_PARAM; 3320 } 3321 break; 3322 case 1000: 3323 /** coverity[equality_cond] **/ 3324 si->fd_1000 = real_ifg; 3325 /** coverity[equality_cond] **/ 3326 break; 3327 case 2500: 3328 #ifdef BCM_RAPTOR1_SUPPORT 3329 if (SOC_IS_RAPTOR(unit) && IS_S_PORT(unit, port)) { 3330 si->fd_2500 = real_ifg; 3331 } else 3332 #endif 3333 { 3334 return SOC_E_PARAM; 3335 } 3336 break; 3337 3338 default: 3339 return SOC_E_PARAM; 3340 break; 3341 } 3342 } else { 3343 switch (speed) { 3344 case 10: 3345 if (soc_feature(unit, soc_feature_fe_gig_macs)) { 3346 si->hd_10 = real_ifg; 3347 } else { 3348 return SOC_E_PARAM; 3349 } 3350 break; 3351 case 100: 3352 if (soc_feature(unit, soc_feature_fe_gig_macs)) { 3353 si->hd_100 = real_ifg; 3354 } else { 3355 return SOC_E_PARAM; 3356 } 3357 break; 3358 case 1000: 3359 si->hd_1000 = real_ifg; 3360 break; 3361 3362 default: 3363 return SOC_E_PARAM; 3364 break; 3365 } 3366 } 3367 3368 SOC_IF_ERROR_RETURN(mac_ge_duplex_get(unit, port, &cur_duplex)); 3369 SOC_IF_ERROR_RETURN(mac_ge_speed_get(unit, port, &cur_speed)); 3370 3371 if (cur_speed == speed && ((soc_port_duplex_t)cur_duplex == duplex)) { 3372 switch (speed) { 3373 case 10: 3374 case 100: 3375 rv = mac_fe_ipg_update(unit, port); 3376 break; 3377 case 1000: 3378 case 2500: 3379 rv = mac_ge_ipg_update(unit, port); 3380 break; 3381 /* coverity[dead_error_begin] */ 3382 default: 3383 rv = SOC_E_PARAM; 3384 } 3385 } else { 3386 rv = SOC_E_NONE; 3387 } 3388 3389 return (rv); 3390 } 3391 3392 /* 3393 * Function: 3394 * mac_ge_ifg_get 3395 * Description: 3396 * Gets the ifg (Inter-frame gap) value for a specific speed/duplex 3397 * combination 3398 * Parameters: 3399 * unit - Device number 3400 * port - Port number 3401 * speed - the speed for which the IFG is being set 3402 * duplex - the duplex for which the IFG is being set 3403 * ifg - Inter-frame gap in bit-times 3404 * Return Value: 3405 * BCM_E_XXX 3406 * Notes: 3407 * The function returns the REAL ifg value that will be (or is currently) 3408 * used by the chip, which might be different from the value initially 3409 * set by the ifg_set() call. The reason for that is that only certain 3410 * values are allowed. 3411 */ 3412 STATIC int 3413 mac_ge_ifg_get(int unit, soc_port_t port, int speed, soc_port_duplex_t duplex, 3414 int *ifg) 3415 { 3416 soc_ipg_t *si = &SOC_PERSIST(unit)->ipg[port]; 3417 3418 if (duplex) { 3419 switch (speed) { 3420 case 10: 3421 if (soc_feature(unit, soc_feature_fe_gig_macs)) { 3422 *ifg = si->fd_10; 3423 } else { 3424 return SOC_E_PARAM; 3425 } 3426 break; 3427 case 100: 3428 if (soc_feature(unit, soc_feature_fe_gig_macs)) { 3429 *ifg = si->fd_100; 3430 } else { 3431 return SOC_E_PARAM; 3432 } 3433 break; 3434 case 1000: 3435 *ifg = si->fd_1000; 3436 break; 3437 case 2500: 3438 #ifdef BCM_RAPTOR1_SUPPORT 3439 if (SOC_IS_RAPTOR(unit) && IS_S_PORT(unit, port)) { 3440 *ifg = si->fd_2500; 3441 } else 3442 #endif 3443 { 3444 return SOC_E_PARAM; 3445 } 3446 break; 3447 3448 default: 3449 return SOC_E_PARAM; 3450 break; 3451 } 3452 } else { 3453 switch (speed) { 3454 case 10: 3455 if (soc_feature(unit, soc_feature_fe_gig_macs)) { 3456 *ifg = si->hd_10; 3457 } else { 3458 return SOC_E_PARAM; 3459 } 3460 break; 3461 case 100: 3462 if (soc_feature(unit, soc_feature_fe_gig_macs)) { 3463 *ifg = si->hd_100; 3464 } else { 3465 return SOC_E_PARAM; 3466 } 3467 break; 3468 case 1000: 3469 *ifg = si->hd_1000; 3470 break; 3471 3472 default: 3473 return SOC_E_PARAM; 3474 break; 3475 } 3476 } 3477 3478 return SOC_E_NONE; 3479 } 3480 3481 /* 3482 * Function: 3483 * mac_ge_encap_set 3484 * Purpose: 3485 * Set the port encapsulation mode. 3486 * Parameters: 3487 * unit - XGS unit #. 3488 * port - XGS port # on unit. 3489 * mode - encapsulation mode 3490 * Returns: 3491 * SOC_E_XXX 3492 */ 3493 STATIC int 3494 mac_ge_encap_set(int unit, soc_port_t port, int mode) 3495 { 3496 if (mode == SOC_ENCAP_IEEE) { 3497 return SOC_E_NONE; 3498 } 3499 return SOC_E_PARAM; 3500 } 3501 3502 /* 3503 * Function: 3504 * mac_ge_encap_get 3505 * Purpose: 3506 * Get the port encapsulation mode. 3507 * Parameters: 3508 * unit - XGS unit #. 3509 * port - XGS port # on unit. 3510 * mode - (INT) encapsulation mode 3511 * Returns: 3512 * SOC_E_XXX 3513 */ 3514 STATIC int 3515 mac_ge_encap_get(int unit, soc_port_t port, int *mode) 3516 { 3517 *mode = SOC_ENCAP_IEEE; 3518 3519 return SOC_E_NONE; 3520 } 3521 3522 /* 3523 * Function: 3524 * mac_ge_control_set 3525 * Purpose: 3526 * To configure GE MAC control properties. 3527 * Parameters: 3528 * unit - XGS unit #. 3529 * port - XGS port # on unit. 3530 * type - MAC control property to set. 3531 * int - New setting for MAC control. 3532 * Returns: 3533 * SOC_E_XXX 3534 */ 3535 STATIC int 3536 mac_ge_control_set(int unit, soc_port_t port, soc_mac_control_t type, 3537 int value) 3538 { 3539 soc_mac_mode_t mode; 3540 uint32 regval, copy; 3541 3542 LOG_VERBOSE(BSL_LS_SOC_GE, 3543 (BSL_META_U(unit, 3544 "mac_ge_control_set: unit %d port %s type=%d value=%d\n"), 3545 unit, SOC_PORT_NAME(unit, port), 3546 type, value)); 3547 3548 switch (type) { 3549 case SOC_MAC_CONTROL_RX_SET: 3550 SOC_IF_ERROR_RETURN(soc_mac_mode_get(unit, port, &mode)); 3551 if ((mode == SOC_MAC_MODE_10_100) || (mode == SOC_MAC_MODE_10)) { 3552 #ifdef BCM_RAPTOR1_SUPPORT 3553 /* Need to reset the FE MAC for Raptor before enabling RX */ 3554 if (SOC_IS_RAPTOR(unit) && value) { 3555 SOC_IF_ERROR_RETURN 3556 (soc_reg_field32_modify(unit, GMACC0r, port, SRSTf, 1)); 3557 SOC_IF_ERROR_RETURN 3558 (soc_reg_field32_modify(unit, GMACC0r, port, SRSTf, 0)); 3559 } 3560 #endif 3561 SOC_IF_ERROR_RETURN(FE_READ(FE_MAC1r, GTH_FE_MAC1r, unit, port, ®val)); 3562 FE_SET(unit, port, FE_MAC1r, GTH_FE_MAC1r, RX_ENf, regval, value ? 1 : 0); 3563 SOC_IF_ERROR_RETURN(FE_WRITE(FE_MAC1r, GTH_FE_MAC1r, unit, port, regval)); 3564 break; 3565 } 3566 3567 SOC_IF_ERROR_RETURN(READ_GMACC1r(unit, port, ®val)); 3568 copy = regval; 3569 if (value) { 3570 soc_reg_field_set(unit, GMACC1r, ®val, RXEN0f, 1); 3571 } else { 3572 soc_reg_field_set(unit, GMACC1r, ®val, RXEN0f, 0); 3573 } 3574 if (regval != copy) { 3575 SOC_IF_ERROR_RETURN(WRITE_GMACC1r(unit, port, regval)); 3576 } 3577 break; 3578 3579 default: 3580 return SOC_E_UNAVAIL; 3581 } 3582 3583 return SOC_E_NONE; 3584 } 3585 3586 /* 3587 * Function: 3588 * mac_ge_control_get 3589 * Purpose: 3590 * To get current GE MAC control setting. 3591 * Parameters: 3592 * unit - XGS unit #. 3593 * port - XGS port # on unit. 3594 * type - MAC control property to set. 3595 * int - New setting for MAC control. 3596 * Returns: 3597 * SOC_E_XXX 3598 */ 3599 STATIC int 3600 mac_ge_control_get(int unit, soc_port_t port, soc_mac_control_t type, 3601 int *value) 3602 { 3603 soc_mac_mode_t mode; 3604 uint32 regval; 3605 3606 if (value == NULL) { 3607 return SOC_E_PARAM; 3608 } 3609 3610 switch (type) { 3611 case SOC_MAC_CONTROL_RX_SET: 3612 SOC_IF_ERROR_RETURN(soc_mac_mode_get(unit, port, &mode)); 3613 if ((mode == SOC_MAC_MODE_10_100) || (mode == SOC_MAC_MODE_10)) { 3614 SOC_IF_ERROR_RETURN(FE_READ(FE_MAC1r, GTH_FE_MAC1r, unit, port, ®val)); 3615 *value = FE_GET(unit, port, FE_MAC1r, GTH_FE_MAC1r, RX_ENf, regval); 3616 break; 3617 } 3618 SOC_IF_ERROR_RETURN(READ_GMACC1r(unit, port, ®val)); 3619 *value = soc_reg_field_get(unit, GMACC1r, regval, RXEN0f); 3620 break; 3621 default: 3622 return SOC_E_UNAVAIL; 3623 } 3624 3625 LOG_VERBOSE(BSL_LS_SOC_GE, 3626 (BSL_META_U(unit, 3627 "mac_ge_control_get: unit %d port %s type=%d value=%d\n"), 3628 unit, SOC_PORT_NAME(unit, port), 3629 type, *value)); 3630 return SOC_E_NONE; 3631 } 3632 3633 /* 3634 * Function: 3635 * mac_ge_ability_local_get 3636 * Purpose: 3637 * Return the GE MAC abilities 3638 * Parameters: 3639 * unit - StrataSwitch Unit #. 3640 * port - StrataSwitch Port # on unit. 3641 * mode - (OUT) Mask of MAC abilities returned. 3642 * Returns: 3643 * SOC_E_NONE 3644 */ 3645 3646 STATIC int 3647 mac_ge_ability_local_get(int unit, soc_port_t port, 3648 soc_port_ability_t *ability) 3649 { 3650 if (NULL == ability) { 3651 return SOC_E_PARAM; 3652 } 3653 3654 ability->speed_half_duplex = SOC_PA_ABILITY_NONE; 3655 ability->speed_full_duplex = SOC_PA_SPEED_1000MB; 3656 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 3657 ability->interface = SOC_PA_INTF_GMII | SOC_PA_INTF_TBI; 3658 ability->medium = SOC_PA_ABILITY_NONE; 3659 ability->loopback = SOC_PA_LB_MAC; 3660 ability->flags = SOC_PA_ABILITY_NONE; 3661 ability->encap = SOC_PA_ENCAP_IEEE; 3662 3663 if (soc_feature(unit, soc_feature_fe_gig_macs)) { 3664 ability->speed_half_duplex |= SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB; 3665 ability->speed_full_duplex |= SOC_PA_SPEED_10MB | SOC_PA_SPEED_100MB; 3666 } 3667 3668 #if defined(BCM_RAPTOR1_SUPPORT) 3669 if (SOC_IS_RAPTOR(unit) && IS_S_PORT(unit, port)) { 3670 ability->speed_full_duplex |= SOC_PA_SPEED_2500MB; 3671 } 3672 #endif /* BCM_RAPTOR_SUPPORT */ 3673 3674 return (SOC_E_NONE); 3675 } 3676 3677 /* Exported GE MAC driver structure */ 3678 mac_driver_t soc_mac_ge = { 3679 "1000Mb MAC Driver", /* drv_name */ 3680 mac_ge_init, /* md_init */ 3681 mac_ge_enable_set, /* md_enable_set */ 3682 mac_ge_enable_get, /* md_enable_get */ 3683 mac_ge_duplex_set, /* md_duplex_set */ 3684 mac_ge_duplex_get, /* md_duplex_get */ 3685 mac_ge_speed_set, /* md_speed_set */ 3686 mac_ge_speed_get, /* md_speed_get */ 3687 mac_ge_pause_set, /* md_pause_set */ 3688 mac_ge_pause_get, /* md_pause_get */ 3689 mac_ge_pause_addr_set, /* md_pause_addr_set */ 3690 mac_ge_pause_addr_get, /* md_pause_addr_get */ 3691 mac_ge_loopback_set, /* md_lb_set */ 3692 mac_ge_loopback_get, /* md_lb_get */ 3693 mac_ge_interface_set, /* md_interface_set */ 3694 mac_ge_interface_get, /* md_interface_get */ 3695 mac_ge_ability_get, /* md_ability_get */ 3696 mac_ge_frame_max_set, /* md_frame_max_set */ 3697 mac_ge_frame_max_get, /* md_frame_max_get */ 3698 mac_ge_ifg_set, /* md_ifg_set */ 3699 mac_ge_ifg_get, /* md_ifg_get */ 3700 mac_ge_encap_set, /* md_encap_set */ 3701 mac_ge_encap_get, /* md_encap_get */ 3702 mac_ge_control_set, /* md_control_set */ 3703 mac_ge_control_get, /* md_control_get */ 3704 mac_ge_ability_local_get, /* md_ability_local_get */ 3705 NULL /* md_timesync_tx_info_get */ 3706 }; 3707 3708 #endif /* defined(BCM_ESW_SUPPORT) */ 3709