phy5482.c (75696B)
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: phy5482.c 8 * Purpose: PHY driver for BCM5482 and BCM5482S 9 * 10 * Supported BCM546X Family of PHY devices: 11 * 12 * Device Ports Media MAC Interface 13 * 5482 2 Copper, Serdes SGMII 14 * 5482S 2 Copper, Serdes SGMII 15 * 16 * Workarounds: 17 * 18 * References: 19 * MCS5482S-DS200R BCM5482S Preliminary Data Sheet 20 * 5482S-AN103-R BCM5482S Configuration Guide for SFP Module with 21 * Optical/Copper Applications 22 * 5482S-ES101-R BCM5482S Errata Sheet 23 * 5482_5482S-AN102-R Designing with BCM5482/BCM5482S 24 * 25 * +----------+ +---------------------------+ 26 * | | | SGMII +->Copper |<--> Magnetic 27 * | SGMII |<->| (Primary <-+ | 28 * | (SerDes) | | SerDes) | | 29 * | | | +->SGMII/ |<--> (PHY)SFP (10/100/1000) 30 * +----------+ | 1000BASE-X/ |<--> 1000BASE-X SFP 31 * MAC | 100BASE-FX |<--> 100BASE-FX SFP 32 * | (Secondary | 33 * | SerDes) | 34 * +---------------------------+ 35 * 5482S 36 * 37 * Notes: 38 * 1. Media auto-negotiation and MAC SGMII auto-negotiation must be enabled 39 * to automatically detect between 40 * SGMII SFP and 1000BASE-X SFP. 41 * 2. Auto detecting 100FX SFP is not supported. 42 * 3. To use 100BASE-FX, 43 * First, insert the 100BASE-FX SFP and connect the fiber cable. 44 * The PHY will detect energy on fiber side and switch to fiber mode. 45 * Second, disable autoneg mode. 46 * Third, force speed to 100. Since the PHY is in fiber mode, forcing 47 * speed to 100 will put the PHY to 100BASE-FX mode. 48 * 4. Forcing speed on the 5482S PHY with SGMII SFP is not supported in this 49 * driver. To use SGMII SFP, autoneg must be enabled. 50 * 5. Some SFP continues to provide energy to the PHY even when the media 51 * connected is removed. For those SFPs, the PHY will not switch to 52 * copper medium in combo mode even when there is no link on the fiber 53 * medium because the PHY is not switching to copper mode. 54 * 6. If the MAC/SerDes attached to the PHY support SGMII autoneg, SGMII 55 * autoneg should be enabled with "config add phy_sgmii_autoneg_ge0=1". 56 * 7. If the SFP module report loss of signal instead of signal detect, the 57 * signal detect should be inverted with "config add phy_fiber_detect=-2". 58 */ 59 60 #include <sal/types.h> 61 #include <sal/core/spl.h> 62 #include <shared/bsl.h> 63 #include <soc/drv.h> 64 #include <soc/debug.h> 65 #include <soc/error.h> 66 #include <soc/phyreg.h> 67 68 #include <soc/phy.h> 69 #include <soc/phy/phyctrl.h> 70 #include <soc/phy/drv.h> 71 72 #include "phydefs.h" /* Must include before other phy related includes */ 73 74 #if defined(INCLUDE_PHY_5482_ESW) 75 #include "phyconfig.h" /* Must be the first phy include after phydefs.h */ 76 #include "phyident.h" 77 #include "phyreg.h" 78 #include "phyfege.h" 79 #include "phy5482.h" 80 81 #define AUTO_MDIX_WHEN_AN_DIS 0 /* Non-standard-compliant option */ 82 #define DISABLE_CLK125 0 /* Disable if unused to reduce */ 83 /* EMI emissions */ 84 85 #define ADVERT_ALL_COPPER \ 86 (SOC_PM_PAUSE | SOC_PM_10MB | SOC_PM_100MB | SOC_PM_1000MB) 87 #define ADVERT_ALL_FIBER \ 88 (SOC_PM_PAUSE | SOC_PM_1000MB_FD) 89 90 STATIC int _phy_5482_no_reset_setup(int unit, soc_port_t port); 91 STATIC int _phy_5482_medium_change(int unit, soc_port_t port,int force_update); 92 STATIC int phy_5482_duplex_set(int unit, soc_port_t port, int duplex); 93 STATIC int phy_5482_speed_set(int unit, soc_port_t port, int speed); 94 STATIC int phy_5482_master_set(int unit, soc_port_t port, int master); 95 STATIC int phy_5482_adv_local_set(int unit, soc_port_t port, 96 soc_port_mode_t mode); 97 STATIC int phy_5482_autoneg_set(int unit, soc_port_t port, int autoneg); 98 STATIC int phy_5482_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode); 99 STATIC int phy_5482_speed_get(int unit, soc_port_t port, int *speed); 100 101 /*********************************************************************** 102 * 103 * HELPER FUNCTIONS 104 */ 105 /* 106 * Function: 107 * _phy_5482_medium_check 108 * Purpose: 109 * Determine if chip should operate in copper or fiber mode. 110 * Parameters: 111 * unit - StrataSwitch unit #. 112 * port - StrataSwitch port #. 113 * medium - (OUT) SOC_PORT_MEDIUM_XXX 114 * Returns: 115 * SOC_E_XXX 116 */ 117 STATIC int 118 _phy_5482_medium_check(int unit, soc_port_t port, int *medium) 119 { 120 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 121 uint16 tmp = 0xffff; 122 123 *medium = SOC_PORT_MEDIUM_COPPER; 124 125 if (pc->automedium) { 126 /* Read Mode Register (0x1c shadow 11111) */ 127 SOC_IF_ERROR_RETURN 128 (READ_PHY5482_MODE_CTRLr(unit, pc, &tmp)); 129 130 if (pc->fiber.preferred) { 131 /* 0x10 Fiber Signal Detect 132 * 0x20 Copper Energy Detect 133 */ 134 if ((tmp & 0x30) == 0x20) { 135 /* Only copper is link up */ 136 *medium = SOC_PORT_MEDIUM_COPPER; 137 } else { 138 *medium = SOC_PORT_MEDIUM_FIBER; 139 } 140 } else { 141 if ((tmp & 0x30) == 0x10) { 142 /* Only fiber is link up */ 143 *medium = SOC_PORT_MEDIUM_FIBER; 144 } else { 145 *medium = SOC_PORT_MEDIUM_COPPER; 146 } 147 } 148 } else { 149 *medium = pc->fiber.preferred ? SOC_PORT_MEDIUM_FIBER: 150 SOC_PORT_MEDIUM_COPPER; 151 } 152 153 LOG_VERBOSE(BSL_LS_SOC_PHY, 154 (BSL_META_U(unit, 155 "_phy_5482_medium_check: " 156 "u=%d p=%d fiber_pref=%d 0x1c(11111)=%04x fiber=%d\n"), 157 unit, port, pc->fiber.preferred, tmp, 158 (*medium == SOC_PORT_MEDIUM_FIBER) ? 1 : 0)); 159 160 return SOC_E_NONE; 161 } 162 163 /* 164 * Function: 165 * phy_5482_medium_status 166 * Purpose: 167 * Indicate the current active medium 168 * Parameters: 169 * unit - StrataSwitch unit #. 170 * port - StrataSwitch port #. 171 * medium - (OUT) One of: 172 * SOC_PORT_MEDIUM_COPPER 173 * SOC_PORT_MEDIUM_FIBER 174 * Returns: 175 * SOC_E_NONE 176 */ 177 178 STATIC int 179 phy_5482_medium_status(int unit, soc_port_t port, soc_port_medium_t *medium) 180 { 181 if (PHY_COPPER_MODE(unit, port)) { 182 *medium = SOC_PORT_MEDIUM_COPPER; 183 } else { 184 *medium = SOC_PORT_MEDIUM_FIBER; 185 } 186 return SOC_E_NONE; 187 } 188 189 /* 190 * Function: 191 * _phy_5482_medium_config_update 192 * Purpose: 193 * Update the PHY with config parameters 194 * Parameters: 195 * unit - StrataSwitch unit #. 196 * port - StrataSwitch port #. 197 * cfg - Config structure. 198 * Returns: 199 * SOC_E_XXX 200 */ 201 202 STATIC int 203 _phy_5482_medium_config_update(int unit, soc_port_t port, 204 soc_phy_config_t *cfg) 205 { 206 SOC_IF_ERROR_RETURN 207 (phy_5482_speed_set(unit, port, cfg->force_speed)); 208 SOC_IF_ERROR_RETURN 209 (phy_5482_duplex_set(unit, port, cfg->force_duplex)); 210 SOC_IF_ERROR_RETURN 211 (phy_5482_master_set(unit, port, cfg->master)); 212 SOC_IF_ERROR_RETURN 213 (phy_5482_adv_local_set(unit, port, cfg->autoneg_advert)); 214 SOC_IF_ERROR_RETURN 215 (phy_5482_autoneg_set(unit, port, cfg->autoneg_enable)); 216 SOC_IF_ERROR_RETURN 217 (phy_5482_mdix_set(unit, port, cfg->mdix)); 218 219 return SOC_E_NONE; 220 } 221 222 /*********************************************************************** 223 * 224 * PHY5482 DRIVER ROUTINES 225 */ 226 227 /* 228 * Function: 229 * phy_5482_medium_config_set 230 * Purpose: 231 * Set the operating parameters that are automatically selected 232 * when medium switches type. 233 * Parameters: 234 * unit - StrataSwitch unit # 235 * port - Port number 236 * medium - SOC_PORT_MEDIUM_COPPER/FIBER 237 * cfg - Operating parameters 238 * Returns: 239 * SOC_E_XXX 240 */ 241 242 STATIC int 243 phy_5482_medium_config_set(int unit, soc_port_t port, 244 soc_port_medium_t medium, 245 soc_phy_config_t *cfg) 246 { 247 phy_ctrl_t *pc; 248 soc_phy_config_t *active_medium; /* Currently active medium */ 249 soc_phy_config_t *change_medium; /* Requested medium */ 250 soc_phy_config_t *other_medium; /* The other medium */ 251 int medium_update; 252 soc_port_mode_t advert_mask; 253 254 if (NULL == cfg) { 255 return SOC_E_PARAM; 256 } 257 258 pc = EXT_PHY_SW_STATE(unit, port); 259 medium_update = FALSE; 260 261 switch (medium) { 262 case SOC_PORT_MEDIUM_COPPER: 263 if (!pc->automedium) { 264 if (!PHY_COPPER_MODE(unit, port)) { 265 return SOC_E_UNAVAIL; 266 } 267 /* check if device is fiber capable before switching */ 268 if (cfg->preferred == 0) { 269 270 if (!soc_property_port_get(unit, port, 271 spn_PHY_FIBER_CAPABLE, TRUE)) { 272 /* return if not fiber capable*/ 273 return SOC_E_UNAVAIL; 274 } 275 } 276 } 277 278 change_medium = &pc->copper; 279 other_medium = &pc->fiber; 280 advert_mask = ADVERT_ALL_COPPER; 281 break; 282 case SOC_PORT_MEDIUM_FIBER: 283 if (!pc->automedium && !PHY_FIBER_MODE(unit, port)) { 284 return SOC_E_UNAVAIL; 285 } 286 change_medium = &pc->fiber; 287 other_medium = &pc->copper; 288 advert_mask = ADVERT_ALL_FIBER; 289 break; 290 default: 291 return SOC_E_PARAM; 292 } 293 294 /* 295 * Changes take effect immediately if the target medium is active or 296 * the preferred medium changes. 297 */ 298 if (change_medium->enable != cfg->enable) { 299 medium_update = TRUE; 300 } 301 if (change_medium->preferred != cfg->preferred) { 302 /* Make sure that only one medium is preferred */ 303 other_medium->preferred = !cfg->preferred; 304 medium_update = TRUE; 305 } 306 307 sal_memcpy(change_medium, cfg, sizeof(*change_medium)); 308 change_medium->autoneg_advert &= advert_mask; 309 310 if (medium_update) { 311 /* The new configuration may cause medium change. Check 312 * and update medium. 313 */ 314 SOC_IF_ERROR_RETURN 315 (_phy_5482_medium_change(unit, port,TRUE)); 316 } else { 317 active_medium = (PHY_COPPER_MODE(unit, port)) ? 318 &pc->copper : &pc->fiber; 319 if (active_medium == change_medium) { 320 /* If the medium to update is active, update the configuration */ 321 SOC_IF_ERROR_RETURN 322 (_phy_5482_medium_config_update(unit, port, change_medium)); 323 } 324 } 325 return SOC_E_NONE; 326 } 327 328 /* 329 * Function: 330 * phy_5482_medium_config_get 331 * Purpose: 332 * Get the operating parameters that are automatically selected 333 * when medium switches type. 334 * Parameters: 335 * unit - StrataSwitch unit # 336 * port - Port number 337 * medium - SOC_PORT_MEDIUM_COPPER/FIBER 338 * cfg - (OUT) Operating parameters 339 * Returns: 340 * SOC_E_XXX 341 */ 342 343 STATIC int 344 phy_5482_medium_config_get(int unit, soc_port_t port, 345 soc_port_medium_t medium, 346 soc_phy_config_t *cfg) 347 { 348 int rv; 349 phy_ctrl_t *pc; 350 351 pc = EXT_PHY_SW_STATE(unit, port); 352 rv = SOC_E_NONE; 353 354 switch (medium) { 355 case SOC_PORT_MEDIUM_COPPER: 356 if (pc->automedium || PHY_COPPER_MODE(unit, port)) { 357 sal_memcpy(cfg, &pc->copper, sizeof (*cfg)); 358 } else { 359 rv = SOC_E_UNAVAIL; 360 } 361 break; 362 case SOC_PORT_MEDIUM_FIBER: 363 if (pc->automedium || PHY_FIBER_MODE(unit, port)) { 364 sal_memcpy(cfg, &pc->fiber, sizeof (*cfg)); 365 } else { 366 rv = SOC_E_UNAVAIL; 367 } 368 break; 369 default: 370 rv = SOC_E_PARAM; 371 break; 372 } 373 374 return rv; 375 } 376 377 /* 378 * Function: 379 * _phy_5482_reset_setup 380 * Purpose: 381 * Function to reset the PHY and set up initial operating registers. 382 * Parameters: 383 * unit - StrataSwitch unit #. 384 * port - StrataSwitch port #. 385 * Returns: 386 * SOC_E_XXX 387 * Notes: 388 * Configures for copper/fiber according to the current 389 * setting of PHY_FLAGS_FIBER. 390 */ 391 392 STATIC int 393 _phy_5482_reset_setup(int unit, soc_port_t port) 394 { 395 phy_ctrl_t *pc; 396 397 pc = EXT_PHY_SW_STATE(unit, port); 398 399 /* Reset the PHY with previously registered callback function. 400 */ 401 SOC_IF_ERROR_RETURN(soc_phy_reset(unit, port)); 402 403 /* Reset the secondary SerDes */ 404 SOC_IF_ERROR_RETURN 405 (WRITE_PHY5482_2ND_SERDES_1000X_CTRLr(unit, pc, MII_CTRL_RESET)); 406 sal_usleep(10000); 407 408 /* Disable super-isolate */ 409 SOC_IF_ERROR_RETURN 410 (MODIFY_PHY5482_MII_POWER_CTRLr(unit, pc, 0x0, 1U<<5)); 411 412 SOC_IF_ERROR_RETURN 413 (_phy_5482_no_reset_setup(unit, port)); 414 415 return SOC_E_NONE; 416 } 417 418 STATIC int 419 _phy_5482_no_reset_setup(int unit, soc_port_t port) 420 { 421 phy_ctrl_t *int_pc; 422 phy_ctrl_t *pc; 423 uint16 data, mask; 424 425 LOG_INFO(BSL_LS_SOC_PHY, 426 (BSL_META_U(unit, 427 "_phy_5482_reset_setup: u=%d p=%d medium=%s\n"), 428 unit, port, 429 PHY_COPPER_MODE(unit, port) ? "COPPER" : "FIBER")); 430 431 pc = EXT_PHY_SW_STATE(unit, port); 432 int_pc = INT_PHY_SW_STATE(unit, port); 433 434 /* SGMII interface to MAC */ 435 /* soc_phy_reset has reset the phy, powering down the unstrapped interface. 436 * Make sure enabled interfaces are powered up. 437 */ 438 SOC_IF_ERROR_RETURN 439 (MODIFY_PHY5482_1000X_MII_CTRLr(unit, pc, 0, MII_CTRL_PD)); 440 441 /* 1000Base-X FullDuplex will be clear after the phy been 442 * reset in phy5482s 443 */ 444 data = MII_CTRL_FD | MII_CTRL_SS_1000 | MII_CTRL_RAN | MII_CTRL_AE; 445 446 SOC_IF_ERROR_RETURN 447 (WRITE_PHY5482_1000X_MII_CTRLr(unit, pc, data)); 448 449 /* copper regs */ 450 if (!pc->copper.enable || (!pc->automedium && pc->fiber.preferred)) { 451 /* Copper interface is not used. Powered down. */ 452 SOC_IF_ERROR_RETURN 453 (MODIFY_PHY5482_MII_CTRLr(unit, pc, MII_CTRL_PD, MII_CTRL_PD)); 454 } else { 455 SOC_IF_ERROR_RETURN 456 (MODIFY_PHY5482_MII_CTRLr(unit, pc, 0, MII_CTRL_PD)); 457 SOC_IF_ERROR_RETURN 458 (WRITE_PHY5482_MII_GB_CTRLr(unit, pc, 459 MII_GB_CTRL_ADV_1000FD | MII_GB_CTRL_PT)); 460 SOC_IF_ERROR_RETURN 461 (WRITE_PHY5482_MII_CTRLr(unit, pc, 462 MII_CTRL_FD | MII_CTRL_SS_1000 | MII_CTRL_AE)); 463 } 464 465 /* Adjust timing */ 466 SOC_IF_ERROR_RETURN 467 (MODIFY_PHY5482_SPARE_CTRLr(unit, pc, 0x0002, 0x0002)); 468 469 if (PHY_SGMII_AUTONEG_MODE(unit, port)) { 470 /* Disable parallel detect on SGMII interface with MAC to elimates 471 * the possibility of the BCM5482S turning off the SGMII auto-neg 472 * interface connected to the MAC inadvertly. 473 * Do not disable parallel detect if SGMII autoneg is disabled. 474 * Otherwise, the PHY will not able to detect the configuration 475 * of MAC SerDes. 476 */ 477 SOC_IF_ERROR_RETURN 478 (WRITE_PHY5482_1ST_SERDES_CTRLr(unit, pc, 0)); 479 } 480 481 if (NULL != int_pc) { 482 SOC_IF_ERROR_RETURN 483 (PHY_INIT(int_pc->pd, unit, port)); 484 485 if (PHY_FIBER_MODE(unit, port)) { 486 /* Interface to MAC or internal SerDes is always SGMII mode. 487 * Typical internal SerDes driver set the interface to 1000BASE-X, 488 * if the media is fiber. Therefore, we need to force the interface 489 * of internal SerDes Driver to SGMII. */ 490 SOC_IF_ERROR_RETURN 491 (PHY_NOTIFY(int_pc->pd, unit, port, phyEventInterface, 492 SOC_PORT_IF_SGMII)); 493 } 494 495 if (PHY_COPPER_MODE(unit, port) && 496 !PHY_SGMII_AUTONEG_MODE(unit, port)) { 497 /* Make sure internal SerDes is in power down state 498 * until the MAC is ready. */ 499 SOC_IF_ERROR_RETURN 500 (PHY_NOTIFY(int_pc->pd, unit, port, 501 phyEventStop, PHY_STOP_COPPER)); 502 } 503 } 504 505 /* Power down secondary SerDes */ 506 SOC_IF_ERROR_RETURN 507 (MODIFY_PHY5482_2ND_SERDES_1000X_CTRLr(unit, pc, MII_CTRL_PD, 508 MII_CTRL_PD)); 509 if (pc->fiber.enable && (pc->automedium || pc->fiber.preferred)) { 510 /* Secondary SerDes Control Register 511 * Select secondary serdes 1000BaseX in full duplex 512 */ 513 data = 1 << 0; /* Enable secondary SerDes */ 514 data |= 1 << 2; /* Select Sync function from secondary SerDes */ 515 data |= 1 << 3; /* Enable secondary SerDes to driver LEDs */ 516 data |= 1 << 5; /* Enable secondary SerDes 100FX full duplex */ 517 SOC_IF_ERROR_RETURN 518 (WRITE_PHY5482_2ND_SERDES_CTRLr(unit, pc, data)); 519 520 /* remove power down of secondary SerDes */ 521 SOC_IF_ERROR_RETURN 522 (MODIFY_PHY5482_2ND_SERDES_1000X_CTRLr(unit, pc, 0, MII_CTRL_PD)); 523 524 /* Enable auto-detection between SGMII-slave and 1000BASE-X */ 525 SOC_IF_ERROR_RETURN 526 (MODIFY_PHY5482_2ND_SERDES_SGMII_SLAVEr(unit, pc, 1, 1)); 527 528 /* set the advertisement of secondary serdes */ 529 /* Disable half-duplex, full-duplex capable */ 530 SOC_IF_ERROR_RETURN 531 (MODIFY_PHY5482_2ND_SERDES_ANAr(unit, pc, (1 << 5), 532 (1 << 5) | (1 << 6))); 533 534 /* Restart secondary SerDes autonegotiation */ 535 SOC_IF_ERROR_RETURN 536 (WRITE_PHY5482_2ND_SERDES_1000X_CTRLr(unit, pc, 537 MII_CTRL_FD | MII_CTRL_SS_1000 | MII_CTRL_AE)); 538 539 switch (pc->fiber_detect) { 540 case 2: /* LED 2 */ 541 case -2: 542 case 4: /* LED 4 : kept for backward compatibility */ 543 case -4: 544 case 10: /* EN_10B for signal detect */ 545 case -10: 546 case 0: /* default */ 547 /* GPIO Control/Status Register (0x1c shadow 01111) */ 548 /* Change LED2 pin into an input */ 549 SOC_IF_ERROR_RETURN 550 (MODIFY_PHY5482_LED_GPIO_CTRLr(unit, pc, 0x08, 0x08)); 551 break; 552 case 1: /* PECL , no such pin in 5482 data sheet */ 553 case -1: 554 default: 555 return SOC_E_CONFIG; 556 } 557 } 558 559 /* Configure Auto-detect Medium (0x1c shadow 11110) */ 560 mask = 0x33f; /* Auto-detect bit mask */ 561 data = 0; 562 if (pc->automedium) { 563 data |= 1 << 0; /* Enable auto-detect medium */ 564 data |= 1 << 9; /* Enable Secondary SerDes auto-detect */ 565 } 566 /* When no link partner exists, fiber should be default medium */ 567 /* When both link partners exipc, fiber should be prefered medium 568 * for the following reasons. 569 * 1. Most fiber module generates signal detect when the fiber cable is 570 * plugged in regardless of any activity even if the link partner is 571 * powered down. 572 * 2. Fiber mode consume much lesser power than copper mode. 573 */ 574 if (pc->fiber.preferred) { 575 data |= 1 << 1; /* Fiber selected when both media are active */ 576 data |= 1 << 2; /* Fiber selected when no medium is active */ 577 } 578 579 /* 580 * Enable internal inversion of LED2/SD input pin. Used only if 581 * the fiber module provides RX_LOS instead of Signal Detect. 582 */ 583 if (pc->fiber_detect < 0) { 584 data |= 1 << 8; /* Fiber signal detect is active low from pin */ 585 } 586 SOC_IF_ERROR_RETURN 587 (MODIFY_PHY5482_AUTO_DETECT_MEDIUMr(unit, pc, data, mask)); 588 589 590 #if DISABLE_CLK125 591 /* Note: CLK125 does not function properly on BCM5482S A0 and A1 */ 592 /* Refer to 5482S-ES101-R for details. */ 593 /* Reduce EMI emissions by disabling the CLK125 pin if not used */ 594 data = 0x001c; /* When write, bit 9 and 7 must be zero and */ 595 data = 0x029c; /* bit 2, 3, and 4 must be one. */ 596 SOC_IF_ERROR_RETURN 597 (MODIFY_PHY5482_SPARE_CTRL_3r(unit, pc, 0, 1)); 598 #endif 599 600 #if AUTO_MDIX_WHEN_AN_DIS 601 /* Enable Auto-MDIX When autoneg disabled */ 602 SOC_IF_ERROR_RETURN 603 (MODIFY_PHY5482_MII_MISC_CTRLr(unit, pc, 0x200, 0x200)); 604 #endif 605 606 /* 607 * Configure Auxiliary 1000BASE-X control register to turn off 608 * carrier extension. The Intel 7131 NIC does not accept carrier 609 * extension and gets CRC errors. 610 */ 611 SOC_IF_ERROR_RETURN 612 (MODIFY_PHY5482_AUX_1000X_CTRLr(unit, pc, 0x0040, 0x0040)); 613 614 /* Configure extended control register for led mode and jumbo frame support 615 */ 616 mask = (1 << 5) | (1 << 0); 617 618 /* if using led link/activity mode, disable led traffic mode */ 619 if (pc->ledctrl & 0x10 || pc->ledselect == 0x01) { 620 data = 0; 621 } else { 622 data = 1 << 5; /* Enable LEDs to indicate traffic status */ 623 } 624 /* Configure Extended Control Register for Jumbo frames support */ 625 data |= 1 << 0; /* Set high FIFO elasticity to support jumbo frames */ 626 SOC_IF_ERROR_RETURN 627 (MODIFY_PHY5482_MII_ECRr(unit, pc, data, mask)); 628 629 /* Enable extended packet length (4.5k through 25k) */ 630 SOC_IF_ERROR_RETURN 631 (MODIFY_PHY5482_MII_AUX_CTRLr(unit, pc, 0x4000, 0x4000)); 632 633 /* Configure LED selectors */ 634 data = ((pc->ledmode[2] & 0xf) << 4) | (pc->ledmode[0] & 0xf); 635 SOC_IF_ERROR_RETURN 636 (WRITE_PHY5482_LED_SELECTOR_1r(unit, pc, data)); 637 638 data = ((pc->ledmode[1] & 0xf) << 4) | (pc->ledmode[3] & 0xf); 639 SOC_IF_ERROR_RETURN 640 (WRITE_PHY5482_LED_SELECTOR_2r(unit, pc, data)); 641 642 data = (pc->ledctrl & 0x3ff); 643 SOC_IF_ERROR_RETURN 644 (WRITE_PHY5482_LED_CTRLr(unit, pc, data)); 645 646 SOC_IF_ERROR_RETURN 647 (WRITE_PHY5482_EXP_LED_SELECTORr(unit, pc, pc->ledselect)); 648 649 return SOC_E_NONE; 650 } 651 652 /* 653 * Function: 654 * phy_5482_init 655 * Purpose: 656 * Init function for 5482 PHY. 657 * Parameters: 658 * unit - StrataSwitch unit #. 659 * port - StrataSwitch port #. 660 * Returns: 661 * SOC_E_NONE 662 */ 663 664 STATIC int 665 phy_5482_init(int unit, soc_port_t port) 666 { 667 phy_ctrl_t *pc; 668 int fiber_capable; 669 int fiber_preferred; 670 671 LOG_INFO(BSL_LS_SOC_PHY, 672 (BSL_META_U(unit, 673 "phy_5482_init: u=%d p=%d\n"), 674 unit, port)); 675 676 /* Only SGMII interface to switch MAC is supported */ 677 if (IS_GMII_PORT(unit, port)) { 678 return SOC_E_CONFIG; 679 } 680 681 pc = EXT_PHY_SW_STATE(unit, port); 682 683 pc->interface = SOC_PORT_IF_SGMII; 684 685 fiber_capable = soc_property_port_get(unit, port, 686 spn_PHY_FIBER_CAPABLE, TRUE); 687 688 /* 689 * In automedium mode, the property phy_fiber_pref_port<X> is used 690 * to set a preference for fiber mode in the event both copper and 691 * fiber links are up. 692 * 693 * If NOT in automedium mode, phy_fiber_pref_port<X> is used to 694 * select which of fiber or copper is forced. 695 */ 696 if (!fiber_capable) { 697 fiber_preferred = 0; 698 pc->automedium = 0; 699 pc->fiber_detect = 0; 700 } else { 701 fiber_preferred = 702 soc_property_port_get(unit, port, spn_PHY_FIBER_PREF, 1); 703 pc->automedium = 704 soc_property_port_get(unit, port, spn_PHY_AUTOMEDIUM, 1); 705 pc->fiber_detect = 706 soc_property_port_get(unit, port, spn_PHY_FIBER_DETECT, 0); 707 } 708 709 LOG_INFO(BSL_LS_SOC_PHY, 710 (BSL_META_U(unit, 711 "phy_5482_init: " 712 "u=%d p=%d type=5482%s automedium=%d fiber_pref=%d detect=%d\n"), 713 unit, port, fiber_capable ? "S" : "", 714 pc->automedium, fiber_preferred, pc->fiber_detect)); 715 716 pc->copper.enable = TRUE; 717 pc->copper.preferred = !fiber_preferred; 718 pc->copper.autoneg_enable = TRUE; 719 pc->copper.autoneg_advert = ADVERT_ALL_COPPER; 720 pc->copper.force_speed = 1000; 721 pc->copper.force_duplex = TRUE; 722 pc->copper.master = SOC_PORT_MS_AUTO; 723 pc->copper.mdix = SOC_PORT_MDIX_AUTO; 724 725 pc->fiber.enable = fiber_capable; 726 pc->fiber.preferred = fiber_preferred; 727 pc->fiber.autoneg_enable = fiber_capable; 728 pc->fiber.autoneg_advert = ADVERT_ALL_FIBER; 729 pc->fiber.force_speed = 1000; 730 pc->fiber.force_duplex = TRUE; 731 pc->fiber.master = SOC_PORT_MS_NONE; 732 pc->fiber.mdix = SOC_PORT_MDIX_NORMAL; 733 734 /* Initially configure for the preferred medium. */ 735 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER); 736 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 737 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_PASSTHRU); 738 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX); 739 if (pc->fiber.preferred) { 740 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 741 } else { 742 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 743 } 744 745 /* Get Requested LED selectors (defaults are hardware defaults) */ 746 pc->ledmode[0] = soc_property_port_get(unit, port, spn_PHY_LED1_MODE, 0); 747 pc->ledmode[1] = soc_property_port_get(unit, port, spn_PHY_LED2_MODE, 1); 748 pc->ledmode[2] = soc_property_port_get(unit, port, spn_PHY_LED3_MODE, 3); 749 pc->ledmode[3] = soc_property_port_get(unit, port, spn_PHY_LED4_MODE, 6); 750 pc->ledctrl = soc_property_port_get(unit, port, spn_PHY_LED_CTRL, 0x8); 751 pc->ledselect = soc_property_port_get(unit, port, spn_PHY_LED_SELECT, 0); 752 753 SOC_IF_ERROR_RETURN 754 (_phy_5482_reset_setup(unit, port)); 755 756 SOC_IF_ERROR_RETURN 757 (_phy_5482_medium_config_update(unit, port, 758 PHY_COPPER_MODE(unit, port) ? 759 &pc->copper : 760 &pc->fiber)); 761 762 return SOC_E_NONE; 763 } 764 765 /* 766 * Function: 767 * phy_5482_enable_set 768 * Purpose: 769 * Enable or disable the physical interface. 770 * Parameters: 771 * unit - StrataSwitch unit #. 772 * port - StrataSwitch port #. 773 * enable - Boolean, true = enable PHY, false = disable. 774 * Returns: 775 * SOC_E_XXX 776 */ 777 778 STATIC int 779 phy_5482_enable_set(int unit, soc_port_t port, int enable) 780 { 781 uint16 power; 782 phy_ctrl_t *pc; 783 784 pc = EXT_PHY_SW_STATE(unit, port); 785 power = (enable) ? 0 : MII_CTRL_PD; 786 787 /* Do not incorrectly Power up the interface if medium is disabled and 788 * global enable = true 789 */ 790 if (pc->copper.enable && (pc->automedium || PHY_COPPER_MODE(unit, port))) { 791 SOC_IF_ERROR_RETURN 792 (MODIFY_PHY5482_MII_CTRLr(unit, pc, power, MII_CTRL_PD)); 793 794 LOG_INFO(BSL_LS_SOC_PHY, 795 (BSL_META_U(unit, 796 "phy_5482_enable_set: " 797 "Power %s copper medium\n"), (enable) ? "up" : "down")); 798 } 799 800 if (pc->fiber.enable && (pc->automedium || PHY_FIBER_MODE(unit, port))) { 801 SOC_IF_ERROR_RETURN 802 (MODIFY_PHY5482_2ND_SERDES_1000X_CTRLr(unit, pc, power, 803 MII_CTRL_PD)); 804 805 LOG_INFO(BSL_LS_SOC_PHY, 806 (BSL_META_U(unit, 807 "phy_5482_enable_set: " 808 "Power %s fiber medium\n"), (enable) ? "up" : "down")); 809 } 810 811 /* Update software state */ 812 SOC_IF_ERROR_RETURN(phy_fe_ge_enable_set(unit, port, enable)); 813 814 return SOC_E_NONE; 815 } 816 817 /* 818 * Function: 819 * phy_5482_enable_get 820 * Purpose: 821 * Enable or disable the physical interface for a 5482 device. 822 * Parameters: 823 * unit - StrataSwitch unit #. 824 * port - StrataSwitch port #. 825 * enable - (OUT) Boolean, true = enable PHY, false = disable. 826 * Returns: 827 * SOC_E_XXX 828 */ 829 830 STATIC int 831 phy_5482_enable_get(int unit, soc_port_t port, int *enable) 832 { 833 return phy_fe_ge_enable_get(unit, port, enable); 834 } 835 836 /* 837 * Function: 838 * _phy_5482_100fx_setup 839 * Purpose: 840 * Switch from 1000X mode to 100FX. 841 * Parameters: 842 * unit - StrataSwitch unit #. 843 * port - StrataSwitch port #. 844 * Returns: 845 * SOC_E_XXX 846 */ 847 STATIC int 848 _phy_5482_fiber_100fx_setup(int unit, soc_port_t port) 849 { 850 uint16 data; 851 phy_ctrl_t *pc; 852 853 pc = EXT_PHY_SW_STATE(unit, port); 854 855 LOG_VERBOSE(BSL_LS_SOC_PHY, 856 (BSL_META_U(unit, 857 "_phy_5482_1000x_to_100fx: u=%d p=%d \n"), 858 unit, port)); 859 860 /* Operate secondary SerDes in 100FX */ 861 data = 1 << 0; /* Enable secondary SerDes */ 862 data |= 1 << 2; /* Select Sync function from secondary SerDes */ 863 data |= 1 << 3; /* Enable secondary SerDes to driver LEDs */ 864 data |= 1 << 4; /* Operate secondary SerDes in 100Base-FX mode */ 865 if (pc->fiber.force_duplex) { 866 data |= 1 << 5; /* Enable secondary SerDes 100FX full duplex */ 867 } 868 SOC_IF_ERROR_RETURN 869 (WRITE_PHY5482_2ND_SERDES_CTRLr(unit, pc, data)); 870 871 /* Secondary SerDes */ 872 /* Reset the secondary SerDes */ 873 SOC_IF_ERROR_RETURN 874 (WRITE_PHY5482_2ND_SERDES_1000X_CTRLr(unit, pc, MII_CTRL_RESET)); 875 sal_usleep(10000); 876 877 /* Power up the secondary SerDes */ 878 SOC_IF_ERROR_RETURN 879 (WRITE_PHY5482_2ND_SERDES_1000X_CTRLr(unit, pc, 880 MII_CTRL_AE | MII_CTRL_FD | MII_CTRL_SS_100 | 881 (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE) ? MII_CTRL_PD : 0))); 882 883 /* Enable extended packet length (100fx-mode) */ 884 SOC_IF_ERROR_RETURN 885 (MODIFY_PHY5482_2ND_SERDES_MISC1r(unit, pc, 0x01, 0x01)); 886 887 PHY_FLAGS_SET(unit, port, PHY_FLAGS_100FX); 888 pc->fiber.force_speed = 100; 889 pc->fiber.autoneg_enable = FALSE; 890 891 return SOC_E_NONE; 892 } 893 894 /* 895 * Function: 896 * _phy_5482_1000x_setup 897 * Purpose: 898 * Switch from 100FX mode to 1000X. 899 * Parameters: 900 * unit - StrataSwitch unit #. 901 * port - StrataSwitch port #. 902 * Returns: 903 * SOC_E_XXX 904 */ 905 STATIC int 906 _phy_5482_fiber_1000x_setup(int unit, soc_port_t port) 907 { 908 uint16 data; 909 phy_ctrl_t *pc; 910 911 pc = EXT_PHY_SW_STATE(unit, port); 912 913 LOG_VERBOSE(BSL_LS_SOC_PHY, 914 (BSL_META_U(unit, 915 "_phy_5482_fiber_1000x_setup: u=%d p=%d \n"), 916 unit, port)); 917 918 /* Operate secondary SerDes in 1000X */ 919 data = 1 << 0; /* Enable secondary SerDes */ 920 data |= 1 << 2; /* Select Sync function from secondary SerDes */ 921 data |= 1 << 3; /* Enable secondary SerDes to driver LEDs */ 922 data |= 1 << 5; /* Enable secondary SerDes 100FX full duplex */ 923 SOC_IF_ERROR_RETURN 924 (WRITE_PHY5482_2ND_SERDES_CTRLr(unit, pc, data)); 925 926 /* Reset the secondary SerDes */ 927 SOC_IF_ERROR_RETURN 928 (WRITE_PHY5482_2ND_SERDES_1000X_CTRLr(unit, pc, MII_CTRL_RESET)); 929 sal_usleep(10000); 930 931 /* Power up the secondary SerDes */ 932 if (pc->fiber.autoneg_enable) { 933 data = MII_CTRL_AE | MII_CTRL_RAN | MII_CTRL_FD | MII_CTRL_SS_1000; 934 } else { 935 data = MII_CTRL_RAN | MII_CTRL_FD | MII_CTRL_SS_1000; 936 } 937 938 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 939 data |= MII_CTRL_PD; 940 } 941 SOC_IF_ERROR_RETURN 942 (WRITE_PHY5482_2ND_SERDES_1000X_CTRLr(unit, pc, data)); 943 944 pc->fiber.force_duplex = TRUE; 945 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX); 946 947 return SOC_E_NONE; 948 } 949 950 STATIC int 951 _phy_5482_medium_change(int unit, soc_port_t port, int force_update) 952 { 953 phy_ctrl_t *pc; 954 int medium; 955 956 pc = EXT_PHY_SW_STATE(unit, port); 957 958 SOC_IF_ERROR_RETURN 959 (_phy_5482_medium_check(unit, port, &medium)); 960 961 if (medium == SOC_PORT_MEDIUM_COPPER) { 962 if ((!PHY_COPPER_MODE(unit, port)) || force_update) { /* Was fiber */ 963 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 964 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 965 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX); 966 PHY_FLAGS_SET(unit, port, PHY_FLAGS_MEDIUM_CHANGE); 967 SOC_IF_ERROR_RETURN 968 (_phy_5482_no_reset_setup(unit, port)); 969 970 /* Do not power up the interface if medium is disabled. */ 971 if (pc->copper.enable) { 972 SOC_IF_ERROR_RETURN 973 (_phy_5482_medium_config_update(unit, port, &pc->copper)); 974 } 975 LOG_INFO(BSL_LS_SOC_PHY, 976 (BSL_META_U(unit, 977 "_phy_5482_link_auto_detect: u=%d p=%d [F->C]\n"), 978 unit, port)); 979 } 980 } else { /* Fiber */ 981 if (PHY_COPPER_MODE(unit, port) || force_update) { /* Was copper */ 982 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER); 983 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 984 PHY_FLAGS_SET(unit, port, PHY_FLAGS_MEDIUM_CHANGE); 985 SOC_IF_ERROR_RETURN 986 (_phy_5482_no_reset_setup(unit, port)); 987 988 if (pc->fiber.enable) { 989 SOC_IF_ERROR_RETURN 990 (_phy_5482_medium_config_update(unit, port, &pc->fiber)); 991 } 992 LOG_INFO(BSL_LS_SOC_PHY, 993 (BSL_META_U(unit, 994 "_phy_5482_link_auto_detect: u=%d p=%d [C->F]\n"), 995 unit, port)); 996 } 997 } 998 return SOC_E_NONE; 999 } 1000 1001 /* 1002 * Function: 1003 * phy_5482_link_get 1004 * Purpose: 1005 * Determine the current link up/down status for a 5482 device. 1006 * Parameters: 1007 * unit - StrataSwitch unit #. 1008 * port - StrataSwitch port #. 1009 * link - (OUT) Boolean, true indicates link established. 1010 * Returns: 1011 * SOC_E_XXX 1012 * Notes: 1013 * If using automedium, also switches the mode. 1014 */ 1015 STATIC int 1016 phy_5482_link_get(int unit, soc_port_t port, int *link) 1017 { 1018 phy_ctrl_t *pc; 1019 uint16 data; 1020 uint16 mask; 1021 1022 pc = EXT_PHY_SW_STATE(unit, port); 1023 *link = FALSE; /* Default return */ 1024 1025 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 1026 return SOC_E_NONE; 1027 } 1028 1029 if (!pc->fiber.enable && !pc->copper.enable) { 1030 return SOC_E_NONE; 1031 } 1032 1033 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_MEDIUM_CHANGE); 1034 if (pc->automedium) { 1035 /* Check for medium change and update HW/SW accordingly. */ 1036 SOC_IF_ERROR_RETURN 1037 (_phy_5482_medium_change(unit, port,FALSE)); 1038 } 1039 if (PHY_COPPER_MODE(unit, port)) { 1040 SOC_IF_ERROR_RETURN(phy_fe_ge_link_get(unit, port, link)); 1041 } else { 1042 SOC_IF_ERROR_RETURN 1043 (READ_PHY5482_2ND_SERDES_1000X_STATr(unit, pc, &data)); 1044 *link = (data != 0xffff) && (data & MII_STAT_LA) ? TRUE : FALSE; 1045 } 1046 1047 /* If preferred medium is up, disable the other medium 1048 * to prevent false link. */ 1049 if (pc->automedium) { 1050 mask = MII_CTRL_PD; 1051 if (pc->copper.preferred) { 1052 if (pc->fiber.enable) { 1053 /* power down secondary serdes */ 1054 data = (*link && PHY_COPPER_MODE(unit, port)) ? MII_CTRL_PD : 0; 1055 } else { 1056 data = MII_CTRL_PD; 1057 } 1058 SOC_IF_ERROR_RETURN 1059 (MODIFY_PHY5482_2ND_SERDES_1000X_CTRLr(unit, pc, data, mask)); 1060 } else { /* pc->fiber.preferred */ 1061 if (pc->copper.enable) { 1062 data = (*link && PHY_FIBER_MODE(unit, port)) ? MII_CTRL_PD : 0; 1063 } else { 1064 data = MII_CTRL_PD; 1065 } 1066 SOC_IF_ERROR_RETURN 1067 (MODIFY_PHY5482_MII_CTRLr(unit, pc, data, mask)); 1068 } 1069 } 1070 1071 LOG_VERBOSE(BSL_LS_SOC_PHY, 1072 (BSL_META_U(unit, 1073 "phy_5482_link_get: u=%d p=%d mode=%s%s link=%d\n"), 1074 unit, port, 1075 PHY_COPPER_MODE(unit, port) ? "C" : "F", 1076 PHY_FIBER_100FX_MODE(unit, port)? "(100FX)" : "", 1077 *link)); 1078 1079 return SOC_E_NONE; 1080 } 1081 1082 /* 1083 * Function: 1084 * phy_5482_duplex_set 1085 * Purpose: 1086 * Set the current duplex mode (forced). 1087 * Parameters: 1088 * unit - StrataSwitch unit #. 1089 * port - StrataSwitch port #. 1090 * duplex - Boolean, true indicates full duplex, false indicates half. 1091 * Returns: 1092 * SOC_E_NONE 1093 * SOC_E_UNAVAIL - Half duplex requested, and not supported. 1094 * Notes: 1095 * The duplex is set only for the ACTIVE medium. 1096 * No synchronization performed at this level. 1097 * Autonegotiation is not manipulated. 1098 */ 1099 1100 STATIC int 1101 phy_5482_duplex_set(int unit, soc_port_t port, int duplex) 1102 { 1103 int rv; 1104 phy_ctrl_t *pc; 1105 1106 pc = EXT_PHY_SW_STATE(unit, port); 1107 rv = SOC_E_NONE; 1108 if (PHY_COPPER_MODE(unit, port)) { 1109 /* Note: mac.c uses phy_5690_notify_duplex to update 5690 */ 1110 rv = phy_fe_ge_duplex_set(unit, port, duplex); 1111 if (SOC_SUCCESS(rv)) { 1112 pc->copper.force_duplex = duplex; 1113 } 1114 } else { /* Fiber */ 1115 if (PHY_FIBER_100FX_MODE(unit, port)) { 1116 SOC_IF_ERROR_RETURN 1117 (MODIFY_PHY5482_2ND_SERDES_CTRLr(unit, pc, 1118 duplex? PHY_5482_2ND_SERDES_100FX_FD:0, 1119 PHY_5482_2ND_SERDES_100FX_FD)); 1120 pc->fiber.force_duplex = duplex; 1121 } else { 1122 if (!duplex) { 1123 rv = SOC_E_UNAVAIL; 1124 } 1125 } 1126 } 1127 1128 LOG_INFO(BSL_LS_SOC_PHY, 1129 (BSL_META_U(unit, 1130 "phy_5482_duplex_set: u=%d p=%d d=%d rv=%d\n"), 1131 unit, port, duplex, rv)); 1132 1133 return rv; 1134 } 1135 1136 /* 1137 * Function: 1138 * phy_5482_duplex_get 1139 * Purpose: 1140 * Get the current operating duplex mode. If autoneg is enabled, 1141 * then operating mode is returned, otherwise forced mode is returned. 1142 * Parameters: 1143 * unit - StrataSwitch unit #. 1144 * port - StrataSwitch port #. 1145 * duplex - (OUT) Boolean, true indicates full duplex, false 1146 * indicates half. 1147 * Returns: 1148 * SOC_E_NONE 1149 * Notes: 1150 * The duplex is retrieved for the ACTIVE medium. 1151 * No synchronization performed at this level. Autonegotiation is 1152 * not manipulated. 1153 */ 1154 1155 STATIC int 1156 phy_5482_duplex_get(int unit, soc_port_t port, int *duplex) 1157 { 1158 phy_ctrl_t *pc; 1159 uint16 data16; 1160 1161 pc = EXT_PHY_SW_STATE(unit, port); 1162 1163 if (PHY_COPPER_MODE(unit, port)) { 1164 return phy_fe_ge_duplex_get(unit, port, duplex); 1165 } else { 1166 if (PHY_FIBER_100FX_MODE(unit, port)) { 1167 SOC_IF_ERROR_RETURN 1168 (READ_PHY5482_2ND_SERDES_CTRLr(unit, pc, &data16)); 1169 *duplex = (data16 & PHY_5482_2ND_SERDES_100FX_FD) ? 1170 TRUE: FALSE; 1171 } else { /* 1000X */ 1172 *duplex = TRUE; 1173 } 1174 } 1175 1176 return SOC_E_NONE; 1177 } 1178 1179 /* 1180 * Function: 1181 * phy_5482_speed_set 1182 * Purpose: 1183 * Set the current operating speed (forced). 1184 * Parameters: 1185 * unit - StrataSwitch unit #. 1186 * port - StrataSwitch port #. 1187 * speed - Requested speed, only 1000 supported. 1188 * Returns: 1189 * SOC_E_XXX 1190 * Notes: 1191 * The speed is set only for the ACTIVE medium. 1192 */ 1193 1194 STATIC int 1195 phy_5482_speed_set(int unit, soc_port_t port, int speed) 1196 { 1197 int rv; 1198 phy_ctrl_t *pc; 1199 1200 pc = EXT_PHY_SW_STATE(unit, port); 1201 rv = SOC_E_NONE; 1202 if (PHY_COPPER_MODE(unit, port)) { 1203 /* Note: mac.c uses phy_5690_notify_speed to update 5690 */ 1204 rv = phy_fe_ge_speed_set(unit, port, speed); 1205 if (SOC_SUCCESS(rv)) { 1206 pc->copper.force_speed = speed; 1207 } 1208 } else { /* Fiber */ 1209 if (speed == 100) { 1210 rv = _phy_5482_fiber_100fx_setup(unit, port); 1211 } else if (speed == 0 || speed == 1000) { 1212 rv = _phy_5482_fiber_1000x_setup(unit, port); 1213 } else { 1214 rv = SOC_E_CONFIG; 1215 } 1216 if (SOC_SUCCESS(rv)) { 1217 pc->fiber.force_speed = speed; 1218 } 1219 } 1220 if (SOC_SUCCESS(rv) && !PHY_SGMII_AUTONEG_MODE(unit, port)) { 1221 uint16 mii_ctrl; 1222 1223 SOC_IF_ERROR_RETURN 1224 (READ_PHY5482_1000X_MII_CTRLr(unit, pc, &mii_ctrl)); 1225 1226 mii_ctrl &= ~(MII_CTRL_SS_LSB | MII_CTRL_SS_MSB); 1227 switch(speed) { 1228 case 10: 1229 mii_ctrl |= MII_CTRL_SS_10; 1230 break; 1231 case 100: 1232 mii_ctrl |= MII_CTRL_SS_100; 1233 break; 1234 case 0: 1235 case 1000: 1236 mii_ctrl |= MII_CTRL_SS_1000; 1237 break; 1238 default: 1239 return(SOC_E_CONFIG); 1240 } 1241 1242 SOC_IF_ERROR_RETURN 1243 (WRITE_PHY5482_1000X_MII_CTRLr(unit, pc, mii_ctrl)); 1244 } 1245 1246 LOG_INFO(BSL_LS_SOC_PHY, 1247 (BSL_META_U(unit, 1248 "phy_5482_speed_set: u=%d p=%d s=%d fiber=%d rv=%d\n"), 1249 unit, port, speed, PHY_FIBER_MODE(unit, port), rv)); 1250 1251 return rv; 1252 } 1253 1254 /* 1255 * Function: 1256 * phy_5482_speed_get 1257 * Purpose: 1258 * Get the current operating speed for a 5482 device. 1259 * Parameters: 1260 * unit - StrataSwitch unit #. 1261 * port - StrataSwitch port #. 1262 * duplex - (OUT) Boolean, true indicates full duplex, false 1263 * indicates half. 1264 * Returns: 1265 * SOC_E_NONE 1266 * Notes: 1267 * The speed is retrieved for the ACTIVE medium. 1268 */ 1269 1270 STATIC int 1271 phy_5482_speed_get(int unit, soc_port_t port, int *speed) 1272 { 1273 phy_ctrl_t *pc; 1274 uint16 opt_mode; 1275 1276 pc = EXT_PHY_SW_STATE(unit, port); 1277 1278 if (PHY_COPPER_MODE(unit, port)) { 1279 return phy_fe_ge_speed_get(unit, port, speed); 1280 } else { 1281 *speed = 1000; 1282 SOC_IF_ERROR_RETURN 1283 (READ_PHY5482_EXP_OPT_MODE_STATr(unit, pc, &opt_mode)); 1284 switch(opt_mode & (0x3 << 13)) { 1285 case (0 << 13): 1286 *speed = 10; 1287 break; 1288 case (1 << 13): 1289 *speed = 100; 1290 break; 1291 case (2 << 13): 1292 *speed = 1000; 1293 break; 1294 default: 1295 LOG_WARN(BSL_LS_SOC_PHY, 1296 (BSL_META_U(unit, 1297 "phy_5482_speed_get: u=%d p=%d invalid speed\n"), 1298 unit, port)); 1299 } 1300 } 1301 1302 return SOC_E_NONE; 1303 } 1304 1305 /* 1306 * Function: 1307 * phy_5482_master_set 1308 * Purpose: 1309 * Set the current master mode 1310 * Parameters: 1311 * unit - StrataSwitch unit #. 1312 * port - StrataSwitch port #. 1313 * master - SOC_PORT_MS_* 1314 * Returns: 1315 * SOC_E_XXX 1316 * Notes: 1317 * The master mode is set only for the ACTIVE medium. 1318 */ 1319 STATIC int 1320 phy_5482_master_set(int unit, soc_port_t port, int master) 1321 { 1322 int rv; 1323 phy_ctrl_t *pc; 1324 1325 pc = EXT_PHY_SW_STATE(unit, port); 1326 rv = SOC_E_NONE; 1327 if (PHY_COPPER_MODE(unit, port)) { 1328 rv = phy_fe_ge_master_set(unit, port, master); 1329 if (SOC_SUCCESS(rv)) { 1330 pc->copper.master = master; 1331 } 1332 } 1333 LOG_INFO(BSL_LS_SOC_PHY, 1334 (BSL_META_U(unit, 1335 "phy_5482_master_set: u=%d p=%d master=%d fiber=%d rv=%d\n"), 1336 unit, port, master, PHY_FIBER_MODE(unit, port), rv)); 1337 return rv; 1338 } 1339 1340 /* 1341 * Function: 1342 * phy_5482_master_get 1343 * Purpose: 1344 * Get the current master mode for a 5482 device. 1345 * Parameters: 1346 * unit - StrataSwitch unit #. 1347 * port - StrataSwitch port #. 1348 * master - (OUT) SOC_PORT_MS_* 1349 * Returns: 1350 * SOC_E_NONE 1351 * Notes: 1352 * The master mode is retrieved for the ACTIVE medium. 1353 */ 1354 1355 STATIC int 1356 phy_5482_master_get(int unit, soc_port_t port, int *master) 1357 { 1358 if (PHY_COPPER_MODE(unit, port)) { 1359 return phy_fe_ge_master_get(unit, port, master); 1360 } else { 1361 *master = SOC_PORT_MS_NONE; 1362 return SOC_E_NONE; 1363 } 1364 } 1365 1366 /* 1367 * Function: 1368 * phy_5482_autoneg_set 1369 * Purpose: 1370 * Enable or disable auto-negotiation on the specified port. 1371 * Parameters: 1372 * unit - StrataSwitch unit #. 1373 * port - StrataSwitch port #. 1374 * autoneg - Boolean, if true, auto-negotiation is enabled 1375 * (and/or restarted). If false, autonegotiation is disabled. 1376 * Returns: 1377 * SOC_E_XXX 1378 * Notes: 1379 * The autoneg mode is set only for the ACTIVE medium. 1380 */ 1381 1382 STATIC int 1383 phy_5482_autoneg_set(int unit, soc_port_t port, int autoneg) 1384 { 1385 int rv; 1386 uint16 data, mask; 1387 phy_ctrl_t *pc; 1388 1389 pc = EXT_PHY_SW_STATE(unit, port); 1390 rv = SOC_E_NONE; 1391 if (PHY_COPPER_MODE(unit, port)) { 1392 rv = phy_fe_ge_an_set(unit, port, autoneg); 1393 if (SOC_SUCCESS(rv)) { 1394 pc->copper.autoneg_enable = autoneg ? 1 : 0; 1395 } 1396 } else { 1397 /* Disable/Enable auto-detection between SGMII-slave and 1000BASE-X */ 1398 if (autoneg) { 1399 /* When enabling autoneg, set the default speed to 1000Mbps first. 1400 * PHY will not enable autoneg if the PHY is in 100FX mode. 1401 */ 1402 SOC_IF_ERROR_RETURN 1403 (phy_5482_speed_set(unit, port, 1000)); 1404 } 1405 data = (autoneg) ? (1 << 0) : 0; 1406 mask = (1 << 0); /* Switch between 1000BASE-X and SGMII slave 1407 * modes based on SerDes-received auto-neg 1408 * code word. */ 1409 mask |= (1 << 1); /* Enable/Disable SGMII slave mode */ 1410 SOC_IF_ERROR_RETURN 1411 (MODIFY_PHY5482_2ND_SERDES_SGMII_SLAVEr(unit, pc, data, mask)); 1412 1413 SOC_IF_ERROR_RETURN 1414 (phy_5482_adv_local_set(unit, port, pc->fiber.autoneg_advert)); 1415 1416 /* If enable autoneg, also enable parallel detect */ 1417 data = (autoneg) ? (1 << 1) : 0; 1418 mask = (1 << 1); 1419 SOC_IF_ERROR_RETURN 1420 (MODIFY_PHY5482_EXP_2ND_SERDES_CTRLr(unit, pc, data, mask)); 1421 1422 data = MII_CTRL_FD; 1423 data |= (autoneg) ? MII_CTRL_AE | MII_CTRL_RAN : 0; 1424 mask = MII_CTRL_AE | MII_CTRL_RAN | MII_CTRL_FD; 1425 SOC_IF_ERROR_RETURN 1426 (MODIFY_PHY5482_2ND_SERDES_1000X_CTRLr(unit, pc, data, mask)); 1427 1428 1429 pc->fiber.autoneg_enable = autoneg ? TRUE : FALSE; 1430 } 1431 1432 LOG_INFO(BSL_LS_SOC_PHY, 1433 (BSL_META_U(unit, 1434 "phy_5482_autoneg_set: u=%d p=%d autoneg=%d rv=%d\n"), 1435 unit, port, autoneg, rv)); 1436 1437 return rv; 1438 } 1439 1440 /* 1441 * Function: 1442 * phy_5482_autoneg_get 1443 * Purpose: 1444 * Get the current auto-negotiation status (enabled/busy). 1445 * Parameters: 1446 * unit - StrataSwitch unit #. 1447 * port - StrataSwitch port #. 1448 * autoneg - (OUT) if true, auto-negotiation is enabled. 1449 * autoneg_done - (OUT) if true, auto-negotiation is complete. This 1450 * value is undefined if autoneg == FALSE. 1451 * Returns: 1452 * SOC_E_XXX 1453 * Notes: 1454 * The autoneg mode is retrieved for the ACTIVE medium. 1455 */ 1456 1457 STATIC int 1458 phy_5482_autoneg_get(int unit, soc_port_t port, 1459 int *autoneg, int *autoneg_done) 1460 { 1461 int rv; 1462 uint16 data; 1463 phy_ctrl_t *pc; 1464 1465 pc = EXT_PHY_SW_STATE(unit, port); 1466 1467 rv = SOC_E_NONE; 1468 *autoneg = FALSE; 1469 *autoneg_done = FALSE; 1470 if (PHY_COPPER_MODE(unit, port)) { 1471 rv = phy_fe_ge_an_get(unit, port, autoneg, autoneg_done); 1472 } else { 1473 /* autoneg is not enabled in 100FX mode */ 1474 if (PHY_FIBER_100FX_MODE(unit, port)) { 1475 *autoneg = FALSE; 1476 *autoneg_done = TRUE; 1477 return rv; 1478 } 1479 SOC_IF_ERROR_RETURN 1480 (READ_PHY5482_2ND_SERDES_1000X_CTRLr(unit, pc, &data)); 1481 if (data & MII_CTRL_AE) { 1482 *autoneg = TRUE; 1483 1484 SOC_IF_ERROR_RETURN 1485 (READ_PHY5482_2ND_SERDES_1000X_STATr(unit, pc, &data)); 1486 if (data & MII_STAT_AN_DONE) { 1487 *autoneg_done = TRUE; 1488 } 1489 } 1490 1491 } 1492 1493 return rv; 1494 } 1495 1496 /* 1497 * Function: 1498 * phy_5482_adv_local_set 1499 * Purpose: 1500 * Set the current advertisement for auto-negotiation. 1501 * Parameters: 1502 * unit - StrataSwitch unit #. 1503 * port - StrataSwitch port #. 1504 * mode - Port mode mask indicating supported options/speeds. 1505 * Returns: 1506 * SOC_E_XXX 1507 * Notes: 1508 * The advertisement is set only for the ACTIVE medium. 1509 * No synchronization performed at this level. 1510 */ 1511 1512 STATIC int 1513 phy_5482_adv_local_set(int unit, soc_port_t port, soc_port_mode_t mode) 1514 { 1515 int rv; 1516 phy_ctrl_t *pc; 1517 1518 pc = EXT_PHY_SW_STATE(unit, port); 1519 rv = SOC_E_NONE; 1520 if (PHY_COPPER_MODE(unit, port)) { 1521 rv = phy_ge_adv_local_set(unit, port, mode); 1522 if (SOC_SUCCESS(rv)) { 1523 pc->copper.autoneg_advert = mode & ADVERT_ALL_COPPER; 1524 } 1525 } else { 1526 uint16 mii_adv; 1527 1528 mii_adv = MII_ANA_C37_FD; /* Always advertise 1000X full duplex */ 1529 switch (mode & SOC_PM_PAUSE) { 1530 case SOC_PM_PAUSE: 1531 mii_adv |= MII_ANA_C37_PAUSE; 1532 break; 1533 case SOC_PM_PAUSE_TX: 1534 mii_adv |= MII_ANA_C37_ASYM_PAUSE; 1535 break; 1536 case SOC_PM_PAUSE_RX: 1537 mii_adv |= (MII_ANA_C37_ASYM_PAUSE | MII_ANA_C37_PAUSE); 1538 break; 1539 } 1540 /* Write to Secondary SerDes Auto-Neg Advertisement Reg */ 1541 rv = WRITE_PHY5482_2ND_SERDES_ANAr(unit, pc, mii_adv); 1542 if (SOC_SUCCESS(rv)) { 1543 pc->fiber.autoneg_advert = mode & ADVERT_ALL_FIBER; 1544 } 1545 } 1546 LOG_INFO(BSL_LS_SOC_PHY, 1547 (BSL_META_U(unit, 1548 "phy_5482_adv_local_set: u=%d p=%d mode=0x%x, rv=%d\n"), 1549 unit, port, mode, rv)); 1550 return rv; 1551 } 1552 1553 /* 1554 * Function: 1555 * phy_5482_adv_local_get 1556 * Purpose: 1557 * Get the current advertisement for auto-negotiation. 1558 * Parameters: 1559 * unit - StrataSwitch unit #. 1560 * port - StrataSwitch port #. 1561 * mode - (OUT) Port mode mask indicating supported options/speeds. 1562 * Returns: 1563 * SOC_E_XXX 1564 * Notes: 1565 * The advertisement is retrieved for the ACTIVE medium. 1566 * No synchronization performed at this level. 1567 */ 1568 1569 STATIC int 1570 phy_5482_adv_local_get(int unit, soc_port_t port, soc_port_mode_t *mode) 1571 { 1572 uint16 mii_adv; 1573 phy_ctrl_t *pc; 1574 1575 pc = EXT_PHY_SW_STATE(unit, port); 1576 1577 if (PHY_COPPER_MODE(unit, port)) { 1578 return phy_ge_adv_local_get(unit, port, mode); 1579 } else { /* PHY_FIBER_MODE */ 1580 /* read the 1000BASE-X Auto-Neg Advertisement Reg ( Address 0x04 ) */ 1581 SOC_IF_ERROR_RETURN 1582 (READ_PHY5482_2ND_SERDES_ANAr(unit, pc, &mii_adv)); 1583 1584 *mode = 0; 1585 *mode |= (mii_adv & MII_ANA_C37_FD) ? SOC_PM_1000MB_FD : 0; 1586 *mode |= (mii_adv & MII_ANA_C37_HD) ? SOC_PM_1000MB_HD : 0; 1587 switch (mii_adv & (MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE)) { 1588 case MII_ANA_C37_PAUSE: 1589 *mode |= SOC_PM_PAUSE; 1590 break; 1591 case MII_ANA_C37_ASYM_PAUSE: 1592 *mode |= SOC_PM_PAUSE_TX; 1593 break; 1594 case (MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE): 1595 *mode |= SOC_PM_PAUSE_RX; 1596 break; 1597 } 1598 } 1599 return SOC_E_NONE; 1600 } 1601 1602 /* 1603 * Function: 1604 * phy_5482_adv_remote_get 1605 * Purpose: 1606 * Get partners current advertisement for auto-negotiation. 1607 * Parameters: 1608 * unit - StrataSwitch unit #. 1609 * port - StrataSwitch port #. 1610 * mode - (OUT) Port mode mask indicating supported options/speeds. 1611 * Returns: 1612 * SOC_E_XXX 1613 * Notes: 1614 * The remote advertisement is retrieved for the ACTIVE medium. 1615 * No synchronization performed at this level. If Autonegotiation is 1616 * disabled or in progress, this routine will return an error. 1617 */ 1618 1619 STATIC int 1620 phy_5482_adv_remote_get(int unit, soc_port_t port, soc_port_mode_t *mode) 1621 { 1622 uint16 data; 1623 phy_ctrl_t *pc; 1624 1625 pc = EXT_PHY_SW_STATE(unit, port); 1626 if (PHY_COPPER_MODE(unit, port)) { 1627 return phy_ge_adv_remote_get(unit, port, mode); 1628 } else { /* PHY_FIBER_MODE */ 1629 1630 *mode = 0; 1631 /* read the 1000BASE-X Control Reg ( Address 0x00 ), 1632 * Auto-Neg Link Partner Ability Reg ( Address 0x05 ) 1633 */ 1634 SOC_IF_ERROR_RETURN 1635 (READ_PHY5482_2ND_SERDES_1000X_CTRLr(unit, pc, &data)); 1636 if (!(data & MII_CTRL_AE)) { 1637 return SOC_E_DISABLED; 1638 } 1639 1640 SOC_IF_ERROR_RETURN 1641 (READ_PHY5482_2ND_SERDES_ANPr(unit, pc, &data)); 1642 if (data & MII_ANP_SGMII_MODE) { 1643 /* Link partner is SGMII master */ 1644 switch(data & MII_ANP_SGMII_SS_MASK) { 1645 case MII_ANP_SGMII_SS_10: 1646 *mode = SOC_PM_10MB; 1647 break; 1648 case MII_ANP_SGMII_SS_100: 1649 *mode = SOC_PM_100MB; 1650 break; 1651 case MII_ANP_SGMII_SS_1000: 1652 *mode = SOC_PM_1000MB; 1653 break; 1654 } 1655 1656 *mode &= (data & MII_ANP_SGMII_FD) ? SOC_PM_FD : SOC_PM_HD; 1657 } else { 1658 *mode |= (data & MII_ANP_C37_FD) ? SOC_PM_1000MB_FD : 0; 1659 *mode |= (data & MII_ANP_C37_HD) ? SOC_PM_1000MB_HD : 0; 1660 switch (data & (MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE)) { 1661 case MII_ANP_C37_PAUSE: 1662 *mode |= SOC_PM_PAUSE; 1663 break; 1664 case MII_ANP_C37_ASYM_PAUSE: 1665 *mode |= SOC_PM_PAUSE_TX; 1666 break; 1667 case (MII_ANP_C37_PAUSE | MII_ANP_C37_ASYM_PAUSE): 1668 *mode |= SOC_PM_PAUSE_RX; 1669 break; 1670 } 1671 } 1672 } 1673 return SOC_E_NONE; 1674 } 1675 1676 /* 1677 * Function: 1678 * phy_5482_lb_set 1679 * Purpose: 1680 * Set the local PHY loopback mode. 1681 * Parameters: 1682 * unit - StrataSwitch unit #. 1683 * port - StrataSwitch port #. 1684 * loopback - Boolean: true = enable loopback, false = disable. 1685 * Returns: 1686 * SOC_E_XXX 1687 * Notes: 1688 * The loopback mode is set only for the ACTIVE medium. 1689 * No synchronization performed at this level. 1690 */ 1691 1692 STATIC int 1693 phy_5482_lb_set(int unit, soc_port_t port, int enable) 1694 { 1695 int rv; 1696 uint16 data; 1697 phy_ctrl_t *pc; 1698 1699 pc = EXT_PHY_SW_STATE(unit, port); 1700 rv = SOC_E_NONE; 1701 1702 #if AUTO_MDIX_WHEN_AN_DIS 1703 { 1704 /* Disable Auto-MDIX When autoneg disabled */ 1705 /* Enable Auto-MDIX When autoneg disabled */ 1706 data = (enable) ? 0x0000 : 0x0200; 1707 SOC_IF_ERROR_RETURN 1708 (MODIFY_PHY_5482_MII_MISC_CTRLr(unit, pc, data, 0x0200)); 1709 } 1710 #endif 1711 1712 if (PHY_COPPER_MODE(unit, port)) { 1713 rv = phy_fe_ge_lb_set(unit, port, enable); 1714 } else { 1715 data = (enable) ? MII_CTRL_LE : 0; 1716 rv = MODIFY_PHY5482_2ND_SERDES_1000X_CTRLr 1717 (unit, pc, data, MII_CTRL_LE); 1718 if (enable && SOC_SUCCESS(rv)) { 1719 uint16 stat; 1720 int link; 1721 soc_timeout_t to; 1722 1723 /* Wait up to 5000 msec for link up */ 1724 soc_timeout_init(&to, 5000000, 0); 1725 link = 0; 1726 while (!soc_timeout_check(&to)) { 1727 rv = READ_PHY5482_2ND_SERDES_1000X_STATr(unit, pc, &stat); 1728 link = stat & MII_STAT_LA; 1729 if (link || SOC_FAILURE(rv)) { 1730 break; 1731 } 1732 } 1733 if (!link) { 1734 LOG_WARN(BSL_LS_SOC_PHY, 1735 (BSL_META_U(unit, 1736 "phy_5482_lb_set: u=%d p=%d TIMEOUT\n"), 1737 unit, port)); 1738 1739 rv = SOC_E_TIMEOUT; 1740 } 1741 } 1742 } 1743 LOG_INFO(BSL_LS_SOC_PHY, 1744 (BSL_META_U(unit, 1745 "phy_5482_lb_set: u=%d p=%d en=%d rv=%d\n"), 1746 unit, port, enable, rv)); 1747 1748 return rv; 1749 } 1750 1751 /* 1752 * Function: 1753 * phy_5482_lb_get 1754 * Purpose: 1755 * Get the local PHY loopback mode. 1756 * Parameters: 1757 * unit - StrataSwitch unit #. 1758 * port - StrataSwitch port #. 1759 * loopback - (OUT) Boolean: true = enable loopback, false = disable. 1760 * Returns: 1761 * SOC_E_XXX 1762 * Notes: 1763 * The loopback mode is retrieved for the ACTIVE medium. 1764 */ 1765 1766 STATIC int 1767 phy_5482_lb_get(int unit, soc_port_t port, int *enable) 1768 { 1769 uint16 data; 1770 phy_ctrl_t *pc; 1771 1772 pc = EXT_PHY_SW_STATE(unit, port); 1773 1774 if (PHY_COPPER_MODE(unit, port)) { 1775 SOC_IF_ERROR_RETURN 1776 (phy_fe_ge_lb_get(unit, port, enable)); 1777 } else { 1778 SOC_IF_ERROR_RETURN 1779 (READ_PHY5482_2ND_SERDES_1000X_CTRLr(unit, pc, &data)); 1780 *enable = (data & MII_CTRL_LE) ? 1 : 0; 1781 } 1782 1783 return SOC_E_NONE; 1784 } 1785 1786 /* 1787 * Function: 1788 * phy_5482_interface_set 1789 * Purpose: 1790 * Set the current operating mode of the PHY. 1791 * Parameters: 1792 * unit - StrataSwitch unit #. 1793 * port - StrataSwitch port #. 1794 * pif - one of SOC_PORT_IF_* 1795 * Returns: 1796 * SOC_E_NONE - success 1797 * SOC_E_UNAVAIL - unsupported interface 1798 */ 1799 1800 STATIC int 1801 phy_5482_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 1802 { 1803 COMPILER_REFERENCE(unit); 1804 COMPILER_REFERENCE(port); 1805 1806 switch (pif) { 1807 case SOC_PORT_IF_SGMII: 1808 case SOC_PORT_IF_GMII: 1809 return SOC_E_NONE; 1810 default: 1811 return SOC_E_UNAVAIL; 1812 } 1813 } 1814 1815 /* 1816 * Function: 1817 * phy_5482_interface_get 1818 * Purpose: 1819 * Get the current operating mode of the PHY. 1820 * Parameters: 1821 * unit - StrataSwitch unit #. 1822 * port - StrataSwitch port #. 1823 * pif - (OUT) one of SOC_PORT_IF_* 1824 * Returns: 1825 * SOC_E_NONE 1826 */ 1827 1828 STATIC int 1829 phy_5482_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 1830 { 1831 COMPILER_REFERENCE(unit); 1832 COMPILER_REFERENCE(port); 1833 1834 *pif = SOC_PORT_IF_SGMII; 1835 1836 return SOC_E_NONE; 1837 } 1838 1839 /* 1840 * Function: 1841 * phy_5482_ability_get 1842 * Purpose: 1843 * Get the abilities of the local gigabit PHY. 1844 * Parameters: 1845 * unit - StrataSwitch unit #. 1846 * port - StrataSwitch port #. 1847 * mode - (OUT) Port mode mask indicating supported options/speeds. 1848 * Returns: 1849 * SOC_E_NONE 1850 * Notes: 1851 * The ability is retrieved only for the ACTIVE medium. 1852 */ 1853 1854 STATIC int 1855 phy_5482_ability_get(int unit, soc_port_t port, soc_port_mode_t *mode) 1856 { 1857 int rv; 1858 phy_ctrl_t *pc; 1859 1860 rv = SOC_E_NONE; 1861 if (PHY_COPPER_MODE(unit, port)) { 1862 rv = phy_ge_ability_get(unit, port, mode); 1863 } else { /* fiber mode */ 1864 *mode = (SOC_PM_AN | SOC_PM_LB_PHY | 1865 SOC_PM_PAUSE | SOC_PM_PAUSE_ASYMM | 1866 SOC_PM_GMII | SOC_PM_SGMII | SOC_PM_1000MB_FD | 1867 SOC_PM_100MB_FD | SOC_PM_100MB_HD); 1868 } 1869 1870 pc = EXT_PHY_SW_STATE(unit, port); 1871 if (pc->automedium) { 1872 *mode |= SOC_PM_COMBO; 1873 } 1874 1875 return rv; 1876 } 1877 1878 /* 1879 * Function: 1880 * phy_5482_mdix_set 1881 * Description: 1882 * Set the Auto-MDIX mode of a port/PHY 1883 * Parameters: 1884 * unit - Device number 1885 * port - Port number 1886 * mode - One of: 1887 * SOC_PORT_MDIX_AUTO 1888 * Enable auto-MDIX when autonegotiation is enabled 1889 * SOC_PORT_MDIX_FORCE_AUTO 1890 * Enable auto-MDIX always 1891 * SOC_PORT_MDIX_NORMAL 1892 * Disable auto-MDIX 1893 * SOC_PORT_MDIX_XOVER 1894 * Disable auto-MDIX, and swap cable pairs 1895 * Return Value: 1896 * SOC_E_XXX 1897 */ 1898 STATIC int 1899 phy_5482_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode) 1900 { 1901 phy_ctrl_t *pc; 1902 int speed; 1903 1904 pc = EXT_PHY_SW_STATE(unit, port); 1905 if (PHY_COPPER_MODE(unit, port)) { 1906 switch (mode) { 1907 case SOC_PORT_MDIX_AUTO: 1908 /* Clear bit 14 for automatic MDI crossover */ 1909 SOC_IF_ERROR_RETURN 1910 (MODIFY_PHY5482_MII_ECRr(unit, pc, 0, 0x4000)); 1911 1912 /* Clear bit 9 to disable forced auto MDI xover */ 1913 SOC_IF_ERROR_RETURN 1914 (MODIFY_PHY5482_MII_MISC_CTRLr(unit, pc, 0, 0x0200)); 1915 break; 1916 1917 case SOC_PORT_MDIX_FORCE_AUTO: 1918 /* Clear bit 14 for automatic MDI crossover */ 1919 SOC_IF_ERROR_RETURN 1920 (MODIFY_PHY5482_MII_ECRr(unit, pc, 0, 0x4000)); 1921 1922 /* Set bit 9 to disable forced auto MDI xover */ 1923 SOC_IF_ERROR_RETURN 1924 (MODIFY_PHY5482_MII_MISC_CTRLr(unit, pc, 0x0200, 0x0200)); 1925 break; 1926 1927 case SOC_PORT_MDIX_NORMAL: 1928 SOC_IF_ERROR_RETURN(phy_5482_speed_get(unit, port, &speed)); 1929 if (speed == 0 || speed == 10 || speed == 100) { 1930 /* Set bit 14 for automatic MDI crossover */ 1931 SOC_IF_ERROR_RETURN 1932 (MODIFY_PHY5482_MII_ECRr(unit, pc, 0x4000, 0x4000)); 1933 1934 SOC_IF_ERROR_RETURN 1935 (WRITE_PHY5482_TEST1r(unit, pc, 0)); 1936 } else { 1937 return SOC_E_UNAVAIL; 1938 } 1939 break; 1940 1941 case SOC_PORT_MDIX_XOVER: 1942 SOC_IF_ERROR_RETURN(phy_5482_speed_get(unit, port, &speed)); 1943 if (speed == 0 || speed == 10 || speed == 100) { 1944 /* Set bit 14 for automatic MDI crossover */ 1945 SOC_IF_ERROR_RETURN 1946 (MODIFY_PHY5482_MII_ECRr(unit, pc, 0x4000, 0x4000)); 1947 1948 SOC_IF_ERROR_RETURN 1949 (WRITE_PHY5482_TEST1r(unit, pc, 0x0080)); 1950 } else { 1951 return SOC_E_UNAVAIL; 1952 } 1953 break; 1954 1955 default: 1956 return SOC_E_PARAM; 1957 } 1958 pc->copper.mdix = mode; 1959 } else { /* fiber */ 1960 if (mode != SOC_PORT_MDIX_NORMAL) { 1961 return SOC_E_UNAVAIL; 1962 } 1963 } 1964 return SOC_E_NONE; 1965 } 1966 1967 /* 1968 * Function: 1969 * phy_5482_mdix_get 1970 * Description: 1971 * Get the Auto-MDIX mode of a port/PHY 1972 * Parameters: 1973 * unit - Device number 1974 * port - Port number 1975 * mode - (Out) One of: 1976 * SOC_PORT_MDIX_AUTO 1977 * Enable auto-MDIX when autonegotiation is enabled 1978 * SOC_PORT_MDIX_FORCE_AUTO 1979 * Enable auto-MDIX always 1980 * SOC_PORT_MDIX_NORMAL 1981 * Disable auto-MDIX 1982 * SOC_PORT_MDIX_XOVER 1983 * Disable auto-MDIX, and swap cable pairs 1984 * Return Value: 1985 * SOC_E_XXX 1986 */ 1987 STATIC int 1988 phy_5482_mdix_get(int unit, soc_port_t port, soc_port_mdix_t *mode) 1989 { 1990 phy_ctrl_t *pc; 1991 int speed; 1992 1993 if (mode == NULL) { 1994 return SOC_E_PARAM; 1995 } 1996 1997 pc = EXT_PHY_SW_STATE(unit, port); 1998 1999 if (PHY_COPPER_MODE(unit, port)) { 2000 SOC_IF_ERROR_RETURN(phy_5482_speed_get(unit, port, &speed)); 2001 if (speed == 1000) { 2002 *mode = SOC_PORT_MDIX_AUTO; 2003 } else { 2004 *mode = pc->copper.mdix; 2005 } 2006 } else { 2007 *mode = SOC_PORT_MDIX_NORMAL; 2008 } 2009 2010 return SOC_E_NONE; 2011 } 2012 2013 /* 2014 * Function: 2015 * phy_5482_mdix_status_get 2016 * Description: 2017 * Get the current MDIX status on a port/PHY 2018 * Parameters: 2019 * unit - Device number 2020 * port - Port number 2021 * status - (OUT) One of: 2022 * SOC_PORT_MDIX_STATUS_NORMAL 2023 * Straight connection 2024 * SOC_PORT_MDIX_STATUS_XOVER 2025 * Crossover has been performed 2026 * Return Value: 2027 * SOC_E_XXX 2028 */ 2029 STATIC int 2030 phy_5482_mdix_status_get(int unit, soc_port_t port, 2031 soc_port_mdix_status_t *status) 2032 { 2033 phy_ctrl_t *pc; 2034 uint16 data; 2035 2036 if (status == NULL) { 2037 return SOC_E_PARAM; 2038 } 2039 2040 pc = EXT_PHY_SW_STATE(unit, port); 2041 2042 if (PHY_COPPER_MODE(unit, port)) { 2043 SOC_IF_ERROR_RETURN 2044 (READ_PHY5482_MII_ESRr(unit, pc, &data)); 2045 if (data & 0x2000) { 2046 *status = SOC_PORT_MDIX_STATUS_XOVER; 2047 } else { 2048 *status = SOC_PORT_MDIX_STATUS_NORMAL; 2049 } 2050 } else { 2051 *status = SOC_PORT_MDIX_STATUS_NORMAL; 2052 } 2053 2054 return SOC_E_NONE; 2055 } 2056 2057 2058 STATIC int 2059 phy_5482_control_linkdown_transmit_set(int unit, soc_port_t port, 2060 uint32 value) 2061 { 2062 phy_ctrl_t *pc; 2063 int speed; 2064 uint16 data; 2065 int rv = SOC_E_NONE; 2066 2067 if (PHY_COPPER_MODE(unit, port)) { 2068 return SOC_E_UNAVAIL; 2069 } 2070 2071 SOC_IF_ERROR_RETURN 2072 (phy_5482_speed_get(unit, port, &speed)); 2073 2074 pc = EXT_PHY_SW_STATE(unit, port); 2075 2076 switch (speed) { 2077 case 10: 2078 rv = SOC_E_UNAVAIL; 2079 break; 2080 case 100: 2081 /* 100FX Unidirectional */ 2082 SOC_IF_ERROR_RETURN 2083 (READ_PHY5482_2ND_SERDES_100FX_TESTr(unit, pc, &data)); 2084 if (value) { 2085 data |= 0x00c0; 2086 } else { 2087 data &= ~0x00c0; 2088 } 2089 SOC_IF_ERROR_RETURN 2090 (WRITE_PHY5482_2ND_SERDES_100FX_TESTr(unit, pc, data)); 2091 /* Supress incoming data */ 2092 2093 SOC_IF_ERROR_RETURN 2094 (READ_PHY5482_EXP_SGMII_REC_CTRLr(unit, pc, &data)); 2095 if (value) { 2096 data |= 0x0001; 2097 } else { 2098 data &= ~0x0001; 2099 } 2100 SOC_IF_ERROR_RETURN 2101 (WRITE_PHY5482_EXP_SGMII_REC_CTRLr(unit, pc, data)); 2102 break; 2103 2104 case 1000: 2105 /* 1000-X Force XMIT */ 2106 SOC_IF_ERROR_RETURN 2107 (READ_PHY5482_2ND_SERDES_MISC_CTRL2r(unit, pc, &data)); 2108 if (value) { 2109 data |= 0x0008; 2110 } else { 2111 data &= ~0x0008; 2112 } 2113 SOC_IF_ERROR_RETURN 2114 (WRITE_PHY5482_2ND_SERDES_MISC_CTRL2r(unit, pc, data)); 2115 2116 SOC_IF_ERROR_RETURN 2117 (READ_PHY5482_MISC_1000X_CTRL2r(unit, pc, &data)); 2118 if (value) { 2119 data |= 0x0008; 2120 } else { 2121 data &= ~0x0008; 2122 } 2123 SOC_IF_ERROR_RETURN 2124 (WRITE_PHY5482_MISC_1000X_CTRL2r(unit, pc, data)); 2125 2126 /* Supress incoming data */ 2127 SOC_IF_ERROR_RETURN 2128 (READ_PHY5482_EXP_SGMII_REC_CTRLr(unit, pc, &data)); 2129 if (value) { 2130 data |= 0x0001; 2131 } else { 2132 data &= ~0x0001; 2133 } 2134 SOC_IF_ERROR_RETURN 2135 (WRITE_PHY5482_EXP_SGMII_REC_CTRLr(unit, pc, data)); 2136 break; 2137 2138 default: 2139 rv = SOC_E_UNAVAIL; 2140 } 2141 2142 return rv; 2143 } 2144 2145 2146 STATIC int 2147 phy_5482_control_linkdown_transmit_get(int unit, soc_port_t port, 2148 uint32 *value) 2149 { 2150 phy_ctrl_t *pc; 2151 int speed; 2152 uint16 data; 2153 int rv = SOC_E_NONE; 2154 2155 if (PHY_COPPER_MODE(unit, port)) { 2156 return SOC_E_UNAVAIL; 2157 } 2158 2159 SOC_IF_ERROR_RETURN 2160 (phy_5482_speed_get(unit, port, &speed)); 2161 2162 pc = EXT_PHY_SW_STATE(unit, port); 2163 2164 switch (speed) { 2165 case 10: 2166 rv = SOC_E_UNAVAIL; 2167 break; 2168 case 100: 2169 /* Check 100FX Unidirectional */ 2170 SOC_IF_ERROR_RETURN 2171 (READ_PHY5482_2ND_SERDES_100FX_TESTr(unit, pc, &data)); 2172 *value = (data & 0x00c0) ? 1 : 0; 2173 break; 2174 2175 case 1000: 2176 /* Check 1000-X Force XMIT */ 2177 SOC_IF_ERROR_RETURN 2178 (READ_PHY5482_2ND_SERDES_MISC_CTRL2r(unit, pc, &data)); 2179 *value = (data & 0x0008) ? 1 : 0; 2180 break; 2181 2182 default: 2183 rv = SOC_E_UNAVAIL; 2184 } 2185 2186 return rv; 2187 } 2188 2189 STATIC int 2190 _phy_5482_power_mode_set (int unit, soc_port_t port, int mode) 2191 { 2192 phy_ctrl_t *pc; 2193 int rv; 2194 pc = EXT_PHY_SW_STATE(unit, port); 2195 2196 rv = SOC_E_NONE; 2197 if (pc->power_mode == mode) { 2198 return SOC_E_NONE; 2199 } 2200 2201 if (mode == SOC_PHY_CONTROL_POWER_FULL) { 2202 /* disable the auto power mode */ 2203 SOC_IF_ERROR_RETURN 2204 (MODIFY_PHY5482_AUTO_POWER_DOWNr(unit,pc, 2205 0, 2206 PHY_5482_AUTO_PWRDWN_EN)); 2207 pc->power_mode = mode; 2208 } else if (mode == SOC_PHY_CONTROL_POWER_AUTO) { 2209 SOC_IF_ERROR_RETURN 2210 (MODIFY_PHY5482_AUTO_POWER_DOWNr(unit,pc, 2211 PHY_5482_AUTO_PWRDWN_EN, 2212 PHY_5482_AUTO_PWRDWN_EN)); 2213 pc->power_mode = mode; 2214 } else { 2215 rv = SOC_E_UNAVAIL; 2216 } 2217 return rv; 2218 } 2219 2220 2221 2222 /* 2223 * Function: 2224 * phy_5482_control_set 2225 * Purpose: 2226 * Configure PHY device specific control fucntion. 2227 * Parameters: 2228 * unit - StrataSwitch unit #. 2229 * port - StrataSwitch port #. 2230 * type - Control to update 2231 * value - New setting for the control 2232 * Returns: 2233 * SOC_E_NONE 2234 */ 2235 STATIC int 2236 phy_5482_control_set(int unit, soc_port_t port, 2237 soc_phy_control_t type, uint32 value) 2238 { 2239 int rv; 2240 phy_ctrl_t *pc; 2241 uint16 data16; 2242 2243 PHY_CONTROL_TYPE_CHECK(type); 2244 2245 pc = EXT_PHY_SW_STATE(unit, port); 2246 rv = SOC_E_NONE; 2247 2248 switch(type) { 2249 case SOC_PHY_CONTROL_CLOCK_ENABLE: 2250 if (pc->phy_rev == 0xB) { 2251 SOC_IF_ERROR_RETURN 2252 (WRITE_PHY5482_EXP_SGMII_REC_CTRLr(unit, pc, value ? (1U<<4) : 0)); 2253 } 2254 break; 2255 2256 case SOC_PHY_CONTROL_LINKDOWN_TRANSMIT: 2257 rv = phy_5482_control_linkdown_transmit_set(unit, port, value); 2258 break; 2259 2260 case SOC_PHY_CONTROL_POWER: 2261 rv = _phy_5482_power_mode_set(unit,port,value); 2262 break; 2263 2264 case SOC_PHY_CONTROL_POWER_AUTO_WAKE_TIME: 2265 if (value <= PHY_5482_AUTO_PWRDWN_WAKEUP_MAX) { 2266 2267 /* at least one unit */ 2268 if (value < PHY_5482_AUTO_PWRDWN_WAKEUP_UNIT) { 2269 value = PHY_5482_AUTO_PWRDWN_WAKEUP_UNIT; 2270 } 2271 } else { /* anything more then max, set to the max */ 2272 value = PHY_5482_AUTO_PWRDWN_WAKEUP_MAX; 2273 } 2274 SOC_IF_ERROR_RETURN 2275 (MODIFY_PHY5482_AUTO_POWER_DOWNr(unit,pc, 2276 value/PHY_5482_AUTO_PWRDWN_WAKEUP_UNIT, 2277 PHY_5482_AUTO_PWRDWN_WAKEUP_MASK)); 2278 break; 2279 2280 case SOC_PHY_CONTROL_POWER_AUTO_SLEEP_TIME: 2281 /* sleep time configuration is either 2.7s or 5.4 s, default is 2.7s */ 2282 if (value < PHY_5482_AUTO_PWRDWN_SLEEP_MAX) { 2283 data16 = 0; /* anything less than 5.4s, default to 2.7s */ 2284 } else { 2285 data16 = PHY_5482_AUTO_PWRDWN_SLEEP_MASK; 2286 } 2287 SOC_IF_ERROR_RETURN 2288 (MODIFY_PHY5482_AUTO_POWER_DOWNr(unit,pc, 2289 data16, 2290 PHY_5482_AUTO_PWRDWN_SLEEP_MASK)); 2291 break; 2292 2293 2294 default: 2295 rv = SOC_E_UNAVAIL; 2296 break; 2297 } 2298 return rv; 2299 } 2300 2301 /* 2302 * Function: 2303 * phy_5482_control_get 2304 * Purpose: 2305 * Get current control settign of the PHY. 2306 * Parameters: 2307 * unit - StrataSwitch unit #. 2308 * port - StrataSwitch port #. 2309 * type - Control to update 2310 * value - (OUT)Current setting for the control 2311 * Returns: 2312 * SOC_E_NONE 2313 */ 2314 STATIC int 2315 phy_5482_control_get(int unit, soc_port_t port, 2316 soc_phy_control_t type, uint32 *value) 2317 { 2318 int rv; 2319 phy_ctrl_t *pc; 2320 uint16 data; 2321 2322 PHY_CONTROL_TYPE_CHECK(type); 2323 2324 pc = EXT_PHY_SW_STATE(unit, port); 2325 rv = SOC_E_NONE; 2326 2327 switch(type) { 2328 case SOC_PHY_CONTROL_CLOCK_ENABLE: 2329 if (pc->phy_rev == 0xB) { 2330 SOC_IF_ERROR_RETURN 2331 (READ_PHY5482_EXP_SGMII_REC_CTRLr(unit, pc, &data)); 2332 *value = (data & (1U << 4)) ? TRUE : FALSE; 2333 } 2334 break; 2335 2336 case SOC_PHY_CONTROL_LINKDOWN_TRANSMIT: 2337 rv = phy_5482_control_linkdown_transmit_get(unit, port, value); 2338 break; 2339 2340 case SOC_PHY_CONTROL_POWER: 2341 *value = pc->power_mode; 2342 break; 2343 2344 case SOC_PHY_CONTROL_POWER_AUTO_SLEEP_TIME: 2345 SOC_IF_ERROR_RETURN 2346 (READ_PHY5482_AUTO_POWER_DOWNr(unit,pc, &data)); 2347 2348 if (data & PHY_5482_AUTO_PWRDWN_SLEEP_MASK) { 2349 *value = PHY_5482_AUTO_PWRDWN_SLEEP_MAX; 2350 } else { 2351 *value = 2700; 2352 } 2353 break; 2354 2355 case SOC_PHY_CONTROL_POWER_AUTO_WAKE_TIME: 2356 SOC_IF_ERROR_RETURN 2357 (READ_PHY5482_AUTO_POWER_DOWNr(unit,pc, &data)); 2358 2359 data &= PHY_5482_AUTO_PWRDWN_WAKEUP_MASK; 2360 *value = data * PHY_5482_AUTO_PWRDWN_WAKEUP_UNIT; 2361 break; 2362 2363 default: 2364 rv = SOC_E_UNAVAIL; 2365 break; 2366 } 2367 return rv; 2368 } 2369 2370 /* 2371 * Function: 2372 * phy_5482_cable_diag 2373 * Purpose: 2374 * Run 546x cable diagnostics 2375 * Parameters: 2376 * unit - device number 2377 * port - port number 2378 * status - (OUT) cable diagnotic status structure 2379 * Returns: 2380 * SOC_E_XXX 2381 */ 2382 STATIC int 2383 phy_5482_cable_diag(int unit, soc_port_t port, 2384 soc_port_cable_diag_t *status) 2385 { 2386 int rv, rv2, i; 2387 2388 extern int phy_5464_cable_diag_sw(int, soc_port_t , 2389 soc_port_cable_diag_t *); 2390 2391 if (status == NULL) { 2392 return SOC_E_PARAM; 2393 } 2394 2395 status->state = SOC_PORT_CABLE_STATE_OK; 2396 status->npairs = 4; 2397 status->fuzz_len = 0; 2398 for (i = 0; i < 4; i++) { 2399 status->pair_state[i] = SOC_PORT_CABLE_STATE_OK; 2400 } 2401 2402 MIIM_LOCK(unit); /* this locks out linkscan, essentially */ 2403 rv = phy_5464_cable_diag_sw(unit,port, status); 2404 MIIM_UNLOCK(unit); 2405 rv2 = 0; 2406 if (rv <= 0) { /* don't reset if > 0 -- link was up */ 2407 rv2 = _phy_5482_reset_setup(unit, port); 2408 } 2409 if (rv >= 0 && rv2 < 0) { 2410 return rv2; 2411 } 2412 return rv; 2413 } 2414 2415 #ifdef BROADCOM_DEBUG 2416 2417 /* 2418 * Function: 2419 * phy_5482_shadow_dump 2420 * Purpose: 2421 * Debug routine to dump all shadow registers. 2422 * Parameters: 2423 * unit - StrataSwitch unit #. 2424 * port - StrataSwitch port #. 2425 */ 2426 2427 void 2428 phy_5482_shadow_dump(int unit, soc_port_t port) 2429 { 2430 phy_ctrl_t *pc; 2431 uint16 tmp; 2432 int i; 2433 2434 pc = EXT_PHY_SW_STATE(unit, port); 2435 2436 /* Register 0x18 Shadows */ 2437 for (i = 0; i <= 7; i++) { 2438 WRITE_PHY_REG(unit, pc, 0x18, (i << 12) | 0x7); 2439 READ_PHY_REG(unit, pc, 0x18, &tmp); 2440 if ((tmp & ~7) == 0x0000) { 2441 continue; 2442 } 2443 LOG_CLI((BSL_META_U(unit, 2444 "0x18[0x%x]=0x%04x\n"), i, tmp)); 2445 } 2446 2447 /* Register 0x1c Shadows */ 2448 for (i = 0; i <= 0x1f; i++) { 2449 WRITE_PHY_REG(unit, pc, 0x1c, i << 10); 2450 READ_PHY_REG(unit, pc, 0x1c, &tmp); 2451 if ((tmp & ~0x7c00) == 0x0000) { 2452 continue; 2453 } 2454 LOG_CLI((BSL_META_U(unit, 2455 "0x1c[0x%x]=0x%04x\n"), i, tmp)); 2456 } 2457 2458 /* Register 0x17/0x15 Shadows */ 2459 for (i = 0; i <= 0x13; i++) { 2460 WRITE_PHY_REG(unit, pc, 0x17, 0xf00 | i); 2461 READ_PHY_REG(unit, pc, 0x15, &tmp); 2462 if (tmp == 0x0000) { 2463 continue; 2464 } 2465 LOG_CLI((BSL_META_U(unit, 2466 "0x17[0x%x]=0x%04x\n"), i, tmp)); 2467 } 2468 } 2469 2470 #endif /* BROADCOM_DEBUG */ 2471 2472 /* 2473 * Variable: phy_5482drv_ge 2474 * Purpose: PHY driver for 5482 2475 */ 2476 2477 phy_driver_t phy_5482drv_ge = { 2478 "5482/801x Gigabit PHY Driver", 2479 phy_5482_init, 2480 phy_fe_ge_reset, 2481 phy_5482_link_get, 2482 phy_5482_enable_set, 2483 phy_5482_enable_get, 2484 phy_5482_duplex_set, 2485 phy_5482_duplex_get, 2486 phy_5482_speed_set, 2487 phy_5482_speed_get, 2488 phy_5482_master_set, 2489 phy_5482_master_get, 2490 phy_5482_autoneg_set, 2491 phy_5482_autoneg_get, 2492 phy_5482_adv_local_set, 2493 phy_5482_adv_local_get, 2494 phy_5482_adv_remote_get, 2495 phy_5482_lb_set, 2496 phy_5482_lb_get, 2497 phy_5482_interface_set, 2498 phy_5482_interface_get, 2499 phy_5482_ability_get, 2500 NULL, /* Phy link up event */ 2501 NULL, /* Phy link down event */ 2502 phy_5482_mdix_set, 2503 phy_5482_mdix_get, 2504 phy_5482_mdix_status_get, 2505 phy_5482_medium_config_set, 2506 phy_5482_medium_config_get, 2507 phy_5482_medium_status, 2508 phy_5482_cable_diag, 2509 NULL, /* phy_link_change */ 2510 phy_5482_control_set, /* phy_control_set */ 2511 phy_5482_control_get, /* phy_control_get */ 2512 phy_ge_reg_read, 2513 phy_ge_reg_write, 2514 phy_ge_reg_modify, 2515 NULL /* Phy event notify */ 2516 }; 2517 2518 #else /* INCLUDE_PHY_5482_ESW */ 2519 int _soc_phy_5482_not_empty; 2520 #endif /* INCLUDE_PHY_5482 */ 2521