phy84749.c (54433B)
1 /* 2 * 3 * 4 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 5 * 6 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 7 */ 8 9 /* 10 * File: phy84749.c 11 * Purpose: SDK PHY driver for BCM84749 (MACSec) 12 * 13 * Supported BCM546X Family of PHY devices: 14 * 15 * Device Ports Media MAC Interface 16 * 84749 4 2 10G SFP+, 2 1G SFP XFI 17 * 18 * Workarounds: 19 * 20 * References: 21 * 22 * Notes: 23 */ 24 25 26 #include <sal/types.h> 27 #include <sal/core/spl.h> 28 #include <shared/bsl.h> 29 #include <soc/drv.h> 30 #include <soc/debug.h> 31 #include <soc/error.h> 32 #include <soc/phyreg.h> 33 34 #include <soc/phy.h> 35 #include <soc/phy/phyctrl.h> 36 #include <soc/phy/drv.h> 37 38 #include "phydefs.h" /* Must include before other phy related includes */ 39 40 41 42 #if defined(INCLUDE_MACSEC) 43 #if defined(INCLUDE_PHY_84749) 44 #include "phyconfig.h" /* Must be the first phy include after phydefs.h */ 45 #include "phyident.h" 46 #include "phyreg.h" 47 #include "phynull.h" 48 #include "phyfege.h" 49 #include "phyxehg.h" 50 #include "phy84749.h" 51 52 #include <soc/macsecphy.h> 53 #include <bmacsec.h> 54 #include <bmacsec_io.h> 55 56 57 #define ADVERT_ALL_COPPER \ 58 (SOC_PA_PAUSE | SOC_PA_SPEED_10MB | \ 59 SOC_PA_SPEED_100MB | SOC_PA_SPEED_1000MB) 60 61 #define ADVERT_ALL_FIBER \ 62 (SOC_PA_PAUSE | SOC_PA_SPEED_1000MB) 63 64 #define ADVERT_ALL_10GFIBER \ 65 (SOC_PA_PAUSE | SOC_PA_SPEED_10GB) 66 67 68 static bmacsec_error_t error_tbl[] = { 69 SOC_E_NONE, 70 SOC_E_INTERNAL, 71 SOC_E_MEMORY, 72 SOC_E_PARAM, 73 SOC_E_EMPTY, 74 SOC_E_FULL, 75 SOC_E_NOT_FOUND, 76 SOC_E_EXISTS, 77 SOC_E_TIMEOUT, 78 SOC_E_FAIL, 79 SOC_E_DISABLED, 80 SOC_E_BADID, 81 SOC_E_RESOURCE, 82 SOC_E_CONFIG, 83 SOC_E_UNAVAIL, 84 SOC_E_INIT, 85 SOC_E_PORT, 86 }; 87 /* 88 * Convert BMACSEC return codes to SOC return code. 89 */ 90 #define SOC_ERROR(e) error_tbl[(-e)] 91 92 #define PHY84749_REG_READ(_unit, _phy_ctrl, _addr, _val) \ 93 READ_PHY_REG((_unit), (_phy_ctrl), (_addr), (_val)) 94 95 #define READ_PHY84749_PMA_PMD_REG(_unit, _phy_ctrl, _reg,_val) \ 96 PHY84749_REG_READ((_unit), (_phy_ctrl), \ 97 SOC_PHY_CLAUSE45_ADDR(1, (_reg)), (_val)) 98 99 100 STATIC int phy_84749_init(int unit, soc_port_t port); 101 STATIC int phy_84749_link_get(int unit, soc_port_t port, int *link); 102 STATIC int phy_84749_enable_set(int unit, soc_port_t port, int enable); 103 STATIC int phy_84749_duplex_set(int unit, soc_port_t port, int duplex); 104 STATIC int phy_84749_duplex_get(int unit, soc_port_t port, int *duplex); 105 STATIC int phy_84749_speed_set(int unit, soc_port_t port, int speed); 106 STATIC int phy_84749_speed_get(int unit, soc_port_t port, int *speed); 107 #if 0 108 STATIC int phy_84749_master_set(int unit, soc_port_t port, int master); 109 STATIC int phy_84749_master_get(int unit, soc_port_t port, int *master); 110 #endif 111 STATIC int phy_84749_an_set(int unit, soc_port_t port, int autoneg); 112 STATIC int phy_84749_an_get(int unit, soc_port_t port, 113 int *autoneg, int *autoneg_done); 114 STATIC int phy_84749_lb_set(int unit, soc_port_t port, int enable); 115 STATIC int phy_84749_lb_get(int unit, soc_port_t port, int *enable); 116 STATIC int phy_84749_medium_config_set(int unit, soc_port_t port, 117 soc_port_medium_t medium, 118 soc_phy_config_t *cfg); 119 STATIC int phy_84749_medium_config_get(int unit, soc_port_t port, 120 soc_port_medium_t medium, 121 soc_phy_config_t *cfg); 122 STATIC int phy_84749_ability_advert_set(int unit, soc_port_t port, 123 soc_port_ability_t *ability); 124 STATIC int phy_84749_ability_advert_get(int unit, soc_port_t port, 125 soc_port_ability_t *ability); 126 STATIC int phy_84749_ability_remote_get(int unit, soc_port_t port, 127 soc_port_ability_t *ability); 128 STATIC int phy_84749_ability_local_get(int unit, soc_port_t port, 129 soc_port_ability_t *ability); 130 STATIC int phy_84749_firmware_set(int unit, int port, int offset, 131 uint8 *data, int len); 132 STATIC int phy_84749_control_set(int unit, soc_port_t port, 133 soc_phy_control_t type, uint32 value); 134 STATIC int phy_84749_control_get(int unit, soc_port_t port, 135 soc_phy_control_t type, uint32 *value); 136 STATIC int phy_84749_linkup(int unit, soc_port_t port); 137 138 /* 139 * Function: 140 * _phy_84749_medium_config_update 141 * Purpose: 142 * Update the PHY with config parameters 143 * Parameters: 144 * unit - StrataSwitch unit #. 145 * port - StrataSwitch port #. 146 * cfg - Config structure. 147 * Returns: 148 * SOC_E_XXX 149 */ 150 151 STATIC int 152 _phy_84749_medium_config_update(int unit, soc_port_t port, 153 soc_phy_config_t *cfg) 154 { 155 156 SOC_IF_ERROR_RETURN 157 (phy_84749_speed_set(unit, port, cfg->force_speed)); 158 SOC_IF_ERROR_RETURN 159 (phy_84749_duplex_set(unit, port, cfg->force_duplex)); 160 SOC_IF_ERROR_RETURN 161 (phy_84749_ability_advert_set(unit, port, &cfg->advert_ability)); 162 SOC_IF_ERROR_RETURN 163 (phy_84749_an_set(unit, port, cfg->autoneg_enable)); 164 165 return SOC_E_NONE; 166 } 167 168 /* Function: 169 * phy_84749_init 170 * Purpose: 171 * Initialize 84749 phys 172 * Parameters: 173 * unit - StrataSwitch unit #. 174 * port - StrataSwitch port #. 175 * Returns: 176 * SOC_E_NONE 177 */ 178 179 STATIC int 180 phy_84749_init(int unit, soc_port_t port) 181 { 182 phy_ctrl_t *pc; 183 bmacsec_dev_addr_t phy_dev_addr; 184 bmacsec_dev_addr_t macsec_dev_addr; 185 int line_mode; 186 int fiber_preferred; 187 int rv = SOC_E_NONE; 188 int macsec_enable = 0, mmi_mdio_addr; 189 int phy_ext_rom_boot; 190 uint32 phy_sys_xaui_tx_lane_map; 191 uint32 phy_sys_xaui_rx_lane_map; 192 char *str; 193 uint16 temp; 194 195 pc = EXT_PHY_SW_STATE(unit, port); 196 197 macsec_dev_addr = 0; 198 199 /* By default MACSEC is disable */ 200 /* Check if enable property is set */ 201 macsec_enable = soc_property_port_get(unit, port, spn_MACSEC_ENABLE, 0); 202 pc->macsec_enable = macsec_enable; 203 204 pc->macsec_dev_port = soc_property_port_get(unit, port, 205 spn_MACSEC_PORT_INDEX, -1); 206 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 207 208 /* Base PHY ID is used to access MACSEC core */ 209 mmi_mdio_addr = soc_property_port_get(unit, port, 210 spn_MACSEC_DEV_ADDR, -1); 211 if (mmi_mdio_addr < 0) { 212 LOG_WARN(BSL_LS_SOC_PHY, 213 (BSL_META_U(unit, 214 "phy_84749_init: " 215 "MACSEC_DEV_ADDR property " 216 "not configured for u=%d p=%d\n"), unit, port)); 217 return SOC_E_CONFIG; 218 } 219 220 macsec_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, mmi_mdio_addr, 1); 221 pc->macsec_dev_addr = macsec_dev_addr; 222 223 rv = bmacsec_phy84749_phy_mac_addr_set(phy_dev_addr, 224 macsec_dev_addr, 225 pc->macsec_dev_port, 226 bmacsec_io_mmi1_cl45); 227 228 229 if(rv != BMACSEC_E_NONE) { 230 LOG_WARN(BSL_LS_SOC_PHY, 231 (BSL_META_U(unit, 232 "phy_84749_init: bmacsec_phy_mac_addr_set " 233 "returned error for u=%d p=%d\n"), unit, port)); 234 return SOC_E_FAIL; 235 } 236 237 phy_ext_rom_boot = soc_property_port_get(unit, port, 238 spn_PHY_EXT_ROM_BOOT, 1); 239 240 LOG_INFO(BSL_LS_SOC_PHY, 241 (BSL_META_U(unit, 242 "phy_84749_init: u=%d p=%d\n"),unit, port)); 243 244 /* Preferred mode: 245 * phy_fiber_pref = 1 ; Port is in SFI mode in 10G Default 246 * when speed is changed to 1G, its 1000X 247 * phy_fiber_pref = 0; Port is in SGMII mode, allows only 1G/100M/10M 248 */ 249 fiber_preferred = 250 soc_property_port_get(unit, port, spn_PHY_FIBER_PREF, 1); 251 252 /* Initially configure for the preferred medium. */ 253 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER); 254 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 255 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_PASSTHRU); 256 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX); 257 258 if (fiber_preferred) { 259 line_mode = BMACSEC_PHY84749_INTF_SFI; 260 pc->copper.enable = FALSE; 261 pc->fiber.enable = TRUE; 262 pc->interface = SOC_PORT_IF_XFI; 263 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 264 } else { 265 pc->interface = SOC_PORT_IF_SGMII; 266 line_mode = BMACSEC_PHY84749_INTF_SGMII; 267 pc->copper.enable = TRUE; 268 pc->fiber.enable = FALSE; 269 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 270 } 271 PHY_FLAGS_SET(unit, port, PHY_FLAGS_C45); 272 273 pc->copper.preferred = !fiber_preferred; 274 pc->copper.autoneg_enable = TRUE; 275 pc->copper.autoneg_advert = ADVERT_ALL_COPPER; 276 pc->copper.force_speed = 1000; 277 pc->copper.force_duplex = TRUE; 278 pc->copper.master = SOC_PORT_MS_AUTO; 279 pc->copper.mdix = SOC_PORT_MDIX_AUTO; 280 281 pc->fiber.preferred = TRUE; 282 pc->fiber.autoneg_enable = FALSE; 283 pc->fiber.autoneg_advert = ADVERT_ALL_FIBER; 284 pc->fiber.force_speed = 10000; 285 pc->fiber.force_duplex = TRUE; 286 pc->fiber.master = SOC_PORT_MS_NONE; 287 pc->fiber.mdix = SOC_PORT_MDIX_NORMAL; 288 289 /* XAUI RX Lane Swap (Lane A, B, C, D changes to Lane D, C, B, A) */ 290 str = soc_property_port_get_str(unit, port, spn_PHY_XAUI_RX_LANE_SWAP); 291 if (str != NULL) { 292 temp = soc_property_port_get(unit, port, 293 spn_PHY_XAUI_RX_LANE_SWAP, 0); 294 } else { 295 temp = 0; 296 } 297 phy_sys_xaui_rx_lane_map = (temp) ? 0x3210 : 0; 298 299 300 /* XAUI TX Lane Swap (Lane A, B, C, D changes to Lane D, C, B, A) */ 301 str = soc_property_port_get_str(unit, port, spn_PHY_XAUI_TX_LANE_SWAP); 302 if (str != NULL) { 303 temp = soc_property_port_get(unit, port, 304 spn_PHY_XAUI_TX_LANE_SWAP, 0); 305 } else { 306 temp = 0; 307 } 308 phy_sys_xaui_tx_lane_map = (temp) ? 0x3210 : 0; 309 310 311 312 /* Init PHYS and MACs to defaults */ 313 rv = bmacsec_phy84749_init(phy_dev_addr, 1, 314 line_mode, 315 macsec_enable, 316 phy_sys_xaui_tx_lane_map, 317 phy_sys_xaui_rx_lane_map, 318 phy_ext_rom_boot); 319 320 if (rv != BMACSEC_E_NONE) { 321 return SOC_E_FAIL; 322 } 323 324 #if 0 325 /* Use lane mapping */ 326 SOC_IF_ERROR_RETURN( 327 bsdk_phy84728_lane_map(pc)); 328 #endif 329 330 331 /* Get Requested LED selectors (defaults are hardware defaults) */ 332 pc->ledmode[0] = soc_property_port_get(unit, port, spn_PHY_LED1_MODE, 0); 333 pc->ledmode[1] = soc_property_port_get(unit, port, spn_PHY_LED2_MODE, 1); 334 pc->ledmode[2] = soc_property_port_get(unit, port, spn_PHY_LED3_MODE, 3); 335 pc->ledmode[3] = soc_property_port_get(unit, port, spn_PHY_LED4_MODE, 6); 336 pc->ledctrl = soc_property_port_get(unit, port, spn_PHY_LED_CTRL, 0x8); 337 pc->ledselect = soc_property_port_get(unit, port, spn_PHY_LED_SELECT, 0); 338 339 /* 340 * Some reasonable defaults 341 */ 342 pc->macsec_switch_fixed = 0; 343 pc->macsec_switch_fixed_speed = 10000; 344 pc->macsec_switch_fixed_duplex = 1; 345 pc->macsec_switch_fixed_pause = 1; 346 pc->macsec_pause_rx_fwd = 0; 347 pc->macsec_pause_tx_fwd = 0; 348 pc->macsec_line_ipg = 0xc; 349 pc->macsec_switch_ipg = 0xc; 350 351 352 if (line_mode != BMACSEC_PHY84749_INTF_SGMII) { 353 SOC_IF_ERROR_RETURN 354 (_phy_84749_medium_config_update(unit, port, 355 PHY_COPPER_MODE(unit, port) ? 356 &pc->copper : 357 &pc->fiber)); 358 } 359 360 if (IS_HG_PORT(unit, port)) { 361 rv = bmacsec_phy84749_higig_mode(phy_dev_addr, 1); 362 if (rv != BMACSEC_E_NONE) { 363 return SOC_E_FAIL; 364 } 365 } 366 367 if (macsec_enable) { 368 rv = soc_macsecphy_init(unit, port, pc, 369 BMACSEC_CORE_BCM84749, bmacsec_io_mmi1_cl45); 370 if (!SOC_SUCCESS(rv)) { 371 LOG_ERROR(BSL_LS_SOC_PHY, 372 (BSL_META_U(unit, 373 "soc_macsecphy_init: MACSEC init for" 374 " u=%d p=%d FAILED "), unit, port)); 375 } else { 376 LOG_INFO(BSL_LS_SOC_PHY, 377 (BSL_META_U(unit, 378 "soc_macsecphy_init: MACSEC init for" 379 " u=%d p=%d SUCCESS "), unit, port)); 380 } 381 } 382 383 384 return SOC_E_NONE; 385 } 386 387 388 /* 389 * Function: 390 * phy_84749_link_get 391 * Purpose: 392 * Get layer2 connection status. 393 * Parameters: 394 * unit - StrataSwitch unit #. 395 * port - StrataSwitch port #. 396 * link - address of memory to store link up/down state. 397 * Returns: 398 * SOC_E_NONE 399 */ 400 401 STATIC int 402 phy_84749_link_get(int unit, soc_port_t port, int *link) 403 { 404 phy_ctrl_t *pc; 405 int rv = SOC_E_NONE; 406 bmacsec_dev_addr_t phy_dev_addr; 407 bmacsec_phy84749_intf_t bmacsec_mode; 408 int bmacsec_link; 409 410 pc = EXT_PHY_SW_STATE(unit, port); 411 *link = FALSE; /* Default return */ 412 413 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 414 return SOC_E_NONE; 415 } 416 417 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 418 419 rv = bmacsec_phy84749_line_intf_get(phy_dev_addr, 0, &bmacsec_mode); 420 if (!BMACSEC_E_SUCCESS(rv)) { 421 return SOC_E_FAIL; 422 } 423 424 if (bmacsec_mode == BMACSEC_PHY84749_INTF_SGMII) { 425 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 426 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 427 } else { 428 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 429 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER); 430 } 431 432 rv = bmacsec_phy84749_link_get(phy_dev_addr, &bmacsec_link); 433 if (!BMACSEC_E_SUCCESS(rv)) { 434 return SOC_E_FAIL; 435 } 436 if (bmacsec_link) { 437 *link = TRUE; 438 } else { 439 *link = FALSE; 440 } 441 442 LOG_VERBOSE(BSL_LS_SOC_PHY, 443 (BSL_META_U(unit, 444 "phy_84749_link_get: u=%d p=%d link=%d\n"), 445 unit, port, 446 *link)); 447 448 return SOC_E_NONE; 449 } 450 451 /* 452 * Function: 453 * phy_84749_enable_set 454 * Purpose: 455 * Enable or disable the physical interface. 456 * Parameters: 457 * unit - StrataSwitch unit #. 458 * port - StrataSwitch port #. 459 * enable - Boolean, true = enable PHY, false = disable. 460 * Returns: 461 * SOC_E_XXX 462 */ 463 464 STATIC int 465 phy_84749_enable_set(int unit, soc_port_t port, int enable) 466 { 467 phy_ctrl_t *pc; 468 int rv = SOC_E_NONE; 469 bmacsec_dev_addr_t phy_dev_addr; 470 471 pc = EXT_PHY_SW_STATE(unit, port); 472 473 if (enable) { 474 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE); 475 } else { 476 PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE); 477 } 478 479 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 480 481 rv = bmacsec_phy84749_enable_set(phy_dev_addr, enable); 482 483 if(rv != BMACSEC_E_NONE) { 484 return SOC_E_FAIL; 485 } 486 487 LOG_INFO(BSL_LS_SOC_PHY, 488 (BSL_META_U(unit, 489 "phy_84749_enable_set: " 490 "Power %s fiber medium\n"), (enable) ? "up" : "down")); 491 492 return SOC_E_NONE; 493 } 494 495 /* 496 * Function: 497 * phy_84749_duplex_set 498 * Purpose: 499 * Set the current duplex mode 500 * Parameters: 501 * unit - StrataSwitch unit #. 502 * port - StrataSwitch port #. 503 * duplex - Boolean, true indicates full duplex, false indicates half. 504 * Returns: 505 * SOC_E_NONE 506 * SOC_E_UNAVAIL - Half duplex requested, and not supported. 507 * Notes: 508 */ 509 STATIC int 510 phy_84749_duplex_set(int unit, soc_port_t port, int duplex) 511 { 512 int rv; 513 phy_ctrl_t *pc; 514 bmacsec_dev_addr_t phy_dev_addr; 515 bmacsec_phy84749_duplex_t bmacsec_duplex; 516 517 pc = EXT_PHY_SW_STATE(unit, port); 518 519 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 520 521 if (duplex) { 522 bmacsec_duplex = BMACSEC_PHY84749_FULL_DUPLEX; 523 } else { 524 bmacsec_duplex = BMACSEC_PHY84749_HALF_DUPLEX; 525 } 526 rv = bmacsec_phy84749_duplex_set(phy_dev_addr, bmacsec_duplex); 527 528 if(BMACSEC_E_SUCCESS(rv)) { 529 pc->copper.force_duplex = duplex; 530 } 531 532 LOG_INFO(BSL_LS_SOC_PHY, 533 (BSL_META_U(unit, 534 "phy_84749_duplex_set: u=%d p=%d d=%d rv=%d\n"), 535 unit, port, duplex, rv)); 536 return (SOC_ERROR(rv)); 537 } 538 539 /* 540 * Function: 541 * phy_84749_duplex_get 542 * Purpose: 543 * Get the current operating duplex mode. If autoneg is enabled, 544 * then operating mode is returned, otherwise forced mode is returned. 545 * Parameters: 546 * unit - StrataSwitch unit #. 547 * port - StrataSwitch port #. 548 * duplex - (OUT) Boolean, true indicates full duplex, false 549 * indicates half. 550 * Returns: 551 * SOC_E_NONE 552 * Notes: 553 * The duplex is retrieved for the ACTIVE medium. 554 * No synchronization performed at this level. Autonegotiation is 555 * not manipulated. 556 */ 557 558 STATIC int 559 phy_84749_duplex_get(int unit, soc_port_t port, int *duplex) 560 { 561 562 int rv = SOC_E_NONE; 563 phy_ctrl_t *pc; 564 bmacsec_dev_addr_t phy_dev_addr; 565 bmacsec_phy84749_duplex_t bmacsec_duplex; 566 567 pc = EXT_PHY_SW_STATE(unit, port); 568 569 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 570 571 rv = bmacsec_phy84749_duplex_get(phy_dev_addr, &bmacsec_duplex); 572 if (rv != BMACSEC_E_NONE) { 573 return SOC_E_FAIL; 574 } 575 if (bmacsec_duplex == BMACSEC_PHY84749_FULL_DUPLEX) { 576 *duplex = TRUE; 577 } else { 578 *duplex = FALSE; 579 } 580 581 LOG_INFO(BSL_LS_SOC_PHY, 582 (BSL_META_U(unit, 583 "phy_84749_duplex_get: u=%d p=%d d=%d rv=%d\n"), 584 unit, port, *duplex, rv)); 585 return SOC_E_NONE; 586 } 587 588 589 /* 590 * Function: 591 * phy_84749_speed_set 592 * Purpose: 593 * Set PHY speed 594 * Parameters: 595 * unit - StrataSwitch unit #. 596 * port - StrataSwitch port #. 597 * speed - link speed in Mbps 598 * Returns: 599 * SOC_E_NONE 600 */ 601 STATIC int 602 phy_84749_speed_set(int unit, soc_port_t port, int speed) 603 { 604 phy_ctrl_t *pc; 605 phy_ctrl_t *int_pc; 606 int rv; 607 bmacsec_dev_addr_t phy_dev_addr; 608 609 pc = EXT_PHY_SW_STATE(unit, port); 610 int_pc = INT_PHY_SW_STATE(unit, port); 611 rv = SOC_E_NONE; 612 613 if (speed > 10000) { 614 return SOC_E_UNAVAIL; 615 } 616 617 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 618 619 if(PHY_FIBER_MODE(unit, port)) { 620 if (speed < 1000) { 621 return SOC_E_UNAVAIL; 622 } 623 } 624 625 rv = bmacsec_phy84749_speed_set(phy_dev_addr, speed); 626 if(BMACSEC_E_SUCCESS(rv)) { 627 if (NULL != int_pc) { 628 PHY_AUTO_NEGOTIATE_SET (int_pc->pd, unit, port, 0); 629 PHY_SPEED_SET(int_pc->pd, unit, port, speed); 630 } 631 if(PHY_COPPER_MODE(unit, port)) { 632 pc->copper.force_speed = speed; 633 } else { 634 if(PHY_FIBER_MODE(unit, port)) { 635 pc->fiber.force_speed = speed; 636 } 637 } 638 } 639 LOG_INFO(BSL_LS_SOC_PHY, 640 (BSL_META_U(unit, 641 "phy_84749_speed_set: u=%d p=%d s=%d fiber=%d rv=%d\n"), 642 unit, port, speed, PHY_FIBER_MODE(unit, port), rv)); 643 644 return SOC_ERROR(rv); 645 } 646 647 /* 648 * Function: 649 * phy_84749_speed_get 650 * Purpose: 651 * Get the current operating speed for a 84749 device. 652 * Parameters: 653 * unit - StrataSwitch unit #. 654 * port - StrataSwitch port #. 655 * speed - (OUT) Speed of the phy 656 * Returns: 657 * SOC_E_NONE 658 * Notes: 659 * The speed is retrieved for the ACTIVE medium. 660 */ 661 662 STATIC int 663 phy_84749_speed_get(int unit, soc_port_t port, int *speed) 664 { 665 int rv = SOC_E_NONE; 666 bmacsec_dev_addr_t phy_dev_addr; 667 phy_ctrl_t *pc; 668 669 pc = EXT_PHY_SW_STATE(unit, port); 670 671 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 672 673 rv = bmacsec_phy84749_speed_get(phy_dev_addr, speed); 674 675 if(!BMACSEC_E_SUCCESS(rv)) { 676 LOG_WARN(BSL_LS_SOC_PHY, 677 (BSL_META_U(unit, 678 "phy_84749_speed_get: u=%d p=%d invalid speed\n"), 679 unit, port)); 680 } else { 681 LOG_INFO(BSL_LS_SOC_PHY, 682 (BSL_META_U(unit, 683 "phy_84749_speed_get: u=%d p=%d speed=%d"), 684 unit, port, *speed)); 685 } 686 687 return SOC_ERROR(rv); 688 } 689 690 /* 691 * Function: 692 * phy_84749_an_set 693 * Purpose: 694 * Enable or disable auto-negotiation on the specified port. 695 * Parameters: 696 * unit - StrataSwitch unit #. 697 * port - StrataSwitch port #. 698 * autoneg - Boolean, if true, auto-negotiation is enabled 699 * (and/or restarted). If false, autonegotiation is disabled. 700 * Returns: 701 * SOC_E_XXX 702 * Notes: 703 * The autoneg mode is set only for the ACTIVE medium. 704 */ 705 706 STATIC int 707 phy_84749_an_set(int unit, soc_port_t port, int autoneg) 708 { 709 int rv; 710 phy_ctrl_t *pc; 711 int autoneg_advert = 0; 712 bmacsec_dev_addr_t phy_dev_addr; 713 714 pc = EXT_PHY_SW_STATE(unit, port); 715 rv = SOC_E_NONE; 716 717 if(PHY_COPPER_MODE(unit, port)) { 718 autoneg_advert = 0; 719 } else { 720 if(PHY_FIBER_MODE(unit, port)) { 721 autoneg_advert = pc->fiber.autoneg_advert; 722 } 723 } 724 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 725 726 rv = bmacsec_phy84749_an_set(phy_dev_addr, autoneg, autoneg_advert); 727 if(BMACSEC_E_SUCCESS(rv)) { 728 if(PHY_COPPER_MODE(unit, port)) { 729 pc->copper.autoneg_enable = autoneg ? TRUE : FALSE; 730 } else { 731 if(PHY_FIBER_MODE(unit, port)) { 732 pc->fiber.autoneg_enable = autoneg ? TRUE : FALSE; 733 } 734 } 735 } 736 737 LOG_INFO(BSL_LS_SOC_PHY, 738 (BSL_META_U(unit, 739 "phy_84749_an_set: u=%d p=%d autoneg=%d rv=%d\n"), 740 unit, port, autoneg, rv)); 741 return SOC_ERROR(rv); 742 } 743 744 /* 745 * Function: 746 * phy_84749_an_get 747 * Purpose: 748 * Get the current auto-negotiation status (enabled/busy). 749 * Parameters: 750 * unit - StrataSwitch unit #. 751 * port - StrataSwitch port #. 752 * autoneg - (OUT) if true, auto-negotiation is enabled. 753 * autoneg_done - (OUT) if true, auto-negotiation is complete. This 754 * value is undefined if autoneg == FALSE. 755 * Returns: 756 * SOC_E_XXX 757 * Notes: 758 * The autoneg mode is retrieved for the ACTIVE medium. 759 */ 760 761 STATIC int 762 phy_84749_an_get(int unit, soc_port_t port, 763 int *autoneg, int *autoneg_done) 764 { 765 int rv; 766 phy_ctrl_t *pc; 767 bmacsec_dev_addr_t phy_dev_addr; 768 769 pc = EXT_PHY_SW_STATE(unit, port); 770 771 rv = SOC_E_NONE; 772 *autoneg = FALSE; 773 *autoneg_done = FALSE; 774 775 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 776 777 rv = bmacsec_phy84749_an_get(phy_dev_addr, autoneg, autoneg_done); 778 779 return SOC_ERROR(rv); 780 } 781 782 /* 783 * Function: 784 * phy_84749_lb_set 785 * Purpose: 786 * Set the local PHY loopback mode. 787 * Parameters: 788 * unit - StrataSwitch unit #. 789 * port - StrataSwitch port #. 790 * loopback - Boolean: true = enable loopback, false = disable. 791 * Returns: 792 * SOC_E_XXX 793 * Notes: 794 * The loopback mode is set only for the ACTIVE medium. 795 * No synchronization performed at this level. 796 */ 797 798 STATIC int 799 phy_84749_lb_set(int unit, soc_port_t port, int enable) 800 { 801 int rv; 802 #if 0 803 int link = 0; 804 soc_timeout_t to; 805 #endif 806 phy_ctrl_t *pc; 807 bmacsec_dev_addr_t phy_dev_addr; 808 809 pc = EXT_PHY_SW_STATE(unit, port); 810 rv = SOC_E_NONE; 811 812 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 813 814 rv = bmacsec_phy84749_loopback_set(phy_dev_addr, enable); 815 816 if (rv == BMACSEC_E_NONE) { 817 /* wait for link up when loopback is enabled */ 818 819 if (enable) { 820 sal_usleep(2000000); 821 } 822 } 823 824 LOG_INFO(BSL_LS_SOC_PHY, 825 (BSL_META_U(unit, 826 "phy_84749_lb_set: u=%d p=%d en=%d rv=%d\n"), 827 unit, port, enable, rv)); 828 829 return SOC_ERROR(rv); 830 } 831 832 /* 833 * Function: 834 * phy_84749_lb_get 835 * Purpose: 836 * Get the local PHY loopback mode. 837 * Parameters: 838 * unit - StrataSwitch unit #. 839 * port - StrataSwitch port #. 840 * loopback - (OUT) Boolean: true = enable loopback, false = disable. 841 * Returns: 842 * SOC_E_XXX 843 * Notes: 844 * The loopback mode is retrieved for the ACTIVE medium. 845 */ 846 847 STATIC int 848 phy_84749_lb_get(int unit, soc_port_t port, int *enable) 849 { 850 int rv; 851 phy_ctrl_t *pc; 852 bmacsec_dev_addr_t phy_dev_addr; 853 854 pc = EXT_PHY_SW_STATE(unit, port); 855 rv = SOC_E_NONE; 856 857 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 858 859 rv = bmacsec_phy84749_loopback_get(phy_dev_addr, enable); 860 861 return SOC_ERROR(rv); 862 } 863 864 /* 865 * Function: 866 * phy_84749_medium_config_set 867 * Purpose: 868 * Set the operating parameters that are automatically selected 869 * when medium switches type. 870 * Parameters: 871 * unit - StrataSwitch unit # 872 * port - Port number 873 * medium - SOC_PORT_MEDIUM_COPPER/FIBER 874 * cfg - Operating parameters 875 * Returns: 876 * SOC_E_XXX 877 */ 878 879 STATIC int 880 phy_84749_medium_config_set(int unit, soc_port_t port, 881 soc_port_medium_t medium, 882 soc_phy_config_t *cfg) 883 { 884 phy_ctrl_t *pc; 885 #if 0 886 soc_phy_config_t *active_medium; /* Currently active medium */ 887 #endif 888 soc_phy_config_t *change_medium; /* Requested medium */ 889 soc_phy_config_t *other_medium; /* The other medium */ 890 891 soc_port_mode_t advert_mask; 892 893 if (NULL == cfg) { 894 return SOC_E_PARAM; 895 } 896 897 pc = EXT_PHY_SW_STATE(unit, port); 898 899 switch (medium) { 900 case SOC_PORT_MEDIUM_COPPER: 901 if (!pc->automedium && !PHY_COPPER_MODE(unit, port)) { 902 return SOC_E_UNAVAIL; 903 } 904 change_medium = &pc->copper; 905 other_medium = &pc->fiber; 906 advert_mask = ADVERT_ALL_COPPER; 907 break; 908 case SOC_PORT_MEDIUM_FIBER: 909 if (!pc->automedium && !PHY_FIBER_MODE(unit, port)) { 910 return SOC_E_UNAVAIL; 911 } 912 change_medium = &pc->fiber; 913 other_medium = &pc->copper; 914 advert_mask = ADVERT_ALL_FIBER; 915 break; 916 default: 917 return SOC_E_PARAM; 918 } 919 920 /* 921 * Changes take effect immediately if the target medium is active or 922 * the preferred medium changes. 923 */ 924 if (change_medium->enable != cfg->enable) { 925 } 926 if (change_medium->preferred != cfg->preferred) { 927 /* Make sure that only one medium is preferred */ 928 other_medium->preferred = !cfg->preferred; 929 } 930 931 sal_memcpy(change_medium, cfg, sizeof(*change_medium)); 932 change_medium->autoneg_advert &= advert_mask; 933 934 #if 0 935 if (medium_update) { 936 /* The new configuration may cause medium change. Check 937 * and update medium. 938 */ 939 SOC_IF_ERROR_RETURN 940 (_phy_84749_medium_change(unit, port, TRUE, medium)); 941 } else { 942 active_medium = (PHY_COPPER_MODE(unit, port)) ? 943 &pc->copper : &pc->fiber; 944 if (active_medium == change_medium) { 945 /* If the medium to update is active, update the configuration */ 946 SOC_IF_ERROR_RETURN 947 (_phy_84749_medium_config_update(unit, port, change_medium)); 948 } 949 } 950 #endif 951 return SOC_E_NONE; 952 } 953 954 /* 955 * Function: 956 * phy_84749_medium_config_get 957 * Purpose: 958 * Get the operating parameters that are automatically selected 959 * when medium switches type. 960 * Parameters: 961 * unit - StrataSwitch unit # 962 * port - Port number 963 * medium - SOC_PORT_MEDIUM_COPPER/FIBER 964 * cfg - (OUT) Operating parameters 965 * Returns: 966 * SOC_E_XXX 967 */ 968 969 STATIC int 970 phy_84749_medium_config_get(int unit, soc_port_t port, 971 soc_port_medium_t medium, 972 soc_phy_config_t *cfg) 973 { 974 int rv; 975 phy_ctrl_t *pc; 976 977 pc = EXT_PHY_SW_STATE(unit, port); 978 rv = SOC_E_NONE; 979 980 switch (medium) { 981 case SOC_PORT_MEDIUM_COPPER: 982 if (pc->automedium || PHY_COPPER_MODE(unit, port)) { 983 sal_memcpy(cfg, &pc->copper, sizeof (*cfg)); 984 } else { 985 rv = SOC_E_UNAVAIL; 986 } 987 break; 988 case SOC_PORT_MEDIUM_FIBER: 989 if (pc->automedium || PHY_FIBER_MODE(unit, port)) { 990 sal_memcpy(cfg, &pc->fiber, sizeof (*cfg)); 991 } else { 992 rv = SOC_E_UNAVAIL; 993 } 994 break; 995 default: 996 rv = SOC_E_PARAM; 997 break; 998 } 999 1000 return rv; 1001 } 1002 1003 /* 1004 * Function: 1005 * phy_84749_ability_advert_set 1006 * Purpose: 1007 * Set the current advertisement for auto-negotiation. 1008 * Parameters: 1009 * unit - StrataSwitch unit #. 1010 * port - StrataSwitch port #. 1011 * mode - Port mode mask indicating supported options/speeds. 1012 * Returns: 1013 * SOC_E_XXX 1014 * Notes: 1015 * The advertisement is set only for the ACTIVE medium. 1016 * No synchronization performed at this level. 1017 */ 1018 STATIC int 1019 phy_84749_ability_advert_set(int unit, soc_port_t port,soc_port_ability_t *ability) 1020 { 1021 int rv; 1022 phy_ctrl_t *pc; 1023 bmacsec_phy84749_port_ability_t local_ability; 1024 bmacsec_dev_addr_t phy_dev_addr; 1025 1026 pc = EXT_PHY_SW_STATE(unit, port); 1027 1028 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 1029 return SOC_E_NONE; 1030 } 1031 1032 if (NULL == ability) { 1033 return (SOC_E_PARAM); 1034 } 1035 1036 if (PHY_COPPER_MODE(unit, port)) { 1037 pc->copper.advert_ability = *ability; 1038 } else { 1039 pc->fiber.advert_ability = *ability; 1040 } 1041 1042 local_ability = 0; 1043 1044 if(ability->speed_full_duplex & SOC_PA_SPEED_1000MB) { 1045 local_ability |= BMACSEC_PHY84749_PA_1000MB_FD; 1046 } 1047 if(ability->speed_full_duplex & SOC_PA_SPEED_10GB) { 1048 local_ability |= BMACSEC_PHY84749_PA_10000MB_FD; 1049 } 1050 1051 if(ability->pause & SOC_PA_PAUSE_TX) { 1052 local_ability |= BMACSEC_PHY84749_PA_PAUSE_TX; 1053 } 1054 if(ability->pause & SOC_PA_PAUSE_RX) { 1055 local_ability |= BMACSEC_PHY84749_PA_PAUSE_RX; 1056 } 1057 if(ability->pause & SOC_PA_PAUSE_ASYMM) { 1058 local_ability |= BMACSEC_PHY84749_PA_PAUSE_ASYMM; 1059 } 1060 1061 if(ability->loopback & SOC_PA_LB_NONE) { 1062 local_ability |= BMACSEC_PHY84749_PA_LB_NONE; 1063 } 1064 if(ability->loopback & SOC_PA_LB_PHY) { 1065 local_ability |= BMACSEC_PHY84749_PA_LB_PHY; 1066 } 1067 if(ability->flags & SOC_PA_AUTONEG) { 1068 local_ability |= BMACSEC_PHY84749_PA_AN; 1069 } 1070 1071 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1072 1073 rv = bmacsec_phy84749_ability_advert_set(phy_dev_addr, local_ability); 1074 1075 1076 return SOC_ERROR(rv); 1077 } 1078 1079 /* 1080 * Function: 1081 * phy_84749_ability_advert_get 1082 * Purpose: 1083 * Get the current advertisement for auto-negotiation. 1084 * Parameters: 1085 * unit - StrataSwitch unit #. 1086 * port - StrataSwitch port #. 1087 * mode - (OUT) Port mode mask indicating supported options/speeds. 1088 * Returns: 1089 * SOC_E_XXX 1090 * Notes: 1091 * The advertisement is retrieved for the ACTIVE medium. 1092 * No synchronization performed at this level. 1093 */ 1094 STATIC int 1095 phy_84749_ability_advert_get(int unit, soc_port_t port,soc_port_ability_t *ability) 1096 { 1097 phy_ctrl_t *pc; 1098 int rv; 1099 bmacsec_phy84749_port_ability_t local_ability; 1100 bmacsec_dev_addr_t phy_dev_addr; 1101 1102 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 1103 return SOC_E_NONE; 1104 } 1105 1106 if (NULL == ability) { 1107 return (SOC_E_PARAM); 1108 } 1109 1110 pc = EXT_PHY_SW_STATE(unit, port); 1111 1112 local_ability = 0; 1113 1114 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1115 1116 rv = bmacsec_phy84749_ability_advert_get(phy_dev_addr, &local_ability); 1117 if (rv != BMACSEC_E_NONE) { 1118 return SOC_E_FAIL; 1119 } 1120 1121 if(local_ability & BMACSEC_PHY84749_PA_1000MB_FD) { 1122 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 1123 } 1124 if(local_ability & BMACSEC_PHY84749_PA_10000MB_FD) { 1125 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 1126 } 1127 1128 if(local_ability & BMACSEC_PHY84749_PA_PAUSE_TX) { 1129 ability->pause |= SOC_PA_PAUSE_TX; 1130 } 1131 if(local_ability & BMACSEC_PHY84749_PA_PAUSE_RX) { 1132 ability->pause |= SOC_PA_PAUSE_RX; 1133 } 1134 if(local_ability & BMACSEC_PHY84749_PA_PAUSE_ASYMM) { 1135 ability->pause |= SOC_PA_PAUSE_ASYMM; 1136 } 1137 1138 if(local_ability & BMACSEC_PHY84749_PA_LB_NONE) { 1139 ability->loopback |= SOC_PA_LB_NONE; 1140 } 1141 if(local_ability & BMACSEC_PHY84749_PA_LB_PHY) { 1142 ability->loopback |= SOC_PA_LB_PHY; 1143 } 1144 if(local_ability & BMACSEC_PHY84749_PA_AN) { 1145 ability->flags = SOC_PA_AUTONEG; 1146 } 1147 1148 return SOC_E_NONE; 1149 } 1150 1151 /* 1152 * Function: 1153 * phy_84749_ability_remote_get 1154 * Purpose: 1155 * Get the current remote advertisement for auto-negotiation. 1156 * Parameters: 1157 * unit - StrataSwitch unit #. 1158 * port - StrataSwitch port #. 1159 * mode - (OUT) Port mode mask indicating supported options/speeds. 1160 * Returns: 1161 * SOC_E_XXX 1162 * Notes: 1163 * The advertisement is retrieved for the ACTIVE medium. 1164 * No synchronization performed at this level. 1165 */ 1166 STATIC int 1167 phy_84749_ability_remote_get(int unit, soc_port_t port,soc_port_ability_t *ability) 1168 { 1169 phy_ctrl_t *pc; 1170 int rv; 1171 bmacsec_phy84749_port_ability_t remote_ability; 1172 bmacsec_dev_addr_t phy_dev_addr; 1173 1174 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 1175 return SOC_E_NONE; 1176 } 1177 1178 if (NULL == ability) { 1179 return (SOC_E_PARAM); 1180 } 1181 1182 pc = EXT_PHY_SW_STATE(unit, port); 1183 1184 remote_ability = 0; 1185 1186 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1187 1188 rv = bmacsec_phy84749_remote_ability_advert_get(phy_dev_addr, 1189 &remote_ability); 1190 if (rv != BMACSEC_E_NONE) { 1191 return SOC_E_FAIL; 1192 } 1193 1194 if(remote_ability & BMACSEC_PHY84749_PA_1000MB_FD) { 1195 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 1196 } 1197 if(remote_ability & BMACSEC_PHY84749_PA_10000MB_FD) { 1198 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 1199 } 1200 1201 if(remote_ability & BMACSEC_PHY84749_PA_PAUSE_TX) { 1202 ability->pause |= SOC_PA_PAUSE_TX; 1203 } 1204 if(remote_ability & BMACSEC_PHY84749_PA_PAUSE_RX) { 1205 ability->pause |= SOC_PA_PAUSE_RX; 1206 } 1207 if(remote_ability & BMACSEC_PHY84749_PA_PAUSE_ASYMM) { 1208 ability->pause |= SOC_PA_PAUSE_ASYMM; 1209 } 1210 1211 if(remote_ability & BMACSEC_PHY84749_PA_LB_NONE) { 1212 ability->loopback |= SOC_PA_LB_NONE; 1213 } 1214 if(remote_ability & BMACSEC_PHY84749_PA_LB_PHY) { 1215 ability->loopback |= SOC_PA_LB_PHY; 1216 } 1217 if(remote_ability & BMACSEC_PHY84749_PA_AN) { 1218 ability->flags = SOC_PA_AUTONEG; 1219 } 1220 1221 return SOC_E_NONE; 1222 } 1223 1224 1225 1226 /* 1227 * Function: 1228 * phy_84749_ability_local_get 1229 * Purpose: 1230 * Get local abilities 1231 * Parameters: 1232 * unit - StrataSwitch unit #. 1233 * port - StrataSwitch port #. 1234 * mode - (OUT) Port mode mask indicating supported options/speeds. 1235 * Returns: 1236 * SOC_E_NONE 1237 * Notes: 1238 * The ability is retrieved only for the ACTIVE medium. 1239 */ 1240 1241 STATIC int 1242 phy_84749_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability) 1243 { 1244 int rv = SOC_E_NONE; 1245 phy_ctrl_t *pc; 1246 bmacsec_phy84749_port_ability_t local_ability = 0; 1247 bmacsec_dev_addr_t phy_dev_addr; 1248 1249 if (NULL == ability) { 1250 return SOC_E_PARAM; 1251 } 1252 1253 pc = EXT_PHY_SW_STATE(unit, port); 1254 1255 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1256 1257 rv = bmacsec_phy84749_ability_local_get(phy_dev_addr, &local_ability); 1258 if (rv != BMACSEC_E_NONE) { 1259 return SOC_E_FAIL; 1260 } 1261 1262 if(local_ability & BMACSEC_PHY84749_PA_1000MB_FD) { 1263 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 1264 } 1265 if(local_ability & BMACSEC_PHY84749_PA_10000MB_FD) { 1266 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 1267 } 1268 1269 if(local_ability & BMACSEC_PHY84749_PA_PAUSE_TX) { 1270 ability->pause |= SOC_PA_PAUSE_TX; 1271 } 1272 if(local_ability & BMACSEC_PHY84749_PA_PAUSE_RX) { 1273 ability->pause |= SOC_PA_PAUSE_RX; 1274 } 1275 if(local_ability & BMACSEC_PHY84749_PA_PAUSE_ASYMM) { 1276 ability->pause |= SOC_PA_PAUSE_ASYMM; 1277 } 1278 1279 1280 if(local_ability & BMACSEC_PHY84749_PA_LB_NONE) { 1281 ability->loopback |= SOC_PA_LB_NONE; 1282 } 1283 if(local_ability & BMACSEC_PHY84749_PA_LB_PHY) { 1284 ability->loopback |= SOC_PA_LB_PHY; 1285 } 1286 if(local_ability & BMACSEC_PHY84749_PA_AN) { 1287 ability->flags = SOC_PA_AUTONEG; 1288 } 1289 1290 return SOC_E_NONE; 1291 } 1292 1293 /* 1294 * Function: 1295 * phy_84749_firmware_set 1296 * Purpose: 1297 * program the given firmware into the SPI-ROM 1298 * Parameters: 1299 * unit - StrataSwitch unit #. 1300 * port - StrataSwitch port #. 1301 * offset - offset to the data stream 1302 * array - the given data 1303 * datalen- the data length 1304 * Returns: 1305 * SOC_E_NONE 1306 */ 1307 1308 STATIC int 1309 phy_84749_firmware_set(int unit, int port, int offset, uint8 *data,int len) 1310 { 1311 int rv; 1312 phy_ctrl_t *pc; 1313 bmacsec_dev_addr_t phy_dev_addr; 1314 1315 pc = EXT_PHY_SW_STATE(unit, port); 1316 1317 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1318 1319 rv = bmacsec_phy84749_spi_firmware_update(phy_dev_addr, data, len); 1320 if (rv != BMACSEC_E_NONE) { 1321 LOG_WARN(BSL_LS_SOC_PHY, 1322 (BSL_META_U(unit, 1323 "PHY84749 firmware upgrade possibly failed:" 1324 "u=%d p=%d\n"), unit, port)); 1325 return (SOC_E_FAIL); 1326 } 1327 LOG_INFO(BSL_LS_SOC_PHY, 1328 (BSL_META_U(unit, 1329 "PHY84749 firmware upgrade successful:" 1330 "u=%d p=%d\n"), unit, port)); 1331 1332 return SOC_E_NONE; 1333 } 1334 1335 /* 1336 * Function: 1337 * phy_84749_medium_status 1338 * Purpose: 1339 * Indicate the current active medium 1340 * Parameters: 1341 * unit - StrataSwitch unit #. 1342 * port - StrataSwitch port #. 1343 * medium - (OUT) One of: 1344 * SOC_PORT_MEDIUM_COPPER 1345 * SOC_PORT_MEDIUM_XAUI 1346 * Returns: 1347 * SOC_E_NONE 1348 */ 1349 1350 STATIC int 1351 phy_84749_medium_status(int unit, soc_port_t port, soc_port_medium_t *medium) 1352 { 1353 COMPILER_REFERENCE(unit); 1354 COMPILER_REFERENCE(port); 1355 1356 *medium = SOC_PORT_MEDIUM_FIBER; 1357 1358 return SOC_E_NONE; 1359 } 1360 1361 1362 /* 1363 * Function: 1364 * phy_84749_control_set 1365 * Purpose: 1366 * Configure PHY device specific control fucntion. 1367 * Parameters: 1368 * unit - StrataSwitch unit #. 1369 * port - StrataSwitch port #. 1370 * type - Control to update 1371 * value - New setting for the control 1372 * Returns: 1373 * SOC_E_NONE 1374 */ 1375 STATIC int 1376 phy_84749_control_set(int unit, soc_port_t port, 1377 soc_phy_control_t type, uint32 value) 1378 { 1379 int rv = BMACSEC_E_NONE; 1380 1381 #ifdef INCLUDE_MACSEC 1382 #ifdef PHY84749_SWITCH_FIXED_MODE 1383 bmacsec_dev_addr_t phy_dev_addr; 1384 bmacsec_phy84749_intf_t line_mode; 1385 int pause_fwd =0, line_speed=0, line_duplex=0, line_pause=1; 1386 phy_ctrl_t *pc; 1387 1388 rv = BMACSEC_E_NONE; 1389 pc = EXT_PHY_SW_STATE(unit, port); 1390 1391 /* Disable switch fixed speed modes and supporting functions 1392 Code not deleted to save the work already done if feature is enabled later 1393 */ 1394 if (pc->macsec_enable != 1) { 1395 return SOC_E_UNAVAIL; 1396 } 1397 1398 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1399 rv = bmacsec_phy84749_line_intf_get(phy_dev_addr, 1400 pc->macsec_dev_port, &line_mode); 1401 if (rv != BMACSEC_E_NONE) { 1402 return SOC_ERROR(rv); 1403 } 1404 switch(type) { 1405 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED: 1406 pc->macsec_switch_fixed = value; 1407 if(value) { 1408 rv = bmacsec_phy84749_switch_side_set_params(phy_dev_addr, 1409 BMACSEC_BCM84749_SWITCH_FIXED, 1410 pc->macsec_switch_fixed_speed, 1411 pc->macsec_switch_fixed_duplex, 1412 pc->macsec_switch_fixed_pause); 1413 } else { /* Switch side follows line side */ 1414 SOC_IF_ERROR_RETURN 1415 (phy_84749_speed_get(unit, port, &line_speed)); 1416 SOC_IF_ERROR_RETURN 1417 (phy_84749_duplex_get(unit, port, &line_duplex)); 1418 #if 0 1419 SOC_IF_ERROR_RETURN 1420 (phy_84749_pause_get(unit, port, &line_pause)); 1421 #endif 1422 rv = bmacsec_phy84749_switch_side_set_params(phy_dev_addr, 1423 BMACSEC_BCM84749_SWITCH_FOLLOWS_LINE, 1424 line_speed, line_duplex, line_pause); 1425 } 1426 break; 1427 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_SPEED: 1428 /* Switch fixed speed is allowed only to be 1000Mbps */ 1429 if (pc->macsec_dev_port > 2) { 1430 if (value != 1000) { 1431 return SOC_E_CONFIG; 1432 } 1433 } else { 1434 if (line_mode == BMACSEC_PHY84749_INTF_1000X) { 1435 if (value != 1000) { 1436 return SOC_E_CONFIG; 1437 } 1438 } else { 1439 if (value != 10000) { 1440 return SOC_E_CONFIG; 1441 } 1442 } 1443 } 1444 1445 if(pc->macsec_switch_fixed_speed != value) { 1446 pc->macsec_switch_fixed_speed = value; 1447 } 1448 break; 1449 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_DUPLEX: 1450 /* Switch fixed Duplex is allowed only to be Full Duplex mode */ 1451 if (value != 1) { 1452 return SOC_E_CONFIG; 1453 } 1454 if(pc->macsec_switch_fixed_duplex != value) { 1455 pc->macsec_switch_fixed_duplex = value; 1456 } 1457 break; 1458 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_PAUSE: 1459 if(pc->macsec_switch_fixed_pause != value) { 1460 pc->macsec_switch_fixed_pause = value; 1461 } 1462 break; 1463 case SOC_PHY_CONTROL_MACSEC_PAUSE_RX_FORWARD: 1464 pc->macsec_pause_rx_fwd = value; 1465 pause_fwd = (value == 1) ? 1 : 0; 1466 1467 rv = bmacsec_phy84749_line_side_pause_forward(phy_dev_addr, 1468 pause_fwd); 1469 if (rv == BMACSEC_E_NONE) { 1470 rv = bmacsec_phy84749_switch_side_pause_forward( 1471 phy_dev_addr, pause_fwd); 1472 } 1473 break; 1474 case SOC_PHY_CONTROL_MACSEC_PAUSE_TX_FORWARD: 1475 pc->macsec_pause_tx_fwd = value; 1476 pause_fwd = (value == 1) ? 1 : 0; 1477 1478 rv = bmacsec_phy84749_line_side_pause_forward(phy_dev_addr, 1479 pause_fwd); 1480 if (rv == BMACSEC_E_NONE) { 1481 rv = bmacsec_phy84749_switch_side_pause_forward(phy_dev_addr, 1482 pause_fwd); 1483 } 1484 break; 1485 case SOC_PHY_CONTROL_MACSEC_LINE_IPG: 1486 pc->macsec_line_ipg = value; 1487 rv = bmacsec_phy84749_line_side_ipg_set(phy_dev_addr, value); 1488 break; 1489 case SOC_PHY_CONTROL_MACSEC_SWITCH_IPG: 1490 pc->macsec_switch_ipg = value; 1491 rv = bmacsec_phy84749_switch_side_ipg_set(phy_dev_addr, value); 1492 break; 1493 default: 1494 rv = SOC_E_UNAVAIL; 1495 break; 1496 } 1497 #endif /* PHY84749_SWITCH_FIXED_MODE */ 1498 #else 1499 bmacsec_dev_addr_t phy_dev_addr; 1500 bmacsec_phy84749_intf_t line_mode; 1501 int pause_fwd =0, line_speed=0, line_duplex=0, line_pause=1; 1502 1503 pause_fwd = 0; 1504 line_speed = 0; 1505 line_duplex = 0; 1506 line_pause = 1; 1507 phy_dev_addr = 0; 1508 line_mode = 0; 1509 1510 rv = SOC_E_UNAVAIL; 1511 #endif 1512 1513 return SOC_ERROR(rv); 1514 } 1515 1516 /* 1517 * Function: 1518 * phy_84749_control_get 1519 * Purpose: 1520 * Get current control settign of the PHY. 1521 * Parameters: 1522 * unit - StrataSwitch unit #. 1523 * port - StrataSwitch port #. 1524 * type - Control to update 1525 * value - (OUT)Current setting for the control 1526 * Returns: 1527 * SOC_E_NONE 1528 */ 1529 STATIC int 1530 phy_84749_control_get(int unit, soc_port_t port, 1531 soc_phy_control_t type, uint32 *value) 1532 { 1533 int rv = SOC_E_NONE; 1534 #ifdef INCLUDE_MACSEC 1535 #ifdef PHY84749_SWITCH_FIXED_MODE 1536 phy_ctrl_t *pc; 1537 1538 pc = EXT_PHY_SW_STATE(unit, port); 1539 1540 /* Disable switch fixed speed modes and supporting functions 1541 Code not deleted to save the work already done if feature is enabled later 1542 */ 1543 1544 if (pc->macsec_enable != 1) { 1545 return SOC_E_UNAVAIL; 1546 } 1547 1548 if (NULL == value) { 1549 return SOC_E_PARAM; 1550 } 1551 1552 if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) { 1553 return SOC_E_PARAM; 1554 } 1555 1556 switch(type) { 1557 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED: 1558 *value = pc->macsec_switch_fixed; 1559 break; 1560 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_SPEED: 1561 *value = pc->macsec_switch_fixed_speed; 1562 break; 1563 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_DUPLEX: 1564 *value = pc->macsec_switch_fixed_duplex; 1565 break; 1566 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_PAUSE: 1567 *value = pc->macsec_switch_fixed_pause; 1568 break; 1569 case SOC_PHY_CONTROL_MACSEC_PAUSE_RX_FORWARD: 1570 *value = pc->macsec_pause_rx_fwd; 1571 break; 1572 case SOC_PHY_CONTROL_MACSEC_PAUSE_TX_FORWARD: 1573 *value = pc->macsec_pause_tx_fwd; 1574 break; 1575 case SOC_PHY_CONTROL_MACSEC_LINE_IPG: 1576 *value = pc->macsec_line_ipg; 1577 break; 1578 case SOC_PHY_CONTROL_MACSEC_SWITCH_IPG: 1579 *value = pc->macsec_switch_ipg; 1580 break; 1581 default: 1582 rv = SOC_E_UNAVAIL; 1583 break; 1584 } 1585 #endif /* PHY84749_SWITCH_FIXED_MODE */ 1586 #else 1587 rv = SOC_E_UNAVAIL; 1588 #endif /* INCLUDE_MACSEC */ 1589 return rv; 1590 } 1591 1592 /* 1593 * Function: 1594 * phy_84749_linkup 1595 * Purpose: 1596 * Link up handler 1597 * Parameters: 1598 * unit - StrataSwitch unit #. 1599 * port - StrataSwitch port #. 1600 * Returns: 1601 * SOC_E_NONE 1602 */ 1603 STATIC int 1604 phy_84749_linkup(int unit, soc_port_t port) 1605 { 1606 int rv = SOC_E_NONE; 1607 phy_ctrl_t *pc; 1608 bmacsec_dev_addr_t phy_dev_addr; 1609 bmacsec_phy84749_intf_t line_mode; 1610 1611 pc = EXT_PHY_SW_STATE(unit, port); 1612 1613 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1614 1615 rv = bmacsec_phy84749_line_intf_get(phy_dev_addr, 0, &line_mode); 1616 if (!BMACSEC_E_SUCCESS(rv)) { 1617 return SOC_E_FAIL; 1618 } 1619 1620 rv = bmacsec_84749_phy_linkup(phy_dev_addr, pc->macsec_enable); 1621 1622 if (line_mode == BMACSEC_PHY84749_INTF_SGMII) { 1623 SOC_IF_ERROR_RETURN( 1624 soc_phyctrl_notify(unit, port, phyEventInterface, SOC_PORT_IF_SGMII)); 1625 } 1626 1627 return SOC_ERROR(rv); 1628 } 1629 1630 /* 1631 * Function: 1632 * phy_84749_interface_get 1633 * Purpose: 1634 * Get interface on a given port. 1635 * Parameters: 1636 * unit - StrataSwitch unit #. 1637 * port - StrataSwitch port #. 1638 * pif - Interface. 1639 * Returns: 1640 * SOC_E_NONE 1641 */ 1642 STATIC int 1643 phy_84749_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 1644 { 1645 *pif = PHY_COPPER_MODE(unit, port) ? SOC_PORT_IF_SGMII : SOC_PORT_IF_XFI; 1646 return SOC_E_NONE; 1647 } 1648 1649 /* 1650 * Function: 1651 * phy_84749_probe 1652 * Purpose: 1653 * Complement the generic phy probe routine to identify this phy when its 1654 * phy id0 and id1 is same as some other phy's. 1655 * Parameters: 1656 * unit - StrataSwitch unit #. 1657 * pc - phy ctrl descriptor. 1658 * Returns: 1659 * SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error> 1660 */ 1661 STATIC int 1662 phy_84749_probe(int unit, phy_ctrl_t *pc) 1663 { 1664 uint16 data1, data2; 1665 1666 if (READ_PHY84749_PMA_PMD_REG(unit, pc, 0xc802, &data1) < 0) { 1667 return SOC_E_NOT_FOUND; 1668 } 1669 1670 if (READ_PHY84749_PMA_PMD_REG(unit, pc, 0xc803, &data2) < 0) { 1671 return SOC_E_NOT_FOUND; 1672 } 1673 1674 if ((data2 & 0xf) == 0x8) { 1675 1676 switch (data1) { 1677 1678 case 0x4728: 1679 case 0x4748: 1680 if (0x8700 != soc_property_port_get(unit, 1681 pc->port, 1682 spn_PORT_PHY_ID1, 0)){ 1683 return SOC_E_NOT_FOUND; 1684 } 1685 /* fall through */ 1686 case 0x4729: 1687 case 0x4749: 1688 1689 /* pc->size = sizeof(phy84749_map_t); */ 1690 return SOC_E_NONE; 1691 } 1692 } 1693 1694 return SOC_E_NOT_FOUND; 1695 } 1696 1697 /* 1698 * Function: 1699 * phy_84749_timesync_config_set 1700 * Description: 1701 * 1702 * Parameters: 1703 * 1704 * Return Value: 1705 * SOC_E_XXX 1706 */ 1707 1708 int 1709 phy_84749_timesync_config_set(int unit, soc_port_t port, soc_port_phy_timesync_config_t *timesync_config) 1710 { 1711 int rv; 1712 phy_ctrl_t *pc; 1713 bmacsec_dev_addr_t phy_dev_addr; 1714 1715 pc = EXT_PHY_SW_STATE(unit, port); 1716 rv = SOC_E_NONE; 1717 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1718 1719 rv = bmacsec_phy84749_timesync_config_set(phy_dev_addr, (bmacsec_port_phy_timesync_config_t *)timesync_config); 1720 return (SOC_ERROR(rv)); 1721 1722 } 1723 1724 /* 1725 * Function: 1726 * phy_84749_timesync_config_get 1727 * Description: 1728 * 1729 * Parameters: 1730 * 1731 * Return Value: 1732 * SOC_E_XXX 1733 */ 1734 1735 int 1736 phy_84749_timesync_config_get(int unit, soc_port_t port, soc_port_phy_timesync_config_t *timesync_config) 1737 { 1738 int rv; 1739 phy_ctrl_t *pc; 1740 bmacsec_dev_addr_t phy_dev_addr; 1741 1742 pc = EXT_PHY_SW_STATE(unit, port); 1743 rv = SOC_E_NONE; 1744 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1745 1746 rv = bmacsec_phy84749_timesync_config_get(phy_dev_addr, (bmacsec_port_phy_timesync_config_t *)timesync_config); 1747 return (SOC_ERROR(rv)); 1748 1749 } 1750 1751 /* 1752 * Function: 1753 * phy_84749_timesync_control_set 1754 * Description: 1755 * 1756 * Parameters: 1757 * 1758 * Return Value: 1759 * SOC_E_XXX 1760 */ 1761 1762 int 1763 phy_84749_timesync_control_set(int unit, soc_port_t port, soc_port_control_phy_timesync_t control_type, uint64 value) 1764 { 1765 int rv; 1766 phy_ctrl_t *pc; 1767 bmacsec_dev_addr_t phy_dev_addr; 1768 buint64_t btemp64; 1769 1770 COMPILER_64_SET(btemp64, COMPILER_64_HI(value), COMPILER_64_LO(value)); 1771 1772 pc = EXT_PHY_SW_STATE(unit, port); 1773 rv = SOC_E_NONE; 1774 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1775 1776 rv = bmacsec_phy84749_timesync_control_set(phy_dev_addr, control_type, btemp64); 1777 return (SOC_ERROR(rv)); 1778 1779 } 1780 1781 /* 1782 * Function: 1783 * phy_84749_timesync_control_get 1784 * Description: 1785 * 1786 * Parameters: 1787 * 1788 * Return Value: 1789 * SOC_E_XXX 1790 */ 1791 int 1792 phy_84749_timesync_control_get(int unit, soc_port_t port, soc_port_control_phy_timesync_t control_type, uint64 *value) 1793 { 1794 int rv; 1795 phy_ctrl_t *pc; 1796 bmacsec_dev_addr_t phy_dev_addr; 1797 buint64_t btemp64; 1798 1799 COMPILER_64_ZERO(btemp64); 1800 pc = EXT_PHY_SW_STATE(unit, port); 1801 rv = SOC_E_NONE; 1802 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1803 1804 rv = bmacsec_phy84749_timesync_control_get(phy_dev_addr, control_type, &btemp64); 1805 1806 COMPILER_64_SET(*value, COMPILER_64_HI(btemp64), COMPILER_64_LO(btemp64)); 1807 1808 return (SOC_ERROR(rv)); 1809 1810 } 1811 1812 1813 /* 1814 * Variable: 1815 * phy_84749_drv 1816 * Purpose: 1817 * Phy Driver for BCM84749 MACSEC PHY 1818 */ 1819 1820 phy_driver_t phy_84749drv_xe = { 1821 "84749 1G/10-Gigabit PHY Driver", 1822 phy_84749_init, /* Init */ 1823 phy_null_reset, /* Reset */ 1824 phy_84749_link_get, /* Link get */ 1825 phy_84749_enable_set, /* Enable set */ 1826 phy_null_enable_get, /* Enable get */ 1827 phy_84749_duplex_set, /* Duplex set */ 1828 phy_84749_duplex_get, /* Duplex get */ 1829 phy_84749_speed_set, /* Speed set */ 1830 phy_84749_speed_get, /* Speed get */ 1831 phy_null_set, /* Master set */ 1832 phy_null_zero_get, /* Master get */ 1833 phy_84749_an_set, /* ANA set */ 1834 phy_84749_an_get, /* ANA get */ 1835 NULL, /* Local Advert set, deprecated */ 1836 NULL, /* Local Advert get, deprecated */ 1837 NULL, /* Remote Advert get, deprecated */ 1838 phy_84749_lb_set, /* PHY loopback set */ 1839 phy_84749_lb_get, /* PHY loopback set */ 1840 phy_null_interface_set, /* IO Interface set */ 1841 phy_84749_interface_get, /* IO Interface get */ 1842 NULL, /* pd_ability, deprecated */ 1843 phy_84749_linkup, 1844 NULL, 1845 phy_null_mdix_set, /* phy_84749_mdix_set */ 1846 phy_null_mdix_get, /* phy_84749_mdix_get */ 1847 phy_null_mdix_status_get, /* phy_84749_mdix_status_get */ 1848 phy_84749_medium_config_set, /* medium config setting set */ 1849 phy_84749_medium_config_get, /* medium config setting get */ 1850 phy_84749_medium_status, /* active medium */ 1851 NULL, /* phy_cable_diag */ 1852 NULL, /* phy_link_change */ 1853 phy_84749_control_set, /* phy_control_set */ 1854 phy_84749_control_get, /* phy_control_get */ 1855 NULL, /* phy_reg_read */ 1856 NULL, /* phy_reg_write */ 1857 NULL, /* phy_reg_modify */ 1858 NULL, /* phy_notify */ 1859 phy_84749_probe, /* pd_probe */ 1860 phy_84749_ability_advert_set, /* pd_ability_advert_set */ 1861 phy_84749_ability_advert_get, /* pd_ability_advert_get */ 1862 phy_84749_ability_remote_get, /* pd_ability_remote_get */ 1863 phy_84749_ability_local_get, /* pd_ability_local_get */ 1864 phy_84749_firmware_set, 1865 phy_84749_timesync_config_set, 1866 phy_84749_timesync_config_get, 1867 phy_84749_timesync_control_set, 1868 phy_84749_timesync_control_get 1869 }; 1870 1871 #else /* INCLUDE_PHY_84749 */ 1872 int _phy_84749_not_empty; 1873 #endif /* INCLUDE_PHY_84749 */ 1874 #endif /* INCLUDE_MACSEC */