serdescombo65.c (56453B)
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 * File: 8 * physerdescombo65.c 9 * Purpose: 10 * Fiber driver for 65nm combo serdes using as internal Serdes PHY. 11 * 12 * When operating with an external PHY, this driver is not used. 13 * However the speed/duplex of the internal PHY must be programmed to 14 * match the MAC and external PHY settings so the data can pass through. 15 * This file supplies some routines to allow mac.c to accomplish this 16 * (think of the internal PHY as part of the MAC in this case): 17 * 18 * _phy_combo65_notify_duplex 19 * _phy_combo65_notify_speed 20 * _phy_combo65_notify_stop 21 * _phy_combo65_notify_resume 22 * 23 * MDIO accesses to the internal PHY are not modeled on Quickturn. 24 */ 25 #include <sal/types.h> 26 #include <sal/core/spl.h> 27 #include <shared/bsl.h> 28 #include <soc/drv.h> 29 #include <soc/debug.h> 30 #include <soc/error.h> 31 #include <soc/phy.h> 32 #include <soc/phyreg.h> 33 34 #include <soc/phy.h> 35 #include <soc/phy/phyctrl.h> 36 #include <soc/phy/drv.h> 37 38 #include "phydefs.h" /* Must include before other phy related includes */ 39 40 #if defined(INCLUDE_SERDES_COMBO65) 41 #include "phyconfig.h" /* Must be the first phy include after phydefs.h */ 42 #include "phyreg.h" 43 #include "phynull.h" 44 #include "serdescombo65.h" 45 46 #define ADVERT_ALL_FIBER \ 47 (SOC_PM_PAUSE | SOC_PM_1000MB_FD | SOC_PM_2500MB_FD) 48 49 /* Notify event forward declaration */ 50 STATIC int 51 _phy_combo65_notify_duplex(int unit, soc_port_t port, uint32 duplex); 52 STATIC int 53 _phy_combo65_notify_speed(int unit, soc_port_t port, uint32 speed); 54 STATIC int 55 _phy_combo65_notify_stop(int unit, soc_port_t port, uint32 flags); 56 STATIC int 57 _phy_combo65_notify_resume(int unit, soc_port_t port, uint32 flags); 58 STATIC int 59 _phy_combo65_notify_interface(int unit, soc_port_t port, uint32 intf); 60 STATIC int 61 phy_combo65_an_set(int unit, soc_port_t port, int an); 62 STATIC int 63 phy_combo65_an_get(int unit, soc_port_t port, int *an, int *an_done); 64 STATIC int 65 phy_combo65_adv_local_set(int unit, soc_port_t port, soc_port_mode_t mode); 66 67 /*********************************************************************** 68 * 69 * HELPER FUNCTIONS 70 */ 71 /* 72 * Function: 73 * phy_combo65_tx_control_set 74 * Purpose: 75 * Set preemphasis, driver current, and predriver current values 76 * Parameters: 77 * unit - StrataSwitch unit #. 78 * pc - PHY state object. 79 * port - StrataSwitch port #. 80 * Returns: 81 * SOC_E_NONE 82 */ 83 84 STATIC int 85 _phy_combo65_tx_control_set(int unit, phy_ctrl_t *pc, 86 soc_port_t port) 87 { 88 uint32 preemph; 89 uint32 idriver; 90 uint32 pdriver; 91 uint16 data16; 92 int fiber; 93 94 fiber = PHY_FIBER_MODE(unit, port); 95 96 /* Default values for Combo SerDes */ 97 if (fiber) { 98 preemph = 0x9; 99 idriver = 0xA; 100 pdriver = 0xA; 101 } else { 102 preemph = 0x0; 103 idriver = 0x0; 104 pdriver = 0x0; 105 } 106 107 /* Read config override */ 108 preemph = soc_property_port_get(unit, port, 109 spn_SERDES_PREEMPHASIS, preemph); 110 idriver = soc_property_port_get(unit, port, 111 spn_SERDES_DRIVER_CURRENT, idriver); 112 pdriver = soc_property_port_get(unit, port, 113 spn_SERDES_PRE_DRIVER_CURRENT, pdriver); 114 115 /* Combo SerDes 116 * preemph[15:12], idriver[11:8], pdriver[7:4] 117 */ 118 preemph = (preemph << 12) & TX_DRIVER_PREEMPHASIS; 119 idriver = (idriver << 8) & TX_DRIVER_IDRIVER; 120 pdriver = (pdriver << 4) & TX_DRIVER_IPREDRIVER; 121 data16 = (uint16)(preemph | idriver | pdriver); 122 123 SOC_IF_ERROR_RETURN 124 (MODIFY_TX_ALL_DRIVERr(unit, pc, data16, 125 TX_DRIVER_PREEMPHASIS | TX_DRIVER_IDRIVER | 126 TX_DRIVER_IPREDRIVER)); 127 128 return SOC_E_NONE; 129 } 130 131 /*********************************************************************** 132 * 133 * FIBER DRIVER ROUTINES 134 */ 135 STATIC int 136 phy_combo65_init_no_reset(int unit, soc_port_t port) 137 { 138 uint16 data16, mask16; 139 uint16 mode_1000x; 140 soc_timeout_t to; 141 phy_ctrl_t *pc; 142 int rv; 143 144 pc = INT_PHY_SW_STATE(unit, port); 145 pc->fiber.enable = PHY_FIBER_MODE(unit, port); 146 pc->fiber.preferred = PHY_FIBER_MODE(unit, port); 147 pc->fiber.autoneg_enable = 1; 148 pc->fiber.autoneg_advert = ADVERT_ALL_FIBER; 149 pc->fiber.force_speed = 1000; 150 pc->fiber.force_duplex = TRUE; 151 pc->fiber.master = SOC_PORT_MS_NONE; 152 pc->fiber.mdix = SOC_PORT_MDIX_NORMAL; 153 154 /* Since physerdescombo driver reset function vector does not reset 155 * the SerDes, reset the SerDes in initialization first. 156 * The internal SERDES PHY's reset bit is self-clearing. 157 */ 158 SOC_IF_ERROR_RETURN 159 (WRITE_COMBO_IEEE0_MII_CTRLr(unit, pc, MII_CTRL_RESET)); 160 soc_timeout_init(&to, 10000, 0); 161 while (!soc_timeout_check(&to)) { 162 rv = READ_COMBO_IEEE0_MII_CTRLr(unit, pc, &data16); 163 if (((data16 & MII_CTRL_RESET) == 0) || 164 SOC_FAILURE(rv)) { 165 break; 166 } 167 } 168 if ((data16 & MII_CTRL_RESET) != 0) { 169 LOG_WARN(BSL_LS_SOC_PHY, 170 (BSL_META_U(unit, 171 "Combo SerDes reset failed: u=%d p=%d\n"), 172 unit, port)); 173 } 174 175 /* Stop PLL Sequencer */ 176 SOC_IF_ERROR_RETURN 177 (MODIFY_XGXS_BLK0_CTRLr(unit, pc, 0, XGXS_CTRL_START_SEQUENCER)); 178 179 SOC_IF_ERROR_RETURN 180 (phy_combo65_adv_local_set(unit, port, pc->fiber.autoneg_advert)); 181 182 /* Initialialize autoneg and fullduplex */ 183 data16 = MII_CTRL_FD | MII_CTRL_SS_1000; 184 if ((PHY_FIBER_MODE(unit, port) && !PHY_EXTERNAL_MODE(unit, port)) || 185 PHY_PASSTHRU_MODE(unit, port) || 186 PHY_SGMII_AUTONEG_MODE(unit, port)) { 187 data16 |= MII_CTRL_AE | MII_CTRL_RAN; 188 } 189 SOC_IF_ERROR_RETURN 190 (WRITE_COMBO_IEEE0_MII_CTRLr(unit, pc, data16)); 191 192 /* Configure default preemphasis, predriver, idriver values */ 193 SOC_IF_ERROR_RETURN 194 (_phy_combo65_tx_control_set(unit, pc, port)); 195 196 /* Configuring operating mode */ 197 data16 = 0; 198 mask16 = CTRL1_AUTODET_EN | CTRL1_FIBER_MODE; 199 /* 200 * Configure signal auto-detection between SGMII and fiber. 201 * This detection only works if auto-negotiation is enabled. 202 */ 203 if (soc_property_port_get(unit, port, 204 spn_SERDES_AUTOMEDIUM, FALSE)) { 205 data16 |= CTRL1_AUTODET_EN; 206 } 207 208 /* 209 * Put the Serdes in Fiber or SGMII mode 210 */ 211 mode_1000x = 0; 212 if ((PHY_FIBER_MODE(unit, port) && !PHY_EXTERNAL_MODE(unit, port)) || 213 PHY_PASSTHRU_MODE(unit, port)) { 214 mode_1000x = CTRL1_FIBER_MODE; 215 } 216 /* Allow property to override */ 217 if (soc_property_port_get(unit, port, 218 spn_SERDES_FIBER_PREF, mode_1000x)) { 219 data16 |= CTRL1_FIBER_MODE; 220 } else { 221 data16 &= ~CTRL1_FIBER_MODE; 222 } 223 224 SOC_IF_ERROR_RETURN 225 (MODIFY_SERDES_DIGITAL_CTRL1r(unit, pc, data16, mask16)); 226 227 /* Start PLL Sequencer */ 228 SOC_IF_ERROR_RETURN 229 (MODIFY_XGXS_BLK0_CTRLr(unit, pc, XGXS_CTRL_START_SEQUENCER, 230 XGXS_CTRL_START_SEQUENCER)); 231 232 LOG_INFO(BSL_LS_SOC_PHY, 233 (BSL_META_U(unit, 234 "phy_combo65_init: u=%d p=%d %s\n"), 235 unit, port, 236 PHY_FIBER_MODE(unit, port) ? "Fiber" : "Copper")); 237 return SOC_E_NONE; 238 } 239 240 241 /* 242 * Function: 243 * phy_combo65_init 244 * Purpose: 245 * Initialize serdescombo65 internal PHY driver 246 * Parameters: 247 * unit - StrataSwitch unit #. 248 * port - StrataSwitch port #. 249 * Returns: 250 * SOC_E_NONE 251 * Notes: 252 * This function implements the bulk part of phy_combo65_init and 253 * provides a method for initializing the SerDes when it is used 254 * as an intermediate PHY between the MAC and an external PHY. 255 * In the latter case the PHY driver reset callback should be 256 * called only once, and this has already been done by the 257 * external PHY driver init function. 258 */ 259 260 STATIC int 261 phy_combo65_init(int unit, soc_port_t port) 262 { 263 LOG_INFO(BSL_LS_SOC_PHY, 264 (BSL_META_U(unit, 265 "phy_combo65_init: u=%d p=%d\n"), 266 unit, port)); 267 268 if (!PHY_EXTERNAL_MODE(unit, port)) { 269 /* PHY reset callbacks */ 270 SOC_IF_ERROR_RETURN(soc_phy_reset(unit, port)); 271 272 if (soc_property_port_get(unit, port, 273 spn_SERDES_FIBER_PREF, 1)) { 274 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 275 } else { 276 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 277 } 278 279 280 if (soc_property_port_get(unit, port, 281 spn_PHY_AN_C73, FALSE)) { 282 PHY_FLAGS_SET(unit, port, PHY_FLAGS_C73); 283 } 284 if (PHY_SGMII_AUTONEG_MODE(unit, port)) { 285 LOG_WARN(BSL_LS_SOC_PHY, 286 (BSL_META_U(unit, 287 "WARNING: SGMII autoneg enabled but no PHY attached:" 288 " u=%d p=%d \n"), unit, port)); 289 } 290 } 291 292 SOC_IF_ERROR_RETURN 293 (phy_combo65_init_no_reset(unit, port)); 294 295 return SOC_E_NONE; 296 } 297 298 /* 299 * Function: 300 * phy_combo65_link_get 301 * Purpose: 302 * Determine the current link up/down status 303 * Parameters: 304 * unit - StrataSwitch unit #. 305 * port - StrataSwitch port #. 306 * link - (OUT) Boolean, true indicates link established. 307 * Returns: 308 * SOC_E_XXX 309 * Notes: 310 * MII_STATUS bit 2 reflects link state. 311 */ 312 STATIC int 313 phy_combo65_link_get(int unit, soc_port_t port, int *link) 314 { 315 uint16 mii_stat; 316 uint16 mii_ctrl; 317 int an_done; 318 phy_ctrl_t *pc; 319 320 if (PHY_DISABLED_MODE(unit, port)) { 321 *link = FALSE; 322 } else { 323 pc = INT_PHY_SW_STATE(unit, port); 324 325 SOC_IF_ERROR_RETURN 326 (READ_COMBO_IEEE0_MII_STATr(unit, pc, &mii_stat)); 327 328 *link = ((mii_stat & MII_STAT_LA) != 0); 329 330 SOC_IF_ERROR_RETURN 331 (READ_COMBO_IEEE0_MII_CTRLr(unit, pc, &mii_ctrl)); 332 333 if (mii_ctrl & MII_CTRL_AE) { 334 /* If autoneg is enabled, check for autoneg done. */ 335 an_done = ((mii_stat & MII_STAT_AN_DONE) != 0); 336 337 *link = (*link) && (an_done); 338 } 339 } 340 return SOC_E_NONE; 341 } 342 343 /* 344 * Function: 345 * phy_combo65_enable_set 346 * Purpose: 347 * Enable or disable the physical interface. 348 * Parameters: 349 * unit - StrataSwitch unit #. 350 * port - StrataSwitch port #. 351 * enable - Boolean, true = enable PHY, false = disable. 352 * Returns: 353 * SOC_E_XXX 354 * Notes: 355 * The PHY is held in reset when disabled. Also, the 356 * MISC_CONTROL.IDDQ bit must be set to 1 so the remote partner 357 * sees link down. 358 */ 359 360 STATIC int 361 phy_combo65_enable_set(int unit, soc_port_t port, int enable) 362 { 363 LOG_INFO(BSL_LS_SOC_PHY, 364 (BSL_META_U(unit, 365 "phy_combo65_enable_set: u=%d p=%d en=%d\n"), 366 unit, port, enable)); 367 if (enable) { 368 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE); 369 370 SOC_IF_ERROR_RETURN 371 (_phy_combo65_notify_resume(unit, port, PHY_STOP_PHY_DIS)); 372 } else { 373 PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE); 374 375 SOC_IF_ERROR_RETURN 376 (_phy_combo65_notify_stop(unit, port, PHY_STOP_PHY_DIS)); 377 } 378 379 return SOC_E_NONE; 380 } 381 382 /* 383 * Function: 384 * phy_combo65_duplex_set 385 * Purpose: 386 * Set the current duplex mode (forced). 387 * Parameters: 388 * unit - StrataSwitch unit #. 389 * port - StrataSwitch port #. 390 * duplex - Boolean, TRUE indicates full duplex, FALSE indicates half. 391 * Returns: 392 * SOC_E_XXX 393 */ 394 395 STATIC int 396 phy_combo65_duplex_set(int unit, soc_port_t port, int duplex) 397 { 398 int rv; 399 400 COMPILER_REFERENCE(unit); 401 COMPILER_REFERENCE(port); 402 403 rv = duplex ? SOC_E_NONE : SOC_E_UNAVAIL; 404 405 LOG_INFO(BSL_LS_SOC_PHY, 406 (BSL_META_U(unit, 407 "phy_combo65_duplex_set: u=%d p=%d duplex=%d rv=%d\n"), 408 unit, port, duplex, rv)); 409 410 return rv; 411 } 412 413 /* 414 * Function: 415 * phy_combo65_speed_set 416 * Purpose: 417 * Set the current operating speed (forced). 418 * Parameters: 419 * unit - StrataSwitch unit #. 420 * port - StrataSwitch port #. 421 * duplex - (OUT) Boolean, true indicates full duplex, false 422 * indicates half. 423 * Returns: 424 * SOC_E_XXX 425 */ 426 427 STATIC int 428 phy_combo65_speed_set(int unit, soc_port_t port, int speed) 429 { 430 uint16 status; 431 uint16 mii_ctrl, misc1; 432 phy_ctrl_t *pc; 433 int rv; 434 435 pc = INT_PHY_SW_STATE(unit, port); 436 rv = SOC_E_NONE; 437 438 SOC_IF_ERROR_RETURN 439 (READ_SERDES_DIGITAL_STAT1r(unit, pc, &status)); 440 441 if (status & STAT1_SGMII_MODE) { 442 if ((speed != 0) && (speed != 10) && 443 (speed != 100) && (speed != 1000)) { 444 return SOC_E_PARAM; 445 } 446 } else { 447 if ((speed != 0) && (speed != 1000) && (speed != 2500)) { 448 return SOC_E_PARAM; 449 } 450 } 451 452 /* Stop Sequencer */ 453 SOC_IF_ERROR_RETURN 454 (MODIFY_XGXS_BLK0_CTRLr(unit, pc, 0, XGXS_CTRL_START_SEQUENCER)); 455 456 mii_ctrl = misc1 = 0; 457 switch (speed) { 458 case 10: 459 mii_ctrl = MII_CTRL_SS_10; 460 break; 461 case 100: 462 mii_ctrl = MII_CTRL_SS_100; 463 break; 464 case 0: 465 case 1000: 466 mii_ctrl = MII_CTRL_SS_1000; 467 break; 468 case 2500: 469 misc1 = MISC1_FORCE_SPEED_SEL | MISC1_FORCE_SPEED_2P5GB; 470 break; 471 } 472 SOC_IF_ERROR_RETURN 473 (MODIFY_COMBO_IEEE0_MII_CTRLr(unit, pc, mii_ctrl, MII_CTRL_SS_MASK)); 474 475 SOC_IF_ERROR_RETURN 476 (MODIFY_SERDES_DIGITAL_MISC1r(unit, pc, misc1, 477 MISC1_FORCE_SPEED_SEL | MISC1_FORCE_SPEED)); 478 479 /* Start Sequencer */ 480 SOC_IF_ERROR_RETURN 481 (MODIFY_XGXS_BLK0_CTRLr(unit, pc, XGXS_CTRL_START_SEQUENCER, 482 XGXS_CTRL_START_SEQUENCER)); 483 484 pc->fiber.force_speed = speed; 485 486 LOG_INFO(BSL_LS_SOC_PHY, 487 (BSL_META_U(unit, 488 "phy_combo65_speed_set: u=%d p=%d speed=%d rv=%d\n"), 489 unit, port, speed, rv)); 490 491 return rv; 492 } 493 494 /* 495 * Function: 496 * phy_combo65_speed_get 497 * Purpose: 498 * Get the current operating speed. If autoneg is enabled, 499 * then operating mode is returned, otherwise forced mode is returned. 500 * Parameters: 501 * unit - StrataSwitch unit #. 502 * port - StrataSwitch port #. 503 * duplex - (OUT) Boolean, true indicates full duplex, false 504 * indicates half. 505 * Returns: 506 * SOC_E_XXX 507 */ 508 509 STATIC int 510 phy_combo65_speed_get(int unit, soc_port_t port, int *speed) 511 { 512 uint16 mii_ctrl, mii_stat, digi_stat; 513 phy_ctrl_t *pc; 514 515 pc = INT_PHY_SW_STATE(unit, port); 516 517 SOC_IF_ERROR_RETURN 518 (READ_COMBO_IEEE0_MII_CTRLr(unit, pc, &mii_ctrl)); 519 520 if (mii_ctrl & MII_CTRL_AE) { /* Auto-negotiation enabled */ 521 SOC_IF_ERROR_RETURN 522 (READ_COMBO_IEEE0_MII_STATr(unit, pc, &mii_stat)); 523 if (!(mii_stat & MII_STAT_AN_DONE)) { /* Auto-neg NOT complete */ 524 *speed = 0; 525 return SOC_E_NONE; 526 } 527 } 528 529 SOC_IF_ERROR_RETURN 530 (READ_SERDES_DIGITAL_STAT1r(unit, pc, &digi_stat)); 531 switch (digi_stat & STAT1_SPEED_STATUS) { 532 case STAT1_SPEED_10MB: 533 *speed = 10; 534 break; 535 case STAT1_SPEED_100MB: 536 *speed = 100; 537 break; 538 case STAT1_SPEED_1000MB: 539 *speed = 1000; 540 break; 541 case STAT1_SPEED_2P5GB: 542 *speed = 2500; 543 break; 544 default: /* Will never happen */ 545 *speed = 1000; 546 break; 547 } 548 549 return SOC_E_NONE; 550 } 551 552 /* 553 * Function: 554 * phy_combo65_an_set 555 * Purpose: 556 * Enable or disabled auto-negotiation on the specified port. 557 * Parameters: 558 * unit - StrataSwitch unit #. 559 * port - StrataSwitch port #. 560 * an - Boolean, if true, auto-negotiation is enabled 561 * (and/or restarted). If false, autonegotiation is disabled. 562 * Returns: 563 * SOC_E_XXX 564 */ 565 566 STATIC int 567 phy_combo65_an_set(int unit, soc_port_t port, int an) 568 { 569 phy_ctrl_t *pc; 570 uint16 an_enable; 571 uint16 auto_det; 572 573 pc = INT_PHY_SW_STATE(unit, port); 574 575 LOG_INFO(BSL_LS_SOC_PHY, 576 (BSL_META_U(unit, 577 "phy_combo65_an_set: u=%d p=%d an=%d\n"), 578 unit, port, an)); 579 580 an_enable = 0; 581 auto_det = 0; 582 if (an) { 583 an_enable = MII_CTRL_AE | MII_CTRL_RAN; 584 if (soc_property_port_get(unit, port, 585 spn_SERDES_AUTOMEDIUM, FALSE)) { 586 auto_det = CTRL1_AUTODET_EN; 587 } 588 /* Stop Sequencer */ 589 SOC_IF_ERROR_RETURN 590 (MODIFY_XGXS_BLK0_CTRLr(unit, pc, 0, XGXS_CTRL_START_SEQUENCER)); 591 592 SOC_IF_ERROR_RETURN 593 (MODIFY_COMBO_IEEE0_MII_CTRLr(unit, pc, MII_CTRL_SS_1000, 594 MII_CTRL_SS_MASK)); 595 596 SOC_IF_ERROR_RETURN 597 (MODIFY_SERDES_DIGITAL_MISC1r(unit, pc, 0, 598 MISC1_FORCE_SPEED_SEL | MISC1_FORCE_SPEED)); 599 600 /* Start Sequencer */ 601 SOC_IF_ERROR_RETURN 602 (MODIFY_XGXS_BLK0_CTRLr(unit, pc, XGXS_CTRL_START_SEQUENCER, 603 XGXS_CTRL_START_SEQUENCER)); 604 } 605 606 /* Enable/Disable auto detect */ 607 SOC_IF_ERROR_RETURN 608 (MODIFY_SERDES_DIGITAL_CTRL1r(unit, pc, auto_det, 609 CTRL1_AUTODET_EN)); 610 /* Enable/Disable parallel detect */ 611 SOC_IF_ERROR_RETURN 612 (MODIFY_SERDES_DIGITAL_CTRL2r(unit, pc, 613 an? CTRL2_ENABLE_PARALLEL_DETECT: 0, 614 CTRL2_ENABLE_PARALLEL_DETECT)); 615 616 /* Enable/Disable and Restart autonegotiation (self-clearing bit) */ 617 SOC_IF_ERROR_RETURN 618 (MODIFY_COMBO_IEEE0_MII_CTRLr(unit, pc, an_enable, 619 MII_CTRL_AE | MII_CTRL_RAN)); 620 621 if (PHY_CLAUSE73_MODE(unit, port)) { 622 if (an) { 623 /* Enable BAM Station Manager */ 624 SOC_IF_ERROR_RETURN 625 (WRITE_CL73_USERB0_BAMCTRL1r(unit, pc, 626 (CL73_BAMCTRL1_BAMEN | CL73_BAMCTRL1_STATION_MNGR_EN | 627 CL73_BAMCTRL1_BAMNP_AFTER_BP_EN))); 628 629 /* Merge CL73 and CL37 autoneg resolution */ 630 SOC_IF_ERROR_RETURN 631 (MODIFY_CL73_USERB0_BAMCTRL3r(unit, pc, 632 CL73_BAMCTRL3_USE_CL73_HCD_MR, 633 CL73_BAMCTRL3_USE_CL73_HCD_MR)); 634 635 /* Enable CL73 Autoneg and restart negotiation */ 636 SOC_IF_ERROR_RETURN 637 (WRITE_CL73_IEEEB0_AN_CTRLr(unit, pc, 638 (CL73_AN_CTRL_AUTONEG_EN | 639 CL73_AN_CTRL_RES_NEGOTIATION))); 640 } else { 641 /* Disable CL73 autoneg */ 642 SOC_IF_ERROR_RETURN 643 (WRITE_CL73_IEEEB0_AN_CTRLr(unit, pc, 0)); 644 } 645 } 646 647 pc->fiber.autoneg_enable = an; 648 649 return SOC_E_NONE; 650 } 651 652 /* 653 * Function: 654 * phy_combo65_an_get 655 * Purpose: 656 * Get the current auto-negotiation status (enabled/busy) 657 * Parameters: 658 * unit - StrataSwitch unit #. 659 * port - StrataSwitch port #. 660 * an - (OUT) if true, auto-negotiation is enabled. 661 * an_done - (OUT) if true, auto-negotiation is complete. 662 * This value is undefined if an == false. 663 * Returns: 664 * SOC_E_XXX 665 * Note: 666 * Clause 37 autoneg is always in sync with clause 73. 667 * Therefore, reading C37 config is sufficient. 668 */ 669 670 STATIC int 671 phy_combo65_an_get(int unit, soc_port_t port, int *an, int *an_done) 672 { 673 uint16 ctrl, stat; 674 phy_ctrl_t *pc; 675 676 pc = INT_PHY_SW_STATE(unit, port); 677 678 SOC_IF_ERROR_RETURN 679 (READ_COMBO_IEEE0_MII_CTRLr(unit, pc, &ctrl)); 680 681 *an = (ctrl & MII_CTRL_AE) != 0; 682 683 SOC_IF_ERROR_RETURN 684 (READ_COMBO_IEEE0_MII_STATr(unit, pc, &stat)); 685 686 *an_done = (stat & MII_STAT_AN_DONE) != 0; 687 688 LOG_INFO(BSL_LS_SOC_PHY, 689 (BSL_META_U(unit, 690 "phy_combo65_an_get: u=%d p=%d an=%d an_done=%d\n"), 691 unit, port, *an, *an_done)); 692 693 return SOC_E_NONE; 694 } 695 696 /* 697 * Function: 698 * phy_combo65_adv_local_set 699 * Purpose: 700 * Set the current advertisement for auto-negotiation. 701 * Parameters: 702 * unit - StrataSwitch unit #. 703 * port - StrataSwitch port #. 704 * mode - Port mode mask indicating supported options/speeds. 705 * Returns: 706 * SOC_E_XXX 707 */ 708 STATIC int 709 phy_combo65_adv_local_set(int unit, soc_port_t port, soc_port_mode_t mode) 710 { 711 uint16 an_adv; 712 phy_ctrl_t *pc; 713 714 /* Note: 715 * We assume that switch SerDes is always used as slave when 716 * the port is in SGMII mode. Therefore, the adv_local_set is applicable 717 * only for fiber mode. 718 */ 719 pc = INT_PHY_SW_STATE(unit, port); 720 721 an_adv = 0; 722 723 /* 724 * Set advertised duplex (only FD supported). 725 */ 726 if (mode & SOC_PM_1000MB_FD) { 727 an_adv |= MII_ANA_C37_FD; 728 } 729 730 /* 731 * Set advertised pause bits in link code word. 732 */ 733 switch (mode & SOC_PM_PAUSE) { 734 case SOC_PM_PAUSE_TX: 735 an_adv |= MII_ANA_C37_ASYM_PAUSE; 736 break; 737 case SOC_PM_PAUSE_RX: 738 an_adv |= MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE; 739 break; 740 case SOC_PM_PAUSE_TX | SOC_PM_PAUSE_RX: 741 an_adv |= MII_ANA_C37_PAUSE; 742 break; 743 } 744 745 SOC_IF_ERROR_RETURN 746 (WRITE_COMBO_IEEE0_MII_ANAr(unit, pc, an_adv)); 747 748 /* Advertise 2.5 Gbps */ 749 an_adv = (mode & SOC_PM_2500MB_FD) ? UP1_ADV_2P5GB : 0; 750 SOC_IF_ERROR_RETURN 751 (WRITE_OVER_1G_UP1r(unit, pc, an_adv)); 752 753 if (PHY_CLAUSE73_MODE(unit, port)) { 754 an_adv = (mode & SOC_PM_1000MB_FD) ? CL73_AN_ADV2_LP_TECH_1G_KX : 0; 755 SOC_IF_ERROR_RETURN 756 (MODIFY_CL73_IEEEB1_AN_ADV2r(unit, pc, an_adv, 757 CL73_AN_ADV2_LP_TECH_1G_KX)); 758 759 switch (mode & SOC_PM_PAUSE) { 760 case SOC_PM_PAUSE_TX: 761 an_adv = CL73_AN_ADV1_LP_ASYM_PAUSE; 762 break; 763 case SOC_PM_PAUSE_RX: 764 an_adv = CL73_AN_ADV1_LP_PAUSE | CL73_AN_ADV1_LP_ASYM_PAUSE; 765 break; 766 case SOC_PM_PAUSE_TX | SOC_PM_PAUSE_RX: 767 an_adv = CL73_AN_ADV1_LP_PAUSE; 768 break; 769 default: 770 an_adv = 0; 771 break; 772 } 773 SOC_IF_ERROR_RETURN 774 (MODIFY_CL73_IEEEB1_AN_ADV1r(unit, pc, an_adv, 775 (CL73_AN_ADV1_LP_PAUSE | 776 CL73_AN_ADV1_LP_ASYM_PAUSE))); 777 778 /* When CL73 BAM is enabled, CL73 simply serves as conduit to 779 * CL37 and transmits next pages and abilities including over 1G. 780 * Therefore, 2.5G advertising will take affect according to 781 * over 1G up1 register. 782 */ 783 784 } 785 786 LOG_INFO(BSL_LS_SOC_PHY, 787 (BSL_META_U(unit, 788 "phy_combo65_adv_local_set: u=%d p=%d adv=%s%s%s%s\n"), 789 unit, port, 790 (mode & SOC_PM_2500MB_FD) ? "2500MB " : "", 791 (mode & SOC_PM_1000MB_FD) ? "1000MB " : "", 792 (mode & SOC_PM_PAUSE_TX) ? "PAUSE_TX " : "", 793 (mode & SOC_PM_PAUSE_RX) ? "PAUSE_TX " : "")); 794 return SOC_E_NONE; 795 } 796 797 /* 798 * Function: 799 * phy_combo65_adv_local_get 800 * Purpose: 801 * Get the current advertisement for auto-negotiation. 802 * Parameters: 803 * unit - StrataSwitch unit #. 804 * port - StrataSwitch port #. 805 * mode - (OUT) Port mode mask indicating supported options/speeds. 806 * Returns: 807 * SOC_E_XXX 808 */ 809 810 STATIC int 811 phy_combo65_adv_local_get(int unit, soc_port_t port, soc_port_mode_t *mode) 812 { 813 uint16 an_adv; 814 phy_ctrl_t *pc; 815 816 pc = INT_PHY_SW_STATE(unit, port); 817 818 *mode = 0; 819 820 SOC_IF_ERROR_RETURN 821 (READ_COMBO_IEEE0_MII_ANAr(unit, pc, &an_adv)); 822 823 if (an_adv & MII_ANA_C37_FD) { 824 *mode |= SOC_PM_1000MB_FD; 825 } 826 827 switch (an_adv & (MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE)) { 828 case MII_ANA_C37_PAUSE: 829 *mode |= SOC_PM_PAUSE_TX | SOC_PM_PAUSE_RX; 830 break; 831 case MII_ANA_C37_ASYM_PAUSE: 832 *mode |= SOC_PM_PAUSE_TX; 833 break; 834 case MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE: 835 *mode |= SOC_PM_PAUSE_RX; 836 break; 837 default: 838 break; 839 } 840 841 SOC_IF_ERROR_RETURN 842 (READ_OVER_1G_UP1r(unit, pc, &an_adv)); 843 *mode |= (an_adv & UP1_ADV_2P5GB) ? SOC_PM_2500MB_FD : 0; 844 845 return SOC_E_NONE; 846 } 847 848 /* 849 * Function: 850 * phy_combo65_adv_remote_get 851 * Purpose: 852 * Get partner's current advertisement for auto-negotiation. 853 * Parameters: 854 * unit - StrataSwitch unit #. 855 * port - StrataSwitch port #. 856 * mode - (OUT) Port mode mask indicating supported options/speeds. 857 * Returns: 858 * SOC_E_XXX 859 */ 860 861 STATIC int 862 phy_combo65_adv_remote_get(int unit, soc_port_t port, soc_port_mode_t *mode) 863 { 864 uint16 anlpa; 865 soc_port_mode_t duplex; 866 phy_ctrl_t *pc; 867 868 pc = INT_PHY_SW_STATE(unit, port); 869 870 SOC_IF_ERROR_RETURN 871 (READ_COMBO_IEEE0_MII_ANPr(unit, pc, &anlpa)); 872 873 *mode = 0; 874 if (anlpa & MII_ANP_SGMII_MODE) { 875 /* Link partner is in SGMII mode */ 876 switch (anlpa & MII_ANP_SGMII_SS_MASK) { 877 case MII_ANP_SGMII_SS_10: 878 *mode = SOC_PM_10MB; 879 break; 880 case MII_ANP_SGMII_SS_100: 881 *mode = SOC_PM_100MB; 882 break; 883 case MII_ANP_SGMII_SS_1000: 884 *mode = SOC_PM_1000MB; 885 break; 886 } 887 888 duplex = (anlpa & MII_ANP_SGMII_FD) ? SOC_PM_FD : SOC_PM_HD; 889 890 *mode = (*mode) & duplex; 891 } else { 892 /* Link partner is in 1000X/2500X mode */ 893 if (anlpa & MII_ANP_C37_FD) { 894 *mode |= SOC_PM_1000MB_FD; 895 } 896 897 if (anlpa & MII_ANP_C37_HD) { 898 *mode |= SOC_PM_1000MB_HD; 899 } 900 901 switch (anlpa & 902 (MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE)) { 903 case MII_ANP_C37_PAUSE: 904 *mode |= SOC_PM_PAUSE_TX | SOC_PM_PAUSE_RX; 905 break; 906 case MII_ANP_C37_ASYM_PAUSE: 907 *mode |= SOC_PM_PAUSE_TX; 908 break; 909 case MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE: 910 *mode |= SOC_PM_PAUSE_RX; 911 break; 912 } 913 914 SOC_IF_ERROR_RETURN 915 (READ_OVER_1G_LP_UP1r(unit, pc, &anlpa)); 916 *mode |= (anlpa & LP_UP1_ADV_2P5GB) ? 917 SOC_PM_2500MB_FD : 0; 918 } 919 920 LOG_INFO(BSL_LS_SOC_PHY, 921 (BSL_META_U(unit, 922 "phy_combo65_adv_remote_get:" 923 " u=%d p=%d adv=%s%s%s%s%s%s%s%s\n"), 924 unit, port, 925 (*mode & SOC_PM_2500MB) ? "2500MB " : "", 926 (*mode & SOC_PM_1000MB) ? "1000MB " : "", 927 (*mode & SOC_PM_100MB) ? "100MB " : "", 928 (*mode & SOC_PM_10MB) ? "10MB " : "", 929 (*mode & SOC_PM_FD) ? "FD " : "", 930 (*mode & SOC_PM_HD) ? "HD " : "", 931 (*mode & SOC_PM_PAUSE_TX) ? "PAUSE_TX " : "", 932 (*mode & SOC_PM_PAUSE_RX) ? "PAUSE_TX " : "")); 933 934 return SOC_E_NONE; 935 } 936 937 /* 938 * Function: 939 * phy_combo65_lb_set 940 * Purpose: 941 * Set the internal PHY loopback mode. 942 * Parameters: 943 * unit - StrataSwitch unit #. 944 * port - StrataSwitch port #. 945 * loopback - Boolean: true = enable loopback, false = disable. 946 * Returns: 947 * SOC_E_XXX 948 */ 949 950 STATIC int 951 phy_combo65_lb_set(int unit, soc_port_t port, int enable) 952 { 953 uint16 ctrl; 954 phy_ctrl_t *pc; 955 int rv; 956 957 pc = INT_PHY_SW_STATE(unit, port); 958 959 ctrl = (enable) ? MII_CTRL_LE : 0; 960 961 rv = MODIFY_COMBO_IEEE0_MII_CTRLr(unit, pc, ctrl, MII_CTRL_LE); 962 963 LOG_INFO(BSL_LS_SOC_PHY, 964 (BSL_META_U(unit, 965 "phy_combo65_lb_set: u=%d p=%d lb=%d rv=%d\n"), 966 unit, port, enable, rv)); 967 968 return rv; 969 } 970 971 /* 972 * Function: 973 * phy_combo65_lb_get 974 * Purpose: 975 * Get the local PHY loopback mode. 976 * Parameters: 977 * unit - StrataSwitch unit #. 978 * port - StrataSwitch port #. 979 * loopback - (OUT) Boolean: true = enable loopback, false = disable. 980 * Returns: 981 * SOC_E_XXX 982 */ 983 984 STATIC int 985 phy_combo65_lb_get(int unit, soc_port_t port, int *enable) 986 { 987 uint16 ctrl; 988 phy_ctrl_t *pc; 989 990 pc = INT_PHY_SW_STATE(unit, port); 991 SOC_IF_ERROR_RETURN 992 (READ_COMBO_IEEE0_MII_CTRLr(unit, pc, &ctrl)); 993 994 *enable = (ctrl & MII_CTRL_LE) != 0; 995 996 return SOC_E_NONE; 997 } 998 999 /* 1000 * Function: 1001 * phy_combo65_interface_set 1002 * Purpose: 1003 * Set the current operating mode of the internal PHY. 1004 * (Pertaining to the MAC/PHY interface, not the line interface). 1005 * Parameters: 1006 * unit - StrataSwitch unit #. 1007 * port - StrataSwitch port #. 1008 * pif - one of SOC_PORT_IF_* 1009 * Returns: 1010 * SOC_E_XXX 1011 */ 1012 1013 STATIC int 1014 phy_combo65_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 1015 { 1016 int rv; 1017 1018 switch (pif) { 1019 case SOC_PORT_IF_MII: 1020 case SOC_PORT_IF_GMII: 1021 case SOC_PORT_IF_SGMII: 1022 case SOC_PORT_IF_NOCXN: 1023 rv = SOC_E_NONE; 1024 break; 1025 default: 1026 rv = SOC_E_UNAVAIL; 1027 break; 1028 } 1029 1030 LOG_INFO(BSL_LS_SOC_PHY, 1031 (BSL_META_U(unit, 1032 "phy_combo65_interface_set: " 1033 "u=%d p=%d pif=%d rv=%d\n"), 1034 unit, port, pif, rv)); 1035 1036 return rv; 1037 } 1038 1039 /* 1040 * Function: 1041 * phy_combo65_interface_get 1042 * Purpose: 1043 * Get the current operating mode of the internal PHY. 1044 * (Pertaining to the MAC/PHY interface, not the line interface). 1045 * Parameters: 1046 * unit - StrataSwitch unit #. 1047 * port - StrataSwitch port #. 1048 * pif - (OUT) one of SOC_PORT_IF_* 1049 * Returns: 1050 * SOC_E_XXX 1051 */ 1052 1053 STATIC int 1054 phy_combo65_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 1055 { 1056 COMPILER_REFERENCE(unit); 1057 COMPILER_REFERENCE(port); 1058 1059 *pif = SOC_PORT_IF_SGMII; 1060 1061 return(SOC_E_NONE); 1062 } 1063 1064 /* 1065 * Function: 1066 * phy_combo65_ability_get 1067 * Purpose: 1068 * Get the abilities of the internal PHY. 1069 * Parameters: 1070 * unit - StrataSwitch unit #. 1071 * port - StrataSwitch port #. 1072 * mode - (OUT) Port mode mask indicating supported options/speeds. 1073 * Returns: 1074 * SOC_E_XXX 1075 */ 1076 1077 STATIC int 1078 phy_combo65_ability_get(int unit, soc_port_t port, soc_port_mode_t *mode) 1079 { 1080 uint16 fiber_status; 1081 phy_ctrl_t *pc; 1082 1083 pc = INT_PHY_SW_STATE(unit, port); 1084 1085 SOC_IF_ERROR_RETURN 1086 (READ_SERDES_DIGITAL_STAT1r(unit, pc, &fiber_status)); 1087 1088 if (fiber_status & STAT1_SGMII_MODE) { 1089 *mode = SOC_PM_10MB | SOC_PM_100MB | SOC_PM_1000MB_FD | 1090 SOC_PM_LB_PHY | SOC_PM_GMII; 1091 } else { 1092 *mode = SOC_PM_2500MB_FD | SOC_PM_1000MB_FD | SOC_PM_PAUSE | 1093 SOC_PM_PAUSE_ASYMM | SOC_PM_LB_PHY | SOC_PM_AN | 1094 SOC_PM_GMII | SOC_PM_SGMII; 1095 } 1096 return SOC_E_NONE; 1097 } 1098 1099 /* 1100 * Function: 1101 * _phy_combo65_medium_config_update 1102 * Purpose: 1103 * Update the PHY with config parameters 1104 * Parameters: 1105 * unit - StrataSwitch unit #. 1106 * port - StrataSwitch port #. 1107 * cfg - Config structure. 1108 * Returns: 1109 * SOC_E_XXX 1110 */ 1111 1112 STATIC int 1113 _phy_combo65_medium_config_update(int unit, soc_port_t port, 1114 soc_phy_config_t *cfg) 1115 { 1116 SOC_IF_ERROR_RETURN 1117 (phy_combo65_speed_set(unit, port, cfg->force_speed)); 1118 SOC_IF_ERROR_RETURN 1119 (phy_combo65_duplex_set(unit, port, cfg->force_duplex)); 1120 SOC_IF_ERROR_RETURN 1121 (phy_combo65_adv_local_set(unit, port, cfg->autoneg_advert)); 1122 SOC_IF_ERROR_RETURN 1123 (phy_combo65_an_set(unit, port, cfg->autoneg_enable)); 1124 1125 return SOC_E_NONE; 1126 } 1127 1128 /* 1129 * Function: 1130 * phy_combo65_medium_config_set 1131 * Purpose: 1132 * Set the operating parameters that are automatically selected 1133 * when medium switches type. 1134 * Parameters: 1135 * unit - StrataSwitch unit # 1136 * port - Port number 1137 * medium - SOC_PORT_MEDIUM_COPPER/FIBER 1138 * cfg - Operating parameters 1139 * Returns: 1140 * SOC_E_XXX 1141 */ 1142 1143 STATIC int 1144 phy_combo65_medium_config_set(int unit, soc_port_t port, 1145 soc_port_medium_t medium, 1146 soc_phy_config_t *cfg) 1147 { 1148 1149 phy_ctrl_t *pc; 1150 1151 pc = INT_PHY_SW_STATE(unit, port); 1152 1153 /* 1154 * Changes take effect immediately if the target medium is active. 1155 */ 1156 switch (medium) { 1157 case SOC_PORT_MEDIUM_FIBER: 1158 /* Change the fiber modes */ 1159 1160 sal_memcpy(&pc->fiber, cfg, sizeof (pc->fiber)); 1161 1162 if (PHY_EXTERNAL_MODE(unit, port)) { 1163 pc->fiber.autoneg_advert &= ADVERT_ALL_FIBER; 1164 } else { 1165 pc->fiber.autoneg_advert &= ADVERT_ALL_FIBER | SOC_PM_2500MB_FD; 1166 } 1167 if (PHY_FIBER_MODE(unit, port)) { 1168 SOC_IF_ERROR_RETURN 1169 (_phy_combo65_medium_config_update(unit, port, &pc->fiber)); 1170 } 1171 return SOC_E_NONE; 1172 case SOC_PORT_MEDIUM_COPPER: 1173 return SOC_E_UNAVAIL; 1174 default: 1175 return SOC_E_PARAM; 1176 } 1177 } 1178 1179 /* 1180 * Function: 1181 * phy_combo65_medium_config_get 1182 * Purpose: 1183 * Get the operating parameters that are automatically selected 1184 * when medium switches type. 1185 * Parameters: 1186 * unit - StrataSwitch unit # 1187 * port - Port number 1188 * medium - SOC_PORT_MEDIUM_COPPER/FIBER 1189 * cfg - (OUT) Operating parameters 1190 * Returns: 1191 * SOC_E_XXX 1192 */ 1193 1194 STATIC int 1195 phy_combo65_medium_config_get(int unit, soc_port_t port, 1196 soc_port_medium_t medium, 1197 soc_phy_config_t *cfg) 1198 { 1199 phy_ctrl_t *pc; 1200 1201 pc = INT_PHY_SW_STATE(unit, port); 1202 1203 switch (medium) { 1204 case SOC_PORT_MEDIUM_FIBER: 1205 sal_memcpy(cfg, &pc->fiber, sizeof (*cfg)); 1206 return SOC_E_NONE; 1207 default: 1208 return SOC_E_PARAM; 1209 } 1210 } 1211 1212 /* 1213 * Function: 1214 * phy_combo65_medium_status 1215 * Purpose: 1216 * Indicate the current active medium 1217 * Parameters: 1218 * unit - StrataSwitch unit #. 1219 * port - StrataSwitch port #. 1220 * medium - (OUT) One of: 1221 * SOC_PORT_MEDIUM_COPPER 1222 * SOC_PORT_MEDIUM_FIBER 1223 * Returns: 1224 * SOC_E_NONE 1225 */ 1226 STATIC int 1227 phy_combo65_medium_status(int unit, soc_port_t port, soc_port_medium_t *medium) 1228 { 1229 COMPILER_REFERENCE(unit); 1230 COMPILER_REFERENCE(port); 1231 1232 *medium = SOC_PORT_MEDIUM_FIBER; 1233 1234 return SOC_E_NONE; 1235 } 1236 1237 /* 1238 * Function: 1239 * phy_combo65_master_set 1240 * Purpose: 1241 * Configure PHY master mode 1242 * Parameters: 1243 * unit - StrataSwitch unit #. 1244 * port - StrataSwitch port #. 1245 * master - PHY master mode. 1246 * Returns: 1247 * SOC_E_UNAVAIL 1248 */ 1249 STATIC int 1250 phy_combo65_master_set(int unit, soc_port_t port, int master) 1251 { 1252 COMPILER_REFERENCE(unit); 1253 COMPILER_REFERENCE(port); 1254 1255 if (master == SOC_PORT_MS_NONE) { 1256 return SOC_E_NONE; 1257 } 1258 return SOC_E_PARAM; 1259 } 1260 1261 /* 1262 * Function: 1263 * phy_combo65_master_get 1264 * Purpose: 1265 * Get current master mode setting 1266 * Parameters: 1267 * unit - StrataSwitch unit #. 1268 * port - StrataSwitch port #. 1269 * master - (OUT) BCM_PORT_MS_NONE 1270 * Returns: 1271 * SOC_E_NONE 1272 */ 1273 STATIC int 1274 phy_combo65_master_get(int unit, soc_port_t port, int *master) 1275 { 1276 uint16 fiber_status; 1277 phy_ctrl_t *pc; 1278 1279 pc = INT_PHY_SW_STATE(unit, port); 1280 1281 SOC_IF_ERROR_RETURN 1282 (READ_SERDES_DIGITAL_STAT1r(unit, pc, &fiber_status)); 1283 1284 if (fiber_status & STAT1_SGMII_MODE) { 1285 /* When in SGMII mode, the switch SerDes is always slave. */ 1286 *master = SOC_PORT_MS_SLAVE; 1287 } else { 1288 *master = SOC_PORT_MS_NONE; 1289 } 1290 1291 return SOC_E_NONE; 1292 } 1293 1294 STATIC int 1295 _phy_combo65_control_tx_driver_set(int unit, soc_port_t port, 1296 soc_phy_control_t type, uint32 value) 1297 { 1298 uint16 data; /* Temporary holder of reg value to be written */ 1299 uint16 mask; /* Bit mask of reg value to be updated */ 1300 phy_ctrl_t *pc; /* PHY software state */ 1301 1302 pc = INT_PHY_SW_STATE(unit, port); 1303 1304 /* Combo SerDes */ 1305 data = mask = 0; 1306 switch(type) { 1307 case SOC_PHY_CONTROL_PREEMPHASIS: 1308 data = (uint16)(value << 12) & TX_DRIVER_PREEMPHASIS; 1309 mask = TX_DRIVER_PREEMPHASIS; 1310 break; 1311 case SOC_PHY_CONTROL_DRIVER_CURRENT: 1312 data = (uint16)(value << 8) & TX_DRIVER_IDRIVER; 1313 mask = TX_DRIVER_IDRIVER; 1314 break; 1315 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 1316 data = (uint16)(value << 4) & TX_DRIVER_IPREDRIVER; 1317 mask = TX_DRIVER_IPREDRIVER; 1318 break; 1319 default: 1320 /* should never get here */ 1321 return SOC_E_PARAM; 1322 } 1323 /* Combo SerDes */ 1324 SOC_IF_ERROR_RETURN 1325 (MODIFY_TX_ALL_DRIVERr(unit, pc, data, mask)); 1326 1327 return SOC_E_NONE; 1328 } 1329 1330 STATIC int 1331 _phy_combo65_control_tx_driver_get(int unit, soc_port_t port, 1332 soc_phy_control_t type, uint32 *value) 1333 { 1334 uint16 data16; /* Temporary holder of a reg value */ 1335 phy_ctrl_t *pc; /* PHY software state */ 1336 1337 pc = INT_PHY_SW_STATE(unit, port); 1338 1339 data16 = 0; 1340 /* Combo SerDes */ 1341 SOC_IF_ERROR_RETURN 1342 (READ_TX_ALL_DRIVERr(unit, pc, &data16)); 1343 switch(type) { 1344 case SOC_PHY_CONTROL_PREEMPHASIS: 1345 *value = (data16 & TX_DRIVER_PREEMPHASIS) >> 12; 1346 break; 1347 case SOC_PHY_CONTROL_DRIVER_CURRENT: 1348 *value = (data16 & TX_DRIVER_IDRIVER) >> 8; 1349 break; 1350 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 1351 *value = (data16 & TX_DRIVER_IPREDRIVER) >> 4; 1352 break; 1353 default: 1354 /* should never get here */ 1355 return SOC_E_PARAM; 1356 } 1357 1358 return SOC_E_NONE; 1359 } 1360 1361 STATIC int 1362 _phy_combo65_control_linkdown_transmit_set(int unit, soc_port_t port, 1363 uint32 value) 1364 { 1365 uint16 data; 1366 phy_ctrl_t *pc; 1367 1368 pc = INT_PHY_SW_STATE(unit, port); 1369 1370 if (value) { 1371 data = CTRL2_FORCE_XMIT_DATA_ON_TXSIDE | CTRL2_FILTER_FORCE_LINK | 1372 CTRL2_DISABLE_FALSE_LINK; 1373 SOC_IF_ERROR_RETURN 1374 (WRITE_SERDES_DIGITAL_CTRL2r(unit, pc, data)); 1375 } else { 1376 data = CTRL2_FILTER_FORCE_LINK | CTRL2_DISABLE_FALSE_LINK | 1377 CTRL2_ENABLE_PARALLEL_DETECT; 1378 SOC_IF_ERROR_RETURN 1379 (WRITE_SERDES_DIGITAL_CTRL2r(unit, pc, data)); 1380 } 1381 1382 return SOC_E_NONE; 1383 } 1384 1385 1386 STATIC int 1387 _phy_combo65_control_linkdown_transmit_get(int unit, soc_port_t port, 1388 uint32 *value) 1389 { 1390 uint16 data; 1391 phy_ctrl_t *pc; 1392 1393 pc = INT_PHY_SW_STATE(unit, port); 1394 1395 SOC_IF_ERROR_RETURN 1396 (READ_SERDES_DIGITAL_CTRL2r(unit, pc, &data)); 1397 1398 *value = (data & CTRL2_FORCE_XMIT_DATA_ON_TXSIDE) ? 1 : 0; 1399 1400 return SOC_E_NONE; 1401 } 1402 1403 1404 /* 1405 * Function: 1406 * phy_physerdescombo65_control_set 1407 * Purpose: 1408 * Configure PHY device specific control fucntion. 1409 * Parameters: 1410 * unit - StrataSwitch unit #. 1411 * port - StrataSwitch port #. 1412 * type - Control to update 1413 * value - New setting for the control 1414 * Returns: 1415 * SOC_E_NONE 1416 */ 1417 STATIC int 1418 phy_combo65_control_set(int unit, soc_port_t port, 1419 soc_phy_control_t type, uint32 value) 1420 { 1421 int rv; 1422 phy_ctrl_t *pc; 1423 1424 pc = INT_PHY_SW_STATE(unit, port); 1425 /* coverity[mixed_enums] */ 1426 if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) { 1427 return SOC_E_PARAM; 1428 } 1429 1430 rv = SOC_E_UNAVAIL; 1431 switch(type) { 1432 case SOC_PHY_CONTROL_PREEMPHASIS: 1433 /* fall through */ 1434 case SOC_PHY_CONTROL_DRIVER_CURRENT: 1435 /* fall through */ 1436 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 1437 rv = _phy_combo65_control_tx_driver_set(unit, port, type, value); 1438 break; 1439 case SOC_PHY_CONTROL_LINKDOWN_TRANSMIT: 1440 rv = _phy_combo65_control_linkdown_transmit_set(unit, port, value); 1441 break; 1442 case SOC_PHY_CONTROL_PARALLEL_DETECTION: 1443 /* enable 1000X parallel detect */ 1444 SOC_IF_ERROR_RETURN 1445 (MODIFY_SERDES_DIGITAL_CTRL2r(unit, pc, 1446 value? CTRL2_ENABLE_PARALLEL_DETECT:0, 1447 CTRL2_ENABLE_PARALLEL_DETECT)); 1448 rv = SOC_E_NONE; 1449 break; 1450 default: 1451 rv = SOC_E_UNAVAIL; 1452 break; 1453 } 1454 return rv; 1455 } 1456 /* 1457 * Function: 1458 * phy_combo65_control_get 1459 * Purpose: 1460 * Get current control settign of the PHY. 1461 * Parameters: 1462 * unit - StrataSwitch unit #. 1463 * port - StrataSwitch port #. 1464 * type - Control to update 1465 * value - (OUT)Current setting for the control 1466 * Returns: 1467 * SOC_E_NONE 1468 */ 1469 STATIC int 1470 phy_combo65_control_get(int unit, soc_port_t port, 1471 soc_phy_control_t type, uint32 *value) 1472 { 1473 int rv; 1474 phy_ctrl_t *pc; 1475 uint16 data16; 1476 1477 pc = INT_PHY_SW_STATE(unit, port); 1478 1479 if (NULL == value) { 1480 return SOC_E_PARAM; 1481 } 1482 /* coverity[mixed_enums] */ 1483 if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) { 1484 return SOC_E_PARAM; 1485 } 1486 1487 rv = SOC_E_UNAVAIL; 1488 switch(type) { 1489 case SOC_PHY_CONTROL_PREEMPHASIS: 1490 /* fall through */ 1491 case SOC_PHY_CONTROL_DRIVER_CURRENT: 1492 /* fall through */ 1493 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 1494 rv = _phy_combo65_control_tx_driver_get(unit, port, type, value); 1495 break; 1496 case SOC_PHY_CONTROL_LINKDOWN_TRANSMIT: 1497 rv = _phy_combo65_control_linkdown_transmit_get(unit, port, value); 1498 break; 1499 case SOC_PHY_CONTROL_PARALLEL_DETECTION: 1500 SOC_IF_ERROR_RETURN 1501 (READ_SERDES_DIGITAL_CTRL2r(unit, pc,&data16)); 1502 *value = data16 & CTRL2_ENABLE_PARALLEL_DETECT? TRUE: FALSE; 1503 rv = SOC_E_NONE; 1504 break; 1505 default: 1506 rv = SOC_E_UNAVAIL; 1507 break; 1508 } 1509 1510 return rv; 1511 } 1512 1513 /* 1514 * Function: 1515 * phy_combo65_reg_read 1516 * Purpose: 1517 * Routine to read PHY register 1518 * Parameters: 1519 * uint - BCM unit number 1520 * pc - PHY state 1521 * flags - Flags which specify the register type 1522 * phy_reg_addr - Encoded register address 1523 * phy_data - (OUT) Value read from PHY register 1524 * Note: 1525 * This register read function is not thread safe. Higher level 1526 * function that calls this function must obtain a per port lock 1527 * to avoid overriding register page mapping between threads. 1528 */ 1529 STATIC int 1530 phy_combo65_reg_read(int unit, soc_port_t port, uint32 flags, 1531 uint32 phy_reg_addr, uint32 *phy_data) 1532 { 1533 uint16 data; /* Temporary holder for phy_data */ 1534 phy_ctrl_t *pc; /* PHY software state */ 1535 1536 pc = INT_PHY_SW_STATE(unit, port); 1537 1538 SOC_IF_ERROR_RETURN 1539 (phy_reg_aer_read(unit, pc, phy_reg_addr, &data)); 1540 1541 *phy_data = data; 1542 1543 return SOC_E_NONE; 1544 } 1545 1546 /* 1547 * Function: 1548 * phy_combo65_reg_write 1549 * Purpose: 1550 * Routine to write PHY register 1551 * Parameters: 1552 * uint - BCM unit number 1553 * pc - PHY state 1554 * flags - Flags which specify the register type 1555 * phy_reg_addr - Encoded register address 1556 * phy_data - Value write to PHY register 1557 * Note: 1558 * This register read function is not thread safe. Higher level 1559 * function that calls this function must obtain a per port lock 1560 * to avoid overriding register page mapping between threads. 1561 */ 1562 STATIC int 1563 phy_combo65_reg_write(int unit, soc_port_t port, uint32 flags, 1564 uint32 phy_reg_addr, uint32 phy_data) 1565 { 1566 uint16 data; /* Temporary holder for phy_data */ 1567 phy_ctrl_t *pc; /* PHY software state */ 1568 1569 pc = INT_PHY_SW_STATE(unit, port); 1570 1571 data = (uint16) (phy_data & 0x0000FFFF); 1572 1573 SOC_IF_ERROR_RETURN 1574 (phy_reg_aer_write(unit, pc, phy_reg_addr, data)); 1575 1576 return SOC_E_NONE; 1577 } 1578 1579 /* 1580 * Function: 1581 * phy_combo65_reg_modify 1582 * Purpose: 1583 * Routine to write PHY register 1584 * Parameters: 1585 * uint - BCM unit number 1586 * pc - PHY state 1587 * flags - Flags which specify the register type 1588 * phy_reg_addr - Encoded register address 1589 * phy_mo_data - New value for the bits specified in phy_mo_mask 1590 * phy_mo_mask - Bit mask to modify 1591 * Note: 1592 * This register read function is not thread safe. Higher level 1593 * function that calls this function must obtain a per port lock 1594 * to avoid overriding register page mapping between threads. 1595 */ 1596 STATIC int 1597 phy_combo65_reg_modify(int unit, soc_port_t port, uint32 flags, 1598 uint32 phy_reg_addr, uint32 phy_data, uint32 phy_data_mask) 1599 { 1600 uint16 data; /* Temporary holder for phy_data */ 1601 uint16 mask; 1602 phy_ctrl_t *pc; /* PHY software state */ 1603 1604 pc = INT_PHY_SW_STATE(unit, port); 1605 1606 data = (uint16) (phy_data & 0x0000FFFF); 1607 mask = (uint16) (phy_data_mask & 0x0000FFFF); 1608 1609 SOC_IF_ERROR_RETURN 1610 (phy_reg_aer_modify(unit, pc, phy_reg_addr, data, mask)); 1611 1612 return SOC_E_NONE; 1613 } 1614 1615 STATIC int 1616 phy_combo65_notify(int unit, soc_port_t port, 1617 soc_phy_event_t event, uint32 value) 1618 { 1619 int rv; 1620 1621 if (event >= phyEventCount) { 1622 return SOC_E_PARAM; 1623 } 1624 1625 rv = SOC_E_NONE; 1626 switch(event) { 1627 case phyEventInterface: 1628 rv = (_phy_combo65_notify_interface(unit, port, value)); 1629 break; 1630 case phyEventDuplex: 1631 rv = (_phy_combo65_notify_duplex(unit, port, value)); 1632 break; 1633 case phyEventSpeed: 1634 rv = (_phy_combo65_notify_speed(unit, port, value)); 1635 break; 1636 case phyEventStop: 1637 rv = (_phy_combo65_notify_stop(unit, port, value)); 1638 break; 1639 case phyEventResume: 1640 rv = (_phy_combo65_notify_resume(unit, port, value)); 1641 break; 1642 case phyEventAutoneg: 1643 rv = (phy_combo65_an_set(unit, port, value)); 1644 break; 1645 default: 1646 rv = SOC_E_UNAVAIL; 1647 break; 1648 } 1649 1650 return rv; 1651 } 1652 1653 STATIC int 1654 phy_combo65_duplex_get(int unit, soc_port_t port, int *duplex) 1655 { 1656 uint16 reg0_16; 1657 uint16 mii_ctrl; 1658 phy_ctrl_t *pc; 1659 1660 pc = INT_PHY_SW_STATE(unit, port); 1661 *duplex = TRUE; 1662 1663 SOC_IF_ERROR_RETURN 1664 (READ_SERDES_DIGITAL_STAT1r(unit, pc, ®0_16)); 1665 1666 if (reg0_16 & STAT1_SGMII_MODE) { 1667 /* retrieve the duplex setting in SGMII mode */ 1668 1669 SOC_IF_ERROR_RETURN 1670 (READ_COMBO_IEEE0_MII_CTRLr(unit, pc, &mii_ctrl)); 1671 1672 if (mii_ctrl & MII_CTRL_AE) { 1673 SOC_IF_ERROR_RETURN 1674 (READ_COMBO_IEEE0_MII_ANPr(unit,pc,®0_16)); 1675 1676 /* make sure link partner is also in SGMII mode 1677 * otherwise fall through to use the FD bit in MII_CTRL reg 1678 */ 1679 if (reg0_16 & MII_ANP_SGMII_MODE) { 1680 if (reg0_16 & MII_ANP_SGMII_FD) { 1681 *duplex = TRUE; 1682 } else { 1683 *duplex = FALSE; 1684 } 1685 return SOC_E_NONE; 1686 } 1687 } 1688 *duplex = (mii_ctrl & MII_CTRL_FD) ? TRUE : FALSE; 1689 } 1690 return SOC_E_NONE; 1691 } 1692 1693 /* 1694 * Variable: phy_serdescombo65_ge 1695 * Purpose: PHY Driver for Dozen SerDes Serdes PHY internal to Draco, 1696 */ 1697 phy_driver_t phy_serdescombo65_ge = { 1698 "Internal 2.5G 65nm SERDES PHY Driver", 1699 phy_combo65_init, 1700 phy_null_reset, 1701 phy_combo65_link_get, 1702 phy_combo65_enable_set, 1703 phy_null_enable_get, 1704 phy_combo65_duplex_set, 1705 phy_combo65_duplex_get, /* duplex_get */ 1706 phy_combo65_speed_set, 1707 phy_combo65_speed_get, 1708 phy_combo65_master_set, /* master_set */ 1709 phy_combo65_master_get, /* master_get */ 1710 phy_combo65_an_set, 1711 phy_combo65_an_get, 1712 phy_combo65_adv_local_set, 1713 phy_combo65_adv_local_get, 1714 phy_combo65_adv_remote_get, 1715 phy_combo65_lb_set, 1716 phy_combo65_lb_get, 1717 phy_combo65_interface_set, 1718 phy_combo65_interface_get, 1719 phy_combo65_ability_get, 1720 NULL, 1721 NULL, 1722 phy_null_mdix_set, 1723 phy_null_mdix_get, 1724 phy_null_mdix_status_get, 1725 phy_combo65_medium_config_set, 1726 phy_combo65_medium_config_get, 1727 phy_combo65_medium_status, 1728 NULL, /* phy_cable_diag */ 1729 NULL, /* phy_link_change */ 1730 phy_combo65_control_set, /* phy_control_set */ 1731 phy_combo65_control_get, /* phy_control_get */ 1732 phy_combo65_reg_read, 1733 phy_combo65_reg_write, 1734 phy_combo65_reg_modify, 1735 phy_combo65_notify 1736 }; 1737 1738 /*********************************************************************** 1739 * 1740 * PASS-THROUGH NOTIFY ROUTINES 1741 */ 1742 1743 /* 1744 * Function: 1745 * _phy_combo65_notify_duplex 1746 * Purpose: 1747 * Program duplex if (and only if) serdescombo65 is an intermediate PHY. 1748 * Parameters: 1749 * unit - StrataSwitch unit #. 1750 * port - StrataSwitch port #. 1751 * duplex - Boolean, TRUE indicates full duplex, FALSE 1752 * indicates half. 1753 * Returns: 1754 * SOC_E_XXX 1755 * Notes: 1756 * If PHY_FLAGS_FIBER is set, it indicates the PHY is being used to 1757 * talk directly to an external fiber module. 1758 * 1759 * If PHY_FLAGS_FIBER is clear, the PHY is being used in 1760 * pass-through mode to talk to an external SGMII PHY. 1761 * 1762 * When used in pass-through mode, autoneg must be turned off and 1763 * the speed/duplex forced to match that of the external PHY. 1764 */ 1765 1766 STATIC int 1767 _phy_combo65_notify_duplex(int unit, soc_port_t port, uint32 duplex) 1768 { 1769 int fiber; 1770 uint16 mii_ctrl; 1771 phy_ctrl_t *pc; 1772 1773 fiber = PHY_FIBER_MODE(unit, port); 1774 pc = INT_PHY_SW_STATE(unit, port); 1775 LOG_INFO(BSL_LS_SOC_PHY, 1776 (BSL_META_U(unit, 1777 "_phy_combo65_notify_duplex: " 1778 "u=%d p=%d duplex=%d fiber=%d\n"), 1779 unit, port, duplex, fiber)); 1780 1781 if (SAL_BOOT_SIMULATION) { 1782 return SOC_E_NONE; 1783 } 1784 1785 if (fiber) { 1786 SOC_IF_ERROR_RETURN 1787 (MODIFY_COMBO_IEEE0_MII_CTRLr(unit, pc, 1788 MII_CTRL_FD, MII_CTRL_FD)); 1789 return SOC_E_NONE; 1790 } 1791 1792 /* Put SERDES PHY in reset */ 1793 1794 SOC_IF_ERROR_RETURN 1795 (_phy_combo65_notify_stop(unit, port, PHY_STOP_DUPLEX_CHG)); 1796 1797 /* Update duplexity */ 1798 mii_ctrl = (duplex) ? MII_CTRL_FD : 0; 1799 SOC_IF_ERROR_RETURN 1800 (MODIFY_COMBO_IEEE0_MII_CTRLr(unit, pc, mii_ctrl, MII_CTRL_FD)); 1801 1802 /* Take SERDES PHY out of reset */ 1803 SOC_IF_ERROR_RETURN 1804 (_phy_combo65_notify_resume(unit, port, PHY_STOP_DUPLEX_CHG)); 1805 1806 /* Autonegotiation must be turned off to talk to external PHY if 1807 * SGMII autoneg is not enabled. 1808 */ 1809 if (!PHY_SGMII_AUTONEG_MODE(unit, port)) { 1810 SOC_IF_ERROR_RETURN 1811 (phy_combo65_an_set(unit, port, FALSE)); 1812 } 1813 return SOC_E_NONE; 1814 } 1815 1816 /* 1817 * Function: 1818 * _phy_combo65_notify_speed 1819 * Purpose: 1820 * Program duplex if (and only if) serdescombo65 is an intermediate PHY. 1821 * Parameters: 1822 * unit - StrataSwitch unit #. 1823 * port - StrataSwitch port #. 1824 * speed - Speed to program. 1825 * Returns: 1826 * SOC_E_XXX 1827 * Notes: 1828 * If PHY_FLAGS_FIBER is set, it indicates the PHY is being used to 1829 * talk directly to an external fiber module. 1830 * 1831 * If PHY_FLAGS_FIBER is clear, the PHY is being used in 1832 * pass-through mode to talk to an external SGMII PHY. 1833 * 1834 * When used in pass-through mode, autoneg must be turned off and 1835 * the speed/duplex forced to match that of the external PHY. 1836 */ 1837 1838 STATIC int 1839 _phy_combo65_notify_speed(int unit, soc_port_t port, uint32 speed) 1840 { 1841 int fiber; 1842 uint16 fiber_status; 1843 phy_ctrl_t *pc; 1844 1845 pc = INT_PHY_SW_STATE(unit, port); 1846 fiber = PHY_FIBER_MODE(unit, port); 1847 1848 LOG_INFO(BSL_LS_SOC_PHY, 1849 (BSL_META_U(unit, 1850 "_phy_combo65_notify_speed: " 1851 "u=%d p=%d speed=%d fiber=%d\n"), 1852 unit, port, speed, fiber)); 1853 1854 if (SAL_BOOT_SIMULATION) { 1855 return SOC_E_NONE; 1856 } 1857 1858 SOC_IF_ERROR_RETURN 1859 (READ_SERDES_DIGITAL_STAT1r(unit, pc, &fiber_status)); 1860 1861 if (fiber && !(fiber_status & STAT1_SGMII_MODE)) { 1862 if ((speed != 0) && (speed != 1000)) { 1863 return SOC_E_CONFIG; 1864 } 1865 } 1866 1867 /* Put SERDES PHY in reset */ 1868 SOC_IF_ERROR_RETURN 1869 (_phy_combo65_notify_stop(unit, port, PHY_STOP_SPEED_CHG)); 1870 1871 /* Update speed */ 1872 SOC_IF_ERROR_RETURN 1873 (phy_combo65_speed_set(unit, port, speed)); 1874 1875 /* Take SERDES PHY out of reset */ 1876 SOC_IF_ERROR_RETURN 1877 (_phy_combo65_notify_resume(unit, port, PHY_STOP_SPEED_CHG)); 1878 1879 /* Autonegotiation must be turned off to talk to external PHY */ 1880 if (!PHY_SGMII_AUTONEG_MODE(unit, port) && !fiber) { 1881 SOC_IF_ERROR_RETURN 1882 (phy_combo65_an_set(unit, port, FALSE)); 1883 } 1884 1885 return SOC_E_NONE; 1886 } 1887 1888 /* 1889 * Function: 1890 * _phy_combo65_stop 1891 * Purpose: 1892 * Put serdescombo65 SERDES in or out of reset depending on conditions 1893 */ 1894 1895 STATIC int 1896 _phy_combo65_stop(int unit, soc_port_t port) 1897 { 1898 uint16 mii_ctrl; 1899 int stop, copper; 1900 phy_ctrl_t *pc; 1901 1902 pc = INT_PHY_SW_STATE(unit, port); 1903 1904 copper = (pc->stop & 1905 PHY_STOP_COPPER) != 0; 1906 1907 stop = ((pc->stop & 1908 (PHY_STOP_PHY_DIS | 1909 PHY_STOP_DRAIN)) != 0 || 1910 (copper && 1911 (pc->stop & 1912 (PHY_STOP_MAC_DIS | 1913 PHY_STOP_DUPLEX_CHG | 1914 PHY_STOP_SPEED_CHG)) != 0)); 1915 1916 LOG_INFO(BSL_LS_SOC_PHY, 1917 (BSL_META_U(unit, 1918 "phy_combo65_stop: u=%d p=%d copper=%d stop=%d flg=0x%x\n"), 1919 unit, port, copper, stop, 1920 pc->stop)); 1921 1922 mii_ctrl = (stop) ? MII_CTRL_PD : 0; 1923 SOC_IF_ERROR_RETURN 1924 (MODIFY_COMBO_IEEE0_MII_CTRLr(unit, pc, mii_ctrl, MII_CTRL_PD)); 1925 1926 return SOC_E_NONE; 1927 } 1928 1929 /* 1930 * Function: 1931 * _phy_combo65_notify_stop 1932 * Purpose: 1933 * Add a reason to put serdescombo65 PHY in reset. 1934 * Parameters: 1935 * unit - StrataSwitch unit #. 1936 * port - StrataSwitch port #. 1937 * flags - Reason to stop 1938 * Returns: 1939 * SOC_E_XXX 1940 */ 1941 1942 STATIC int 1943 _phy_combo65_notify_stop(int unit, soc_port_t port, uint32 flags) 1944 { 1945 INT_PHY_SW_STATE(unit, port)->stop |= flags; 1946 1947 return _phy_combo65_stop(unit, port); 1948 } 1949 1950 /* 1951 * Function: 1952 * _phy_combo65_notify_resume 1953 * Purpose: 1954 * Remove a reason to put serdescombo65 PHY in reset. 1955 * Parameters: 1956 * unit - StrataSwitch unit #. 1957 * port - StrataSwitch port #. 1958 * flags - Reason to stop 1959 * Returns: 1960 * SOC_E_XXX 1961 */ 1962 1963 STATIC int 1964 _phy_combo65_notify_resume(int unit, soc_port_t port, uint32 flags) 1965 { 1966 INT_PHY_SW_STATE(unit, port)->stop &= ~flags; 1967 1968 return _phy_combo65_stop(unit, port); 1969 } 1970 1971 /* 1972 * Function: 1973 * phy_combo65_media_setup 1974 * Purpose: 1975 * Configure 1976 * Parameters: 1977 * unit - StrataSwitch unit #. 1978 * port - StrataSwitch port #. 1979 * fiber_mode - Configure for fiber mode 1980 * fiber_pref - Fiber preferrred (if fiber mode) 1981 * Returns: 1982 * SOC_E_XXX 1983 */ 1984 STATIC int 1985 _phy_combo65_notify_interface(int unit, soc_port_t port, uint32 intf) 1986 { 1987 phy_ctrl_t *pc; 1988 uint16 data16; 1989 1990 pc = INT_PHY_SW_STATE(unit, port); 1991 1992 data16 = 0; 1993 if (intf != SOC_PORT_IF_SGMII) { 1994 data16 = CTRL1_FIBER_MODE; 1995 } 1996 1997 SOC_IF_ERROR_RETURN 1998 (MODIFY_SERDES_DIGITAL_CTRL1r(unit, pc, data16, 1999 CTRL1_FIBER_MODE)); 2000 2001 return SOC_E_NONE; 2002 } 2003 #else /* INCLUDE_SERDES_COMBO65 */ 2004 int _phy_serdescombo65_not_empty; 2005 #endif /* INCLUDE_SERDES_COMBO65 */ 2006