phy82780.c (222568B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: phy82780.c 8 * Purpose: Support for Quadra28 external PHY 9 */ 10 11 /* 12 * This module implements an NTSW SDK Phy driver for the phy82780 External PHY. 13 * 14 * LAYERING. 15 * 16 * This driver is built on top of the PHYMOD library, which is a PHY 17 * driver library that can operate on a family of PHYs, including 18 * phy82780 and Sesto and etc.., PHYMOD can be built in a standalone enviroment and be 19 * provided independently from the SDK. PHYMOD APIs consist of 20 * "core" APIs and "phy" APIs. 21 * 22 * 23 * KEY IDEAS AND MAIN FUNCTIONS 24 * 25 * Some key ideas in this architecture are: 26 * 27 * o A PHMOD "phy" consists of one more more lanes, all residing in a single 28 * core. An SDK "phy" is a logical port, which can consist of one or 29 * more lanes in a single core, OR, can consist of multiples lanes in 30 * more than one core. 31 * o PHYMOD code is "stateless" in the sense that all calls to PHYMOD 32 * APIs are fully parameterized and no per-phy state is held by a PHYMOD 33 * driver. 34 * o PHYMOD APIs do not map 1-1 with SDK .pd_control_set or .pd_control_get 35 * APIs (nor ".pd_xx" calls, nor to .phy82780_per_lane_control_set and 36 * .phy82780_per_lane_control_get APIs. 37 * 38 * The purpose of this code, then, is to provide the necessary translations 39 * between the SDK interfaces and the PHYMOD interfaces. This includes: 40 * 41 * o Looping over the cores in a logical PHY in order to operate on the 42 * supporting PHMOD PHYs 43 * o Determining the configuration data for the phy, based on programmed 44 * defaults and SOC properties. 45 * o Managing the allocation and freeing of phy data structures required for 46 * working storage. Locating these structures on procedure invocation. 47 * o Mapping SDK API concepts to PHYMOD APIs. In some cases, local state is 48 * required in this module in order to present the legacy API. 49 * 50 * 51 * MAIN DATA STRUCTURES 52 * 53 * phy_ctrl_t 54 * The PHY control structure defines the SDK notion of a PHY 55 * (existing) structure owned by SDK phy driver modules. In order 56 * to support PHYMOD PHYs, one addition was made to this structure 57 * (soc_phymod_ctrl_t phymod_ctrl;) 58 * 59 * quarda28_config_t 60 * Driver specific data. This structure is used by quadra28 to hold 61 * logical port specific working storage. 62 * 63 * soc_phymod_ctrl_t 64 * PHYMOD drivers. Resides in phy_ctrl_t specifies how many cores 65 * are in this phy and contains an array of pointers to 66 * soc_phymod_phy_t structures, which define a PHYMOD PHY. 67 * 68 * soc_phymod_phy_t 69 * This structure contains a pointer to phymod_phy_access_t and a 70 * pointer to the associated soc_phymod_core_t. Instances if this 71 * structure are created during device probe/init and are maintained 72 * by the SOC. 73 * 74 * soc_phymod_core_t 75 * This structure contains per-core information. Multiple PHYMOD 76 * PHYS can point to a single core. 77 * 78 * phymod_phy_access_t 79 * This structure contains information about how to read/write PHY 80 * registers. A required parameter for PHYMOD PHY APIs 81 * 82 * phymod_core_access_t 83 * This structure contains information about how to read/write PHY 84 * registers. A required parameter for PHYMOD core APIs. 85 */ 86 87 #include <shared/bsl.h> 88 89 #include <sal/types.h> 90 #include <sal/types.h> 91 #include <sal/core/spl.h> 92 #include <shared/bsl.h> 93 #include <soc/drv.h> 94 #include <soc/debug.h> 95 #include <soc/error.h> 96 #include <soc/phyreg.h> 97 #include <soc/port_ability.h> 98 #include <soc/phy.h> 99 #include <soc/phy/phyctrl.h> 100 #include <soc/phy/drv.h> 101 #include <soc/phy/phymod_ids.h> 102 103 #include "phydefs.h" /* Must include before other phy related includes */ 104 105 #include "phyconfig.h" /* Must include before other phy related includes */ 106 #include "phyident.h" 107 #include "phyreg.h" 108 #include "phynull.h" 109 #include "xgxs.h" 110 111 112 #define PHYMOD_QUADRA28_SUPPORT 113 114 115 #if defined(INCLUDE_PHY_82780) 116 117 #include <phymod/phymod.h> 118 #include <phymod/phymod_debug.h> 119 #include <phymod/phymod_diagnostics.h> 120 121 122 #define NUM_LANES 4 /* num of lanes per core */ 123 #define MAX_NUM_LANES 4 /* max num of lanes per port */ 124 #define PHY82780_NO_CFG_VALUE (-1) 125 #define PHY82780_DBG_REGACC 0x2 126 #define PHY82780_DBG_MEM 0x3 127 #define PHY82780_SPD_10G 10000 128 #define PHY82780_SPD_11G 11000 129 #define PHY82780_SPD_40G 40000 130 #define PHY82780_SPD_42G 42000 131 #define PHY82780_SPD_1G 1000 132 #define INTERFACE_SIDE_SHIFT 31 133 #define Q28_ID_82780 0x82780 134 #define Q28_ID_8278F 0x8278F 135 #define Q28_ID_82752 0x82752 136 #define Q28_ID_82758 0x82758 137 138 #define PHY82780_MAX_LANE 4 139 #define PHY82780_CHIP_ID_SIZE 25 140 141 typedef struct phy82780_device_aux_mode { 142 uint32_t repeater; 143 uint32_t ull_datapath; 144 uint32_t core_id; 145 } phy82780_device_aux_mode_t; 146 147 typedef struct phy82780_speed_config_s { 148 uint32 port_refclk_int; 149 int speed; 150 int port_num_lanes; 151 uint32 line_interface; 152 int pll_divider_req ; 153 int higig_port; 154 } phy82780_speed_config_t; 155 156 typedef enum PHY82780_INTF_SIDE { 157 PHY82780_LINE_SIDE, 158 PHY82780_SYS_SIDE 159 }PHY82780_INTF_SIDE; 160 161 /* 162 Config - per logical port 163 */ 164 typedef struct { 165 phymod_polarity_t phy_polarity_config; 166 phymod_phy_reset_t phy_reset_config; 167 phy82780_speed_config_t speed_config; 168 int ull_datapath; 169 int devid; 170 char dev_name[PHY82780_CHIP_ID_SIZE]; 171 int auto_mod_detect; 172 phy82780_device_aux_mode_t *device_aux_modes ; 173 } phy82780_config_t; 174 175 #define DEVID(_pc) (((phy82780_config_t *)((_pc)->driver_data))->devid) 176 #define DEV_NAME(_pc) (((phy82780_config_t *)((_pc)->driver_data))->dev_name) 177 178 #define PHY82780_SET_SYS_SIDE(x) (x).port_loc = phymodPortLocSys 179 #define PHY82780_CLEAR_SYS_SIDE(x) (x).port_loc = phymodPortLocLine 180 181 STATIC int 182 phy_82780_ability_advert_set(int unit, soc_port_t port, 183 soc_port_ability_t *ability); 184 185 STATIC int 186 phy_82780_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability); 187 STATIC int 188 _phy_82780_find_soc_phy_lane(soc_phymod_ctrl_t *pmc, uint32_t lane, 189 soc_phymod_phy_t **p_phy, uint32 *lane_map); 190 191 STATIC int 192 phy_82780_power_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value); 193 STATIC int 194 phy_82780_power_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value); 195 STATIC int 196 phy_82780_per_lane_tx_get(soc_phymod_ctrl_t *pmc, int32 intf, soc_phy_control_t type, int lane, uint32 *value); 197 STATIC int 198 phy_82780_per_lane_tx_set(soc_phymod_ctrl_t *pmc, int32 intf, soc_phy_control_t type, int lane, uint32 value); 199 STATIC int 200 phy_82780_cl72_enable_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value); 201 STATIC int 202 phy_82780_cl72_status_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value); 203 STATIC int 204 phy_82780_cl72_enable_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value); 205 STATIC int 206 phy_82780_link_monitor_status_get (soc_phymod_ctrl_t *pmc, int32 intf, int32 lane); 207 STATIC int 208 phy_82780_link_monitor_set (soc_phymod_ctrl_t *pmc, int32 intf, int32 lane, uint32 value); 209 STATIC int 210 phy_82780_tx_lane_squelch_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value); 211 STATIC int 212 phy_82780_per_lane_tx_lane_squelch_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 *value); 213 STATIC int 214 phy_82780_fec_enable_set(soc_phymod_ctrl_t *pmc, uint32 value); 215 STATIC int 216 phy_82780_loopback_internal_pmd_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value); 217 STATIC int 218 phy_82780_an_set(int unit, soc_port_t port, int enable); 219 STATIC int 220 phy_82780_control_get(int unit, soc_port_t port, soc_phy_control_t type, uint32 *value); 221 STATIC int 222 phy_82780_adoptation_release(phy_ctrl_t *pc, int32 intf); 223 STATIC int 224 phy_82780_config_fail_over(phy_ctrl_t *pc, int32 intf, uint32_t value); 225 STATIC int 226 phy_82780_config_fail_over_get(phy_ctrl_t *pc, int32 intf, uint32_t *value); 227 228 229 /* 230 * Function: 231 * _phy82780_reg_read 232 * Doc: 233 * register read operations 234 * Parameters: 235 * unit - (IN) unit number 236 * core_addr - (IN) core address 237 * reg_addr - (IN) address to read 238 * val - (OUT) read value 239 */ 240 STATIC int 241 _phy82780_reg_read(void* user_acc, uint32_t core_addr, uint32_t reg_addr, uint32_t *val) 242 { 243 uint16 data16; 244 int rv; 245 soc_phymod_core_t *core = (soc_phymod_core_t *)user_acc; 246 247 rv = core->read(core->unit, core_addr, reg_addr, &data16); 248 *val = data16; 249 PHYMOD_VDBG(PHY82780_DBG_REGACC, NULL,("-22%s: core_addr: 0x%08x reg_addr: 0x%08x, data: 0x%04x\n", __func__, core_addr, reg_addr, *val )); 250 251 return rv; 252 } 253 254 /* 255 * Function: 256 * _phy82780_reg_write 257 * Doc: 258 * register write operations 259 * Parameters: 260 * unit - (IN) unit number 261 * core_addr - (IN) core address 262 * reg_addr - (IN) address to write 263 * val - (IN) write value 264 */ 265 STATIC int 266 _phy82780_reg_write(void* user_acc, uint32_t core_addr, uint32_t reg_addr, uint32_t val) 267 { 268 soc_phymod_core_t *core = (soc_phymod_core_t *)user_acc; 269 uint16 data16 = (uint16)val; 270 uint16 mask = (uint16)(val >> 16); 271 272 if (mask) { 273 if (core->wrmask) { 274 return core->wrmask(core->unit, core_addr, reg_addr, data16, mask); 275 } 276 (void)core->read(core->unit, core_addr, reg_addr, &data16); 277 data16 &= ~mask; 278 data16 |= (val & mask); 279 } 280 PHYMOD_VDBG(PHY82780_DBG_REGACC, NULL,("-22%s: core_addr: 0x%08x reg_addr: 0x%08x, data: 0x%04x\n", __func__, core_addr, reg_addr, val )); 281 return core->write(core->unit, core_addr, reg_addr, data16); 282 } 283 284 /* 285 * Function: 286 * phy82780_speed_to_interface_config_get 287 * Purpose: 288 * Convert speed to interface_config struct 289 * Parameters: 290 * unit - BCM unit number. 291 * port - Port number. 292 * speed - speed to convert 293 * interface_config - output interface config struct 294 * Returns: 295 * SOC_E_NONE 296 */ 297 STATIC int 298 phy82780_speed_to_interface_config_get(phy82780_speed_config_t* speed_config, phymod_phy_inf_config_t* interface_config) 299 { 300 SOC_IF_ERROR_RETURN(phymod_phy_inf_config_t_init(interface_config)); 301 302 interface_config->interface_modes = 0; 303 interface_config->data_rate = speed_config->speed; 304 interface_config->pll_divider_req = speed_config->pll_divider_req ; 305 306 switch (speed_config->speed) { 307 case PHY82780_SPD_10G: 308 case PHY82780_SPD_11G: 309 switch(speed_config->line_interface) { 310 case SOC_PORT_IF_KR: 311 interface_config->interface_type = phymodInterfaceKR; 312 break; 313 case SOC_PORT_IF_LR: 314 interface_config->interface_type = phymodInterfaceLR; 315 break; 316 case SOC_PORT_IF_SR: 317 interface_config->interface_type = phymodInterfaceSR; 318 break; 319 case SOC_PORT_IF_XFI: 320 interface_config->interface_type = phymodInterfaceXFI; 321 break; 322 case SOC_PORT_IF_CR: 323 interface_config->interface_type = phymodInterfaceCR; 324 break; 325 case SOC_PORT_IF_LRM: 326 interface_config->interface_type = phymodInterfaceLRM; 327 break; 328 case SOC_PORT_IF_ZR: 329 interface_config->interface_type = phymodInterfaceZR; 330 break; 331 332 333 default: 334 return SOC_E_PARAM; 335 336 } 337 break; 338 case PHY82780_SPD_1G: 339 switch(speed_config->line_interface) { 340 case SOC_PORT_IF_KX: 341 interface_config->interface_type = phymodInterfaceKX; 342 break; 343 case SOC_PORT_IF_SR: 344 case SOC_PORT_IF_LR: 345 interface_config->interface_type = phymodInterfaceSR; 346 break; 347 default: 348 return SOC_E_PARAM; 349 350 } 351 break ; 352 case PHY82780_SPD_40G: 353 case PHY82780_SPD_42G: 354 switch(speed_config->line_interface) { 355 case SOC_PORT_IF_KR4: 356 interface_config->interface_type = phymodInterfaceKR4; 357 break; 358 case SOC_PORT_IF_LR4: 359 interface_config->interface_type = phymodInterfaceLR4; 360 break; 361 case SOC_PORT_IF_SR4: 362 interface_config->interface_type = phymodInterfaceSR4; 363 break; 364 case SOC_PORT_IF_CR4: 365 interface_config->interface_type = phymodInterfaceCR4; 366 break; 367 case SOC_PORT_IF_XLAUI: 368 interface_config->interface_type = phymodInterfaceXLAUI; 369 break; 370 371 default: 372 return SOC_E_PARAM; 373 374 } 375 break; 376 default: 377 return SOC_E_PARAM; 378 } 379 380 switch (speed_config->port_refclk_int) { 381 case 156: 382 interface_config->ref_clock = phymodRefClk156Mhz; 383 break; 384 case 155: 385 interface_config->ref_clock = phymodRefClk155Mhz; 386 break; 387 388 default: 389 return SOC_E_PARAM; 390 } 391 if (speed_config->higig_port) { 392 PHYMOD_INTF_MODES_HIGIG_SET(interface_config); 393 } 394 return SOC_E_NONE; 395 } 396 397 /* 398 * Function: 399 * phy82780_speed_set 400 * Purpose: 401 * Set PHY speed 402 * Parameters: 403 * unit - BCM unit number. 404 * port - Port number. 405 * speed - link speed in Mbps 406 * Returns: 407 * SOC_E_NONE 408 */ 409 410 STATIC int 411 phy82780_speed_set(int unit, soc_port_t port, int speed) 412 { 413 phy_ctrl_t *pc; 414 phy_ctrl_t *int_pc; 415 phy82780_config_t *pCfg; 416 soc_phymod_ctrl_t *pmc; 417 soc_phymod_phy_t *phy; 418 int idx; 419 phy82780_speed_config_t speed_config; 420 phymod_phy_inf_config_t interface_config; 421 int int_speed; 422 423 /* locate phy control */ 424 pc = EXT_PHY_SW_STATE(unit, port); 425 int_pc = INT_PHY_SW_STATE(unit, port); 426 if (pc == NULL || int_pc == NULL) { 427 return SOC_E_INTERNAL; 428 } 429 430 if (speed == 0) { 431 return SOC_E_NONE; 432 } 433 if (SOC_INFO(unit).chip_type == SOC_INFO_CHIP_TYPE_HURRICANE3) { 434 SOC_IF_ERROR_RETURN(PHY_SPEED_SET(int_pc->pd, unit, port, speed)); 435 SOC_IF_ERROR_RETURN(PHY_SPEED_GET(int_pc->pd, unit, port, &int_speed)); 436 if (int_speed != speed) { 437 return SOC_E_CONFIG; 438 } 439 } else { 440 SOC_IF_ERROR_RETURN(PHY_SPEED_GET(int_pc->pd, unit, port, &int_speed)); 441 if (int_speed != speed) 442 { 443 SOC_IF_ERROR_RETURN(PHY_SPEED_SET(int_pc->pd, unit, port, speed)); 444 SOC_IF_ERROR_RETURN(PHY_SPEED_GET(int_pc->pd, unit, port, &int_speed)); 445 if (int_speed != speed) { 446 return SOC_E_CONFIG; 447 } 448 } 449 } 450 pmc = &pc->phymod_ctrl; 451 pCfg = (phy82780_config_t *) pc->driver_data; 452 453 /* take a copy of core and phy configuration values, and set the desired speed */ 454 sal_memcpy(&speed_config, &pCfg->speed_config, sizeof(speed_config)); 455 speed_config.speed = speed; 456 457 /* determine the interface configuration */ 458 SOC_IF_ERROR_RETURN 459 (phy82780_speed_to_interface_config_get(&speed_config, &interface_config)); 460 461 /* now loop through all cores */ 462 for (idx = 0; idx < pmc->num_phys; idx++) { 463 phy = pmc->phy[idx]; 464 if (phy == NULL) { 465 return SOC_E_INTERNAL; 466 } 467 468 SOC_IF_ERROR_RETURN 469 (phymod_phy_interface_config_set(&phy->pm_phy, 470 0 /* flags */, &interface_config)); 471 } 472 473 /* record success */ 474 pCfg->speed_config.speed = speed; 475 return (SOC_E_NONE); 476 } 477 478 /* 479 * Function: 480 * phy82780_speed_get 481 * Purpose: 482 * Get PHY speed 483 * Parameters: 484 * unit - BCM unit number. 485 * port - Port number. 486 * speed - current link speed in Mbps 487 * Returns: 488 * SOC_E_NONE 489 */ 490 STATIC int 491 phy82780_speed_get(int unit, soc_port_t port, int *speed) 492 { 493 phy_ctrl_t *pc; 494 soc_phymod_ctrl_t *pmc; 495 soc_phymod_phy_t *phy; 496 phymod_phy_inf_config_t interface_config; 497 phymod_ref_clk_t ref_clock; 498 int flag = 0; 499 ref_clock = 0; 500 /* locate phy control */ 501 pc = EXT_PHY_SW_STATE(unit, port); 502 if (pc == NULL) { 503 return SOC_E_INTERNAL; 504 } 505 pmc = &pc->phymod_ctrl; 506 507 /* initialize the data structure */ 508 interface_config.data_rate = 0; 509 510 /* now loop through all cores */ 511 phy = pmc->phy[pmc->main_phy]; 512 if (phy == NULL) { 513 return SOC_E_INTERNAL; 514 } 515 /* note that the flags have an option to indicate whether it's ok to reprogram the PLL */ 516 SOC_IF_ERROR_RETURN 517 (phymod_phy_interface_config_get(&phy->pm_phy, flag, 518 ref_clock, 519 &interface_config)); 520 521 *speed = interface_config.data_rate; 522 return (SOC_E_NONE); 523 } 524 525 STATIC int 526 phy82780_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 527 { 528 phy_ctrl_t *pc; 529 phy82780_config_t *pCfg; 530 phy82780_speed_config_t speed_config; 531 phymod_phy_inf_config_t interface_config; 532 soc_phymod_ctrl_t *pmc; 533 soc_phymod_phy_t *phy; 534 int idx; 535 536 pc = EXT_PHY_SW_STATE(unit, port); 537 if (pc == NULL) { 538 return SOC_E_INTERNAL; 539 } 540 pCfg = (phy82780_config_t *) pc->driver_data; 541 pmc = &pc->phymod_ctrl; 542 543 if (pif >= SOC_PORT_IF_COUNT) { 544 return SOC_E_PARAM; 545 } 546 if (pif == SOC_PORT_IF_MII || pif == SOC_PORT_IF_XGMII || pif == SOC_PORT_IF_GMII) { 547 return phy_null_interface_set(unit, port, pif); 548 } 549 550 551 /* take a copy of core and phy configuration values, and set the desired speed */ 552 sal_memcpy(&speed_config, &pCfg->speed_config, sizeof(speed_config)); 553 speed_config.line_interface = pif; 554 SOC_IF_ERROR_RETURN 555 (phy82780_speed_to_interface_config_get(&speed_config, &interface_config)); 556 557 /* now loop through all cores */ 558 for (idx = 0; idx < pmc->num_phys; idx++) { 559 phy = pmc->phy[idx]; 560 if (phy == NULL) { 561 return SOC_E_INTERNAL; 562 } 563 SOC_IF_ERROR_RETURN 564 (phymod_phy_interface_config_set(&phy->pm_phy, 565 0 /* flags */, &interface_config)); 566 } 567 568 pCfg->speed_config.line_interface = pif; 569 return SOC_E_NONE; 570 } 571 572 STATIC int 573 phy82780_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 574 { 575 phy_ctrl_t *pc; 576 soc_phymod_ctrl_t *pmc; 577 soc_phymod_phy_t *phy; 578 phymod_phy_inf_config_t interface_config; 579 phymod_ref_clk_t ref_clock; 580 int flag = 0; 581 ref_clock = 0; 582 583 /* locate phy control */ 584 pc = EXT_PHY_SW_STATE(unit, port); 585 if (pc == NULL) { 586 return SOC_E_INTERNAL; 587 } 588 589 pmc = &pc->phymod_ctrl; 590 591 /* initialize the data structure */ 592 sal_memset(&interface_config, 0x0, sizeof(phymod_phy_inf_config_t)); 593 594 /* now loop through all cores */ 595 phy = pmc->phy[pmc->main_phy]; 596 if (phy == NULL) { 597 return SOC_E_INTERNAL; 598 } 599 /* note that the flags have an option to indicate whether it's ok to reprogram the PLL */ 600 SOC_IF_ERROR_RETURN 601 (phymod_phy_interface_config_get(&phy->pm_phy, ref_clock, 602 flag, &interface_config)); 603 switch (interface_config.interface_type) { 604 case phymodInterfaceKX: 605 *pif = SOC_PORT_IF_KX; 606 break; 607 case phymodInterfaceKR: 608 *pif = SOC_PORT_IF_KR; 609 break; 610 case phymodInterfaceXFI: 611 *pif = SOC_PORT_IF_XFI; 612 break; 613 case phymodInterfaceXLAUI: 614 *pif = SOC_PORT_IF_XLAUI; 615 break; 616 case phymodInterfaceKR4: 617 *pif = SOC_PORT_IF_KR4; 618 break; 619 case phymodInterfaceCR4: 620 *pif = SOC_PORT_IF_CR4; 621 break; 622 case phymodInterfaceSR: 623 *pif = SOC_PORT_IF_SR; 624 break; 625 case phymodInterfaceLR: 626 *pif = SOC_PORT_IF_LR; 627 break; 628 case phymodInterfaceSR4: 629 *pif = SOC_PORT_IF_SR4; 630 break; 631 case phymodInterfaceLR4: 632 *pif = SOC_PORT_IF_LR4; 633 break; 634 case phymodInterfaceCR: 635 *pif = SOC_PORT_IF_CR; 636 break; 637 case phymodInterfaceLRM: 638 *pif = SOC_PORT_IF_LRM; 639 break; 640 case phymodInterfaceZR: 641 *pif = SOC_PORT_IF_ZR; 642 break; 643 644 default: 645 break; 646 } 647 return (SOC_E_NONE); 648 649 } 650 651 /* 652 * Function: 653 * phy82780_reg_read 654 * Purpose: 655 * Routine to read PHY register 656 * Parameters: 657 * unit - BCM unit number 658 * port - Port number 659 * flags - Flags which specify the register type 660 * phy_reg_addr - Encoded register address 661 * phy_data - (OUT) Value read from PHY register 662 * Note: 663 * This register read function is not thread safe. Higher level 664 * function that calls this function must obtain a per port lock 665 * to avoid overriding register page mapping between threads. 666 */ 667 STATIC int 668 phy82780_reg_read(int unit, soc_port_t port, uint32 flags, 669 uint32 phy_reg_addr, uint32 *phy_reg_data) 670 { 671 phy_ctrl_t *pc; 672 soc_phymod_ctrl_t *pmc; 673 phymod_phy_access_t *pm_phy; 674 int idx = 0; 675 uint8 data8 = 0; 676 677 678 pc = EXT_PHY_SW_STATE(unit, port); 679 if (pc == NULL) { 680 return SOC_E_INTERNAL; 681 } 682 683 pmc = &pc->phymod_ctrl; 684 idx = pmc->main_phy ; 685 pm_phy = &pmc->phy[idx]->pm_phy; 686 687 if (flags & SOC_PHY_I2C_DATA8) { 688 SOC_IF_ERROR_RETURN 689 (phymod_phy_i2c_read(pm_phy, 0, SOC_PHY_I2C_DEVAD(phy_reg_addr), SOC_PHY_I2C_REGAD(phy_reg_addr), 1, &data8)); 690 *phy_reg_data = data8; 691 } else { 692 SOC_IF_ERROR_RETURN 693 (phymod_phy_reg_read(pm_phy, phy_reg_addr, phy_reg_data)); 694 } 695 return SOC_E_NONE; 696 } 697 698 /* 699 * Function: 700 * phy82780_reg_write 701 * Purpose: 702 * Routine to write PHY register 703 * Parameters: 704 * uint - BCM unit number 705 * pc - PHY state 706 * flags - Flags which specify the register type 707 * phy_reg_addr - Encoded register address 708 * phy_data - Value write to PHY register 709 * Note: 710 * This register read function is not thread safe. Higher level 711 * function that calls this function must obtain a per port lock 712 * to avoid overriding register page mapping between threads. 713 */ 714 STATIC int 715 phy82780_reg_write(int unit, soc_port_t port, uint32 flags, 716 uint32 phy_reg_addr, uint32 phy_reg_data) 717 { 718 phy_ctrl_t *pc; 719 soc_phymod_ctrl_t *pmc; 720 phymod_phy_access_t *pm_phy; 721 int idx; 722 uint8 data8 = 0; 723 data8 = phy_reg_data & 0xFF; 724 725 pc = EXT_PHY_SW_STATE(unit, port); 726 if (pc == NULL) { 727 return SOC_E_INTERNAL; 728 } 729 730 pmc = &pc->phymod_ctrl; 731 for (idx = 0; idx < pmc->num_phys; idx++) { 732 pm_phy = &pmc->phy[idx]->pm_phy; 733 if (flags & SOC_PHY_I2C_DATA8) { 734 SOC_IF_ERROR_RETURN 735 (phymod_phy_i2c_write(pm_phy, 0, SOC_PHY_I2C_DEVAD(phy_reg_addr), SOC_PHY_I2C_REGAD(phy_reg_addr), 1, &data8)); 736 } else { 737 SOC_IF_ERROR_RETURN 738 (phymod_phy_reg_write(pm_phy, phy_reg_addr, phy_reg_data)); 739 } 740 } 741 return SOC_E_NONE; 742 } 743 744 /* 745 * Function: 746 * phy82780_reg_modify 747 * Purpose: 748 * Routine to write PHY register 749 * Parameters: 750 * uint - BCM unit number 751 * pc - PHY state 752 * flags - Flags which specify the register type 753 * phy_reg_addr - Encoded register address 754 * phy_mo_data - New value for the bits specified in phy_mo_mask 755 * phy_mo_mask - Bit mask to modify 756 * Note: 757 * This function is not thread safe. Higher level 758 * function that calls this function must obtain a per port lock 759 * to avoid overriding register page mapping between threads. 760 */ 761 STATIC int 762 phy82780_reg_modify(int unit, soc_port_t port, uint32 flags, 763 uint32 phy_reg_addr, uint32 phy_data, 764 uint32 phy_data_mask) 765 { 766 phy_ctrl_t *pc; 767 soc_phymod_ctrl_t *pmc; 768 phymod_phy_access_t *pm_phy; 769 uint32 data32, tmp; 770 int idx; 771 772 pc = EXT_PHY_SW_STATE(unit, port); 773 if (pc == NULL) { 774 return SOC_E_INTERNAL; 775 } 776 777 pmc = &pc->phymod_ctrl; 778 for (idx = 0; idx < pmc->num_phys; idx++) { 779 pm_phy = &pmc->phy[idx]->pm_phy; 780 SOC_IF_ERROR_RETURN 781 (phymod_phy_reg_read(pm_phy, phy_reg_addr, &data32)); 782 tmp = data32; 783 data32 &= ~(phy_data_mask); 784 data32 |= (phy_data & phy_data_mask); 785 if (data32 != tmp) { 786 SOC_IF_ERROR_RETURN 787 (phymod_phy_reg_write(pm_phy, phy_reg_addr, data32)); 788 } 789 } 790 return SOC_E_NONE; 791 } 792 793 STATIC void 794 phy82780_core_init(phy_ctrl_t *pc, soc_phymod_core_t *core, 795 phymod_bus_t *core_bus, uint32 core_addr) 796 { 797 phymod_core_access_t *pm_core; 798 phymod_access_t *pm_acc; 799 800 core->unit = pc->unit; 801 core->port = pc->port; 802 core->read = pc->read; 803 core->write = pc->write; 804 core->wrmask = pc->wrmask; 805 806 pm_core = &core->pm_core; 807 phymod_core_access_t_init(pm_core); 808 pm_acc = &pm_core->access; 809 phymod_access_t_init(pm_acc); 810 PHYMOD_ACC_USER_ACC(pm_acc) = core; 811 PHYMOD_ACC_BUS(pm_acc) = core_bus; 812 PHYMOD_ACC_ADDR(pm_acc) = core_addr; 813 814 PHYMOD_ACC_F_CLAUSE45_SET(pm_acc); 815 816 return; 817 } 818 819 STATIC int 820 _phy82780_device_create_attach(soc_phymod_core_t *core, uint32_t core_id) 821 { 822 phy82780_device_aux_mode_t *new_device ; 823 new_device = sal_alloc(sizeof(phy82780_device_aux_mode_t), "phy82780_device_aux_mode"); 824 if (new_device == NULL) { 825 return SOC_E_MEMORY; 826 } 827 sal_memset(new_device, 0 ,sizeof(phy82780_device_aux_mode_t)); 828 829 new_device->core_id = core_id ; 830 core->device_aux_modes = (void *)new_device ; 831 return SOC_E_NONE; 832 } 833 834 STATIC int 835 _phy82780_device_destroy(phy82780_device_aux_mode_t *device) 836 { 837 if (device == NULL) { 838 return SOC_E_PARAM; 839 } 840 sal_free(device); 841 842 return SOC_E_NONE; 843 } 844 845 STATIC void 846 phy82780_cleanup(soc_phymod_ctrl_t *pmc) 847 { 848 int idx; 849 soc_phymod_phy_t *phy; 850 soc_phymod_core_t *core; 851 phy82780_device_aux_mode_t *device ; 852 853 for (idx = 0; idx < pmc->num_phys ; idx++) { 854 phy = pmc->phy[idx]; 855 if (phy == NULL) { 856 LOG_WARN(BSL_LS_SOC_PHY, 857 (BSL_META_U(pmc->unit, 858 "phy object is empty"))); 859 continue; 860 } 861 862 core = phy->core; 863 if (core != NULL) { 864 device = (phy82780_device_aux_mode_t *)core->device_aux_modes ; 865 } 866 /* Destroy core object if not used anymore */ 867 if (core && core->ref_cnt) { 868 if (--core->ref_cnt == 0) { 869 PHYMOD_VDBG(PHY82780_DBG_MEM, NULL,("clean_up device=%p core_p=%p\n", (void *)device, (void *)core)) ; 870 _phy82780_device_destroy(device) ; 871 soc_phymod_core_destroy(pmc->unit, core); 872 } 873 } 874 875 /* Destroy phy object */ 876 if (phy) { 877 PHYMOD_VDBG(PHY82780_DBG_MEM, NULL,("clean_up phy=%p\n", (void *)phy)) ; 878 soc_phymod_phy_destroy(pmc->unit, phy); 879 } 880 } 881 pmc->num_phys = 0; 882 } 883 884 STATIC int32 885 _phy_82780_chip_id_get(phymod_phy_access_t *pm_phy, uint32 *chip_id) 886 { 887 uint32 chip_id_msb = 0, chip_id_lsb = 0; 888 889 890 SOC_IF_ERROR_RETURN( 891 phymod_phy_reg_read(pm_phy, 0xc803, &chip_id_msb)); 892 893 chip_id_msb = (chip_id_msb & 0xF); 894 895 SOC_IF_ERROR_RETURN( 896 phymod_phy_reg_read(pm_phy, 0xc802, &chip_id_lsb)); 897 if (chip_id_msb == 0x8) { 898 if (chip_id_lsb == 0x2780) { 899 *chip_id = 0x82780; 900 } else if(chip_id_lsb == 0x2752) { 901 *chip_id = 0x82752; 902 } else if(chip_id_lsb == 0x2758) { 903 *chip_id = 0x82758; 904 } else if(chip_id_lsb == 0x278F) { 905 *chip_id = 0x8278F; 906 } 907 } else { 908 LOG_WARN(BSL_LS_SOC_PHY, (BSL_META_U(0, 909 "Chip ID not found \n"))); 910 return SOC_E_NOT_FOUND; 911 } 912 913 return SOC_E_NONE; 914 } 915 916 /* 917 * Function: 918 * _phy82780_is_write_disabled 919 * Doc: 920 * register write is disable in wormboot 921 * Parameters: 922 * unit - (IN) unit number 923 * val - (IN) is write disable 924 */ 925 STATIC int 926 _phy82780_is_write_disabled(void* user_acc, uint32_t *val) 927 { 928 #if defined(BCM_WARM_BOOT_SUPPORT) 929 soc_phymod_core_t *core = (soc_phymod_core_t *)user_acc; 930 int unitV; 931 unitV = core->unit; 932 *val = SOC_WARM_BOOT(unitV); 933 #else 934 *val = 0; 935 #endif 936 return SOC_E_NONE; 937 } 938 939 /* 940 * Function: 941 * phy82780_probe 942 * Purpose: 943 * xx 944 * Parameters: 945 * pc->phy_id (IN) 946 * pc->unit (IN) 947 * pc->port (IN) 948 * pc->size (OUT) - memory required by phy port 949 * pc->dev_name (OUT) - set to port device name 950 * 951 * Note: 952 */ 953 STATIC int 954 phy82780_probe(int unit, phy_ctrl_t *pc) 955 { 956 int rv, idx; 957 uint32 lane_map, num_phys, core_id, phy_id, found; 958 phymod_bus_t core_bus; 959 phymod_dispatch_type_t phy_type; 960 phymod_core_access_t *pm_core; 961 phymod_phy_access_t *pm_phy; 962 phymod_access_t *pm_acc; 963 soc_phymod_ctrl_t *pmc; 964 soc_phymod_phy_t *phy; 965 soc_phymod_core_t *core; 966 soc_phymod_core_t core_probe; 967 soc_info_t *si; 968 phyident_core_info_t core_info[8]; 969 int port; 970 int phy_port; /* physical port number */ 971 /* Initialize PHY bus */ 972 SOC_IF_ERROR_RETURN(phymod_bus_t_init(&core_bus)); 973 core_bus.bus_name = "phy82780"; 974 core_bus.read = _phy82780_reg_read; 975 core_bus.write = _phy82780_reg_write; 976 core_bus.is_write_disabled = _phy82780_is_write_disabled; 977 #ifdef PORTMOD_SUPPORT 978 /* If portmod feature is enabled let the 979 * PM take care of phy control*/ 980 981 if (soc_feature(unit, soc_feature_portmod)) { 982 return SOC_E_NOT_FOUND; 983 } 984 #endif/* PORTMOD_SUPPORT */ 985 986 /* Configure PHY bus properties */ 987 if (pc->wrmask) { 988 PHYMOD_BUS_CAP_WR_MODIFY_SET(&core_bus); 989 PHYMOD_BUS_CAP_LANE_CTRL_SET(&core_bus); 990 } 991 992 port = pc->port; 993 pmc = &pc->phymod_ctrl; 994 si = &SOC_INFO(unit); 995 if (soc_feature(unit, soc_feature_logical_port_num)) { 996 phy_port = si->port_l2p_mapping[port]; 997 } else { 998 phy_port = port; 999 } 1000 1001 /* Install clean up function */ 1002 pmc->unit = pc->unit; 1003 pmc->cleanup = phy82780_cleanup; 1004 /*pmc->symbols = &bcmi_tscf_xgxs_symbols;*/ 1005 1006 1007 pc->lane_num = SOC_PORT_BINDEX(unit, phy_port); 1008 pc->chip_num = SOC_BLOCK_NUMBER(unit, SOC_PORT_BLOCK(unit, phy_port)); 1009 1010 /* request memory for the configuration structure */ 1011 pc->size = sizeof(phy82780_config_t); 1012 1013 /* Bit N corresponds to lane N in lane_map */ 1014 lane_map = 0xf; 1015 num_phys = 1; 1016 switch (si->port_num_lanes[port]) { 1017 case 10: 1018 pc->phy_mode = PHYCTRL_MULTI_CORE_PORT; 1019 break; 1020 case 4: 1021 pc->phy_mode = PHYCTRL_QUAD_LANE_PORT; 1022 break; 1023 case 2: 1024 lane_map = 0x3; 1025 pc->phy_mode = PHYCTRL_DUAL_LANE_PORT; 1026 break; 1027 case 1: 1028 case 0: 1029 lane_map = 0x1; 1030 pc->phy_mode = PHYCTRL_ONE_LANE_PORT; 1031 break; 1032 default: 1033 return SOC_E_CONFIG; 1034 } 1035 /*lane_map <<= pc->lane_num;*/ 1036 1037 core_info[0].mdio_addr = pc->phy_id; 1038 phy_type = phymodDispatchTypeQuadra28; 1039 1040 /* Probe cores */ 1041 for (idx = 0; idx < num_phys ; idx++) { 1042 phy82780_core_init(pc, &core_probe, &core_bus, 1043 core_info[idx].mdio_addr); 1044 /* Check that core is indeed an quadra28 core */ 1045 pm_core = &core_probe.pm_core; 1046 pm_core->type = phy_type; 1047 rv = phymod_core_identify(pm_core, 0, &found); 1048 if (SOC_FAILURE(rv)) { 1049 LOG_WARN(BSL_LS_SOC_PHY, 1050 (BSL_META_U(unit, 1051 "port %d: ERROR!!!\n"), 1052 pc->port)); 1053 1054 return rv; 1055 } 1056 if (!found) { 1057 LOG_WARN(BSL_LS_SOC_PHY, 1058 (BSL_META_U(unit, 1059 "port %d: NOT FOUND!!\n"), 1060 pc->port)); 1061 1062 return SOC_E_NOT_FOUND; 1063 } 1064 } 1065 1066 rv = SOC_E_NONE; 1067 for (idx = 0; idx < num_phys ; idx++) { 1068 /* Set core and phy IDs based on PHY address */ 1069 core_id = pc->phy_id + idx; 1070 phy_id = (lane_map << 16) | core_id; 1071 1072 /* Create PHY object */ 1073 rv = soc_phymod_phy_create(unit, phy_id, &pmc->phy[idx]); 1074 if (SOC_FAILURE(rv)) { 1075 break; 1076 } 1077 pmc->num_phys++; 1078 1079 /* Initialize phy object */ 1080 phy = pmc->phy[idx]; 1081 pm_phy = &phy->pm_phy; 1082 phymod_phy_access_t_init(pm_phy); 1083 1084 /* Find or create associated core object */ 1085 rv = soc_phymod_core_find_by_id(unit, core_id, &phy->core); 1086 if (rv == SOC_E_NOT_FOUND) { 1087 rv = soc_phymod_core_create(unit, core_id, &phy->core); 1088 rv |= _phy82780_device_create_attach(phy->core, core_id) ; 1089 } 1090 if (SOC_FAILURE(rv)) { 1091 break; 1092 } 1093 } 1094 if (SOC_FAILURE(rv)) { 1095 phy82780_cleanup(pmc); 1096 return rv; 1097 } 1098 1099 for (idx = 0; idx < num_phys ; idx++) { 1100 phy = pmc->phy[idx]; 1101 core = phy->core; 1102 pm_core = &core->pm_core; 1103 1104 /* Initialize core object if newly created */ 1105 if (core->ref_cnt == 0) { 1106 sal_memcpy(&core->pm_bus, &core_bus, sizeof(core->pm_bus)); 1107 phy82780_core_init(pc, core, &core->pm_bus, 1108 core_info[idx].mdio_addr); 1109 /* Set dispatch type */ 1110 pm_core->type = phy_type; 1111 } 1112 core->ref_cnt++; 1113 1114 /* Initialize phy access based on associated core */ 1115 pm_acc = &phy->pm_phy.access; 1116 sal_memcpy(pm_acc, &pm_core->access, sizeof(*pm_acc)); 1117 phy->pm_phy.type = phy_type; 1118 PHYMOD_ACC_LANE_MASK(pm_acc) = lane_map; 1119 } 1120 1121 return SOC_E_NONE; 1122 } 1123 1124 1125 /* 1126 * Function: 1127 * phy82780_config_init 1128 * Purpose: 1129 * Determine phy configuration data for purposes of PHYMOD initialization. 1130 * 1131 * A side effect of this procedure is to save some per-logical port 1132 * information in (phy82780_cfg_t *) &pc->driver_data; 1133 * 1134 * Parameters: 1135 * unit - BCM unit number. 1136 * port - Port number. 1137 * logical_lane_offset - starting logical lane number 1138 * Returns: 1139 * SOC_E_NONE 1140 */ 1141 STATIC int 1142 phy82780_config_init(int unit, soc_port_t port, int logical_lane_offset, 1143 phymod_core_init_config_t *core_init_config, 1144 phymod_phy_init_config_t *pm_phy_init_config) 1145 { 1146 phy_ctrl_t *pc; 1147 phy82780_speed_config_t *speed_config; 1148 phy82780_config_t *pCfg; 1149 phymod_firmware_load_method_t fw_ld_method; 1150 int port_num_lanes; 1151 int core_num; 1152 int phy_num_lanes; 1153 int phy_speed_max; 1154 1155 pc = EXT_PHY_SW_STATE(unit, port); 1156 if (pc == NULL) { 1157 return SOC_E_INTERNAL; 1158 } 1159 pCfg = (phy82780_config_t *) pc->driver_data; 1160 1161 port_num_lanes = SOC_INFO(unit).port_num_lanes[port]; 1162 1163 /* figure out how many lanes are in this phy */ 1164 core_num = (logical_lane_offset / 4); 1165 phy_num_lanes = (port_num_lanes - logical_lane_offset); 1166 if (phy_num_lanes > MAX_NUM_LANES) { 1167 phy_num_lanes = MAX_NUM_LANES; 1168 } 1169 1170 /*CORE configuration*/ 1171 phymod_core_init_config_t_init(core_init_config); 1172 fw_ld_method = phymodFirmwareLoadMethodInternal; 1173 if (soc_property_port_get(pc->unit, pc->port, "82780_glue", 0)) { 1174 fw_ld_method = phymodFirmwareLoadMethodNone; 1175 } 1176 core_init_config->flags = PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY; 1177 core_init_config->firmware_load_method = soc_property_port_get(unit, port, 1178 spn_LOAD_FIRMWARE, fw_ld_method); 1179 core_init_config->firmware_load_method &= 0xff; /* clear checksum bits */ 1180 core_init_config->lane_map.num_of_lanes = NUM_LANES; 1181 1182 speed_config = &(pCfg->speed_config); 1183 speed_config->port_refclk_int = 156; 1184 speed_config->port_num_lanes = phy_num_lanes; 1185 phy_speed_max = soc_property_port_get(unit, port, spn_PHY_INIT_SPEED, pc->speed_max); 1186 1187 if (port_num_lanes == 1) { 1188 if (phy_speed_max == PHY82780_SPD_10G) { 1189 speed_config->line_interface = SOC_PORT_IF_SR; 1190 speed_config->speed = PHY82780_SPD_10G; 1191 } else if (phy_speed_max == PHY82780_SPD_1G) { 1192 speed_config->line_interface = SOC_PORT_IF_SR; 1193 speed_config->speed = PHY82780_SPD_1G; 1194 } else if (phy_speed_max == PHY82780_SPD_11G) { 1195 speed_config->line_interface = SOC_PORT_IF_SR; 1196 speed_config->speed = PHY82780_SPD_11G; 1197 } else { 1198 speed_config->line_interface = SOC_PORT_IF_SR; 1199 speed_config->speed = PHY82780_SPD_10G; 1200 } 1201 } else if (port_num_lanes == 4) { 1202 if (phy_speed_max == PHY82780_SPD_40G) { 1203 speed_config->speed = PHY82780_SPD_40G; 1204 speed_config->line_interface = SOC_PORT_IF_SR4; 1205 } else if (phy_speed_max == PHY82780_SPD_42G) { 1206 speed_config->line_interface = SOC_PORT_IF_SR4; 1207 speed_config->speed = PHY82780_SPD_42G; 1208 } else { 1209 speed_config->line_interface = SOC_PORT_IF_SR4; 1210 speed_config->speed = PHY82780_SPD_40G; 1211 } 1212 } else { 1213 LOG_CLI((BSL_META_U(unit,"Invalid number of lanes:%d\n "), port_num_lanes)); 1214 return SOC_E_CONFIG; 1215 } 1216 1217 /* PHY configuration */ 1218 phymod_phy_init_config_t_init(pm_phy_init_config); 1219 1220 pm_phy_init_config->polarity.rx_polarity 1221 = soc_property_port_get(unit, port, 1222 spn_PHY_RX_POLARITY_FLIP, 1223 0xFFFF); 1224 pm_phy_init_config->polarity.tx_polarity 1225 = soc_property_port_get(unit, port, 1226 spn_PHY_TX_POLARITY_FLIP, 1227 0xFFFF); 1228 1229 1230 /* phy_ctrl_t configuration (LOGICAL PORT BASED) 1231 * Only do this once, for the first core of the logical port*/ 1232 if (core_num == 0) { 1233 /* phy_mode, PHYCTRL_MDIO_ADDR_SHARE, PHY_FLAGS_INDEPENDENT_LANE */ 1234 if (port_num_lanes == 4) { 1235 pc->phy_mode = PHYCTRL_QUAD_LANE_PORT; 1236 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_INDEPENDENT_LANE); 1237 } else if (port_num_lanes == 1) { 1238 pc->phy_mode = PHYCTRL_ONE_LANE_PORT; 1239 pc->flags |= PHYCTRL_MDIO_ADDR_SHARE; 1240 PHY_FLAGS_SET(unit, port, PHY_FLAGS_INDEPENDENT_LANE); 1241 } 1242 } 1243 1244 return SOC_E_NONE; 1245 } 1246 1247 STATIC int 1248 _phy_82780_init_pass1(int unit, soc_port_t port) 1249 { 1250 phy_ctrl_t *pc; 1251 soc_phymod_ctrl_t *pmc; 1252 soc_phymod_phy_t *phy = NULL; 1253 soc_phymod_core_t *core; 1254 phy82780_config_t *pCfg; 1255 phy82780_speed_config_t *speed_config; 1256 phymod_phy_inf_config_t interface_config; 1257 phymod_core_status_t core_status; 1258 int idx; 1259 int logical_lane_offset; 1260 soc_port_ability_t ability; 1261 soc_phy_info_t *pi; 1262 char *dev_name; 1263 int len = 0; 1264 uint32 chip_id = 0; 1265 int phy_force_dload = 0, dload_method = 0; 1266 1267 pc = EXT_PHY_SW_STATE(unit, port); 1268 1269 if (pc == NULL) { 1270 return SOC_E_INTERNAL; 1271 } 1272 1273 pc->driver_data = (void*)(pc+1); 1274 pmc = &pc->phymod_ctrl; 1275 pCfg = (phy82780_config_t *) pc->driver_data; 1276 1277 sal_memset(pCfg, 0, sizeof(*pCfg)); 1278 speed_config = &(pCfg->speed_config); 1279 1280 sal_memset(&ability, 0, sizeof(ability)); 1281 1282 dev_name = DEV_NAME(pc); 1283 1284 phy = pmc->phy[0]; 1285 1286 SOC_IF_ERROR_RETURN( 1287 _phy_82780_chip_id_get(&phy->pm_phy, &chip_id)); 1288 DEVID(pc) = chip_id; 1289 1290 pi = &SOC_PHY_INFO(unit, port); 1291 1292 /* Since Bcast is enabled so the device name is same for all the 1293 * Q28, In pass 2 dev name will be overwritten*/ 1294 sal_strncpy (dev_name, "Quarda28", sal_strlen("Quadra28")); 1295 len = sal_strlen(dev_name); 1296 1297 dev_name[len++] = '/'; 1298 dev_name[len++] = pc->lane_num + '0'; 1299 dev_name[len] = 0; 1300 pc->dev_name = dev_name; /* string terminator */ 1301 pi->phy_name = dev_name; 1302 1303 /* Loop through all phymod phys that support this SDK phy */ 1304 logical_lane_offset = 0; 1305 for (idx = 0; idx < pmc->num_phys; idx++) { 1306 phy = pmc->phy[idx]; 1307 core = phy->core; 1308 1309 pCfg->device_aux_modes = (phy82780_device_aux_mode_t *)(core->device_aux_modes) ; 1310 pCfg->device_aux_modes->repeater = soc_property_port_get(unit, port, spn_PHY_PCS_REPEATER, phymodOperationModeRepeater); 1311 pCfg->device_aux_modes->ull_datapath = soc_property_port_get(unit, port, 1312 spn_PHY_ULL_DATAPATH, phymodDatapathNormal); 1313 phy_force_dload = soc_property_port_get(unit, port, 1314 spn_PHY_FORCE_FIRMWARE_LOAD, 0x11); 1315 #if defined (BCM_WARM_BOOT_SUPPORT) /* Warmboot support */ 1316 if ( SOC_WARM_BOOT(pc->unit) || SOC_IS_RELOADING(pc->unit) ) { 1317 dload_method = phymodFirmwareLoadMethodNone; 1318 core->init_config.firmware_load_method = phymodFirmwareLoadMethodNone; 1319 } else 1320 #endif 1321 { 1322 dload_method = ((phy_force_dload & 0xF0)>>4); 1323 phy_force_dload &= 0xf; 1324 } 1325 if (!pCfg->device_aux_modes->repeater && 1326 pCfg->device_aux_modes->ull_datapath) { 1327 1328 LOG_CLI((BSL_META_U(unit,"Both ULL datapath and retimer cannot be enabled simultaneously," 1329 "so disabling ULL:%d\n "), port)); 1330 pCfg->device_aux_modes->repeater = phymodOperationModeRetimer; 1331 pCfg->device_aux_modes->ull_datapath = phymodDatapathNormal; 1332 } 1333 1334 /* determine configuration data structure to default values, based on SOC properties */ 1335 SOC_IF_ERROR_RETURN 1336 (phy82780_config_init(unit, port, 1337 logical_lane_offset, 1338 &core->init_config, &phy->init_config)); 1339 speed_config->higig_port = PBMP_MEMBER(PBMP_HG_ALL(unit), port); 1340 /* set the port to its max or init_speed */ 1341 SOC_IF_ERROR_RETURN 1342 (phy82780_speed_to_interface_config_get(speed_config, &interface_config)); 1343 sal_memcpy(&core->init_config.interface, &interface_config, sizeof(interface_config)); 1344 core->init_config.interface.device_aux_modes = (void *)pCfg->device_aux_modes; 1345 1346 core->init_config.op_datapath = pCfg->device_aux_modes->ull_datapath; 1347 if (((DEVID(pc) == Q28_ID_82752) && ((pc->phy_id & 0x1) == 0)) || 1348 ((pc->phy_id & 0x3) == 0)) { 1349 core_status.pmd_active = 0; 1350 if (dload_method == phymodFirmwareLoadMethodInternal && (phy_force_dload == phymodFirmwareLoadForce ||\ 1351 phy_force_dload == phymodFirmwareLoadAuto)) { 1352 core->init_config.firmware_load_method = phymodFirmwareLoadMethodInternal; 1353 if(phy_force_dload == phymodFirmwareLoadForce) 1354 { 1355 PHYMOD_CORE_INIT_F_FW_FORCE_DOWNLOAD_SET(&(core->init_config)); 1356 }else if(phy_force_dload == phymodFirmwareLoadAuto){ 1357 PHYMOD_CORE_INIT_F_FW_AUTO_DOWNLOAD_SET(&(core->init_config)); 1358 } 1359 pc->flags |= PHYCTRL_MDIO_BCST; 1360 } else if (dload_method == 2 && (phy_force_dload == phymodFirmwareLoadForce ||\ 1361 phy_force_dload == phymodFirmwareLoadAuto)) { 1362 core->init_config.firmware_load_method = phymodFirmwareLoadMethodProgEEPROM; 1363 SOC_IF_ERROR_RETURN ( 1364 phymod_core_init(&core->pm_core, &core->init_config, &core_status)); 1365 } else if (dload_method == phymodFirmwareLoadMethodNone) { 1366 phymod_core_firmware_info_t fw_info; 1367 SOC_IF_ERROR_RETURN ( 1368 phymod_core_firmware_info_get(&core->pm_core, &fw_info)); 1369 if (fw_info.fw_version == 0) { 1370 LOG_CLI((BSL_META_U(unit, "No FW found on the chip, Please use" 1371 "spn_PHY_FORCE_FIRMWARE_LOAD as 0x11 to download FW to chip"))); 1372 return SOC_E_UNAVAIL; 1373 } 1374 } 1375 core->init = TRUE; 1376 } 1377 logical_lane_offset += core->init_config.lane_map.num_of_lanes; 1378 } 1379 1380 /* indicate second pass of init is needed */ 1381 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS2); 1382 1383 return SOC_E_NONE; 1384 } 1385 void phy82780_phyctrl_to_phymod_interface (uint16_t sys_if, phymod_interface_t *sys_intf) 1386 { 1387 switch (sys_if) 1388 { 1389 case SOC_PORT_IF_XFI: 1390 *sys_intf = phymodInterfaceXFI; 1391 break; 1392 case SOC_PORT_IF_KR: 1393 *sys_intf = phymodInterfaceKR; 1394 break; 1395 case SOC_PORT_IF_KR4: 1396 *sys_intf = phymodInterfaceKR4; 1397 break; 1398 case SOC_PORT_IF_CR: 1399 *sys_intf = phymodInterfaceCR; 1400 break; 1401 case SOC_PORT_IF_CR4: 1402 *sys_intf = phymodInterfaceCR4; 1403 break; 1404 case SOC_PORT_IF_XLAUI: 1405 *sys_intf = phymodInterfaceXLAUI; 1406 break; 1407 case SOC_PORT_IF_SR: 1408 *sys_intf = phymodInterfaceSR; 1409 break; 1410 case SOC_PORT_IF_CAUI: 1411 *sys_intf = phymodInterfaceCAUI; 1412 break; 1413 case SOC_PORT_IF_LR: 1414 *sys_intf = phymodInterfaceLR; 1415 break; 1416 case SOC_PORT_IF_LR4: 1417 *sys_intf = phymodInterfaceLR4; 1418 break; 1419 case SOC_PORT_IF_SR4: 1420 *sys_intf = phymodInterfaceSR4; 1421 break; 1422 case SOC_PORT_IF_KX: 1423 *sys_intf = phymodInterfaceKX; 1424 break; 1425 case SOC_PORT_IF_XLAUI2: 1426 *sys_intf = phymodInterfaceXLAUI2; 1427 break; 1428 default: 1429 *sys_intf = phymodInterfaceXLAUI; 1430 } 1431 1432 } 1433 1434 #if defined (BCM_WARM_BOOT_SUPPORT) 1435 void phy82780_phymod_to_phyctrl_interface(uint16_t sys_if, soc_port_if_t *sys_intf) 1436 { 1437 switch (sys_if) 1438 { 1439 case phymodInterfaceXFI: 1440 *sys_intf = SOC_PORT_IF_XFI; 1441 break; 1442 case phymodInterfaceKX: 1443 *sys_intf = SOC_PORT_IF_KX; 1444 break; 1445 case phymodInterfaceKR: 1446 *sys_intf = SOC_PORT_IF_KR; 1447 break; 1448 case phymodInterfaceKR4: 1449 *sys_intf = SOC_PORT_IF_KR4; 1450 break; 1451 case phymodInterfaceCR: 1452 *sys_intf = SOC_PORT_IF_CR; 1453 break; 1454 case phymodInterfaceCR4: 1455 *sys_intf = SOC_PORT_IF_CR4; 1456 break; 1457 case phymodInterfaceXLAUI: 1458 *sys_intf = SOC_PORT_IF_XLAUI; 1459 break; 1460 case phymodInterfaceSR: 1461 *sys_intf = SOC_PORT_IF_SR; 1462 break; 1463 case phymodInterfaceCAUI: 1464 *sys_intf = SOC_PORT_IF_CAUI; 1465 break; 1466 case phymodInterfaceLR: 1467 *sys_intf = SOC_PORT_IF_LR; 1468 break; 1469 case phymodInterfaceLR4: 1470 *sys_intf = SOC_PORT_IF_LR4; 1471 break; 1472 case phymodInterfaceSR4: 1473 *sys_intf = SOC_PORT_IF_SR4; 1474 break; 1475 case phymodInterfaceXLAUI2: 1476 *sys_intf = SOC_PORT_IF_XLAUI2; 1477 break; 1478 1479 default: 1480 *sys_intf = 0; 1481 } 1482 1483 } 1484 #endif 1485 1486 STATIC int 1487 _phy_82780_init_pass2(int unit, soc_port_t port) 1488 { 1489 phy_ctrl_t *pc; 1490 soc_phymod_ctrl_t *pmc; 1491 soc_phymod_phy_t *phy = NULL; 1492 phy82780_config_t *pCfg; 1493 phy82780_speed_config_t *speed_config; 1494 phymod_phy_inf_config_t interface_config; 1495 soc_port_ability_t ability; 1496 uint16_t sys_if = 0; 1497 phymod_interface_t sys_intf = 0; 1498 uint16_t temp = 0; 1499 soc_phy_info_t *pi; 1500 char *dev_name; 1501 int len = 0; 1502 #if defined (BCM_WARM_BOOT_SUPPORT) 1503 soc_port_if_t pif; 1504 #endif 1505 1506 pc = EXT_PHY_SW_STATE(unit, port); 1507 1508 if (pc == NULL) { 1509 return SOC_E_INTERNAL; 1510 } 1511 1512 dev_name = DEV_NAME(pc); 1513 sal_memset(&ability, 0, sizeof(ability)); 1514 pc->driver_data = (void*)(pc+1); 1515 pmc = &pc->phymod_ctrl; 1516 pCfg = (phy82780_config_t *) pc->driver_data; 1517 1518 pi = &SOC_PHY_INFO(unit, port); 1519 if (DEVID(pc) == Q28_ID_82780) { 1520 /* coverity[secure_coding] */ 1521 sal_strncpy (dev_name, "BCM82780", sal_strlen("BCM82780")); 1522 } else if (DEVID(pc) == Q28_ID_82752) { 1523 /* coverity[secure_coding] */ 1524 sal_strncpy (dev_name, "BCM82752", sal_strlen("BCM82752")); 1525 } else if (DEVID(pc) == Q28_ID_82758) { 1526 /* coverity[secure_coding] */ 1527 sal_strncpy (dev_name, "BCM82758", sal_strlen("BCM82758")); 1528 } else if (DEVID(pc) == Q28_ID_8278F) { 1529 /* coverity[secure_coding] */ 1530 sal_strncpy (dev_name, "BCM8278F", sal_strlen("BCM8278F")); 1531 } else { 1532 /* coverity[secure_coding] */ 1533 sal_strncpy (dev_name, "Quarda28", sal_strlen("Quadra28")); 1534 } 1535 1536 len = sal_strlen(dev_name); 1537 1538 dev_name[len++] = '/'; 1539 dev_name[len++] = pc->lane_num + '0'; 1540 dev_name[len] = 0; 1541 pc->dev_name = dev_name; /* string terminator */ 1542 pi->phy_name = dev_name; 1543 1544 speed_config = &(pCfg->speed_config); 1545 phy = pmc->phy[0]; 1546 { 1547 soc_phymod_core_t *pmc_core; 1548 phymod_core_access_t *pm_core; 1549 phymod_core_status_t core_status; 1550 1551 pmc_core = pmc->phy[0]->core; 1552 pm_core = &pmc_core->pm_core; 1553 PHYMOD_CORE_INIT_F_FW_LOAD_END_SET(&(pmc_core->init_config)); 1554 pmc_core->init_config.op_datapath = pCfg->device_aux_modes->ull_datapath; 1555 if (((DEVID(pc) == Q28_ID_82752) && ((pc->phy_id & 0x1) == 0)) || 1556 ((pc->phy_id & 0x3) == 0)) { 1557 temp = soc_property_port_get(unit, port, 1558 spn_PHY_FORCE_FIRMWARE_LOAD, 0x11); 1559 #if defined (BCM_WARM_BOOT_SUPPORT) /* */ 1560 if ( SOC_WARM_BOOT(pc->unit) || SOC_IS_RELOADING(pc->unit) ) { 1561 /* In case of warm boot do not reinitialize */ 1562 } else 1563 #endif /* BCM_WARM_BOOT_SUPPORT */ 1564 if (((temp & 0xf) == 1) && ((temp & 0xf0) == 0x10)) { 1565 SOC_IF_ERROR_RETURN ( 1566 phymod_core_init(pm_core, &pmc_core->init_config, &core_status)); 1567 } 1568 } 1569 1570 SOC_IF_ERROR_RETURN 1571 (phy82780_speed_to_interface_config_get(speed_config, &interface_config)); 1572 phy->init_config.interface.interface_type=interface_config.interface_type; 1573 phy->init_config.interface.data_rate=interface_config.data_rate; 1574 phy->init_config.op_mode = pCfg->device_aux_modes->repeater; 1575 #if defined (BCM_WARM_BOOT_SUPPORT) /* */ 1576 if ( SOC_WARM_BOOT(pc->unit) || SOC_IS_RELOADING(pc->unit) ) { 1577 /* In case of warm boot do not reinitialize */ 1578 } else 1579 #endif /* BCM_WARM_BOOT_SUPPORT */ 1580 SOC_IF_ERROR_RETURN 1581 (phymod_phy_init(&phy->pm_phy, &phy->init_config)); 1582 } 1583 1584 SOC_IF_ERROR_RETURN 1585 (phy82780_speed_to_interface_config_get(speed_config, &interface_config)); 1586 #if defined (BCM_WARM_BOOT_SUPPORT) /* */ 1587 if ( SOC_WARM_BOOT(pc->unit) || SOC_IS_RELOADING(pc->unit) ) { 1588 /* In case of warm boot do not reinitialize */ 1589 phy82780_phymod_to_phyctrl_interface(interface_config.interface_type, &pif); 1590 pCfg->speed_config.line_interface = pif; 1591 pCfg->speed_config.speed=interface_config.data_rate; 1592 } else 1593 #endif /* BCM_WARM_BOOT_SUPPORT */ 1594 SOC_IF_ERROR_RETURN 1595 (phymod_phy_interface_config_set(&phy->pm_phy, 1596 0 /* flags */, &interface_config)); 1597 /* Config Sys interface*/ 1598 sys_if = soc_property_port_get(unit, port, spn_PHY_SYS_INTERFACE, 0); 1599 if (sys_if) { 1600 phy82780_phyctrl_to_phymod_interface(sys_if, &sys_intf); 1601 if (sys_intf == 0) { 1602 return SOC_E_PARAM; 1603 } 1604 PHY82780_SET_SYS_SIDE(phy->pm_phy); 1605 interface_config.interface_type = sys_intf; 1606 #if defined (BCM_WARM_BOOT_SUPPORT) /* */ 1607 if ( SOC_WARM_BOOT(pc->unit) || SOC_IS_RELOADING(pc->unit) ) { 1608 /* In case of warm boot do not reinitialize */ 1609 } else 1610 #endif /* BCM_WARM_BOOT_SUPPORT */ 1611 SOC_IF_ERROR_RETURN 1612 (phymod_phy_interface_config_set(&phy->pm_phy, 1613 0 /* flags */, &interface_config)); 1614 1615 PHY82780_CLEAR_SYS_SIDE(phy->pm_phy); 1616 } 1617 1618 /* setup the port's an cap */ 1619 SOC_IF_ERROR_RETURN 1620 (phy_82780_ability_local_get(unit, port, &ability)); 1621 1622 LOG_INFO(BSL_LS_SOC_PHY, 1623 (BSL_META_U(pc->unit, 1624 "phy82780_init_pass2: u=%d p=%d\n"), unit, port)); 1625 1626 if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) { 1627 /* indicate third pass of init is needed */ 1628 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS3); 1629 } 1630 1631 return SOC_E_NONE; 1632 } 1633 1634 STATIC int 1635 _phy_82780_init_pass3(int unit, soc_port_t port) 1636 { 1637 phy_ctrl_t *pc; 1638 phy82780_config_t *pCfg; 1639 1640 pc = EXT_PHY_SW_STATE(unit, port); 1641 1642 if (pc == NULL) { 1643 return SOC_E_INTERNAL; 1644 } 1645 1646 pc->driver_data = (void*)(pc+1); 1647 pCfg = (phy82780_config_t *) pc->driver_data; 1648 1649 LOG_INFO(BSL_LS_SOC_PHY, 1650 (BSL_META_U(unit, 1651 "PHY82328 init pass3: u=%d p=%d\n"), unit, port)); 1652 1653 /* If configured, enable module auto detection */ 1654 pCfg->auto_mod_detect = soc_property_port_get(unit, port, spn_PHY_MOD_AUTO_DETECT, 0); 1655 if (pCfg->auto_mod_detect) { 1656 /* Nothing added for now*/ 1657 1658 } 1659 1660 return SOC_E_NONE; 1661 } 1662 1663 /* 1664 * Function: 1665 * phy82780_init 1666 * 1667 * An SDK "phy" is a logical port, which can consist of from 1-10 lanes, 1668 * (A phy with more than 4 lanes requires more than one core). 1669 * Per-logical port information is saved in &pc->driver_data. 1670 * An SDK phy is implemented as one or more PHYMOD "phy"s. 1671 * 1672 * A PHYMOD "phy" resides completely within a single core, which can be 1673 * from 1 to 4 lanes. 1674 * Per-phymod phy information is kept in (soc_phymod_ctrl_t) *pc->phymod_ctrl 1675 * A phymod phy points to its core. Up to 4 phymod phys can be on a single core 1676 * 1677 * Purpose: 1678 * Initialize a phy82780 1679 * Parameters: 1680 * unit - BCM unit number. 1681 * port - Port number. 1682 * Returns: 1683 * SOC_E_NONE 1684 */ 1685 STATIC int 1686 phy_82780_init(int unit, soc_port_t port) 1687 { 1688 phy_ctrl_t *pc; 1689 1690 pc = EXT_PHY_SW_STATE(unit, port); 1691 if (pc == NULL) { 1692 return SOC_E_INTERNAL; 1693 } 1694 1695 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) || 1696 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 1697 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER | PHY_FLAGS_C45 | PHY_FLAGS_REPEATER); 1698 SOC_IF_ERROR_RETURN(_phy_82780_init_pass1(unit, port)); 1699 if (PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT) { 1700 return SOC_E_NONE; 1701 } 1702 } 1703 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) || 1704 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 1705 SOC_IF_ERROR_RETURN( _phy_82780_init_pass2(unit, port)); 1706 1707 LOG_INFO(BSL_LS_SOC_PHY, 1708 (BSL_META_U(unit, 1709 "82780 init pass2 completed: u=%d p=%d\n"), unit, port)); 1710 if (PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT) { 1711 return SOC_E_NONE; 1712 } 1713 } 1714 1715 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS3) || 1716 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 1717 1718 SOC_IF_ERROR_RETURN(_phy_82780_init_pass3(unit, port)); 1719 1720 LOG_INFO(BSL_LS_SOC_PHY, 1721 (BSL_META_U(unit, 1722 "PHY82780 init pass3 completed: u=%d p=%d\n"), unit, port)); 1723 PHYCTRL_INIT_STATE_SET(pc, PHYCTRL_INIT_STATE_DEFAULT); 1724 return SOC_E_NONE; 1725 } 1726 return SOC_E_NONE; 1727 } 1728 1729 /* 1730 * Function: 1731 * phy_82780_ability_local_get 1732 * Purpose: 1733 * xx 1734 * Parameters: 1735 * unit - BCM unit number. 1736 * port - Port number. 1737 * ability - xx 1738 * Returns: 1739 * SOC_E_NONE 1740 */ 1741 STATIC int 1742 phy_82780_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability) 1743 { 1744 phy_ctrl_t *pc; 1745 uint32_t pa_speed = 0; 1746 1747 pc = EXT_PHY_SW_STATE(unit, port); 1748 1749 if (NULL == ability) { 1750 return SOC_E_PARAM; 1751 } 1752 1753 sal_memset(ability, 0, sizeof(*ability)); 1754 if (pc->speed_max == PHY82780_SPD_40G) { 1755 pa_speed = SOC_PA_SPEED_40GB | SOC_PA_SPEED_1000MB 1756 | SOC_PA_SPEED_10GB | SOC_PA_SPEED_11GB | SOC_PA_SPEED_42GB; 1757 } else if (pc->speed_max == PHY82780_SPD_10G) { 1758 pa_speed = SOC_PA_SPEED_10GB | SOC_PA_SPEED_1000MB; 1759 } else { 1760 pa_speed = SOC_PA_SPEED_40GB | SOC_PA_SPEED_10GB | SOC_PA_SPEED_1000MB 1761 | SOC_PA_SPEED_11GB | SOC_PA_SPEED_42GB; 1762 } 1763 1764 ability->loopback = SOC_PA_LB_PHY; 1765 ability->medium = SOC_PA_MEDIUM_FIBER; 1766 ability->pause = 0; 1767 ability->flags = SOC_PA_AUTONEG; 1768 ability->speed_full_duplex = pa_speed; 1769 1770 1771 LOG_INFO(BSL_LS_SOC_PHY, 1772 (BSL_META_U(pc->unit, 1773 "phy82780_ability_local_get:unit=%d p=%d sp=%08x\n"), 1774 unit, port, ability->speed_full_duplex)); 1775 return (SOC_E_NONE); 1776 } 1777 1778 int 1779 phy_82780_link_get(int unit, soc_port_t port, int *link) 1780 { 1781 phy_ctrl_t *pc; 1782 soc_phymod_ctrl_t *pmc; 1783 phymod_phy_access_t *pm_phy; 1784 phy_ctrl_t *int_pc; 1785 int32 int_phy_link = 0; 1786 *link = 0; 1787 int_pc = INT_PHY_SW_STATE(unit, port); 1788 pc = EXT_PHY_SW_STATE(unit, port); 1789 if (pc == NULL) { 1790 return SOC_E_INTERNAL; 1791 } 1792 pmc = &pc->phymod_ctrl; 1793 pm_phy = &pmc->phy[pmc->main_phy]->pm_phy; 1794 1795 if (int_pc != NULL) { 1796 SOC_IF_ERROR_RETURN(PHY_LINK_GET(int_pc->pd, unit, port, &int_phy_link)); 1797 } 1798 1799 SOC_IF_ERROR_RETURN 1800 (phymod_phy_link_status_get(pm_phy, (uint32_t *) link)); 1801 1802 /* When PMD lock of 82780 is not Set, Leave the port link as 1803 * PMD status of 82780. When PMD lock of 82780 is set use 1804 * PCS status of internal serdes as port link status. 1805 * When internal serdes is not there use 82780 PMS as link status*/ 1806 #ifdef PHY82780_DEBUG 1807 if (*link == 1 && int_phy_link == 0) { 1808 LOG_CLI((BSL_META_U(unit,"PMD UP PCS Down: port:%d\n "), port)); 1809 } 1810 if (*link == 0 && int_phy_link == 1) { 1811 LOG_CLI((BSL_META_U(unit,"PMD DOWN PCS UP port:%d\n "), port)); 1812 } 1813 #endif 1814 if (*link && int_pc) { 1815 *link = int_phy_link; 1816 } 1817 return SOC_E_NONE; 1818 } 1819 1820 STATIC int 1821 phy_82780_enable_set(int unit, soc_port_t port, int enable) 1822 { 1823 phy_ctrl_t *pc; 1824 soc_phymod_ctrl_t *pmc; 1825 int32 intf, idx; 1826 phy_ctrl_t *int_pc; 1827 phymod_phy_access_t pm_phy_copy; 1828 phymod_phy_tx_lane_control_t tx_control; 1829 phymod_phy_rx_lane_control_t rx_control; 1830 /* locate phy control */ 1831 int_pc = INT_PHY_SW_STATE(unit, port); 1832 pc = EXT_PHY_SW_STATE(unit, port); 1833 if (pc == NULL) { 1834 return SOC_E_INTERNAL; 1835 } 1836 intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY82780_SYS_SIDE : PHY82780_LINE_SIDE; 1837 1838 pmc = &pc->phymod_ctrl; 1839 1840 if (enable == 1) { 1841 tx_control = phymodTxSquelchOff; 1842 rx_control = phymodRxSquelchOff; 1843 } else { 1844 tx_control = phymodTxSquelchOn; 1845 rx_control = phymodRxSquelchOn; 1846 } 1847 for (idx = 0; idx < pmc->num_phys; idx++) { 1848 sal_memcpy(&pm_phy_copy, &pmc->phy[idx]->pm_phy, sizeof(pm_phy_copy)); 1849 if (intf == PHY82780_SYS_SIDE) { 1850 PHY82780_SET_SYS_SIDE(pm_phy_copy); 1851 } 1852 SOC_IF_ERROR_RETURN 1853 (phymod_phy_tx_lane_control_set(&pm_phy_copy, tx_control)); 1854 SOC_IF_ERROR_RETURN 1855 (phymod_phy_rx_lane_control_set(&pm_phy_copy, rx_control)); 1856 } 1857 1858 SOC_IF_ERROR_RETURN(PHY_ENABLE_SET(int_pc->pd, unit, port, enable)); 1859 1860 if (enable) { 1861 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE); 1862 } else { 1863 PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE); 1864 } 1865 1866 return SOC_E_NONE; 1867 } 1868 1869 STATIC int 1870 phy_82780_enable_get(int unit, soc_port_t port, int *enable) 1871 { 1872 phy_ctrl_t *pc; 1873 soc_phymod_ctrl_t *pmc; 1874 int32 intf, idx; 1875 phymod_phy_access_t pm_phy_copy; 1876 phymod_phy_tx_lane_control_t tx_control; 1877 phymod_phy_rx_lane_control_t rx_control; 1878 1879 *enable = 0; 1880 1881 /* locate phy control */ 1882 pc = EXT_PHY_SW_STATE(unit, port); 1883 if (pc == NULL) { 1884 return SOC_E_INTERNAL; 1885 } 1886 pmc = &pc->phymod_ctrl; 1887 intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY82780_SYS_SIDE : PHY82780_LINE_SIDE; 1888 1889 for (idx = 0; idx < pmc->num_phys; idx++) { 1890 sal_memcpy(&pm_phy_copy, &pmc->phy[idx]->pm_phy, sizeof(pm_phy_copy)); 1891 if (intf == PHY82780_SYS_SIDE) { 1892 PHY82780_SET_SYS_SIDE(pm_phy_copy); 1893 } 1894 SOC_IF_ERROR_RETURN 1895 (phymod_phy_tx_lane_control_get(&pm_phy_copy, &tx_control)); 1896 SOC_IF_ERROR_RETURN 1897 (phymod_phy_rx_lane_control_get(&pm_phy_copy, &rx_control)); 1898 } 1899 if ((tx_control == phymodTxSquelchOff) && (rx_control == phymodRxSquelchOff)) { 1900 *enable = 1; 1901 } else { 1902 *enable = 0; 1903 } 1904 1905 return SOC_E_NONE; 1906 } 1907 1908 STATIC int 1909 phy_82780_lb_set(int unit, soc_port_t port, int enable) 1910 { 1911 phy_ctrl_t* pc; 1912 soc_phymod_ctrl_t *pmc; 1913 phymod_phy_access_t *pm_phy; 1914 1915 pc = EXT_PHY_SW_STATE(unit, port); 1916 pmc = &pc->phymod_ctrl; 1917 pm_phy = &pmc->phy[pmc->main_phy]->pm_phy; 1918 1919 SOC_IF_ERROR_RETURN 1920 (phymod_phy_loopback_set(pm_phy, phymodLoopbackGlobal, enable)); 1921 1922 return SOC_E_NONE; 1923 } 1924 1925 STATIC int 1926 phy_82780_firmware_set(int unit, int port, int cmd, uint8 *array,int datalen) 1927 { 1928 phy_ctrl_t *pc; 1929 soc_phymod_core_t *pmc_core; 1930 phymod_core_access_t *pm_core; 1931 soc_phymod_ctrl_t *pmc; 1932 phymod_core_status_t core_status; 1933 1934 /* locate phy control */ 1935 pc = EXT_PHY_SW_STATE(unit, port); 1936 if (pc == NULL) { 1937 return SOC_E_INTERNAL; 1938 } 1939 pmc = &pc->phymod_ctrl; 1940 1941 pmc_core = pmc->phy[0]->core; 1942 pm_core = &pmc_core->pm_core; 1943 if (pm_core == NULL) { 1944 return SOC_E_INTERNAL; 1945 } 1946 if (array == NULL) { 1947 if (cmd == PHYCTRL_UCODE_BCST_SETUP) { 1948 PHYMOD_CORE_INIT_F_UNTIL_FW_LOAD_SET(&(pmc_core->init_config)); 1949 SOC_IF_ERROR_RETURN ( 1950 phymod_core_init(pm_core, &pmc_core->init_config, &core_status)); 1951 PHYMOD_CORE_INIT_F_UNTIL_FW_LOAD_CLR(&(pmc_core->init_config)); 1952 return SOC_E_NONE; 1953 } else if (cmd == PHYCTRL_UCODE_BCST_uC_SETUP) { 1954 return SOC_E_NONE; 1955 } else if (cmd == PHYCTRL_UCODE_BCST_ENABLE) { 1956 return SOC_E_NONE; 1957 } else if (cmd == PHYCTRL_UCODE_BCST_LOAD) { 1958 PHYMOD_CORE_INIT_F_EXECUTE_FW_LOAD_SET(&(pmc_core->init_config)); 1959 SOC_IF_ERROR_RETURN ( 1960 phymod_core_init(pm_core, &pmc_core->init_config, &core_status)); 1961 PHYMOD_CORE_INIT_F_EXECUTE_FW_LOAD_CLR(&(pmc_core->init_config)); 1962 return SOC_E_NONE; 1963 } else if (cmd == PHYCTRL_UCODE_BCST_END) { 1964 PHYMOD_CORE_INIT_F_RESUME_AFTER_FW_LOAD_SET(&(pmc_core->init_config)); 1965 SOC_IF_ERROR_RETURN ( 1966 phymod_core_init(pm_core, &pmc_core->init_config, &core_status)); 1967 PHYMOD_CORE_INIT_F_RESUME_AFTER_FW_LOAD_CLR(&(pmc_core->init_config)); 1968 return SOC_E_NONE; 1969 } 1970 } else { 1971 return SOC_E_UNAVAIL; 1972 } 1973 1974 return SOC_E_NONE; 1975 1976 } 1977 1978 /* 1979 * phy_82780_per_lane_loopback_internal_pmd_get (this is the PMD global loopback) 1980 */ 1981 STATIC int 1982 phy_82780_per_lane_loopback_internal_pmd_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 *value) 1983 { 1984 phymod_phy_access_t *pm_phy; 1985 uint32_t enable; 1986 soc_phymod_phy_t *p_phy; 1987 uint32 lane_map; 1988 phymod_phy_access_t pm_phy_copy; 1989 1990 /* locate the desired phy and lane */ 1991 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 1992 1993 /* Make a copy of the phy access and overwrite the desired lane */ 1994 pm_phy = &p_phy->pm_phy; 1995 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 1996 pm_phy_copy.access.lane_mask = lane_map; 1997 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 1998 if(intf == PHY82780_SYS_SIDE) { 1999 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2000 } 2001 2002 2003 SOC_IF_ERROR_RETURN(phymod_phy_loopback_get(&pm_phy_copy, phymodLoopbackGlobalPMD, &enable)); 2004 *value = enable; 2005 return(SOC_E_NONE); 2006 } 2007 /* 2008 * phy_82780_loopback_internal_pmd_get (this is the PMD global loopback) 2009 */ 2010 STATIC int 2011 phy_82780_loopback_internal_pmd_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 2012 { 2013 phymod_phy_access_t *pm_phy; 2014 uint32_t enable; 2015 phymod_phy_access_t pm_phy_copy; 2016 2017 /* just take the value from the first phy */ 2018 if (pmc->phy[0] == NULL) { 2019 return SOC_E_INTERNAL; 2020 } 2021 pm_phy = &pmc->phy[0]->pm_phy; 2022 2023 if (pm_phy == NULL) { 2024 return SOC_E_INTERNAL; 2025 } 2026 2027 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2028 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2029 if(intf == PHY82780_SYS_SIDE) { 2030 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2031 } 2032 SOC_IF_ERROR_RETURN(phymod_phy_loopback_get(&pm_phy_copy, phymodLoopbackGlobalPMD, &enable)); 2033 *value = enable; 2034 return(SOC_E_NONE); 2035 } 2036 2037 /* 2038 * phy_82780_per_lane_loopback_remote_get 2039 */ 2040 STATIC int 2041 phy_82780_per_lane_loopback_remote_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 *value) 2042 { 2043 phymod_phy_access_t *pm_phy; 2044 uint32_t enable; 2045 soc_phymod_phy_t *p_phy; 2046 uint32 lane_map; 2047 phymod_phy_access_t pm_phy_copy; 2048 2049 /* locate the desired phy and lane */ 2050 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 2051 2052 /* Make a copy of the phy access and overwrite the desired lane */ 2053 pm_phy = &p_phy->pm_phy; 2054 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2055 pm_phy_copy.access.lane_mask = lane_map; 2056 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2057 if(intf == PHY82780_SYS_SIDE) { 2058 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2059 } 2060 2061 SOC_IF_ERROR_RETURN(phymod_phy_loopback_get(&pm_phy_copy, phymodLoopbackRemotePMD, &enable)); 2062 *value = enable; 2063 return(SOC_E_NONE); 2064 } 2065 2066 /* 2067 * phy_82780_loopback_remote_get 2068 */ 2069 STATIC int 2070 phy_82780_loopback_remote_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 2071 { 2072 phymod_phy_access_t *pm_phy; 2073 uint32_t enable; 2074 phymod_phy_access_t pm_phy_copy; 2075 2076 /* just take the value from the first phy */ 2077 if (pmc->phy[0] == NULL) { 2078 return SOC_E_INTERNAL; 2079 } 2080 pm_phy = &pmc->phy[0]->pm_phy; 2081 2082 if (pm_phy == NULL) { 2083 return SOC_E_INTERNAL; 2084 } 2085 2086 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2087 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2088 if(intf == PHY82780_SYS_SIDE) { 2089 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2090 } 2091 SOC_IF_ERROR_RETURN(phymod_phy_loopback_get(&pm_phy_copy, phymodLoopbackRemotePMD, &enable)); 2092 *value = enable; 2093 return(SOC_E_NONE); 2094 } 2095 2096 /* 2097 * phy_82780_per_lane_prbs_tx_poly_get 2098 */ 2099 STATIC int 2100 phy_82780_per_lane_prbs_tx_poly_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 *value) 2101 { 2102 phymod_phy_access_t *pm_phy; 2103 phymod_prbs_t prbs; 2104 uint32_t flags = 0; 2105 2106 2107 soc_phymod_phy_t *p_phy; 2108 uint32 lane_map; 2109 phymod_phy_access_t pm_phy_copy; 2110 2111 /* locate the desired phy and lane */ 2112 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 2113 2114 /* Make a copy of the phy access and overwrite the desired lane */ 2115 pm_phy = &p_phy->pm_phy; 2116 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2117 pm_phy_copy.access.lane_mask = lane_map; 2118 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2119 if(intf == PHY82780_SYS_SIDE) { 2120 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2121 } 2122 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 2123 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 2124 2125 *value = (int) prbs.poly; 2126 2127 /* convert from PHYMOD enum to SDK enum */ 2128 switch(prbs.poly){ 2129 case phymodPrbsPoly7: 2130 *value = SOC_PHY_PRBS_POLYNOMIAL_X7_X6_1; 2131 break; 2132 case phymodPrbsPoly9: 2133 *value = SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1; 2134 break; 2135 case phymodPrbsPoly15: 2136 *value = SOC_PHY_PRBS_POLYNOMIAL_X15_X14_1; 2137 break; 2138 case phymodPrbsPoly23: 2139 *value = SOC_PHY_PRBS_POLYNOMIAL_X23_X18_1; 2140 break; 2141 case phymodPrbsPoly31: 2142 *value = SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1; 2143 break; 2144 case phymodPrbsPoly11: 2145 *value = SOC_PHY_PRBS_POLYNOMIAL_X11_X9_1; 2146 break; 2147 case phymodPrbsPoly58: 2148 *value = SOC_PHY_PRBS_POLYNOMIAL_X58_X31_1; 2149 break; 2150 default: 2151 return SOC_E_INTERNAL; 2152 } 2153 return SOC_E_NONE; 2154 } 2155 /* 2156 * phy_82780_prbs_tx_poly_get 2157 */ 2158 STATIC int 2159 phy_82780_prbs_tx_poly_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 2160 { 2161 phymod_phy_access_t *pm_phy; 2162 phymod_prbs_t prbs; 2163 uint32_t flags = 0; 2164 phymod_phy_access_t pm_phy_copy; 2165 2166 /* just take the value from the first phy */ 2167 if (pmc->phy[0] == NULL) { 2168 return SOC_E_INTERNAL; 2169 } 2170 pm_phy = &pmc->phy[0]->pm_phy; 2171 2172 if (pm_phy == NULL) { 2173 return SOC_E_INTERNAL; 2174 } 2175 2176 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2177 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2178 if(intf == PHY82780_SYS_SIDE) { 2179 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2180 } 2181 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 2182 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 2183 2184 *value = (int) prbs.poly; 2185 2186 /* convert from PHYMOD enum to SDK enum */ 2187 switch(prbs.poly){ 2188 case phymodPrbsPoly7: 2189 *value = SOC_PHY_PRBS_POLYNOMIAL_X7_X6_1; 2190 break; 2191 case phymodPrbsPoly9: 2192 *value = SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1; 2193 break; 2194 case phymodPrbsPoly15: 2195 *value = SOC_PHY_PRBS_POLYNOMIAL_X15_X14_1; 2196 break; 2197 case phymodPrbsPoly23: 2198 *value = SOC_PHY_PRBS_POLYNOMIAL_X23_X18_1; 2199 break; 2200 case phymodPrbsPoly31: 2201 *value = SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1; 2202 break; 2203 case phymodPrbsPoly11: 2204 *value = SOC_PHY_PRBS_POLYNOMIAL_X11_X9_1; 2205 break; 2206 case phymodPrbsPoly58: 2207 *value = SOC_PHY_PRBS_POLYNOMIAL_X58_X31_1; 2208 break; 2209 default: 2210 return SOC_E_INTERNAL; 2211 } 2212 return SOC_E_NONE; 2213 } 2214 /* 2215 * phy_82780_per_lane_prbs_rx_poly_get 2216 */ 2217 STATIC int 2218 phy_82780_per_lane_prbs_rx_poly_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 *value) 2219 { 2220 phymod_phy_access_t *pm_phy; 2221 phymod_prbs_t prbs; 2222 uint32_t flags = 0; 2223 2224 2225 soc_phymod_phy_t *p_phy; 2226 uint32 lane_map; 2227 phymod_phy_access_t pm_phy_copy; 2228 2229 /* locate the desired phy and lane */ 2230 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 2231 2232 /* Make a copy of the phy access and overwrite the desired lane */ 2233 pm_phy = &p_phy->pm_phy; 2234 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2235 pm_phy_copy.access.lane_mask = lane_map; 2236 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2237 if(intf == PHY82780_SYS_SIDE) { 2238 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2239 } 2240 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 2241 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 2242 2243 *value = (int) prbs.poly; 2244 2245 /* convert from PHYMOD enum to SDK enum */ 2246 switch(prbs.poly){ 2247 case phymodPrbsPoly7: 2248 *value = SOC_PHY_PRBS_POLYNOMIAL_X7_X6_1; 2249 break; 2250 case phymodPrbsPoly9: 2251 *value = SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1; 2252 break; 2253 case phymodPrbsPoly15: 2254 *value = SOC_PHY_PRBS_POLYNOMIAL_X15_X14_1; 2255 break; 2256 case phymodPrbsPoly23: 2257 *value = SOC_PHY_PRBS_POLYNOMIAL_X23_X18_1; 2258 break; 2259 case phymodPrbsPoly31: 2260 *value = SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1; 2261 break; 2262 case phymodPrbsPoly11: 2263 *value = SOC_PHY_PRBS_POLYNOMIAL_X11_X9_1; 2264 break; 2265 case phymodPrbsPoly58: 2266 *value = SOC_PHY_PRBS_POLYNOMIAL_X58_X31_1; 2267 break; 2268 default: 2269 return SOC_E_INTERNAL; 2270 } 2271 return SOC_E_NONE; 2272 } 2273 /* 2274 * phy_82780_prbs_rx_poly_get 2275 */ 2276 STATIC int 2277 phy_82780_prbs_rx_poly_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 2278 { 2279 phymod_phy_access_t *pm_phy; 2280 phymod_prbs_t prbs; 2281 phymod_phy_access_t pm_phy_copy; 2282 uint32_t flags = 0; 2283 2284 /* just take the value from the first phy */ 2285 if (pmc->phy[0] == NULL) { 2286 return SOC_E_INTERNAL; 2287 } 2288 pm_phy = &pmc->phy[0]->pm_phy; 2289 2290 if (pm_phy == NULL) { 2291 return SOC_E_INTERNAL; 2292 } 2293 2294 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2295 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2296 if(intf == PHY82780_SYS_SIDE) { 2297 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2298 } 2299 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 2300 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 2301 2302 *value = (int) prbs.poly; 2303 2304 /* convert from PHYMOD enum to SDK enum */ 2305 switch(prbs.poly){ 2306 case phymodPrbsPoly7: 2307 *value = SOC_PHY_PRBS_POLYNOMIAL_X7_X6_1; 2308 break; 2309 case phymodPrbsPoly9: 2310 *value = SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1; 2311 break; 2312 case phymodPrbsPoly15: 2313 *value = SOC_PHY_PRBS_POLYNOMIAL_X15_X14_1; 2314 break; 2315 case phymodPrbsPoly23: 2316 *value = SOC_PHY_PRBS_POLYNOMIAL_X23_X18_1; 2317 break; 2318 case phymodPrbsPoly31: 2319 *value = SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1; 2320 break; 2321 case phymodPrbsPoly11: 2322 *value = SOC_PHY_PRBS_POLYNOMIAL_X11_X9_1; 2323 break; 2324 case phymodPrbsPoly58: 2325 *value = SOC_PHY_PRBS_POLYNOMIAL_X58_X31_1; 2326 break; 2327 default: 2328 return SOC_E_INTERNAL; 2329 } 2330 return SOC_E_NONE; 2331 } 2332 2333 /* 2334 * phy_82780_per_lane_prbs_tx_invert_data_get 2335 */ 2336 STATIC int 2337 phy_82780_per_lane_prbs_tx_invert_data_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 *value) 2338 { 2339 phymod_phy_access_t *pm_phy; 2340 phymod_prbs_t prbs; 2341 uint32_t flags = 0; 2342 2343 soc_phymod_phy_t *p_phy; 2344 uint32 lane_map; 2345 phymod_phy_access_t pm_phy_copy; 2346 2347 /* locate the desired phy and lane */ 2348 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 2349 2350 /* Make a copy of the phy access and overwrite the desired lane */ 2351 pm_phy = &p_phy->pm_phy; 2352 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2353 pm_phy_copy.access.lane_mask = lane_map; 2354 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2355 if(intf == PHY82780_SYS_SIDE) { 2356 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2357 } 2358 2359 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 2360 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 2361 *value = prbs.invert; 2362 2363 return(SOC_E_NONE); 2364 } 2365 /* 2366 * phy_82780_prbs_tx_invert_data_get 2367 */ 2368 STATIC int 2369 phy_82780_prbs_tx_invert_data_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 2370 { 2371 phymod_phy_access_t *pm_phy; 2372 phymod_prbs_t prbs; 2373 uint32_t flags = 0; 2374 phymod_phy_access_t pm_phy_copy; 2375 2376 /* just take the value from the first phy */ 2377 if (pmc->phy[0] == NULL) { 2378 return SOC_E_INTERNAL; 2379 } 2380 pm_phy = &pmc->phy[0]->pm_phy; 2381 2382 if (pm_phy == NULL) { 2383 return SOC_E_INTERNAL; 2384 } 2385 2386 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2387 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2388 if(intf == PHY82780_SYS_SIDE) { 2389 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2390 } 2391 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 2392 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 2393 *value = prbs.invert; 2394 2395 return(SOC_E_NONE); 2396 } 2397 2398 /* 2399 * phy_82780_per_lane_prbs_rx_invert_data_get 2400 */ 2401 STATIC int 2402 phy_82780_per_lane_prbs_rx_invert_data_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 *value) 2403 { 2404 phymod_phy_access_t *pm_phy; 2405 phymod_prbs_t prbs; 2406 uint32_t flags = 0; 2407 soc_phymod_phy_t *p_phy; 2408 uint32 lane_map; 2409 phymod_phy_access_t pm_phy_copy; 2410 2411 /* locate the desired phy and lane */ 2412 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 2413 2414 /* Make a copy of the phy access and overwrite the desired lane */ 2415 pm_phy = &p_phy->pm_phy; 2416 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2417 pm_phy_copy.access.lane_mask = lane_map; 2418 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2419 if(intf == PHY82780_SYS_SIDE) { 2420 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2421 } 2422 2423 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 2424 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 2425 *value = prbs.invert; 2426 2427 return(SOC_E_NONE); 2428 } 2429 /* 2430 * phy_82780_prbs_rx_invert_data_get 2431 */ 2432 STATIC int 2433 phy_82780_prbs_rx_invert_data_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 2434 { 2435 phymod_phy_access_t *pm_phy; 2436 phymod_prbs_t prbs; 2437 uint32_t flags = 0; 2438 phymod_phy_access_t pm_phy_copy; 2439 2440 /* just take the value from the first phy */ 2441 if (pmc->phy[0] == NULL) { 2442 return SOC_E_INTERNAL; 2443 } 2444 pm_phy = &pmc->phy[0]->pm_phy; 2445 2446 if (pm_phy == NULL) { 2447 return SOC_E_INTERNAL; 2448 } 2449 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2450 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2451 if(intf == PHY82780_SYS_SIDE) { 2452 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2453 } 2454 2455 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 2456 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 2457 *value = prbs.invert; 2458 2459 return(SOC_E_NONE); 2460 } 2461 2462 /* 2463 * phy_82780_per_lane_prbs_tx_enable_get 2464 */ 2465 STATIC int 2466 phy_82780_per_lane_prbs_tx_enable_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 *value) 2467 { 2468 phymod_phy_access_t *pm_phy; 2469 uint32_t flags = 0; 2470 soc_phymod_phy_t *p_phy; 2471 uint32 lane_map; 2472 phymod_phy_access_t pm_phy_copy; 2473 2474 /* locate the desired phy and lane */ 2475 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 2476 2477 /* Make a copy of the phy access and overwrite the desired lane */ 2478 pm_phy = &p_phy->pm_phy; 2479 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2480 pm_phy_copy.access.lane_mask = lane_map; 2481 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2482 if(intf == PHY82780_SYS_SIDE) { 2483 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2484 } 2485 2486 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 2487 SOC_IF_ERROR_RETURN(phymod_phy_prbs_enable_get(&pm_phy_copy, flags, value)); 2488 2489 return(SOC_E_NONE); 2490 } 2491 2492 /* 2493 * phy_82780_prbs_tx_enable_get 2494 */ 2495 STATIC int 2496 phy_82780_prbs_tx_enable_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 2497 { 2498 phymod_phy_access_t *pm_phy; 2499 uint32_t flags = 0; 2500 phymod_phy_access_t pm_phy_copy; 2501 2502 /* just take the value from the first phy */ 2503 if (pmc->phy[0] == NULL) { 2504 return SOC_E_INTERNAL; 2505 } 2506 pm_phy = &pmc->phy[0]->pm_phy; 2507 2508 if (pm_phy == NULL) { 2509 return SOC_E_INTERNAL; 2510 } 2511 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2512 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2513 if(intf == PHY82780_SYS_SIDE) { 2514 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2515 } 2516 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 2517 SOC_IF_ERROR_RETURN(phymod_phy_prbs_enable_get(&pm_phy_copy, flags, value)); 2518 2519 return(SOC_E_NONE); 2520 } 2521 2522 /* 2523 * phy_82780_per_lane_prbs_rx_enable_get 2524 */ 2525 STATIC int 2526 phy_82780_per_lane_prbs_rx_enable_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 *value) 2527 { 2528 phymod_phy_access_t *pm_phy; 2529 uint32_t flags = 0; 2530 soc_phymod_phy_t *p_phy; 2531 uint32 lane_map; 2532 phymod_phy_access_t pm_phy_copy; 2533 2534 /* locate the desired phy and lane */ 2535 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 2536 2537 /* Make a copy of the phy access and overwrite the desired lane */ 2538 pm_phy = &p_phy->pm_phy; 2539 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2540 pm_phy_copy.access.lane_mask = lane_map; 2541 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2542 if(intf == PHY82780_SYS_SIDE) { 2543 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2544 } 2545 2546 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 2547 SOC_IF_ERROR_RETURN(phymod_phy_prbs_enable_get(&pm_phy_copy, flags, value)); 2548 2549 return(SOC_E_NONE); 2550 } 2551 /* 2552 * phy_82780_prbs_rx_enable_get 2553 */ 2554 STATIC int 2555 phy_82780_prbs_rx_enable_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 2556 { 2557 phymod_phy_access_t *pm_phy; 2558 uint32_t flags = 0; 2559 phymod_phy_access_t pm_phy_copy; 2560 2561 /* just take the value from the first phy */ 2562 if (pmc->phy[0] == NULL) { 2563 return SOC_E_INTERNAL; 2564 } 2565 pm_phy = &pmc->phy[0]->pm_phy; 2566 2567 if (pm_phy == NULL) { 2568 return SOC_E_INTERNAL; 2569 } 2570 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2571 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2572 if(intf == PHY82780_SYS_SIDE) { 2573 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2574 } 2575 2576 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 2577 SOC_IF_ERROR_RETURN(phymod_phy_prbs_enable_get(&pm_phy_copy, flags, value)); 2578 2579 return(SOC_E_NONE); 2580 } 2581 2582 /* 2583 * phy_82780_per_lane_prbs_rx_status_get 2584 */ 2585 STATIC int 2586 phy_82780_per_lane_prbs_rx_status_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 *value) 2587 { 2588 phymod_phy_access_t *pm_phy; 2589 phymod_prbs_status_t prbs_tmp; 2590 int prbs_lock, lock_loss, error_count ; 2591 soc_phymod_phy_t *p_phy; 2592 uint32 lane_map; 2593 phymod_phy_access_t pm_phy_copy; 2594 2595 prbs_lock = 1 ; 2596 lock_loss = 0 ; 2597 error_count = 0 ; 2598 /* locate the desired phy and lane */ 2599 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 2600 2601 /* Make a copy of the phy access and overwrite the desired lane */ 2602 pm_phy = &p_phy->pm_phy; 2603 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2604 pm_phy_copy.access.lane_mask = lane_map; 2605 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2606 if(intf == PHY82780_SYS_SIDE) { 2607 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2608 } 2609 /* $$$ Need to add diagnostic API */ 2610 SOC_IF_ERROR_RETURN 2611 (phymod_phy_prbs_status_get(&pm_phy_copy, 0, &prbs_tmp)); 2612 2613 if(prbs_tmp.prbs_lock==0) { 2614 prbs_lock = 0 ; 2615 } else { 2616 if(prbs_tmp.prbs_lock_loss) { 2617 lock_loss = 1 ; 2618 } else { 2619 error_count += prbs_tmp.error_count; 2620 } 2621 } 2622 2623 if (prbs_lock == 0) { 2624 *value = -1; 2625 } else if ((lock_loss == 1) && (prbs_lock == 1)) { 2626 *value = -2; 2627 } else { 2628 *value = error_count; 2629 } 2630 return(SOC_E_NONE); 2631 } 2632 /* 2633 * phy_82780_prbs_rx_status_get 2634 */ 2635 STATIC int 2636 phy_82780_prbs_rx_status_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 2637 { 2638 phymod_phy_access_t *pm_phy; 2639 phymod_prbs_status_t prbs_tmp; 2640 int idx, prbs_lock, lock_loss, error_count ; 2641 phymod_phy_access_t pm_phy_copy; 2642 2643 /* just take the value from the first phy */ 2644 if (pmc->phy[0] == NULL) { 2645 return SOC_E_INTERNAL; 2646 } 2647 2648 prbs_lock = 1 ; 2649 lock_loss = 0 ; 2650 error_count = 0 ; 2651 for (idx = 0; idx < pmc->num_phys; idx++) { 2652 pm_phy = &pmc->phy[idx]->pm_phy; 2653 2654 if (pm_phy == NULL) { 2655 return SOC_E_INTERNAL; 2656 } 2657 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2658 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2659 if(intf == PHY82780_SYS_SIDE) { 2660 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2661 } 2662 /* $$$ Need to add diagnostic API */ 2663 SOC_IF_ERROR_RETURN 2664 (phymod_phy_prbs_status_get(&pm_phy_copy, 0, &prbs_tmp)); 2665 2666 if(prbs_tmp.prbs_lock==0) { 2667 prbs_lock = 0 ; 2668 } else { 2669 if(prbs_tmp.prbs_lock_loss) { 2670 lock_loss = 1 ; 2671 } else { 2672 error_count += prbs_tmp.error_count; 2673 } 2674 } 2675 } 2676 2677 if (prbs_lock == 0) { 2678 *value = -1; 2679 } else if ((lock_loss == 1) && (prbs_lock == 1)) { 2680 *value = -2; 2681 } else { 2682 *value = error_count; 2683 } 2684 return(SOC_E_NONE); 2685 } 2686 /* 2687 * phy_82780_per_lane_rx_peak_filter_get 2688 */ 2689 STATIC int 2690 phy_82780_per_lane_rx_peak_filter_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 *value) 2691 { 2692 soc_phymod_phy_t *p_phy; 2693 uint32 lane_map; 2694 phymod_phy_access_t pm_phy_copy, *pm_phy; 2695 phymod_rx_t phymod_rx; 2696 2697 *value = 0; 2698 2699 /* locate the desired phy and lane */ 2700 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 2701 2702 /* Make a copy of the phy access and overwrite the desired lane */ 2703 pm_phy = &p_phy->pm_phy; 2704 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2705 pm_phy_copy.access.lane_mask = lane_map; 2706 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2707 if(intf == PHY82780_SYS_SIDE) { 2708 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2709 } 2710 2711 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 2712 *value = phymod_rx.peaking_filter.value; 2713 2714 return(SOC_E_NONE); 2715 } 2716 2717 /* 2718 * phy_82780_per_lane_rx_vga_get 2719 */ 2720 STATIC int 2721 phy_82780_per_lane_rx_vga_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 *value) 2722 { 2723 soc_phymod_phy_t *p_phy; 2724 uint32 lane_map; 2725 phymod_phy_access_t pm_phy_copy, *pm_phy; 2726 phymod_rx_t phymod_rx; 2727 2728 *value = 0; 2729 2730 /* locate the desired phy and lane */ 2731 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 2732 2733 /* Make a copy of the phy access and overwrite the desired lane */ 2734 pm_phy = &p_phy->pm_phy; 2735 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2736 pm_phy_copy.access.lane_mask = lane_map; 2737 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2738 if(intf == PHY82780_SYS_SIDE) { 2739 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2740 } 2741 2742 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 2743 *value = phymod_rx.vga.value; 2744 2745 return(SOC_E_NONE); 2746 } 2747 2748 /* 2749 * phy_82780_per_lane_rx_dfe_tap_control_get 2750 */ 2751 STATIC int 2752 phy_82780_per_lane_rx_dfe_tap_control_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, int tap, uint32 *value) 2753 { 2754 soc_phymod_phy_t *p_phy; 2755 uint32 lane_map; 2756 phymod_phy_access_t pm_phy_copy, *pm_phy; 2757 phymod_rx_t phymod_rx; 2758 2759 *value = 0; 2760 2761 /* locate the desired phy and lane */ 2762 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 2763 2764 /* Make a copy of the phy access and overwrite the desired lane */ 2765 pm_phy = &p_phy->pm_phy; 2766 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2767 pm_phy_copy.access.lane_mask = lane_map; 2768 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2769 if(intf == PHY82780_SYS_SIDE) { 2770 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2771 } 2772 2773 if (tap < 0 || tap >= COUNTOF(phymod_rx.dfe)) { 2774 /* this can only happen with a coding error */ 2775 return SOC_E_INTERNAL; 2776 } 2777 2778 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 2779 *value = phymod_rx.dfe[tap].value; 2780 2781 return(SOC_E_NONE); 2782 } 2783 2784 2785 /* 2786 * phy_82780_per_lane_rx_low_freq_filter_get 2787 */ 2788 STATIC int 2789 phy_82780_per_lane_rx_low_freq_filter_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 *value) 2790 { 2791 soc_phymod_phy_t *p_phy; 2792 uint32 lane_map; 2793 phymod_phy_access_t pm_phy_copy, *pm_phy; 2794 phymod_rx_t phymod_rx; 2795 2796 *value = 0; 2797 2798 /* locate the desired phy and lane */ 2799 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 2800 2801 /* Make a copy of the phy access and overwrite the desired lane */ 2802 pm_phy = &p_phy->pm_phy; 2803 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2804 pm_phy_copy.access.lane_mask = lane_map; 2805 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2806 if(intf == PHY82780_SYS_SIDE) { 2807 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2808 } 2809 2810 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 2811 *value = phymod_rx.low_freq_peaking_filter.value; 2812 return(SOC_E_NONE); 2813 } 2814 2815 /* 2816 * phy_82780_rx_peak_filter_get 2817 */ 2818 STATIC int 2819 phy_82780_rx_peak_filter_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 2820 { 2821 phymod_phy_access_t *pm_phy; 2822 phymod_rx_t phymod_rx; 2823 phymod_phy_access_t pm_phy_copy; 2824 2825 /* just take the value from the first phy */ 2826 if (pmc->phy[0] == NULL) { 2827 return SOC_E_INTERNAL; 2828 } 2829 pm_phy = &pmc->phy[0]->pm_phy; 2830 2831 if (pm_phy == NULL) { 2832 return SOC_E_INTERNAL; 2833 } 2834 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2835 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2836 if(intf == PHY82780_SYS_SIDE) { 2837 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2838 } 2839 2840 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 2841 *value = phymod_rx.peaking_filter.value; 2842 2843 return(SOC_E_NONE); 2844 } 2845 2846 /* 2847 * phy_82780_rx_low_peak_filter_get 2848 */ 2849 STATIC int 2850 phy_82780_rx_low_peak_filter_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 2851 { 2852 phymod_phy_access_t *pm_phy; 2853 phymod_rx_t phymod_rx; 2854 phymod_phy_access_t pm_phy_copy; 2855 2856 /* just take the value from the first phy */ 2857 if (pmc->phy[0] == NULL) { 2858 return SOC_E_INTERNAL; 2859 } 2860 pm_phy = &pmc->phy[0]->pm_phy; 2861 2862 if (pm_phy == NULL) { 2863 return SOC_E_INTERNAL; 2864 } 2865 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2866 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2867 if(intf == PHY82780_SYS_SIDE) { 2868 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2869 } 2870 2871 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 2872 *value = phymod_rx.low_freq_peaking_filter.value; 2873 2874 return(SOC_E_NONE); 2875 } 2876 2877 /* 2878 * phy_82780_rx_vga_set 2879 */ 2880 STATIC int 2881 phy_82780_rx_vga_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 2882 { 2883 phymod_phy_access_t *pm_phy; 2884 phymod_rx_t phymod_rx; 2885 phymod_phy_access_t pm_phy_copy; 2886 2887 /* just take the value from the first phy */ 2888 if (pmc->phy[0] == NULL) { 2889 return SOC_E_INTERNAL; 2890 } 2891 pm_phy = &pmc->phy[0]->pm_phy; 2892 2893 if (pm_phy == NULL) { 2894 return SOC_E_INTERNAL; 2895 } 2896 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2897 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2898 if(intf == PHY82780_SYS_SIDE) { 2899 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2900 } 2901 2902 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 2903 *value = phymod_rx.vga.value; 2904 2905 return(SOC_E_NONE); 2906 } 2907 2908 /* 2909 * phy_82780_rx_tap_get 2910 */ 2911 STATIC int 2912 phy_82780_rx_tap_get(soc_phymod_ctrl_t *pmc, int32 intf, int tap, uint32 *value) 2913 { 2914 phymod_phy_access_t *pm_phy; 2915 phymod_rx_t phymod_rx; 2916 phymod_phy_access_t pm_phy_copy; 2917 2918 if (tap < 0 || tap >= COUNTOF(phymod_rx.dfe)) { 2919 /* this can only happen with a coding error */ 2920 return SOC_E_INTERNAL; 2921 } 2922 /* just take the value from the first phy */ 2923 if (pmc->phy[0] == NULL) { 2924 return SOC_E_INTERNAL; 2925 } 2926 pm_phy = &pmc->phy[0]->pm_phy; 2927 2928 if (pm_phy == NULL) { 2929 return SOC_E_INTERNAL; 2930 } 2931 2932 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2933 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2934 if(intf == PHY82780_SYS_SIDE) { 2935 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2936 } 2937 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 2938 *value = phymod_rx.dfe[tap].value; 2939 2940 return(SOC_E_NONE); 2941 } 2942 2943 /* 2944 * phy_82780_pi_control_get 2945 */ 2946 STATIC int 2947 phy_82780_pi_control_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 2948 { 2949 phymod_phy_access_t *pm_phy; 2950 phymod_tx_override_t tx_override; 2951 phymod_phy_access_t pm_phy_copy; 2952 2953 /* just take the value from the first phy */ 2954 if (pmc->phy[0] == NULL) { 2955 return SOC_E_INTERNAL; 2956 } 2957 pm_phy = &pmc->phy[0]->pm_phy; 2958 2959 if (pm_phy == NULL) { 2960 return SOC_E_INTERNAL; 2961 } 2962 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2963 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2964 if(intf == PHY82780_SYS_SIDE) { 2965 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2966 } 2967 2968 SOC_IF_ERROR_RETURN(phymod_phy_tx_override_get(&pm_phy_copy, &tx_override)); 2969 *value = tx_override.phase_interpolator.value; 2970 2971 return(SOC_E_NONE); 2972 } 2973 /* 2974 * phy_82780_rx_seq_done_get 2975 */ 2976 STATIC int 2977 phy_82780_rx_seq_done_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 2978 { 2979 phymod_phy_access_t *pm_phy; 2980 phymod_phy_access_t pm_phy_copy; 2981 2982 /* just take the value from the first phy */ 2983 if (pmc->phy[0] == NULL) { 2984 return SOC_E_INTERNAL; 2985 } 2986 pm_phy = &pmc->phy[0]->pm_phy; 2987 2988 if (pm_phy == NULL) { 2989 return SOC_E_INTERNAL; 2990 } 2991 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2992 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 2993 if(intf == PHY82780_SYS_SIDE) { 2994 PHY82780_SET_SYS_SIDE(pm_phy_copy); 2995 } 2996 2997 SOC_IF_ERROR_RETURN(phymod_phy_rx_pmd_locked_get(&pm_phy_copy, value)); 2998 2999 return(SOC_E_NONE); 3000 } 3001 /* 3002 * phy_82780_fec_get 3003 */ 3004 STATIC int 3005 phy_82780_fec_enable_get(soc_phymod_ctrl_t *pmc, uint32 *value) 3006 { 3007 phymod_phy_access_t *pm_phy; 3008 uint32_t enable; 3009 3010 /* just take the value from the first phy */ 3011 if (pmc->phy[0] == NULL) { 3012 return SOC_E_INTERNAL; 3013 } 3014 pm_phy = &pmc->phy[0]->pm_phy; 3015 3016 if (pm_phy == NULL) { 3017 return SOC_E_INTERNAL; 3018 } 3019 3020 SOC_IF_ERROR_RETURN(phymod_phy_fec_enable_get(pm_phy, &enable)); 3021 *value = enable; 3022 3023 return(SOC_E_NONE); 3024 } 3025 /* 3026 * phy_82780_tx_fir_pre_get 3027 */ 3028 STATIC int 3029 phy_82780_tx_fir_pre_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 3030 { 3031 phymod_phy_access_t *pm_phy; 3032 phymod_tx_t phymod_tx; 3033 phymod_phy_access_t pm_phy_copy; 3034 3035 pm_phy = &pmc->phy[0]->pm_phy; 3036 3037 if (pm_phy == NULL) { 3038 return SOC_E_INTERNAL; 3039 } 3040 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3041 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 3042 if(intf == PHY82780_SYS_SIDE) { 3043 PHY82780_SET_SYS_SIDE(pm_phy_copy); 3044 } 3045 3046 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 3047 *value = phymod_tx.pre; 3048 3049 return(SOC_E_NONE); 3050 } 3051 /* 3052 * phy_82780_tx_fir_main_get 3053 */ 3054 STATIC int 3055 phy_82780_tx_fir_main_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 3056 { 3057 phymod_phy_access_t *pm_phy; 3058 phymod_tx_t phymod_tx; 3059 phymod_phy_access_t pm_phy_copy; 3060 3061 pm_phy = &pmc->phy[0]->pm_phy; 3062 3063 if (pm_phy == NULL) { 3064 return SOC_E_INTERNAL; 3065 } 3066 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3067 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 3068 if(intf == PHY82780_SYS_SIDE) { 3069 PHY82780_SET_SYS_SIDE(pm_phy_copy); 3070 } 3071 3072 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 3073 *value = phymod_tx.main; 3074 3075 return(SOC_E_NONE); 3076 } 3077 3078 /* 3079 * phy_82780_tx_fir_post_get 3080 */ 3081 STATIC int 3082 phy_82780_tx_fir_post_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 3083 { 3084 phymod_phy_access_t *pm_phy; 3085 phymod_tx_t phymod_tx; 3086 phymod_phy_access_t pm_phy_copy; 3087 3088 pm_phy = &pmc->phy[0]->pm_phy; 3089 3090 if (pm_phy == NULL) { 3091 return SOC_E_INTERNAL; 3092 } 3093 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3094 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 3095 if(intf == PHY82780_SYS_SIDE) { 3096 PHY82780_SET_SYS_SIDE(pm_phy_copy); 3097 } 3098 3099 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 3100 *value = phymod_tx.post; 3101 3102 return(SOC_E_NONE); 3103 } 3104 3105 /* 3106 * phy_82780_tx_fir_post2_get 3107 */ 3108 STATIC int 3109 phy_82780_tx_fir_post2_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 3110 { 3111 phymod_phy_access_t *pm_phy; 3112 phymod_tx_t phymod_tx; 3113 phymod_phy_access_t pm_phy_copy; 3114 3115 pm_phy = &pmc->phy[0]->pm_phy; 3116 3117 if (pm_phy == NULL) { 3118 return SOC_E_INTERNAL; 3119 } 3120 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3121 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 3122 if(intf == PHY82780_SYS_SIDE) { 3123 PHY82780_SET_SYS_SIDE(pm_phy_copy); 3124 } 3125 3126 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(pm_phy, &phymod_tx)); 3127 *value = phymod_tx.post2; 3128 3129 return(SOC_E_NONE); 3130 } 3131 3132 /* 3133 * phy_82780_per_lane_driver_current_get 3134 */ 3135 STATIC int 3136 phy_82780_per_lane_driver_current_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 *value) 3137 { 3138 soc_phymod_phy_t *p_phy; 3139 uint32 lane_map; 3140 phymod_phy_access_t pm_phy_copy, *pm_phy; 3141 phymod_tx_t phymod_tx; 3142 3143 /* locate the desired phy and lane */ 3144 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 3145 3146 /* Make a copy of the phy access and overwrite the desired lane */ 3147 pm_phy = &p_phy->pm_phy; 3148 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3149 pm_phy_copy.access.lane_mask = lane_map; 3150 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 3151 if(intf == PHY82780_SYS_SIDE) { 3152 PHY82780_SET_SYS_SIDE(pm_phy_copy); 3153 } 3154 3155 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 3156 *value = phymod_tx.amp; 3157 3158 return(SOC_E_NONE); 3159 } 3160 3161 /* 3162 * phy_82780_per_lane_preemphasis_get 3163 */ 3164 STATIC int 3165 phy_82780_per_lane_preemphasis_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 *value) 3166 { 3167 soc_phymod_phy_t *p_phy; 3168 uint32 lane_map; 3169 phymod_phy_access_t pm_phy_copy, *pm_phy; 3170 phymod_tx_t phymod_tx; 3171 3172 /* locate the desired phy and lane */ 3173 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 3174 3175 /* Make a copy of the phy access and overwrite the desired lane */ 3176 pm_phy = &p_phy->pm_phy; 3177 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3178 pm_phy_copy.access.lane_mask = lane_map; 3179 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 3180 if(intf == PHY82780_SYS_SIDE) { 3181 PHY82780_SET_SYS_SIDE(pm_phy_copy); 3182 } 3183 3184 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 3185 /* 0 to 7 = pre 3186 * 8 to 15 = main 3187 * 16 to 24 = post*/ 3188 *value |= (phymod_tx.pre & 0xff); 3189 *value |= ((phymod_tx.main & 0xff) << 8); 3190 *value |= ((phymod_tx.post & 0xff) << 16); 3191 3192 return(SOC_E_NONE); 3193 } 3194 3195 /* 3196 * phy_82780_per_lane_rx_low_freq_filter_set 3197 */ 3198 STATIC int 3199 phy_82780_per_lane_rx_low_freq_filter_set(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 value) 3200 { 3201 soc_phymod_phy_t *p_phy; 3202 uint32 lane_map; 3203 phymod_phy_access_t pm_phy_copy, *pm_phy; 3204 phymod_rx_t phymod_rx; 3205 3206 /* locate the desired phy and lane */ 3207 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 3208 3209 /* Make a copy of the phy access and overwrite the desired lane */ 3210 pm_phy = &p_phy->pm_phy; 3211 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3212 pm_phy_copy.access.lane_mask = lane_map; 3213 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 3214 if(intf == PHY82780_SYS_SIDE) { 3215 PHY82780_SET_SYS_SIDE(pm_phy_copy); 3216 } 3217 3218 phymod_rx.low_freq_peaking_filter.value = value; 3219 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(&pm_phy_copy, &phymod_rx)); 3220 return(SOC_E_NONE); 3221 } 3222 /* 3223 * phy_82780_per_lane_power_get 3224 */ 3225 STATIC int 3226 phy_82780_per_lane_power_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 *value) 3227 { 3228 phymod_phy_access_t *pm_phy; 3229 phymod_phy_power_t power; 3230 soc_phymod_phy_t *p_phy; 3231 uint32 lane_map; 3232 phymod_phy_access_t pm_phy_copy; 3233 3234 /* locate the desired phy and lane */ 3235 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 3236 3237 /* Make a copy of the phy access and overwrite the desired lane */ 3238 pm_phy = &p_phy->pm_phy; 3239 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3240 pm_phy_copy.access.lane_mask = lane_map; 3241 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 3242 if(intf == PHY82780_SYS_SIDE) { 3243 PHY82780_SET_SYS_SIDE(pm_phy_copy); 3244 } 3245 3246 phymod_phy_power_t_init(&power); 3247 3248 SOC_IF_ERROR_RETURN(phymod_phy_power_get(&pm_phy_copy, &power)); 3249 3250 if(power.tx == phymodPowerOn && power.rx == phymodPowerOn) { 3251 *value = 1; 3252 } else { 3253 *value = 0; 3254 } 3255 3256 return(SOC_E_NONE); 3257 } 3258 /* 3259 * phy_82780_power_get 3260 */ 3261 STATIC int 3262 phy_82780_power_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 3263 { 3264 phymod_phy_access_t *pm_phy; 3265 phymod_phy_power_t power; 3266 phymod_phy_access_t pm_phy_copy; 3267 3268 /* just take the value from the first phy */ 3269 if (pmc->phy[0] == NULL) { 3270 return SOC_E_INTERNAL; 3271 } 3272 pm_phy = &pmc->phy[0]->pm_phy; 3273 3274 if (pm_phy == NULL) { 3275 return SOC_E_INTERNAL; 3276 } 3277 3278 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3279 phymod_phy_power_t_init(&power); 3280 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 3281 if(intf == PHY82780_SYS_SIDE) { 3282 PHY82780_SET_SYS_SIDE(pm_phy_copy); 3283 } 3284 3285 SOC_IF_ERROR_RETURN(phymod_phy_power_get(&pm_phy_copy, &power)); 3286 3287 if(power.tx == phymodPowerOn && power.rx == phymodPowerOn) { 3288 *value = 1; 3289 } else { 3290 *value = 0; 3291 } 3292 3293 return(SOC_E_NONE); 3294 } 3295 /* 3296 * phy_82780_per_lane_tx_polarity_get 3297 */ 3298 STATIC int 3299 phy_82780_per_lane_tx_polarity_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 *value) 3300 { 3301 phymod_phy_access_t *pm_phy; 3302 phymod_polarity_t polarity; 3303 soc_phymod_phy_t *p_phy; 3304 uint32 lane_map; 3305 phymod_phy_access_t pm_phy_copy; 3306 3307 /* locate the desired phy and lane */ 3308 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 3309 3310 /* Make a copy of the phy access and overwrite the desired lane */ 3311 pm_phy = &p_phy->pm_phy; 3312 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3313 pm_phy_copy.access.lane_mask = lane_map; 3314 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 3315 if(intf == PHY82780_SYS_SIDE) { 3316 PHY82780_SET_SYS_SIDE(pm_phy_copy); 3317 } 3318 3319 phymod_polarity_t_init(&polarity); 3320 SOC_IF_ERROR_RETURN(phymod_phy_polarity_get(&pm_phy_copy, &polarity)); 3321 3322 *value = polarity.tx_polarity; 3323 3324 return(SOC_E_NONE); 3325 } 3326 /* 3327 * phy_82780_tx_polarity_get 3328 */ 3329 STATIC int 3330 phy_82780_tx_polarity_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 3331 { 3332 phymod_phy_access_t *pm_phy; 3333 phymod_polarity_t polarity; 3334 phymod_phy_access_t pm_phy_copy; 3335 3336 /* just take the value from the first phy */ 3337 if (pmc->phy[0] == NULL) { 3338 return SOC_E_INTERNAL; 3339 } 3340 pm_phy = &pmc->phy[0]->pm_phy; 3341 3342 if (pm_phy == NULL) { 3343 return SOC_E_INTERNAL; 3344 } 3345 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3346 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 3347 if(intf == PHY82780_SYS_SIDE) { 3348 PHY82780_SET_SYS_SIDE(pm_phy_copy); 3349 } 3350 phymod_polarity_t_init(&polarity); 3351 SOC_IF_ERROR_RETURN(phymod_phy_polarity_get(&pm_phy_copy, &polarity)); 3352 3353 *value = polarity.tx_polarity; 3354 3355 return(SOC_E_NONE); 3356 } 3357 3358 /* 3359 * phy_82780_per_lane_rx_polarity_get 3360 */ 3361 STATIC int 3362 phy_82780_per_lane_rx_polarity_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 *value) 3363 { 3364 phymod_phy_access_t *pm_phy; 3365 phymod_polarity_t polarity; 3366 soc_phymod_phy_t *p_phy; 3367 uint32 lane_map; 3368 phymod_phy_access_t pm_phy_copy; 3369 3370 /* locate the desired phy and lane */ 3371 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 3372 3373 /* Make a copy of the phy access and overwrite the desired lane */ 3374 pm_phy = &p_phy->pm_phy; 3375 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3376 pm_phy_copy.access.lane_mask = lane_map; 3377 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 3378 if(intf == PHY82780_SYS_SIDE) { 3379 PHY82780_SET_SYS_SIDE(pm_phy_copy); 3380 } 3381 3382 phymod_polarity_t_init(&polarity); 3383 SOC_IF_ERROR_RETURN(phymod_phy_polarity_get(&pm_phy_copy, &polarity)); 3384 3385 *value = polarity.rx_polarity; 3386 3387 return(SOC_E_NONE); 3388 } 3389 /* 3390 * phy_82780_rx_polarity_get 3391 */ 3392 STATIC int 3393 phy_82780_rx_polarity_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 3394 { 3395 phymod_phy_access_t *pm_phy; 3396 phymod_polarity_t polarity; 3397 phymod_phy_access_t pm_phy_copy; 3398 3399 /* just take the value from the first phy */ 3400 if (pmc->phy[0] == NULL) { 3401 return SOC_E_INTERNAL; 3402 } 3403 pm_phy = &pmc->phy[0]->pm_phy; 3404 3405 if (pm_phy == NULL) { 3406 return SOC_E_INTERNAL; 3407 } 3408 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3409 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 3410 if(intf == PHY82780_SYS_SIDE) { 3411 PHY82780_SET_SYS_SIDE(pm_phy_copy); 3412 } 3413 phymod_polarity_t_init(&polarity); 3414 SOC_IF_ERROR_RETURN(phymod_phy_polarity_get(&pm_phy_copy, &polarity)); 3415 3416 *value = polarity.rx_polarity; 3417 3418 return(SOC_E_NONE); 3419 } 3420 3421 /* 3422 * phy_82780_gpio_config_get 3423 */ 3424 STATIC int 3425 phy_82780_gpio_config_get(soc_phymod_ctrl_t *pmc, uint32 *value) 3426 { 3427 phymod_phy_access_t *pm_phy; 3428 phymod_phy_access_t pm_phy_copy; 3429 phymod_gpio_mode_t gpio_mode; 3430 int gpio_pin_no = 0; 3431 *value = 0; 3432 3433 /* just take the value from the first phy */ 3434 if (pmc->phy[0] == NULL) { 3435 return SOC_E_INTERNAL; 3436 } 3437 pm_phy = &pmc->phy[0]->pm_phy; 3438 3439 if (pm_phy == NULL) { 3440 return SOC_E_INTERNAL; 3441 } 3442 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3443 3444 for (gpio_pin_no = 0; gpio_pin_no < 6; gpio_pin_no++) { 3445 SOC_IF_ERROR_RETURN(phymod_phy_gpio_config_get(&pm_phy_copy, gpio_pin_no, &gpio_mode)); 3446 *value |= (gpio_mode << (4 * gpio_pin_no)); 3447 } 3448 3449 return(SOC_E_NONE); 3450 } 3451 /* 3452 * phy_82780_gpio_value_get 3453 */ 3454 STATIC int 3455 phy_82780_gpio_value_get(soc_phymod_ctrl_t *pmc, uint32 *value) 3456 { 3457 phymod_phy_access_t *pm_phy; 3458 phymod_phy_access_t pm_phy_copy; 3459 int gpio_pin_no = 0; 3460 int pin_value = 0; 3461 *value = 0; 3462 3463 /* just take the value from the first phy */ 3464 if (pmc->phy[0] == NULL) { 3465 return SOC_E_INTERNAL; 3466 } 3467 pm_phy = &pmc->phy[0]->pm_phy; 3468 3469 if (pm_phy == NULL) { 3470 return SOC_E_INTERNAL; 3471 } 3472 3473 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3474 3475 for (gpio_pin_no = 0; gpio_pin_no < 6; gpio_pin_no++) { 3476 SOC_IF_ERROR_RETURN(phymod_phy_gpio_pin_value_get(&pm_phy_copy, gpio_pin_no, &pin_value)); 3477 *value |= (pin_value << (4 * gpio_pin_no)); 3478 } 3479 3480 return(SOC_E_NONE); 3481 } 3482 /* 3483 * Function: 3484 * phy82780_control_get 3485 * Purpose: 3486 * Get current control settings of the PHY. 3487 * Parameters: 3488 * unit - BCM unit number. 3489 * port - Port number. 3490 * type - Control to update 3491 * value - (OUT) Current setting for the control 3492 * Returns: 3493 * SOC_E_NONE 3494 */ 3495 STATIC int 3496 phy_82780_control_get(int unit, soc_port_t port, soc_phy_control_t type, uint32 *value) 3497 { 3498 int rv; 3499 phy_ctrl_t *pc; 3500 soc_phymod_ctrl_t *pmc; 3501 int32 intf; 3502 soc_port_t primary= 0; 3503 int offset = 0; 3504 3505 PHY_CONTROL_TYPE_CHECK(type); 3506 3507 /* locate phy control */ 3508 pc = EXT_PHY_SW_STATE(unit, port); 3509 if (pc == NULL) { 3510 return SOC_E_INTERNAL; 3511 } 3512 3513 pmc = &pc->phymod_ctrl; 3514 3515 intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY82780_SYS_SIDE : PHY82780_LINE_SIDE; 3516 3517 switch(type) { 3518 /* PRBS */ 3519 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_POLYNOMIAL: 3520 rv = phy_82780_prbs_tx_poly_get(pmc, intf, value); 3521 break; 3522 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_INVERT_DATA: 3523 rv = phy_82780_prbs_tx_invert_data_get(pmc, intf, value); 3524 break; 3525 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_ENABLE: 3526 rv = phy_82780_prbs_tx_enable_get(pmc, intf, value); 3527 break; 3528 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_POLYNOMIAL: 3529 rv = phy_82780_prbs_rx_poly_get(pmc, intf, value); 3530 break; 3531 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_INVERT_DATA: 3532 rv = phy_82780_prbs_rx_invert_data_get(pmc, intf, value); 3533 break; 3534 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_ENABLE: 3535 rv = phy_82780_prbs_rx_enable_get(pmc, intf, value); 3536 break; 3537 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 3538 rv = phy_82780_prbs_tx_poly_get(pmc, intf, value); 3539 break; 3540 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 3541 rv = phy_82780_prbs_tx_invert_data_get(pmc, intf, value); 3542 break; 3543 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 3544 rv = phy_82780_prbs_tx_enable_get(pmc, intf, value); 3545 break; 3546 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 3547 rv = phy_82780_prbs_rx_enable_get(pmc, intf, value); 3548 break; 3549 case SOC_PHY_CONTROL_PRBS_RX_STATUS: 3550 rv = phy_82780_prbs_rx_status_get(pmc, intf, value); 3551 break; 3552 /* LOOPBACK */ 3553 case SOC_PHY_CONTROL_LOOPBACK_REMOTE: 3554 rv = phy_82780_loopback_remote_get(pmc, intf, value); 3555 break; 3556 case SOC_PHY_CONTROL_LOOPBACK_PMD: 3557 rv = phy_82780_loopback_internal_pmd_get(pmc, intf, value); 3558 break; 3559 /* PREEMPHASIS */ 3560 case SOC_PHY_CONTROL_PREEMPHASIS: 3561 case SOC_PHY_CONTROL_PREEMPHASIS_LANE0: 3562 rv = phy_82780_per_lane_preemphasis_get(pmc, intf, 0, value); 3563 break; 3564 case SOC_PHY_CONTROL_PREEMPHASIS_LANE1: 3565 rv = phy_82780_per_lane_preemphasis_get(pmc, intf, 1, value); 3566 break; 3567 case SOC_PHY_CONTROL_PREEMPHASIS_LANE2: 3568 rv = phy_82780_per_lane_preemphasis_get(pmc, intf, 2, value); 3569 break; 3570 case SOC_PHY_CONTROL_PREEMPHASIS_LANE3: 3571 rv = phy_82780_per_lane_preemphasis_get(pmc, intf, 3, value); 3572 break; 3573 case SOC_PHY_CONTROL_TX_FIR_PRE: 3574 /* assume they are all the same as lane 0 */ 3575 rv = phy_82780_tx_fir_pre_get(pmc, intf, value); 3576 break; 3577 case SOC_PHY_CONTROL_TX_FIR_MAIN: 3578 /* assume they are all the same as lane 0 */ 3579 rv = phy_82780_tx_fir_main_get(pmc, intf, value); 3580 break; 3581 case SOC_PHY_CONTROL_TX_FIR_POST: 3582 /* assume they are all the same as lane 0 */ 3583 rv = phy_82780_tx_fir_post_get(pmc, intf, value); 3584 break; 3585 case SOC_PHY_CONTROL_TX_FIR_POST2: 3586 /* assume they are all the same as lane 0 */ 3587 rv = phy_82780_tx_fir_post2_get(pmc, intf, value); 3588 break; 3589 3590 /* DRIVER CURRENT */ 3591 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0: 3592 rv = phy_82780_per_lane_driver_current_get(pmc, intf, 0, value); 3593 break; 3594 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1: 3595 rv = phy_82780_per_lane_driver_current_get(pmc, intf, 1, value); 3596 break; 3597 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2: 3598 rv = phy_82780_per_lane_driver_current_get(pmc, intf, 2, value); 3599 break; 3600 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3: 3601 rv = phy_82780_per_lane_driver_current_get(pmc, intf, 3, value); 3602 break; 3603 case SOC_PHY_CONTROL_DRIVER_CURRENT: 3604 rv = phy_82780_per_lane_driver_current_get(pmc, intf, 0, value); 3605 break; 3606 3607 /* RX PEAK FILTER */ 3608 case SOC_PHY_CONTROL_RX_PEAK_FILTER: 3609 rv = phy_82780_rx_peak_filter_get(pmc, intf, value); 3610 break; 3611 3612 case SOC_PHY_CONTROL_RX_LOW_FREQ_PEAK_FILTER: 3613 rv = phy_82780_rx_low_peak_filter_get(pmc, intf, value); 3614 break; 3615 /* RX VGA */ 3616 case SOC_PHY_CONTROL_RX_VGA: 3617 rv = phy_82780_rx_vga_get(pmc, intf, value); 3618 break; 3619 3620 /* RX TAP */ 3621 case SOC_PHY_CONTROL_RX_TAP1: 3622 rv = phy_82780_rx_tap_get(pmc, intf, 0, value); 3623 break; 3624 case SOC_PHY_CONTROL_RX_TAP2: 3625 rv = phy_82780_rx_tap_get(pmc, intf, 1, value); 3626 break; 3627 case SOC_PHY_CONTROL_RX_TAP3: 3628 rv = phy_82780_rx_tap_get(pmc, intf, 2, value); 3629 break; 3630 case SOC_PHY_CONTROL_RX_TAP4: 3631 rv = phy_82780_rx_tap_get(pmc, intf, 3, value); 3632 break; 3633 case SOC_PHY_CONTROL_RX_TAP5: 3634 rv = phy_82780_rx_tap_get(pmc, intf, 4, value); 3635 break; 3636 3637 /* PHASE INTERPOLATOR */ 3638 case SOC_PHY_CONTROL_PHASE_INTERP: 3639 rv = phy_82780_pi_control_get(pmc, intf, value); 3640 break; 3641 3642 case SOC_PHY_CONTROL_RX_SEQ_DONE: 3643 rv = phy_82780_rx_seq_done_get(pmc, intf, value); 3644 break; 3645 /* FEC */ 3646 case SOC_PHY_CONTROL_FORWARD_ERROR_CORRECTION: 3647 rv = phy_82780_fec_enable_get(pmc, value); 3648 break; 3649 case SOC_PHY_CONTROL_RX_POLARITY: 3650 rv = phy_82780_rx_polarity_get(pmc, intf, value);; 3651 break; 3652 case SOC_PHY_CONTROL_TX_POLARITY: 3653 rv = phy_82780_tx_polarity_get(pmc, intf, value); 3654 break; 3655 /* POWER */ 3656 case SOC_PHY_CONTROL_POWER: 3657 rv = phy_82780_power_get(pmc, intf, value); 3658 break; 3659 case SOC_PHY_CONTROL_CL72: 3660 rv = phy_82780_cl72_enable_get(pmc, intf, value); 3661 break; 3662 case SOC_PHY_CONTROL_CL72_STATUS: 3663 rv = phy_82780_cl72_status_get(pmc, intf, value); 3664 break; 3665 case SOC_PHY_CONTROL_TX_LANE_SQUELCH: 3666 rv = phy_82780_tx_lane_squelch_get(pmc, intf, value); 3667 break; 3668 case SOC_PHY_CONTROL_GPIO_CONFIG: 3669 rv = phy_82780_gpio_config_get(pmc, value); 3670 break; 3671 case SOC_PHY_CONTROL_GPIO_VALUE: 3672 rv = phy_82780_gpio_value_get(pmc, value); 3673 break; 3674 case SOC_PHY_CONTROL_FAIL_OVER_MODE: 3675 rv = phy_82780_config_fail_over_get(pc, intf, value); 3676 break; 3677 3678 case SOC_PHY_CONTROL_PORT_PRIMARY: 3679 SOC_IF_ERROR_RETURN 3680 (soc_phyctrl_primary_get(unit, port, &primary)); 3681 *value = (uint32) primary; 3682 rv = SOC_E_NONE; 3683 break; 3684 3685 case SOC_PHY_CONTROL_PORT_OFFSET: 3686 SOC_IF_ERROR_RETURN 3687 (soc_phyctrl_offset_get(unit, port, &offset)); 3688 *value = (uint32) offset; 3689 rv = SOC_E_NONE; 3690 break; 3691 3692 3693 default: 3694 rv = SOC_E_UNAVAIL; 3695 break; 3696 } 3697 return rv; 3698 } 3699 3700 /* 3701 * Function: 3702 * phy_82780_per_lane_control_get 3703 * Purpose: 3704 * Configure PHY device specific control fucntion. 3705 * Parameters: 3706 * unit - StrataSwitch unit #. 3707 * port - StrataSwitch port #. 3708 * lane - lane number 3709 * type - Control to update 3710 * value - New setting for the control 3711 * Returns: 3712 * SOC_E_NONE 3713 */ 3714 STATIC int 3715 phy_82780_per_lane_control_get(int unit, soc_port_t port, int lane, 3716 soc_phy_control_t type, uint32 *value) 3717 { 3718 int rv; 3719 phy_ctrl_t *pc; 3720 soc_phymod_ctrl_t *pmc; 3721 int32 intf; 3722 3723 3724 /* locate phy control, phymod control, and the configuration data */ 3725 pc = EXT_PHY_SW_STATE(unit, port); 3726 if (pc == NULL) { 3727 return SOC_E_INTERNAL; 3728 } 3729 pmc = &pc->phymod_ctrl; 3730 3731 PHY_CONTROL_TYPE_CHECK(type); 3732 3733 intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY82780_SYS_SIDE : PHY82780_LINE_SIDE; 3734 3735 switch(type) { 3736 3737 case SOC_PHY_CONTROL_PREEMPHASIS: 3738 rv = phy_82780_per_lane_preemphasis_get(pmc, intf, lane, value); 3739 break; 3740 case SOC_PHY_CONTROL_DRIVER_CURRENT: 3741 rv = phy_82780_per_lane_driver_current_get(pmc, intf, lane, value); 3742 break; 3743 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_POLYNOMIAL: 3744 rv = phy_82780_per_lane_prbs_tx_poly_get(pmc, intf, lane, value); 3745 break; 3746 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_INVERT_DATA: 3747 rv = phy_82780_per_lane_prbs_tx_invert_data_get(pmc, intf, lane, value); 3748 break; 3749 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_ENABLE: 3750 rv = phy_82780_per_lane_prbs_tx_enable_get(pmc, intf, lane, value); 3751 break; 3752 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_POLYNOMIAL: 3753 rv = phy_82780_per_lane_prbs_rx_poly_get(pmc, intf, lane, value); 3754 break; 3755 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_INVERT_DATA: 3756 rv = phy_82780_per_lane_prbs_rx_invert_data_get(pmc, intf, lane, value); 3757 break; 3758 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_ENABLE: 3759 rv = phy_82780_per_lane_prbs_rx_enable_get(pmc, intf, lane, value); 3760 break; 3761 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 3762 rv = phy_82780_per_lane_prbs_tx_poly_get(pmc, intf, lane, value); 3763 rv = phy_82780_per_lane_prbs_rx_poly_get(pmc, intf, lane, value); 3764 break; 3765 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 3766 rv = phy_82780_per_lane_prbs_tx_invert_data_get(pmc, intf, lane, value); 3767 break; 3768 case SOC_PHY_CONTROL_PRBS_RX_INVERT_DATA: 3769 rv = phy_82780_per_lane_prbs_rx_invert_data_get(pmc, intf, lane, value); 3770 break; 3771 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 3772 rv = phy_82780_per_lane_prbs_tx_enable_get(pmc, intf, lane, value); 3773 rv = phy_82780_per_lane_prbs_rx_enable_get(pmc, intf, lane, value); 3774 break; 3775 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 3776 rv = phy_82780_per_lane_prbs_rx_enable_get(pmc, intf, lane, value); 3777 rv = phy_82780_per_lane_prbs_tx_enable_get(pmc, intf, lane, value); 3778 break; 3779 case SOC_PHY_CONTROL_PRBS_RX_STATUS: 3780 rv = phy_82780_per_lane_prbs_rx_status_get(pmc, intf, lane, value); 3781 break; 3782 case SOC_PHY_CONTROL_RX_PEAK_FILTER: 3783 rv = phy_82780_per_lane_rx_peak_filter_get(pmc, intf, lane, value); 3784 break; 3785 case SOC_PHY_CONTROL_RX_VGA: 3786 rv = phy_82780_per_lane_rx_vga_get(pmc, intf, lane, value); 3787 break; 3788 case SOC_PHY_CONTROL_RX_TAP1: 3789 rv = phy_82780_per_lane_rx_dfe_tap_control_get(pmc, intf, lane, 0, value); 3790 break; 3791 case SOC_PHY_CONTROL_RX_TAP2: 3792 rv = phy_82780_per_lane_rx_dfe_tap_control_get(pmc, intf, lane, 1, value); 3793 break; 3794 case SOC_PHY_CONTROL_RX_TAP3: 3795 rv = phy_82780_per_lane_rx_dfe_tap_control_get(pmc, intf, lane, 2, value); 3796 break; 3797 case SOC_PHY_CONTROL_RX_TAP4: 3798 rv = phy_82780_per_lane_rx_dfe_tap_control_get(pmc, intf, lane, 3, value); 3799 break; 3800 case SOC_PHY_CONTROL_RX_TAP5: 3801 rv = phy_82780_per_lane_rx_dfe_tap_control_get(pmc, intf, lane, 4, value); 3802 break; 3803 case SOC_PHY_CONTROL_RX_LOW_FREQ_PEAK_FILTER: 3804 rv = phy_82780_per_lane_rx_low_freq_filter_get(pmc, intf, lane, value); 3805 break; 3806 /* LOOPBACK */ 3807 case SOC_PHY_CONTROL_LOOPBACK_REMOTE: 3808 rv = phy_82780_per_lane_loopback_remote_get(pmc, intf, lane, value); 3809 break; 3810 case SOC_PHY_CONTROL_LOOPBACK_PMD: 3811 rv = phy_82780_per_lane_loopback_internal_pmd_get(pmc, intf, lane, value); 3812 break; 3813 case SOC_PHY_CONTROL_RX_POLARITY: 3814 rv = phy_82780_per_lane_rx_polarity_get(pmc, intf, lane, value); 3815 break; 3816 case SOC_PHY_CONTROL_TX_POLARITY: 3817 rv = phy_82780_per_lane_tx_polarity_get(pmc, intf, lane, value); 3818 break; 3819 /* POWER */ 3820 case SOC_PHY_CONTROL_POWER: 3821 rv = phy_82780_per_lane_power_get(pmc, intf, lane, value); 3822 break; 3823 case SOC_PHY_CONTROL_TX_FIR_PRE: 3824 case SOC_PHY_CONTROL_TX_FIR_MAIN: 3825 case SOC_PHY_CONTROL_TX_FIR_POST: 3826 case SOC_PHY_CONTROL_TX_FIR_POST2: 3827 rv = phy_82780_per_lane_tx_get(pmc, intf, type, lane, value); 3828 break; 3829 case SOC_PHY_CONTROL_TX_LANE_SQUELCH: 3830 rv = phy_82780_per_lane_tx_lane_squelch_get(pmc, intf, lane, value); 3831 break; 3832 3833 default: 3834 rv = SOC_E_UNAVAIL; 3835 break; 3836 } 3837 return rv; 3838 } 3839 3840 /* 3841 * Function: 3842 * phy_82780_an_set 3843 * Purpose: 3844 * Enable or disable auto-negotiation on the specified port. 3845 * Parameters: 3846 * unit - BCM unit number. 3847 * port - Port number. 3848 * an - Boolean, if true, auto-negotiation is enabled 3849 * (and/or restarted). If false, autonegotiation is disabled. 3850 * Returns: 3851 * SOC_E_XXX _soc_triumph_tx 3852 */ 3853 STATIC int 3854 phy_82780_an_set(int unit, soc_port_t port, int enable) 3855 { 3856 phy_ctrl_t *pc; 3857 phy82780_config_t *pCfg; 3858 soc_phymod_ctrl_t *pmc; 3859 phymod_phy_access_t *pm_phy; 3860 int idx = 0; 3861 phymod_autoneg_control_t an; 3862 3863 sal_memset(&an, 0, sizeof(phymod_autoneg_control_t)); 3864 /* locate phy control */ 3865 pc = EXT_PHY_SW_STATE(unit, port); 3866 pmc = &pc->phymod_ctrl; 3867 pCfg = (phy82780_config_t *) pc->driver_data; 3868 idx = pmc->main_phy; 3869 pm_phy = &pmc->phy[idx]->pm_phy; 3870 3871 if (pCfg->speed_config.speed == 1000 && 3872 pCfg->speed_config.line_interface == SOC_PORT_IF_SR) { 3873 an.an_mode = phymod_AN_MODE_CL37; 3874 an.enable = enable; 3875 SOC_IF_ERROR_RETURN( 3876 phymod_phy_autoneg_set(pm_phy, &an)); 3877 3878 } 3879 3880 return (SOC_E_NONE); 3881 } 3882 /* 3883 * Function: 3884 * phy_82780_an_get 3885 * Purpose: 3886 * Get the current auto-negotiation status (enabled/busy) 3887 * Parameters: 3888 * unit - BCM unit number. 3889 * port - Port number. 3890 * an - (OUT) if true, auto-negotiation is enabled. 3891 * an_done - (OUT) if true, auto-negotiation is complete. This 3892 * value is undefined if an == false. 3893 * Returns: 3894 * SOC_E_XXX 3895 */ 3896 3897 STATIC int 3898 phy_82780_an_get(int unit, soc_port_t port, int *an, int *an_done) 3899 { 3900 phy_ctrl_t* pc; 3901 soc_phymod_ctrl_t *pmc; 3902 phymod_phy_access_t *pm_phy; 3903 phymod_autoneg_control_t an_control; 3904 int idx, an_complete; 3905 3906 *an = 0; 3907 *an_done = 0; 3908 3909 pc = EXT_PHY_SW_STATE(unit, port); 3910 pmc = &pc->phymod_ctrl; 3911 3912 sal_memset(&an_control, 0x0, sizeof(an_control)); 3913 3914 idx = pmc->main_phy; 3915 pm_phy = &pmc->phy[idx]->pm_phy; 3916 3917 SOC_IF_ERROR_RETURN 3918 (phymod_phy_autoneg_get(pm_phy, &an_control, (uint32_t *) &an_complete)); 3919 3920 if (an_control.enable) { 3921 *an = 1; 3922 *an_done = an_complete; 3923 #ifdef PHY82780_DEBUG 3924 LOG_CLI((BSL_META_U(unit,"AN complete:%d\n "),*an_done)); 3925 #endif 3926 } else { 3927 *an = 0; 3928 *an_done = 0; 3929 } 3930 return SOC_E_NONE; 3931 } 3932 /* 3933 * Function: 3934 * phy_82780_ability_advert_set 3935 * Purpose: 3936 * Set the current advertisement for auto-negotiation. 3937 * Parameters: 3938 * unit - BCM unit number. 3939 * port - Port number. 3940 * ability - Port mode mask indicating supported options/speeds. 3941 * Returns: 3942 * SOC_E_XXX 3943 * Notes: 3944 * The advertisement is set only for the ACTIVE medium. 3945 * No synchronization performed at this level. 3946 */ 3947 3948 STATIC int 3949 phy_82780_ability_advert_set(int unit, soc_port_t port, 3950 soc_port_ability_t *ability) 3951 { 3952 phy_ctrl_t *pc; 3953 soc_phymod_ctrl_t *pmc; 3954 soc_phymod_phy_t *phy; 3955 int line_interface; 3956 uint32_t an_tech_ability; 3957 uint32_t an_bam37_ability; 3958 uint32_t an_bam73_ability; 3959 _shr_port_mode_t speed_full_duplex; 3960 phymod_autoneg_ability_t phymod_autoneg_ability; 3961 3962 /* locate phy control */ 3963 pc = EXT_PHY_SW_STATE(unit, port); 3964 if (pc == NULL) { 3965 return SOC_E_INTERNAL; 3966 } 3967 3968 phymod_autoneg_ability_t_init(&phymod_autoneg_ability); 3969 3970 pmc = &pc->phymod_ctrl; 3971 3972 /* only set abilities on the first core */ 3973 phy = pmc->phy[pmc->main_phy]; 3974 if (phy == NULL) { 3975 return SOC_E_INTERNAL; 3976 } 3977 3978 an_tech_ability = 0; 3979 an_bam37_ability = 0; 3980 an_bam73_ability = 0; 3981 speed_full_duplex = ability->speed_full_duplex; 3982 line_interface = ability->interface; 3983 3984 if (speed_full_duplex & SOC_PA_SPEED_40GB) { 3985 if (line_interface & SOC_PORT_IF_CR4) { 3986 PHYMOD_AN_CAP_40G_CR4_SET(an_tech_ability); 3987 } else { 3988 PHYMOD_AN_CAP_40G_KR4_SET(an_tech_ability); 3989 } 3990 } else if (speed_full_duplex & SOC_PA_SPEED_10GB) { 3991 PHYMOD_AN_CAP_10G_KR_SET(an_tech_ability); 3992 } else { 3993 an_tech_ability = 0; 3994 } 3995 3996 phymod_autoneg_ability.an_cap = an_tech_ability; 3997 phymod_autoneg_ability.cl73bam_cap = an_bam73_ability; 3998 phymod_autoneg_ability.cl37bam_cap = an_bam37_ability; 3999 #ifdef PHY82780_DEBUG 4000 LOG_CLI((BSL_META_U(unit,"AN:abilitySet =%x tech ability:%x pause:%d\n"), speed_full_duplex, an_tech_ability,ability->pause)); 4001 #endif 4002 switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) { 4003 case SOC_PA_PAUSE_TX: 4004 PHYMOD_AN_CAP_ASYM_PAUSE_SET(&phymod_autoneg_ability); 4005 break; 4006 case SOC_PA_PAUSE_RX: 4007 /* an_adv |= MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE; */ 4008 PHYMOD_AN_CAP_ASYM_PAUSE_SET(&phymod_autoneg_ability); 4009 PHYMOD_AN_CAP_SYMM_PAUSE_SET(&phymod_autoneg_ability); 4010 break; 4011 case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX: 4012 PHYMOD_AN_CAP_SYMM_PAUSE_SET(&phymod_autoneg_ability); 4013 break; 4014 } 4015 4016 4017 4018 phymod_autoneg_ability.sgmii_speed = 2; 4019 4020 SOC_IF_ERROR_RETURN 4021 (phymod_phy_autoneg_ability_set(&phy->pm_phy, &phymod_autoneg_ability)); 4022 return SOC_E_NONE; 4023 } 4024 4025 /* 4026 * Function: 4027 * phy_82780_ability_advert_get 4028 * Purpose: 4029 * Get the current advertisement for auto-negotiation. 4030 * Parameters: 4031 * unit - BCM unit number. 4032 * port - Port number. 4033 * ability - (OUT) Port mode mask indicating supported options/speeds. 4034 * Returns: 4035 * SOC_E_XXX 4036 * Notes: 4037 * The advertisement is retrieved for the ACTIVE medium. 4038 * No synchronization performed at this level. 4039 */ 4040 4041 STATIC int 4042 phy_82780_ability_advert_get(int unit, soc_port_t port, 4043 soc_port_ability_t *ability) 4044 { 4045 phy_ctrl_t *pc; 4046 soc_phymod_ctrl_t *pmc; 4047 soc_phymod_phy_t *phy; 4048 int reg73_ability; 4049 int reg_ability; 4050 _shr_port_mode_t speed_full_duplex; 4051 phymod_autoneg_ability_t phymod_autoneg_ability; 4052 4053 /* locate phy control */ 4054 pc = EXT_PHY_SW_STATE(unit, port); 4055 if (pc == NULL) { 4056 return SOC_E_INTERNAL; 4057 } 4058 4059 pmc = &pc->phymod_ctrl; 4060 4061 /* only get abilities from the first core */ 4062 phy = pmc->phy[0]; 4063 if (phy == NULL) { 4064 return SOC_E_INTERNAL; 4065 } 4066 4067 phymod_autoneg_ability_t_init(&phymod_autoneg_ability); 4068 4069 SOC_IF_ERROR_RETURN 4070 (phymod_phy_autoneg_ability_get(&phy->pm_phy, &phymod_autoneg_ability)); 4071 4072 4073 speed_full_duplex = 0; 4074 4075 /* retrieve CL73 abilities */ 4076 reg73_ability = phymod_autoneg_ability.an_cap; 4077 speed_full_duplex |= PHYMOD_AN_CAP_40G_CR4_GET(reg73_ability) ? SOC_PA_SPEED_40GB : 0; 4078 speed_full_duplex |= PHYMOD_AN_CAP_40G_KR4_GET(reg73_ability) ? SOC_PA_SPEED_40GB : 0; 4079 speed_full_duplex |= PHYMOD_AN_CAP_10G_KR_GET (reg73_ability) ? SOC_PA_SPEED_10GB : 0; 4080 4081 if (speed_full_duplex & SOC_PA_SPEED_40GB) { 4082 if (PHYMOD_AN_CAP_40G_CR4_GET(reg73_ability)) { 4083 ability->interface = SOC_PORT_IF_CR4; 4084 } else { 4085 ability->interface = SOC_PORT_IF_KR4; 4086 } 4087 } else if (speed_full_duplex & SOC_PA_SPEED_10GB) { 4088 ability->interface = SOC_PORT_IF_KR; 4089 } else { 4090 ability->interface = 0; 4091 } 4092 4093 4094 /* retrieve "pause" abilities */ 4095 reg_ability = phymod_autoneg_ability.capabilities; 4096 4097 ability->pause = 0; 4098 if (reg_ability == PHYMOD_AN_CAP_ASYM_PAUSE) { 4099 ability->pause = SOC_PA_PAUSE_TX; 4100 } else if (reg_ability == (PHYMOD_AN_CAP_SYMM_PAUSE | PHYMOD_AN_CAP_ASYM_PAUSE)) { 4101 ability->pause = SOC_PA_PAUSE_RX; 4102 } else if (reg_ability == PHYMOD_AN_CAP_SYMM_PAUSE) { 4103 ability->pause = (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX); 4104 } 4105 4106 ability->speed_full_duplex = speed_full_duplex; 4107 return SOC_E_NONE; 4108 } 4109 4110 /* 4111 * Function: 4112 * phy82780_lb_get 4113 * Purpose: 4114 * Get current PHY loopback mode 4115 * Parameters: 4116 * unit - BCM unit number. 4117 * port - Port number. 4118 * enable - address of location to store binary value for on/off (1/0) 4119 * Returns: 4120 * SOC_E_NONE 4121 */ 4122 STATIC int 4123 phy82780_lb_get(int unit, soc_port_t port, int *enable) 4124 { 4125 phy_ctrl_t* pc; 4126 soc_phymod_ctrl_t *pmc; 4127 uint32 out_en; 4128 4129 pc = EXT_PHY_SW_STATE(unit, port); 4130 pmc = &pc->phymod_ctrl; 4131 SOC_IF_ERROR_RETURN( 4132 phy_82780_loopback_internal_pmd_get(pmc, PHY82780_LINE_SIDE, &out_en)); 4133 *enable = (int) out_en; 4134 4135 return SOC_E_NONE; 4136 } 4137 4138 /* 4139 * phy_82780_per_lane_loopback_internal_pmd_set 4140 */ 4141 STATIC int 4142 phy_82780_per_lane_loopback_internal_pmd_set(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 value) 4143 { 4144 phymod_phy_access_t *pm_phy; 4145 uint32 lane_map; 4146 phymod_phy_access_t pm_phy_copy; 4147 soc_phymod_phy_t *p_phy; 4148 4149 /* locate the desired phy and lane */ 4150 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 4151 4152 /* Make a copy of the phy access and overwrite the desired lane */ 4153 pm_phy = &p_phy->pm_phy; 4154 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4155 pm_phy_copy.access.lane_mask = lane_map; 4156 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4157 if(intf == PHY82780_SYS_SIDE) { 4158 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4159 } 4160 4161 SOC_IF_ERROR_RETURN 4162 (phymod_phy_loopback_set(&pm_phy_copy, phymodLoopbackGlobalPMD, value)); 4163 return(SOC_E_NONE); 4164 } 4165 4166 /* 4167 * phy_82780_loopback_internal_pmd_set 4168 */ 4169 STATIC int 4170 phy_82780_loopback_internal_pmd_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 4171 { 4172 phymod_phy_access_t *pm_phy; 4173 int idx; 4174 phymod_phy_access_t pm_phy_copy; 4175 4176 for (idx = 0; idx < pmc->num_phys; idx++) { 4177 if (pmc->phy[idx] == NULL) { 4178 return SOC_E_INTERNAL; 4179 } 4180 pm_phy = &pmc->phy[idx]->pm_phy; 4181 if (pm_phy == NULL) { 4182 return SOC_E_INTERNAL; 4183 } 4184 4185 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4186 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4187 if(intf == PHY82780_SYS_SIDE) { 4188 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4189 } 4190 4191 SOC_IF_ERROR_RETURN 4192 (phymod_phy_loopback_set(&pm_phy_copy, phymodLoopbackGlobalPMD, value)); 4193 } 4194 return(SOC_E_NONE); 4195 } 4196 4197 /* 4198 * phy_82780_per_lane_loopback_remote_set 4199 */ 4200 STATIC int 4201 phy_82780_per_lane_loopback_remote_set(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 value) 4202 { 4203 phymod_phy_access_t *pm_phy; 4204 uint32 lane_map; 4205 phymod_phy_access_t pm_phy_copy; 4206 soc_phymod_phy_t *p_phy; 4207 4208 /* locate the desired phy and lane */ 4209 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 4210 4211 /* Make a copy of the phy access and overwrite the desired lane */ 4212 pm_phy = &p_phy->pm_phy; 4213 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4214 pm_phy_copy.access.lane_mask = lane_map; 4215 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4216 if(intf == PHY82780_SYS_SIDE) { 4217 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4218 } 4219 4220 SOC_IF_ERROR_RETURN 4221 (phymod_phy_loopback_set(&pm_phy_copy, phymodLoopbackRemotePMD, value)); 4222 return(SOC_E_NONE); 4223 } 4224 /* 4225 * phy_82780_loopback_remote_set 4226 */ 4227 STATIC int 4228 phy_82780_loopback_remote_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 4229 { 4230 phymod_phy_access_t *pm_phy; 4231 int idx; 4232 phymod_phy_access_t pm_phy_copy; 4233 4234 for (idx = 0; idx < pmc->num_phys; idx++) { 4235 if (pmc->phy[idx] == NULL) { 4236 return SOC_E_INTERNAL; 4237 } 4238 pm_phy = &pmc->phy[idx]->pm_phy; 4239 if (pm_phy == NULL) { 4240 return SOC_E_INTERNAL; 4241 } 4242 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4243 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4244 if(intf == PHY82780_SYS_SIDE) { 4245 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4246 } 4247 4248 SOC_IF_ERROR_RETURN 4249 (phymod_phy_loopback_set(&pm_phy_copy, phymodLoopbackRemotePMD, value)); 4250 } 4251 return(SOC_E_NONE); 4252 } 4253 4254 /* 4255 * phy_82780_fec_enable_set 4256 */ 4257 STATIC int 4258 phy_82780_fec_enable_set(soc_phymod_ctrl_t *pmc, uint32 value) 4259 { 4260 phymod_phy_access_t *pm_phy; 4261 int idx; 4262 4263 /* loop through all cores */ 4264 for (idx = 0; idx < pmc->num_phys; idx++) { 4265 pm_phy = &pmc->phy[idx]->pm_phy; 4266 4267 if (pm_phy == NULL) { 4268 return SOC_E_INTERNAL; 4269 } 4270 SOC_IF_ERROR_RETURN(phymod_phy_fec_enable_set(pm_phy, value)); 4271 } 4272 return(SOC_E_NONE); 4273 } 4274 4275 STATIC int 4276 phy_82780_sdk_poly_to_phymod_poly(uint32 sdk_poly, phymod_prbs_poly_t *phymod_poly){ 4277 switch(sdk_poly){ 4278 case SOC_PHY_PRBS_POLYNOMIAL_X7_X6_1: 4279 *phymod_poly = phymodPrbsPoly7; 4280 break; 4281 case SOC_PHY_PRBS_POLYNOMIAL_X15_X14_1: 4282 *phymod_poly = phymodPrbsPoly15; 4283 break; 4284 case SOC_PHY_PRBS_POLYNOMIAL_X23_X18_1: 4285 *phymod_poly = phymodPrbsPoly23; 4286 break; 4287 case SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1: 4288 *phymod_poly = phymodPrbsPoly31; 4289 break; 4290 case SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1: 4291 *phymod_poly = phymodPrbsPoly9; 4292 break; 4293 case SOC_PHY_PRBS_POLYNOMIAL_X11_X9_1: 4294 *phymod_poly = phymodPrbsPoly11; 4295 break; 4296 case SOC_PHY_PRBS_POLYNOMIAL_X58_X31_1: 4297 *phymod_poly = phymodPrbsPoly58; 4298 break; 4299 default: 4300 return SOC_E_INTERNAL; 4301 } 4302 return SOC_E_NONE; 4303 } 4304 /* 4305 * phy_82780_per_lane_prbs_tx_poly_set 4306 */ 4307 STATIC int 4308 phy_82780_per_lane_prbs_tx_poly_set(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 value) 4309 { 4310 phymod_phy_access_t *pm_phy; 4311 phymod_prbs_t prbs; 4312 uint32_t flags = 0; 4313 uint32 lane_map; 4314 phymod_phy_access_t pm_phy_copy; 4315 soc_phymod_phy_t *p_phy; 4316 4317 /* locate the desired phy and lane */ 4318 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 4319 4320 /* Make a copy of the phy access and overwrite the desired lane */ 4321 pm_phy = &p_phy->pm_phy; 4322 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4323 pm_phy_copy.access.lane_mask = lane_map; 4324 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4325 if(intf == PHY82780_SYS_SIDE) { 4326 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4327 } 4328 4329 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 4330 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 4331 SOC_IF_ERROR_RETURN(phy_82780_sdk_poly_to_phymod_poly(value, &prbs.poly)); 4332 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(&pm_phy_copy, flags, &prbs)); 4333 return(SOC_E_NONE); 4334 } 4335 /* 4336 * phy_82780_prbs_tx_poly_set 4337 */ 4338 STATIC int 4339 phy_82780_prbs_tx_poly_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 4340 { 4341 phymod_phy_access_t *pm_phy; 4342 phymod_prbs_t prbs; 4343 uint32_t flags = 0; 4344 int idx; 4345 phymod_phy_access_t pm_phy_copy; 4346 4347 for (idx = 0; idx < pmc->num_phys; idx++) { 4348 if (pmc->phy[idx] == NULL) { 4349 return SOC_E_INTERNAL; 4350 } 4351 pm_phy = &pmc->phy[idx]->pm_phy; 4352 if (pm_phy == NULL) { 4353 return SOC_E_INTERNAL; 4354 } 4355 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4356 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4357 if(intf == PHY82780_SYS_SIDE) { 4358 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4359 } 4360 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 4361 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 4362 SOC_IF_ERROR_RETURN(phy_82780_sdk_poly_to_phymod_poly(value, &prbs.poly)); 4363 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(&pm_phy_copy, flags, &prbs)); 4364 } 4365 return(SOC_E_NONE); 4366 } 4367 /* 4368 * phy_82780_per_lane_prbs_rx_poly_set 4369 */ 4370 STATIC int 4371 phy_82780_per_lane_prbs_rx_poly_set(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 value) 4372 { 4373 phymod_phy_access_t *pm_phy; 4374 phymod_prbs_t prbs; 4375 uint32_t flags = 0; 4376 uint32 lane_map; 4377 phymod_phy_access_t pm_phy_copy; 4378 soc_phymod_phy_t *p_phy; 4379 4380 /* locate the desired phy and lane */ 4381 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 4382 4383 /* Make a copy of the phy access and overwrite the desired lane */ 4384 pm_phy = &p_phy->pm_phy; 4385 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4386 pm_phy_copy.access.lane_mask = lane_map; 4387 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4388 if(intf == PHY82780_SYS_SIDE) { 4389 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4390 } 4391 4392 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 4393 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 4394 SOC_IF_ERROR_RETURN(phy_82780_sdk_poly_to_phymod_poly(value, &prbs.poly)); 4395 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(&pm_phy_copy, flags, &prbs)); 4396 return(SOC_E_NONE); 4397 } 4398 4399 /* 4400 * phy_82780_prbs_rx_poly_set 4401 */ 4402 STATIC int 4403 phy_82780_prbs_rx_poly_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 4404 { 4405 phymod_phy_access_t *pm_phy; 4406 phymod_prbs_t prbs; 4407 uint32_t flags = 0; 4408 int idx; 4409 phymod_phy_access_t pm_phy_copy; 4410 4411 for (idx = 0; idx < pmc->num_phys; idx++) { 4412 if (pmc->phy[idx] == NULL) { 4413 return SOC_E_INTERNAL; 4414 } 4415 pm_phy = &pmc->phy[idx]->pm_phy; 4416 if (pm_phy == NULL) { 4417 return SOC_E_INTERNAL; 4418 } 4419 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4420 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4421 if(intf == PHY82780_SYS_SIDE) { 4422 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4423 } 4424 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 4425 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 4426 SOC_IF_ERROR_RETURN(phy_82780_sdk_poly_to_phymod_poly(value, &prbs.poly)); 4427 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(&pm_phy_copy, flags, &prbs)); 4428 } 4429 return(SOC_E_NONE); 4430 } 4431 4432 4433 /* 4434 * phy_82780_per_lane_prbs_tx_invert_data_set 4435 */ 4436 STATIC int 4437 phy_82780_per_lane_prbs_tx_invert_data_set(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 value) 4438 { 4439 phymod_phy_access_t *pm_phy; 4440 phymod_prbs_t prbs; 4441 uint32_t flags = 0; 4442 4443 uint32 lane_map; 4444 phymod_phy_access_t pm_phy_copy; 4445 soc_phymod_phy_t *p_phy; 4446 4447 /* locate the desired phy and lane */ 4448 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 4449 4450 /* Make a copy of the phy access and overwrite the desired lane */ 4451 pm_phy = &p_phy->pm_phy; 4452 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4453 pm_phy_copy.access.lane_mask = lane_map; 4454 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4455 if(intf == PHY82780_SYS_SIDE) { 4456 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4457 } 4458 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 4459 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 4460 prbs.invert = value; 4461 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(&pm_phy_copy, flags, &prbs)); 4462 return(SOC_E_NONE); 4463 } 4464 4465 /* 4466 * phy_82780_prbs_tx_invert_data_set 4467 */ 4468 STATIC int 4469 phy_82780_prbs_tx_invert_data_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 4470 { 4471 phymod_phy_access_t *pm_phy; 4472 phymod_prbs_t prbs; 4473 uint32_t flags = 0; 4474 int idx; 4475 phymod_phy_access_t pm_phy_copy; 4476 4477 for (idx = 0; idx < pmc->num_phys; idx++) { 4478 if (pmc->phy[idx] == NULL) { 4479 return SOC_E_INTERNAL; 4480 } 4481 pm_phy = &pmc->phy[idx]->pm_phy; 4482 if (pm_phy == NULL) { 4483 return SOC_E_INTERNAL; 4484 } 4485 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4486 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4487 if(intf == PHY82780_SYS_SIDE) { 4488 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4489 } 4490 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 4491 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 4492 prbs.invert = value; 4493 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(&pm_phy_copy, flags, &prbs)); 4494 } 4495 return(SOC_E_NONE); 4496 } 4497 4498 /* 4499 * phy_82780_per_lane_prbs_rx_invert_data_set 4500 */ 4501 STATIC int 4502 phy_82780_per_lane_prbs_rx_invert_data_set(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 value) 4503 { 4504 phymod_phy_access_t *pm_phy; 4505 phymod_prbs_t prbs; 4506 uint32_t flags = 0; 4507 uint32 lane_map; 4508 phymod_phy_access_t pm_phy_copy; 4509 soc_phymod_phy_t *p_phy; 4510 4511 /* locate the desired phy and lane */ 4512 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 4513 4514 /* Make a copy of the phy access and overwrite the desired lane */ 4515 pm_phy = &p_phy->pm_phy; 4516 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4517 pm_phy_copy.access.lane_mask = lane_map; 4518 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4519 if(intf == PHY82780_SYS_SIDE) { 4520 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4521 } 4522 4523 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 4524 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 4525 prbs.invert = value; 4526 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(&pm_phy_copy, flags, &prbs)); 4527 return(SOC_E_NONE); 4528 } 4529 /* 4530 * phy_82780_prbs_rx_invert_data_set 4531 */ 4532 STATIC int 4533 phy_82780_prbs_rx_invert_data_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 4534 { 4535 phymod_phy_access_t *pm_phy; 4536 phymod_prbs_t prbs; 4537 uint32_t flags = 0; 4538 int idx; 4539 phymod_phy_access_t pm_phy_copy; 4540 4541 for (idx = 0; idx < pmc->num_phys; idx++) { 4542 if (pmc->phy[idx] == NULL) { 4543 return SOC_E_INTERNAL; 4544 } 4545 pm_phy = &pmc->phy[idx]->pm_phy; 4546 if (pm_phy == NULL) { 4547 return SOC_E_INTERNAL; 4548 } 4549 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4550 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4551 if(intf == PHY82780_SYS_SIDE) { 4552 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4553 } 4554 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 4555 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 4556 prbs.invert = value; 4557 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(&pm_phy_copy, flags, &prbs)); 4558 } 4559 return(SOC_E_NONE); 4560 } 4561 4562 /* 4563 * phy_82780_per_lane_prbs_tx_enable_set 4564 */ 4565 STATIC int 4566 phy_82780_per_lane_prbs_tx_enable_set(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 value) 4567 { 4568 phymod_phy_access_t *pm_phy; 4569 uint32_t flags = 0; 4570 uint32 lane_map; 4571 phymod_phy_access_t pm_phy_copy; 4572 soc_phymod_phy_t *p_phy; 4573 4574 /* locate the desired phy and lane */ 4575 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 4576 4577 /* Make a copy of the phy access and overwrite the desired lane */ 4578 pm_phy = &p_phy->pm_phy; 4579 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4580 pm_phy_copy.access.lane_mask = lane_map; 4581 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4582 if(intf == PHY82780_SYS_SIDE) { 4583 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4584 } 4585 4586 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 4587 SOC_IF_ERROR_RETURN( 4588 phymod_phy_prbs_enable_set(&pm_phy_copy, flags, value)); 4589 return(SOC_E_NONE); 4590 } 4591 /* 4592 * phy_82780_prbs_tx_enable_set 4593 */ 4594 STATIC int 4595 phy_82780_prbs_tx_enable_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 4596 { 4597 phymod_phy_access_t *pm_phy; 4598 uint32_t flags = 0; 4599 int idx; 4600 phymod_phy_access_t pm_phy_copy; 4601 4602 for (idx = 0; idx < pmc->num_phys; idx++) { 4603 if (pmc->phy[idx] == NULL) { 4604 return SOC_E_INTERNAL; 4605 } 4606 pm_phy = &pmc->phy[idx]->pm_phy; 4607 if (pm_phy == NULL) { 4608 return SOC_E_INTERNAL; 4609 } 4610 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4611 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4612 if(intf == PHY82780_SYS_SIDE) { 4613 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4614 } 4615 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 4616 SOC_IF_ERROR_RETURN(phymod_phy_prbs_enable_set(&pm_phy_copy, flags, value)); 4617 } 4618 return(SOC_E_NONE); 4619 } 4620 4621 /* 4622 * phy_82780_per_lane_prbs_rx_enable_set 4623 */ 4624 STATIC int 4625 phy_82780_per_lane_prbs_rx_enable_set(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 value) 4626 { 4627 phymod_phy_access_t *pm_phy; 4628 uint32_t flags = 0; 4629 4630 uint32 lane_map; 4631 phymod_phy_access_t pm_phy_copy; 4632 soc_phymod_phy_t *p_phy; 4633 4634 /* locate the desired phy and lane */ 4635 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 4636 4637 /* Make a copy of the phy access and overwrite the desired lane */ 4638 pm_phy = &p_phy->pm_phy; 4639 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4640 pm_phy_copy.access.lane_mask = lane_map; 4641 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4642 if(intf == PHY82780_SYS_SIDE) { 4643 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4644 } 4645 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 4646 SOC_IF_ERROR_RETURN(phymod_phy_prbs_enable_set(&pm_phy_copy, flags, value)); 4647 return(SOC_E_NONE); 4648 } 4649 /* 4650 * phy_82780_prbs_rx_enable_set 4651 */ 4652 STATIC int 4653 phy_82780_prbs_rx_enable_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 4654 { 4655 phymod_phy_access_t *pm_phy; 4656 uint32_t flags = 0; 4657 int idx; 4658 phymod_phy_access_t pm_phy_copy; 4659 4660 for (idx = 0; idx < pmc->num_phys; idx++) { 4661 if (pmc->phy[idx] == NULL) { 4662 return SOC_E_INTERNAL; 4663 } 4664 pm_phy = &pmc->phy[idx]->pm_phy; 4665 if (pm_phy == NULL) { 4666 return SOC_E_INTERNAL; 4667 } 4668 4669 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4670 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4671 if(intf == PHY82780_SYS_SIDE) { 4672 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4673 } 4674 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 4675 SOC_IF_ERROR_RETURN(phymod_phy_prbs_enable_set(&pm_phy_copy, flags, value)); 4676 } 4677 return(SOC_E_NONE); 4678 } 4679 4680 4681 /* 4682 * given a pc (phymod_ctrl_t) and logical lane number, 4683 * find the correct soc_phymod_phy_t object and lane 4684 */ 4685 STATIC int 4686 _phy_82780_find_soc_phy_lane(soc_phymod_ctrl_t *pmc, uint32_t lane, 4687 soc_phymod_phy_t **p_phy, uint32 *lane_map) 4688 { 4689 phymod_phy_access_t *pm_phy; 4690 int idx, lnx, ln_cnt, found; 4691 uint32 lane_map_copy; 4692 4693 /* Traverse lanes belonging to this port */ 4694 found = 0; 4695 ln_cnt = 0; 4696 for (idx = 0; idx < pmc->num_phys; idx++) { 4697 pm_phy = &pmc->phy[idx]->pm_phy; 4698 if (pm_phy == NULL) { 4699 return SOC_E_INTERNAL; 4700 } 4701 lane_map_copy = pm_phy->access.lane_mask; 4702 for (lnx = 0; lnx < 4; lnx++) { 4703 if ((1 << lnx) & lane_map_copy) { 4704 if ((ln_cnt == lane) || (lane == 0)) { 4705 found = 1; 4706 break; 4707 } 4708 ln_cnt++; 4709 } 4710 } 4711 if (found) { 4712 *p_phy = pmc->phy[idx]; 4713 *lane_map = (1 << lnx); 4714 break; 4715 } 4716 } 4717 4718 if (!found) { 4719 LOG_CLI((BSL_META_U(pmc->unit,"\nInvalid lane \n"))); 4720 /* No such lane */ 4721 return SOC_E_PARAM; 4722 } 4723 return (SOC_E_NONE); 4724 } 4725 4726 /* 4727 * phy_82780_per_lane_preemphasis_set 4728 */ 4729 STATIC int 4730 phy_82780_per_lane_preemphasis_set(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 value) 4731 { 4732 soc_phymod_phy_t *p_phy; 4733 uint32 lane_map; 4734 phymod_phy_access_t pm_phy_copy, *pm_phy; 4735 phymod_tx_t phymod_tx; 4736 4737 /* locate the desired phy and lane */ 4738 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 4739 4740 /* Make a copy of the phy access and overwrite the desired lane */ 4741 pm_phy = &p_phy->pm_phy; 4742 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4743 pm_phy_copy.access.lane_mask = lane_map; 4744 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4745 if(intf == PHY82780_SYS_SIDE) { 4746 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4747 } 4748 4749 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 4750 /* 0 to 7 = pre 4751 * 8 to 15 = main 4752 * 16 to 24 = post*/ 4753 phymod_tx.pre = (value & 0xff); 4754 phymod_tx.main = (value & 0xff00) >> 8; 4755 phymod_tx.post = (value & 0xff0000) >> 16; 4756 4757 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 4758 4759 return(SOC_E_NONE); 4760 } 4761 4762 /* 4763 * phy_82780_preemphasis_set 4764 */ 4765 STATIC int 4766 phy_82780_preemphasis_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 4767 { 4768 phymod_phy_access_t *pm_phy; 4769 phymod_tx_t phymod_tx; 4770 int idx; 4771 phymod_phy_access_t pm_phy_copy; 4772 4773 /* loop through all cores */ 4774 for (idx = 0; idx < pmc->num_phys; idx++) { 4775 pm_phy = &pmc->phy[idx]->pm_phy; 4776 4777 if (pm_phy == NULL) { 4778 return SOC_E_INTERNAL; 4779 } 4780 4781 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4782 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4783 if(intf == PHY82780_SYS_SIDE) { 4784 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4785 } 4786 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 4787 /* 0 to 7 = pre 4788 * 8 to 15 = main 4789 * 16 to 24 = post*/ 4790 phymod_tx.pre = (value & 0xff); 4791 phymod_tx.main = (value & 0xff00) >> 8; 4792 phymod_tx.post = (value & 0xff0000) >> 16; 4793 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 4794 4795 } 4796 4797 return(SOC_E_NONE); 4798 } 4799 4800 /* 4801 * phy_82780_tx_fir_pre_set 4802 */ 4803 STATIC int 4804 phy_82780_tx_fir_pre_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 4805 { 4806 phymod_phy_access_t *pm_phy; 4807 phymod_tx_t phymod_tx; 4808 int idx; 4809 phymod_phy_access_t pm_phy_copy; 4810 4811 /* loop through all cores */ 4812 for (idx = 0; idx < pmc->num_phys; idx++) { 4813 pm_phy = &pmc->phy[idx]->pm_phy; 4814 4815 if (pm_phy == NULL) { 4816 return SOC_E_INTERNAL; 4817 } 4818 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4819 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4820 if(intf == PHY82780_SYS_SIDE) { 4821 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4822 } 4823 4824 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 4825 phymod_tx.pre = value; 4826 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 4827 } 4828 4829 return(SOC_E_NONE); 4830 } 4831 4832 /* 4833 * phy_82780_tx_fir_main_set 4834 */ 4835 STATIC int 4836 phy_82780_tx_fir_main_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 4837 { 4838 phymod_phy_access_t *pm_phy; 4839 phymod_tx_t phymod_tx; 4840 int idx; 4841 phymod_phy_access_t pm_phy_copy; 4842 /* loop through all cores */ 4843 for (idx = 0; idx < pmc->num_phys; idx++) { 4844 pm_phy = &pmc->phy[idx]->pm_phy; 4845 4846 if (pm_phy == NULL) { 4847 return SOC_E_INTERNAL; 4848 } 4849 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4850 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4851 if(intf == PHY82780_SYS_SIDE) { 4852 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4853 } 4854 4855 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 4856 phymod_tx.main = value; 4857 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 4858 } 4859 4860 return(SOC_E_NONE); 4861 } 4862 4863 /* 4864 * phy_82780_tx_fir_post_set 4865 */ 4866 STATIC int 4867 phy_82780_tx_fir_post_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 4868 { 4869 phymod_phy_access_t *pm_phy; 4870 phymod_tx_t phymod_tx; 4871 int idx; 4872 phymod_phy_access_t pm_phy_copy; 4873 4874 /* loop through all cores */ 4875 for (idx = 0; idx < pmc->num_phys; idx++) { 4876 pm_phy = &pmc->phy[idx]->pm_phy; 4877 4878 if (pm_phy == NULL) { 4879 return SOC_E_INTERNAL; 4880 } 4881 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4882 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4883 if(intf == PHY82780_SYS_SIDE) { 4884 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4885 } 4886 4887 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 4888 phymod_tx.post = value; 4889 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 4890 } 4891 4892 return(SOC_E_NONE); 4893 } 4894 4895 /* 4896 * phy_82780_tx_fir_post2_set 4897 */ 4898 STATIC int 4899 phy_82780_tx_fir_post2_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 4900 { 4901 phymod_phy_access_t *pm_phy; 4902 phymod_tx_t phymod_tx; 4903 int idx; 4904 phymod_phy_access_t pm_phy_copy; 4905 4906 /* loop through all cores */ 4907 for (idx = 0; idx < pmc->num_phys; idx++) { 4908 pm_phy = &pmc->phy[idx]->pm_phy; 4909 4910 if (pm_phy == NULL) { 4911 return SOC_E_INTERNAL; 4912 } 4913 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4914 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4915 if(intf == PHY82780_SYS_SIDE) { 4916 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4917 } 4918 4919 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 4920 phymod_tx.post2 = value; 4921 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 4922 } 4923 4924 return(SOC_E_NONE); 4925 } 4926 4927 /* 4928 * phy_82780_per_lane_driver_current_set 4929 */ 4930 STATIC int 4931 phy_82780_per_lane_driver_current_set(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 value) 4932 { 4933 soc_phymod_phy_t *p_phy; 4934 uint32 lane_map; 4935 phymod_phy_access_t pm_phy_copy, *pm_phy; 4936 phymod_tx_t phymod_tx; 4937 4938 /* locate the desired phy and lane */ 4939 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 4940 4941 /* Make a copy of the phy access and overwrite the desired lane */ 4942 pm_phy = &p_phy->pm_phy; 4943 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4944 pm_phy_copy.access.lane_mask = lane_map; 4945 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4946 if(intf == PHY82780_SYS_SIDE) { 4947 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4948 } 4949 4950 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 4951 phymod_tx.amp = value; 4952 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 4953 4954 return(SOC_E_NONE); 4955 } 4956 4957 /* 4958 * phy_82780_driver_current_set 4959 */ 4960 STATIC int 4961 phy_82780_driver_current_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 4962 { 4963 phymod_phy_access_t *pm_phy; 4964 phymod_tx_t phymod_tx; 4965 int idx; 4966 phymod_phy_access_t pm_phy_copy; 4967 4968 /* loop through all cores */ 4969 for (idx = 0; idx < pmc->num_phys; idx++) { 4970 pm_phy = &pmc->phy[idx]->pm_phy; 4971 4972 if (pm_phy == NULL) { 4973 return SOC_E_INTERNAL; 4974 } 4975 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4976 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 4977 if(intf == PHY82780_SYS_SIDE) { 4978 PHY82780_SET_SYS_SIDE(pm_phy_copy); 4979 } 4980 4981 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 4982 phymod_tx.amp = value; 4983 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 4984 } 4985 4986 return(SOC_E_NONE); 4987 } 4988 4989 /* 4990 * phy_82780_per_lane_rx_dfe_tap_control_set 4991 */ 4992 STATIC int 4993 phy_82780_per_lane_rx_dfe_tap_control_set(soc_phymod_ctrl_t *pmc, int32 intf, int lane, int tap, int enable, uint32 value) 4994 { 4995 soc_phymod_phy_t *p_phy; 4996 uint32 lane_map; 4997 phymod_phy_access_t pm_phy_copy, *pm_phy; 4998 phymod_rx_t phymod_rx; 4999 5000 /* locate the desired phy and lane */ 5001 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 5002 5003 /* Make a copy of the phy access and overwrite the desired lane */ 5004 pm_phy = &p_phy->pm_phy; 5005 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5006 pm_phy_copy.access.lane_mask = lane_map; 5007 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5008 if(intf == PHY82780_SYS_SIDE) { 5009 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5010 } 5011 5012 if (tap < 0 || tap >= COUNTOF(phymod_rx.dfe)) { 5013 /* this can only happen with a coding error */ 5014 return SOC_E_INTERNAL; 5015 } 5016 sal_memset(&phymod_rx, 0, sizeof(phymod_rx)); 5017 phymod_rx.dfe[tap].enable = enable; 5018 phymod_rx.dfe[tap].value = value; 5019 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(&pm_phy_copy, &phymod_rx)); 5020 5021 return(SOC_E_NONE); 5022 } 5023 /* 5024 * phy_82780_per_lane_tx_lane_squelch 5025 */ 5026 STATIC int 5027 phy_82780_per_lane_tx_lane_squelch(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 value) 5028 { 5029 phymod_phy_access_t *pm_phy; 5030 phymod_phy_tx_lane_control_t tx_control; 5031 int idx; 5032 phymod_phy_access_t pm_phy_copy; 5033 soc_phymod_phy_t *p_phy; 5034 uint32 lane_map; 5035 5036 /* locate the desired phy and lane */ 5037 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 5038 5039 /* loop through all cores */ 5040 for (idx = 0; idx < pmc->num_phys; idx++) { 5041 pm_phy = &pmc->phy[idx]->pm_phy; 5042 5043 if (pm_phy == NULL) { 5044 return SOC_E_INTERNAL; 5045 } 5046 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5047 pm_phy_copy.access.lane_mask = lane_map; 5048 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5049 if(intf == PHY82780_SYS_SIDE) { 5050 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5051 } 5052 5053 if (value == 1) { 5054 tx_control = phymodTxSquelchOn; 5055 } else { 5056 tx_control = phymodTxSquelchOff; 5057 } 5058 SOC_IF_ERROR_RETURN 5059 (phymod_phy_tx_lane_control_set(&pm_phy_copy, tx_control)); 5060 5061 } 5062 return(SOC_E_NONE); 5063 } 5064 5065 STATIC int 5066 phy_82780_per_lane_tx_lane_squelch_get(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 *value) 5067 { 5068 phymod_phy_access_t *pm_phy; 5069 phymod_phy_tx_lane_control_t tx_control; 5070 int idx; 5071 phymod_phy_access_t pm_phy_copy; 5072 soc_phymod_phy_t *p_phy; 5073 uint32 lane_map; 5074 5075 /* locate the desired phy and lane */ 5076 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 5077 5078 /* loop through all cores */ 5079 for (idx = 0; idx < pmc->num_phys; idx++) { 5080 pm_phy = &pmc->phy[idx]->pm_phy; 5081 5082 if (pm_phy == NULL) { 5083 return SOC_E_INTERNAL; 5084 } 5085 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5086 pm_phy_copy.access.lane_mask = lane_map; 5087 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5088 if(intf == PHY82780_SYS_SIDE) { 5089 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5090 } 5091 5092 SOC_IF_ERROR_RETURN 5093 (phymod_phy_tx_lane_control_get(&pm_phy_copy, &tx_control)); 5094 if (tx_control == phymodTxSquelchOn) { 5095 *value = 1; 5096 } else { 5097 *value = 0; 5098 } 5099 } 5100 return(SOC_E_NONE); 5101 } 5102 5103 /* 5104 * phy_82780_tx_lane_squelch 5105 */ 5106 STATIC int 5107 phy_82780_tx_lane_squelch(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 5108 { 5109 phymod_phy_access_t *pm_phy; 5110 phymod_phy_tx_lane_control_t tx_control; 5111 int idx; 5112 phymod_phy_access_t pm_phy_copy; 5113 5114 /* loop through all cores */ 5115 for (idx = 0; idx < pmc->num_phys; idx++) { 5116 pm_phy = &pmc->phy[idx]->pm_phy; 5117 5118 if (pm_phy == NULL) { 5119 return SOC_E_INTERNAL; 5120 } 5121 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5122 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5123 if(intf == PHY82780_SYS_SIDE) { 5124 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5125 } 5126 5127 if (value == 1) { 5128 tx_control = phymodTxSquelchOn; 5129 } else { 5130 tx_control = phymodTxSquelchOff; 5131 } 5132 SOC_IF_ERROR_RETURN 5133 (phymod_phy_tx_lane_control_set(&pm_phy_copy, tx_control)); 5134 5135 } 5136 return(SOC_E_NONE); 5137 } 5138 5139 /* 5140 * phy_82780_tx_lane_squelch_get 5141 */ 5142 STATIC int 5143 phy_82780_tx_lane_squelch_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 5144 { 5145 phymod_phy_access_t *pm_phy; 5146 phymod_phy_tx_lane_control_t tx_control; 5147 int idx; 5148 phymod_phy_access_t pm_phy_copy; 5149 5150 /* loop through all cores */ 5151 for (idx = 0; idx < pmc->num_phys; idx++) { 5152 pm_phy = &pmc->phy[idx]->pm_phy; 5153 5154 if (pm_phy == NULL) { 5155 return SOC_E_INTERNAL; 5156 } 5157 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5158 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5159 if(intf == PHY82780_SYS_SIDE) { 5160 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5161 } 5162 SOC_IF_ERROR_RETURN 5163 (phymod_phy_tx_lane_control_get(&pm_phy_copy, &tx_control)); 5164 if (tx_control == phymodTxSquelchOn) { 5165 *value = 1; 5166 } else { 5167 *value = 0; 5168 } 5169 } 5170 return(SOC_E_NONE); 5171 } 5172 5173 /* 5174 * phy_82780_per_lane_rx_peak_filter_set 5175 */ 5176 STATIC int 5177 phy_82780_per_lane_rx_peak_filter_set(soc_phymod_ctrl_t *pmc, int32 intf, int lane, int enable, uint32 value) 5178 { 5179 soc_phymod_phy_t *p_phy; 5180 uint32 lane_map; 5181 phymod_phy_access_t pm_phy_copy, *pm_phy; 5182 phymod_rx_t phymod_rx; 5183 5184 /* locate the desired phy and lane */ 5185 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 5186 5187 /* Make a copy of the phy access and overwrite the desired lane */ 5188 pm_phy = &p_phy->pm_phy; 5189 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5190 pm_phy_copy.access.lane_mask = lane_map; 5191 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5192 if(intf == PHY82780_SYS_SIDE) { 5193 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5194 } 5195 sal_memset(&phymod_rx, 0, sizeof(phymod_rx)); 5196 phymod_rx.peaking_filter.enable = TRUE; 5197 phymod_rx.peaking_filter.value = value; 5198 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(&pm_phy_copy, &phymod_rx)); 5199 5200 return(SOC_E_NONE); 5201 } 5202 5203 /* 5204 * phy_82780_rx_peak_filter_set 5205 */ 5206 STATIC int 5207 phy_82780_rx_peak_filter_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 5208 { 5209 phymod_phy_access_t *pm_phy; 5210 phymod_rx_t phymod_rx; 5211 int idx; 5212 phymod_phy_access_t pm_phy_copy; 5213 5214 /* loop through all cores */ 5215 for (idx = 0; idx < pmc->num_phys; idx++) { 5216 pm_phy = &pmc->phy[idx]->pm_phy; 5217 5218 if (pm_phy == NULL) { 5219 return SOC_E_INTERNAL; 5220 } 5221 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5222 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5223 if(intf == PHY82780_SYS_SIDE) { 5224 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5225 } 5226 5227 sal_memset(&phymod_rx, 0, sizeof(phymod_rx)); 5228 phymod_rx.peaking_filter.enable = TRUE; 5229 phymod_rx.peaking_filter.value = value; 5230 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(&pm_phy_copy, &phymod_rx)); 5231 } 5232 5233 return(SOC_E_NONE); 5234 } 5235 5236 /* 5237 * phy_82780_per_lane_rx_vga_set 5238 */ 5239 STATIC int 5240 phy_82780_per_lane_rx_vga_set(soc_phymod_ctrl_t *pmc, int32 intf, int lane, int enable, uint32 value) 5241 { 5242 soc_phymod_phy_t *p_phy; 5243 uint32 lane_map; 5244 phymod_phy_access_t pm_phy_copy, *pm_phy; 5245 phymod_rx_t phymod_rx; 5246 5247 /* locate the desired phy and lane */ 5248 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 5249 5250 /* Make a copy of the phy access and overwrite the desired lane */ 5251 pm_phy = &p_phy->pm_phy; 5252 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5253 pm_phy_copy.access.lane_mask = lane_map; 5254 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5255 if(intf == PHY82780_SYS_SIDE) { 5256 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5257 } 5258 5259 sal_memset(&phymod_rx, 0, sizeof(phymod_rx)); 5260 phymod_rx.vga.enable = TRUE; 5261 phymod_rx.vga.value = value; 5262 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(&pm_phy_copy, &phymod_rx)); 5263 5264 return(SOC_E_NONE); 5265 } 5266 5267 /* 5268 * phy_82780_rx_vga_set 5269 */ 5270 STATIC int 5271 phy_82780_rx_vga_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 5272 { 5273 phymod_phy_access_t *pm_phy; 5274 phymod_rx_t phymod_rx; 5275 int idx; 5276 phymod_phy_access_t pm_phy_copy; 5277 5278 /* loop through all cores */ 5279 for (idx = 0; idx < pmc->num_phys; idx++) { 5280 pm_phy = &pmc->phy[idx]->pm_phy; 5281 5282 if (pm_phy == NULL) { 5283 return SOC_E_INTERNAL; 5284 } 5285 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5286 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5287 if(intf == PHY82780_SYS_SIDE) { 5288 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5289 } 5290 5291 sal_memset(&phymod_rx, 0, sizeof(phymod_rx)); 5292 phymod_rx.vga.enable = TRUE; 5293 phymod_rx.vga.value = value; 5294 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(&pm_phy_copy, &phymod_rx)); 5295 } 5296 5297 return(SOC_E_NONE); 5298 } 5299 5300 /* 5301 * phy_82780_rx_tap_set 5302 */ 5303 STATIC int 5304 phy_82780_rx_tap_set(soc_phymod_ctrl_t *pmc, int32 intf, int tap, uint32 value) 5305 { 5306 phymod_phy_access_t *pm_phy; 5307 phymod_rx_t phymod_rx; 5308 int idx; 5309 phymod_phy_access_t pm_phy_copy; 5310 5311 /* bounds check "tap" */ 5312 if (tap < 0 || tap >= COUNTOF(phymod_rx.dfe)) { 5313 return SOC_E_INTERNAL; 5314 } 5315 5316 /* loop through all cores */ 5317 for (idx = 0; idx < pmc->num_phys; idx++) { 5318 pm_phy = &pmc->phy[idx]->pm_phy; 5319 5320 if (pm_phy == NULL) { 5321 return SOC_E_INTERNAL; 5322 } 5323 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5324 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5325 if(intf == PHY82780_SYS_SIDE) { 5326 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5327 } 5328 5329 sal_memset(&phymod_rx, 0, sizeof(phymod_rx)); 5330 phymod_rx.num_of_dfe_taps = 5; 5331 phymod_rx.dfe[tap].enable = TRUE; 5332 phymod_rx.dfe[tap].value = value; 5333 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(&pm_phy_copy, &phymod_rx)); 5334 } 5335 5336 return(SOC_E_NONE); 5337 } 5338 5339 /* 5340 * phy_82780_pi_control_set 5341 */ 5342 STATIC int 5343 phy_82780_pi_control_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 5344 { 5345 phymod_phy_access_t *pm_phy; 5346 phymod_tx_override_t tx_override; 5347 int idx; 5348 phymod_phy_access_t pm_phy_copy; 5349 5350 /* loop through all cores */ 5351 for (idx = 0; idx < pmc->num_phys; idx++) { 5352 pm_phy = &pmc->phy[idx]->pm_phy; 5353 5354 if (pm_phy == NULL) { 5355 return SOC_E_INTERNAL; 5356 } 5357 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5358 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5359 if(intf == PHY82780_SYS_SIDE) { 5360 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5361 } 5362 5363 phymod_tx_override_t_init(&tx_override); 5364 tx_override.phase_interpolator.enable = (value == 0) ? 0 : 1; 5365 tx_override.phase_interpolator.value = value; 5366 SOC_IF_ERROR_RETURN(phymod_phy_tx_override_set(&pm_phy_copy, &tx_override)); 5367 } 5368 5369 return(SOC_E_NONE); 5370 } 5371 5372 STATIC int 5373 phy_82780_per_lane_tx_polarity_set(soc_phymod_ctrl_t *pmc, phymod_polarity_t *cfg_polarity, int32 intf, int lane, uint32 value) 5374 { 5375 phymod_phy_access_t *pm_phy; 5376 phymod_polarity_t polarity; 5377 uint32 lane_map; 5378 phymod_phy_access_t pm_phy_copy; 5379 soc_phymod_phy_t *p_phy; 5380 5381 /* locate the desired phy and lane */ 5382 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 5383 5384 /* Make a copy of the phy access and overwrite the desired lane */ 5385 pm_phy = &p_phy->pm_phy; 5386 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5387 pm_phy_copy.access.lane_mask = lane_map; 5388 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5389 if(intf == PHY82780_SYS_SIDE) { 5390 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5391 } 5392 5393 5394 sal_memcpy(&polarity, cfg_polarity, sizeof(polarity)); 5395 SOC_IF_ERROR_RETURN(phymod_phy_polarity_get(&pm_phy_copy, &polarity)); 5396 polarity.tx_polarity = value; 5397 SOC_IF_ERROR_RETURN(phymod_phy_polarity_set(&pm_phy_copy, &polarity)); 5398 5399 /* after successfully setting the parity, update the configured value */ 5400 cfg_polarity->tx_polarity = value; 5401 5402 return(SOC_E_NONE); 5403 } 5404 /* 5405 * phy_82780_tx_polarity_set 5406 */ 5407 STATIC int 5408 phy_82780_tx_polarity_set(soc_phymod_ctrl_t *pmc, phymod_polarity_t *cfg_polarity, int32 intf, uint32 value) 5409 { 5410 phymod_phy_access_t *pm_phy; 5411 phymod_polarity_t polarity; 5412 int idx; 5413 phymod_phy_access_t pm_phy_copy; 5414 5415 /* loop through all cores */ 5416 for (idx = 0; idx < pmc->num_phys; idx++) { 5417 pm_phy = &pmc->phy[idx]->pm_phy; 5418 5419 if (pm_phy == NULL) { 5420 return SOC_E_INTERNAL; 5421 } 5422 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5423 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5424 if(intf == PHY82780_SYS_SIDE) { 5425 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5426 } 5427 5428 sal_memcpy(&polarity, cfg_polarity, sizeof(polarity)); 5429 SOC_IF_ERROR_RETURN(phymod_phy_polarity_get(&pm_phy_copy, &polarity)); 5430 polarity.tx_polarity = value; 5431 SOC_IF_ERROR_RETURN(phymod_phy_polarity_set(&pm_phy_copy, &polarity)); 5432 5433 /* after successfully setting the parity, update the configured value */ 5434 cfg_polarity->tx_polarity = value; 5435 } 5436 5437 return(SOC_E_NONE); 5438 } 5439 /* 5440 * phy_82780_per_lane_rx_polarity_set 5441 */ 5442 STATIC int 5443 phy_82780_per_lane_rx_polarity_set(soc_phymod_ctrl_t *pmc, phymod_polarity_t *cfg_polarity, int32 intf, int lane, uint32 value) 5444 { 5445 phymod_phy_access_t *pm_phy; 5446 phymod_polarity_t polarity; 5447 uint32 lane_map; 5448 phymod_phy_access_t pm_phy_copy; 5449 soc_phymod_phy_t *p_phy; 5450 5451 /* locate the desired phy and lane */ 5452 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 5453 5454 /* Make a copy of the phy access and overwrite the desired lane */ 5455 pm_phy = &p_phy->pm_phy; 5456 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5457 pm_phy_copy.access.lane_mask = lane_map; 5458 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5459 if(intf == PHY82780_SYS_SIDE) { 5460 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5461 } 5462 5463 sal_memcpy(&polarity, cfg_polarity, sizeof(polarity)); 5464 SOC_IF_ERROR_RETURN(phymod_phy_polarity_get(&pm_phy_copy, &polarity)); 5465 polarity.rx_polarity = value; 5466 SOC_IF_ERROR_RETURN(phymod_phy_polarity_set(&pm_phy_copy, &polarity)); 5467 5468 /* after successfully setting the parity, update the configured value */ 5469 cfg_polarity->rx_polarity = value; 5470 return(SOC_E_NONE); 5471 } 5472 5473 /* 5474 * phy_82780_rx_polarity_set 5475 */ 5476 5477 STATIC int 5478 phy_82780_rx_polarity_set(soc_phymod_ctrl_t *pmc, phymod_polarity_t *cfg_polarity, int32 intf, uint32 value) 5479 { 5480 phymod_phy_access_t *pm_phy; 5481 phymod_polarity_t polarity; 5482 int idx; 5483 phymod_phy_access_t pm_phy_copy; 5484 5485 /* loop through all cores */ 5486 for (idx = 0; idx < pmc->num_phys; idx++) { 5487 pm_phy = &pmc->phy[idx]->pm_phy; 5488 5489 if (pm_phy == NULL) { 5490 return SOC_E_INTERNAL; 5491 } 5492 5493 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5494 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5495 if(intf == PHY82780_SYS_SIDE) { 5496 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5497 } 5498 sal_memcpy(&polarity, cfg_polarity, sizeof(polarity)); 5499 SOC_IF_ERROR_RETURN(phymod_phy_polarity_get(&pm_phy_copy, &polarity)); 5500 polarity.rx_polarity = value; 5501 SOC_IF_ERROR_RETURN(phymod_phy_polarity_set(&pm_phy_copy, &polarity)); 5502 5503 /* after successfully setting the parity, update the configured value */ 5504 cfg_polarity->rx_polarity = value; 5505 } 5506 5507 return(SOC_E_NONE); 5508 } 5509 5510 /* 5511 * phy_82780_rx_reset_set 5512 */ 5513 STATIC int 5514 phy_82780_rx_reset(soc_phymod_ctrl_t *pmc, phymod_phy_reset_t *cfg_reset, int32 intf, uint32 value) 5515 { 5516 phymod_phy_access_t *pm_phy; 5517 phymod_phy_reset_t reset; 5518 int idx; 5519 phymod_phy_access_t pm_phy_copy; 5520 5521 /* loop through all cores */ 5522 for (idx = 0; idx < pmc->num_phys; idx++) { 5523 pm_phy = &pmc->phy[idx]->pm_phy; 5524 5525 if (pm_phy == NULL) { 5526 return SOC_E_INTERNAL; 5527 } 5528 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5529 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5530 if(intf == PHY82780_SYS_SIDE) { 5531 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5532 } 5533 5534 sal_memcpy(&reset, cfg_reset, sizeof(reset)); 5535 reset.rx = (phymod_reset_direction_t) value; 5536 SOC_IF_ERROR_RETURN(phymod_phy_reset_set(&pm_phy_copy, &reset)); 5537 5538 /* after successfully setting the parity, update the configured value */ 5539 cfg_reset->rx = (phymod_reset_direction_t) value; 5540 } 5541 5542 return(SOC_E_NONE); 5543 } 5544 5545 /* 5546 * phy_82780_tx_reset 5547 */ 5548 STATIC int 5549 phy_82780_tx_reset(soc_phymod_ctrl_t *pmc, phymod_phy_reset_t *cfg_reset, int32 intf, uint32 value) 5550 { 5551 phymod_phy_access_t *pm_phy; 5552 phymod_phy_reset_t reset; 5553 int idx; 5554 phymod_phy_access_t pm_phy_copy; 5555 5556 /* loop through all cores */ 5557 for (idx = 0; idx < pmc->num_phys; idx++) { 5558 pm_phy = &pmc->phy[idx]->pm_phy; 5559 5560 if (pm_phy == NULL) { 5561 return SOC_E_INTERNAL; 5562 } 5563 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5564 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5565 if(intf == PHY82780_SYS_SIDE) { 5566 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5567 } 5568 5569 sal_memcpy(&reset, cfg_reset, sizeof(reset)); 5570 reset.tx = (phymod_reset_direction_t) value; 5571 SOC_IF_ERROR_RETURN(phymod_phy_reset_set(&pm_phy_copy, &reset)); 5572 5573 /* after successfully setting the parity, update the configured value */ 5574 cfg_reset->tx = (phymod_reset_direction_t) value; 5575 } 5576 5577 return(SOC_E_NONE); 5578 } 5579 5580 5581 /* 5582 * phy_82780_per_lane_power_set 5583 */ 5584 STATIC int 5585 phy_82780_per_lane_power_set(soc_phymod_ctrl_t *pmc, int32 intf, int lane, uint32 value) 5586 { 5587 phymod_phy_access_t *pm_phy; 5588 phymod_phy_power_t power; 5589 uint32 lane_map; 5590 phymod_phy_access_t pm_phy_copy; 5591 soc_phymod_phy_t *p_phy; 5592 5593 /* locate the desired phy and lane */ 5594 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 5595 5596 /* Make a copy of the phy access and overwrite the desired lane */ 5597 pm_phy = &p_phy->pm_phy; 5598 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5599 pm_phy_copy.access.lane_mask = lane_map; 5600 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5601 if(intf == PHY82780_SYS_SIDE) { 5602 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5603 } 5604 5605 phymod_phy_power_t_init(&power); 5606 if (value) { 5607 power.tx = phymodPowerOn; 5608 power.rx = phymodPowerOn; 5609 } 5610 else { 5611 power.tx = phymodPowerOff; 5612 power.rx = phymodPowerOff; 5613 } 5614 5615 SOC_IF_ERROR_RETURN(phymod_phy_power_set(&pm_phy_copy, &power)); 5616 5617 return(SOC_E_NONE); 5618 } 5619 /* 5620 * phy_82780_power_set 5621 */ 5622 STATIC int 5623 phy_82780_power_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 5624 { 5625 phymod_phy_access_t *pm_phy; 5626 phymod_phy_power_t power; 5627 int idx; 5628 phymod_phy_access_t pm_phy_copy; 5629 5630 /* loop through all cores */ 5631 for (idx = 0; idx < pmc->num_phys; idx++) { 5632 pm_phy = &pmc->phy[idx]->pm_phy; 5633 5634 if (pm_phy == NULL) { 5635 return SOC_E_INTERNAL; 5636 } 5637 5638 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5639 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5640 if(intf == PHY82780_SYS_SIDE) { 5641 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5642 } 5643 5644 phymod_phy_power_t_init(&power); 5645 if (value) { 5646 power.tx = phymodPowerOn; 5647 power.rx = phymodPowerOn; 5648 } 5649 else { 5650 power.tx = phymodPowerOff; 5651 power.rx = phymodPowerOff; 5652 } 5653 5654 SOC_IF_ERROR_RETURN(phymod_phy_power_set(&pm_phy_copy, &power)); 5655 } 5656 5657 return(SOC_E_NONE); 5658 } 5659 5660 5661 /* 5662 * phy_82780_rx_low_freq_filter_set 5663 */ 5664 STATIC int 5665 phy_82780_rx_low_freq_filter_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 5666 { 5667 phymod_phy_access_t *pm_phy; 5668 phymod_rx_t phymod_rx; 5669 int idx; 5670 phymod_phy_access_t pm_phy_copy; 5671 5672 /* loop through all cores */ 5673 for (idx = 0; idx < pmc->num_phys; idx++) { 5674 pm_phy = &pmc->phy[idx]->pm_phy; 5675 5676 if (pm_phy == NULL) { 5677 return SOC_E_INTERNAL; 5678 } 5679 5680 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5681 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5682 if(intf == PHY82780_SYS_SIDE) { 5683 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5684 } 5685 5686 sal_memset(&phymod_rx, 0, sizeof(phymod_rx)); 5687 phymod_rx.low_freq_peaking_filter.enable = TRUE; 5688 phymod_rx.low_freq_peaking_filter.value = value; 5689 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(&pm_phy_copy, &phymod_rx)); 5690 } 5691 5692 return(SOC_E_NONE); 5693 } 5694 5695 STATIC int 5696 phy_82780_rx_seq_restart(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 5697 { 5698 phymod_sequencer_operation_t seq_operation; 5699 int idx; 5700 soc_phymod_core_t *pmc_core; 5701 phymod_core_access_t *pm_core; 5702 phymod_core_access_t pm_core_copy; 5703 uint32_t flags = 0; 5704 5705 /* loop through all cores */ 5706 for (idx = 0; idx < pmc->num_phys; idx++) { 5707 pmc_core = pmc->phy[idx]->core; 5708 pm_core = &pmc_core->pm_core; 5709 if (pm_core == NULL) { 5710 return SOC_E_INTERNAL; 5711 } 5712 5713 sal_memcpy(&pm_core_copy, pm_core, sizeof(pm_core_copy)); 5714 PHY82780_CLEAR_SYS_SIDE(pm_core_copy); 5715 if(intf == PHY82780_SYS_SIDE) { 5716 PHY82780_SET_SYS_SIDE(pm_core_copy); 5717 } 5718 seq_operation = phymodSeqOpRestart; 5719 SOC_IF_ERROR_RETURN(phymod_core_pll_sequencer_restart(pm_core, flags, seq_operation)); 5720 } 5721 return(SOC_E_NONE); 5722 } 5723 5724 STATIC int 5725 phy_82780_phy_dump(soc_phymod_ctrl_t *pmc, int32 intf) 5726 { 5727 phymod_phy_access_t *pm_phy; 5728 int idx; 5729 phymod_phy_access_t pm_phy_copy; 5730 5731 /* loop through all cores */ 5732 for (idx = 0; idx < pmc->num_phys; idx++) { 5733 pm_phy = &pmc->phy[idx]->pm_phy; 5734 5735 if (pm_phy == NULL) { 5736 return SOC_E_INTERNAL; 5737 } 5738 5739 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5740 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5741 if(intf == PHY82780_SYS_SIDE) { 5742 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5743 } 5744 SOC_IF_ERROR_RETURN(phymod_phy_status_dump(&pm_phy_copy)); 5745 5746 } 5747 5748 return(SOC_E_NONE); 5749 } 5750 STATIC int 5751 phy_82780_per_lane_phy_dump(soc_phymod_ctrl_t *pmc, int32 intf, int lane) 5752 { 5753 phymod_phy_access_t *pm_phy; 5754 uint32 lane_map; 5755 phymod_phy_access_t pm_phy_copy; 5756 soc_phymod_phy_t *p_phy; 5757 5758 /* locate the desired phy and lane */ 5759 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 5760 5761 /* Make a copy of the phy access and overwrite the desired lane */ 5762 pm_phy = &p_phy->pm_phy; 5763 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5764 pm_phy_copy.access.lane_mask = lane_map; 5765 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 5766 if(intf == PHY82780_SYS_SIDE) { 5767 PHY82780_SET_SYS_SIDE(pm_phy_copy); 5768 } 5769 5770 SOC_IF_ERROR_RETURN(phymod_phy_status_dump(&pm_phy_copy)); 5771 return(SOC_E_NONE); 5772 } 5773 /* 5774 * phy_82780_gpio_config_set 5775 */ 5776 STATIC int 5777 phy_82780_gpio_config_set(soc_phymod_ctrl_t *pmc, uint32 value) 5778 { 5779 phymod_phy_access_t *pm_phy; 5780 int idx; 5781 phymod_phy_access_t pm_phy_copy; 5782 int gpio_mode = 0; 5783 int gpio_pin_no = 0; 5784 5785 /* loop through all cores */ 5786 for (idx = 0; idx < pmc->num_phys; idx++) { 5787 pm_phy = &pmc->phy[idx]->pm_phy; 5788 5789 if (pm_phy == NULL) { 5790 return SOC_E_INTERNAL; 5791 } 5792 5793 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5794 5795 for (gpio_pin_no = 0; gpio_pin_no < 6; gpio_pin_no++) { 5796 gpio_mode = (value >> (4 * gpio_pin_no)) & 0xF; 5797 SOC_IF_ERROR_RETURN(phymod_phy_gpio_config_set(&pm_phy_copy, gpio_pin_no, (phymod_gpio_mode_t)gpio_mode)); 5798 } 5799 } 5800 5801 return(SOC_E_NONE); 5802 } 5803 /* 5804 * phy_82780_gpio_value_set 5805 */ 5806 STATIC int 5807 phy_82780_gpio_value_set(soc_phymod_ctrl_t *pmc, uint32 value) 5808 { 5809 phymod_phy_access_t *pm_phy; 5810 int idx; 5811 phymod_phy_access_t pm_phy_copy; 5812 int pin_value = 0; 5813 int gpio_pin_no = 0; 5814 5815 /* loop through all cores */ 5816 for (idx = 0; idx < pmc->num_phys; idx++) { 5817 pm_phy = &pmc->phy[idx]->pm_phy; 5818 5819 if (pm_phy == NULL) { 5820 return SOC_E_INTERNAL; 5821 } 5822 5823 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5824 5825 for (gpio_pin_no = 0; gpio_pin_no < 6; gpio_pin_no++) { 5826 pin_value = (value >> (4 * gpio_pin_no)) & 0xF; 5827 SOC_IF_ERROR_RETURN(phymod_phy_gpio_pin_value_set(&pm_phy_copy, gpio_pin_no, pin_value)); 5828 } 5829 } 5830 5831 return(SOC_E_NONE); 5832 } 5833 /* 5834 * Function: 5835 * phy_82780_control_set 5836 * Purpose: 5837 * Configure PHY device specific control fucntion. 5838 * Parameters: 5839 * unit - BCM unit number. 5840 * port - Port number. 5841 * type - Control to update 5842 * value - New setting for the control 5843 * Returns: 5844 * SOC_E_NONE 5845 */ 5846 STATIC int 5847 phy_82780_control_set(int unit, soc_port_t port, soc_phy_control_t type, uint32 value) 5848 { 5849 int rv; 5850 phy_ctrl_t *pc; 5851 soc_phymod_ctrl_t *pmc; 5852 phy82780_config_t *pCfg; 5853 int32 intf; 5854 5855 rv = SOC_E_UNAVAIL; 5856 5857 PHY_CONTROL_TYPE_CHECK(type); 5858 5859 /* locate phy control, phymod control, and the configuration data */ 5860 pc = EXT_PHY_SW_STATE(unit, port); 5861 if (pc == NULL) { 5862 return SOC_E_INTERNAL; 5863 } 5864 pmc = &pc->phymod_ctrl; 5865 pCfg = (phy82780_config_t *) pc->driver_data; 5866 5867 5868 intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY82780_SYS_SIDE : PHY82780_LINE_SIDE; 5869 5870 switch(type) { 5871 /* decoupled PRBS */ 5872 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_POLYNOMIAL: 5873 rv = phy_82780_prbs_tx_poly_set(pmc, intf, value); 5874 break; 5875 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_INVERT_DATA: 5876 rv = phy_82780_prbs_tx_invert_data_set(pmc, intf, value); 5877 break; 5878 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_ENABLE: 5879 rv = phy_82780_prbs_tx_enable_set(pmc, intf, value); 5880 break; 5881 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_POLYNOMIAL: 5882 rv = phy_82780_prbs_rx_poly_set(pmc, intf, value); 5883 break; 5884 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_INVERT_DATA: 5885 rv = phy_82780_prbs_rx_invert_data_set(pmc, intf, value); 5886 break; 5887 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_ENABLE: 5888 rv = phy_82780_prbs_rx_enable_set(pmc, intf, value); 5889 break; 5890 /* for legacy prbs usage mainly set both tx/rx the same */ 5891 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 5892 rv = phy_82780_prbs_tx_poly_set(pmc, intf, value); 5893 if (!rv) { 5894 rv = phy_82780_prbs_rx_poly_set(pmc, intf, value); 5895 } 5896 break; 5897 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 5898 rv = phy_82780_prbs_tx_invert_data_set(pmc, intf, value); 5899 break; 5900 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 5901 rv = phy_82780_prbs_tx_enable_set(pmc, intf, value); 5902 if (!rv) { 5903 rv = phy_82780_prbs_rx_enable_set(pmc, intf, value); 5904 } 5905 break; 5906 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 5907 rv = phy_82780_prbs_tx_enable_set(pmc, intf, value); 5908 if (!rv) { 5909 rv = phy_82780_prbs_rx_enable_set(pmc, intf, value); 5910 } 5911 break; 5912 /* LOOPBACK */ 5913 case SOC_PHY_CONTROL_LOOPBACK_PMD: 5914 rv = phy_82780_loopback_internal_pmd_set(pmc, intf, value); 5915 break; 5916 case SOC_PHY_CONTROL_LOOPBACK_REMOTE: 5917 rv = phy_82780_loopback_remote_set(pmc, intf, value); 5918 break; 5919 case SOC_PHY_CONTROL_TX_FIR_PRE: 5920 rv = phy_82780_tx_fir_pre_set(pmc, intf, value); 5921 break; 5922 case SOC_PHY_CONTROL_TX_FIR_MAIN: 5923 rv = phy_82780_tx_fir_main_set(pmc, intf, value); 5924 break; 5925 case SOC_PHY_CONTROL_TX_FIR_POST: 5926 rv = phy_82780_tx_fir_post_set(pmc, intf, value); 5927 break; 5928 case SOC_PHY_CONTROL_TX_FIR_POST2: 5929 rv = phy_82780_tx_fir_post2_set(pmc, intf, value); 5930 break; 5931 /* PREEMPHASIS */ 5932 case SOC_PHY_CONTROL_PREEMPHASIS_LANE0: 5933 rv = phy_82780_per_lane_preemphasis_set(pmc, intf, 0, value); 5934 break; 5935 case SOC_PHY_CONTROL_PREEMPHASIS_LANE1: 5936 rv = phy_82780_per_lane_preemphasis_set(pmc, intf, 1, value); 5937 break; 5938 case SOC_PHY_CONTROL_PREEMPHASIS_LANE2: 5939 rv = phy_82780_per_lane_preemphasis_set(pmc, intf, 2, value); 5940 break; 5941 case SOC_PHY_CONTROL_PREEMPHASIS_LANE3: 5942 rv = phy_82780_per_lane_preemphasis_set(pmc, intf, 3, value); 5943 break; 5944 case SOC_PHY_CONTROL_PREEMPHASIS: 5945 rv = phy_82780_preemphasis_set(pmc, intf, value); 5946 break; 5947 case SOC_PHY_CONTROL_PORT_PRIMARY: 5948 rv = soc_phyctrl_primary_set(unit, port, (soc_port_t)value); 5949 break; 5950 case SOC_PHY_CONTROL_PORT_OFFSET: 5951 rv = soc_phyctrl_offset_set(unit, port, (int)value); 5952 break; 5953 5954 /* DRIVER CURRENT */ 5955 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0: 5956 rv = phy_82780_per_lane_driver_current_set(pmc, intf, 0, value); 5957 break; 5958 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1: 5959 rv = phy_82780_per_lane_driver_current_set(pmc, intf, 1, value); 5960 break; 5961 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2: 5962 rv = phy_82780_per_lane_driver_current_set(pmc, intf, 2, value); 5963 break; 5964 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3: 5965 rv = phy_82780_per_lane_driver_current_set(pmc, intf, 3, value); 5966 break; 5967 case SOC_PHY_CONTROL_DRIVER_CURRENT: 5968 rv = phy_82780_driver_current_set(pmc, intf, value); 5969 break; 5970 /* TX LANE SQUELCH */ 5971 case SOC_PHY_CONTROL_TX_LANE_SQUELCH: 5972 rv = phy_82780_tx_lane_squelch(pmc, intf, value); 5973 break; 5974 /* RX PEAK FILTER */ 5975 case SOC_PHY_CONTROL_RX_PEAK_FILTER: 5976 rv = phy_82780_rx_peak_filter_set(pmc, intf, value); 5977 break; 5978 5979 /* RX VGA */ 5980 case SOC_PHY_CONTROL_RX_VGA: 5981 rv = phy_82780_rx_vga_set(pmc, intf, value); 5982 break; 5983 /* RX TAP */ 5984 case SOC_PHY_CONTROL_RX_TAP1: 5985 rv = phy_82780_rx_tap_set(pmc, intf, 0, value); 5986 break; 5987 case SOC_PHY_CONTROL_RX_TAP2: 5988 rv = phy_82780_rx_tap_set(pmc, intf, 1, value); 5989 break; 5990 case SOC_PHY_CONTROL_RX_TAP3: 5991 rv = phy_82780_rx_tap_set(pmc, intf, 2, value); 5992 break; 5993 case SOC_PHY_CONTROL_RX_TAP4: 5994 rv = phy_82780_rx_tap_set(pmc, intf, 3, value); 5995 break; 5996 case SOC_PHY_CONTROL_RX_TAP5: 5997 rv = phy_82780_rx_tap_set(pmc, intf, 4, value); 5998 break; 5999 /* PHASE INTERPOLATOR */ 6000 case SOC_PHY_CONTROL_PHASE_INTERP: 6001 rv = phy_82780_pi_control_set(pmc, intf, value); 6002 break; 6003 /* POLARITY */ 6004 case SOC_PHY_CONTROL_RX_POLARITY: 6005 rv = phy_82780_rx_polarity_set(pmc, &pCfg->phy_polarity_config, intf, value);; 6006 break; 6007 case SOC_PHY_CONTROL_TX_POLARITY: 6008 rv = phy_82780_tx_polarity_set(pmc, &pCfg->phy_polarity_config, intf, value); 6009 break; 6010 /* RESET */ 6011 case SOC_PHY_CONTROL_RX_RESET: 6012 rv = phy_82780_rx_reset(pmc, &pCfg->phy_reset_config, intf, value); 6013 break; 6014 case SOC_PHY_CONTROL_TX_RESET: 6015 rv = phy_82780_tx_reset(pmc, &pCfg->phy_reset_config, intf, value); 6016 break; 6017 /* POWER */ 6018 case SOC_PHY_CONTROL_POWER: 6019 { 6020 phy_ctrl_t *int_pc; 6021 int_pc = INT_PHY_SW_STATE(unit, port); 6022 SOC_IF_ERROR_RETURN(PHY_ENABLE_SET(int_pc->pd, unit, port, value)); 6023 rv = phy_82780_power_set(pmc, intf, value); 6024 } 6025 break; 6026 case SOC_PHY_CONTROL_RX_LOW_FREQ_PEAK_FILTER: 6027 rv = phy_82780_rx_low_freq_filter_set(pmc, intf, value); 6028 break; 6029 case SOC_PHY_CONTROL_FORWARD_ERROR_CORRECTION: 6030 rv = phy_82780_fec_enable_set(pmc, value); 6031 break; 6032 case SOC_PHY_CONTROL_RX_SEQ_TOGGLE: 6033 rv = phy_82780_rx_seq_restart(pmc, intf, value); 6034 break; 6035 case SOC_PHY_CONTROL_DUMP: 6036 rv = phy_82780_phy_dump(pmc, intf); 6037 break; 6038 case SOC_PHY_CONTROL_CL72: 6039 rv = phy_82780_cl72_enable_set(pmc, intf, value); 6040 break; 6041 case SOC_PHY_CONTROL_GPIO_CONFIG: 6042 rv = phy_82780_gpio_config_set(pmc, value); 6043 break; 6044 case SOC_PHY_CONTROL_GPIO_VALUE: 6045 rv = phy_82780_gpio_value_set(pmc, value); 6046 break; 6047 case SOC_PHY_CONTROL_RX_VGA_RELEASE: 6048 case SOC_PHY_CONTROL_RX_TAP1_RELEASE: 6049 case SOC_PHY_CONTROL_RX_TAP2_RELEASE: 6050 case SOC_PHY_CONTROL_RX_TAP3_RELEASE: 6051 case SOC_PHY_CONTROL_RX_TAP4_RELEASE: 6052 case SOC_PHY_CONTROL_RX_TAP5_RELEASE: 6053 rv = phy_82780_adoptation_release(pc, intf); 6054 break; 6055 case SOC_PHY_CONTROL_FAIL_OVER_MODE: 6056 rv = phy_82780_config_fail_over(pc, intf, value); 6057 break; 6058 6059 default: 6060 rv = SOC_E_UNAVAIL; 6061 break; 6062 } 6063 return rv; 6064 } 6065 6066 /* 6067 * Function: 6068 * phy_82780_per_lane_control_set 6069 * Purpose: 6070 * Configure PHY device specific control fucntion. 6071 * Parameters: 6072 * unit - StrataSwitch unit #. 6073 * port - StrataSwitch port #. 6074 * lane - lane number 6075 * type - Control to update 6076 * value - New setting for the control 6077 * Returns: 6078 * SOC_E_NONE 6079 */ 6080 STATIC int 6081 phy_82780_per_lane_control_set(int unit, soc_port_t port, int lane, soc_phy_control_t type, uint32 value) 6082 { 6083 int rv = SOC_E_UNAVAIL; 6084 phy_ctrl_t *pc; 6085 soc_phymod_ctrl_t *pmc; 6086 phy82780_config_t *pCfg; 6087 int32 intf; 6088 6089 /* locate phy control, phymod control, and the configuration data */ 6090 pc = EXT_PHY_SW_STATE(unit, port); 6091 if (pc == NULL) { 6092 return SOC_E_INTERNAL; 6093 } 6094 pmc = &pc->phymod_ctrl; 6095 pCfg = (phy82780_config_t *) pc->driver_data; 6096 6097 PHY_CONTROL_TYPE_CHECK(type); 6098 6099 intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY82780_SYS_SIDE : PHY82780_LINE_SIDE; 6100 6101 switch(type) { 6102 case SOC_PHY_CONTROL_PREEMPHASIS: 6103 rv = phy_82780_per_lane_preemphasis_set(pmc, intf, lane, value); 6104 break; 6105 case SOC_PHY_CONTROL_DRIVER_CURRENT: 6106 rv = phy_82780_per_lane_driver_current_set(pmc, intf, lane, value); 6107 break; 6108 case SOC_PHY_CONTROL_RX_TAP1: 6109 rv = phy_82780_per_lane_rx_dfe_tap_control_set (pmc, intf, lane, 0 /* tap */, 1 /* enable */, value); 6110 break; 6111 case SOC_PHY_CONTROL_RX_TAP2: 6112 rv = phy_82780_per_lane_rx_dfe_tap_control_set (pmc, intf, lane, 1 /* tap */, 1 /* enable */, value); 6113 break; 6114 case SOC_PHY_CONTROL_RX_TAP3: 6115 rv = phy_82780_per_lane_rx_dfe_tap_control_set (pmc, intf, lane, 2 /* tap */, 1 /* enable */, value); 6116 break; 6117 case SOC_PHY_CONTROL_RX_TAP4: 6118 rv = phy_82780_per_lane_rx_dfe_tap_control_set (pmc, intf, lane, 3 /* tap */, 1 /* enable */, value); 6119 break; 6120 case SOC_PHY_CONTROL_RX_TAP5: 6121 rv = phy_82780_per_lane_rx_dfe_tap_control_set (pmc, intf, lane, 4 /* tap */, 1 /* enable */, value); 6122 break; 6123 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_POLYNOMIAL: 6124 rv = phy_82780_per_lane_prbs_tx_poly_set(pmc, intf, lane, value); 6125 break; 6126 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_INVERT_DATA: 6127 rv = phy_82780_per_lane_prbs_tx_invert_data_set(pmc, intf, lane, value); 6128 break; 6129 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_ENABLE: 6130 rv = phy_82780_per_lane_prbs_tx_enable_set(pmc, intf, lane, value); 6131 break; 6132 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_POLYNOMIAL: 6133 rv = phy_82780_per_lane_prbs_rx_poly_set(pmc, intf, lane, value); 6134 break; 6135 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_INVERT_DATA: 6136 rv = phy_82780_per_lane_prbs_rx_invert_data_set(pmc, intf, lane, value); 6137 break; 6138 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_ENABLE: 6139 rv = phy_82780_per_lane_prbs_rx_enable_set(pmc, intf, lane, value); 6140 break; 6141 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 6142 rv = phy_82780_per_lane_prbs_tx_poly_set(pmc, intf, lane, value); 6143 if (rv == SOC_E_NONE) { 6144 rv = phy_82780_per_lane_prbs_rx_poly_set(pmc, intf, lane, value); 6145 } 6146 break; 6147 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 6148 rv = phy_82780_per_lane_prbs_tx_invert_data_set(pmc, intf, lane, value); 6149 break; 6150 case SOC_PHY_CONTROL_PRBS_RX_INVERT_DATA: 6151 rv = phy_82780_per_lane_prbs_rx_invert_data_set(pmc, intf, lane, value); 6152 break; 6153 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 6154 /* TX_ENABLE does both tx and rx */ 6155 rv = phy_82780_per_lane_prbs_tx_enable_set(pmc, intf, lane, value); 6156 if (rv == SOC_E_NONE) { 6157 rv = phy_82780_per_lane_prbs_rx_enable_set(pmc, intf, lane, value); 6158 } 6159 break; 6160 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 6161 rv = phy_82780_per_lane_prbs_tx_enable_set(pmc, intf, lane, value); 6162 if (rv == SOC_E_NONE) { 6163 rv = phy_82780_per_lane_prbs_rx_enable_set(pmc, intf, lane, value); 6164 } 6165 break; 6166 case SOC_PHY_CONTROL_RX_PEAK_FILTER: 6167 rv = phy_82780_per_lane_rx_peak_filter_set(pmc, intf, lane, 1 /* enable */, value); 6168 break; 6169 case SOC_PHY_CONTROL_RX_LOW_FREQ_PEAK_FILTER: 6170 rv = phy_82780_per_lane_rx_low_freq_filter_set(pmc, intf, lane, value); 6171 break; 6172 case SOC_PHY_CONTROL_RX_VGA: 6173 rv = phy_82780_per_lane_rx_vga_set(pmc, intf, lane, 1 /* enable */, value); 6174 break; 6175 /* TX LANE SQUELCH */ 6176 case SOC_PHY_CONTROL_TX_LANE_SQUELCH: 6177 rv = phy_82780_per_lane_tx_lane_squelch(pmc, intf, lane, value); 6178 break; 6179 /* POWER */ 6180 case SOC_PHY_CONTROL_POWER: 6181 rv = phy_82780_per_lane_power_set(pmc, intf, lane, value); 6182 break; 6183 /* POLARITY */ 6184 case SOC_PHY_CONTROL_RX_POLARITY: 6185 rv = phy_82780_per_lane_rx_polarity_set(pmc, &pCfg->phy_polarity_config, intf, lane, value);; 6186 break; 6187 case SOC_PHY_CONTROL_TX_POLARITY: 6188 rv = phy_82780_per_lane_tx_polarity_set(pmc, &pCfg->phy_polarity_config, 6189 intf, lane, value); 6190 break; 6191 /* LOOPBACK */ 6192 case SOC_PHY_CONTROL_LOOPBACK_PMD: 6193 rv = phy_82780_per_lane_loopback_internal_pmd_set(pmc, intf, lane, value); 6194 break; 6195 case SOC_PHY_CONTROL_LOOPBACK_REMOTE: 6196 rv = phy_82780_per_lane_loopback_remote_set(pmc, intf, lane, value); 6197 break; 6198 case SOC_PHY_CONTROL_DUMP: 6199 rv = phy_82780_per_lane_phy_dump(pmc, intf, lane); 6200 break; 6201 case SOC_PHY_CONTROL_TX_FIR_PRE: 6202 case SOC_PHY_CONTROL_TX_FIR_MAIN: 6203 case SOC_PHY_CONTROL_TX_FIR_POST: 6204 case SOC_PHY_CONTROL_TX_FIR_POST2: 6205 rv = phy_82780_per_lane_tx_set(pmc, intf, type, lane, value); 6206 break; 6207 default: 6208 rv = SOC_E_UNAVAIL; 6209 break; 6210 } 6211 6212 return rv; 6213 } 6214 6215 STATIC int phy_82780_diag_eyescan(soc_port_t port, soc_phymod_ctrl_t *pmc, int32 intf, int32 lane) 6216 { 6217 phymod_phy_access_t *pm_phy; 6218 int idx = 0, rv = 0; 6219 phymod_phy_access_t pm_phy_copy; 6220 soc_phymod_phy_t *p_phy; 6221 uint32_t lane_map = 0; 6222 6223 for (idx = 0; idx < pmc->num_phys; idx++) { 6224 if (pmc->phy[idx] == NULL) { 6225 return SOC_E_INTERNAL; 6226 } 6227 p_phy = pmc->phy[idx]; 6228 6229 /* Make a copy of the phy access and overwrite the desired lane */ 6230 pm_phy = &p_phy->pm_phy; 6231 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6232 6233 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 6234 if(intf == PHY_DIAG_INTF_SYS) { 6235 PHY82780_SET_SYS_SIDE(pm_phy_copy); 6236 } 6237 if (lane == 0xf) { 6238 /* Get p_phy alone and let lane map be as Phy structure value */ 6239 lane = 1; 6240 SOC_IF_ERROR_RETURN( 6241 _phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 6242 lane = 0xf; 6243 } else { 6244 SOC_IF_ERROR_RETURN( 6245 _phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 6246 } 6247 6248 /* Make a copy of the phy access and overwrite the desired lane */ 6249 if (lane != 0xf) { 6250 pm_phy_copy.access.lane_mask = lane_map; 6251 } 6252 6253 rv = phymod_phy_eyescan_run(&pm_phy_copy, PHYMOD_EYESCAN_F_DONE, 0, NULL); 6254 if (rv != SOC_E_NONE) { 6255 return rv; 6256 } 6257 } 6258 return SOC_E_NONE; 6259 } 6260 STATIC int 6261 phy_82780_diag_dsc(soc_phymod_ctrl_t *pmc, int32 intf) 6262 { 6263 phymod_phy_access_t *pm_phy; 6264 int idx; 6265 phymod_phy_access_t pm_phy_copy; 6266 soc_phymod_phy_t *p_phy; 6267 phymod_phy_diagnostics_t phy_diag; 6268 uint16_t lane_index = 0; 6269 6270 6271 for (idx = 0; idx < pmc->num_phys; idx++) { 6272 if (pmc->phy[idx] == NULL) { 6273 return SOC_E_INTERNAL; 6274 } 6275 p_phy = pmc->phy[idx]; 6276 /* Make a copy of the phy access and overwrite the desired lane */ 6277 pm_phy = &p_phy->pm_phy; 6278 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6279 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 6280 if(intf == PHY_DIAG_INTF_SYS) { 6281 PHY82780_SET_SYS_SIDE(pm_phy_copy); 6282 } 6283 LOG_CLI((BSL_META_U(pmc->unit, 6284 "DSC parameters for port %d\n"), p_phy->core->port)); 6285 for (lane_index = 0; lane_index < 4; lane_index ++) { 6286 if ((pm_phy->access.lane_mask & (1 << lane_index))) { 6287 pm_phy_copy.access.lane_mask = (1 << lane_index); 6288 SOC_IF_ERROR_RETURN(phymod_phy_diagnostics_get(&pm_phy_copy, &phy_diag)); 6289 6290 /* display */ 6291 LOG_CLI((BSL_META_U(pmc->unit, 6292 "LaneN SIGDET VGABIASREDUCED POSTCMET OSR PMDMODE " 6293 "RXLOCK RXPPM TXPPM CLK90OFFSET CLKP1OFFSET P1LVL1 " 6294 "M1LVL1 DFE1_DCD DFE2_DCD SLICERTARGET PE ZE ME " 6295 "PO ZO MO HLFT HRGT VUPPR VLOWR SMSTS LNKTM " 6296 "MAIN HIZ BST\n"))); 6297 LOG_CLI((BSL_META_U(pmc->unit, 6298 "%05d %03d %06d %07d %03d %05d %05d %05d %06d %05d %08d " 6299 " %03d %05d %04d %04d %04d %02d %02d %02d %02d %02d %02d" 6300 " %03d %04d %05d %05d %04d %05d %04d %03d %03d \n"), 6301 (lane_index+1), phy_diag.signal_detect, phy_diag.vga_bias_reduced, 6302 phy_diag.postc_metric, phy_diag.osr_mode, phy_diag.pmd_mode, 6303 phy_diag.rx_lock, phy_diag.rx_ppm, phy_diag.tx_ppm, 6304 phy_diag.clk90_offset, phy_diag.clkp1_offset, 6305 phy_diag.p1_lvl, phy_diag.m1_lvl, phy_diag.dfe1_dcd, 6306 phy_diag.dfe2_dcd, phy_diag.slicer_target, 6307 phy_diag.slicer_offset.offset_pe, phy_diag.slicer_offset.offset_ze, 6308 phy_diag.slicer_offset.offset_me, phy_diag.slicer_offset.offset_po, 6309 phy_diag.slicer_offset.offset_zo, phy_diag.slicer_offset.offset_mo, 6310 phy_diag.eyescan.heye_left, phy_diag.eyescan.heye_right, 6311 phy_diag.eyescan.veye_upper, phy_diag.eyescan.veye_lower, 6312 phy_diag.state_machine_status, phy_diag.link_time, 6313 phy_diag.pf_main, phy_diag.pf_hiz, 6314 phy_diag.pf_bst)); 6315 LOG_CLI((BSL_META_U(pmc->unit, 6316 "LOW PF2CTRL VGA DCOFFT P1LVLCTRL " 6317 "DFE1 DFE2 DFE3 DFE4 DFE5 DFE6 PRE MAIN POST1 " 6318 "POST2 POST3 TXAMPCTRL BRPDEN \n"))); 6319 6320 LOG_CLI((BSL_META_U(pmc->unit, 6321 "%03d %07d %03d %06d %04d %04d %04d %04d %04d %04d %04d %04d" 6322 " %03d %04d %05d %05d %04d %04d\n\n"), 6323 phy_diag.pf_low, 6324 phy_diag.pf2_ctrl, phy_diag.vga, 6325 phy_diag.dc_offset, phy_diag.p1_lvl_ctrl, 6326 phy_diag.dfe1, phy_diag.dfe2, 6327 phy_diag.dfe3, phy_diag.dfe4, 6328 phy_diag.dfe5, phy_diag.dfe6, 6329 phy_diag.txfir_pre, phy_diag.txfir_main, 6330 phy_diag.txfir_post1, phy_diag.txfir_post2, 6331 phy_diag.txfir_post3, phy_diag.tx_amp_ctrl, 6332 phy_diag.br_pd_en)); 6333 } 6334 } 6335 } 6336 return SOC_E_NONE; 6337 } 6338 /* 6339 * Function: 6340 * phy_82780_diag_ctrl 6341 * Purpose: 6342 * xx 6343 * Parameters: 6344 * unit - BCM unit number. 6345 * port - Port number. 6346 6347 * Returns: 6348 * SOC_E_NONE 6349 */ 6350 6351 STATIC int 6352 phy_82780_diag_ctrl( 6353 int unit, /* unit */ 6354 soc_port_t port, /* port */ 6355 uint32 inst, /* the specific device block the control action directs to */ 6356 int op_type, /* operation types: read,write or command sequence */ 6357 int op_cmd, /* command code */ 6358 void *arg) /* command argument based on op_type/op_cmd */ 6359 { 6360 int rv = -1; 6361 int32 lane; 6362 int32 intf; 6363 soc_phymod_ctrl_t *pmc; 6364 phy_ctrl_t *pc; 6365 /* locate phy control, phymod control, and the configuration data */ 6366 pc = EXT_PHY_SW_STATE(unit, port); 6367 if (pc == NULL) { 6368 return SOC_E_INTERNAL; 6369 } 6370 pmc = &pc->phymod_ctrl; 6371 6372 lane = PHY_DIAG_INST_LN(inst); 6373 intf = PHY_DIAG_INST_INTF(inst); 6374 if (intf == PHY_DIAG_INTF_DFLT) { 6375 intf = PHY_DIAG_INTF_LINE; 6376 } 6377 if (intf == PHY_DIAG_INTF_SYS) { 6378 pc->flags |= PHYCTRL_SYS_SIDE_CTRL; 6379 } else { 6380 pc->flags &= ~PHYCTRL_SYS_SIDE_CTRL; 6381 } 6382 switch(op_cmd) { 6383 case PHY_DIAG_CTRL_DSC: 6384 rv = phy_82780_diag_dsc(pmc, intf); 6385 break; 6386 case PHY_DIAG_CTRL_START_FAST_EYESCAN: 6387 rv = phy_82780_diag_eyescan(port, pmc, intf, lane); 6388 break; 6389 case PHY_DIAG_CTRL_LINKMON_MODE: 6390 { 6391 uint32_t value = PTR_TO_INT(arg); 6392 rv = phy_82780_link_monitor_set(pmc, intf, lane, value); 6393 } 6394 break; 6395 case PHY_DIAG_CTRL_LINKMON_STATUS: 6396 { 6397 rv = phy_82780_link_monitor_status_get(pmc, intf, lane); 6398 } 6399 break; 6400 6401 default: 6402 if (op_type == PHY_DIAG_CTRL_SET) { 6403 rv = phy_82780_control_set(unit,port,op_cmd,PTR_TO_INT(arg)); 6404 } else if (op_type == PHY_DIAG_CTRL_GET) { 6405 rv = phy_82780_control_get(unit,port,op_cmd,(uint32 *)arg); 6406 } 6407 break ; 6408 } 6409 6410 /* clear the pc->flags to make default as PHY_DIAG_INTF_LINE */ 6411 pc->flags &= ~PHYCTRL_SYS_SIDE_CTRL; 6412 6413 return rv; 6414 } 6415 6416 int32 phy_82780_core_reset(int32 unit, soc_port_t port, void *not_used) 6417 { 6418 phy_ctrl_t *pc; 6419 soc_phymod_core_t *pmc_core; 6420 int idx; 6421 phymod_core_access_t *pm_core; 6422 soc_phymod_ctrl_t *pmc; 6423 phymod_reset_direction_t reset_direction; 6424 /* locate phy control */ 6425 pc = EXT_PHY_SW_STATE(unit, port); 6426 if (pc == NULL) { 6427 return SOC_E_INTERNAL; 6428 } 6429 reset_direction = phymodResetDirectionInOut; 6430 pmc = &pc->phymod_ctrl; 6431 6432 /* loop through all cores */ 6433 for (idx = 0; idx < pmc->num_phys; idx++) { 6434 pmc_core = pmc->phy[idx]->core; 6435 pm_core = &pmc_core->pm_core; 6436 if (pm_core == NULL) { 6437 return SOC_E_INTERNAL; 6438 } 6439 6440 SOC_IF_ERROR_RETURN(phymod_core_reset_set(pm_core, phymodResetModeSoft, reset_direction)); 6441 } 6442 return(SOC_E_NONE); 6443 } 6444 6445 /* 6446 * phy_82780_per_lane_tx_set 6447 */ 6448 STATIC int 6449 phy_82780_per_lane_tx_set(soc_phymod_ctrl_t *pmc, int32 intf, soc_phy_control_t type, int lane, uint32 value) 6450 { 6451 soc_phymod_phy_t *p_phy; 6452 uint32 lane_map; 6453 phymod_phy_access_t pm_phy_copy, *pm_phy; 6454 phymod_tx_t phymod_tx; 6455 6456 /* locate the desired phy and lane */ 6457 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 6458 6459 /* Make a copy of the phy access and overwrite the desired lane */ 6460 pm_phy = &p_phy->pm_phy; 6461 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6462 pm_phy_copy.access.lane_mask = lane_map; 6463 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 6464 if(intf == PHY82780_SYS_SIDE) { 6465 PHY82780_SET_SYS_SIDE(pm_phy_copy); 6466 } 6467 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 6468 switch (type) { 6469 case SOC_PHY_CONTROL_TX_FIR_PRE: 6470 phymod_tx.pre = value; 6471 break; 6472 case SOC_PHY_CONTROL_TX_FIR_MAIN: 6473 phymod_tx.main = value; 6474 break; 6475 case SOC_PHY_CONTROL_TX_FIR_POST: 6476 phymod_tx.post = value; 6477 break; 6478 case SOC_PHY_CONTROL_TX_FIR_POST2: 6479 phymod_tx.post2 = value; 6480 break; 6481 default: 6482 return SOC_E_UNAVAIL; 6483 } 6484 6485 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 6486 6487 return(SOC_E_NONE); 6488 } 6489 6490 /* 6491 * phy_82780_per_lane_tx_get 6492 */ 6493 STATIC int 6494 phy_82780_per_lane_tx_get(soc_phymod_ctrl_t *pmc, int32 intf, soc_phy_control_t type, int lane, uint32 *value) 6495 { 6496 soc_phymod_phy_t *p_phy; 6497 uint32 lane_map; 6498 phymod_phy_access_t pm_phy_copy, *pm_phy; 6499 phymod_tx_t phymod_tx; 6500 6501 /* locate the desired phy and lane */ 6502 SOC_IF_ERROR_RETURN(_phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 6503 6504 /* Make a copy of the phy access and overwrite the desired lane */ 6505 pm_phy = &p_phy->pm_phy; 6506 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6507 pm_phy_copy.access.lane_mask = lane_map; 6508 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 6509 if(intf == PHY82780_SYS_SIDE) { 6510 PHY82780_SET_SYS_SIDE(pm_phy_copy); 6511 } 6512 6513 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 6514 *value = phymod_tx.amp; 6515 switch (type) { 6516 case SOC_PHY_CONTROL_TX_FIR_PRE: 6517 *value = phymod_tx.pre; 6518 break; 6519 case SOC_PHY_CONTROL_TX_FIR_MAIN: 6520 *value = phymod_tx.main; 6521 break; 6522 case SOC_PHY_CONTROL_TX_FIR_POST: 6523 *value = phymod_tx.post; 6524 break; 6525 case SOC_PHY_CONTROL_TX_FIR_POST2: 6526 *value = phymod_tx.post2; 6527 break; 6528 default: 6529 return SOC_E_UNAVAIL; 6530 } 6531 6532 return(SOC_E_NONE); 6533 } 6534 6535 /* 6536 * Function: 6537 * _phy_84328_ability_remote_get 6538 * Purpose: 6539 * Get the device's complete abilities. 6540 * Parameters: 6541 * unit - StrataSwitch unit #. 6542 * port - StrataSwitch port #. 6543 * ability - return device's abilities. 6544 * Returns: 6545 * SOC_E_XXX 6546 */ 6547 STATIC int 6548 phy_82780_ability_remote_get(int unit, soc_port_t port, 6549 soc_port_ability_t *ability) 6550 { 6551 int an, an_done; 6552 phy_ctrl_t *pc, *int_pc; 6553 int line_intf; 6554 phymod_autoneg_ability_t phymod_autoneg_ability; 6555 uint32_t an_cap = 0; 6556 soc_phymod_ctrl_t *pmc; 6557 phy82780_config_t *pCfg; 6558 soc_phymod_phy_t *phy; 6559 6560 6561 if (ability == NULL) { 6562 return SOC_E_PARAM; 6563 } 6564 pc = EXT_PHY_SW_STATE(unit, port); 6565 6566 6567 /* Only firmware has visibility into remote ability */ 6568 sal_memset(ability, 0, sizeof(soc_port_ability_t)); 6569 6570 pmc = &pc->phymod_ctrl; 6571 pCfg = (phy82780_config_t *) pc->driver_data; 6572 6573 /* only set abilities on the first core */ 6574 phy = pmc->phy[pmc->main_phy]; 6575 if (phy == NULL) { 6576 return SOC_E_INTERNAL; 6577 } 6578 phymod_autoneg_ability_t_init(&phymod_autoneg_ability); 6579 6580 6581 line_intf = pCfg->speed_config.line_interface; 6582 6583 if ((line_intf == SOC_PORT_IF_KX) || (line_intf == SOC_PORT_IF_GMII)) { 6584 int_pc = INT_PHY_SW_STATE(unit, port); 6585 if (int_pc) { 6586 SOC_IF_ERROR_RETURN(PHY_ABILITY_REMOTE_GET(int_pc->pd, unit, port, ability)); 6587 } 6588 return SOC_E_NONE; 6589 } 6590 6591 ability->speed_half_duplex = SOC_PA_ABILITY_NONE; 6592 6593 /* Return what the firmware is setting */ 6594 /* If an done, then return the speed for the port */ 6595 SOC_IF_ERROR_RETURN(phy_82780_an_get(unit, port, &an, &an_done)); 6596 if (an && an_done) { 6597 SOC_IF_ERROR_RETURN 6598 (phymod_phy_autoneg_remote_ability_get(&phy->pm_phy, &phymod_autoneg_ability)); 6599 an_cap = phymod_autoneg_ability.an_cap; 6600 ability->speed_full_duplex |= PHYMOD_AN_CAP_40G_CR4_GET(an_cap) ? SOC_PA_SPEED_40GB : 0; 6601 ability->speed_full_duplex |= PHYMOD_AN_CAP_40G_KR4_GET(an_cap) ? SOC_PA_SPEED_40GB : 0; 6602 ability->speed_full_duplex |= PHYMOD_AN_CAP_10G_KR_GET(an_cap) ? SOC_PA_SPEED_10GB : 0; 6603 6604 an_cap = phymod_autoneg_ability.capabilities; 6605 if (an_cap == PHYMOD_AN_CAP_ASYM_PAUSE) { 6606 ability->pause = SOC_PA_PAUSE_TX; 6607 } else if (an_cap == (PHYMOD_AN_CAP_SYMM_PAUSE | PHYMOD_AN_CAP_ASYM_PAUSE)) { 6608 ability->pause = SOC_PA_PAUSE_RX; 6609 } else if (an_cap == PHYMOD_AN_CAP_SYMM_PAUSE) { 6610 ability->pause = (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX); 6611 } 6612 } 6613 LOG_INFO(BSL_LS_SOC_PHY, 6614 (BSL_META_U(unit, 6615 "phy_84328_ability_remote_get: u=%d p=%d speed(FD)=0x%x pause=0x%x\n"), 6616 unit, port, ability->speed_full_duplex, ability->pause)); 6617 6618 return SOC_E_NONE; 6619 } 6620 6621 STATIC int 6622 phy_82780_cl72_enable_set(soc_phymod_ctrl_t *pmc, int32 intf, uint32 value) 6623 { 6624 phymod_phy_access_t *pm_phy; 6625 int idx; 6626 phymod_phy_access_t pm_phy_copy; 6627 6628 for (idx = 0; idx < pmc->num_phys; idx++) { 6629 pm_phy = &pmc->phy[idx]->pm_phy; 6630 6631 if (pm_phy == NULL) { 6632 return SOC_E_INTERNAL; 6633 } 6634 6635 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6636 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 6637 6638 if (intf == PHY82780_SYS_SIDE) { 6639 PHY82780_SET_SYS_SIDE(pm_phy_copy); 6640 } 6641 #ifdef PHY82780_DEBUG 6642 LOG_CLI((BSL_META_U(0,"Tx training: %d Flags:0x%x\n"), value, pm_phy_copy.access.flags)); 6643 #endif 6644 SOC_IF_ERROR_RETURN(phymod_phy_cl72_set(&pm_phy_copy, value)); 6645 } 6646 6647 return(SOC_E_NONE); 6648 } 6649 6650 6651 STATIC int 6652 phy_82780_cl72_status_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 6653 { 6654 phymod_phy_access_t *pm_phy; 6655 int idx; 6656 phymod_phy_access_t pm_phy_copy; 6657 phymod_cl72_status_t status; 6658 6659 for (idx = 0; idx < pmc->num_phys; idx++) { 6660 pm_phy = &pmc->phy[idx]->pm_phy; 6661 6662 if (pm_phy == NULL) { 6663 return SOC_E_INTERNAL; 6664 } 6665 6666 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6667 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 6668 6669 if (intf == PHY82780_SYS_SIDE) { 6670 PHY82780_SET_SYS_SIDE(pm_phy_copy); 6671 } 6672 6673 sal_memset(&status, 0, sizeof(status)); 6674 SOC_IF_ERROR_RETURN(phymod_phy_cl72_status_get(&pm_phy_copy, &status)); 6675 *value = status.locked; 6676 } 6677 #ifdef PHY82780_DEBUG 6678 LOG_CLI((BSL_META_U(0,"Tx training Sts: %d Flags:0x%x\n"), *value, pm_phy_copy.access.flags)); 6679 #endif 6680 6681 return(SOC_E_NONE); 6682 } 6683 6684 STATIC int 6685 phy_82780_cl72_enable_get(soc_phymod_ctrl_t *pmc, int32 intf, uint32 *value) 6686 { 6687 phymod_phy_access_t *pm_phy; 6688 int idx; 6689 phymod_phy_access_t pm_phy_copy; 6690 6691 for (idx = 0; idx < pmc->num_phys; idx++) { 6692 pm_phy = &pmc->phy[idx]->pm_phy; 6693 6694 if (pm_phy == NULL) { 6695 return SOC_E_INTERNAL; 6696 } 6697 6698 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6699 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 6700 6701 if (intf == PHY82780_SYS_SIDE) { 6702 PHY82780_SET_SYS_SIDE(pm_phy_copy); 6703 } 6704 6705 SOC_IF_ERROR_RETURN(phymod_phy_cl72_get(&pm_phy_copy, value)); 6706 } 6707 return(SOC_E_NONE); 6708 } 6709 6710 STATIC int 6711 phy_82780_link_monitor_set (soc_phymod_ctrl_t *pmc, int32 intf, int32 lane, uint32 value) 6712 { 6713 phymod_phy_access_t *pm_phy; 6714 soc_phymod_phy_t *p_phy; 6715 uint32 lane_map = 0; 6716 phymod_phy_access_t pm_phy_copy; 6717 uint32_t link_mon_mode = 0; 6718 6719 intf = (intf == PHY_DIAG_INTF_LINE) ? PHY82780_LINE_SIDE : PHY82780_SYS_SIDE; 6720 if (lane == 0xf) { 6721 /* Get p_phy alone and let lane map be as Phy structure value */ 6722 lane = 1; 6723 SOC_IF_ERROR_RETURN( 6724 _phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 6725 lane = 0xf; 6726 } else { 6727 SOC_IF_ERROR_RETURN( 6728 _phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 6729 } 6730 6731 /* Make a copy of the phy access and overwrite the desired lane */ 6732 pm_phy = &p_phy->pm_phy; 6733 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6734 if (lane != 0xf) { 6735 pm_phy_copy.access.lane_mask = lane_map; 6736 } 6737 6738 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 6739 if(intf == PHY82780_SYS_SIDE) { 6740 PHY82780_SET_SYS_SIDE(pm_phy_copy); 6741 } 6742 6743 if (value == 0) { 6744 SOC_IF_ERROR_RETURN( 6745 phymod_phy_link_mon_enable_set(&pm_phy_copy, 0 /*When disable Dont care*/, 0)); 6746 } else { 6747 link_mon_mode = value - 1; 6748 SOC_IF_ERROR_RETURN( 6749 phymod_phy_link_mon_enable_set(&pm_phy_copy, link_mon_mode, 1)); 6750 } 6751 6752 return(SOC_E_NONE); 6753 } 6754 6755 STATIC int 6756 phy_82780_link_monitor_status_get (soc_phymod_ctrl_t *pmc, int32 intf, int32 lane) 6757 { 6758 phymod_phy_access_t *pm_phy; 6759 soc_phymod_phy_t *p_phy; 6760 uint32 lane_map = 0; 6761 phymod_phy_access_t pm_phy_copy; 6762 uint32_t lock_status = 0, lock_lost_lh = 0, error_count = 0; 6763 6764 intf = (intf == PHY_DIAG_INTF_LINE) ? PHY82780_LINE_SIDE : PHY82780_SYS_SIDE; 6765 if (lane == 0xf) { 6766 /* Get p_phy alone and let lane map be as Phy structure value */ 6767 lane = 1; 6768 SOC_IF_ERROR_RETURN( 6769 _phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 6770 lane = 0xf; 6771 } else { 6772 SOC_IF_ERROR_RETURN( 6773 _phy_82780_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 6774 } 6775 6776 /* Make a copy of the phy access and overwrite the desired lane */ 6777 pm_phy = &p_phy->pm_phy; 6778 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6779 if (lane != 0xf) { 6780 pm_phy_copy.access.lane_mask = lane_map; 6781 } 6782 6783 PHY82780_CLEAR_SYS_SIDE(pm_phy_copy); 6784 6785 if(intf == PHY82780_SYS_SIDE) { 6786 PHY82780_SET_SYS_SIDE(pm_phy_copy); 6787 } 6788 6789 SOC_IF_ERROR_RETURN( 6790 phymod_phy_link_mon_status_get(&pm_phy_copy, &lock_status, &lock_lost_lh, &error_count)); 6791 6792 if (lane != 0xF) { 6793 LOG_CLI((BSL_META_U(0,"Lane:%d Lock Status:%d lock lost:%d Error count:%d\n "), 6794 lane, lock_status, lock_lost_lh, error_count)); 6795 } else { 6796 LOG_CLI((BSL_META_U(0,"Lane Map:0x%x Lock Status:%d lock lost:%d Error count:%d\n "), 6797 pm_phy_copy.access.lane_mask, lock_status, lock_lost_lh, error_count)); 6798 } 6799 6800 return(SOC_E_NONE); 6801 6802 } 6803 6804 STATIC int 6805 phy_82780_adoptation_release(phy_ctrl_t *pc, int32 intf) 6806 { 6807 phymod_phy_access_t *pm_phy; 6808 int idx; 6809 phymod_phy_access_t pm_phy_copy; 6810 soc_phymod_ctrl_t *pmc; 6811 pmc = &pc->phymod_ctrl; 6812 6813 /* loop through all cores */ 6814 for (idx = 0; idx < pmc->num_phys; idx++) { 6815 pm_phy = &pmc->phy[idx]->pm_phy; 6816 6817 if (pm_phy == NULL) { 6818 return SOC_E_INTERNAL; 6819 } 6820 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6821 if (intf == PHY82780_SYS_SIDE) { 6822 PHY82780_SET_SYS_SIDE(pm_phy_copy); 6823 } 6824 SOC_IF_ERROR_RETURN(phymod_phy_rx_adaptation_resume(&pm_phy_copy)); 6825 } 6826 return(SOC_E_NONE); 6827 } 6828 6829 STATIC int 6830 phy_82780_config_fail_over(phy_ctrl_t *pc, int32 intf, uint32_t value) 6831 { 6832 phymod_phy_access_t *pm_phy; 6833 int idx; 6834 phymod_phy_access_t pm_phy_copy; 6835 soc_phymod_ctrl_t *pmc; 6836 phymod_failover_mode_t failover_mode; 6837 pmc = &pc->phymod_ctrl; 6838 6839 /* loop through all cores */ 6840 for (idx = 0; idx < pmc->num_phys; idx++) { 6841 pm_phy = &pmc->phy[idx]->pm_phy; 6842 6843 if (pm_phy == NULL) { 6844 return SOC_E_INTERNAL; 6845 } 6846 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6847 if (intf == PHY82780_SYS_SIDE) { 6848 PHY82780_SET_SYS_SIDE(pm_phy_copy); 6849 } 6850 failover_mode = value? phymodFailovermodeEnable : phymodFailovermodeNone; 6851 SOC_IF_ERROR_RETURN( 6852 phymod_failover_mode_set(&pm_phy_copy, failover_mode)); 6853 } 6854 return(SOC_E_NONE); 6855 } 6856 6857 STATIC int 6858 phy_82780_config_fail_over_get(phy_ctrl_t *pc, int32 intf, uint32_t *value) 6859 { 6860 phymod_phy_access_t *pm_phy; 6861 int idx; 6862 phymod_phy_access_t pm_phy_copy; 6863 soc_phymod_ctrl_t *pmc; 6864 phymod_failover_mode_t failover_mode; 6865 pmc = &pc->phymod_ctrl; 6866 6867 /* loop through all cores */ 6868 for (idx = 0; idx < pmc->num_phys; idx++) { 6869 pm_phy = &pmc->phy[idx]->pm_phy; 6870 6871 if (pm_phy == NULL) { 6872 return SOC_E_INTERNAL; 6873 } 6874 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6875 if (intf == PHY82780_SYS_SIDE) { 6876 PHY82780_SET_SYS_SIDE(pm_phy_copy); 6877 } 6878 SOC_IF_ERROR_RETURN( 6879 phymod_failover_mode_get(&pm_phy_copy, &failover_mode)); 6880 if (failover_mode == phymodFailovermodeEnable) { 6881 *value = 1; 6882 } else { 6883 *value = 0; 6884 } 6885 } 6886 return(SOC_E_NONE); 6887 } 6888 6889 /* 6890 * Function: 6891 * phy_82780_precondition_before_probe 6892 * Purpose: 6893 * When the device is in 40G, ie. after a power reset, and the 10G 6894 * port being probed does not have the 40G address in PRTAD, the 6895 * device will not respond until the port that has the 40G address 6896 * is probed. To avoid not programming ports correctly, make 6897 * sure the device is in quad (4x10G) PMD mode when the SDK port is 10G. 6898 * Need to set "port_phy_precondition_before_probe_xe0/4" in config file. 6899 * Parameters: 6900 * unit - StrataSwitch unit #. 6901 * pc - phy ctrl descriptor. 6902 * Returns: 6903 * SOC_E_NONE,SOC_E_NOT_FOUND and SOC_E_<error> 6904 */ 6905 6906 6907 STATIC int32 6908 phy_82780_precondition_before_probe(int32 unit, phy_ctrl_t *pc) 6909 { 6910 uint16_t val; 6911 int max_lane = 4, index = 0; 6912 uint16 saved_phy_id; 6913 int rv = SOC_E_NOT_FOUND; 6914 6915 if (SOC_INFO((pc)->unit).port_num_lanes[(pc)->port] >= 4) { 6916 return rv; 6917 } 6918 SOC_IF_ERROR_RETURN( 6919 READ_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(0x1, 0xc802), &val)); 6920 if (val == 0x2752) { 6921 max_lane = 2; 6922 } else if (val == 0x2780 || val == 0x2758 || val == 0x278F) { 6923 max_lane = 4; 6924 } else { 6925 return rv; 6926 } 6927 saved_phy_id = pc->phy_id; 6928 for (index = 0; index < max_lane; index ++) { 6929 pc->phy_id = (saved_phy_id & ~0x3) + index; 6930 SOC_IF_ERROR_RETURN( 6931 READ_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(0x1, 0x2), &val)); 6932 if (val != 0xAE02) { 6933 continue; 6934 } 6935 SOC_IF_ERROR_RETURN( 6936 READ_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(0x1, 0x3), &val)); 6937 if (val != 0x5250) { 6938 continue; 6939 } 6940 6941 SOC_IF_ERROR_RETURN( 6942 READ_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(0x1, 0xc843), &val)); 6943 if (((val & 0xf) == 0x4) || ((val & 0xf) == 0x7)) { 6944 SOC_IF_ERROR_RETURN( 6945 WRITE_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(0x1, 0xc712), 1)); 6946 6947 val &= ~(0x80); 6948 SOC_IF_ERROR_RETURN( 6949 WRITE_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(0x1, 0xc8d8), val)); 6950 val = 0x8882; 6951 SOC_IF_ERROR_RETURN( 6952 WRITE_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(0x1, 0xc8d8), val)); 6953 6954 SOC_IF_ERROR_RETURN( 6955 READ_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(0x1, 0x0), &val)); 6956 val |= (0x8000); 6957 SOC_IF_ERROR_RETURN( 6958 WRITE_PHY_REG(unit, pc, SOC_PHY_CLAUSE45_ADDR(0x1, 0x0), val)); 6959 6960 sal_usleep(5000); 6961 } 6962 rv = SOC_E_NONE; 6963 break; 6964 } 6965 pc->phy_id = saved_phy_id; 6966 6967 return rv; 6968 } 6969 6970 STATIC int 6971 phy_82780_multi_get(int unit, soc_port_t port, uint32 flags, 6972 uint32 dev_addr, uint32 offset, int max_size, uint8 *data, 6973 int *actual_size) 6974 { 6975 phy_ctrl_t *pc; 6976 soc_phymod_ctrl_t *pmc; 6977 phymod_phy_access_t *pm_phy; 6978 6979 pc = EXT_PHY_SW_STATE(unit, port); 6980 if (pc == NULL) { 6981 return SOC_E_INTERNAL; 6982 } 6983 6984 pmc = &pc->phymod_ctrl; 6985 pm_phy = &pmc->phy[pmc->main_phy]->pm_phy; 6986 6987 *actual_size = 0; 6988 SOC_IF_ERROR_RETURN 6989 (phymod_phy_i2c_read(pm_phy, 0, dev_addr, offset, max_size, data)); 6990 6991 *actual_size = max_size; 6992 return SOC_E_NONE; 6993 } 6994 /* 6995 * Variable: 6996 * phy82780_drv 6997 * Purpose: 6998 * Phy Driver for phy82780 6999 */ 7000 phy_driver_t phy82780_drv = { 7001 /* .drv_name = */ "PHY82780 PHYMOD PHY Driver", 7002 /* .pd_init = */ phy_82780_init, 7003 /* .pd_reset = */ phy_82780_core_reset, 7004 /* .pd_link_get = */ phy_82780_link_get, 7005 /* .pd_enable_set = */ phy_82780_enable_set, 7006 /* .pd_enable_get = */ phy_82780_enable_get, 7007 /* .pd_duplex_set = */ phy_null_set, 7008 /* .pd_duplex_get = */ phy_null_duplex_get, 7009 /* .pd_speed_set = */ phy82780_speed_set, 7010 /* .pd_speed_get = */ phy82780_speed_get, 7011 /* .pd_master_set = */ phy_null_set, 7012 /* .pd_master_get = */ phy_null_zero_get, 7013 /* .pd_an_set = */ phy_82780_an_set, 7014 /* .pd_an_get = */ phy_82780_an_get, 7015 /* .pd_adv_local_set = */ NULL, /* Deprecated */ 7016 /* .pd_adv_local_get = */ NULL, /* Deprecated */ 7017 /* .pd_adv_remote_get = */ NULL, /* Deprecated */ 7018 /* .pd_lb_set = */ phy_82780_lb_set, 7019 /* .pd_lb_get = */ phy82780_lb_get, 7020 /* .pd_interface_set = */ phy82780_interface_set, 7021 /* .pd_interface_get = */ phy82780_interface_get, 7022 /* .pd_ability = */ NULL, /* Deprecated */ 7023 /* .pd_linkup_evt = */ NULL, 7024 /* .pd_linkdn_evt = */ NULL, 7025 /* .pd_mdix_set = */ phy_null_mdix_set, 7026 /* .pd_mdix_get = */ phy_null_mdix_get, 7027 /* .pd_mdix_status_get = */ phy_null_mdix_status_get, 7028 /* .pd_medium_config_set = */ NULL, 7029 /* .pd_medium_config_get = */ NULL, 7030 /* .pd_medium_get = */ phy_null_medium_get, 7031 /* .pd_cable_diag = */ NULL, 7032 /* .pd_link_change = */ NULL, 7033 /* .pd_control_set = */ phy_82780_control_set, 7034 /* .pd_control_get = */ phy_82780_control_get, 7035 /* .pd_reg_read = */ phy82780_reg_read, 7036 /* .pd_reg_write = */ phy82780_reg_write, 7037 /* .pd_reg_modify = */ phy82780_reg_modify, 7038 /* .pd_notify = */ NULL, 7039 /* .pd_probe = */ phy82780_probe, 7040 /* .pd_ability_advert_set = */ phy_82780_ability_advert_set, 7041 /* .pd_ability_advert_get = */ phy_82780_ability_advert_get, 7042 /* .pd_ability_remote_get = */ phy_82780_ability_remote_get, 7043 /* .pd_ability_local_get = */ phy_82780_ability_local_get, 7044 /* .pd_firmware_set = */ phy_82780_firmware_set, 7045 /* .pd_timesync_config_set = */ NULL, 7046 /* .pd_timesync_config_get = */ NULL, 7047 /* .pd_timesync_control_set = */ NULL, 7048 /* .pd_timesync_control_set = */ NULL, 7049 /* .pd_diag_ctrl = */ phy_82780_diag_ctrl, 7050 /* .pd_lane_control_set = */ phy_82780_per_lane_control_set, 7051 /* .pd_lane_control_get = */ phy_82780_per_lane_control_get, 7052 /* pd_lane_reg_read */ NULL, 7053 /* pd_lane_reg_write */ NULL, 7054 /* pd_oam_config_set */ NULL, 7055 /* pd_oam_config_get */ NULL, 7056 /* pd_oam_control_set */ NULL, 7057 /* pd_oam_control_get */ NULL, 7058 /* pd_timesync_enhanced_capture_get */ NULL, 7059 /* pd_multi_get */ phy_82780_multi_get, 7060 /* pd_precondition_before_probe */ phy_82780_precondition_before_probe 7061 7062 }; 7063 7064 #else 7065 int _phy82780_not_empty; 7066 #endif /* INCLUDE_PHY_82780 */ 7067