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