phyfege.c (53001B)
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: phy.c 8 * Purpose: Defines PHY driver routines, and standard 802.3 10/100/1000 9 * PHY interface routines. 10 */ 11 12 13 #include <sal/types.h> 14 #include <sal/core/spl.h> 15 #include <shared/bsl.h> 16 #include <soc/drv.h> 17 #include <soc/debug.h> 18 #include <soc/error.h> 19 #include <soc/phyreg.h> 20 #include <soc/phy.h> 21 22 #include <soc/phy.h> 23 #include <soc/phy/phyctrl.h> 24 #include <soc/phy/drv.h> 25 26 #include "phyident.h" 27 #include "phyreg.h" 28 #include "phynull.h" 29 #include "phyfege.h" 30 31 #define BCM5400_LOOPBACK_WAR 32 33 /* Variable: 34 * phy_drv_fe 35 * Purpose: 36 * Phy driver callouts for a standard phy (IEEE 802.3) 37 */ 38 39 phy_driver_t phy_drv_fe = { 40 "Fast Ethernet PHY Driver", 41 phy_fe_init, 42 phy_fe_ge_reset, 43 phy_fe_ge_link_get, 44 phy_fe_ge_enable_set, 45 phy_fe_ge_enable_get, 46 phy_fe_ge_duplex_set, 47 phy_fe_ge_duplex_get, 48 phy_fe_ge_speed_set, 49 phy_fe_ge_speed_get, 50 phy_fe_ge_master_set, 51 phy_fe_ge_master_get, 52 phy_fe_ge_an_set, 53 phy_fe_ge_an_get, 54 phy_fe_adv_local_set, 55 phy_fe_adv_local_get, 56 phy_fe_adv_remote_get, 57 phy_fe_ge_lb_set, 58 phy_fe_ge_lb_get, 59 phy_fe_interface_set, 60 phy_fe_interface_get, 61 phy_fe_ability_get, 62 NULL, 63 NULL, 64 phy_null_mdix_set, 65 phy_null_mdix_get, 66 phy_null_mdix_status_get, 67 NULL, 68 NULL, 69 phy_fe_ge_medium_get, 70 NULL, 71 NULL 72 }; 73 74 /* 75 * Variable: 76 * phy_drv_ge 77 * Purpose: 78 * Phy driver callouts for a Gigabit phy (IEEE 802.3) 79 */ 80 81 phy_driver_t phy_drv_ge = { 82 "Gigabit PHY Driver", 83 phy_ge_init, 84 phy_fe_ge_reset, 85 phy_fe_ge_link_get, 86 phy_fe_ge_enable_set, 87 phy_fe_ge_enable_get, 88 phy_fe_ge_duplex_set, 89 phy_fe_ge_duplex_get, 90 phy_fe_ge_speed_set, 91 phy_fe_ge_speed_get, 92 phy_fe_ge_master_set, 93 phy_fe_ge_master_get, 94 phy_fe_ge_an_set, 95 phy_fe_ge_an_get, 96 phy_ge_adv_local_set, 97 phy_ge_adv_local_get, 98 phy_ge_adv_remote_get, 99 phy_fe_ge_lb_set, 100 phy_fe_ge_lb_get, 101 phy_ge_interface_set, 102 phy_ge_interface_get, 103 phy_ge_ability_get, 104 NULL, 105 NULL, 106 phy_null_mdix_set, 107 phy_null_mdix_get, 108 phy_null_mdix_status_get, 109 NULL, 110 NULL, 111 phy_fe_ge_medium_get, 112 NULL, /* phy_cable_diag */ 113 NULL /* phy_link_change */ 114 }; 115 116 /* 117 * Function: 118 * phy_fe_ge_reset 119 * Purpose: 120 * Reset PHY and wait for it to come out of reset. 121 * Parameters: 122 * unit - StrataSwitch unit #. 123 * port - StrataSwitch port #. 124 * Returns: 125 * SOC_E_XXX 126 */ 127 128 int 129 phy_fe_ge_reset(int unit, soc_port_t port, void *user_arg) 130 { 131 phy_ctrl_t *pc; 132 uint16 ctrl, tmp; 133 soc_timeout_t to; 134 int timeout = 0; 135 136 COMPILER_REFERENCE(user_arg); 137 138 pc = EXT_PHY_SW_STATE(unit, port); 139 SOC_IF_ERROR_RETURN 140 (READ_PHYFEGE_MII_CTRLr(unit, pc, &ctrl)); 141 142 SOC_IF_ERROR_RETURN 143 (WRITE_PHYFEGE_MII_CTRLr(unit, pc, (ctrl | MII_CTRL_RESET))); 144 145 soc_timeout_init(&to, 146 soc_property_get(unit, 147 spn_PHY_RESET_TIMEOUT, 148 PHY_RESET_TIMEOUT_USEC), 1); 149 150 do { 151 SOC_IF_ERROR_RETURN 152 (READ_PHYFEGE_MII_CTRLr(unit, pc, &tmp)); 153 if (soc_timeout_check(&to)) { 154 timeout = 1; 155 break; 156 } 157 } while ((tmp & MII_CTRL_RESET) != 0); 158 159 if (timeout) { 160 LOG_WARN(BSL_LS_SOC_PHY, 161 (BSL_META_U(unit, 162 "phy_fe_ge_reset: timeout on u=%d p=%d\n"), 163 unit, port)); 164 SOC_IF_ERROR_RETURN 165 (WRITE_PHYFEGE_MII_CTRLr(unit, pc, ctrl)); 166 } 167 168 return (SOC_E_NONE); 169 } 170 171 /* 172 * Function: 173 * phy_fe_ge_enable_set 174 * Purpose: 175 * Enable or disable the physical interface. 176 * Parameters: 177 * unit - StrataSwitch unit #. 178 * port - StrataSwitch port #. 179 * enable - Boolean, true = enable PHY, false = disable. 180 * Returns: 181 * SOC_E_XXX 182 * Notes: 183 * There does not seem to be a way to truly disable the external 184 * link on standard PHYs. Isolate mode disables the MII side but 185 * not the wire side. Super-isolate mode disables the MII and 186 * link pulses; however disabling MII causes duplex-switch hangs. 187 * 188 * This code uses a PHY flag to keep track of enable state. 189 * This is important because linkscan copies the PHY enable state 190 * to the MAC enable state. 191 */ 192 193 int 194 phy_fe_ge_enable_set(int unit, soc_port_t port, int enable) 195 { 196 if (enable) { 197 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE); 198 } else { 199 PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE); 200 } 201 202 return (SOC_E_NONE); 203 } 204 205 /* 206 * Function: 207 * phy_fe_ge_enable_get 208 * Purpose: 209 * Return physical interface enable/disable state. 210 * Parameters: 211 * unit - StrataSwitch unit #. 212 * port - StrataSwitch port #. 213 * enable - (OUT) Boolean, true = enable PHY, false = disable. 214 * Returns: 215 * SOC_E_XXX 216 */ 217 218 int 219 phy_fe_ge_enable_get(int unit, soc_port_t port, int *enable) 220 { 221 *enable = !PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE); 222 return(SOC_E_NONE); 223 } 224 225 /* 226 * Function: 227 * phy_fe_init 228 * Purpose: 229 * Initialize the PHY to a known good state. 230 * Parameters: 231 * unit - StrataSwitch unit #. 232 * port - StrataSwitch port #. 233 * Returns: 234 * SOC_E_XXX 235 * Notes: 236 * No synchronization performed at this level. By default, phy set 237 * in autonegotiation mode, with maximum abilities advertised. 238 */ 239 240 int 241 phy_fe_init(int unit, soc_port_t port) 242 { 243 uint16 mii_ana, mii_ctrl; 244 phy_ctrl_t *pc; 245 246 /* Reset PHY */ 247 SOC_IF_ERROR_RETURN(soc_phy_reset(unit, port)); 248 249 pc = EXT_PHY_SW_STATE(unit, port); 250 251 mii_ana = MII_ANA_HD_10 | MII_ANA_FD_10 | MII_ANA_HD_100 | 252 MII_ANA_FD_100 | MII_ANA_ASF_802_3; 253 mii_ctrl = MII_CTRL_FD | MII_CTRL_SS_100 | MII_CTRL_AE | MII_CTRL_RAN; 254 255 SOC_IF_ERROR_RETURN 256 (WRITE_PHYFEGE_MII_CTRLr(unit, pc, mii_ctrl)); 257 SOC_IF_ERROR_RETURN 258 (WRITE_PHYFEGE_MII_ANAr(unit, pc, mii_ana)); 259 260 261 return(SOC_E_NONE); 262 } 263 264 /* 265 * Function: 266 * phy_ge_init 267 * Purpose: 268 * Initialize the PHY (MII mode) to a known good state. 269 * Parameters: 270 * unit - StrataSwitch unit #. 271 * port - StrataSwitch port #. 272 * Returns: 273 * SOC_E_XXX 274 275 * Notes: 276 * No synchronization performed at this level. 277 */ 278 279 int 280 phy_ge_init(int unit, soc_port_t port) 281 { 282 uint16 mii_ctrl, mii_gb_ctrl; 283 soc_port_if_t pif; 284 phy_ctrl_t *pc; 285 286 /* Reset PHY */ 287 SOC_IF_ERROR_RETURN(soc_phy_reset(unit, port)); 288 289 pc = EXT_PHY_SW_STATE(unit, port); 290 291 mii_ctrl = MII_CTRL_FD | MII_CTRL_SS_1000 | MII_CTRL_AE | MII_CTRL_RAN; 292 mii_gb_ctrl = MII_GB_CTRL_ADV_1000FD | MII_GB_CTRL_PT; 293 294 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_10B)) { 295 pif = SOC_PORT_IF_TBI; 296 } else { 297 pif = SOC_PORT_IF_GMII; 298 } 299 300 SOC_IF_ERROR_RETURN(phy_ge_interface_set(unit, port, pif)); 301 302 SOC_IF_ERROR_RETURN 303 (WRITE_PHYFEGE_MII_GB_CTRLr(unit, pc, mii_gb_ctrl)); 304 SOC_IF_ERROR_RETURN 305 (WRITE_PHYFEGE_MII_CTRLr(unit, pc, mii_ctrl)); 306 307 #if defined(INCLUDE_PHY_54XX) && defined(BCM5400_LOOPBACK_WAR) 308 /* Workaround for loop back w/5400; use a pseudo-random value */ 309 if (PHY_IS_BCM5400(pc)) { 310 uint16 seed = (uint16) (sal_time_usecs() + port) & MII_MSSEED_SEED; 311 312 /* Set up test reg/seed reg for external loopback */ 313 SOC_IF_ERROR_RETURN 314 (WRITE_PHYFEGE_MII_TEST2r(unit, pc, MII_TEST2_MS_SEL)); 315 SOC_IF_ERROR_RETURN 316 (WRITE_PHYFEGE_MII_MSSEEDr(unit, pc, seed)); 317 } 318 #endif 319 320 return(SOC_E_NONE); 321 } 322 323 /* 324 * Function: 325 * phy_fe_ge_link_get 326 * Purpose: 327 * Determine the current link up/down status 328 * Parameters: 329 * unit - StrataSwitch unit #. 330 * port - StrataSwitch port #. 331 * link - (OUT) Boolean, true indicates link established. 332 * Returns: 333 * SOC_E_XXX 334 * Notes: 335 * No synchronization performed at this level. 336 */ 337 338 int 339 phy_fe_ge_link_get(int unit, soc_port_t port, int *link) 340 { 341 uint16 mii_ctrl, mii_stat; 342 soc_timeout_t to; 343 phy_ctrl_t *pc; 344 345 *link = FALSE; /* Default */ 346 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 347 return SOC_E_NONE; 348 } 349 350 pc = EXT_PHY_SW_STATE(unit, port); 351 SOC_IF_ERROR_RETURN 352 (READ_PHYFEGE_MII_STATr(unit, pc, &mii_stat)); 353 354 if (!(mii_stat & MII_STAT_LA) || (mii_stat == 0xffff)) { 355 /* mii_stat == 0xffff check is to handle removable PHY daughter cards */ 356 return SOC_E_NONE; 357 } 358 359 /* Link appears to be up; we are done if autoneg is off. */ 360 361 SOC_IF_ERROR_RETURN 362 (READ_PHYFEGE_MII_CTRLr(unit, pc, &mii_ctrl)); 363 364 if (!(mii_ctrl & MII_CTRL_AE)) { 365 *link = TRUE; 366 return SOC_E_NONE; 367 } 368 369 /* 370 * If link appears to be up but autonegotiation is still in 371 * progress, wait for it to complete. For BCM5228, autoneg can 372 * still be busy up to about 200 usec after link is indicated. Also 373 * continue to check link state in case it goes back down. 374 */ 375 soc_timeout_init(&to, SOC_PHY_INFO(unit, port).an_timeout, 0); 376 for (;;) { 377 SOC_IF_ERROR_RETURN 378 (READ_PHYFEGE_MII_STATr(unit, pc, &mii_stat)); 379 380 if (!(mii_stat & MII_STAT_LA)) { 381 return SOC_E_NONE; 382 } 383 384 if (mii_stat & MII_STAT_AN_DONE) { 385 break; 386 } 387 388 if (soc_timeout_check(&to)) { 389 return SOC_E_BUSY; 390 } 391 } 392 393 /* Return link state at end of polling */ 394 395 *link = ((mii_stat & MII_STAT_LA) != 0); 396 397 return SOC_E_NONE; 398 } 399 400 /* 401 * Function: 402 * _phy_auto_negotiate_gcd (greatest common denominator). 403 * Purpose: 404 * Determine the current greatest common denominator between 405 * two ends of a link 406 * Parameters: 407 * unit - StrataSwitch unit #. 408 * port - StrataSwitch port #. 409 * speed - (OUT) greatest common speed. 410 * duplex - (OUT) greatest common duplex. 411 * link - (OUT) Boolean, true indicates link established. 412 * Returns: 413 * SOC_E_XXX 414 * Notes: 415 * No synchronization performed at this level. 416 */ 417 418 static int 419 _phy_auto_negotiate_gcd(int unit, soc_port_t port, int *speed, int *duplex) 420 { 421 int t_speed, t_duplex; 422 uint16 mii_ana, mii_anp, mii_stat; 423 uint16 mii_gb_stat, mii_esr, mii_gb_ctrl; 424 phy_ctrl_t *pc; 425 426 mii_gb_stat = 0; /* Start off 0 */ 427 mii_gb_ctrl = 0; /* Start off 0 */ 428 429 pc = EXT_PHY_SW_STATE(unit, port); 430 SOC_IF_ERROR_RETURN 431 (READ_PHYFEGE_MII_ANAr(unit, pc, &mii_ana)); 432 SOC_IF_ERROR_RETURN 433 (READ_PHYFEGE_MII_ANPr(unit, pc, &mii_anp)); 434 SOC_IF_ERROR_RETURN 435 (READ_PHYFEGE_MII_STATr(unit, pc, &mii_stat)); 436 437 if (mii_stat & MII_STAT_ES) { /* Supports extended status */ 438 /* 439 * If the PHY supports extended status, check if it is 1000MB 440 * capable. If it is, check the 1000Base status register to see 441 * if 1000MB negotiated. 442 */ 443 SOC_IF_ERROR_RETURN 444 (READ_PHYFEGE_MII_ESRr(unit, pc, &mii_esr)); 445 446 if (mii_esr & (MII_ESR_1000_X_FD | MII_ESR_1000_X_HD | 447 MII_ESR_1000_T_FD | MII_ESR_1000_T_HD)) { 448 SOC_IF_ERROR_RETURN 449 (READ_PHYFEGE_MII_GB_STATr(unit, pc, &mii_gb_stat)); 450 SOC_IF_ERROR_RETURN 451 (READ_PHYFEGE_MII_GB_CTRLr(unit, pc, &mii_gb_ctrl)); 452 } 453 } 454 455 /* 456 * At this point, if we did not see Gig status, one of mii_gb_stat or 457 * mii_gb_ctrl will be 0. This will cause the first 2 cases below to 458 * fail and fall into the default 10/100 cases. 459 */ 460 461 mii_ana &= mii_anp; 462 463 if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000FD) && 464 (mii_gb_stat & MII_GB_STAT_LP_1000FD)) { 465 t_speed = 1000; 466 t_duplex = 1; 467 } else if ((mii_gb_ctrl & MII_GB_CTRL_ADV_1000HD) && 468 (mii_gb_stat & MII_GB_STAT_LP_1000HD)) { 469 t_speed = 1000; 470 t_duplex = 0; 471 } else if (mii_ana & MII_ANA_FD_100) { /* [a] */ 472 t_speed = 100; 473 t_duplex = 1; 474 } else if (mii_ana & MII_ANA_T4) { /* [b] */ 475 t_speed = 100; 476 t_duplex = 0; 477 } else if (mii_ana & MII_ANA_HD_100) { /* [c] */ 478 t_speed = 100; 479 t_duplex = 0; 480 } else if (mii_ana & MII_ANA_FD_10) { /* [d] */ 481 t_speed = 10; 482 t_duplex = 1 ; 483 } else if (mii_ana & MII_ANA_HD_10) { /* [e] */ 484 t_speed = 10; 485 t_duplex = 0; 486 } else { 487 return(SOC_E_FAIL); 488 } 489 490 if (speed) *speed = t_speed; 491 if (duplex) *duplex = t_duplex; 492 493 return(SOC_E_NONE); 494 } 495 496 /* 497 * Function: 498 * _phy_auto_negotiate_ew (Autoneg-ed mode with E@W on). 499 * Purpose: 500 * Determine autoneg-ed mode between 501 * two ends of a link 502 * Parameters: 503 * unit - StrataSwitch unit #. 504 * port - StrataSwitch port #. 505 * speed - (OUT) greatest common speed. 506 * duplex - (OUT) greatest common duplex. 507 * link - (OUT) Boolean, true indicates link established. 508 * Returns: 509 * SOC_E_XXX 510 * Notes: 511 * No synchronization performed at this level. 512 */ 513 514 static int 515 _phy_auto_negotiate_ew(int unit, soc_port_t port, int *speed, int *duplex) 516 { 517 int t_speed, t_duplex; 518 uint16 mii_assr; 519 phy_ctrl_t *pc; 520 521 pc = EXT_PHY_SW_STATE(unit, port); 522 523 SOC_IF_ERROR_RETURN 524 (READ_PHYFEGE_MII_ASSRr(unit, pc, &mii_assr)); 525 526 switch ((mii_assr >> 8) & 0x7) { 527 case 0x7: 528 t_speed = 1000; 529 t_duplex = TRUE; 530 break; 531 case 0x6: 532 t_speed = 1000; 533 t_duplex = FALSE; 534 break; 535 case 0x5: 536 t_speed = 100; 537 t_duplex = TRUE; 538 break; 539 case 0x3: 540 t_speed = 100; 541 t_duplex = FALSE; 542 break; 543 case 0x2: 544 t_speed = 10; 545 t_duplex = TRUE; 546 break; 547 case 0x1: 548 t_speed = 10; 549 t_duplex = FALSE; 550 break; 551 default: 552 t_speed = 0; /* 0x4 is 100BASE-T4 which is not supported */ 553 t_duplex = FALSE; 554 break; 555 } 556 557 if (speed) *speed = t_speed; 558 if (duplex) *duplex = t_duplex; 559 560 return(SOC_E_NONE); 561 } 562 563 /* 564 * Function: 565 * phy_fe_ge_duplex_set 566 * Purpose: 567 * Set the current duplex mode (forced). 568 * Parameters: 569 * unit - StrataSwitch unit #. 570 * port - StrataSwitch port #. 571 * duplex - Boolean, true indicates full duplex, false indicates half. 572 * Returns: 573 * SOC_E_XXX 574 * Notes: 575 * No synchronization performed at this level. Autonegotiation is 576 * not manipulated. 577 */ 578 579 int 580 phy_fe_ge_duplex_set(int unit, soc_port_t port, int duplex) 581 { 582 uint16 mii_ctrl; 583 phy_ctrl_t *pc; 584 585 pc = EXT_PHY_SW_STATE(unit, port); 586 SOC_IF_ERROR_RETURN 587 (READ_PHYFEGE_MII_CTRLr(unit, pc, &mii_ctrl)); 588 589 if (duplex) { 590 mii_ctrl |= MII_CTRL_FD; 591 } else { 592 mii_ctrl &= ~MII_CTRL_FD; 593 } 594 595 SOC_IF_ERROR_RETURN 596 (WRITE_PHYFEGE_MII_CTRLr(unit, pc, mii_ctrl)); 597 598 return(SOC_E_NONE); 599 } 600 601 /* 602 * Function: 603 * phy_fe_ge_duplex_get 604 * Purpose: 605 * Get the current operating duplex mode. If autoneg is enabled, 606 * then operating mode is returned, otherwise forced mode is returned. 607 * Parameters: 608 * unit - StrataSwitch unit #. 609 * port - StrataSwitch port #. 610 * duplex - (OUT) Boolean, TRUE indicates full duplex, FALSE 611 * indicates half. 612 * Returns: 613 * SOC_E_XXX 614 * Notes: 615 * Returns a duplex of FALSE if autonegotiation is not complete. 616 * No synchronization performed at this level. Autonegotiation is 617 * not manipulated. 618 */ 619 620 int 621 phy_fe_ge_duplex_get(int unit, soc_port_t port, int *duplex) 622 { 623 int rv; 624 uint16 mii_ctrl, mii_stat; 625 phy_ctrl_t *pc; 626 627 pc = EXT_PHY_SW_STATE(unit, port); 628 629 SOC_IF_ERROR_RETURN 630 (READ_PHYFEGE_MII_CTRLr(unit, pc, &mii_ctrl)); 631 SOC_IF_ERROR_RETURN 632 (READ_PHYFEGE_MII_STATr(unit, pc, &mii_stat)); 633 634 rv = SOC_E_NONE; 635 if (mii_ctrl & MII_CTRL_AE) { /* Auto-negotiation enabled */ 636 if (!(mii_stat & MII_STAT_AN_DONE)) { /* Auto-neg NOT complete */ 637 *duplex = FALSE; 638 } else 639 if (IS_GE_PORT(unit, port)) { 640 uint16 misc_ctrl; 641 SOC_IF_ERROR_RETURN 642 (phy_reg_ge_read(unit, pc, 0x00, 0x0007, 0x18, &misc_ctrl)); 643 /* First check for Ethernet@Wirespeed */ 644 if (misc_ctrl & (1U << 4)) { /* Ethernet@Wirespeed enabled */ 645 rv = _phy_auto_negotiate_ew(unit, port, NULL, duplex); 646 } else { 647 rv = _phy_auto_negotiate_gcd(unit, port, NULL, duplex); 648 } 649 } else { 650 rv = _phy_auto_negotiate_gcd(unit, port, NULL, duplex); 651 } 652 } else { /* Auto-negotiation disabled */ 653 *duplex = (mii_ctrl & MII_CTRL_FD) ? TRUE : FALSE; 654 } 655 656 return(rv); 657 } 658 659 /* 660 * Function: 661 * phy_fe_ge_speed_set 662 * Purpose: 663 * Set the current operating speed (forced). 664 * Parameters: 665 * unit - StrataSwitch unit #. 666 * port - StrataSwitch port #. 667 * duplex - (OUT) Boolean, true indicates full duplex, false 668 * indicates half. 669 * Returns: 670 * SOC_E_XXX 671 * Notes: 672 * No synchronization performed at this level. Autonegotiation is 673 * not manipulated. 674 */ 675 676 int 677 phy_fe_ge_speed_set(int unit, soc_port_t port, int speed) 678 { 679 uint16 mii_ctrl; 680 phy_ctrl_t *pc; 681 soc_pbmp_t pbmp_100fx; 682 683 if (speed == 0) { 684 return SOC_E_NONE; 685 } 686 687 /* 688 * Get 100-FX ports from config.bcm. 689 */ 690 pbmp_100fx = soc_property_get_pbmp(unit, spn_PBMP_FE_100FX, 0); 691 if (SOC_PBMP_MEMBER(pbmp_100fx, port) && (speed != 100)) { 692 return SOC_E_CONFIG; 693 } 694 695 pc = EXT_PHY_SW_STATE(unit, port); 696 697 SOC_IF_ERROR_RETURN 698 (READ_PHYFEGE_MII_CTRLr(unit, pc, &mii_ctrl)); 699 700 mii_ctrl &= ~(MII_CTRL_SS_LSB | MII_CTRL_SS_MSB); 701 switch(speed) { 702 case 10: 703 mii_ctrl |= MII_CTRL_SS_10; 704 break; 705 case 100: 706 mii_ctrl |= MII_CTRL_SS_100; 707 break; 708 case 1000: 709 mii_ctrl |= MII_CTRL_SS_1000; 710 break; 711 default: 712 return(SOC_E_CONFIG); 713 } 714 715 SOC_IF_ERROR_RETURN 716 (WRITE_PHYFEGE_MII_CTRLr(unit, pc, mii_ctrl)); 717 718 return(SOC_E_NONE); 719 } 720 721 /* 722 * Function: 723 * phy_fe_ge_speed_get 724 * Purpose: 725 * Get the current operating speed. If autoneg is enabled, 726 * then operating mode is returned, otherwise forced mode is returned. 727 * Parameters: 728 * unit - StrataSwitch unit #. 729 * port - StrataSwitch port #. 730 * duplex - (OUT) Boolean, true indicates full duplex, false 731 * indicates half. 732 * Returns: 733 * SOC_E_XXX 734 * Notes: 735 * Returns a speed of 0 if autonegotiation is not complete. 736 * No synchronization performed at this level. Autonegotiation is 737 * not manipulated. 738 */ 739 740 int 741 phy_fe_ge_speed_get(int unit, soc_port_t port, int *speed) 742 { 743 int rv; 744 uint16 mii_ctrl, mii_stat; 745 phy_ctrl_t *pc; 746 747 pc = EXT_PHY_SW_STATE(unit, port); 748 749 SOC_IF_ERROR_RETURN 750 (READ_PHYFEGE_MII_CTRLr(unit, pc, &mii_ctrl)); 751 SOC_IF_ERROR_RETURN 752 (READ_PHYFEGE_MII_STATr(unit, pc, &mii_stat)); 753 754 if (mii_ctrl & MII_CTRL_AE) { /* Auto-negotiation enabled */ 755 if (!(mii_stat & MII_STAT_AN_DONE)) { /* Auto-neg NOT complete */ 756 *speed = 0; 757 rv = SOC_E_NONE; 758 } else 759 if (IS_GE_PORT(unit, port)) { 760 uint16 misc_ctrl; 761 SOC_IF_ERROR_RETURN 762 (phy_reg_ge_read(unit, pc, 0x00, 0x0007, 0x18, &misc_ctrl)); 763 /* First check for Ethernet@Wirespeed */ 764 if (misc_ctrl & (1U << 4)) { /* Ethernet@Wirespeed enabled */ 765 rv = _phy_auto_negotiate_ew(unit, port, speed, NULL); 766 } else { 767 rv = _phy_auto_negotiate_gcd(unit, port, speed, NULL); 768 } 769 } else { 770 rv = _phy_auto_negotiate_gcd(unit, port, speed, NULL); 771 } 772 } else { /* Auto-negotiation disabled */ 773 /* 774 * Simply pick up the values we force in CTRL register. 775 */ 776 switch(MII_CTRL_SS(mii_ctrl)) { 777 case MII_CTRL_SS_10: 778 *speed = 10; 779 break; 780 case MII_CTRL_SS_100: 781 *speed = 100; 782 break; 783 case MII_CTRL_SS_1000: 784 *speed = 1000; 785 break; 786 default: /* Just pass error back */ 787 return(SOC_E_UNAVAIL); 788 } 789 rv = SOC_E_NONE; 790 } 791 792 return(rv); 793 } 794 795 /* 796 * Function: 797 * phy_fe_ge_master_get 798 * Purpose: 799 * Get the master mode for the PHY. If mode is forced, then 800 * forced mode is returned; otherwise operating mode is returned. 801 * Parameters: 802 * unit - StrataSwitch unit #. 803 * port - StrataSwitch port #. 804 * master - (OUT) SOC_PORT_MS_* 805 * Returns: 806 * SOC_E_XXX 807 * Notes: 808 * No synchronization performed at this level. Autonegotiation is 809 * not manipulated. 810 */ 811 812 int 813 phy_fe_ge_master_get(int unit, soc_port_t port, int *master) 814 { 815 int an = 0, an_done = 0, speed = 0; 816 uint16 mii_gb_ctrl, mii_gb_stat; 817 phy_ctrl_t *pc; 818 819 pc = EXT_PHY_SW_STATE(unit, port); 820 821 if (IS_FE_PORT(unit, port)) { 822 *master = SOC_PORT_MS_NONE; 823 } else { 824 SOC_IF_ERROR_RETURN 825 (READ_PHYFEGE_MII_GB_CTRLr(unit, pc, &mii_gb_ctrl)); 826 827 if (!(mii_gb_ctrl & MII_GB_CTRL_MS_MAN)) { 828 *master = SOC_PORT_MS_AUTO; 829 return SOC_E_NONE; 830 } 831 832 833 SOC_IF_ERROR_RETURN 834 (phy_fe_ge_an_get(unit, port, &an, &an_done)); 835 836 SOC_IF_ERROR_RETURN 837 (phy_fe_ge_speed_get(unit, port, &speed)); 838 839 /* 840 * Master/Slave Status check can be skipped if : 841 * - autoneg is off 842 * or - speed not 1000Mbps 843 * 844 * Here we just return the Manually configured result 845 */ 846 if (!an || speed != 1000) { 847 if (mii_gb_ctrl & MII_GB_CTRL_MS) { 848 *master = SOC_PORT_MS_MASTER; 849 } else { 850 *master = SOC_PORT_MS_SLAVE; 851 } 852 return SOC_E_NONE; 853 } 854 855 /* Status check needed for 1000Mbps with autoneg */ 856 SOC_IF_ERROR_RETURN 857 (READ_PHYFEGE_MII_GB_STATr(unit, pc, &mii_gb_stat)); 858 859 if (mii_gb_stat & MII_GB_STAT_MS_FAULT) { 860 *master = SOC_PORT_MS_NONE; 861 } else if (mii_gb_stat & MII_GB_STAT_MS) { 862 *master = SOC_PORT_MS_MASTER; 863 } else { 864 *master = SOC_PORT_MS_SLAVE; 865 } 866 } 867 868 return(SOC_E_NONE); 869 } 870 871 /* 872 * Function: 873 * phy_fe_ge_master_set 874 * Purpose: 875 * Set the master mode for the PHY. 876 * Parameters: 877 * unit - StrataSwitch unit #. 878 * port - StrataSwitch port #. 879 * master - SOC_PORT_MS_* 880 * Returns: 881 * SOC_E_XXX 882 * Notes: 883 * No synchronization performed at this level. Autonegotiation is 884 * not manipulated. 885 */ 886 887 int 888 phy_fe_ge_master_set(int unit, soc_port_t port, int master) 889 { 890 uint16 mii_gb_ctrl; 891 phy_ctrl_t *pc; 892 893 if (IS_FE_PORT(unit, port)) { 894 return(SOC_E_NONE); 895 } 896 897 pc = EXT_PHY_SW_STATE(unit, port); 898 899 SOC_IF_ERROR_RETURN 900 (READ_PHYFEGE_MII_GB_CTRLr(unit, pc, &mii_gb_ctrl)); 901 902 switch (master) { 903 case SOC_PORT_MS_SLAVE: 904 mii_gb_ctrl |= MII_GB_CTRL_MS_MAN; 905 mii_gb_ctrl &= ~MII_GB_CTRL_MS; 906 break; 907 case SOC_PORT_MS_MASTER: 908 mii_gb_ctrl |= MII_GB_CTRL_MS_MAN; 909 mii_gb_ctrl |= MII_GB_CTRL_MS; 910 break; 911 case SOC_PORT_MS_AUTO: 912 mii_gb_ctrl &= ~MII_GB_CTRL_MS_MAN; 913 break; 914 } 915 916 SOC_IF_ERROR_RETURN 917 (WRITE_PHYFEGE_MII_GB_CTRLr(unit, pc, mii_gb_ctrl)); 918 919 return(SOC_E_NONE); 920 } 921 922 /* 923 * Function: 924 * phy_fe_ge_an_set 925 * Purpose: 926 * Enable or disabled auto-negotiation on the specified port. 927 * Parameters: 928 * unit - StrataSwitch unit #. 929 * port - StrataSwitch port #. 930 * an - Boolean, if true, auto-negotiation is enabled 931 * (and/or restarted). If false, autonegotiation is disabled. 932 * Returns: 933 * SOC_E_XXX 934 */ 935 936 int 937 phy_fe_ge_an_set(int unit, soc_port_t port, int an) 938 { 939 uint16 mii_ctrl; 940 phy_ctrl_t *pc; 941 942 pc = EXT_PHY_SW_STATE(unit, port); 943 SOC_IF_ERROR_RETURN 944 (READ_PHYFEGE_MII_CTRLr(unit, pc, &mii_ctrl)); 945 946 if (an) { 947 mii_ctrl |= MII_CTRL_AE | MII_CTRL_RAN; 948 } else { 949 mii_ctrl &= ~(MII_CTRL_AE | MII_CTRL_RAN); 950 } 951 952 SOC_IF_ERROR_RETURN 953 (WRITE_PHYFEGE_MII_CTRLr(unit, pc, mii_ctrl)); 954 955 return(SOC_E_NONE); 956 } 957 958 /* 959 * Function: 960 * phy_fe_ge_an_get 961 * Purpose: 962 * Get the current auto-negotiation status (enabled/busy) 963 * Parameters: 964 * unit - StrataSwitch unit #. 965 * port - StrataSwitch port #. 966 * an - (OUT) if true, auto-negotiation is enabled. 967 * an_done - (OUT) if true, auto-negotiation is complete. This 968 * value is undefined if an == false. 969 * Returns: 970 * SOC_E_XXX 971 */ 972 973 int 974 phy_fe_ge_an_get(int unit, soc_port_t port, int *an, int *an_done) 975 { 976 uint16 mii_ctrl, mii_stat; 977 phy_ctrl_t *pc; 978 979 pc = EXT_PHY_SW_STATE(unit, port); 980 981 SOC_IF_ERROR_RETURN 982 (READ_PHYFEGE_MII_CTRLr(unit, pc, &mii_ctrl)); 983 SOC_IF_ERROR_RETURN 984 (READ_PHYFEGE_MII_STATr(unit, pc, &mii_stat)); 985 986 *an = (mii_ctrl & MII_CTRL_AE) ? TRUE : FALSE; 987 *an_done = (mii_stat & MII_STAT_AN_DONE) ? TRUE : FALSE; 988 989 return(SOC_E_NONE); 990 } 991 992 /* 993 * Function: 994 * phy_fe_adv_local_set 995 * Purpose: 996 * Set the current advertisement for auto-negotiation. 997 * Parameters: 998 * unit - StrataSwitch unit #. 999 * port - StrataSwitch port #. 1000 * mode - Port mode mask indicating supported options/speeds. 1001 * Returns: 1002 * SOC_E_XXX 1003 */ 1004 1005 int 1006 phy_fe_adv_local_set(int unit, soc_port_t port, soc_port_mode_t mode) 1007 { 1008 uint16 mii_adv, mii_ctrl; 1009 phy_ctrl_t *pc; 1010 1011 pc = EXT_PHY_SW_STATE(unit, port); 1012 1013 mii_adv = MII_ANA_ASF_802_3; 1014 1015 if (mode & SOC_PM_10MB_HD) mii_adv |= MII_ANA_HD_10; 1016 if (mode & SOC_PM_10MB_FD) mii_adv |= MII_ANA_FD_10; 1017 if (mode & SOC_PM_100MB_HD) mii_adv |= MII_ANA_HD_100; 1018 if (mode & SOC_PM_100MB_FD) mii_adv |= MII_ANA_FD_100; 1019 1020 switch(mode & SOC_PM_PAUSE) { 1021 case 0: 1022 break; 1023 case SOC_PM_PAUSE_TX | SOC_PM_PAUSE_RX: 1024 mii_adv |= MII_ANA_PAUSE; 1025 break; 1026 default: 1027 return(SOC_E_UNAVAIL); /* Parameter error */ 1028 } 1029 1030 SOC_IF_ERROR_RETURN 1031 (WRITE_PHYFEGE_MII_ANAr(unit, pc, mii_adv)); 1032 1033 /* Restart auto-neg if enabled */ 1034 1035 SOC_IF_ERROR_RETURN 1036 (READ_PHYFEGE_MII_CTRLr(unit, pc, &mii_ctrl)); 1037 1038 if (mii_ctrl & MII_CTRL_AE) { 1039 SOC_IF_ERROR_RETURN 1040 (WRITE_PHYFEGE_MII_CTRLr(unit, pc, mii_ctrl | MII_CTRL_RAN)); 1041 } 1042 1043 return(SOC_E_NONE); 1044 } 1045 1046 /* 1047 * Function: 1048 * phy_fe_adv_local_get 1049 * Purpose: 1050 * Get the current advertisement for auto-negotiation. 1051 * Parameters: 1052 * unit - StrataSwitch unit #. 1053 * port - StrataSwitch port #. 1054 * mode - (OUT) Port mode mask indicating supported options/speeds. 1055 * Returns: 1056 * SOC_E_XXX 1057 */ 1058 1059 int 1060 phy_fe_adv_local_get(int unit, soc_port_t port, soc_port_mode_t *mode) 1061 { 1062 uint16 mii_ana; 1063 phy_ctrl_t *pc; 1064 1065 pc = EXT_PHY_SW_STATE(unit, port); 1066 1067 *mode = 0; 1068 1069 SOC_IF_ERROR_RETURN 1070 (READ_PHYFEGE_MII_ANAr(unit, pc, &mii_ana)); 1071 1072 if (mii_ana & MII_ANA_HD_10) *mode |= SOC_PM_10MB_HD; 1073 if (mii_ana & MII_ANA_FD_10) *mode |= SOC_PM_10MB_FD; 1074 if (mii_ana & MII_ANA_HD_100) *mode |= SOC_PM_100MB_HD; 1075 if (mii_ana & MII_ANA_FD_100) *mode |= SOC_PM_100MB_FD; 1076 if (mii_ana & MII_ANA_PAUSE) *mode |= SOC_PM_PAUSE; 1077 1078 return(SOC_E_NONE); 1079 } 1080 1081 /* 1082 * Function: 1083 * phy_fe_adv_remote_get 1084 * Purpose: 1085 * Get link partner's current advertisement for auto-negotiation. 1086 * Parameters: 1087 * unit - StrataSwitch unit #. 1088 * port - StrataSwitch port #. 1089 * mode - (OUT) Port mode mask indicating supported options/speeds. 1090 * Returns: 1091 * SOC_E_XXX 1092 * Notes: 1093 * Returns an empty mask if autonegotiation is not complete. 1094 */ 1095 1096 int 1097 phy_fe_adv_remote_get(int unit, soc_port_t port, soc_port_mode_t *mode) 1098 { 1099 uint16 mii_anp, mii_ctrl, mii_stat; 1100 phy_ctrl_t *pc; 1101 1102 pc = EXT_PHY_SW_STATE(unit, port); 1103 1104 *mode = 0; 1105 1106 /* ORDER: must read control, then stat, then anp */ 1107 1108 SOC_IF_ERROR_RETURN 1109 (READ_PHYFEGE_MII_CTRLr(unit, pc, &mii_ctrl)); 1110 SOC_IF_ERROR_RETURN 1111 (READ_PHYFEGE_MII_STATr(unit, pc, &mii_stat)); 1112 SOC_IF_ERROR_RETURN 1113 (READ_PHYFEGE_MII_ANPr(unit, pc, &mii_anp)); 1114 1115 if (!(mii_ctrl & MII_CTRL_AE)) { 1116 return(SOC_E_DISABLED); 1117 } else if (!(mii_stat & MII_STAT_AN_DONE)) { 1118 return(SOC_E_NONE); 1119 } 1120 1121 /* Figure out what it means */ 1122 1123 if (mii_anp & MII_ANA_HD_10) *mode |= SOC_PM_10MB_HD; 1124 if (mii_anp & MII_ANA_FD_10) *mode |= SOC_PM_10MB_FD; 1125 if (mii_anp & MII_ANA_HD_100) *mode |= SOC_PM_100MB_HD; 1126 if (mii_anp & MII_ANA_FD_100) *mode |= SOC_PM_100MB_FD; 1127 1128 if (mii_anp & MII_ANA_PAUSE) { 1129 *mode |= SOC_PM_PAUSE; 1130 } 1131 1132 return(SOC_E_NONE); 1133 } 1134 1135 /* 1136 * Function: 1137 * phy_ge_adv_local_set 1138 * Purpose: 1139 * Set the current advertisement for auto-negotiation. 1140 * Parameters: 1141 * unit - StrataSwitch unit #. 1142 * port - StrataSwitch port #. 1143 * mode - Port mode mask indicating supported options/speeds. 1144 * Returns: 1145 * SOC_E_XXX 1146 */ 1147 1148 int 1149 phy_ge_adv_local_set(int unit, soc_port_t port, soc_port_mode_t mode) 1150 { 1151 uint16 mii_ctrl, mii_adv, mii_gb_ctrl; 1152 phy_ctrl_t *pc; 1153 1154 pc = EXT_PHY_SW_STATE(unit, port); 1155 mii_adv = MII_ANA_ASF_802_3; 1156 1157 SOC_IF_ERROR_RETURN 1158 (READ_PHYFEGE_MII_GB_CTRLr(unit, pc, &mii_gb_ctrl)); 1159 1160 mii_gb_ctrl &= ~(MII_GB_CTRL_ADV_1000HD | MII_GB_CTRL_ADV_1000FD); 1161 1162 if (mode & SOC_PM_10MB_HD) mii_adv |= MII_ANA_HD_10; 1163 if (mode & SOC_PM_10MB_FD) mii_adv |= MII_ANA_FD_10; 1164 if (mode & SOC_PM_100MB_HD) mii_adv |= MII_ANA_HD_100; 1165 if (mode & SOC_PM_100MB_FD) mii_adv |= MII_ANA_FD_100; 1166 if (mode & SOC_PM_1000MB_HD) mii_gb_ctrl |= MII_GB_CTRL_ADV_1000HD; 1167 if (mode & SOC_PM_1000MB_FD) mii_gb_ctrl |= MII_GB_CTRL_ADV_1000FD; 1168 1169 if ((mode & SOC_PM_PAUSE) == SOC_PM_PAUSE) { 1170 /* Advertise symmetric pause */ 1171 mii_adv |= MII_ANA_PAUSE; 1172 } else { 1173 /* 1174 * For Asymmetric pause, 1175 * if (Bit 10) 1176 * then pause frames flow toward the Transceiver 1177 * else pause frames flow toward link partner. 1178 */ 1179 if (mode & SOC_PM_PAUSE_TX) { 1180 mii_adv |= MII_ANA_ASYM_PAUSE; 1181 } else if (mode & SOC_PM_PAUSE_RX) { 1182 mii_adv |= MII_ANA_ASYM_PAUSE; 1183 mii_adv |= MII_ANA_PAUSE; 1184 } 1185 } 1186 1187 SOC_IF_ERROR_RETURN 1188 (WRITE_PHYFEGE_MII_ANAr(unit, pc, mii_adv)); 1189 SOC_IF_ERROR_RETURN 1190 (WRITE_PHYFEGE_MII_GB_CTRLr(unit, pc, mii_gb_ctrl)); 1191 1192 /* Restart auto-neg if enabled */ 1193 1194 SOC_IF_ERROR_RETURN 1195 (READ_PHYFEGE_MII_CTRLr(unit, pc, &mii_ctrl)); 1196 1197 if (mii_ctrl & MII_CTRL_AE) { 1198 SOC_IF_ERROR_RETURN 1199 (WRITE_PHYFEGE_MII_CTRLr(unit, pc, mii_ctrl | MII_CTRL_RAN)); 1200 } 1201 1202 return(SOC_E_NONE); 1203 } 1204 1205 /* 1206 * Function: 1207 * phy_ge_adv_local_get 1208 * Purpose: 1209 * Get the current advertisement for auto-negotiation. 1210 * Parameters: 1211 * unit - StrataSwitch unit #. 1212 * port - StrataSwitch port #. 1213 * mode - (OUT) Port mode mask indicating supported options/speeds. 1214 * Returns: 1215 * SOC_E_XXX 1216 */ 1217 1218 int 1219 phy_ge_adv_local_get(int unit, soc_port_t port, soc_port_mode_t *mode) 1220 { 1221 uint16 mii_ana, mii_gb_ctrl; 1222 phy_ctrl_t *pc; 1223 1224 pc = EXT_PHY_SW_STATE(unit, port); 1225 SOC_IF_ERROR_RETURN 1226 (READ_PHYFEGE_MII_ANAr(unit, pc, &mii_ana)); 1227 SOC_IF_ERROR_RETURN 1228 (READ_PHYFEGE_MII_GB_CTRLr(unit, pc, &mii_gb_ctrl)); 1229 1230 *mode = 0; 1231 1232 if (mii_ana & MII_ANA_HD_10) *mode |= SOC_PM_10MB_HD; 1233 if (mii_ana & MII_ANA_FD_10) *mode |= SOC_PM_10MB_FD; 1234 if (mii_ana & MII_ANA_HD_100) *mode |= SOC_PM_100MB_HD; 1235 if (mii_ana & MII_ANA_FD_100) *mode |= SOC_PM_100MB_FD; 1236 1237 if (mii_ana & MII_ANA_ASYM_PAUSE) { 1238 if (mii_ana & MII_ANA_PAUSE) { 1239 *mode |= SOC_PM_PAUSE_RX; 1240 } else { 1241 *mode |= SOC_PM_PAUSE_TX; 1242 } 1243 } else if (mii_ana & MII_ANA_PAUSE) { 1244 *mode |= SOC_PM_PAUSE; 1245 } 1246 1247 /* GE Specific values */ 1248 1249 if (mii_gb_ctrl & MII_GB_CTRL_ADV_1000FD) *mode |= SOC_PM_1000MB_FD; 1250 if (mii_gb_ctrl & MII_GB_CTRL_ADV_1000HD) *mode |= SOC_PM_1000MB_HD; 1251 1252 return(SOC_E_NONE); 1253 } 1254 1255 /* 1256 * Function: 1257 * phy_ge_adv_remote_get 1258 * Purpose: 1259 * Get partner's current advertisement for auto-negotiation. 1260 * Parameters: 1261 * unit - StrataSwitch unit #. 1262 * port - StrataSwitch port #. 1263 * mode - (OUT) Port mode mask indicating supported options/speeds. 1264 * Returns: 1265 * SOC_E_XXX 1266 * Notes: 1267 * Returns an empty mask if autonegotiation is not complete. 1268 */ 1269 1270 int 1271 phy_ge_adv_remote_get(int unit, soc_port_t port, soc_port_mode_t *mode) 1272 { 1273 uint16 mii_ctrl, mii_stat, mii_gb_stat, mii_anp; 1274 phy_ctrl_t *pc; 1275 1276 pc = EXT_PHY_SW_STATE(unit, port); 1277 1278 *mode = 0; 1279 1280 /* ORDER: must read control, then stat, then anp */ 1281 1282 SOC_IF_ERROR_RETURN 1283 (READ_PHYFEGE_MII_CTRLr(unit, pc, &mii_ctrl)); 1284 SOC_IF_ERROR_RETURN 1285 (READ_PHYFEGE_MII_STATr(unit, pc, &mii_stat)); 1286 SOC_IF_ERROR_RETURN 1287 (READ_PHYFEGE_MII_ANPr(unit, pc, &mii_anp)); 1288 SOC_IF_ERROR_RETURN 1289 (READ_PHYFEGE_MII_GB_STATr(unit, pc, &mii_gb_stat)); 1290 1291 if (!(mii_ctrl & MII_CTRL_AE)) { 1292 return(SOC_E_DISABLED); 1293 } else if (!(mii_stat & MII_STAT_AN_DONE)) { 1294 return(SOC_E_NONE); 1295 } 1296 1297 /* Figure out what it means */ 1298 1299 if (mii_anp & MII_ANA_HD_10) *mode |= SOC_PM_10MB_HD; 1300 if (mii_anp & MII_ANA_FD_10) *mode |= SOC_PM_10MB_FD; 1301 if (mii_anp & MII_ANA_HD_100) *mode |= SOC_PM_100MB_HD; 1302 if (mii_anp & MII_ANA_FD_100) *mode |= SOC_PM_100MB_FD; 1303 1304 if (mii_gb_stat & MII_GB_STAT_LP_1000FD) *mode |= SOC_PM_1000MB_FD; 1305 if (mii_gb_stat & MII_GB_STAT_LP_1000HD) *mode |= SOC_PM_1000MB_HD; 1306 1307 if (mii_anp & MII_ANA_ASYM_PAUSE) { 1308 if (mii_anp & MII_ANA_PAUSE) { 1309 *mode |= SOC_PM_PAUSE_RX; 1310 } else { 1311 *mode |= SOC_PM_PAUSE_TX; 1312 } 1313 } else if (mii_anp & MII_ANA_PAUSE) { 1314 *mode |= SOC_PM_PAUSE; 1315 } 1316 1317 return(SOC_E_NONE); 1318 } 1319 1320 /* 1321 * Function: 1322 * phy_fe_ge_lb_set 1323 * Purpose: 1324 * Set the local PHY loopback mode. 1325 * Parameters: 1326 * unit - StrataSwitch unit #. 1327 * port - StrataSwitch port #. 1328 * loopback - Boolean: true = enable loopback, false = disable. 1329 * Returns: 1330 * SOC_E_XXX 1331 */ 1332 1333 int 1334 phy_fe_ge_lb_set(int unit, soc_port_t port, int enable) 1335 { 1336 uint16 mii_ctrl; 1337 phy_ctrl_t *pc; 1338 1339 pc = EXT_PHY_SW_STATE(unit, port); 1340 1341 SOC_IF_ERROR_RETURN 1342 (READ_PHYFEGE_MII_CTRLr(unit, pc, &mii_ctrl)); 1343 1344 mii_ctrl &= ~MII_CTRL_LE; 1345 mii_ctrl |= enable ? MII_CTRL_LE : 0; 1346 1347 SOC_IF_ERROR_RETURN 1348 (WRITE_PHYFEGE_MII_CTRLr(unit, pc, mii_ctrl)); 1349 1350 return(SOC_E_NONE); 1351 } 1352 1353 /* 1354 * Function: 1355 * phy_fe_ge_lb_get 1356 * Purpose: 1357 * Get the local PHY loopback mode. 1358 * Parameters: 1359 * unit - StrataSwitch unit #. 1360 * port - StrataSwitch port #. 1361 * loopback - (OUT) Boolean: true = enable loopback, false = disable. 1362 * Returns: 1363 * SOC_E_XXX 1364 */ 1365 1366 int 1367 phy_fe_ge_lb_get(int unit, soc_port_t port, int *enable) 1368 { 1369 uint16 mii_ctrl; 1370 phy_ctrl_t *pc; 1371 1372 pc = EXT_PHY_SW_STATE(unit, port); 1373 1374 SOC_IF_ERROR_RETURN 1375 (READ_PHYFEGE_MII_CTRLr(unit, pc, &mii_ctrl)); 1376 1377 *enable = (mii_ctrl & MII_CTRL_LE) ? 1 : 0; 1378 1379 return(SOC_E_NONE); 1380 } 1381 1382 /* 1383 * Function: 1384 * phy_fe_interface_set 1385 * Purpose: 1386 * Set the current operating mode of the PHY (SOC_PORT_IF_*) 1387 * For example: TBI or MII/GMII. 1388 * Parameters: 1389 * unit - StrataSwitch unit #. 1390 * port - StrataSwitch port #. 1391 * pif - one of SOC_PORT_IF_* 1392 * Returns: 1393 * SOC_E_XXX 1394 */ 1395 1396 int 1397 phy_fe_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 1398 { 1399 COMPILER_REFERENCE(unit); 1400 COMPILER_REFERENCE(port); 1401 1402 switch (pif) { 1403 case SOC_PORT_IF_MII: 1404 case SOC_PORT_IF_NOCXN: 1405 break; 1406 default: 1407 return SOC_E_UNAVAIL; 1408 } 1409 1410 return (SOC_E_NONE); 1411 } 1412 1413 /* 1414 * Function: 1415 * phy_fe_interface_get 1416 * Purpose: 1417 * Get the current operating mode of the PHY. 1418 * Parameters: 1419 * unit - StrataSwitch unit #. 1420 * port - StrataSwitch port #. 1421 * pif - (OUT) one of SORT_PORT_IF_* 1422 * Returns: 1423 * SOC_E_XXX 1424 */ 1425 1426 int 1427 phy_fe_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 1428 { 1429 COMPILER_REFERENCE(unit); 1430 COMPILER_REFERENCE(port); 1431 1432 *pif = SOC_PORT_IF_MII; 1433 1434 return(SOC_E_NONE); 1435 } 1436 1437 /* 1438 * Function: 1439 * phy_ge_interface_set 1440 * Purpose: 1441 * Set the current operating mode of the PHY. 1442 * (Pertaining to the MAC/PHY interface, not the line interface). 1443 * For example: TBI or MII/GMII. 1444 * Parameters: 1445 * unit - StrataSwitch unit #. 1446 * port - StrataSwitch port #. 1447 * pif - one of SOC_PORT_IF_* 1448 * Returns: 1449 * SOC_E_XXX 1450 */ 1451 1452 int 1453 phy_ge_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 1454 { 1455 uint16 mii_ecr; 1456 int mii; /* MII if true, TBI otherwise */ 1457 phy_ctrl_t *pc; 1458 1459 pc = EXT_PHY_SW_STATE(unit, port); 1460 1461 switch (pif) { 1462 case SOC_PORT_IF_MII: 1463 case SOC_PORT_IF_GMII: 1464 case SOC_PORT_IF_SGMII: 1465 mii = TRUE; 1466 break; 1467 case SOC_PORT_IF_NOCXN: 1468 return (SOC_E_NONE); 1469 case SOC_PORT_IF_TBI: 1470 mii = FALSE; 1471 break; 1472 default: 1473 return SOC_E_UNAVAIL; 1474 } 1475 1476 SOC_IF_ERROR_RETURN 1477 (READ_PHYFEGE_MII_ECRr(unit, pc, &mii_ecr)); 1478 1479 if (mii) { 1480 mii_ecr &= ~MII_ECR_10B; 1481 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_10B); 1482 } else { 1483 mii_ecr |= MII_ECR_10B; 1484 PHY_FLAGS_SET(unit, port, PHY_FLAGS_10B); 1485 } 1486 1487 SOC_IF_ERROR_RETURN 1488 (WRITE_PHYFEGE_MII_ECRr(unit, pc, mii_ecr)); 1489 1490 return(SOC_E_NONE); 1491 } 1492 1493 /* 1494 * Function: 1495 * phy_ge_interface_get 1496 * Purpose: 1497 * Get the current operating mode of the PHY. 1498 * (Pertaining to the MAC/PHY interface, not the line interface). 1499 * Parameters: 1500 * unit - StrataSwitch unit #. 1501 * port - StrataSwitch port #. 1502 * pif - (OUT) one of SOC_PORT_IF_* 1503 * Returns: 1504 * SOC_E_XXX 1505 */ 1506 1507 int 1508 phy_ge_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 1509 { 1510 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_10B)) { 1511 *pif = SOC_PORT_IF_TBI; 1512 } else { 1513 *pif = SOC_PORT_IF_GMII; 1514 } 1515 1516 return(SOC_E_NONE); 1517 } 1518 1519 /* 1520 * Function: 1521 * phy_fe_ability_get 1522 * Purpose: 1523 * Get the abilities of the local phy. 1524 * Parameters: 1525 * unit - StrataSwitch unit #. 1526 * port - StrataSwitch port #. 1527 * mode - (OUT) Port mode mask indicating supported options/speeds. 1528 * Returns: 1529 * SOC_E_XXX 1530 */ 1531 1532 int 1533 phy_fe_ability_get(int unit, soc_port_t port, soc_port_mode_t *mode) 1534 { 1535 uint16 mii_status; 1536 1537 phy_ctrl_t *pc; 1538 1539 pc = EXT_PHY_SW_STATE(unit, port); 1540 *mode = SOC_PM_LB_PHY | SOC_PM_MII | SOC_PM_PAUSE; /* No PAUSE_ASYMM */ 1541 *mode |= SOC_PM_AN; 1542 SOC_IF_ERROR_RETURN 1543 (READ_PHYFEGE_MII_STATr(unit, pc, &mii_status)); 1544 1545 if (mii_status & MII_STAT_100_T4) *mode |= SOC_PM_100MB_FD; 1546 if (mii_status & MII_STAT_FD_100_T2) *mode |= SOC_PM_100MB_FD; 1547 if (mii_status & MII_STAT_HD_100_T2) *mode |= SOC_PM_100MB_HD; 1548 if (mii_status & MII_STAT_FD_10) *mode |= SOC_PM_10MB_FD; 1549 if (mii_status & MII_STAT_HD_10) *mode |= SOC_PM_10MB_HD; 1550 if (mii_status & MII_STAT_FD_100) *mode |= SOC_PM_100MB_FD; 1551 if (mii_status & MII_STAT_HD_100) *mode |= SOC_PM_100MB_HD; 1552 1553 return(SOC_E_NONE); 1554 } 1555 1556 /* 1557 * Function: 1558 * phy_ge_ability_get 1559 * Purpose: 1560 * Get the abilities of the local gigabit phy. 1561 * Parameters: 1562 * unit - StrataSwitch unit #. 1563 * port - StrataSwitch port #. 1564 * mode - (OUT) Port mode mask indicating supported options/speeds. 1565 * Returns: 1566 * SOC_E_XXX 1567 */ 1568 1569 int 1570 phy_ge_ability_get(int unit, soc_port_t port, soc_port_mode_t *mode) 1571 { 1572 uint16 mii_esr; 1573 phy_ctrl_t *pc; 1574 1575 pc = EXT_PHY_SW_STATE(unit, port); 1576 1577 SOC_IF_ERROR_RETURN 1578 (phy_fe_ability_get(unit, port, mode)); 1579 1580 *mode |= (SOC_PM_PAUSE | SOC_PM_PAUSE_ASYMM | SOC_PM_GMII | SOC_PM_SGMII); 1581 1582 SOC_IF_ERROR_RETURN 1583 (READ_PHYFEGE_MII_ESRr(unit, pc, &mii_esr)); 1584 1585 1586 1587 if (mii_esr & MII_ESR_1000_T_FD) *mode |= SOC_PM_1000MB_FD; 1588 if (mii_esr & MII_ESR_1000_T_HD) *mode |= SOC_PM_1000MB_HD; 1589 if (mii_esr & MII_ESR_1000_X_FD) *mode |= SOC_PM_1000MB_FD; 1590 if (mii_esr & MII_ESR_1000_X_HD) *mode |= SOC_PM_1000MB_HD; 1591 1592 return(SOC_E_NONE); 1593 } 1594 1595 /* 1596 * Function: 1597 * phy_fe_ge_medium_get 1598 * Description: 1599 * Get the currently chosen medium for the dual-medium PHY 1600 * Parameters: 1601 * unit -- Device number 1602 * port -- Port number 1603 * medium -- (Out) One of 1604 * SOC_PORT_MEDIUM_NONE 1605 * SOC_PORT_MEDIUM_COPPER 1606 * SOC_PORT_MEDIUM_FIBER 1607 * 1608 * Return value: 1609 * SOC_E_NONE 1610 * SOC_E_PARAM 1611 * SOC_E_UNAVAIL 1612 */ 1613 int 1614 phy_fe_ge_medium_get(int unit, soc_port_t port, 1615 soc_port_medium_t *medium) 1616 { 1617 int rv; 1618 soc_pbmp_t pbmp_100fx; 1619 1620 COMPILER_REFERENCE(unit); 1621 COMPILER_REFERENCE(port); 1622 1623 if (medium != NULL) { 1624 /* 1625 * Get 100-FX ports from config.bcm. 1626 */ 1627 pbmp_100fx = soc_property_get_pbmp(unit, spn_PBMP_FE_100FX, 0); 1628 if (SOC_PBMP_MEMBER(pbmp_100fx, port)) { 1629 *medium = SOC_PORT_MEDIUM_FIBER; 1630 return SOC_E_NONE; 1631 } 1632 1633 *medium = SOC_PORT_MEDIUM_COPPER; 1634 rv = SOC_E_NONE; 1635 } else { 1636 rv = SOC_E_PARAM; 1637 } 1638 1639 return (rv); 1640 } 1641 1642 /* 1643 * Function: 1644 * phy_fe_ge_ability_advert_set 1645 * Purpose: 1646 * Set the current advertisement for auto-negotiation. 1647 * Parameters: 1648 * unit - StrataSwitch unit #. 1649 * port - StrataSwitch port #. 1650 * ability - Port ability indicating supported options/speeds. 1651 * Returns: 1652 * SOC_E_XXX 1653 */ 1654 1655 int 1656 phy_fe_ge_ability_advert_set(int unit, soc_port_t port, soc_port_ability_t *ability) 1657 { 1658 phy_ctrl_t *pc; 1659 uint16 mii_adv, mii_gb_ctrl; 1660 1661 if (NULL == ability) { 1662 return (SOC_E_PARAM); 1663 } 1664 1665 pc = EXT_PHY_SW_STATE(unit, port); 1666 1667 mii_adv = MII_ANA_ASF_802_3; 1668 1669 if (ability->speed_half_duplex & SOC_PA_SPEED_10MB) { 1670 mii_adv |= MII_ANA_HD_10; 1671 } 1672 if (ability->speed_half_duplex & SOC_PA_SPEED_100MB) { 1673 mii_adv |= MII_ANA_HD_100; 1674 } 1675 if (ability->speed_full_duplex & SOC_PA_SPEED_10MB) { 1676 mii_adv |= MII_ANA_FD_10; 1677 } 1678 if (ability->speed_full_duplex & SOC_PA_SPEED_100MB) { 1679 mii_adv |= MII_ANA_FD_100; 1680 } 1681 1682 switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) { 1683 case SOC_PA_PAUSE_TX: 1684 mii_adv |= MII_ANA_ASYM_PAUSE; 1685 break; 1686 case SOC_PA_PAUSE_RX: 1687 mii_adv |= MII_ANA_PAUSE | MII_ANA_ASYM_PAUSE; 1688 break; 1689 case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX: 1690 mii_adv |= MII_ANA_PAUSE; 1691 break; 1692 } 1693 1694 SOC_IF_ERROR_RETURN 1695 (MODIFY_PHYFEGE_MII_ANAr(unit, pc, mii_adv, 1696 MII_ANA_PAUSE|MII_ANA_ASYM_PAUSE|MII_ANA_FD_100|MII_ANA_HD_100| 1697 MII_ANA_FD_10|MII_ANA_HD_10|MII_ANA_ASF_802_3)); 1698 1699 if (IS_GE_PORT(unit, port)) { 1700 SOC_IF_ERROR_RETURN 1701 (READ_PHYFEGE_MII_GB_CTRLr(unit, pc, &mii_gb_ctrl)); 1702 1703 mii_gb_ctrl &= ~(MII_GB_CTRL_ADV_1000HD | MII_GB_CTRL_ADV_1000FD); 1704 mii_gb_ctrl |= MII_GB_CTRL_PT; /* repeater / switch port */ 1705 1706 if (ability->speed_half_duplex & SOC_PA_SPEED_1000MB) { 1707 mii_gb_ctrl |= MII_GB_CTRL_ADV_1000HD; 1708 } 1709 if (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) { 1710 mii_gb_ctrl |= MII_GB_CTRL_ADV_1000FD; 1711 } 1712 SOC_IF_ERROR_RETURN 1713 (MODIFY_PHYFEGE_MII_GB_CTRLr(unit, pc, mii_gb_ctrl, 1714 MII_GB_CTRL_PT|MII_GB_CTRL_ADV_1000FD|MII_GB_CTRL_ADV_1000HD)); 1715 } 1716 1717 return SOC_E_NONE; 1718 1719 } 1720 1721 /* 1722 * Function: 1723 * phy_fe_ge_ability_advert_get 1724 * Purpose: 1725 * Get the current advertisement for auto-negotiation. 1726 * Parameters: 1727 * unit - StrataSwitch unit #. 1728 * port - StrataSwitch port #. 1729 * ability - Port ability indicating supported options/speeds. 1730 * Returns: 1731 * SOC_E_XXX 1732 * Notes: 1733 * The advertisement is retrieved for the ACTIVE medium. 1734 * No synchronization performed at this level. 1735 */ 1736 1737 int 1738 phy_fe_ge_ability_advert_get(int unit, soc_port_t port, soc_port_ability_t *ability) 1739 { 1740 phy_ctrl_t *pc; 1741 uint16 mii_ana; 1742 uint16 mii_gb_ctrl; 1743 1744 if (NULL == ability) { 1745 return (SOC_E_PARAM); 1746 } 1747 1748 pc = EXT_PHY_SW_STATE(unit, port); 1749 1750 SOC_IF_ERROR_RETURN 1751 (READ_PHYFEGE_MII_ANAr(unit, pc, &mii_ana)); 1752 1753 sal_memset(ability, 0, sizeof(*ability)); 1754 1755 if (mii_ana & MII_ANA_HD_10) { 1756 ability->speed_half_duplex |= SOC_PA_SPEED_10MB; 1757 } 1758 if (mii_ana & MII_ANA_HD_100) { 1759 ability->speed_half_duplex |= SOC_PA_SPEED_100MB; 1760 } 1761 if (mii_ana & MII_ANA_FD_10) { 1762 ability->speed_full_duplex |= SOC_PA_SPEED_10MB; 1763 } 1764 if (mii_ana & MII_ANA_FD_100) { 1765 ability->speed_full_duplex |= SOC_PA_SPEED_100MB; 1766 } 1767 1768 switch (mii_ana & (MII_ANA_PAUSE | MII_ANA_ASYM_PAUSE)) { 1769 case MII_ANA_PAUSE: 1770 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 1771 break; 1772 case MII_ANA_ASYM_PAUSE: 1773 ability->pause = SOC_PA_PAUSE_TX; 1774 break; 1775 case MII_ANA_PAUSE | MII_ANA_ASYM_PAUSE: 1776 ability->pause = SOC_PA_PAUSE_RX; 1777 break; 1778 } 1779 1780 /* GE Specific values */ 1781 if (IS_GE_PORT(unit, port)) { 1782 SOC_IF_ERROR_RETURN 1783 (READ_PHYFEGE_MII_GB_CTRLr(unit, pc, &mii_gb_ctrl)); 1784 1785 if (mii_gb_ctrl & MII_GB_CTRL_ADV_1000HD) { 1786 ability->speed_half_duplex |= SOC_PA_SPEED_1000MB; 1787 } 1788 if (mii_gb_ctrl & MII_GB_CTRL_ADV_1000FD) { 1789 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 1790 } 1791 } 1792 1793 return SOC_E_NONE; 1794 } 1795 1796 /* 1797 * Function: 1798 * phy_fe_ge_ability_remote_get 1799 * Purpose: 1800 * Get partners current advertisement for auto-negotiation. 1801 * Parameters: 1802 * unit - StrataSwitch unit #. 1803 * port - StrataSwitch port #. 1804 * ability - Port ability indicating supported options/speeds. 1805 * Returns: 1806 * SOC_E_XXX 1807 * Notes: 1808 * The remote advertisement is retrieved for the ACTIVE medium. 1809 * No synchronization performed at this level. If Autonegotiation is 1810 * disabled or in progress, this routine will return an error. 1811 */ 1812 1813 int 1814 phy_fe_ge_ability_remote_get(int unit, soc_port_t port, soc_port_ability_t *ability) 1815 { 1816 phy_ctrl_t *pc; 1817 uint16 mii_stat; 1818 uint16 mii_anp; 1819 uint16 mii_gb_stat; 1820 1821 if (NULL == ability) { 1822 return (SOC_E_PARAM); 1823 } 1824 1825 pc = EXT_PHY_SW_STATE(unit, port); 1826 1827 SOC_IF_ERROR_RETURN 1828 (READ_PHYFEGE_MII_STATr(unit, pc, &mii_stat)); 1829 1830 sal_memset(ability, 0, sizeof(*ability)); 1831 1832 if ((mii_stat & (MII_STAT_AN_DONE | MII_STAT_LA)) 1833 == (MII_STAT_AN_DONE | MII_STAT_LA)) { 1834 /* Decode remote advertisement only when link is up and autoneg is 1835 * completed. 1836 */ 1837 SOC_IF_ERROR_RETURN 1838 (READ_PHYFEGE_MII_ANPr(unit, pc, &mii_anp)); 1839 1840 if (mii_anp & MII_ANA_HD_10) { 1841 ability->speed_half_duplex |= SOC_PA_SPEED_10MB; 1842 } 1843 if (mii_anp & MII_ANA_HD_100) { 1844 ability->speed_half_duplex |= SOC_PA_SPEED_100MB; 1845 } 1846 if (mii_anp & MII_ANA_FD_10) { 1847 ability->speed_full_duplex |= SOC_PA_SPEED_10MB; 1848 } 1849 if (mii_anp & MII_ANA_FD_100) { 1850 ability->speed_full_duplex |= SOC_PA_SPEED_100MB; 1851 } 1852 1853 switch (mii_anp & (MII_ANA_PAUSE | MII_ANA_ASYM_PAUSE)) { 1854 case MII_ANA_PAUSE: 1855 ability->pause = SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX; 1856 break; 1857 case MII_ANA_ASYM_PAUSE: 1858 ability->pause = SOC_PA_PAUSE_TX; 1859 break; 1860 case MII_ANA_PAUSE | MII_ANA_ASYM_PAUSE: 1861 ability->pause = SOC_PA_PAUSE_RX; 1862 break; 1863 } 1864 1865 /* GE Specific values */ 1866 if (IS_GE_PORT(unit, port)) { 1867 SOC_IF_ERROR_RETURN 1868 (READ_PHYFEGE_MII_GB_STATr(unit, pc, &mii_gb_stat)); 1869 1870 if (mii_gb_stat & MII_GB_STAT_LP_1000HD) { 1871 ability->speed_half_duplex |= SOC_PA_SPEED_1000MB; 1872 } 1873 if (mii_gb_stat & MII_GB_STAT_LP_1000FD) { 1874 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 1875 } 1876 } 1877 1878 } else { 1879 /* Simply return local abilities */ 1880 SOC_IF_ERROR_RETURN 1881 (phy_fe_ge_ability_advert_get(unit, port, ability)); 1882 } 1883 LOG_INFO(BSL_LS_SOC_PHY, 1884 (BSL_META_U(unit, 1885 "phy_fe_ge_ability_remote_get:unit=%d p=%d pause=%08x sp=%08x\n"), 1886 unit, port, ability->pause, ability->speed_full_duplex)); 1887 1888 return SOC_E_NONE; 1889 } 1890 1891 /* 1892 * Function: 1893 * phy_fe_cable_diag 1894 * Purpose: 1895 * Run 5248 cable diagnostics 1896 * Parameters: 1897 * unit - device number 1898 * port - port number 1899 * status - (OUT) cable diagnotic status structure 1900 * Returns: 1901 * SOC_E_XXX 1902 */ 1903 1904 int 1905 phy_fe_cable_diag(int unit, soc_port_t port, 1906 soc_port_cable_diag_t *status) 1907 { 1908 1909 return SOC_E_UNAVAIL; 1910 } 1911 1912 /* 1913 * Function: 1914 * phy_ge_reg_read 1915 * Purpose: 1916 * Routine to read PHY register 1917 * Parameters: 1918 * uint - BCM unit number 1919 * pc - PHY state 1920 * flags - Flags which specify the register type 1921 * phy_reg_addr - Encoded register address 1922 * phy_data - (OUT) Value read from PHY register 1923 * Note: 1924 * This register read function is not thread safe. Higher level 1925 * function that calls this function must obtain a per port lock 1926 * to avoid overriding register page mapping between threads. 1927 */ 1928 int 1929 phy_ge_reg_read(int unit, soc_port_t port, uint32 flags, 1930 uint32 phy_reg_addr, uint32 *phy_data) 1931 { 1932 uint32 reg_flags; 1933 uint16 reg_bank; 1934 uint8 reg_addr; 1935 uint16 data; /* Temporary holder for phy_data */ 1936 phy_ctrl_t *pc; /* PHY software state */ 1937 1938 COMPILER_REFERENCE(flags); 1939 1940 pc = EXT_PHY_SW_STATE(unit, port); 1941 1942 reg_flags = SOC_PHY_REG_FLAGS(phy_reg_addr); 1943 reg_bank = SOC_PHY_REG_BANK(phy_reg_addr); 1944 reg_addr = SOC_PHY_REG_ADDR(phy_reg_addr); 1945 1946 SOC_IF_ERROR_RETURN 1947 (phy_reg_ge_read(unit, pc, reg_flags, reg_bank, reg_addr, &data)); 1948 1949 *phy_data = data; 1950 1951 return SOC_E_NONE; 1952 } 1953 1954 /* 1955 * Function: 1956 * phy_ge_reg_write 1957 * Purpose: 1958 * Routine to write PHY register 1959 * Parameters: 1960 * uint - BCM unit number 1961 * pc - PHY state 1962 * flags - Flags which specify the register type 1963 * phy_reg_addr - Encoded register address 1964 * phy_data - Value write to PHY register 1965 * Note: 1966 * This register read function is not thread safe. Higher level 1967 * function that calls this function must obtain a per port lock 1968 * to avoid overriding register page mapping between threads. 1969 */ 1970 int 1971 phy_ge_reg_write(int unit, soc_port_t port, uint32 flags, 1972 uint32 phy_reg_addr, uint32 phy_data) 1973 { 1974 uint32 reg_flags; 1975 uint16 reg_bank; 1976 uint8 reg_addr; 1977 uint16 data; /* Temporary holder for phy_data */ 1978 phy_ctrl_t *pc; /* PHY software state */ 1979 1980 COMPILER_REFERENCE(flags); 1981 1982 1983 pc = EXT_PHY_SW_STATE(unit, port); 1984 data = (uint16) (phy_data & 0x0000FFFF); 1985 1986 reg_flags = SOC_PHY_REG_FLAGS(phy_reg_addr); 1987 reg_bank = SOC_PHY_REG_BANK(phy_reg_addr); 1988 reg_addr = SOC_PHY_REG_ADDR(phy_reg_addr); 1989 1990 return phy_reg_ge_write(unit, pc, reg_flags, reg_bank, reg_addr, data); 1991 } 1992 1993 /* 1994 * Function: 1995 * phy_ge_reg_modify 1996 * Purpose: 1997 * Routine to write PHY register 1998 * Parameters: 1999 * uint - BCM unit number 2000 * pc - PHY state 2001 * flags - Flags which specify the register type 2002 * phy_reg_addr - Encoded register address 2003 * phy_mo_data - New value for the bits specified in phy_mo_mask 2004 * phy_mo_mask - Bit mask to modify 2005 * Note: 2006 * This register read function is not thread safe. Higher level 2007 * function that calls this function must obtain a per port lock 2008 * to avoid overriding register page mapping between threads. 2009 */ 2010 int 2011 phy_ge_reg_modify(int unit, soc_port_t port, uint32 flags, 2012 uint32 phy_reg_addr, uint32 phy_data, 2013 uint32 phy_data_mask) 2014 { 2015 uint32 reg_flags; 2016 uint16 reg_bank; 2017 uint8 reg_addr; 2018 uint16 data; /* Temporary holder for phy_data */ 2019 uint16 mask; /* Temporary holder for phy_data_mask */ 2020 phy_ctrl_t *pc; /* PHY software state */ 2021 2022 COMPILER_REFERENCE(flags); 2023 2024 pc = EXT_PHY_SW_STATE(unit, port); 2025 data = (uint16) (phy_data & 0x0000FFFF); 2026 mask = (uint16) (phy_data_mask & 0x0000FFFF); 2027 2028 reg_flags = SOC_PHY_REG_FLAGS(phy_reg_addr); 2029 reg_bank = SOC_PHY_REG_BANK(phy_reg_addr); 2030 reg_addr = SOC_PHY_REG_ADDR(phy_reg_addr); 2031 2032 return phy_reg_ge_modify(unit, pc, reg_flags, reg_bank, 2033 reg_addr, data, mask); 2034 } 2035