viper.c (159608B)
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: viper.c 8 * Purpose: Support Broadcom 28nm XGXS/SGMIIPLUS2 internal SerDes 9 */ 10 11 /* 12 * This module implements an NTSW SDK Phy driver for the VIPER Serdes. 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 * VIPER. 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 .phy_viper_per_lane_control_set and 36 * .phy_viper_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 * viper_config_t 60 * Driver specific data. This structure is used by viper to hold 61 * logical port specific working storage. 62 * 63 * soc_phymod_ctrl_t 64 * PHYMOD drivers. Resides in phy_ctrl_t specifies how many cores 65 * are in this phy and contains an array of pointers to 66 * soc_phymod_phy_t structures, which define a PHYMOD PHY. 67 * 68 * soc_phymod_phy_t 69 * This structure contains a pointer to phymod_phy_access_t and a 70 * pointer to the associated soc_phymod_core_t. Instances if this 71 * structure are created during device probe/init and are maintained 72 * by the SOC. 73 * 74 * soc_phymod_core_t 75 * This structure contains per-core information. Multiple PHYMOD 76 * PHYS can point to a single core. 77 * 78 * phymod_phy_access_t 79 * This structure contains information about how to read/write PHY 80 * registers. A required parameter for PHYMOD PHY APIs 81 * 82 * phymod_core_access_t 83 * This structure contains information about how to read/write PHY 84 * registers. A required parameter for PHYMOD core APIs. 85 */ 86 87 #include <shared/bsl.h> 88 89 #include <sal/types.h> 90 #include <sal/types.h> 91 #include <sal/core/spl.h> 92 #include <shared/bsl.h> 93 #include <soc/drv.h> 94 #include <soc/debug.h> 95 #include <soc/error.h> 96 #include <soc/phyreg.h> 97 #include <soc/port_ability.h> 98 #include <soc/phy.h> 99 #include <soc/phy/phyctrl.h> 100 #include <soc/phy/drv.h> 101 #include <soc/phy/phymod_ids.h> 102 103 #include "phydefs.h" /* Must include before other phy related includes */ 104 105 #include "phyconfig.h" /* Must include before other phy related includes */ 106 #include "phyident.h" 107 #include "phyreg.h" 108 #include "phynull.h" 109 #include "xgxs.h" 110 #include "serdesid.h" 111 112 #if defined(INCLUDE_XGXS_VIPER) 113 114 #include <phymod/phymod.h> 115 #include <phymod/phymod_debug.h> 116 #include <phymod/phymod_diagnostics.h> 117 #include <phymod/phymod_util.h> 118 #include <phymod/chip/bcmi_viper_xgxs_sym.h> 119 #include <phymod/chip/bcmi_sgmiip2x4_serdes_sym.h> 120 #include <phymod/chip/viper.h> 121 122 123 #include "../../../libs/phymod/chip/viper/tier1/viper_err_code.h" 124 125 #define NUM_LANES 4 /* num of lanes per core */ 126 #define MAX_NUM_LANES 4 /* max num of lanes per port */ 127 #define VIPER_NO_CFG_VALUE (-1) 128 129 #define VIPERX 1 130 131 typedef struct viper_speed_config_s { 132 uint32 port_refclk_int; 133 int speed; 134 int port_num_lanes; 135 int scrambler_en; 136 uint32 line_interface; 137 int fiber_pref; 138 int pll_divider_req; 139 } viper_speed_config_t; 140 141 #define NUM_PATTERN_DATA_INTS 8 142 typedef struct viper_pattern_s { 143 uint32 pattern_data[NUM_PATTERN_DATA_INTS]; 144 uint32 pattern_length; 145 } viper_pattern_t; 146 147 #define VIPER_LANE_NAME_LEN 30 148 149 typedef struct { 150 uint16 serdes_id0; 151 char name[VIPER_LANE_NAME_LEN]; 152 } viper_dev_info_t; 153 154 /* index to TX drive configuration table for each VCO setting. 155 */ 156 typedef enum txdrv_inxs { 157 TXDRV_XAUI_INX, /* 10G XAUI mode */ 158 TXDRV_SGMII_INX, /* 1G SGMII mode */ 159 TXDRV_AN_INX, /* a common entry for autoneg mode */ 160 TXDRV_DFT_INX, /* temp for any missing speed modes */ 161 TXDRV_LAST_INX /* always last */ 162 } TXDRV_INXS_t; 163 164 #define TXDRV_ENTRY_NUM (TXDRV_LAST_INX) 165 #define MAX_NUM_LANES 4 166 167 /* 168 Config - per logical port 169 */ 170 typedef struct { 171 phymod_polarity_t phy_polarity_config; 172 phymod_phy_reset_t phy_reset_config; 173 viper_pattern_t pattern; 174 viper_speed_config_t speed_config; 175 176 int fiber_pref; /* spn_SERDES_FIBER_PREF */ 177 int cl37an; /* spn_PHY_AN_C37 */ 178 int auto_medium; 179 viper_dev_info_t info; /*serdes id info */ 180 phymod_tx_t tx_drive[TXDRV_ENTRY_NUM]; 181 phymod_tx_t ln_txparam[MAX_NUM_LANES] ; 182 183 } viper_config_t; 184 185 186 #define VIPER_IF_NULL (1 << SOC_PORT_IF_NULL) 187 #define VIPER_IF_SR (1 << SOC_PORT_IF_SR) 188 #define VIPER_IF_KR (1 << SOC_PORT_IF_KR) 189 #define VIPER_IF_KR4 (1 << SOC_PORT_IF_KR4) 190 #define VIPER_IF_CR (1 << SOC_PORT_IF_CR) 191 #define VIPER_IF_CR4 (1 << SOC_PORT_IF_CR4) 192 #define VIPER_IF_XAUI (1 << SOC_PORT_IF_XAUI) 193 194 #define VIPER_CL37_W_1G 3 195 #define VIPER_CL37_WO_BAM 2 196 #define VIPER_CL37_W_BAM 1 197 #define VIPER_CL37_DISABLE 0 198 199 STATIC int phy_viper_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability); 200 STATIC int phy_viper_ability_advert_set(int unit, soc_port_t port, 201 soc_port_ability_t *ability); 202 STATIC int _phy_viper_enable_set(int unit, soc_port_t port, int enable); 203 204 /* 205 * Function: 206 * _viper_reg_read 207 * Doc: 208 * register read operations 209 * Parameters: 210 * unit - (IN) unit number 211 * core_addr - (IN) core address 212 * reg_addr - (IN) address to read 213 * val - (OUT) read value 214 */ 215 STATIC int 216 _viper_reg_read(void* user_acc, uint32_t core_addr, uint32_t reg_addr, uint32_t *val) 217 { 218 uint16 data16; 219 int rv; 220 soc_phymod_core_t *core = (soc_phymod_core_t *)user_acc; 221 222 rv = core->read(core->unit, core_addr, reg_addr, &data16); 223 *val = data16; 224 PHYMOD_VDBG(VIPER_DBG_REGACC,NULL,("%-22s: core_addr: 0x%08x reg_addr: 0x%08x, data: 0x%04x\n", __func__, core_addr, reg_addr, *val )); 225 return rv; 226 } 227 228 /* 229 * Function: 230 * _viper_reg_write 231 * Doc: 232 * register write operations 233 * Parameters: 234 * unit - (IN) unit number 235 * core_addr - (IN) core address 236 * reg_addr - (IN) address to write 237 * val - (IN) write value 238 */ 239 STATIC int 240 _viper_reg_write(void* user_acc, uint32_t core_addr, uint32_t reg_addr, uint32_t val) 241 { 242 soc_phymod_core_t *core = (soc_phymod_core_t *)user_acc; 243 uint16 data16 = (uint16)val; 244 uint16 mask = (uint16)(val >> 16); 245 246 if (mask) { 247 if (core->wrmask) { 248 return core->wrmask(core->unit, core_addr, reg_addr, data16, mask); 249 } 250 (void)core->read(core->unit, core_addr, reg_addr, &data16); 251 data16 &= ~mask; 252 data16 |= (val & mask); 253 } 254 PHYMOD_VDBG(VIPER_DBG_REGACC,NULL,("-22%s: core_addr: 0x%08x reg_addr: 0x%08x, data: 0x%04x\n", __func__, core_addr, reg_addr, val )); 255 256 return core->write(core->unit, core_addr, reg_addr, data16); 257 } 258 259 260 261 #define IS_DUAL_LANE_PORT(_pc) ((_pc)->phy_mode == PHYCTRL_DUAL_LANE_PORT) 262 #define IND_LANE_MODE(_pc) ((_pc)->phy_mode == PHYCTRL_ONE_LANE_PORT) 263 #define MAIN0_SERDESID_REV_LETTER_SHIFT (14) 264 #define MAIN0_SERDESID_REV_NUMBER_SHIFT (11) 265 266 #define MODEL_MASK 0x3f 267 #define MODEL_XGXS_10G_028 0x8 268 #define MODEL_SGMIIPLUS2_X4 0xf 269 /* 270 * Function: 271 * viper_show_serdes_info 272 * Purpose: 273 * Show Serdes information. 274 * Parameters: 275 * pc - (IN) phyctrl oject 276 * pInfo - (IN) device info object 277 * rev_id - (IN) serdes revid 278 * Returns: 279 * SOC_E_NONE 280 */ 281 STATIC int 282 viper_show_serdes_info(phy_ctrl_t *pc, viper_dev_info_t *pInfo, phymod_core_info_t *core_info) 283 { 284 uint32_t serdes_id0, len; 285 286 pInfo->serdes_id0 = core_info->serdes_id ; 287 288 /* This is Viper device */ 289 serdes_id0 = pInfo->serdes_id0; 290 if ((serdes_id0 & MODEL_MASK) == MODEL_XGXS_10G_028) { 291 sal_strncpy(pInfo->name,"VIPERX-", sal_strlen("VIPERX-")); 292 } else if ((serdes_id0 & MODEL_MASK) == MODEL_SGMIIPLUS2_X4){ 293 sal_strncpy(pInfo->name,"VIPERG-", sal_strlen("VIPERG-")); 294 } 295 len = sal_strlen(pInfo->name); 296 /* add rev letter */ 297 pInfo->name[len++] = 'A' + ((serdes_id0 >> 298 MAIN0_SERDESID_REV_LETTER_SHIFT) & 0x3); 299 /* add rev number */ 300 pInfo->name[len++] = '0' + ((serdes_id0 >> 301 MAIN0_SERDESID_REV_NUMBER_SHIFT) & 0x7); 302 pInfo->name[len++] = '/'; 303 pInfo->name[len++] = (pc->chip_num / 10) % 10 + '0'; 304 pInfo->name[len++] = pc->chip_num % 10 + '0'; 305 pInfo->name[len++] = '/'; 306 307 /* phy_mode: 0 single port mode, port uses all four lanes 308 * 1 dual port mode, port uses 2 lane 309 * 2 quad port mode, port uses 1 lane 310 */ 311 if (IS_DUAL_LANE_PORT(pc)) { /* dual-xgxs mode */ 312 if (pc->lane_num < 2) { /* the first dual-xgxs port */ 313 pInfo->name[len++] = '0'; 314 pInfo->name[len++] = '-'; 315 pInfo->name[len++] = '1'; 316 } else { 317 pInfo->name[len++] = '2'; 318 pInfo->name[len++] = '-'; 319 pInfo->name[len++] = '3'; 320 } 321 } else if (pc->phy_mode == PHYCTRL_ONE_LANE_PORT) { 322 pInfo->name[len++] = pc->lane_num + '0'; 323 } else { 324 pInfo->name[len++] = '4'; 325 } 326 pInfo->name[len] = 0; /* string terminator */ 327 328 if (len > VIPER_LANE_NAME_LEN) { 329 LOG_ERROR(BSL_LS_SOC_COMMON, 330 (BSL_META("VIPER info string length %d exceeds max length 0x%x: u=%d p=%d\n"), 331 len,VIPER_LANE_NAME_LEN, pc->unit, pc->port)); 332 return SOC_E_MEMORY; 333 } 334 return SOC_E_NONE; 335 } 336 337 /* 338 * Function: 339 * viper_speed_to_interface_config_get 340 * Purpose: 341 * Convert speed to interface_config struct 342 * Parameters: 343 * unit - BCM unit number. 344 * port - Port number. 345 * speed - speed to convert 346 * interface_config - output interface config struct 347 * Returns: 348 * SOC_E_NONE 349 */ 350 STATIC int 351 viper_speed_to_interface_config_get(const phymod_phy_access_t *phy, viper_speed_config_t* speed_config, phymod_phy_inf_config_t* interface_config, TXDRV_INXS_t* tx_index) 352 { 353 int fiber_pref; 354 fiber_pref = speed_config->fiber_pref; 355 356 SOC_IF_ERROR_RETURN(phymod_phy_inf_config_t_init(interface_config)); 357 358 interface_config->interface_modes = 0; 359 interface_config->data_rate = speed_config->speed; 360 interface_config->pll_divider_req = speed_config->pll_divider_req ; 361 362 *tx_index = TXDRV_DFT_INX; 363 364 if (fiber_pref) { 365 PHYMOD_INTF_MODES_FIBER_SET(interface_config); 366 } 367 switch (speed_config->speed) { 368 case 10: 369 interface_config->interface_type = phymodInterfaceSGMII; 370 *tx_index = TXDRV_DFT_INX; 371 break; 372 case 100: 373 case 1000: 374 if (speed_config->fiber_pref) { 375 interface_config->interface_type = phymodInterface1000X; 376 *tx_index = TXDRV_DFT_INX; 377 } else { 378 interface_config->interface_type = phymodInterfaceSGMII; 379 *tx_index = TXDRV_SGMII_INX; 380 } 381 break; 382 case 2500: 383 interface_config->interface_type = phymodInterface1000X; 384 *tx_index = TXDRV_DFT_INX; 385 break; 386 case 10000: 387 interface_config->interface_type = phymodInterfaceXAUI; 388 *tx_index = TXDRV_XAUI_INX; 389 break; 390 default: 391 return SOC_E_PARAM; 392 } 393 return SOC_E_NONE; 394 } 395 396 397 /* 398 * Function: 399 * viper_config_init 400 * Purpose: 401 * Determine phy configuration data for purposes of PHYMOD initialization. 402 * 403 * A side effect of this procedure is to save some per-logical port 404 * information in (viper_cfg_t *) &pc->driver_data; 405 * 406 * Parameters: 407 * unit - BCM unit number. 408 * port - Port number. 409 * logical_lane_offset - starting logical lane number 410 * Returns: 411 * SOC_E_NONE 412 */ 413 414 STATIC int 415 viper_config_init(int unit, soc_port_t port, const phymod_phy_access_t* phy, 416 int logical_lane_offset, 417 phymod_core_init_config_t *core_init_config, 418 phymod_phy_init_config_t *pm_phy_init_config) 419 { 420 phy_ctrl_t *pc; 421 viper_speed_config_t *speed_config; 422 viper_config_t *pCfg; 423 phymod_tx_t *p_tx; 424 int port_refclk_int; 425 int port_num_lanes; 426 int core_num; 427 int phy_num_lanes; 428 int lane_map_rx = 0, lane_map_tx = 0; 429 int i; 430 int fiber_pref = 0; 431 uint32_t preemphasis; 432 TXDRV_INXS_t tx_index = TXDRV_DFT_INX; 433 434 pc = INT_PHY_SW_STATE(unit, port); 435 if (pc == NULL) { 436 return SOC_E_INTERNAL; 437 } 438 pCfg = (viper_config_t *) pc->driver_data; 439 440 /* extract data from SOC_INFO */ 441 port_refclk_int = SOC_INFO(unit).port_refclk_int[port]; 442 port_refclk_int = 156; 443 port_refclk_int = soc_property_port_get(unit, port,spn_XGXS_LCPLL_XTAL_REFCLK, port_refclk_int); 444 port_num_lanes = SOC_INFO(unit).port_num_lanes[port]; 445 446 /* figure out how many lanes are in this phy */ 447 core_num = (port / 4); 448 phy_num_lanes = port_num_lanes - logical_lane_offset; 449 if (phy_num_lanes > MAX_NUM_LANES) { 450 phy_num_lanes = MAX_NUM_LANES; 451 } 452 453 /* 454 CORE configuration 455 */ 456 phymod_core_init_config_t_init(core_init_config); 457 458 core_init_config->lane_map.num_of_lanes = NUM_LANES; 459 core_init_config->flags = PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY; 460 lane_map_rx = soc_property_port_get(unit, port, 461 spn_XGXS_RX_LANE_MAP, 0x3210); 462 463 for (i=0; i<NUM_LANES; i++) { 464 core_init_config->lane_map.lane_map_rx[i] = (lane_map_rx >> (i * 4 /* 4 bit per lane */)) & 0xf; 465 } 466 467 lane_map_tx = soc_property_port_get(unit, port, 468 spn_XGXS_TX_LANE_MAP, 0x3210); 469 for (i=0; i<NUM_LANES; i++) { 470 core_init_config->lane_map.lane_map_tx[i] = (lane_map_tx >> (i * 4 /*4 bit per lane*/)) & 0xf; 471 } 472 /* next get the tx/rx polairty info */ 473 core_init_config->polarity_map.tx_polarity = soc_property_port_get(unit, port, 474 spn_PHY_XAUI_TX_POLARITY_FLIP, 0); 475 core_init_config->polarity_map.rx_polarity = soc_property_port_get(unit, port, 476 spn_PHY_XAUI_RX_POLARITY_FLIP, 0); 477 speed_config = &(pCfg->speed_config); 478 speed_config->port_refclk_int = port_refclk_int; 479 speed_config->speed = soc_property_port_get(unit, port, spn_PORT_INIT_SPEED, pc->speed_max); 480 speed_config->port_num_lanes = phy_num_lanes; 481 speed_config->line_interface = soc_property_port_get(unit, port, spn_SERDES_IF_TYPE, 0); 482 speed_config->fiber_pref = soc_property_port_get(unit, port, spn_SERDES_FIBER_PREF, speed_config->fiber_pref); 483 speed_config->pll_divider_req = soc_property_port_get(unit, port, spn_XGXS_PHY_PLL_DIVIDER, 0); 484 485 SOC_IF_ERROR_RETURN 486 (viper_speed_to_interface_config_get(phy, speed_config, &(core_init_config->interface), &tx_index)); 487 488 /* 489 PHY configuration 490 */ 491 for (i=0; i<MAX_NUM_LANES; i++) { 492 pCfg->ln_txparam[i+logical_lane_offset].main = -1 ; 493 pCfg->ln_txparam[i+logical_lane_offset].post = -1 ; 494 } 495 496 for (i = 0; i < TXDRV_ENTRY_NUM; i++) { 497 p_tx = &pCfg->tx_drive[i]; 498 SOC_IF_ERROR_RETURN(phymod_tx_t_init(p_tx)); 499 } 500 /* set the default tx parameters */ 501 p_tx = &pCfg->tx_drive[TXDRV_DFT_INX]; 502 p_tx->main = 0x32; 503 p_tx->post = 0; 504 505 p_tx = &pCfg->tx_drive[TXDRV_AN_INX]; 506 p_tx->main = 0x32; 507 p_tx->post = 0x0; 508 509 p_tx = &pCfg->tx_drive[TXDRV_XAUI_INX]; 510 p_tx->main = 0x32; 511 p_tx->post = 0x0; 512 513 phymod_phy_init_config_t_init(pm_phy_init_config); 514 for (i = 0; i < 4; i++) { 515 pm_phy_init_config->tx[i].main = pCfg->tx_drive[tx_index].main; 516 pm_phy_init_config->tx[i].post = pCfg->tx_drive[tx_index].post; 517 } 518 519 pm_phy_init_config->polarity.rx_polarity 520 = soc_property_port_get(unit, port, 521 spn_PHY_XAUI_RX_POLARITY_FLIP, 522 pm_phy_init_config->polarity.rx_polarity); 523 pm_phy_init_config->polarity.tx_polarity 524 = soc_property_port_get(unit, port, 525 spn_PHY_XAUI_TX_POLARITY_FLIP, 526 pm_phy_init_config->polarity.tx_polarity); 527 pm_phy_init_config->rx_los.rx_los_en 528 = soc_property_port_get(unit, port, 529 spn_SERDES_RX_LOS, 0); 530 pm_phy_init_config->rx_los.rx_los_invert_en 531 = soc_property_port_get(unit, port, 532 spn_SERDES_RX_LOS_INVERT, 0); 533 534 pm_phy_init_config->rx_swing = soc_property_port_get(unit, port, spn_SERDES_RX_LARGE_SWING, 0); 535 536 for (i = 0; i < MAX_NUM_LANES; i++) { 537 /*first get the preemphasis */ 538 preemphasis = 0; 539 preemphasis = soc_property_port_suffix_num_get(unit, port, 540 i + core_num * 4, spn_SERDES_PREEMPHASIS, 541 "lane", preemphasis); 542 pm_phy_init_config->tx[i].main = (preemphasis & 0xff00) >> 8; 543 pm_phy_init_config->tx[i].post = (preemphasis & 0xff0000) >> 16; 544 } 545 546 547 pm_phy_init_config->an_en = TRUE; 548 549 /* By default enable cl37 */ 550 pCfg->cl37an = TRUE; 551 552 pCfg->cl37an = soc_property_port_get(unit, port, 553 spn_PHY_AN_C37, pCfg->cl37an); /* no L: C37, not CL37 */ 554 555 /* 556 phy_ctrl_t configuration (LOGICAL PORT BASED) 557 Only do this once, for the first core of the logical port 558 */ 559 if (core_num == 0) { 560 /* phy_mode, PHYCTRL_MDIO_ADDR_SHARE, PHY_FLAGS_INDEPENDENT_LANE */ 561 if (port_num_lanes == 4) { 562 pc->phy_mode = PHYCTRL_QUAD_LANE_PORT; 563 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_INDEPENDENT_LANE); 564 } else if (port_num_lanes == 2) { 565 pc->phy_mode = PHYCTRL_DUAL_LANE_PORT; 566 pc->flags |= PHYCTRL_MDIO_ADDR_SHARE; 567 PHY_FLAGS_SET(unit, port, PHY_FLAGS_INDEPENDENT_LANE); 568 } else if (port_num_lanes == 1) { 569 pc->phy_mode = PHYCTRL_ONE_LANE_PORT; 570 pc->flags |= PHYCTRL_MDIO_ADDR_SHARE; 571 PHY_FLAGS_SET(unit, port, PHY_FLAGS_INDEPENDENT_LANE); 572 } 573 /* PHY_FLAGS_FIBER */ 574 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_FIBER); 575 if (!PHY_EXTERNAL_MODE(unit, port)) { 576 577 fiber_pref = FALSE; 578 if (PHY_FIBER_MODE(unit, port) || 579 (!PHY_INDEPENDENT_LANE_MODE(unit, port)) || 580 (pc->speed_max >= 10000)) { 581 fiber_pref = TRUE; 582 } 583 fiber_pref = soc_property_port_get(unit, port, 584 spn_SERDES_FIBER_PREF, fiber_pref); 585 if (fiber_pref) { 586 PHY_FLAGS_SET(unit, port, PHY_FLAGS_FIBER); 587 } 588 } 589 590 591 PHY_FLAGS_SET(unit,port,PHY_FLAGS_SERVICE_INT_PHY_LINK_GET); 592 593 } 594 595 return SOC_E_NONE; 596 } 597 598 STATIC int 599 _viper_device_print(soc_phymod_core_t *core) 600 { 601 phymod_core_access_t *pm_core; 602 phymod_access_t *pm_acc; 603 604 pm_core = &core->pm_core; 605 pm_acc = &pm_core->access; 606 607 if(core) { 608 PHYMOD_VDBG(VIPER_DBG_MEM, pm_acc, ("ref_cnt=%0d core_p=%p\n", core->ref_cnt, (void *)core)) ; 609 } else { 610 PHYMOD_VDBG(VIPER_DBG_MEM, pm_acc, ("Error: no defined phymod core.\n")); 611 } 612 return SOC_E_NONE; 613 } 614 615 /* 616 * Function: 617 * phy_viper_init 618 * 619 * An SDK "phy" is a logical port, which can consist of from 1-10 lanes, 620 * (A phy with more than 4 lanes requires more than one core). 621 * Per-logical port information is saved in (viper_config_t *) &pc->driver_data. 622 * An SDK phy is implemented as one or more PHYMOD "phy"s. 623 * 624 * A PHYMOD "phy" resides completely within a single core, which can be 625 * from 1 to 4 lanes. 626 * Per-phymod phy information is kept in (soc_phymod_ctrl_t) *pc->phymod_ctrl 627 * A phymod phy points to its core. Up to 4 phymod phys can be on a single core 628 * 629 * Purpose: 630 * Initialize a viper phy 631 * Parameters: 632 * unit - BCM unit number. 633 * port - Port number. 634 * Returns: 635 * SOC_E_NONE 636 */ 637 STATIC int 638 phy_viper_init(int unit, soc_port_t port) 639 { 640 phy_ctrl_t *pc; 641 soc_phymod_ctrl_t *pmc; 642 soc_phymod_phy_t *phy = NULL; 643 soc_phymod_core_t *core; 644 viper_config_t *pCfg; 645 viper_speed_config_t *speed_config; 646 viper_dev_info_t *pInfo; 647 soc_phy_info_t *pi; 648 phymod_phy_inf_config_t interface_config; 649 phymod_core_status_t core_status; 650 phymod_core_info_t core_info; 651 int idx; 652 int logical_lane_offset; 653 soc_port_ability_t ability; 654 TXDRV_INXS_t tx_index = TXDRV_DFT_INX; 655 656 657 pc = INT_PHY_SW_STATE(unit, port); 658 if (pc == NULL) { 659 return SOC_E_INTERNAL; 660 } 661 pc->driver_data = (void*)(pc+1); 662 pmc = &pc->phymod_ctrl; 663 pCfg = (viper_config_t *) pc->driver_data; 664 pInfo = &pCfg->info; 665 666 sal_memset(pCfg, 0, sizeof(*pCfg)); 667 speed_config = &(pCfg->speed_config); 668 669 sal_memset(&ability, 0, sizeof(ability)); 670 671 /* Loop through all phymod phys that support this SDK phy */ 672 logical_lane_offset = 0; 673 for (idx = 0; idx < pmc->num_phys; idx++) { 674 phy = pmc->phy[idx]; 675 core = phy->core; 676 core->pm_core.access.lane_mask = phy->pm_phy.access.lane_mask; 677 _viper_device_print(core) ; 678 /* determine configuration data structure to default values, based on SOC properties */ 679 SOC_IF_ERROR_RETURN 680 (viper_config_init(unit, port, &phy->pm_phy, 681 logical_lane_offset, 682 &core->init_config, &phy->init_config)); 683 684 core_status.pmd_active = 0; 685 if (!SOC_WARM_BOOT(unit)) { 686 SOC_IF_ERROR_RETURN 687 (phymod_core_init(&core->pm_core, &core->init_config, &core_status)); 688 689 } 690 691 if (!SOC_WARM_BOOT(unit)) { 692 SOC_IF_ERROR_RETURN 693 (phymod_phy_init(&phy->pm_phy, &phy->init_config)); 694 } 695 696 697 /*read serdes id info */ 698 SOC_IF_ERROR_RETURN 699 (phymod_core_info_get(&core->pm_core, &core_info)); 700 701 702 /* for multicore phys, need to ratchet up to the next batch of lanes */ 703 logical_lane_offset += core->init_config.lane_map.num_of_lanes; 704 } 705 706 /* fill up the pInfo table for displaying the serdes driver info */ 707 SOC_IF_ERROR_RETURN 708 (viper_show_serdes_info(pc, pInfo, &core_info)); 709 710 /* retrieve chip level information for serdes driver info */ 711 pi = &SOC_PHY_INFO(unit, port); 712 713 if (!PHY_EXTERNAL_MODE(unit, port)) { 714 pi->phy_name = pInfo->name; 715 } 716 717 if (SOC_WARM_BOOT(unit)) { 718 return SOC_E_NONE; 719 } 720 721 speed_config->pll_divider_req = 40; 722 723 /* set the port to its max or init_speed */ 724 SOC_IF_ERROR_RETURN 725 (viper_speed_to_interface_config_get(&phy->pm_phy, speed_config, &interface_config, &tx_index)); 726 727 SOC_IF_ERROR_RETURN 728 (phymod_phy_interface_config_set(&phy->pm_phy, 729 0 /* flags */, &interface_config)); 730 731 /* setup the port's an cap */ 732 SOC_IF_ERROR_RETURN 733 (phy_viper_ability_local_get(unit, port, &ability)); 734 735 SOC_IF_ERROR_RETURN 736 (phy_viper_ability_advert_set(unit, port, &ability)); 737 738 LOG_INFO(BSL_LS_SOC_PHY, 739 (BSL_META_U(pc->unit, 740 "phy_viper_init: u=%d p=%d\n"), unit, port)); 741 742 return SOC_E_NONE; 743 } 744 745 /* 746 * Function: 747 * phy_viper_link_get 748 * Purpose: 749 * Get layer2 connection status. 750 * Parameters: 751 * unit - BCM unit number. 752 * port - Port number. 753 * link - address of memory to store link up/down state. 754 * Returns: 755 * SOC_E_NONE 756 */ 757 STATIC int 758 phy_viper_link_get(int unit, soc_port_t port, int *link) 759 { 760 phy_ctrl_t *pc; 761 soc_phymod_ctrl_t *pmc; 762 phymod_phy_access_t *pm_phy; 763 764 *link = 0; 765 /* locate phy control */ 766 pc = INT_PHY_SW_STATE(unit, port); 767 if (pc == NULL) { 768 return SOC_E_INTERNAL; 769 } 770 771 pmc = &pc->phymod_ctrl; 772 pm_phy = &pmc->phy[pmc->main_phy]->pm_phy; 773 774 SOC_IF_ERROR_RETURN 775 (phymod_phy_link_status_get(pm_phy, (uint32_t *) link)); 776 return (SOC_E_NONE); 777 } 778 779 /* 780 * Function: 781 * phy_viper_enable_set 782 * Purpose: 783 * Enable/Disable phy 784 * Parameters: 785 * unit - BCM unit number. 786 * port - Port number. 787 * enable - on/off state to set 788 * Returns: 789 * SOC_E_NONE 790 */ 791 STATIC int 792 phy_viper_enable_set(int unit, soc_port_t port, int enable) 793 { 794 return (_phy_viper_enable_set( unit, port, enable)); 795 } 796 797 /* 798 * Function: 799 * phy_viper_enable_get 800 * Purpose: 801 * Enable/Disable phy 802 * Parameters: 803 * unit - BCM unit number. 804 * port - Port number. 805 * enable - on/off state to set 806 * Returns: 807 * SOC_E_NONE 808 */ 809 STATIC int 810 phy_viper_enable_get(int unit, soc_port_t port, int *enable) 811 { 812 phy_ctrl_t *pc; 813 soc_phymod_ctrl_t *pmc; 814 phymod_phy_access_t *pm_phy; 815 phymod_phy_power_t phy_power; 816 817 /* locate phy control */ 818 pc = INT_PHY_SW_STATE(unit, port); 819 if (pc == NULL) { 820 return SOC_E_INTERNAL; 821 } 822 823 pmc = &pc->phymod_ctrl; 824 pm_phy = &pmc->phy[pmc->main_phy]->pm_phy; 825 826 SOC_IF_ERROR_RETURN(phymod_phy_power_get(pm_phy, &phy_power)); 827 if (phy_power.tx & phy_power.rx) { 828 *enable = 1; 829 } else { 830 *enable = 0; 831 } 832 833 return (SOC_E_NONE); 834 } 835 836 /* 837 * Function: 838 * phy_viper_speed_set 839 * Purpose: 840 * Set PHY speed 841 * Parameters: 842 * unit - BCM unit number. 843 * port - Port number. 844 * speed - link speed in Mbps 845 * Returns: 846 * SOC_E_NONE 847 */ 848 849 STATIC int 850 phy_viper_speed_set(int unit, soc_port_t port, int speed) 851 { 852 phy_ctrl_t *pc; 853 viper_config_t *pCfg; 854 soc_phymod_ctrl_t *pmc; 855 soc_phymod_phy_t *phy; 856 int idx,ln; 857 viper_speed_config_t speed_config; 858 phymod_phy_inf_config_t interface_config; 859 TXDRV_INXS_t tx_index = TXDRV_DFT_INX; 860 phymod_tx_t phymod_tx; 861 phymod_phy_access_t pm_phy_copy; 862 int start_lane, num_lane ; 863 864 /* locate phy control */ 865 pc = INT_PHY_SW_STATE(unit, port); 866 if (pc == NULL) { 867 return SOC_E_INTERNAL; 868 } 869 if (speed == 0) { 870 return SOC_E_NONE; 871 } 872 873 pmc = &pc->phymod_ctrl; 874 pCfg = (viper_config_t *) pc->driver_data; 875 876 /* take a copy of core and phy configuration values, and set the desired speed */ 877 sal_memcpy(&speed_config, &pCfg->speed_config, sizeof(speed_config)); 878 speed_config.speed = speed; 879 880 SOC_IF_ERROR_RETURN(phymod_tx_t_init(&phymod_tx)); 881 882 /* determine the interface configuration */ 883 phy = pmc->phy[0]; 884 SOC_IF_ERROR_RETURN 885 (viper_speed_to_interface_config_get(&phy->pm_phy, &speed_config, &interface_config, &tx_index)); 886 887 /* now loop through all cores */ 888 for (idx = 0; idx < pmc->num_phys; idx++) { 889 phy = pmc->phy[idx]; 890 if (phy == NULL) { 891 return SOC_E_INTERNAL; 892 } 893 894 sal_memcpy(&pm_phy_copy, &phy->pm_phy, sizeof(pm_phy_copy)); 895 PHYMOD_IF_ERR_RETURN 896 (phymod_util_lane_config_get(&pm_phy_copy.access, &start_lane, &num_lane)); 897 898 for(ln=0; ln<num_lane; ln++) { 899 pm_phy_copy.access.lane_mask = 1 << (start_lane +ln) ; 900 901 phymod_tx.main = pCfg->tx_drive[tx_index].main; 902 phymod_tx.post = pCfg->tx_drive[tx_index].post; 903 904 if( pCfg->ln_txparam[4*idx+ln].main >=0) { 905 phymod_tx.main = pCfg->ln_txparam[4*idx+ln].main; 906 } 907 if( pCfg->ln_txparam[4*idx+ln].post >=0) { 908 phymod_tx.post = pCfg->ln_txparam[4*idx+ln].post; 909 } 910 911 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 912 } 913 914 SOC_IF_ERROR_RETURN 915 (phymod_phy_interface_config_set(&phy->pm_phy, 916 0 /* flags */, &interface_config)); 917 } 918 919 /* record success */ 920 pCfg->speed_config.speed = speed; 921 922 return (SOC_E_NONE); 923 } 924 925 /* 926 * Function: 927 * phy_viper_speed_get 928 * Purpose: 929 * Get PHY speed 930 * Parameters: 931 * unit - BCM unit number. 932 * port - Port number. 933 * speed - current link speed in Mbps 934 * Returns: 935 * SOC_E_NONE 936 */ 937 STATIC int 938 phy_viper_speed_get(int unit, soc_port_t port, int *speed) 939 { 940 phy_ctrl_t *pc; 941 soc_phymod_ctrl_t *pmc; 942 soc_phymod_phy_t *phy; 943 phymod_phy_inf_config_t interface_config; 944 /*viper_config_t *pCfg; */ 945 int flag = 0; 946 phymod_ref_clk_t ref_clock = phymodRefClk156Mhz; 947 948 /* locate phy control */ 949 pc = INT_PHY_SW_STATE(unit, port); 950 if (pc == NULL) { 951 return SOC_E_INTERNAL; 952 } 953 /*pCfg = (viper_config_t *) pc->driver_data;*/ 954 955 pmc = &pc->phymod_ctrl; 956 957 /* initialize the data structure */ 958 interface_config.data_rate = 0; 959 960 /* now loop through all cores */ 961 phy = pmc->phy[pmc->main_phy]; 962 if (phy == NULL) { 963 return SOC_E_INTERNAL; 964 } 965 966 SOC_IF_ERROR_RETURN 967 (phymod_phy_interface_config_get(&phy->pm_phy, 968 flag, ref_clock, &interface_config)); 969 *speed = interface_config.data_rate; 970 return (SOC_E_NONE); 971 } 972 973 /* 974 * Function: 975 * phy_viper_duplex_set 976 * Purpose: 977 * Set PHY duplex mode 978 * Parameters: 979 * unit - BCM unit number. 980 * port - Port number. 981 * duplex - current duplex mode 982 * Returns: 983 * SOC_E_NONE 984 */ 985 STATIC int 986 phy_viper_duplex_set(int unit, soc_port_t port, int duplex) 987 { 988 phy_ctrl_t* pc; 989 soc_phymod_ctrl_t *pmc; 990 phymod_phy_access_t *pm_phy; 991 int idx; 992 phymod_duplex_mode_t duplex_mode; 993 994 pc = INT_PHY_SW_STATE(unit, port); 995 pmc = &pc->phymod_ctrl; 996 switch (duplex) { 997 case SOC_PORT_DUPLEX_HALF: 998 duplex_mode = phymodDuplexHalf; 999 break; 1000 case SOC_PORT_DUPLEX_FULL: 1001 duplex_mode = phymodDuplexFull; 1002 break; 1003 default: 1004 duplex_mode = phymodDuplexFull; 1005 break; 1006 } 1007 1008 for (idx = 0; idx < pmc->num_phys; idx++) { 1009 pm_phy = &pmc->phy[idx]->pm_phy; 1010 SOC_IF_ERROR_RETURN(phymod_phy_duplex_set(pm_phy, duplex_mode)); 1011 } 1012 1013 return SOC_E_NONE; 1014 } 1015 1016 /* 1017 * Function: 1018 * phy_viper_duplex_get 1019 * Purpose: 1020 * Get PHY duplex mode 1021 * Parameters: 1022 * unit - BCM unit number. 1023 * port - Port number. 1024 * duplex - current duplex mode 1025 * Returns: 1026 * SOC_E_NONE 1027 */ 1028 STATIC int 1029 phy_viper_duplex_get(int unit, soc_port_t port, int *duplex) 1030 { 1031 phy_ctrl_t* pc; 1032 soc_phymod_ctrl_t *pmc; 1033 phymod_phy_access_t *pm_phy; 1034 phymod_duplex_mode_t duplex_mode; 1035 1036 pc = INT_PHY_SW_STATE(unit, port); 1037 pmc = &pc->phymod_ctrl; 1038 1039 /* Check first PHY only */ 1040 pm_phy = &pmc->phy[0]->pm_phy; 1041 SOC_IF_ERROR_RETURN 1042 (phymod_phy_duplex_get(pm_phy, &duplex_mode)); 1043 switch (duplex_mode) { 1044 case phymodDuplexHalf: 1045 *duplex = SOC_PORT_DUPLEX_HALF; 1046 break; 1047 case phymodDuplexFull: 1048 *duplex = SOC_PORT_DUPLEX_FULL; 1049 break; 1050 default: 1051 *duplex = SOC_PORT_DUPLEX_FULL; 1052 break; 1053 } 1054 1055 return SOC_E_NONE; 1056 } 1057 1058 /* 1059 * Function: 1060 * phy_viper_an_set 1061 * Purpose: 1062 * Enable or disable auto-negotiation on the specified port. 1063 * Parameters: 1064 * unit - BCM unit number. 1065 * port - Port number. 1066 * an - Boolean, if true, auto-negotiation is enabled 1067 * (and/or restarted). If false, autonegotiation is disabled. 1068 * Returns: 1069 * SOC_E_XXX _soc_triumph_tx 1070 */ 1071 STATIC int 1072 phy_viper_an_set(int unit, soc_port_t port, int enable) 1073 { 1074 phy_ctrl_t *pc; 1075 viper_config_t *pCfg; 1076 soc_phymod_ctrl_t *pmc; 1077 soc_phymod_phy_t *phy; 1078 phymod_autoneg_control_t an; 1079 soc_info_t *si; 1080 1081 /* locate phy control */ 1082 pc = INT_PHY_SW_STATE(unit, port); 1083 if (pc == NULL) { 1084 return SOC_E_INTERNAL; 1085 } 1086 1087 phymod_autoneg_control_t_init(&an); 1088 pmc = &pc->phymod_ctrl; 1089 pCfg = (viper_config_t *) pc->driver_data; 1090 si = &SOC_INFO(unit); 1091 1092 /* for legacy purpose autodet is 1 by defalut */ 1093 pCfg->auto_medium = 1; 1094 pCfg->auto_medium = soc_property_port_get(unit, port, 1095 spn_SERDES_AUTOMEDIUM, pCfg->auto_medium); 1096 1097 /* only request autoneg on the first core */ 1098 phy = pmc->phy[pmc->main_phy]; 1099 if (phy == NULL) { 1100 return SOC_E_INTERNAL; 1101 } 1102 an.enable = enable; 1103 an.num_lane_adv = si->port_num_lanes[port]; 1104 an.an_mode = phymod_AN_MODE_NONE; 1105 if (pCfg->cl37an) { 1106 an.an_mode = phymod_AN_MODE_CL37; 1107 } else { 1108 if(pCfg->speed_config.fiber_pref) { 1109 an.an_mode = phymod_AN_MODE_CL37; 1110 } else { 1111 an.an_mode = phymod_AN_MODE_SGMII; 1112 } 1113 } 1114 if (pCfg->auto_medium) { 1115 PHYMOD_AN_F_AUTO_MEDIUM_DETECT_SET(&an); 1116 } 1117 SOC_IF_ERROR_RETURN 1118 (phymod_phy_autoneg_set(&phy->pm_phy, &an)); 1119 1120 return (SOC_E_NONE); 1121 } 1122 1123 /* 1124 * Function: 1125 * phy_viper_an_get 1126 * Purpose: 1127 * Get the current auto-negotiation status (enabled/busy) 1128 * Parameters: 1129 * unit - BCM unit number. 1130 * port - Port number. 1131 * an - (OUT) if true, auto-negotiation is enabled. 1132 * an_done - (OUT) if true, auto-negotiation is complete. This 1133 * value is undefined if an == false. 1134 * Returns: 1135 * SOC_E_XXX 1136 */ 1137 1138 STATIC int 1139 phy_viper_an_get(int unit, soc_port_t port, int *an, int *an_done) 1140 { 1141 phy_ctrl_t* pc; 1142 soc_phymod_ctrl_t *pmc; 1143 phymod_phy_access_t *pm_phy; 1144 phymod_autoneg_control_t an_control; 1145 int idx, an_complete; 1146 1147 pc = INT_PHY_SW_STATE(unit, port); 1148 pmc = &pc->phymod_ctrl; 1149 1150 sal_memset(&an_control, 0x0, sizeof(an_control)); 1151 1152 idx = pmc->main_phy; 1153 pm_phy = &pmc->phy[idx]->pm_phy; 1154 SOC_IF_ERROR_RETURN 1155 (phymod_phy_autoneg_get(pm_phy, &an_control, (uint32_t *) &an_complete)); 1156 1157 if (an_control.enable) { 1158 *an = 1; 1159 *an_done = an_complete; 1160 } else { 1161 *an = 0; 1162 *an_done = 0; 1163 } 1164 1165 return (SOC_E_NONE); 1166 } 1167 1168 /* 1169 * Function: 1170 * phy_viper_ability_advert_set 1171 * Purpose: 1172 * Set the current advertisement for auto-negotiation. 1173 * Parameters: 1174 * unit - BCM unit number. 1175 * port - Port number. 1176 * ability - Port mode mask indicating supported options/speeds. 1177 * Returns: 1178 * SOC_E_XXX 1179 * Notes: 1180 * The advertisement is set only for the ACTIVE medium. 1181 * No synchronization performed at this level. 1182 */ 1183 1184 STATIC int 1185 phy_viper_ability_advert_set(int unit, soc_port_t port, 1186 soc_port_ability_t *ability) 1187 { 1188 phy_ctrl_t *pc; 1189 viper_config_t *pCfg; 1190 soc_phymod_ctrl_t *pmc; 1191 soc_phymod_phy_t *phy; 1192 phymod_autoneg_ability_t phymod_autoneg_ability; 1193 1194 /* locate phy control */ 1195 pc = INT_PHY_SW_STATE(unit, port); 1196 if (pc == NULL) { 1197 return SOC_E_INTERNAL; 1198 } 1199 1200 phymod_autoneg_ability_t_init(&phymod_autoneg_ability); 1201 1202 pmc = &pc->phymod_ctrl; 1203 pCfg = (viper_config_t *) pc->driver_data; 1204 1205 /* only set abilities on the first core */ 1206 phy = pmc->phy[pmc->main_phy]; 1207 if (phy == NULL) { 1208 return SOC_E_INTERNAL; 1209 } 1210 1211 1212 switch (ability->pause & (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX)) { 1213 case SOC_PA_PAUSE_TX: 1214 PHYMOD_AN_CAP_ASYM_PAUSE_SET(&phymod_autoneg_ability); 1215 break; 1216 case SOC_PA_PAUSE_RX: 1217 /* an_adv |= MII_ANA_C37_PAUSE | MII_ANA_C37_ASYM_PAUSE; */ 1218 PHYMOD_AN_CAP_ASYM_PAUSE_SET(&phymod_autoneg_ability); 1219 PHYMOD_AN_CAP_SYMM_PAUSE_SET(&phymod_autoneg_ability); 1220 break; 1221 case SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX: 1222 PHYMOD_AN_CAP_SYMM_PAUSE_SET(&phymod_autoneg_ability); 1223 break; 1224 } 1225 1226 /* Set 1000MB CL37*/ 1227 if (pCfg->cl37an){ 1228 if(ability->speed_full_duplex & SOC_PA_SPEED_1000MB) { 1229 PHYMOD_AN_CAP_CL37_SET(&phymod_autoneg_ability); 1230 } 1231 } else { 1232 /* set the sgmii speed */ 1233 if(ability->speed_full_duplex & SOC_PA_SPEED_1000MB) { 1234 PHYMOD_AN_CAP_SGMII_SET(&phymod_autoneg_ability); 1235 phymod_autoneg_ability.sgmii_speed = phymod_CL37_SGMII_1000M; 1236 } else if(ability->speed_full_duplex & SOC_PA_SPEED_100MB) { 1237 PHYMOD_AN_CAP_SGMII_SET(&phymod_autoneg_ability); 1238 phymod_autoneg_ability.sgmii_speed = phymod_CL37_SGMII_100M; 1239 } else if(ability->speed_full_duplex & SOC_PA_SPEED_10MB) { 1240 PHYMOD_AN_CAP_SGMII_SET(&phymod_autoneg_ability); 1241 phymod_autoneg_ability.sgmii_speed = phymod_CL37_SGMII_10M; 1242 } else { 1243 PHYMOD_AN_CAP_SGMII_SET(&phymod_autoneg_ability); 1244 phymod_autoneg_ability.sgmii_speed = phymod_CL37_SGMII_1000M; 1245 } 1246 1247 } 1248 1249 SOC_IF_ERROR_RETURN 1250 (phymod_phy_autoneg_ability_set(&phy->pm_phy, &phymod_autoneg_ability)); 1251 1252 return SOC_E_NONE; 1253 } 1254 1255 /* 1256 * Function: 1257 * phy_viper_ability_advert_get 1258 * Purpose: 1259 * Get the current advertisement for auto-negotiation. 1260 * Parameters: 1261 * unit - BCM unit number. 1262 * port - Port number. 1263 * ability - (OUT) Port mode mask indicating supported options/speeds. 1264 * Returns: 1265 * SOC_E_XXX 1266 * Notes: 1267 * The advertisement is retrieved for the ACTIVE medium. 1268 * No synchronization performed at this level. 1269 */ 1270 1271 STATIC int 1272 phy_viper_ability_advert_get(int unit, soc_port_t port, 1273 soc_port_ability_t *ability) 1274 { 1275 phy_ctrl_t *pc; 1276 soc_phymod_ctrl_t *pmc; 1277 soc_phymod_phy_t *phy; 1278 int reg_ability; 1279 _shr_port_mode_t speed_full_duplex; 1280 phymod_autoneg_ability_t phymod_autoneg_ability; 1281 phymod_cl37_sgmii_speed_t cl37_sgmii_speed; 1282 1283 /* locate phy control */ 1284 pc = INT_PHY_SW_STATE(unit, port); 1285 if (pc == NULL) { 1286 return SOC_E_INTERNAL; 1287 } 1288 1289 pmc = &pc->phymod_ctrl; 1290 1291 /* only get abilities from the first core */ 1292 phy = pmc->phy[pmc->main_phy]; 1293 if (phy == NULL) { 1294 return SOC_E_INTERNAL; 1295 } 1296 1297 phymod_autoneg_ability_t_init(&phymod_autoneg_ability); 1298 SOC_IF_ERROR_RETURN 1299 (phymod_phy_autoneg_ability_get(&phy->pm_phy, &phymod_autoneg_ability)); 1300 1301 cl37_sgmii_speed = phymod_autoneg_ability.sgmii_speed; 1302 reg_ability = phymod_autoneg_ability.capabilities; 1303 speed_full_duplex = 0; 1304 1305 /* retrieve CL37 abilities */ 1306 if (reg_ability == PHYMOD_AN_CAP_CL37){ 1307 speed_full_duplex|= SOC_PA_SPEED_1000MB; 1308 } 1309 1310 /* retrieve sgmii speed */ 1311 if (cl37_sgmii_speed == phymod_CL37_SGMII_1000M){ 1312 speed_full_duplex|= SOC_PA_SPEED_1000MB; 1313 } else if (cl37_sgmii_speed == phymod_CL37_SGMII_100M){ 1314 speed_full_duplex|= SOC_PA_SPEED_100MB; 1315 } else if (cl37_sgmii_speed == phymod_CL37_SGMII_10M){ 1316 speed_full_duplex|= SOC_PA_SPEED_10MB; 1317 } else { 1318 speed_full_duplex|= 0; 1319 } 1320 1321 /* retrieve "pause" abilities */ 1322 ability->pause = 0; 1323 if (reg_ability == PHYMOD_AN_CAP_ASYM_PAUSE) { 1324 ability->pause = SOC_PA_PAUSE_TX; 1325 } else if (reg_ability == (PHYMOD_AN_CAP_SYMM_PAUSE|PHYMOD_AN_CAP_ASYM_PAUSE)) { 1326 ability->pause = SOC_PA_PAUSE_RX; 1327 } else if (reg_ability == PHYMOD_AN_CAP_SYMM_PAUSE) { 1328 ability->pause = (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX); 1329 } 1330 1331 ability->speed_full_duplex = speed_full_duplex; 1332 1333 return SOC_E_NONE; 1334 } 1335 1336 /* 1337 * Function: 1338 * phy_viper_ability_remote_get 1339 * Purpose: 1340 * Get the current advertisement for auto-negotiation. 1341 * Parameters: 1342 * unit - BCM unit number. 1343 * port - Port number. 1344 * ability - (OUT) Port mode mask indicating supported options/speeds. 1345 * Returns: 1346 * SOC_E_XXX 1347 * Notes: 1348 * The advertisement is retrieved for the ACTIVE medium. 1349 * No synchronization performed at this level. 1350 */ 1351 1352 STATIC int 1353 phy_viper_ability_remote_get(int unit, soc_port_t port, 1354 soc_port_ability_t *ability) 1355 { 1356 phy_ctrl_t *pc; 1357 soc_phymod_ctrl_t *pmc; 1358 soc_phymod_phy_t *phy; 1359 int reg37_ability; 1360 int reg_ability; 1361 _shr_port_mode_t speed_full_duplex; 1362 phymod_autoneg_ability_t phymod_autoneg_ability; 1363 1364 /* locate phy control */ 1365 pc = INT_PHY_SW_STATE(unit, port); 1366 if (pc == NULL) { 1367 return SOC_E_INTERNAL; 1368 } 1369 1370 pmc = &pc->phymod_ctrl; 1371 1372 /* only get abilities from the first core */ 1373 phy = pmc->phy[pmc->main_phy]; 1374 if (phy == NULL) { 1375 return SOC_E_INTERNAL; 1376 } 1377 1378 phymod_autoneg_ability_t_init(&phymod_autoneg_ability); 1379 SOC_IF_ERROR_RETURN 1380 (phymod_phy_autoneg_remote_ability_get(&phy->pm_phy, &phymod_autoneg_ability)); 1381 1382 speed_full_duplex = 0; 1383 1384 /* retrieve CL37 abilities */ 1385 reg37_ability = phymod_autoneg_ability.an_cap; 1386 speed_full_duplex|= PHYMOD_AN_CAP_1G_KX_GET(reg37_ability)? SOC_PA_SPEED_1000MB : 0; 1387 speed_full_duplex|= SOC_PA_SPEED_1000MB ; 1388 1389 /* retrieve "pause" abilities */ 1390 reg_ability = phymod_autoneg_ability.capabilities; 1391 1392 ability->pause = 0; 1393 if (reg_ability == PHYMOD_AN_CAP_ASYM_PAUSE) { 1394 ability->pause = SOC_PA_PAUSE_TX; 1395 } else if (reg_ability == (PHYMOD_AN_CAP_SYMM_PAUSE|PHYMOD_AN_CAP_ASYM_PAUSE)) { 1396 ability->pause = SOC_PA_PAUSE_RX; 1397 } else if (reg_ability == PHYMOD_AN_CAP_SYMM_PAUSE) { 1398 ability->pause = (SOC_PA_PAUSE_TX | SOC_PA_PAUSE_RX); 1399 } 1400 1401 ability->speed_full_duplex = speed_full_duplex; 1402 1403 return SOC_E_NONE; 1404 } 1405 1406 /* 1407 * Function: 1408 * phy_viper_lb_set 1409 * Purpose: 1410 * Enable/disable PHY loopback mode 1411 * Parameters: 1412 * unit - BCM unit number. 1413 * port - Port number. 1414 * enable - binary value for on/off (1/0) 1415 * Returns: 1416 * SOC_E_NONE 1417 */ 1418 STATIC int 1419 phy_viper_lb_set(int unit, soc_port_t port, int enable) 1420 { 1421 phy_ctrl_t* pc; 1422 soc_phymod_ctrl_t *pmc; 1423 phymod_phy_access_t *pm_phy; 1424 int idx; 1425 1426 pc = INT_PHY_SW_STATE(unit, port); 1427 pmc = &pc->phymod_ctrl; 1428 1429 for (idx = 0; idx < pmc->num_phys; idx++) { 1430 pm_phy = &pmc->phy[idx]->pm_phy; 1431 SOC_IF_ERROR_RETURN 1432 (phymod_phy_loopback_set(pm_phy, phymodLoopbackGlobal, enable)); 1433 } 1434 1435 return (SOC_E_NONE); 1436 } 1437 1438 /* 1439 * Function: 1440 * phy_viper_lb_get 1441 * Purpose: 1442 * Get current PHY loopback mode 1443 * Parameters: 1444 * unit - BCM unit number. 1445 * port - Port number. 1446 * enable - address of location to store binary value for on/off (1/0) 1447 * Returns: 1448 * SOC_E_NONE 1449 */ 1450 STATIC int 1451 phy_viper_lb_get(int unit, soc_port_t port, int *enable) 1452 { 1453 phy_ctrl_t* pc; 1454 soc_phymod_ctrl_t *pmc; 1455 phymod_phy_access_t *pm_phy; 1456 uint32 lb_enable; 1457 1458 pc = INT_PHY_SW_STATE(unit, port); 1459 pmc = &pc->phymod_ctrl; 1460 1461 *enable = 0; 1462 1463 /* Check first PHY only */ 1464 pm_phy = &pmc->phy[0]->pm_phy; 1465 SOC_IF_ERROR_RETURN 1466 (phymod_phy_loopback_get(pm_phy, phymodLoopbackGlobal, &lb_enable)); 1467 if (lb_enable) { 1468 *enable = 1; 1469 } 1470 1471 return (SOC_E_NONE); 1472 } 1473 1474 /* 1475 * Function: 1476 * phy_viper_ability_local_get 1477 * Purpose: 1478 * xx 1479 * Parameters: 1480 * unit - BCM unit number. 1481 * port - Port number. 1482 * ability - xx 1483 * Returns: 1484 * SOC_E_NONE 1485 */ 1486 STATIC int 1487 phy_viper_ability_local_get(int unit, soc_port_t port, soc_port_ability_t *ability) 1488 { 1489 phy_ctrl_t *pc; 1490 viper_config_t *pCfg; 1491 1492 pc = INT_PHY_SW_STATE(unit, port); 1493 pCfg = (viper_config_t *) pc->driver_data; 1494 1495 if (NULL == ability) { 1496 return SOC_E_PARAM; 1497 } 1498 1499 sal_memset(ability, 0, sizeof(*ability)); 1500 1501 ability->loopback = SOC_PA_LB_PHY; 1502 ability->medium = SOC_PA_MEDIUM_FIBER; 1503 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 1504 ability->flags = SOC_PA_AUTONEG; 1505 1506 if (IND_LANE_MODE(pc)) { 1507 ability->speed_full_duplex = SOC_PA_SPEED_1000MB; 1508 if (pCfg->speed_config.fiber_pref) { 1509 ability->speed_full_duplex |= SOC_PA_SPEED_100MB; 1510 if (pc->speed_max >= 2500) { 1511 ability->speed_full_duplex |= SOC_PA_SPEED_2500MB; 1512 } 1513 ability->speed_half_duplex = SOC_PA_SPEED_100MB; 1514 } else { 1515 ability->speed_full_duplex |= SOC_PA_SPEED_10MB | 1516 SOC_PA_SPEED_100MB; 1517 ability->speed_half_duplex = SOC_PA_SPEED_10MB | 1518 SOC_PA_SPEED_100MB; 1519 } 1520 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 1521 ability->interface = SOC_PA_INTF_GMII | SOC_PA_INTF_SGMII; 1522 ability->medium = SOC_PA_MEDIUM_FIBER; 1523 ability->eee = SOC_PA_ABILITY_NONE; 1524 ability->loopback = SOC_PA_LB_PHY; 1525 ability->flags = SOC_PA_AUTONEG; 1526 } else { 1527 if (pCfg->speed_config.fiber_pref) { 1528 ability->speed_half_duplex = SOC_PA_SPEED_100MB; 1529 } else { 1530 ability->speed_half_duplex = SOC_PA_SPEED_10MB | 1531 SOC_PA_SPEED_100MB; 1532 } 1533 ability->speed_full_duplex = SOC_PA_SPEED_10GB; 1534 ability->pause = SOC_PA_PAUSE | SOC_PA_PAUSE_ASYMM; 1535 ability->interface = SOC_PA_INTF_XGMII; 1536 ability->medium = SOC_PA_MEDIUM_FIBER; 1537 ability->loopback = SOC_PA_LB_PHY; 1538 ability->eee = SOC_PA_ABILITY_NONE; 1539 ability->flags = SOC_PA_ABILITY_NONE; 1540 } 1541 1542 LOG_INFO(BSL_LS_SOC_PHY, 1543 (BSL_META_U(pc->unit, 1544 "phy_viper_ability_local_get:unit=%d p=%d sp=%08x\n"), 1545 unit, port, ability->speed_full_duplex)); 1546 return (SOC_E_NONE); 1547 } 1548 1549 1550 STATIC int 1551 phy_viper_interface_set(int unit, soc_port_t port, soc_port_if_t pif) 1552 { 1553 phy_ctrl_t *pc; 1554 viper_config_t *pCfg; 1555 1556 pc = INT_PHY_SW_STATE(unit, port); 1557 pCfg = (viper_config_t *) pc->driver_data; 1558 1559 pCfg->speed_config.line_interface = (uint32) pif; 1560 1561 if (pif == SOC_PORT_IF_GMII) { 1562 pCfg->speed_config.fiber_pref = 1; 1563 } else if (pif == SOC_PORT_IF_SGMII){ 1564 pCfg->speed_config.fiber_pref = 0; 1565 } 1566 1567 return SOC_E_NONE; 1568 } 1569 1570 STATIC int 1571 phy_viper_interface_get(int unit, soc_port_t port, soc_port_if_t *pif) 1572 { 1573 phy_ctrl_t *pc; 1574 soc_phymod_ctrl_t *pmc; 1575 soc_phymod_phy_t *phy; 1576 phymod_phy_inf_config_t interface_config; 1577 viper_config_t *pCfg; 1578 int flag = 0; 1579 phymod_ref_clk_t ref_clock = phymodRefClk156Mhz; 1580 1581 /* locate phy control */ 1582 pc = INT_PHY_SW_STATE(unit, port); 1583 if (pc == NULL) { 1584 return SOC_E_INTERNAL; 1585 } 1586 pCfg = (viper_config_t *) pc->driver_data; 1587 1588 pmc = &pc->phymod_ctrl; 1589 1590 /* initialize the data structure */ 1591 sal_memset(&interface_config, 0x0, sizeof(phymod_phy_inf_config_t)); 1592 1593 /* now loop through all cores */ 1594 phy = pmc->phy[pmc->main_phy]; 1595 if (phy == NULL) { 1596 return SOC_E_INTERNAL; 1597 } 1598 1599 /* note that the flags have an option to indicate whether it's ok to reprogram the PLL */ 1600 SOC_IF_ERROR_RETURN 1601 (phymod_phy_interface_config_get(&phy->pm_phy, 1602 flag, ref_clock, &interface_config)); 1603 switch (interface_config.interface_type) { 1604 case phymodInterfaceXAUI: 1605 *pif = _SHR_PORT_IF_XAUI; 1606 break; 1607 case phymodInterface1000X: 1608 *pif = SOC_PORT_IF_GMII; 1609 break; 1610 case phymodInterfaceKX: 1611 *pif = SOC_PORT_IF_KX; 1612 break; 1613 case phymodInterfaceSGMII: 1614 { 1615 if(interface_config.data_rate == 1000) { 1616 if (PHY_EXTERNAL_MODE(unit, port) || !(pCfg->speed_config.fiber_pref)) { 1617 *pif = SOC_PORT_IF_SGMII; 1618 } else { 1619 *pif = SOC_PORT_IF_GMII; 1620 } 1621 } else { 1622 *pif = SOC_PORT_IF_SGMII; 1623 } 1624 break; 1625 } 1626 default: 1627 *pif = SOC_PORT_IF_SGMII; 1628 break; 1629 } 1630 1631 return (SOC_E_NONE); 1632 1633 } 1634 1635 1636 /* 1637 * Function: 1638 * viper_pcs_status_dump 1639 * Purpose: 1640 * display all the serdes related parameters 1641 * Parameters: 1642 * unit - BCM unit number. 1643 * port - Port number. 1644 1645 * Returns: 1646 * SOC_E_NONE 1647 */ 1648 STATIC int 1649 viper_pcs_status_dump(int unit, soc_port_t port, void *arg) 1650 { 1651 phy_ctrl_t* pc; 1652 soc_phymod_ctrl_t *pmc; 1653 phymod_phy_access_t *pm_phy; 1654 int idx; 1655 1656 pc = INT_PHY_SW_STATE(unit, port); 1657 pmc = &pc->phymod_ctrl; 1658 1659 for (idx = 0; idx < pmc->num_phys; idx++) { 1660 pm_phy = &pmc->phy[idx]->pm_phy; 1661 SOC_IF_ERROR_RETURN 1662 (phymod_phy_pcs_info_dump(pm_phy, arg)); 1663 } 1664 return (SOC_E_NONE); 1665 } 1666 1667 1668 /* 1669 * given a pc (phymod_ctrl_t) and logical lane number, 1670 * find the correct soc_phymod_phy_t object and lane 1671 */ 1672 STATIC int 1673 _viper_find_soc_phy_lane(soc_phymod_ctrl_t *pmc, uint32_t lane, 1674 soc_phymod_phy_t **p_phy, uint32 *lane_map) 1675 { 1676 phymod_phy_access_t *pm_phy; 1677 int idx, lnx, ln_cnt, found; 1678 uint32 lane_map_copy; 1679 1680 /* Traverse lanes belonging to this port */ 1681 found = 0; 1682 ln_cnt = 0; 1683 for (idx = 0; idx < pmc->num_phys; idx++) { 1684 pm_phy = &pmc->phy[idx]->pm_phy; 1685 if (pm_phy == NULL) { 1686 return SOC_E_INTERNAL; 1687 } 1688 lane_map_copy = pm_phy->access.lane_mask; 1689 for (lnx = 0; lnx < 4; lnx++) { 1690 if ((1 << lnx) & lane_map_copy) { 1691 if (ln_cnt == lane) { 1692 found = 1; 1693 break; 1694 } 1695 ln_cnt++; 1696 } 1697 } 1698 if (found) { 1699 *p_phy = pmc->phy[idx]; 1700 *lane_map = (1 << lnx); 1701 break; 1702 } 1703 } 1704 1705 if (!found) { 1706 /* No such lane */ 1707 return SOC_E_PARAM; 1708 } 1709 return (SOC_E_NONE); 1710 } 1711 1712 /* 1713 * viper_per_lane_preemphasis_set 1714 */ 1715 STATIC int 1716 viper_per_lane_preemphasis_set(soc_phymod_ctrl_t *pmc, int lane, uint32 value) 1717 { 1718 soc_phymod_phy_t *p_phy; 1719 uint32 lane_map; 1720 phymod_phy_access_t pm_phy_copy, *pm_phy; 1721 phymod_tx_t phymod_tx; 1722 1723 /* locate the desired phy and lane */ 1724 SOC_IF_ERROR_RETURN(_viper_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 1725 1726 /* Make a copy of the phy access and overwrite the desired lane */ 1727 pm_phy = &p_phy->pm_phy; 1728 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 1729 pm_phy_copy.access.lane_mask = lane_map; 1730 1731 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 1732 phymod_tx.main = (value >> 8) & 0xff; 1733 phymod_tx.post = (value >> 16) & 0xff; 1734 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(&pm_phy_copy, &phymod_tx)); 1735 1736 return(SOC_E_NONE); 1737 } 1738 1739 /* 1740 * viper_preemphasis_set 1741 */ 1742 STATIC int 1743 viper_preemphasis_set(soc_phymod_ctrl_t *pmc, uint32 value) 1744 { 1745 phymod_phy_access_t *pm_phy; 1746 phymod_tx_t phymod_tx; 1747 int idx; 1748 1749 /* loop through all cores */ 1750 for (idx = 0; idx < pmc->num_phys; idx++) { 1751 pm_phy = &pmc->phy[idx]->pm_phy; 1752 1753 if (pm_phy == NULL) { 1754 return SOC_E_INTERNAL; 1755 } 1756 1757 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(pm_phy, &phymod_tx)); 1758 phymod_tx.main = (value >> 8) & 0xff; 1759 phymod_tx.post = (value >> 16) & 0xff; 1760 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(pm_phy, &phymod_tx)); 1761 1762 } 1763 1764 return(SOC_E_NONE); 1765 } 1766 1767 /* 1768 * viper_tx_fir_main_set 1769 */ 1770 STATIC int 1771 viper_tx_fir_main_set(soc_phymod_ctrl_t *pmc, uint32 value) 1772 { 1773 phymod_phy_access_t *pm_phy; 1774 phymod_tx_t phymod_tx; 1775 int idx; 1776 1777 /* loop through all cores */ 1778 for (idx = 0; idx < pmc->num_phys; idx++) { 1779 pm_phy = &pmc->phy[idx]->pm_phy; 1780 1781 if (pm_phy == NULL) { 1782 return SOC_E_INTERNAL; 1783 } 1784 1785 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(pm_phy, &phymod_tx)); 1786 phymod_tx.main = value; 1787 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(pm_phy, &phymod_tx)); 1788 } 1789 1790 return(SOC_E_NONE); 1791 } 1792 1793 /* 1794 * viper_tx_fir_post_set 1795 */ 1796 STATIC int 1797 viper_tx_fir_post_set(soc_phymod_ctrl_t *pmc, uint32 value) 1798 { 1799 phymod_phy_access_t *pm_phy; 1800 phymod_tx_t phymod_tx; 1801 int idx; 1802 1803 /* loop through all cores */ 1804 for (idx = 0; idx < pmc->num_phys; idx++) { 1805 pm_phy = &pmc->phy[idx]->pm_phy; 1806 1807 if (pm_phy == NULL) { 1808 return SOC_E_INTERNAL; 1809 } 1810 1811 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(pm_phy, &phymod_tx)); 1812 phymod_tx.post = value; 1813 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(pm_phy, &phymod_tx)); 1814 } 1815 1816 return(SOC_E_NONE); 1817 } 1818 1819 #if 0 1820 /* 1821 * viper_tx_fir_post2_set 1822 */ 1823 STATIC int 1824 viper_tx_fir_post2_set(soc_phymod_ctrl_t *pmc, uint32 value) 1825 { 1826 phymod_phy_access_t *pm_phy; 1827 phymod_tx_t phymod_tx; 1828 int idx; 1829 1830 /* loop through all cores */ 1831 for (idx = 0; idx < pmc->num_phys; idx++) { 1832 pm_phy = &pmc->phy[idx]->pm_phy; 1833 1834 if (pm_phy == NULL) { 1835 return SOC_E_INTERNAL; 1836 } 1837 1838 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(pm_phy, &phymod_tx)); 1839 phymod_tx.post2 = value; 1840 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(pm_phy, &phymod_tx)); 1841 } 1842 1843 return(SOC_E_NONE); 1844 } 1845 1846 /* 1847 * viper_tx_fir_post3_set 1848 */ 1849 STATIC int 1850 viper_tx_fir_post3_set(soc_phymod_ctrl_t *pmc, uint32 value) 1851 { 1852 phymod_phy_access_t *pm_phy; 1853 phymod_tx_t phymod_tx; 1854 int idx; 1855 1856 /* loop through all cores */ 1857 for (idx = 0; idx < pmc->num_phys; idx++) { 1858 pm_phy = &pmc->phy[idx]->pm_phy; 1859 1860 if (pm_phy == NULL) { 1861 return SOC_E_INTERNAL; 1862 } 1863 1864 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(pm_phy, &phymod_tx)); 1865 phymod_tx.post3 = value; 1866 SOC_IF_ERROR_RETURN(phymod_phy_tx_set(pm_phy, &phymod_tx)); 1867 } 1868 1869 return(SOC_E_NONE); 1870 } 1871 #endif 1872 1873 1874 /* 1875 * viper_per_lane_rx_dfe_tap_control_set 1876 */ 1877 STATIC int 1878 viper_per_lane_rx_dfe_tap_control_set(soc_phymod_ctrl_t *pmc, int lane, int tap, int enable, uint32 value) 1879 { 1880 soc_phymod_phy_t *p_phy; 1881 uint32 lane_map; 1882 phymod_phy_access_t pm_phy_copy, *pm_phy; 1883 phymod_rx_t phymod_rx; 1884 1885 /* locate the desired phy and lane */ 1886 SOC_IF_ERROR_RETURN(_viper_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 1887 1888 /* Make a copy of the phy access and overwrite the desired lane */ 1889 pm_phy = &p_phy->pm_phy; 1890 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 1891 pm_phy_copy.access.lane_mask = lane_map; 1892 1893 if (tap < 0 || tap >= COUNTOF(phymod_rx.dfe)) { 1894 /* this can only happen with a coding error */ 1895 return SOC_E_INTERNAL; 1896 } 1897 1898 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 1899 phymod_rx.dfe[tap].enable = enable; 1900 phymod_rx.dfe[tap].value = value; 1901 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(&pm_phy_copy, &phymod_rx)); 1902 1903 return(SOC_E_NONE); 1904 } 1905 1906 1907 /* 1908 * viper_tx_lane_squelch 1909 */ 1910 STATIC int 1911 viper_tx_lane_squelch(soc_phymod_ctrl_t *pmc, uint32 value) 1912 { 1913 phymod_phy_access_t *pm_phy; 1914 phymod_phy_tx_lane_control_t tx_control; 1915 int idx; 1916 1917 /* loop through all cores */ 1918 for (idx = 0; idx < pmc->num_phys; idx++) { 1919 pm_phy = &pmc->phy[idx]->pm_phy; 1920 1921 if (pm_phy == NULL) { 1922 return SOC_E_INTERNAL; 1923 } 1924 1925 if (value == 1) { 1926 tx_control = phymodTxSquelchOn; 1927 } else { 1928 tx_control = phymodTxSquelchOff; 1929 } 1930 SOC_IF_ERROR_RETURN 1931 (phymod_phy_tx_lane_control_set(pm_phy, tx_control)); 1932 } 1933 return(SOC_E_NONE); 1934 } 1935 1936 /* 1937 * viper_per_lane_rx_peak_filter_set 1938 */ 1939 STATIC int 1940 viper_per_lane_rx_peak_filter_set(soc_phymod_ctrl_t *pmc, int lane, int enable, uint32 value) 1941 { 1942 soc_phymod_phy_t *p_phy; 1943 uint32 lane_map; 1944 phymod_phy_access_t pm_phy_copy, *pm_phy; 1945 phymod_rx_t phymod_rx; 1946 1947 /* locate the desired phy and lane */ 1948 SOC_IF_ERROR_RETURN(_viper_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 1949 1950 /* Make a copy of the phy access and overwrite the desired lane */ 1951 pm_phy = &p_phy->pm_phy; 1952 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 1953 pm_phy_copy.access.lane_mask = lane_map; 1954 1955 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 1956 phymod_rx.peaking_filter.enable = TRUE; 1957 phymod_rx.peaking_filter.value = value; 1958 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(pm_phy, &phymod_rx)); 1959 1960 return(SOC_E_NONE); 1961 } 1962 1963 /* 1964 * viper_rx_peak_filter_set 1965 */ 1966 STATIC int 1967 viper_rx_peak_filter_set(soc_phymod_ctrl_t *pmc, uint32 value) 1968 { 1969 phymod_phy_access_t *pm_phy; 1970 phymod_rx_t phymod_rx; 1971 int idx; 1972 1973 /* loop through all cores */ 1974 for (idx = 0; idx < pmc->num_phys; idx++) { 1975 pm_phy = &pmc->phy[idx]->pm_phy; 1976 1977 if (pm_phy == NULL) { 1978 return SOC_E_INTERNAL; 1979 } 1980 1981 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(pm_phy, &phymod_rx)); 1982 phymod_rx.peaking_filter.enable = TRUE; 1983 phymod_rx.peaking_filter.value = value; 1984 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(pm_phy, &phymod_rx)); 1985 } 1986 1987 return(SOC_E_NONE); 1988 } 1989 1990 /* 1991 * viper_per_lane_rx_vga_set 1992 */ 1993 STATIC int 1994 viper_per_lane_rx_vga_set(soc_phymod_ctrl_t *pmc, int lane, int enable, uint32 value) 1995 { 1996 soc_phymod_phy_t *p_phy; 1997 uint32 lane_map; 1998 phymod_phy_access_t pm_phy_copy, *pm_phy; 1999 phymod_rx_t phymod_rx; 2000 2001 /* locate the desired phy and lane */ 2002 SOC_IF_ERROR_RETURN(_viper_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 2003 2004 /* Make a copy of the phy access and overwrite the desired lane */ 2005 pm_phy = &p_phy->pm_phy; 2006 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 2007 pm_phy_copy.access.lane_mask = lane_map; 2008 2009 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 2010 phymod_rx.vga.enable = TRUE; 2011 phymod_rx.vga.value = value; 2012 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(pm_phy, &phymod_rx)); 2013 2014 return(SOC_E_NONE); 2015 } 2016 2017 2018 STATIC int 2019 viper_rx_tap_release(soc_phymod_ctrl_t *pmc, int tap) 2020 { 2021 phymod_phy_access_t *pm_phy; 2022 phymod_rx_t phymod_rx; 2023 int idx; 2024 2025 /* bounds check "tap" */ 2026 if (tap < 0 || tap >= COUNTOF(phymod_rx.dfe)) { 2027 return SOC_E_INTERNAL; 2028 } 2029 2030 /* loop through all cores */ 2031 for (idx = 0; idx < pmc->num_phys; idx++) { 2032 pm_phy = &pmc->phy[idx]->pm_phy; 2033 2034 if (pm_phy == NULL) { 2035 return SOC_E_INTERNAL; 2036 } 2037 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(pm_phy, &phymod_rx)); 2038 phymod_rx.dfe[tap].enable = FALSE; 2039 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(pm_phy, &phymod_rx)); 2040 } 2041 return(SOC_E_NONE); 2042 } 2043 2044 /* 2045 * viper_rx_tap_set 2046 */ 2047 STATIC int 2048 viper_rx_tap_set(soc_phymod_ctrl_t *pmc, int tap, uint32 value) 2049 { 2050 phymod_phy_access_t *pm_phy; 2051 phymod_rx_t phymod_rx; 2052 int idx; 2053 2054 /* bounds check "tap" */ 2055 if (tap < 0 || tap >= COUNTOF(phymod_rx.dfe)) { 2056 return SOC_E_INTERNAL; 2057 } 2058 2059 /* loop through all cores */ 2060 for (idx = 0; idx < pmc->num_phys; idx++) { 2061 pm_phy = &pmc->phy[idx]->pm_phy; 2062 2063 if (pm_phy == NULL) { 2064 return SOC_E_INTERNAL; 2065 } 2066 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(pm_phy, &phymod_rx)); 2067 phymod_rx.dfe[tap].enable = TRUE; 2068 phymod_rx.dfe[tap].value = value; 2069 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(pm_phy, &phymod_rx)); 2070 } 2071 2072 return(SOC_E_NONE); 2073 } 2074 2075 /* 2076 * viper_pi_control_set 2077 */ 2078 STATIC int 2079 viper_pi_control_set(soc_phymod_ctrl_t *pmc, uint32 value) 2080 { 2081 phymod_phy_access_t *pm_phy; 2082 phymod_tx_override_t tx_override; 2083 int idx; 2084 2085 /* loop through all cores */ 2086 for (idx = 0; idx < pmc->num_phys; idx++) { 2087 pm_phy = &pmc->phy[idx]->pm_phy; 2088 2089 if (pm_phy == NULL) { 2090 return SOC_E_INTERNAL; 2091 } 2092 2093 phymod_tx_override_t_init(&tx_override); 2094 tx_override.phase_interpolator.enable = (value == 0) ? 0 : 1; 2095 tx_override.phase_interpolator.value = value; 2096 SOC_IF_ERROR_RETURN(phymod_phy_tx_override_set(pm_phy, &tx_override)); 2097 } 2098 2099 return(SOC_E_NONE); 2100 } 2101 2102 /* 2103 * viper_tx_polarity_set 2104 */ 2105 STATIC int 2106 viper_tx_polarity_set(soc_phymod_ctrl_t *pmc, phymod_polarity_t *cfg_polarity, uint32 value) 2107 { 2108 phymod_phy_access_t *pm_phy; 2109 phymod_polarity_t polarity; 2110 int idx; 2111 2112 /* loop through all cores */ 2113 for (idx = 0; idx < pmc->num_phys; idx++) { 2114 pm_phy = &pmc->phy[idx]->pm_phy; 2115 2116 if (pm_phy == NULL) { 2117 return SOC_E_INTERNAL; 2118 } 2119 2120 sal_memcpy(&polarity, cfg_polarity, sizeof(polarity)); 2121 polarity.tx_polarity = value; 2122 SOC_IF_ERROR_RETURN(phymod_phy_polarity_set(pm_phy, &polarity)); 2123 2124 /* after successfully setting the parity, update the configured value */ 2125 cfg_polarity->tx_polarity = value; 2126 } 2127 2128 return(SOC_E_NONE); 2129 } 2130 2131 /* 2132 * viper_rx_polarity_set 2133 */ 2134 2135 STATIC int 2136 viper_rx_polarity_set(soc_phymod_ctrl_t *pmc, phymod_polarity_t *cfg_polarity, uint32 value) 2137 { 2138 phymod_phy_access_t *pm_phy; 2139 phymod_polarity_t polarity; 2140 int idx; 2141 2142 /* loop through all cores */ 2143 for (idx = 0; idx < pmc->num_phys; idx++) { 2144 pm_phy = &pmc->phy[idx]->pm_phy; 2145 2146 if (pm_phy == NULL) { 2147 return SOC_E_INTERNAL; 2148 } 2149 2150 sal_memcpy(&polarity, cfg_polarity, sizeof(polarity)); 2151 polarity.rx_polarity = value; 2152 SOC_IF_ERROR_RETURN(phymod_phy_polarity_set(pm_phy, &polarity)); 2153 2154 /* after successfully setting the parity, update the configured value */ 2155 cfg_polarity->rx_polarity = value; 2156 } 2157 2158 return(SOC_E_NONE); 2159 } 2160 2161 /* 2162 * viper_rx_reset 2163 */ 2164 STATIC int 2165 viper_rx_reset(soc_phymod_ctrl_t *pmc, phymod_phy_reset_t *cfg_reset, uint32 value) 2166 { 2167 phymod_phy_access_t *pm_phy; 2168 phymod_phy_reset_t reset; 2169 int idx; 2170 2171 /* loop through all cores */ 2172 for (idx = 0; idx < pmc->num_phys; idx++) { 2173 pm_phy = &pmc->phy[idx]->pm_phy; 2174 2175 if (pm_phy == NULL) { 2176 return SOC_E_INTERNAL; 2177 } 2178 2179 sal_memcpy(&reset, cfg_reset, sizeof(reset)); 2180 reset.rx = (phymod_reset_direction_t) value; 2181 SOC_IF_ERROR_RETURN(phymod_phy_reset_set(pm_phy, &reset)); 2182 2183 /* after successfully setting the parity, update the configured value */ 2184 cfg_reset->rx = (phymod_reset_direction_t) value; 2185 } 2186 2187 return(SOC_E_NONE); 2188 } 2189 2190 /* 2191 * viper_tx_reset 2192 */ 2193 STATIC int 2194 viper_tx_reset(soc_phymod_ctrl_t *pmc, phymod_phy_reset_t *cfg_reset, uint32 value) 2195 { 2196 phymod_phy_access_t *pm_phy; 2197 phymod_phy_reset_t reset; 2198 int idx; 2199 2200 /* loop through all cores */ 2201 for (idx = 0; idx < pmc->num_phys; idx++) { 2202 pm_phy = &pmc->phy[idx]->pm_phy; 2203 2204 if (pm_phy == NULL) { 2205 return SOC_E_INTERNAL; 2206 } 2207 2208 sal_memcpy(&reset, cfg_reset, sizeof(reset)); 2209 reset.tx = (phymod_reset_direction_t) value; 2210 SOC_IF_ERROR_RETURN(phymod_phy_reset_set(pm_phy, &reset)); 2211 2212 /* after successfully setting the parity, update the configured value */ 2213 cfg_reset->tx = (phymod_reset_direction_t) value; 2214 } 2215 2216 return(SOC_E_NONE); 2217 } 2218 2219 2220 STATIC int 2221 viper_lane_map_set(soc_phymod_ctrl_t *pmc, uint32 value){ 2222 int idx; 2223 phymod_lane_map_t lane_map; 2224 2225 lane_map.num_of_lanes = NUM_LANES; 2226 if(pmc->phy[0] == NULL){ 2227 return(SOC_E_INTERNAL); 2228 } 2229 for (idx=0; idx < NUM_LANES; idx++) { 2230 lane_map.lane_map_rx[idx] = (value >> (idx * 4 /* 4 bit per lane */)) & 0xf; 2231 } 2232 for (idx=0; idx < NUM_LANES; idx++) { 2233 lane_map.lane_map_tx[idx] = (value >> (16 + idx * 4 /* 4 bit per lane */)) & 0xf; 2234 } 2235 SOC_IF_ERROR_RETURN(phymod_core_lane_map_set(&pmc->phy[0]->core->pm_core, &lane_map)); 2236 return(SOC_E_NONE); 2237 } 2238 2239 2240 STATIC int 2241 viper_lane_map_get(soc_phymod_ctrl_t *pmc, uint32 *value){ 2242 int idx; 2243 phymod_lane_map_t lane_map; 2244 2245 *value = 0; 2246 if(pmc->phy[0] == NULL){ 2247 return(SOC_E_INTERNAL); 2248 } 2249 SOC_IF_ERROR_RETURN(phymod_core_lane_map_get(&pmc->phy[0]->core->pm_core, &lane_map)); 2250 if(lane_map.num_of_lanes != NUM_LANES){ 2251 return SOC_E_INTERNAL; 2252 } 2253 for (idx=0; idx < NUM_LANES; idx++) { 2254 *value += (lane_map.lane_map_rx[idx] << (idx * 4)); 2255 } 2256 for (idx=0; idx < NUM_LANES; idx++) { 2257 *value += (lane_map.lane_map_tx[idx]<< (idx * 4 + 16 )); 2258 } 2259 2260 return(SOC_E_NONE); 2261 } 2262 2263 2264 2265 STATIC int 2266 viper_pattern_len_set(soc_phymod_ctrl_t *pmc, uint32_t value) 2267 { 2268 phymod_phy_access_t *pm_phy; 2269 phymod_pattern_t phymod_pattern; 2270 int idx; 2271 2272 /* loop through all cores */ 2273 for (idx = 0; idx < pmc->num_phys; idx++) { 2274 pm_phy = &pmc->phy[idx]->pm_phy; 2275 2276 if (pm_phy == NULL) { 2277 return SOC_E_INTERNAL; 2278 } 2279 2280 phymod_pattern_t_init(&phymod_pattern); 2281 SOC_IF_ERROR_RETURN 2282 (phymod_phy_pattern_config_get(pm_phy, &phymod_pattern)); 2283 phymod_pattern.pattern_len = value; 2284 SOC_IF_ERROR_RETURN(phymod_phy_pattern_config_set(pm_phy, &phymod_pattern)); 2285 } 2286 return(SOC_E_NONE); 2287 } 2288 2289 STATIC int 2290 viper_pattern_enable_set(soc_phymod_ctrl_t *pmc, uint32_t value) 2291 { 2292 phymod_phy_access_t *pm_phy; 2293 phymod_pattern_t phymod_pattern; 2294 int idx; 2295 2296 /* loop through all cores */ 2297 for (idx = 0; idx < pmc->num_phys; idx++) { 2298 pm_phy = &pmc->phy[idx]->pm_phy; 2299 2300 if (pm_phy == NULL) { 2301 return SOC_E_INTERNAL; 2302 } 2303 2304 phymod_pattern_t_init(&phymod_pattern); 2305 SOC_IF_ERROR_RETURN 2306 (phymod_phy_pattern_config_get(pm_phy, &phymod_pattern)); 2307 SOC_IF_ERROR_RETURN(phymod_phy_pattern_enable_set(pm_phy, value, &phymod_pattern)); 2308 } 2309 return(SOC_E_NONE); 2310 } 2311 2312 /* 2313 * viper_pattern_data_set 2314 * Sets 32 bits of the 256 bit data pattern. 2315 */ 2316 STATIC int 2317 viper_pattern_data_set(int idx, viper_pattern_t *pattern, uint32 value) 2318 { 2319 if ((idx<0) || (idx >= COUNTOF(pattern->pattern_data))) { 2320 return SOC_E_INTERNAL; 2321 } 2322 2323 /* update pattern data */ 2324 pattern->pattern_data[idx] = value; 2325 2326 return(SOC_E_NONE); 2327 } 2328 2329 /* 2330 * viper_per_lane_prbs_poly_set 2331 */ 2332 STATIC int 2333 viper_per_lane_prbs_poly_set(soc_phymod_ctrl_t *pmc, int lane, uint32 value) 2334 { 2335 return(SOC_E_UNAVAIL); 2336 } 2337 2338 2339 STATIC 2340 int 2341 viper_sdk_poly_to_phymod_poly(uint32 sdk_poly, phymod_prbs_poly_t *phymod_poly){ 2342 switch(sdk_poly){ 2343 case SOC_PHY_PRBS_POLYNOMIAL_X7_X6_1: 2344 *phymod_poly = phymodPrbsPoly7; 2345 break; 2346 case SOC_PHY_PRBS_POLYNOMIAL_X15_X14_1: 2347 *phymod_poly = phymodPrbsPoly15; 2348 break; 2349 case SOC_PHY_PRBS_POLYNOMIAL_X23_X18_1: 2350 *phymod_poly = phymodPrbsPoly23; 2351 break; 2352 case SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1: 2353 *phymod_poly = phymodPrbsPoly31; 2354 break; 2355 case SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1: 2356 *phymod_poly = phymodPrbsPoly9; 2357 break; 2358 case SOC_PHY_PRBS_POLYNOMIAL_X11_X9_1: 2359 *phymod_poly = phymodPrbsPoly11; 2360 break; 2361 case SOC_PHY_PRBS_POLYNOMIAL_X58_X31_1: 2362 *phymod_poly = phymodPrbsPoly58; 2363 break; 2364 default: 2365 return SOC_E_INTERNAL; 2366 } 2367 return SOC_E_NONE; 2368 } 2369 2370 /* 2371 * viper_prbs_tx_poly_set 2372 */ 2373 STATIC int 2374 viper_prbs_tx_poly_set(soc_phymod_ctrl_t *pmc, uint32 value) 2375 { 2376 phymod_phy_access_t *pm_phy; 2377 phymod_prbs_t prbs; 2378 uint32_t flags = 0; 2379 int idx; 2380 2381 for (idx = 0; idx < pmc->num_phys; idx++) { 2382 if (pmc->phy[idx] == NULL) { 2383 return SOC_E_INTERNAL; 2384 } 2385 pm_phy = &pmc->phy[idx]->pm_phy; 2386 if (pm_phy == NULL) { 2387 return SOC_E_INTERNAL; 2388 } 2389 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 2390 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(pm_phy, flags, &prbs)); 2391 SOC_IF_ERROR_RETURN(viper_sdk_poly_to_phymod_poly(value, &prbs.poly)); 2392 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(pm_phy, flags, &prbs)); 2393 } 2394 return(SOC_E_NONE); 2395 } 2396 2397 /* 2398 * viper_prbs_rx_poly_set 2399 */ 2400 STATIC int 2401 viper_prbs_rx_poly_set(soc_phymod_ctrl_t *pmc, uint32 value) 2402 { 2403 phymod_phy_access_t *pm_phy; 2404 phymod_prbs_t prbs; 2405 uint32_t flags = 0; 2406 int idx; 2407 2408 for (idx = 0; idx < pmc->num_phys; idx++) { 2409 if (pmc->phy[idx] == NULL) { 2410 return SOC_E_INTERNAL; 2411 } 2412 pm_phy = &pmc->phy[idx]->pm_phy; 2413 if (pm_phy == NULL) { 2414 return SOC_E_INTERNAL; 2415 } 2416 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 2417 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(pm_phy, flags, &prbs)); 2418 SOC_IF_ERROR_RETURN(viper_sdk_poly_to_phymod_poly(value, &prbs.poly)); 2419 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(pm_phy, flags, &prbs)); 2420 } 2421 return(SOC_E_NONE); 2422 } 2423 2424 2425 /* 2426 * viper_per_lane_prbs_tx_invert_data_set 2427 */ 2428 STATIC int 2429 viper_per_lane_prbs_tx_invert_data_set(soc_phymod_ctrl_t *pmc, int lane, uint32 value) 2430 { 2431 return(SOC_E_UNAVAIL); 2432 } 2433 2434 /* 2435 * viper_prbs_tx_invert_data_set 2436 */ 2437 STATIC int 2438 viper_prbs_tx_invert_data_set(soc_phymod_ctrl_t *pmc, uint32 value) 2439 { 2440 phymod_phy_access_t *pm_phy; 2441 phymod_prbs_t prbs; 2442 uint32_t flags = 0; 2443 int idx; 2444 2445 for (idx = 0; idx < pmc->num_phys; idx++) { 2446 if (pmc->phy[idx] == NULL) { 2447 return SOC_E_INTERNAL; 2448 } 2449 pm_phy = &pmc->phy[idx]->pm_phy; 2450 if (pm_phy == NULL) { 2451 return SOC_E_INTERNAL; 2452 } 2453 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 2454 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(pm_phy, flags, &prbs)); 2455 prbs.invert = value; 2456 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(pm_phy, flags, &prbs)); 2457 } 2458 return(SOC_E_NONE); 2459 } 2460 2461 /* 2462 * viper_prbs_rx_invert_data_set 2463 */ 2464 STATIC int 2465 viper_prbs_rx_invert_data_set(soc_phymod_ctrl_t *pmc, uint32 value) 2466 { 2467 phymod_phy_access_t *pm_phy; 2468 phymod_prbs_t prbs; 2469 uint32_t flags = 0; 2470 int idx; 2471 2472 for (idx = 0; idx < pmc->num_phys; idx++) { 2473 if (pmc->phy[idx] == NULL) { 2474 return SOC_E_INTERNAL; 2475 } 2476 pm_phy = &pmc->phy[idx]->pm_phy; 2477 if (pm_phy == NULL) { 2478 return SOC_E_INTERNAL; 2479 } 2480 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 2481 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(pm_phy, flags, &prbs)); 2482 prbs.invert = value; 2483 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_set(pm_phy, flags, &prbs)); 2484 } 2485 return(SOC_E_NONE); 2486 } 2487 2488 /* 2489 * viper_per_lane_prbs_tx_enable_set 2490 */ 2491 STATIC int 2492 viper_per_lane_prbs_tx_enable_set(soc_phymod_ctrl_t *pmc, int lane, uint32 value) 2493 { 2494 return(SOC_E_UNAVAIL); 2495 } 2496 /* 2497 * viper_prbs_tx_enable_set 2498 */ 2499 STATIC int 2500 viper_prbs_tx_enable_set(soc_phymod_ctrl_t *pmc, uint32 value) 2501 { 2502 phymod_phy_access_t *pm_phy; 2503 uint32_t flags = 0; 2504 int idx; 2505 2506 for (idx = 0; idx < pmc->num_phys; idx++) { 2507 if (pmc->phy[idx] == NULL) { 2508 return SOC_E_INTERNAL; 2509 } 2510 pm_phy = &pmc->phy[idx]->pm_phy; 2511 if (pm_phy == NULL) { 2512 return SOC_E_INTERNAL; 2513 } 2514 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 2515 SOC_IF_ERROR_RETURN(phymod_phy_prbs_enable_set(pm_phy, flags, value)); 2516 } 2517 return(SOC_E_NONE); 2518 } 2519 2520 /* 2521 * viper_prbs_rx_enable_set 2522 */ 2523 STATIC int 2524 viper_prbs_rx_enable_set(soc_phymod_ctrl_t *pmc, uint32 value) 2525 { 2526 phymod_phy_access_t *pm_phy; 2527 uint32_t flags = 0; 2528 int idx; 2529 2530 for (idx = 0; idx < pmc->num_phys; idx++) { 2531 if (pmc->phy[idx] == NULL) { 2532 return SOC_E_INTERNAL; 2533 } 2534 pm_phy = &pmc->phy[idx]->pm_phy; 2535 if (pm_phy == NULL) { 2536 return SOC_E_INTERNAL; 2537 } 2538 2539 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 2540 SOC_IF_ERROR_RETURN(phymod_phy_prbs_enable_set(pm_phy, flags, value)); 2541 } 2542 return(SOC_E_NONE); 2543 } 2544 2545 /* 2546 * viper_loopback_internal_set 2547 */ 2548 STATIC int 2549 viper_loopback_internal_set(soc_phymod_ctrl_t *pmc, uint32 value) 2550 { 2551 phymod_phy_access_t *pm_phy; 2552 int idx; 2553 2554 for (idx = 0; idx < pmc->num_phys; idx++) { 2555 if (pmc->phy[idx] == NULL) { 2556 return SOC_E_INTERNAL; 2557 } 2558 pm_phy = &pmc->phy[idx]->pm_phy; 2559 if (pm_phy == NULL) { 2560 return SOC_E_INTERNAL; 2561 } 2562 2563 SOC_IF_ERROR_RETURN 2564 (phymod_phy_loopback_set(pm_phy, phymodLoopbackGlobal, value)); 2565 } 2566 return(SOC_E_NONE); 2567 } 2568 2569 /* 2570 * viper_loopback_internal_pmd_set 2571 */ 2572 STATIC int 2573 viper_loopback_internal_pmd_set(soc_phymod_ctrl_t *pmc, uint32 value) 2574 { 2575 phymod_phy_access_t *pm_phy; 2576 int idx; 2577 2578 for (idx = 0; idx < pmc->num_phys; idx++) { 2579 if (pmc->phy[idx] == NULL) { 2580 return SOC_E_INTERNAL; 2581 } 2582 pm_phy = &pmc->phy[idx]->pm_phy; 2583 if (pm_phy == NULL) { 2584 return SOC_E_INTERNAL; 2585 } 2586 2587 SOC_IF_ERROR_RETURN 2588 (phymod_phy_loopback_set(pm_phy, phymodLoopbackGlobalPMD, value)); 2589 } 2590 return(SOC_E_NONE); 2591 } 2592 2593 /* 2594 * viper_loopback_remote_set 2595 */ 2596 STATIC int 2597 viper_loopback_remote_set(soc_phymod_ctrl_t *pmc, uint32 value) 2598 { 2599 phymod_phy_access_t *pm_phy; 2600 int idx; 2601 2602 for (idx = 0; idx < pmc->num_phys; idx++) { 2603 if (pmc->phy[idx] == NULL) { 2604 return SOC_E_INTERNAL; 2605 } 2606 pm_phy = &pmc->phy[idx]->pm_phy; 2607 if (pm_phy == NULL) { 2608 return SOC_E_INTERNAL; 2609 } 2610 2611 SOC_IF_ERROR_RETURN 2612 (phymod_phy_loopback_set(pm_phy, phymodLoopbackRemotePMD, value)); 2613 } 2614 return(SOC_E_NONE); 2615 } 2616 2617 /* 2618 * viper_loopback_remote_pcs_set 2619 */ 2620 STATIC int 2621 viper_loopback_remote_pcs_set(soc_phymod_ctrl_t *pmc, uint32 value) 2622 { 2623 phymod_phy_access_t *pm_phy; 2624 int idx; 2625 2626 for (idx = 0; idx < pmc->num_phys; idx++) { 2627 if (pmc->phy[idx] == NULL) { 2628 return SOC_E_INTERNAL; 2629 } 2630 pm_phy = &pmc->phy[idx]->pm_phy; 2631 if (pm_phy == NULL) { 2632 return SOC_E_INTERNAL; 2633 } 2634 2635 SOC_IF_ERROR_RETURN 2636 (phymod_phy_loopback_set(pm_phy, phymodLoopbackRemotePCS, value)); 2637 } 2638 return(SOC_E_NONE); 2639 } 2640 2641 /* 2642 * viper_fec_enable_set 2643 */ 2644 STATIC int 2645 viper_fec_enable_set(soc_phymod_ctrl_t *pmc, uint32 value) 2646 { 2647 phymod_phy_access_t *pm_phy; 2648 int idx; 2649 2650 /* loop through all cores */ 2651 for (idx = 0; idx < pmc->num_phys; idx++) { 2652 pm_phy = &pmc->phy[idx]->pm_phy; 2653 2654 if (pm_phy == NULL) { 2655 return SOC_E_INTERNAL; 2656 } 2657 SOC_IF_ERROR_RETURN(phymod_phy_fec_enable_set(pm_phy, value)); 2658 } 2659 return(SOC_E_NONE); 2660 } 2661 2662 /* 2663 * viper_8b10b_set 2664 */ 2665 STATIC int 2666 viper_8b10b_set(soc_phymod_ctrl_t *pmc, uint32 value) 2667 { 2668 return(SOC_E_UNAVAIL); 2669 } 2670 2671 /* 2672 * viper_64b65b_set 2673 */ 2674 STATIC int 2675 viper_64b65b_set(soc_phymod_ctrl_t *pmc, uint32 value) 2676 { 2677 2678 return(SOC_E_UNAVAIL); 2679 } 2680 2681 /* 2682 * viper_power_set 2683 */ 2684 STATIC int 2685 viper_power_set(soc_phymod_ctrl_t *pmc, uint32 value) 2686 { 2687 phymod_phy_access_t *pm_phy; 2688 phymod_phy_power_t power; 2689 int idx; 2690 2691 /* loop through all cores */ 2692 for (idx = 0; idx < pmc->num_phys; idx++) { 2693 pm_phy = &pmc->phy[idx]->pm_phy; 2694 2695 if (pm_phy == NULL) { 2696 return SOC_E_INTERNAL; 2697 } 2698 2699 phymod_phy_power_t_init(&power); 2700 if (value) { 2701 power.tx = phymodPowerOn; 2702 power.rx = phymodPowerOn; 2703 } 2704 else { 2705 power.tx = phymodPowerOff; 2706 power.rx = phymodPowerOff; 2707 } 2708 2709 SOC_IF_ERROR_RETURN(phymod_phy_power_set(pm_phy, &power)); 2710 } 2711 2712 return(SOC_E_NONE); 2713 } 2714 2715 /* 2716 * viper_per_lane_rx_low_freq_filter_set 2717 */ 2718 STATIC int 2719 viper_per_lane_rx_low_freq_filter_set(soc_phymod_ctrl_t *pmc, int lane, uint32 value) 2720 { 2721 return(SOC_E_UNAVAIL); 2722 } 2723 2724 /* 2725 * viper_rx_low_freq_filter_set 2726 */ 2727 STATIC int 2728 viper_rx_low_freq_filter_set(soc_phymod_ctrl_t *pmc, uint32 value) 2729 { 2730 phymod_phy_access_t *pm_phy; 2731 phymod_rx_t phymod_rx; 2732 int idx; 2733 2734 /* loop through all cores */ 2735 for (idx = 0; idx < pmc->num_phys; idx++) { 2736 pm_phy = &pmc->phy[idx]->pm_phy; 2737 2738 if (pm_phy == NULL) { 2739 return SOC_E_INTERNAL; 2740 } 2741 2742 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(pm_phy, &phymod_rx)); 2743 2744 phymod_rx.low_freq_peaking_filter.enable = TRUE; 2745 phymod_rx.low_freq_peaking_filter.value = value; 2746 SOC_IF_ERROR_RETURN(phymod_phy_rx_set(pm_phy, &phymod_rx)); 2747 } 2748 2749 return(SOC_E_NONE); 2750 } 2751 2752 /* 2753 * viper_tx_ppm_adjust_set 2754 */ 2755 STATIC int 2756 viper_tx_ppm_adjust_set(soc_phymod_ctrl_t *pmc, uint32 value) 2757 { 2758 phymod_phy_access_t *pm_phy; 2759 phymod_tx_override_t tx_override; 2760 int idx; 2761 2762 /* loop through all cores */ 2763 for (idx = 0; idx < pmc->num_phys; idx++) { 2764 pm_phy = &pmc->phy[idx]->pm_phy; 2765 2766 if (pm_phy == NULL) { 2767 return SOC_E_INTERNAL; 2768 } 2769 2770 tx_override.phase_interpolator.enable = 1; 2771 tx_override.phase_interpolator.value = value; 2772 SOC_IF_ERROR_RETURN(phymod_phy_tx_override_set(pm_phy, &tx_override)); 2773 } 2774 return(SOC_E_NONE); 2775 } 2776 2777 #if 0 2778 /* 2779 * viper_vco_freq_set 2780 */ 2781 STATIC int 2782 viper__vco_freq_set(soc_phymod_ctrl_t *pmc, uint32 value) 2783 { 2784 /* 2785 The following 3 controls are used to override pre-defined speed in the phy. 2786 What we discussed in SJ is that in case of rate which is not officially supported the driver will try to 2787 understand this parameters by itself. 2788 Questions: 2789 1. Do we want to support direct configuration of PLL\OS? 2790 2. If yes - same API or new API 2791 2792 phymod_phy_interface_config_set (?) 2793 */ 2794 2795 return(SOC_E_UNAVAIL); 2796 } 2797 #endif 2798 /* 2799 * viper_pll_divider_set 2800 */ 2801 STATIC int 2802 viper_pll_divider_set(soc_phymod_ctrl_t *pmc, uint32 value) 2803 { 2804 return(SOC_E_UNAVAIL); 2805 } 2806 2807 /* 2808 * viper_oversample_mode_set 2809 */ 2810 STATIC int 2811 viper_oversample_mode_set(soc_phymod_ctrl_t *pmc, uint32 value) 2812 { 2813 return(SOC_E_UNAVAIL); 2814 } 2815 2816 /* 2817 * viper_ref_clk_set 2818 */ 2819 STATIC int 2820 viper_ref_clk_set(soc_phymod_ctrl_t *pmc, uint32 value) 2821 { 2822 return(SOC_E_UNAVAIL); 2823 } 2824 2825 /* 2826 * viper_rx_seq_toggle_set 2827 */ 2828 STATIC int 2829 viper_rx_seq_toggle_set(soc_phymod_ctrl_t *pmc) 2830 { 2831 phymod_phy_access_t *pm_phy; 2832 int idx; 2833 2834 /* loop through all cores */ 2835 for (idx = 0; idx < pmc->num_phys; idx++) { 2836 if (pmc->phy[idx] == NULL) { 2837 return(SOC_E_INTERNAL); 2838 } 2839 2840 pm_phy = &pmc->phy[idx]->pm_phy; 2841 if (pm_phy == NULL) { 2842 return(SOC_E_INTERNAL); 2843 } 2844 SOC_IF_ERROR_RETURN(phymod_phy_rx_restart(pm_phy)); 2845 } 2846 2847 return(SOC_E_NONE); 2848 } 2849 2850 /* 2851 * viper_eee_set 2852 */ 2853 STATIC int 2854 viper_eee_set(soc_phymod_ctrl_t *pmc, uint32 value) 2855 { 2856 phymod_phy_access_t *pm_phy; 2857 int idx; 2858 2859 /* loop through all cores */ 2860 for (idx = 0; idx < pmc->num_phys; idx++) { 2861 if (pmc->phy[idx] == NULL) { 2862 return(SOC_E_INTERNAL); 2863 } 2864 2865 pm_phy = &pmc->phy[idx]->pm_phy; 2866 if (pm_phy == NULL) { 2867 return(SOC_E_INTERNAL); 2868 } 2869 SOC_IF_ERROR_RETURN(phymod_phy_eee_set(pm_phy, value)); 2870 } 2871 2872 return(SOC_E_NONE); 2873 } 2874 2875 STATIC int 2876 viper_control_linkdown_transmit_set(soc_phymod_ctrl_t *pmc, uint32 value) 2877 { 2878 phymod_phy_access_t *pm_phy; 2879 int idx; 2880 2881 /* loop through all cores */ 2882 for (idx = 0; idx < pmc->num_phys; idx++) { 2883 if (pmc->phy[idx] == NULL) { 2884 return(SOC_E_INTERNAL); 2885 } 2886 2887 pm_phy = &pmc->phy[idx]->pm_phy; 2888 if (pm_phy == NULL) { 2889 return(SOC_E_INTERNAL); 2890 } 2891 SOC_IF_ERROR_RETURN(phymod_phy_linkdown_transmit_set(pm_phy, value)); 2892 } 2893 2894 return(SOC_E_NONE); 2895 } 2896 2897 STATIC int 2898 viper_control_linkdown_transmit_get(soc_phymod_ctrl_t *pmc, uint32 *value) 2899 { 2900 phymod_phy_access_t *pm_phy; 2901 2902 /* just take the value from the first phy */ 2903 if (pmc->phy[0] == NULL) { 2904 return SOC_E_INTERNAL; 2905 } 2906 pm_phy = &pmc->phy[0]->pm_phy; 2907 2908 if (pm_phy == NULL) { 2909 return SOC_E_INTERNAL; 2910 } 2911 2912 SOC_IF_ERROR_RETURN(phymod_phy_linkdown_transmit_get(pm_phy, value)); 2913 2914 return(SOC_E_NONE); 2915 } 2916 2917 /* 2918 * viper_driver_supply_set 2919 */ 2920 STATIC int 2921 viper_driver_supply_set(soc_phymod_ctrl_t *pmc, uint32 value) 2922 { 2923 return(SOC_E_UNAVAIL); 2924 } 2925 2926 #if 0 2927 STATIC int 2928 viper_user_speed_set(soc_phymod_ctrl_t *pmc, 2929 phymod_pcs_userspeed_mode_t mode, 2930 phymod_pcs_userspeed_param_t param, 2931 uint32 value) 2932 { 2933 phymod_phy_access_t *pm_phy; 2934 soc_phymod_phy_t *p_phy; 2935 phymod_pcs_userspeed_config_t config ; 2936 int idx; 2937 uint32 lane_map; 2938 2939 SOC_IF_ERROR_RETURN(_viper_find_soc_phy_lane(pmc, 0, &p_phy, &lane_map)); 2940 config.mode = mode ; 2941 config.param = param ; 2942 config.current_entry = (lane_map&0x1)? 0:((lane_map&0x2)? 1:((lane_map&0x4)? 2: ((lane_map&0x8)? 3:0))); 2943 config.value = value ; 2944 2945 /* loop through all cores */ 2946 for (idx = 0; idx < pmc->num_phys; idx++) { 2947 if (pmc->phy[idx] == NULL) { 2948 return(SOC_E_INTERNAL); 2949 } 2950 2951 pm_phy = &pmc->phy[idx]->pm_phy; 2952 if (pm_phy == NULL) { 2953 return(SOC_E_INTERNAL); 2954 } 2955 SOC_IF_ERROR_RETURN(phymod_phy_pcs_userspeed_set(pm_phy, &config)); 2956 } 2957 2958 return(SOC_E_NONE); 2959 } 2960 2961 2962 STATIC int 2963 viper_user_speed_get(soc_phymod_ctrl_t *pmc, 2964 phymod_pcs_userspeed_mode_t mode, 2965 phymod_pcs_userspeed_param_t param, 2966 uint32 *value) 2967 { 2968 phymod_phy_access_t *pm_phy; 2969 soc_phymod_phy_t *p_phy; 2970 phymod_pcs_userspeed_config_t config ; 2971 int idx; 2972 uint32 lane_map; 2973 2974 SOC_IF_ERROR_RETURN(_viper_find_soc_phy_lane(pmc, 0, &p_phy, &lane_map)); 2975 config.mode = mode ; 2976 config.param = param ; 2977 config.current_entry = (lane_map&0x1)? 0:((lane_map&0x2)? 1:((lane_map&0x4)? 2: ((lane_map&0x8)? 3:0))); 2978 config.value = 0 ; 2979 2980 *value = 0 ; 2981 2982 /* loop through all cores */ 2983 for (idx = 0; idx < pmc->num_phys; idx++) { 2984 if (pmc->phy[idx] == NULL) { 2985 return(SOC_E_INTERNAL); 2986 } 2987 2988 pm_phy = &pmc->phy[idx]->pm_phy; 2989 if (pm_phy == NULL) { 2990 return(SOC_E_INTERNAL); 2991 } 2992 2993 SOC_IF_ERROR_RETURN(phymod_phy_pcs_userspeed_get(pm_phy, &config)); 2994 *value = config.value ; 2995 } 2996 2997 return(SOC_E_NONE); 2998 } 2999 #endif 3000 /* 3001 * Function: 3002 * phy_viper_control_set 3003 * Purpose: 3004 * Configure PHY device specific control fucntion. 3005 * Parameters: 3006 * unit - BCM unit number. 3007 * port - Port number. 3008 * type - Control to update 3009 * value - New setting for the control 3010 * Returns: 3011 * SOC_E_NONE 3012 */ 3013 STATIC int 3014 phy_viper_control_set(int unit, soc_port_t port, soc_phy_control_t type, uint32 value) 3015 { 3016 int rv; 3017 phy_ctrl_t *pc; 3018 soc_phymod_ctrl_t *pmc; 3019 viper_config_t *pCfg; 3020 3021 rv = SOC_E_UNAVAIL; 3022 3023 /* coverity[mixed_enums] */ 3024 if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) { 3025 return (SOC_E_PARAM); 3026 } 3027 3028 /* locate phy control, phymod control, and the configuration data */ 3029 pc = INT_PHY_SW_STATE(unit, port); 3030 if (pc == NULL) { 3031 return SOC_E_INTERNAL; 3032 } 3033 pmc = &pc->phymod_ctrl; 3034 pCfg = (viper_config_t *) pc->driver_data; 3035 3036 switch(type) { 3037 3038 case SOC_PHY_CONTROL_TX_FIR_PRE: 3039 rv = SOC_E_UNAVAIL; 3040 break; 3041 case SOC_PHY_CONTROL_TX_FIR_MAIN: 3042 rv = viper_tx_fir_main_set(pmc, value); 3043 break; 3044 case SOC_PHY_CONTROL_TX_FIR_POST: 3045 rv = viper_tx_fir_post_set(pmc, value); 3046 break; 3047 #if 0 3048 case SOC_PHY_CONTROL_TX_FIR_POST2: 3049 rv = viper_tx_fir_post2_set(pmc, value); 3050 break; 3051 case SOC_PHY_CONTROL_TX_FIR_POST3: 3052 rv = viper_tx_fir_post3_set(pmc, value); 3053 break; 3054 #endif 3055 /* PREEMPHASIS */ 3056 case SOC_PHY_CONTROL_PREEMPHASIS_LANE0: 3057 rv = viper_per_lane_preemphasis_set(pmc, 0, value); 3058 break; 3059 case SOC_PHY_CONTROL_PREEMPHASIS_LANE1: 3060 rv = viper_per_lane_preemphasis_set(pmc, 1, value); 3061 break; 3062 case SOC_PHY_CONTROL_PREEMPHASIS_LANE2: 3063 rv = viper_per_lane_preemphasis_set(pmc, 2, value); 3064 break; 3065 case SOC_PHY_CONTROL_PREEMPHASIS_LANE3: 3066 rv = viper_per_lane_preemphasis_set(pmc, 3, value); 3067 break; 3068 case SOC_PHY_CONTROL_PREEMPHASIS: 3069 rv = viper_preemphasis_set(pmc, value); 3070 break; 3071 3072 /* DRIVER CURRENT */ 3073 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0: 3074 rv = SOC_E_UNAVAIL; 3075 break; 3076 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1: 3077 rv = SOC_E_UNAVAIL; 3078 break; 3079 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2: 3080 rv = SOC_E_UNAVAIL; 3081 break; 3082 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3: 3083 rv = SOC_E_UNAVAIL; 3084 break; 3085 case SOC_PHY_CONTROL_DRIVER_CURRENT: 3086 rv = SOC_E_UNAVAIL; 3087 break; 3088 3089 /* PRE_DRIVER CURRENT not supported anymore */ 3090 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0: 3091 rv = SOC_E_UNAVAIL; 3092 break; 3093 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1: 3094 rv = SOC_E_UNAVAIL; 3095 break; 3096 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2: 3097 rv = SOC_E_UNAVAIL; 3098 break; 3099 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3: 3100 rv = SOC_E_UNAVAIL; 3101 break; 3102 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 3103 rv = SOC_E_UNAVAIL; 3104 break; 3105 3106 /* POST2_DRIVER CURRENT not supported anymore */ 3107 case SOC_PHY_CONTROL_DRIVER_POST2_CURRENT: 3108 rv = SOC_E_UNAVAIL; 3109 break; 3110 case SOC_PHY_CONTROL_DUMP: 3111 /* "N/A: will be part of common phymod application" */ 3112 /* was rv = tscmod_uc_status_dump(unit, port); */ 3113 break; 3114 3115 /* TX LANE SQUELCH */ 3116 case SOC_PHY_CONTROL_TX_LANE_SQUELCH: 3117 rv = viper_tx_lane_squelch(pmc, value); 3118 break; 3119 3120 /* RX PEAK FILTER */ 3121 case SOC_PHY_CONTROL_RX_PEAK_FILTER: 3122 rv = viper_rx_peak_filter_set(pmc, value); 3123 break; 3124 3125 /* RX VGA */ 3126 case SOC_PHY_CONTROL_RX_VGA: 3127 rv = SOC_E_UNAVAIL; 3128 break; 3129 3130 /* RX TAP */ 3131 case SOC_PHY_CONTROL_RX_TAP1: 3132 rv = viper_rx_tap_set(pmc, 0, value); 3133 break; 3134 case SOC_PHY_CONTROL_RX_TAP2: 3135 rv = viper_rx_tap_set(pmc, 1, value); 3136 break; 3137 case SOC_PHY_CONTROL_RX_TAP3: 3138 rv = viper_rx_tap_set(pmc, 2, value); 3139 break; 3140 case SOC_PHY_CONTROL_RX_TAP4: 3141 rv = viper_rx_tap_set(pmc, 3, value); 3142 break; 3143 case SOC_PHY_CONTROL_RX_TAP5: 3144 rv = viper_rx_tap_set(pmc, 4, value); 3145 break; 3146 case SOC_PHY_CONTROL_RX_TAP1_RELEASE: /* $$$ tbd $$$ */ 3147 rv = viper_rx_tap_release(pmc, 0); 3148 break; 3149 case SOC_PHY_CONTROL_RX_TAP2_RELEASE: /* $$$ tbd $$$ */ 3150 rv = viper_rx_tap_release(pmc, 1); 3151 break; 3152 case SOC_PHY_CONTROL_RX_TAP3_RELEASE: /* $$$ tbd $$$ */ 3153 rv = viper_rx_tap_release(pmc, 2); 3154 break; 3155 case SOC_PHY_CONTROL_RX_TAP4_RELEASE: /* $$$ tbd $$$ */ 3156 rv = viper_rx_tap_release(pmc, 3); 3157 break; 3158 case SOC_PHY_CONTROL_RX_TAP5_RELEASE: /* $$$ tbd $$$ */ 3159 rv = viper_rx_tap_release(pmc, 4); 3160 break; 3161 /* RX SLICER */ 3162 case SOC_PHY_CONTROL_RX_PLUS1_SLICER: 3163 rv = SOC_E_UNAVAIL; 3164 break; 3165 case SOC_PHY_CONTROL_RX_MINUS1_SLICER: 3166 rv = SOC_E_UNAVAIL; 3167 break; 3168 case SOC_PHY_CONTROL_RX_D_SLICER: 3169 rv = SOC_E_UNAVAIL; 3170 break; 3171 3172 /* PHASE INTERPOLATOR */ 3173 case SOC_PHY_CONTROL_PHASE_INTERP: 3174 rv = viper_pi_control_set(pmc, value); 3175 break; 3176 3177 /* POLARITY */ 3178 case SOC_PHY_CONTROL_RX_POLARITY: 3179 rv = viper_rx_polarity_set(pmc, &pCfg->phy_polarity_config, value);; 3180 break; 3181 case SOC_PHY_CONTROL_TX_POLARITY: 3182 rv = viper_tx_polarity_set(pmc, &pCfg->phy_polarity_config, value); 3183 break; 3184 3185 /* RESET */ 3186 case SOC_PHY_CONTROL_RX_RESET: 3187 rv = viper_rx_reset(pmc, &pCfg->phy_reset_config, value); 3188 break; 3189 case SOC_PHY_CONTROL_TX_RESET: 3190 rv = viper_tx_reset(pmc, &pCfg->phy_reset_config, value); 3191 break; 3192 /* LANE SWAP */ 3193 case SOC_PHY_CONTROL_LANE_SWAP: 3194 rv = viper_lane_map_set(pmc, value); 3195 break; 3196 /* TX PATTERN */ 3197 case SOC_PHY_CONTROL_TX_PATTERN_20BIT: 3198 rv = SOC_E_UNAVAIL; 3199 break; 3200 case SOC_PHY_CONTROL_TX_PATTERN_256BIT: 3201 rv = SOC_E_UNAVAIL; 3202 break; 3203 case SOC_PHY_CONTROL_TX_PATTERN_LENGTH: 3204 rv = viper_pattern_len_set(pmc, value); 3205 break; 3206 case SOC_PHY_CONTROL_TX_PATTERN_GEN_ENABLE: 3207 rv = viper_pattern_enable_set(pmc, value); 3208 break; 3209 case SOC_PHY_CONTROL_TX_PATTERN_DATA0: 3210 rv = viper_pattern_data_set(0, &pCfg->pattern, value); 3211 break; 3212 case SOC_PHY_CONTROL_TX_PATTERN_DATA1: 3213 rv = viper_pattern_data_set(1, &pCfg->pattern, value); 3214 break; 3215 case SOC_PHY_CONTROL_TX_PATTERN_DATA2: 3216 rv = viper_pattern_data_set(2, &pCfg->pattern, value); 3217 break; 3218 case SOC_PHY_CONTROL_TX_PATTERN_DATA3: 3219 rv = viper_pattern_data_set(3, &pCfg->pattern, value); 3220 break; 3221 case SOC_PHY_CONTROL_TX_PATTERN_DATA4: 3222 rv = viper_pattern_data_set(4, &pCfg->pattern, value); 3223 break; 3224 case SOC_PHY_CONTROL_TX_PATTERN_DATA5: 3225 rv = viper_pattern_data_set(5, &pCfg->pattern, value); 3226 break; 3227 case SOC_PHY_CONTROL_TX_PATTERN_DATA6: 3228 rv = viper_pattern_data_set(6, &pCfg->pattern, value); 3229 break; 3230 case SOC_PHY_CONTROL_TX_PATTERN_DATA7: 3231 rv = viper_pattern_data_set(7, &pCfg->pattern, value); 3232 break; 3233 3234 /* decoupled PRBS */ 3235 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_POLYNOMIAL: 3236 rv = viper_prbs_tx_poly_set(pmc, value); 3237 break; 3238 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_INVERT_DATA: 3239 rv = viper_prbs_tx_invert_data_set(pmc, value); 3240 break; 3241 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_ENABLE: 3242 rv = viper_prbs_tx_enable_set(pmc, value); 3243 break; 3244 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_POLYNOMIAL: 3245 rv = viper_prbs_rx_poly_set(pmc, value); 3246 break; 3247 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_INVERT_DATA: 3248 rv = viper_prbs_rx_invert_data_set(pmc, value); 3249 break; 3250 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_ENABLE: 3251 rv = viper_prbs_rx_enable_set(pmc, value); 3252 break; 3253 /* for legacy prbs usage mainly set both tx/rx the same */ 3254 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 3255 rv = viper_prbs_tx_poly_set(pmc, value); 3256 rv = viper_prbs_rx_poly_set(pmc, value); 3257 break; 3258 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 3259 rv = viper_prbs_tx_invert_data_set(pmc, value); 3260 break; 3261 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 3262 rv = viper_prbs_tx_enable_set(pmc, value); 3263 rv = viper_prbs_rx_enable_set(pmc, value); 3264 break; 3265 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 3266 rv = viper_prbs_tx_enable_set(pmc, value); 3267 rv = viper_prbs_rx_enable_set(pmc, value); 3268 break; 3269 3270 /* LOOPBACK */ 3271 case SOC_PHY_CONTROL_LOOPBACK_INTERNAL: 3272 rv = viper_loopback_internal_set(pmc, value); 3273 break; 3274 case SOC_PHY_CONTROL_LOOPBACK_PMD: 3275 rv = viper_loopback_internal_pmd_set(pmc, value); 3276 break; 3277 case SOC_PHY_CONTROL_LOOPBACK_REMOTE: 3278 rv = viper_loopback_remote_set(pmc, value); 3279 break; 3280 case SOC_PHY_CONTROL_LOOPBACK_REMOTE_PCS_BYPASS: 3281 rv = viper_loopback_remote_pcs_set(pmc, value); 3282 break; 3283 3284 /* FEC */ 3285 case SOC_PHY_CONTROL_FORWARD_ERROR_CORRECTION: 3286 rv = viper_fec_enable_set(pmc, value); 3287 break; 3288 3289 /* CUSTOM */ 3290 case SOC_PHY_CONTROL_CUSTOM1: 3291 /* Obsolete ?? 3292 DEV_CFG_PTR(pc)->custom1 = value? TRUE: FALSE ; 3293 rv = SOC_E_NONE; */ 3294 rv = SOC_E_UNAVAIL; 3295 break; 3296 /* 8B10B */ 3297 case SOC_PHY_CONTROL_8B10B: 3298 rv = viper_8b10b_set(pmc, value); 3299 break; 3300 3301 /* 64B65B */ 3302 case SOC_PHY_CONTROL_64B66B: 3303 rv = viper_64b65b_set(pmc, value); 3304 break; 3305 3306 /* POWER */ 3307 case SOC_PHY_CONTROL_POWER: 3308 rv = viper_power_set(pmc, value); 3309 break; 3310 3311 /* RX_LOW_FREQ_PEAK_FILTER */ 3312 case SOC_PHY_CONTROL_RX_LOW_FREQ_PEAK_FILTER: 3313 rv = viper_rx_low_freq_filter_set(pmc, value); 3314 break; 3315 3316 /* TX_PPM_ADJUST */ 3317 case SOC_PHY_CONTROL_TX_PPM_ADJUST: 3318 rv = viper_tx_ppm_adjust_set(pmc, value); 3319 break; 3320 #if 0 3321 /* VCO_FREQ */ 3322 case SOC_PHY_CONTROL_VCO_FREQ: 3323 rv = viper_vco_freq_set(pmc, value); 3324 break; 3325 #endif 3326 /* PLL_DIVIDER */ 3327 case SOC_PHY_CONTROL_PLL_DIVIDER: 3328 rv = viper_pll_divider_set(pmc, value); 3329 break; 3330 3331 /* OVERSAMPLE_MODE */ 3332 case SOC_PHY_CONTROL_OVERSAMPLE_MODE: 3333 rv = viper_oversample_mode_set(pmc, value); 3334 break; 3335 3336 /* REF_CLK */ 3337 case SOC_PHY_CONTROL_REF_CLK: 3338 rv = viper_ref_clk_set(pmc, value); 3339 break; 3340 3341 /* RX_SEQ_TOGGLE */ 3342 case SOC_PHY_CONTROL_RX_SEQ_TOGGLE: 3343 rv = viper_rx_seq_toggle_set(pmc); 3344 break; 3345 3346 /* DRIVER_SUPPLY */ 3347 case SOC_PHY_CONTROL_DRIVER_SUPPLY: 3348 rv = viper_driver_supply_set(pmc, value); 3349 break; 3350 /* EEE */ 3351 case SOC_PHY_CONTROL_EEE: 3352 rv = viper_eee_set(pmc, value); 3353 break; 3354 3355 /* EEE */ 3356 #ifdef TSC_EEE_SUPPORT 3357 case SOC_PHY_CONTROL_EEE: 3358 case SOC_PHY_CONTROL_EEE_AUTO: 3359 rv = SOC_E_NONE; /* not supported */ 3360 break; 3361 #endif 3362 case SOC_PHY_CONTROL_LINKDOWN_TRANSMIT: 3363 rv = viper_control_linkdown_transmit_set(pmc, value); 3364 break; 3365 #if 0 3366 /* Added to support WA for HW bug; probably not required. */ 3367 case SOC_PHY_CONTROL_SOFTWARE_RX_LOS: 3368 DEV_CFG_PTR(pc)->sw_rx_los.enable = (value == 0? 0: 1); 3369 DEV_CFG_PTR(pc)->sw_rx_los.sys_link = 0; 3370 DEV_CFG_PTR(pc)->sw_rx_los.state = RXLOS_RESET; 3371 DEV_CFG_PTR(pc)->sw_rx_los.link_status = 0; 3372 /* THE FLAG IS SET IN INIT. FOR TSCMOD DRIVER 3373 TO WORK IT'S LINK_GET MUST BE CALLED */ 3374 /* Manage the _SERVICE_INT_PHY_LINK_GET flag so that 3375 if external phy is present link_get for 3376 internal phy is still called to process 3377 software rx los feature 3378 if(value) { 3379 PHY_FLAGS_SET(unit, port, PHY_FLAGS_SERVICE_INT_PHY_LINK_GET); 3380 } else { 3381 PHY_FLAGS_CLR(unit, port, PHY_FLAGS_SERVICE_INT_PHY_LINK_GET); 3382 } 3383 */ 3384 rv = SOC_E_NONE; 3385 break; 3386 /* UNAVAIL */ 3387 case SOC_PHY_CONTROL_PARALLEL_DETECTION: 3388 case SOC_PHY_CONTROL_BERT_PATTERN: 3389 case SOC_PHY_CONTROL_BERT_RUN: 3390 case SOC_PHY_CONTROL_BERT_PACKET_SIZE: 3391 case SOC_PHY_CONTROL_BERT_IPG: 3392 case SOC_PHY_CONTROL_RX_PEAK_FILTER_TEMP_COMP: 3393 case SOC_PHY_CONTROL_CL73_FSM_AUTO_RECOVER: 3394 #endif 3395 default: 3396 rv = SOC_E_UNAVAIL; 3397 break; 3398 } 3399 return rv; 3400 } 3401 3402 3403 /* 3404 * viper_tx_fir_pre_get 3405 */ 3406 STATIC int 3407 viper_tx_fir_pre_get(soc_phymod_ctrl_t *pmc, uint32 *value) 3408 { 3409 phymod_phy_access_t *pm_phy; 3410 phymod_tx_t phymod_tx; 3411 int idx; 3412 3413 /* loop through all cores */ 3414 for (idx = 0; idx < pmc->num_phys; idx++) { 3415 pm_phy = &pmc->phy[idx]->pm_phy; 3416 3417 if (pm_phy == NULL) { 3418 return SOC_E_INTERNAL; 3419 } 3420 3421 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(pm_phy, &phymod_tx)); 3422 *value = phymod_tx.pre; 3423 } 3424 3425 return(SOC_E_NONE); 3426 } 3427 3428 /* 3429 * viper_tx_fir_main_get 3430 */ 3431 STATIC int 3432 viper_tx_fir_main_get(soc_phymod_ctrl_t *pmc, uint32 *value) 3433 { 3434 phymod_phy_access_t *pm_phy; 3435 phymod_tx_t phymod_tx; 3436 int idx; 3437 3438 /* loop through all cores */ 3439 for (idx = 0; idx < pmc->num_phys; idx++) { 3440 pm_phy = &pmc->phy[idx]->pm_phy; 3441 3442 if (pm_phy == NULL) { 3443 return SOC_E_INTERNAL; 3444 } 3445 3446 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(pm_phy, &phymod_tx)); 3447 *value = phymod_tx.main; 3448 } 3449 3450 return(SOC_E_NONE); 3451 } 3452 3453 /* 3454 * viper_tx_fir_post_get 3455 */ 3456 STATIC int 3457 viper_tx_fir_post_get(soc_phymod_ctrl_t *pmc, uint32 *value) 3458 { 3459 phymod_phy_access_t *pm_phy; 3460 phymod_tx_t phymod_tx; 3461 int idx; 3462 3463 /* loop through all cores */ 3464 for (idx = 0; idx < pmc->num_phys; idx++) { 3465 pm_phy = &pmc->phy[idx]->pm_phy; 3466 3467 if (pm_phy == NULL) { 3468 return SOC_E_INTERNAL; 3469 } 3470 3471 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(pm_phy, &phymod_tx)); 3472 *value = phymod_tx.post; 3473 } 3474 3475 return(SOC_E_NONE); 3476 } 3477 3478 /* 3479 * viper_tx_fir_post2_get 3480 */ 3481 STATIC int 3482 viper_tx_fir_post2_get(soc_phymod_ctrl_t *pmc, uint32 *value) 3483 { 3484 phymod_phy_access_t *pm_phy; 3485 phymod_tx_t phymod_tx; 3486 int idx; 3487 3488 /* loop through all cores */ 3489 for (idx = 0; idx < pmc->num_phys; idx++) { 3490 pm_phy = &pmc->phy[idx]->pm_phy; 3491 3492 if (pm_phy == NULL) { 3493 return SOC_E_INTERNAL; 3494 } 3495 3496 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(pm_phy, &phymod_tx)); 3497 *value = phymod_tx.post2; 3498 } 3499 3500 return(SOC_E_NONE); 3501 } 3502 3503 /* 3504 * viper_tx_fir_post3_get 3505 */ 3506 STATIC int 3507 viper_tx_fir_post3_get(soc_phymod_ctrl_t *pmc, uint32 *value) 3508 { 3509 phymod_phy_access_t *pm_phy; 3510 phymod_tx_t phymod_tx; 3511 int idx; 3512 3513 /* loop through all cores */ 3514 for (idx = 0; idx < pmc->num_phys; idx++) { 3515 pm_phy = &pmc->phy[idx]->pm_phy; 3516 3517 if (pm_phy == NULL) { 3518 return SOC_E_INTERNAL; 3519 } 3520 3521 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(pm_phy, &phymod_tx)); 3522 *value = phymod_tx.post3; 3523 } 3524 3525 return(SOC_E_NONE); 3526 } 3527 3528 /* 3529 * viper_per_lane_preemphasis_get 3530 */ 3531 STATIC int 3532 viper_per_lane_preemphasis_get(soc_phymod_ctrl_t *pmc, int lane, uint32 *value) 3533 { 3534 soc_phymod_phy_t *p_phy; 3535 uint32 lane_map; 3536 phymod_phy_access_t pm_phy_copy, *pm_phy; 3537 phymod_tx_t phymod_tx; 3538 3539 /* locate the desired phy and lane */ 3540 SOC_IF_ERROR_RETURN(_viper_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 3541 3542 /* Make a copy of the phy access and overwrite the desired lane */ 3543 pm_phy = &p_phy->pm_phy; 3544 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3545 pm_phy_copy.access.lane_mask = lane_map; 3546 3547 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 3548 *value = phymod_tx.pre | (phymod_tx.main << 8) | (phymod_tx.post << 16); 3549 3550 return(SOC_E_NONE); 3551 } 3552 3553 /* 3554 * viper_per_lane_driver_current_get 3555 */ 3556 STATIC int 3557 viper_per_lane_driver_current_get(soc_phymod_ctrl_t *pmc, int lane, uint32 *value) 3558 { 3559 soc_phymod_phy_t *p_phy; 3560 uint32 lane_map; 3561 phymod_phy_access_t pm_phy_copy, *pm_phy; 3562 phymod_tx_t phymod_tx; 3563 3564 /* locate the desired phy and lane */ 3565 SOC_IF_ERROR_RETURN(_viper_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 3566 3567 /* Make a copy of the phy access and overwrite the desired lane */ 3568 pm_phy = &p_phy->pm_phy; 3569 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3570 pm_phy_copy.access.lane_mask = lane_map; 3571 3572 SOC_IF_ERROR_RETURN(phymod_phy_tx_get(&pm_phy_copy, &phymod_tx)); 3573 *value = phymod_tx.amp; 3574 3575 return(SOC_E_NONE); 3576 } 3577 3578 /* 3579 * viper_per_lane_prbs_poly_get 3580 */ 3581 STATIC int 3582 viper_per_lane_prbs_poly_get(soc_phymod_ctrl_t *pmc, int lane, uint32 *value) 3583 { 3584 return(SOC_E_UNAVAIL); 3585 } 3586 3587 /* 3588 * viper_per_lane_prbs_tx_invert_data_get 3589 */ 3590 STATIC int 3591 viper_per_lane_prbs_tx_invert_data_get(soc_phymod_ctrl_t *pmc, int lane, uint32 *value) 3592 { 3593 return(SOC_E_UNAVAIL); 3594 } 3595 3596 /* 3597 * viper_per_lane_prbs_tx_enable_get 3598 */ 3599 STATIC int 3600 viper_per_lane_prbs_tx_enable_get(soc_phymod_ctrl_t *pmc, int lane, uint32 *value) 3601 { 3602 return(SOC_E_UNAVAIL); 3603 } 3604 3605 /* 3606 * viper_per_lane_prbs_rx_enable_get 3607 */ 3608 STATIC int 3609 viper_per_lane_prbs_rx_enable_get(soc_phymod_ctrl_t *pmc, int lane, uint32 *value) 3610 { 3611 return(SOC_E_UNAVAIL); 3612 } 3613 3614 /* 3615 * viper_per_lane_prbs_rx_status_get 3616 */ 3617 STATIC int 3618 viper_per_lane_prbs_rx_status_get(soc_phymod_ctrl_t *pmc, int lane, uint32 *value) 3619 { 3620 /* $$$ Need to add diagnostic API */ 3621 return(SOC_E_UNAVAIL); 3622 } 3623 3624 /* 3625 * viper_per_lane_rx_peak_filter_get 3626 */ 3627 STATIC int 3628 viper_per_lane_rx_peak_filter_get(soc_phymod_ctrl_t *pmc, int lane, uint32 *value) 3629 { 3630 soc_phymod_phy_t *p_phy; 3631 uint32 lane_map; 3632 phymod_phy_access_t pm_phy_copy, *pm_phy; 3633 phymod_rx_t phymod_rx; 3634 3635 *value = 0; 3636 3637 /* locate the desired phy and lane */ 3638 SOC_IF_ERROR_RETURN(_viper_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 3639 3640 /* Make a copy of the phy access and overwrite the desired lane */ 3641 pm_phy = &p_phy->pm_phy; 3642 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3643 pm_phy_copy.access.lane_mask = lane_map; 3644 3645 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 3646 if (phymod_rx.peaking_filter.enable) 3647 *value = phymod_rx.peaking_filter.value; 3648 3649 return(SOC_E_NONE); 3650 } 3651 3652 /* 3653 * viper_per_lane_rx_vga_get 3654 */ 3655 STATIC int 3656 viper_per_lane_rx_vga_get(soc_phymod_ctrl_t *pmc, int lane, uint32 *value) 3657 { 3658 soc_phymod_phy_t *p_phy; 3659 uint32 lane_map; 3660 phymod_phy_access_t pm_phy_copy, *pm_phy; 3661 phymod_rx_t phymod_rx; 3662 3663 *value = 0; 3664 3665 /* locate the desired phy and lane */ 3666 SOC_IF_ERROR_RETURN(_viper_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 3667 3668 /* Make a copy of the phy access and overwrite the desired lane */ 3669 pm_phy = &p_phy->pm_phy; 3670 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3671 pm_phy_copy.access.lane_mask = lane_map; 3672 3673 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 3674 if (phymod_rx.vga.enable) 3675 *value = phymod_rx.vga.value; 3676 3677 return(SOC_E_NONE); 3678 } 3679 3680 /* 3681 * viper_per_lane_rx_dfe_tap_control_get 3682 */ 3683 STATIC int 3684 viper_per_lane_rx_dfe_tap_control_get(soc_phymod_ctrl_t *pmc, int lane, int tap, uint32 *value) 3685 { 3686 soc_phymod_phy_t *p_phy; 3687 uint32 lane_map; 3688 phymod_phy_access_t pm_phy_copy, *pm_phy; 3689 phymod_rx_t phymod_rx; 3690 3691 *value = 0; 3692 3693 /* locate the desired phy and lane */ 3694 SOC_IF_ERROR_RETURN(_viper_find_soc_phy_lane(pmc, lane, &p_phy, &lane_map)); 3695 3696 /* Make a copy of the phy access and overwrite the desired lane */ 3697 pm_phy = &p_phy->pm_phy; 3698 sal_memcpy(&pm_phy_copy, pm_phy, sizeof(pm_phy_copy)); 3699 pm_phy_copy.access.lane_mask = lane_map; 3700 3701 if (tap < 0 || tap >= COUNTOF(phymod_rx.dfe)) { 3702 /* this can only happen with a coding error */ 3703 return SOC_E_INTERNAL; 3704 } 3705 3706 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(&pm_phy_copy, &phymod_rx)); 3707 if (phymod_rx.dfe[tap].enable) 3708 *value = phymod_rx.dfe[tap].value; 3709 3710 return(SOC_E_NONE); 3711 } 3712 3713 3714 /* 3715 * viper_per_lane_rx_low_freq_filter_get 3716 */ 3717 STATIC int 3718 viper_per_lane_rx_low_freq_filter_get(soc_phymod_ctrl_t *pmc, int lane, uint32 *value) 3719 { 3720 return(SOC_E_UNAVAIL); 3721 } 3722 3723 /* 3724 * viper_rx_peak_filter_get 3725 */ 3726 STATIC int 3727 viper_rx_peak_filter_get(soc_phymod_ctrl_t *pmc, uint32 *value) 3728 { 3729 phymod_phy_access_t *pm_phy; 3730 phymod_rx_t phymod_rx; 3731 3732 /* just take the value from the first phy */ 3733 if (pmc->phy[0] == NULL) { 3734 return SOC_E_INTERNAL; 3735 } 3736 pm_phy = &pmc->phy[0]->pm_phy; 3737 3738 if (pm_phy == NULL) { 3739 return SOC_E_INTERNAL; 3740 } 3741 3742 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(pm_phy, &phymod_rx)); 3743 *value = phymod_rx.peaking_filter.value; 3744 3745 return(SOC_E_NONE); 3746 } 3747 3748 3749 /* 3750 * viper_rx_tap_get 3751 */ 3752 STATIC int 3753 viper_rx_tap_get(soc_phymod_ctrl_t *pmc, int tap, uint32 *value) 3754 { 3755 phymod_phy_access_t *pm_phy; 3756 phymod_rx_t phymod_rx; 3757 3758 if (tap < 0 || tap >= COUNTOF(phymod_rx.dfe)) { 3759 /* this can only happen with a coding error */ 3760 return SOC_E_INTERNAL; 3761 } 3762 /* just take the value from the first phy */ 3763 if (pmc->phy[0] == NULL) { 3764 return SOC_E_INTERNAL; 3765 } 3766 pm_phy = &pmc->phy[0]->pm_phy; 3767 3768 if (pm_phy == NULL) { 3769 return SOC_E_INTERNAL; 3770 } 3771 3772 SOC_IF_ERROR_RETURN(phymod_phy_rx_get(pm_phy, &phymod_rx)); 3773 *value = phymod_rx.dfe[tap].value; 3774 3775 return(SOC_E_NONE); 3776 } 3777 3778 /* 3779 * viper_pi_control_get 3780 */ 3781 STATIC int 3782 viper_pi_control_get(soc_phymod_ctrl_t *pmc, uint32 *value) 3783 { 3784 phymod_phy_access_t *pm_phy; 3785 phymod_tx_override_t tx_override; 3786 3787 /* just take the value from the first phy */ 3788 if (pmc->phy[0] == NULL) { 3789 return SOC_E_INTERNAL; 3790 } 3791 pm_phy = &pmc->phy[0]->pm_phy; 3792 3793 if (pm_phy == NULL) { 3794 return SOC_E_INTERNAL; 3795 } 3796 3797 SOC_IF_ERROR_RETURN(phymod_phy_tx_override_get(pm_phy, &tx_override)); 3798 *value = tx_override.phase_interpolator.value; 3799 3800 return(SOC_E_NONE); 3801 } 3802 3803 /* 3804 * viper_rx_signal_detect_get 3805 */ 3806 STATIC int 3807 viper_rx_signal_detect_get(soc_phymod_ctrl_t *pmc, uint32 *value) 3808 { 3809 /* $$$ Need to add diagnostic API */ 3810 return(SOC_E_UNAVAIL); 3811 } 3812 3813 /* 3814 * viper_rx_seq_done_get 3815 */ 3816 STATIC int 3817 viper_rx_seq_done_get(soc_phymod_ctrl_t *pmc, uint32 *value) 3818 { 3819 phymod_phy_access_t *pm_phy; 3820 3821 /* just take the value from the first phy */ 3822 if (pmc->phy[pmc->main_phy] == NULL) { 3823 return SOC_E_INTERNAL; 3824 } 3825 pm_phy = &pmc->phy[pmc->main_phy]->pm_phy; 3826 3827 if (pm_phy == NULL) { 3828 return SOC_E_INTERNAL; 3829 } 3830 3831 SOC_IF_ERROR_RETURN(phymod_phy_rx_pmd_locked_get(pm_phy, value)); 3832 3833 return(SOC_E_NONE); 3834 } 3835 3836 /* 3837 * viper_eee_get 3838 */ 3839 STATIC int 3840 viper_eee_get(soc_phymod_ctrl_t *pmc, uint32 *value) 3841 { 3842 phymod_phy_access_t *pm_phy; 3843 3844 /* just take the value from the first phy */ 3845 if (pmc->phy[0] == NULL) { 3846 return SOC_E_INTERNAL; 3847 } 3848 pm_phy = &pmc->phy[0]->pm_phy; 3849 3850 if (pm_phy == NULL) { 3851 return SOC_E_INTERNAL; 3852 } 3853 3854 SOC_IF_ERROR_RETURN(phymod_phy_eee_get(pm_phy, value)); 3855 3856 return(SOC_E_NONE); 3857 } 3858 3859 3860 /* 3861 * viper_rx_ppm_get 3862 */ 3863 STATIC int 3864 viper_rx_ppm_get(soc_phymod_ctrl_t *pmc, uint32 *value) 3865 { 3866 /* $$$ Need to add diagnostic API */ 3867 return(SOC_E_UNAVAIL); 3868 } 3869 3870 /* 3871 * viper_prbs_tx_poly_get 3872 */ 3873 STATIC int 3874 viper_prbs_tx_poly_get(soc_phymod_ctrl_t *pmc, uint32 *value) 3875 { 3876 phymod_phy_access_t *pm_phy; 3877 phymod_prbs_t prbs; 3878 uint32_t flags = 0; 3879 3880 /* just take the value from the first phy */ 3881 if (pmc->phy[0] == NULL) { 3882 return SOC_E_INTERNAL; 3883 } 3884 pm_phy = &pmc->phy[0]->pm_phy; 3885 3886 if (pm_phy == NULL) { 3887 return SOC_E_INTERNAL; 3888 } 3889 3890 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 3891 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(pm_phy, flags, &prbs)); 3892 3893 *value = (int) prbs.poly; 3894 3895 /* convert from PHYMOD enum to SDK enum */ 3896 switch(prbs.poly){ 3897 case phymodPrbsPoly7: 3898 *value = SOC_PHY_PRBS_POLYNOMIAL_X7_X6_1; 3899 break; 3900 case phymodPrbsPoly9: 3901 *value = SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1; 3902 break; 3903 case phymodPrbsPoly15: 3904 *value = SOC_PHY_PRBS_POLYNOMIAL_X15_X14_1; 3905 break; 3906 case phymodPrbsPoly23: 3907 *value = SOC_PHY_PRBS_POLYNOMIAL_X23_X18_1; 3908 break; 3909 case phymodPrbsPoly31: 3910 *value = SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1; 3911 break; 3912 case phymodPrbsPoly11: 3913 *value = SOC_PHY_PRBS_POLYNOMIAL_X11_X9_1; 3914 break; 3915 case phymodPrbsPoly58: 3916 *value = SOC_PHY_PRBS_POLYNOMIAL_X58_X31_1; 3917 break; 3918 default: 3919 return SOC_E_INTERNAL; 3920 } 3921 return SOC_E_NONE; 3922 } 3923 /* 3924 * viper_prbs_rx_poly_get 3925 */ 3926 STATIC int 3927 viper_prbs_rx_poly_get(soc_phymod_ctrl_t *pmc, uint32 *value) 3928 { 3929 phymod_phy_access_t *pm_phy; 3930 phymod_prbs_t prbs; 3931 uint32_t flags = 0; 3932 3933 /* just take the value from the first phy */ 3934 if (pmc->phy[0] == NULL) { 3935 return SOC_E_INTERNAL; 3936 } 3937 pm_phy = &pmc->phy[0]->pm_phy; 3938 3939 if (pm_phy == NULL) { 3940 return SOC_E_INTERNAL; 3941 } 3942 3943 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 3944 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(pm_phy, flags, &prbs)); 3945 3946 *value = (int) prbs.poly; 3947 3948 /* convert from PHYMOD enum to SDK enum */ 3949 switch(prbs.poly){ 3950 case phymodPrbsPoly7: 3951 *value = SOC_PHY_PRBS_POLYNOMIAL_X7_X6_1; 3952 break; 3953 case phymodPrbsPoly9: 3954 *value = SOC_PHY_PRBS_POLYNOMIAL_X9_X5_1; 3955 break; 3956 case phymodPrbsPoly15: 3957 *value = SOC_PHY_PRBS_POLYNOMIAL_X15_X14_1; 3958 break; 3959 case phymodPrbsPoly23: 3960 *value = SOC_PHY_PRBS_POLYNOMIAL_X23_X18_1; 3961 break; 3962 case phymodPrbsPoly31: 3963 *value = SOC_PHY_PRBS_POLYNOMIAL_X31_X28_1; 3964 break; 3965 case phymodPrbsPoly11: 3966 *value = SOC_PHY_PRBS_POLYNOMIAL_X11_X9_1; 3967 break; 3968 case phymodPrbsPoly58: 3969 *value = SOC_PHY_PRBS_POLYNOMIAL_X58_X31_1; 3970 break; 3971 default: 3972 return SOC_E_INTERNAL; 3973 } 3974 return SOC_E_NONE; 3975 } 3976 3977 /* 3978 * viper_prbs_tx_invert_data_get 3979 */ 3980 STATIC int 3981 viper_prbs_tx_invert_data_get(soc_phymod_ctrl_t *pmc, uint32 *value) 3982 { 3983 phymod_phy_access_t *pm_phy; 3984 phymod_prbs_t prbs; 3985 uint32_t flags = 0; 3986 3987 /* just take the value from the first phy */ 3988 if (pmc->phy[0] == NULL) { 3989 return SOC_E_INTERNAL; 3990 } 3991 pm_phy = &pmc->phy[0]->pm_phy; 3992 3993 if (pm_phy == NULL) { 3994 return SOC_E_INTERNAL; 3995 } 3996 3997 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 3998 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(pm_phy, flags, &prbs)); 3999 *value = prbs.invert; 4000 4001 return(SOC_E_NONE); 4002 } 4003 4004 /* 4005 * viper_prbs_rx_invert_data_get 4006 */ 4007 STATIC int 4008 viper_prbs_rx_invert_data_get(soc_phymod_ctrl_t *pmc, uint32 *value) 4009 { 4010 phymod_phy_access_t *pm_phy; 4011 phymod_prbs_t prbs; 4012 uint32_t flags = 0; 4013 4014 /* just take the value from the first phy */ 4015 if (pmc->phy[0] == NULL) { 4016 return SOC_E_INTERNAL; 4017 } 4018 pm_phy = &pmc->phy[0]->pm_phy; 4019 4020 if (pm_phy == NULL) { 4021 return SOC_E_INTERNAL; 4022 } 4023 4024 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 4025 SOC_IF_ERROR_RETURN(phymod_phy_prbs_config_get(pm_phy, flags, &prbs)); 4026 *value = prbs.invert; 4027 4028 return(SOC_E_NONE); 4029 } 4030 4031 4032 /* 4033 * viper_prbs_tx_enable_get 4034 */ 4035 STATIC int 4036 viper_prbs_tx_enable_get(soc_phymod_ctrl_t *pmc, uint32 *value) 4037 { 4038 phymod_phy_access_t *pm_phy; 4039 uint32_t flags = 0; 4040 4041 /* just take the value from the first phy */ 4042 if (pmc->phy[0] == NULL) { 4043 return SOC_E_INTERNAL; 4044 } 4045 pm_phy = &pmc->phy[0]->pm_phy; 4046 4047 if (pm_phy == NULL) { 4048 return SOC_E_INTERNAL; 4049 } 4050 PHYMOD_PRBS_DIRECTION_TX_SET(flags); 4051 SOC_IF_ERROR_RETURN(phymod_phy_prbs_enable_get(pm_phy, flags, value)); 4052 4053 return(SOC_E_NONE); 4054 } 4055 4056 /* 4057 * viper_prbs_rx_enable_get 4058 */ 4059 STATIC int 4060 viper_prbs_rx_enable_get(soc_phymod_ctrl_t *pmc, uint32 *value) 4061 { 4062 phymod_phy_access_t *pm_phy; 4063 uint32_t flags = 0; 4064 4065 /* just take the value from the first phy */ 4066 if (pmc->phy[0] == NULL) { 4067 return SOC_E_INTERNAL; 4068 } 4069 pm_phy = &pmc->phy[0]->pm_phy; 4070 4071 if (pm_phy == NULL) { 4072 return SOC_E_INTERNAL; 4073 } 4074 4075 PHYMOD_PRBS_DIRECTION_RX_SET(flags); 4076 SOC_IF_ERROR_RETURN(phymod_phy_prbs_enable_get(pm_phy, flags, value)); 4077 4078 return(SOC_E_NONE); 4079 } 4080 4081 /* 4082 * viper_prbs_rx_status_get 4083 */ 4084 STATIC int 4085 viper_prbs_rx_status_get(soc_phymod_ctrl_t *pmc, uint32 *value) 4086 { 4087 phymod_phy_access_t *pm_phy; 4088 phymod_prbs_status_t prbs_tmp; 4089 int idx, prbs_lock, lock_loss, error_count ; 4090 4091 /* just take the value from the first phy */ 4092 if (pmc->phy[0] == NULL) { 4093 return SOC_E_INTERNAL; 4094 } 4095 4096 prbs_lock = 1 ; 4097 lock_loss = 0 ; 4098 error_count = 0 ; 4099 for (idx = 0; idx < pmc->num_phys; idx++) { 4100 pm_phy = &pmc->phy[idx]->pm_phy; 4101 4102 if (pm_phy == NULL) { 4103 return SOC_E_INTERNAL; 4104 } 4105 /* $$$ Need to add diagnostic API */ 4106 SOC_IF_ERROR_RETURN 4107 (phymod_phy_prbs_status_get(pm_phy, 0, &prbs_tmp)); 4108 4109 if(prbs_tmp.prbs_lock==0) { 4110 prbs_lock = 0 ; 4111 } else { 4112 if(prbs_tmp.prbs_lock_loss) { 4113 lock_loss = 1 ; 4114 } else { 4115 error_count += prbs_tmp.error_count; 4116 } 4117 } 4118 } 4119 4120 if (prbs_lock == 0) { 4121 *value = -1; 4122 } else if ((lock_loss == 1) && (prbs_lock == 1)) { 4123 *value = -2; 4124 } else { 4125 *value = error_count; 4126 } 4127 return(SOC_E_NONE); 4128 } 4129 4130 /* 4131 * viper_loopback_internal_pmd_get (this is the PMD global loopback) 4132 */ 4133 STATIC int 4134 viper_loopback_internal_pmd_get(soc_phymod_ctrl_t *pmc, uint32 *value) 4135 { 4136 phymod_phy_access_t *pm_phy; 4137 uint32_t enable; 4138 4139 /* just take the value from the first phy */ 4140 if (pmc->phy[0] == NULL) { 4141 return SOC_E_INTERNAL; 4142 } 4143 pm_phy = &pmc->phy[0]->pm_phy; 4144 4145 if (pm_phy == NULL) { 4146 return SOC_E_INTERNAL; 4147 } 4148 4149 SOC_IF_ERROR_RETURN(phymod_phy_loopback_get(pm_phy, phymodLoopbackGlobalPMD, &enable)); 4150 *value = enable; 4151 return(SOC_E_NONE); 4152 } 4153 4154 4155 /* 4156 * viper_loopback_remote_get 4157 */ 4158 STATIC int 4159 viper_loopback_remote_get(soc_phymod_ctrl_t *pmc, uint32 *value) 4160 { 4161 phymod_phy_access_t *pm_phy; 4162 uint32_t enable; 4163 4164 /* just take the value from the first phy */ 4165 if (pmc->phy[0] == NULL) { 4166 return SOC_E_INTERNAL; 4167 } 4168 pm_phy = &pmc->phy[0]->pm_phy; 4169 4170 if (pm_phy == NULL) { 4171 return SOC_E_INTERNAL; 4172 } 4173 4174 SOC_IF_ERROR_RETURN(phymod_phy_loopback_get(pm_phy, phymodLoopbackRemotePMD, &enable)); 4175 *value = enable; 4176 return(SOC_E_NONE); 4177 } 4178 4179 /* 4180 * viper_loopback_remote_pcs_get 4181 */ 4182 STATIC int 4183 viper_loopback_remote_pcs_get(soc_phymod_ctrl_t *pmc, uint32 *value) 4184 { 4185 phymod_phy_access_t *pm_phy; 4186 uint32_t enable; 4187 4188 /* just take the value from the first phy */ 4189 if (pmc->phy[0] == NULL) { 4190 return SOC_E_INTERNAL; 4191 } 4192 pm_phy = &pmc->phy[0]->pm_phy; 4193 4194 if (pm_phy == NULL) { 4195 return SOC_E_INTERNAL; 4196 } 4197 4198 SOC_IF_ERROR_RETURN(phymod_phy_loopback_get(pm_phy, phymodLoopbackRemotePCS, &enable)); 4199 *value = enable; 4200 return(SOC_E_NONE); 4201 } 4202 4203 /* 4204 * viper_fec_get 4205 */ 4206 STATIC int 4207 viper_fec_enable_get(soc_phymod_ctrl_t *pmc, uint32 *value) 4208 { 4209 phymod_phy_access_t *pm_phy; 4210 uint32_t enable; 4211 4212 /* just take the value from the first phy */ 4213 if (pmc->phy[0] == NULL) { 4214 return SOC_E_INTERNAL; 4215 } 4216 pm_phy = &pmc->phy[0]->pm_phy; 4217 4218 if (pm_phy == NULL) { 4219 return SOC_E_INTERNAL; 4220 } 4221 4222 SOC_IF_ERROR_RETURN(phymod_phy_fec_enable_get(pm_phy, &enable)); 4223 *value = enable; 4224 4225 return(SOC_E_NONE); 4226 } 4227 /* 4228 * viper_pattern_256bit_get 4229 * 4230 * CHECK SEMANTICS: assumption is that this procedure will retrieve the pattern 4231 * from Tier1 and return whether the tx pattern is enabled. Note that this 4232 * is different from the 20 bit pattern retrieval semantics 4233 */ 4234 /* 4235 * viper_pattern_256bit_get 4236 * 4237 * CHECK SEMANTICS: assumption is that this procedure will retrieve the pattern 4238 * from Tier1 and return whether the tx pattern is enabled. Note that this 4239 * is different from the 20 bit pattern retrieval semantics 4240 */ 4241 STATIC int 4242 viper_pattern_get(soc_phymod_ctrl_t *pmc, viper_pattern_t* cfg_pattern) 4243 { 4244 phymod_phy_access_t *pm_phy; 4245 phymod_pattern_t phymod_pattern; 4246 4247 /* just take the value from the first phy */ 4248 if (pmc->phy[0] == NULL) { 4249 return SOC_E_INTERNAL; 4250 } 4251 pm_phy = &pmc->phy[0]->pm_phy; 4252 4253 if (pm_phy == NULL) { 4254 return SOC_E_INTERNAL; 4255 } 4256 4257 SOC_IF_ERROR_RETURN(phymod_phy_pattern_config_get(pm_phy, &phymod_pattern)); 4258 sal_memcpy(cfg_pattern , phymod_pattern.pattern, sizeof(*cfg_pattern)); 4259 return(SOC_E_NONE); 4260 } 4261 4262 STATIC int 4263 viper_pattern_len_get(soc_phymod_ctrl_t *pmc, uint32_t *value) 4264 { 4265 phymod_phy_access_t *pm_phy; 4266 phymod_pattern_t phymod_pattern; 4267 4268 /* just take the value from the first phy */ 4269 if (pmc->phy[0] == NULL) { 4270 return SOC_E_INTERNAL; 4271 } 4272 pm_phy = &pmc->phy[0]->pm_phy; 4273 4274 if (pm_phy == NULL) { 4275 return SOC_E_INTERNAL; 4276 } 4277 4278 SOC_IF_ERROR_RETURN(phymod_phy_pattern_config_get(pm_phy, &phymod_pattern)); 4279 *value = phymod_pattern.pattern_len; 4280 return(SOC_E_NONE); 4281 } 4282 4283 /* 4284 * viper_scrambler_get 4285 */ 4286 STATIC int 4287 viper_scrambler_get(soc_phymod_ctrl_t *pmc, soc_port_t port, uint32 *value) 4288 { 4289 phymod_phy_access_t *pm_phy; 4290 phymod_phy_inf_config_t config; 4291 phymod_ref_clk_t ref_clock = phymodRefClk156Mhz; 4292 4293 /* just take the value from the first phy */ 4294 if (pmc->phy[0] == NULL) { 4295 return SOC_E_INTERNAL; 4296 } 4297 pm_phy = &pmc->phy[0]->pm_phy; 4298 4299 if (pm_phy == NULL) { 4300 return SOC_E_INTERNAL; 4301 } 4302 4303 SOC_IF_ERROR_RETURN(phymod_phy_interface_config_get(pm_phy, 0 /* flags */, ref_clock, &config)); 4304 *value = PHYMOD_INTF_MODES_SCR_GET(&config); 4305 4306 return(SOC_E_NONE); 4307 } 4308 4309 /* 4310 * Function: 4311 * phy_viper_control_get 4312 * Purpose: 4313 * Get current control settings of the PHY. 4314 * Parameters: 4315 * unit - BCM unit number. 4316 * port - Port number. 4317 * type - Control to update 4318 * value - (OUT) Current setting for the control 4319 * Returns: 4320 * SOC_E_NONE 4321 */ 4322 STATIC int 4323 phy_viper_control_get(int unit, soc_port_t port, soc_phy_control_t type, uint32 *value) 4324 { 4325 int rv; 4326 phy_ctrl_t *pc; 4327 soc_phymod_ctrl_t *pmc; 4328 viper_config_t *pCfg; 4329 4330 /* coverity[mixed_enums] */ 4331 if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) { 4332 return (SOC_E_PARAM); 4333 } 4334 4335 /* locate phy control */ 4336 pc = INT_PHY_SW_STATE(unit, port); 4337 if (pc == NULL) { 4338 return SOC_E_INTERNAL; 4339 } 4340 4341 pmc = &pc->phymod_ctrl; 4342 pCfg = (viper_config_t *) pc->driver_data; 4343 4344 switch(type) { 4345 4346 /* PREEMPHASIS */ 4347 case SOC_PHY_CONTROL_PREEMPHASIS_LANE0: 4348 rv = viper_per_lane_preemphasis_get(pmc, 0, value); 4349 break; 4350 case SOC_PHY_CONTROL_PREEMPHASIS_LANE1: 4351 rv = viper_per_lane_preemphasis_get(pmc, 1, value); 4352 break; 4353 case SOC_PHY_CONTROL_PREEMPHASIS_LANE2: 4354 rv = viper_per_lane_preemphasis_get(pmc, 2, value); 4355 break; 4356 case SOC_PHY_CONTROL_PREEMPHASIS_LANE3: 4357 rv = viper_per_lane_preemphasis_get(pmc, 3, value); 4358 break; 4359 case SOC_PHY_CONTROL_TX_FIR_PRE: 4360 /* assume they are all the same as lane 0 */ 4361 rv = viper_tx_fir_pre_get(pmc, value); 4362 break; 4363 case SOC_PHY_CONTROL_TX_FIR_MAIN: 4364 /* assume they are all the same as lane 0 */ 4365 rv = viper_tx_fir_main_get(pmc, value); 4366 break; 4367 case SOC_PHY_CONTROL_TX_FIR_POST: 4368 /* assume they are all the same as lane 0 */ 4369 rv = viper_tx_fir_post_get(pmc, value); 4370 break; 4371 case SOC_PHY_CONTROL_TX_FIR_POST2: 4372 /* assume they are all the same as lane 0 */ 4373 rv = viper_tx_fir_post2_get(pmc, value); 4374 break; 4375 case SOC_PHY_CONTROL_TX_FIR_POST3: 4376 /* assume they are all the same as lane 0 */ 4377 rv = viper_tx_fir_post3_get(pmc, value); 4378 break; 4379 4380 /* DRIVER CURRENT */ 4381 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE0: 4382 rv = viper_per_lane_driver_current_get(pmc, 0, value); 4383 break; 4384 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE1: 4385 rv = viper_per_lane_driver_current_get(pmc, 1, value); 4386 break; 4387 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE2: 4388 rv = viper_per_lane_driver_current_get(pmc, 2, value); 4389 break; 4390 case SOC_PHY_CONTROL_DRIVER_CURRENT_LANE3: 4391 rv = viper_per_lane_driver_current_get(pmc, 3, value); 4392 break; 4393 case SOC_PHY_CONTROL_DRIVER_CURRENT: 4394 rv = viper_per_lane_driver_current_get(pmc, 0, value); 4395 break; 4396 4397 /* PRE-DRIVER CURRENT */ 4398 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE0: 4399 rv = SOC_E_UNAVAIL; 4400 break; 4401 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE1: 4402 rv = SOC_E_UNAVAIL; 4403 break; 4404 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE2: 4405 rv = SOC_E_UNAVAIL; 4406 break; 4407 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT_LANE3: 4408 rv = SOC_E_UNAVAIL; 4409 break; 4410 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 4411 rv = SOC_E_UNAVAIL; 4412 break; 4413 4414 /* POST2_DRIVER CURRENT */ 4415 case SOC_PHY_CONTROL_DRIVER_POST2_CURRENT: 4416 rv = SOC_E_UNAVAIL; 4417 break; 4418 4419 /* RX PEAK FILTER */ 4420 case SOC_PHY_CONTROL_RX_PEAK_FILTER: 4421 rv = viper_rx_peak_filter_get(pmc, value); 4422 break; 4423 4424 /* RX VGA */ 4425 case SOC_PHY_CONTROL_RX_VGA: 4426 rv = SOC_E_UNAVAIL; 4427 break; 4428 4429 /* RX TAP */ 4430 case SOC_PHY_CONTROL_RX_TAP1: 4431 rv = viper_rx_tap_get(pmc, 0, value); 4432 break; 4433 case SOC_PHY_CONTROL_RX_TAP2: 4434 rv = viper_rx_tap_get(pmc, 1, value); 4435 break; 4436 case SOC_PHY_CONTROL_RX_TAP3: 4437 rv = viper_rx_tap_get(pmc, 2, value); 4438 break; 4439 case SOC_PHY_CONTROL_RX_TAP4: 4440 rv = viper_rx_tap_get(pmc, 3, value); 4441 break; 4442 case SOC_PHY_CONTROL_RX_TAP5: 4443 rv = viper_rx_tap_get(pmc, 4, value); 4444 break; 4445 4446 /* RX SLICER */ 4447 case SOC_PHY_CONTROL_RX_PLUS1_SLICER: 4448 rv = SOC_E_UNAVAIL; 4449 break; 4450 case SOC_PHY_CONTROL_RX_MINUS1_SLICER: 4451 rv = SOC_E_UNAVAIL; 4452 break; 4453 case SOC_PHY_CONTROL_RX_D_SLICER: 4454 rv = SOC_E_UNAVAIL; 4455 break; 4456 4457 /* PHASE INTERPOLATOR */ 4458 case SOC_PHY_CONTROL_PHASE_INTERP: 4459 rv = viper_pi_control_get(pmc, value); 4460 break; 4461 4462 /* RX SIGNAL DETECT */ 4463 case SOC_PHY_CONTROL_RX_SIGNAL_DETECT: 4464 rv = viper_rx_signal_detect_get(pmc, value); 4465 break; 4466 case SOC_PHY_CONTROL_RX_SEQ_DONE: 4467 rv = viper_rx_seq_done_get(pmc, value); 4468 break; 4469 case SOC_PHY_CONTROL_RX_PPM: 4470 rv = viper_rx_ppm_get(pmc, value); 4471 break; 4472 /* PRBS */ 4473 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_POLYNOMIAL: 4474 rv = viper_prbs_tx_poly_get(pmc, value); 4475 break; 4476 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_INVERT_DATA: 4477 rv = viper_prbs_tx_invert_data_get(pmc, value); 4478 break; 4479 case SOC_PHY_CONTROL_PRBS_DECOUPLED_TX_ENABLE: 4480 rv = viper_prbs_tx_enable_get(pmc, value); 4481 break; 4482 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_POLYNOMIAL: 4483 rv = viper_prbs_rx_poly_get(pmc, value); 4484 break; 4485 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_INVERT_DATA: 4486 rv = viper_prbs_rx_invert_data_get(pmc, value); 4487 break; 4488 case SOC_PHY_CONTROL_PRBS_DECOUPLED_RX_ENABLE: 4489 rv = viper_prbs_rx_enable_get(pmc, value); 4490 break; 4491 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 4492 rv = viper_prbs_tx_poly_get(pmc, value); 4493 break; 4494 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 4495 rv = viper_prbs_tx_invert_data_get(pmc, value); 4496 break; 4497 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 4498 rv = viper_prbs_tx_enable_get(pmc, value); 4499 break; 4500 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 4501 rv = viper_prbs_rx_enable_get(pmc, value); 4502 break; 4503 case SOC_PHY_CONTROL_PRBS_RX_STATUS: 4504 rv = viper_prbs_rx_status_get(pmc, value); 4505 break; 4506 4507 /* LOOPBACK */ 4508 case SOC_PHY_CONTROL_LOOPBACK_REMOTE: 4509 rv = viper_loopback_remote_get(pmc, value); 4510 break; 4511 case SOC_PHY_CONTROL_LOOPBACK_REMOTE_PCS_BYPASS: 4512 rv = viper_loopback_remote_pcs_get(pmc, value); 4513 break; 4514 case SOC_PHY_CONTROL_LOOPBACK_PMD: 4515 rv = viper_loopback_internal_pmd_get(pmc, value); 4516 break; 4517 4518 /* FEC */ 4519 case SOC_PHY_CONTROL_FORWARD_ERROR_CORRECTION: 4520 rv = viper_fec_enable_get(pmc, value); 4521 break; 4522 4523 /* TX PATTERN */ 4524 case SOC_PHY_CONTROL_TX_PATTERN_256BIT: 4525 rv = viper_pattern_get(pmc, &pCfg->pattern); 4526 break; 4527 case SOC_PHY_CONTROL_TX_PATTERN_LENGTH: 4528 rv = viper_pattern_len_get(pmc, value); 4529 break; 4530 case SOC_PHY_CONTROL_TX_PATTERN_20BIT: 4531 rv = viper_pattern_get(pmc, &pCfg->pattern); 4532 break; 4533 4534 /* SCRAMBLER */ 4535 case SOC_PHY_CONTROL_SCRAMBLER: 4536 rv = viper_scrambler_get(pmc, port, value); 4537 break; 4538 case SOC_PHY_CONTROL_LANE_SWAP: 4539 rv = viper_lane_map_get(pmc, value); 4540 break; 4541 /* EEE */ 4542 case SOC_PHY_CONTROL_EEE: 4543 rv = viper_eee_get(pmc, value); 4544 break; 4545 case SOC_PHY_CONTROL_LINKDOWN_TRANSMIT: 4546 rv = viper_control_linkdown_transmit_get(pmc, value); 4547 break; 4548 4549 /* UNAVAIL */ 4550 4551 #if 0 4552 /* BERT */ 4553 case SOC_PHY_CONTROL_BERT_TX_PACKETS: /* fall through */ 4554 case SOC_PHY_CONTROL_BERT_RX_PACKETS: /* fall through */ 4555 case SOC_PHY_CONTROL_BERT_RX_ERROR_BITS: /* fall through */ 4556 case SOC_PHY_CONTROL_BERT_RX_ERROR_BYTES: /* fall through */ 4557 case SOC_PHY_CONTROL_BERT_RX_ERROR_PACKETS: /* fall through */ 4558 case SOC_PHY_CONTROL_BERT_PATTERN: /* fall through */ 4559 case SOC_PHY_CONTROL_BERT_PACKET_SIZE: /* fall through */ 4560 case SOC_PHY_CONTROL_BERT_IPG: /* fall through */ 4561 rv = SOC_E_NONE; 4562 break; 4563 4564 /* CUSTOM */ 4565 case SOC_PHY_CONTROL_CUSTOM1: 4566 /* Obsolete ?? 4567 *value = DEV_CFG_PTR(pc)->custom1; 4568 rv = SOC_E_NONE; */ 4569 break; 4570 4571 /* SOFTWARE RX LOS */ 4572 case SOC_PHY_CONTROL_SOFTWARE_RX_LOS: 4573 /* Was 4574 *value = DEV_CFG_PTR(pc)->sw_rx_los.enable ; */ 4575 rv = SOC_E_NONE ; 4576 break ; 4577 4578 /* UNAVAIL */ 4579 case SOC_PHY_CONTROL_PARALLEL_DETECTION: 4580 rv = SOC_E_UNAVAIL; 4581 break; 4582 #endif 4583 default: 4584 rv = SOC_E_UNAVAIL; 4585 break; 4586 } 4587 return rv; 4588 } 4589 4590 /* 4591 * Function: 4592 * phy_viper_per_lane_control_set 4593 * Purpose: 4594 * Configure PHY device specific control fucntion. 4595 * Parameters: 4596 * unit - StrataSwitch unit #. 4597 * port - StrataSwitch port #. 4598 * lane - lane number 4599 * type - Control to update 4600 * value - New setting for the control 4601 * Returns: 4602 * SOC_E_NONE 4603 */ 4604 STATIC int 4605 phy_viper_per_lane_control_set(int unit, soc_port_t port, int lane, soc_phy_control_t type, uint32 value) 4606 { 4607 int rv; 4608 phy_ctrl_t *pc; 4609 soc_phymod_ctrl_t *pmc; 4610 4611 /* locate phy control, phymod control, and the configuration data */ 4612 pc = INT_PHY_SW_STATE(unit, port); 4613 if (pc == NULL) { 4614 return SOC_E_INTERNAL; 4615 } 4616 pmc = &pc->phymod_ctrl; 4617 /* coverity[mixed_enums] */ 4618 if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) { 4619 return SOC_E_PARAM; 4620 } 4621 4622 switch(type) { 4623 case SOC_PHY_CONTROL_PREEMPHASIS: 4624 rv = viper_per_lane_preemphasis_set(pmc, lane, value); 4625 break; 4626 case SOC_PHY_CONTROL_DRIVER_CURRENT: 4627 rv = SOC_E_UNAVAIL; 4628 break; 4629 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 4630 rv = SOC_E_UNAVAIL; 4631 break; 4632 case SOC_PHY_CONTROL_DRIVER_POST2_CURRENT: 4633 rv = SOC_E_UNAVAIL; 4634 break; 4635 case SOC_PHY_CONTROL_RX_TAP1: 4636 rv = viper_per_lane_rx_dfe_tap_control_set (pmc, lane, 0 /* tap */, 1 /* enable */, value); 4637 break; 4638 case SOC_PHY_CONTROL_RX_TAP1_RELEASE: 4639 rv = viper_per_lane_rx_dfe_tap_control_set (pmc, lane, 0 /* tap */, 0 /* release */, 0x8000); 4640 break; 4641 case SOC_PHY_CONTROL_RX_TAP2: 4642 rv = viper_per_lane_rx_dfe_tap_control_set (pmc, lane, 1 /* tap */, 1 /* enable */, value); 4643 break; 4644 case SOC_PHY_CONTROL_RX_TAP2_RELEASE: 4645 rv = viper_per_lane_rx_dfe_tap_control_set (pmc, lane, 1 /* tap */, 0 /* release */, 0x8000); 4646 break; 4647 case SOC_PHY_CONTROL_RX_TAP3: 4648 rv = viper_per_lane_rx_dfe_tap_control_set (pmc, lane, 2 /* tap */, 1 /* enable */, value); 4649 break; 4650 case SOC_PHY_CONTROL_RX_TAP3_RELEASE: 4651 rv = viper_per_lane_rx_dfe_tap_control_set (pmc, lane, 2 /* tap */, 0 /* release */, 0x8000); 4652 break; 4653 case SOC_PHY_CONTROL_RX_TAP4: 4654 rv = viper_per_lane_rx_dfe_tap_control_set (pmc, lane, 3 /* tap */, 1 /* enable */, value); 4655 break; 4656 case SOC_PHY_CONTROL_RX_TAP4_RELEASE: 4657 rv = viper_per_lane_rx_dfe_tap_control_set (pmc, lane, 3 /* tap */, 0 /* release */, 0x8000); 4658 break; 4659 case SOC_PHY_CONTROL_RX_TAP5: 4660 rv = viper_per_lane_rx_dfe_tap_control_set (pmc, lane, 4 /* tap */, 1 /* enable */, value); 4661 break; 4662 case SOC_PHY_CONTROL_RX_TAP5_RELEASE: 4663 rv = viper_per_lane_rx_dfe_tap_control_set (pmc, lane, 4 /* tap */, 0 /* release */, 0x8000); 4664 break; 4665 4666 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 4667 rv = viper_per_lane_prbs_poly_set(pmc, lane, value); 4668 break; 4669 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 4670 rv = viper_per_lane_prbs_tx_invert_data_set(pmc, lane, value); 4671 break; 4672 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 4673 /* TX_ENABLE does both tx and rx */ 4674 rv = viper_per_lane_prbs_tx_enable_set(pmc, lane, value); 4675 break; 4676 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 4677 rv = SOC_E_NONE; 4678 break; 4679 case SOC_PHY_CONTROL_RX_PEAK_FILTER: 4680 rv = viper_per_lane_rx_peak_filter_set(pmc, lane, 1 /* enable */, value); 4681 break; 4682 case SOC_PHY_CONTROL_RX_LOW_FREQ_PEAK_FILTER: 4683 rv = viper_per_lane_rx_low_freq_filter_set(pmc, lane, value); 4684 break; 4685 case SOC_PHY_CONTROL_RX_VGA: 4686 rv = viper_per_lane_rx_vga_set(pmc, lane, 1 /* enable */, value); 4687 break; 4688 case SOC_PHY_CONTROL_RX_VGA_RELEASE: 4689 rv = viper_per_lane_rx_vga_set(pmc, lane, 0 /* release */, 0x8000); 4690 break; 4691 case SOC_PHY_CONTROL_RX_PLUS1_SLICER: 4692 rv = SOC_E_UNAVAIL; 4693 break; 4694 case SOC_PHY_CONTROL_RX_MINUS1_SLICER: 4695 rv = SOC_E_UNAVAIL; 4696 break; 4697 case SOC_PHY_CONTROL_RX_D_SLICER: 4698 rv = SOC_E_UNAVAIL; 4699 break; 4700 default: 4701 rv = SOC_E_UNAVAIL; 4702 break; 4703 } 4704 4705 return rv; 4706 } 4707 4708 /* 4709 * Function: 4710 * phy_viper_per_lane_control_get 4711 * Purpose: 4712 * Configure PHY device specific control fucntion. 4713 * Parameters: 4714 * unit - StrataSwitch unit #. 4715 * port - StrataSwitch port #. 4716 * lane - lane number 4717 * type - Control to update 4718 * value - New setting for the control 4719 * Returns: 4720 * SOC_E_NONE 4721 */ 4722 STATIC int 4723 phy_viper_per_lane_control_get(int unit, soc_port_t port, int lane, 4724 soc_phy_control_t type, uint32 *value) 4725 { 4726 int rv; 4727 phy_ctrl_t *pc; 4728 soc_phymod_ctrl_t *pmc; 4729 4730 /* locate phy control, phymod control, and the configuration data */ 4731 pc = INT_PHY_SW_STATE(unit, port); 4732 if (pc == NULL) { 4733 return SOC_E_INTERNAL; 4734 } 4735 pmc = &pc->phymod_ctrl; 4736 /* coverity[mixed_enums] */ 4737 if ((type < 0) || (type >= SOC_PHY_CONTROL_COUNT)) { 4738 return SOC_E_PARAM; 4739 } 4740 4741 switch(type) { 4742 4743 case SOC_PHY_CONTROL_PREEMPHASIS: 4744 rv = viper_per_lane_preemphasis_get(pmc, lane, value); 4745 break; 4746 case SOC_PHY_CONTROL_DRIVER_CURRENT: 4747 rv = SOC_E_UNAVAIL; 4748 break; 4749 case SOC_PHY_CONTROL_PRE_DRIVER_CURRENT: 4750 rv = SOC_E_UNAVAIL; 4751 break; 4752 case SOC_PHY_CONTROL_DRIVER_POST2_CURRENT: 4753 rv = SOC_E_UNAVAIL; 4754 break; 4755 case SOC_PHY_CONTROL_PRBS_POLYNOMIAL: 4756 rv = viper_per_lane_prbs_poly_get(pmc, lane, value); 4757 break; 4758 case SOC_PHY_CONTROL_PRBS_TX_INVERT_DATA: 4759 rv = viper_per_lane_prbs_tx_invert_data_get(pmc, lane, value); 4760 break; 4761 case SOC_PHY_CONTROL_PRBS_TX_ENABLE: 4762 rv = viper_per_lane_prbs_tx_enable_get(pmc, lane, value); 4763 break; 4764 case SOC_PHY_CONTROL_PRBS_RX_ENABLE: 4765 rv = viper_per_lane_prbs_rx_enable_get(pmc, lane, value); 4766 break; 4767 case SOC_PHY_CONTROL_PRBS_RX_STATUS: 4768 rv = viper_per_lane_prbs_rx_status_get(pmc, lane, value); 4769 break; 4770 case SOC_PHY_CONTROL_RX_PEAK_FILTER: 4771 rv = viper_per_lane_rx_peak_filter_get(pmc, lane, value); 4772 break; 4773 case SOC_PHY_CONTROL_RX_VGA: 4774 rv = viper_per_lane_rx_vga_get(pmc, lane, value); 4775 break; 4776 case SOC_PHY_CONTROL_RX_TAP1: 4777 rv = viper_per_lane_rx_dfe_tap_control_get(pmc, lane, 0, value); 4778 break; 4779 case SOC_PHY_CONTROL_RX_TAP2: 4780 rv = viper_per_lane_rx_dfe_tap_control_get(pmc, lane, 1, value); 4781 break; 4782 case SOC_PHY_CONTROL_RX_TAP3: 4783 rv = viper_per_lane_rx_dfe_tap_control_get(pmc, lane, 2, value); 4784 break; 4785 case SOC_PHY_CONTROL_RX_TAP4: 4786 rv = viper_per_lane_rx_dfe_tap_control_get(pmc, lane, 3, value); 4787 break; 4788 case SOC_PHY_CONTROL_RX_TAP5: 4789 rv = viper_per_lane_rx_dfe_tap_control_get(pmc, lane, 4, value); 4790 break; 4791 case SOC_PHY_CONTROL_RX_LOW_FREQ_PEAK_FILTER: 4792 rv = viper_per_lane_rx_low_freq_filter_get(pmc, lane, value); 4793 break; 4794 case SOC_PHY_CONTROL_RX_PLUS1_SLICER: 4795 rv = SOC_E_UNAVAIL; 4796 break; 4797 case SOC_PHY_CONTROL_RX_MINUS1_SLICER: 4798 rv = SOC_E_UNAVAIL; 4799 break; 4800 case SOC_PHY_CONTROL_RX_D_SLICER: 4801 rv = SOC_E_UNAVAIL; 4802 break; 4803 default: 4804 rv = SOC_E_UNAVAIL; 4805 break; 4806 } 4807 return rv; 4808 } 4809 4810 /* 4811 * Function: 4812 * phy_viper_reg_read 4813 * Purpose: 4814 * Routine to read PHY register 4815 * Parameters: 4816 * unit - BCM unit number 4817 * port - Port number 4818 * flags - Flags which specify the register type 4819 * phy_reg_addr - Encoded register address 4820 * phy_data - (OUT) Value read from PHY register 4821 * Note: 4822 * This register read function is not thread safe. Higher level 4823 * function that calls this function must obtain a per port lock 4824 * to avoid overriding register page mapping between threads. 4825 */ 4826 STATIC int 4827 phy_viper_reg_read(int unit, soc_port_t port, uint32 flags, 4828 uint32 phy_reg_addr, uint32 *phy_reg_data) 4829 { 4830 phy_ctrl_t *pc; 4831 soc_phymod_ctrl_t *pmc; 4832 phymod_phy_access_t *pm_phy; 4833 int idx; 4834 4835 pc = INT_PHY_SW_STATE(unit, port); 4836 if (pc == NULL) { 4837 return SOC_E_INTERNAL; 4838 } 4839 4840 pmc = &pc->phymod_ctrl; 4841 idx = pmc->main_phy ; 4842 pm_phy = &pmc->phy[idx]->pm_phy; 4843 4844 return phymod_phy_reg_read(pm_phy, phy_reg_addr, phy_reg_data); 4845 } 4846 4847 /* 4848 * Function: 4849 * phy_viper_reg_write 4850 * Purpose: 4851 * Routine to write PHY register 4852 * Parameters: 4853 * uint - BCM unit number 4854 * pc - PHY state 4855 * flags - Flags which specify the register type 4856 * phy_reg_addr - Encoded register address 4857 * phy_data - Value write to PHY register 4858 * Note: 4859 * This register read function is not thread safe. Higher level 4860 * function that calls this function must obtain a per port lock 4861 * to avoid overriding register page mapping between threads. 4862 */ 4863 STATIC int 4864 phy_viper_reg_write(int unit, soc_port_t port, uint32 flags, 4865 uint32 phy_reg_addr, uint32 phy_reg_data) 4866 { 4867 phy_ctrl_t *pc; 4868 soc_phymod_ctrl_t *pmc; 4869 phymod_phy_access_t *pm_phy; 4870 int idx; 4871 4872 pc = INT_PHY_SW_STATE(unit, port); 4873 if (pc == NULL) { 4874 return SOC_E_INTERNAL; 4875 } 4876 4877 pmc = &pc->phymod_ctrl; 4878 for (idx = 0; idx < pmc->num_phys; idx++) { 4879 pm_phy = &pmc->phy[idx]->pm_phy; 4880 SOC_IF_ERROR_RETURN 4881 (phymod_phy_reg_write(pm_phy, phy_reg_addr, phy_reg_data)); 4882 } 4883 return SOC_E_NONE; 4884 } 4885 4886 /* 4887 * Function: 4888 * phy_viper_reg_modify 4889 * Purpose: 4890 * Routine to write PHY register 4891 * Parameters: 4892 * uint - BCM unit number 4893 * pc - PHY state 4894 * flags - Flags which specify the register type 4895 * phy_reg_addr - Encoded register address 4896 * phy_mo_data - New value for the bits specified in phy_mo_mask 4897 * phy_mo_mask - Bit mask to modify 4898 * Note: 4899 * This function is not thread safe. Higher level 4900 * function that calls this function must obtain a per port lock 4901 * to avoid overriding register page mapping between threads. 4902 */ 4903 STATIC int 4904 phy_viper_reg_modify(int unit, soc_port_t port, uint32 flags, 4905 uint32 phy_reg_addr, uint32 phy_data, 4906 uint32 phy_data_mask) 4907 { 4908 phy_ctrl_t *pc; 4909 soc_phymod_ctrl_t *pmc; 4910 phymod_phy_access_t *pm_phy; 4911 uint32 data32, tmp; 4912 int idx; 4913 4914 pc = INT_PHY_SW_STATE(unit, port); 4915 if (pc == NULL) { 4916 return SOC_E_INTERNAL; 4917 } 4918 4919 pmc = &pc->phymod_ctrl; 4920 for (idx = 0; idx < pmc->num_phys; idx++) { 4921 pm_phy = &pmc->phy[idx]->pm_phy; 4922 SOC_IF_ERROR_RETURN 4923 (phymod_phy_reg_read(pm_phy, phy_reg_addr, &data32)); 4924 tmp = data32; 4925 data32 &= ~(phy_data_mask); 4926 data32 |= (phy_data & phy_data_mask); 4927 if (data32 != tmp) { 4928 SOC_IF_ERROR_RETURN 4929 (phymod_phy_reg_write(pm_phy, phy_reg_addr, data32)); 4930 } 4931 } 4932 return SOC_E_NONE; 4933 } 4934 4935 STATIC void 4936 phy_viper_cleanup(soc_phymod_ctrl_t *pmc) 4937 { 4938 int idx; 4939 soc_phymod_phy_t *phy; 4940 soc_phymod_core_t *core; 4941 4942 for (idx = 0; idx < pmc->num_phys ; idx++) { 4943 phy = pmc->phy[idx]; 4944 if (phy == NULL) { 4945 LOG_WARN(BSL_LS_SOC_PHY, 4946 (BSL_META_U(pmc->unit, 4947 "phy object is empty"))); 4948 continue; 4949 } 4950 4951 core = phy->core; 4952 /* Destroy core object if not used anymore */ 4953 if (core && core->ref_cnt) { 4954 if (--core->ref_cnt == 0) { 4955 PHYMOD_VDBG(VIPER_DBG_MEM, NULL,("clean_up core_p=%p\n", (void *)core)) ; 4956 soc_phymod_core_destroy(pmc->unit, core); 4957 } 4958 } 4959 4960 /* Destroy phy object */ 4961 if (phy) { 4962 PHYMOD_VDBG(VIPER_DBG_MEM, NULL,("clean_up phy=%p\n", (void *)phy)) ; 4963 soc_phymod_phy_destroy(pmc->unit, phy); 4964 } 4965 } 4966 pmc->num_phys = 0; 4967 } 4968 4969 STATIC void 4970 phy_viper_core_init(phy_ctrl_t *pc, soc_phymod_core_t *core, 4971 phymod_bus_t *core_bus, uint32 core_addr) 4972 { 4973 phymod_core_access_t *pm_core; 4974 phymod_access_t *pm_acc; 4975 4976 core->unit = pc->unit; 4977 core->port = pc->port; 4978 core->read = pc->read; 4979 core->write = pc->write; 4980 core->wrmask = pc->wrmask; 4981 4982 pm_core = &core->pm_core; 4983 phymod_core_access_t_init(pm_core); 4984 pm_acc = &pm_core->access; 4985 phymod_access_t_init(pm_acc); 4986 PHYMOD_ACC_USER_ACC(pm_acc) = core; 4987 PHYMOD_ACC_BUS(pm_acc) = core_bus; 4988 PHYMOD_ACC_ADDR(pm_acc) = core_addr; 4989 #if 0 4990 if (soc_property_port_get(pc->unit, pc->port, "viper_sim", 0) == 45) { 4991 PHYMOD_ACC_F_CLAUSE45_SET(pm_acc); 4992 } 4993 #endif 4994 return; 4995 } 4996 4997 4998 /* 4999 * Function: 5000 * phy_viper_probe 5001 * Purpose: 5002 * xx 5003 * Parameters: 5004 * pc->phy_id (IN) 5005 * pc->unit (IN) 5006 * pc->port (IN) 5007 * pc->size (OUT) - memory required by phy port 5008 * pc->dev_name (OUT) - set to port device name 5009 * 5010 * Note: 5011 */ 5012 STATIC int 5013 phy_viper_probe(int unit, phy_ctrl_t *pc) 5014 { 5015 int rv, idx; 5016 uint32 lane_map[3], num_phys, core_id, phy_id, found; 5017 phymod_bus_t core_bus; 5018 phymod_dispatch_type_t phy_type; 5019 phymod_core_access_t *pm_core; 5020 phymod_phy_access_t *pm_phy; 5021 phymod_access_t *pm_acc; 5022 soc_phymod_ctrl_t *pmc; 5023 soc_phymod_phy_t *phy; 5024 soc_phymod_core_t *core; 5025 soc_phymod_core_t core_probe; 5026 soc_info_t *si; 5027 phyident_core_info_t core_info[8]; 5028 int array_max = 8; 5029 int array_size = 0; 5030 int port; 5031 int phy_port; /* physical port number */ 5032 5033 /* Initialize PHY bus */ 5034 SOC_IF_ERROR_RETURN(phymod_bus_t_init(&core_bus)); 5035 core_bus.bus_name = "viper_sim"; 5036 core_bus.read = _viper_reg_read; 5037 core_bus.write = _viper_reg_write; 5038 5039 /* Configure PHY bus properties */ 5040 if (pc->wrmask) { 5041 PHYMOD_BUS_CAP_WR_MODIFY_SET(&core_bus); 5042 PHYMOD_BUS_CAP_LANE_CTRL_SET(&core_bus); 5043 } 5044 5045 port = pc->port; 5046 pmc = &pc->phymod_ctrl; 5047 si = &SOC_INFO(unit); 5048 if (soc_feature(unit, soc_feature_logical_port_num)) { 5049 phy_port = si->port_l2p_mapping[port]; 5050 } else { 5051 phy_port = port; 5052 } 5053 5054 /* Install clean up function */ 5055 pmc->unit = pc->unit; 5056 pmc->cleanup = phy_viper_cleanup; 5057 if(SOC_IS_GREYHOUND2(unit) || soc_feature(unit, soc_feature_wh2)) { 5058 pmc->symbols = &bcmi_sgmiip2x4_serdes_symbols; 5059 } 5060 else { 5061 pmc->symbols = &bcmi_viper_xgxs_symbols; 5062 } 5063 pmc->main_phy= 0; 5064 5065 if(SOC_IS_SABER2(unit)) { 5066 pc->lane_num = SOC_PORT_BINDEX(unit, phy_port); 5067 pc->chip_num = SOC_BLOCK_NUMBER(unit, SOC_PORT_BLOCK(unit, phy_port)); 5068 } 5069 else if (SOC_IS_GREYHOUND2(unit)){ 5070 /* every block has 2 SGMIIPlus2 cores, every core has 4 lanes */ 5071 pc->lane_num = SOC_PORT_BINDEX(unit, phy_port) % 4; 5072 pc->chip_num = SOC_BLOCK_NUMBER(unit, SOC_PORT_BLOCK(unit, phy_port)) * 2 + SOC_PORT_BINDEX(unit, phy_port) / 4; 5073 } 5074 else if (soc_feature(unit, soc_feature_wh2)) { 5075 /* viper ports belong to gport3 and gport4 block of wolfhound2 */ 5076 pc->lane_num = SOC_PORT_BINDEX(unit, phy_port); 5077 pc->chip_num = SOC_BLOCK_NUMBER(unit, SOC_PORT_BLOCK(unit, phy_port)) - 3; 5078 } 5079 /* request memory for the configuration structure */ 5080 pc->size = sizeof(viper_config_t); 5081 5082 /* Bit N corresponds to lane N in lane_map */ 5083 lane_map[0] = 0xf; 5084 lane_map[1] = 0 ; 5085 lane_map[2] = 0 ; 5086 num_phys = 1; 5087 switch (si->port_num_lanes[port]) { 5088 case 4: 5089 pc->phy_mode = PHYCTRL_QUAD_LANE_PORT; 5090 break; 5091 case 2: 5092 lane_map[0] = 0x3; 5093 pc->phy_mode = PHYCTRL_DUAL_LANE_PORT; 5094 break; 5095 case 1: 5096 case 0: 5097 lane_map[0] = 0x1; 5098 pc->phy_mode = PHYCTRL_ONE_LANE_PORT; 5099 break; 5100 default: 5101 return SOC_E_CONFIG; 5102 } 5103 lane_map[0] <<= pc->lane_num; 5104 5105 /* we need to get the other core id if more than 1 core per port */ 5106 if (num_phys > 1) { 5107 /* get the other core address */ 5108 SOC_IF_ERROR_RETURN 5109 (soc_phy_addr_multi_get(unit, port, array_max, &array_size, &core_info[0])); 5110 } else { 5111 core_info[0].mdio_addr = pc->phy_id; 5112 } 5113 5114 phy_type = phymodDispatchTypeViper; 5115 5116 /* Probe cores */ 5117 for (idx = 0; idx < num_phys ; idx++) { 5118 phy_viper_core_init(pc, &core_probe, &core_bus, 5119 core_info[idx].mdio_addr); 5120 /* Check that core is indeed an VIPER core */ 5121 pm_core = &core_probe.pm_core; 5122 pm_core->type = phy_type; 5123 rv = phymod_core_identify(pm_core, 0, &found); 5124 if (SOC_FAILURE(rv)) { 5125 return rv; 5126 } 5127 if (!found) { 5128 return SOC_E_NOT_FOUND; 5129 } 5130 } 5131 5132 rv = SOC_E_NONE; 5133 for (idx = 0; idx < num_phys ; idx++) { 5134 /* Set core and phy IDs based on PHY address */ 5135 core_id = pc->phy_id + idx; 5136 phy_id = (lane_map[idx] << 16) | core_id; 5137 5138 /* Create PHY object */ 5139 rv = soc_phymod_phy_create(unit, phy_id, &pmc->phy[idx]); 5140 if (SOC_FAILURE(rv)) { 5141 break; 5142 } 5143 pmc->num_phys++; 5144 5145 /* Initialize phy object */ 5146 phy = pmc->phy[idx]; 5147 pm_phy = &phy->pm_phy; 5148 phymod_phy_access_t_init(pm_phy); 5149 5150 /* Find or create associated core object */ 5151 rv = soc_phymod_core_find_by_id(unit, core_id, &phy->core); 5152 if (rv == SOC_E_NOT_FOUND) { 5153 rv = soc_phymod_core_create(unit, core_id, &phy->core); 5154 } 5155 if (SOC_FAILURE(rv)) { 5156 break; 5157 } 5158 } 5159 if (SOC_FAILURE(rv)) { 5160 phy_viper_cleanup(pmc); 5161 return rv; 5162 } 5163 5164 for (idx = 0; idx < pmc->num_phys ; idx++) { 5165 phy = pmc->phy[idx]; 5166 core = phy->core; 5167 pm_core = &core->pm_core; 5168 5169 /* Initialize core object if newly created */ 5170 if (core->ref_cnt == 0) { 5171 sal_memcpy(&core->pm_bus, &core_bus, sizeof(core->pm_bus)); 5172 phy_viper_core_init(pc, core, &core->pm_bus, 5173 core_info[idx].mdio_addr); 5174 /* Set dispatch type */ 5175 pm_core->type = phy_type; 5176 } 5177 core->ref_cnt++; 5178 5179 /* Initialize phy access based on associated core */ 5180 pm_acc = &phy->pm_phy.access; 5181 sal_memcpy(pm_acc, &pm_core->access, sizeof(*pm_acc)); 5182 phy->pm_phy.type = phy_type; 5183 PHYMOD_ACC_LANE_MASK(pm_acc) = lane_map[idx]; 5184 } 5185 5186 return SOC_E_NONE; 5187 } 5188 5189 5190 /*********************************************************************** 5191 * 5192 * PASS-THROUGH NOTIFY ROUTINES 5193 */ 5194 5195 /* 5196 * Function: 5197 * _viper_notify_duplex 5198 * Purpose: 5199 * Program duplex if (and only if) serdesphy is an intermediate PHY. 5200 * Parameters: 5201 * unit - BCM unit number. 5202 * port - Port number. 5203 * duplex - Boolean, TRUE indicates full duplex, FALSE 5204 * indicates half. 5205 * Returns: 5206 * SOC_E_XXX 5207 * Notes: 5208 * If PHY_FLAGS_FIBER is set, it indicates the PHY is being used to 5209 * talk directly to an external fiber module. 5210 * 5211 * If PHY_FLAGS_FIBER is clear, the PHY is being used in 5212 * pass-through mode to talk to an external SGMII PHY. 5213 * 5214 * When used in pass-through mode, autoneg must be turned off and 5215 * the speed/duplex forced to match that of the external PHY. 5216 */ 5217 5218 STATIC int 5219 _viper_notify_duplex(int unit, soc_port_t port, uint32 duplex) 5220 { 5221 SOC_IF_ERROR_RETURN 5222 (phy_viper_duplex_set(unit, port, duplex)); 5223 return SOC_E_NONE; 5224 } 5225 5226 /* 5227 * Function: 5228 * _viper_stop 5229 * Purpose: 5230 * Put serdesviper SERDES in or out of reset depending on conditions 5231 */ 5232 5233 STATIC int 5234 _viper_stop(int unit, soc_port_t port) 5235 { 5236 phy_ctrl_t* pc; 5237 soc_phymod_ctrl_t *pmc; 5238 phymod_phy_access_t *pm_phy; 5239 phymod_phy_power_t phy_power; 5240 int stop, copper, speed; 5241 5242 pc = INT_PHY_SW_STATE(unit, port); 5243 pmc = &pc->phymod_ctrl; 5244 pm_phy = &pmc->phy[pmc->main_phy]->pm_phy; 5245 5246 if (pc->phy_mode != PHYCTRL_ONE_LANE_PORT) { 5247 return SOC_E_NONE; 5248 } 5249 5250 /* 'Stop' only for speeds < 10G. */ 5251 SOC_IF_ERROR_RETURN 5252 (phy_viper_speed_get(unit,port,&speed)); 5253 if(10000 <= speed) { 5254 return SOC_E_NONE; 5255 } 5256 copper = (pc->stop & 5257 PHY_STOP_COPPER) != 0; 5258 5259 stop = ((pc->stop & 5260 (PHY_STOP_PHY_DIS | 5261 PHY_STOP_DRAIN)) != 0 || 5262 (copper && 5263 (pc->stop & 5264 (PHY_STOP_MAC_DIS | 5265 PHY_STOP_DUPLEX_CHG | 5266 PHY_STOP_SPEED_CHG)) != 0)); 5267 5268 LOG_INFO(BSL_LS_SOC_PHY, 5269 (BSL_META_U(pc->unit, 5270 "qsgmiie_stop: u=%d p=%d copper=%d stop=%d flg=0x%x\n"), 5271 unit, port, copper, stop, 5272 pc->stop)); 5273 if (stop) { 5274 phy_power.tx = phymodPowerOff; 5275 phy_power.rx = phymodPowerOff; 5276 } else { 5277 phy_power.tx = phymodPowerOn; 5278 phy_power.rx = phymodPowerOn; 5279 } 5280 SOC_IF_ERROR_RETURN 5281 (phymod_phy_power_set(pm_phy, &phy_power)); 5282 return SOC_E_NONE; 5283 } 5284 5285 /* 5286 * Function: 5287 * _viper_notify_stop 5288 * Purpose: 5289 * Add a reason to put serdesviper PHY in reset. 5290 * Parameters: 5291 * unit - BCM unit number. 5292 * port - Port number. 5293 * flags - Reason to stop 5294 * Returns: 5295 * SOC_E_XXX 5296 */ 5297 5298 STATIC int 5299 _viper_notify_stop(int unit, soc_port_t port, uint32 flags) 5300 { 5301 INT_PHY_SW_STATE(unit, port)->stop |= flags; 5302 return _viper_stop(unit, port); 5303 } 5304 5305 /* 5306 * Function: 5307 * _viper_notify_resume 5308 * Purpose: 5309 * Remove a reason to put serdesviper PHY in reset. 5310 * Parameters: 5311 * unit - BCM unit number. 5312 * port - Port number. 5313 * flags - Reason to stop 5314 * Returns: 5315 * SOC_E_XXX 5316 */ 5317 5318 STATIC int 5319 _viper_notify_resume(int unit, soc_port_t port, uint32 flags) 5320 { 5321 INT_PHY_SW_STATE(unit, port)->stop &= ~flags; 5322 return _viper_stop(unit, port); 5323 } 5324 5325 /* 5326 * Function: 5327 * _viper_notify_speed 5328 * Purpose: 5329 * Program duplex if (and only if) serdesviper is an intermediate PHY. 5330 * Parameters: 5331 * unit - BCM unit number. 5332 * port - Port number. 5333 * speed - Speed to program. 5334 * Returns: 5335 * SOC_E_XXX 5336 * Notes: 5337 * If PHY_FLAGS_FIBER is set, it indicates the PHY is being used to 5338 * talk directly to an external fiber module. 5339 * 5340 * If PHY_FLAGS_FIBER is clear, the PHY is being used in 5341 * pass-through mode to talk to an external SGMII PHY. 5342 * 5343 * When used in pass-through mode, autoneg must be turned off and 5344 * the speed/duplex forced to match that of the external PHY. 5345 */ 5346 5347 STATIC int 5348 _viper_notify_speed(int unit, soc_port_t port, uint32 speed) 5349 { 5350 phy_ctrl_t* pc; 5351 viper_config_t *pCfg; 5352 int fiber; 5353 5354 pc = INT_PHY_SW_STATE(unit, port); 5355 pCfg = (viper_config_t *) pc->driver_data; 5356 fiber = pCfg->fiber_pref; 5357 5358 LOG_INFO(BSL_LS_SOC_PHY, 5359 (BSL_META_U(pc->unit, 5360 "_qsgmiie_notify_speed: " 5361 "u=%d p=%d speed=%d fiber=%d\n"), 5362 unit, port, speed, fiber)); 5363 5364 if (SAL_BOOT_SIMULATION) { 5365 return SOC_E_NONE; 5366 } 5367 5368 /* Put SERDES PHY in reset */ 5369 SOC_IF_ERROR_RETURN 5370 (_viper_notify_stop(unit, port, PHY_STOP_SPEED_CHG)); 5371 5372 /* Update speed */ 5373 SOC_IF_ERROR_RETURN 5374 (phy_viper_speed_set(unit, port, speed)); 5375 5376 /* Take SERDES PHY out of reset */ 5377 SOC_IF_ERROR_RETURN 5378 (_viper_notify_resume(unit, port, PHY_STOP_SPEED_CHG)); 5379 5380 /* Autonegotiation must be turned off to talk to external PHY */ 5381 if (!PHY_SGMII_AUTONEG_MODE(unit, port) && PHY_EXTERNAL_MODE(unit, port)) { 5382 SOC_IF_ERROR_RETURN 5383 (phy_viper_an_set(unit, port, FALSE)); 5384 } 5385 return SOC_E_NONE; 5386 } 5387 5388 /* 5389 * Function: 5390 * viper_media_setup 5391 * Purpose: 5392 * Configure 5393 * Parameters: 5394 * unit - BCM unit number. 5395 * port - Port number. 5396 * fiber_mode - Configure for fiber mode 5397 * fiber_pref - Fiber preferrred (if fiber mode) 5398 * Returns: 5399 * SOC_E_XXX 5400 */ 5401 STATIC int 5402 _viper_notify_interface(int unit, soc_port_t port, uint32 intf) 5403 { 5404 return SOC_E_NONE; 5405 } 5406 5407 /* 5408 * Function: 5409 * _viper_notify_mac_loopback 5410 * Purpose: 5411 * Turn on rx clock compensation in mac loopback mode for 5412 * applicable XGXS devices 5413 * Parameters: 5414 * unit - BCM unit number. 5415 * port - Port number. 5416 * enable - TRUE: In MAC loopback mode, FALSE: Not in MAC loopback mode 5417 * Returns: 5418 * SOC_E_XXX 5419 */ 5420 STATIC int 5421 _viper_notify_mac_loopback(int unit, soc_port_t port, uint32 enable) 5422 { 5423 return SOC_E_NONE; 5424 } 5425 5426 STATIC int 5427 phy_viper_notify(int unit, soc_port_t port, 5428 soc_phy_event_t event, uint32 value) 5429 { 5430 int rv; 5431 rv = SOC_E_NONE ; 5432 if (event >= phyEventCount) { 5433 return SOC_E_PARAM; 5434 } 5435 5436 switch(event) { 5437 case phyEventInterface: 5438 rv = (_viper_notify_interface(unit, port, value)); 5439 break; 5440 case phyEventDuplex: 5441 rv = (_viper_notify_duplex(unit, port, value)); 5442 break; 5443 case phyEventSpeed: 5444 rv = (_viper_notify_speed(unit, port, value)); 5445 break; 5446 case phyEventStop: 5447 rv = (_viper_notify_stop(unit, port, value)); 5448 break; 5449 case phyEventResume: 5450 rv = (_viper_notify_resume(unit, port, value)); 5451 break; 5452 case phyEventAutoneg: 5453 #if 0 5454 rv = (_viper_an_set(unit, port, value)); 5455 #endif 5456 break; 5457 case phyEventMacLoopback: 5458 rv = (_viper_notify_mac_loopback(unit, port, value)); 5459 break; 5460 case phyEventLpiBypass: 5461 PHYMOD_LPI_BYPASS_SET(value); 5462 rv = phy_viper_control_set(unit, port, SOC_PHY_CONTROL_EEE, value); 5463 break; 5464 default: 5465 rv = SOC_E_UNAVAIL; 5466 break; 5467 } 5468 5469 return rv; 5470 } 5471 5472 5473 /* 5474 * Function: 5475 * phy_viper_master_set 5476 * Purpose: 5477 * Configure master mode 5478 * Parameters: 5479 * unit - StrataSwitch unit #. 5480 * port - StrataSwitch port #. 5481 * master - Master mode. 5482 * Returns: 5483 * SOC_E_NONE/SOC_E_UNAVAIL 5484 */ 5485 STATIC int 5486 phy_viper_master_set(int unit, soc_port_t port, int master) 5487 { 5488 if (master != SOC_PORT_MS_SLAVE) 5489 return SOC_E_UNAVAIL; 5490 5491 return SOC_E_NONE; 5492 } 5493 5494 /* 5495 * Function: 5496 * phy_viper_master_get 5497 * Purpose: 5498 * this function is meant for 1000Base-T PHY. Added here to support 5499 * internal PHY regression test 5500 * Parameters: 5501 * unit - StrataSwitch unit #. 5502 * port - StrataSwitch port #. 5503 * master - (OUT) SOC_PORT_MS_* 5504 * Returns: 5505 * SOC_E_NONE 5506 * Notes: 5507 * The master mode is retrieved for the ACTIVE medium. 5508 */ 5509 STATIC int 5510 phy_viper_master_get(int unit, soc_port_t port, int *master) 5511 { 5512 *master = SOC_PORT_MS_SLAVE; 5513 5514 return SOC_E_NONE; 5515 } 5516 5517 /* 5518 * Function: 5519 * phy_viper_diag_ctrl 5520 * Purpose: 5521 * xx 5522 * Parameters: 5523 * unit - BCM unit number. 5524 * port - Port number. 5525 5526 * Returns: 5527 * SOC_E_NONE 5528 */ 5529 5530 STATIC int 5531 phy_viper_diag_ctrl( 5532 int unit, /* unit */ 5533 soc_port_t port, /* port */ 5534 uint32 inst, /* the specific device block the control action directs to */ 5535 int op_type, /* operation types: read,write or command sequence */ 5536 int op_cmd, /* command code */ 5537 void *arg) /* command argument based on op_type/op_cmd */ 5538 { 5539 switch(op_cmd) { 5540 case PHY_DIAG_CTRL_PCS: 5541 LOG_INFO(BSL_LS_SOC_PHY, 5542 (BSL_META_U(unit, 5543 "phy_temod_diag_ctrl: " 5544 "u=%d p=%d PHY_DIAG_CTRL_PCS 0x%x\n"), 5545 unit, port, PHY_DIAG_CTRL_PCS)); 5546 SOC_IF_ERROR_RETURN(viper_pcs_status_dump(unit, port, arg)); 5547 break; 5548 default: 5549 if (op_type == PHY_DIAG_CTRL_SET) { 5550 SOC_IF_ERROR_RETURN(phy_viper_control_set(unit,port,op_cmd,PTR_TO_INT(arg))); 5551 } else if (op_type == PHY_DIAG_CTRL_GET) { 5552 SOC_IF_ERROR_RETURN(phy_viper_control_get(unit,port,op_cmd,(uint32 *)arg)); 5553 } 5554 break ; 5555 } 5556 return (SOC_E_NONE); 5557 } 5558 5559 5560 #ifdef BROADCOM_DEBUG 5561 void 5562 viper_state_dump(int unit, soc_port_t port) 5563 { 5564 /* Show PHY configuration summary */ 5565 /* Lane status */ 5566 /* Show Counters */ 5567 /* Dump Registers */ 5568 } 5569 #endif /* BROADCOM_DEBUG */ 5570 5571 /* 5572 * Variable: 5573 * viper_drv 5574 * Purpose: 5575 * Phy Driver for VIPER 5576 */ 5577 phy_driver_t phy_viper_drv = { 5578 /* .drv_name = */ "VIPER PHYMOD PHY Driver", 5579 /* .pd_init = */ phy_viper_init, 5580 /* .pd_reset = */ phy_null_reset, 5581 /* .pd_link_get = */ phy_viper_link_get, 5582 /* .pd_enable_set = */ phy_viper_enable_set, 5583 /* .pd_enable_get = */ phy_viper_enable_get, 5584 /* .pd_duplex_set = */ phy_viper_duplex_set, 5585 /* .pd_duplex_get = */ phy_viper_duplex_get, 5586 /* .pd_speed_set = */ phy_viper_speed_set, 5587 /* .pd_speed_get = */ phy_viper_speed_get, 5588 /* .pd_master_set = */ phy_viper_master_set, 5589 /* .pd_master_get = */ phy_viper_master_get, 5590 /* .pd_an_set = */ phy_viper_an_set, 5591 /* .pd_an_get = */ phy_viper_an_get, 5592 /* .pd_adv_local_set = */ NULL, /* Deprecated */ 5593 /* .pd_adv_local_get = */ NULL, /* Deprecated */ 5594 /* .pd_adv_remote_get = */ NULL, /* Deprecated */ 5595 /* .pd_lb_set = */ phy_viper_lb_set, 5596 /* .pd_lb_get = */ phy_viper_lb_get, 5597 /* .pd_interface_set = */ phy_viper_interface_set, 5598 /* .pd_interface_get = */ phy_viper_interface_get, 5599 /* .pd_ability = */ NULL, /* Deprecated */ 5600 /* .pd_linkup_evt = */ NULL, 5601 /* .pd_linkdn_evt = */ NULL, 5602 /* .pd_mdix_set = */ phy_null_mdix_set, 5603 /* .pd_mdix_get = */ phy_null_mdix_get, 5604 /* .pd_mdix_status_get = */ phy_null_mdix_status_get, 5605 /* .pd_medium_config_set = */ NULL, 5606 /* .pd_medium_config_get = */ NULL, 5607 /* .pd_medium_get = */ phy_null_medium_get, 5608 /* .pd_cable_diag = */ NULL, 5609 /* .pd_link_change = */ NULL, 5610 /* .pd_control_set = */ phy_viper_control_set, 5611 /* .pd_control_get = */ phy_viper_control_get, 5612 /* .pd_reg_read = */ phy_viper_reg_read, 5613 /* .pd_reg_write = */ phy_viper_reg_write, 5614 /* .pd_reg_modify = */ phy_viper_reg_modify, 5615 /* .pd_notify = */ phy_viper_notify, 5616 /* .pd_probe = */ phy_viper_probe, 5617 /* .pd_ability_advert_set = */ phy_viper_ability_advert_set, 5618 /* .pd_ability_advert_get = */ phy_viper_ability_advert_get, 5619 /* .pd_ability_remote_get = */ phy_viper_ability_remote_get, 5620 /* .pd_ability_local_get = */ phy_viper_ability_local_get, 5621 /* .pd_firmware_set = */ NULL, 5622 /* .pd_timesync_config_set = */ NULL, 5623 /* .pd_timesync_config_get = */ NULL, 5624 /* .pd_timesync_control_set = */ NULL, 5625 /* .pd_timesync_control_set = */ NULL, 5626 /* .pd_diag_ctrl = */ phy_viper_diag_ctrl, 5627 /* .pd_lane_control_set = */ phy_viper_per_lane_control_set, 5628 /* .pd_lane_control_get = */ phy_viper_per_lane_control_get 5629 }; 5630 5631 STATIC int 5632 _phy_viper_enable_set(int unit, soc_port_t port, int enable) 5633 { 5634 phy_ctrl_t *pc; 5635 soc_phymod_ctrl_t *pmc; 5636 phymod_phy_access_t *pm_phy; 5637 phymod_phy_power_t phy_power; 5638 5639 /* locate phy control */ 5640 pc = INT_PHY_SW_STATE(unit, port); 5641 if (pc == NULL) { 5642 return SOC_E_INTERNAL; 5643 } 5644 5645 pmc = &pc->phymod_ctrl; 5646 pm_phy = &pmc->phy[pmc->main_phy]->pm_phy; 5647 5648 if (enable) { 5649 phy_power.tx = phymodPowerOn; 5650 phy_power.rx = phymodPowerOn; 5651 } else { 5652 phy_power.tx = phymodPowerOff; 5653 phy_power.rx = phymodPowerOff; 5654 } 5655 5656 SOC_IF_ERROR_RETURN(phymod_phy_power_set(pm_phy, &phy_power)); 5657 /*viper_phy_power_set(&pm_phy->access, &power); */ 5658 5659 return SOC_E_NONE; 5660 } 5661 5662 5663 5664 5665 5666 #else 5667 int _viper_not_empty; 5668 #endif /* INCLUDE_XGXS_VIPER */ 5669