phy82864.c (271615B)
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: phy82864.c 8 * Purpose: Support for madura external PHY 9 */ 10 11 /* 12 * This module implements an NTSW SDK Phy driver for the phy82864 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 * phy82864 and Madura 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 .phy82864_per_lane_control_set and 36 * .phy82864_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 * madura_config_t 60 * Driver specific data. This structure is used by madura 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/eyescan.h> 98 #include <soc/port_ability.h> 99 #include <soc/phy.h> 100 #include <soc/phy/phyctrl.h> 101 #include <soc/phy/drv.h> 102 #include <soc/phy/phymod_ids.h> 103 104 #include "phydefs.h" /* Must include before other phy related includes */ 105 106 #include "phyconfig.h" /* Must include before other phy related includes */ 107 #include "phyident.h" 108 #include "phyreg.h" 109 #include "phynull.h" 110 #include "xgxs.h" 111 112 113 #define PHYMOD_MADURA_SUPPORT 114 115 #if defined(INCLUDE_PHY_82864) 116 117 #include <phymod/phymod.h> 118 #include <phymod/phymod_debug.h> 119 #include <phymod/phymod_diagnostics.h> 120 #include <phymod/chip/madura.h> 121 122 #define PHY82864_LINE_SIDE(_pm)\ 123 do {\ 124 (_pm)->port_loc = phymodPortLocLine; \ 125 (_pm)->access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); \ 126 } while (0) 127 128 #define PHY82864_SYSTEM_SIDE(_pm)\ 129 do {\ 130 (_pm)->port_loc = phymodPortLocSys; \ 131 (_pm)->access.flags |= (1 << INTERFACE_SIDE_SHIFT); \ 132 } while (0) 133 134 #define SOC_MADURA_IF_ERR_RETURN_FREE(B, A) \ 135 do { \ 136 int loc_err ; \ 137 if ((loc_err = (A)) != SOC_E_NONE) \ 138 { if (B) { sal_free(B) ; } ; return loc_err ; } \ 139 } while (0) 140 141 142 #define NUM_LANES 8 /* num of lanes per core */ 143 #define MAX_NUM_LANES 4 /* max num of lanes per port */ 144 #define PHY82864_NO_CFG_VALUE (-1) 145 #define PHY82864_DBG_REGACC 0x2 146 #define PHY82864_DBG_MEM 0x3 147 #define PHY82864_PORT_NO_LANES_4 4 148 #define PHY82864_PORT_NO_LANES_2 2 149 #define PHY82864_PORT_NO_LANES_1 1 150 #define PHY82864_SPD_1G 1000 151 #define PHY82864_SPD_10G 10000 152 #define PHY82864_SPD_11G 11000 153 #define PHY82864_SPD_25G 25000 154 #define PHY82864_SPD_40G 40000 155 #define PHY82864_SPD_42G 42000 156 #define PHY82864_SPD_50G 50000 157 #define PHY82864_SPD_100G 100000 158 #define PHY82864_SPD_106G 106000 159 #define INTERFACE_SIDE_SHIFT 31 160 #define MADURA_ID_82864 0x82864 161 #define PHY82864_CHIP_ID_SIZE 25 162 163 typedef struct phy82864_device_cfg_aux_mode{ 164 uint16_t pass_thru; 165 uint16_t alternate; 166 uint16_t pass_thru_dual_lane; 167 uint16_t reserved1; 168 }phy82864_device_cfg_aux_mode_t; 169 170 typedef struct phy82864_device_aux_mode { 171 uint32_t an_mst_lane_p0; 172 uint32_t an_mst_lane_p1; 173 uint32_t core_id; 174 } phy82864_device_aux_mode_t; 175 176 typedef struct phy82864_speed_config_s { 177 uint32 port_refclk_int; 178 int speed; 179 int port_num_lanes; 180 uint32 line_interface; 181 int pll_divider_req ; 182 int higig_port; 183 int otn_port; 184 } phy82864_speed_config_t; 185 186 typedef enum PHY82864_INTF_SIDE { 187 PHY82864_LINE_SIDE, 188 PHY82864_SYS_SIDE 189 }PHY82864_INTF_SIDE; 190 191 /* 192 Config - per logical port 193 */ 194 typedef struct { 195 phymod_polarity_t phy_polarity_config; 196 phymod_phy_reset_t phy_reset_config; 197 phy82864_speed_config_t speed_config; 198 int an_master_lane; 199 int devid; 200 char dev_name[PHY82864_CHIP_ID_SIZE]; 201 int auto_mod_detect; 202 int sys_lane_map; 203 phy82864_device_aux_mode_t *device_aux_modes; 204 phy82864_device_cfg_aux_mode_t *device_cfg_aux_modes; 205 } phy82864_config_t; 206 207 #define DEVID(_pc) (((phy82864_config_t *)((_pc) + 1))->devid) 208 #define DEV_NAME(_pc) (((phy82864_config_t *)((_pc) + 1))->dev_name) 209 210 static int eye_scan_mdr_enabled = 0; 211 212 STATIC int 213 phy_82864_ability_advert_set(int unit, soc_port_t port, 214 soc_port_ability_t *ability); 215 216 STATIC int 217 phy_82864_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability); 218 STATIC int 219 _phy_82864_find_soc_phy_lane(soc_phymod_ctrl_t *pmc, soc_port_t port, uint32_t lane, 220 soc_phymod_phy_t **p_phy, uint32 *lane_map); 221 222 STATIC int 223 phy_82864_power_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value); 224 STATIC int 225 phy_82864_power_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value); 226 STATIC int 227 phy_82864_per_lane_tx_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, soc_phy_control_t type, int lane, uint32 *value); 228 STATIC int 229 phy_82864_per_lane_tx_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, soc_phy_control_t type, int lane, uint32 value); 230 STATIC int 231 phy_82864_per_lane_cl72_enable_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value); 232 STATIC int 233 phy_82864_per_lane_cl72_status_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value); 234 STATIC int 235 phy_82864_per_lane_cl72_enable_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 value); 236 STATIC int 237 phy_82864_cl72_enable_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value); 238 STATIC int 239 phy_82864_cl72_status_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value); 240 STATIC int 241 phy_82864_cl72_enable_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value); 242 STATIC int 243 phy_82864_tx_lane_squelch_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value); 244 STATIC int 245 phy_82864_intr_enable_set(phy_ctrl_t *pc, int32 intf, uint32 value); 246 STATIC int 247 phy_82864_intr_enable_get(phy_ctrl_t *pc, int32 intf, uint32 *value); 248 STATIC int 249 phy_82864_intr_status_get(phy_ctrl_t *pc, int32 intf, uint32 *value); 250 STATIC int 251 phy_82864_gpio_config_get(phy_ctrl_t *pc, uint32 *value); 252 STATIC int 253 phy_82864_gpio_config_set(phy_ctrl_t *pc, uint32 value); 254 STATIC int 255 phy_82864_gpio_value_get(phy_ctrl_t *pc, uint32 *value); 256 STATIC int 257 phy_82864_gpio_value_set(phy_ctrl_t *pc, uint32 value); 258 STATIC int 259 phy_82864_per_lane_tx_lane_squelch_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value); 260 STATIC int 261 phy_82864_loopback_internal_pmd_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value); 262 STATIC int 263 phy_82864_loopback_internal_pmd_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value); 264 STATIC int 265 phy_82864_link_monitor_status_get (soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int32 lane); 266 STATIC int 267 phy_82864_link_monitor_set (soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int32 lane, uint32 value); 268 STATIC int 269 phy_82864_firmware_lp_dfe_enable_get(phy_ctrl_t *pc, soc_port_t port, int32 intf, uint32 *value); 270 STATIC int 271 phy_82864_firmware_dfe_enable_get(phy_ctrl_t *pc, soc_port_t port, int32 intf, uint32 *value); 272 STATIC int 273 phy_82864_firmware_mode_get(phy_ctrl_t *pc, soc_port_t port, int32 intf, uint32 *value); 274 STATIC int 275 phy_82864_firmware_lp_dfe_enable_set(phy_ctrl_t *pc, soc_port_t port, int32 intf, uint32 enable); 276 STATIC int 277 phy_82864_firmware_dfe_enable_set(phy_ctrl_t *pc, soc_port_t port, int32 intf, uint32 enable); 278 STATIC int 279 phy_82864_firmware_mode_set(phy_ctrl_t *pc, soc_port_t port, int32 intf, uint32 value); 280 STATIC int 281 phy_82864_unreliable_los_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value); 282 STATIC int 283 phy_82864_unreliable_los_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 enable); 284 /* 285 * Function: 286 * _phy82864_sys_side_lane_map_get 287 * Purpose: 288 * Mapping to speed to lane map based on config 289 * Parameters: 290 * unit - BCM unit number. 291 * port - Port number. 292 * phymod_phy_access_t - [OUT] Line Lane map 293 * Returns: 294 * SOC_E_NONE 295 */ 296 297 298 STATIC int 299 _phy82864_sys_side_lane_map_get(int unit, soc_port_t port, phymod_phy_access_t *pm_phy_copy) 300 { 301 phy_ctrl_t *pc; 302 phy82864_config_t *pCfg; 303 304 pc = EXT_PHY_SW_STATE(unit, port); 305 306 if (pc == NULL) { 307 return SOC_E_INTERNAL; 308 } 309 pCfg = (phy82864_config_t *) pc->driver_data; 310 311 pm_phy_copy->access.lane_mask = pCfg->sys_lane_map; 312 313 return SOC_E_NONE; 314 } 315 316 /* 317 * Function: 318 * _phy82864_reg_read 319 * Doc: 320 * register read operations 321 * Parameters: 322 * unit - (IN) unit number 323 * core_addr - (IN) core address 324 * reg_addr - (IN) address to read 325 * val - (OUT) read value 326 */ 327 STATIC int 328 _phy82864_reg_read(void* user_acc, uint32_t core_addr, uint32_t reg_addr, uint32_t *val) 329 { 330 uint16 data16 = 0; 331 int rv = 0; 332 soc_phymod_core_t *core = (soc_phymod_core_t *)user_acc; 333 334 rv = core->read(core->unit, core_addr, reg_addr, &data16); 335 *val = data16; 336 PHYMOD_VDBG(PHY82864_DBG_REGACC, NULL,("-22%s: core_addr: 0x%08x reg_addr: 0x%08x, data: 0x%04x\n", __func__, core_addr, reg_addr, *val )); 337 338 return rv; 339 } 340 341 /* 342 * Function: 343 * _phy82864_reg_write 344 * Doc: 345 * register write operations 346 * Parameters: 347 * unit - (IN) unit number 348 * core_addr - (IN) core address 349 * reg_addr - (IN) address to write 350 * val - (IN) write value 351 */ 352 STATIC int 353 _phy82864_reg_write(void* user_acc, uint32_t core_addr, uint32_t reg_addr, uint32_t val) 354 { 355 soc_phymod_core_t *core = (soc_phymod_core_t *)user_acc; 356 uint16 data16 = (uint16)val; 357 uint16 mask = (uint16)(val >> 16); 358 359 if (mask) { 360 if (core->wrmask) { 361 return core->wrmask(core->unit, core_addr, reg_addr, data16, mask); 362 } 363 (void)core->read(core->unit, core_addr, reg_addr, &data16); 364 data16 &= ~mask; 365 data16 |= (val & mask); 366 } 367 PHYMOD_VDBG(PHY82864_DBG_REGACC, NULL,("-22%s: core_addr: 0x%08x reg_addr: 0x%08x, data: 0x%04x\n", __func__, core_addr, reg_addr, val )); 368 return core->write(core->unit, core_addr, reg_addr, data16); 369 } 370 371 /* 372 * Function: 373 * phy82864_speed_to_interface_config_get 374 * Purpose: 375 * Convert speed to interface_config struct 376 * Parameters: 377 * unit - BCM unit number. 378 * port - Port number. 379 * speed - speed to convert 380 * interface_config - output interface config struct 381 * Returns: 382 * SOC_E_NONE 383 */ 384 STATIC int 385 phy82864_speed_to_interface_config_get(phy82864_speed_config_t* speed_config, phymod_phy_inf_config_t* interface_config) 386 { 387 SOC_IF_ERROR_RETURN(phymod_phy_inf_config_t_init(interface_config)); 388 389 interface_config->interface_modes = 0; 390 interface_config->data_rate = speed_config->speed; 391 interface_config->pll_divider_req = speed_config->pll_divider_req ; 392 393 switch (speed_config->speed) { 394 case PHY82864_SPD_1G: 395 case PHY82864_SPD_10G: 396 case PHY82864_SPD_11G: 397 case PHY82864_SPD_25G: 398 switch(speed_config->line_interface) { 399 case SOC_PORT_IF_KX: 400 interface_config->interface_type = phymodInterfaceKX; 401 break; 402 case SOC_PORT_IF_KR: 403 interface_config->interface_type = phymodInterfaceKR; 404 break; 405 case SOC_PORT_IF_LR: 406 interface_config->interface_type = phymodInterfaceLR; 407 break; 408 case SOC_PORT_IF_SR: 409 interface_config->interface_type = phymodInterfaceSR; 410 break; 411 case SOC_PORT_IF_CR: 412 interface_config->interface_type = phymodInterfaceCR; 413 break; 414 case SOC_PORT_IF_XFI: 415 interface_config->interface_type = phymodInterfaceXFI; 416 break; 417 case SOC_PORT_IF_SFI: 418 interface_config->interface_type = phymodInterfaceSFI; 419 break; 420 default: 421 return SOC_E_PARAM; 422 423 } 424 break; 425 case PHY82864_SPD_50G: 426 switch(speed_config->line_interface) { 427 case SOC_PORT_IF_KR2: 428 interface_config->interface_type = phymodInterfaceKR2; 429 break; 430 case SOC_PORT_IF_SR2: 431 interface_config->interface_type = phymodInterfaceSR2; 432 break; 433 case SOC_PORT_IF_CR2: 434 interface_config->interface_type = phymodInterfaceCR2; 435 break; 436 case SOC_PORT_IF_LR2: 437 interface_config->interface_type = phymodInterfaceLR2; 438 break; 439 default: 440 return SOC_E_PARAM; 441 } 442 break; 443 case PHY82864_SPD_40G: 444 case PHY82864_SPD_42G: 445 switch(speed_config->line_interface) { 446 case SOC_PORT_IF_KR4: 447 interface_config->interface_type = phymodInterfaceKR4; 448 break; 449 case SOC_PORT_IF_LR4: 450 interface_config->interface_type = phymodInterfaceLR4; 451 break; 452 case SOC_PORT_IF_SR4: 453 interface_config->interface_type = phymodInterfaceSR4; 454 break; 455 case SOC_PORT_IF_CR4: 456 interface_config->interface_type = phymodInterfaceCR4; 457 break; 458 case SOC_PORT_IF_KR2: 459 interface_config->interface_type = phymodInterfaceKR2; 460 break; 461 case SOC_PORT_IF_SR2: 462 interface_config->interface_type = phymodInterfaceSR2; 463 break; 464 case SOC_PORT_IF_CR2: 465 interface_config->interface_type = phymodInterfaceCR2; 466 break; 467 case SOC_PORT_IF_LR2: 468 interface_config->interface_type = phymodInterfaceLR2; 469 break; 470 case SOC_PORT_IF_XLAUI: 471 interface_config->interface_type = phymodInterfaceXLAUI; 472 break; 473 case SOC_PORT_IF_XLPPI: 474 interface_config->interface_type = phymodInterfaceXLPPI; 475 break; 476 default: 477 return SOC_E_PARAM; 478 479 } 480 break; 481 case PHY82864_SPD_100G: 482 case PHY82864_SPD_106G: 483 switch(speed_config->line_interface) { 484 case SOC_PORT_IF_CAUI: 485 interface_config->interface_type = phymodInterfaceCAUI; 486 break; 487 case SOC_PORT_IF_CAUI_C2C: 488 interface_config->interface_type = phymodInterfaceCAUI4_C2C; 489 break; 490 case SOC_PORT_IF_CAUI_C2M: 491 interface_config->interface_type = phymodInterfaceCAUI4_C2M; 492 break; 493 case SOC_PORT_IF_KR4: 494 interface_config->interface_type = phymodInterfaceKR4; 495 break; 496 case SOC_PORT_IF_LR4: 497 interface_config->interface_type = phymodInterfaceLR4; 498 break; 499 case SOC_PORT_IF_SR4: 500 interface_config->interface_type = phymodInterfaceSR4; 501 break; 502 case SOC_PORT_IF_CR4: 503 interface_config->interface_type = phymodInterfaceCR4; 504 break; 505 case SOC_PORT_IF_VSR: 506 interface_config->interface_type = phymodInterfaceVSR; 507 break; 508 default: 509 return SOC_E_PARAM; 510 } 511 break; 512 default: 513 return SOC_E_PARAM; 514 } 515 516 switch (speed_config->port_refclk_int) { 517 case 106: 518 interface_config->ref_clock = phymodRefClk106Mhz; 519 break; 520 case 156: 521 interface_config->ref_clock = phymodRefClk156Mhz; 522 break; 523 case 125: 524 interface_config->ref_clock = phymodRefClk125Mhz; 525 break; 526 case 161: 527 interface_config->ref_clock = phymodRefClk161Mhz; 528 break; 529 case 174: 530 interface_config->ref_clock = phymodRefClk174Mhz; 531 break; 532 case 312: 533 interface_config->ref_clock = phymodRefClk312Mhz; 534 break; 535 case 322: 536 interface_config->ref_clock = phymodRefClk322Mhz; 537 break; 538 case 644: 539 interface_config->ref_clock = phymodRefClk644Mhz; 540 break; 541 case 349: 542 interface_config->ref_clock = phymodRefClk349Mhz; 543 break; 544 case 698: 545 interface_config->ref_clock = phymodRefClk698Mhz; 546 break; 547 default: 548 return SOC_E_PARAM; 549 } 550 551 if (speed_config->higig_port) { 552 PHYMOD_INTF_MODES_HIGIG_SET(interface_config); 553 } 554 if (speed_config->otn_port) { 555 PHYMOD_INTF_MODES_OTN_SET(interface_config); 556 } 557 558 return SOC_E_NONE; 559 } 560 561 /* 562 * Function: 563 * phy82864_speed_set 564 * Purpose: 565 * Set PHY speed 566 * Parameters: 567 * unit - BCM unit number. 568 * port - Port number. 569 * speed - link speed in Mbps 570 * Returns: 571 * SOC_E_NONE 572 */ 573 574 STATIC int 575 phy82864_speed_set(int unit, soc_port_t port, int speed) 576 { 577 phy_ctrl_t *pc; 578 phy_ctrl_t *int_pc; 579 phy82864_config_t *pCfg; 580 soc_phymod_ctrl_t *pmc; 581 soc_phymod_phy_t *phy; 582 int idx; 583 int int_speed; 584 phy82864_speed_config_t speed_config; 585 phymod_phy_inf_config_t interface_config; 586 587 /* locate phy control */ 588 pc = EXT_PHY_SW_STATE(unit, port); 589 int_pc = INT_PHY_SW_STATE(unit, port); 590 if (pc == NULL || int_pc == NULL) { 591 return SOC_E_INTERNAL; 592 } 593 594 if (speed == 0) { 595 return SOC_E_NONE; 596 } 597 SOC_IF_ERROR_RETURN(PHY_SPEED_GET(int_pc->pd, unit, port, &int_speed)); 598 pmc = &pc->phymod_ctrl; 599 pCfg = (phy82864_config_t *) pc->driver_data; 600 601 /* take a copy of core and phy configuration values, and set the desired speed */ 602 sal_memcpy(&speed_config, &pCfg->speed_config, sizeof(speed_config)); 603 speed_config.speed = speed; 604 605 /* determine the interface configuration */ 606 SOC_IF_ERROR_RETURN 607 (phy82864_speed_to_interface_config_get(&speed_config, &interface_config)); 608 609 /*if it comes here then speed is valid and we can change sw for speed.*/ 610 /* PHY-3299 : fix is to set same speed again to clear lane dp reset in 10G*/ 611 if (int_speed != speed || (int_speed == speed && speed==PHY82864_SPD_10G)) { 612 SOC_IF_ERROR_RETURN(PHY_SPEED_SET(int_pc->pd, unit, port, speed)); 613 SOC_IF_ERROR_RETURN(PHY_SPEED_GET(int_pc->pd, unit, port, &int_speed)); 614 if (int_speed != speed) { 615 return SOC_E_CONFIG; 616 } 617 } 618 619 /* phy82864_device_cfg_aux_mode_t assignment */ 620 interface_config.device_aux_modes = (phy82864_device_cfg_aux_mode_t *) pCfg->device_cfg_aux_modes; 621 622 /* now loop through all cores */ 623 for (idx = 0; idx < pmc->num_phys; idx++) { 624 phy = pmc->phy[idx]; 625 if (phy == NULL) { 626 return SOC_E_INTERNAL; 627 } 628 SOC_IF_ERROR_RETURN 629 (phymod_phy_interface_config_set(&phy->pm_phy, 630 0 /* flags */, &interface_config)); 631 } 632 633 /* record success */ 634 pCfg->speed_config.speed = speed; 635 636 return (SOC_E_NONE); 637 } 638 639 /* 640 * Function: 641 * phy82864_speed_get 642 * Purpose: 643 * Get PHY speed 644 * Parameters: 645 * unit - BCM unit number. 646 * port - Port number. 647 * speed - current link speed in Mbps 648 * Returns: 649 * SOC_E_NONE 650 */ 651 STATIC int 652 phy82864_speed_get(int unit, soc_port_t port, int *speed) 653 { 654 phy_ctrl_t *pc; 655 soc_phymod_ctrl_t *pmc; 656 soc_phymod_phy_t *phy; 657 phymod_phy_inf_config_t interface_config; 658 phymod_ref_clk_t ref_clock; 659 int flag = 0; 660 ref_clock = 0; 661 /* locate phy control */ 662 pc = EXT_PHY_SW_STATE(unit, port); 663 if (pc == NULL) { 664 return SOC_E_INTERNAL; 665 } 666 667 pmc = &pc->phymod_ctrl; 668 669 /* initialize the data structure */ 670 interface_config.data_rate = 0; 671 672 /* now loop through all cores */ 673 phy = pmc->phy[pmc->main_phy]; 674 if (phy == NULL) { 675 return SOC_E_INTERNAL; 676 } 677 /* note that the flags have an option to indicate whether it's ok to reprogram the PLL */ 678 SOC_IF_ERROR_RETURN 679 (phymod_phy_interface_config_get(&phy->pm_phy, flag, 680 ref_clock, 681 &interface_config)); 682 683 *speed = interface_config.data_rate; 684 685 return (SOC_E_NONE); 686 } 687 688 689 STATIC int 690 phy82864_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 691 { 692 phy_ctrl_t *pc; 693 phy82864_config_t *pCfg; 694 phy82864_speed_config_t speed_config; 695 phymod_phy_inf_config_t interface_config; 696 soc_phymod_ctrl_t *pmc; 697 soc_phymod_phy_t *phy; 698 int idx = 0; 699 700 pc = EXT_PHY_SW_STATE(unit, port); 701 if (pc == NULL) { 702 return SOC_E_INTERNAL; 703 } 704 pCfg = (phy82864_config_t *) pc->driver_data; 705 pmc = &pc->phymod_ctrl; 706 707 if (pif >= SOC_PORT_IF_COUNT) { 708 return SOC_E_PARAM; 709 } 710 if (pif == SOC_PORT_IF_MII || pif == SOC_PORT_IF_XGMII || pif == SOC_PORT_IF_GMII) { 711 return phy_null_interface_set(unit, port, pif); 712 } 713 714 /* take a copy of core and phy configuration values, and set the desired speed */ 715 sal_memcpy(&speed_config, &pCfg->speed_config, sizeof(speed_config)); 716 speed_config.line_interface = pif; 717 SOC_IF_ERROR_RETURN 718 (phy82864_speed_to_interface_config_get(&speed_config, &interface_config)); 719 720 /* phy82864_device_cfg_aux_mode_t assignment */ 721 interface_config.device_aux_modes = (phy82864_device_cfg_aux_mode_t *) pCfg->device_cfg_aux_modes; 722 /* now loop through all cores */ 723 for (idx = 0; idx < pmc->num_phys; idx++) { 724 phy = pmc->phy[idx]; 725 if (phy == NULL) { 726 return SOC_E_INTERNAL; 727 } 728 SOC_IF_ERROR_RETURN 729 (phymod_phy_interface_config_set(&phy->pm_phy, 730 0 /* flags */, &interface_config)); 731 } 732 733 pCfg->speed_config.line_interface = pif; 734 735 return SOC_E_NONE; 736 } 737 738 STATIC int 739 phy82864_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 740 { 741 /*phy82864_config_t *pCfg;*/ 742 phy_ctrl_t *pc; 743 soc_phymod_ctrl_t *pmc; 744 soc_phymod_phy_t *phy; 745 phymod_phy_inf_config_t interface_config; 746 phymod_ref_clk_t ref_clock; 747 int flag = 0; 748 ref_clock = 0; 749 750 /* locate phy control */ 751 pc = EXT_PHY_SW_STATE(unit, port); 752 if (pc == NULL) { 753 return SOC_E_INTERNAL; 754 } 755 756 /*pCfg = (phy82864_config_t *) pc->driver_data;*/ 757 758 pmc = &pc->phymod_ctrl; 759 760 /* initialize the data structure */ 761 sal_memset(&interface_config, 0x0, sizeof(phymod_phy_inf_config_t)); 762 763 /* now loop through all cores */ 764 phy = pmc->phy[pmc->main_phy]; 765 if (phy == NULL) { 766 return SOC_E_INTERNAL; 767 } 768 /* note that the flags have an option to indicate whether it's ok to reprogram the PLL */ 769 SOC_IF_ERROR_RETURN 770 (phymod_phy_interface_config_get(&phy->pm_phy, ref_clock, 771 flag, &interface_config)); 772 switch (interface_config.interface_type) { 773 case phymodInterfaceKX: 774 *pif = SOC_PORT_IF_KX; 775 break; 776 case phymodInterfaceKR: 777 *pif = SOC_PORT_IF_KR; 778 break; 779 case phymodInterfaceCR: 780 *pif = SOC_PORT_IF_CR; 781 break; 782 case phymodInterfaceKR2: 783 *pif = SOC_PORT_IF_KR2; 784 break; 785 case phymodInterfaceSR2: 786 *pif = SOC_PORT_IF_SR2; 787 break; 788 case phymodInterfaceCR2: 789 *pif = SOC_PORT_IF_CR2; 790 break; 791 case phymodInterfaceLR2: 792 *pif = SOC_PORT_IF_LR2; 793 break; 794 case phymodInterfaceKR4: 795 *pif = SOC_PORT_IF_KR4; 796 break; 797 case phymodInterfaceXLAUI: 798 *pif = SOC_PORT_IF_XLAUI; 799 break; 800 case phymodInterfaceXLPPI: 801 *pif = SOC_PORT_IF_XLPPI; 802 break; 803 case phymodInterfaceXFI: 804 *pif = SOC_PORT_IF_XFI; 805 break; 806 case phymodInterfaceSFI: 807 *pif = SOC_PORT_IF_SFI; 808 break; 809 case phymodInterfaceCR4: 810 *pif = SOC_PORT_IF_CR4; 811 break; 812 case phymodInterfaceSR: 813 *pif = SOC_PORT_IF_SR; 814 break; 815 case phymodInterfaceLR: 816 *pif = SOC_PORT_IF_LR; 817 break; 818 case phymodInterfaceSR4: 819 *pif = SOC_PORT_IF_SR4; 820 break; 821 case phymodInterfaceLR4: 822 *pif = SOC_PORT_IF_LR4; 823 break; 824 case phymodInterfaceSR10: 825 *pif = SOC_PORT_IF_SR10; 826 break; 827 case phymodInterfaceKR10: 828 *pif = SOC_PORT_IF_KR10; 829 break; 830 case phymodInterfaceLR10: 831 *pif = SOC_PORT_IF_LR10; 832 break; 833 case phymodInterfaceCR10: 834 *pif = SOC_PORT_IF_CR10; 835 break; 836 case phymodInterfaceCAUI4_C2C: 837 *pif = SOC_PORT_IF_CAUI_C2C; 838 break; 839 case phymodInterfaceCAUI4_C2M: 840 *pif = SOC_PORT_IF_CAUI_C2M; 841 break; 842 case phymodInterfaceCAUI: 843 *pif = SOC_PORT_IF_CAUI; 844 break; 845 case phymodInterfaceVSR: 846 *pif = SOC_PORT_IF_VSR; 847 break; 848 default: 849 break; 850 } 851 852 /* 853 * We need to depend on software state here since 854 * LR/LR4/SR/SR4 looks same in hardware 855 */ 856 857 /* *pif = pCfg->speed_config.line_interface; */ 858 859 return (SOC_E_NONE); 860 } 861 862 /* 863 * Function: 864 * phy82864_reg_read 865 * Purpose: 866 * Routine to read PHY register 867 * Parameters: 868 * unit - BCM unit number 869 * port - Port number 870 * flags - Flags which specify the register type 871 * phy_reg_addr - Encoded register address 872 * phy_data - (OUT) Value read from PHY register 873 * Note: 874 * This register read function is not thread safe. Higher level 875 * function that calls this function must obtain a per port lock 876 * to avoid overriding register page mapping between threads. 877 */ 878 STATIC int 879 phy82864_reg_read(int unit, soc_port_t port, uint32 flags, 880 uint32 phy_reg_addr, uint32 *phy_reg_data) 881 { 882 phy_ctrl_t *pc; 883 soc_phymod_ctrl_t *pmc; 884 phymod_phy_access_t *pm_phy; 885 int idx = 0; 886 uint8 data8 = 0; 887 888 pc = EXT_PHY_SW_STATE(unit, port); 889 if (pc == NULL) { 890 return SOC_E_INTERNAL; 891 } 892 893 pmc = &pc->phymod_ctrl; 894 idx = pmc->main_phy ; 895 pm_phy = &pmc->phy[idx]->pm_phy; 896 if (flags & SOC_PHY_I2C_DATA8) { 897 SOC_IF_ERROR_RETURN 898 (phymod_phy_i2c_read(pm_phy, 0, SOC_PHY_I2C_DEVAD(phy_reg_addr), SOC_PHY_I2C_REGAD(phy_reg_addr), 1, &data8)); 899 *phy_reg_data = data8; 900 } else { 901 SOC_IF_ERROR_RETURN 902 (phymod_phy_reg_read(pm_phy, phy_reg_addr, phy_reg_data)); 903 } 904 return SOC_E_NONE; 905 } 906 907 /* 908 * Function: 909 * phy82864_reg_write 910 * Purpose: 911 * Routine to write PHY register 912 * Parameters: 913 * uint - BCM unit number 914 * pc - PHY state 915 * flags - Flags which specify the register type 916 * phy_reg_addr - Encoded register address 917 * phy_data - Value write to PHY register 918 * Note: 919 * This register read function is not thread safe. Higher level 920 * function that calls this function must obtain a per port lock 921 * to avoid overriding register page mapping between threads. 922 */ 923 STATIC int 924 phy82864_reg_write(int unit, soc_port_t port, uint32 flags, 925 uint32 phy_reg_addr, uint32 phy_reg_data) 926 { 927 phy_ctrl_t *pc; 928 soc_phymod_ctrl_t *pmc; 929 phymod_phy_access_t *pm_phy; 930 int idx = 0; 931 uint8 data8 = 0; 932 933 data8 = (uint8)phy_reg_data ; 934 pc = EXT_PHY_SW_STATE(unit, port); 935 if (pc == NULL) { 936 return SOC_E_INTERNAL; 937 } 938 939 pmc = &pc->phymod_ctrl; 940 for (idx = 0; idx < pmc->num_phys; idx++) { 941 pm_phy = &pmc->phy[idx]->pm_phy; 942 if (flags & SOC_PHY_I2C_DATA8) { 943 SOC_IF_ERROR_RETURN 944 (phymod_phy_i2c_write(pm_phy, 0, SOC_PHY_I2C_DEVAD(phy_reg_addr), SOC_PHY_I2C_REGAD(phy_reg_addr), 1, &data8)); 945 } else { 946 SOC_IF_ERROR_RETURN 947 (phymod_phy_reg_write(pm_phy, phy_reg_addr, phy_reg_data)); 948 } 949 } 950 return SOC_E_NONE; 951 } 952 953 /* 954 * Function: 955 * phy82864_reg_modify 956 * Purpose: 957 * Routine to write PHY register 958 * Parameters: 959 * uint - BCM unit number 960 * pc - PHY state 961 * flags - Flags which specify the register type 962 * phy_reg_addr - Encoded register address 963 * phy_mo_data - New value for the bits specified in phy_mo_mask 964 * phy_mo_mask - Bit mask to modify 965 * Note: 966 * This function is not thread safe. Higher level 967 * function that calls this function must obtain a per port lock 968 * to avoid overriding register page mapping between threads. 969 */ 970 STATIC int 971 phy82864_reg_modify(int unit, soc_port_t port, uint32 flags, 972 uint32 phy_reg_addr, uint32 phy_data, 973 uint32 phy_data_mask) 974 { 975 phy_ctrl_t *pc; 976 soc_phymod_ctrl_t *pmc; 977 phymod_phy_access_t *pm_phy; 978 uint32 data32 = 0, tmp = 0; 979 int idx = 0; 980 981 pc = EXT_PHY_SW_STATE(unit, port); 982 if (pc == NULL) { 983 return SOC_E_INTERNAL; 984 } 985 986 pmc = &pc->phymod_ctrl; 987 for (idx = 0; idx < pmc->num_phys; idx++) { 988 pm_phy = &pmc->phy[idx]->pm_phy; 989 SOC_IF_ERROR_RETURN 990 (phymod_phy_reg_read(pm_phy, phy_reg_addr, &data32)); 991 tmp = data32; 992 data32 &= ~(phy_data_mask); 993 data32 |= (phy_data & phy_data_mask); 994 if (data32 != tmp) { 995 SOC_IF_ERROR_RETURN 996 (phymod_phy_reg_write(pm_phy, phy_reg_addr, data32)); 997 } 998 } 999 1000 return SOC_E_NONE; 1001 } 1002 1003 STATIC void 1004 phy82864_core_init(phy_ctrl_t *pc, soc_phymod_core_t *core, 1005 phymod_bus_t *core_bus, uint32 core_addr) 1006 { 1007 phymod_core_access_t *pm_core; 1008 phymod_access_t *pm_acc; 1009 1010 core->unit = pc->unit; 1011 core->port = pc->port; 1012 core->read = pc->read; 1013 core->write = pc->write; 1014 core->wrmask = pc->wrmask; 1015 1016 pm_core = &core->pm_core; 1017 phymod_core_access_t_init(pm_core); 1018 pm_acc = &pm_core->access; 1019 phymod_access_t_init(pm_acc); 1020 PHYMOD_ACC_USER_ACC(pm_acc) = core; 1021 PHYMOD_ACC_BUS(pm_acc) = core_bus; 1022 PHYMOD_ACC_ADDR(pm_acc) = core_addr; 1023 1024 if (soc_property_port_get(pc->unit, pc->port, "phy82864", 0) == 45) { 1025 PHYMOD_ACC_F_CLAUSE45_SET(pm_acc); 1026 } 1027 1028 return; 1029 } 1030 1031 STATIC int 1032 _phy82864_device_create_attach(soc_phymod_core_t *core, uint32_t core_id) 1033 { 1034 phy82864_device_aux_mode_t *new_device ; 1035 new_device = sal_alloc(sizeof(phy82864_device_aux_mode_t), "phy82864_device_aux_mode"); 1036 if (new_device == NULL) { 1037 return SOC_E_MEMORY; 1038 } 1039 sal_memset(new_device, 0 ,sizeof(phy82864_device_aux_mode_t)); 1040 1041 new_device->core_id = core_id ; 1042 core->device_aux_modes = (void *)new_device ; 1043 1044 return SOC_E_NONE; 1045 } 1046 1047 STATIC int 1048 _phy82864_device_destroy(phy82864_device_aux_mode_t *device) 1049 { 1050 if (device == NULL) { 1051 return SOC_E_PARAM; 1052 } 1053 sal_free(device); 1054 1055 return SOC_E_NONE; 1056 } 1057 1058 STATIC void 1059 phy82864_cleanup(soc_phymod_ctrl_t *pmc) 1060 { 1061 int idx = 0; 1062 soc_phymod_phy_t *phy; 1063 soc_phymod_core_t *core; 1064 phy82864_device_aux_mode_t *device ; 1065 1066 for (idx = 0; idx < pmc->num_phys ; idx++) { 1067 phy = pmc->phy[idx]; 1068 if (phy == NULL) { 1069 LOG_WARN(BSL_LS_SOC_PHY, 1070 (BSL_META_U(pmc->unit, 1071 "phy object is empty"))); 1072 continue; 1073 } 1074 1075 core = phy->core; 1076 if (core != NULL) { 1077 device = (phy82864_device_aux_mode_t *)core->device_aux_modes ; 1078 } 1079 /* Destroy core object if not used anymore */ 1080 if (core && core->ref_cnt) { 1081 if (--core->ref_cnt == 0) { 1082 PHYMOD_VDBG(PHY82864_DBG_MEM, NULL,("clean_up device=%p core_p=%p\n", (void *)device, (void *)core)) ; 1083 _phy82864_device_destroy(device) ; 1084 soc_phymod_core_destroy(pmc->unit, core); 1085 } 1086 } 1087 1088 /* Destroy phy object */ 1089 if (phy) { 1090 PHYMOD_VDBG(PHY82864_DBG_MEM, NULL,("clean_up phy=%p\n", (void *)phy)) ; 1091 soc_phymod_phy_destroy(pmc->unit, phy); 1092 } 1093 } 1094 pmc->num_phys = 0; 1095 } 1096 1097 STATIC int32 1098 _phy_82864_chip_id_get(phymod_phy_access_t *pm_phy, uint32 *chip_id) 1099 { 1100 uint32 chip_id_msb = 0, chip_id_lsb = 0; 1101 1102 1103 SOC_IF_ERROR_RETURN( 1104 phymod_phy_reg_read(pm_phy, 0x8b01, &chip_id_msb)); 1105 1106 chip_id_msb = (chip_id_msb & 0xF000) >> 12; 1107 1108 SOC_IF_ERROR_RETURN( 1109 phymod_phy_reg_read(pm_phy, 0x8b00, &chip_id_lsb)); 1110 1111 if (chip_id_msb == 0x8) { 1112 if (chip_id_lsb == 0x2864) { 1113 *chip_id = 0x82864; 1114 } 1115 } 1116 1117 return SOC_E_NONE; 1118 } 1119 1120 /* 1121 * Function: 1122 * phy82864_speed_to_lane_map_get 1123 * Purpose: 1124 * Mapping to speed to lane map based on config 1125 * Parameters: 1126 * pc - phy_ctrl_t 1127 * line_lane_map - [OUT] Line Lane map 1128 * sys_lane_map - [OUT] Sys Lane map 1129 * Returns: 1130 * SOC_E_NONE 1131 */ 1132 1133 1134 STATIC int 1135 _phy82864_speed_to_lane_map_get(phy_ctrl_t *pc, uint32 *line_lane_map, uint32 *sys_lane_map) 1136 { 1137 int phy_gearbox_enable = 0; 1138 int phy_pin_compatibility_enable = 0; 1139 1140 phy_gearbox_enable = soc_property_port_get(pc->unit, pc->port, spn_PHY_GEARBOX_ENABLE, FALSE); 1141 phy_pin_compatibility_enable = soc_property_port_get(pc->unit, pc->port, "phy_alt_datapath_mode", FALSE); 1142 1143 /* phy_gearbox_enable should be "1" or "0" */ 1144 /* phy_pin_compatibility_enable should be "1" or "0" */ 1145 if (((phy_gearbox_enable != TRUE) && (phy_gearbox_enable != FALSE)) || 1146 ((phy_pin_compatibility_enable != TRUE) && (phy_pin_compatibility_enable != FALSE))) { 1147 LOG_ERROR(BSL_LS_SOC_PHY,(BSL_META_U(0, 1148 "Error: Could not set port %d information: Invalid parameter.\n"), 1149 pc->port)); 1150 return SOC_E_PARAM; 1151 } 1152 1153 *line_lane_map = 0xF; 1154 *sys_lane_map = 0xF; 1155 switch(pc->speed_max) { 1156 case PHY82864_SPD_100G: 1157 case PHY82864_SPD_106G: 1158 if ((phy_pin_compatibility_enable == TRUE)) { 1159 *line_lane_map = 0xf0; 1160 } else { 1161 *line_lane_map = 0xf; 1162 } 1163 *sys_lane_map = 0xf; 1164 break; 1165 case PHY82864_SPD_40G: 1166 case PHY82864_SPD_42G: 1167 case PHY82864_SPD_50G: 1168 /* phy_gearbox_enable should be "1" or "0" */ 1169 /* phy_pin_compatibility_enable should be "1" or "0" */ 1170 /* phy_pin_compatibility_enable = 1 is valid only when pass_thru is set */ 1171 if ((phy_gearbox_enable != TRUE) && (phy_pin_compatibility_enable != TRUE)) { 1172 if ( SOC_INFO(pc->unit).port_num_lanes[pc->port] == 2 ) { 1173 if (pc->lane_num > 1) { 1174 *line_lane_map = 0xc; 1175 *sys_lane_map = 0xc; 1176 } else { 1177 *line_lane_map = 0x3; 1178 *sys_lane_map = 0x3; 1179 } 1180 } else { 1181 *line_lane_map = 0xf; 1182 *sys_lane_map = 0xf; 1183 } 1184 pc->phy_mode = PHYCTRL_QUAD_LANE_PORT; 1185 } else if ((phy_gearbox_enable != TRUE) && (phy_pin_compatibility_enable == TRUE)) { 1186 if ( SOC_INFO(pc->unit).port_num_lanes[pc->port] == 2 ) { 1187 if (pc->lane_num > 1) { 1188 *line_lane_map = 0xc0; 1189 *sys_lane_map = 0xc; 1190 } else { 1191 *line_lane_map = 0x30; 1192 *sys_lane_map = 0x3; 1193 } 1194 } else { 1195 *line_lane_map = 0xf0; 1196 *sys_lane_map = 0xf; 1197 } 1198 pc->phy_mode = PHYCTRL_QUAD_LANE_PORT; 1199 } else if ((phy_gearbox_enable == TRUE) && (phy_pin_compatibility_enable != TRUE)) { 1200 if (pc->lane_num > 1) { 1201 *line_lane_map = 0xf0; 1202 *sys_lane_map = 0xc; 1203 } else { 1204 *line_lane_map = 0xf; 1205 *sys_lane_map = 0x3; 1206 } 1207 pc->phy_mode = PHYCTRL_QUAD_LANE_PORT; 1208 } else { 1209 LOG_ERROR(BSL_LS_SOC_PHY,(BSL_META_U(0, 1210 "Error: Could not set port %d information: Invalid parameter.\n"), 1211 pc->port)); 1212 return SOC_E_PARAM; 1213 } 1214 break; 1215 case PHY82864_SPD_1G: 1216 case PHY82864_SPD_10G: 1217 case PHY82864_SPD_11G: 1218 case PHY82864_SPD_25G: 1219 if ((phy_gearbox_enable != TRUE) && (phy_pin_compatibility_enable == TRUE)) { 1220 *line_lane_map = 0x10; 1221 *line_lane_map <<= pc->lane_num; 1222 *sys_lane_map = 0x1; 1223 *sys_lane_map <<= pc->lane_num; 1224 } else if (phy_gearbox_enable != TRUE) { 1225 *line_lane_map = 0x1; 1226 *line_lane_map <<= pc->lane_num; 1227 *sys_lane_map = 0x1; 1228 *sys_lane_map <<= pc->lane_num; 1229 } else { 1230 return SOC_E_PARAM; 1231 } 1232 pc->phy_mode = PHYCTRL_ONE_LANE_PORT; 1233 break; 1234 default: 1235 return SOC_E_PARAM; 1236 } 1237 1238 return SOC_E_NONE; 1239 } 1240 1241 /* 1242 * Function: 1243 * phy82864_probe 1244 * Purpose: 1245 * xx 1246 * Parameters: 1247 * pc->phy_id (IN) 1248 * pc->unit (IN) 1249 * pc->port (IN) 1250 * pc->size (OUT) - memory required by phy port 1251 * pc->dev_name (OUT) - set to port device name 1252 * 1253 * Note: 1254 */ 1255 STATIC int 1256 phy82864_probe(int unit, phy_ctrl_t *pc) 1257 { 1258 int rv, idx; 1259 uint32 num_phys, core_id, phy_id, found = 0; 1260 uint32 line_lane_map, sys_lane_map; 1261 phymod_bus_t core_bus; 1262 phymod_dispatch_type_t phy_type; 1263 phymod_core_access_t *pm_core; 1264 phymod_phy_access_t *pm_phy; 1265 phymod_access_t *pm_acc; 1266 soc_phymod_ctrl_t *pmc; 1267 soc_phymod_phy_t *phy; 1268 soc_phymod_core_t *core; 1269 soc_phymod_core_t core_probe; 1270 soc_info_t *si; 1271 phyident_core_info_t core_info[8]; 1272 int array_max = 8; 1273 int array_size = 0; 1274 int port; 1275 int phy_port; /* physical port number */ 1276 /* Initialize PHY bus */ 1277 SOC_IF_ERROR_RETURN(phymod_bus_t_init(&core_bus)); 1278 core_bus.bus_name = "phy82864"; 1279 core_bus.read = _phy82864_reg_read; 1280 core_bus.write = _phy82864_reg_write; 1281 1282 #ifdef PORTMOD_SUPPORT 1283 /* If portmod feature is enabled let the 1284 * * PM take care of phy control*/ 1285 1286 if (soc_feature(unit, soc_feature_portmod)) { 1287 return SOC_E_NOT_FOUND; 1288 } 1289 #endif/* PORTMOD_SUPPORT */ 1290 1291 /* Configure PHY bus properties */ 1292 if (pc->wrmask) { 1293 PHYMOD_BUS_CAP_WR_MODIFY_SET(&core_bus); 1294 PHYMOD_BUS_CAP_LANE_CTRL_SET(&core_bus); 1295 } 1296 1297 port = pc->port; 1298 pmc = &pc->phymod_ctrl; 1299 si = &SOC_INFO(unit); 1300 if (soc_feature(unit, soc_feature_logical_port_num)) { 1301 phy_port = si->port_l2p_mapping[port]; 1302 } else { 1303 phy_port = port; 1304 } 1305 1306 /* Install clean up function */ 1307 pmc->unit = pc->unit; 1308 pmc->cleanup = phy82864_cleanup; 1309 /*pmc->symbols = &bcmi_tscf_xgxs_symbols;*/ 1310 1311 1312 pc->lane_num = SOC_PORT_BINDEX(unit, phy_port); 1313 pc->chip_num = SOC_BLOCK_NUMBER(unit, SOC_PORT_BLOCK(unit, phy_port)); 1314 1315 /* request memory for the configuration structure */ 1316 pc->size = sizeof(phy82864_config_t); 1317 1318 /* Bit N corresponds to lane N in lane_map */ 1319 num_phys = 1; 1320 SOC_IF_ERROR_RETURN 1321 (_phy82864_speed_to_lane_map_get(pc, &line_lane_map, &sys_lane_map)); 1322 1323 /* we need to get the other core id if more than 1 core per port */ 1324 if (num_phys > 1) { 1325 /* get the other core address */ 1326 SOC_IF_ERROR_RETURN 1327 /* 1328 * COVERITY 1329 * This is unreachable. It is kept intentionally as a defensive 1330 * default for future development. 1331 */ 1332 /* coverity[dead_error_begin] */ 1333 (soc_phy_addr_multi_get(unit, port, array_max, &array_size, &core_info[0])); 1334 } else { 1335 core_info[0].mdio_addr = pc->phy_id; 1336 } 1337 1338 phy_type = phymodDispatchTypeMadura; 1339 1340 /* Probe cores */ 1341 for (idx = 0; idx < num_phys ; idx++) { 1342 phy82864_core_init(pc, &core_probe, &core_bus, 1343 core_info[idx].mdio_addr); 1344 /* Check that core is indeed an madura core */ 1345 pm_core = &core_probe.pm_core; 1346 pm_core->type = phy_type; 1347 rv = phymod_core_identify(pm_core, 0, &found); 1348 if (SOC_FAILURE(rv)) { 1349 LOG_WARN(BSL_LS_SOC_PHY, 1350 (BSL_META_U(unit, 1351 "port %d: ERROR!!!\n"), 1352 pc->port)); 1353 1354 return rv; 1355 } 1356 if (!found) { 1357 LOG_WARN(BSL_LS_SOC_PHY, 1358 (BSL_META_U(unit, 1359 "port %d: NOT FOUND!!\n"), 1360 pc->port)); 1361 1362 return SOC_E_NOT_FOUND; 1363 } 1364 } 1365 1366 rv = SOC_E_NONE; 1367 for (idx = 0; idx < num_phys ; idx++) { 1368 /* Set core and phy IDs based on PHY address */ 1369 core_id = pc->phy_id + idx; 1370 phy_id = (line_lane_map << 16) | core_id; 1371 1372 /* Create PHY object */ 1373 rv = soc_phymod_phy_create(unit, phy_id, &pmc->phy[idx]); 1374 if (SOC_FAILURE(rv)) { 1375 break; 1376 } 1377 pmc->num_phys++; 1378 1379 /* Initialize phy object */ 1380 phy = pmc->phy[idx]; 1381 pm_phy = &phy->pm_phy; 1382 phymod_phy_access_t_init(pm_phy); 1383 1384 /* Find or create associated core object */ 1385 rv = soc_phymod_core_find_by_id(unit, core_id, &phy->core); 1386 if (rv == SOC_E_NOT_FOUND) { 1387 rv = soc_phymod_core_create(unit, core_id, &phy->core); 1388 rv |= _phy82864_device_create_attach(phy->core, core_id) ; 1389 } 1390 if (SOC_FAILURE(rv)) { 1391 break; 1392 } 1393 } 1394 if (SOC_FAILURE(rv)) { 1395 phy82864_cleanup(pmc); 1396 return rv; 1397 } 1398 1399 for (idx = 0; idx < pmc->num_phys ; idx++) { 1400 phy = pmc->phy[idx]; 1401 core = phy->core; 1402 pm_core = &core->pm_core; 1403 1404 /* Initialize core object if newly created */ 1405 if (core->ref_cnt == 0) { 1406 sal_memcpy(&core->pm_bus, &core_bus, sizeof(core->pm_bus)); 1407 phy82864_core_init(pc, core, &core->pm_bus, 1408 core_info[idx].mdio_addr); 1409 /* Set dispatch type */ 1410 pm_core->type = phy_type; 1411 } 1412 core->ref_cnt++; 1413 1414 /* Initialize phy access based on associated core */ 1415 pm_acc = &phy->pm_phy.access; 1416 sal_memcpy(pm_acc, &pm_core->access, sizeof(*pm_acc)); 1417 phy->pm_phy.type = phy_type; 1418 PHYMOD_ACC_LANE_MASK(pm_acc) = line_lane_map; 1419 } 1420 1421 return SOC_E_NONE; 1422 } 1423 1424 1425 /* 1426 * Function: 1427 * phy82864_config_init 1428 * Purpose: 1429 * Determine phy configuration data for purposes of PHYMOD initialization. 1430 * 1431 * A side effect of this procedure is to save some per-logical port 1432 * information in (phy82864_cfg_t *) &pc->driver_data; 1433 * 1434 * Parameters: 1435 * unit - BCM unit number. 1436 * port - Port number. 1437 * logical_lane_offset - starting logical lane number 1438 * Returns: 1439 * SOC_E_NONE 1440 */ 1441 STATIC int 1442 phy82864_config_init(int unit, soc_port_t port, int logical_lane_offset, 1443 phymod_core_init_config_t *core_init_config, 1444 phymod_phy_init_config_t *pm_phy_init_config) 1445 { 1446 phy_ctrl_t *pc; 1447 phy82864_speed_config_t *speed_config; 1448 phy82864_config_t *pCfg; 1449 phymod_firmware_load_method_t fw_ld_method; 1450 int port_num_lanes; 1451 int core_num; 1452 int phy_num_lanes; 1453 1454 pc = EXT_PHY_SW_STATE(unit, port); 1455 if (pc == NULL) { 1456 return SOC_E_INTERNAL; 1457 } 1458 pCfg = (phy82864_config_t *) pc->driver_data; 1459 1460 port_num_lanes = SOC_INFO(unit).port_num_lanes[port]; 1461 1462 /* figure out how many lanes are in this phy */ 1463 core_num = (logical_lane_offset / 4); 1464 phy_num_lanes = (port_num_lanes - logical_lane_offset); 1465 if (phy_num_lanes > MAX_NUM_LANES) { 1466 phy_num_lanes = MAX_NUM_LANES; 1467 } 1468 1469 /*CORE configuration*/ 1470 phymod_core_init_config_t_init(core_init_config); 1471 fw_ld_method = phymodFirmwareLoadMethodInternal; 1472 if (soc_property_port_get(pc->unit, pc->port, "82864_glue", 0)) { 1473 fw_ld_method = phymodFirmwareLoadMethodNone; 1474 } 1475 1476 core_init_config->firmware_load_method = soc_property_port_get(unit, port, 1477 spn_LOAD_FIRMWARE, fw_ld_method); 1478 core_init_config->firmware_load_method &= 0xff; /* clear checksum bits */ 1479 core_init_config->lane_map.num_of_lanes = NUM_LANES; 1480 core_init_config->flags = PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY; 1481 speed_config = &(pCfg->speed_config); 1482 speed_config->port_refclk_int = 156; 1483 speed_config->port_num_lanes = phy_num_lanes; 1484 speed_config->speed = pc->speed_max; 1485 1486 if (port_num_lanes == 4) { /* 100G/106G/40G/42G PT */ 1487 speed_config->line_interface = SOC_PORT_IF_KR4; 1488 } else if (port_num_lanes == 1) { /* 10G/11G */ 1489 speed_config->line_interface = SOC_PORT_IF_SR; 1490 } else if (port_num_lanes == 2) { /* 40G/42G (2-lane) PT */ 1491 speed_config->line_interface = SOC_PORT_IF_KR2; 1492 if(soc_property_port_get(unit, port, spn_PHY_GEARBOX_ENABLE, FALSE)) { 1493 speed_config->line_interface = SOC_PORT_IF_KR4; 1494 } 1495 } else { 1496 LOG_CLI((BSL_META_U(unit,"Invalid number of lanes:%d\n "), port_num_lanes)); 1497 return SOC_E_CONFIG; 1498 } 1499 1500 /* PHY configuration */ 1501 phymod_phy_init_config_t_init(pm_phy_init_config); 1502 1503 pm_phy_init_config->polarity.rx_polarity 1504 = soc_property_port_get(unit, port, 1505 spn_PHY_RX_POLARITY_FLIP, 1506 0xFFFF); 1507 pm_phy_init_config->polarity.tx_polarity 1508 = soc_property_port_get(unit, port, 1509 spn_PHY_TX_POLARITY_FLIP, 1510 0xFFFF); 1511 1512 /* phy_ctrl_t configuration (LOGICAL PORT BASED) 1513 * Only do this once, for the first core of the logical port*/ 1514 if (core_num == 0) { 1515 /* phy_mode, PHYCTRL_MDIO_ADDR_SHARE, PHY_FLAGS_INDEPENDENT_LANE */ 1516 if (port_num_lanes == 4) { 1517 pc->phy_mode = PHYCTRL_QUAD_LANE_PORT; 1518 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_INDEPENDENT_LANE); 1519 } else if (port_num_lanes == 2) { 1520 pc->phy_mode = PHYCTRL_QUAD_LANE_PORT; 1521 pc->flags |= PHYCTRL_MDIO_ADDR_SHARE; 1522 PHY_FLAGS_SET(unit, port, PHY_FLAGS_INDEPENDENT_LANE); 1523 } else if (port_num_lanes == 1) { 1524 pc->phy_mode = PHYCTRL_ONE_LANE_PORT; 1525 pc->flags |= PHYCTRL_MDIO_ADDR_SHARE; 1526 PHY_FLAGS_SET(unit, port, PHY_FLAGS_INDEPENDENT_LANE); 1527 } 1528 1529 } 1530 1531 return SOC_E_NONE; 1532 } 1533 1534 STATIC int 1535 _phy_82864_init_pass1(int unit, soc_port_t port) 1536 { 1537 phy_ctrl_t *pc; 1538 soc_phymod_ctrl_t *pmc; 1539 soc_phymod_phy_t *phy = NULL; 1540 soc_phymod_core_t *core; 1541 phy82864_config_t *pCfg; 1542 phy82864_speed_config_t *speed_config; 1543 phymod_phy_inf_config_t interface_config; 1544 phymod_core_status_t core_status; 1545 phymod_core_info_t core_info; 1546 phymod_core_firmware_info_t fw_info; 1547 int idx; 1548 int logical_lane_offset; 1549 soc_port_ability_t ability; 1550 soc_phy_info_t *pi; 1551 char *dev_name; 1552 int len = 0; 1553 uint32 chip_id = 0; 1554 int phy_force_dload = 0, dload_method = 0; 1555 uint32 line_lane_map, sys_lane_map; 1556 uint16_t repeater = 0 ; 1557 1558 pc = EXT_PHY_SW_STATE(unit, port); 1559 1560 if (pc == NULL) { 1561 return SOC_E_INTERNAL; 1562 } 1563 1564 pc->driver_data = (void*)(pc+1); 1565 pmc = &pc->phymod_ctrl; 1566 pCfg = (phy82864_config_t *) pc->driver_data; 1567 1568 sal_memset(pCfg, 0, sizeof(*pCfg)); 1569 speed_config = &(pCfg->speed_config); 1570 1571 sal_memset(&ability, 0, sizeof(ability)); 1572 1573 dev_name = DEV_NAME(pc); 1574 1575 phy = pmc->phy[0]; 1576 1577 SOC_IF_ERROR_RETURN( 1578 _phy_82864_chip_id_get(&phy->pm_phy, &chip_id)); 1579 DEVID(pc) = chip_id; 1580 1581 pi = &SOC_PHY_INFO(unit, port); 1582 if (DEVID(pc) == MADURA_ID_82864) { 1583 /* coverity[secure_coding] */ 1584 sal_strncpy (dev_name, "BCM82864", sal_strlen("BCM82864")); 1585 } else { 1586 /* coverity[secure_coding] */ 1587 sal_strncpy (dev_name, "Madura", sal_strlen("Madura")); 1588 } 1589 1590 len = sal_strlen(dev_name); 1591 1592 dev_name[len++] = '/'; 1593 dev_name[len++] = pc->lane_num + '0'; 1594 dev_name[len] = 0; 1595 pc->dev_name = dev_name; /* string terminator */ 1596 pi->phy_name = dev_name; 1597 1598 pCfg->device_cfg_aux_modes = (phy82864_device_cfg_aux_mode_t *) sal_alloc(sizeof(phy82864_device_cfg_aux_mode_t), "phy82864_device_cfg_aux_mode"); 1599 sal_memset(pCfg->device_cfg_aux_modes, 0 , sizeof(phy82864_device_cfg_aux_mode_t)); 1600 /* Loop through all phymod phys that support this SDK phy */ 1601 logical_lane_offset = 0; 1602 for (idx = 0; idx < pmc->num_phys; idx++) { 1603 phy = pmc->phy[idx]; 1604 core = phy->core; 1605 1606 pCfg->device_aux_modes = (phy82864_device_aux_mode_t *)(core->device_aux_modes) ; 1607 pCfg->device_aux_modes->an_mst_lane_p0 = soc_property_port_get(unit, port, 1608 "phy_82864_an_mst_lane_p0", 0); 1609 pCfg->device_aux_modes->an_mst_lane_p1 = soc_property_port_get(unit, port, 1610 "phy_82864_an_mst_lane_p1", 0); 1611 1612 phy_force_dload = soc_property_port_get(unit, port, 1613 spn_PHY_FORCE_FIRMWARE_LOAD, 0x11); 1614 dload_method = ((phy_force_dload & 0xF0)>>4); 1615 phy_force_dload &= 0xf; 1616 1617 /* determine configuration data structure to default values, based on SOC properties */ 1618 SOC_MADURA_IF_ERR_RETURN_FREE( pCfg->device_cfg_aux_modes , 1619 (phy82864_config_init(unit, port, 1620 logical_lane_offset, 1621 &core->init_config, &phy->init_config))); 1622 1623 speed_config->higig_port = PBMP_MEMBER(PBMP_HG_ALL(unit), port); 1624 1625 /* set the port to its max or init_speed */ 1626 SOC_MADURA_IF_ERR_RETURN_FREE( pCfg->device_cfg_aux_modes , 1627 (phy82864_speed_to_interface_config_get(speed_config, &interface_config))); 1628 sal_memcpy(&core->init_config.interface, &interface_config, sizeof(interface_config)); 1629 core->init_config.interface.device_aux_modes = (void *)pCfg->device_aux_modes; 1630 core->init_config.op_datapath = soc_property_port_get(unit, port, 1631 spn_PHY_ULL_DATAPATH, 0); 1632 repeater = soc_property_port_get(unit, port, spn_PHY_PCS_REPEATER, 1); 1633 SOC_MADURA_IF_ERR_RETURN_FREE( pCfg->device_cfg_aux_modes , 1634 (_phy82864_speed_to_lane_map_get(pc, &line_lane_map, &sys_lane_map))); 1635 core->pm_core.access.lane_mask = line_lane_map; 1636 1637 if (core->init_config.op_datapath == phymodDatapathUll) { 1638 LOG_INFO(BSL_LS_SOC_PHY, 1639 (BSL_META_U(unit,"ULL datapath is supported with repeater mode only," 1640 "so configuring ULL+repeater alone on port:%d. Disable ULL to set Repeater/Retimer only modes\n "), port)); 1641 } 1642 1643 if (!core->init) { 1644 core_status.pmd_active = 0; 1645 if (dload_method == phymodFirmwareLoadMethodInternal && (phy_force_dload == phymodFirmwareLoadForce|| \ 1646 phy_force_dload == phymodFirmwareLoadAuto )) { 1647 core->init_config.firmware_load_method = phymodFirmwareLoadMethodInternal; 1648 pc->flags |= PHYCTRL_MDIO_BCST; 1649 if(phy_force_dload == phymodFirmwareLoadForce) 1650 { 1651 PHYMOD_CORE_INIT_F_FW_FORCE_DOWNLOAD_SET(&(core->init_config)); 1652 }else if(phy_force_dload == phymodFirmwareLoadAuto){ 1653 PHYMOD_CORE_INIT_F_FW_AUTO_DOWNLOAD_SET(&(core->init_config)); 1654 } 1655 } else if ((phy_force_dload == phymodFirmwareLoadForce || phy_force_dload == phymodFirmwareLoadAuto)\ 1656 && (dload_method == phymodFirmwareLoadMethodExternal || dload_method == phymodFirmwareLoadMethodProgEEPROM )) { 1657 core->init_config.firmware_load_method = phymodFirmwareLoadMethodProgEEPROM; 1658 SOC_MADURA_IF_ERR_RETURN_FREE( pCfg->device_cfg_aux_modes , 1659 (phymod_core_init(&core->pm_core, &core->init_config, &core_status))); 1660 } else if (dload_method == phymodFirmwareLoadMethodNone) { 1661 core->init_config.firmware_load_method = phymodFirmwareLoadMethodNone; 1662 SOC_MADURA_IF_ERR_RETURN_FREE( pCfg->device_cfg_aux_modes , 1663 (phymod_core_firmware_info_get(&core->pm_core, &fw_info))); 1664 if (fw_info.fw_version == 0) { 1665 LOG_CLI((BSL_META_U(unit, "No FW found on the chip, Please use" 1666 "spn_PHY_FORCE_FIRMWARE_LOAD as 0x11 to download FW to chip"))); 1667 sal_free(pCfg->device_cfg_aux_modes); 1668 return SOC_E_UNAVAIL; 1669 } 1670 } 1671 core->init = TRUE; 1672 } 1673 if (repeater == 1) { 1674 phy->init_config.op_mode = phymodOperationModeRepeater; 1675 } else { 1676 phy->init_config.op_mode = phymodOperationModeRetimer; 1677 } 1678 1679 /*read serdes id info */ 1680 SOC_MADURA_IF_ERR_RETURN_FREE( pCfg->device_cfg_aux_modes , 1681 (phymod_core_info_get(&core->pm_core, &core_info))); 1682 1683 /* for multicore phys, need to ratchet up to the next batch of lanes */ 1684 logical_lane_offset += core->init_config.lane_map.num_of_lanes; 1685 } 1686 1687 /* indicate second pass of init is needed */ 1688 if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) { 1689 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS2); 1690 } 1691 1692 return SOC_E_NONE; 1693 } 1694 void phy82864_phyctrl_to_phymod_interface (uint16_t sys_if, phymod_interface_t *sys_intf) 1695 { 1696 switch (sys_if) 1697 { 1698 case SOC_PORT_IF_XFI: 1699 *sys_intf = phymodInterfaceXFI; 1700 break; 1701 case SOC_PORT_IF_SFI: 1702 *sys_intf = phymodInterfaceSFI; 1703 break; 1704 case SOC_PORT_IF_KR: 1705 *sys_intf = phymodInterfaceKR; 1706 break; 1707 case SOC_PORT_IF_KR4: 1708 *sys_intf = phymodInterfaceKR4; 1709 break; 1710 case SOC_PORT_IF_CR: 1711 *sys_intf = phymodInterfaceCR; 1712 break; 1713 case SOC_PORT_IF_CR4: 1714 *sys_intf = phymodInterfaceCR4; 1715 break; 1716 case SOC_PORT_IF_XLAUI: 1717 *sys_intf = phymodInterfaceXLAUI; 1718 break; 1719 case SOC_PORT_IF_XLPPI: 1720 *sys_intf = phymodInterfaceXLPPI; 1721 break; 1722 case SOC_PORT_IF_SR: 1723 *sys_intf = phymodInterfaceSR; 1724 break; 1725 case SOC_PORT_IF_VSR: 1726 *sys_intf = phymodInterfaceVSR; 1727 break; 1728 case SOC_PORT_IF_CAUI: 1729 *sys_intf = phymodInterfaceCAUI; 1730 break; 1731 case SOC_PORT_IF_CAUI_C2C: 1732 *sys_intf = phymodInterfaceCAUI4_C2C; 1733 break; 1734 case SOC_PORT_IF_CAUI_C2M: 1735 *sys_intf = phymodInterfaceCAUI4_C2M; 1736 break; 1737 case SOC_PORT_IF_LR: 1738 *sys_intf = phymodInterfaceLR; 1739 break; 1740 case SOC_PORT_IF_LR4: 1741 *sys_intf = phymodInterfaceLR4; 1742 break; 1743 case SOC_PORT_IF_SR4: 1744 *sys_intf = phymodInterfaceSR4; 1745 break; 1746 case SOC_PORT_IF_KX: 1747 *sys_intf = phymodInterfaceKX; 1748 break; 1749 case SOC_PORT_IF_KR2: 1750 *sys_intf = phymodInterfaceKR2; 1751 break; 1752 case SOC_PORT_IF_CR2: 1753 *sys_intf = phymodInterfaceCR2; 1754 break; 1755 case SOC_PORT_IF_SR2: 1756 *sys_intf = phymodInterfaceSR2; 1757 break; 1758 case SOC_PORT_IF_LR2: 1759 *sys_intf = phymodInterfaceLR2; 1760 break; 1761 case SOC_PORT_IF_XLAUI2: 1762 *sys_intf = phymodInterfaceXLAUI2; 1763 break; 1764 default: 1765 *sys_intf = phymodInterfaceKR; 1766 } 1767 1768 } 1769 1770 STATIC int 1771 _phy_82864_init_pass2(int unit, soc_port_t port) 1772 { 1773 phy_ctrl_t *int_pc; 1774 phy_ctrl_t *pc; 1775 soc_phymod_ctrl_t *pmc; 1776 soc_phymod_phy_t *phy = NULL; 1777 phy82864_config_t *pCfg; 1778 phy82864_speed_config_t *speed_config; 1779 phymod_phy_inf_config_t interface_config; 1780 soc_port_ability_t ability; 1781 uint16_t sys_if = 0; 1782 phymod_interface_t sys_intf = 0; 1783 uint32 line_lane_map, sys_lane_map; 1784 1785 int_pc = INT_PHY_SW_STATE(unit, port); 1786 pc = EXT_PHY_SW_STATE(unit, port); 1787 1788 if (pc == NULL) { 1789 return SOC_E_INTERNAL; 1790 } 1791 1792 sal_memset(&ability, 0, sizeof(ability)); 1793 pc->driver_data = (void*)(pc+1); 1794 pmc = &pc->phymod_ctrl; 1795 pCfg = (phy82864_config_t *) pc->driver_data; 1796 1797 speed_config = &(pCfg->speed_config); 1798 phy = pmc->phy[0]; 1799 1800 SOC_IF_ERROR_RETURN 1801 (phy82864_speed_to_interface_config_get(speed_config, &interface_config)); 1802 1803 interface_config.device_aux_modes = (void *) pCfg->device_cfg_aux_modes; 1804 pCfg->device_cfg_aux_modes->pass_thru = !(soc_property_port_get(unit, port, spn_PHY_GEARBOX_ENABLE, FALSE)); 1805 pCfg->device_cfg_aux_modes->alternate = 1806 soc_property_port_get( 1807 unit, port, "phy_alt_datapath_mode", FALSE); 1808 phy->init_config.interface = interface_config; 1809 1810 if (pCfg->device_cfg_aux_modes->pass_thru) { 1811 if (speed_config->port_num_lanes == 2) { 1812 pCfg->device_cfg_aux_modes->pass_thru_dual_lane = 1; 1813 } 1814 } 1815 phy->init_config.interface.device_aux_modes = pCfg->device_cfg_aux_modes; 1816 SOC_IF_ERROR_RETURN 1817 (phymod_phy_init(&phy->pm_phy, &phy->init_config)); 1818 1819 SOC_IF_ERROR_RETURN 1820 (_phy82864_speed_to_lane_map_get(pc, &line_lane_map, &sys_lane_map)); 1821 pCfg->sys_lane_map = sys_lane_map; 1822 /* Config Sys interface*/ 1823 sys_if = speed_config->line_interface; 1824 sys_if = soc_property_port_get(unit, port, spn_PHY_SYS_INTERFACE, sys_if); 1825 if (sys_if) { 1826 phy82864_phyctrl_to_phymod_interface(sys_if, &sys_intf); 1827 if (sys_intf == 0) { 1828 return SOC_E_PARAM; 1829 } 1830 phy->pm_phy.access.flags |= (1 << 31); 1831 phy->pm_phy.access.lane_mask = sys_lane_map; 1832 interface_config.interface_type = sys_intf; 1833 1834 SOC_IF_ERROR_RETURN 1835 (phymod_phy_interface_config_set(&phy->pm_phy, 1836 0 /* flags */, &interface_config)); 1837 1838 phy->pm_phy.access.flags &= ~(1 << 31); 1839 phy->pm_phy.access.lane_mask = line_lane_map; 1840 1841 if (int_pc != NULL) { 1842 SOC_IF_ERROR_RETURN(PHY_INTERFACE_SET(int_pc->pd, unit, port, sys_if)); 1843 } 1844 } 1845 1846 /* setup the port's an cap */ 1847 SOC_IF_ERROR_RETURN 1848 (phy_82864_ability_local_get(unit, port, &ability)); 1849 1850 LOG_INFO(BSL_LS_SOC_PHY, 1851 (BSL_META_U(pc->unit, 1852 "phy82864_init_pass2: u=%d p=%d\n"), unit, port)); 1853 1854 if (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) { 1855 /* indicate third pass of init is needed */ 1856 PHYCTRL_INIT_STATE_SET(pc,PHYCTRL_INIT_STATE_PASS3); 1857 } 1858 1859 return SOC_E_NONE; 1860 } 1861 1862 STATIC int 1863 _phy_82864_init_pass3(int unit, soc_port_t port) 1864 { 1865 phy_ctrl_t *pc; 1866 phy82864_config_t *pCfg; 1867 1868 pc = EXT_PHY_SW_STATE(unit, port); 1869 1870 if (pc == NULL) { 1871 return SOC_E_INTERNAL; 1872 } 1873 1874 pc->driver_data = (void*)(pc+1); 1875 pCfg = (phy82864_config_t *) pc->driver_data; 1876 1877 LOG_INFO(BSL_LS_SOC_PHY, 1878 (BSL_META_U(unit, 1879 "PHY82864 init pass3: u=%d p=%d\n"), unit, port)); 1880 1881 /* If configured, enable module auto detection */ 1882 pCfg->auto_mod_detect = soc_property_port_get(unit, port, spn_PHY_MOD_AUTO_DETECT, 0); 1883 if (pCfg->auto_mod_detect) { 1884 1885 } 1886 1887 return SOC_E_NONE; 1888 } 1889 1890 /* 1891 * Function: 1892 * phy_82864_init 1893 * 1894 * An SDK "phy" is a logical port, which can consist of from 1-10 lanes, 1895 * (A phy with more than 4 lanes requires more than one core). 1896 * Per-logical port information is saved in &pc->driver_data. 1897 * An SDK phy is implemented as one or more PHYMOD "phy"s. 1898 * 1899 * A PHYMOD "phy" resides completely within a single core, which can be 1900 * from 1 to 8 lanes. 1901 * Per-phymod phy information is kept in (soc_phymod_ctrl_t) *pc->phymod_ctrl 1902 * A phymod phy points to its core. Up to 4 phymod phys can be on a single core 1903 * 1904 * Purpose: 1905 * Initialize a phy82864 1906 * Parameters: 1907 * unit - BCM unit number. 1908 * port - Port number. 1909 * Returns: 1910 * SOC_E_NONE 1911 */ 1912 STATIC int 1913 phy_82864_init(int unit, soc_port_t port) 1914 { 1915 phy_ctrl_t *pc; 1916 1917 pc = EXT_PHY_SW_STATE(unit, port); 1918 if (pc == NULL) { 1919 return SOC_E_INTERNAL; 1920 } 1921 1922 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS1) || 1923 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 1924 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER | PHY_FLAGS_C45 | PHY_FLAGS_REPEATER); 1925 SOC_IF_ERROR_RETURN(_phy_82864_init_pass1(unit, port)); 1926 1927 if (PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT) { 1928 return SOC_E_NONE; 1929 } 1930 } 1931 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS2) || 1932 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 1933 1934 SOC_IF_ERROR_RETURN( _phy_82864_init_pass2(unit, port)); 1935 1936 LOG_INFO(BSL_LS_SOC_PHY, 1937 (BSL_META_U(unit, 1938 "82864 init pass2 completed: u=%d p=%d\n"), unit, port)); 1939 if (PHYCTRL_INIT_STATE(pc) != PHYCTRL_INIT_STATE_DEFAULT) { 1940 return SOC_E_NONE; 1941 } 1942 } 1943 1944 if ((PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_PASS3) || 1945 (PHYCTRL_INIT_STATE(pc) == PHYCTRL_INIT_STATE_DEFAULT)) { 1946 1947 SOC_IF_ERROR_RETURN(_phy_82864_init_pass3(unit, port)); 1948 1949 LOG_INFO(BSL_LS_SOC_PHY, 1950 (BSL_META_U(unit, 1951 "PHY82864 init pass3 completed: u=%d p=%d\n"), unit, port)); 1952 PHYCTRL_INIT_STATE_SET(pc, PHYCTRL_INIT_STATE_DEFAULT); 1953 return SOC_E_NONE; 1954 } 1955 1956 return SOC_E_NONE; 1957 } 1958 1959 /* 1960 * Function: 1961 * phy_82864_ability_local_get 1962 * Purpose: 1963 * xx 1964 * Parameters: 1965 * unit - BCM unit number. 1966 * port - Port number. 1967 * ability - xx 1968 * Returns: 1969 * SOC_E_NONE 1970 */ 1971 STATIC int 1972 phy_82864_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability) 1973 { 1974 phy_ctrl_t *pc; 1975 uint32_t pa_speed = 0; 1976 1977 pc = EXT_PHY_SW_STATE(unit, port); 1978 1979 if (NULL == ability) { 1980 return SOC_E_PARAM; 1981 } 1982 1983 sal_memset(ability, 0, sizeof(*ability)); 1984 if ((pc->speed_max == PHY82864_SPD_106G) || 1985 (pc->speed_max == PHY82864_SPD_100G)) { 1986 pa_speed = SOC_PA_SPEED_106GB | SOC_PA_SPEED_100GB | 1987 SOC_PA_SPEED_42GB | SOC_PA_SPEED_40GB | 1988 SOC_PA_SPEED_11GB | SOC_PA_SPEED_10GB; 1989 } else if ((pc->speed_max == PHY82864_SPD_42G) || 1990 (pc->speed_max == PHY82864_SPD_40G) || 1991 (pc->speed_max == PHY82864_SPD_50G)) { 1992 pa_speed = SOC_PA_SPEED_42GB | SOC_PA_SPEED_40GB | SOC_PA_SPEED_50GB | 1993 SOC_PA_SPEED_11GB | SOC_PA_SPEED_10GB; 1994 } else if ((pc->speed_max == PHY82864_SPD_11G) || 1995 (pc->speed_max == PHY82864_SPD_10G) || (pc->speed_max == PHY82864_SPD_1G) || 1996 (pc->speed_max == PHY82864_SPD_25G)) { 1997 pa_speed = SOC_PA_SPEED_11GB | SOC_PA_SPEED_10GB | SOC_PA_SPEED_25GB; 1998 } else { 1999 pa_speed = SOC_PA_SPEED_106GB | SOC_PA_SPEED_100GB | 2000 SOC_PA_SPEED_42GB | SOC_PA_SPEED_40GB | 2001 SOC_PA_SPEED_11GB | SOC_PA_SPEED_10GB; 2002 } 2003 2004 ability->loopback = SOC_PA_LB_PHY; 2005 ability->medium = SOC_PA_MEDIUM_COPPER; 2006 ability->pause = 0; 2007 ability->flags = SOC_PA_AUTONEG; 2008 ability->speed_full_duplex = pa_speed; 2009 2010 LOG_INFO(BSL_LS_SOC_PHY, 2011 (BSL_META_U(pc->unit, 2012 "phy82864_ability_local_get:unit=%d p=%d sp=%08x\n"), 2013 unit, port, ability->speed_full_duplex)); 2014 2015 return (SOC_E_NONE); 2016 } 2017 2018 STATIC int 2019 phy_82864_link_get(int unit, soc_port_t port, int *link) 2020 { 2021 phy_ctrl_t *pc; 2022 soc_phymod_ctrl_t *pmc; 2023 phymod_phy_access_t *pm_phy; 2024 phy_ctrl_t *int_pc; 2025 int32 int_phy_link = 0; 2026 int32 speed = 0; 2027 soc_port_if_t interface = 0; 2028 *link = 0; 2029 int_pc = INT_PHY_SW_STATE(unit, port); 2030 pc = EXT_PHY_SW_STATE(unit, port); 2031 if (pc == NULL) { 2032 return SOC_E_INTERNAL; 2033 } 2034 pmc = &pc->phymod_ctrl; 2035 pm_phy = &pmc->phy[pmc->main_phy]->pm_phy; 2036 if (eye_scan_mdr_enabled) { 2037 /* Return Success if eyescan is in progress*/ 2038 if (int_pc != NULL) { 2039 SOC_IF_ERROR_RETURN(PHY_LINK_GET(int_pc->pd, unit, port, &int_phy_link)); 2040 } 2041 *link = int_phy_link; 2042 #ifdef PHY82864_DEBUG 2043 if (*link == 0) { 2044 LOG_CLI((BSL_META_U(unit,"PCS Down: port:%d\n "), port)); 2045 } 2046 #endif 2047 return SOC_E_NONE; 2048 } 2049 2050 /* default side is line side */ 2051 pm_phy->access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2052 2053 if (int_pc != NULL) { 2054 SOC_IF_ERROR_RETURN(PHY_LINK_GET(int_pc->pd, unit, port, &int_phy_link)); 2055 SOC_IF_ERROR_RETURN(PHY_SPEED_GET(int_pc->pd, unit, port, &speed)); 2056 SOC_IF_ERROR_RETURN(PHY_INTERFACE_GET(int_pc->pd, unit, port, &interface)); 2057 } 2058 2059 SOC_IF_ERROR_RETURN 2060 (phymod_phy_link_status_get(pm_phy, (uint32_t *) link)); 2061 /* When PMD lock of 82864 is not Set, Leave the port link as 2062 * PMD status of 82864. When PMD lock of 82864 is set use 2063 * PCS status of internal serdes as port link status. 2064 * When internal serdes is not there use 82864 PMS as link status*/ 2065 #ifdef PHY82864_DEBUG 2066 printf("slink=%d maduralink=%d\n",int_phy_link,*link); 2067 if (*link == 1 && int_phy_link == 0) { 2068 LOG_CLI((BSL_META_U(unit,"PMD UP PCS Down: port:%d\n "), port)); 2069 } 2070 if (*link == 0 && int_phy_link == 1) { 2071 LOG_CLI((BSL_META_U(unit,"PMD DOWN PCS UP port:%d\n "), port)); 2072 } 2073 #endif 2074 if (*link && int_pc) { 2075 *link = int_phy_link; 2076 } 2077 2078 return SOC_E_NONE; 2079 } 2080 2081 STATIC int 2082 phy_82864_enable_set(int unit, soc_port_t port, int enable) 2083 { 2084 phy_ctrl_t *pc; 2085 soc_phymod_ctrl_t *pmc; 2086 int32 intf; 2087 phy_ctrl_t *int_pc; 2088 2089 /* locate phy control */ 2090 int_pc = INT_PHY_SW_STATE(unit, port); 2091 pc = EXT_PHY_SW_STATE(unit, port); 2092 if (pc == NULL) { 2093 return SOC_E_INTERNAL; 2094 } 2095 2096 if (eye_scan_mdr_enabled) { 2097 /* Return Success if eyescan is in progress*/ 2098 return SOC_E_NONE; 2099 } 2100 intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY82864_SYS_SIDE : PHY82864_LINE_SIDE; 2101 2102 pmc = &pc->phymod_ctrl; 2103 2104 SOC_IF_ERROR_RETURN 2105 (phy_82864_power_set(pmc, port, intf, enable)); 2106 if (int_pc != NULL) { 2107 SOC_IF_ERROR_RETURN(PHY_ENABLE_SET(int_pc->pd, unit, port, enable)); 2108 } 2109 2110 if (enable) { 2111 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_DISABLE); 2112 } else { 2113 PHY_FLAGS_SET(unit, port, PHY_FLAGS_DISABLE); 2114 } 2115 2116 return SOC_E_NONE; 2117 } 2118 2119 STATIC int 2120 phy_82864_enable_get(int unit, soc_port_t port, int *enable) 2121 { 2122 phy_ctrl_t *pc; 2123 soc_phymod_ctrl_t *pmc; 2124 int32 intf; 2125 uint32_t ena_dis; 2126 *enable = 0; 2127 2128 /* locate phy control */ 2129 pc = EXT_PHY_SW_STATE(unit, port); 2130 if (pc == NULL) { 2131 return SOC_E_INTERNAL; 2132 } 2133 pmc = &pc->phymod_ctrl; 2134 if (eye_scan_mdr_enabled) { 2135 /* Return Success if eyescan is in progress*/ 2136 *enable =1; 2137 return SOC_E_NONE; 2138 } 2139 intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY82864_SYS_SIDE : PHY82864_LINE_SIDE; 2140 SOC_IF_ERROR_RETURN 2141 (phy_82864_power_get(pmc, port, intf, &ena_dis)); 2142 2143 *enable = ena_dis; 2144 2145 return SOC_E_NONE; 2146 } 2147 2148 STATIC int 2149 phy_82864_lb_set(int unit, soc_port_t port, int enable) 2150 { 2151 phy_ctrl_t* pc; 2152 soc_phymod_ctrl_t *pmc; 2153 2154 pc = EXT_PHY_SW_STATE(unit, port); 2155 pmc = &pc->phymod_ctrl; 2156 SOC_IF_ERROR_RETURN ( 2157 phy_82864_loopback_internal_pmd_set(pmc, port, PHY82864_LINE_SIDE, enable)); 2158 2159 return SOC_E_NONE; 2160 } 2161 2162 STATIC int 2163 phy_82864_firmware_set(int unit, int port, int cmd, uint8 *array,int datalen) 2164 { 2165 phy_ctrl_t *pc; 2166 soc_phymod_core_t *pmc_core; 2167 phymod_core_access_t *pm_core; 2168 soc_phymod_ctrl_t *pmc; 2169 phymod_core_status_t core_status; 2170 2171 /* locate phy control */ 2172 pc = EXT_PHY_SW_STATE(unit, port); 2173 if (pc == NULL) { 2174 return SOC_E_INTERNAL; 2175 } 2176 pmc = &pc->phymod_ctrl; 2177 2178 pmc_core = pmc->phy[0]->core; 2179 pm_core = &pmc_core->pm_core; 2180 if (pm_core == NULL) { 2181 return SOC_E_INTERNAL; 2182 } 2183 2184 if (array == NULL) { 2185 if (cmd == PHYCTRL_UCODE_BCST_SETUP) { 2186 PHYMOD_CORE_INIT_F_RESET_CORE_FOR_FW_LOAD_SET(&(pmc_core->init_config)); 2187 SOC_IF_ERROR_RETURN ( 2188 phymod_core_init(pm_core, &pmc_core->init_config, &core_status)); 2189 PHYMOD_CORE_INIT_F_RESET_CORE_FOR_FW_LOAD_CLR(&(pmc_core->init_config)); 2190 return SOC_E_NONE; 2191 } else if (cmd == PHYCTRL_UCODE_BCST_uC_SETUP) { 2192 return SOC_E_NONE; 2193 } else if (cmd == PHYCTRL_UCODE_BCST_ENABLE) { 2194 PHYMOD_CORE_INIT_F_UNTIL_FW_LOAD_SET(&(pmc_core->init_config)); 2195 SOC_IF_ERROR_RETURN ( 2196 phymod_core_init(pm_core, &pmc_core->init_config, &core_status)); 2197 PHYMOD_CORE_INIT_F_UNTIL_FW_LOAD_CLR(&(pmc_core->init_config)); 2198 return SOC_E_NONE; 2199 } else if (cmd == PHYCTRL_UCODE_BCST_LOAD) { 2200 PHYMOD_CORE_INIT_F_EXECUTE_FW_LOAD_SET(&(pmc_core->init_config)); 2201 SOC_IF_ERROR_RETURN ( 2202 phymod_core_init(pm_core, &pmc_core->init_config, &core_status)); 2203 PHYMOD_CORE_INIT_F_EXECUTE_FW_LOAD_CLR(&(pmc_core->init_config)); 2204 return SOC_E_NONE; 2205 } else if (cmd == PHYCTRL_UCODE_BCST_END) { 2206 PHYMOD_CORE_INIT_F_RESUME_AFTER_FW_LOAD_SET(&(pmc_core->init_config)); 2207 SOC_IF_ERROR_RETURN ( 2208 phymod_core_init(pm_core, &pmc_core->init_config, &core_status)); 2209 PHYMOD_CORE_INIT_F_RESUME_AFTER_FW_LOAD_CLR(&(pmc_core->init_config)); 2210 return SOC_E_NONE; 2211 } 2212 } else { 2213 return SOC_E_UNAVAIL; 2214 } 2215 2216 return SOC_E_NONE; 2217 } 2218 2219 /* 2220 * phy_82864_per_lane_loopback_internal_pmd_get (this is the PMD global loopback) 2221 */ 2222 STATIC int 2223 phy_82864_per_lane_loopback_internal_pmd_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 2224 { 2225 phymod_phy_access_t *pm_phy; 2226 uint32_t enable; 2227 soc_phymod_phy_t *p_phy; 2228 uint32 lane_map; 2229 phymod_phy_access_t pm_phy_copy; 2230 2231 /* locate the desired phy and lane */ 2232 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 2233 2234 /* Make a copy of the phy access and overwrite the desired lane */ 2235 pm_phy = &p_phy->pm_phy; 2236 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2237 pm_phy_copy.access.lane_mask = lane_map; 2238 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2239 if(intf == PHY82864_SYS_SIDE) { 2240 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2241 } 2242 2243 SOC_IF_ERROR_RETURN(phymod_phy_loopback_get(&pm_phy_copy, phymodLoopbackGlobalPMD, &enable)); 2244 *value = enable; 2245 2246 return(SOC_E_NONE); 2247 } 2248 /* 2249 * phy_82864_loopback_internal_pmd_get (this is the PMD global loopback) 2250 */ 2251 STATIC int 2252 phy_82864_loopback_internal_pmd_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 2253 { 2254 phymod_phy_access_t *pm_phy; 2255 uint32_t enable; 2256 phymod_phy_access_t pm_phy_copy; 2257 2258 /* just take the value from the first phy */ 2259 if (pmc->phy[0] == NULL) { 2260 return SOC_E_INTERNAL; 2261 } 2262 pm_phy = &pmc->phy[0]->pm_phy; 2263 2264 if (pm_phy == NULL) { 2265 return SOC_E_INTERNAL; 2266 } 2267 2268 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2269 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2270 if(intf == PHY82864_SYS_SIDE) { 2271 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2272 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 2273 } 2274 SOC_IF_ERROR_RETURN(phymod_phy_loopback_get(&pm_phy_copy, phymodLoopbackGlobalPMD, &enable)); 2275 *value = enable; 2276 2277 return(SOC_E_NONE); 2278 } 2279 2280 /* 2281 * phy_82864_per_lane_loopback_remote_get 2282 */ 2283 STATIC int 2284 phy_82864_per_lane_loopback_remote_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 2285 { 2286 phymod_phy_access_t *pm_phy; 2287 uint32_t enable; 2288 soc_phymod_phy_t *p_phy; 2289 uint32 lane_map; 2290 phymod_phy_access_t pm_phy_copy; 2291 2292 /* locate the desired phy and lane */ 2293 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 2294 2295 /* Make a copy of the phy access and overwrite the desired lane */ 2296 pm_phy = &p_phy->pm_phy; 2297 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2298 pm_phy_copy.access.lane_mask = lane_map; 2299 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2300 if(intf == PHY82864_SYS_SIDE) { 2301 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2302 } 2303 2304 SOC_IF_ERROR_RETURN(phymod_phy_loopback_get(&pm_phy_copy, phymodLoopbackRemotePMD, &enable)); 2305 *value = enable; 2306 2307 return(SOC_E_NONE); 2308 } 2309 2310 /* 2311 * phy_82864_loopback_remote_get 2312 */ 2313 STATIC int 2314 phy_82864_loopback_remote_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 2315 { 2316 phymod_phy_access_t *pm_phy; 2317 uint32_t enable; 2318 phymod_phy_access_t pm_phy_copy; 2319 2320 /* just take the value from the first phy */ 2321 if (pmc->phy[0] == NULL) { 2322 return SOC_E_INTERNAL; 2323 } 2324 pm_phy = &pmc->phy[0]->pm_phy; 2325 2326 if (pm_phy == NULL) { 2327 return SOC_E_INTERNAL; 2328 } 2329 2330 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2331 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2332 if(intf == PHY82864_SYS_SIDE) { 2333 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2334 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 2335 } 2336 SOC_IF_ERROR_RETURN(phymod_phy_loopback_get(&pm_phy_copy, phymodLoopbackRemotePMD, &enable)); 2337 *value = enable; 2338 2339 return(SOC_E_NONE); 2340 } 2341 2342 /* 2343 * phy_82864_per_lane_prbs_tx_poly_get 2344 */ 2345 STATIC int 2346 phy_82864_per_lane_prbs_tx_poly_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 2347 { 2348 phymod_phy_access_t *pm_phy; 2349 phymod_prbs_t prbs; 2350 uint32_t flags = 0; 2351 2352 2353 soc_phymod_phy_t *p_phy; 2354 uint32 lane_map; 2355 phymod_phy_access_t pm_phy_copy; 2356 2357 /* locate the desired phy and lane */ 2358 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 2359 2360 /* Make a copy of the phy access and overwrite the desired lane */ 2361 pm_phy = &p_phy->pm_phy; 2362 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2363 pm_phy_copy.access.lane_mask = lane_map; 2364 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2365 if(intf == PHY82864_SYS_SIDE) { 2366 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2367 } 2368 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 2369 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 2370 2371 *value = (int) prbs.poly; 2372 2373 /* convert from PHYMOD enum to SDK enum */ 2374 switch(prbs.poly){ 2375 case phymodPrbsPoly7: 2376 *value = SOC_PHY_PRBS_POLYNOMIAL_X7_X6_1; 2377 break; 2378 case phymodPrbsPoly9: 2379 *value = SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1; 2380 break; 2381 case phymodPrbsPoly15: 2382 *value = SOC_PHY_PRBS_POLYNOMIAL_X15_X14_1; 2383 break; 2384 case phymodPrbsPoly23: 2385 *value = SOC_PHY_PRBS_POLYNOMIAL_X23_X18_1; 2386 break; 2387 case phymodPrbsPoly31: 2388 *value = SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1; 2389 break; 2390 case phymodPrbsPoly11: 2391 *value = SOC_PHY_PRBS_POLYNOMIAL_X11_X9_1; 2392 break; 2393 case phymodPrbsPoly58: 2394 *value = SOC_PHY_PRBS_POLYNOMIAL_X58_X31_1; 2395 break; 2396 default: 2397 return SOC_E_INTERNAL; 2398 } 2399 2400 return SOC_E_NONE; 2401 } 2402 /* 2403 * phy_82864_prbs_tx_poly_get 2404 */ 2405 STATIC int 2406 phy_82864_prbs_tx_poly_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 2407 { 2408 phymod_phy_access_t *pm_phy; 2409 phymod_prbs_t prbs; 2410 uint32_t flags = 0; 2411 phymod_phy_access_t pm_phy_copy; 2412 2413 /* just take the value from the first phy */ 2414 if (pmc->phy[0] == NULL) { 2415 return SOC_E_INTERNAL; 2416 } 2417 pm_phy = &pmc->phy[0]->pm_phy; 2418 2419 if (pm_phy == NULL) { 2420 return SOC_E_INTERNAL; 2421 } 2422 2423 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2424 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2425 if(intf == PHY82864_SYS_SIDE) { 2426 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2427 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 2428 } 2429 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 2430 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 2431 2432 *value = (int) prbs.poly; 2433 2434 /* convert from PHYMOD enum to SDK enum */ 2435 switch(prbs.poly){ 2436 case phymodPrbsPoly7: 2437 *value = SOC_PHY_PRBS_POLYNOMIAL_X7_X6_1; 2438 break; 2439 case phymodPrbsPoly9: 2440 *value = SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1; 2441 break; 2442 case phymodPrbsPoly15: 2443 *value = SOC_PHY_PRBS_POLYNOMIAL_X15_X14_1; 2444 break; 2445 case phymodPrbsPoly23: 2446 *value = SOC_PHY_PRBS_POLYNOMIAL_X23_X18_1; 2447 break; 2448 case phymodPrbsPoly31: 2449 *value = SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1; 2450 break; 2451 case phymodPrbsPoly11: 2452 *value = SOC_PHY_PRBS_POLYNOMIAL_X11_X9_1; 2453 break; 2454 case phymodPrbsPoly58: 2455 *value = SOC_PHY_PRBS_POLYNOMIAL_X58_X31_1; 2456 break; 2457 default: 2458 return SOC_E_INTERNAL; 2459 } 2460 2461 return SOC_E_NONE; 2462 } 2463 /* 2464 * phy_82864_per_lane_prbs_rx_poly_get 2465 */ 2466 STATIC int 2467 phy_82864_per_lane_prbs_rx_poly_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 2468 { 2469 phymod_phy_access_t *pm_phy; 2470 phymod_prbs_t prbs; 2471 uint32_t flags = 0; 2472 2473 2474 soc_phymod_phy_t *p_phy; 2475 uint32 lane_map; 2476 phymod_phy_access_t pm_phy_copy; 2477 2478 /* locate the desired phy and lane */ 2479 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 2480 2481 /* Make a copy of the phy access and overwrite the desired lane */ 2482 pm_phy = &p_phy->pm_phy; 2483 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2484 pm_phy_copy.access.lane_mask = lane_map; 2485 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2486 if(intf == PHY82864_SYS_SIDE) { 2487 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2488 } 2489 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 2490 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 2491 2492 *value = (int) prbs.poly; 2493 2494 /* convert from PHYMOD enum to SDK enum */ 2495 switch(prbs.poly){ 2496 case phymodPrbsPoly7: 2497 *value = SOC_PHY_PRBS_POLYNOMIAL_X7_X6_1; 2498 break; 2499 case phymodPrbsPoly9: 2500 *value = SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1; 2501 break; 2502 case phymodPrbsPoly15: 2503 *value = SOC_PHY_PRBS_POLYNOMIAL_X15_X14_1; 2504 break; 2505 case phymodPrbsPoly23: 2506 *value = SOC_PHY_PRBS_POLYNOMIAL_X23_X18_1; 2507 break; 2508 case phymodPrbsPoly31: 2509 *value = SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1; 2510 break; 2511 case phymodPrbsPoly11: 2512 *value = SOC_PHY_PRBS_POLYNOMIAL_X11_X9_1; 2513 break; 2514 case phymodPrbsPoly58: 2515 *value = SOC_PHY_PRBS_POLYNOMIAL_X58_X31_1; 2516 break; 2517 default: 2518 return SOC_E_INTERNAL; 2519 } 2520 2521 return SOC_E_NONE; 2522 } 2523 /* 2524 * phy_82864_prbs_rx_poly_get 2525 */ 2526 STATIC int 2527 phy_82864_prbs_rx_poly_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 2528 { 2529 phymod_phy_access_t *pm_phy; 2530 phymod_prbs_t prbs; 2531 phymod_phy_access_t pm_phy_copy; 2532 uint32_t flags = 0; 2533 2534 /* just take the value from the first phy */ 2535 if (pmc->phy[0] == NULL) { 2536 return SOC_E_INTERNAL; 2537 } 2538 pm_phy = &pmc->phy[0]->pm_phy; 2539 2540 if (pm_phy == NULL) { 2541 return SOC_E_INTERNAL; 2542 } 2543 2544 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2545 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2546 if(intf == PHY82864_SYS_SIDE) { 2547 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2548 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 2549 } 2550 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 2551 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 2552 2553 *value = (int) prbs.poly; 2554 2555 /* convert from PHYMOD enum to SDK enum */ 2556 switch(prbs.poly){ 2557 case phymodPrbsPoly7: 2558 *value = SOC_PHY_PRBS_POLYNOMIAL_X7_X6_1; 2559 break; 2560 case phymodPrbsPoly9: 2561 *value = SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1; 2562 break; 2563 case phymodPrbsPoly15: 2564 *value = SOC_PHY_PRBS_POLYNOMIAL_X15_X14_1; 2565 break; 2566 case phymodPrbsPoly23: 2567 *value = SOC_PHY_PRBS_POLYNOMIAL_X23_X18_1; 2568 break; 2569 case phymodPrbsPoly31: 2570 *value = SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1; 2571 break; 2572 case phymodPrbsPoly11: 2573 *value = SOC_PHY_PRBS_POLYNOMIAL_X11_X9_1; 2574 break; 2575 case phymodPrbsPoly58: 2576 *value = SOC_PHY_PRBS_POLYNOMIAL_X58_X31_1; 2577 break; 2578 default: 2579 return SOC_E_INTERNAL; 2580 } 2581 2582 return SOC_E_NONE; 2583 } 2584 2585 /* 2586 * phy_82864_per_lane_prbs_tx_invert_data_get 2587 */ 2588 STATIC int 2589 phy_82864_per_lane_prbs_tx_invert_data_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 2590 { 2591 phymod_phy_access_t *pm_phy; 2592 phymod_prbs_t prbs; 2593 uint32_t flags = 0; 2594 2595 soc_phymod_phy_t *p_phy; 2596 uint32 lane_map; 2597 phymod_phy_access_t pm_phy_copy; 2598 2599 /* locate the desired phy and lane */ 2600 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 2601 2602 /* Make a copy of the phy access and overwrite the desired lane */ 2603 pm_phy = &p_phy->pm_phy; 2604 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2605 pm_phy_copy.access.lane_mask = lane_map; 2606 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2607 if(intf == PHY82864_SYS_SIDE) { 2608 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2609 } 2610 2611 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 2612 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 2613 *value = prbs.invert; 2614 2615 return(SOC_E_NONE); 2616 } 2617 /* 2618 * phy_82864_prbs_tx_invert_data_get 2619 */ 2620 STATIC int 2621 phy_82864_prbs_tx_invert_data_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 2622 { 2623 phymod_phy_access_t *pm_phy; 2624 phymod_prbs_t prbs; 2625 uint32_t flags = 0; 2626 phymod_phy_access_t pm_phy_copy; 2627 2628 /* just take the value from the first phy */ 2629 if (pmc->phy[0] == NULL) { 2630 return SOC_E_INTERNAL; 2631 } 2632 pm_phy = &pmc->phy[0]->pm_phy; 2633 2634 if (pm_phy == NULL) { 2635 return SOC_E_INTERNAL; 2636 } 2637 2638 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2639 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2640 if(intf == PHY82864_SYS_SIDE) { 2641 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2642 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 2643 } 2644 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 2645 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 2646 *value = prbs.invert; 2647 2648 return(SOC_E_NONE); 2649 } 2650 2651 /* 2652 * phy_82864_per_lane_prbs_rx_invert_data_get 2653 */ 2654 STATIC int 2655 phy_82864_per_lane_prbs_rx_invert_data_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 2656 { 2657 phymod_phy_access_t *pm_phy; 2658 phymod_prbs_t prbs; 2659 uint32_t flags = 0; 2660 soc_phymod_phy_t *p_phy; 2661 uint32 lane_map; 2662 phymod_phy_access_t pm_phy_copy; 2663 2664 /* locate the desired phy and lane */ 2665 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 2666 2667 /* Make a copy of the phy access and overwrite the desired lane */ 2668 pm_phy = &p_phy->pm_phy; 2669 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2670 pm_phy_copy.access.lane_mask = lane_map; 2671 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2672 if(intf == PHY82864_SYS_SIDE) { 2673 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2674 } 2675 2676 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 2677 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 2678 *value = prbs.invert; 2679 2680 return(SOC_E_NONE); 2681 } 2682 /* 2683 * phy_82864_prbs_rx_invert_data_get 2684 */ 2685 STATIC int 2686 phy_82864_prbs_rx_invert_data_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 2687 { 2688 phymod_phy_access_t *pm_phy; 2689 phymod_prbs_t prbs; 2690 uint32_t flags = 0; 2691 phymod_phy_access_t pm_phy_copy; 2692 2693 /* just take the value from the first phy */ 2694 if (pmc->phy[0] == NULL) { 2695 return SOC_E_INTERNAL; 2696 } 2697 pm_phy = &pmc->phy[0]->pm_phy; 2698 2699 if (pm_phy == NULL) { 2700 return SOC_E_INTERNAL; 2701 } 2702 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2703 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2704 if(intf == PHY82864_SYS_SIDE) { 2705 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2706 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 2707 } 2708 2709 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 2710 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 2711 *value = prbs.invert; 2712 2713 return(SOC_E_NONE); 2714 } 2715 2716 /* 2717 * phy_82864_per_lane_prbs_tx_enable_get 2718 */ 2719 STATIC int 2720 phy_82864_per_lane_prbs_tx_enable_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 2721 { 2722 phymod_phy_access_t *pm_phy; 2723 uint32_t flags = 0; 2724 soc_phymod_phy_t *p_phy; 2725 uint32 lane_map; 2726 phymod_phy_access_t pm_phy_copy; 2727 2728 /* locate the desired phy and lane */ 2729 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 2730 2731 /* Make a copy of the phy access and overwrite the desired lane */ 2732 pm_phy = &p_phy->pm_phy; 2733 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2734 pm_phy_copy.access.lane_mask = lane_map; 2735 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2736 if(intf == PHY82864_SYS_SIDE) { 2737 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2738 } 2739 2740 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 2741 SOC_IF_ERROR_RETURN(phymod_phy_prbs_enable_get(&pm_phy_copy, flags, value)); 2742 2743 return(SOC_E_NONE); 2744 } 2745 2746 /* 2747 * phy_82864_prbs_tx_enable_get 2748 */ 2749 STATIC int 2750 phy_82864_prbs_tx_enable_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 2751 { 2752 phymod_phy_access_t *pm_phy; 2753 uint32_t flags = 0; 2754 phymod_phy_access_t pm_phy_copy; 2755 2756 /* just take the value from the first phy */ 2757 if (pmc->phy[0] == NULL) { 2758 return SOC_E_INTERNAL; 2759 } 2760 pm_phy = &pmc->phy[0]->pm_phy; 2761 2762 if (pm_phy == NULL) { 2763 return SOC_E_INTERNAL; 2764 } 2765 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2766 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2767 if(intf == PHY82864_SYS_SIDE) { 2768 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2769 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 2770 } 2771 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 2772 SOC_IF_ERROR_RETURN(phymod_phy_prbs_enable_get(&pm_phy_copy, flags, value)); 2773 2774 return(SOC_E_NONE); 2775 } 2776 2777 /* 2778 * phy_82864_per_lane_prbs_rx_enable_get 2779 */ 2780 STATIC int 2781 phy_82864_per_lane_prbs_rx_enable_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 2782 { 2783 phymod_phy_access_t *pm_phy; 2784 uint32_t flags = 0; 2785 soc_phymod_phy_t *p_phy; 2786 uint32 lane_map; 2787 phymod_phy_access_t pm_phy_copy; 2788 2789 /* locate the desired phy and lane */ 2790 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 2791 2792 /* Make a copy of the phy access and overwrite the desired lane */ 2793 pm_phy = &p_phy->pm_phy; 2794 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2795 pm_phy_copy.access.lane_mask = lane_map; 2796 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2797 if(intf == PHY82864_SYS_SIDE) { 2798 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2799 } 2800 2801 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 2802 SOC_IF_ERROR_RETURN(phymod_phy_prbs_enable_get(&pm_phy_copy, flags, value)); 2803 2804 return(SOC_E_NONE); 2805 } 2806 /* 2807 * phy_82864_prbs_rx_enable_get 2808 */ 2809 STATIC int 2810 phy_82864_prbs_rx_enable_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 2811 { 2812 phymod_phy_access_t *pm_phy; 2813 uint32_t flags = 0; 2814 phymod_phy_access_t pm_phy_copy; 2815 2816 /* just take the value from the first phy */ 2817 if (pmc->phy[0] == NULL) { 2818 return SOC_E_INTERNAL; 2819 } 2820 pm_phy = &pmc->phy[0]->pm_phy; 2821 2822 if (pm_phy == NULL) { 2823 return SOC_E_INTERNAL; 2824 } 2825 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2826 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2827 if(intf == PHY82864_SYS_SIDE) { 2828 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2829 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 2830 } 2831 2832 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 2833 SOC_IF_ERROR_RETURN(phymod_phy_prbs_enable_get(&pm_phy_copy, flags, value)); 2834 2835 return(SOC_E_NONE); 2836 } 2837 2838 /* 2839 * phy_82864_per_lane_prbs_rx_status_get 2840 */ 2841 STATIC int 2842 phy_82864_per_lane_prbs_rx_status_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 2843 { 2844 phymod_phy_access_t *pm_phy; 2845 phymod_prbs_status_t prbs_tmp; 2846 int prbs_lock, lock_loss, error_count ; 2847 soc_phymod_phy_t *p_phy; 2848 uint32 lane_map; 2849 phymod_phy_access_t pm_phy_copy; 2850 2851 prbs_lock = 1 ; 2852 lock_loss = 0 ; 2853 error_count = 0 ; 2854 /* locate the desired phy and lane */ 2855 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 2856 2857 /* Make a copy of the phy access and overwrite the desired lane */ 2858 pm_phy = &p_phy->pm_phy; 2859 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2860 pm_phy_copy.access.lane_mask = lane_map; 2861 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2862 if(intf == PHY82864_SYS_SIDE) { 2863 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2864 } 2865 /* $$$ Need to add diagnostic API */ 2866 SOC_IF_ERROR_RETURN 2867 (phymod_phy_prbs_status_get(&pm_phy_copy, 0, &prbs_tmp)); 2868 2869 if(prbs_tmp.prbs_lock==0) { 2870 prbs_lock = 0 ; 2871 } else { 2872 if(prbs_tmp.prbs_lock_loss) { 2873 lock_loss = 1 ; 2874 } else { 2875 error_count += prbs_tmp.error_count; 2876 } 2877 } 2878 2879 if (prbs_lock == 0) { 2880 *value = -1; 2881 } else if ((lock_loss == 1) && (prbs_lock == 1)) { 2882 *value = -2; 2883 } else { 2884 *value = error_count; 2885 } 2886 2887 return(SOC_E_NONE); 2888 } 2889 /* 2890 * phy_82864_prbs_rx_status_get 2891 */ 2892 STATIC int 2893 phy_82864_prbs_rx_status_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 2894 { 2895 phymod_phy_access_t *pm_phy; 2896 phymod_prbs_status_t prbs_tmp; 2897 int idx, prbs_lock, lock_loss, error_count ; 2898 phymod_phy_access_t pm_phy_copy; 2899 2900 /* just take the value from the first phy */ 2901 if (pmc->phy[0] == NULL) { 2902 return SOC_E_INTERNAL; 2903 } 2904 2905 prbs_lock = 1 ; 2906 lock_loss = 0 ; 2907 error_count = 0 ; 2908 for (idx = 0; idx < pmc->num_phys; idx++) { 2909 pm_phy = &pmc->phy[idx]->pm_phy; 2910 2911 if (pm_phy == NULL) { 2912 return SOC_E_INTERNAL; 2913 } 2914 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2915 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2916 if(intf == PHY82864_SYS_SIDE) { 2917 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2918 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 2919 } 2920 /* $$$ Need to add diagnostic API */ 2921 SOC_IF_ERROR_RETURN 2922 (phymod_phy_prbs_status_get(&pm_phy_copy, 0, &prbs_tmp)); 2923 2924 if(prbs_tmp.prbs_lock==0) { 2925 prbs_lock = 0 ; 2926 } else { 2927 if(prbs_tmp.prbs_lock_loss) { 2928 lock_loss = 1 ; 2929 } else { 2930 error_count += prbs_tmp.error_count; 2931 } 2932 } 2933 } 2934 2935 if (prbs_lock == 0) { 2936 *value = -1; 2937 } else if ((lock_loss == 1) && (prbs_lock == 1)) { 2938 *value = -2; 2939 } else { 2940 *value = error_count; 2941 } 2942 2943 return(SOC_E_NONE); 2944 } 2945 /* 2946 * phy_82864_per_lane_rx_peak_filter_get 2947 */ 2948 STATIC int 2949 phy_82864_per_lane_rx_peak_filter_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 2950 { 2951 soc_phymod_phy_t *p_phy; 2952 uint32 lane_map; 2953 phymod_phy_access_t pm_phy_copy, *pm_phy; 2954 phymod_rx_t phymod_rx; 2955 2956 *value = 0; 2957 2958 /* locate the desired phy and lane */ 2959 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 2960 2961 /* Make a copy of the phy access and overwrite the desired lane */ 2962 pm_phy = &p_phy->pm_phy; 2963 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2964 pm_phy_copy.access.lane_mask = lane_map; 2965 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2966 if(intf == PHY82864_SYS_SIDE) { 2967 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2968 } 2969 2970 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 2971 *value = phymod_rx.peaking_filter.value; 2972 2973 return(SOC_E_NONE); 2974 } 2975 2976 /* 2977 * phy_82864_per_lane_rx_vga_get 2978 */ 2979 STATIC int 2980 phy_82864_per_lane_rx_vga_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 2981 { 2982 soc_phymod_phy_t *p_phy; 2983 uint32 lane_map; 2984 phymod_phy_access_t pm_phy_copy, *pm_phy; 2985 phymod_rx_t phymod_rx; 2986 2987 *value = 0; 2988 2989 /* locate the desired phy and lane */ 2990 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 2991 2992 /* Make a copy of the phy access and overwrite the desired lane */ 2993 pm_phy = &p_phy->pm_phy; 2994 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2995 pm_phy_copy.access.lane_mask = lane_map; 2996 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 2997 if(intf == PHY82864_SYS_SIDE) { 2998 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 2999 } 3000 3001 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 3002 *value = phymod_rx.vga.value; 3003 3004 return(SOC_E_NONE); 3005 } 3006 3007 /* 3008 * phy_82864_per_lane_rx_dfe_tap_control_get 3009 */ 3010 STATIC int 3011 phy_82864_per_lane_rx_dfe_tap_control_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, int tap, uint32 *value) 3012 { 3013 soc_phymod_phy_t *p_phy; 3014 uint32 lane_map; 3015 phymod_phy_access_t pm_phy_copy, *pm_phy; 3016 phymod_rx_t phymod_rx; 3017 3018 *value = 0; 3019 3020 /* locate the desired phy and lane */ 3021 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 3022 3023 /* Make a copy of the phy access and overwrite the desired lane */ 3024 pm_phy = &p_phy->pm_phy; 3025 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3026 pm_phy_copy.access.lane_mask = lane_map; 3027 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3028 if(intf == PHY82864_SYS_SIDE) { 3029 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3030 } 3031 3032 if (tap < 0 || tap >= COUNTOF(phymod_rx.dfe)) { 3033 /* this can only happen with a coding error */ 3034 return SOC_E_INTERNAL; 3035 } 3036 3037 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 3038 *value = phymod_rx.dfe[tap].value; 3039 3040 return(SOC_E_NONE); 3041 } 3042 3043 3044 /* 3045 * phy_82864_per_lane_rx_low_freq_filter_get 3046 */ 3047 STATIC int 3048 phy_82864_per_lane_rx_low_freq_filter_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 3049 { 3050 soc_phymod_phy_t *p_phy; 3051 uint32 lane_map; 3052 phymod_phy_access_t pm_phy_copy, *pm_phy; 3053 phymod_rx_t phymod_rx; 3054 3055 *value = 0; 3056 3057 /* locate the desired phy and lane */ 3058 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 3059 3060 /* Make a copy of the phy access and overwrite the desired lane */ 3061 pm_phy = &p_phy->pm_phy; 3062 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3063 pm_phy_copy.access.lane_mask = lane_map; 3064 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3065 if(intf == PHY82864_SYS_SIDE) { 3066 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3067 } 3068 3069 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 3070 *value = phymod_rx.low_freq_peaking_filter.value; 3071 3072 return(SOC_E_NONE); 3073 } 3074 3075 /* 3076 * phy_82864_rx_low_freq_filter_get 3077 */ 3078 STATIC int 3079 phy_82864_rx_low_freq_filter_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 3080 { 3081 phymod_phy_access_t *pm_phy; 3082 phymod_rx_t phymod_rx; 3083 phymod_phy_access_t pm_phy_copy; 3084 3085 /* just take the value from the first phy */ 3086 if (pmc->phy[0] == NULL) { 3087 return SOC_E_INTERNAL; 3088 } 3089 pm_phy = &pmc->phy[0]->pm_phy; 3090 3091 if (pm_phy == NULL) { 3092 return SOC_E_INTERNAL; 3093 } 3094 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3095 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3096 if(intf == PHY82864_SYS_SIDE) { 3097 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3098 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 3099 } 3100 3101 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 3102 *value = phymod_rx.low_freq_peaking_filter.value; 3103 3104 return(SOC_E_NONE); 3105 } 3106 3107 3108 /* 3109 * phy_82864_rx_peak_filter_get 3110 */ 3111 STATIC int 3112 phy_82864_rx_peak_filter_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 3113 { 3114 phymod_phy_access_t *pm_phy; 3115 phymod_rx_t phymod_rx; 3116 phymod_phy_access_t pm_phy_copy; 3117 3118 /* just take the value from the first phy */ 3119 if (pmc->phy[0] == NULL) { 3120 return SOC_E_INTERNAL; 3121 } 3122 pm_phy = &pmc->phy[0]->pm_phy; 3123 3124 if (pm_phy == NULL) { 3125 return SOC_E_INTERNAL; 3126 } 3127 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3128 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3129 if(intf == PHY82864_SYS_SIDE) { 3130 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3131 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 3132 } 3133 3134 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 3135 *value = phymod_rx.peaking_filter.value; 3136 3137 return(SOC_E_NONE); 3138 } 3139 3140 /* 3141 * phy_82864_rx_vga_get 3142 */ 3143 STATIC int 3144 phy_82864_rx_vga_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 3145 { 3146 phymod_phy_access_t *pm_phy; 3147 phymod_rx_t phymod_rx; 3148 phymod_phy_access_t pm_phy_copy; 3149 3150 /* just take the value from the first phy */ 3151 if (pmc->phy[0] == NULL) { 3152 return SOC_E_INTERNAL; 3153 } 3154 pm_phy = &pmc->phy[0]->pm_phy; 3155 3156 if (pm_phy == NULL) { 3157 return SOC_E_INTERNAL; 3158 } 3159 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3160 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3161 if(intf == PHY82864_SYS_SIDE) { 3162 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3163 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 3164 } 3165 3166 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 3167 *value = phymod_rx.vga.value; 3168 3169 return(SOC_E_NONE); 3170 } 3171 3172 /* 3173 * phy_82864_rx_tap_get 3174 */ 3175 STATIC int 3176 phy_82864_rx_tap_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int tap, uint32 *value) 3177 { 3178 phymod_phy_access_t *pm_phy; 3179 phymod_rx_t phymod_rx; 3180 phymod_phy_access_t pm_phy_copy; 3181 3182 if (tap < 0 || tap >= COUNTOF(phymod_rx.dfe)) { 3183 /* this can only happen with a coding error */ 3184 return SOC_E_INTERNAL; 3185 } 3186 /* just take the value from the first phy */ 3187 if (pmc->phy[0] == NULL) { 3188 return SOC_E_INTERNAL; 3189 } 3190 pm_phy = &pmc->phy[0]->pm_phy; 3191 3192 if (pm_phy == NULL) { 3193 return SOC_E_INTERNAL; 3194 } 3195 3196 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3197 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3198 if(intf == PHY82864_SYS_SIDE) { 3199 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3200 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 3201 } 3202 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 3203 *value = phymod_rx.dfe[tap].value; 3204 3205 return(SOC_E_NONE); 3206 } 3207 3208 /* 3209 * phy_82864_pi_control_get 3210 */ 3211 STATIC int 3212 phy_82864_pi_control_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 3213 { 3214 phymod_phy_access_t *pm_phy; 3215 phymod_tx_override_t tx_override; 3216 phymod_phy_access_t pm_phy_copy; 3217 3218 /* just take the value from the first phy */ 3219 if (pmc->phy[0] == NULL) { 3220 return SOC_E_INTERNAL; 3221 } 3222 pm_phy = &pmc->phy[0]->pm_phy; 3223 3224 if (pm_phy == NULL) { 3225 return SOC_E_INTERNAL; 3226 } 3227 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3228 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3229 if(intf == PHY82864_SYS_SIDE) { 3230 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3231 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 3232 } 3233 3234 SOC_IF_ERROR_RETURN(phymod_phy_tx_override_get(&pm_phy_copy, &tx_override)); 3235 *value = tx_override.phase_interpolator.value; 3236 3237 return(SOC_E_NONE); 3238 } 3239 /* 3240 * phy_82864_Rx_seq_done_get 3241 */ 3242 STATIC int 3243 phy_82864_rx_seq_done_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 3244 { 3245 phymod_phy_access_t *pm_phy; 3246 phymod_phy_access_t pm_phy_copy; 3247 3248 /* just take the value from the first phy */ 3249 if (pmc->phy[0] == NULL) { 3250 return SOC_E_INTERNAL; 3251 } 3252 pm_phy = &pmc->phy[0]->pm_phy; 3253 3254 if (pm_phy == NULL) { 3255 return SOC_E_INTERNAL; 3256 } 3257 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3258 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3259 if(intf == PHY82864_SYS_SIDE) { 3260 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3261 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 3262 } 3263 3264 SOC_IF_ERROR_RETURN(phymod_phy_rx_pmd_locked_get(&pm_phy_copy, value)); 3265 3266 return(SOC_E_NONE); 3267 } 3268 3269 /* 3270 * phy_82864_per_lane_rx_seq_done_get 3271 */ 3272 STATIC int 3273 phy_82864_per_lane_rx_seq_done_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 3274 { 3275 soc_phymod_phy_t *p_phy; 3276 uint32 lane_map; 3277 phymod_phy_access_t pm_phy_copy, *pm_phy; 3278 3279 /* locate the desired phy and lane */ 3280 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 3281 3282 /* Make a copy of the phy access and overwrite the desired lane */ 3283 pm_phy = &p_phy->pm_phy; 3284 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3285 pm_phy_copy.access.lane_mask = lane_map; 3286 pm_phy_copy.port_loc = phymodPortLocLine; 3287 if(intf == PHY82864_SYS_SIDE) { 3288 pm_phy_copy.port_loc = phymodPortLocSys; 3289 } 3290 3291 SOC_IF_ERROR_RETURN(phymod_phy_rx_pmd_locked_get(&pm_phy_copy, value)); 3292 3293 return(SOC_E_NONE); 3294 } 3295 3296 /* 3297 * phy_82864_fec_get 3298 */ 3299 STATIC int 3300 phy_82864_fec_enable_get(soc_phymod_ctrl_t *pmc, uint32 *value) 3301 { 3302 phymod_phy_access_t *pm_phy; 3303 pm_phy = &pmc->phy[pmc->main_phy]->pm_phy; 3304 3305 SOC_IF_ERROR_RETURN( 3306 phymod_phy_fec_enable_get(pm_phy, value)); 3307 return(SOC_E_NONE); 3308 } 3309 /* 3310 * phy_82864_tx_fir_pre_get 3311 */ 3312 STATIC int 3313 phy_82864_tx_fir_pre_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 3314 { 3315 phymod_phy_access_t *pm_phy; 3316 phymod_tx_t phymod_tx; 3317 phymod_phy_access_t pm_phy_copy; 3318 3319 pm_phy = &pmc->phy[0]->pm_phy; 3320 3321 if (pm_phy == NULL) { 3322 return SOC_E_INTERNAL; 3323 } 3324 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3325 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3326 if(intf == PHY82864_SYS_SIDE) { 3327 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3328 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 3329 } 3330 3331 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 3332 *value = phymod_tx.pre; 3333 3334 return(SOC_E_NONE); 3335 } 3336 /* 3337 * phy_82864_tx_fir_main_get 3338 */ 3339 STATIC int 3340 phy_82864_tx_fir_main_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 3341 { 3342 phymod_phy_access_t *pm_phy; 3343 phymod_tx_t phymod_tx; 3344 phymod_phy_access_t pm_phy_copy; 3345 3346 pm_phy = &pmc->phy[0]->pm_phy; 3347 3348 if (pm_phy == NULL) { 3349 return SOC_E_INTERNAL; 3350 } 3351 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3352 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3353 if(intf == PHY82864_SYS_SIDE) { 3354 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3355 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 3356 } 3357 3358 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 3359 *value = phymod_tx.main; 3360 3361 return(SOC_E_NONE); 3362 } 3363 3364 /* 3365 * phy_82864_tx_fir_post_get 3366 */ 3367 STATIC int 3368 phy_82864_tx_fir_post_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 3369 { 3370 phymod_phy_access_t *pm_phy; 3371 phymod_tx_t phymod_tx; 3372 phymod_phy_access_t pm_phy_copy; 3373 3374 pm_phy = &pmc->phy[0]->pm_phy; 3375 3376 if (pm_phy == NULL) { 3377 return SOC_E_INTERNAL; 3378 } 3379 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3380 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3381 if(intf == PHY82864_SYS_SIDE) { 3382 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3383 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 3384 } 3385 3386 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 3387 *value = phymod_tx.post; 3388 3389 return(SOC_E_NONE); 3390 } 3391 3392 /* 3393 * phy_82864_tx_fir_post2_get 3394 */ 3395 STATIC int 3396 phy_82864_tx_fir_post2_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 3397 { 3398 phymod_phy_access_t *pm_phy; 3399 phymod_tx_t phymod_tx; 3400 phymod_phy_access_t pm_phy_copy; 3401 3402 pm_phy = &pmc->phy[0]->pm_phy; 3403 3404 if (pm_phy == NULL) { 3405 return SOC_E_INTERNAL; 3406 } 3407 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3408 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3409 if(intf == PHY82864_SYS_SIDE) { 3410 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3411 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 3412 } 3413 3414 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 3415 *value = phymod_tx.post2; 3416 3417 return(SOC_E_NONE); 3418 } 3419 3420 /* 3421 * phy_82864_tx_fir_post3_get 3422 */ 3423 STATIC int 3424 phy_82864_tx_fir_post3_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 3425 { 3426 phymod_phy_access_t *pm_phy; 3427 phymod_tx_t phymod_tx; 3428 phymod_phy_access_t pm_phy_copy; 3429 3430 pm_phy = &pmc->phy[0]->pm_phy; 3431 3432 if (pm_phy == NULL) { 3433 return SOC_E_INTERNAL; 3434 } 3435 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3436 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3437 if(intf == PHY82864_SYS_SIDE) { 3438 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3439 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 3440 } 3441 3442 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 3443 *value = phymod_tx.post3; 3444 3445 return(SOC_E_NONE); 3446 } 3447 /* 3448 * phy_82864_per_lane_driver_current_get 3449 */ 3450 STATIC int 3451 phy_82864_per_lane_driver_current_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 3452 { 3453 soc_phymod_phy_t *p_phy; 3454 uint32 lane_map; 3455 phymod_phy_access_t pm_phy_copy, *pm_phy; 3456 phymod_tx_t phymod_tx; 3457 3458 /* locate the desired phy and lane */ 3459 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 3460 3461 /* Make a copy of the phy access and overwrite the desired lane */ 3462 pm_phy = &p_phy->pm_phy; 3463 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3464 pm_phy_copy.access.lane_mask = lane_map; 3465 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3466 if(intf == PHY82864_SYS_SIDE) { 3467 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3468 } 3469 3470 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 3471 *value = phymod_tx.amp; 3472 3473 return(SOC_E_NONE); 3474 } 3475 /* 3476 * phy_82864_rx_signal_detect_get 3477 */ 3478 STATIC int 3479 phy_82864_rx_signal_detect_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 3480 { 3481 /* $$$ Need to add diagnostic API */ 3482 return(SOC_E_UNAVAIL); 3483 } 3484 /* 3485 * phy_82864_rx_ppm_get 3486 */ 3487 STATIC int 3488 phy_82864_rx_ppm_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 3489 { 3490 /* $$$ Need to add diagnostic API */ 3491 return(SOC_E_UNAVAIL); 3492 } 3493 /* 3494 * phy_82864_per_lane_preemphasis_get 3495 */ 3496 STATIC int 3497 phy_82864_per_lane_preemphasis_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 3498 { 3499 soc_phymod_phy_t *p_phy; 3500 uint32 lane_map; 3501 phymod_phy_access_t pm_phy_copy, *pm_phy; 3502 phymod_tx_t phymod_tx; 3503 3504 /* locate the desired phy and lane */ 3505 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 3506 3507 /* Make a copy of the phy access and overwrite the desired lane */ 3508 pm_phy = &p_phy->pm_phy; 3509 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3510 pm_phy_copy.access.lane_mask = lane_map; 3511 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3512 if(intf == PHY82864_SYS_SIDE) { 3513 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3514 } 3515 3516 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 3517 /* 0 to 7 = pre 3518 * 8 to 15 = main 3519 * 16 to 24 = post*/ 3520 *value |= (phymod_tx.pre & 0xff); 3521 *value |= ((phymod_tx.main & 0xff) << 8); 3522 *value |= ((phymod_tx.post & 0xff) << 16); 3523 3524 3525 return(SOC_E_NONE); 3526 } 3527 3528 /* 3529 * phy_82864_per_lane_rx_low_freq_filter_set 3530 */ 3531 STATIC int 3532 phy_82864_per_lane_rx_low_freq_filter_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 value) 3533 { 3534 soc_phymod_phy_t *p_phy; 3535 uint32 lane_map; 3536 phymod_phy_access_t pm_phy_copy, *pm_phy; 3537 phymod_rx_t phymod_rx; 3538 3539 /* locate the desired phy and lane */ 3540 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 3541 3542 /* Make a copy of the phy access and overwrite the desired lane */ 3543 pm_phy = &p_phy->pm_phy; 3544 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3545 pm_phy_copy.access.lane_mask = lane_map; 3546 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3547 if(intf == PHY82864_SYS_SIDE) { 3548 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3549 } 3550 3551 sal_memset(&phymod_rx, 0, sizeof(phymod_rx_t)); 3552 phymod_rx.low_freq_peaking_filter.enable = TRUE; 3553 phymod_rx.low_freq_peaking_filter.value = value; 3554 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(&pm_phy_copy, &phymod_rx)); 3555 3556 return(SOC_E_NONE); 3557 } 3558 /* 3559 * phy_82864_per_lane_power_get 3560 */ 3561 STATIC int 3562 phy_82864_per_lane_power_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 3563 { 3564 phymod_phy_access_t *pm_phy; 3565 phymod_phy_power_t power; 3566 soc_phymod_phy_t *p_phy; 3567 uint32 lane_map; 3568 phymod_phy_access_t pm_phy_copy; 3569 3570 /* locate the desired phy and lane */ 3571 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 3572 3573 /* Make a copy of the phy access and overwrite the desired lane */ 3574 pm_phy = &p_phy->pm_phy; 3575 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3576 pm_phy_copy.access.lane_mask = lane_map; 3577 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3578 if(intf == PHY82864_SYS_SIDE) { 3579 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3580 } 3581 3582 phymod_phy_power_t_init(&power); 3583 3584 SOC_IF_ERROR_RETURN(phymod_phy_power_get(&pm_phy_copy, &power)); 3585 3586 if(power.tx == phymodPowerOn && power.rx == phymodPowerOn) { 3587 *value = 1; 3588 } else { 3589 *value = 0; 3590 } 3591 3592 return(SOC_E_NONE); 3593 } 3594 /* 3595 * phy_82864_power_get 3596 */ 3597 STATIC int 3598 phy_82864_power_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 3599 { 3600 phymod_phy_access_t *pm_phy; 3601 phymod_phy_power_t power; 3602 phymod_phy_access_t pm_phy_copy; 3603 3604 /* just take the value from the first phy */ 3605 if (pmc->phy[0] == NULL) { 3606 return SOC_E_INTERNAL; 3607 } 3608 pm_phy = &pmc->phy[0]->pm_phy; 3609 3610 if (pm_phy == NULL) { 3611 return SOC_E_INTERNAL; 3612 } 3613 3614 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3615 phymod_phy_power_t_init(&power); 3616 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3617 if(intf == PHY82864_SYS_SIDE) { 3618 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3619 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 3620 } 3621 3622 SOC_IF_ERROR_RETURN(phymod_phy_power_get(&pm_phy_copy, &power)); 3623 3624 if(power.tx == phymodPowerOn && power.rx == phymodPowerOn) { 3625 *value = 1; 3626 } else { 3627 *value = 0; 3628 } 3629 3630 return(SOC_E_NONE); 3631 } 3632 /* 3633 * phy_82864_per_lane_tx_polarity_get 3634 */ 3635 STATIC int 3636 phy_82864_per_lane_tx_polarity_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 3637 { 3638 phymod_phy_access_t *pm_phy; 3639 phymod_polarity_t polarity; 3640 soc_phymod_phy_t *p_phy; 3641 uint32 lane_map; 3642 phymod_phy_access_t pm_phy_copy; 3643 3644 /* locate the desired phy and lane */ 3645 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 3646 3647 /* Make a copy of the phy access and overwrite the desired lane */ 3648 pm_phy = &p_phy->pm_phy; 3649 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3650 pm_phy_copy.access.lane_mask = lane_map; 3651 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3652 if(intf == PHY82864_SYS_SIDE) { 3653 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3654 } 3655 3656 phymod_polarity_t_init(&polarity); 3657 SOC_IF_ERROR_RETURN(phymod_phy_polarity_get(&pm_phy_copy, &polarity)); 3658 3659 *value = polarity.tx_polarity; 3660 3661 return(SOC_E_NONE); 3662 } 3663 /* 3664 * phy_82864_tx_polarity_get 3665 */ 3666 STATIC int 3667 phy_82864_tx_polarity_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 3668 { 3669 phymod_phy_access_t *pm_phy; 3670 phymod_polarity_t polarity; 3671 phymod_phy_access_t pm_phy_copy; 3672 3673 /* just take the value from the first phy */ 3674 if (pmc->phy[0] == NULL) { 3675 return SOC_E_INTERNAL; 3676 } 3677 pm_phy = &pmc->phy[0]->pm_phy; 3678 3679 if (pm_phy == NULL) { 3680 return SOC_E_INTERNAL; 3681 } 3682 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3683 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3684 if(intf == PHY82864_SYS_SIDE) { 3685 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3686 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 3687 } 3688 phymod_polarity_t_init(&polarity); 3689 SOC_IF_ERROR_RETURN(phymod_phy_polarity_get(&pm_phy_copy, &polarity)); 3690 3691 *value = polarity.tx_polarity; 3692 3693 return(SOC_E_NONE); 3694 } 3695 3696 /* 3697 * phy_82864_per_lane_rx_polarity_get 3698 */ 3699 STATIC int 3700 phy_82864_per_lane_rx_polarity_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 3701 { 3702 phymod_phy_access_t *pm_phy; 3703 phymod_polarity_t polarity; 3704 soc_phymod_phy_t *p_phy; 3705 uint32 lane_map; 3706 phymod_phy_access_t pm_phy_copy; 3707 3708 /* locate the desired phy and lane */ 3709 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 3710 3711 /* Make a copy of the phy access and overwrite the desired lane */ 3712 pm_phy = &p_phy->pm_phy; 3713 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3714 pm_phy_copy.access.lane_mask = lane_map; 3715 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3716 if(intf == PHY82864_SYS_SIDE) { 3717 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3718 } 3719 3720 phymod_polarity_t_init(&polarity); 3721 SOC_IF_ERROR_RETURN(phymod_phy_polarity_get(&pm_phy_copy, &polarity)); 3722 3723 *value = polarity.rx_polarity; 3724 3725 return(SOC_E_NONE); 3726 } 3727 /* 3728 * phy_82864_rx_polarity_get 3729 */ 3730 STATIC int 3731 phy_82864_rx_polarity_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 3732 { 3733 phymod_phy_access_t *pm_phy; 3734 phymod_polarity_t polarity; 3735 phymod_phy_access_t pm_phy_copy; 3736 3737 /* just take the value from the first phy */ 3738 if (pmc->phy[0] == NULL) { 3739 return SOC_E_INTERNAL; 3740 } 3741 pm_phy = &pmc->phy[0]->pm_phy; 3742 3743 if (pm_phy == NULL) { 3744 return SOC_E_INTERNAL; 3745 } 3746 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3747 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3748 if(intf == PHY82864_SYS_SIDE) { 3749 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3750 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 3751 } 3752 phymod_polarity_t_init(&polarity); 3753 SOC_IF_ERROR_RETURN(phymod_phy_polarity_get(&pm_phy_copy, &polarity)); 3754 3755 *value = polarity.rx_polarity; 3756 3757 return(SOC_E_NONE); 3758 } 3759 3760 /* 3761 * phy_82864_unreliable_los_get 3762 */ 3763 STATIC int 3764 phy_82864_unreliable_los_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 3765 { 3766 phymod_phy_access_t *pm_phy; 3767 phymod_firmware_lane_config_t fw_config; 3768 phymod_phy_access_t pm_phy_copy; 3769 *value = 0; 3770 sal_memset(&fw_config, 0, sizeof(fw_config)); 3771 3772 /* just take the value from the first phy */ 3773 if (pmc->phy[0] == NULL) { 3774 return SOC_E_INTERNAL; 3775 } 3776 3777 pm_phy = &pmc->phy[0]->pm_phy; 3778 if (pm_phy == NULL) { 3779 return SOC_E_INTERNAL; 3780 } 3781 3782 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3783 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 3784 if(intf == PHY82864_SYS_SIDE) { 3785 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 3786 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 3787 } 3788 3789 SOC_IF_ERROR_RETURN(phymod_phy_firmware_lane_config_get(&pm_phy_copy, &fw_config)); 3790 if (fw_config.UnreliableLos) { 3791 *value = 1; 3792 } else { 3793 *value = 0; 3794 } 3795 3796 return(SOC_E_NONE); 3797 } 3798 /* 3799 * Function: 3800 * phy82864_control_get 3801 * Purpose: 3802 * Get current control settings of the PHY. 3803 * Parameters: 3804 * unit - BCM unit number. 3805 * port - Port number. 3806 * type - Control to update 3807 * value - (OUT) Current setting for the control 3808 * Returns: 3809 * SOC_E_NONE 3810 */ 3811 STATIC int 3812 phy_82864_control_get(int unit, soc_port_t port, soc_phy_control_t type, uint32 *value) 3813 { 3814 int rv; 3815 phy_ctrl_t *pc; 3816 soc_phymod_ctrl_t *pmc; 3817 int32 intf; 3818 3819 PHY_CONTROL_TYPE_CHECK(type); 3820 3821 /* locate phy control */ 3822 pc = EXT_PHY_SW_STATE(unit, port); 3823 if (pc == NULL) { 3824 return SOC_E_INTERNAL; 3825 } 3826 3827 pmc = &pc->phymod_ctrl; 3828 3829 intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY82864_SYS_SIDE : PHY82864_LINE_SIDE; 3830 3831 switch(type) { 3832 /* PRBS */ 3833 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_POLYNOMIAL: 3834 rv = phy_82864_prbs_tx_poly_get(pmc, port, intf, value); 3835 break; 3836 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_INVERT_DATA: 3837 rv = phy_82864_prbs_tx_invert_data_get(pmc, port, intf, value); 3838 break; 3839 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_ENABLE: 3840 rv = phy_82864_prbs_tx_enable_get(pmc, port, intf, value); 3841 break; 3842 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_POLYNOMIAL: 3843 rv = phy_82864_prbs_rx_poly_get(pmc, port, intf, value); 3844 break; 3845 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_INVERT_DATA: 3846 rv = phy_82864_prbs_rx_invert_data_get(pmc, port, intf, value); 3847 break; 3848 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_ENABLE: 3849 rv = phy_82864_prbs_rx_enable_get(pmc, port, intf, value); 3850 break; 3851 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 3852 rv = phy_82864_prbs_tx_poly_get(pmc, port, intf, value); 3853 break; 3854 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 3855 rv = phy_82864_prbs_tx_invert_data_get(pmc, port, intf, value); 3856 break; 3857 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 3858 rv = phy_82864_prbs_tx_enable_get(pmc, port, intf, value); 3859 break; 3860 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 3861 rv = phy_82864_prbs_rx_enable_get(pmc, port, intf, value); 3862 break; 3863 case SOC_PHY_CONTROL_PRBS_RX_STATUS: 3864 rv = phy_82864_prbs_rx_status_get(pmc, port, intf, value); 3865 break; 3866 /* LOOPBACK */ 3867 case SOC_PHY_CONTROL_LOOPBACK_REMOTE: 3868 case SOC_PHY_CONTROL_LOOPBACK_REMOTE_PCS_BYPASS: 3869 rv = phy_82864_loopback_remote_get(pmc, port, intf, value); 3870 break; 3871 case SOC_PHY_CONTROL_LOOPBACK_PMD: 3872 rv = phy_82864_loopback_internal_pmd_get(pmc, port, intf, value); 3873 break; 3874 /* PREEMPHASIS */ 3875 case SOC_PHY_CONTROL_PREEMPHASIS: 3876 case SOC_PHY_CONTROL_PREEMPHASIS_LANE0: 3877 rv = phy_82864_per_lane_preemphasis_get(pmc, port, intf, 0, value); 3878 break; 3879 case SOC_PHY_CONTROL_PREEMPHASIS_LANE1: 3880 rv = phy_82864_per_lane_preemphasis_get(pmc, port, intf, 1, value); 3881 break; 3882 case SOC_PHY_CONTROL_PREEMPHASIS_LANE2: 3883 rv = phy_82864_per_lane_preemphasis_get(pmc, port, intf, 2, value); 3884 break; 3885 case SOC_PHY_CONTROL_PREEMPHASIS_LANE3: 3886 rv = phy_82864_per_lane_preemphasis_get(pmc, port, intf, 3, value); 3887 break; 3888 case SOC_PHY_CONTROL_TX_FIR_PRE: 3889 /* assume they are all the same as lane 0 */ 3890 rv = phy_82864_tx_fir_pre_get(pmc, port, intf, value); 3891 break; 3892 case SOC_PHY_CONTROL_TX_FIR_MAIN: 3893 /* assume they are all the same as lane 0 */ 3894 rv = phy_82864_tx_fir_main_get(pmc, port, intf, value); 3895 break; 3896 case SOC_PHY_CONTROL_TX_FIR_POST: 3897 /* assume they are all the same as lane 0 */ 3898 rv = phy_82864_tx_fir_post_get(pmc, port, intf, value); 3899 break; 3900 case SOC_PHY_CONTROL_TX_FIR_POST2: 3901 /* assume they are all the same as lane 0 */ 3902 rv = phy_82864_tx_fir_post2_get(pmc, port, intf, value); 3903 break; 3904 case SOC_PHY_CONTROL_TX_FIR_POST3: 3905 /* assume they are all the same as lane 0 */ 3906 rv = phy_82864_tx_fir_post3_get(pmc, port, intf, value); 3907 break; 3908 3909 /* DRIVER CURRENT */ 3910 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0: 3911 rv = phy_82864_per_lane_driver_current_get(pmc, port, intf, 0, value); 3912 break; 3913 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1: 3914 rv = phy_82864_per_lane_driver_current_get(pmc, port, intf, 1, value); 3915 break; 3916 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2: 3917 rv = phy_82864_per_lane_driver_current_get(pmc, port, intf, 2, value); 3918 break; 3919 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3: 3920 rv = phy_82864_per_lane_driver_current_get(pmc, port, intf, 3, value); 3921 break; 3922 case SOC_PHY_CONTROL_DRIVER_CURRENT: 3923 rv = phy_82864_per_lane_driver_current_get(pmc, port, intf, 0, value); 3924 break; 3925 3926 /* RX PEAK FILTER */ 3927 case SOC_PHY_CONTROL_RX_PEAK_FILTER: 3928 rv = phy_82864_rx_peak_filter_get(pmc, port, intf, value); 3929 break; 3930 case SOC_PHY_CONTROL_RX_LOW_FREQ_PEAK_FILTER: 3931 rv = phy_82864_rx_low_freq_filter_get(pmc, port, intf, value); 3932 break; 3933 3934 /* RX VGA */ 3935 case SOC_PHY_CONTROL_RX_VGA: 3936 rv = phy_82864_rx_vga_get(pmc, port, intf, value); 3937 break; 3938 3939 /* RX TAP */ 3940 case SOC_PHY_CONTROL_RX_TAP1: 3941 rv = phy_82864_rx_tap_get(pmc, port, intf, 0, value); 3942 break; 3943 case SOC_PHY_CONTROL_RX_TAP2: 3944 rv = phy_82864_rx_tap_get(pmc, port, intf, 1, value); 3945 break; 3946 case SOC_PHY_CONTROL_RX_TAP3: 3947 rv = phy_82864_rx_tap_get(pmc, port, intf, 2, value); 3948 break; 3949 case SOC_PHY_CONTROL_RX_TAP4: 3950 rv = phy_82864_rx_tap_get(pmc, port, intf, 3, value); 3951 break; 3952 case SOC_PHY_CONTROL_RX_TAP5: 3953 rv = phy_82864_rx_tap_get(pmc, port, intf, 4, value); 3954 break; 3955 3956 /* PHASE INTERPOLATOR */ 3957 case SOC_PHY_CONTROL_PHASE_INTERP: 3958 rv = phy_82864_pi_control_get(pmc, port, intf, value); 3959 break; 3960 3961 /* RX SIGNAL DETECT */ 3962 case SOC_PHY_CONTROL_RX_SIGNAL_DETECT: 3963 rv = phy_82864_rx_signal_detect_get(pmc, port, intf, value); 3964 break; 3965 case SOC_PHY_CONTROL_RX_SEQ_DONE: 3966 rv = phy_82864_rx_seq_done_get(pmc, port, intf, value); 3967 break; 3968 case SOC_PHY_CONTROL_RX_PPM: 3969 rv = phy_82864_rx_ppm_get(pmc, port, intf, value); 3970 break; 3971 /* FEC */ 3972 case SOC_PHY_CONTROL_FORWARD_ERROR_CORRECTION: 3973 rv = phy_82864_fec_enable_get(pmc, value); 3974 break; 3975 case SOC_PHY_CONTROL_RX_POLARITY: 3976 rv = phy_82864_rx_polarity_get(pmc, port, intf, value);; 3977 break; 3978 case SOC_PHY_CONTROL_TX_POLARITY: 3979 rv = phy_82864_tx_polarity_get(pmc, port, intf, value); 3980 break; 3981 /* POWER */ 3982 case SOC_PHY_CONTROL_POWER: 3983 rv = phy_82864_power_get(pmc, port, intf, value); 3984 break; 3985 case SOC_PHY_CONTROL_CL72: 3986 rv = phy_82864_cl72_enable_get(pmc, port, intf, value); 3987 break; 3988 case SOC_PHY_CONTROL_CL72_STATUS: 3989 rv = phy_82864_cl72_status_get(pmc, port, intf, value); 3990 break; 3991 case SOC_PHY_CONTROL_INTR_MASK: 3992 rv = phy_82864_intr_enable_get(pc, intf, value); 3993 break; 3994 case SOC_PHY_CONTROL_INTR_STATUS: 3995 rv = phy_82864_intr_status_get(pc, intf, value); 3996 break; 3997 case SOC_PHY_CONTROL_TX_LANE_SQUELCH: 3998 rv = phy_82864_tx_lane_squelch_get(pmc, port, intf, value); 3999 break; 4000 case SOC_PHY_CONTROL_GPIO_CONFIG: 4001 rv = phy_82864_gpio_config_get(pc, value); 4002 break; 4003 case SOC_PHY_CONTROL_GPIO_VALUE: 4004 rv = phy_82864_gpio_value_get(pc, value); 4005 break; 4006 case SOC_PHY_CONTROL_FIRMWARE_MODE: 4007 rv = phy_82864_firmware_mode_get(pc, port, intf, value); 4008 break; 4009 case SOC_PHY_CONTROL_FIRMWARE_DFE_ENABLE: 4010 rv = phy_82864_firmware_dfe_enable_get(pc, port, intf, value); 4011 break; 4012 case SOC_PHY_CONTROL_FIRMWARE_LP_DFE_ENABLE: 4013 rv = phy_82864_firmware_lp_dfe_enable_get(pc, port, intf, value); 4014 break; 4015 case SOC_PHY_CONTROL_UNRELIABLE_LOS: 4016 rv = phy_82864_unreliable_los_get(pmc, port, intf, value); 4017 break; 4018 default: 4019 rv = SOC_E_UNAVAIL; 4020 break; 4021 } 4022 4023 return rv; 4024 } 4025 4026 /* 4027 * Function: 4028 * phy_82864_per_lane_control_get 4029 * Purpose: 4030 * Configure PHY device specific control fucntion. 4031 * Parameters: 4032 * unit - StrataSwitch unit #. 4033 * port - StrataSwitch port #. 4034 * lane - lane number 4035 * type - Control to update 4036 * value - New setting for the control 4037 * Returns: 4038 * SOC_E_NONE 4039 */ 4040 STATIC int 4041 phy_82864_per_lane_control_get(int unit, soc_port_t port, int lane, 4042 soc_phy_control_t type, uint32 *value) 4043 { 4044 int rv = SOC_E_UNAVAIL; 4045 phy_ctrl_t *pc; 4046 soc_phymod_ctrl_t *pmc; 4047 int32 intf; 4048 4049 /* locate phy control, phymod control, and the configuration data */ 4050 pc = EXT_PHY_SW_STATE(unit, port); 4051 if (pc == NULL) { 4052 return SOC_E_INTERNAL; 4053 } 4054 pmc = &pc->phymod_ctrl; 4055 4056 PHY_CONTROL_TYPE_CHECK(type); 4057 4058 intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY82864_SYS_SIDE : PHY82864_LINE_SIDE; 4059 4060 switch(type) { 4061 case SOC_PHY_CONTROL_RX_SEQ_DONE: 4062 rv = phy_82864_per_lane_rx_seq_done_get(pmc, port, intf, lane, value); 4063 break; 4064 case SOC_PHY_CONTROL_PREEMPHASIS: 4065 rv = phy_82864_per_lane_preemphasis_get(pmc, port, intf, lane, value); 4066 break; 4067 case SOC_PHY_CONTROL_DRIVER_CURRENT: 4068 rv = phy_82864_per_lane_driver_current_get(pmc, port, intf, lane, value); 4069 break; 4070 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 4071 rv = SOC_E_UNAVAIL; 4072 break; 4073 case SOC_PHY_CONTROL_DRIVER_POST2_CURRENT: 4074 rv = SOC_E_UNAVAIL; 4075 break; 4076 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_POLYNOMIAL: 4077 rv = phy_82864_per_lane_prbs_tx_poly_get(pmc, port, intf, lane, value); 4078 break; 4079 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_INVERT_DATA: 4080 rv = phy_82864_per_lane_prbs_tx_invert_data_get(pmc, port, intf, lane, value); 4081 break; 4082 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_ENABLE: 4083 rv = phy_82864_per_lane_prbs_tx_enable_get(pmc, port, intf, lane, value); 4084 break; 4085 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_POLYNOMIAL: 4086 rv = phy_82864_per_lane_prbs_rx_poly_get(pmc, port, intf, lane, value); 4087 break; 4088 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_INVERT_DATA: 4089 rv = phy_82864_per_lane_prbs_rx_invert_data_get(pmc, port, intf, lane, value); 4090 break; 4091 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_ENABLE: 4092 rv = phy_82864_per_lane_prbs_rx_enable_get(pmc, port, intf, lane, value); 4093 break; 4094 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 4095 rv = phy_82864_per_lane_prbs_tx_poly_get(pmc, port, intf, lane, value); 4096 rv = phy_82864_per_lane_prbs_rx_poly_get(pmc, port, intf, lane, value); 4097 break; 4098 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 4099 rv = phy_82864_per_lane_prbs_tx_invert_data_get(pmc, port, intf, lane, value); 4100 break; 4101 case SOC_PHY_CONTROL_PRBS_RX_INVERT_DATA: 4102 rv = phy_82864_per_lane_prbs_rx_invert_data_get(pmc, port, intf, lane, value); 4103 break; 4104 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 4105 rv = phy_82864_per_lane_prbs_tx_enable_get(pmc, port, intf, lane, value); 4106 rv = phy_82864_per_lane_prbs_rx_enable_get(pmc, port, intf, lane, value); 4107 break; 4108 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 4109 rv = phy_82864_per_lane_prbs_rx_enable_get(pmc, port, intf, lane, value); 4110 rv = phy_82864_per_lane_prbs_tx_enable_get(pmc, port, intf, lane, value); 4111 break; 4112 case SOC_PHY_CONTROL_PRBS_RX_STATUS: 4113 rv = phy_82864_per_lane_prbs_rx_status_get(pmc, port, intf, lane, value); 4114 break; 4115 case SOC_PHY_CONTROL_RX_PEAK_FILTER: 4116 rv = phy_82864_per_lane_rx_peak_filter_get(pmc, port, intf, lane, value); 4117 break; 4118 case SOC_PHY_CONTROL_RX_VGA: 4119 rv = phy_82864_per_lane_rx_vga_get(pmc, port, intf, lane, value); 4120 break; 4121 case SOC_PHY_CONTROL_RX_TAP1: 4122 rv = phy_82864_per_lane_rx_dfe_tap_control_get(pmc, port, intf, lane, 0, value); 4123 break; 4124 case SOC_PHY_CONTROL_RX_TAP2: 4125 rv = phy_82864_per_lane_rx_dfe_tap_control_get(pmc, port, intf, lane, 1, value); 4126 break; 4127 case SOC_PHY_CONTROL_RX_TAP3: 4128 rv = phy_82864_per_lane_rx_dfe_tap_control_get(pmc, port, intf, lane, 2, value); 4129 break; 4130 case SOC_PHY_CONTROL_RX_TAP4: 4131 rv = phy_82864_per_lane_rx_dfe_tap_control_get(pmc, port, intf, lane, 3, value); 4132 break; 4133 case SOC_PHY_CONTROL_RX_TAP5: 4134 rv = phy_82864_per_lane_rx_dfe_tap_control_get(pmc, port, intf, lane, 4, value); 4135 break; 4136 case SOC_PHY_CONTROL_RX_LOW_FREQ_PEAK_FILTER: 4137 rv = phy_82864_per_lane_rx_low_freq_filter_get(pmc, port, intf, lane, value); 4138 break; 4139 case SOC_PHY_CONTROL_RX_PLUS1_SLICER: 4140 rv = SOC_E_UNAVAIL; 4141 break; 4142 case SOC_PHY_CONTROL_RX_MINUS1_SLICER: 4143 rv = SOC_E_UNAVAIL; 4144 break; 4145 case SOC_PHY_CONTROL_RX_D_SLICER: 4146 rv = SOC_E_UNAVAIL; 4147 break; 4148 /* LOOPBACK */ 4149 case SOC_PHY_CONTROL_LOOPBACK_REMOTE: 4150 case SOC_PHY_CONTROL_LOOPBACK_REMOTE_PCS_BYPASS: 4151 rv = phy_82864_per_lane_loopback_remote_get(pmc, port, intf, lane, value); 4152 break; 4153 case SOC_PHY_CONTROL_LOOPBACK_PMD: 4154 rv = phy_82864_per_lane_loopback_internal_pmd_get(pmc, port, intf, lane, value); 4155 break; 4156 case SOC_PHY_CONTROL_RX_POLARITY: 4157 rv = phy_82864_per_lane_rx_polarity_get(pmc, port, intf, lane, value); 4158 break; 4159 case SOC_PHY_CONTROL_TX_POLARITY: 4160 rv = phy_82864_per_lane_tx_polarity_get(pmc, port, intf, lane, value); 4161 break; 4162 /* POWER */ 4163 case SOC_PHY_CONTROL_POWER: 4164 rv = phy_82864_per_lane_power_get(pmc, port, intf, lane, value); 4165 break; 4166 case SOC_PHY_CONTROL_TX_FIR_PRE: 4167 case SOC_PHY_CONTROL_TX_FIR_MAIN: 4168 case SOC_PHY_CONTROL_TX_FIR_POST: 4169 case SOC_PHY_CONTROL_TX_FIR_POST2: 4170 case SOC_PHY_CONTROL_TX_FIR_POST3: 4171 rv = phy_82864_per_lane_tx_get(pmc, port, intf, type, lane, value); 4172 break; 4173 case SOC_PHY_CONTROL_TX_LANE_SQUELCH: 4174 rv = phy_82864_per_lane_tx_lane_squelch_get(pmc, port, intf, lane, value); 4175 break; 4176 case SOC_PHY_CONTROL_CL72: 4177 rv = phy_82864_per_lane_cl72_enable_get(pmc, port, intf, lane, value); 4178 break; 4179 case SOC_PHY_CONTROL_CL72_STATUS: 4180 rv = phy_82864_per_lane_cl72_status_get(pmc, port, intf, lane, value); 4181 break; 4182 default: 4183 rv = SOC_E_UNAVAIL; 4184 break; 4185 } 4186 4187 return rv; 4188 } 4189 4190 /* 4191 * phy_82864_firmware_mode_set 4192 */ 4193 STATIC int 4194 phy_82864_firmware_mode_set(phy_ctrl_t *pc, soc_port_t port, int32 intf, uint32 value) 4195 { 4196 int idx; 4197 soc_phymod_ctrl_t *pmc; 4198 phymod_phy_access_t *pm_phy; 4199 phymod_phy_access_t pm_phy_copy; 4200 phymod_firmware_lane_config_t fw_config; 4201 pmc = &pc->phymod_ctrl; 4202 4203 /* loop through all cores */ 4204 for (idx = 0; idx < pmc->num_phys; idx++) { 4205 if (pmc->phy[idx] == NULL) { 4206 return(SOC_E_INTERNAL); 4207 } 4208 pm_phy = &pmc->phy[idx]->pm_phy; 4209 if (pm_phy == NULL) { 4210 return(SOC_E_INTERNAL); 4211 } 4212 4213 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4214 PHY82864_LINE_SIDE(&pm_phy_copy); 4215 if(intf == PHY82864_SYS_SIDE) { 4216 PHY82864_SYSTEM_SIDE(&pm_phy_copy); 4217 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 4218 } 4219 4220 sal_memset(&fw_config, 0, sizeof(fw_config)); 4221 SOC_IF_ERROR_RETURN(phymod_phy_firmware_lane_config_get(&pm_phy_copy, &fw_config)); 4222 4223 switch (value) { 4224 case SOC_PHY_FIRMWARE_DEFAULT: 4225 fw_config.DfeOn = 0xF; 4226 fw_config.LpDfeOn = 0xF; 4227 fw_config.ForceBrDfe = 0xF; 4228 break; 4229 case SOC_PHY_FIRMWARE_FORCE_OSDFE: 4230 fw_config.DfeOn = 1; 4231 fw_config.ForceBrDfe = 0; 4232 break; 4233 case SOC_PHY_FIRMWARE_SFP_DAC: 4234 fw_config.MediaType = phymodFirmwareMediaTypeCopperCable; 4235 break; 4236 case SOC_PHY_FIRMWARE_XLAUI: 4237 fw_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane; 4238 break; 4239 case SOC_PHY_FIRMWARE_SFP_OPT_SR4: 4240 fw_config.MediaType = phymodFirmwareMediaTypeOptics; 4241 break; 4242 case SOC_PHY_FIRMWARE_LP_DFE_ENABLE: 4243 fw_config.LpDfeOn = 1; 4244 fw_config.DfeOn = 1; 4245 break; 4246 case SOC_PHY_FIRMWARE_DFE_ENABLE: 4247 fw_config.DfeOn = 1; 4248 break; 4249 default: 4250 return SOC_E_UNAVAIL; 4251 } 4252 4253 SOC_IF_ERROR_RETURN(phymod_phy_firmware_lane_config_set(&pm_phy_copy, fw_config)); 4254 } 4255 4256 return(SOC_E_NONE); 4257 } 4258 4259 /* 4260 * phy_82864_firmware_dfe_enable_set 4261 */ 4262 STATIC int 4263 phy_82864_firmware_dfe_enable_set(phy_ctrl_t *pc, soc_port_t port, int32 intf, uint32 enable) 4264 { 4265 int idx; 4266 soc_phymod_ctrl_t *pmc; 4267 phymod_phy_access_t pm_phy_copy; 4268 phymod_phy_access_t *pm_phy; 4269 phymod_firmware_lane_config_t fw_config; 4270 pmc = &pc->phymod_ctrl; 4271 4272 /* loop through all cores */ 4273 for (idx = 0; idx < pmc->num_phys; idx++) { 4274 if (pmc->phy[idx] == NULL) { 4275 return(SOC_E_INTERNAL); 4276 } 4277 4278 pm_phy = &pmc->phy[idx]->pm_phy; 4279 if (pm_phy == NULL) { 4280 return(SOC_E_INTERNAL); 4281 } 4282 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4283 PHY82864_LINE_SIDE(&pm_phy_copy); 4284 if(intf == PHY82864_SYS_SIDE) { 4285 PHY82864_SYSTEM_SIDE(&pm_phy_copy); 4286 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 4287 } 4288 4289 sal_memset(&fw_config, 0, sizeof(fw_config)); 4290 SOC_IF_ERROR_RETURN(phymod_phy_firmware_lane_config_get(&pm_phy_copy, &fw_config)); 4291 4292 if (enable) { 4293 fw_config.DfeOn = 1; 4294 } else { 4295 fw_config.DfeOn = 0; 4296 } 4297 4298 SOC_IF_ERROR_RETURN(phymod_phy_firmware_lane_config_set(&pm_phy_copy, fw_config)); 4299 } 4300 4301 return(SOC_E_NONE); 4302 } 4303 4304 /* 4305 * phy_82864_firmware_lp_dfe_enable_set 4306 */ 4307 STATIC int 4308 phy_82864_firmware_lp_dfe_enable_set(phy_ctrl_t *pc, soc_port_t port, int32 intf, uint32 enable) 4309 { 4310 int idx; 4311 soc_phymod_ctrl_t *pmc; 4312 phymod_phy_access_t pm_phy_copy; 4313 phymod_phy_access_t *pm_phy; 4314 phymod_firmware_lane_config_t fw_config; 4315 pmc = &pc->phymod_ctrl; 4316 4317 /* loop through all cores */ 4318 for (idx = 0; idx < pmc->num_phys; idx++) { 4319 if (pmc->phy[idx] == NULL) { 4320 return(SOC_E_INTERNAL); 4321 } 4322 4323 pm_phy = &pmc->phy[idx]->pm_phy; 4324 if (pm_phy == NULL) { 4325 return(SOC_E_INTERNAL); 4326 } 4327 4328 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4329 PHY82864_LINE_SIDE(&pm_phy_copy); 4330 if(intf == PHY82864_SYS_SIDE) { 4331 PHY82864_SYSTEM_SIDE(&pm_phy_copy); 4332 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 4333 } 4334 4335 sal_memset(&fw_config, 0, sizeof(fw_config)); 4336 SOC_IF_ERROR_RETURN(phymod_phy_firmware_lane_config_get(&pm_phy_copy, &fw_config)); 4337 4338 if (enable) { 4339 fw_config.DfeOn = 1; 4340 fw_config.LpDfeOn = 1; 4341 } else { 4342 fw_config.LpDfeOn = 0; 4343 } 4344 4345 SOC_IF_ERROR_RETURN(phymod_phy_firmware_lane_config_set(&pm_phy_copy, fw_config)); 4346 } 4347 4348 return(SOC_E_NONE); 4349 } 4350 4351 /* 4352 * phy_82864_firmware_mode_get 4353 */ 4354 STATIC int 4355 phy_82864_firmware_mode_get(phy_ctrl_t *pc, soc_port_t port, int32 intf, uint32 *value) 4356 { 4357 soc_phymod_ctrl_t *pmc; 4358 phymod_phy_access_t pm_phy_copy; 4359 phymod_phy_access_t *pm_phy; 4360 phymod_firmware_lane_config_t fw_config; 4361 pmc = &pc->phymod_ctrl; 4362 *value = 0; 4363 4364 /* just take the value from the first phy */ 4365 if (pmc->phy[0] == NULL) { 4366 return SOC_E_INTERNAL; 4367 } 4368 4369 pm_phy = &pmc->phy[0]->pm_phy; 4370 if (pm_phy == NULL) { 4371 return SOC_E_INTERNAL; 4372 } 4373 4374 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4375 PHY82864_LINE_SIDE(&pm_phy_copy); 4376 if(intf == PHY82864_SYS_SIDE) { 4377 PHY82864_SYSTEM_SIDE(&pm_phy_copy); 4378 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 4379 } 4380 4381 sal_memset(&fw_config, 0, sizeof(fw_config)); 4382 SOC_IF_ERROR_RETURN(phymod_phy_firmware_lane_config_get(&pm_phy_copy, &fw_config)); 4383 4384 if ((fw_config.LpDfeOn) && (fw_config.DfeOn)) { 4385 *value = SOC_PHY_FIRMWARE_LP_DFE_ENABLE; 4386 } else if (fw_config.MediaType == phymodFirmwareMediaTypeCopperCable) { 4387 *value = SOC_PHY_FIRMWARE_SFP_DAC; 4388 } else if (fw_config.MediaType == phymodFirmwareMediaTypePcbTraceBackPlane) { 4389 *value = SOC_PHY_FIRMWARE_XLAUI; 4390 } else if (fw_config.MediaType == phymodFirmwareMediaTypeOptics){ 4391 *value = SOC_PHY_FIRMWARE_SFP_OPT_SR4; 4392 } else if ((fw_config.DfeOn) && (fw_config.ForceBrDfe == 0) && (fw_config.LpDfeOn == 0)) { 4393 *value = SOC_PHY_FIRMWARE_DFE_ENABLE; 4394 } else if ((fw_config.DfeOn) && (fw_config.ForceBrDfe == 0)) { 4395 *value = SOC_PHY_FIRMWARE_FORCE_OSDFE; 4396 } else { 4397 *value = SOC_PHY_FIRMWARE_DEFAULT; 4398 } 4399 4400 return(SOC_E_NONE); 4401 } 4402 /* 4403 * phy_82864_firmware_dfe_enable_get 4404 */ 4405 STATIC int 4406 phy_82864_firmware_dfe_enable_get(phy_ctrl_t *pc, soc_port_t port, int32 intf, uint32 *value) 4407 { 4408 soc_phymod_ctrl_t *pmc; 4409 phymod_phy_access_t pm_phy_copy; 4410 phymod_phy_access_t *pm_phy; 4411 phymod_firmware_lane_config_t fw_config; 4412 pmc = &pc->phymod_ctrl; 4413 *value = 0; 4414 4415 /* just take the value from the first phy */ 4416 if (pmc->phy[0] == NULL) { 4417 return SOC_E_INTERNAL; 4418 } 4419 4420 pm_phy = &pmc->phy[0]->pm_phy; 4421 if (pm_phy == NULL) { 4422 return SOC_E_INTERNAL; 4423 } 4424 4425 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4426 PHY82864_LINE_SIDE(&pm_phy_copy); 4427 if(intf == PHY82864_SYS_SIDE) { 4428 PHY82864_SYSTEM_SIDE(&pm_phy_copy); 4429 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 4430 } 4431 4432 sal_memset(&fw_config, 0, sizeof(fw_config)); 4433 SOC_IF_ERROR_RETURN(phymod_phy_firmware_lane_config_get(&pm_phy_copy, &fw_config)); 4434 4435 if (fw_config.DfeOn) { 4436 *value = 1; 4437 } else { 4438 *value = 0; 4439 } 4440 4441 return(SOC_E_NONE); 4442 } 4443 /* 4444 * phy_82864_firmware_lp_dfe_enable_get 4445 */ 4446 STATIC int 4447 phy_82864_firmware_lp_dfe_enable_get(phy_ctrl_t *pc, soc_port_t port, int32 intf, uint32 *value) 4448 { 4449 soc_phymod_ctrl_t *pmc; 4450 phymod_phy_access_t *pm_phy; 4451 phymod_firmware_lane_config_t fw_config; 4452 phymod_phy_access_t pm_phy_copy; 4453 pmc = &pc->phymod_ctrl; 4454 *value = 0; 4455 4456 /* just take the value from the first phy */ 4457 if (pmc->phy[0] == NULL) { 4458 return SOC_E_INTERNAL; 4459 } 4460 4461 pm_phy = &pmc->phy[0]->pm_phy; 4462 if (pm_phy == NULL) { 4463 return SOC_E_INTERNAL; 4464 } 4465 4466 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4467 PHY82864_LINE_SIDE(&pm_phy_copy); 4468 if(intf == PHY82864_SYS_SIDE) { 4469 PHY82864_SYSTEM_SIDE(&pm_phy_copy); 4470 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 4471 } 4472 4473 sal_memset(&fw_config, 0, sizeof(fw_config)); 4474 SOC_IF_ERROR_RETURN(phymod_phy_firmware_lane_config_get(&pm_phy_copy, &fw_config)); 4475 4476 if (fw_config.LpDfeOn && fw_config.DfeOn) { 4477 *value = 1; 4478 } else { 4479 *value = 0; 4480 } 4481 4482 return(SOC_E_NONE); 4483 } 4484 4485 /* 4486 * Function: 4487 * phy82864_duplex_get 4488 * Purpose: 4489 * Get PHY duplex mode 4490 * Parameters: 4491 * unit - BCM unit number. 4492 * port - Port number. 4493 * duplex - current duplex mode 4494 * Returns: 4495 * SOC_E_NONE 4496 */ 4497 STATIC int 4498 phy82864_duplex_get(int unit, soc_port_t port, int *duplex) 4499 { 4500 *duplex = TRUE; 4501 return SOC_E_NONE; 4502 } 4503 4504 /* 4505 * Function: 4506 * phy_82864_an_set 4507 * Purpose: 4508 * Enable or disable auto-negotiation on the specified port. 4509 * Parameters: 4510 * unit - BCM unit number. 4511 * port - Port number. 4512 * an - Boolean, if true, auto-negotiation is enabled 4513 * (and/or restarted). If false, autonegotiation is disabled. 4514 * Returns: 4515 * SOC_E_XXX _soc_triumph_tx 4516 */ 4517 STATIC int 4518 phy_82864_an_set(int unit, soc_port_t port, int enable) 4519 { 4520 phy_ctrl_t *pc; 4521 soc_phymod_ctrl_t *pmc; 4522 soc_phymod_phy_t *phy; 4523 phymod_autoneg_control_t an; 4524 soc_info_t *si; 4525 4526 /* locate phy control */ 4527 pc = EXT_PHY_SW_STATE(unit, port); 4528 if (pc == NULL) { 4529 return SOC_E_INTERNAL; 4530 } 4531 4532 /*skip autoneg init for 25G/50G */ 4533 if(pc->speed_max==50000 || pc->speed_max==25000){ 4534 return (SOC_E_NONE); 4535 } 4536 phymod_autoneg_control_t_init(&an); 4537 pmc = &pc->phymod_ctrl; 4538 si = &SOC_INFO(unit); 4539 4540 /* only request autoneg on the first core */ 4541 phy = pmc->phy[pmc->main_phy]; 4542 if (phy == NULL) { 4543 return SOC_E_INTERNAL; 4544 } 4545 an.enable = enable; 4546 an.num_lane_adv = si->port_num_lanes[port]; 4547 an.an_mode = phymod_AN_MODE_CL73; 4548 SOC_IF_ERROR_RETURN 4549 (phymod_phy_autoneg_set(&phy->pm_phy, &an)); 4550 4551 return (SOC_E_NONE); 4552 } 4553 /* 4554 * Function: 4555 * phy_82864_an_get 4556 * Purpose: 4557 * Get the current auto-negotiation status (enabled/busy) 4558 * Parameters: 4559 * unit - BCM unit number. 4560 * port - Port number. 4561 * an - (OUT) if true, auto-negotiation is enabled. 4562 * an_done - (OUT) if true, auto-negotiation is complete. This 4563 * value is undefined if an == false. 4564 * Returns: 4565 * SOC_E_XXX 4566 */ 4567 4568 STATIC int 4569 phy_82864_an_get(int unit, soc_port_t port, int *an, int *an_done) 4570 { 4571 phy_ctrl_t* pc; 4572 soc_phymod_ctrl_t *pmc; 4573 phymod_phy_access_t *pm_phy; 4574 phymod_autoneg_control_t an_control; 4575 int idx, an_complete; 4576 4577 *an = 0; 4578 *an_done = 0; 4579 4580 pc = EXT_PHY_SW_STATE(unit, port); 4581 pmc = &pc->phymod_ctrl; 4582 4583 sal_memset(&an_control, 0x0, sizeof(an_control)); 4584 4585 idx = pmc->main_phy; 4586 pm_phy = &pmc->phy[idx]->pm_phy; 4587 4588 SOC_IF_ERROR_RETURN 4589 (phymod_phy_autoneg_get(pm_phy, &an_control, (uint32_t *) &an_complete)); 4590 4591 if (an_control.enable) { 4592 *an = 1; 4593 *an_done = an_complete; 4594 #ifdef PHY82864_DEBUG 4595 LOG_CLI((BSL_META_U(unit,"AN complete:%d\n "),*an_done)); 4596 #endif 4597 } else { 4598 *an = 0; 4599 *an_done = 0; 4600 } 4601 4602 return SOC_E_NONE; 4603 } 4604 /* 4605 * Function: 4606 * phy_82864_ability_advert_set 4607 * Purpose: 4608 * Set the current advertisement for auto-negotiation. 4609 * Parameters: 4610 * unit - BCM unit number. 4611 * port - Port number. 4612 * ability - Port mode mask indicating supported options/speeds. 4613 * Returns: 4614 * SOC_E_XXX 4615 * Notes: 4616 * The advertisement is set only for the ACTIVE medium. 4617 * No synchronization performed at this level. 4618 */ 4619 4620 STATIC int 4621 phy_82864_ability_advert_set(int unit, soc_port_t port, 4622 soc_port_ability_t *ability) 4623 { 4624 phy_ctrl_t *pc; 4625 soc_phymod_ctrl_t *pmc; 4626 soc_phymod_phy_t *phy; 4627 soc_port_if_t line_interface; 4628 int an = 0, an_done = 0; 4629 uint8_t an_enabled = 0; 4630 uint32_t an_tech_ability; 4631 uint32_t an_bam37_ability; 4632 uint32_t an_bam73_ability; 4633 _shr_port_mode_t speed_full_duplex; 4634 phymod_autoneg_ability_t phymod_autoneg_ability; 4635 4636 /* locate phy control */ 4637 pc = EXT_PHY_SW_STATE(unit, port); 4638 if (pc == NULL) { 4639 return SOC_E_INTERNAL; 4640 } 4641 4642 phymod_autoneg_ability_t_init(&phymod_autoneg_ability); 4643 4644 pmc = &pc->phymod_ctrl; 4645 4646 /* only set abilities on the first core */ 4647 phy = pmc->phy[pmc->main_phy]; 4648 if (phy == NULL) { 4649 return SOC_E_INTERNAL; 4650 } 4651 4652 an_tech_ability = 0; 4653 an_bam37_ability = 0; 4654 an_bam73_ability = 0; 4655 speed_full_duplex = ability->speed_full_duplex; 4656 line_interface = ability->interface; 4657 4658 /* if ability->interface is NULL, get the configured interface */ 4659 if (!line_interface) { 4660 SOC_IF_ERROR_RETURN(phy82864_interface_get(unit, port, &line_interface)); 4661 } 4662 /* When ability_advert_set called disable AN and set the ability */ 4663 SOC_IF_ERROR_RETURN(phy_82864_an_get(unit, port, &an, &an_done)); 4664 if (an) { 4665 SOC_IF_ERROR_RETURN(phy_82864_an_set(unit, port, FALSE)); 4666 an_enabled = 1; 4667 } 4668 4669 if(speed_full_duplex & SOC_PA_SPEED_100GB) { 4670 if (line_interface == SOC_PORT_IF_KR4) { 4671 PHYMOD_AN_CAP_100G_KR4_SET(an_tech_ability); 4672 } else { 4673 PHYMOD_AN_CAP_100G_CR4_SET(an_tech_ability); 4674 } 4675 } else if (speed_full_duplex & SOC_PA_SPEED_40GB) { 4676 if (line_interface == SOC_PORT_IF_KR4) { 4677 PHYMOD_AN_CAP_40G_KR4_SET(an_tech_ability); 4678 } else { 4679 PHYMOD_AN_CAP_40G_CR4_SET(an_tech_ability); 4680 } 4681 } else if (speed_full_duplex & SOC_PA_SPEED_10GB) { 4682 PHYMOD_AN_CAP_10G_KR_SET(an_tech_ability); 4683 } else { 4684 an_tech_ability = 0; 4685 } 4686 4687 phymod_autoneg_ability.an_cap = an_tech_ability; 4688 phymod_autoneg_ability.cl73bam_cap = an_bam73_ability; 4689 phymod_autoneg_ability.cl37bam_cap = an_bam37_ability; 4690 #ifdef PHY82864_DEBUG 4691 LOG_CLI((BSL_META_U(unit,"AN:abilitySet =%x tech ability:%x pause:%d\n"), speed_full_duplex, an_tech_ability,ability->pause)); 4692 #endif 4693 switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) { 4694 case SOC_PA_PAUSE_TX: 4695 PHYMOD_AN_CAP_ASYM_PAUSE_SET(&phymod_autoneg_ability); 4696 break; 4697 case SOC_PA_PAUSE_RX: 4698 /* an_adv |= MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE; */ 4699 PHYMOD_AN_CAP_ASYM_PAUSE_SET(&phymod_autoneg_ability); 4700 PHYMOD_AN_CAP_SYMM_PAUSE_SET(&phymod_autoneg_ability); 4701 break; 4702 case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX: 4703 PHYMOD_AN_CAP_SYMM_PAUSE_SET(&phymod_autoneg_ability); 4704 break; 4705 } 4706 4707 4708 phymod_autoneg_ability.an_master_lane = soc_property_port_get(unit, port, 4709 "phy_autoneg_master_lane", 4710 phymod_autoneg_ability.an_master_lane); 4711 phymod_autoneg_ability.sgmii_speed = 2; 4712 4713 SOC_IF_ERROR_RETURN 4714 (phymod_phy_autoneg_ability_set(&phy->pm_phy, &phymod_autoneg_ability)); 4715 4716 /* Enable the AN after ability set */ 4717 if (an_enabled) { 4718 SOC_IF_ERROR_RETURN(phy_82864_an_set(unit, port, TRUE)); 4719 } 4720 4721 return SOC_E_NONE; 4722 } 4723 4724 /* 4725 * Function: 4726 * phy_82864_ability_advert_get 4727 * Purpose: 4728 * Get the current advertisement for auto-negotiation. 4729 * Parameters: 4730 * unit - BCM unit number. 4731 * port - Port number. 4732 * ability - (OUT) Port mode mask indicating supported options/speeds. 4733 * Returns: 4734 * SOC_E_XXX 4735 * Notes: 4736 * The advertisement is retrieved for the ACTIVE medium. 4737 * No synchronization performed at this level. 4738 */ 4739 4740 STATIC int 4741 phy_82864_ability_advert_get(int unit, soc_port_t port, 4742 soc_port_ability_t *ability) 4743 { 4744 phy_ctrl_t *pc; 4745 soc_phymod_ctrl_t *pmc; 4746 soc_phymod_phy_t *phy; 4747 int reg73_ability; 4748 int reg_ability; 4749 _shr_port_mode_t speed_full_duplex; 4750 phymod_autoneg_ability_t phymod_autoneg_ability; 4751 4752 /* locate phy control */ 4753 pc = EXT_PHY_SW_STATE(unit, port); 4754 if (pc == NULL) { 4755 return SOC_E_INTERNAL; 4756 } 4757 4758 pmc = &pc->phymod_ctrl; 4759 4760 /* only get abilities from the first core */ 4761 phy = pmc->phy[0]; 4762 if (phy == NULL) { 4763 return SOC_E_INTERNAL; 4764 } 4765 4766 phymod_autoneg_ability_t_init(&phymod_autoneg_ability); 4767 4768 SOC_IF_ERROR_RETURN 4769 (phymod_phy_autoneg_ability_get(&phy->pm_phy, &phymod_autoneg_ability)); 4770 4771 4772 speed_full_duplex = 0; 4773 4774 /* retrieve CL73 abilities */ 4775 reg73_ability = phymod_autoneg_ability.an_cap; 4776 speed_full_duplex |= PHYMOD_AN_CAP_100G_CR4_GET(reg73_ability) ? SOC_PA_SPEED_100GB : 0; 4777 speed_full_duplex |= PHYMOD_AN_CAP_100G_KR4_GET(reg73_ability) ? SOC_PA_SPEED_100GB : 0; 4778 speed_full_duplex |= PHYMOD_AN_CAP_40G_CR4_GET(reg73_ability) ? SOC_PA_SPEED_40GB : 0; 4779 speed_full_duplex |= PHYMOD_AN_CAP_40G_KR4_GET(reg73_ability) ? SOC_PA_SPEED_40GB : 0; 4780 speed_full_duplex |= PHYMOD_AN_CAP_10G_KR_GET (reg73_ability) ? SOC_PA_SPEED_10GB : 0; 4781 4782 if (speed_full_duplex & SOC_PA_SPEED_100GB) { 4783 if (PHYMOD_AN_CAP_100G_CR4_GET(reg73_ability)) { 4784 ability->interface = SOC_PORT_IF_CR4; 4785 } else { 4786 ability->interface = SOC_PORT_IF_KR4; 4787 } 4788 } else if (speed_full_duplex & SOC_PA_SPEED_40GB) { 4789 if (PHYMOD_AN_CAP_40G_CR4_GET(reg73_ability)) { 4790 ability->interface = SOC_PORT_IF_CR4; 4791 } else { 4792 ability->interface = SOC_PORT_IF_KR4; 4793 } 4794 } else if (speed_full_duplex & SOC_PA_SPEED_10GB) { 4795 ability->interface = SOC_PORT_IF_KR; 4796 } else { 4797 ability->interface = 0; 4798 } 4799 4800 4801 /* retrieve "pause" abilities */ 4802 reg_ability = phymod_autoneg_ability.capabilities; 4803 4804 ability->pause = 0; 4805 if (reg_ability == PHYMOD_AN_CAP_ASYM_PAUSE) { 4806 ability->pause = SOC_PA_PAUSE_TX; 4807 } else if (reg_ability == (PHYMOD_AN_CAP_SYMM_PAUSE | PHYMOD_AN_CAP_ASYM_PAUSE)) { 4808 ability->pause = SOC_PA_PAUSE_RX; 4809 } else if (reg_ability == PHYMOD_AN_CAP_SYMM_PAUSE) { 4810 ability->pause = (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX); 4811 } 4812 4813 ability->speed_full_duplex = speed_full_duplex; 4814 4815 return SOC_E_NONE; 4816 } 4817 4818 /* 4819 * Function: 4820 * phy82864_lb_get 4821 * Purpose: 4822 * Get current PHY loopback mode 4823 * Parameters: 4824 * unit - BCM unit number. 4825 * port - Port number. 4826 * enable - address of location to store binary value for on/off (1/0) 4827 * Returns: 4828 * SOC_E_NONE 4829 */ 4830 STATIC int 4831 phy82864_lb_get(int unit, soc_port_t port, int *enable) 4832 { 4833 phy_ctrl_t* pc; 4834 soc_phymod_ctrl_t *pmc; 4835 uint32 out_en; 4836 4837 pc = EXT_PHY_SW_STATE(unit, port); 4838 pmc = &pc->phymod_ctrl; 4839 SOC_IF_ERROR_RETURN( 4840 phy_82864_loopback_internal_pmd_get(pmc, port, PHY82864_LINE_SIDE, &out_en)); 4841 *enable = (int) out_en; 4842 4843 return SOC_E_NONE; 4844 } 4845 4846 /* 4847 * phy_82864_per_lane_loopback_internal_pmd_set 4848 */ 4849 STATIC int 4850 phy_82864_per_lane_loopback_internal_pmd_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 value) 4851 { 4852 phymod_phy_access_t *pm_phy; 4853 uint32 lane_map; 4854 phymod_phy_access_t pm_phy_copy; 4855 soc_phymod_phy_t *p_phy; 4856 4857 /* locate the desired phy and lane */ 4858 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 4859 4860 /* Make a copy of the phy access and overwrite the desired lane */ 4861 pm_phy = &p_phy->pm_phy; 4862 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4863 pm_phy_copy.access.lane_mask = lane_map; 4864 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 4865 if(intf == PHY82864_SYS_SIDE) { 4866 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 4867 } 4868 4869 SOC_IF_ERROR_RETURN 4870 (phymod_phy_loopback_set(&pm_phy_copy, phymodLoopbackGlobalPMD, value)); 4871 4872 return(SOC_E_NONE); 4873 } 4874 4875 /* 4876 * phy_82864_loopback_internal_pmd_set 4877 */ 4878 STATIC int 4879 phy_82864_loopback_internal_pmd_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 4880 { 4881 phymod_phy_access_t *pm_phy; 4882 int idx; 4883 phymod_phy_access_t pm_phy_copy; 4884 4885 for (idx = 0; idx < pmc->num_phys; idx++) { 4886 if (pmc->phy[idx] == NULL) { 4887 return SOC_E_INTERNAL; 4888 } 4889 pm_phy = &pmc->phy[idx]->pm_phy; 4890 if (pm_phy == NULL) { 4891 return SOC_E_INTERNAL; 4892 } 4893 4894 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4895 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 4896 if(intf == PHY82864_SYS_SIDE) { 4897 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 4898 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 4899 } 4900 4901 SOC_IF_ERROR_RETURN 4902 (phymod_phy_loopback_set(&pm_phy_copy, phymodLoopbackGlobalPMD, value)); 4903 } 4904 4905 return(SOC_E_NONE); 4906 } 4907 4908 /* 4909 * phy_82864_per_lane_loopback_remote_set 4910 */ 4911 STATIC int 4912 phy_82864_per_lane_loopback_remote_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 value) 4913 { 4914 phymod_phy_access_t *pm_phy; 4915 uint32 lane_map; 4916 phymod_phy_access_t pm_phy_copy; 4917 soc_phymod_phy_t *p_phy; 4918 4919 /* locate the desired phy and lane */ 4920 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 4921 4922 /* Make a copy of the phy access and overwrite the desired lane */ 4923 pm_phy = &p_phy->pm_phy; 4924 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4925 pm_phy_copy.access.lane_mask = lane_map; 4926 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 4927 if(intf == PHY82864_SYS_SIDE) { 4928 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 4929 } 4930 4931 SOC_IF_ERROR_RETURN 4932 (phymod_phy_loopback_set(&pm_phy_copy, phymodLoopbackRemotePMD, value)); 4933 4934 return(SOC_E_NONE); 4935 } 4936 /* 4937 * phy_82864_loopback_remote_set 4938 */ 4939 STATIC int 4940 phy_82864_loopback_remote_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 4941 { 4942 phymod_phy_access_t *pm_phy; 4943 int idx; 4944 phymod_phy_access_t pm_phy_copy; 4945 4946 for (idx = 0; idx < pmc->num_phys; idx++) { 4947 if (pmc->phy[idx] == NULL) { 4948 return SOC_E_INTERNAL; 4949 } 4950 pm_phy = &pmc->phy[idx]->pm_phy; 4951 if (pm_phy == NULL) { 4952 return SOC_E_INTERNAL; 4953 } 4954 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 4955 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 4956 if(intf == PHY82864_SYS_SIDE) { 4957 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 4958 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 4959 } 4960 4961 SOC_IF_ERROR_RETURN 4962 (phymod_phy_loopback_set(&pm_phy_copy, phymodLoopbackRemotePMD, value)); 4963 } 4964 4965 return(SOC_E_NONE); 4966 } 4967 4968 /* 4969 * phy_82864_fec_enable_set 4970 */ 4971 STATIC int 4972 phy_82864_fec_enable_set(soc_phymod_ctrl_t *pmc, uint32 value) 4973 { 4974 phymod_phy_access_t *pm_phy; 4975 pm_phy = &pmc->phy[pmc->main_phy]->pm_phy; 4976 4977 SOC_IF_ERROR_RETURN( 4978 phymod_phy_fec_enable_set(pm_phy, value)); 4979 return(SOC_E_NONE); 4980 } 4981 4982 STATIC int 4983 phy_82864_sdk_poly_to_phymod_poly(uint32 sdk_poly, phymod_prbs_poly_t *phymod_poly){ 4984 switch(sdk_poly){ 4985 case SOC_PHY_PRBS_POLYNOMIAL_X7_X6_1: 4986 *phymod_poly = phymodPrbsPoly7; 4987 break; 4988 case SOC_PHY_PRBS_POLYNOMIAL_X15_X14_1: 4989 *phymod_poly = phymodPrbsPoly15; 4990 break; 4991 case SOC_PHY_PRBS_POLYNOMIAL_X23_X18_1: 4992 *phymod_poly = phymodPrbsPoly23; 4993 break; 4994 case SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1: 4995 *phymod_poly = phymodPrbsPoly31; 4996 break; 4997 case SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1: 4998 *phymod_poly = phymodPrbsPoly9; 4999 break; 5000 case SOC_PHY_PRBS_POLYNOMIAL_X11_X9_1: 5001 *phymod_poly = phymodPrbsPoly11; 5002 break; 5003 case SOC_PHY_PRBS_POLYNOMIAL_X58_X31_1: 5004 *phymod_poly = phymodPrbsPoly58; 5005 break; 5006 default: 5007 return SOC_E_INTERNAL; 5008 } 5009 5010 return SOC_E_NONE; 5011 } 5012 /* 5013 * phy_82864_per_lane_prbs_tx_poly_set 5014 */ 5015 STATIC int 5016 phy_82864_per_lane_prbs_tx_poly_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 value) 5017 { 5018 phymod_phy_access_t *pm_phy; 5019 phymod_prbs_t prbs; 5020 uint32_t flags = 0; 5021 uint32 lane_map; 5022 phymod_phy_access_t pm_phy_copy; 5023 soc_phymod_phy_t *p_phy; 5024 5025 /* locate the desired phy and lane */ 5026 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 5027 5028 /* Make a copy of the phy access and overwrite the desired lane */ 5029 pm_phy = &p_phy->pm_phy; 5030 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5031 pm_phy_copy.access.lane_mask = lane_map; 5032 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5033 if(intf == PHY82864_SYS_SIDE) { 5034 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5035 } 5036 5037 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 5038 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 5039 SOC_IF_ERROR_RETURN(phy_82864_sdk_poly_to_phymod_poly(value, &prbs.poly)); 5040 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(&pm_phy_copy, flags, &prbs)); 5041 5042 return(SOC_E_NONE); 5043 } 5044 /* 5045 * phy_82864_prbs_tx_poly_set 5046 */ 5047 STATIC int 5048 phy_82864_prbs_tx_poly_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 5049 { 5050 phymod_phy_access_t *pm_phy; 5051 phymod_prbs_t prbs; 5052 uint32_t flags = 0; 5053 int idx; 5054 phymod_phy_access_t pm_phy_copy; 5055 5056 for (idx = 0; idx < pmc->num_phys; idx++) { 5057 if (pmc->phy[idx] == NULL) { 5058 return SOC_E_INTERNAL; 5059 } 5060 pm_phy = &pmc->phy[idx]->pm_phy; 5061 if (pm_phy == NULL) { 5062 return SOC_E_INTERNAL; 5063 } 5064 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5065 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5066 if(intf == PHY82864_SYS_SIDE) { 5067 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5068 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 5069 } 5070 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 5071 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 5072 SOC_IF_ERROR_RETURN(phy_82864_sdk_poly_to_phymod_poly(value, &prbs.poly)); 5073 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(&pm_phy_copy, flags, &prbs)); 5074 } 5075 5076 return(SOC_E_NONE); 5077 } 5078 /* 5079 * phy_82864_per_lane_prbs_rx_poly_set 5080 */ 5081 STATIC int 5082 phy_82864_per_lane_prbs_rx_poly_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 value) 5083 { 5084 phymod_phy_access_t *pm_phy; 5085 phymod_prbs_t prbs; 5086 uint32_t flags = 0; 5087 uint32 lane_map; 5088 phymod_phy_access_t pm_phy_copy; 5089 soc_phymod_phy_t *p_phy; 5090 5091 /* locate the desired phy and lane */ 5092 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 5093 5094 /* Make a copy of the phy access and overwrite the desired lane */ 5095 pm_phy = &p_phy->pm_phy; 5096 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5097 pm_phy_copy.access.lane_mask = lane_map; 5098 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5099 if(intf == PHY82864_SYS_SIDE) { 5100 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5101 } 5102 5103 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 5104 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 5105 SOC_IF_ERROR_RETURN(phy_82864_sdk_poly_to_phymod_poly(value, &prbs.poly)); 5106 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(&pm_phy_copy, flags, &prbs)); 5107 5108 return(SOC_E_NONE); 5109 } 5110 5111 /* 5112 * phy_82864_prbs_rx_poly_set 5113 */ 5114 STATIC int 5115 phy_82864_prbs_rx_poly_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 5116 { 5117 phymod_phy_access_t *pm_phy; 5118 phymod_prbs_t prbs; 5119 uint32_t flags = 0; 5120 int idx; 5121 phymod_phy_access_t pm_phy_copy; 5122 5123 for (idx = 0; idx < pmc->num_phys; idx++) { 5124 if (pmc->phy[idx] == NULL) { 5125 return SOC_E_INTERNAL; 5126 } 5127 pm_phy = &pmc->phy[idx]->pm_phy; 5128 if (pm_phy == NULL) { 5129 return SOC_E_INTERNAL; 5130 } 5131 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5132 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5133 if(intf == PHY82864_SYS_SIDE) { 5134 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5135 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 5136 } 5137 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 5138 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 5139 SOC_IF_ERROR_RETURN(phy_82864_sdk_poly_to_phymod_poly(value, &prbs.poly)); 5140 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(&pm_phy_copy, flags, &prbs)); 5141 } 5142 5143 return(SOC_E_NONE); 5144 } 5145 5146 5147 /* 5148 * phy_82864_per_lane_prbs_tx_invert_data_set 5149 */ 5150 STATIC int 5151 phy_82864_per_lane_prbs_tx_invert_data_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 value) 5152 { 5153 phymod_phy_access_t *pm_phy; 5154 phymod_prbs_t prbs; 5155 uint32_t flags = 0; 5156 5157 uint32 lane_map; 5158 phymod_phy_access_t pm_phy_copy; 5159 soc_phymod_phy_t *p_phy; 5160 5161 /* locate the desired phy and lane */ 5162 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 5163 5164 /* Make a copy of the phy access and overwrite the desired lane */ 5165 pm_phy = &p_phy->pm_phy; 5166 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5167 pm_phy_copy.access.lane_mask = lane_map; 5168 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5169 if(intf == PHY82864_SYS_SIDE) { 5170 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5171 } 5172 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 5173 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 5174 prbs.invert = value; 5175 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(&pm_phy_copy, flags, &prbs)); 5176 5177 return(SOC_E_NONE); 5178 } 5179 5180 /* 5181 * phy_82864_prbs_tx_invert_data_set 5182 */ 5183 STATIC int 5184 phy_82864_prbs_tx_invert_data_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 5185 { 5186 phymod_phy_access_t *pm_phy; 5187 phymod_prbs_t prbs; 5188 uint32_t flags = 0; 5189 int idx; 5190 phymod_phy_access_t pm_phy_copy; 5191 5192 for (idx = 0; idx < pmc->num_phys; idx++) { 5193 if (pmc->phy[idx] == NULL) { 5194 return SOC_E_INTERNAL; 5195 } 5196 pm_phy = &pmc->phy[idx]->pm_phy; 5197 if (pm_phy == NULL) { 5198 return SOC_E_INTERNAL; 5199 } 5200 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5201 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5202 if(intf == PHY82864_SYS_SIDE) { 5203 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5204 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 5205 } 5206 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 5207 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 5208 prbs.invert = value; 5209 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(&pm_phy_copy, flags, &prbs)); 5210 } 5211 5212 return(SOC_E_NONE); 5213 } 5214 5215 /* 5216 * phy_82864_per_lane_prbs_rx_invert_data_set 5217 */ 5218 STATIC int 5219 phy_82864_per_lane_prbs_rx_invert_data_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 value) 5220 { 5221 phymod_phy_access_t *pm_phy; 5222 phymod_prbs_t prbs; 5223 uint32_t flags = 0; 5224 uint32 lane_map; 5225 phymod_phy_access_t pm_phy_copy; 5226 soc_phymod_phy_t *p_phy; 5227 5228 /* locate the desired phy and lane */ 5229 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 5230 5231 /* Make a copy of the phy access and overwrite the desired lane */ 5232 pm_phy = &p_phy->pm_phy; 5233 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5234 pm_phy_copy.access.lane_mask = lane_map; 5235 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5236 if(intf == PHY82864_SYS_SIDE) { 5237 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5238 } 5239 5240 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 5241 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 5242 prbs.invert = value; 5243 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(&pm_phy_copy, flags, &prbs)); 5244 5245 return(SOC_E_NONE); 5246 } 5247 /* 5248 * phy_82864_prbs_rx_invert_data_set 5249 */ 5250 STATIC int 5251 phy_82864_prbs_rx_invert_data_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 5252 { 5253 phymod_phy_access_t *pm_phy; 5254 phymod_prbs_t prbs; 5255 uint32_t flags = 0; 5256 int idx; 5257 phymod_phy_access_t pm_phy_copy; 5258 5259 for (idx = 0; idx < pmc->num_phys; idx++) { 5260 if (pmc->phy[idx] == NULL) { 5261 return SOC_E_INTERNAL; 5262 } 5263 pm_phy = &pmc->phy[idx]->pm_phy; 5264 if (pm_phy == NULL) { 5265 return SOC_E_INTERNAL; 5266 } 5267 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5268 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5269 if(intf == PHY82864_SYS_SIDE) { 5270 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5271 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 5272 } 5273 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 5274 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(&pm_phy_copy, flags, &prbs)); 5275 prbs.invert = value; 5276 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(&pm_phy_copy, flags, &prbs)); 5277 } 5278 5279 return(SOC_E_NONE); 5280 } 5281 5282 /* 5283 * phy_82864_per_lane_prbs_tx_enable_set 5284 */ 5285 STATIC int 5286 phy_82864_per_lane_prbs_tx_enable_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 value) 5287 { 5288 phymod_phy_access_t *pm_phy; 5289 uint32_t flags = 0; 5290 uint32 lane_map; 5291 phymod_phy_access_t pm_phy_copy; 5292 soc_phymod_phy_t *p_phy; 5293 5294 /* locate the desired phy and lane */ 5295 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 5296 5297 /* Make a copy of the phy access and overwrite the desired lane */ 5298 pm_phy = &p_phy->pm_phy; 5299 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5300 pm_phy_copy.access.lane_mask = lane_map; 5301 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5302 if(intf == PHY82864_SYS_SIDE) { 5303 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5304 } 5305 5306 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 5307 SOC_IF_ERROR_RETURN(phymod_phy_prbs_enable_set(&pm_phy_copy, flags, value)); 5308 5309 return(SOC_E_NONE); 5310 } 5311 5312 /* 5313 * phy_82864_prbs_tx_enable_set 5314 */ 5315 STATIC int 5316 phy_82864_prbs_tx_enable_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 5317 { 5318 int idx; 5319 uint32_t flags = 0; 5320 phymod_phy_access_t *pm_phy; 5321 phymod_phy_access_t pm_phy_copy; 5322 5323 for (idx = 0; idx < pmc->num_phys; idx++) { 5324 if (pmc->phy[idx] == NULL) { 5325 return SOC_E_INTERNAL; 5326 } 5327 pm_phy = &pmc->phy[idx]->pm_phy; 5328 if (pm_phy == NULL) { 5329 return SOC_E_INTERNAL; 5330 } 5331 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5332 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5333 if(intf == PHY82864_SYS_SIDE) { 5334 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5335 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 5336 } 5337 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 5338 SOC_IF_ERROR_RETURN(phymod_phy_prbs_enable_set(&pm_phy_copy, flags, value)); 5339 } 5340 5341 return(SOC_E_NONE); 5342 } 5343 5344 /* 5345 * phy_82864_per_lane_prbs_rx_enable_set 5346 */ 5347 STATIC int 5348 phy_82864_per_lane_prbs_rx_enable_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 value) 5349 { 5350 phymod_phy_access_t *pm_phy; 5351 uint32_t flags = 0; 5352 5353 uint32 lane_map; 5354 phymod_phy_access_t pm_phy_copy; 5355 soc_phymod_phy_t *p_phy; 5356 5357 /* locate the desired phy and lane */ 5358 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 5359 5360 /* Make a copy of the phy access and overwrite the desired lane */ 5361 pm_phy = &p_phy->pm_phy; 5362 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5363 pm_phy_copy.access.lane_mask = lane_map; 5364 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5365 if(intf == PHY82864_SYS_SIDE) { 5366 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5367 } 5368 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 5369 SOC_IF_ERROR_RETURN(phymod_phy_prbs_enable_set(&pm_phy_copy, flags, value)); 5370 5371 return(SOC_E_NONE); 5372 } 5373 /* 5374 * phy_82864_prbs_rx_enable_set 5375 */ 5376 STATIC int 5377 phy_82864_prbs_rx_enable_set(soc_phymod_ctrl_t *pmc, soc_port_t port, uint32 intf, uint32 value) 5378 { 5379 phymod_phy_access_t *pm_phy; 5380 uint32_t flags = 0; 5381 int idx; 5382 phymod_phy_access_t pm_phy_copy; 5383 5384 for (idx = 0; idx < pmc->num_phys; idx++) { 5385 if (pmc->phy[idx] == NULL) { 5386 return SOC_E_INTERNAL; 5387 } 5388 pm_phy = &pmc->phy[idx]->pm_phy; 5389 if (pm_phy == NULL) { 5390 return SOC_E_INTERNAL; 5391 } 5392 5393 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5394 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5395 if(intf == PHY82864_SYS_SIDE) { 5396 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5397 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 5398 } 5399 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 5400 SOC_IF_ERROR_RETURN(phymod_phy_prbs_enable_set(&pm_phy_copy, flags, value)); 5401 } 5402 5403 return(SOC_E_NONE); 5404 } 5405 5406 5407 /* 5408 * given a pc (phymod_ctrl_t) and logical lane number, 5409 * find the correct soc_phymod_phy_t object and lane 5410 */ 5411 STATIC int 5412 _phy_82864_find_soc_phy_lane(soc_phymod_ctrl_t *pmc, soc_port_t port, uint32_t lane, 5413 soc_phymod_phy_t **p_phy, uint32 *lane_map) 5414 { 5415 phy82864_config_t *pCfg; 5416 phy_ctrl_t *pc; 5417 uint32_t intf; 5418 int idx, found = 0; 5419 5420 /* locate phy control, phymod control, and the configuration data */ 5421 pc = EXT_PHY_SW_STATE(pmc->unit, port); 5422 if (pc == NULL) { 5423 return SOC_E_INTERNAL; 5424 } 5425 5426 pCfg = (phy82864_config_t *) pc->driver_data; 5427 intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY82864_SYS_SIDE : PHY82864_LINE_SIDE; 5428 5429 *lane_map = 0; 5430 5431 /* Traverse lanes belonging to this port */ 5432 for (idx = 0; idx < pmc->num_phys; idx++) { 5433 if(intf == PHY82864_SYS_SIDE) { 5434 switch (pc->speed_max) { 5435 case PHY82864_SPD_100G: 5436 case PHY82864_SPD_106G: 5437 if (lane > 3) { 5438 return SOC_E_CONFIG; 5439 } 5440 *lane_map = 0x1 << lane; 5441 found = 1; 5442 break; 5443 case PHY82864_SPD_40G: 5444 case PHY82864_SPD_42G: 5445 case PHY82864_SPD_50G: 5446 if ((pCfg->device_cfg_aux_modes->pass_thru_dual_lane)) { 5447 if (lane > 1) { 5448 return SOC_E_CONFIG; 5449 } 5450 if (pc->lane_num > 1) { 5451 *lane_map = 0x4 << lane; 5452 found = 1; 5453 } else { 5454 *lane_map = 0x1 << lane; 5455 found = 1; 5456 } 5457 } else if ((pCfg->device_cfg_aux_modes->pass_thru)) { 5458 if (lane > 3) { 5459 return SOC_E_CONFIG; 5460 } 5461 *lane_map = 0x1 << lane; 5462 found = 1; 5463 } else { 5464 if (lane > 1) { 5465 return SOC_E_CONFIG; 5466 } 5467 if (pc->lane_num > 1) { 5468 *lane_map = 0x4 << lane; 5469 found = 1; 5470 } else { 5471 *lane_map = 0x1 << lane; 5472 found = 1; 5473 } 5474 } 5475 break; 5476 case PHY82864_SPD_1G: 5477 case PHY82864_SPD_10G: 5478 case PHY82864_SPD_11G: 5479 case PHY82864_SPD_25G: 5480 if (lane > 0) { 5481 return SOC_E_CONFIG; 5482 } 5483 *lane_map = 0x1 << pc->lane_num; 5484 found = 1; 5485 break; 5486 default: 5487 return SOC_E_CONFIG; 5488 5489 } 5490 } else { 5491 switch (pc->speed_max) { 5492 case PHY82864_SPD_100G: 5493 case PHY82864_SPD_106G: 5494 if (lane > 7) { 5495 return SOC_E_CONFIG; 5496 } 5497 *lane_map = 0x1 << lane; 5498 found = 1; 5499 break; 5500 case PHY82864_SPD_40G: 5501 case PHY82864_SPD_42G: 5502 case PHY82864_SPD_50G: 5503 if ((pCfg->device_cfg_aux_modes->pass_thru_dual_lane)) { 5504 if (lane > 1) { 5505 return SOC_E_CONFIG; 5506 } 5507 if (pc->lane_num > 1) { 5508 *lane_map = 0x4 << lane; 5509 found = 1; 5510 } else { 5511 *lane_map = 0x1 << lane; 5512 found = 1; 5513 } 5514 } else if ((pCfg->device_cfg_aux_modes->pass_thru)) { 5515 if (lane > 3) { 5516 return SOC_E_CONFIG; 5517 } 5518 *lane_map = 0x1 << lane; 5519 found = 1; 5520 } else { 5521 if (lane > 3) { 5522 return SOC_E_CONFIG; 5523 } 5524 if (pc->lane_num > 1) { 5525 *lane_map = 0x10 << lane; 5526 found = 1; 5527 } else { 5528 *lane_map = 0x1 << lane; 5529 found = 1; 5530 } 5531 } 5532 break; 5533 case PHY82864_SPD_1G: 5534 case PHY82864_SPD_10G: 5535 case PHY82864_SPD_11G: 5536 case PHY82864_SPD_25G: 5537 if (lane > 0) { 5538 return SOC_E_CONFIG; 5539 } 5540 *lane_map = 0x1 << pc->lane_num; 5541 found = 1; 5542 break; 5543 default: 5544 return SOC_E_CONFIG; 5545 } 5546 if ((pCfg->device_cfg_aux_modes->alternate)) { 5547 if ((*lane_map) & 0xF) { 5548 *lane_map <<= 4; 5549 } 5550 } 5551 } 5552 /* coverity[dead_error_condition] */ 5553 if (found) { 5554 *p_phy = pmc->phy[idx]; 5555 break; 5556 } 5557 } 5558 5559 if (!found) { 5560 LOG_CLI((BSL_META_U(pmc->unit,"\nInvalid lane \n"))); 5561 /* No such lane */ 5562 return SOC_E_PARAM; 5563 } 5564 5565 return (SOC_E_NONE); 5566 } 5567 5568 /* 5569 * phy_82864_per_lane_preemphasis_set 5570 */ 5571 STATIC int 5572 phy_82864_per_lane_preemphasis_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 value) 5573 { 5574 soc_phymod_phy_t *p_phy; 5575 uint32 lane_map; 5576 phymod_phy_access_t pm_phy_copy, *pm_phy; 5577 phymod_tx_t phymod_tx; 5578 5579 /* locate the desired phy and lane */ 5580 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 5581 5582 /* Make a copy of the phy access and overwrite the desired lane */ 5583 pm_phy = &p_phy->pm_phy; 5584 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5585 pm_phy_copy.access.lane_mask = lane_map; 5586 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5587 if(intf == PHY82864_SYS_SIDE) { 5588 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5589 } 5590 5591 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 5592 /* 0 to 7 = pre 5593 * 8 to 15 = main 5594 * 16 to 24 = post*/ 5595 phymod_tx.pre = (value & 0xff); 5596 phymod_tx.main = (value & 0xff00) >> 8; 5597 phymod_tx.post = (value & 0xff0000) >> 16; 5598 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 5599 5600 return(SOC_E_NONE); 5601 } 5602 5603 /* 5604 * phy_82864_preemphasis_set 5605 */ 5606 STATIC int 5607 phy_82864_preemphasis_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 5608 { 5609 phymod_phy_access_t *pm_phy; 5610 phymod_tx_t phymod_tx; 5611 int idx; 5612 phymod_phy_access_t pm_phy_copy; 5613 5614 /* loop through all cores */ 5615 for (idx = 0; idx < pmc->num_phys; idx++) { 5616 pm_phy = &pmc->phy[idx]->pm_phy; 5617 5618 if (pm_phy == NULL) { 5619 return SOC_E_INTERNAL; 5620 } 5621 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5622 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5623 if(intf == PHY82864_SYS_SIDE) { 5624 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5625 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 5626 } 5627 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 5628 /* 0 to 7 = pre 5629 * 8 to 15 = main 5630 * 16 to 24 = post*/ 5631 phymod_tx.pre = (value & 0xff); 5632 phymod_tx.main = (value & 0xff00) >> 8; 5633 phymod_tx.post = (value & 0xff0000) >> 16; 5634 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 5635 5636 } 5637 5638 return(SOC_E_NONE); 5639 } 5640 5641 /* 5642 * phy_82864_tx_fir_pre_set 5643 */ 5644 STATIC int 5645 phy_82864_tx_fir_pre_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 5646 { 5647 phymod_phy_access_t *pm_phy; 5648 phymod_tx_t phymod_tx; 5649 int idx; 5650 phymod_phy_access_t pm_phy_copy; 5651 5652 /* loop through all cores */ 5653 for (idx = 0; idx < pmc->num_phys; idx++) { 5654 pm_phy = &pmc->phy[idx]->pm_phy; 5655 5656 if (pm_phy == NULL) { 5657 return SOC_E_INTERNAL; 5658 } 5659 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5660 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5661 if(intf == PHY82864_SYS_SIDE) { 5662 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5663 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 5664 } 5665 5666 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 5667 phymod_tx.pre = value; 5668 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 5669 } 5670 5671 return(SOC_E_NONE); 5672 } 5673 5674 /* 5675 * phy_82864_tx_fir_main_set 5676 */ 5677 STATIC int 5678 phy_82864_tx_fir_main_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 5679 { 5680 phymod_phy_access_t *pm_phy; 5681 phymod_tx_t phymod_tx; 5682 int idx; 5683 phymod_phy_access_t pm_phy_copy; 5684 /* loop through all cores */ 5685 for (idx = 0; idx < pmc->num_phys; idx++) { 5686 pm_phy = &pmc->phy[idx]->pm_phy; 5687 5688 if (pm_phy == NULL) { 5689 return SOC_E_INTERNAL; 5690 } 5691 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5692 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5693 if(intf == PHY82864_SYS_SIDE) { 5694 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5695 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 5696 } 5697 5698 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 5699 phymod_tx.main = value; 5700 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 5701 } 5702 5703 return(SOC_E_NONE); 5704 } 5705 5706 /* 5707 * phy_82864_tx_fir_post_set 5708 */ 5709 STATIC int 5710 phy_82864_tx_fir_post_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 5711 { 5712 phymod_phy_access_t *pm_phy; 5713 phymod_tx_t phymod_tx; 5714 int idx; 5715 phymod_phy_access_t pm_phy_copy; 5716 5717 /* loop through all cores */ 5718 for (idx = 0; idx < pmc->num_phys; idx++) { 5719 pm_phy = &pmc->phy[idx]->pm_phy; 5720 5721 if (pm_phy == NULL) { 5722 return SOC_E_INTERNAL; 5723 } 5724 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5725 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5726 if(intf == PHY82864_SYS_SIDE) { 5727 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5728 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 5729 } 5730 5731 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 5732 phymod_tx.post = value; 5733 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 5734 } 5735 5736 return(SOC_E_NONE); 5737 } 5738 5739 /* 5740 * phy_82864_tx_fir_post2_set 5741 */ 5742 STATIC int 5743 phy_82864_tx_fir_post2_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 5744 { 5745 phymod_phy_access_t *pm_phy; 5746 phymod_tx_t phymod_tx; 5747 int idx; 5748 phymod_phy_access_t pm_phy_copy; 5749 5750 /* loop through all cores */ 5751 for (idx = 0; idx < pmc->num_phys; idx++) { 5752 pm_phy = &pmc->phy[idx]->pm_phy; 5753 5754 if (pm_phy == NULL) { 5755 return SOC_E_INTERNAL; 5756 } 5757 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5758 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5759 if(intf == PHY82864_SYS_SIDE) { 5760 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5761 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 5762 } 5763 5764 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 5765 phymod_tx.post2 = value; 5766 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 5767 } 5768 5769 return(SOC_E_NONE); 5770 } 5771 5772 /* 5773 * phy_82864_tx_fir_post3_set 5774 */ 5775 STATIC int 5776 phy_82864_tx_fir_post3_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 5777 { 5778 phymod_phy_access_t *pm_phy; 5779 phymod_tx_t phymod_tx; 5780 int idx; 5781 phymod_phy_access_t pm_phy_copy; 5782 5783 /* loop through all cores */ 5784 for (idx = 0; idx < pmc->num_phys; idx++) { 5785 pm_phy = &pmc->phy[idx]->pm_phy; 5786 5787 if (pm_phy == NULL) { 5788 return SOC_E_INTERNAL; 5789 } 5790 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5791 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5792 if(intf == PHY82864_SYS_SIDE) { 5793 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5794 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 5795 } 5796 5797 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 5798 phymod_tx.post3 = value; 5799 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 5800 } 5801 5802 return(SOC_E_NONE); 5803 } 5804 5805 5806 /* 5807 * phy_82864_per_lane_driver_current_set 5808 */ 5809 STATIC int 5810 phy_82864_per_lane_driver_current_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 value) 5811 { 5812 soc_phymod_phy_t *p_phy; 5813 uint32 lane_map; 5814 phymod_phy_access_t pm_phy_copy, *pm_phy; 5815 phymod_tx_t phymod_tx; 5816 5817 /* locate the desired phy and lane */ 5818 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 5819 5820 /* Make a copy of the phy access and overwrite the desired lane */ 5821 pm_phy = &p_phy->pm_phy; 5822 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5823 pm_phy_copy.access.lane_mask = lane_map; 5824 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5825 if(intf == PHY82864_SYS_SIDE) { 5826 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5827 } 5828 5829 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 5830 phymod_tx.amp = value; 5831 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 5832 5833 return(SOC_E_NONE); 5834 } 5835 5836 /* 5837 * phy_82864_driver_current_set 5838 */ 5839 STATIC int 5840 phy_82864_driver_current_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 5841 { 5842 phymod_phy_access_t *pm_phy; 5843 phymod_tx_t phymod_tx; 5844 int idx; 5845 phymod_phy_access_t pm_phy_copy; 5846 5847 /* loop through all cores */ 5848 for (idx = 0; idx < pmc->num_phys; idx++) { 5849 pm_phy = &pmc->phy[idx]->pm_phy; 5850 5851 if (pm_phy == NULL) { 5852 return SOC_E_INTERNAL; 5853 } 5854 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5855 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5856 if(intf == PHY82864_SYS_SIDE) { 5857 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5858 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 5859 } 5860 5861 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 5862 phymod_tx.amp = value; 5863 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 5864 } 5865 5866 return(SOC_E_NONE); 5867 } 5868 5869 /* 5870 * phy_82864_per_lane_rx_dfe_tap_control_set 5871 */ 5872 STATIC int 5873 phy_82864_per_lane_rx_dfe_tap_control_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, int tap, int enable, uint32 value) 5874 { 5875 soc_phymod_phy_t *p_phy; 5876 uint32 lane_map; 5877 phymod_phy_access_t pm_phy_copy, *pm_phy; 5878 phymod_rx_t phymod_rx; 5879 5880 /* locate the desired phy and lane */ 5881 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 5882 5883 /* Make a copy of the phy access and overwrite the desired lane */ 5884 pm_phy = &p_phy->pm_phy; 5885 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5886 pm_phy_copy.access.lane_mask = lane_map; 5887 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5888 if(intf == PHY82864_SYS_SIDE) { 5889 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5890 } 5891 5892 if (tap < 0 || tap >= COUNTOF(phymod_rx.dfe)) { 5893 /* this can only happen with a coding error */ 5894 return SOC_E_INTERNAL; 5895 } 5896 sal_memset(&phymod_rx, 0, sizeof(phymod_rx)); 5897 phymod_rx.dfe[tap].enable = enable; 5898 phymod_rx.dfe[tap].value = value; 5899 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(&pm_phy_copy, &phymod_rx)); 5900 if (!enable) { 5901 SOC_IF_ERROR_RETURN(phymod_phy_rx_adaptation_resume(&pm_phy_copy)); 5902 } 5903 5904 return(SOC_E_NONE); 5905 } 5906 /* 5907 * phy_82864_per_lane_tx_lane_squelch 5908 */ 5909 STATIC int 5910 phy_82864_per_lane_tx_lane_squelch(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 value) 5911 { 5912 phymod_phy_access_t *pm_phy; 5913 phymod_phy_tx_lane_control_t tx_control; 5914 int idx; 5915 phymod_phy_access_t pm_phy_copy; 5916 soc_phymod_phy_t *p_phy; 5917 uint32 lane_map; 5918 5919 /* locate the desired phy and lane */ 5920 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 5921 5922 /* loop through all cores */ 5923 for (idx = 0; idx < pmc->num_phys; idx++) { 5924 pm_phy = &pmc->phy[idx]->pm_phy; 5925 5926 if (pm_phy == NULL) { 5927 return SOC_E_INTERNAL; 5928 } 5929 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5930 pm_phy_copy.access.lane_mask = lane_map; 5931 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5932 if(intf == PHY82864_SYS_SIDE) { 5933 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5934 } 5935 5936 if (value == 1) { 5937 tx_control = phymodTxSquelchOn; 5938 } else { 5939 tx_control = phymodTxSquelchOff; 5940 } 5941 SOC_IF_ERROR_RETURN 5942 (phymod_phy_tx_lane_control_set(&pm_phy_copy, tx_control)); 5943 5944 } 5945 5946 return(SOC_E_NONE); 5947 } 5948 5949 STATIC int 5950 phy_82864_per_lane_tx_lane_squelch_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 5951 { 5952 phymod_phy_access_t *pm_phy; 5953 phymod_phy_tx_lane_control_t tx_control; 5954 phymod_phy_access_t pm_phy_copy; 5955 soc_phymod_phy_t *p_phy; 5956 uint32 lane_map; 5957 5958 /* locate the desired phy and lane */ 5959 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 5960 5961 /* Make a copy of the phy access and overwrite the desired lane */ 5962 pm_phy = &p_phy->pm_phy; 5963 5964 if (pm_phy == NULL) { 5965 return SOC_E_INTERNAL; 5966 } 5967 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 5968 pm_phy_copy.access.lane_mask = lane_map; 5969 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 5970 if(intf == PHY82864_SYS_SIDE) { 5971 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 5972 } 5973 5974 tx_control = phymodTxSquelchOn; 5975 SOC_IF_ERROR_RETURN 5976 (phymod_phy_tx_lane_control_get(&pm_phy_copy, &tx_control)); 5977 if (tx_control == phymodTxSquelchOn) { 5978 *value = 1; 5979 } else { 5980 *value = 0; 5981 } 5982 5983 return(SOC_E_NONE); 5984 } 5985 5986 /* 5987 * phy_82864_tx_lane_squelch 5988 */ 5989 STATIC int 5990 phy_82864_tx_lane_squelch(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 5991 { 5992 phymod_phy_access_t *pm_phy; 5993 phymod_phy_tx_lane_control_t tx_control; 5994 int idx; 5995 phymod_phy_access_t pm_phy_copy; 5996 5997 /* loop through all cores */ 5998 for (idx = 0; idx < pmc->num_phys; idx++) { 5999 pm_phy = &pmc->phy[idx]->pm_phy; 6000 6001 if (pm_phy == NULL) { 6002 return SOC_E_INTERNAL; 6003 } 6004 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6005 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6006 if(intf == PHY82864_SYS_SIDE) { 6007 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6008 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 6009 } 6010 6011 if (value == 1) { 6012 tx_control = phymodTxSquelchOn; 6013 } else { 6014 tx_control = phymodTxSquelchOff; 6015 } 6016 SOC_IF_ERROR_RETURN 6017 (phymod_phy_tx_lane_control_set(&pm_phy_copy, tx_control)); 6018 6019 } 6020 6021 return(SOC_E_NONE); 6022 } 6023 6024 /* 6025 * phy_82864_tx_lane_squelch_get 6026 */ 6027 STATIC int 6028 phy_82864_tx_lane_squelch_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 6029 { 6030 phymod_phy_access_t *pm_phy; 6031 phymod_phy_tx_lane_control_t tx_control; 6032 int idx; 6033 phymod_phy_access_t pm_phy_copy; 6034 6035 /* loop through all cores */ 6036 for (idx = 0; idx < pmc->num_phys; idx++) { 6037 pm_phy = &pmc->phy[idx]->pm_phy; 6038 6039 if (pm_phy == NULL) { 6040 return SOC_E_INTERNAL; 6041 } 6042 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6043 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6044 if(intf == PHY82864_SYS_SIDE) { 6045 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6046 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 6047 } 6048 tx_control = phymodTxSquelchOn; 6049 SOC_IF_ERROR_RETURN 6050 (phymod_phy_tx_lane_control_get(&pm_phy_copy, &tx_control)); 6051 if (tx_control == phymodTxSquelchOn) { 6052 *value = 1; 6053 } else { 6054 *value = 0; 6055 } 6056 } 6057 6058 return(SOC_E_NONE); 6059 } 6060 6061 /* 6062 * phy_82864_per_lane_rx_peak_filter_set 6063 */ 6064 STATIC int 6065 phy_82864_per_lane_rx_peak_filter_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, int enable, uint32 value) 6066 { 6067 soc_phymod_phy_t *p_phy; 6068 uint32 lane_map; 6069 phymod_phy_access_t pm_phy_copy, *pm_phy; 6070 phymod_rx_t phymod_rx; 6071 6072 /* locate the desired phy and lane */ 6073 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 6074 6075 /* Make a copy of the phy access and overwrite the desired lane */ 6076 pm_phy = &p_phy->pm_phy; 6077 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6078 pm_phy_copy.access.lane_mask = lane_map; 6079 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6080 if(intf == PHY82864_SYS_SIDE) { 6081 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6082 } 6083 sal_memset(&phymod_rx, 0, sizeof(phymod_rx)); 6084 phymod_rx.peaking_filter.enable = TRUE; 6085 phymod_rx.peaking_filter.value = value; 6086 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(&pm_phy_copy, &phymod_rx)); 6087 6088 return(SOC_E_NONE); 6089 } 6090 6091 /* 6092 * phy_82864_rx_peak_filter_set 6093 */ 6094 STATIC int 6095 phy_82864_rx_peak_filter_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 6096 { 6097 phymod_phy_access_t *pm_phy; 6098 phymod_rx_t phymod_rx; 6099 int idx; 6100 phymod_phy_access_t pm_phy_copy; 6101 6102 /* loop through all cores */ 6103 for (idx = 0; idx < pmc->num_phys; idx++) { 6104 pm_phy = &pmc->phy[idx]->pm_phy; 6105 6106 if (pm_phy == NULL) { 6107 return SOC_E_INTERNAL; 6108 } 6109 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6110 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6111 if(intf == PHY82864_SYS_SIDE) { 6112 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6113 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 6114 } 6115 6116 sal_memset(&phymod_rx, 0, sizeof(phymod_rx)); 6117 phymod_rx.peaking_filter.enable = TRUE; 6118 phymod_rx.peaking_filter.value = value; 6119 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(&pm_phy_copy, &phymod_rx)); 6120 } 6121 6122 return(SOC_E_NONE); 6123 } 6124 6125 /* 6126 * phy_82864_per_lane_rx_vga_set 6127 */ 6128 STATIC int 6129 phy_82864_per_lane_rx_vga_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, int enable, uint32 value) 6130 { 6131 soc_phymod_phy_t *p_phy; 6132 uint32 lane_map; 6133 phymod_phy_access_t pm_phy_copy, *pm_phy; 6134 phymod_rx_t phymod_rx; 6135 6136 /* locate the desired phy and lane */ 6137 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 6138 6139 /* Make a copy of the phy access and overwrite the desired lane */ 6140 pm_phy = &p_phy->pm_phy; 6141 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6142 pm_phy_copy.access.lane_mask = lane_map; 6143 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6144 if(intf == PHY82864_SYS_SIDE) { 6145 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6146 } 6147 6148 sal_memset(&phymod_rx, 0, sizeof(phymod_rx)); 6149 phymod_rx.vga.enable = TRUE; 6150 phymod_rx.vga.value = value; 6151 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(&pm_phy_copy, &phymod_rx)); 6152 if (!enable) { 6153 SOC_IF_ERROR_RETURN(phymod_phy_rx_adaptation_resume(&pm_phy_copy)); 6154 } 6155 6156 return(SOC_E_NONE); 6157 } 6158 6159 /* 6160 * phy_82864_rx_vga_set 6161 */ 6162 STATIC int 6163 phy_82864_rx_vga_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int enable, uint32 value) 6164 { 6165 phymod_phy_access_t *pm_phy; 6166 phymod_rx_t phymod_rx; 6167 int idx; 6168 phymod_phy_access_t pm_phy_copy; 6169 6170 /* loop through all cores */ 6171 for (idx = 0; idx < pmc->num_phys; idx++) { 6172 pm_phy = &pmc->phy[idx]->pm_phy; 6173 6174 if (pm_phy == NULL) { 6175 return SOC_E_INTERNAL; 6176 } 6177 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6178 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6179 if(intf == PHY82864_SYS_SIDE) { 6180 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6181 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 6182 } 6183 6184 sal_memset(&phymod_rx, 0, sizeof(phymod_rx)); 6185 phymod_rx.vga.enable = TRUE; 6186 phymod_rx.vga.value = value; 6187 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(&pm_phy_copy, &phymod_rx)); 6188 if (!enable) { 6189 SOC_IF_ERROR_RETURN(phymod_phy_rx_adaptation_resume(&pm_phy_copy)); 6190 } 6191 } 6192 6193 return(SOC_E_NONE); 6194 } 6195 6196 STATIC int 6197 phy_82864_rx_tap_release(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int tap) 6198 { 6199 phymod_phy_access_t *pm_phy; 6200 phymod_rx_t phymod_rx; 6201 int idx; 6202 phymod_phy_access_t pm_phy_copy; 6203 6204 /* bounds check "tap" */ 6205 if (tap < 0 || tap >= COUNTOF(phymod_rx.dfe)) { 6206 return SOC_E_INTERNAL; 6207 } 6208 6209 /* loop through all cores */ 6210 for (idx = 0; idx < pmc->num_phys; idx++) { 6211 pm_phy = &pmc->phy[idx]->pm_phy; 6212 6213 if (pm_phy == NULL) { 6214 return SOC_E_INTERNAL; 6215 } 6216 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6217 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6218 if(intf == PHY82864_SYS_SIDE) { 6219 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6220 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 6221 } 6222 SOC_IF_ERROR_RETURN(phymod_phy_rx_adaptation_resume(&pm_phy_copy)); 6223 } 6224 6225 return(SOC_E_NONE); 6226 } 6227 6228 /* 6229 * phy_82864_rx_tap_set 6230 */ 6231 STATIC int 6232 phy_82864_rx_tap_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int tap, uint32 value) 6233 { 6234 phymod_phy_access_t *pm_phy; 6235 phymod_rx_t phymod_rx; 6236 int idx; 6237 phymod_phy_access_t pm_phy_copy; 6238 6239 /* bounds check "tap" */ 6240 if (tap < 0 || tap >= COUNTOF(phymod_rx.dfe)) { 6241 return SOC_E_INTERNAL; 6242 } 6243 6244 /* loop through all cores */ 6245 for (idx = 0; idx < pmc->num_phys; idx++) { 6246 pm_phy = &pmc->phy[idx]->pm_phy; 6247 6248 if (pm_phy == NULL) { 6249 return SOC_E_INTERNAL; 6250 } 6251 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6252 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6253 if(intf == PHY82864_SYS_SIDE) { 6254 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6255 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 6256 } 6257 6258 sal_memset(&phymod_rx, 0, sizeof(phymod_rx)); 6259 phymod_rx.dfe[tap].enable = TRUE; 6260 phymod_rx.dfe[tap].value = value; 6261 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(&pm_phy_copy, &phymod_rx)); 6262 } 6263 6264 return(SOC_E_NONE); 6265 } 6266 6267 /* 6268 * phy_82864_pi_control_set 6269 */ 6270 STATIC int 6271 phy_82864_pi_control_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 6272 { 6273 phymod_phy_access_t *pm_phy; 6274 phymod_tx_override_t tx_override; 6275 int idx; 6276 phymod_phy_access_t pm_phy_copy; 6277 6278 /* loop through all cores */ 6279 for (idx = 0; idx < pmc->num_phys; idx++) { 6280 pm_phy = &pmc->phy[idx]->pm_phy; 6281 6282 if (pm_phy == NULL) { 6283 return SOC_E_INTERNAL; 6284 } 6285 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6286 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6287 if(intf == PHY82864_SYS_SIDE) { 6288 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6289 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 6290 } 6291 6292 phymod_tx_override_t_init(&tx_override); 6293 tx_override.phase_interpolator.enable = (value == 0) ? 0 : 1; 6294 tx_override.phase_interpolator.value = value; 6295 SOC_IF_ERROR_RETURN(phymod_phy_tx_override_set(&pm_phy_copy, &tx_override)); 6296 } 6297 6298 return(SOC_E_NONE); 6299 } 6300 6301 STATIC int 6302 phy_82864_per_lane_tx_polarity_set(soc_phymod_ctrl_t *pmc, soc_port_t port, phymod_polarity_t *cfg_polarity, int32 intf, int lane, uint32 value) 6303 { 6304 phymod_phy_access_t *pm_phy; 6305 phymod_polarity_t polarity; 6306 uint32 lane_map; 6307 phymod_phy_access_t pm_phy_copy; 6308 soc_phymod_phy_t *p_phy; 6309 6310 /* locate the desired phy and lane */ 6311 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 6312 6313 /* Make a copy of the phy access and overwrite the desired lane */ 6314 pm_phy = &p_phy->pm_phy; 6315 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6316 pm_phy_copy.access.lane_mask = lane_map; 6317 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6318 if(intf == PHY82864_SYS_SIDE) { 6319 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6320 } 6321 6322 sal_memcpy(&polarity, cfg_polarity, sizeof(polarity)); 6323 SOC_IF_ERROR_RETURN(phymod_phy_polarity_get(&pm_phy_copy, &polarity)); 6324 polarity.tx_polarity = value; 6325 SOC_IF_ERROR_RETURN(phymod_phy_polarity_set(&pm_phy_copy, &polarity)); 6326 6327 /* after successfully setting the parity, update the configured value */ 6328 cfg_polarity->tx_polarity = value; 6329 6330 return(SOC_E_NONE); 6331 } 6332 /* 6333 * phy_82864_tx_polarity_set 6334 */ 6335 STATIC int 6336 phy_82864_tx_polarity_set(soc_phymod_ctrl_t *pmc, soc_port_t port, phymod_polarity_t *cfg_polarity, int32 intf, uint32 value) 6337 { 6338 phymod_phy_access_t *pm_phy; 6339 phymod_polarity_t polarity; 6340 int idx; 6341 phymod_phy_access_t pm_phy_copy; 6342 6343 /* loop through all cores */ 6344 for (idx = 0; idx < pmc->num_phys; idx++) { 6345 pm_phy = &pmc->phy[idx]->pm_phy; 6346 6347 if (pm_phy == NULL) { 6348 return SOC_E_INTERNAL; 6349 } 6350 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6351 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6352 if(intf == PHY82864_SYS_SIDE) { 6353 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6354 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 6355 } 6356 6357 sal_memcpy(&polarity, cfg_polarity, sizeof(polarity)); 6358 SOC_IF_ERROR_RETURN(phymod_phy_polarity_get(&pm_phy_copy, &polarity)); 6359 polarity.tx_polarity = value; 6360 SOC_IF_ERROR_RETURN(phymod_phy_polarity_set(&pm_phy_copy, &polarity)); 6361 6362 /* after successfully setting the parity, update the configured value */ 6363 cfg_polarity->tx_polarity = value; 6364 } 6365 6366 return(SOC_E_NONE); 6367 } 6368 /* 6369 * phy_82864_per_lane_rx_polarity_set 6370 */ 6371 STATIC int 6372 phy_82864_per_lane_rx_polarity_set(soc_phymod_ctrl_t *pmc, soc_port_t port, phymod_polarity_t *cfg_polarity, int32 intf, int lane, uint32 value) 6373 { 6374 phymod_phy_access_t *pm_phy; 6375 phymod_polarity_t polarity; 6376 uint32 lane_map; 6377 phymod_phy_access_t pm_phy_copy; 6378 soc_phymod_phy_t *p_phy; 6379 6380 /* locate the desired phy and lane */ 6381 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 6382 6383 /* Make a copy of the phy access and overwrite the desired lane */ 6384 pm_phy = &p_phy->pm_phy; 6385 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6386 pm_phy_copy.access.lane_mask = lane_map; 6387 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6388 if(intf == PHY82864_SYS_SIDE) { 6389 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6390 } 6391 6392 sal_memcpy(&polarity, cfg_polarity, sizeof(polarity)); 6393 SOC_IF_ERROR_RETURN(phymod_phy_polarity_get(&pm_phy_copy, &polarity)); 6394 polarity.rx_polarity = value; 6395 SOC_IF_ERROR_RETURN(phymod_phy_polarity_set(&pm_phy_copy, &polarity)); 6396 6397 /* after successfully setting the parity, update the configured value */ 6398 cfg_polarity->rx_polarity = value; 6399 6400 return(SOC_E_NONE); 6401 } 6402 6403 /* 6404 * phy_82864_rx_polarity_set 6405 */ 6406 6407 STATIC int 6408 phy_82864_rx_polarity_set(soc_phymod_ctrl_t *pmc, soc_port_t port, phymod_polarity_t *cfg_polarity, int32 intf, uint32 value) 6409 { 6410 phymod_phy_access_t *pm_phy; 6411 phymod_polarity_t polarity; 6412 int idx; 6413 phymod_phy_access_t pm_phy_copy; 6414 6415 /* loop through all cores */ 6416 for (idx = 0; idx < pmc->num_phys; idx++) { 6417 pm_phy = &pmc->phy[idx]->pm_phy; 6418 6419 if (pm_phy == NULL) { 6420 return SOC_E_INTERNAL; 6421 } 6422 6423 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6424 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6425 if(intf == PHY82864_SYS_SIDE) { 6426 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6427 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 6428 } 6429 sal_memcpy(&polarity, cfg_polarity, sizeof(polarity)); 6430 SOC_IF_ERROR_RETURN(phymod_phy_polarity_get(&pm_phy_copy, &polarity)); 6431 polarity.rx_polarity = value; 6432 SOC_IF_ERROR_RETURN(phymod_phy_polarity_set(&pm_phy_copy, &polarity)); 6433 6434 /* after successfully setting the parity, update the configured value */ 6435 cfg_polarity->rx_polarity = value; 6436 } 6437 6438 return(SOC_E_NONE); 6439 } 6440 6441 /* 6442 * phy_82864_rx_reset 6443 */ 6444 STATIC int 6445 phy_82864_rx_reset(soc_phymod_ctrl_t *pmc, soc_port_t port, phymod_phy_reset_t *cfg_reset, int32 intf, uint32 value) 6446 { 6447 phymod_phy_access_t *pm_phy; 6448 phymod_phy_reset_t reset; 6449 int idx; 6450 phymod_phy_access_t pm_phy_copy; 6451 6452 /* loop through all cores */ 6453 for (idx = 0; idx < pmc->num_phys; idx++) { 6454 pm_phy = &pmc->phy[idx]->pm_phy; 6455 6456 if (pm_phy == NULL) { 6457 return SOC_E_INTERNAL; 6458 } 6459 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6460 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6461 if(intf == PHY82864_SYS_SIDE) { 6462 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6463 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 6464 } 6465 6466 sal_memcpy(&reset, cfg_reset, sizeof(reset)); 6467 reset.rx = (phymod_reset_direction_t) value; 6468 SOC_IF_ERROR_RETURN(phymod_phy_reset_set(&pm_phy_copy, &reset)); 6469 6470 /* after successfully setting the parity, update the configured value */ 6471 cfg_reset->rx = (phymod_reset_direction_t) value; 6472 } 6473 6474 return(SOC_E_NONE); 6475 } 6476 6477 /* 6478 * phy_82864_tx_reset 6479 */ 6480 STATIC int 6481 phy_82864_tx_reset(soc_phymod_ctrl_t *pmc, soc_port_t port, phymod_phy_reset_t *cfg_reset, int32 intf, uint32 value) 6482 { 6483 phymod_phy_access_t *pm_phy; 6484 phymod_phy_reset_t reset; 6485 int idx; 6486 phymod_phy_access_t pm_phy_copy; 6487 6488 /* loop through all cores */ 6489 for (idx = 0; idx < pmc->num_phys; idx++) { 6490 pm_phy = &pmc->phy[idx]->pm_phy; 6491 6492 if (pm_phy == NULL) { 6493 return SOC_E_INTERNAL; 6494 } 6495 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6496 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6497 if(intf == PHY82864_SYS_SIDE) { 6498 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6499 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 6500 } 6501 6502 sal_memcpy(&reset, cfg_reset, sizeof(reset)); 6503 reset.tx = (phymod_reset_direction_t) value; 6504 SOC_IF_ERROR_RETURN(phymod_phy_reset_set(&pm_phy_copy, &reset)); 6505 6506 /* after successfully setting the parity, update the configured value */ 6507 cfg_reset->tx = (phymod_reset_direction_t) value; 6508 } 6509 6510 return(SOC_E_NONE); 6511 } 6512 6513 6514 /* 6515 * phy_82864_per_lane_power_set 6516 */ 6517 STATIC int 6518 phy_82864_per_lane_power_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 value) 6519 { 6520 phymod_phy_access_t *pm_phy; 6521 phymod_phy_power_t power; 6522 uint32 lane_map; 6523 phymod_phy_access_t pm_phy_copy; 6524 soc_phymod_phy_t *p_phy; 6525 6526 /* locate the desired phy and lane */ 6527 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 6528 6529 /* Make a copy of the phy access and overwrite the desired lane */ 6530 pm_phy = &p_phy->pm_phy; 6531 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6532 pm_phy_copy.access.lane_mask = lane_map; 6533 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6534 if(intf == PHY82864_SYS_SIDE) { 6535 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6536 } 6537 6538 phymod_phy_power_t_init(&power); 6539 if (value) { 6540 power.tx = phymodPowerOn; 6541 power.rx = phymodPowerOn; 6542 } 6543 else { 6544 power.tx = phymodPowerOff; 6545 power.rx = phymodPowerOff; 6546 } 6547 6548 SOC_IF_ERROR_RETURN(phymod_phy_power_set(&pm_phy_copy, &power)); 6549 6550 return(SOC_E_NONE); 6551 } 6552 /* 6553 * phy_82864_power_set 6554 */ 6555 STATIC int 6556 phy_82864_power_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 6557 { 6558 phymod_phy_access_t *pm_phy; 6559 phymod_phy_power_t power; 6560 int idx; 6561 phymod_phy_access_t pm_phy_copy; 6562 6563 /* loop through all cores */ 6564 for (idx = 0; idx < pmc->num_phys; idx++) { 6565 pm_phy = &pmc->phy[idx]->pm_phy; 6566 6567 if (pm_phy == NULL) { 6568 return SOC_E_INTERNAL; 6569 } 6570 6571 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6572 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6573 if(intf == PHY82864_SYS_SIDE) { 6574 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6575 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 6576 } 6577 6578 phymod_phy_power_t_init(&power); 6579 if (value) { 6580 power.tx = phymodPowerOn; 6581 power.rx = phymodPowerOn; 6582 } 6583 else { 6584 power.tx = phymodPowerOff; 6585 power.rx = phymodPowerOff; 6586 } 6587 6588 SOC_IF_ERROR_RETURN(phymod_phy_power_set(&pm_phy_copy, &power)); 6589 } 6590 6591 return(SOC_E_NONE); 6592 } 6593 6594 6595 /* 6596 * phy_82864_rx_low_freq_filter_set 6597 */ 6598 STATIC int 6599 phy_82864_rx_low_freq_filter_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 6600 { 6601 phymod_phy_access_t *pm_phy; 6602 phymod_rx_t phymod_rx; 6603 int idx; 6604 phymod_phy_access_t pm_phy_copy; 6605 6606 /* loop through all cores */ 6607 for (idx = 0; idx < pmc->num_phys; idx++) { 6608 pm_phy = &pmc->phy[idx]->pm_phy; 6609 6610 if (pm_phy == NULL) { 6611 return SOC_E_INTERNAL; 6612 } 6613 6614 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6615 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6616 if(intf == PHY82864_SYS_SIDE) { 6617 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6618 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 6619 } 6620 6621 sal_memset(&phymod_rx, 0, sizeof(phymod_rx)); 6622 phymod_rx.low_freq_peaking_filter.enable = TRUE; 6623 phymod_rx.low_freq_peaking_filter.value = value; 6624 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(&pm_phy_copy, &phymod_rx)); 6625 } 6626 6627 return(SOC_E_NONE); 6628 } 6629 6630 STATIC int 6631 phy_82864_rx_seq_restart(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 6632 { 6633 int idx; 6634 uint32_t flags = 0; 6635 soc_phymod_core_t *pmc_core; 6636 phymod_core_access_t *pm_core; 6637 phymod_core_access_t pm_core_copy; 6638 phymod_sequencer_operation_t seq_operation; 6639 6640 /* loop through all cores */ 6641 for (idx = 0; idx < pmc->num_phys; idx++) { 6642 pmc_core = pmc->phy[idx]->core; 6643 pm_core = &pmc_core->pm_core; 6644 if (pm_core == NULL) { 6645 return SOC_E_INTERNAL; 6646 } 6647 6648 sal_memcpy(&pm_core_copy, pm_core, sizeof(pm_core_copy)); 6649 pm_core_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6650 if(intf == PHY82864_SYS_SIDE) { 6651 pm_core_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6652 } 6653 seq_operation = phymodSeqOpRestart; 6654 SOC_IF_ERROR_RETURN(phymod_core_pll_sequencer_restart(pm_core, flags, seq_operation)); 6655 } 6656 6657 return(SOC_E_NONE); 6658 } 6659 6660 STATIC int 6661 phy_82864_phy_dump(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf) 6662 { 6663 phymod_phy_access_t *pm_phy; 6664 int idx; 6665 phymod_phy_access_t pm_phy_copy; 6666 6667 /* loop through all cores */ 6668 for (idx = 0; idx < pmc->num_phys; idx++) { 6669 pm_phy = &pmc->phy[idx]->pm_phy; 6670 6671 if (pm_phy == NULL) { 6672 return SOC_E_INTERNAL; 6673 } 6674 6675 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6676 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6677 if(intf == PHY82864_SYS_SIDE) { 6678 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6679 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 6680 } 6681 SOC_IF_ERROR_RETURN(phymod_phy_status_dump(&pm_phy_copy)); 6682 } 6683 6684 return(SOC_E_NONE); 6685 } 6686 STATIC int 6687 phy_82864_per_lane_phy_dump(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane) 6688 { 6689 phymod_phy_access_t *pm_phy; 6690 uint32 lane_map; 6691 phymod_phy_access_t pm_phy_copy; 6692 soc_phymod_phy_t *p_phy; 6693 6694 /* locate the desired phy and lane */ 6695 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 6696 6697 /* Make a copy of the phy access and overwrite the desired lane */ 6698 pm_phy = &p_phy->pm_phy; 6699 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6700 pm_phy_copy.access.lane_mask = lane_map; 6701 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6702 if(intf == PHY82864_SYS_SIDE) { 6703 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6704 } 6705 6706 SOC_IF_ERROR_RETURN(phymod_phy_status_dump(&pm_phy_copy)); 6707 6708 return(SOC_E_NONE); 6709 } 6710 6711 /* 6712 * phy_82864_unreliable_los_set 6713 */ 6714 STATIC int 6715 phy_82864_unreliable_los_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 enable) 6716 { 6717 phymod_phy_access_t *pm_phy; 6718 phymod_firmware_lane_config_t fw_config; 6719 int idx; 6720 phymod_phy_access_t pm_phy_copy; 6721 sal_memset(&fw_config, 0, sizeof(fw_config)); 6722 6723 /* loop through all cores */ 6724 for (idx = 0; idx < pmc->num_phys; idx++) { 6725 if (pmc->phy[idx] == NULL) { 6726 return(SOC_E_INTERNAL); 6727 } 6728 6729 pm_phy = &pmc->phy[idx]->pm_phy; 6730 if (pm_phy == NULL) { 6731 return(SOC_E_INTERNAL); 6732 } 6733 6734 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 6735 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 6736 if(intf == PHY82864_SYS_SIDE) { 6737 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 6738 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 6739 } 6740 6741 SOC_IF_ERROR_RETURN(phymod_phy_firmware_lane_config_get(&pm_phy_copy, &fw_config)); 6742 6743 if (enable) { 6744 fw_config.UnreliableLos = 1; 6745 } else { 6746 fw_config.UnreliableLos = 0; 6747 } 6748 6749 SOC_IF_ERROR_RETURN(phymod_phy_firmware_lane_config_set(&pm_phy_copy, fw_config)); 6750 } 6751 6752 return(SOC_E_NONE); 6753 } 6754 /* 6755 * Function: 6756 * phy_82864_control_set 6757 * Purpose: 6758 * Configure PHY device specific control fucntion. 6759 * Parameters: 6760 * unit - BCM unit number. 6761 * port - Port number. 6762 * type - Control to update 6763 * value - New setting for the control 6764 * Returns: 6765 * SOC_E_NONE 6766 */ 6767 STATIC int 6768 phy_82864_control_set(int unit, soc_port_t port, soc_phy_control_t type, uint32 value) 6769 { 6770 int rv; 6771 int32 intf; 6772 phy_ctrl_t *pc; 6773 soc_phymod_ctrl_t *pmc; 6774 phy82864_config_t *pCfg; 6775 6776 rv = SOC_E_UNAVAIL; 6777 6778 PHY_CONTROL_TYPE_CHECK(type); 6779 6780 /* locate phy control, phymod control, and the configuration data */ 6781 pc = EXT_PHY_SW_STATE(unit, port); 6782 if (pc == NULL) { 6783 return SOC_E_INTERNAL; 6784 } 6785 pmc = &pc->phymod_ctrl; 6786 pCfg = (phy82864_config_t *) pc->driver_data; 6787 6788 intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY82864_SYS_SIDE : PHY82864_LINE_SIDE; 6789 6790 switch(type) { 6791 /* decoupled PRBS */ 6792 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_POLYNOMIAL: 6793 rv = phy_82864_prbs_tx_poly_set(pmc, port, intf, value); 6794 break; 6795 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_INVERT_DATA: 6796 rv = phy_82864_prbs_tx_invert_data_set(pmc, port, intf, value); 6797 break; 6798 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_ENABLE: 6799 rv = phy_82864_prbs_tx_enable_set(pmc, port, intf, value); 6800 break; 6801 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_POLYNOMIAL: 6802 rv = phy_82864_prbs_rx_poly_set(pmc, port, intf, value); 6803 break; 6804 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_INVERT_DATA: 6805 rv = phy_82864_prbs_rx_invert_data_set(pmc, port, intf, value); 6806 break; 6807 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_ENABLE: 6808 rv = phy_82864_prbs_rx_enable_set(pmc, port, intf, value); 6809 break; 6810 /* for legacy prbs usage mainly set both tx/rx the same */ 6811 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 6812 rv = phy_82864_prbs_tx_poly_set(pmc, port, intf, value); 6813 rv = phy_82864_prbs_rx_poly_set(pmc, port, intf, value); 6814 break; 6815 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 6816 rv = phy_82864_prbs_tx_invert_data_set(pmc, port, intf, value); 6817 break; 6818 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 6819 rv = phy_82864_prbs_tx_enable_set(pmc, port, intf, value); 6820 rv = phy_82864_prbs_rx_enable_set(pmc, port, intf, value); 6821 break; 6822 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 6823 rv = phy_82864_prbs_tx_enable_set(pmc, port, intf, value); 6824 rv = phy_82864_prbs_rx_enable_set(pmc, port, intf, value); 6825 break; 6826 /* LOOPBACK */ 6827 case SOC_PHY_CONTROL_LOOPBACK_PMD: 6828 rv = phy_82864_loopback_internal_pmd_set(pmc, port, intf, value); 6829 break; 6830 case SOC_PHY_CONTROL_LOOPBACK_REMOTE: 6831 case SOC_PHY_CONTROL_LOOPBACK_REMOTE_PCS_BYPASS: 6832 rv = phy_82864_loopback_remote_set(pmc, port, intf, value); 6833 break; 6834 case SOC_PHY_CONTROL_TX_FIR_PRE: 6835 rv = phy_82864_tx_fir_pre_set(pmc, port, intf, value); 6836 break; 6837 case SOC_PHY_CONTROL_TX_FIR_MAIN: 6838 rv = phy_82864_tx_fir_main_set(pmc, port, intf, value); 6839 break; 6840 case SOC_PHY_CONTROL_TX_FIR_POST: 6841 rv = phy_82864_tx_fir_post_set(pmc, port, intf, value); 6842 break; 6843 case SOC_PHY_CONTROL_TX_FIR_POST2: 6844 rv = phy_82864_tx_fir_post2_set(pmc, port, intf, value); 6845 break; 6846 case SOC_PHY_CONTROL_TX_FIR_POST3: 6847 rv = phy_82864_tx_fir_post3_set(pmc, port, intf, value); 6848 break; 6849 /* PREEMPHASIS */ 6850 case SOC_PHY_CONTROL_PREEMPHASIS_LANE0: 6851 rv = phy_82864_per_lane_preemphasis_set(pmc, port, intf, 0, value); 6852 break; 6853 case SOC_PHY_CONTROL_PREEMPHASIS_LANE1: 6854 rv = phy_82864_per_lane_preemphasis_set(pmc, port, intf, 1, value); 6855 break; 6856 case SOC_PHY_CONTROL_PREEMPHASIS_LANE2: 6857 rv = phy_82864_per_lane_preemphasis_set(pmc, port, intf, 2, value); 6858 break; 6859 case SOC_PHY_CONTROL_PREEMPHASIS_LANE3: 6860 rv = phy_82864_per_lane_preemphasis_set(pmc, port, intf, 3, value); 6861 break; 6862 case SOC_PHY_CONTROL_PREEMPHASIS: 6863 rv = phy_82864_preemphasis_set(pmc, port, intf, value); 6864 break; 6865 6866 /* DRIVER CURRENT */ 6867 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0: 6868 rv = phy_82864_per_lane_driver_current_set(pmc, port, intf, 0, value); 6869 break; 6870 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1: 6871 rv = phy_82864_per_lane_driver_current_set(pmc, port, intf, 1, value); 6872 break; 6873 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2: 6874 rv = phy_82864_per_lane_driver_current_set(pmc, port, intf, 2, value); 6875 break; 6876 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3: 6877 rv = phy_82864_per_lane_driver_current_set(pmc, port, intf, 3, value); 6878 break; 6879 case SOC_PHY_CONTROL_DRIVER_CURRENT: 6880 rv = phy_82864_driver_current_set(pmc, port, intf, value); 6881 break; 6882 /* TX LANE SQUELCH */ 6883 case SOC_PHY_CONTROL_TX_LANE_SQUELCH: 6884 rv = phy_82864_tx_lane_squelch(pmc, port, intf, value); 6885 break; 6886 /* RX PEAK FILTER */ 6887 case SOC_PHY_CONTROL_RX_PEAK_FILTER: 6888 rv = phy_82864_rx_peak_filter_set(pmc, port, intf, value); 6889 break; 6890 6891 /* RX VGA */ 6892 case SOC_PHY_CONTROL_RX_VGA: 6893 rv = phy_82864_rx_vga_set(pmc, port, intf, 1, value); 6894 break; 6895 case SOC_PHY_CONTROL_RX_VGA_RELEASE: 6896 rv = phy_82864_rx_vga_set(pmc, port, intf, 0, value); 6897 break; 6898 /* RX TAP */ 6899 case SOC_PHY_CONTROL_RX_TAP1: 6900 rv = phy_82864_rx_tap_set(pmc, port, intf, 0, value); 6901 break; 6902 case SOC_PHY_CONTROL_RX_TAP2: 6903 rv = phy_82864_rx_tap_set(pmc, port, intf, 1, value); 6904 break; 6905 case SOC_PHY_CONTROL_RX_TAP3: 6906 rv = phy_82864_rx_tap_set(pmc, port, intf, 2, value); 6907 break; 6908 case SOC_PHY_CONTROL_RX_TAP4: 6909 rv = phy_82864_rx_tap_set(pmc, port, intf, 3, value); 6910 break; 6911 case SOC_PHY_CONTROL_RX_TAP5: 6912 rv = phy_82864_rx_tap_set(pmc, port, intf, 4, value); 6913 break; 6914 case SOC_PHY_CONTROL_RX_TAP1_RELEASE: /* $$$ tbd $$$ */ 6915 rv = phy_82864_rx_tap_release(pmc, port, intf, 0); 6916 break; 6917 case SOC_PHY_CONTROL_RX_TAP2_RELEASE: /* $$$ tbd $$$ */ 6918 rv = phy_82864_rx_tap_release(pmc, port, intf, 1); 6919 break; 6920 case SOC_PHY_CONTROL_RX_TAP3_RELEASE: /* $$$ tbd $$$ */ 6921 rv = phy_82864_rx_tap_release(pmc, port, intf, 2); 6922 break; 6923 case SOC_PHY_CONTROL_RX_TAP4_RELEASE: /* $$$ tbd $$$ */ 6924 rv = phy_82864_rx_tap_release(pmc, port, intf, 3); 6925 break; 6926 case SOC_PHY_CONTROL_RX_TAP5_RELEASE: /* $$$ tbd $$$ */ 6927 rv = phy_82864_rx_tap_release(pmc, port, intf, 4); 6928 break; 6929 /* PHASE INTERPOLATOR */ 6930 case SOC_PHY_CONTROL_PHASE_INTERP: 6931 rv = phy_82864_pi_control_set(pmc, port, intf, value); 6932 break; 6933 /* POLARITY */ 6934 case SOC_PHY_CONTROL_RX_POLARITY: 6935 rv = phy_82864_rx_polarity_set(pmc, port, &pCfg->phy_polarity_config, intf, value);; 6936 break; 6937 case SOC_PHY_CONTROL_TX_POLARITY: 6938 rv = phy_82864_tx_polarity_set(pmc, port, &pCfg->phy_polarity_config, intf, value); 6939 break; 6940 /* RESET */ 6941 case SOC_PHY_CONTROL_RX_RESET: 6942 rv = phy_82864_rx_reset(pmc, port, &pCfg->phy_reset_config, intf, value); 6943 break; 6944 case SOC_PHY_CONTROL_TX_RESET: 6945 rv = phy_82864_tx_reset(pmc, port, &pCfg->phy_reset_config, intf, value); 6946 break; 6947 /* POWER */ 6948 case SOC_PHY_CONTROL_POWER: 6949 { 6950 phy_ctrl_t *int_pc; 6951 int_pc = INT_PHY_SW_STATE(unit, port); 6952 if (int_pc != NULL) { 6953 SOC_IF_ERROR_RETURN(PHY_ENABLE_SET(int_pc->pd, unit, port, value)); 6954 rv = phy_82864_power_set(pmc, port, intf, value); 6955 } 6956 } 6957 break; 6958 case SOC_PHY_CONTROL_RX_LOW_FREQ_PEAK_FILTER: 6959 rv = phy_82864_rx_low_freq_filter_set(pmc, port, intf, value); 6960 break; 6961 case SOC_PHY_CONTROL_FORWARD_ERROR_CORRECTION: 6962 rv = phy_82864_fec_enable_set(pmc, value); 6963 break; 6964 case SOC_PHY_CONTROL_RX_SEQ_TOGGLE: 6965 rv = phy_82864_rx_seq_restart(pmc, port, intf, value); 6966 break; 6967 case SOC_PHY_CONTROL_DUMP: 6968 rv = phy_82864_phy_dump(pmc, port, intf); 6969 break; 6970 case SOC_PHY_CONTROL_CL72: 6971 rv = phy_82864_cl72_enable_set(pmc, port, intf, value); 6972 break; 6973 case SOC_PHY_CONTROL_INTR_MASK: 6974 rv = phy_82864_intr_enable_set(pc, intf, value); 6975 break; 6976 case SOC_PHY_CONTROL_GPIO_CONFIG: 6977 rv = phy_82864_gpio_config_set(pc, value); 6978 break; 6979 case SOC_PHY_CONTROL_GPIO_VALUE: 6980 rv = phy_82864_gpio_value_set(pc, value); 6981 break; 6982 case SOC_PHY_CONTROL_FIRMWARE_MODE: 6983 rv = phy_82864_firmware_mode_set(pc, port, intf, value); 6984 break; 6985 case SOC_PHY_CONTROL_FIRMWARE_DFE_ENABLE: 6986 rv = phy_82864_firmware_dfe_enable_set(pc, port, intf, value); 6987 break; 6988 case SOC_PHY_CONTROL_FIRMWARE_LP_DFE_ENABLE: 6989 rv = phy_82864_firmware_lp_dfe_enable_set(pc, port, intf, value); 6990 break; 6991 case SOC_PHY_CONTROL_UNRELIABLE_LOS: 6992 rv = phy_82864_unreliable_los_set(pmc, port, intf, value); 6993 break; 6994 default: 6995 rv = SOC_E_UNAVAIL; 6996 break; 6997 } 6998 6999 return rv; 7000 } 7001 /* 7002 * Function: 7003 * phy_82864_per_lane_control_set 7004 * Purpose: 7005 * Configure PHY device specific control fucntion. 7006 * Parameters: 7007 * unit - StrataSwitch unit #. 7008 * port - StrataSwitch port #. 7009 * lane - lane number 7010 * type - Control to update 7011 * value - New setting for the control 7012 * Returns: 7013 * SOC_E_NONE 7014 */ 7015 STATIC int 7016 phy_82864_per_lane_control_set(int unit, soc_port_t port, int lane, soc_phy_control_t type, uint32 value) 7017 { 7018 int rv = -1; 7019 int32 intf; 7020 phy_ctrl_t *pc; 7021 soc_phymod_ctrl_t *pmc; 7022 phy82864_config_t *pCfg; 7023 7024 /* locate phy control, phymod control, and the configuration data */ 7025 pc = EXT_PHY_SW_STATE(unit, port); 7026 if (pc == NULL) { 7027 return SOC_E_INTERNAL; 7028 } 7029 pmc = &pc->phymod_ctrl; 7030 pCfg = (phy82864_config_t *) pc->driver_data; 7031 7032 PHY_CONTROL_TYPE_CHECK(type); 7033 7034 intf = (pc->flags & PHYCTRL_SYS_SIDE_CTRL) ? PHY82864_SYS_SIDE : PHY82864_LINE_SIDE; 7035 7036 switch(type) { 7037 case SOC_PHY_CONTROL_PREEMPHASIS: 7038 rv = phy_82864_per_lane_preemphasis_set(pmc, port, intf, lane, value); 7039 break; 7040 case SOC_PHY_CONTROL_DRIVER_CURRENT: 7041 rv = phy_82864_per_lane_driver_current_set(pmc, port, intf, lane, value); 7042 break; 7043 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 7044 rv = SOC_E_UNAVAIL; 7045 break; 7046 case SOC_PHY_CONTROL_DRIVER_POST2_CURRENT: 7047 rv = SOC_E_UNAVAIL; 7048 break; 7049 case SOC_PHY_CONTROL_RX_TAP1: 7050 rv = phy_82864_per_lane_rx_dfe_tap_control_set (pmc, port, intf, lane, 0 /* tap */, 1 /* enable */, value); 7051 break; 7052 case SOC_PHY_CONTROL_RX_TAP1_RELEASE: 7053 rv = phy_82864_per_lane_rx_dfe_tap_control_set (pmc, port, intf, lane, 0 /* tap */, 0 /* release */, 0x8000); 7054 break; 7055 case SOC_PHY_CONTROL_RX_TAP2: 7056 rv = phy_82864_per_lane_rx_dfe_tap_control_set (pmc, port, intf, lane, 1 /* tap */, 1 /* enable */, value); 7057 break; 7058 case SOC_PHY_CONTROL_RX_TAP2_RELEASE: 7059 rv = phy_82864_per_lane_rx_dfe_tap_control_set (pmc, port, intf, lane, 1 /* tap */, 0 /* release */, 0x8000); 7060 break; 7061 case SOC_PHY_CONTROL_RX_TAP3: 7062 rv = phy_82864_per_lane_rx_dfe_tap_control_set (pmc, port, intf, lane, 2 /* tap */, 1 /* enable */, value); 7063 break; 7064 case SOC_PHY_CONTROL_RX_TAP3_RELEASE: 7065 rv = phy_82864_per_lane_rx_dfe_tap_control_set (pmc, port, intf, lane, 2 /* tap */, 0 /* release */, 0x8000); 7066 break; 7067 case SOC_PHY_CONTROL_RX_TAP4: 7068 rv = phy_82864_per_lane_rx_dfe_tap_control_set (pmc, port, intf, lane, 3 /* tap */, 1 /* enable */, value); 7069 break; 7070 case SOC_PHY_CONTROL_RX_TAP4_RELEASE: 7071 rv = phy_82864_per_lane_rx_dfe_tap_control_set (pmc, port, intf, lane, 3 /* tap */, 0 /* release */, 0x8000); 7072 break; 7073 case SOC_PHY_CONTROL_RX_TAP5: 7074 rv = phy_82864_per_lane_rx_dfe_tap_control_set (pmc, port, intf, lane, 4 /* tap */, 1 /* enable */, value); 7075 break; 7076 case SOC_PHY_CONTROL_RX_TAP5_RELEASE: 7077 rv = phy_82864_per_lane_rx_dfe_tap_control_set (pmc, port, intf, lane, 4 /* tap */, 0 /* release */, 0x8000); 7078 break; 7079 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_POLYNOMIAL: 7080 rv = phy_82864_per_lane_prbs_tx_poly_set(pmc, port, intf, lane, value); 7081 break; 7082 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_INVERT_DATA: 7083 rv = phy_82864_per_lane_prbs_tx_invert_data_set(pmc, port, intf, lane, value); 7084 break; 7085 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_ENABLE: 7086 rv = phy_82864_per_lane_prbs_tx_enable_set(pmc, port, intf, lane, value); 7087 break; 7088 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_POLYNOMIAL: 7089 rv = phy_82864_per_lane_prbs_rx_poly_set(pmc, port, intf, lane, value); 7090 break; 7091 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_INVERT_DATA: 7092 rv = phy_82864_per_lane_prbs_rx_invert_data_set(pmc, port, intf, lane, value); 7093 break; 7094 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_ENABLE: 7095 rv = phy_82864_per_lane_prbs_rx_enable_set(pmc, port, intf, lane, value); 7096 break; 7097 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 7098 rv = phy_82864_per_lane_prbs_tx_poly_set(pmc, port, intf, lane, value); 7099 rv = phy_82864_per_lane_prbs_rx_poly_set(pmc, port, intf, lane, value); 7100 break; 7101 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 7102 rv = phy_82864_per_lane_prbs_tx_invert_data_set(pmc, port, intf, lane, value); 7103 break; 7104 case SOC_PHY_CONTROL_PRBS_RX_INVERT_DATA: 7105 rv = phy_82864_per_lane_prbs_rx_invert_data_set(pmc, port, intf, lane, value); 7106 break; 7107 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 7108 /* TX_ENABLE does both tx and rx */ 7109 rv = phy_82864_per_lane_prbs_tx_enable_set(pmc, port, intf, lane, value); 7110 rv = phy_82864_per_lane_prbs_rx_enable_set(pmc, port, intf, lane, value); 7111 break; 7112 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 7113 rv = phy_82864_per_lane_prbs_tx_enable_set(pmc, port, intf, lane, value); 7114 rv = phy_82864_per_lane_prbs_rx_enable_set(pmc, port, intf, lane, value); 7115 break; 7116 case SOC_PHY_CONTROL_RX_PEAK_FILTER: 7117 rv = phy_82864_per_lane_rx_peak_filter_set(pmc, port, intf, lane, 1 /* enable */, value); 7118 break; 7119 case SOC_PHY_CONTROL_RX_LOW_FREQ_PEAK_FILTER: 7120 rv = phy_82864_per_lane_rx_low_freq_filter_set(pmc, port, intf, lane, value); 7121 break; 7122 case SOC_PHY_CONTROL_RX_VGA: 7123 rv = phy_82864_per_lane_rx_vga_set(pmc, port, intf, lane, 1 /* enable */, value); 7124 break; 7125 case SOC_PHY_CONTROL_RX_VGA_RELEASE: 7126 rv = phy_82864_per_lane_rx_vga_set(pmc, port, intf, lane, 0 /* release */, 0x8000); 7127 break; 7128 case SOC_PHY_CONTROL_RX_PLUS1_SLICER: 7129 rv = SOC_E_UNAVAIL; 7130 break; 7131 case SOC_PHY_CONTROL_RX_MINUS1_SLICER: 7132 rv = SOC_E_UNAVAIL; 7133 break; 7134 case SOC_PHY_CONTROL_RX_D_SLICER: 7135 rv = SOC_E_UNAVAIL; 7136 break; 7137 /* TX LANE SQUELCH */ 7138 case SOC_PHY_CONTROL_TX_LANE_SQUELCH: 7139 rv = phy_82864_per_lane_tx_lane_squelch(pmc, port, intf, lane, value); 7140 break; 7141 /* POWER */ 7142 case SOC_PHY_CONTROL_POWER: 7143 rv = phy_82864_per_lane_power_set(pmc, port, intf, lane, value); 7144 break; 7145 /* POLARITY */ 7146 case SOC_PHY_CONTROL_RX_POLARITY: 7147 rv = phy_82864_per_lane_rx_polarity_set(pmc, port, &pCfg->phy_polarity_config, intf, lane, value);; 7148 break; 7149 case SOC_PHY_CONTROL_TX_POLARITY: 7150 rv = phy_82864_per_lane_tx_polarity_set(pmc, port, &pCfg->phy_polarity_config, intf, lane, value); 7151 break; 7152 /* LOOPBACK */ 7153 case SOC_PHY_CONTROL_LOOPBACK_PMD: 7154 rv = phy_82864_per_lane_loopback_internal_pmd_set(pmc, port, intf, lane, value); 7155 break; 7156 case SOC_PHY_CONTROL_LOOPBACK_REMOTE: 7157 case SOC_PHY_CONTROL_LOOPBACK_REMOTE_PCS_BYPASS: 7158 rv = phy_82864_per_lane_loopback_remote_set(pmc, port, intf, lane, value); 7159 break; 7160 case SOC_PHY_CONTROL_DUMP: 7161 rv = phy_82864_per_lane_phy_dump(pmc, port, intf, lane); 7162 break; 7163 case SOC_PHY_CONTROL_TX_FIR_PRE: 7164 case SOC_PHY_CONTROL_TX_FIR_MAIN: 7165 case SOC_PHY_CONTROL_TX_FIR_POST: 7166 case SOC_PHY_CONTROL_TX_FIR_POST2: 7167 case SOC_PHY_CONTROL_TX_FIR_POST3: 7168 rv = phy_82864_per_lane_tx_set(pmc, port, intf, type, lane, value); 7169 break; 7170 case SOC_PHY_CONTROL_CL72: 7171 rv = phy_82864_per_lane_cl72_enable_set(pmc, port, intf, lane, value); 7172 break; 7173 default: 7174 rv = SOC_E_UNAVAIL; 7175 break; 7176 } 7177 7178 return rv; 7179 } 7180 7181 STATIC int phy_82864_diag_eyescan(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int32 lane) 7182 { 7183 phymod_phy_access_t *pm_phy; 7184 int idx = 0, rv = 0; 7185 phymod_phy_access_t pm_phy_copy; 7186 soc_phymod_phy_t *p_phy; 7187 uint32_t lane_map = 0; 7188 7189 for (idx = 0; idx < pmc->num_phys; idx++) { 7190 if (pmc->phy[idx] == NULL) { 7191 return SOC_E_INTERNAL; 7192 } 7193 p_phy = pmc->phy[idx]; 7194 /* Make a copy of the phy access and overwrite the desired lane */ 7195 pm_phy = &p_phy->pm_phy; 7196 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 7197 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 7198 if(intf == PHY_DIAG_INTF_SYS) { 7199 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 7200 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 7201 } 7202 if (lane == 0xf) { 7203 /* Get p_phy alone and let lane map be as Phy structure value */ 7204 lane = 1; 7205 SOC_IF_ERROR_RETURN( 7206 _phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 7207 lane = 0xf; 7208 } else { 7209 SOC_IF_ERROR_RETURN( 7210 _phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 7211 } 7212 7213 /* Make a copy of the phy access and overwrite the desired lane */ 7214 if (lane != 0xf) { 7215 pm_phy_copy.access.lane_mask = lane_map; 7216 } 7217 7218 eye_scan_mdr_enabled = 1; 7219 rv = phymod_phy_eyescan_run(&pm_phy_copy, PHYMOD_EYESCAN_F_DONE, 0, NULL); 7220 if (rv != SOC_E_NONE) { 7221 eye_scan_mdr_enabled = 0; 7222 return rv; 7223 } 7224 } 7225 eye_scan_mdr_enabled = 0; 7226 7227 return SOC_E_NONE; 7228 } 7229 7230 STATIC int phy_82864_diag_ber(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int32 lane, void *params) 7231 { 7232 phymod_phy_access_t *pm_phy; 7233 int idx = 0, rv = 0; 7234 phymod_phy_access_t pm_phy_copy; 7235 soc_phymod_phy_t *p_phy; 7236 uint32_t lane_map = 0; 7237 phymod_phy_eyescan_options_t eyescan_options; 7238 7239 for (idx = 0; idx < pmc->num_phys; idx++) { 7240 if (pmc->phy[idx] == NULL) { 7241 return SOC_E_INTERNAL; 7242 } 7243 p_phy = pmc->phy[idx]; 7244 /* Make a copy of the phy access and overwrite the desired lane */ 7245 pm_phy = &p_phy->pm_phy; 7246 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 7247 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 7248 if(intf == PHY_DIAG_INTF_SYS) { 7249 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 7250 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 7251 } 7252 if (lane == 0xf) { 7253 /* Get p_phy alone and let lane map be as Phy structure value */ 7254 lane = 1; 7255 SOC_IF_ERROR_RETURN( 7256 _phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 7257 lane = 0xf; 7258 } else { 7259 SOC_IF_ERROR_RETURN( 7260 _phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 7261 } 7262 7263 /* Make a copy of the phy access and overwrite the desired lane */ 7264 if (lane != 0xf) { 7265 pm_phy_copy.access.lane_mask = lane_map; 7266 } 7267 7268 eye_scan_mdr_enabled = 1; 7269 /* following param are used in BER projection */ 7270 sal_memset(&eyescan_options, 0, sizeof(phymod_phy_eyescan_options_t)); 7271 eyescan_options.ber_proj_scan_mode = ((soc_port_phy_eyescan_params_t *)params)->ber_proj_scan_mode; 7272 eyescan_options.ber_proj_timer_cnt = ((soc_port_phy_eyescan_params_t *)params)->ber_proj_timer_cnt; 7273 eyescan_options.ber_proj_err_cnt = ((soc_port_phy_eyescan_params_t *)params)->ber_proj_err_cnt; 7274 rv = phymod_phy_eyescan_run(&pm_phy_copy, PHYMOD_EYESCAN_F_DONE, phymodEyescanModeBERProj, &eyescan_options); 7275 if (rv != SOC_E_NONE) { 7276 eye_scan_mdr_enabled = 0; 7277 return rv; 7278 } 7279 } 7280 eye_scan_mdr_enabled = 0; 7281 7282 return SOC_E_NONE; 7283 } 7284 7285 STATIC int 7286 phy_82864_diag_dsc(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf) 7287 { 7288 phymod_phy_access_t *pm_phy; 7289 int idx; 7290 phymod_phy_access_t pm_phy_copy; 7291 soc_phymod_phy_t *p_phy; 7292 phymod_phy_diagnostics_t phy_diag; 7293 uint16_t lane_index = 0; 7294 7295 7296 for (idx = 0; idx < pmc->num_phys; idx++) { 7297 if (pmc->phy[idx] == NULL) { 7298 return SOC_E_INTERNAL; 7299 } 7300 p_phy = pmc->phy[idx]; 7301 /* Make a copy of the phy access and overwrite the desired lane */ 7302 pm_phy = &p_phy->pm_phy; 7303 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 7304 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 7305 if(intf == PHY_DIAG_INTF_SYS) { 7306 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 7307 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 7308 } 7309 7310 LOG_CLI((BSL_META_U(pmc->unit, 7311 "DSC parameters for port %d\n"), port)); 7312 for (lane_index = 0; lane_index < 10; lane_index ++) { 7313 if ((pm_phy_copy.access.lane_mask & (1 << lane_index))) { 7314 SOC_IF_ERROR_RETURN(phymod_phy_diagnostics_get(&pm_phy_copy, &phy_diag)); 7315 7316 /* display */ 7317 LOG_CLI((BSL_META_U(pmc->unit, 7318 "LaneN SIGDET VGABIASREDUCED POSTCMET OSR PMDMODE " 7319 "RXLOCK RXPPM TXPPM CLK90OFFSET CLKP1OFFSET P1LVL1 " 7320 "M1LVL1 DFE1_DCD DFE2_DCD SLICERTARGET PE ZE ME " 7321 "PO ZO MO HLFT HRGT VUPPR VLOWR SMSTS LNKTM " 7322 "MAIN HIZ BST\n"))); 7323 LOG_CLI((BSL_META_U(pmc->unit, 7324 "%05d %03d %06d %07d %03d %05d %05d %05d %06d %05d %08d " 7325 " %03d %05d %04d %04d %04d %02d %02d %02d %02d %02d %02d" 7326 " %03d %04d %05d %05d %04d %05d %04d %03d %03d \n"), 7327 lane_index, phy_diag.signal_detect, phy_diag.vga_bias_reduced, 7328 phy_diag.postc_metric, phy_diag.osr_mode, phy_diag.pmd_mode, 7329 phy_diag.rx_lock, phy_diag.rx_ppm, phy_diag.tx_ppm, 7330 phy_diag.clk90_offset, phy_diag.clkp1_offset, 7331 phy_diag.p1_lvl, phy_diag.m1_lvl, phy_diag.dfe1_dcd, 7332 phy_diag.dfe2_dcd, phy_diag.slicer_target, 7333 phy_diag.slicer_offset.offset_pe, phy_diag.slicer_offset.offset_ze, 7334 phy_diag.slicer_offset.offset_me, phy_diag.slicer_offset.offset_po, 7335 phy_diag.slicer_offset.offset_zo, phy_diag.slicer_offset.offset_mo, 7336 phy_diag.eyescan.heye_left, phy_diag.eyescan.heye_right, 7337 phy_diag.eyescan.veye_upper, phy_diag.eyescan.veye_lower, 7338 phy_diag.state_machine_status, phy_diag.link_time, 7339 phy_diag.pf_main, phy_diag.pf_hiz, 7340 phy_diag.pf_bst)); 7341 LOG_CLI((BSL_META_U(pmc->unit, 7342 "LOW PF2CTRL VGA DCOFFT P1LVLCTRL " 7343 "DFE1 DFE2 DFE3 DFE4 DFE5 DFE6 PRE MAIN POST1 " 7344 "POST2 POST3 TXAMPCTRL BRPDEN \n"))); 7345 7346 LOG_CLI((BSL_META_U(pmc->unit, 7347 "%03d %07d %03d %06d %04d %04d %04d %04d %04d %04d %04d %04d" 7348 " %03d %04d %05d %05d %04d %04d\n\n"), 7349 phy_diag.pf_low, 7350 phy_diag.pf2_ctrl, phy_diag.vga, 7351 phy_diag.dc_offset, phy_diag.p1_lvl_ctrl, 7352 phy_diag.dfe1, phy_diag.dfe2, 7353 phy_diag.dfe3, phy_diag.dfe4, 7354 phy_diag.dfe5, phy_diag.dfe6, 7355 phy_diag.txfir_pre, phy_diag.txfir_main, 7356 phy_diag.txfir_post1, phy_diag.txfir_post2, 7357 phy_diag.txfir_post3, phy_diag.tx_amp_ctrl, 7358 phy_diag.br_pd_en)); 7359 } 7360 } 7361 } 7362 return SOC_E_NONE; 7363 } 7364 /* 7365 * Function: 7366 * phy_82864_diag_ctrl 7367 * Purpose: 7368 * xx 7369 * Parameters: 7370 * unit - BCM unit number. 7371 * port - Port number. 7372 7373 * Returns: 7374 * SOC_E_NONE 7375 */ 7376 7377 STATIC int 7378 phy_82864_diag_ctrl( 7379 int unit, /* unit */ 7380 soc_port_t port, /* port */ 7381 uint32 inst, /* the specific device block the control action directs to */ 7382 int op_type, /* operation types: read,write or command sequence */ 7383 int op_cmd, /* command code */ 7384 void *arg) /* command argument based on op_type/op_cmd */ 7385 { 7386 int rv = -1; 7387 int32 lane; 7388 int32 intf; 7389 soc_phymod_ctrl_t *pmc; 7390 phy_ctrl_t *pc; 7391 /* locate phy control, phymod control, and the configuration data */ 7392 pc = EXT_PHY_SW_STATE(unit, port); 7393 if (pc == NULL) { 7394 return SOC_E_INTERNAL; 7395 } 7396 pmc = &pc->phymod_ctrl; 7397 lane = PHY_DIAG_INST_LN(inst); 7398 intf = PHY_DIAG_INST_INTF(inst); 7399 if (intf == PHY_DIAG_INTF_DFLT) { 7400 intf = PHY_DIAG_INTF_LINE; 7401 } 7402 if (intf == PHY_DIAG_INTF_SYS) { 7403 pc->flags |= PHYCTRL_SYS_SIDE_CTRL; 7404 } else { 7405 pc->flags &= ~PHYCTRL_SYS_SIDE_CTRL; 7406 } 7407 switch(op_cmd) { 7408 case PHY_DIAG_CTRL_DSC: 7409 rv = phy_82864_diag_dsc(pmc, port, intf); 7410 break; 7411 case PHY_DIAG_CTRL_START_FAST_EYESCAN: 7412 rv = phy_82864_diag_eyescan(pmc, port, intf, lane); 7413 break; 7414 case PHY_DIAG_CTRL_BER: 7415 rv = phy_82864_diag_ber(pmc, port, intf, lane, arg); 7416 break; 7417 case PHY_DIAG_CTRL_LINKMON_MODE: 7418 { 7419 uint32_t value = PTR_TO_INT(arg); 7420 rv = phy_82864_link_monitor_set(pmc, port, intf, lane, value); 7421 } 7422 break; 7423 case PHY_DIAG_CTRL_LINKMON_STATUS: 7424 { 7425 rv = phy_82864_link_monitor_status_get(pmc, port, intf, lane); 7426 } 7427 break; 7428 default: 7429 if (op_type == PHY_DIAG_CTRL_SET) { 7430 rv = phy_82864_control_set(unit,port,op_cmd,PTR_TO_INT(arg)); 7431 } else if (op_type == PHY_DIAG_CTRL_GET) { 7432 rv = phy_82864_control_get(unit,port,op_cmd,(uint32 *)arg); 7433 } 7434 break ; 7435 } 7436 7437 return rv; 7438 } 7439 7440 int32 phy_82864_core_reset(int32 unit, soc_port_t port, void *not_used) 7441 { 7442 phy_ctrl_t *pc; 7443 soc_phymod_core_t *pmc_core; 7444 int idx; 7445 phymod_core_access_t *pm_core; 7446 soc_phymod_ctrl_t *pmc; 7447 phymod_reset_direction_t reset_direction; 7448 /* locate phy control */ 7449 pc = EXT_PHY_SW_STATE(unit, port); 7450 if (pc == NULL) { 7451 return SOC_E_INTERNAL; 7452 } 7453 reset_direction = phymodResetDirectionIn; 7454 pmc = &pc->phymod_ctrl; 7455 7456 /* loop through all cores */ 7457 for (idx = 0; idx < pmc->num_phys; idx++) { 7458 pmc_core = pmc->phy[idx]->core; 7459 pm_core = &pmc_core->pm_core; 7460 if (pm_core == NULL) { 7461 return SOC_E_INTERNAL; 7462 } 7463 7464 SOC_IF_ERROR_RETURN(phymod_core_reset_set(pm_core, phymodResetModeSoft, reset_direction)); 7465 } 7466 7467 return(SOC_E_NONE); 7468 } 7469 7470 /* 7471 * phy_82864_per_lane_tx_set 7472 */ 7473 STATIC int 7474 phy_82864_per_lane_tx_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, soc_phy_control_t type, int lane, uint32 value) 7475 { 7476 soc_phymod_phy_t *p_phy; 7477 uint32 lane_map; 7478 phymod_phy_access_t pm_phy_copy, *pm_phy; 7479 phymod_tx_t phymod_tx; 7480 7481 /* locate the desired phy and lane */ 7482 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 7483 7484 /* Make a copy of the phy access and overwrite the desired lane */ 7485 pm_phy = &p_phy->pm_phy; 7486 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 7487 pm_phy_copy.access.lane_mask = lane_map; 7488 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 7489 if(intf == PHY82864_SYS_SIDE) { 7490 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 7491 } 7492 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 7493 switch (type) { 7494 case SOC_PHY_CONTROL_TX_FIR_PRE: 7495 phymod_tx.pre = value; 7496 break; 7497 case SOC_PHY_CONTROL_TX_FIR_MAIN: 7498 phymod_tx.main = value; 7499 break; 7500 case SOC_PHY_CONTROL_TX_FIR_POST: 7501 phymod_tx.post = value; 7502 break; 7503 case SOC_PHY_CONTROL_TX_FIR_POST2: 7504 phymod_tx.post2 = value; 7505 break; 7506 case SOC_PHY_CONTROL_TX_FIR_POST3: 7507 phymod_tx.post3 = value; 7508 break; 7509 default: 7510 return SOC_E_UNAVAIL; 7511 } 7512 7513 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 7514 7515 return(SOC_E_NONE); 7516 } 7517 7518 /* 7519 * phy_82864_per_lane_tx_get 7520 */ 7521 STATIC int 7522 phy_82864_per_lane_tx_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, soc_phy_control_t type, int lane, uint32 *value) 7523 { 7524 soc_phymod_phy_t *p_phy; 7525 uint32 lane_map; 7526 phymod_phy_access_t pm_phy_copy, *pm_phy; 7527 phymod_tx_t phymod_tx; 7528 7529 /* locate the desired phy and lane */ 7530 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 7531 7532 /* Make a copy of the phy access and overwrite the desired lane */ 7533 pm_phy = &p_phy->pm_phy; 7534 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 7535 pm_phy_copy.access.lane_mask = lane_map; 7536 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 7537 if(intf == PHY82864_SYS_SIDE) { 7538 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 7539 } 7540 7541 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 7542 *value = phymod_tx.amp; 7543 switch (type) { 7544 case SOC_PHY_CONTROL_TX_FIR_PRE: 7545 *value = phymod_tx.pre; 7546 break; 7547 case SOC_PHY_CONTROL_TX_FIR_MAIN: 7548 *value = phymod_tx.main; 7549 break; 7550 case SOC_PHY_CONTROL_TX_FIR_POST: 7551 *value = phymod_tx.post; 7552 break; 7553 case SOC_PHY_CONTROL_TX_FIR_POST2: 7554 *value = phymod_tx.post2; 7555 break; 7556 case SOC_PHY_CONTROL_TX_FIR_POST3: 7557 *value = phymod_tx.post3; 7558 break; 7559 default: 7560 return SOC_E_UNAVAIL; 7561 } 7562 7563 return(SOC_E_NONE); 7564 } 7565 7566 /* 7567 * Function: 7568 * _phy_84328_ability_remote_get 7569 * Purpose: 7570 * Get the device's complete abilities. 7571 * Parameters: 7572 * unit - StrataSwitch unit #. 7573 * port - StrataSwitch port #. 7574 * ability - return device's abilities. 7575 * Returns: 7576 * SOC_E_XXX 7577 */ 7578 STATIC int 7579 phy_82864_ability_remote_get(int unit, soc_port_t port, 7580 soc_port_ability_t *ability) 7581 { 7582 int an = 0, an_done = 0; 7583 int line_intf; 7584 uint32_t an_cap = 0; 7585 phy_ctrl_t *pc, *int_pc; 7586 soc_phymod_ctrl_t *pmc; 7587 phy82864_config_t *pCfg; 7588 soc_phymod_phy_t *phy; 7589 phymod_autoneg_ability_t phymod_autoneg_ability; 7590 7591 7592 if (ability == NULL) { 7593 return SOC_E_PARAM; 7594 } 7595 pc = EXT_PHY_SW_STATE(unit, port); 7596 7597 7598 /* Only firmware has visibility into remote ability */ 7599 sal_memset(ability, 0, sizeof(soc_port_ability_t)); 7600 7601 pmc = &pc->phymod_ctrl; 7602 pCfg = (phy82864_config_t *) pc->driver_data; 7603 7604 /* only set abilities on the first core */ 7605 phy = pmc->phy[pmc->main_phy]; 7606 if (phy == NULL) { 7607 return SOC_E_INTERNAL; 7608 } 7609 phymod_autoneg_ability_t_init(&phymod_autoneg_ability); 7610 7611 7612 line_intf = pCfg->speed_config.line_interface; 7613 7614 if ((line_intf == SOC_PORT_IF_KX) || (line_intf == SOC_PORT_IF_GMII)) { 7615 int_pc = INT_PHY_SW_STATE(unit, port); 7616 if (int_pc) { 7617 SOC_IF_ERROR_RETURN(PHY_ABILITY_REMOTE_GET(int_pc->pd, unit, port, ability)); 7618 } 7619 return SOC_E_NONE; 7620 } 7621 7622 ability->speed_half_duplex = SOC_PA_ABILITY_NONE; 7623 7624 /* Return what the firmware is setting */ 7625 /* If an done, then return the speed for the port */ 7626 SOC_IF_ERROR_RETURN(phy_82864_an_get(unit, port, &an, &an_done)); 7627 if (an && an_done) { 7628 SOC_IF_ERROR_RETURN 7629 (phymod_phy_autoneg_remote_ability_get(&phy->pm_phy, &phymod_autoneg_ability)); 7630 an_cap = phymod_autoneg_ability.an_cap; 7631 ability->speed_full_duplex |= PHYMOD_AN_CAP_100G_CR4_GET(an_cap) ? SOC_PA_SPEED_100GB : 0; 7632 ability->speed_full_duplex |= PHYMOD_AN_CAP_100G_KR4_GET(an_cap) ? SOC_PA_SPEED_100GB : 0; 7633 ability->speed_full_duplex |= PHYMOD_AN_CAP_40G_CR4_GET(an_cap) ? SOC_PA_SPEED_40GB : 0; 7634 ability->speed_full_duplex |= PHYMOD_AN_CAP_40G_KR4_GET(an_cap) ? SOC_PA_SPEED_40GB : 0; 7635 7636 an_cap = phymod_autoneg_ability.capabilities; 7637 if (an_cap == PHYMOD_AN_CAP_ASYM_PAUSE) { 7638 ability->pause = SOC_PA_PAUSE_TX; 7639 } else if (an_cap == (PHYMOD_AN_CAP_SYMM_PAUSE | PHYMOD_AN_CAP_ASYM_PAUSE)) { 7640 ability->pause = SOC_PA_PAUSE_RX; 7641 } else if (an_cap == PHYMOD_AN_CAP_SYMM_PAUSE) { 7642 ability->pause = (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX); 7643 } 7644 } 7645 LOG_INFO(BSL_LS_SOC_PHY, 7646 (BSL_META_U(unit, 7647 "phy_82864_ability_remote_get: u=%d p=%d speed(FD)=0x%x pause=0x%x\n"), 7648 unit, port, ability->speed_full_duplex, ability->pause)); 7649 7650 return SOC_E_NONE; 7651 } 7652 7653 STATIC int 7654 phy_82864_per_lane_cl72_enable_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 value) 7655 { 7656 phymod_phy_access_t *pm_phy; 7657 phymod_phy_access_t pm_phy_copy; 7658 soc_phymod_phy_t *p_phy; 7659 uint32 lane_map; 7660 7661 /* locate the desired phy and lane */ 7662 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 7663 7664 /* Make a copy of the phy access and overwrite the desired lane */ 7665 pm_phy = &p_phy->pm_phy; 7666 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 7667 pm_phy_copy.access.lane_mask = lane_map; 7668 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 7669 if(intf == PHY82864_SYS_SIDE) { 7670 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 7671 } 7672 LOG_CLI((BSL_META_U(0,"Tx training: %d Flags:0x%x\n"), value, pm_phy_copy.access.flags)); 7673 7674 SOC_IF_ERROR_RETURN(phymod_phy_cl72_set(&pm_phy_copy, value)); 7675 7676 return(SOC_E_NONE); 7677 } 7678 7679 STATIC int 7680 phy_82864_cl72_enable_set(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 value) 7681 { 7682 phymod_phy_access_t *pm_phy; 7683 int idx; 7684 phymod_phy_access_t pm_phy_copy; 7685 7686 for (idx = 0; idx < pmc->num_phys; idx++) { 7687 pm_phy = &pmc->phy[idx]->pm_phy; 7688 7689 if (pm_phy == NULL) { 7690 return SOC_E_INTERNAL; 7691 } 7692 7693 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 7694 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 7695 7696 if (intf == PHY82864_SYS_SIDE) { 7697 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 7698 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 7699 } 7700 7701 LOG_CLI((BSL_META_U(0,"Tx training: %d Flags:0x%x\n"), value, pm_phy_copy.access.flags)); 7702 7703 SOC_IF_ERROR_RETURN(phymod_phy_cl72_set(&pm_phy_copy, value)); 7704 } 7705 7706 return(SOC_E_NONE); 7707 } 7708 7709 STATIC int 7710 phy_82864_per_lane_cl72_status_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 7711 { 7712 phymod_phy_access_t *pm_phy; 7713 phymod_phy_access_t pm_phy_copy; 7714 phymod_cl72_status_t status; 7715 soc_phymod_phy_t *p_phy; 7716 uint32 lane_map; 7717 7718 /* locate the desired phy and lane */ 7719 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 7720 7721 /* Make a copy of the phy access and overwrite the desired lane */ 7722 pm_phy = &p_phy->pm_phy; 7723 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 7724 pm_phy_copy.access.lane_mask = lane_map; 7725 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 7726 if(intf == PHY82864_SYS_SIDE) { 7727 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 7728 } 7729 7730 sal_memset(&status, 0, sizeof(status)); 7731 SOC_IF_ERROR_RETURN(phymod_phy_cl72_status_get(&pm_phy_copy, &status)); 7732 *value = status.locked; 7733 7734 LOG_CLI((BSL_META_U(0,"Tx training Sts: %d Flags:0x%x\n"), *value, pm_phy_copy.access.flags)); 7735 7736 return(SOC_E_NONE); 7737 } 7738 7739 STATIC int 7740 phy_82864_cl72_status_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 7741 { 7742 phymod_phy_access_t *pm_phy; 7743 int idx; 7744 phymod_phy_access_t pm_phy_copy; 7745 phymod_cl72_status_t status; 7746 7747 for (idx = 0; idx < pmc->num_phys; idx++) { 7748 pm_phy = &pmc->phy[idx]->pm_phy; 7749 7750 if (pm_phy == NULL) { 7751 return SOC_E_INTERNAL; 7752 } 7753 7754 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 7755 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 7756 7757 if (intf == PHY82864_SYS_SIDE) { 7758 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 7759 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 7760 } 7761 7762 sal_memset(&status, 0, sizeof(status)); 7763 SOC_IF_ERROR_RETURN(phymod_phy_cl72_status_get(&pm_phy_copy, &status)); 7764 *value = status.locked; 7765 } 7766 7767 LOG_CLI((BSL_META_U(0,"Tx training Sts: %d Flags:0x%x\n"), *value, pm_phy_copy.access.flags)); 7768 7769 return(SOC_E_NONE); 7770 } 7771 7772 STATIC int 7773 phy_82864_per_lane_cl72_enable_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int lane, uint32 *value) 7774 { 7775 phymod_phy_access_t *pm_phy; 7776 phymod_phy_access_t pm_phy_copy; 7777 soc_phymod_phy_t *p_phy; 7778 uint32 lane_map; 7779 7780 /* locate the desired phy and lane */ 7781 SOC_IF_ERROR_RETURN(_phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 7782 7783 /* Make a copy of the phy access and overwrite the desired lane */ 7784 pm_phy = &p_phy->pm_phy; 7785 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 7786 pm_phy_copy.access.lane_mask = lane_map; 7787 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 7788 if(intf == PHY82864_SYS_SIDE) { 7789 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 7790 } 7791 7792 SOC_IF_ERROR_RETURN(phymod_phy_cl72_get(&pm_phy_copy, value)); 7793 7794 return(SOC_E_NONE); 7795 } 7796 7797 STATIC int 7798 phy_82864_cl72_enable_get(soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, uint32 *value) 7799 { 7800 phymod_phy_access_t *pm_phy; 7801 int idx; 7802 phymod_phy_access_t pm_phy_copy; 7803 7804 for (idx = 0; idx < pmc->num_phys; idx++) { 7805 pm_phy = &pmc->phy[idx]->pm_phy; 7806 7807 if (pm_phy == NULL) { 7808 return SOC_E_INTERNAL; 7809 } 7810 7811 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 7812 pm_phy_copy.access.flags &= ~(1 << INTERFACE_SIDE_SHIFT); 7813 7814 if (intf == PHY82864_SYS_SIDE) { 7815 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 7816 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 7817 } 7818 7819 SOC_IF_ERROR_RETURN(phymod_phy_cl72_get(&pm_phy_copy, value)); 7820 } 7821 7822 return(SOC_E_NONE); 7823 } 7824 7825 STATIC int 7826 phy_82864_link_monitor_set (soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int32 lane, uint32 value) 7827 { 7828 phymod_phy_access_t *pm_phy; 7829 soc_phymod_phy_t *p_phy; 7830 uint32 lane_map = 0; 7831 phymod_phy_access_t pm_phy_copy; 7832 uint32_t link_mon_mode = 0; 7833 7834 intf = (intf == PHY_DIAG_INTF_LINE) ? PHY82864_LINE_SIDE : PHY82864_SYS_SIDE; 7835 7836 if (lane == 0xf) { 7837 /* Get p_phy alone and let lane map be as Phy structure value */ 7838 lane = 1; 7839 SOC_IF_ERROR_RETURN( 7840 _phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 7841 lane = 0xf; 7842 } else { 7843 SOC_IF_ERROR_RETURN( 7844 _phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 7845 } 7846 /* Make a copy of the phy access and overwrite the desired lane */ 7847 pm_phy = &p_phy->pm_phy; 7848 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 7849 if (lane != 0xf) { 7850 pm_phy_copy.access.lane_mask = lane_map; 7851 } 7852 7853 PHY82864_LINE_SIDE(&pm_phy_copy); 7854 if(intf == PHY82864_SYS_SIDE) { 7855 PHY82864_SYSTEM_SIDE(&pm_phy_copy); 7856 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 7857 } 7858 7859 if (value == 0) { 7860 SOC_IF_ERROR_RETURN( 7861 phymod_phy_link_mon_enable_set(&pm_phy_copy, 0 /*When disable Dont care*/, 0)); 7862 } else { 7863 link_mon_mode = value - 1; 7864 SOC_IF_ERROR_RETURN( 7865 phymod_phy_link_mon_enable_set(&pm_phy_copy, link_mon_mode, 1)); 7866 } 7867 7868 return(SOC_E_NONE); 7869 } 7870 7871 STATIC int 7872 phy_82864_link_monitor_status_get (soc_phymod_ctrl_t *pmc, soc_port_t port, int32 intf, int32 lane) 7873 { 7874 phymod_phy_access_t *pm_phy; 7875 soc_phymod_phy_t *p_phy; 7876 uint32 lane_map = 0; 7877 phymod_phy_access_t pm_phy_copy; 7878 uint32_t lock_status = 0, lock_lost_lh = 0, error_count = 0; 7879 7880 intf = (intf == PHY_DIAG_INTF_LINE) ? PHY82864_LINE_SIDE : PHY82864_SYS_SIDE; 7881 7882 if (lane == 0xf) { 7883 /* Get p_phy alone and let lane map be as Phy structure value */ 7884 lane = 1; 7885 SOC_IF_ERROR_RETURN( 7886 _phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 7887 lane = 0xf; 7888 } else { 7889 SOC_IF_ERROR_RETURN( 7890 _phy_82864_find_soc_phy_lane(pmc, port, lane, &p_phy, &lane_map)); 7891 } 7892 /* Make a copy of the phy access and overwrite the desired lane */ 7893 pm_phy = &p_phy->pm_phy; 7894 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 7895 if (lane != 0xf) { 7896 pm_phy_copy.access.lane_mask = lane_map; 7897 } 7898 7899 PHY82864_LINE_SIDE(&pm_phy_copy); 7900 if(intf == PHY82864_SYS_SIDE) { 7901 PHY82864_SYSTEM_SIDE(&pm_phy_copy); 7902 SOC_IF_ERROR_RETURN(_phy82864_sys_side_lane_map_get(pmc->unit, port, &pm_phy_copy)); 7903 } 7904 7905 SOC_IF_ERROR_RETURN( 7906 phymod_phy_link_mon_status_get(&pm_phy_copy, &lock_status, &lock_lost_lh, &error_count)); 7907 7908 if (lane != 0xF) { 7909 LOG_CLI((BSL_META_U(0,"Lane:%d Lock Status:%d lock lost:%d Error count:%d\n "), 7910 lane, lock_status, lock_lost_lh, error_count)); 7911 } else { 7912 LOG_CLI((BSL_META_U(0,"Lane Map:0x%x Lock Status:%d lock lost:%d Error count:%d\n "), 7913 pm_phy_copy.access.lane_mask, lock_status, lock_lost_lh, error_count)); 7914 } 7915 7916 return(SOC_E_NONE); 7917 7918 } 7919 7920 STATIC int 7921 phy_82864_intr_enable_get(phy_ctrl_t *pc, int32 intf, uint32 *value) 7922 { 7923 phymod_phy_access_t *pm_phy; 7924 int idx; 7925 phymod_phy_access_t pm_phy_copy; 7926 soc_phymod_ctrl_t *pmc; 7927 pmc = &pc->phymod_ctrl; 7928 7929 *value = 0; 7930 for (idx = 0; idx < pmc->num_phys; idx++) { 7931 pm_phy = &pmc->phy[idx]->pm_phy; 7932 7933 if (pm_phy == NULL) { 7934 return SOC_E_INTERNAL; 7935 } 7936 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 7937 if(intf == PHY82864_SYS_SIDE) { 7938 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 7939 } 7940 SOC_IF_ERROR_RETURN( 7941 phymod_phy_intr_enable_get(&pm_phy_copy, value)); 7942 } 7943 7944 return(SOC_E_NONE); 7945 } 7946 7947 7948 STATIC int 7949 phy_82864_intr_status_get(phy_ctrl_t *pc, int32 intf, uint32 *value) 7950 { 7951 phymod_phy_access_t *pm_phy; 7952 int idx; 7953 phymod_phy_access_t pm_phy_copy; 7954 soc_phymod_ctrl_t *pmc; 7955 pmc = &pc->phymod_ctrl; 7956 7957 *value = 0; 7958 for (idx = 0; idx < pmc->num_phys; idx++) { 7959 pm_phy = &pmc->phy[idx]->pm_phy; 7960 7961 if (pm_phy == NULL) { 7962 return SOC_E_INTERNAL; 7963 } 7964 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 7965 if(intf == PHY82864_SYS_SIDE) { 7966 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 7967 } 7968 SOC_IF_ERROR_RETURN( 7969 phymod_phy_intr_status_get(&pm_phy_copy, value)); 7970 SOC_IF_ERROR_RETURN( 7971 phymod_phy_intr_status_clear(&pm_phy_copy, *value)); 7972 } 7973 7974 return(SOC_E_NONE); 7975 } 7976 7977 /* 7978 * phy_82864_gpio_config_get 7979 */ 7980 STATIC int 7981 phy_82864_gpio_config_get(phy_ctrl_t *pc, uint32 *value) 7982 { 7983 phymod_phy_access_t *pm_phy; 7984 phymod_phy_access_t pm_phy_copy; 7985 phymod_gpio_mode_t gpio_mode; 7986 int gpio_pin_no = 0; 7987 soc_phymod_ctrl_t *pmc; 7988 pmc = &pc->phymod_ctrl; 7989 *value = 0; 7990 7991 /* just take the value from the first phy */ 7992 if (pmc->phy[0] == NULL) { 7993 return SOC_E_INTERNAL; 7994 } 7995 pm_phy = &pmc->phy[0]->pm_phy; 7996 7997 if (pm_phy == NULL) { 7998 return SOC_E_INTERNAL; 7999 } 8000 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 8001 8002 for (gpio_pin_no = 0; gpio_pin_no < 4; gpio_pin_no++) { 8003 SOC_IF_ERROR_RETURN(phymod_phy_gpio_config_get(&pm_phy_copy, gpio_pin_no, &gpio_mode)); 8004 *value |= (gpio_mode << (4 * gpio_pin_no)); 8005 } 8006 return(SOC_E_NONE); 8007 } 8008 /* 8009 * phy_82864_gpio_value_get 8010 */ 8011 STATIC int 8012 phy_82864_gpio_value_get(phy_ctrl_t *pc, uint32 *value) 8013 { 8014 phymod_phy_access_t *pm_phy; 8015 phymod_phy_access_t pm_phy_copy; 8016 int gpio_pin_no = 0; 8017 int pin_value = 0; 8018 soc_phymod_ctrl_t *pmc; 8019 pmc = &pc->phymod_ctrl; 8020 *value = 0; 8021 8022 /* just take the value from the first phy */ 8023 if (pmc->phy[0] == NULL) { 8024 return SOC_E_INTERNAL; 8025 } 8026 pm_phy = &pmc->phy[0]->pm_phy; 8027 8028 if (pm_phy == NULL) { 8029 return SOC_E_INTERNAL; 8030 } 8031 8032 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 8033 8034 for (gpio_pin_no = 0; gpio_pin_no < 4; gpio_pin_no++) { 8035 SOC_IF_ERROR_RETURN(phymod_phy_gpio_pin_value_get(&pm_phy_copy, gpio_pin_no, &pin_value)); 8036 *value |= (pin_value << (4 * gpio_pin_no)); 8037 } 8038 8039 return(SOC_E_NONE); 8040 } 8041 8042 STATIC int 8043 phy_82864_intr_enable_set(phy_ctrl_t *pc, int32 intf, uint32 value) 8044 { 8045 phymod_phy_access_t *pm_phy; 8046 int idx; 8047 phymod_phy_access_t pm_phy_copy; 8048 soc_phymod_ctrl_t *pmc; 8049 pmc = &pc->phymod_ctrl; 8050 for (idx = 0; idx < pmc->num_phys; idx++) { 8051 pm_phy = &pmc->phy[idx]->pm_phy; 8052 8053 if (pm_phy == NULL) { 8054 return SOC_E_INTERNAL; 8055 } 8056 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 8057 if(intf == PHY82864_SYS_SIDE) { 8058 pm_phy_copy.access.flags |= (1 << INTERFACE_SIDE_SHIFT); 8059 } 8060 SOC_IF_ERROR_RETURN( 8061 phymod_phy_intr_enable_set(&pm_phy_copy, value)); 8062 } 8063 8064 return(SOC_E_NONE); 8065 } 8066 8067 /* 8068 * phy_82864_gpio_config_set 8069 */ 8070 STATIC int 8071 phy_82864_gpio_config_set(phy_ctrl_t *pc, uint32 value) 8072 { 8073 phymod_phy_access_t *pm_phy; 8074 int idx; 8075 phymod_phy_access_t pm_phy_copy; 8076 int gpio_mode = 0; 8077 int gpio_pin_no = 0; 8078 soc_phymod_ctrl_t *pmc; 8079 pmc = &pc->phymod_ctrl; 8080 8081 /* loop through all cores */ 8082 for (idx = 0; idx < pmc->num_phys; idx++) { 8083 pm_phy = &pmc->phy[idx]->pm_phy; 8084 8085 if (pm_phy == NULL) { 8086 return SOC_E_INTERNAL; 8087 } 8088 8089 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 8090 8091 for (gpio_pin_no = 0; gpio_pin_no < 4; gpio_pin_no++) { 8092 gpio_mode = (value >> (4 * gpio_pin_no)) & 0xF; 8093 SOC_IF_ERROR_RETURN(phymod_phy_gpio_config_set(&pm_phy_copy, gpio_pin_no, (phymod_gpio_mode_t)gpio_mode)); 8094 } 8095 } 8096 return(SOC_E_NONE); 8097 } 8098 8099 /* 8100 * phy_82864_gpio_value_set 8101 */ 8102 STATIC int 8103 phy_82864_gpio_value_set(phy_ctrl_t *pc, uint32 value) 8104 { 8105 phymod_phy_access_t *pm_phy; 8106 int idx; 8107 phymod_phy_access_t pm_phy_copy; 8108 int pin_value = 0; 8109 int gpio_pin_no = 0; 8110 soc_phymod_ctrl_t *pmc; 8111 pmc = &pc->phymod_ctrl; 8112 8113 /* loop through all cores */ 8114 for (idx = 0; idx < pmc->num_phys; idx++) { 8115 pm_phy = &pmc->phy[idx]->pm_phy; 8116 8117 if (pm_phy == NULL) { 8118 return SOC_E_INTERNAL; 8119 } 8120 8121 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 8122 8123 for (gpio_pin_no = 0; gpio_pin_no < 4; gpio_pin_no++) { 8124 pin_value = (value >> (4 * gpio_pin_no)) & 0xF; 8125 SOC_IF_ERROR_RETURN(phymod_phy_gpio_pin_value_set(&pm_phy_copy, gpio_pin_no, pin_value)); 8126 } 8127 } 8128 return(SOC_E_NONE); 8129 } 8130 8131 /* 8132 * Variable: 8133 * phy82864_drv 8134 * Purpose: 8135 * Phy Driver for phy82864 8136 */ 8137 phy_driver_t phy82864_drv = { 8138 /* .drv_name = */ "PHY82864 PHYMOD PHY Driver", 8139 /* .pd_init = */ phy_82864_init, 8140 /* .pd_reset = */ phy_82864_core_reset, 8141 /* .pd_link_get = */ phy_82864_link_get, 8142 /* .pd_enable_set = */ phy_82864_enable_set, 8143 /* .pd_enable_get = */ phy_82864_enable_get, 8144 /* .pd_duplex_set = */ phy_null_set, 8145 /* .pd_duplex_get = */ phy82864_duplex_get, 8146 /* .pd_speed_set = */ phy82864_speed_set, 8147 /* .pd_speed_get = */ phy82864_speed_get, 8148 /* .pd_master_set = */ phy_null_set, 8149 /* .pd_master_get = */ phy_null_zero_get, 8150 /* .pd_an_set = */ phy_82864_an_set, 8151 /* .pd_an_get = */ phy_82864_an_get, 8152 /* .pd_adv_local_set = */ NULL, /* Deprecated */ 8153 /* .pd_adv_local_get = */ NULL, /* Deprecated */ 8154 /* .pd_adv_remote_get = */ NULL, /* Deprecated */ 8155 /* .pd_lb_set = */ phy_82864_lb_set, 8156 /* .pd_lb_get = */ phy82864_lb_get, 8157 /* .pd_interface_set = */ phy82864_interface_set, 8158 /* .pd_interface_get = */ phy82864_interface_get, 8159 /* .pd_ability = */ NULL, /* Deprecated */ 8160 /* .pd_linkup_evt = */ NULL, 8161 /* .pd_linkdn_evt = */ NULL, 8162 /* .pd_mdix_set = */ phy_null_mdix_set, 8163 /* .pd_mdix_get = */ phy_null_mdix_get, 8164 /* .pd_mdix_status_get = */ phy_null_mdix_status_get, 8165 /* .pd_medium_config_set = */ NULL, 8166 /* .pd_medium_config_get = */ NULL, 8167 /* .pd_medium_get = */ phy_null_medium_get, 8168 /* .pd_cable_diag = */ NULL, 8169 /* .pd_link_change = */ NULL, 8170 /* .pd_control_set = */ phy_82864_control_set, 8171 /* .pd_control_get = */ phy_82864_control_get, 8172 /* .pd_reg_read = */ phy82864_reg_read, 8173 /* .pd_reg_write = */ phy82864_reg_write, 8174 /* .pd_reg_modify = */ phy82864_reg_modify, 8175 /* .pd_notify = */ NULL, 8176 /* .pd_probe = */ phy82864_probe, 8177 /* .pd_ability_advert_set = */ phy_82864_ability_advert_set, 8178 /* .pd_ability_advert_get = */ phy_82864_ability_advert_get, 8179 /* .pd_ability_remote_get = */ phy_82864_ability_remote_get, 8180 /* .pd_ability_local_get = */ phy_82864_ability_local_get, 8181 /* .pd_firmware_set = */ phy_82864_firmware_set, 8182 /* .pd_timesync_config_set = */ NULL, 8183 /* .pd_timesync_config_get = */ NULL, 8184 /* .pd_timesync_control_set = */ NULL, 8185 /* .pd_timesync_control_set = */ NULL, 8186 /* .pd_diag_ctrl = */ phy_82864_diag_ctrl, 8187 /* .pd_lane_control_set = */ phy_82864_per_lane_control_set, 8188 /* .pd_lane_control_get = */ phy_82864_per_lane_control_get 8189 }; 8190 8191 #else 8192 int _phy82864_not_empty; 8193 #endif /* INCLUDE_PHY_82864 */ 8194