phy84756.c (64621B)
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: phy84756.c 11 * Purpose: SDK PHY driver for BCM84756 (MACSec) 12 * 13 * Supported BCM546X Family of PHY devices: 14 * 15 * Device Ports Media MAC Interface 16 * 84756 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_84756) 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 "phy84756.h" 51 #include "phy84756_i2c.h" 52 53 #if defined(INCLUDE_MACSEC) 54 #include <soc/macsecphy.h> 55 #include <bmacsec.h> 56 #include <bmacsec_io.h> 57 #endif 58 59 #if defined(INCLUDE_FCMAP) 60 #include <soc/fcmapphy.h> 61 #include <bfcmap.h> 62 #include <bfcmap_io.h> 63 #endif 64 65 #define ADVERT_ALL_COPPER \ 66 (SOC_PA_PAUSE | SOC_PA_SPEED_10MB | \ 67 SOC_PA_SPEED_100MB | SOC_PA_SPEED_1000MB) 68 69 #define ADVERT_ALL_FIBER \ 70 (SOC_PA_PAUSE | SOC_PA_SPEED_1000MB) 71 72 #define ADVERT_ALL_10GFIBER \ 73 (SOC_PA_PAUSE | SOC_PA_SPEED_10GB) 74 75 76 static bmacsec_error_t error_tbl[] = { 77 SOC_E_NONE, 78 SOC_E_INTERNAL, 79 SOC_E_MEMORY, 80 SOC_E_PARAM, 81 SOC_E_EMPTY, 82 SOC_E_FULL, 83 SOC_E_NOT_FOUND, 84 SOC_E_EXISTS, 85 SOC_E_TIMEOUT, 86 SOC_E_FAIL, 87 SOC_E_DISABLED, 88 SOC_E_BADID, 89 SOC_E_RESOURCE, 90 SOC_E_CONFIG, 91 SOC_E_UNAVAIL, 92 SOC_E_INIT, 93 SOC_E_PORT, 94 }; 95 /* 96 * Convert BMACSEC return codes to SOC return code. 97 */ 98 #define SOC_ERROR(e) error_tbl[(-e)] 99 100 #define PHY84756_REG_READ(_unit, _phy_ctrl, _addr, _val) \ 101 READ_PHY_REG((_unit), (_phy_ctrl), (_addr), (_val)) 102 103 #define READ_PHY84756_PMA_PMD_REG(_unit, _phy_ctrl, _reg,_val) \ 104 PHY84756_REG_READ((_unit), (_phy_ctrl), \ 105 SOC_PHY_CLAUSE45_ADDR(1, (_reg)), (_val)) 106 107 #define PHY84756_REG_WRITE(_unit, _phy_ctrl, _addr, _val) \ 108 WRITE_PHY_REG((_unit), (_phy_ctrl), (_addr), (_val)) 109 110 #define WRITE_PHY84756_PMA_PMD_REG(_unit, _phy_ctrl, _reg,_val) \ 111 PHY84756_REG_WRITE((_unit), (_phy_ctrl), \ 112 SOC_PHY_CLAUSE45_ADDR(1, (_reg)), (_val)) 113 114 STATIC int phy_84756_init(int unit, soc_port_t port); 115 STATIC int phy_84756_link_get(int unit, soc_port_t port, int *link); 116 STATIC int phy_84756_enable_set(int unit, soc_port_t port, int enable); 117 STATIC int phy_84756_duplex_set(int unit, soc_port_t port, int duplex); 118 STATIC int phy_84756_duplex_get(int unit, soc_port_t port, int *duplex); 119 STATIC int phy_84756_speed_set(int unit, soc_port_t port, int speed); 120 STATIC int phy_84756_speed_get(int unit, soc_port_t port, int *speed); 121 #if 0 122 STATIC int phy_84756_master_set(int unit, soc_port_t port, int master); 123 STATIC int phy_84756_master_get(int unit, soc_port_t port, int *master); 124 #endif 125 STATIC int phy_84756_an_set(int unit, soc_port_t port, int autoneg); 126 STATIC int phy_84756_an_get(int unit, soc_port_t port, 127 int *autoneg, int *autoneg_done); 128 STATIC int phy_84756_lb_set(int unit, soc_port_t port, int enable); 129 STATIC int phy_84756_lb_get(int unit, soc_port_t port, int *enable); 130 STATIC int phy_84756_medium_config_set(int unit, soc_port_t port, 131 soc_port_medium_t medium, 132 soc_phy_config_t *cfg); 133 STATIC int phy_84756_medium_config_get(int unit, soc_port_t port, 134 soc_port_medium_t medium, 135 soc_phy_config_t *cfg); 136 STATIC int phy_84756_ability_advert_set(int unit, soc_port_t port, 137 soc_port_ability_t *ability); 138 STATIC int phy_84756_ability_advert_get(int unit, soc_port_t port, 139 soc_port_ability_t *ability); 140 STATIC int phy_84756_ability_remote_get(int unit, soc_port_t port, 141 soc_port_ability_t *ability); 142 STATIC int phy_84756_ability_local_get(int unit, soc_port_t port, 143 soc_port_ability_t *ability); 144 STATIC int phy_84756_firmware_set(int unit, int port, int offset, 145 uint8 *data, int len); 146 STATIC int phy_84756_control_set(int unit, soc_port_t port, 147 soc_phy_control_t type, uint32 value); 148 STATIC int phy_84756_control_get(int unit, soc_port_t port, 149 soc_phy_control_t type, uint32 *value); 150 STATIC int phy_84756_linkup(int unit, soc_port_t port); 151 STATIC int phy_84756_interface_get(int unit, soc_port_t port, 152 soc_port_if_t *pif); 153 154 STATIC int phy_84756_reg_read(int unit, soc_port_t port, uint32 flags, 155 uint32 phy_reg_addr, uint32 *phy_data); 156 157 STATIC int phy_84756_reg_write(int unit, soc_port_t port, uint32 flags, 158 uint32 phy_reg_addr, uint32 phy_data); 159 160 typedef struct phy84756_data_s { 161 int phy_ext_rom_boot; 162 bmacsec_dev_addr_t phy_dev_addr; 163 int line_mode; 164 int macsec_enable; 165 int fcmap_enable; 166 }phy84756_data_t; 167 168 #define PHY_EXT_ROM_BOOT(_pc) (((phy84756_data_t *)((_pc) + 1))->phy_ext_rom_boot) 169 #define PHY_DEV_ADDR(_pc) (((phy84756_data_t *)((_pc) + 1))->phy_dev_addr) 170 #define LINE_MODE(_pc) (((phy84756_data_t *)((_pc) + 1))->line_mode) 171 #define MACSEC_ENABLE(_pc) (((phy84756_data_t *)((_pc) + 1))->macsec_enable) 172 #define FCMAP_ENABLE(_pc) (((phy84756_data_t *)((_pc) + 1))->fcmap_enable) 173 174 /* 175 * Function: 176 * _phy_84756_medium_config_update 177 * Purpose: 178 * Update the PHY with config parameters 179 * Parameters: 180 * unit - StrataSwitch unit #. 181 * port - StrataSwitch port #. 182 * cfg - Config structure. 183 * Returns: 184 * SOC_E_XXX 185 */ 186 187 STATIC int 188 _phy_84756_medium_config_update(int unit, soc_port_t port, 189 soc_phy_config_t *cfg) 190 { 191 192 SOC_IF_ERROR_RETURN 193 (phy_84756_speed_set(unit, port, cfg->force_speed)); 194 SOC_IF_ERROR_RETURN 195 (phy_84756_duplex_set(unit, port, cfg->force_duplex)); 196 SOC_IF_ERROR_RETURN 197 (phy_84756_ability_advert_set(unit, port, &cfg->advert_ability)); 198 SOC_IF_ERROR_RETURN 199 (phy_84756_an_set(unit, port, cfg->autoneg_enable)); 200 201 return SOC_E_NONE; 202 } 203 204 /* Function: 205 * phy_84756_init 206 * Purpose: 207 * Initialize 84756 phys 208 * Parameters: 209 * unit - StrataSwitch unit #. 210 * port - StrataSwitch port #. 211 * Returns: 212 * SOC_E_NONE 213 */ 214 215 STATIC int 216 phy_84756_init(int unit, soc_port_t port) 217 { 218 phy_ctrl_t *pc; 219 int rv = SOC_E_NONE; 220 221 pc = EXT_PHY_SW_STATE(unit, port); 222 223 MACSEC_ENABLE(pc) = 0; 224 FCMAP_ENABLE(pc) = 0; 225 226 if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT || 227 PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1 ) { 228 int fiber_preferred; 229 int mmi_mdio_addr; 230 231 #if defined(INCLUDE_MACSEC) 232 /* By default MACSEC is disable */ 233 /* Check if enable property is set */ 234 pc->macsec_enable = soc_property_port_get(unit, port, spn_MACSEC_ENABLE, 0); 235 MACSEC_ENABLE(pc) = pc->macsec_enable; 236 237 pc->macsec_dev_port = soc_property_port_get(unit, port, 238 spn_MACSEC_PORT_INDEX, -1); 239 PHY_DEV_ADDR(pc) = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 240 241 /* Base PHY ID is used to access MACSEC core */ 242 mmi_mdio_addr = soc_property_port_get(unit, port, 243 spn_MACSEC_DEV_ADDR, -1); 244 if (mmi_mdio_addr < 0) { 245 LOG_WARN(BSL_LS_SOC_PHY, 246 (BSL_META_U(unit, 247 "phy_84756_init: " 248 "MACSEC_DEV_ADDR property " 249 "not configured for u=%d p=%d\n"), unit, port)); 250 return SOC_E_CONFIG; 251 } 252 253 pc->macsec_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, mmi_mdio_addr, 1); 254 255 rv = bmacsec_phy84756_phy_mac_addr_set(PHY_DEV_ADDR(pc), 256 pc->macsec_dev_addr, 257 pc->macsec_dev_port, 258 bmacsec_io_mmi1_cl45); 259 #endif 260 261 #if defined(INCLUDE_FCMAP) 262 263 pc->fcmap_enable = soc_property_port_get(unit, port, spn_FCMAP_ENABLE, 0); 264 FCMAP_ENABLE(pc) = pc->fcmap_enable; 265 266 pc->fcmap_dev_port = soc_property_port_get(unit, port, 267 spn_FCMAP_PORT_INDEX, -1); 268 PHY_DEV_ADDR(pc) = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 269 270 /* Base PHY ID is used to access MACSEC core */ 271 mmi_mdio_addr = soc_property_port_get(unit, port, 272 spn_FCMAP_DEV_ADDR, -1); 273 if (mmi_mdio_addr < 0) { 274 LOG_WARN(BSL_LS_SOC_PHY, 275 (BSL_META_U(unit, 276 "phy_84756_init: " 277 "FCMAP_DEV_ADDR property " 278 "not configured for u=%d p=%d\n"), unit, port)); 279 return SOC_E_CONFIG; 280 } 281 282 pc->fcmap_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, mmi_mdio_addr, 1); 283 pc->fcmap_uc_dev_addr = PHY_DEV_ADDR(pc); 284 285 rv = bmacsec_phy84756_phy_mac_addr_set(PHY_DEV_ADDR(pc), 286 pc->fcmap_dev_addr, 287 pc->fcmap_dev_port, 288 bfcmap_io_mmi1_cl45); 289 290 #endif 291 292 if(rv != BMACSEC_E_NONE) { 293 LOG_WARN(BSL_LS_SOC_PHY, 294 (BSL_META_U(unit, 295 "phy_84756_init: bmacsec_phy_mac_addr_set " 296 "returned error for u=%d p=%d\n"), unit, port)); 297 return SOC_E_FAIL; 298 } 299 300 LOG_INFO(BSL_LS_SOC_PHY, 301 (BSL_META_U(unit, 302 "phy_84756_init: u=%d p=%d\n"),unit, port)); 303 304 /* Preferred mode: 305 * phy_fiber_pref = 1 ; Port is in SFI mode in 10G Default 306 * when speed is changed to 1G, its 1000X 307 * phy_fiber_pref = 0; Port is in SGMII mode, allows only 1G/100M/10M 308 */ 309 fiber_preferred = 310 soc_property_port_get(unit, port, spn_PHY_FIBER_PREF, 1); 311 312 /* Initially configure for the preferred medium. */ 313 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER); 314 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 315 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_PASSTHRU); 316 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_100FX); 317 318 if (fiber_preferred) { 319 LINE_MODE(pc) = BMACSEC_PHY84756_INTF_SFI; 320 pc->copper.enable = FALSE; 321 pc->fiber.enable = TRUE; 322 pc->interface = SOC_PORT_IF_XFI; 323 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 324 } else { 325 pc->interface = SOC_PORT_IF_SGMII; 326 LINE_MODE(pc) = BMACSEC_PHY84756_INTF_SGMII; 327 pc->copper.enable = TRUE; 328 pc->fiber.enable = FALSE; 329 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 330 } 331 PHY_FLAGS_SET(unit, port, PHY_FLAGS_C45); 332 333 pc->copper.preferred = !fiber_preferred; 334 pc->copper.autoneg_enable = TRUE; 335 pc->copper.autoneg_advert = ADVERT_ALL_COPPER; 336 pc->copper.force_speed = 1000; 337 pc->copper.force_duplex = TRUE; 338 pc->copper.master = SOC_PORT_MS_AUTO; 339 pc->copper.mdix = SOC_PORT_MDIX_AUTO; 340 341 pc->fiber.preferred = TRUE; 342 pc->fiber.autoneg_enable = FALSE; 343 pc->fiber.autoneg_advert = ADVERT_ALL_FIBER; 344 pc->fiber.force_speed = 10000; 345 pc->fiber.force_duplex = TRUE; 346 pc->fiber.master = SOC_PORT_MS_NONE; 347 pc->fiber.mdix = SOC_PORT_MDIX_NORMAL; 348 349 PHY_EXT_ROM_BOOT(pc) = soc_property_port_get(unit, port, 350 spn_PHY_EXT_ROM_BOOT, 1); 351 if ((!PHY_EXT_ROM_BOOT(pc)) && (PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT)) { 352 pc->flags |= PHYCTRL_MDIO_BCST; 353 pc->dev_name = "BCM84756"; 354 } 355 356 if ( PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT ) { 357 /* indicate second pass of init is needed */ 358 PHYCTRL_INIT_STATE_SET(pc, PHYCTRL_INIT_STATE_PASS2); 359 360 return SOC_E_NONE; 361 } 362 363 } 364 365 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) || 366 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 367 368 /* Init PHYS and MACs to defaults */ 369 rv = bmacsec_phy84756_init(PHY_DEV_ADDR(pc), 1, 370 LINE_MODE(pc), 371 MACSEC_ENABLE(pc), 372 FCMAP_ENABLE(pc), 373 PHY_EXT_ROM_BOOT(pc) ? 1 : (pc->flags & PHYCTRL_MDIO_BCST ? -1 : 0)); 374 375 if (rv != BMACSEC_E_NONE) { 376 return SOC_E_FAIL; 377 } 378 379 380 /* Get Requested LED selectors (defaults are hardware defaults) */ 381 pc->ledmode[0] = soc_property_port_get(unit, port, spn_PHY_LED1_MODE, 0); 382 pc->ledmode[1] = soc_property_port_get(unit, port, spn_PHY_LED2_MODE, 1); 383 pc->ledmode[2] = soc_property_port_get(unit, port, spn_PHY_LED3_MODE, 3); 384 pc->ledmode[3] = soc_property_port_get(unit, port, spn_PHY_LED4_MODE, 6); 385 pc->ledctrl = soc_property_port_get(unit, port, spn_PHY_LED_CTRL, 0x8); 386 pc->ledselect = soc_property_port_get(unit, port, spn_PHY_LED_SELECT, 0); 387 388 /* 389 * Some reasonable defaults 390 */ 391 #if defined(INCLUDE_MACSEC) 392 pc->macsec_switch_fixed = 0; 393 pc->macsec_switch_fixed_speed = 10000; 394 pc->macsec_switch_fixed_duplex = 1; 395 pc->macsec_switch_fixed_pause = 1; 396 pc->macsec_pause_rx_fwd = 0; 397 pc->macsec_pause_tx_fwd = 0; 398 pc->macsec_line_ipg = 0xc; 399 pc->macsec_switch_ipg = 0xc; 400 #endif 401 402 #if defined(INCLUDE_FCMAP) 403 pc->fcmap_switch_fixed = 0; 404 pc->fcmap_switch_fixed_speed = 10000; 405 pc->fcmap_switch_fixed_duplex = 1; 406 pc->fcmap_switch_fixed_pause = 1; 407 pc->fcmap_pause_rx_fwd = 0; 408 pc->fcmap_pause_tx_fwd = 0; 409 pc->fcmap_line_ipg = 0xc; 410 pc->fcmap_switch_ipg = 0xc; 411 #endif 412 413 SOC_IF_ERROR_RETURN 414 (_phy_84756_medium_config_update(unit, port, 415 PHY_COPPER_MODE(unit, port) ? 416 &pc->copper : 417 &pc->fiber)); 418 419 #if defined(INCLUDE_MACSEC) 420 if (MACSEC_ENABLE(pc)) { 421 rv = soc_macsecphy_init(unit, port, pc, 422 BMACSEC_CORE_BCM84756, bmacsec_io_mmi1_cl45); 423 if (!SOC_SUCCESS(rv)) { 424 LOG_ERROR(BSL_LS_SOC_PHY, 425 (BSL_META_U(unit, 426 "soc_macsecphy_init: MACSEC init for" 427 " u=%d p=%d FAILED "), unit, port)); 428 } else { 429 LOG_INFO(BSL_LS_SOC_PHY, 430 (BSL_META_U(unit, 431 "soc_macsecphy_init: MACSEC init for" 432 " u=%d p=%d SUCCESS "), unit, port)); 433 } 434 } 435 #endif 436 437 #if defined(INCLUDE_FCMAP) 438 if (FCMAP_ENABLE(pc)) { 439 rv = soc_fcmapphy_init(unit, port, pc, 440 BFCMAP_CORE_BCM84756, bfcmap_io_mmi1_cl45); 441 if (!SOC_SUCCESS(rv)) { 442 LOG_ERROR(BSL_LS_SOC_PHY, 443 (BSL_META_U(unit, 444 "soc_fcmapphy_init: FCMAP init for" 445 " u=%d p=%d FAILED "), unit, port)); 446 } else { 447 LOG_INFO(BSL_LS_SOC_PHY, 448 (BSL_META_U(unit, 449 "soc_fcmapphy_init: FCMAP init for" 450 " u=%d p=%d SUCCESS "), unit, port)); 451 } 452 } 453 #endif 454 PHYCTRL_INIT_STATE_SET(pc, PHYCTRL_INIT_STATE_DEFAULT); 455 456 } 457 458 return SOC_E_NONE; 459 } 460 461 462 /* 463 * Function: 464 * phy_84756_link_get 465 * Purpose: 466 * Get layer2 connection status. 467 * Parameters: 468 * unit - StrataSwitch unit #. 469 * port - StrataSwitch port #. 470 * link - address of memory to store link up/down state. 471 * Returns: 472 * SOC_E_NONE 473 */ 474 475 STATIC int 476 phy_84756_link_get(int unit, soc_port_t port, int *link) 477 { 478 phy_ctrl_t *pc; 479 int rv = SOC_E_NONE; 480 bmacsec_dev_addr_t phy_dev_addr; 481 bmacsec_phy84756_intf_t bmacsec_mode; 482 int bmacsec_link; 483 484 pc = EXT_PHY_SW_STATE(unit, port); 485 *link = FALSE; /* Default return */ 486 487 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 488 return SOC_E_NONE; 489 } 490 491 #if defined(INCLUDE_MACSEC) 492 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 493 #endif 494 #if defined(INCLUDE_FCMAP) 495 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 496 #endif 497 498 rv = bmacsec_phy84756_line_intf_get(phy_dev_addr, 0, &bmacsec_mode); 499 if (!BMACSEC_E_SUCCESS(rv)) { 500 return SOC_E_FAIL; 501 } 502 503 if (bmacsec_mode == BMACSEC_PHY84756_INTF_SGMII) { 504 PHY_FLAGS_SET(unit, port, PHY_FLAGS_COPPER); 505 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 506 } else { 507 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 508 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_COPPER); 509 } 510 511 rv = bmacsec_phy84756_link_get(phy_dev_addr, &bmacsec_link); 512 if (!BMACSEC_E_SUCCESS(rv)) { 513 return SOC_E_FAIL; 514 } 515 if (bmacsec_link) { 516 *link = TRUE; 517 } else { 518 *link = FALSE; 519 } 520 521 LOG_VERBOSE(BSL_LS_SOC_PHY, 522 (BSL_META_U(unit, 523 "phy_84756_link_get: u=%d p=%d link=%d\n"), 524 unit, port, 525 *link)); 526 527 return SOC_E_NONE; 528 } 529 530 /* 531 * Function: 532 * phy_84756_enable_set 533 * Purpose: 534 * Enable or disable the physical interface. 535 * Parameters: 536 * unit - StrataSwitch unit #. 537 * port - StrataSwitch port #. 538 * enable - Boolean, true = enable PHY, false = disable. 539 * Returns: 540 * SOC_E_XXX 541 */ 542 543 STATIC int 544 phy_84756_enable_set(int unit, soc_port_t port, int enable) 545 { 546 phy_ctrl_t *pc; 547 int rv = SOC_E_NONE; 548 bmacsec_dev_addr_t phy_dev_addr; 549 550 pc = EXT_PHY_SW_STATE(unit, port); 551 552 if (enable) { 553 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE); 554 } else { 555 PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE); 556 } 557 558 #if defined(INCLUDE_MACSEC) 559 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 560 #endif 561 #if defined(INCLUDE_FCMAP) 562 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 563 #endif 564 565 rv = bmacsec_phy84756_enable_set(phy_dev_addr, enable); 566 567 if(rv != BMACSEC_E_NONE) { 568 return SOC_E_FAIL; 569 } 570 571 LOG_INFO(BSL_LS_SOC_PHY, 572 (BSL_META_U(unit, 573 "phy_84756_enable_set: " 574 "Power %s fiber medium\n"), (enable) ? "up" : "down")); 575 576 return SOC_E_NONE; 577 } 578 579 /* 580 * Function: 581 * phy_84756_duplex_set 582 * Purpose: 583 * Set the current duplex mode 584 * Parameters: 585 * unit - StrataSwitch unit #. 586 * port - StrataSwitch port #. 587 * duplex - Boolean, true indicates full duplex, false indicates half. 588 * Returns: 589 * SOC_E_NONE 590 * SOC_E_UNAVAIL - Half duplex requested, and not supported. 591 * Notes: 592 */ 593 STATIC int 594 phy_84756_duplex_set(int unit, soc_port_t port, int duplex) 595 { 596 int rv; 597 phy_ctrl_t *pc; 598 bmacsec_dev_addr_t phy_dev_addr; 599 bmacsec_phy84756_duplex_t bmacsec_duplex; 600 601 pc = EXT_PHY_SW_STATE(unit, port); 602 603 #if defined(INCLUDE_MACSEC) 604 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 605 #endif 606 #if defined(INCLUDE_FCMAP) 607 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 608 #endif 609 610 if (duplex) { 611 bmacsec_duplex = BMACSEC_PHY84756_FULL_DUPLEX; 612 } else { 613 bmacsec_duplex = BMACSEC_PHY84756_HALF_DUPLEX; 614 } 615 rv = bmacsec_phy84756_duplex_set(phy_dev_addr, bmacsec_duplex); 616 617 if(BMACSEC_E_SUCCESS(rv)) { 618 pc->copper.force_duplex = duplex; 619 } 620 621 LOG_INFO(BSL_LS_SOC_PHY, 622 (BSL_META_U(unit, 623 "phy_84756_duplex_set: u=%d p=%d d=%d rv=%d\n"), 624 unit, port, duplex, rv)); 625 return (SOC_ERROR(rv)); 626 } 627 628 /* 629 * Function: 630 * phy_84756_duplex_get 631 * Purpose: 632 * Get the current operating duplex mode. If autoneg is enabled, 633 * then operating mode is returned, otherwise forced mode is returned. 634 * Parameters: 635 * unit - StrataSwitch unit #. 636 * port - StrataSwitch port #. 637 * duplex - (OUT) Boolean, true indicates full duplex, false 638 * indicates half. 639 * Returns: 640 * SOC_E_NONE 641 * Notes: 642 * The duplex is retrieved for the ACTIVE medium. 643 * No synchronization performed at this level. Autonegotiation is 644 * not manipulated. 645 */ 646 647 STATIC int 648 phy_84756_duplex_get(int unit, soc_port_t port, int *duplex) 649 { 650 651 int rv = SOC_E_NONE; 652 phy_ctrl_t *pc; 653 bmacsec_dev_addr_t phy_dev_addr; 654 bmacsec_phy84756_duplex_t bmacsec_duplex; 655 656 pc = EXT_PHY_SW_STATE(unit, port); 657 658 #if defined(INCLUDE_MACSEC) 659 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 660 #endif 661 #if defined(INCLUDE_FCMAP) 662 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 663 #endif 664 665 rv = bmacsec_phy84756_duplex_get(phy_dev_addr, &bmacsec_duplex); 666 if (rv != BMACSEC_E_NONE) { 667 return SOC_E_FAIL; 668 } 669 if (bmacsec_duplex == BMACSEC_PHY84756_FULL_DUPLEX) { 670 *duplex = TRUE; 671 } else { 672 *duplex = FALSE; 673 } 674 675 LOG_INFO(BSL_LS_SOC_PHY, 676 (BSL_META_U(unit, 677 "phy_84756_duplex_get: u=%d p=%d d=%d rv=%d\n"), 678 unit, port, *duplex, rv)); 679 return SOC_E_NONE; 680 } 681 682 683 /* 684 * Function: 685 * phy_84756_speed_set 686 * Purpose: 687 * Set PHY speed 688 * Parameters: 689 * unit - StrataSwitch unit #. 690 * port - StrataSwitch port #. 691 * speed - link speed in Mbps 692 * Returns: 693 * SOC_E_NONE 694 */ 695 STATIC int 696 phy_84756_speed_set(int unit, soc_port_t port, int speed) 697 { 698 phy_ctrl_t *pc; 699 phy_ctrl_t *int_pc; 700 int rv; 701 bmacsec_dev_addr_t phy_dev_addr; 702 703 pc = EXT_PHY_SW_STATE(unit, port); 704 int_pc = INT_PHY_SW_STATE(unit, port); 705 rv = SOC_E_NONE; 706 707 if (speed > 10000) { 708 return SOC_E_UNAVAIL; 709 } 710 711 #if defined(INCLUDE_MACSEC) 712 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 713 #endif 714 #if defined(INCLUDE_FCMAP) 715 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 716 #endif 717 718 if(PHY_FIBER_MODE(unit, port)) { 719 if (speed < 1000) { 720 return SOC_E_UNAVAIL; 721 } 722 } 723 724 rv = bmacsec_phy84756_speed_set(phy_dev_addr, speed); 725 if(BMACSEC_E_SUCCESS(rv)) { 726 if (NULL != int_pc) { 727 PHY_AUTO_NEGOTIATE_SET (int_pc->pd, unit, port, 0); 728 PHY_SPEED_SET(int_pc->pd, unit, port, speed); 729 } 730 if(PHY_COPPER_MODE(unit, port)) { 731 pc->copper.force_speed = speed; 732 } else { 733 if(PHY_FIBER_MODE(unit, port)) { 734 pc->fiber.force_speed = speed; 735 } 736 } 737 } 738 LOG_INFO(BSL_LS_SOC_PHY, 739 (BSL_META_U(unit, 740 "phy_84756_speed_set: u=%d p=%d s=%d fiber=%d rv=%d\n"), 741 unit, port, speed, PHY_FIBER_MODE(unit, port), rv)); 742 743 return SOC_ERROR(rv); 744 } 745 746 /* 747 * Function: 748 * phy_84756_speed_get 749 * Purpose: 750 * Get the current operating speed for a 84756 device. 751 * Parameters: 752 * unit - StrataSwitch unit #. 753 * port - StrataSwitch port #. 754 * speed - (OUT) Speed of the phy 755 * Returns: 756 * SOC_E_NONE 757 * Notes: 758 * The speed is retrieved for the ACTIVE medium. 759 */ 760 761 STATIC int 762 phy_84756_speed_get(int unit, soc_port_t port, int *speed) 763 { 764 int rv = SOC_E_NONE; 765 bmacsec_dev_addr_t phy_dev_addr; 766 phy_ctrl_t *pc; 767 768 pc = EXT_PHY_SW_STATE(unit, port); 769 770 #if defined(INCLUDE_MACSEC) 771 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 772 #endif 773 #if defined(INCLUDE_FCMAP) 774 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 775 #endif 776 777 rv = bmacsec_phy84756_speed_get(phy_dev_addr, speed); 778 779 if(!BMACSEC_E_SUCCESS(rv)) { 780 LOG_WARN(BSL_LS_SOC_PHY, 781 (BSL_META_U(unit, 782 "phy_84756_speed_get: u=%d p=%d invalid speed\n"), 783 unit, port)); 784 } else { 785 LOG_INFO(BSL_LS_SOC_PHY, 786 (BSL_META_U(unit, 787 "phy_84756_speed_get: u=%d p=%d speed=%d"), 788 unit, port, *speed)); 789 } 790 791 return SOC_ERROR(rv); 792 } 793 794 /* 795 * Function: 796 * phy_84756_an_set 797 * Purpose: 798 * Enable or disable auto-negotiation on the specified port. 799 * Parameters: 800 * unit - StrataSwitch unit #. 801 * port - StrataSwitch port #. 802 * autoneg - Boolean, if true, auto-negotiation is enabled 803 * (and/or restarted). If false, autonegotiation is disabled. 804 * Returns: 805 * SOC_E_XXX 806 * Notes: 807 * The autoneg mode is set only for the ACTIVE medium. 808 */ 809 810 STATIC int 811 phy_84756_an_set(int unit, soc_port_t port, int autoneg) 812 { 813 int rv; 814 phy_ctrl_t *pc; 815 int autoneg_advert = 0; 816 bmacsec_dev_addr_t phy_dev_addr; 817 818 if ( PHY_FLAGS_TST(unit, port, PHY_FLAGS_REPEATER) ) { 819 soc_port_if_t pif; 820 SOC_IF_ERROR_RETURN( phy_84756_interface_get(unit, port, &pif) ); 821 if ( SOC_PORT_IF_SGMII == pif ) { 822 /* in Repeater and SGMII mode, *\ 823 \* AN need to be done by the Internal SerDes */ 824 phy_ctrl_t* int_pc = INT_PHY_SW_STATE(unit, port); 825 rv = PHY_AUTO_NEGOTIATE_SET(int_pc->pd, unit, port, autoneg); 826 return rv; 827 } 828 } 829 830 pc = EXT_PHY_SW_STATE(unit, port); 831 rv = SOC_E_NONE; 832 833 if(PHY_COPPER_MODE(unit, port)) { 834 autoneg_advert = 0; 835 } else { 836 if(PHY_FIBER_MODE(unit, port)) { 837 autoneg_advert = pc->fiber.autoneg_advert; 838 } 839 } 840 #if defined(INCLUDE_MACSEC) 841 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 842 #endif 843 #if defined(INCLUDE_FCMAP) 844 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 845 #endif 846 847 rv = bmacsec_phy84756_an_set(phy_dev_addr, autoneg, autoneg_advert); 848 if(BMACSEC_E_SUCCESS(rv)) { 849 if(PHY_COPPER_MODE(unit, port)) { 850 pc->copper.autoneg_enable = autoneg ? TRUE : FALSE; 851 } else { 852 if(PHY_FIBER_MODE(unit, port)) { 853 pc->fiber.autoneg_enable = autoneg ? TRUE : FALSE; 854 } 855 } 856 } 857 858 LOG_INFO(BSL_LS_SOC_PHY, 859 (BSL_META_U(unit, 860 "phy_84756_an_set: u=%d p=%d autoneg=%d rv=%d\n"), 861 unit, port, autoneg, rv)); 862 return SOC_ERROR(rv); 863 } 864 865 /* 866 * Function: 867 * phy_84756_an_get 868 * Purpose: 869 * Get the current auto-negotiation status (enabled/busy). 870 * Parameters: 871 * unit - StrataSwitch unit #. 872 * port - StrataSwitch port #. 873 * autoneg - (OUT) if true, auto-negotiation is enabled. 874 * autoneg_done - (OUT) if true, auto-negotiation is complete. This 875 * value is undefined if autoneg == FALSE. 876 * Returns: 877 * SOC_E_XXX 878 * Notes: 879 * The autoneg mode is retrieved for the ACTIVE medium. 880 */ 881 882 STATIC int 883 phy_84756_an_get(int unit, soc_port_t port, 884 int *autoneg, int *autoneg_done) 885 { 886 int rv; 887 phy_ctrl_t *pc; 888 bmacsec_dev_addr_t phy_dev_addr; 889 890 pc = EXT_PHY_SW_STATE(unit, port); 891 892 rv = SOC_E_NONE; 893 *autoneg = FALSE; 894 *autoneg_done = FALSE; 895 896 #if defined(INCLUDE_MACSEC) 897 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 898 #endif 899 #if defined(INCLUDE_FCMAP) 900 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 901 #endif 902 903 rv = bmacsec_phy84756_an_get(phy_dev_addr, autoneg, autoneg_done); 904 905 return SOC_ERROR(rv); 906 } 907 908 /* 909 * Function: 910 * phy_84756_lb_set 911 * Purpose: 912 * Set the local PHY loopback mode. 913 * Parameters: 914 * unit - StrataSwitch unit #. 915 * port - StrataSwitch port #. 916 * loopback - Boolean: true = enable loopback, false = disable. 917 * Returns: 918 * SOC_E_XXX 919 * Notes: 920 * The loopback mode is set only for the ACTIVE medium. 921 * No synchronization performed at this level. 922 */ 923 924 STATIC int 925 phy_84756_lb_set(int unit, soc_port_t port, int enable) 926 { 927 int rv; 928 #if 0 929 int link = 0; 930 soc_timeout_t to; 931 #endif 932 phy_ctrl_t *pc; 933 bmacsec_dev_addr_t phy_dev_addr; 934 935 pc = EXT_PHY_SW_STATE(unit, port); 936 rv = SOC_E_NONE; 937 938 #if defined(INCLUDE_MACSEC) 939 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 940 #endif 941 #if defined(INCLUDE_FCMAP) 942 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 943 #endif 944 945 rv = bmacsec_phy84756_loopback_set(phy_dev_addr, enable); 946 947 if (rv == BMACSEC_E_NONE) { 948 /* wait for link up when loopback is enabled */ 949 950 if (enable) { 951 sal_usleep(2000000); 952 } 953 } 954 955 LOG_INFO(BSL_LS_SOC_PHY, 956 (BSL_META_U(unit, 957 "phy_84756_lb_set: u=%d p=%d en=%d rv=%d\n"), 958 unit, port, enable, rv)); 959 960 return SOC_ERROR(rv); 961 } 962 963 /* 964 * Function: 965 * phy_84756_lb_get 966 * Purpose: 967 * Get the local PHY loopback mode. 968 * Parameters: 969 * unit - StrataSwitch unit #. 970 * port - StrataSwitch port #. 971 * loopback - (OUT) Boolean: true = enable loopback, false = disable. 972 * Returns: 973 * SOC_E_XXX 974 * Notes: 975 * The loopback mode is retrieved for the ACTIVE medium. 976 */ 977 978 STATIC int 979 phy_84756_lb_get(int unit, soc_port_t port, int *enable) 980 { 981 int rv; 982 phy_ctrl_t *pc; 983 bmacsec_dev_addr_t phy_dev_addr; 984 985 pc = EXT_PHY_SW_STATE(unit, port); 986 rv = SOC_E_NONE; 987 988 #if defined(INCLUDE_MACSEC) 989 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 990 #endif 991 #if defined(INCLUDE_FCMAP) 992 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 993 #endif 994 995 rv = bmacsec_phy84756_loopback_get(phy_dev_addr, enable); 996 997 return SOC_ERROR(rv); 998 } 999 1000 /* 1001 * Function: 1002 * phy_84756_medium_config_set 1003 * Purpose: 1004 * Set the operating parameters that are automatically selected 1005 * when medium switches type. 1006 * Parameters: 1007 * unit - StrataSwitch unit # 1008 * port - Port number 1009 * medium - SOC_PORT_MEDIUM_COPPER/FIBER 1010 * cfg - Operating parameters 1011 * Returns: 1012 * SOC_E_XXX 1013 */ 1014 1015 STATIC int 1016 phy_84756_medium_config_set(int unit, soc_port_t port, 1017 soc_port_medium_t medium, 1018 soc_phy_config_t *cfg) 1019 { 1020 phy_ctrl_t *pc; 1021 #if 0 1022 soc_phy_config_t *active_medium; /* Currently active medium */ 1023 int medium_update = FALSE; 1024 #endif 1025 soc_phy_config_t *change_medium; /* Requested medium */ 1026 soc_phy_config_t *other_medium; /* The other medium */ 1027 soc_port_mode_t advert_mask; 1028 1029 if (NULL == cfg) { 1030 return SOC_E_PARAM; 1031 } 1032 1033 pc = EXT_PHY_SW_STATE(unit, port); 1034 1035 switch (medium) { 1036 case SOC_PORT_MEDIUM_COPPER: 1037 if (!pc->automedium && !PHY_COPPER_MODE(unit, port)) { 1038 return SOC_E_UNAVAIL; 1039 } 1040 change_medium = &pc->copper; 1041 other_medium = &pc->fiber; 1042 advert_mask = ADVERT_ALL_COPPER; 1043 break; 1044 case SOC_PORT_MEDIUM_FIBER: 1045 if (!pc->automedium && !PHY_FIBER_MODE(unit, port)) { 1046 return SOC_E_UNAVAIL; 1047 } 1048 change_medium = &pc->fiber; 1049 other_medium = &pc->copper; 1050 advert_mask = ADVERT_ALL_FIBER; 1051 break; 1052 default: 1053 return SOC_E_PARAM; 1054 } 1055 1056 /* 1057 * Changes take effect immediately if the target medium is active or 1058 * the preferred medium changes. 1059 */ 1060 #if 0 1061 if (change_medium->enable != cfg->enable) { 1062 medium_update = TRUE; 1063 } 1064 #endif 1065 if (change_medium->preferred != cfg->preferred) { 1066 /* Make sure that only one medium is preferred */ 1067 other_medium->preferred = !cfg->preferred; 1068 #if 0 1069 medium_update = TRUE; 1070 #endif 1071 } 1072 1073 sal_memcpy(change_medium, cfg, sizeof(*change_medium)); 1074 change_medium->autoneg_advert &= advert_mask; 1075 1076 #if 0 1077 if (medium_update) { 1078 /* The new configuration may cause medium change. Check 1079 * and update medium. 1080 */ 1081 SOC_IF_ERROR_RETURN 1082 (_phy_84756_medium_change(unit, port, TRUE, medium)); 1083 } else { 1084 active_medium = (PHY_COPPER_MODE(unit, port)) ? 1085 &pc->copper : &pc->fiber; 1086 if (active_medium == change_medium) { 1087 /* If the medium to update is active, update the configuration */ 1088 SOC_IF_ERROR_RETURN 1089 (_phy_84756_medium_config_update(unit, port, change_medium)); 1090 } 1091 } 1092 #endif 1093 return SOC_E_NONE; 1094 } 1095 1096 /* 1097 * Function: 1098 * phy_84756_medium_config_get 1099 * Purpose: 1100 * Get the operating parameters that are automatically selected 1101 * when medium switches type. 1102 * Parameters: 1103 * unit - StrataSwitch unit # 1104 * port - Port number 1105 * medium - SOC_PORT_MEDIUM_COPPER/FIBER 1106 * cfg - (OUT) Operating parameters 1107 * Returns: 1108 * SOC_E_XXX 1109 */ 1110 1111 STATIC int 1112 phy_84756_medium_config_get(int unit, soc_port_t port, 1113 soc_port_medium_t medium, 1114 soc_phy_config_t *cfg) 1115 { 1116 int rv; 1117 phy_ctrl_t *pc; 1118 1119 pc = EXT_PHY_SW_STATE(unit, port); 1120 rv = SOC_E_NONE; 1121 1122 switch (medium) { 1123 case SOC_PORT_MEDIUM_COPPER: 1124 if (pc->automedium || PHY_COPPER_MODE(unit, port)) { 1125 sal_memcpy(cfg, &pc->copper, sizeof (*cfg)); 1126 } else { 1127 rv = SOC_E_UNAVAIL; 1128 } 1129 break; 1130 case SOC_PORT_MEDIUM_FIBER: 1131 if (pc->automedium || PHY_FIBER_MODE(unit, port)) { 1132 sal_memcpy(cfg, &pc->fiber, sizeof (*cfg)); 1133 } else { 1134 rv = SOC_E_UNAVAIL; 1135 } 1136 break; 1137 default: 1138 rv = SOC_E_PARAM; 1139 break; 1140 } 1141 1142 return rv; 1143 } 1144 1145 /* 1146 * Function: 1147 * phy_84756_ability_advert_set 1148 * Purpose: 1149 * Set the current advertisement for auto-negotiation. 1150 * Parameters: 1151 * unit - StrataSwitch unit #. 1152 * port - StrataSwitch port #. 1153 * mode - Port mode mask indicating supported options/speeds. 1154 * Returns: 1155 * SOC_E_XXX 1156 * Notes: 1157 * The advertisement is set only for the ACTIVE medium. 1158 * No synchronization performed at this level. 1159 */ 1160 STATIC int 1161 phy_84756_ability_advert_set(int unit, soc_port_t port,soc_port_ability_t *ability) 1162 { 1163 int rv; 1164 phy_ctrl_t *pc; 1165 bmacsec_phy84756_port_ability_t local_ability; 1166 bmacsec_dev_addr_t phy_dev_addr; 1167 1168 pc = EXT_PHY_SW_STATE(unit, port); 1169 1170 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 1171 return SOC_E_NONE; 1172 } 1173 1174 if (NULL == ability) { 1175 return (SOC_E_PARAM); 1176 } 1177 1178 if (PHY_COPPER_MODE(unit, port)) { 1179 pc->copper.advert_ability = *ability; 1180 } else { 1181 pc->fiber.advert_ability = *ability; 1182 } 1183 1184 local_ability = 0; 1185 1186 if(ability->speed_full_duplex & SOC_PA_SPEED_1000MB) { 1187 local_ability |= BMACSEC_PHY84756_PA_1000MB_FD; 1188 } 1189 if(ability->speed_full_duplex & SOC_PA_SPEED_10GB) { 1190 local_ability |= BMACSEC_PHY84756_PA_10000MB_FD; 1191 } 1192 1193 if(ability->pause & SOC_PA_PAUSE_TX) { 1194 local_ability |= BMACSEC_PHY84756_PA_PAUSE_TX; 1195 } 1196 if(ability->pause & SOC_PA_PAUSE_RX) { 1197 local_ability |= BMACSEC_PHY84756_PA_PAUSE_RX; 1198 } 1199 if(ability->pause & SOC_PA_PAUSE_ASYMM) { 1200 local_ability |= BMACSEC_PHY84756_PA_PAUSE_ASYMM; 1201 } 1202 1203 if(ability->loopback & SOC_PA_LB_NONE) { 1204 local_ability |= BMACSEC_PHY84756_PA_LB_NONE; 1205 } 1206 if(ability->loopback & SOC_PA_LB_PHY) { 1207 local_ability |= BMACSEC_PHY84756_PA_LB_PHY; 1208 } 1209 if(ability->flags & SOC_PA_AUTONEG) { 1210 local_ability |= BMACSEC_PHY84756_PA_AN; 1211 } 1212 1213 #if defined(INCLUDE_MACSEC) 1214 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1215 #endif 1216 #if defined(INCLUDE_FCMAP) 1217 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1218 #endif 1219 1220 rv = bmacsec_phy84756_ability_advert_set(phy_dev_addr, local_ability); 1221 1222 1223 return SOC_ERROR(rv); 1224 } 1225 1226 /* 1227 * Function: 1228 * phy_84756_ability_advert_get 1229 * Purpose: 1230 * Get the current advertisement for auto-negotiation. 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_XXX 1237 * Notes: 1238 * The advertisement is retrieved for the ACTIVE medium. 1239 * No synchronization performed at this level. 1240 */ 1241 STATIC int 1242 phy_84756_ability_advert_get(int unit, soc_port_t port,soc_port_ability_t *ability) 1243 { 1244 phy_ctrl_t *pc; 1245 int rv; 1246 bmacsec_phy84756_port_ability_t local_ability; 1247 bmacsec_dev_addr_t phy_dev_addr; 1248 1249 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 1250 return SOC_E_NONE; 1251 } 1252 1253 if (NULL == ability) { 1254 return (SOC_E_PARAM); 1255 } 1256 1257 pc = EXT_PHY_SW_STATE(unit, port); 1258 1259 local_ability = 0; 1260 1261 #if defined(INCLUDE_MACSEC) 1262 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1263 #endif 1264 #if defined(INCLUDE_FCMAP) 1265 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1266 #endif 1267 1268 rv = bmacsec_phy84756_ability_advert_get(phy_dev_addr, &local_ability); 1269 if (rv != BMACSEC_E_NONE) { 1270 return SOC_E_FAIL; 1271 } 1272 1273 if(local_ability & BMACSEC_PHY84756_PA_1000MB_FD) { 1274 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 1275 } 1276 if(local_ability & BMACSEC_PHY84756_PA_10000MB_FD) { 1277 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 1278 } 1279 1280 if(local_ability & BMACSEC_PHY84756_PA_PAUSE_TX) { 1281 ability->pause |= SOC_PA_PAUSE_TX; 1282 } 1283 if(local_ability & BMACSEC_PHY84756_PA_PAUSE_RX) { 1284 ability->pause |= SOC_PA_PAUSE_RX; 1285 } 1286 if(local_ability & BMACSEC_PHY84756_PA_PAUSE_ASYMM) { 1287 ability->pause |= SOC_PA_PAUSE_ASYMM; 1288 } 1289 1290 if(local_ability & BMACSEC_PHY84756_PA_LB_NONE) { 1291 ability->loopback |= SOC_PA_LB_NONE; 1292 } 1293 if(local_ability & BMACSEC_PHY84756_PA_LB_PHY) { 1294 ability->loopback |= SOC_PA_LB_PHY; 1295 } 1296 if(local_ability & BMACSEC_PHY84756_PA_AN) { 1297 ability->flags = SOC_PA_AUTONEG; 1298 } 1299 1300 return SOC_E_NONE; 1301 } 1302 1303 /* 1304 * Function: 1305 * phy_84756_ability_remote_get 1306 * Purpose: 1307 * Get the current remote advertisement for auto-negotiation. 1308 * Parameters: 1309 * unit - StrataSwitch unit #. 1310 * port - StrataSwitch port #. 1311 * mode - (OUT) Port mode mask indicating supported options/speeds. 1312 * Returns: 1313 * SOC_E_XXX 1314 * Notes: 1315 * The advertisement is retrieved for the ACTIVE medium. 1316 * No synchronization performed at this level. 1317 */ 1318 STATIC int 1319 phy_84756_ability_remote_get(int unit, soc_port_t port,soc_port_ability_t *ability) 1320 { 1321 phy_ctrl_t *pc; 1322 int rv; 1323 bmacsec_phy84756_port_ability_t remote_ability; 1324 bmacsec_dev_addr_t phy_dev_addr; 1325 1326 if (PHY_FLAGS_TST(unit, port, PHY_FLAGS_DISABLE)) { 1327 return SOC_E_NONE; 1328 } 1329 1330 if (NULL == ability) { 1331 return (SOC_E_PARAM); 1332 } 1333 1334 pc = EXT_PHY_SW_STATE(unit, port); 1335 1336 remote_ability = 0; 1337 1338 #if defined(INCLUDE_MACSEC) 1339 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1340 #endif 1341 #if defined(INCLUDE_FCMAP) 1342 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1343 #endif 1344 1345 rv = bmacsec_phy84756_remote_ability_advert_get(phy_dev_addr, 1346 &remote_ability); 1347 if (rv != BMACSEC_E_NONE) { 1348 return SOC_E_FAIL; 1349 } 1350 1351 if(remote_ability & BMACSEC_PHY84756_PA_1000MB_FD) { 1352 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 1353 } 1354 if(remote_ability & BMACSEC_PHY84756_PA_10000MB_FD) { 1355 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 1356 } 1357 1358 if(remote_ability & BMACSEC_PHY84756_PA_PAUSE_TX) { 1359 ability->pause |= SOC_PA_PAUSE_TX; 1360 } 1361 if(remote_ability & BMACSEC_PHY84756_PA_PAUSE_RX) { 1362 ability->pause |= SOC_PA_PAUSE_RX; 1363 } 1364 if(remote_ability & BMACSEC_PHY84756_PA_PAUSE_ASYMM) { 1365 ability->pause |= SOC_PA_PAUSE_ASYMM; 1366 } 1367 1368 if(remote_ability & BMACSEC_PHY84756_PA_LB_NONE) { 1369 ability->loopback |= SOC_PA_LB_NONE; 1370 } 1371 if(remote_ability & BMACSEC_PHY84756_PA_LB_PHY) { 1372 ability->loopback |= SOC_PA_LB_PHY; 1373 } 1374 if(remote_ability & BMACSEC_PHY84756_PA_AN) { 1375 ability->flags = SOC_PA_AUTONEG; 1376 } 1377 1378 return SOC_E_NONE; 1379 } 1380 1381 1382 1383 /* 1384 * Function: 1385 * phy_84756_ability_local_get 1386 * Purpose: 1387 * Get local abilities 1388 * Parameters: 1389 * unit - StrataSwitch unit #. 1390 * port - StrataSwitch port #. 1391 * mode - (OUT) Port mode mask indicating supported options/speeds. 1392 * Returns: 1393 * SOC_E_NONE 1394 * Notes: 1395 * The ability is retrieved only for the ACTIVE medium. 1396 */ 1397 1398 STATIC int 1399 phy_84756_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability) 1400 { 1401 int rv = SOC_E_NONE; 1402 phy_ctrl_t *pc; 1403 bmacsec_phy84756_port_ability_t local_ability = 0; 1404 bmacsec_dev_addr_t phy_dev_addr; 1405 1406 if (NULL == ability) { 1407 return SOC_E_PARAM; 1408 } 1409 1410 pc = EXT_PHY_SW_STATE(unit, port); 1411 1412 #if defined(INCLUDE_MACSEC) 1413 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1414 #endif 1415 #if defined(INCLUDE_FCMAP) 1416 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1417 #endif 1418 1419 rv = bmacsec_phy84756_ability_local_get(phy_dev_addr, &local_ability); 1420 if (rv != BMACSEC_E_NONE) { 1421 return SOC_E_FAIL; 1422 } 1423 1424 if(local_ability & BMACSEC_PHY84756_PA_1000MB_FD) { 1425 ability->speed_full_duplex |= SOC_PA_SPEED_1000MB; 1426 } 1427 if(local_ability & BMACSEC_PHY84756_PA_10000MB_FD) { 1428 ability->speed_full_duplex |= SOC_PA_SPEED_10GB; 1429 } 1430 1431 if(local_ability & BMACSEC_PHY84756_PA_PAUSE_TX) { 1432 ability->pause |= SOC_PA_PAUSE_TX; 1433 } 1434 if(local_ability & BMACSEC_PHY84756_PA_PAUSE_RX) { 1435 ability->pause |= SOC_PA_PAUSE_RX; 1436 } 1437 if(local_ability & BMACSEC_PHY84756_PA_PAUSE_ASYMM) { 1438 ability->pause |= SOC_PA_PAUSE_ASYMM; 1439 } 1440 1441 1442 if(local_ability & BMACSEC_PHY84756_PA_LB_NONE) { 1443 ability->loopback |= SOC_PA_LB_NONE; 1444 } 1445 if(local_ability & BMACSEC_PHY84756_PA_LB_PHY) { 1446 ability->loopback |= SOC_PA_LB_PHY; 1447 } 1448 if(local_ability & BMACSEC_PHY84756_PA_AN) { 1449 ability->flags = SOC_PA_AUTONEG; 1450 } 1451 1452 return SOC_E_NONE; 1453 } 1454 1455 /* 1456 * Function: 1457 * phy_84756_firmware_set 1458 * Purpose: 1459 * program the given firmware into the SPI-ROM 1460 * Parameters: 1461 * unit - StrataSwitch unit #. 1462 * port - StrataSwitch port #. 1463 * offset - offset to the data stream 1464 * array - the given data 1465 * datalen- the data length 1466 * Returns: 1467 * SOC_E_NONE 1468 */ 1469 1470 STATIC int 1471 phy_84756_firmware_set(int unit, int port, int offset, uint8 *data,int len) 1472 { 1473 int rv; 1474 phy_ctrl_t *pc; 1475 bmacsec_dev_addr_t phy_dev_addr; 1476 1477 pc = EXT_PHY_SW_STATE(unit, port); 1478 1479 #if defined(INCLUDE_MACSEC) 1480 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1481 #endif 1482 #if defined(INCLUDE_FCMAP) 1483 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1484 #endif 1485 1486 rv = bmacsec_phy84756_spi_firmware_update(phy_dev_addr, offset, data, len); 1487 if (rv != BMACSEC_E_NONE) { 1488 LOG_WARN(BSL_LS_SOC_PHY, 1489 (BSL_META_U(unit, 1490 "PHY84756 firmware upgrade possibly failed:" 1491 "u=%d p=%d\n"), unit, port)); 1492 return (SOC_E_FAIL); 1493 } 1494 LOG_INFO(BSL_LS_SOC_PHY, 1495 (BSL_META_U(unit, 1496 "PHY84756 firmware upgrade successful:" 1497 "u=%d p=%d\n"), unit, port)); 1498 1499 return SOC_E_NONE; 1500 } 1501 1502 /* 1503 * Function: 1504 * phy_84756_medium_status 1505 * Purpose: 1506 * Indicate the current active medium 1507 * Parameters: 1508 * unit - StrataSwitch unit #. 1509 * port - StrataSwitch port #. 1510 * medium - (OUT) One of: 1511 * SOC_PORT_MEDIUM_COPPER 1512 * SOC_PORT_MEDIUM_XAUI 1513 * Returns: 1514 * SOC_E_NONE 1515 */ 1516 1517 STATIC int 1518 phy_84756_medium_status(int unit, soc_port_t port, soc_port_medium_t *medium) 1519 { 1520 COMPILER_REFERENCE(unit); 1521 COMPILER_REFERENCE(port); 1522 1523 *medium = SOC_PORT_MEDIUM_FIBER; 1524 1525 return SOC_E_NONE; 1526 } 1527 1528 1529 /* 1530 * Function: 1531 * phy_84756_control_set 1532 * Purpose: 1533 * Configure PHY device specific control fucntion. 1534 * Parameters: 1535 * unit - StrataSwitch unit #. 1536 * port - StrataSwitch port #. 1537 * type - Control to update 1538 * value - New setting for the control 1539 * Returns: 1540 * SOC_E_NONE 1541 */ 1542 STATIC int 1543 phy_84756_control_set(int unit, soc_port_t port, 1544 soc_phy_control_t type, uint32 value) 1545 { 1546 int rv = BMACSEC_E_NONE; 1547 1548 #ifdef INCLUDE_MACSEC 1549 #ifdef PHY84756_SWITCH_FIXED_MODE 1550 bmacsec_dev_addr_t phy_dev_addr; 1551 bmacsec_phy84756_intf_t line_mode; 1552 int pause_fwd =0, line_speed=0, line_duplex=0, line_pause=1; 1553 phy_ctrl_t *pc; 1554 1555 rv = BMACSEC_E_NONE; 1556 pc = EXT_PHY_SW_STATE(unit, port); 1557 1558 /* Disable switch fixed speed modes and supporting functions 1559 Code not deleted to save the work already done if feature is enabled later 1560 */ 1561 if (pc->macsec_enable != 1) { 1562 return SOC_E_UNAVAIL; 1563 } 1564 1565 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1566 rv = bmacsec_phy84756_line_intf_get(phy_dev_addr, 1567 pc->macsec_dev_port, &line_mode); 1568 if (rv != BMACSEC_E_NONE) { 1569 return SOC_ERROR(rv); 1570 } 1571 switch(type) { 1572 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED: 1573 pc->macsec_switch_fixed = value; 1574 if(value) { 1575 rv = bmacsec_phy84756_switch_side_set_params(phy_dev_addr, 1576 BMACSEC_BCM84756_SWITCH_FIXED, 1577 pc->macsec_switch_fixed_speed, 1578 pc->macsec_switch_fixed_duplex, 1579 pc->macsec_switch_fixed_pause); 1580 } else { /* Switch side follows line side */ 1581 SOC_IF_ERROR_RETURN 1582 (phy_84756_speed_get(unit, port, &line_speed)); 1583 SOC_IF_ERROR_RETURN 1584 (phy_84756_duplex_get(unit, port, &line_duplex)); 1585 #if 0 1586 SOC_IF_ERROR_RETURN 1587 (phy_84756_pause_get(unit, port, &line_pause)); 1588 #endif 1589 rv = bmacsec_phy84756_switch_side_set_params(phy_dev_addr, 1590 BMACSEC_BCM84756_SWITCH_FOLLOWS_LINE, 1591 line_speed, line_duplex, line_pause); 1592 } 1593 break; 1594 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_SPEED: 1595 /* Switch fixed speed is allowed only to be 1000Mbps */ 1596 if (pc->macsec_dev_port > 2) { 1597 if (value != 1000) { 1598 return SOC_E_CONFIG; 1599 } 1600 } else { 1601 if (line_mode == BMACSEC_PHY84756_INTF_1000X) { 1602 if (value != 1000) { 1603 return SOC_E_CONFIG; 1604 } 1605 } else { 1606 if (value != 10000) { 1607 return SOC_E_CONFIG; 1608 } 1609 } 1610 } 1611 1612 if(pc->macsec_switch_fixed_speed != value) { 1613 pc->macsec_switch_fixed_speed = value; 1614 } 1615 break; 1616 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_DUPLEX: 1617 /* Switch fixed Duplex is allowed only to be Full Duplex mode */ 1618 if (value != 1) { 1619 return SOC_E_CONFIG; 1620 } 1621 if(pc->macsec_switch_fixed_duplex != value) { 1622 pc->macsec_switch_fixed_duplex = value; 1623 } 1624 break; 1625 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_PAUSE: 1626 if(pc->macsec_switch_fixed_pause != value) { 1627 pc->macsec_switch_fixed_pause = value; 1628 } 1629 break; 1630 case SOC_PHY_CONTROL_MACSEC_PAUSE_RX_FORWARD: 1631 pc->macsec_pause_rx_fwd = value; 1632 pause_fwd = (value == 1) ? 1 : 0; 1633 1634 rv = bmacsec_phy84756_line_side_pause_forward(phy_dev_addr, 1635 pause_fwd); 1636 if (rv == BMACSEC_E_NONE) { 1637 rv = bmacsec_phy84756_switch_side_pause_forward( 1638 phy_dev_addr, pause_fwd); 1639 } 1640 break; 1641 case SOC_PHY_CONTROL_MACSEC_PAUSE_TX_FORWARD: 1642 pc->macsec_pause_tx_fwd = value; 1643 pause_fwd = (value == 1) ? 1 : 0; 1644 1645 rv = bmacsec_phy84756_line_side_pause_forward(phy_dev_addr, 1646 pause_fwd); 1647 if (rv == BMACSEC_E_NONE) { 1648 rv = bmacsec_phy84756_switch_side_pause_forward(phy_dev_addr, 1649 pause_fwd); 1650 } 1651 break; 1652 case SOC_PHY_CONTROL_MACSEC_LINE_IPG: 1653 pc->macsec_line_ipg = value; 1654 rv = bmacsec_phy84756_line_side_ipg_set(phy_dev_addr, value); 1655 break; 1656 case SOC_PHY_CONTROL_MACSEC_SWITCH_IPG: 1657 pc->macsec_switch_ipg = value; 1658 rv = bmacsec_phy84756_switch_side_ipg_set(phy_dev_addr, value); 1659 break; 1660 default: 1661 rv = SOC_E_UNAVAIL; 1662 break; 1663 } 1664 #endif /* PHY84756_SWITCH_FIXED_MODE */ 1665 #else 1666 bmacsec_dev_addr_t phy_dev_addr; 1667 bmacsec_phy84756_intf_t line_mode; 1668 int pause_fwd =0, line_speed=0, line_duplex=0, line_pause=1; 1669 1670 pause_fwd = 0; 1671 line_speed = 0; 1672 line_duplex = 0; 1673 line_pause = 1; 1674 phy_dev_addr = 0; 1675 line_mode = 0; 1676 1677 rv = SOC_E_UNAVAIL; 1678 #endif 1679 1680 return SOC_ERROR(rv); 1681 } 1682 1683 /* 1684 * Function: 1685 * phy_84756_control_get 1686 * Purpose: 1687 * Get current control settign of the PHY. 1688 * Parameters: 1689 * unit - StrataSwitch unit #. 1690 * port - StrataSwitch port #. 1691 * type - Control to update 1692 * value - (OUT)Current setting for the control 1693 * Returns: 1694 * SOC_E_NONE 1695 */ 1696 STATIC int 1697 phy_84756_control_get(int unit, soc_port_t port, 1698 soc_phy_control_t type, uint32 *value) 1699 { 1700 int rv = SOC_E_NONE; 1701 #ifdef INCLUDE_MACSEC 1702 #ifdef PHY84756_SWITCH_FIXED_MODE 1703 phy_ctrl_t *pc; 1704 1705 pc = EXT_PHY_SW_STATE(unit, port); 1706 1707 /* Disable switch fixed speed modes and supporting functions 1708 Code not deleted to save the work already done if feature is enabled later 1709 */ 1710 1711 if (pc->macsec_enable != 1) { 1712 return SOC_E_UNAVAIL; 1713 } 1714 1715 if (NULL == value) { 1716 return SOC_E_PARAM; 1717 } 1718 1719 if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) { 1720 return SOC_E_PARAM; 1721 } 1722 1723 rv = SOC_E_NONE; 1724 switch(type) { 1725 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED: 1726 *value = pc->macsec_switch_fixed; 1727 break; 1728 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_SPEED: 1729 *value = pc->macsec_switch_fixed_speed; 1730 break; 1731 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_DUPLEX: 1732 *value = pc->macsec_switch_fixed_duplex; 1733 break; 1734 case SOC_PHY_CONTROL_MACSEC_SWITCH_FIXED_PAUSE: 1735 *value = pc->macsec_switch_fixed_pause; 1736 break; 1737 case SOC_PHY_CONTROL_MACSEC_PAUSE_RX_FORWARD: 1738 *value = pc->macsec_pause_rx_fwd; 1739 break; 1740 case SOC_PHY_CONTROL_MACSEC_PAUSE_TX_FORWARD: 1741 *value = pc->macsec_pause_tx_fwd; 1742 break; 1743 case SOC_PHY_CONTROL_MACSEC_LINE_IPG: 1744 *value = pc->macsec_line_ipg; 1745 break; 1746 case SOC_PHY_CONTROL_MACSEC_SWITCH_IPG: 1747 *value = pc->macsec_switch_ipg; 1748 break; 1749 default: 1750 rv = SOC_E_UNAVAIL; 1751 break; 1752 } 1753 #endif /* PHY84756_SWITCH_FIXED_MODE */ 1754 #else 1755 rv = SOC_E_UNAVAIL; 1756 #endif 1757 return rv; 1758 } 1759 1760 /* 1761 * Function: 1762 * phy_84756_linkup 1763 * Purpose: 1764 * Link up handler 1765 * Parameters: 1766 * unit - StrataSwitch unit #. 1767 * port - StrataSwitch port #. 1768 * Returns: 1769 * SOC_E_NONE 1770 */ 1771 STATIC int 1772 phy_84756_linkup(int unit, soc_port_t port) 1773 { 1774 int rv = SOC_E_NONE; 1775 phy_ctrl_t *pc; 1776 bmacsec_dev_addr_t phy_dev_addr; 1777 pc = EXT_PHY_SW_STATE(unit, port); 1778 1779 #ifdef INCLUDE_MACSEC 1780 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1781 1782 rv = bmacsec_84756_phy_linkup(phy_dev_addr, pc->macsec_enable); 1783 #else 1784 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1785 1786 rv = bmacsec_84756_phy_linkup(phy_dev_addr, pc->fcmap_enable); 1787 #endif 1788 1789 return SOC_ERROR(rv); 1790 } 1791 1792 /* 1793 * Function: 1794 * phy_84756_interface_get 1795 * Purpose: 1796 * Get interface on a given port. 1797 * Parameters: 1798 * unit - StrataSwitch unit #. 1799 * port - StrataSwitch port #. 1800 * pif - Interface. 1801 * Returns: 1802 * SOC_E_NONE 1803 */ 1804 STATIC int 1805 phy_84756_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 1806 { 1807 *pif = PHY_COPPER_MODE(unit, port) ? SOC_PORT_IF_SGMII : SOC_PORT_IF_XFI; 1808 return SOC_E_NONE; 1809 } 1810 1811 /* 1812 * Function: 1813 * phy_84756_probe 1814 * Purpose: 1815 * Complement the generic phy probe routine to identify this phy when its 1816 * phy id0 and id1 is same as some other phy's. 1817 * Parameters: 1818 * unit - StrataSwitch unit #. 1819 * pc - phy ctrl descriptor. 1820 * Returns: 1821 * SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error> 1822 */ 1823 STATIC int 1824 phy_84756_probe(int unit, phy_ctrl_t *pc) 1825 { 1826 uint16 data1, data2; 1827 1828 if (READ_PHY84756_PMA_PMD_REG(unit, pc, 0xc802, &data1) < 0) { 1829 return SOC_E_NOT_FOUND; 1830 } 1831 1832 if (READ_PHY84756_PMA_PMD_REG(unit, pc, 0xc803, &data2) < 0) { 1833 return SOC_E_NOT_FOUND; 1834 } 1835 1836 /* Use of Standalone MACSEC driver is selected by fcmap_enable=0xff */ 1837 if (0xff == soc_property_port_get(unit, pc->port, spn_FCMAP_ENABLE, 0)) { 1838 pc->size = sizeof(phy84756_data_t); 1839 LOG_CLI((BSL_META_U(unit, 1840 "u=%d p=%d Using Standalone PHY driver for BCM84756\n"), 1841 unit, pc->port)); 1842 return SOC_E_NONE; 1843 } 1844 return SOC_E_NOT_FOUND; 1845 1846 } 1847 1848 /* 1849 * Function: 1850 * phy_84756_timesync_config_set 1851 * Description: 1852 * 1853 * Parameters: 1854 * 1855 * Return Value: 1856 * SOC_E_XXX 1857 */ 1858 1859 int 1860 phy_84756_timesync_config_set(int unit, soc_port_t port, soc_port_phy_timesync_config_t *timesync_config) 1861 { 1862 int rv; 1863 phy_ctrl_t *pc; 1864 bmacsec_dev_addr_t phy_dev_addr; 1865 1866 pc = EXT_PHY_SW_STATE(unit, port); 1867 rv = SOC_E_NONE; 1868 #if defined(INCLUDE_MACSEC) 1869 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1870 #endif 1871 #if defined(INCLUDE_FCMAP) 1872 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1873 #endif 1874 1875 rv = bmacsec_phy84756_timesync_config_set(phy_dev_addr, (bmacsec_port_phy_timesync_config_t *)timesync_config); 1876 return (SOC_ERROR(rv)); 1877 1878 } 1879 1880 /* 1881 * Function: 1882 * phy_84756_timesync_config_get 1883 * Description: 1884 * 1885 * Parameters: 1886 * 1887 * Return Value: 1888 * SOC_E_XXX 1889 */ 1890 1891 int 1892 phy_84756_timesync_config_get(int unit, soc_port_t port, soc_port_phy_timesync_config_t *timesync_config) 1893 { 1894 int rv; 1895 phy_ctrl_t *pc; 1896 bmacsec_dev_addr_t phy_dev_addr; 1897 1898 pc = EXT_PHY_SW_STATE(unit, port); 1899 rv = SOC_E_NONE; 1900 #if defined(INCLUDE_MACSEC) 1901 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1902 #endif 1903 #if defined(INCLUDE_FCMAP) 1904 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1905 #endif 1906 1907 rv = bmacsec_phy84756_timesync_config_get(phy_dev_addr, (bmacsec_port_phy_timesync_config_t *)timesync_config); 1908 return (SOC_ERROR(rv)); 1909 1910 } 1911 1912 /* 1913 * Function: 1914 * phy_84756_timesync_control_set 1915 * Description: 1916 * 1917 * Parameters: 1918 * 1919 * Return Value: 1920 * SOC_E_XXX 1921 */ 1922 1923 int 1924 phy_84756_timesync_control_set(int unit, soc_port_t port, soc_port_control_phy_timesync_t control_type, uint64 value) 1925 { 1926 int rv; 1927 phy_ctrl_t *pc; 1928 bmacsec_dev_addr_t phy_dev_addr; 1929 buint64_t btemp64; 1930 1931 COMPILER_64_SET(btemp64, COMPILER_64_HI(value), COMPILER_64_LO(value)); 1932 1933 pc = EXT_PHY_SW_STATE(unit, port); 1934 rv = SOC_E_NONE; 1935 #if defined(INCLUDE_MACSEC) 1936 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1937 #endif 1938 #if defined(INCLUDE_FCMAP) 1939 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1940 #endif 1941 1942 rv = bmacsec_phy84756_timesync_control_set(phy_dev_addr, control_type, btemp64); 1943 return (SOC_ERROR(rv)); 1944 1945 } 1946 1947 /* 1948 * Function: 1949 * phy_84756_timesync_control_get 1950 * Description: 1951 * 1952 * Parameters: 1953 * 1954 * Return Value: 1955 * SOC_E_XXX 1956 */ 1957 int 1958 phy_84756_timesync_control_get(int unit, soc_port_t port, soc_port_control_phy_timesync_t control_type, uint64 *value) 1959 { 1960 int rv; 1961 phy_ctrl_t *pc; 1962 bmacsec_dev_addr_t phy_dev_addr; 1963 buint64_t btemp64; 1964 1965 COMPILER_64_ZERO(btemp64); 1966 pc = EXT_PHY_SW_STATE(unit, port); 1967 rv = SOC_E_NONE; 1968 #if defined(INCLUDE_MACSEC) 1969 phy_dev_addr = SOC_MACSECPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1970 #endif 1971 #if defined(INCLUDE_FCMAP) 1972 phy_dev_addr = SOC_FCMAPPHY_MDIO_ADDR(unit, pc->phy_id, 1); 1973 #endif 1974 1975 rv = bmacsec_phy84756_timesync_control_get(phy_dev_addr, control_type, &btemp64); 1976 1977 COMPILER_64_SET(*value, COMPILER_64_HI(btemp64), COMPILER_64_LO(btemp64)); 1978 1979 return (SOC_ERROR(rv)); 1980 1981 } 1982 1983 1984 STATIC int 1985 phy_84756_reg_read(int unit, soc_port_t port, uint32 flags, 1986 uint32 phy_reg_addr, uint32 *phy_data) 1987 { 1988 uint16 data16; 1989 uint16 regdata; 1990 phy_ctrl_t *pc; /* PHY software state */ 1991 int rv = SOC_E_NONE; 1992 int rd_cnt; 1993 1994 pc = EXT_PHY_SW_STATE(unit, port); 1995 1996 rd_cnt = 1; 1997 1998 if (flags & SOC_PHY_I2C_DATA8) { 1999 2000 SOC_IF_ERROR_RETURN 2001 (phy_84756_i2cdev_read(pc, 2002 SOC_PHY_I2C_DEVAD(phy_reg_addr), 2003 SOC_PHY_I2C_REGAD(phy_reg_addr), 2004 rd_cnt, 2005 (uint8 *)&data16)); 2006 *phy_data = *((uint8 *)&data16); 2007 2008 } else if (flags & SOC_PHY_I2C_DATA16) { 2009 /* This operation is generally targeted to access 16-bit device, 2010 * such as PHY IC inside the SFP. However there is no 16-bit 2011 * scratch register space on the device. Use 1.800e 2012 * for this operation. 2013 */ 2014 SOC_IF_ERROR_RETURN 2015 (READ_PHY84756_PMA_PMD_REG(unit, pc, PHY84756_I2C_TEMP_RAM, 2016 ®data)); 2017 2018 rv = _phy_84756_bsc_rw(pc, 2019 SOC_PHY_I2C_DEVAD(phy_reg_addr), 2020 PHY84756_I2C_OP_TYPE(PHY84756_I2CDEV_READ,PHY84756_I2C_16BIT), 2021 SOC_PHY_I2C_REGAD(phy_reg_addr),1, 2022 (void *)&data16,PHY84756_I2C_TEMP_RAM); 2023 2024 *phy_data = data16; 2025 2026 /* restore the ram register value */ 2027 SOC_IF_ERROR_RETURN 2028 (WRITE_PHY84756_PMA_PMD_REG(unit, pc, PHY84756_I2C_TEMP_RAM, 2029 regdata)); 2030 } else { 2031 SOC_IF_ERROR_RETURN 2032 (READ_PHY_REG(unit, pc, phy_reg_addr, &data16)); 2033 *phy_data = data16; 2034 } 2035 2036 return rv; 2037 2038 } 2039 2040 2041 2042 STATIC int 2043 phy_84756_reg_write(int unit, soc_port_t port, uint32 flags, 2044 uint32 phy_reg_addr, uint32 phy_data) 2045 { 2046 uint8 data8[4]; 2047 uint16 data16[2]; 2048 uint16 regdata[2]; 2049 phy_ctrl_t *pc; /* PHY software state */ 2050 int rv = SOC_E_NONE; 2051 int wr_cnt; 2052 2053 pc = EXT_PHY_SW_STATE(unit, port); 2054 2055 wr_cnt = 1; 2056 2057 if (flags & SOC_PHY_I2C_DATA8) { 2058 data8[0] = (uint8)phy_data; 2059 SOC_IF_ERROR_RETURN 2060 (phy_84756_i2cdev_write(pc, 2061 SOC_PHY_I2C_DEVAD(phy_reg_addr), 2062 SOC_PHY_I2C_REGAD(phy_reg_addr), 2063 wr_cnt, 2064 data8)); 2065 } else if (flags & SOC_PHY_I2C_DATA16) { 2066 2067 /* This operation is generally targeted to access 16-bit device, 2068 * such as PHY IC inside the SFP. However there is no 16-bit 2069 * scratch register space on the device. Use 1.800e 2070 * for this operation. 2071 */ 2072 /* save the temp ram register */ 2073 SOC_IF_ERROR_RETURN 2074 (READ_PHY84756_PMA_PMD_REG(unit, pc, PHY84756_I2C_TEMP_RAM, 2075 ®data[0])); 2076 data16[0] = phy_data; 2077 rv = _phy_84756_bsc_rw(pc, 2078 SOC_PHY_I2C_DEVAD(phy_reg_addr), 2079 PHY84756_I2C_OP_TYPE(PHY84756_I2CDEV_READ,PHY84756_I2C_16BIT), 2080 SOC_PHY_I2C_REGAD(phy_reg_addr),wr_cnt, 2081 (void *)data16,PHY84756_I2C_TEMP_RAM); 2082 2083 /* restore the ram register value */ 2084 SOC_IF_ERROR_RETURN 2085 (WRITE_PHY84756_PMA_PMD_REG(unit, pc, PHY84756_I2C_TEMP_RAM, 2086 regdata[0])); 2087 } else { 2088 SOC_IF_ERROR_RETURN 2089 (WRITE_PHY_REG(unit, pc, phy_reg_addr, (uint16)phy_data)); 2090 } 2091 return rv; 2092 } 2093 2094 2095 2096 /* 2097 * Variable: 2098 * phy_84756_drv 2099 * Purpose: 2100 * Phy Driver for BCM84756 MACSEC PHY 2101 */ 2102 2103 phy_driver_t phy_84756drv_xe = { 2104 "84756 1G/10-Gigabit PHY Driver", 2105 phy_84756_init, /* Init */ 2106 phy_null_reset, /* Reset */ 2107 phy_84756_link_get, /* Link get */ 2108 phy_84756_enable_set, /* Enable set */ 2109 phy_null_enable_get, /* Enable get */ 2110 phy_84756_duplex_set, /* Duplex set */ 2111 phy_84756_duplex_get, /* Duplex get */ 2112 phy_84756_speed_set, /* Speed set */ 2113 phy_84756_speed_get, /* Speed get */ 2114 phy_null_set, /* Master set */ 2115 phy_null_zero_get, /* Master get */ 2116 phy_84756_an_set, /* ANA set */ 2117 phy_84756_an_get, /* ANA get */ 2118 NULL, /* Local Advert set, deprecated */ 2119 NULL, /* Local Advert get, deprecated */ 2120 NULL, /* Remote Advert get, deprecated */ 2121 phy_84756_lb_set, /* PHY loopback set */ 2122 phy_84756_lb_get, /* PHY loopback set */ 2123 phy_null_interface_set, /* IO Interface set */ 2124 phy_84756_interface_get, /* IO Interface get */ 2125 NULL, /* pd_ability, deprecated */ 2126 phy_84756_linkup, 2127 NULL, 2128 phy_null_mdix_set, /* phy_84756_mdix_set */ 2129 phy_null_mdix_get, /* phy_84756_mdix_get */ 2130 phy_null_mdix_status_get, /* phy_84756_mdix_status_get */ 2131 phy_84756_medium_config_set, /* medium config setting set */ 2132 phy_84756_medium_config_get, /* medium config setting get */ 2133 phy_84756_medium_status, /* active medium */ 2134 NULL, /* phy_cable_diag */ 2135 NULL, /* phy_link_change */ 2136 phy_84756_control_set, /* phy_control_set */ 2137 phy_84756_control_get, /* phy_control_get */ 2138 phy_84756_reg_read, /* phy_reg_read */ 2139 phy_84756_reg_write, /* phy_reg_write */ 2140 NULL, /* phy_reg_modify */ 2141 NULL, /* phy_notify */ 2142 phy_84756_probe, /* pd_probe */ 2143 phy_84756_ability_advert_set, /* pd_ability_advert_set */ 2144 phy_84756_ability_advert_get, /* pd_ability_advert_get */ 2145 phy_84756_ability_remote_get, /* pd_ability_remote_get */ 2146 phy_84756_ability_local_get, /* pd_ability_local_get */ 2147 phy_84756_firmware_set, 2148 phy_84756_timesync_config_set, 2149 phy_84756_timesync_config_get, 2150 phy_84756_timesync_control_set, 2151 phy_84756_timesync_control_get 2152 }; 2153 2154 #else /* INCLUDE_PHY_84756 */ 2155 int _phy_84756_not_empty; 2156 #endif /* INCLUDE_PHY_84756 */ 2157 #endif /* INCLUDE_MACSEC */