phy84334.c (88453B)
1 /* 2 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 3 * 4 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 5 */ 6 7 /* 8 * File: phy84334.c 9 * Purpose: PHY driver for BCM84334 (MACSec) 10 * 11 * References: 12 * 13 * +----------+ +---------------------------+ 14 * | XAUI / | | +->Copper |<--> Magnetic 15 * | SGMII |<->| XAUI/SGMII-+ | 16 * | (SerDes) | | | | 17 * | | | +->SGMII/ |<--> (PHY)SFP (10/100/1000) 18 * +----------+ | 1000BASE-X/ |<--> 1000BASE-X SFP 19 * Switch | XAUI | 20 * | | 21 * | | 22 * +---------------------------+ 23 * 84334 24 * 25 * Notes: 26 */ 27 28 29 #include <sal/types.h> 30 #include <sal/core/spl.h> 31 #include <shared/bsl.h> 32 #include <soc/drv.h> 33 #include <soc/debug.h> 34 #include <soc/error.h> 35 #include <soc/phyreg.h> 36 37 #include <soc/phy.h> 38 #include <soc/phy/phyctrl.h> 39 #include <soc/phy/drv.h> 40 41 #include "phynull.h" 42 #include "phyxehg.h" 43 44 #include "phydefs.h" /* Must include before other phy related includes */ 45 46 47 48 #ifdef INCLUDE_MACSEC 49 #if defined(INCLUDE_PHY_84334) 50 #include "phyconfig.h" /* Must be the first phy include after phydefs.h */ 51 #include "phyident.h" 52 #include "phyreg.h" 53 #include "phyfege.h" 54 #include "phy84334.h" 55 #include <soc/macsecphy.h> 56 57 #define AUTO_MDIX_WHEN_AN_DIS 0 /* Non-standard-compliant option */ 58 #define DISABLE_CLK125 0 /* Disable if unused to reduce */ 59 /* EMI emissions */ 60 61 /* Move flag to mac_ctrl.c */ 62 #define MAC_CTRL_FLAG_MACSEC_XMAC_V2 (1<<1) 63 64 /* typedefs */ 65 typedef struct { 66 int flags; 67 soc_timeout_t to; 68 uint8 *firmware; 69 int firmware_len; 70 unsigned int iter; 71 int phy_ext_boot; 72 int fiber_preferred; 73 } PHY8433_PRIV_t; 74 75 #define FLAGS(_pc) (((PHY8433_PRIV_t *)((_pc) + 1))->flags) 76 #define ITER(_pc) (((PHY8433_PRIV_t *)((_pc) + 1))->iter) 77 #define PHY_EXT_BOOT(_pc) (((PHY8433_PRIV_t *)((_pc) + 1))->phy_ext_boot) 78 #define FIBER_PREF(_pc) (((PHY8433_PRIV_t *)((_pc) + 1))->fiber_preferred) 79 #define TO(_pc) (((PHY8433_PRIV_t *)((_pc) + 1))->to) 80 #define FIRMWARE(_pc) (((PHY8433_PRIV_t *)((_pc) + 1))->firmware) 81 #define FIRMWARE_LEN(_pc) (((PHY8433_PRIV_t *)((_pc) + 1))->firmware_len) 82 83 extern buint8_t bcm84334_firmware[]; 84 extern buint32_t bcm84334_firmware_length; 85 86 #define BMACSEC_PHY84334_MAP_UCODE_OFFSET(x)\ 87 ((x) == PHYCTRL_UCODE_BCST_SETUP ? BMACSEC_PHY84334_UCODE_BCST_SETUP :\ 88 ((x) == PHYCTRL_UCODE_BCST_uC_SETUP ? BMACSEC_PHY84334_UCODE_BCST_uC_SETUP:\ 89 ((x) == PHYCTRL_UCODE_BCST_ENABLE ? BMACSEC_PHY84334_UCODE_BCST_ENABLE :\ 90 ((x) == PHYCTRL_UCODE_BCST_LOAD ? BMACSEC_PHY84334_UCODE_BCST_LOAD :\ 91 BMACSEC_PHY84334_UCODE_BCST_END )))) 92 93 94 95 96 97 static bmacsec_error_t error_tbl[] = { 98 SOC_E_NONE, 99 SOC_E_INTERNAL, 100 SOC_E_MEMORY, 101 SOC_E_PARAM, 102 SOC_E_EMPTY, 103 SOC_E_FULL, 104 SOC_E_NOT_FOUND, 105 SOC_E_EXISTS, 106 SOC_E_TIMEOUT, 107 SOC_E_FAIL, 108 SOC_E_DISABLED, 109 SOC_E_BADID, 110 SOC_E_RESOURCE, 111 SOC_E_CONFIG, 112 SOC_E_UNAVAIL, 113 SOC_E_INIT, 114 SOC_E_PORT, 115 }; 116 /* 117 * Convert BMACSEC return codes to SOC return code. 118 */ 119 #define SOC_ERROR(e) error_tbl[(-e)] 120 121 #define PHY84334_REG_READ(_unit, _phy_ctrl, _addr, _val) \ 122 READ_PHY_REG((_unit), (_phy_ctrl), (_addr), (_val)) 123 124 #define READ_PHY84334_PMA_PMD_REG(_unit, _phy_ctrl, _reg,_val) \ 125 PHY84334_REG_READ((_unit), (_phy_ctrl), \ 126 SOC_PHY_CLAUSE45_ADDR(1, (_reg)), (_val)) 127 128 #define MACSEC_READ_PHY_REG(_unit, _pc, _mdio, _reg, _value) \ 129 ((_pc->read)((_unit), (_mdio), (_reg), (_value))) 130 #define MACSEC_WRITE_PHY_REG(_unit, _pc, _mdio, _reg, _value) \ 131 ((_pc->write)((_unit), (_mdio), (_reg), (_value))) 132 133 134 STATIC int _phy_84334_medium_change(int unit, soc_port_t port, 135 int force_update, soc_port_medium_t force_medium); 136 STATIC int phy_84334_duplex_set(int unit, soc_port_t port, int duplex); 137 STATIC int phy_84334_speed_set(int unit, soc_port_t port, int speed); 138 STATIC int phy_84334_master_set(int unit, soc_port_t port, int master); 139 STATIC int phy_84334_autoneg_set(int unit, soc_port_t port, int autoneg); 140 STATIC int phy_84334_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode); 141 STATIC int phy_84334_speed_get(int unit, soc_port_t port, int *speed); 142 STATIC int phy_84334_ability_advert_set(int unit, soc_port_t port, soc_port_ability_t *ability); 143 STATIC int phy_84334_ability_local_get(int unit, soc_port_t port,soc_port_ability_t *ability); 144 STATIC int phy_84334_linkup(int unit, soc_port_t port); 145 int phy_84334_reset(int unit, soc_port_t port, void *user_arg); 146 147 148 149 /*********************************************************************** 150 * 151 * HELPER FUNCTIONS 152 */ 153 /* 154 * Function: 155 * _phy_84334_medium_check 156 * Purpose: 157 * Determine if chip should operate in copper or fiber mode. 158 * Parameters: 159 * unit - StrataSwitch unit #. 160 * port - StrataSwitch port #. 161 * medium - (OUT) SOC_PORT_MEDIUM_XXX 162 * Returns: 163 * SOC_E_XXX 164 */ 165 STATIC int 166 _phy_84334_medium_check(int unit, soc_port_t port, int *medium) 167 { 168 phy_ctrl_t *pc = EXT_PHY_SW_STATE(unit, port); 169 int rv; 170 bmacsec_dev_addr_t phy_dev_addr; 171 bmacsec_phy84334_port_medium_t bmacsec_port_medium; 172 173 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 174 175 rv = bmacsec_phy84334_medium_check(phy_dev_addr, &bmacsec_port_medium); 176 if(!BMACSEC_E_SUCCESS(rv)) { 177 return SOC_E_FAIL; 178 } 179 180 *medium = SOC_PORT_MEDIUM_COPPER; 181 182 if (pc->automedium) { 183 if (pc->fiber.preferred) { 184 if (bmacsec_port_medium == BMACSEC_PHY_MEDIUM_COPPER) { 185 /* Only Copper is lined up */ 186 *medium = SOC_PORT_MEDIUM_COPPER; 187 } else { 188 *medium = SOC_PORT_MEDIUM_FIBER; 189 } 190 } else { 191 if (bmacsec_port_medium == BMACSEC_PHY_MEDIUM_FIBER) { 192 /* Only Fiber is linked up */ 193 *medium = SOC_PORT_MEDIUM_FIBER; 194 } else { 195 *medium = SOC_PORT_MEDIUM_COPPER; 196 } 197 } 198 } else { 199 *medium = pc->fiber.preferred ? SOC_PORT_MEDIUM_FIBER: 200 SOC_PORT_MEDIUM_COPPER; 201 } 202 203 LOG_VERBOSE(BSL_LS_SOC_PHY, 204 (BSL_META_U(unit, 205 "_phy_84334_medium_check: " 206 "u=%d p=%d fiber_pref=%d fiber=%d\n"), 207 unit, port, pc->fiber.preferred, 208 (*medium == SOC_PORT_MEDIUM_FIBER) ? 1 : 0)); 209 210 return SOC_E_NONE; 211 } 212 213 /* 214 * Function: 215 * phy_84334_medium_status 216 * Purpose: 217 * Indicate the current active medium 218 * Parameters: 219 * unit - StrataSwitch unit #. 220 * port - StrataSwitch port #. 221 * medium - (OUT) One of: 222 * SOC_PORT_MEDIUM_COPPER 223 * SOC_PORT_MEDIUM_FIBER 224 * Returns: 225 * SOC_E_NONE 226 */ 227 228 STATIC int 229 phy_84334_medium_status(int unit, soc_port_t port, soc_port_medium_t *medium) 230 { 231 if (PHY_COPPER_MODE(unit, port)) { 232 *medium = SOC_PORT_MEDIUM_COPPER; 233 } else { 234 *medium = SOC_PORT_MEDIUM_FIBER; 235 } 236 return SOC_E_NONE; 237 } 238 239 /* 240 * Function: 241 * _phy_84334_medium_config_update 242 * Purpose: 243 * Update the PHY with config parameters 244 * Parameters: 245 * unit - StrataSwitch unit #. 246 * port - StrataSwitch port #. 247 * cfg - Config structure. 248 * Returns: 249 * SOC_E_XXX 250 */ 251 252 STATIC int 253 _phy_84334_medium_config_update(int unit, soc_port_t port, 254 soc_phy_config_t *cfg) 255 { 256 SOC_IF_ERROR_RETURN 257 (phy_84334_speed_set(unit, port, cfg->force_speed)); 258 SOC_IF_ERROR_RETURN 259 (phy_84334_duplex_set(unit, port, cfg->force_duplex)); 260 SOC_IF_ERROR_RETURN 261 (phy_84334_master_set(unit, port, cfg->master)); 262 SOC_IF_ERROR_RETURN 263 (phy_84334_ability_advert_set(unit, port, &cfg->advert_ability)); 264 SOC_IF_ERROR_RETURN 265 (phy_84334_autoneg_set(unit, port, cfg->autoneg_enable)); 266 SOC_IF_ERROR_RETURN 267 (phy_84334_mdix_set(unit, port, cfg->mdix)); 268 269 return SOC_E_NONE; 270 } 271 272 /*********************************************************************** 273 * 274 * PHY84334 DRIVER ROUTINES 275 */ 276 277 /* 278 * Function: 279 * phy_84334_medium_config_set 280 * Purpose: 281 * Set the operating parameters that are automatically selected 282 * when medium switches type. 283 * Parameters: 284 * unit - StrataSwitch unit # 285 * port - Port number 286 * medium - SOC_PORT_MEDIUM_COPPER/FIBER 287 * cfg - Operating parameters 288 * Returns: 289 * SOC_E_XXX 290 */ 291 292 STATIC int 293 phy_84334_medium_config_set(int unit, soc_port_t port, 294 soc_port_medium_t medium, 295 soc_phy_config_t *cfg) 296 { 297 phy_ctrl_t *pc; 298 soc_phy_config_t *active_medium; /* Currently active medium */ 299 soc_phy_config_t *change_medium; /* Requested medium */ 300 soc_phy_config_t *other_medium; /* The other medium */ 301 int medium_update; 302 int rv; 303 bmacsec_dev_addr_t phy_dev_addr; 304 305 if (NULL == cfg) { 306 return SOC_E_PARAM; 307 } 308 309 pc = EXT_PHY_SW_STATE(unit, port); 310 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 311 medium_update = FALSE; 312 313 switch (medium) { 314 case SOC_PORT_MEDIUM_COPPER: 315 if (!pc->automedium && !PHY_COPPER_MODE(unit, port)) { 316 return SOC_E_UNAVAIL; 317 } 318 change_medium = &pc->copper; 319 other_medium = &pc->fiber; 320 break; 321 case SOC_PORT_MEDIUM_FIBER: 322 if (!pc->automedium && !PHY_FIBER_MODE(unit, port)) { 323 return SOC_E_UNAVAIL; 324 } 325 change_medium = &pc->fiber; 326 other_medium = &pc->copper; 327 break; 328 default: 329 return SOC_E_PARAM; 330 } 331 332 /* 333 * Changes take effect immediately if the target medium is active or 334 * the preferred medium changes. 335 */ 336 if (change_medium->enable != cfg->enable) { 337 medium_update = TRUE; 338 } 339 if (change_medium->preferred != cfg->preferred) { 340 /* Make sure that only one medium is preferred */ 341 other_medium->preferred = !cfg->preferred; 342 medium_update = TRUE; 343 } 344 345 sal_memcpy(change_medium, cfg, sizeof(*change_medium)); 346 347 rv = bmacsec_phy84334_port_priority_set(phy_dev_addr, pc->fiber.preferred ? BMACSEC_PHY_MEDIUM_FIBER : BMACSEC_PHY_MEDIUM_COPPER); 348 349 if(!BMACSEC_E_SUCCESS(rv)) { 350 return SOC_E_FAIL; 351 } 352 353 if (medium_update) { 354 /* The new configuration may cause medium change. Check 355 * and update medium. 356 */ 357 SOC_IF_ERROR_RETURN 358 (_phy_84334_medium_change(unit, port, TRUE, medium)); 359 } else { 360 active_medium = (PHY_COPPER_MODE(unit, port)) ? 361 &pc->copper : &pc->fiber; 362 if (active_medium == change_medium) { 363 /* If the medium to update is active, update the configuration */ 364 SOC_IF_ERROR_RETURN 365 (_phy_84334_medium_config_update(unit, port, change_medium)); 366 } 367 } 368 return SOC_E_NONE; 369 } 370 371 /* 372 * Function: 373 * phy_84334_medium_config_get 374 * Purpose: 375 * Get the operating parameters that are automatically selected 376 * when medium switches type. 377 * Parameters: 378 * unit - StrataSwitch unit # 379 * port - Port number 380 * medium - SOC_PORT_MEDIUM_COPPER/FIBER 381 * cfg - (OUT) Operating parameters 382 * Returns: 383 * SOC_E_XXX 384 */ 385 386 STATIC int 387 phy_84334_medium_config_get(int unit, soc_port_t port, 388 soc_port_medium_t medium, 389 soc_phy_config_t *cfg) 390 { 391 int rv; 392 phy_ctrl_t *pc; 393 394 pc = EXT_PHY_SW_STATE(unit, port); 395 rv = SOC_E_NONE; 396 397 switch (medium) { 398 case SOC_PORT_MEDIUM_COPPER: 399 if (pc->automedium || PHY_COPPER_MODE(unit, port)) { 400 sal_memcpy(cfg, &pc->copper, sizeof (*cfg)); 401 } else { 402 rv = SOC_E_UNAVAIL; 403 } 404 break; 405 case SOC_PORT_MEDIUM_FIBER: 406 if (pc->automedium || PHY_FIBER_MODE(unit, port)) { 407 sal_memcpy(cfg, &pc->fiber, sizeof (*cfg)); 408 } else { 409 rv = SOC_E_UNAVAIL; 410 } 411 break; 412 default: 413 rv = SOC_E_PARAM; 414 break; 415 } 416 417 return rv; 418 } 419 420 #if 0 421 /* 422 * Function: 423 * _phy_84334_no_reset_setup 424 * Purpose: 425 * Setup the operating parameters of the PHY without resetting PHY 426 * Parameters: 427 * unit - StrataSwitch unit # 428 * port - Port number 429 * Returns: 430 * SOC_E_XXX 431 */ 432 433 STATIC int 434 _phy_84334_no_reset_setup(int unit, soc_port_t port, int fiber) 435 { 436 phy_ctrl_t *int_pc; 437 phy_ctrl_t *pc; 438 bmacsec_dev_addr_t phy_dev_addr; 439 int rv = SOC_E_NONE; 440 int fiber_capable = 0; 441 442 LOG_INFO(BSL_LS_SOC_PHY, 443 (BSL_META_U(unit, 444 "_phy_84334_reset_setup: u=%d p=%d medium=%s\n"), 445 unit, port, 446 PHY_COPPER_MODE(unit, port) ? "COPPER" : "FIBER")); 447 448 pc = EXT_PHY_SW_STATE(unit, port); 449 int_pc = INT_PHY_SW_STATE(unit, port); 450 451 if (NULL != int_pc) { 452 SOC_IF_ERROR_RETURN 453 (PHY_INIT(int_pc->pd, unit, port)); 454 455 if (PHY_FIBER_MODE(unit, port)) { 456 /* Interface to MAC or internal SerDes is always SGMII mode. 457 * Typical internal SerDes driver set the interface to 1000BASE-X, 458 * if the media is fiber. Therefore, we need to force the interface 459 * of internal SerDes Driver to SGMII. */ 460 SOC_IF_ERROR_RETURN 461 (PHY_NOTIFY(int_pc->pd, unit, port, phyEventInterface, 462 SOC_PORT_IF_SGMII)); 463 } 464 465 if (PHY_COPPER_MODE(unit, port) && 466 !PHY_SGMII_AUTONEG_MODE(unit, port)) { 467 /* Make sure internal SerDes is in power down state 468 * until the MAC is ready. */ 469 SOC_IF_ERROR_RETURN 470 (PHY_NOTIFY(int_pc->pd, unit, port, 471 phyEventStop, PHY_STOP_COPPER)); 472 } 473 } 474 475 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 476 rv = bmacsec_phy84334_init(phy_dev_addr, 0, 477 pc->automedium, 478 fiber, 479 pc->fiber_detect, 480 pc->macsec_enable, 481 &fiber_capable, 1, NULL); 482 if (rv != BMACSEC_E_NONE) { 483 return SOC_E_FAIL; 484 } 485 return SOC_E_NONE; 486 } 487 #endif 488 489 /* 490 * Function: 491 * phy_84334_init 492 * Purpose: 493 * Init function for 84334 PHY. 494 * Parameters: 495 * unit - StrataSwitch unit #. 496 * port - StrataSwitch port #. 497 * Returns: 498 * SOC_E_NONE 499 */ 500 501 STATIC int 502 phy_84334_init(int unit, soc_port_t port) 503 { 504 phy_ctrl_t *pc; 505 int fiber_capable, rv; 506 int fiber_preferred; 507 bmacsec_dev_addr_t phy_dev_addr; 508 int mmi_mdio_addr, port_index, macsec_enable, phy_ext_boot; 509 uint32 phy_mdi_pair_map; 510 int status; 511 uint32 mac_config_flag = 0; 512 uint16 temp1, temp2, saved_phy_addr; 513 514 LOG_INFO(BSL_LS_SOC_PHY, 515 (BSL_META_U(unit, 516 "phy_84334_init: u=%d p=%d\n"), 517 unit, port)); 518 519 pc = EXT_PHY_SW_STATE(unit, port); 520 521 if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT || 522 PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1 ) { 523 524 PHY_FLAGS_SET(unit, port, PHY_FLAGS_C45); 525 rv = BMACSEC_E_NONE; 526 527 pc->interface = SOC_PORT_IF_XGMII; 528 529 530 mmi_mdio_addr = soc_property_port_get(unit, port, spn_MACSEC_DEV_ADDR, -1); 531 phy_ext_boot = soc_property_port_get(unit, port, 532 spn_PHY_EXT_ROM_BOOT, 1); 533 PHY_EXT_BOOT(pc) = phy_ext_boot; 534 535 if (mmi_mdio_addr == -1) { 536 LOG_WARN(BSL_LS_SOC_PHY, 537 (BSL_META_U(unit, 538 "phy_84334_init: " 539 "MACSEC_DEV_ADDR property " 540 "not configured for u=%d p=%d\n"), unit, port)); 541 return SOC_E_CONFIG; 542 } 543 544 port_index = soc_property_port_get(unit, port, spn_MACSEC_PORT_INDEX, -1); 545 if (port_index == -1) { 546 LOG_WARN(BSL_LS_SOC_PHY, 547 (BSL_META_U(unit, 548 "phy_84334_init: " 549 "MACSEC_PORT_INDEX property not configured for " 550 "u=%d p=%d\n"), unit, port)); 551 return SOC_E_CONFIG; 552 } 553 554 pc->macsec_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, mmi_mdio_addr, 1); 555 pc->macsec_dev_port = port_index; 556 557 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 558 559 macsec_enable = soc_property_port_get(unit, port, spn_MACSEC_ENABLE, 0); 560 pc->macsec_enable = macsec_enable; 561 562 switch (PHY_MODEL(pc->phy_id0, pc->phy_id1)) { 563 case PHY_BCM84844_MODEL: 564 case PHY_BCM84846_MODEL: 565 case PHY_BCM84848_MODEL: 566 mac_config_flag |= MAC_CTRL_FLAG_MACSEC_XMAC_V2; 567 break; 568 default: 569 mac_config_flag = 0; 570 break; 571 } 572 573 rv = bmacsec_phy84334_phy_mac_addr_set(phy_dev_addr, pc->macsec_dev_addr, 574 pc->macsec_dev_port, 575 bmacsec_io_mmi1_cl45_10gbt, 576 mac_config_flag ); 577 578 if(rv != BMACSEC_E_NONE) { 579 LOG_WARN(BSL_LS_SOC_PHY, 580 (BSL_META_U(unit, 581 "phy_84334_init: bmacsec_phy_mac_addr_set " 582 "returned error for u=%d p=%d\n"), unit, port)); 583 return SOC_E_FAIL; 584 } 585 586 fiber_capable = 1; 587 588 fiber_preferred = 589 soc_property_port_get(unit, port, spn_PHY_FIBER_PREF, 0); 590 591 FIBER_PREF(pc) = fiber_preferred; 592 593 /* 594 pc->automedium = 595 soc_property_port_get(unit, port, spn_PHY_AUTOMEDIUM, 1); 596 */ 597 pc->automedium = TRUE; 598 599 pc->fiber_detect = 600 soc_property_port_get(unit, port, spn_PHY_FIBER_DETECT, 0); 601 602 LOG_INFO(BSL_LS_SOC_PHY, 603 (BSL_META_U(unit, 604 "phy_84334_init: " 605 "u=%d p=%d type=84334%s automedium=%d fiber_pref=%d detect=%d\n"), 606 unit, port, fiber_capable ? "S" : "", 607 pc->automedium, fiber_preferred, pc->fiber_detect)); 608 609 ITER(pc) = 0 ; 610 soc_timeout_init(&TO(pc), 0, 0); 611 if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) { 612 /* indicate second pass of init is needed */ 613 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS2); 614 } 615 616 #ifdef PHY84334_FIRMWARE_INIT_CHECK 617 /* prepare for download(init check) */ 618 rv = bmacsec_phy84334_init_check(phy_dev_addr, &status); 619 if(rv != BMACSEC_E_NONE) { 620 LOG_WARN(BSL_LS_SOC_PHY, 621 (BSL_META_U(unit, 622 "phy_84334_init: bmacsec_phy84334_init_check " 623 "returned error %d for u=%d p=%d\n"), rv, unit, port)); 624 return SOC_E_FAIL; 625 } 626 627 if (!phy_ext_boot && status != BMACSEC_PHY84334_INIT_UCODE_ACTIVE) { 628 #else 629 if (!phy_ext_boot) { 630 #endif 631 632 /* read ID registers for address zero of the MDIO bus */ 633 saved_phy_addr = pc->phy_id; 634 pc->phy_id &= ~0x1f; 635 636 SOC_IF_ERROR_RETURN 637 (READ_PHY84334_PMA_PMD_REG(unit, pc, 0x2, &temp1)); 638 SOC_IF_ERROR_RETURN 639 (READ_PHY84334_PMA_PMD_REG(unit, pc, 0x3, &temp2)); 640 641 pc->phy_id = saved_phy_addr; 642 643 if(temp1 != 0xffff) { 644 if((temp1 != pc->phy_id0) || (temp2 != pc->phy_id1)) { 645 LOG_WARN(BSL_LS_SOC_PHY, 646 (BSL_META_U(unit, 647 "Another PHY already exist on same broadcast MDIO address. Doing unicast\n"))); 648 649 if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT) { 650 goto skip_bcst; 651 } else { 652 return SOC_E_NONE; 653 } 654 } 655 } 656 657 658 659 /* do MDIO download steps */ 660 ITER(pc) = 1 ; 661 FIRMWARE(pc) = bcm84334_firmware ; 662 FIRMWARE_LEN(pc) = bcm84334_firmware_length ; 663 pc->flags |= PHYCTRL_MDIO_BCST; 664 switch (PHY_MODEL(pc->phy_id0, pc->phy_id1)) { 665 case PHY_BCM84844_MODEL: 666 case PHY_BCM84846_MODEL: 667 case PHY_BCM84848_MODEL: 668 pc->dev_name = "BCM8484X" ; 669 break; 670 default: 671 pc->dev_name = "BCM8433X" ; 672 break; 673 } 674 675 soc_timeout_init(&TO(pc), 60000000, 0); 676 /* indicate second pass of init is needed */ 677 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS2); 678 679 /* reset port */ 680 rv = bmacsec_phy84334_reset_no_wait(phy_dev_addr); 681 if(rv != BMACSEC_E_NONE) { 682 LOG_WARN(BSL_LS_SOC_PHY, 683 (BSL_META_U(unit, 684 "phy_84334_init: bmacsec_phy84334_reset_no_wait " 685 "returned error %d for u=%d p=%d\n"), rv, unit, port)); 686 return SOC_E_FAIL; 687 } 688 689 return SOC_E_NONE; 690 } 691 } 692 693 skip_bcst: 694 695 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 696 phy_ext_boot = PHY_EXT_BOOT(pc); 697 fiber_preferred = FIBER_PREF(pc); 698 699 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) || 700 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 701 702 do { 703 /* Init PHYS and MACs to defaults */ 704 rv = bmacsec_phy84334_init(phy_dev_addr, 1, 705 pc->automedium, 706 fiber_preferred, 707 pc->fiber_detect, 708 pc->macsec_enable, 709 &fiber_capable, phy_ext_boot, 710 ITER(pc) == 0 ? NULL : &ITER(pc) ); 711 712 if (rv != BMACSEC_E_NONE || ITER(pc) == 0) { 713 break; 714 } 715 716 } while (!soc_timeout_check(&TO(pc))); 717 718 if (rv != BMACSEC_E_NONE) { 719 return SOC_E_FAIL; 720 } 721 722 if (ITER(pc) != 0) { 723 return SOC_E_TIMEOUT; 724 } 725 726 if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) { 727 /* indicate second pass of init is needed */ 728 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS3); 729 soc_timeout_init(&TO(pc), 700000, 0); 730 return SOC_E_NONE; 731 } 732 } 733 734 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS3) || 735 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 736 737 #if 1 738 while (!soc_timeout_check(&TO(pc))) { 739 rv = bmacsec_phy84334_handshake_status(phy_dev_addr, &status); 740 if(rv != BMACSEC_E_NONE) { 741 return SOC_E_FAIL; 742 } 743 if(status == BMACSEC_PHY84334_HS_STATUS_DONE) { 744 break; 745 } 746 } 747 #endif 748 749 /* software controlled medium selection is not available yet */ 750 pc->copper.enable = TRUE; 751 pc->copper.force_duplex = TRUE; 752 pc->copper.force_speed = 10000; 753 pc->copper.autoneg_enable = TRUE; 754 pc->copper.master = SOC_PORT_MS_AUTO; 755 pc->copper.mdix = SOC_PORT_MDIX_AUTO; 756 pc->copper.preferred = !fiber_preferred; 757 758 pc->fiber.enable = TRUE; 759 pc->fiber.force_speed = 10000; 760 pc->fiber.force_duplex = TRUE; 761 pc->fiber.autoneg_enable = FALSE; 762 pc->fiber.preferred = fiber_preferred; 763 764 765 /* Initially configure for the preferred medium. */ 766 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 767 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 768 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_PASSTHRU); 769 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX); 770 771 /* 772 * Some reasonable defaults 773 */ 774 pc->macsec_switch_fixed = 0; 775 pc->macsec_switch_fixed_speed = 10000; 776 pc->macsec_switch_fixed_duplex = 1; 777 pc->macsec_switch_fixed_pause = 1; 778 pc->macsec_pause_rx_fwd = 0; 779 pc->macsec_pause_tx_fwd = 0; 780 pc->macsec_line_ipg = 0xc; 781 pc->macsec_switch_ipg = 0xc; 782 783 /* Check config for MDI PAIR */ 784 phy_mdi_pair_map = soc_property_port_get(unit, port, 785 spn_PHY_MDI_PAIR_MAP, 0); 786 if (phy_mdi_pair_map) { 787 rv = bmacsec_phy84334_phy_mdi_pair_set(phy_dev_addr, phy_mdi_pair_map); 788 789 if(rv != BMACSEC_E_NONE) { 790 LOG_WARN(BSL_LS_SOC_PHY, 791 (BSL_META_U(unit, 792 "phy_84334_init: bmacsec_phy84334_phy_mdi_pair_set " 793 "returned error %d for u=%d p=%d\n"), rv, unit, port)); 794 return SOC_E_FAIL; 795 } 796 } 797 798 /* Set Local Advertising Configuration */ 799 SOC_IF_ERROR_RETURN 800 (phy_84334_ability_local_get(unit, port, &pc->copper.advert_ability)); 801 802 SOC_IF_ERROR_RETURN 803 (phy_84334_ability_advert_set(unit, port, &pc->copper.advert_ability)); 804 805 806 #ifdef PHY84334_FIBER_1G_SUPPORT /* Need to Revist this */ 807 if (!(PHY_FLAGS_TST(unit, port, PHY_FLAGS_FORCED_COPPER)) && 808 pc->fiber.preferred && 809 pc->automedium ){ 810 int medium; 811 812 /* Try 1G Fiber */ 813 pc->fiber.force_speed = 1000; 814 SOC_IF_ERROR_RETURN 815 (_phy_84334_medium_change(unit, port, TRUE, 816 SOC_PORT_MEDIUM_FIBER )); 817 818 819 /* Wait to check if 1G Fiber is up */ 820 sal_usleep(400000); 821 822 SOC_IF_ERROR_RETURN 823 (_phy_84334_medium_check(unit, port, &medium)); 824 825 pc->fiber.force_speed = 10000; 826 if (medium != SOC_PORT_MEDIUM_FIBER) { 827 /* Did not detect 1G Fiber - Try 10G Fiber */ 828 SOC_IF_ERROR_RETURN 829 (_phy_84334_medium_change(unit, port, TRUE, 830 SOC_PORT_MEDIUM_FIBER )); 831 /* Wait to check if 10G Fiber is up */ 832 sal_usleep(400000); 833 } 834 } 835 #endif 836 837 if (pc->macsec_enable) { 838 switch (PHY_MODEL(pc->phy_id0, pc->phy_id1)) { 839 case PHY_BCM84844_MODEL: 840 case PHY_BCM84846_MODEL: 841 case PHY_BCM84848_MODEL: 842 rv = soc_macsecphy_init(unit, port, pc, 843 BMACSEC_CORE_BCM8484X, bmacsec_io_mmi1_cl45_10gbt); 844 break; 845 default: 846 rv = soc_macsecphy_init(unit, port, pc, 847 BMACSEC_CORE_BCM8483X, bmacsec_io_mmi1_cl45_10gbt); 848 break; 849 } 850 if (!SOC_SUCCESS(rv)) { 851 LOG_ERROR(BSL_LS_SOC_PHY, 852 (BSL_META_U(unit, 853 "soc_macsecphy_init: MACSEC init for" 854 " u=%d p=%d FAILED "), unit, port)); 855 } else { 856 LOG_INFO(BSL_LS_SOC_PHY, 857 (BSL_META_U(unit, 858 "soc_macsecphy_init: MACSEC init for" 859 " u=%d p=%d SUCCESS "), unit, port)); 860 } 861 } 862 } 863 return SOC_E_NONE; 864 } 865 866 867 /* 868 * Function: 869 * phy_84334_reset 870 * Purpose: 871 * Reset PHY and wait for it to come out of reset. 872 * Parameters: 873 * unit - StrataSwitch unit #. 874 * port - StrataSwitch port #. 875 * Returns: 876 * SOC_E_XXX 877 */ 878 879 int 880 phy_84334_reset(int unit, soc_port_t port, void *user_arg) 881 { 882 883 int rv; 884 phy_ctrl_t *pc; 885 bmacsec_dev_addr_t phy_dev_addr; 886 887 pc = EXT_PHY_SW_STATE(unit, port); 888 889 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 890 rv = bmacsec_phy84334_reset(phy_dev_addr); 891 892 return (SOC_ERROR(rv)); 893 } 894 895 /* 896 * Function: 897 * phy_84334_enable_set 898 * Purpose: 899 * Enable or disable the physical interface. 900 * Parameters: 901 * unit - StrataSwitch unit #. 902 * port - StrataSwitch port #. 903 * enable - Boolean, true = enable PHY, false = disable. 904 * Returns: 905 * SOC_E_XXX 906 */ 907 908 STATIC int 909 phy_84334_enable_set(int unit, soc_port_t port, int enable) 910 { 911 phy_ctrl_t *pc; 912 int rv = SOC_E_NONE; 913 bmacsec_dev_addr_t phy_dev_addr; 914 bmacsec_phy84334_port_mode_t port_mode = 0; 915 916 pc = EXT_PHY_SW_STATE(unit, port); 917 918 if(PHY_COPPER_MODE(unit, port)) { 919 port_mode = BMACSEC_PHY_COPPER; 920 } else { 921 port_mode = BMACSEC_PHY_FIBER; 922 } 923 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 924 rv = bmacsec_phy84334_enable_set(phy_dev_addr, pc->automedium, 925 port_mode, enable); 926 if(rv != BMACSEC_E_NONE) { 927 return SOC_E_FAIL; 928 } 929 930 if (pc->automedium || PHY_FIBER_MODE(unit, port)) { 931 phy_ctrl_t *int_pc; 932 933 int_pc = INT_PHY_SW_STATE(unit, port); 934 if (NULL != int_pc) { 935 SOC_IF_ERROR_RETURN 936 (PHY_ENABLE_SET(int_pc->pd, unit, port, enable)); 937 } 938 939 LOG_INFO(BSL_LS_SOC_PHY, 940 (BSL_META_U(unit, 941 "phy_84334_enable_set: " 942 "Power %s fiber medium\n"), (enable) ? "up" : "down")); 943 } 944 945 /* Update software state */ 946 SOC_IF_ERROR_RETURN(phy_fe_ge_enable_set(unit, port, enable)); 947 948 return SOC_E_NONE; 949 } 950 951 /* 952 * Function: 953 * phy_84334_enable_get 954 * Purpose: 955 * Enable or disable the physical interface for a 84334 device. 956 * Parameters: 957 * unit - StrataSwitch unit #. 958 * port - StrataSwitch port #. 959 * enable - (OUT) Boolean, true = enable PHY, false = disable. 960 * Returns: 961 * SOC_E_XXX 962 */ 963 964 STATIC int 965 phy_84334_enable_get(int unit, soc_port_t port, int *enable) 966 { 967 return phy_fe_ge_enable_get(unit, port, enable); 968 } 969 970 /* 971 * Function: 972 * _phy_84334_medium_change 973 * Purpose: 974 * Change medium when media change detected or forced 975 * Parameters: 976 * unit - StrataSwitch unit #. 977 * port - StrataSwitch port #. 978 * force_update - Force update 979 * force_medium - Force update medium 980 * Returns: 981 * SOC_E_XXX 982 */ 983 STATIC int 984 _phy_84334_medium_change(int unit, soc_port_t port, int force_update, 985 soc_port_medium_t force_medium) 986 { 987 phy_ctrl_t *pc; 988 int medium = SOC_PORT_MEDIUM_COPPER; 989 bmacsec_dev_addr_t phy_dev_addr; 990 int rv; 991 992 pc = EXT_PHY_SW_STATE(unit, port); 993 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 994 995 if (force_update == TRUE) { 996 medium = force_medium; 997 } else { 998 SOC_IF_ERROR_RETURN 999 (_phy_84334_medium_check(unit, port, &medium)); 1000 } 1001 1002 if (medium == SOC_PORT_MEDIUM_COPPER) { 1003 if (!PHY_COPPER_MODE(unit, port) || force_update) { /* Was fiber */ 1004 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 1005 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 1006 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX); 1007 PHY_FLAGS_SET(unit, port, PHY_FLAGS_MEDIUM_CHANGE); 1008 rv = bmacsec_phy84334_port_mode_set(phy_dev_addr, BMACSEC_PHY_COPPER); 1009 if (!BMACSEC_E_SUCCESS(rv)) { 1010 return SOC_E_FAIL; 1011 } 1012 1013 /* Do Not power up the interface if medium is disabled */ 1014 if (pc->copper.enable) { 1015 SOC_IF_ERROR_RETURN 1016 (_phy_84334_medium_config_update(unit, port, &pc->copper)); 1017 } 1018 LOG_INFO(BSL_LS_SOC_PHY, 1019 (BSL_META_U(unit, 1020 "_phy_84334_link_auto_detect: u=%d p=%d [F->C]\n"), 1021 unit, port)); 1022 } 1023 } else { /* Fiber */ 1024 if (PHY_COPPER_MODE(unit, port) || force_update) { /* Was copper */ 1025 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER); 1026 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 1027 PHY_FLAGS_SET(unit, port, PHY_FLAGS_MEDIUM_CHANGE); 1028 rv = bmacsec_phy84334_port_mode_set(phy_dev_addr, BMACSEC_PHY_FIBER); 1029 if (!BMACSEC_E_SUCCESS(rv)) { 1030 return SOC_E_FAIL; 1031 } 1032 1033 /* Do Not power up the interface if medium is disabled */ 1034 if (pc->fiber.enable) { 1035 SOC_IF_ERROR_RETURN 1036 (_phy_84334_medium_config_update(unit, port, &pc->fiber)); 1037 } 1038 LOG_INFO(BSL_LS_SOC_PHY, 1039 (BSL_META_U(unit, 1040 "_phy_84334_link_auto_detect: u=%d p=%d [C->F]\n"), 1041 unit, port)); 1042 } 1043 } 1044 1045 return SOC_E_NONE; 1046 } 1047 1048 /* 1049 * Function: 1050 * phy_84334_link_get 1051 * Purpose: 1052 * Determine the current link up/down status for a 84334 device. 1053 * Parameters: 1054 * unit - StrataSwitch unit #. 1055 * port - StrataSwitch port #. 1056 * link - (OUT) Boolean, true indicates link established. 1057 * Returns: 1058 * SOC_E_XXX 1059 * Notes: 1060 * If using automedium, also switches the mode. 1061 */ 1062 STATIC int 1063 phy_84334_link_get(int unit, soc_port_t port, int *link) 1064 { 1065 phy_ctrl_t *pc; 1066 uint16 data; 1067 int rv = SOC_E_NONE; 1068 bmacsec_phy84334_port_mode_t port_mode = 0; 1069 bmacsec_dev_addr_t phy_dev_addr; 1070 int bmacsec_link; 1071 1072 1073 pc = EXT_PHY_SW_STATE(unit, port); 1074 *link = FALSE; /* Default return */ 1075 1076 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 1077 return SOC_E_NONE; 1078 } 1079 1080 if (!pc->fiber.enable && !pc->copper.enable) { 1081 return SOC_E_NONE; 1082 } 1083 1084 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_MEDIUM_CHANGE); 1085 if (pc->automedium) { 1086 /* Check for medium change and update HW/SW accordingly. */ 1087 SOC_IF_ERROR_RETURN 1088 (_phy_84334_medium_change(unit, port, FALSE, 0)); 1089 } 1090 1091 if(PHY_COPPER_MODE(unit, port)) { 1092 port_mode = BMACSEC_PHY_COPPER; 1093 } else { 1094 port_mode = BMACSEC_PHY_FIBER; 1095 } 1096 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1097 rv = bmacsec_phy84334_link_get(phy_dev_addr, port_mode, &bmacsec_link); 1098 if (!BMACSEC_E_SUCCESS(rv)) { 1099 return SOC_E_FAIL; 1100 } 1101 if (bmacsec_link == 1) { 1102 *link = TRUE; 1103 } else { 1104 *link = FALSE; 1105 } 1106 1107 /* If preferred medium is up, disable the other medium 1108 * to prevent false link. */ 1109 if (pc->automedium) { 1110 if (pc->copper.preferred) { 1111 #if 0 /* Revisit this after implementing enable set for FIBER/COPPER */ 1112 if (pc->fiber.enable) { 1113 /* Power down Serdes if Copper mode is up */ 1114 data = (*link && PHY_COPPER_MODE(unit, port)) ? 0 : 1; 1115 } else { 1116 data = 0; 1117 1118 } 1119 port_mode = BMACSEC_PHY_FIBER; 1120 (void)bmacsec_phy84334_enable_set(phy_dev_addr, pc->automedium, 1121 port_mode, data); 1122 #endif 1123 } else { /* pc->fiber.preferred */ 1124 if (pc->copper.enable) { 1125 data = (*link && PHY_FIBER_MODE(unit, port)) ? 0 : 1; 1126 } else { 1127 data = 0; 1128 } 1129 port_mode = BMACSEC_PHY_COPPER; 1130 (void)bmacsec_phy84334_enable_set(phy_dev_addr, pc->automedium, 1131 port_mode, data); 1132 } 1133 } 1134 1135 LOG_VERBOSE(BSL_LS_SOC_PHY, 1136 (BSL_META_U(unit, 1137 "phy_84334_link_get: u=%d p=%d mode=%s%s link=%d\n"), 1138 unit, port, 1139 PHY_COPPER_MODE(unit, port) ? "C" : "F", 1140 PHY_FIBER_100FX_MODE(unit, port)? "(100FX)" : "", 1141 *link)); 1142 1143 return SOC_E_NONE; 1144 } 1145 1146 1147 /* 1148 * Function: 1149 * phy_84334_duplex_set 1150 * Purpose: 1151 * Set the current duplex mode (forced). 1152 * Parameters: 1153 * unit - StrataSwitch unit #. 1154 * port - StrataSwitch port #. 1155 * duplex - Boolean, true indicates full duplex, false indicates half. 1156 * Returns: 1157 * SOC_E_NONE 1158 * SOC_E_UNAVAIL - Half duplex requested, and not supported. 1159 * Notes: 1160 * The duplex is set only for the ACTIVE medium. 1161 * No synchronization performed at this level. 1162 * Autonegotiation is not manipulated. 1163 */ 1164 1165 STATIC int 1166 phy_84334_duplex_set(int unit, soc_port_t port, int duplex) 1167 { 1168 int rv; 1169 phy_ctrl_t *pc; 1170 bmacsec_phy84334_port_mode_t port_mode = 0; 1171 bmacsec_dev_addr_t phy_dev_addr; 1172 bmacsec_phy84334_duplex_t bmacsec_duplex; 1173 1174 pc = EXT_PHY_SW_STATE(unit, port); 1175 rv = SOC_E_NONE; 1176 1177 if(PHY_COPPER_MODE(unit, port)) { 1178 port_mode = BMACSEC_PHY_COPPER; 1179 } else { 1180 port_mode = BMACSEC_PHY_FIBER; 1181 if (duplex == 0) { 1182 return SOC_E_UNAVAIL; 1183 } 1184 } 1185 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1186 if (duplex) { 1187 bmacsec_duplex = BMACSEC_PHY84334_FULL_DUPLEX; 1188 } else { 1189 bmacsec_duplex = BMACSEC_PHY84334_HALF_DUPLEX; 1190 } 1191 rv = bmacsec_phy84334_duplex_set(phy_dev_addr, port_mode, 1192 bmacsec_duplex); 1193 1194 if(BMACSEC_E_SUCCESS(rv)) { 1195 pc->copper.force_duplex = duplex; 1196 } 1197 1198 LOG_INFO(BSL_LS_SOC_PHY, 1199 (BSL_META_U(unit, 1200 "phy_84334_duplex_set: u=%d p=%d d=%d rv=%d\n"), 1201 unit, port, duplex, rv)); 1202 return (SOC_ERROR(rv)); 1203 } 1204 1205 /* 1206 * Function: 1207 * phy_84334_duplex_get 1208 * Purpose: 1209 * Get the current operating duplex mode. If autoneg is enabled, 1210 * then operating mode is returned, otherwise forced mode is returned. 1211 * Parameters: 1212 * unit - StrataSwitch unit #. 1213 * port - StrataSwitch port #. 1214 * duplex - (OUT) Boolean, true indicates full duplex, false 1215 * indicates half. 1216 * Returns: 1217 * SOC_E_NONE 1218 * Notes: 1219 * The duplex is retrieved for the ACTIVE medium. 1220 * No synchronization performed at this level. Autonegotiation is 1221 * not manipulated. 1222 */ 1223 1224 STATIC int 1225 phy_84334_duplex_get(int unit, soc_port_t port, int *duplex) 1226 { 1227 1228 int rv = SOC_E_NONE; 1229 bmacsec_phy84334_port_mode_t port_mode = 0; 1230 phy_ctrl_t *pc; 1231 bmacsec_dev_addr_t phy_dev_addr; 1232 bmacsec_phy84334_duplex_t bmacsec_duplex; 1233 1234 pc = EXT_PHY_SW_STATE(unit, port); 1235 1236 if(PHY_COPPER_MODE(unit, port)) { 1237 port_mode = BMACSEC_PHY_COPPER; 1238 } else { 1239 port_mode = BMACSEC_PHY_FIBER; 1240 *duplex = TRUE; 1241 return SOC_E_NONE; 1242 } 1243 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1244 rv = bmacsec_phy84334_duplex_get(phy_dev_addr, port_mode, 1245 &bmacsec_duplex); 1246 if (rv != BMACSEC_E_NONE) { 1247 return SOC_E_FAIL; 1248 } 1249 if (bmacsec_duplex == BMACSEC_PHY84334_FULL_DUPLEX) { 1250 *duplex = TRUE; 1251 } else { 1252 *duplex = FALSE; 1253 } 1254 1255 return SOC_E_NONE; 1256 } 1257 1258 /* 1259 * Function: 1260 * phy_84334_speed_set 1261 * Purpose: 1262 * Set the current operating speed (forced). 1263 * Parameters: 1264 * unit - StrataSwitch unit #. 1265 * port - StrataSwitch port #. 1266 * speed - Requested speed, only 1000 supported. 1267 * Returns: 1268 * SOC_E_XXX 1269 * Notes: 1270 * The speed is set only for the ACTIVE medium. 1271 */ 1272 1273 STATIC int 1274 phy_84334_speed_set(int unit, soc_port_t port, int speed) 1275 { 1276 int rv; 1277 phy_ctrl_t *pc; 1278 bmacsec_dev_addr_t phy_dev_addr; 1279 bmacsec_phy84334_port_mode_t port_mode = 0; 1280 1281 pc = EXT_PHY_SW_STATE(unit, port); 1282 rv = SOC_E_NONE; 1283 1284 if(PHY_COPPER_MODE(unit, port)) { 1285 port_mode = BMACSEC_PHY_COPPER; 1286 } else { 1287 port_mode = BMACSEC_PHY_FIBER; 1288 if (speed == 10) { 1289 return SOC_E_UNAVAIL; 1290 } 1291 } 1292 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1293 rv = bmacsec_phy84334_speed_set(phy_dev_addr, port_mode, speed); 1294 1295 if(BMACSEC_E_SUCCESS(rv)) { 1296 if(PHY_COPPER_MODE(unit, port)) { 1297 pc->copper.force_speed = speed; 1298 } else { 1299 pc->fiber.force_speed = speed; 1300 } 1301 } 1302 LOG_INFO(BSL_LS_SOC_PHY, 1303 (BSL_META_U(unit, 1304 "phy_84334_speed_set: u=%d p=%d s=%d fiber=%d rv=%d\n"), 1305 unit, port, speed, PHY_FIBER_MODE(unit, port), rv)); 1306 1307 return SOC_ERROR(rv); 1308 } 1309 1310 /* 1311 * Function: 1312 * phy_84334_speed_get 1313 * Purpose: 1314 * Get the current operating speed for a 84334 device. 1315 * Parameters: 1316 * unit - StrataSwitch unit #. 1317 * port - StrataSwitch port #. 1318 * duplex - (OUT) Boolean, true indicates full duplex, false 1319 * indicates half. 1320 * Returns: 1321 * SOC_E_NONE 1322 * Notes: 1323 * The speed is retrieved for the ACTIVE medium. 1324 */ 1325 1326 STATIC int 1327 phy_84334_speed_get(int unit, soc_port_t port, int *speed) 1328 { 1329 int rv = SOC_E_NONE; 1330 bmacsec_phy84334_port_mode_t port_mode = 0; 1331 bmacsec_dev_addr_t phy_dev_addr; 1332 phy_ctrl_t *pc; 1333 1334 pc = EXT_PHY_SW_STATE(unit, port); 1335 1336 if(PHY_COPPER_MODE(unit, port)) { 1337 port_mode = BMACSEC_PHY_COPPER; 1338 } else { 1339 port_mode = BMACSEC_PHY_FIBER; 1340 } 1341 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1342 rv = bmacsec_phy84334_speed_get(phy_dev_addr, port_mode, speed); 1343 1344 if(!BMACSEC_E_SUCCESS(rv)) { 1345 LOG_WARN(BSL_LS_SOC_PHY, 1346 (BSL_META_U(unit, 1347 "phy_84334_speed_get: u=%d p=%d invalid speed\n"), 1348 unit, port)); 1349 } else { 1350 LOG_INFO(BSL_LS_SOC_PHY, 1351 (BSL_META_U(unit, 1352 "phy_84334_speed_get: u=%d p=%d speed=%d"), 1353 unit, port, *speed)); 1354 } 1355 1356 return SOC_ERROR(rv); 1357 } 1358 1359 /* 1360 * Function: 1361 * phy_84334_master_set 1362 * Purpose: 1363 * Set the current master mode 1364 * Parameters: 1365 * unit - StrataSwitch unit #. 1366 * port - StrataSwitch port #. 1367 * master - SOC_PORT_MS_* 1368 * Returns: 1369 * SOC_E_XXX 1370 * Notes: 1371 * The master mode is set only for the ACTIVE medium. 1372 */ 1373 STATIC int 1374 phy_84334_master_set(int unit, soc_port_t port, int master) 1375 { 1376 int rv; 1377 phy_ctrl_t *pc; 1378 bmacsec_phy84334_port_mode_t port_mode = 0; 1379 bmacsec_dev_addr_t phy_dev_addr; 1380 1381 pc = EXT_PHY_SW_STATE(unit, port); 1382 rv = SOC_E_NONE; 1383 1384 if(PHY_COPPER_MODE(unit, port)) { 1385 port_mode = BMACSEC_PHY_COPPER; 1386 } else { 1387 port_mode = BMACSEC_PHY_FIBER; 1388 } 1389 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1390 rv = bmacsec_phy84334_master_set(phy_dev_addr, port_mode, master); 1391 if(BMACSEC_E_SUCCESS(rv) && PHY_COPPER_MODE(unit, port)) { 1392 pc->copper.master = master; 1393 } 1394 1395 LOG_INFO(BSL_LS_SOC_PHY, 1396 (BSL_META_U(unit, 1397 "phy_84334_master_set: u=%d p=%d master=%d fiber=%d rv=%d\n"), 1398 unit, port, master, PHY_FIBER_MODE(unit, port), rv)); 1399 1400 return SOC_ERROR(rv); 1401 } 1402 1403 /* 1404 * Function: 1405 * phy_84334_master_get 1406 * Purpose: 1407 * Get the current master mode for a 84334 device. 1408 * Parameters: 1409 * unit - StrataSwitch unit #. 1410 * port - StrataSwitch port #. 1411 * master - (OUT) SOC_PORT_MS_* 1412 * Returns: 1413 * SOC_E_NONE 1414 * Notes: 1415 * The master mode is retrieved for the ACTIVE medium. 1416 */ 1417 1418 STATIC int 1419 phy_84334_master_get(int unit, soc_port_t port, int *master) 1420 { 1421 int rv; 1422 phy_ctrl_t *pc; 1423 bmacsec_phy84334_port_mode_t port_mode = 0; 1424 bmacsec_dev_addr_t phy_dev_addr; 1425 1426 pc = EXT_PHY_SW_STATE(unit, port); 1427 rv = SOC_E_NONE; 1428 1429 if(PHY_COPPER_MODE(unit, port)) { 1430 port_mode = BMACSEC_PHY_COPPER; 1431 } else { 1432 port_mode = BMACSEC_PHY_FIBER; 1433 } 1434 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1435 rv = bmacsec_phy84334_master_get(phy_dev_addr, port_mode, master); 1436 1437 return SOC_ERROR(rv); 1438 } 1439 1440 /* 1441 * Function: 1442 * phy_84334_autoneg_set 1443 * Purpose: 1444 * Enable or disable auto-negotiation on the specified port. 1445 * Parameters: 1446 * unit - StrataSwitch unit #. 1447 * port - StrataSwitch port #. 1448 * autoneg - Boolean, if true, auto-negotiation is enabled 1449 * (and/or restarted). If false, autonegotiation is disabled. 1450 * Returns: 1451 * SOC_E_XXX 1452 * Notes: 1453 * The autoneg mode is set only for the ACTIVE medium. 1454 */ 1455 1456 STATIC int 1457 phy_84334_autoneg_set(int unit, soc_port_t port, int autoneg) 1458 { 1459 int rv; 1460 phy_ctrl_t *pc; 1461 bmacsec_phy84334_port_mode_t port_mode = 0; 1462 bmacsec_dev_addr_t phy_dev_addr; 1463 1464 1465 pc = EXT_PHY_SW_STATE(unit, port); 1466 rv = SOC_E_NONE; 1467 1468 if(PHY_COPPER_MODE(unit, port)) { 1469 port_mode = BMACSEC_PHY_COPPER; 1470 } else { 1471 port_mode = BMACSEC_PHY_FIBER; 1472 } 1473 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1474 rv = bmacsec_phy84334_an_set(phy_dev_addr, port_mode,autoneg); 1475 1476 if(BMACSEC_E_SUCCESS(rv)) { 1477 if(PHY_COPPER_MODE(unit, port)) { 1478 pc->copper.autoneg_enable = autoneg ? TRUE : FALSE; 1479 } else { 1480 pc->fiber.autoneg_enable = autoneg ? TRUE : FALSE; 1481 } 1482 } 1483 1484 LOG_INFO(BSL_LS_SOC_PHY, 1485 (BSL_META_U(unit, 1486 "phy_84334_autoneg_set: u=%d p=%d autoneg=%d rv=%d\n"), 1487 unit, port, autoneg, rv)); 1488 return SOC_ERROR(rv); 1489 } 1490 1491 /* 1492 * Function: 1493 * phy_84334_autoneg_get 1494 * Purpose: 1495 * Get the current auto-negotiation status (enabled/busy). 1496 * Parameters: 1497 * unit - StrataSwitch unit #. 1498 * port - StrataSwitch port #. 1499 * autoneg - (OUT) if true, auto-negotiation is enabled. 1500 * autoneg_done - (OUT) if true, auto-negotiation is complete. This 1501 * value is undefined if autoneg == FALSE. 1502 * Returns: 1503 * SOC_E_XXX 1504 * Notes: 1505 * The autoneg mode is retrieved for the ACTIVE medium. 1506 */ 1507 1508 STATIC int 1509 phy_84334_autoneg_get(int unit, soc_port_t port, 1510 int *autoneg, int *autoneg_done) 1511 { 1512 int rv; 1513 phy_ctrl_t *pc; 1514 bmacsec_phy84334_port_mode_t port_mode = 0; 1515 bmacsec_dev_addr_t phy_dev_addr; 1516 1517 pc = EXT_PHY_SW_STATE(unit, port); 1518 1519 rv = SOC_E_NONE; 1520 *autoneg = FALSE; 1521 *autoneg_done = FALSE; 1522 1523 if(PHY_COPPER_MODE(unit, port)) { 1524 port_mode = BMACSEC_PHY_COPPER; 1525 } else { 1526 port_mode = BMACSEC_PHY_FIBER; 1527 } 1528 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1529 rv = bmacsec_phy84334_an_get(phy_dev_addr, port_mode, autoneg, 1530 autoneg_done); 1531 1532 return SOC_ERROR(rv); 1533 } 1534 1535 /* 1536 * Function: 1537 * phy_84334_ability_advert_get 1538 * Purpose: 1539 * Get the current advertisement for auto-negotiation. 1540 * Parameters: 1541 * unit - StrataSwitch unit #. 1542 * port - StrataSwitch port #. 1543 * mode - (OUT) Port mode mask indicating supported options/speeds. 1544 * Returns: 1545 * SOC_E_XXX 1546 * Notes: 1547 * The advertisement is retrieved for the ACTIVE medium. 1548 * No synchronization performed at this level. 1549 */ 1550 1551 STATIC int 1552 phy_84334_ability_advert_get(int unit, soc_port_t port,soc_port_ability_t *ability) 1553 { 1554 phy_ctrl_t *pc; 1555 bmacsec_phy84334_port_mode_t port_mode; 1556 bmacsec_phy84334_port_ability_t bmacsec_ability; 1557 bmacsec_dev_addr_t phy_dev_addr; 1558 int rv; 1559 1560 pc = EXT_PHY_SW_STATE(unit, port); 1561 1562 sal_memset(ability, 0, sizeof(*ability)); 1563 1564 if(PHY_COPPER_MODE(unit, port)) { 1565 port_mode = BMACSEC_PHY_COPPER; 1566 } else { 1567 port_mode = BMACSEC_PHY_FIBER; 1568 } 1569 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1570 rv = bmacsec_phy84334_ability_advert_get(phy_dev_addr, port_mode, 1571 &bmacsec_ability); 1572 if (rv == BMACSEC_E_NONE) { 1573 if(bmacsec_ability & BMACSEC_PHY84334_PA_10MB_HD) { 1574 ability->speed_half_duplex |= SOC_PA_SPEED_10MB; 1575 } 1576 if(bmacsec_ability & BMACSEC_PHY84334_PA_10MB_FD) { 1577 ability->speed_full_duplex |= SOC_PA_SPEED_10MB; 1578 } 1579 if(bmacsec_ability & BMACSEC_PHY84334_PA_100MB_HD) { 1580 ability->speed_half_duplex |= SOC_PA_SPEED_100MB; 1581 } 1582 if(bmacsec_ability & BMACSEC_PHY84334_PA_100MB_FD) { 1583 ability->speed_full_duplex |= SOC_PA_SPEED_100MB; 1584 } 1585 if(bmacsec_ability & BMACSEC_PHY84334_PA_1000MB_HD) { 1586 ability->speed_half_duplex |= SOC_PA_SPEED_1000MB; 1587 } 1588 if(bmacsec_ability & BMACSEC_PHY84334_PA_1000MB_FD) { 1589 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 1590 } 1591 if(bmacsec_ability & BMACSEC_PHY84334_PA_10000MB_FD) { 1592 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 1593 } 1594 if(bmacsec_ability & BMACSEC_PHY84334_PA_PAUSE_TX) { 1595 ability->pause |= SOC_PA_PAUSE_TX; 1596 } 1597 if(bmacsec_ability & BMACSEC_PHY84334_PA_PAUSE_RX) { 1598 ability->pause |= SOC_PA_PAUSE_RX; 1599 } 1600 1601 if(bmacsec_ability & BMACSEC_PHY84334_PA_EEE_100MB) { 1602 ability->eee |= SOC_PA_EEE_100MB_BASETX; 1603 } 1604 if(bmacsec_ability & BMACSEC_PHY84334_PA_EEE_1000MB) { 1605 ability->eee |= SOC_PA_EEE_1GB_BASET; 1606 } 1607 if(bmacsec_ability & BMACSEC_PHY84334_PA_EEE_10000MB) { 1608 ability->eee |= SOC_PA_EEE_10GB_BASET; 1609 } 1610 } 1611 1612 return (SOC_ERROR(rv)); 1613 } 1614 1615 /* 1616 * Function: 1617 * phy_84334_ability_advert_set 1618 * Purpose: 1619 * Set the current advertisement for auto-negotiation. 1620 * Parameters: 1621 * unit - StrataSwitch unit #. 1622 * port - StrataSwitch port #. 1623 * mode - Port mode mask indicating supported options/speeds. 1624 * Returns: 1625 * SOC_E_XXX 1626 * Notes: 1627 * The advertisement is set only for the ACTIVE medium. 1628 * No synchronization performed at this level. 1629 */ 1630 1631 1632 STATIC int 1633 phy_84334_ability_advert_set(int unit, soc_port_t port, soc_port_ability_t *ability) 1634 { 1635 phy_ctrl_t *pc; 1636 bmacsec_phy84334_port_mode_t port_mode; 1637 bmacsec_phy84334_port_ability_t bmacsec_ability; 1638 bmacsec_dev_addr_t phy_dev_addr; 1639 int rv; 1640 1641 pc = EXT_PHY_SW_STATE(unit, port); 1642 1643 if(PHY_COPPER_MODE(unit, port)) { 1644 port_mode = BMACSEC_PHY_COPPER; 1645 } else { 1646 port_mode = BMACSEC_PHY_FIBER; 1647 } 1648 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1649 1650 bmacsec_ability = 0; 1651 1652 if (ability->speed_half_duplex & SOC_PA_SPEED_10MB) { 1653 bmacsec_ability |= BMACSEC_PHY84334_PA_10MB_HD; 1654 } 1655 if (ability->speed_half_duplex & SOC_PA_SPEED_100MB) { 1656 bmacsec_ability |= BMACSEC_PHY84334_PA_100MB_HD; 1657 } 1658 if (ability->speed_half_duplex & SOC_PA_SPEED_1000MB) { 1659 bmacsec_ability |= BMACSEC_PHY84334_PA_1000MB_HD; 1660 } 1661 if (ability->speed_full_duplex & SOC_PA_SPEED_10MB) { 1662 bmacsec_ability |= BMACSEC_PHY84334_PA_10MB_FD; 1663 } 1664 if (ability->speed_full_duplex & SOC_PA_SPEED_100MB) { 1665 bmacsec_ability |= BMACSEC_PHY84334_PA_100MB_FD; 1666 } 1667 if (ability->speed_full_duplex & SOC_PA_SPEED_1000MB) { 1668 bmacsec_ability |= BMACSEC_PHY84334_PA_1000MB_FD; 1669 } 1670 if (ability->speed_full_duplex & SOC_PA_SPEED_10GB) { 1671 bmacsec_ability |= BMACSEC_PHY84334_PA_10000MB_FD; 1672 } 1673 if (ability->pause & SOC_PA_PAUSE_TX) { 1674 bmacsec_ability |= BMACSEC_PHY84334_PA_PAUSE_TX; 1675 } 1676 if (ability->pause & SOC_PA_PAUSE_RX) { 1677 bmacsec_ability |= BMACSEC_PHY84334_PA_PAUSE_RX; 1678 } 1679 1680 if (ability->eee & SOC_PA_EEE_100MB_BASETX) { 1681 bmacsec_ability |= BMACSEC_PHY84334_PA_EEE_100MB; 1682 } 1683 if (ability->eee & SOC_PA_EEE_1GB_BASET) { 1684 bmacsec_ability |= BMACSEC_PHY84334_PA_EEE_100MB; 1685 } 1686 if (ability->eee & SOC_PA_EEE_10GB_BASET) { 1687 bmacsec_ability |= BMACSEC_PHY84334_PA_EEE_10000MB; 1688 } 1689 1690 rv = bmacsec_phy84334_ability_advert_set(phy_dev_addr, port_mode, bmacsec_ability); 1691 1692 return (SOC_ERROR(rv)); 1693 } 1694 1695 /* 1696 * Function: 1697 * phy_84334_ability_remote_get 1698 * Purpose: 1699 * Get the current remoteisement for auto-negotiation. 1700 * Parameters: 1701 * unit - StrataSwitch unit #. 1702 * port - StrataSwitch port #. 1703 * mode - (OUT) Port mode mask indicating supported options/speeds. 1704 * Returns: 1705 * SOC_E_XXX 1706 * Notes: 1707 * The remoteisement is retrieved for the ACTIVE medium. 1708 * No synchronization performed at this level. 1709 */ 1710 1711 STATIC int 1712 phy_84334_ability_remote_get(int unit, soc_port_t port,soc_port_ability_t *ability) 1713 { 1714 phy_ctrl_t *pc; 1715 bmacsec_phy84334_port_mode_t port_mode; 1716 bmacsec_phy84334_port_ability_t bmacsec_ability = 0; 1717 bmacsec_dev_addr_t phy_dev_addr; 1718 int rv; 1719 1720 pc = EXT_PHY_SW_STATE(unit, port); 1721 1722 sal_memset(ability, 0, sizeof(*ability)); 1723 1724 if(PHY_COPPER_MODE(unit, port)) { 1725 port_mode = BMACSEC_PHY_COPPER; 1726 } else { 1727 port_mode = BMACSEC_PHY_FIBER; 1728 } 1729 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1730 rv = bmacsec_phy84334_remote_ability_advert_get(phy_dev_addr, port_mode, 1731 &bmacsec_ability); 1732 if (rv == BMACSEC_E_NONE) { 1733 if(bmacsec_ability & BMACSEC_PHY84334_PA_10MB_HD) { 1734 ability->speed_half_duplex |= SOC_PA_SPEED_10MB; 1735 } 1736 if(bmacsec_ability & BMACSEC_PHY84334_PA_10MB_FD) { 1737 ability->speed_full_duplex |= SOC_PA_SPEED_10MB; 1738 } 1739 if(bmacsec_ability & BMACSEC_PHY84334_PA_100MB_HD) { 1740 ability->speed_half_duplex |= SOC_PA_SPEED_100MB; 1741 } 1742 if(bmacsec_ability & BMACSEC_PHY84334_PA_100MB_FD) { 1743 ability->speed_full_duplex |= SOC_PA_SPEED_100MB; 1744 } 1745 if(bmacsec_ability & BMACSEC_PHY84334_PA_1000MB_HD) { 1746 ability->speed_half_duplex |= SOC_PA_SPEED_1000MB; 1747 } 1748 if(bmacsec_ability & BMACSEC_PHY84334_PA_1000MB_FD) { 1749 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 1750 } 1751 if(bmacsec_ability & BMACSEC_PHY84334_PA_10000MB_FD) { 1752 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 1753 } 1754 if(bmacsec_ability & BMACSEC_PHY84334_PA_PAUSE_TX) { 1755 ability->pause |= SOC_PA_PAUSE_TX; 1756 } 1757 if(bmacsec_ability & BMACSEC_PHY84334_PA_PAUSE_RX) { 1758 ability->pause |= SOC_PA_PAUSE_RX; 1759 } 1760 1761 if(bmacsec_ability & BMACSEC_PHY84334_PA_EEE_100MB) { 1762 ability->eee |= SOC_PA_EEE_100MB_BASETX; 1763 } 1764 if(bmacsec_ability & BMACSEC_PHY84334_PA_EEE_1000MB) { 1765 ability->eee |= SOC_PA_EEE_1GB_BASET; 1766 } 1767 if(bmacsec_ability & BMACSEC_PHY84334_PA_EEE_10000MB) { 1768 ability->eee |= SOC_PA_EEE_10GB_BASET; 1769 } 1770 } 1771 1772 return (SOC_ERROR(rv)); 1773 } 1774 1775 /* 1776 * Function: 1777 * phy_84334_ability_local_get 1778 * Purpose: 1779 * Get the device's complete abilities. 1780 * Parameters: 1781 * unit - StrataSwitch unit #. 1782 * port - StrataSwitch port #. 1783 * ability - return device's abilities. 1784 * Returns: 1785 * SOC_E_XXX 1786 */ 1787 1788 STATIC int 1789 phy_84334_ability_local_get(int unit, soc_port_t port,soc_port_ability_t *ability) 1790 { 1791 phy_ctrl_t *pc; 1792 bmacsec_phy84334_port_mode_t port_mode; 1793 bmacsec_phy84334_port_ability_t bmacsec_ability; 1794 bmacsec_dev_addr_t phy_dev_addr; 1795 int rv; 1796 1797 pc = EXT_PHY_SW_STATE(unit, port); 1798 1799 sal_memset(ability, 0, sizeof(*ability)); 1800 1801 if(PHY_COPPER_MODE(unit, port)) { 1802 port_mode = BMACSEC_PHY_COPPER; 1803 } else { 1804 port_mode = BMACSEC_PHY_FIBER; 1805 } 1806 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1807 rv = bmacsec_phy84334_ability_local_get(phy_dev_addr, port_mode, 1808 &bmacsec_ability); 1809 if (rv == BMACSEC_E_NONE) { 1810 if(bmacsec_ability & BMACSEC_PHY84334_PA_10MB_HD) { 1811 ability->speed_half_duplex |= SOC_PA_SPEED_10MB; 1812 } 1813 if(bmacsec_ability & BMACSEC_PHY84334_PA_10MB_FD) { 1814 ability->speed_full_duplex |= SOC_PA_SPEED_10MB; 1815 } 1816 if(bmacsec_ability & BMACSEC_PHY84334_PA_100MB_HD) { 1817 ability->speed_half_duplex |= SOC_PA_SPEED_100MB; 1818 } 1819 if(bmacsec_ability & BMACSEC_PHY84334_PA_100MB_FD) { 1820 ability->speed_full_duplex |= SOC_PA_SPEED_100MB; 1821 } 1822 if(bmacsec_ability & BMACSEC_PHY84334_PA_1000MB_HD) { 1823 ability->speed_half_duplex |= SOC_PA_SPEED_1000MB; 1824 } 1825 if(bmacsec_ability & BMACSEC_PHY84334_PA_1000MB_FD) { 1826 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 1827 } 1828 if(bmacsec_ability & BMACSEC_PHY84334_PA_10000MB_FD) { 1829 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 1830 } 1831 if(bmacsec_ability & BMACSEC_PHY84334_PA_PAUSE_TX) { 1832 ability->pause |= SOC_PA_PAUSE_TX; 1833 } 1834 if(bmacsec_ability & BMACSEC_PHY84334_PA_PAUSE_RX) { 1835 ability->pause |= SOC_PA_PAUSE_RX; 1836 } 1837 1838 if(bmacsec_ability & BMACSEC_PHY84334_PA_EEE_100MB) { 1839 ability->eee |= SOC_PA_EEE_100MB_BASETX; 1840 } 1841 if(bmacsec_ability & BMACSEC_PHY84334_PA_EEE_1000MB) { 1842 ability->eee |= SOC_PA_EEE_1GB_BASET; 1843 } 1844 if(bmacsec_ability & BMACSEC_PHY84334_PA_EEE_10000MB) { 1845 ability->eee |= SOC_PA_EEE_10GB_BASET; 1846 } 1847 } 1848 1849 return (SOC_ERROR(rv)); 1850 } 1851 1852 /* 1853 * Function: 1854 * phy_84334_lb_set 1855 * Purpose: 1856 * Set the local PHY loopback mode. 1857 * Parameters: 1858 * unit - StrataSwitch unit #. 1859 * port - StrataSwitch port #. 1860 * loopback - Boolean: true = enable loopback, false = disable. 1861 * Returns: 1862 * SOC_E_XXX 1863 * Notes: 1864 * The loopback mode is set only for the ACTIVE medium. 1865 * No synchronization performed at this level. 1866 */ 1867 1868 STATIC int 1869 phy_84334_lb_set(int unit, soc_port_t port, int enable) 1870 { 1871 int rv; 1872 phy_ctrl_t *pc; 1873 bmacsec_phy84334_port_mode_t port_mode = BMACSEC_PHY_COPPER; 1874 bmacsec_dev_addr_t phy_dev_addr; 1875 1876 pc = EXT_PHY_SW_STATE(unit, port); 1877 rv = SOC_E_NONE; 1878 1879 #if AUTO_MDIX_WHEN_AN_DIS 1880 { 1881 /* Disable Auto-MDIX When autoneg disabled */ 1882 /* Enable Auto-MDIX When autoneg disabled */ 1883 data = (enable) ? 0x0000 : 0x0200; 1884 rv = BMACSEC_MODIFY_PHY_84334_MII_MISC_CTRLr(pc->phy_id, data, 0x0200); 1885 if(!BMACSEC_E_SUCCESS(rv)) { 1886 return SOC_ERROR(rv); 1887 } 1888 1889 } 1890 #endif 1891 1892 pc = EXT_PHY_SW_STATE(unit, port); 1893 rv = SOC_E_NONE; 1894 1895 if(PHY_COPPER_MODE(unit, port)) { 1896 port_mode = BMACSEC_PHY_COPPER; 1897 } else { 1898 port_mode = BMACSEC_PHY_FIBER; 1899 } 1900 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1901 rv = bmacsec_phy84334_loopback_set(phy_dev_addr, port_mode, enable); 1902 1903 if(!BMACSEC_E_SUCCESS(rv)) { 1904 return SOC_E_FAIL; 1905 } 1906 sal_usleep(1000000); 1907 1908 if (enable) { 1909 SOC_IF_ERROR_RETURN 1910 (phy_84334_linkup(unit, port)); 1911 } 1912 1913 LOG_INFO(BSL_LS_SOC_PHY, 1914 (BSL_META_U(unit, 1915 "phy_84334_lb_set: u=%d p=%d en=%d rv=%d\n"), 1916 unit, port, enable, rv)); 1917 1918 return SOC_ERROR(rv); 1919 } 1920 1921 /* 1922 * Function: 1923 * phy_84334_lb_get 1924 * Purpose: 1925 * Get the local PHY loopback mode. 1926 * Parameters: 1927 * unit - StrataSwitch unit #. 1928 * port - StrataSwitch port #. 1929 * loopback - (OUT) Boolean: true = enable loopback, false = disable. 1930 * Returns: 1931 * SOC_E_XXX 1932 * Notes: 1933 * The loopback mode is retrieved for the ACTIVE medium. 1934 */ 1935 1936 STATIC int 1937 phy_84334_lb_get(int unit, soc_port_t port, int *enable) 1938 { 1939 int rv; 1940 phy_ctrl_t *pc; 1941 bmacsec_phy84334_port_mode_t port_mode = BMACSEC_PHY_COPPER; 1942 bmacsec_dev_addr_t phy_dev_addr; 1943 1944 pc = EXT_PHY_SW_STATE(unit, port); 1945 rv = SOC_E_NONE; 1946 1947 if(PHY_COPPER_MODE(unit, port)) { 1948 port_mode = BMACSEC_PHY_COPPER; 1949 } else { 1950 port_mode = BMACSEC_PHY_FIBER; 1951 } 1952 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1953 rv = bmacsec_phy84334_loopback_get(phy_dev_addr, port_mode, enable); 1954 1955 return SOC_ERROR(rv); 1956 } 1957 1958 /* 1959 * Function: 1960 * phy_84334_mdix_set 1961 * Description: 1962 * Set the Auto-MDIX mode of a port/PHY 1963 * Parameters: 1964 * unit - Device number 1965 * port - Port number 1966 * mode - One of: 1967 * SOC_PORT_MDIX_AUTO 1968 * Enable auto-MDIX when autonegotiation is enabled 1969 * SOC_PORT_MDIX_FORCE_AUTO 1970 * Enable auto-MDIX always 1971 * SOC_PORT_MDIX_NORMAL 1972 * Disable auto-MDIX 1973 * SOC_PORT_MDIX_XOVER 1974 * Disable auto-MDIX, and swap cable pairs 1975 * Return Value: 1976 * SOC_E_XXX 1977 */ 1978 STATIC int 1979 phy_84334_mdix_set(int unit, soc_port_t port, soc_port_mdix_t mode) 1980 { 1981 1982 int rv; 1983 phy_ctrl_t *pc; 1984 bmacsec_phy84334_port_mode_t port_mode = BMACSEC_PHY_COPPER; 1985 bmacsec_dev_addr_t phy_dev_addr; 1986 bmacsec_phy84334_port_mdix_t bmacsec_mode; 1987 1988 pc = EXT_PHY_SW_STATE(unit, port); 1989 1990 if(PHY_COPPER_MODE(unit, port)) { 1991 port_mode = BMACSEC_PHY_COPPER; 1992 } else { 1993 port_mode = BMACSEC_PHY_FIBER; 1994 } 1995 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1996 switch(mode) { 1997 case SOC_PORT_MDIX_AUTO: 1998 bmacsec_mode = BMACSEC_PHY84334_PORT_MDIX_AUTO; 1999 break; 2000 case SOC_PORT_MDIX_FORCE_AUTO: 2001 bmacsec_mode = BMACSEC_PHY84334_PORT_MDIX_FORCE_AUTO; 2002 break; 2003 case SOC_PORT_MDIX_NORMAL: 2004 bmacsec_mode = BMACSEC_PHY84334_PORT_MDIX_NORMAL; 2005 break; 2006 case SOC_PORT_MDIX_XOVER: 2007 bmacsec_mode = BMACSEC_PHY84334_PORT_MDIX_XOVER; 2008 break; 2009 default : 2010 return SOC_E_CONFIG; 2011 } 2012 2013 rv = bmacsec_phy84334_mdix_set(phy_dev_addr, port_mode, bmacsec_mode); 2014 2015 if(BMACSEC_E_SUCCESS(rv) && PHY_COPPER_MODE(unit, port)) { 2016 pc->copper.mdix = mode; 2017 } 2018 return SOC_ERROR(rv); 2019 } 2020 2021 /* 2022 * Function: 2023 * phy_84334_mdix_get 2024 * Description: 2025 * Get the Auto-MDIX mode of a port/PHY 2026 * Parameters: 2027 * unit - Device number 2028 * port - Port number 2029 * mode - (Out) One of: 2030 * SOC_PORT_MDIX_AUTO 2031 * Enable auto-MDIX when autonegotiation is enabled 2032 * SOC_PORT_MDIX_FORCE_AUTO 2033 * Enable auto-MDIX always 2034 * SOC_PORT_MDIX_NORMAL 2035 * Disable auto-MDIX 2036 * SOC_PORT_MDIX_XOVER 2037 * Disable auto-MDIX, and swap cable pairs 2038 * Return Value: 2039 * SOC_E_XXX 2040 */ 2041 STATIC int 2042 phy_84334_mdix_get(int unit, soc_port_t port, soc_port_mdix_t *mode) 2043 { 2044 phy_ctrl_t *pc; 2045 int speed; 2046 2047 if (mode == NULL) { 2048 return SOC_E_PARAM; 2049 } 2050 2051 pc = EXT_PHY_SW_STATE(unit, port); 2052 2053 if (PHY_COPPER_MODE(unit, port)) { 2054 SOC_IF_ERROR_RETURN(phy_84334_speed_get(unit, port, &speed)); 2055 if (speed == 1000) { 2056 *mode = SOC_PORT_MDIX_AUTO; 2057 } else { 2058 *mode = pc->copper.mdix; 2059 } 2060 } else { 2061 *mode = SOC_PORT_MDIX_NORMAL; 2062 } 2063 2064 return SOC_E_NONE; 2065 } 2066 2067 /* 2068 * Function: 2069 * phy_84334_mdix_status_get 2070 * Description: 2071 * Get the current MDIX status on a port/PHY 2072 * Parameters: 2073 * unit - Device number 2074 * port - Port number 2075 * status - (OUT) One of: 2076 * SOC_PORT_MDIX_STATUS_NORMAL 2077 * Straight connection 2078 * SOC_PORT_MDIX_STATUS_XOVER 2079 * Crossover has been performed 2080 * Return Value: 2081 * SOC_E_XXX 2082 */ 2083 STATIC int 2084 phy_84334_mdix_status_get(int unit, soc_port_t port, 2085 soc_port_mdix_status_t *status) 2086 { 2087 int rv; 2088 phy_ctrl_t *pc; 2089 2090 bmacsec_phy84334_port_mode_t port_mode = BMACSEC_PHY_COPPER; 2091 bmacsec_dev_addr_t phy_dev_addr; 2092 bmacsec_phy84334_port_mdix_status_t mdix_status; 2093 2094 if (status == NULL) { 2095 return SOC_E_PARAM; 2096 } 2097 2098 pc = EXT_PHY_SW_STATE(unit, port); 2099 2100 if(PHY_COPPER_MODE(unit, port)) { 2101 port_mode = BMACSEC_PHY_COPPER; 2102 } else { 2103 port_mode = BMACSEC_PHY_FIBER; 2104 } 2105 2106 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 2107 rv = bmacsec_phy84334_mdix_status_get(phy_dev_addr, port_mode, 2108 &mdix_status); 2109 if(BMACSEC_E_SUCCESS(rv)) { 2110 if(mdix_status == BMACSEC_PHY84334_PORT_MDIX_STATUS_NORMAL) { 2111 *status = SOC_PORT_MDIX_STATUS_NORMAL; 2112 } 2113 if(mdix_status == BMACSEC_PHY84334_PORT_MDIX_STATUS_XOVER) { 2114 *status = SOC_PORT_MDIX_STATUS_XOVER; 2115 } 2116 return SOC_E_NONE; 2117 } 2118 2119 return SOC_ERROR(rv); 2120 } 2121 2122 2123 /* 2124 * Function: 2125 * phy_84334_timesync_config_set 2126 * Description: 2127 * 2128 * Parameters: 2129 * 2130 * Return Value: 2131 * SOC_E_XXX 2132 */ 2133 2134 int 2135 phy_84334_timesync_config_set(int unit, soc_port_t port, soc_port_phy_timesync_config_t *timesync_config) 2136 { 2137 int rv; 2138 phy_ctrl_t *pc; 2139 bmacsec_dev_addr_t phy_dev_addr; 2140 2141 pc = EXT_PHY_SW_STATE(unit, port); 2142 rv = SOC_E_NONE; 2143 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 2144 2145 rv = bmacsec_phy84334_timesync_config_set(phy_dev_addr, (bmacsec_port_phy_timesync_config_t *)timesync_config); 2146 return (SOC_ERROR(rv)); 2147 2148 } 2149 2150 2151 /* 2152 * Function: 2153 * phy_84334_timesync_config_get 2154 * Description: 2155 * 2156 * Parameters: 2157 * 2158 * Return Value: 2159 * SOC_E_XXX 2160 */ 2161 2162 int 2163 phy_84334_timesync_config_get(int unit, soc_port_t port, soc_port_phy_timesync_config_t *timesync_config) 2164 { 2165 int rv; 2166 phy_ctrl_t *pc; 2167 bmacsec_dev_addr_t phy_dev_addr; 2168 2169 pc = EXT_PHY_SW_STATE(unit, port); 2170 rv = SOC_E_NONE; 2171 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 2172 2173 rv = bmacsec_phy84334_timesync_config_get(phy_dev_addr, (bmacsec_port_phy_timesync_config_t *)timesync_config); 2174 return (SOC_ERROR(rv)); 2175 2176 } 2177 2178 2179 /* 2180 * Function: 2181 * phy_84334_timesync_control_set 2182 * Description: 2183 * 2184 * Parameters: 2185 * 2186 * Return Value: 2187 * SOC_E_XXX 2188 */ 2189 2190 int 2191 phy_84334_timesync_control_set(int unit, soc_port_t port, soc_port_control_phy_timesync_t control_type, uint64 value) 2192 { 2193 int rv; 2194 phy_ctrl_t *pc; 2195 bmacsec_dev_addr_t phy_dev_addr; 2196 buint64_t btemp64; 2197 2198 COMPILER_64_SET(btemp64, COMPILER_64_HI(value), COMPILER_64_LO(value)); 2199 2200 pc = EXT_PHY_SW_STATE(unit, port); 2201 rv = SOC_E_NONE; 2202 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 2203 2204 rv = bmacsec_phy84334_timesync_control_set(phy_dev_addr, control_type, btemp64); 2205 return (SOC_ERROR(rv)); 2206 2207 } 2208 2209 2210 2211 /* 2212 * Function: 2213 * phy_84334_timesync_control_get 2214 * Description: 2215 * 2216 * Parameters: 2217 * 2218 * Return Value: 2219 * SOC_E_XXX 2220 */ 2221 int 2222 phy_84334_timesync_control_get(int unit, soc_port_t port, soc_port_control_phy_timesync_t control_type, uint64 *value) 2223 { 2224 int rv; 2225 phy_ctrl_t *pc; 2226 bmacsec_dev_addr_t phy_dev_addr; 2227 buint64_t btemp64; 2228 2229 COMPILER_64_ZERO(btemp64); 2230 pc = EXT_PHY_SW_STATE(unit, port); 2231 rv = SOC_E_NONE; 2232 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 0); 2233 2234 rv = bmacsec_phy84334_timesync_control_get(phy_dev_addr, control_type, &btemp64); 2235 2236 COMPILER_64_SET(*value, COMPILER_64_HI(btemp64), COMPILER_64_LO(btemp64)); 2237 2238 return (SOC_ERROR(rv)); 2239 2240 } 2241 2242 2243 /* 2244 * Function: 2245 * phy_84334_control_set 2246 * Purpose: 2247 * Configure PHY device specific control fucntion. 2248 * Parameters: 2249 * unit - StrataSwitch unit #. 2250 * port - StrataSwitch port #. 2251 * type - Control to update 2252 * value - New setting for the control 2253 * Returns: 2254 * SOC_E_NONE 2255 */ 2256 STATIC int 2257 phy_84334_control_set(int unit, soc_port_t port, 2258 soc_phy_control_t type, uint32 value) 2259 { 2260 int rv, pause_fwd = 0, temp; 2261 phy_ctrl_t *pc; 2262 bmacsec_dev_addr_t phy_dev_addr; 2263 2264 pc = EXT_PHY_SW_STATE(unit, port); 2265 2266 2267 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 2268 2269 rv = BMACSEC_E_NONE; 2270 switch(type) { 2271 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED: 2272 pc->macsec_switch_fixed = value; 2273 if(value) { 2274 rv = bmacsec_phy84334_switch_side_set_params(phy_dev_addr, 2275 BMACSEC_BCM84334_SWITCH_FIXED, 2276 pc->macsec_switch_fixed_speed, 2277 pc->macsec_switch_fixed_duplex, 2278 pc->macsec_switch_fixed_pause); 2279 } else { /* Switch side follows line side */ 2280 rv = bmacsec_phy84334_switch_side_set_params(phy_dev_addr, 2281 BMACSEC_BCM84334_SWITCH_FOLLOWS_LINE, 2282 -1, -1, -1); 2283 } 2284 2285 break; 2286 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_SPEED: 2287 /* Switch fixed speed is allowed only to be 1000Mbps */ 2288 if (value != 1000) { 2289 return SOC_E_CONFIG; 2290 } 2291 if(pc->macsec_switch_fixed_speed != value) { 2292 int line_speed; 2293 2294 pc->macsec_switch_fixed_speed = value; 2295 2296 SOC_IF_ERROR_RETURN 2297 (phy_84334_speed_get(unit, port, &line_speed)); 2298 pc->macsec_switch_fixed_speed = line_speed; 2299 2300 } 2301 break; 2302 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_DUPLEX: 2303 /* Switch fixed Duplex is allowed only to be Full Duplex mode */ 2304 if (value != 1) { 2305 return SOC_E_CONFIG; 2306 } 2307 if(pc->macsec_switch_fixed_duplex != value) { 2308 pc->macsec_switch_fixed_duplex = value; 2309 } 2310 break; 2311 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_PAUSE: 2312 if(pc->macsec_switch_fixed_pause != value) { 2313 pc->macsec_switch_fixed_pause = value; 2314 } 2315 break; 2316 case SOC_PHY_CONTROL_MACSEC_PAUSE_RX_FORWARD: 2317 pc->macsec_pause_rx_fwd = value; 2318 pause_fwd = (value == 1) ? 1 : 0; 2319 2320 rv = bmacsec_phy84334_line_side_pause_forward(phy_dev_addr, 2321 pause_fwd); 2322 if (rv == BMACSEC_E_NONE) { 2323 rv = bmacsec_phy84334_switch_side_pause_forward( 2324 phy_dev_addr, pause_fwd); 2325 } 2326 break; 2327 case SOC_PHY_CONTROL_MACSEC_PAUSE_TX_FORWARD: 2328 pc->macsec_pause_tx_fwd = value; 2329 pause_fwd = (value == 1) ? 1 : 0; 2330 2331 rv = bmacsec_phy84334_line_side_pause_forward(phy_dev_addr, 2332 pause_fwd); 2333 if (rv == BMACSEC_E_NONE) { 2334 rv = bmacsec_phy84334_switch_side_pause_forward(phy_dev_addr, 2335 pause_fwd); 2336 } 2337 break; 2338 case SOC_PHY_CONTROL_MACSEC_LINE_IPG: 2339 pc->macsec_line_ipg = value; 2340 rv = bmacsec_phy84334_line_side_ipg_set(phy_dev_addr, value); 2341 break; 2342 case SOC_PHY_CONTROL_MACSEC_SWITCH_IPG: 2343 pc->macsec_switch_ipg = value; 2344 rv = bmacsec_phy84334_switch_side_ipg_set(phy_dev_addr, value); 2345 break; 2346 2347 2348 2349 2350 case SOC_PHY_CONTROL_EEE: 2351 if (value) { 2352 SOC_IF_ERROR_RETURN 2353 (bmacsec_phy84334_eee_mode_set(phy_dev_addr, 1, 0x0000, 0x0000, 0x0000 )); 2354 2355 pc->copper.advert_ability.eee |= (SOC_PA_EEE_10GB_BASET | SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX); 2356 temp = pc->copper.autoneg_enable; 2357 /* Initiate AN */ 2358 SOC_IF_ERROR_RETURN 2359 (phy_84334_autoneg_set(unit, port, 1)); 2360 pc->copper.autoneg_enable = temp; 2361 PHY_FLAGS_SET(unit, port, PHY_FLAGS_EEE_ENABLED); 2362 PHY_FLAGS_CLR(unit, pc->port, PHY_FLAGS_EEE_MODE); 2363 } else { 2364 SOC_IF_ERROR_RETURN 2365 (bmacsec_phy84334_eee_mode_set(phy_dev_addr, 0, 0x0000, 0x0000, 0x0000 )); 2366 pc->copper.advert_ability.eee &= ~(SOC_PA_EEE_10GB_BASET | SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX); 2367 SOC_IF_ERROR_RETURN 2368 (phy_84334_autoneg_set(unit, port, pc->copper.autoneg_enable ? 1 : 0)); 2369 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_EEE_ENABLED); 2370 } 2371 break; 2372 2373 case SOC_PHY_CONTROL_EEE_AUTO: 2374 if (value) { 2375 SOC_IF_ERROR_RETURN 2376 (bmacsec_phy84334_eee_mode_set(phy_dev_addr, 2, 0x0000, 0x047f, 0x047e )); 2377 2378 pc->copper.advert_ability.eee |= (SOC_PA_EEE_10GB_BASET | SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX); 2379 temp = pc->copper.autoneg_enable; 2380 /* Initiate AN */ 2381 SOC_IF_ERROR_RETURN 2382 (phy_84334_autoneg_set(unit, port, 1)); 2383 pc->copper.autoneg_enable = temp; 2384 PHY_FLAGS_SET(unit, port, PHY_FLAGS_EEE_ENABLED); 2385 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_EEE_MODE); 2386 } else { 2387 SOC_IF_ERROR_RETURN 2388 (bmacsec_phy84334_eee_mode_set(phy_dev_addr, 0, 0x0000, 0x0000, 0x0000 )); 2389 pc->copper.advert_ability.eee &= ~(SOC_PA_EEE_10GB_BASET | SOC_PA_EEE_1GB_BASET | SOC_PA_EEE_100MB_BASETX); 2390 SOC_IF_ERROR_RETURN 2391 (phy_84334_autoneg_set(unit, port, pc->copper.autoneg_enable ? 1 : 0)); 2392 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_EEE_ENABLED); 2393 } 2394 break; 2395 2396 case SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY: 2397 { 2398 uint16 mode=0, latency=0, th_high=0, th_low=0; 2399 SOC_IF_ERROR_RETURN 2400 (bmacsec_phy84334_eee_mode_get(phy_dev_addr, &mode, &th_high, &th_low, &latency )); 2401 /* Fixed latency can have only 0 or 1 value */ 2402 if ((value != FALSE) && (value != TRUE)) { 2403 return SOC_E_PARAM; 2404 } 2405 if (value == FALSE) { 2406 /* Variable latency */ 2407 SOC_IF_ERROR_RETURN 2408 (bmacsec_phy84334_eee_mode_set(phy_dev_addr, 3, th_high, th_low, latency )); 2409 } else { 2410 /* Fixed latency */ 2411 SOC_IF_ERROR_RETURN 2412 (bmacsec_phy84334_eee_mode_set(phy_dev_addr, 2, th_high, th_low, latency )); 2413 } 2414 } 2415 break; 2416 2417 case SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD: 2418 { 2419 uint16 mode, buffer_len; 2420 SOC_IF_ERROR_RETURN 2421 (bmacsec_phy84334_eee_mode_get(phy_dev_addr, &mode, NULL, NULL, &buffer_len )); 2422 if ( (mode != 2) || (buffer_len > value)) { 2423 return SOC_E_PARAM; 2424 } 2425 SOC_IF_ERROR_RETURN 2426 (bmacsec_phy84334_eee_mode_set(phy_dev_addr, 2, (uint16)((value >> 16) & 0xffff), (uint16)(value & 0xffff), buffer_len )); 2427 } 2428 break; 2429 2430 case SOC_PHY_CONTROL_EEE_STATISTICS_CLEAR: 2431 SOC_IF_ERROR_RETURN 2432 (bmacsec_phy84334_eee_statistics_clear(phy_dev_addr)); 2433 2434 break; 2435 2436 case SOC_PHY_CONTROL_EEE_AUTO_BUFFER_LIMIT: 2437 case SOC_PHY_CONTROL_EEE_TRANSMIT_WAKE_TIME: 2438 case SOC_PHY_CONTROL_EEE_RECEIVE_WAKE_TIME: 2439 case SOC_PHY_CONTROL_EEE_TRANSMIT_SLEEP_TIME: 2440 case SOC_PHY_CONTROL_EEE_RECEIVE_SLEEP_TIME: 2441 case SOC_PHY_CONTROL_EEE_TRANSMIT_QUIET_TIME: 2442 case SOC_PHY_CONTROL_EEE_RECEIVE_QUIET_TIME: 2443 case SOC_PHY_CONTROL_EEE_TRANSMIT_REFRESH_TIME: 2444 return SOC_E_UNAVAIL; 2445 2446 2447 default: 2448 return SOC_E_UNAVAIL; 2449 } 2450 2451 if (rv != BMACSEC_E_NONE) { 2452 return SOC_ERROR(rv); 2453 } 2454 return SOC_E_NONE; 2455 } 2456 2457 /* 2458 * Function: 2459 * phy_84334_control_get 2460 * Purpose: 2461 * Get current control settign of the PHY. 2462 * Parameters: 2463 * unit - StrataSwitch unit #. 2464 * port - StrataSwitch port #. 2465 * type - Control to update 2466 * value - (OUT)Current setting for the control 2467 * Returns: 2468 * SOC_E_NONE 2469 */ 2470 STATIC int 2471 phy_84334_control_get(int unit, soc_port_t port, 2472 soc_phy_control_t type, uint32 *value) 2473 { 2474 int rv; 2475 phy_ctrl_t *pc; 2476 bmacsec_dev_addr_t phy_dev_addr; 2477 buint16_t mode, temp, temp1; 2478 2479 pc = EXT_PHY_SW_STATE(unit, port); 2480 2481 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 2482 2483 if (NULL == value) { 2484 return SOC_E_PARAM; 2485 } 2486 2487 if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) { 2488 return SOC_E_PARAM; 2489 } 2490 2491 rv = SOC_E_NONE; 2492 switch(type) { 2493 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED: 2494 *value = pc->macsec_switch_fixed; 2495 break; 2496 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_SPEED: 2497 *value = pc->macsec_switch_fixed_speed; 2498 break; 2499 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_DUPLEX: 2500 *value = pc->macsec_switch_fixed_duplex; 2501 break; 2502 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_PAUSE: 2503 *value = pc->macsec_switch_fixed_pause; 2504 break; 2505 case SOC_PHY_CONTROL_MACSEC_PAUSE_RX_FORWARD: 2506 *value = pc->macsec_pause_rx_fwd; 2507 break; 2508 case SOC_PHY_CONTROL_MACSEC_PAUSE_TX_FORWARD: 2509 *value = pc->macsec_pause_tx_fwd; 2510 break; 2511 case SOC_PHY_CONTROL_MACSEC_LINE_IPG: 2512 *value = pc->macsec_line_ipg; 2513 break; 2514 case SOC_PHY_CONTROL_MACSEC_SWITCH_IPG: 2515 *value = pc->macsec_switch_ipg; 2516 break; 2517 2518 2519 case SOC_PHY_CONTROL_EEE: 2520 *value = (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED) && 2521 !PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_MODE)) ? 1 : 0; 2522 break; 2523 2524 case SOC_PHY_CONTROL_EEE_AUTO: 2525 *value = (PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_ENABLED) && 2526 PHY_FLAGS_TST(unit, port, PHY_FLAGS_EEE_MODE)) ? 1 : 0; 2527 break; 2528 2529 case SOC_PHY_CONTROL_EEE_AUTO_FIXED_LATENCY: 2530 { 2531 uint16 mode=0 ,latency=0; 2532 SOC_IF_ERROR_RETURN 2533 (bmacsec_phy84334_eee_mode_get(phy_dev_addr, &mode, NULL, NULL, &latency)); 2534 if (mode == 2 || mode == 6 || mode == 0xa) { 2535 *value = 1; 2536 } 2537 else if (mode == 3 || mode == 7 || mode == 0xb) { 2538 *value = 0; 2539 } 2540 } 2541 break; 2542 2543 case SOC_PHY_CONTROL_EEE_AUTO_IDLE_THRESHOLD: 2544 SOC_IF_ERROR_RETURN 2545 (bmacsec_phy84334_eee_mode_get(phy_dev_addr, &mode, &temp1, &temp, NULL)); 2546 if (mode != 2) { 2547 return SOC_E_UNAVAIL; 2548 } 2549 *value = (((uint32) temp1) << 16) | temp; 2550 break; 2551 2552 case SOC_PHY_CONTROL_EEE_TRANSMIT_EVENTS: 2553 SOC_IF_ERROR_RETURN 2554 (bmacsec_phy84334_eee_tx_events_get(phy_dev_addr, value)); 2555 break; 2556 2557 case SOC_PHY_CONTROL_EEE_TRANSMIT_DURATION: 2558 SOC_IF_ERROR_RETURN 2559 (bmacsec_phy84334_eee_tx_duration_get(phy_dev_addr, value)); 2560 break; 2561 2562 case SOC_PHY_CONTROL_EEE_RECEIVE_EVENTS: 2563 SOC_IF_ERROR_RETURN 2564 (bmacsec_phy84334_eee_rx_events_get(phy_dev_addr, value)); 2565 break; 2566 2567 case SOC_PHY_CONTROL_EEE_RECEIVE_DURATION: 2568 SOC_IF_ERROR_RETURN 2569 (bmacsec_phy84334_eee_tx_duration_get(phy_dev_addr, value)); 2570 break; 2571 2572 default: 2573 rv = SOC_E_UNAVAIL; 2574 break; 2575 } 2576 return rv; 2577 } 2578 2579 /* 2580 * Function: 2581 * phy_84334_linkup 2582 * Purpose: 2583 * Link up handler 2584 * Parameters: 2585 * unit - StrataSwitch unit #. 2586 * port - StrataSwitch port #. 2587 * Returns: 2588 * SOC_E_NONE 2589 */ 2590 STATIC int 2591 phy_84334_linkup(int unit, soc_port_t port) 2592 { 2593 int rv; 2594 int line_speed; 2595 phy_ctrl_t *pc; 2596 bmacsec_dev_addr_t phy_dev_addr; 2597 2598 2599 pc = EXT_PHY_SW_STATE(unit, port); 2600 2601 SOC_IF_ERROR_RETURN 2602 (phy_84334_speed_get(unit, port, &line_speed)); 2603 2604 switch (line_speed) { 2605 2606 case 10000: 2607 SOC_IF_ERROR_RETURN 2608 (soc_phyctrl_notify(unit, port, phyEventInterface, SOC_PORT_IF_XAUI)); 2609 SOC_IF_ERROR_RETURN 2610 (soc_phyctrl_notify(unit, port, phyEventSpeed, 10000)); 2611 SOC_IF_ERROR_RETURN 2612 (soc_phyctrl_notify(unit, port, phyEventResume, 1)); 2613 break; 2614 2615 case 1000: 2616 if (PHY_COPPER_MODE(unit, port)) { 2617 SOC_IF_ERROR_RETURN 2618 (soc_phyctrl_notify(unit, port, phyEventInterface, SOC_PORT_IF_SGMII)); 2619 SOC_IF_ERROR_RETURN 2620 (soc_phyctrl_notify(unit, port, phyEventSpeed, 1000)); 2621 } else { 2622 SOC_IF_ERROR_RETURN 2623 (soc_phyctrl_notify(unit, port, phyEventInterface, SOC_PORT_IF_XAUI)); 2624 } 2625 break; 2626 2627 case 100: 2628 case 10: 2629 SOC_IF_ERROR_RETURN 2630 (soc_phyctrl_notify(unit, port, phyEventInterface, SOC_PORT_IF_SGMII)); 2631 SOC_IF_ERROR_RETURN 2632 (soc_phyctrl_notify(unit, port, phyEventSpeed, line_speed)); 2633 break; 2634 2635 default: 2636 break; 2637 } 2638 2639 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 2640 2641 /* Call BMACSEC linkup routine */ 2642 rv = bmacsec_84334_phy_linkup(phy_dev_addr, pc->macsec_enable); 2643 2644 if (BMACSEC_E_FAILURE(rv)) { 2645 return SOC_E_FAIL; 2646 } 2647 2648 if (pc->macsec_enable != 1) { 2649 return SOC_E_NONE; 2650 } 2651 2652 pc->macsec_switch_fixed_speed = line_speed; 2653 2654 2655 /* wait for Power Down of unused MACSEC sub-blocks to complete */ 2656 sal_usleep(400000); 2657 2658 rv = bmacsec_phy84334_switch_side_set_params(phy_dev_addr, 2659 BMACSEC_BCM84334_SWITCH_FIXED, 2660 pc->macsec_switch_fixed_speed, 2661 pc->macsec_switch_fixed_duplex, 2662 pc->macsec_switch_fixed_pause); 2663 if (BMACSEC_E_FAILURE(rv)) { 2664 return SOC_E_FAIL; 2665 } 2666 2667 return SOC_E_NONE; 2668 } 2669 2670 /* 2671 * Function: 2672 * phy_84334_firmware_set 2673 * Purpose: 2674 * program the given firmware into the SPI-ROM 2675 * Parameters: 2676 * unit - StrataSwitch unit #. 2677 * port - StrataSwitch port #. 2678 * offset - offset to the data stream 2679 * array - the given data 2680 * datalen- the data length 2681 * Returns: 2682 * SOC_E_NONE 2683 */ 2684 2685 STATIC int 2686 phy_84334_firmware_set(int unit, int port, int offset, uint8 *data,int len) 2687 { 2688 int rv; 2689 phy_ctrl_t *pc; 2690 bmacsec_dev_addr_t phy_dev_addr; 2691 2692 pc = EXT_PHY_SW_STATE(unit, port); 2693 2694 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 2695 2696 offset = (data == 0) ? BMACSEC_PHY84334_MAP_UCODE_OFFSET(offset) : 0 ; 2697 len = (data == 0) ? (PHY_MODEL(pc->phy_id0, pc->phy_id1)) : len; 2698 2699 rv = bmacsec_phy84334_firmware_set(phy_dev_addr, offset, data, len); 2700 if (rv != BMACSEC_E_NONE) { 2701 LOG_WARN(BSL_LS_SOC_PHY, 2702 (BSL_META_U(unit, 2703 "PHY84334 firmware upgrade possibly failed:" 2704 "u=%d p=%d\n"), unit, port)); 2705 return (SOC_E_FAIL); 2706 } 2707 LOG_INFO(BSL_LS_SOC_PHY, 2708 (BSL_META_U(unit, 2709 "PHY84334 firmware upgrade successful:" 2710 "u=%d p=%d\n"), unit, port)); 2711 2712 #if 0 2713 if (data == 0 && offset == BMACSEC_PHY84334_UCODE_BCST_END) { 2714 soc_timeout_init(&TO(pc), 2000000, 0); 2715 } 2716 #endif 2717 2718 return SOC_E_NONE; 2719 } 2720 2721 /* 2722 * Function: 2723 * phy_84334_probe 2724 * Purpose: 2725 * Complement the generic phy probe routine to identify this phy when its 2726 * phy id0 and id1 is same as some other phy's. 2727 * Parameters: 2728 * unit - StrataSwitch unit #. 2729 * pc - phy ctrl descriptor. 2730 * Returns: 2731 * SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error> 2732 */ 2733 2734 STATIC int 2735 phy_84334_probe(int unit, phy_ctrl_t *pc) 2736 { 2737 uint16 id0, id1; 2738 2739 if (READ_PHY84334_PMA_PMD_REG(unit, pc, 0x2, &id0) < 0) { 2740 return SOC_E_NOT_FOUND; 2741 } 2742 2743 if (READ_PHY84334_PMA_PMD_REG(unit, pc, 0x3, &id1) < 0) { 2744 return SOC_E_NOT_FOUND; 2745 } 2746 2747 switch (PHY_MODEL(id0, id1)) { 2748 2749 case PHY_BCM84334_MODEL: 2750 if (id1 & 0x8) { 2751 if (!soc_property_port_get(unit, pc->port, spn_MACSEC_ENABLE, 0)) { 2752 break; 2753 } 2754 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER); 2755 pc->size = sizeof(PHY8433_PRIV_t); 2756 return SOC_E_NONE; 2757 } 2758 break; 2759 2760 case PHY_BCM84333_MODEL: 2761 case PHY_BCM84336_MODEL: 2762 if (id1 & 0x8) { 2763 if (!soc_property_port_get(unit, pc->port, spn_MACSEC_ENABLE, 0)) { 2764 break; 2765 } 2766 pc->size = sizeof(PHY8433_PRIV_t); 2767 return SOC_E_NONE; 2768 } 2769 break; 2770 2771 case PHY_BCM84844_MODEL: 2772 case PHY_BCM84848_MODEL: 2773 #if 1 2774 if (!soc_property_port_get(unit, pc->port, spn_MACSEC_ENABLE, 0)) { 2775 break; 2776 } 2777 #endif 2778 PHY_FLAGS_SET(unit, pc->port, PHY_FLAGS_FORCED_COPPER); 2779 pc->size = sizeof(PHY8433_PRIV_t); 2780 return SOC_E_NONE; 2781 break; 2782 2783 case PHY_BCM84846_MODEL: 2784 #if 1 2785 if (!soc_property_port_get(unit, pc->port, spn_MACSEC_ENABLE, 0)) { 2786 break; 2787 } 2788 #endif 2789 pc->size = sizeof(PHY8433_PRIV_t); 2790 return SOC_E_NONE; 2791 break; 2792 2793 default: 2794 break; 2795 } 2796 return SOC_E_NOT_FOUND; 2797 } 2798 2799 2800 #ifdef BROADCOM_DEBUG 2801 2802 /* 2803 * Function: 2804 * phy_84334_shadow_dump 2805 * Purpose: 2806 * Debug routine to dump all shadow registers. 2807 * Parameters: 2808 * unit - StrataSwitch unit #. 2809 * port - StrataSwitch port #. 2810 */ 2811 2812 void 2813 phy_84334_shadow_dump(int unit, soc_port_t port) 2814 { 2815 phy_ctrl_t *pc; 2816 uint16 tmp; 2817 int i; 2818 2819 pc = EXT_PHY_SW_STATE(unit, port); 2820 2821 /* Register 0x18 Shadows */ 2822 for (i = 0; i <= 7; i++) { 2823 WRITE_PHY_REG(unit, pc, 0x18, (i << 12) | 0x7); 2824 READ_PHY_REG(unit, pc, 0x18, &tmp); 2825 if ((tmp & ~7) == 0x0000) { 2826 continue; 2827 } 2828 LOG_CLI((BSL_META_U(unit, 2829 "0x18[0x%x]=0x%04x\n"), i, tmp)); 2830 } 2831 2832 /* Register 0x1c Shadows */ 2833 for (i = 0; i <= 0x1f; i++) { 2834 WRITE_PHY_REG(unit, pc, 0x1c, i << 10); 2835 READ_PHY_REG(unit, pc, 0x1c, &tmp); 2836 if ((tmp & ~0x7c00) == 0x0000) { 2837 continue; 2838 } 2839 LOG_CLI((BSL_META_U(unit, 2840 "0x1c[0x%x]=0x%04x\n"), i, tmp)); 2841 } 2842 2843 /* Register 0x17/0x15 Shadows */ 2844 for (i = 0; i <= 0x13; i++) { 2845 WRITE_PHY_REG(unit, pc, 0x17, 0xf00 | i); 2846 READ_PHY_REG(unit, pc, 0x15, &tmp); 2847 if (tmp == 0x0000) { 2848 continue; 2849 } 2850 LOG_CLI((BSL_META_U(unit, 2851 "0x17[0x%x]=0x%04x\n"), i, tmp)); 2852 } 2853 } 2854 2855 #endif /* BROADCOM_DEBUG */ 2856 2857 /* 2858 * Variable: phy_84334drv_ge 2859 * Purpose: PHY driver for 84334 2860 */ 2861 phy_driver_t phy_84334drv_xe = { 2862 "84334 (MACSec PHY) Gigabit PHY Driver", 2863 phy_84334_init, 2864 phy_84334_reset, 2865 phy_84334_link_get, 2866 phy_84334_enable_set, 2867 phy_84334_enable_get, 2868 phy_84334_duplex_set, 2869 phy_84334_duplex_get, 2870 phy_84334_speed_set, 2871 phy_84334_speed_get, 2872 phy_84334_master_set, 2873 phy_84334_master_get, 2874 phy_84334_autoneg_set, 2875 phy_84334_autoneg_get, 2876 NULL, 2877 NULL, 2878 NULL, 2879 phy_84334_lb_set, 2880 phy_84334_lb_get, 2881 phy_null_interface_set, 2882 phy_xehg_interface_get, 2883 NULL, 2884 phy_84334_linkup, /* Phy link up event */ 2885 NULL, /* Phy link down event */ 2886 phy_84334_mdix_set, 2887 phy_84334_mdix_get, 2888 phy_84334_mdix_status_get, 2889 phy_84334_medium_config_set, 2890 phy_84334_medium_config_get, 2891 phy_84334_medium_status, 2892 NULL, /* cable diag */ 2893 NULL, /* phy_link_change */ 2894 phy_84334_control_set, /* phy_control_set */ 2895 phy_84334_control_get, /* phy_control_get */ 2896 NULL, /* phy_ge_reg_read */ 2897 NULL, /* phy_ge_reg_write */ 2898 NULL, /* phy_ge_reg_modify */ 2899 NULL, /* Phy event notify */ 2900 phy_84334_probe, /* pd_probe */ 2901 phy_84334_ability_advert_set, /* pd_ability_advert_set */ 2902 phy_84334_ability_advert_get, /* pd_ability_advert_get */ 2903 phy_84334_ability_remote_get, /* pd_ability_remote_get */ 2904 phy_84334_ability_local_get, /* pd_ability_local_get */ 2905 phy_84334_firmware_set, 2906 phy_84334_timesync_config_set, 2907 phy_84334_timesync_config_get, 2908 phy_84334_timesync_control_set, 2909 phy_84334_timesync_control_get 2910 }; 2911 2912 #else /* INCLUDE_PHY_84334 */ 2913 int _soc_phy_84334_not_empty; 2914 #endif /* INCLUDE_PHY_84334 */ 2915 #endif /* INCLUDE_MACSEC */