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

qtce16.c (67908B)


      1 /*
      2  *         
      3  * 
      4  * 
      5  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      6  * 
      7  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      8  */
      9 
     10 #include <phymod/phymod.h>
     11 #include <phymod/phymod_system.h>
     12 #include <phymod/phymod_dispatch.h>
     13 #include <phymod/phymod_debug.h>
     14 #include <phymod/phymod_util.h>
     15 #include <phymod/chip/bcmi_qtce16_xgxs_defs.h>
     16 #include <phymod/chip/merlin16.h>
     17 
     18 #include "qtce16/tier1/qe16PCSRegEnums.h"
     19 #include "qtce16/tier1/qmod16_enum_defines.h"
     20 #include "qtce16/tier1/qmod16_device.h"
     21 #include "qtce16/tier1/qmod16.h"
     22 #include "qtce16/tier1/qmod16_defines.h"
     23 #include "qtce16/tier1/qmod16_sc_lkup_table.h"
     24 #include "qtce16/tier1/phy_tsc_iblk.h"
     25 #include "merlin16/tier1/merlin16_cfg_seq.h"
     26 #include "merlin16/tier1/merlin16_common.h" 
     27 #include "merlin16/tier1/merlin16_interface.h" 
     28 #include "merlin16/tier1/merlin16_dependencies.h" 
     29 #include "merlin16/tier1/merlin16_internal.h"
     30 
     31 #ifdef PHYMOD_QTCE16_SUPPORT
     32 
     33 #define QTCE16_ID0        0x600d
     34 #define QTCE16_ID1        0x8770
     35 #define QTCE16_REV_MASK   0x0
     36 
     37 #define QTCE16_MODEL     0x16
     38 
     39 #define QTCE16_NOF_DFES (5)
     40 #define QTCE16_NOF_LANES_IN_CORE (4) 
     41 #define QTCE16_LANE_SWAP_LANE_MASK (0x3)
     42 #define QTCE16_PHY_ALL_LANES (0xf)
     43 #define QTCE16_CORE_TO_PHY_ACCESS(_phy_access, _core_access) \
     44     do{\
     45         PHYMOD_MEMCPY(&(_phy_access)->access, &(_core_access)->access, sizeof((_phy_access)->access));\
     46         (_phy_access)->type = (_core_access)->type; \
     47         (_phy_access)->access.lane_mask = QTCE16_PHY_ALL_LANES; \
     48     }while(0)
     49 
     50 extern unsigned char merlin16_ucode[];
     51 extern unsigned short merlin16_ucode_ver;
     52 extern unsigned short merlin16_ucode_crc;
     53 extern unsigned short merlin16_ucode_len;
     54 
     55 STATIC
     56 int _qtce16_phy_firmware_lane_config_set(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t fw_config)
     57 {
     58     struct merlin16_uc_lane_config_st serdes_firmware_config;
     59     phymod_phy_access_t phy_copy;
     60     int start_lane, num_lane, i;
     61     /* uint32_t rst_status; */
     62     uint32_t is_warm_boot;
     63 
     64     PHYMOD_IF_ERR_RETURN
     65         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
     66     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
     67 
     68     for (i = 0; i < num_lane; i++) {
     69         phy_copy.access.lane_mask = 1 << (start_lane + i);
     70         serdes_firmware_config.field.lane_cfg_from_pcs = fw_config.LaneConfigFromPCS;
     71         serdes_firmware_config.field.an_enabled        = fw_config.AnEnabled;
     72         serdes_firmware_config.field.dfe_on            = fw_config.DfeOn; 
     73         serdes_firmware_config.field.force_brdfe_on    = fw_config.ForceBrDfe;
     74         /* serdes_firmware_config.field.cl72_emulation_en = fw_config.Cl72Enable; */
     75         serdes_firmware_config.field.scrambling_dis    = fw_config.ScramblingDisable;
     76         serdes_firmware_config.field.unreliable_los    = fw_config.UnreliableLos;
     77         serdes_firmware_config.field.media_type        = fw_config.MediaType; 
     78 
     79         PHYMOD_IF_ERR_RETURN(PHYMOD_IS_WRITE_DISABLED(&phy_copy.access, &is_warm_boot));
     80 
     81         if (!is_warm_boot) {
     82             PHYMOD_IF_ERR_RETURN (merlin16_set_uc_lane_cfg(&phy_copy.access, serdes_firmware_config));
     83         }
     84     }
     85     return PHYMOD_E_NONE;
     86 }
     87 
     88 int qtce16_core_identify(const phymod_core_access_t* core, uint32_t core_id, uint32_t* is_identified)
     89 {        
     90     int ioerr = 0;
     91     const phymod_access_t *pm_acc = &core->access;
     92     PHYID2r_t id2;
     93     PHYID3r_t id3;
     94     MAIN_SERDESIDr_t serdesid;
     95     /* DIG_REVID0r_t revid; */
     96     uint32_t model;
     97     int rv ;
     98     *is_identified = 0;
     99 
    100     if(core_id == 0){
    101         ioerr += READ_PHYID2r(pm_acc, &id2);
    102         ioerr += READ_PHYID3r(pm_acc, &id3);
    103     }
    104     else{
    105         PHYID2r_SET(id2, ((core_id >> 16) & 0xffff));
    106         PHYID3r_SET(id3, core_id & 0xffff);
    107     }
    108 
    109     if (PHYID2r_GET(id2) == QTCE16_ID0 &&
    110         (PHYID3r_GET(id3) &= ~QTCE16_REV_MASK) == QTCE16_ID1) {
    111         /* PHY IDs match - now check PCS model */
    112         ioerr += READ_MAIN_SERDESIDr(pm_acc, &serdesid);
    113         model = MAIN_SERDESIDr_MODEL_NUMBERf_GET(serdesid);
    114         if (model == QTCE16_MODEL)  {
    115             *is_identified = 1;
    116         }
    117     }
    118     rv = ioerr ? PHYMOD_E_IO : PHYMOD_E_NONE;
    119     return rv ;    
    120 }
    121 
    122 
    123 int qtce16_core_info_get(const phymod_core_access_t* phy, phymod_core_info_t* info)
    124 {        
    125     uint32_t serdes_id;
    126     PHYID2r_t id2;
    127     PHYID3r_t id3;
    128     const phymod_access_t *pm_acc = &phy->access;
    129     PHYMOD_IF_ERR_RETURN
    130         (qmod16_revid_read(&phy->access, &serdes_id));
    131     info->serdes_id = serdes_id;
    132     if ((serdes_id & 0x3f) == QTCE16_MODEL) {
    133         info->core_version = phymodCoreVersionQtce16;
    134         PHYMOD_STRNCPY(info->name, "Qtce16", PHYMOD_STRLEN("Qtce16")+1);  /* need to remove when the master rev*/
    135     }
    136     /* need to update with the master rev
    137     PHYMOD_IF_ERR_RETURN
    138         (phymod_core_name_get(phy, serdes_id, core_name, info));
    139     */
    140 
    141     PHYMOD_IF_ERR_RETURN(READ_PHYID2r(pm_acc, &id2));
    142     PHYMOD_IF_ERR_RETURN(READ_PHYID3r(pm_acc, &id3));
    143 
    144     info->phy_id0 = (uint16_t) id2.v[0];
    145     info->phy_id1 = (uint16_t) id3.v[0];
    146     return PHYMOD_E_NONE;
    147 }
    148 
    149 /* 
    150  * set lane swapping for core 
    151  * The tx swap is composed of tx PCS swap. 
    152  * The rx swap is composed of rx PCS swap
    153  *
    154  * lane_map_tx and lane_map_rx[lane=logic_lane] are logic-lane base.
    155  * pcs_swap and register is logic_lane base. 
    156  */
    157 int qtce16_core_lane_map_set(const phymod_core_access_t* core, const phymod_lane_map_t* lane_map)
    158 {        
    159     uint32_t pcs_rx_swap = 0 , pcs_tx_swap = 0, lane;
    160     uint8_t pmd_tx_lane_map[PHYMOD_MAX_LANES_PER_CORE];
    161     uint8_t pmd_rx_lane_map[PHYMOD_MAX_LANES_PER_CORE];
    162     uint8_t num_lanes = (uint8_t) lane_map->num_of_lanes;
    163 
    164     if(lane_map->num_of_lanes != QTCE16_NOF_LANES_IN_CORE){
    165         return PHYMOD_E_CONFIG;
    166     }
    167     for( lane = 0 ; lane < QTCE16_NOF_LANES_IN_CORE ; lane++){
    168         if(lane_map->lane_map_rx[lane] >= QTCE16_NOF_LANES_IN_CORE){
    169             return PHYMOD_E_CONFIG;
    170         }
    171         /* encode each lane as four bits */
    172         /* pcs_rx_map[lane] = rx_map[lane] */
    173         pcs_rx_swap += lane_map->lane_map_rx[lane]<<(lane*4);
    174     }
    175 
    176     for( lane = 0 ; lane < QTCE16_NOF_LANES_IN_CORE ; lane++){
    177         if(lane_map->lane_map_tx[lane] >= QTCE16_NOF_LANES_IN_CORE){
    178             return PHYMOD_E_CONFIG;
    179         }
    180         pcs_tx_swap += lane_map->lane_map_tx[lane]<<(lane*4);
    181     }
    182 
    183     for (lane = 0; lane < QTCE16_NOF_LANES_IN_CORE; lane++) {
    184         pmd_tx_lane_map[(int)lane_map->lane_map_tx[lane]] = lane;
    185         pmd_rx_lane_map[(int)lane_map->lane_map_rx[lane]] = lane;
    186     }
    187 
    188 
    189     PHYMOD_IF_ERR_RETURN(qmod16_pcs_lane_swap(&core->access, pcs_tx_swap, pcs_rx_swap));
    190 
    191     PHYMOD_IF_ERR_RETURN
    192         (merlin16_map_lanes(&core->access, num_lanes, pmd_tx_lane_map, pmd_rx_lane_map));
    193 
    194     return PHYMOD_E_NONE;
    195 }
    196 
    197 int qtce16_core_lane_map_get(const phymod_core_access_t* core, phymod_lane_map_t* lane_map)
    198 {        
    199     uint32_t pcs_tx_swap = 0 , pcs_rx_swap = 0, lane; 
    200     PHYMOD_IF_ERR_RETURN(qmod16_pcs_lane_swap_get(&core->access, &pcs_tx_swap, &pcs_rx_swap));
    201     for( lane = 0 ; lane < QTCE16_NOF_LANES_IN_CORE ; lane++){
    202         /* deccode each lane from four bits */
    203         lane_map->lane_map_rx[lane] = (pcs_rx_swap>>(lane*4)) & QTCE16_LANE_SWAP_LANE_MASK;
    204 
    205         lane_map->lane_map_tx[lane] = (pcs_tx_swap>>(lane*4)) & QTCE16_LANE_SWAP_LANE_MASK;
    206     }
    207     lane_map->num_of_lanes = QTCE16_NOF_LANES_IN_CORE;
    208     return PHYMOD_E_NONE;
    209 }
    210 
    211 
    212 int qtce16_core_firmware_info_get(const phymod_core_access_t* core, phymod_core_firmware_info_t* fw_info)
    213 {
    214     /* 
    215      * It's O.K to use this code as is since the firmware CRC is already checked at 
    216      * at the time we load it.
    217      */
    218     fw_info->fw_crc = merlin16_ucode_crc;
    219     fw_info->fw_version = merlin16_ucode_ver;
    220     return PHYMOD_E_NONE;
    221     
    222 }
    223 /* load qtce16 fw. the fw_loader parameter is valid just for external fw load */
    224 STATIC
    225 int _qtce16_core_firmware_load(const phymod_core_access_t* core, phymod_firmware_load_method_t load_method, phymod_firmware_loader_f fw_loader)
    226 {
    227 
    228 
    229     switch(load_method){
    230     case phymodFirmwareLoadMethodInternal:
    231         PHYMOD_IF_ERR_RETURN(merlin16_ucode_mdio_load(&core->access, merlin16_ucode, merlin16_ucode_len));
    232         break;
    233     case phymodFirmwareLoadMethodExternal:
    234         PHYMOD_NULL_CHECK(fw_loader); 
    235 
    236         PHYMOD_IF_ERR_RETURN(merlin16_ucode_pram_load_pre(&core->access));
    237         PHYMOD_IF_ERR_RETURN(fw_loader(core, merlin16_ucode_len, merlin16_ucode));
    238         PHYMOD_IF_ERR_RETURN(merlin16_ucode_pram_load_post(&core->access)); 
    239         break;
    240     case phymodFirmwareLoadMethodNone:
    241         break;
    242     default:
    243         PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("illegal fw load method %u"), load_method));
    244     }
    245     return PHYMOD_E_NONE;
    246 }
    247 
    248 
    249 int qtce16_phy_firmware_core_config_set(const phymod_phy_access_t* phy, phymod_firmware_core_config_t fw_config)
    250 {
    251     struct merlin16_uc_core_config_st serdes_firmware_core_config;
    252     PHYMOD_MEMSET(&serdes_firmware_core_config, 0, sizeof(serdes_firmware_core_config));
    253     serdes_firmware_core_config.field.core_cfg_from_pcs = fw_config.CoreConfigFromPCS;
    254     serdes_firmware_core_config.field.vco_rate = fw_config.VcoRate;
    255  
    256     PHYMOD_IF_ERR_RETURN(merlin16_INTERNAL_set_uc_core_config(&phy->access, serdes_firmware_core_config));
    257     return PHYMOD_E_NONE;
    258 }
    259 
    260 int qtce16_phy_firmware_core_config_get(const phymod_phy_access_t* phy, phymod_firmware_core_config_t* fw_config)
    261 {
    262     struct merlin16_uc_core_config_st serdes_firmware_core_config;
    263     PHYMOD_IF_ERR_RETURN(merlin16_get_uc_core_config(&phy->access, &serdes_firmware_core_config));
    264     PHYMOD_MEMSET(fw_config, 0, sizeof(*fw_config));
    265     fw_config->CoreConfigFromPCS = serdes_firmware_core_config.field.core_cfg_from_pcs;
    266     fw_config->VcoRate = serdes_firmware_core_config.field.vco_rate;
    267     return PHYMOD_E_NONE;
    268 }
    269 
    270 
    271 int qtce16_phy_firmware_lane_config_set(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t fw_lane_config)
    272 {
    273     phymod_phy_access_t phy_copy;
    274     int start_lane, num_lane, i, lane_id, sub_port;
    275 
    276     PHYMOD_IF_ERR_RETURN
    277         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    278     PHYMOD_IF_ERR_RETURN
    279         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
    280     start_lane = lane_id;
    281     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    282 
    283     /*Hold the per lne soft reset bit*/
    284     for (i = 0; i < num_lane; i++) {
    285         phy_copy.access.lane_mask = 1 << (start_lane + i);
    286         PHYMOD_IF_ERR_RETURN
    287             (merlin16_lane_soft_reset_release(&phy_copy.access, 0));
    288     }
    289 
    290     for (i = 0; i < num_lane; i++) {
    291         phy_copy.access.lane_mask = 1 << (start_lane + i);
    292     PHYMOD_IF_ERR_RETURN
    293         (_qtce16_phy_firmware_lane_config_set(&phy_copy, fw_lane_config));
    294     }
    295     /*Hold the per lne soft reset bit*/
    296     for (i = 0; i < num_lane; i++) {
    297         phy_copy.access.lane_mask = 1 << (start_lane + i);
    298         PHYMOD_IF_ERR_RETURN
    299             (merlin16_lane_soft_reset_release(&phy_copy.access, 1));
    300     }
    301 
    302     /* no need to set speed trigger here */
    303     return PHYMOD_E_NONE;
    304 }
    305 
    306 int qtce16_phy_firmware_lane_config_get(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t* fw_config)
    307 {        
    308     
    309     struct merlin16_uc_lane_config_st serdes_firmware_config;
    310     phymod_phy_access_t phy_copy;
    311     int lane_id, sub_port;
    312 
    313     PHYMOD_IF_ERR_RETURN
    314         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
    315     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    316     phy_copy.access.lane_mask = 1 << lane_id;
    317 
    318     PHYMOD_IF_ERR_RETURN(merlin16_get_uc_lane_cfg(&phy_copy.access, &serdes_firmware_config));
    319     PHYMOD_MEMSET(fw_config, 0, sizeof(*fw_config));
    320     fw_config->LaneConfigFromPCS = serdes_firmware_config.field.lane_cfg_from_pcs;
    321     fw_config->AnEnabled         = serdes_firmware_config.field.an_enabled;
    322     fw_config->DfeOn             = serdes_firmware_config.field.dfe_on;
    323     fw_config->ForceBrDfe        = serdes_firmware_config.field.force_brdfe_on;
    324     fw_config->Cl72AutoPolEn        = serdes_firmware_config.field.cl72_auto_polarity_en;
    325     fw_config->Cl72RestTO      = serdes_firmware_config.field.cl72_restart_timeout_en;
    326     fw_config->ScramblingDisable = serdes_firmware_config.field.scrambling_dis;
    327     fw_config->UnreliableLos     = serdes_firmware_config.field.unreliable_los;
    328     fw_config->MediaType         = serdes_firmware_config.field.media_type;
    329 
    330     return PHYMOD_E_NONE;    
    331 }
    332 
    333 int qtce16_phy_polarity_set(const phymod_phy_access_t* phy, const phymod_polarity_t* polarity)
    334 {        
    335     phymod_phy_access_t phy_copy;
    336     int lane_id, sub_port;
    337 
    338     PHYMOD_IF_ERR_RETURN
    339         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
    340     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    341     phy_copy.access.lane_mask = 1 << lane_id;
    342 
    343     PHYMOD_IF_ERR_RETURN
    344         (qmod16_tx_rx_polarity_set(&phy_copy.access, polarity->tx_polarity, polarity->rx_polarity));
    345 
    346     return PHYMOD_E_NONE;
    347     
    348 }
    349 
    350 int qtce16_phy_polarity_get(const phymod_phy_access_t* phy, phymod_polarity_t* polarity)
    351 {        
    352     phymod_phy_access_t phy_copy;
    353     int lane_id, sub_port;
    354 
    355     PHYMOD_IF_ERR_RETURN
    356         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
    357     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    358     phy_copy.access.lane_mask = 1 << lane_id;
    359 
    360     PHYMOD_IF_ERR_RETURN
    361         (qmod16_tx_rx_polarity_get(&phy_copy.access, &polarity->tx_polarity, &polarity->rx_polarity));
    362     
    363     return PHYMOD_E_NONE;    
    364 }
    365 
    366 
    367 int qtce16_phy_tx_set(const phymod_phy_access_t* phy, const phymod_tx_t* tx)
    368 {        
    369     phymod_phy_access_t phy_copy;
    370     int lane_id, sub_port;
    371 
    372     PHYMOD_IF_ERR_RETURN
    373         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
    374     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    375     phy_copy.access.lane_mask = 1 << lane_id;
    376 
    377     PHYMOD_IF_ERR_RETURN
    378         (merlin16_apply_txfir_cfg(&phy_copy.access, (int8_t)tx->pre, (int8_t)tx->main, (int8_t)tx->post, (int8_t)tx->post2));
    379     return PHYMOD_E_NONE;    
    380 }
    381 
    382 int qtce16_phy_tx_get(const phymod_phy_access_t* phy, phymod_tx_t* tx)
    383 {
    384     phymod_phy_access_t phy_copy;
    385     int lane_id, sub_port;
    386     int8_t value = 0;
    387 
    388     PHYMOD_IF_ERR_RETURN
    389         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
    390     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    391     phy_copy.access.lane_mask = 1 << lane_id;
    392 
    393     PHYMOD_IF_ERR_RETURN
    394         (merlin16_read_tx_afe(&phy_copy.access, TX_AFE_PRE, &value));
    395     tx->pre = value;
    396     PHYMOD_IF_ERR_RETURN
    397         (merlin16_read_tx_afe(&phy_copy.access, TX_AFE_MAIN, &value));
    398     tx->main = value;
    399     PHYMOD_IF_ERR_RETURN
    400         (merlin16_read_tx_afe(&phy_copy.access, TX_AFE_POST1, &value));
    401     tx->post = value;
    402     PHYMOD_IF_ERR_RETURN
    403         (merlin16_read_tx_afe(&phy_copy.access, TX_AFE_POST2, &value));
    404     tx->post2 = value;
    405 
    406     return PHYMOD_E_NONE;
    407 }
    408 
    409 int qtce16_phy_cl72_set(const phymod_phy_access_t* phy, uint32_t cl72_en)
    410 {
    411     struct merlin16_uc_lane_config_st serdes_firmware_config;
    412     phymod_phy_access_t phy_copy;
    413     int lane_id, sub_port;
    414 
    415     PHYMOD_IF_ERR_RETURN
    416         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
    417     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    418     phy_copy.access.lane_mask = 1 << lane_id;
    419 
    420     PHYMOD_IF_ERR_RETURN(merlin16_get_uc_lane_cfg(&phy_copy.access, &serdes_firmware_config));
    421 
    422     if (serdes_firmware_config.field.dfe_on == 0) {
    423       PHYMOD_DEBUG_ERROR(("ERROR :: DFE is off : Can not start CL72 with no DFE\n"));
    424       return PHYMOD_E_CONFIG;
    425     }
    426 
    427     PHYMOD_IF_ERR_RETURN
    428         (qmod16_clause72_control(&phy->access, cl72_en));
    429 
    430     return PHYMOD_E_NONE;
    431 }
    432 
    433 int qtce16_phy_cl72_get(const phymod_phy_access_t* phy, uint32_t* cl72_en)
    434 {
    435     phymod_phy_access_t phy_copy;
    436     int lane_id, sub_port;
    437 
    438     PHYMOD_IF_ERR_RETURN
    439         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
    440     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    441     phy_copy.access.lane_mask = 1 << lane_id;
    442 
    443     PHYMOD_IF_ERR_RETURN
    444         (merlin16_pmd_cl72_enable_get(&phy_copy.access, cl72_en));
    445 
    446     return PHYMOD_E_NONE;
    447 }
    448 
    449 int qtce16_phy_cl72_status_get(const phymod_phy_access_t* phy, phymod_cl72_status_t* status)
    450 {
    451     uint32_t local_status;
    452     phymod_phy_access_t phy_copy;
    453     int lane_id, sub_port;
    454 
    455     PHYMOD_IF_ERR_RETURN
    456         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
    457     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    458     phy_copy.access.lane_mask = 1 << lane_id;
    459 
    460     PHYMOD_IF_ERR_RETURN
    461         (merlin16_pmd_cl72_receiver_status(&phy_copy.access, &local_status));
    462     status->locked = local_status;
    463 
    464     return PHYMOD_E_NONE;
    465 }
    466 
    467 int qtce16_phy_tx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t tx_control)
    468 {        
    469    phymod_phy_access_t pm_phy_copy;
    470     int start_lane, num_lane, lane_id, sub_port;
    471     int qmode = 0, subports = 0, sq_value = 0;
    472 
    473     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
    474     /* next program the tx fir taps and driver current based on the input */
    475     PHYMOD_IF_ERR_RETURN
    476         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    477 
    478     PHYMOD_IF_ERR_RETURN
    479         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
    480 
    481     start_lane = lane_id ;  
    482     pm_phy_copy.access.lane_mask = 0x1 << start_lane;
    483 
    484     if (PHYMOD_ACC_F_QMODE_GET(&phy->access) || PHYMOD_ACC_F_USXMODE_GET(&phy->access)) {
    485         qmode = 1;
    486         PHYMOD_IF_ERR_RETURN(qmod16_port_state_get(&pm_phy_copy.access, QMOD16_PORT_STATE_CONFIGED, &subports));
    487     }
    488 
    489     switch (tx_control) {
    490     case phymodTxTrafficDisable:
    491         PHYMOD_IF_ERR_RETURN(qmod16_tx_lane_control_set(&pm_phy_copy.access, QMOD16_TX_LANE_TRAFFIC_DISABLE));
    492         break;
    493     case phymodTxTrafficEnable:
    494         PHYMOD_IF_ERR_RETURN(qmod16_tx_lane_control_set(&pm_phy_copy.access, QMOD16_TX_LANE_TRAFFIC_ENABLE));
    495         break;
    496     case phymodTxReset:
    497         PHYMOD_IF_ERR_RETURN(qmod16_tx_lane_control_set(&pm_phy_copy.access, QMOD16_TX_LANE_RESET));
    498         break;
    499     case phymodTxSquelchOn:
    500         PHYMOD_IF_ERR_RETURN(qmod16_port_state_set(&pm_phy_copy.access, QMOD16_PORT_STATE_TX_SQUELCH, sub_port, 1));
    501         PHYMOD_IF_ERR_RETURN(qmod16_port_state_get(&pm_phy_copy.access, QMOD16_PORT_STATE_TX_SQUELCH, &sq_value));
    502         if ((qmode == 0) || (sq_value == subports)) { 
    503             /* not qmode or all subports want to squelch*/
    504             PHYMOD_IF_ERR_RETURN(qmod16_tx_squelch_set(&pm_phy_copy.access, 1));
    505         }
    506         break;
    507     case phymodTxSquelchOff:
    508         PHYMOD_IF_ERR_RETURN(qmod16_port_state_set(&pm_phy_copy.access, QMOD16_PORT_STATE_TX_SQUELCH, sub_port, 0));
    509         PHYMOD_IF_ERR_RETURN(qmod16_tx_squelch_set(&pm_phy_copy.access, 0));
    510         break;
    511     default:
    512         break;
    513     }     
    514     return PHYMOD_E_NONE;
    515     
    516 }
    517 
    518 int qtce16_phy_tx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t* tx_control)
    519 {        
    520     int enable, reset, tx_lane;
    521     uint32_t lb_enable;
    522     phymod_phy_access_t pm_phy_copy;
    523     int start_lane, num_lane, lane_id, sub_port;
    524 
    525     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
    526     /* next program the tx fir taps and driver current based on the input */
    527     PHYMOD_IF_ERR_RETURN
    528         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    529     
    530     PHYMOD_IF_ERR_RETURN
    531         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
    532     start_lane = lane_id ;
    533     pm_phy_copy.access.lane_mask = 0x1 << start_lane;
    534 
    535     PHYMOD_IF_ERR_RETURN(qmod16_tx_squelch_get(&pm_phy_copy.access, &enable));
    536 
    537     /* next check if PMD loopback is on */ 
    538     if (enable) {                           
    539         PHYMOD_IF_ERR_RETURN(merlin16_pmd_loopback_get(&pm_phy_copy.access, &lb_enable));
    540         if (lb_enable) enable = 0;
    541     }
    542 
    543     if(enable) {
    544         *tx_control = phymodTxSquelchOn;
    545     } else {
    546         PHYMOD_IF_ERR_RETURN(qmod16_tx_lane_control_get(&pm_phy_copy.access, &reset, &tx_lane));
    547         if (!reset) {
    548             *tx_control = phymodTxReset;
    549         } else if (!tx_lane) {
    550             *tx_control = phymodTxTrafficDisable;
    551         } else {
    552             *tx_control = phymodTxTrafficEnable;
    553         }
    554     }
    555    
    556     return PHYMOD_E_NONE;
    557     
    558 }
    559 
    560 
    561 int qtce16_phy_rx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t rx_control)
    562 {
    563     phymod_phy_access_t pm_phy_copy;
    564     int start_lane, num_lane, lane_id, sub_port;
    565     int qmode = 0, subports = 0, sq_value = 0;
    566 
    567     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
    568     /* next program the tx fir taps and driver current based on the input */
    569     PHYMOD_IF_ERR_RETURN
    570         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    571 
    572     PHYMOD_IF_ERR_RETURN
    573         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
    574 
    575     start_lane = lane_id ;  
    576     pm_phy_copy.access.lane_mask = 0x1 << start_lane;
    577 
    578     if (PHYMOD_ACC_F_QMODE_GET(&phy->access) || PHYMOD_ACC_F_USXMODE_GET(&phy->access)) {
    579         qmode = 1;
    580         PHYMOD_IF_ERR_RETURN(qmod16_port_state_get(&pm_phy_copy.access, QMOD16_PORT_STATE_CONFIGED, &subports));
    581     }
    582     switch (rx_control) {
    583     case phymodRxReset:
    584         PHYMOD_IF_ERR_RETURN(qmod16_rx_lane_control_set(&pm_phy_copy.access, 1));
    585         break;
    586     case phymodRxSquelchOn:
    587         PHYMOD_IF_ERR_RETURN(qmod16_port_state_set(&pm_phy_copy.access, QMOD16_PORT_STATE_RX_SQUELCH, sub_port, 1));
    588         PHYMOD_IF_ERR_RETURN(qmod16_port_state_get(&pm_phy_copy.access, QMOD16_PORT_STATE_RX_SQUELCH, &sq_value));
    589         if ((qmode == 0) || (sq_value == subports)) {  
    590             /* not qmode or all subports want to squelch */
    591             PHYMOD_IF_ERR_RETURN(qmod16_rx_squelch_set(&pm_phy_copy.access, 1));    
    592         }
    593         break;
    594     case phymodRxSquelchOff:
    595         PHYMOD_IF_ERR_RETURN(qmod16_port_state_set(&pm_phy_copy.access, QMOD16_PORT_STATE_RX_SQUELCH, sub_port, 0));
    596         PHYMOD_IF_ERR_RETURN(qmod16_rx_squelch_set(&pm_phy_copy.access, 0));
    597         break;
    598     default:
    599         break;
    600     }   
    601     return PHYMOD_E_NONE;
    602     
    603 }
    604 
    605 int qtce16_phy_rx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t* rx_control)
    606 {
    607     int enable, reset;
    608     uint32_t lb_enable;
    609     phymod_phy_access_t pm_phy_copy;
    610     int start_lane, num_lane, lane_id, sub_port;
    611 
    612     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
    613     /* next program the tx fir taps and driver current based on the input */
    614     PHYMOD_IF_ERR_RETURN
    615         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    616 
    617     PHYMOD_IF_ERR_RETURN
    618         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
    619 
    620     start_lane = lane_id ;
    621     pm_phy_copy.access.lane_mask = 0x1 << start_lane;
    622 
    623     PHYMOD_IF_ERR_RETURN(qmod16_rx_squelch_get(&pm_phy_copy.access, &enable));
    624     /* next check if PMD loopback is on */ 
    625     if (enable) {                           
    626         PHYMOD_IF_ERR_RETURN(merlin16_pmd_loopback_get(&pm_phy_copy.access, &lb_enable));
    627         if (lb_enable) enable = 0;
    628     }
    629     if(enable) {
    630         *rx_control = phymodRxSquelchOn;
    631     } else {
    632         PHYMOD_IF_ERR_RETURN(qmod16_rx_lane_control_get(&pm_phy_copy.access, &reset));
    633         if (reset == 0) {
    634             *rx_control = phymodRxReset;
    635         } else {
    636             *rx_control = phymodRxSquelchOff;
    637         }
    638     }   
    639     return PHYMOD_E_NONE;    
    640 }
    641 
    642 int qtce16_phy_power_set(const phymod_phy_access_t* phy, const phymod_phy_power_t* power)
    643 {        
    644      phymod_phy_access_t pm_phy_copy;
    645     int start_lane, num_lane, lane_id, sub_port;
    646     
    647     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
    648     /* next program the tx fir taps and driver current based on the input */
    649     PHYMOD_IF_ERR_RETURN
    650         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    651 
    652     PHYMOD_IF_ERR_RETURN
    653         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
    654 
    655     start_lane = lane_id ;
    656     pm_phy_copy.access.lane_mask = 0x1 << start_lane;
    657 
    658 
    659     if ((power->tx == phymodPowerOff) && (power->rx == phymodPowerOff)) {        
    660         PHYMOD_IF_ERR_RETURN(qmod16_port_enable_set(&pm_phy_copy.access, 0));
    661     }
    662     if ((power->tx == phymodPowerOn) && (power->rx == phymodPowerOn)) {
    663         PHYMOD_IF_ERR_RETURN(qmod16_port_enable_set(&pm_phy_copy.access, 1));
    664     }
    665 
    666     if ((power->tx == phymodPowerOff) && (power->rx == phymodPowerNoChange)) {
    667         /* disable tx on the PMD side */
    668         PHYMOD_IF_ERR_RETURN(merlin16_tx_disable(&pm_phy_copy.access, 1));
    669     }
    670     if ((power->tx == phymodPowerOn) && (power->rx == phymodPowerNoChange)) {
    671         /* enable tx on the PMD side */
    672         PHYMOD_IF_ERR_RETURN(merlin16_tx_disable(&pm_phy_copy.access, 0));
    673     }
    674     if ((power->tx == phymodPowerNoChange) && (power->rx == phymodPowerOff)) {
    675         /* disable rx on the PMD side */
    676         PHYMOD_IF_ERR_RETURN(qmod16_rx_squelch_set(&pm_phy_copy.access, 1));
    677     }
    678     if ((power->tx == phymodPowerNoChange) && (power->rx == phymodPowerOn)) {
    679         /* enable rx on the PMD side */
    680         PHYMOD_IF_ERR_RETURN(qmod16_rx_squelch_set(&pm_phy_copy.access, 0));
    681     }    
    682     return PHYMOD_E_NONE;
    683     
    684 }
    685 
    686 int qtce16_phy_power_get(const phymod_phy_access_t* phy, phymod_phy_power_t* power)
    687 {        
    688     int enable;
    689     uint32_t lb_enable;
    690     phymod_phy_access_t pm_phy_copy;
    691     int start_lane, num_lane, lane_id, sub_port;
    692 
    693     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
    694     /* next program the tx fir taps and driver current based on the input */
    695     PHYMOD_IF_ERR_RETURN
    696         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    697     
    698     PHYMOD_IF_ERR_RETURN
    699         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
    700     
    701     start_lane = lane_id ;
    702     pm_phy_copy.access.lane_mask = 0x1 << start_lane;
    703 
    704     PHYMOD_IF_ERR_RETURN(qmod16_rx_squelch_get(&pm_phy_copy.access, &enable));
    705 
    706     /* next check if PMD loopback is on */ 
    707     if (enable) {                           
    708         PHYMOD_IF_ERR_RETURN(merlin16_pmd_loopback_get(&pm_phy_copy.access, &lb_enable));
    709         if (lb_enable) enable = 0;
    710     }
    711 
    712     power->rx = (enable == 1)? phymodPowerOff: phymodPowerOn;
    713     power->tx = (enable == 1)? phymodPowerOff: phymodPowerOn;
    714         
    715     return PHYMOD_E_NONE;
    716 }
    717 
    718 int _qtce16_pll_multiplier_get(uint32_t pll_div, uint32_t *pll_multiplier)
    719 {
    720     switch (pll_div) {
    721     case 0x0:
    722         *pll_multiplier = 46;
    723         break;
    724     case 0x1:
    725         *pll_multiplier = 72;
    726         break;
    727     case QMOD16_PLL_MODE_DIV_40:
    728         *pll_multiplier = 40;
    729         break;
    730     case QMOD16_PLL_MODE_DIV_42:
    731         *pll_multiplier = 42;
    732         break;
    733     case QMOD16_PLL_MODE_DIV_48:
    734         *pll_multiplier = 48;
    735         break;
    736     case 0x5:
    737         *pll_multiplier = 50;
    738         break;
    739     case QMOD16_PLL_MODE_DIV_52:
    740         *pll_multiplier = 52;
    741         break;
    742     case QMOD16_PLL_MODE_DIV_54:
    743         *pll_multiplier = 54;
    744         break;
    745     case QMOD16_PLL_MODE_DIV_60:
    746         *pll_multiplier = 60;
    747         break;
    748     case QMOD16_PLL_MODE_DIV_64:
    749         *pll_multiplier = 64;
    750         break;
    751     case QMOD16_PLL_MODE_DIV_66:
    752         *pll_multiplier = 66;
    753         break;
    754     case 0xb:
    755         *pll_multiplier = 68;
    756         break;
    757     case QMOD16_PLL_MODE_DIV_70:
    758         *pll_multiplier = 70;
    759         break;
    760     case QMOD16_PLL_MODE_DIV_80:
    761         *pll_multiplier = 80;
    762         break;
    763     case QMOD16_PLL_MODE_DIV_92:
    764         *pll_multiplier = 92;
    765         break;
    766     case 0xf:
    767         *pll_multiplier = 100;
    768         break;
    769     default:
    770         *pll_multiplier = 66;
    771         break;
    772     }
    773     return PHYMOD_E_NONE;
    774 }
    775 
    776 /* to modify the sub-port speed */
    777 STATIC
    778 int _qtce16_qsgmii_interface_config_set(const phymod_phy_access_t* phy, uint32_t flags, const phymod_phy_inf_config_t* config)
    779 {
    780     qmod16_spd_intfc_type spd_intf = QMOD16_SPD_ILLEGAL;
    781     qmod16_spd_intfc_type qmod16_spd_intf = QMOD16_SPD_ILLEGAL, base_spd_intf;
    782     phymod_phy_access_t pm_phy_copy;
    783     int      start_lane, lane_id, sub_port, num_lane ;
    784 
    785     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
    786 
    787     /* next program the tx fir taps and driver current based on the input */
    788     /* get num_lane only in QTC */
    789     PHYMOD_IF_ERR_RETURN
    790         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    791 
    792     PHYMOD_IF_ERR_RETURN
    793         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
    794 
    795     start_lane = lane_id ;  
    796     pm_phy_copy.access.lane_mask = 0x1 << start_lane;
    797 
    798     spd_intf = QMOD16_SPD_1000_SGMII; /* to prevent undefinded QMOD16_SPD_ILLEGAL accessing tables */
    799 
    800     switch(config->data_rate) {
    801     case 10:
    802         spd_intf = QMOD16_SPD_10_SGMII;
    803         break;
    804     case 100:
    805         spd_intf = QMOD16_SPD_100_SGMII;
    806         break;
    807     case 1000:
    808         spd_intf = QMOD16_SPD_1000_SGMII;
    809         break;
    810     case 2500:
    811         spd_intf = QMOD16_SPD_2500_USXGMII;
    812         break;
    813     default:
    814         spd_intf = QMOD16_SPD_ILLEGAL;
    815         break;
    816     }
    817     
    818     qmod16_spd_intf = spd_intf;
    819     base_spd_intf = PHYMOD_ACC_F_QMODE_GET(&phy->access) ? QMOD16_SPD_1000_SGMII : QMOD16_SPD_2500_USXGMII;
    820 
    821     /* All sub-port speed changes have to go through the base, not replicated speed */
    822     PHYMOD_IF_ERR_RETURN
    823         (qmod16_set_qport_spd(&pm_phy_copy.access, sub_port, base_spd_intf));
    824     
    825     if (qmod16_spd_intf != base_spd_intf) {
    826         PHYMOD_IF_ERR_RETURN
    827             (qmod16_set_qport_spd(&pm_phy_copy.access, sub_port, qmod16_spd_intf));
    828     }
    829 
    830     return PHYMOD_E_NONE;
    831 
    832 }
    833 
    834 int qtce16_phy_interface_config_set(const phymod_phy_access_t* phy, uint32_t flags, const phymod_phy_inf_config_t* config)
    835 {
    836     uint32_t current_pll_div=0;
    837     uint32_t new_pll_div=0;
    838     uint16_t new_speed_vec=0;
    839     qmod16_spd_intfc_type spd_intf = QMOD16_SPD_ILLEGAL;
    840     phymod_phy_access_t pm_phy_copy;
    841     int start_lane, num_lane, i;
    842     int      lane_id, sub_port ;
    843     uint32_t sc_enable = 0;
    844     uint32_t u_os_mode = 0;
    845     phymod_firmware_lane_config_t firmware_lane_config;  
    846 
    847     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
    848 
    849     firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane;  /* MediaType=0 */
    850 
    851     /* next program the tx fir taps and driver current based on the input */
    852     /* get num_lane only in QTC */
    853     PHYMOD_IF_ERR_RETURN
    854         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    855 
    856     PHYMOD_IF_ERR_RETURN
    857         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
    858 
    859     start_lane = lane_id ;  
    860     pm_phy_copy.access.lane_mask = 0x1 << start_lane;
    861     
    862     /* Set subport speed if the lane speed is configured in QSGMII/USXGMII mode */
    863     if (PHYMOD_ACC_F_QMODE_GET(&phy->access) || PHYMOD_ACC_F_USXMODE_GET(&phy->access)) {
    864         qmod16_speedchange_get(&pm_phy_copy.access, &sc_enable) ;
    865         if (sc_enable) {
    866             return _qtce16_qsgmii_interface_config_set(phy, flags, config);
    867         }
    868     }
    869 
    870     PHYMOD_IF_ERR_RETURN
    871         (qmod16_reset(&pm_phy_copy.access)); 
    872       
    873     /* Hold the per lane soft reset bit */
    874     for (i = 0; i < num_lane; i++) {
    875         pm_phy_copy.access.lane_mask = 1 << (start_lane + i);
    876         PHYMOD_IF_ERR_RETURN
    877             (merlin16_lane_soft_reset_release(&pm_phy_copy.access, 0));
    878     }
    879 
    880     pm_phy_copy.access.lane_mask = 0x1 << start_lane;
    881      PHYMOD_IF_ERR_RETURN
    882         (qtce16_phy_firmware_lane_config_get(&pm_phy_copy, &firmware_lane_config));
    883 
    884     /* make sure that an and config from pcs is off */
    885     firmware_lane_config.AnEnabled = 0;
    886     firmware_lane_config.LaneConfigFromPCS = 0;
    887     if (PHYMOD_INTF_MODES_FIBER_GET(config)) {
    888         firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics;
    889     }     
    890 
    891     if (config->data_rate == 10 || config->data_rate == 100 || config->data_rate == 1000) {
    892         if (config->interface_type == phymodInterfaceSGMII) {
    893             firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane;
    894         }
    895         if (config->interface_type == phymodInterface1000X) {
    896             firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics;
    897         }
    898     } else if (config->data_rate == 2500) {
    899         if (config->interface_type == phymodInterfaceSGMII) {
    900             firmware_lane_config.MediaType  = phymodFirmwareMediaTypePcbTraceBackPlane;
    901             firmware_lane_config.DfeOn      = 1;
    902             firmware_lane_config.Cl72RestTO = 1;
    903         } else {
    904             firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics;
    905         }
    906     }
    907 
    908     switch (config->data_rate) {
    909     case 10:
    910         spd_intf = QMOD16_SPD_10_X1_10;
    911         break;
    912     case 100:
    913         spd_intf = QMOD16_SPD_100_X1_10;
    914         break;
    915     case 1000:
    916         spd_intf = QMOD16_SPD_1000_X1_10;
    917         break;
    918     default:
    919         spd_intf = QMOD16_SPD_ILLEGAL;
    920         break;
    921     }
    922 
    923     if (PHYMOD_ACC_F_QMODE_GET(&phy->access)) {
    924          spd_intf = QMOD16_SPD_4000;
    925     } else if (PHYMOD_ACC_F_USXMODE_GET(&phy->access)) {
    926          spd_intf = QMOD16_SPD_10G_X1_USXGMII;
    927     }
    928 
    929     PHYMOD_IF_ERR_RETURN
    930         (qmod16_get_plldiv(&pm_phy_copy.access, &current_pll_div));
    931 
    932     PHYMOD_IF_ERR_RETURN
    933         (qmod16_plldiv_lkup_get(&pm_phy_copy.access, spd_intf, &new_pll_div, &new_speed_vec));
    934 
    935     PHYMOD_IF_ERR_RETURN
    936         (qmod16_pmd_osmode_set(&pm_phy_copy.access, spd_intf, u_os_mode));
    937 
    938     /* Don't support PLL change because 10.3125G is for USXGMII and 10G for QSGMII/SGMII/GMII.*/
    939     if (current_pll_div != new_pll_div) {
    940         PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 
    941                                (_PHYMOD_MSG("Not support VCO change: %u %u\r\n"),
    942                                  current_pll_div, new_pll_div));
    943     }
    944 
    945     for (i = 0; i < num_lane; i++) {
    946         pm_phy_copy.access.lane_mask = 0x1 << (start_lane + i);
    947         PHYMOD_IF_ERR_RETURN
    948             (_qtce16_phy_firmware_lane_config_set(&pm_phy_copy, firmware_lane_config));
    949     }
    950 
    951     /* Release the per lane soft reset bit */
    952     for (i = 0; i < num_lane; i++) {
    953         pm_phy_copy.access.lane_mask = 1 << (start_lane + i);
    954         PHYMOD_IF_ERR_RETURN
    955             (merlin16_lane_soft_reset_release(&pm_phy_copy.access, 1));
    956     }
    957 
    958     /* Set lane speed ID and trigger speed change */
    959     PHYMOD_IF_ERR_RETURN
    960         (qmod16_set_spd_intf(&pm_phy_copy.access, spd_intf, 0));
    961 
    962     /* Set sub-port speed of this lane */
    963     if (PHYMOD_ACC_F_QMODE_GET(&phy->access) || PHYMOD_ACC_F_USXMODE_GET(&phy->access)) {
    964         PHYMOD_IF_ERR_RETURN
    965             (_qtce16_qsgmii_interface_config_set(phy, flags, config));
    966     }
    967 
    968 
    969     return PHYMOD_E_NONE;
    970 }
    971 
    972 int _qtce16_speed_id_interface_config_get(const phymod_phy_access_t* phy, int speed_id, 
    973                                         phymod_phy_inf_config_t* config, uint16_t an_enable, 
    974                                         phymod_firmware_lane_config_t *lane_config)
    975 {
    976     int ilkn_set;
    977     int osr_mode;
    978     uint32_t vco_rate;
    979     uint32_t pll_multiplier;
    980     uint32_t current_pll_div=0;
    981     uint32_t actual_osr, actual_osr_rem;
    982     phymod_osr_mode_t osr_mode_enum;
    983 
    984     PHYMOD_IF_ERR_RETURN
    985         (qmod16_get_plldiv(&phy->access, &current_pll_div));
    986 
    987     ilkn_set = 0;
    988     /* coverity[dead_error_condition] */
    989     if(ilkn_set) {
    990         /* coverity[dead_error_begin] */
    991         config->interface_type = phymodInterfaceBypass;
    992         PHYMOD_IF_ERR_RETURN
    993             (_qtce16_pll_multiplier_get(current_pll_div, &pll_multiplier));
    994         PHYMOD_IF_ERR_RETURN
    995             (merlin16_osr_mode_get(&phy->access, &osr_mode));
    996 
    997         switch (config->ref_clock) {
    998             case phymodRefClk156Mhz:
    999                 vco_rate = pll_multiplier * 156 + pll_multiplier * 25 / 100;
   1000                 break;
   1001             case phymodRefClk125Mhz:
   1002                 vco_rate = pll_multiplier * 125;
   1003                 break;
   1004             default:
   1005                 vco_rate = pll_multiplier * 156 + pll_multiplier * 25 / 100;
   1006                 break;
   1007         }
   1008 
   1009         PHYMOD_IF_ERR_RETURN(merlin16_osr_mode_to_enum(osr_mode, &osr_mode_enum));
   1010         PHYMOD_IF_ERR_RETURN(phymod_osr_mode_to_actual_os(osr_mode_enum, &actual_osr, &actual_osr_rem));
   1011         config->data_rate = vco_rate/actual_osr;
   1012     } else {
   1013       switch (speed_id) {
   1014       case 0x1:
   1015           config->data_rate = 10;
   1016           config->interface_type = phymodInterfaceSGMII;
   1017           break;
   1018       case 0x2:
   1019           config->data_rate = 100;
   1020           config->interface_type = phymodInterfaceSGMII;
   1021           break;
   1022       case 0x3:
   1023           if (lane_config->MediaType == phymodFirmwareMediaTypeOptics) {
   1024               config->interface_type = phymodInterface1000X;
   1025           } else {
   1026               config->interface_type = phymodInterfaceSGMII;
   1027           }     
   1028           config->data_rate = 1000;
   1029           break;
   1030       case 0x5:
   1031           config->data_rate = 1000;
   1032           config->interface_type = phymodInterfaceKX;
   1033           break;
   1034       case 0x6:
   1035           config->data_rate = 2500;
   1036           if (lane_config->MediaType == phymodFirmwareMediaTypeOptics) {
   1037               config->interface_type = phymodInterfaceSR;
   1038           } else {
   1039               config->interface_type = phymodInterfaceSGMII;
   1040           }
   1041           break;
   1042       case 0x39:
   1043           config->data_rate = 10;
   1044           config->interface_type = phymodInterfaceSGMII;
   1045           break;
   1046       case 0x3a:
   1047           config->data_rate = 100;
   1048           config->interface_type = phymodInterfaceSGMII;
   1049           break;
   1050       case 0x3b:
   1051           config->data_rate = 1000;
   1052           config->interface_type = phymodInterfaceSGMII;
   1053           break;
   1054       case 0x3c:  /* this is qsgmii mode */
   1055           config->data_rate = 1000;
   1056           config->interface_type = phymodInterfaceSGMII;
   1057           break;
   1058       case 0x48:
   1059           config->data_rate = 2500;
   1060           config->interface_type = phymodInterfaceSGMII;
   1061           break;
   1062       default:
   1063           config->data_rate = 0;
   1064           config->interface_type = phymodInterfaceSGMII;
   1065           break;
   1066       }
   1067     }
   1068     return PHYMOD_E_NONE;
   1069 }
   1070 
   1071 int qtce16_phy_interface_config_get(const phymod_phy_access_t* phy, uint32_t flags, phymod_ref_clk_t ref_clock, phymod_phy_inf_config_t* config)
   1072 {        
   1073     int speed_id;
   1074     phymod_firmware_lane_config_t firmware_lane_config;  
   1075     phymod_phy_access_t pm_phy_copy;
   1076     int start_lane, num_lane;
   1077     qmod16_an_control_t an_control;
   1078     qmod16_an_ability_t an_ability_st;
   1079     int an_complete = 0;
   1080     int      lane_id, sub_port ;
   1081 
   1082     config->ref_clock = ref_clock;
   1083     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
   1084     PHYMOD_IF_ERR_RETURN
   1085         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
   1086 
   1087     PHYMOD_IF_ERR_RETURN
   1088         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
   1089     start_lane = lane_id ;
   1090     
   1091     pm_phy_copy.access.lane_mask = 0x1 << start_lane;
   1092     PHYMOD_IF_ERR_RETURN
   1093         (qmod16_speed_id_get(&pm_phy_copy.access, &speed_id, sub_port));
   1094 
   1095     PHYMOD_MEMSET(&an_control, 0x0,  sizeof(qmod16_an_control_t));
   1096     PHYMOD_IF_ERR_RETURN
   1097         (qmod16_autoneg_control_get(&pm_phy_copy.access, sub_port, &an_control, &an_complete));
   1098 
   1099     /* There is no resolved speed ID register for USXGMII. Get it from AN resolution HCD if AN is enabled */
   1100     if (PHYMOD_ACC_F_USXMODE_GET(&phy->access) && an_control.enable && an_complete) {
   1101         PHYMOD_MEMSET(&an_ability_st, 0x0,  sizeof(qmod16_an_ability_t));
   1102         PHYMOD_IF_ERR_RETURN
   1103             (qmod16_autoneg_resolution_ability_get(&pm_phy_copy.access, &an_ability_st, sub_port));
   1104 
   1105         speed_id = an_ability_st.cl37_adv.cl37_sgmii_speed;
   1106     }
   1107 
   1108     PHYMOD_IF_ERR_RETURN
   1109         (qtce16_phy_firmware_lane_config_get(phy, &firmware_lane_config));
   1110     
   1111     PHYMOD_IF_ERR_RETURN
   1112         (_qtce16_speed_id_interface_config_get(&pm_phy_copy, speed_id, config, an_control.enable, &firmware_lane_config));
   1113 
   1114     if (firmware_lane_config.MediaType == phymodFirmwareMediaTypeOptics) {
   1115         PHYMOD_INTF_MODES_FIBER_SET(config);
   1116     } else {
   1117         PHYMOD_INTF_MODES_FIBER_CLR(config);
   1118     }
   1119 
   1120     return PHYMOD_E_NONE;
   1121     
   1122 }
   1123 
   1124 int qtce16_phy_autoneg_ability_set(const phymod_phy_access_t* phy, const phymod_autoneg_ability_t* an_ability)
   1125 {        
   1126     qmod16_an_ability_t value;
   1127     int start_lane, num_lane;
   1128     phymod_phy_access_t phy_copy;
   1129     int      lane_id, sub_port ;
   1130 
   1131     /* next program the tx fir taps and driver current based on the input */
   1132     PHYMOD_IF_ERR_RETURN
   1133         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
   1134 
   1135     PHYMOD_IF_ERR_RETURN
   1136         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
   1137 
   1138     start_lane = lane_id ;  
   1139 
   1140     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1141     phy_copy.access.lane_mask = 0x1 << start_lane;
   1142 
   1143     PHYMOD_MEMSET(&value, 0x0, sizeof(value));
   1144 
   1145     /* check if sgmii  or not */
   1146     if (PHYMOD_AN_CAP_SGMII_GET(an_ability)) {
   1147         switch (an_ability->sgmii_speed) {
   1148         case phymod_CL37_SGMII_10M:
   1149             value.cl37_adv.cl37_sgmii_speed = QMOD16_CL37_SGMII_10M;
   1150             break;
   1151         case phymod_CL37_SGMII_100M:
   1152             value.cl37_adv.cl37_sgmii_speed = QMOD16_CL37_SGMII_100M;
   1153             break;
   1154         case phymod_CL37_SGMII_1000M:
   1155             value.cl37_adv.cl37_sgmii_speed = QMOD16_CL37_SGMII_1000M;
   1156             break;
   1157         case phymod_CL37_SGMII_2500M:
   1158             value.cl37_adv.cl37_sgmii_speed = QMOD16_CL37_SGMII_2500M;
   1159             break;
   1160         default:
   1161             value.cl37_adv.cl37_sgmii_speed = QMOD16_CL37_SGMII_1000M;
   1162             break;
   1163         }
   1164         if( PHYMOD_AN_CAP_HALF_DUPLEX_GET(an_ability)) {
   1165             value.cl37_adv.an_duplex = QMOD16_AN_HALF_DUPLEX_SET ;
   1166         }
   1167     }
   1168     /* next check pause */
   1169     if (PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability) && !PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability)) {
   1170         value.cl37_adv.an_pause = QMOD16_SYMM_PAUSE;
   1171     }
   1172     if (PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability) && !PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability)) {
   1173         value.cl37_adv.an_pause = QMOD16_ASYM_PAUSE;
   1174     }
   1175     if (PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability) && PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability)) {
   1176         value.cl37_adv.an_pause = QMOD16_ASYM_SYMM_PAUSE;
   1177     }
   1178 
   1179     /* check cl37 and cl37 bam ability */
   1180     if (PHYMOD_AN_CAP_CL37BAM_GET(an_ability)) {
   1181         value.cl37_adv.an_bam_speed |= 1 << QMOD16_CL37_BAM_2p5GBASE_X;
   1182         PHYMOD_IF_ERR_RETURN
   1183             (qmod16_an_cl37_bam_abilities(&phy_copy.access, &value, sub_port));
   1184     } else { 
   1185         PHYMOD_IF_ERR_RETURN
   1186             (qmod16_autoneg_cl37_base_abilities(&phy_copy.access, &value, sub_port));
   1187     }
   1188         
   1189     return PHYMOD_E_NONE;
   1190     
   1191 }
   1192 
   1193 int qtce16_phy_autoneg_ability_get(const phymod_phy_access_t* phy, phymod_autoneg_ability_t* an_ability_get_type)
   1194 {        
   1195     qmod16_an_ability_t value;
   1196     phymod_phy_access_t phy_copy;
   1197     int      lane_id, sub_port ;
   1198 
   1199 
   1200     PHYMOD_IF_ERR_RETURN
   1201         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
   1202 
   1203     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1204     phy_copy.access.lane_mask = 0x1 << lane_id;
   1205     PHYMOD_MEMSET(&value, 0x0, sizeof(value));
   1206      
   1207     PHYMOD_IF_ERR_RETURN
   1208         (qmod16_autoneg_local_ability_get(&phy_copy.access, &value, sub_port));
   1209 
   1210     if(value.cl37_adv.an_type != QMOD16_AN_MODE_NONE) {
   1211         if (value.cl37_adv.an_pause == QMOD16_ASYM_PAUSE) {
   1212             PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type);
   1213         } else if (value.cl37_adv.an_pause == QMOD16_SYMM_PAUSE) {
   1214             PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type);
   1215         } else if (value.cl37_adv.an_pause == QMOD16_ASYM_SYMM_PAUSE) {
   1216             PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type);
   1217             PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type);
   1218         }
   1219         if(value.cl37_adv.an_type & QMOD16_AN_MODE_CL37) {
   1220             PHYMOD_AN_CAP_CL37_SET(an_ability_get_type) ;
   1221             PHYMOD_AN_CAP_HALF_DUPLEX_CLR(an_ability_get_type) ;
   1222         }
   1223         if(value.cl37_adv.an_type & QMOD16_AN_MODE_SGMII) {
   1224             PHYMOD_AN_CAP_SGMII_SET(an_ability_get_type) ;
   1225             /* get the cl37 sgmii speed */
   1226             switch (value.cl37_adv.cl37_sgmii_speed) {
   1227             case QMOD16_CL37_SGMII_10M:
   1228                 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_10M;
   1229                 break;
   1230             case QMOD16_CL37_SGMII_100M:
   1231                 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_100M;
   1232                 break;
   1233             case QMOD16_CL37_SGMII_1000M:
   1234                 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_1000M;
   1235                 break;
   1236             case QMOD16_CL37_SGMII_2500M:
   1237                 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_2500M;
   1238                 break;
   1239             default:
   1240                 break;
   1241             }
   1242             if(value.cl37_adv.an_duplex & QMOD16_AN_HALF_DUPLEX_SET ) { 
   1243                 PHYMOD_AN_CAP_HALF_DUPLEX_SET(an_ability_get_type) ;
   1244             } else {
   1245                 PHYMOD_AN_CAP_HALF_DUPLEX_CLR(an_ability_get_type) ;
   1246             }
   1247         }
   1248         if(value.cl37_adv.an_type & QMOD16_AN_MODE_CL37BAM) {
   1249             /* check cl37 bam ability */
   1250             if (value.cl37_adv.an_bam_speed & 1 << QMOD16_CL37_BAM_2p5GBASE_X) 
   1251                 PHYMOD_BAM_CL37_CAP_2P5G_SET(an_ability_get_type->cl37bam_cap);
   1252         }
   1253     }
   1254     return PHYMOD_E_NONE;
   1255     
   1256 }
   1257 
   1258 
   1259 int qtce16_phy_autoneg_remote_ability_get(const phymod_phy_access_t* phy, phymod_autoneg_ability_t* an_ability_get_type)
   1260 {        
   1261     
   1262     qmod16_an_ability_t value;
   1263     phymod_phy_access_t phy_copy;
   1264     int      lane_id, sub_port ;
   1265 
   1266     
   1267     PHYMOD_IF_ERR_RETURN
   1268         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
   1269 
   1270     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1271     phy_copy.access.lane_mask = 0x1 << lane_id;
   1272     PHYMOD_MEMSET(&value, 0x0, sizeof(value));
   1273      
   1274     PHYMOD_IF_ERR_RETURN
   1275         (qmod16_autoneg_remote_ability_get(&phy_copy.access, &value, sub_port));
   1276 
   1277     if (value.cl37_adv.an_pause == QMOD16_ASYM_PAUSE) {
   1278         PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type);
   1279     } else if (value.cl37_adv.an_pause == QMOD16_SYMM_PAUSE) {
   1280         PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type);
   1281     } else if (value.cl37_adv.an_pause == QMOD16_ASYM_SYMM_PAUSE) {
   1282         PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type);
   1283         PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type);
   1284     }
   1285     if(value.cl37_adv.an_type != QMOD16_AN_MODE_NONE) {     
   1286        if(value.cl37_adv.an_type & QMOD16_AN_MODE_CL37) {
   1287             PHYMOD_AN_CAP_CL37_SET(an_ability_get_type) ;
   1288             PHYMOD_AN_CAP_HALF_DUPLEX_CLR(an_ability_get_type) ;
   1289        }
   1290         if(value.cl37_adv.an_type & QMOD16_AN_MODE_SGMII) {
   1291             PHYMOD_AN_CAP_SGMII_SET(an_ability_get_type) ;
   1292             /* get the cl37 sgmii speed */
   1293             switch (value.cl37_adv.cl37_sgmii_speed) {
   1294             case QMOD16_CL37_SGMII_10M:
   1295                 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_10M;
   1296                 break;
   1297             case QMOD16_CL37_SGMII_100M:
   1298                 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_100M;
   1299                 break;
   1300             case QMOD16_CL37_SGMII_1000M:
   1301                 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_1000M;
   1302                 break;
   1303             case QMOD16_CL37_SGMII_2500M:
   1304                 an_ability_get_type->sgmii_speed = phymod_CL37_SGMII_2500M;
   1305                 break;
   1306             default:
   1307                 break;
   1308             }
   1309         }
   1310         /* check cl37 bam ability */
   1311         if (value.cl37_adv.an_bam_speed & 1 << QMOD16_CL37_BAM_2p5GBASE_X) 
   1312             PHYMOD_BAM_CL37_CAP_2P5G_SET(an_ability_get_type->cl37bam_cap);
   1313     }
   1314         
   1315     return PHYMOD_E_NONE;
   1316     
   1317 }
   1318 
   1319 STATIC
   1320 int _qtce16_qsgmii_autoneg_set(const phymod_phy_access_t* phy, const phymod_autoneg_control_t* an)
   1321 {
   1322     int num_lane_adv_encoded;
   1323     int start_lane, num_lane, lane_id, sub_port;
   1324     phymod_phy_access_t phy_copy;
   1325     qmod16_an_control_t an_control;
   1326     
   1327     
   1328     /* next program the tx fir taps and driver current based on the input */
   1329     PHYMOD_IF_ERR_RETURN
   1330         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
   1331 
   1332     PHYMOD_IF_ERR_RETURN
   1333         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
   1334 
   1335     start_lane = lane_id ;
   1336 
   1337     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1338     phy_copy.access.lane_mask = 0x1 << start_lane;
   1339 
   1340     num_lane_adv_encoded = 0;  /* one lane */
   1341     an_control.pd_kx4_en = 0;  /* for now  disable */
   1342     an_control.pd_kx_en  = 0;   /* for now disable */
   1343     an_control.num_lane_adv = num_lane_adv_encoded;
   1344     an_control.enable       = an->enable;
   1345     an_control.an_property_type = 0x0;   /* for now disable */
   1346     an_control.an_type          = QMOD16_AN_MODE_SGMII;
   1347 
   1348     phy_copy.access.lane_mask = 0x1 << start_lane;
   1349 
   1350     PHYMOD_IF_ERR_RETURN
   1351         (qmod16_autoneg_control(&phy_copy.access, &an_control, sub_port));
   1352     
   1353     return PHYMOD_E_NONE;
   1354 
   1355 }
   1356 
   1357 int qtce16_phy_autoneg_set(const phymod_phy_access_t* phy, const phymod_autoneg_control_t* an)
   1358 {        
   1359     phymod_firmware_lane_config_t firmware_lane_config;
   1360     int start_lane, num_lane, i, lane_id, sub_port;
   1361     phymod_phy_access_t phy_copy;
   1362     qmod16_an_control_t an_control;
   1363 
   1364     /* QTCE16 doesn't support 10G KX4 and 1G KX parallel detection */
   1365     if (PHYMOD_AN_F_SET_CL73_PDET_KX4_ENABLE_GET(an) ||
   1366         PHYMOD_AN_F_SET_CL73_PDET_KX_ENABLE_GET(an)) {
   1367         return PHYMOD_E_UNAVAIL;
   1368     }
   1369 
   1370     if (PHYMOD_ACC_F_QMODE_GET(&phy->access) || PHYMOD_ACC_F_USXMODE_GET(&phy->access)) {
   1371         return _qtce16_qsgmii_autoneg_set(phy, an);
   1372     }
   1373 
   1374     /* next program the tx fir taps and driver current based on the input */
   1375     PHYMOD_IF_ERR_RETURN
   1376         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
   1377 
   1378     PHYMOD_IF_ERR_RETURN
   1379         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
   1380 
   1381     start_lane = lane_id ;  
   1382     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1383     phy_copy.access.lane_mask = 0x1 << start_lane;
   1384 
   1385     an_control.pd_kx4_en = 0;  /* for now  disable */
   1386     an_control.pd_kx_en = 0;   /* for now disable */
   1387     an_control.num_lane_adv = 0;
   1388     an_control.enable       = an->enable;
   1389     an_control.an_property_type = 0x0;   /* for now disable */  
   1390     switch (an->an_mode) {
   1391     case phymod_AN_MODE_CL37:
   1392         an_control.an_type = QMOD16_AN_MODE_CL37;
   1393         break;
   1394     case phymod_AN_MODE_CL37BAM:
   1395         { 
   1396             an_control.an_type = QMOD16_AN_MODE_CL37BAM;
   1397             break;
   1398         }
   1399     case phymod_AN_MODE_SGMII:
   1400         an_control.an_type = QMOD16_AN_MODE_SGMII;
   1401         break;
   1402     default:
   1403         an_control.an_type = QMOD16_AN_MODE_CL37;
   1404         break;
   1405     }
   1406 
   1407     /* put pcs into reset */
   1408     PHYMOD_IF_ERR_RETURN
   1409             (qmod16_reset(&phy_copy.access)); 
   1410     
   1411     for (i = 0; i < num_lane; i++) {
   1412         phy_copy.access.lane_mask = 0x1 << (i + start_lane);
   1413         PHYMOD_IF_ERR_RETURN
   1414             (merlin16_lane_soft_reset_release(&phy_copy.access, 0));
   1415     }
   1416      
   1417     /* make sure the firmware config is set to an eenabled */
   1418     PHYMOD_IF_ERR_RETURN
   1419         (qtce16_phy_firmware_lane_config_get(phy, &firmware_lane_config));
   1420     if (an->enable) {
   1421         firmware_lane_config.AnEnabled = 1;
   1422         firmware_lane_config.LaneConfigFromPCS = 1;
   1423     } else {
   1424         firmware_lane_config.AnEnabled = 0;
   1425         firmware_lane_config.LaneConfigFromPCS = 0;
   1426     }
   1427 
   1428     for (i = 0; i < num_lane; i++) {
   1429         phy_copy.access.lane_mask = 0x1 << (i + start_lane);
   1430         PHYMOD_IF_ERR_RETURN
   1431             (_qtce16_phy_firmware_lane_config_set(&phy_copy, firmware_lane_config));
   1432     }
   1433 
   1434     for (i = 0; i < num_lane; i++) {
   1435         phy_copy.access.lane_mask = 0x1 << (i + start_lane);
   1436         PHYMOD_IF_ERR_RETURN
   1437             (merlin16_lane_soft_reset_release(&phy_copy.access, 1));
   1438     } 
   1439 
   1440     if (!an->enable) {  /* would SGMII AN exception */
   1441         PHYMOD_IF_ERR_RETURN
   1442             (qmod16_trigger_speed_change(&phy_copy.access));  
   1443     }
   1444 
   1445     phy_copy.access.lane_mask = 0x1 << start_lane;
   1446     PHYMOD_IF_ERR_RETURN
   1447         (qmod16_autoneg_control(&phy_copy.access, &an_control, sub_port));
   1448     
   1449         
   1450     return PHYMOD_E_NONE;
   1451     
   1452 }
   1453 
   1454 int qtce16_phy_autoneg_get(const phymod_phy_access_t* phy, phymod_autoneg_control_t* an, uint32_t* an_done)
   1455 {        
   1456 
   1457     qmod16_an_control_t an_control;
   1458     phymod_phy_access_t phy_copy;
   1459     int start_lane, num_lane, lane_id, sub_port; 
   1460     int an_complete = 0;
   1461     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1462 
   1463     PHYMOD_IF_ERR_RETURN
   1464         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
   1465 
   1466     PHYMOD_IF_ERR_RETURN
   1467         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
   1468 
   1469     start_lane = lane_id ;  
   1470     phy_copy.access.lane_mask = 0x1 << start_lane;
   1471 
   1472     PHYMOD_MEMSET(&an_control, 0x0,  sizeof(qmod16_an_control_t));
   1473     PHYMOD_IF_ERR_RETURN
   1474         (qmod16_autoneg_control_get(&phy_copy.access,  sub_port, &an_control, &an_complete));
   1475     
   1476     if (an_control.enable) {
   1477         an->enable = 1;
   1478         if (an_control.an_type == QMOD16_AN_MODE_CL37) {
   1479             an->an_mode = phymod_AN_MODE_CL37;
   1480         } else if (an_control.an_type == QMOD16_AN_MODE_CL37BAM) {
   1481             an->an_mode = phymod_AN_MODE_CL37BAM;
   1482         } else {
   1483             an->an_mode = phymod_AN_MODE_SGMII;
   1484         }
   1485         *an_done = an_complete; 
   1486     } else {
   1487         an->enable = 0;
   1488     }
   1489 
   1490     /* QTCE16 doesn't support 10G KX4 and 1G KX parallel detection */
   1491     PHYMOD_AN_F_SET_CL73_PDET_KX_ENABLE_CLR(an);
   1492     PHYMOD_AN_F_SET_CL73_PDET_KX4_ENABLE_CLR(an);
   1493 
   1494         
   1495     return PHYMOD_E_NONE;
   1496     
   1497 }
   1498 
   1499 
   1500 int qtce16_phy_autoneg_status_get(const phymod_phy_access_t* phy, phymod_autoneg_status_t* status)
   1501 {
   1502 
   1503     return PHYMOD_E_NONE;
   1504     
   1505 }
   1506 
   1507 
   1508 int qtce16_core_init(const phymod_core_access_t* core, const phymod_core_init_config_t* init_config, const phymod_core_status_t* core_status)
   1509 {        
   1510     phymod_phy_access_t phy_access, phy_access_copy;
   1511     phymod_core_access_t  core_copy;
   1512     phymod_firmware_core_config_t  firmware_core_config_tmp;
   1513     uint32_t  uc_active = 0;
   1514     int i, num_lane, start_lane;
   1515 
   1516 
   1517     PHYMOD_MEMCPY(&core_copy, core, sizeof(core_copy));
   1518     core_copy.access.lane_mask = 0x1;
   1519 
   1520     PHYMOD_IF_ERR_RETURN(phymod_phy_access_t_init(&phy_access));
   1521     QTCE16_CORE_TO_PHY_ACCESS(&phy_access, core);
   1522     PHYMOD_MEMCPY(&phy_access_copy, &phy_access, sizeof(phy_access_copy));
   1523     phy_access_copy.access.lane_mask = 0x1;
   1524 
   1525     PHYMOD_IF_ERR_RETURN
   1526         (qmod16_pmd_reset_seq(&core_copy.access, core_status->pmd_active));
   1527 
   1528     PHYMOD_IF_ERR_RETURN
   1529         (phymod_util_lane_config_get(&phy_access.access, &start_lane, &num_lane));
   1530 
   1531     /*
   1532      * Before programming the PMD lane address map register, the PMD lanes
   1533      * have to be reset. Without do this, writing the PMD lane address map
   1534      * regsiter will not take effect, meaning the reading value != writing
   1535      * value.
   1536      */
   1537     for (i = 0; i < QTCE16_NOF_LANES_IN_CORE; i++) {
   1538         phy_access.access.lane_mask = 1 << (start_lane + i);
   1539         PHYMOD_IF_ERR_RETURN
   1540             (qmod16_pmd_x4_reset(&phy_access.access));
   1541     }
   1542 
   1543     PHYMOD_IF_ERR_RETURN(merlin16_uc_active_get(&core_copy.access, &uc_active));
   1544     if (uc_active) {
   1545         return(PHYMOD_E_NONE);
   1546     }
   1547 
   1548     /* Propgram shim fifo threshold for USXGMII mode */
   1549     if (PHYMOD_ACC_F_USXMODE_GET(&core->access)) {
   1550         PHYMOD_IF_ERR_RETURN(qmod16_usgmii_shim_fifo_threshold_set(&core_copy.access));
   1551     }
   1552 
   1553     /* need to set the heart beat default is for 156.25M */
   1554     if (init_config->interface.ref_clock == phymodRefClk125Mhz) {
   1555         PHYMOD_IF_ERR_RETURN
   1556             (qmod16_refclk_set(&core_copy.access, QMOD16REFCLK125MHZ)) ;
   1557     } else {
   1558         PHYMOD_IF_ERR_RETURN
   1559             (qmod16_refclk_set(&core_copy.access, QMOD16REFCLK156MHZ)) ;
   1560     }
   1561   
   1562      PHYMOD_IF_ERR_RETURN
   1563         (qtce16_core_lane_map_set(&core_copy, &init_config->lane_map));
   1564 
   1565     PHYMOD_IF_ERR_RETURN
   1566         (merlin16_uc_reset(&phy_access_copy.access, 1));
   1567 
   1568     if (_qtce16_core_firmware_load(&core_copy, init_config->firmware_load_method, init_config->firmware_loader)) {
   1569         PHYMOD_DEBUG_ERROR(("devad 0x%x lane 0x%x: UC firmware-load failed\n", core->access.addr, core->access.lane_mask));  
   1570         PHYMOD_IF_ERR_RETURN (PHYMOD_E_INIT);
   1571     }
   1572 
   1573     /* merlin16 programmer quide */
   1574     PHYMOD_IF_ERR_RETURN
   1575         (merlin16_pmd_ln_h_rstb_pkill_override( &phy_access_copy.access, 0x1));
   1576 
   1577     PHYMOD_IF_ERR_RETURN
   1578         (merlin16_uc_reset(&phy_access_copy.access, 0));
   1579     PHYMOD_IF_ERR_RETURN
   1580         (merlin16_wait_uc_active(&phy_access_copy.access));
   1581 
   1582     /* Initialize software information table for the micro */
   1583     PHYMOD_IF_ERR_RETURN
   1584         (merlin16_init_merlin16_info(&core_copy.access));
   1585 
   1586     if (init_config->firmware_load_method != phymodFirmwareLoadMethodNone) {
   1587         if (PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY_GET(init_config)) {
   1588             PHYMOD_IF_ERR_RETURN
   1589                 (merlin16_start_ucode_crc_calc(&core_copy.access, merlin16_ucode_len));
   1590         }
   1591     }
   1592 
   1593     if (init_config->firmware_load_method != phymodFirmwareLoadMethodNone) {
   1594         if (PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY_GET(init_config)) {
   1595             PHYMOD_IF_ERR_RETURN
   1596                 (merlin16_check_ucode_crc(&core_copy.access, merlin16_ucode_crc, 250));
   1597         }
   1598     }
   1599 
   1600     PHYMOD_IF_ERR_RETURN(
   1601         merlin16_pmd_ln_h_rstb_pkill_override( &phy_access_copy.access, 0x0));
   1602 
   1603     PHYMOD_IF_ERR_RETURN
   1604         (merlin16_core_soft_reset_release(&core_copy.access, 0));
   1605 
   1606     /* plldiv CONFIG */
   1607     if (PHYMOD_ACC_F_USXMODE_GET(&core->access)) {
   1608         PHYMOD_IF_ERR_RETURN
   1609             (merlin16_configure_pll_refclk_div(&core_copy.access, MERLIN16_PLL_REFCLK_156P25MHZ, MERLIN16_PLL_DIV_66));
   1610     } else {
   1611         PHYMOD_IF_ERR_RETURN
   1612             (merlin16_configure_pll_refclk_div(&core_copy.access, MERLIN16_PLL_REFCLK_156P25MHZ, MERLIN16_PLL_DIV_64));
   1613     }
   1614    
   1615     PHYMOD_IF_ERR_RETURN
   1616         (qmod16_autoneg_timer_init(&core_copy.access));
   1617     PHYMOD_IF_ERR_RETURN
   1618         (qmod16_master_port_num_set(&core_copy.access, 0));
   1619 
   1620     /* don't overide the fw that set in config set if not specified */
   1621     PHYMOD_IF_ERR_RETURN
   1622         (qtce16_phy_firmware_core_config_get(&phy_access_copy, &firmware_core_config_tmp));
   1623     firmware_core_config_tmp.CoreConfigFromPCS = 0;
   1624     PHYMOD_IF_ERR_RETURN
   1625         (qtce16_phy_firmware_core_config_set(&phy_access_copy, firmware_core_config_tmp)); 
   1626 
   1627     /* release core soft reset */
   1628     PHYMOD_IF_ERR_RETURN
   1629         (merlin16_core_soft_reset_release(&core_copy.access, 1));
   1630         
   1631     return PHYMOD_E_NONE;
   1632     
   1633 }
   1634 
   1635 
   1636 int qtce16_phy_pll_multiplier_get(const phymod_phy_access_t* phy, uint32_t* core_vco_pll_multiplier)
   1637 {        
   1638     
   1639     /* Place your code here */
   1640 
   1641         
   1642     return PHYMOD_E_NONE;
   1643     
   1644 }
   1645 
   1646 
   1647 int qtce16_phy_init(const phymod_phy_access_t* phy, const phymod_phy_init_config_t* init_config)
   1648 {
   1649     const phymod_access_t *pm_acc = &phy->access;
   1650     phymod_phy_access_t pm_phy_copy;
   1651     int start_lane, num_lane, i, lane_id, sub_port;
   1652     uint32_t sc_enable = 0;
   1653     phymod_polarity_t tmp_pol;
   1654     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
   1655     PHYMOD_MEMSET(&tmp_pol, 0x0, sizeof(tmp_pol));
   1656 
   1657     /* next program the tx fir taps and driver current based on the input */
   1658     PHYMOD_IF_ERR_RETURN
   1659         (phymod_util_lane_config_get(pm_acc, &start_lane, &num_lane));
   1660     PHYMOD_IF_ERR_RETURN
   1661         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
   1662 
   1663     start_lane = lane_id ;  
   1664     pm_phy_copy.access.lane_mask = 1 << start_lane;
   1665 
   1666     if (PHYMOD_ACC_F_QMODE_GET(&phy->access) || PHYMOD_ACC_F_USXMODE_GET(&phy->access)) {
   1667         PHYMOD_IF_ERR_RETURN(qmod16_port_state_set(&pm_phy_copy.access, QMOD16_PORT_STATE_CONFIGED, sub_port, 1));
   1668         PHYMOD_IF_ERR_RETURN(qmod16_speedchange_get(&pm_phy_copy.access, &sc_enable)) ;
   1669         /* this lane has been initialized */
   1670         if (sc_enable) {
   1671             return PHYMOD_E_NONE;
   1672         }
   1673     }
   1674 
   1675     /* per lane based reset release */
   1676     PHYMOD_IF_ERR_RETURN
   1677         (qmod16_pmd_x4_reset(&pm_phy_copy.access));
   1678 
   1679     /* poll for per lane uc_dsc_ready */
   1680     for (i = 0; i < num_lane; i++) {
   1681         pm_phy_copy.access.lane_mask = 1 << (start_lane + i);
   1682         PHYMOD_IF_ERR_RETURN
   1683             (merlin16_lane_soft_reset_release(&pm_phy_copy.access, 1));
   1684     }
   1685 
   1686     /* program the rx/tx polarity */
   1687     tmp_pol.tx_polarity = (init_config->polarity.tx_polarity) & 0x1;
   1688     tmp_pol.rx_polarity = (init_config->polarity.rx_polarity) & 0x1;
   1689     PHYMOD_IF_ERR_RETURN(qtce16_phy_polarity_set(phy, &tmp_pol));
   1690 
   1691     /* configure TX parameters */
   1692     PHYMOD_IF_ERR_RETURN
   1693         (qtce16_phy_tx_set(phy, &init_config->tx[0]));
   1694 
   1695     pm_phy_copy.access.lane_mask = 1 << start_lane;
   1696     PHYMOD_IF_ERR_RETURN
   1697         (qmod16_rx_lane_control_set(&pm_phy_copy.access, TRUE));
   1698     PHYMOD_IF_ERR_RETURN
   1699         (qmod16_tx_lane_control_set(&pm_phy_copy.access, QMOD16_TX_LANE_RESET_TRAFFIC_ENABLE));         /* TX_LANE_CONTROL */
   1700         
   1701     return PHYMOD_E_NONE;
   1702     
   1703 }
   1704 
   1705 
   1706 int qtce16_phy_loopback_set(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t enable)
   1707 {        
   1708     
   1709     int start_lane, num_lane, lane_id, sub_port;
   1710     int i = 0;
   1711     phymod_phy_access_t phy_copy;
   1712     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1713 
   1714     /* next figure out the lane num and start_lane based on the input */
   1715     PHYMOD_IF_ERR_RETURN
   1716         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
   1717 
   1718     PHYMOD_IF_ERR_RETURN
   1719         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
   1720     start_lane = lane_id ;
   1721 
   1722     phy_copy.access.lane_mask = 0x1 << (i + start_lane);
   1723     
   1724       
   1725     switch (loopback) {
   1726     case phymodLoopbackGlobal :
   1727         PHYMOD_IF_ERR_RETURN(qmod16_tx_loopback_control(&phy_copy.access, enable, start_lane, num_lane));
   1728         break;
   1729     case phymodLoopbackGlobalPMD :
   1730         PHYMOD_IF_ERR_RETURN(merlin16_pmd_loopback_set(&phy_copy.access, enable));
   1731         break;
   1732     case phymodLoopbackRemotePMD :
   1733         PHYMOD_IF_ERR_RETURN(merlin16_rmt_lpbk(&phy_copy.access, (uint8_t)enable));
   1734         break;
   1735     case phymodLoopbackRemotePCS :
   1736         PHYMOD_IF_ERR_RETURN(qmod16_rx_loopback_control(&phy_copy.access, enable, enable, enable));
   1737         break;
   1738     default :
   1739         break;
   1740     }
   1741         
   1742     return PHYMOD_E_NONE;
   1743     
   1744 }
   1745 
   1746 int qtce16_phy_loopback_get(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t* enable)
   1747 {        
   1748     
   1749     uint32_t enable_core;
   1750     int start_lane, num_lane, lane_id, sub_port;
   1751     phymod_phy_access_t phy_copy;
   1752 
   1753     *enable = 0;
   1754 
   1755     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1756     /* next figure out the lane num and start_lane based on the input */
   1757     PHYMOD_IF_ERR_RETURN
   1758         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
   1759 
   1760     PHYMOD_IF_ERR_RETURN
   1761         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
   1762     start_lane = lane_id ;
   1763 
   1764     phy_copy.access.lane_mask = 0x1 << start_lane;
   1765     
   1766 
   1767     switch (loopback) {
   1768     case phymodLoopbackGlobal :
   1769         PHYMOD_IF_ERR_RETURN(qmod16_tx_loopback_get(&phy_copy.access, &enable_core));
   1770         *enable = (enable_core >> start_lane) & 0x1; 
   1771         break;
   1772     case phymodLoopbackGlobalPMD :
   1773         PHYMOD_IF_ERR_RETURN(merlin16_pmd_loopback_get(&phy_copy.access, enable));
   1774         break;
   1775     case phymodLoopbackRemotePMD :
   1776         PHYMOD_IF_ERR_RETURN(merlin16_rmt_lpbk_get(&phy_copy.access, enable));
   1777         break;
   1778     case phymodLoopbackRemotePCS :
   1779         PHYMOD_IF_ERR_RETURN(qmod16_rx_loopback_get(&phy_copy.access, enable));
   1780         break;
   1781     default :
   1782         break;
   1783     }   
   1784     return PHYMOD_E_NONE;
   1785     
   1786 }
   1787 
   1788 
   1789 int qtce16_phy_rx_pmd_locked_get(const phymod_phy_access_t* phy, uint32_t* rx_pmd_locked)
   1790 {        
   1791     
   1792     int lane_id, sub_port;
   1793     phymod_phy_access_t phy_copy;
   1794 
   1795     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1796     PHYMOD_IF_ERR_RETURN
   1797         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
   1798     phy_copy.access.lane_mask = 1 << lane_id;
   1799 
   1800     PHYMOD_IF_ERR_RETURN(qmod16_pmd_lock_get(&phy_copy.access, rx_pmd_locked));
   1801         
   1802     return PHYMOD_E_NONE;
   1803     
   1804 }
   1805 
   1806 
   1807 int qtce16_phy_link_status_get(const phymod_phy_access_t* phy, uint32_t* link_status)
   1808 {        
   1809     
   1810     int lane_id, sub_port;
   1811     phymod_phy_access_t pm_phy_copy;
   1812 
   1813     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
   1814     PHYMOD_IF_ERR_RETURN
   1815         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
   1816     pm_phy_copy.access.lane_mask = 1 << lane_id;
   1817 
   1818     PHYMOD_IF_ERR_RETURN(qmod16_get_pcs_link_status(&pm_phy_copy.access, sub_port, link_status));
   1819 
   1820         
   1821     return PHYMOD_E_NONE;
   1822     
   1823 }
   1824 
   1825 int qtce16_phy_reg_read(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t* val)
   1826 {
   1827     int lane_id, sub_port;
   1828     phymod_phy_access_t phy_copy;
   1829 
   1830     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1831     PHYMOD_IF_ERR_RETURN
   1832         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
   1833     phy_copy.access.lane_mask = 1 << lane_id;
   1834 
   1835     PHYMOD_IF_ERR_RETURN(phymod_tsc_iblk_read(&phy_copy.access, reg_addr, val));
   1836     return PHYMOD_E_NONE;
   1837 }
   1838 
   1839 
   1840 int qtce16_phy_reg_write(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t val)
   1841 {
   1842     int lane_id, sub_port;
   1843     phymod_phy_access_t phy_copy;
   1844 
   1845     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1846     PHYMOD_IF_ERR_RETURN
   1847         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
   1848     phy_copy.access.lane_mask = 1 << lane_id;
   1849 
   1850     PHYMOD_IF_ERR_RETURN(phymod_tsc_iblk_write(&phy_copy.access, reg_addr, val));
   1851     return PHYMOD_E_NONE;
   1852 }
   1853 
   1854 int qtce16_phy_eee_set(const phymod_phy_access_t* phy, uint32_t enable)
   1855 {
   1856     int lane_id, sub_port;
   1857     phymod_phy_access_t phy_copy;
   1858 
   1859     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1860     PHYMOD_IF_ERR_RETURN
   1861         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
   1862     phy_copy.access.lane_mask = 1 << lane_id;
   1863 
   1864     PHYMOD_IF_ERR_RETURN(qmod16_eee_control_set(&phy_copy.access, enable));
   1865     return PHYMOD_E_NONE;
   1866 }
   1867 
   1868 int qtce16_phy_eee_get(const phymod_phy_access_t* phy, uint32_t* enable)
   1869 {
   1870     uint32_t enable_local;
   1871     int lane_id, sub_port;
   1872     phymod_phy_access_t phy_copy;
   1873 
   1874     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1875     PHYMOD_IF_ERR_RETURN
   1876         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
   1877     phy_copy.access.lane_mask = 1 << lane_id;
   1878 
   1879     PHYMOD_IF_ERR_RETURN(qmod16_eee_control_get(&phy_copy.access, &enable_local));
   1880     *enable = enable_local;
   1881     return PHYMOD_E_NONE;
   1882 }
   1883 
   1884 int qtce16_phy_rx_ppm_get(const phymod_phy_access_t* phy, int16_t* rx_ppm)
   1885 {
   1886     int lane_id, sub_port;
   1887     phymod_phy_access_t phy_copy;
   1888 
   1889     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1890     PHYMOD_IF_ERR_RETURN
   1891         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
   1892     phy_copy.access.lane_mask = 1 << lane_id;
   1893 
   1894     PHYMOD_IF_ERR_RETURN
   1895         (merlin16_tsc_rx_ppm(&phy_copy.access, rx_ppm));
   1896 
   1897     return PHYMOD_E_NONE;
   1898 }
   1899 
   1900 int qtce16_phy_synce_clk_ctrl_set(const phymod_phy_access_t* phy,
   1901                                   phymod_synce_clk_ctrl_t cfg)
   1902 {
   1903     int lane_id, sub_port;
   1904     phymod_phy_access_t phy_copy;
   1905 
   1906     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1907     PHYMOD_IF_ERR_RETURN
   1908         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
   1909     phy_copy.access.lane_mask = 1 << lane_id;
   1910 
   1911     PHYMOD_IF_ERR_RETURN
   1912         (qmod16_synce_mode_set(&phy_copy.access, cfg.stg0_mode, cfg.stg1_mode));
   1913 
   1914     PHYMOD_IF_ERR_RETURN
   1915         (qmod16_synce_clk_ctrl_set(&phy_copy.access, cfg.sdm_val));
   1916 
   1917     return PHYMOD_E_NONE;
   1918 }
   1919 
   1920 int qtce16_phy_synce_clk_ctrl_get(const phymod_phy_access_t* phy,
   1921                                   phymod_synce_clk_ctrl_t *cfg)
   1922 {
   1923     int lane_id, sub_port;
   1924     phymod_phy_access_t phy_copy;
   1925 
   1926     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1927     PHYMOD_IF_ERR_RETURN
   1928         (qmod16_lane_info(&phy->access, &lane_id, &sub_port));
   1929     phy_copy.access.lane_mask = 1 << lane_id;
   1930 
   1931     PHYMOD_IF_ERR_RETURN
   1932         (qmod16_synce_mode_get(&phy_copy.access, &(cfg->stg0_mode), &(cfg->stg1_mode)));
   1933 
   1934     PHYMOD_IF_ERR_RETURN
   1935         (qmod16_synce_clk_ctrl_get(&phy_copy.access, &(cfg->sdm_val)));
   1936 
   1937     return PHYMOD_E_NONE;
   1938 }
   1939 
   1940 #endif /* PHYMOD_QTCE16_SUPPORT */