openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

qtce.c (174445B)


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