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