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

qsgmiie.c (42610B)


      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_util.h>
     13 #include <phymod/chip/bcmi_qsgmiie_serdes_defs.h>
     14 #include <phymod/chip/qsgmiie.h>
     15 #include "../tier1/tqmod_cfg_seq.h"
     16 #include "../../tsce/tier1/temod_enum_defines.h"
     17 #include "../../tsce/tier1/temod.h"
     18 #include "../../tsce/tier1/tePCSRegEnums.h"
     19 #include "../../eagle/tier1/eagle_cfg_seq.h"
     20 #include "../../eagle/tier1/eagle_tsc_interface.h"
     21 #include "../../eagle/tier1/eagle_tsc_dependencies.h"
     22 #include "../../../include/phymod/chip/eagle.h"
     23 
     24 
     25 #define QSGMIIE_ID0             0x0143
     26 #define QSGMIIE_ID1             0xbff0
     27 #define QSGMIIE_REV_MASK        0x0
     28 #define TSCE4_MODEL             0x12
     29 
     30 #define PHY_REG_ADDR_DEVAD(_phy_reg)                        (((_phy_reg) >> 27) & 0x1f)
     31 #define QSGMII_REG_ADDR_REG(_phy_reg)                       ((((_phy_reg) & 0x8000) >> 11) | ((_phy_reg) & 0xf))
     32 #define IS_QSGMII_REGISTER(_phy_reg)                        (((_phy_reg) & 0xf800f000) == 0x8000)
     33 
     34 #define QSGMII_MODEL            0x07
     35 #define EAGLE_MODEL             0x1a
     36 
     37 #define TSCE_NOF_LANES_IN_CORE (4)
     38 #define TSCE_PHY_ALL_LANES (0xf)
     39 #define TSCE_CORE_TO_PHY_ACCESS(_phy_access, _core_access) \
     40     do{\
     41         PHYMOD_MEMCPY(&(_phy_access)->access, &(_core_access)->access, sizeof((_phy_access)->access));\
     42         (_phy_access)->type           = (_core_access)->type; \
     43         (_phy_access)->port_loc       = (_core_access)->port_loc; \
     44         (_phy_access)->device_op_mode = (_core_access)->device_op_mode; \
     45         (_phy_access)->access.lane_mask = TSCE_PHY_ALL_LANES; \
     46     }while(0)
     47 
     48 /* uController's firmware */
     49 extern unsigned char tsce_ucode[];
     50 extern unsigned short tsce_ucode_ver;
     51 extern unsigned short tsce_ucode_crc;
     52 extern unsigned short tsce_ucode_len;
     53 
     54 int qsgmiie_core_identify(const phymod_core_access_t* core, uint32_t core_id, uint32_t* is_identified)
     55 {
     56     int ioerr = 0;
     57     const phymod_access_t *pm_acc = &core->access;
     58     PHYID2r_t id2;
     59     PHYID3r_t id3;
     60     MAIN0_SERDESIDr_t serdesid;
     61     uint32_t model;
     62 
     63     *is_identified = 0;
     64 
     65     if(core_id == 0){
     66         ioerr += READ_PHYID2r(pm_acc, &id2);
     67         ioerr += READ_PHYID3r(pm_acc, &id3);
     68     }
     69     else{
     70         PHYID2r_SET(id2, ((core_id >> 16) & 0xffff));
     71         PHYID3r_SET(id3, core_id & 0xffff);
     72     }
     73 
     74     if (PHYID2r_GET(id2) == QSGMIIE_ID0 &&
     75         (PHYID3r_GET(id3) &= ~QSGMIIE_REV_MASK) == QSGMIIE_ID1) {
     76         /* PHY IDs match - now check PCS model */
     77         ioerr += READ_MAIN0_SERDESIDr(pm_acc, &serdesid);
     78         model = MAIN0_SERDESIDr_MODEL_NUMBERf_GET(serdesid);
     79         if (model == TSCE4_MODEL)  {
     80                 *is_identified = 1;
     81         }
     82     }
     83         
     84     return ioerr ? PHYMOD_E_IO : PHYMOD_E_NONE;    
     85     return PHYMOD_E_NONE;
     86     
     87 }
     88 
     89 
     90 int qsgmiie_core_info_get(const phymod_core_access_t* core, phymod_core_info_t* info)
     91 {
     92         
     93     
     94     /* Place your code here */
     95 
     96         
     97     return PHYMOD_E_UNAVAIL;
     98     
     99 }
    100 
    101 /* 
    102  * set lane swapping for core 
    103  * The tx swap is composed of PCS swap and after that the PMD swap. 
    104  * The rx swap is composed just by PCS swap
    105  *
    106  * lane_map_tx and lane_map_rx[lane=logic_lane] are logic-lane base.
    107  * pcs_swap and register is logic_lane base.
    108  * but pmd_tx_map and addr_index_swap (and registers) are physical lane base 
    109  */
    110 
    111 
    112 int qsgmiie_core_lane_map_set(const phymod_core_access_t* core, const phymod_lane_map_t* lane_map)
    113 {
    114     uint32_t pcs_swap = 0 , pmd_swap = 0, lane;
    115     uint32_t addr_index_swap = 0, pmd_tx_map =0;
    116 
    117     if(lane_map->num_of_lanes != TSCE_NOF_LANES_IN_CORE){
    118         return PHYMOD_E_CONFIG;
    119     }
    120     for( lane = 0 ; lane < TSCE_NOF_LANES_IN_CORE ; lane++){
    121         if(lane_map->lane_map_rx[lane] >= TSCE_NOF_LANES_IN_CORE){
    122             return PHYMOD_E_CONFIG;
    123         }
    124         /* encode each lane as four bits */
    125         /* pcs_map[lane] = rx_map[lane] */
    126         pcs_swap += lane_map->lane_map_rx[lane]<<(lane*4);
    127     }
    128 
    129     for( lane = 0 ; lane < TSCE_NOF_LANES_IN_CORE ; lane++){
    130         if(lane_map->lane_map_tx[lane] >= TSCE_NOF_LANES_IN_CORE){
    131             return PHYMOD_E_CONFIG;
    132         }
    133         /* encode each lane as four bits. pmd_swap is logic base */
    134         /* considering the pcs lane swap: pmd_map[pcs_map[lane]] = tx_map[lane] */
    135         pmd_swap += lane_map->lane_map_tx[lane]<<(lane_map->lane_map_rx[lane]*4);
    136     }
    137 
    138     for( lane = 0 ; lane < TSCE_NOF_LANES_IN_CORE ; lane++){
    139         addr_index_swap |= (lane << 4*((pcs_swap >> lane*4) & 0xf)) ;
    140         pmd_tx_map      |= (lane << 4*((pmd_swap >> lane*4) & 0xf)) ;
    141     }
    142     PHYMOD_IF_ERR_RETURN(tqmod_pcs_lane_swap(&core->access, pcs_swap));
    143 
    144     PHYMOD_IF_ERR_RETURN
    145         (temod_pmd_addr_lane_swap(&core->access, addr_index_swap));
    146     PHYMOD_IF_ERR_RETURN
    147         (temod_pmd_lane_swap_tx(&core->access, pmd_tx_map));
    148     return PHYMOD_E_NONE;
    149 }
    150 
    151 int qsgmiie_core_lane_map_get(const phymod_core_access_t* core, phymod_lane_map_t* lane_map)
    152 {
    153     uint32_t pmd_swap = 0 , pcs_swap = 0, lane;
    154     PHYMOD_IF_ERR_RETURN(tqmod_pcs_lane_swap_get(&core->access, &pcs_swap));
    155     PHYMOD_IF_ERR_RETURN(temod_pmd_lane_swap_tx_get(&core->access, &pmd_swap));
    156     for( lane = 0 ; lane < TSCE_NOF_LANES_IN_CORE ; lane++){
    157         lane_map->lane_map_rx[lane] = (pcs_swap>>(lane*4)) & 3;
    158         lane_map->lane_map_tx[lane] = (pmd_swap>>(lane_map->lane_map_rx[lane]*4)) & 3;
    159     }
    160     lane_map->num_of_lanes = TSCE_NOF_LANES_IN_CORE;
    161 
    162     return PHYMOD_E_NONE;
    163     
    164 }
    165 
    166 
    167 int qsgmiie_core_reset_set(const phymod_core_access_t* core, phymod_reset_mode_t reset_mode, phymod_reset_direction_t direction)
    168 {
    169         
    170     
    171     /* Place your code here */
    172 
    173         
    174     return PHYMOD_E_UNAVAIL;
    175     
    176 }
    177 
    178 int qsgmiie_core_reset_get(const phymod_core_access_t* core, phymod_reset_mode_t reset_mode, phymod_reset_direction_t* direction)
    179 {
    180         
    181     
    182     /* Place your code here */
    183 
    184         
    185     return PHYMOD_E_UNAVAIL;
    186     
    187 }
    188 
    189 
    190 int qsgmiie_core_firmware_info_get(const phymod_core_access_t* core, phymod_core_firmware_info_t* fw_info)
    191 {
    192         
    193     
    194     fw_info->fw_crc = tsce_ucode_crc;
    195     fw_info->fw_version = tsce_ucode_ver;
    196     return PHYMOD_E_NONE;    
    197 }
    198 
    199 /* load tsce fw. the fw_loader parameter is valid just for external fw load */
    200 STATIC
    201 int _qsgmiie_core_firmware_load(const phymod_core_access_t* core, phymod_firmware_load_method_t load_method, phymod_firmware_loader_f fw_loader)
    202 {
    203     phymod_core_firmware_info_t actual_fw;
    204 
    205     switch(load_method){
    206     case phymodFirmwareLoadMethodInternal:
    207         PHYMOD_IF_ERR_RETURN(eagle_tsc_ucode_mdio_load(&core->access, tsce_ucode, tsce_ucode_len));
    208         break;
    209     case phymodFirmwareLoadMethodExternal:
    210         PHYMOD_NULL_CHECK(fw_loader); 
    211 
    212         eagle_pram_flop_set(&core->access, 0x0);
    213 
    214         PHYMOD_IF_ERR_RETURN(eagle_tsc_ucode_init(&core->access));
    215 
    216         PHYMOD_IF_ERR_RETURN
    217             (temod_pram_abl_enable_set(&core->access,1));
    218         PHYMOD_IF_ERR_RETURN
    219             (eagle_pram_firmware_enable(&core->access, 1));
    220 
    221         PHYMOD_IF_ERR_RETURN(fw_loader(core, tsce_ucode_len, tsce_ucode)); 
    222 
    223         PHYMOD_IF_ERR_RETURN
    224             (eagle_pram_firmware_enable(&core->access, 0));
    225         PHYMOD_IF_ERR_RETURN
    226             (temod_pram_abl_enable_set(&core->access,0));
    227         break;
    228     case phymodFirmwareLoadMethodNone:
    229         break;
    230     default:
    231         PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("illegal fw load method %u"), load_method));
    232     }
    233     if(load_method != phymodFirmwareLoadMethodNone){
    234         PHYMOD_IF_ERR_RETURN(qsgmiie_core_firmware_info_get(core, &actual_fw));
    235         if((tsce_ucode_crc != actual_fw.fw_crc) || (tsce_ucode_ver != actual_fw.fw_version)){
    236             PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("fw load validation was failed")));
    237         }
    238     }
    239     return PHYMOD_E_NONE;
    240 }
    241 
    242 int qsgmiie_phy_firmware_core_config_set(const phymod_phy_access_t* phy, phymod_firmware_core_config_t fw_config)
    243 {
    244     struct eagle_tsc_uc_core_config_st serdes_firmware_core_config;
    245     /* coverity fix: deferencing &serdes_firmware_core_config in sizeof() 
    246      * so that entire struct is set to value 0 by PHYMOD_MEMSET 
    247      */
    248     PHYMOD_MEMSET(&serdes_firmware_core_config, 0, sizeof(*&serdes_firmware_core_config));
    249     serdes_firmware_core_config.field.core_cfg_from_pcs = fw_config.CoreConfigFromPCS;
    250     serdes_firmware_core_config.field.vco_rate = fw_config.VcoRate; 
    251     PHYMOD_IF_ERR_RETURN(eagle_tsc_set_uc_core_config(&phy->access, serdes_firmware_core_config));
    252     return PHYMOD_E_NONE;
    253 }
    254 
    255 int qsgmiie_phy_firmware_core_config_get(const phymod_phy_access_t* phy, phymod_firmware_core_config_t* fw_config)
    256 {
    257     struct eagle_tsc_uc_core_config_st serdes_firmware_core_config;
    258     PHYMOD_IF_ERR_RETURN(eagle_tsc_get_uc_core_config(&phy->access, &serdes_firmware_core_config));
    259     /* coverity fix: deferencing pointer fw_config in sizeof()
    260      * so that entire struct is set to value 0 by PHYMOD_MEMSET
    261      */
    262     PHYMOD_MEMSET(fw_config, 0, sizeof(*fw_config));
    263     fw_config->CoreConfigFromPCS = serdes_firmware_core_config.field.core_cfg_from_pcs;
    264     fw_config->VcoRate = serdes_firmware_core_config.field.vco_rate;
    265     return PHYMOD_E_NONE; 
    266 }
    267 
    268 int qsgmiie_phy_firmware_lane_config_set(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t fw_config)
    269 {
    270     struct eagle_tsc_uc_lane_config_st serdes_firmware_config;
    271     serdes_firmware_config.field.lane_cfg_from_pcs = fw_config.LaneConfigFromPCS;
    272     serdes_firmware_config.field.an_enabled        = fw_config.AnEnabled;
    273     serdes_firmware_config.field.dfe_on            = fw_config.DfeOn; 
    274     serdes_firmware_config.field.force_brdfe_on    = fw_config.ForceBrDfe;
    275     serdes_firmware_config.field.cl72_auto_polarity_en = fw_config.Cl72AutoPolEn;
    276     serdes_firmware_config.field.cl72_restart_timeout_en = fw_config.Cl72RestTO;
    277     serdes_firmware_config.field.scrambling_dis    = fw_config.ScramblingDisable;
    278     serdes_firmware_config.field.unreliable_los    = fw_config.UnreliableLos;
    279     serdes_firmware_config.field.media_type        = fw_config.MediaType;
    280     PHYMOD_IF_ERR_RETURN(eagle_tsc_set_uc_lane_cfg(&phy->access, serdes_firmware_config));
    281     return PHYMOD_E_NONE;
    282 }
    283 
    284 int qsgmiie_phy_firmware_lane_config_get(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t* fw_config)
    285 {
    286     struct eagle_tsc_uc_lane_config_st serdes_firmware_config;
    287     PHYMOD_IF_ERR_RETURN(eagle_tsc_get_uc_lane_cfg(&phy->access, &serdes_firmware_config));
    288     PHYMOD_MEMSET(fw_config, 0, sizeof(*fw_config));
    289     fw_config->LaneConfigFromPCS = serdes_firmware_config.field.lane_cfg_from_pcs;
    290     fw_config->AnEnabled         = serdes_firmware_config.field.an_enabled;
    291     fw_config->DfeOn             = serdes_firmware_config.field.dfe_on;
    292     fw_config->ForceBrDfe        = serdes_firmware_config.field.force_brdfe_on;
    293     fw_config->Cl72AutoPolEn        = serdes_firmware_config.field.cl72_auto_polarity_en;
    294     fw_config->Cl72RestTO      = serdes_firmware_config.field.cl72_restart_timeout_en;
    295     fw_config->ScramblingDisable = serdes_firmware_config.field.scrambling_dis;
    296     fw_config->UnreliableLos     = serdes_firmware_config.field.unreliable_los;
    297     fw_config->MediaType         = serdes_firmware_config.field.media_type;
    298      
    299     return PHYMOD_E_NONE; 
    300 }
    301 
    302 
    303 int qsgmiie_core_pll_sequencer_restart(const phymod_core_access_t* core, uint32_t flags, phymod_sequencer_operation_t operation)
    304 {
    305         
    306     
    307     /* Place your code here */
    308 
    309         
    310     return PHYMOD_E_UNAVAIL;
    311     
    312 }
    313 
    314 
    315 int qsgmiie_core_wait_event(const phymod_core_access_t* core, phymod_core_event_t event, uint32_t timeout)
    316 {
    317         
    318     
    319     /* Place your code here */
    320 
    321         
    322     return PHYMOD_E_UNAVAIL;
    323     
    324 }
    325 
    326 
    327 int qsgmiie_phy_rx_restart(const phymod_phy_access_t* phy)
    328 {
    329     return PHYMOD_E_UNAVAIL;
    330 }
    331 
    332 
    333 int qsgmiie_phy_polarity_set(const phymod_phy_access_t* phy, const phymod_polarity_t* polarity)
    334 {
    335         
    336     PHYMOD_IF_ERR_RETURN
    337         (tqmod_tx_rx_polarity_set(&phy->access, polarity->tx_polarity, polarity->rx_polarity));
    338 
    339     return PHYMOD_E_NONE;
    340     
    341 }
    342 
    343 int qsgmiie_phy_polarity_get(const phymod_phy_access_t* phy, phymod_polarity_t* polarity)
    344 {
    345         
    346      PHYMOD_IF_ERR_RETURN
    347          (tqmod_tx_rx_polarity_get(&phy->access, &polarity->tx_polarity, &polarity->rx_polarity));
    348      return PHYMOD_E_NONE;
    349     
    350 }
    351 
    352 
    353 int qsgmiie_phy_tx_set(const phymod_phy_access_t* phy, const phymod_tx_t* tx)
    354 {
    355     phymod_phy_access_t pm_phy_copy;
    356     int start_lane, num_lane;
    357 
    358     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
    359     PHYMOD_IF_ERR_RETURN
    360         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    361 
    362     pm_phy_copy.access.lane_mask = 0x1 << (start_lane/4);
    363 
    364     
    365     PHYMOD_IF_ERR_RETURN
    366         (eagle_tsc_write_tx_afe(&pm_phy_copy.access, TX_AFE_PRE, (int8_t)tx->pre));
    367     PHYMOD_IF_ERR_RETURN
    368         (eagle_tsc_write_tx_afe(&pm_phy_copy.access, TX_AFE_MAIN, (int8_t)tx->main));
    369     PHYMOD_IF_ERR_RETURN
    370         (eagle_tsc_write_tx_afe(&pm_phy_copy.access, TX_AFE_POST1, (int8_t)tx->post));
    371     PHYMOD_IF_ERR_RETURN
    372         (eagle_tsc_write_tx_afe(&pm_phy_copy.access, TX_AFE_POST2, (int8_t)tx->post2));
    373     PHYMOD_IF_ERR_RETURN
    374         (eagle_tsc_write_tx_afe(&pm_phy_copy.access, TX_AFE_POST3, (int8_t)tx->post3));
    375     PHYMOD_IF_ERR_RETURN
    376         (eagle_tsc_write_tx_afe(&pm_phy_copy.access, TX_AFE_AMP,  (int8_t)tx->amp));
    377     if((tx->drivermode != -1) &&
    378        (phy->device_op_mode & PHYMOD_INTF_CONFIG_TX_FIR_DRIVERMODE_ENABLE)) {
    379         PHYMOD_IF_ERR_RETURN
    380             (eagle_tsc_write_tx_afe(&pm_phy_copy.access, TX_AFE_DRIVERMODE,  (int8_t)tx->drivermode));
    381     }
    382         
    383     return PHYMOD_E_NONE;
    384     
    385 }
    386 
    387 int qsgmiie_phy_tx_get(const phymod_phy_access_t* phy, phymod_tx_t* tx)
    388 {
    389     phymod_phy_access_t pm_phy_copy;
    390     int start_lane, num_lane;
    391     int8_t value = 0;
    392 
    393     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
    394     PHYMOD_IF_ERR_RETURN
    395         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    396 
    397     pm_phy_copy.access.lane_mask = 0x1 << (start_lane/4);
    398 
    399     PHYMOD_IF_ERR_RETURN
    400         (eagle_tsc_read_tx_afe(&pm_phy_copy.access, TX_AFE_PRE, &value));
    401     tx->pre = value;
    402     PHYMOD_IF_ERR_RETURN
    403         (eagle_tsc_read_tx_afe(&pm_phy_copy.access, TX_AFE_MAIN, &value));
    404     tx->main = value;
    405     PHYMOD_IF_ERR_RETURN
    406         (eagle_tsc_read_tx_afe(&pm_phy_copy.access, TX_AFE_POST1, &value));
    407     tx->post = value;
    408     PHYMOD_IF_ERR_RETURN
    409         (eagle_tsc_read_tx_afe(&pm_phy_copy.access, TX_AFE_POST2, &value));
    410     tx->post2 = value;
    411     PHYMOD_IF_ERR_RETURN
    412         (eagle_tsc_read_tx_afe(&pm_phy_copy.access, TX_AFE_POST3, &value));
    413     tx->post3 = value;
    414     PHYMOD_IF_ERR_RETURN
    415         (eagle_tsc_read_tx_afe(&pm_phy_copy.access, TX_AFE_AMP, &value));
    416     tx->amp = value;
    417     PHYMOD_IF_ERR_RETURN
    418         (eagle_tsc_read_tx_afe(&pm_phy_copy.access, TX_AFE_DRIVERMODE, &value));
    419     tx->drivermode = value;
    420 
    421     return PHYMOD_E_NONE;
    422     
    423 }
    424 
    425 
    426 int qsgmiie_phy_tx_override_set(const phymod_phy_access_t* phy, const phymod_tx_override_t* tx_override)
    427 {
    428         
    429     
    430     /* Place your code here */
    431 
    432         
    433     return PHYMOD_E_UNAVAIL;
    434     
    435 }
    436 
    437 int qsgmiie_phy_tx_override_get(const phymod_phy_access_t* phy, phymod_tx_override_t* tx_override)
    438 {
    439         
    440     
    441     /* Place your code here */
    442 
    443         
    444     return PHYMOD_E_UNAVAIL;
    445     
    446 }
    447 
    448 
    449 int qsgmiie_phy_rx_set(const phymod_phy_access_t* phy, const phymod_rx_t* rx)
    450 {
    451         
    452     
    453     /* Place your code here */
    454 
    455         
    456     return PHYMOD_E_UNAVAIL;
    457     
    458 }
    459 
    460 int qsgmiie_phy_rx_get(const phymod_phy_access_t* phy, phymod_rx_t* rx)
    461 {
    462         
    463     
    464     /* Place your code here */
    465 
    466         
    467     return PHYMOD_E_UNAVAIL;
    468     
    469 }
    470 
    471 
    472 int qsgmiie_phy_reset_set(const phymod_phy_access_t* phy, const phymod_phy_reset_t* reset)
    473 {
    474         
    475     
    476     /* Place your code here */
    477 
    478         
    479     return PHYMOD_E_UNAVAIL;
    480     
    481 }
    482 
    483 int qsgmiie_phy_reset_get(const phymod_phy_access_t* phy, phymod_phy_reset_t* reset)
    484 {
    485         
    486     
    487     /* Place your code here */
    488 
    489         
    490     return PHYMOD_E_UNAVAIL;
    491     
    492 }
    493 
    494 
    495 int qsgmiie_phy_power_set(const phymod_phy_access_t* phy, const phymod_phy_power_t* power)
    496 {
    497         
    498         
    499     phymod_phy_access_t pm_phy_copy;
    500     int start_lane, num_lane;
    501 
    502     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
    503     /*next program the tx fir taps and driver current based on the input*/
    504     PHYMOD_IF_ERR_RETURN
    505         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    506 
    507     if ((power->tx == phymodPowerOff) && (power->rx == phymodPowerOff)) {
    508         PHYMOD_IF_ERR_RETURN(tqmod_tx_squelch_set(&pm_phy_copy.access, 1));
    509         PHYMOD_IF_ERR_RETURN(tqmod_rx_squelch_set(&pm_phy_copy.access, 1));
    510     }
    511     if ((power->tx == phymodPowerOn) && (power->rx == phymodPowerOn)) {
    512         PHYMOD_IF_ERR_RETURN(tqmod_tx_squelch_set(&pm_phy_copy.access, 0));
    513         PHYMOD_IF_ERR_RETURN(tqmod_rx_squelch_set(&pm_phy_copy.access, 0));
    514     }
    515 
    516     pm_phy_copy.access.lane_mask = 0x1 << (start_lane/4);
    517     if ((power->tx == phymodPowerOff) && (power->rx == phymodPowerNoChange)) {
    518             /*disable tx on the PMD side */
    519             PHYMOD_IF_ERR_RETURN(eagle_tsc_tx_disable(&pm_phy_copy.access, 1));
    520     }
    521     if ((power->tx == phymodPowerOn) && (power->rx == phymodPowerNoChange)) {
    522             /*enable tx on the PMD side */
    523             PHYMOD_IF_ERR_RETURN(eagle_tsc_tx_disable(&pm_phy_copy.access, 0));
    524     }
    525     if ((power->tx == phymodPowerNoChange) && (power->rx == phymodPowerOff)) {
    526             /*disable rx on the PMD side */
    527             PHYMOD_IF_ERR_RETURN(temod_rx_squelch_set(&pm_phy_copy.access, 1));
    528     }
    529     if ((power->tx == phymodPowerNoChange) && (power->rx == phymodPowerOn)) {
    530             /*enable rx on the PMD side */
    531             PHYMOD_IF_ERR_RETURN(temod_rx_squelch_set(&pm_phy_copy.access, 0));
    532     }
    533         
    534     return PHYMOD_E_NONE;
    535     
    536 }
    537 
    538 int qsgmiie_phy_power_get(const phymod_phy_access_t* phy, phymod_phy_power_t* power)
    539 {
    540     int enable;
    541     uint32_t lb_enable;
    542     phymod_phy_access_t pm_phy_copy;
    543     int start_lane, num_lane;
    544 
    545     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
    546     /* next program the tx fir taps and driver current based on the input */
    547     PHYMOD_IF_ERR_RETURN
    548         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    549 
    550     pm_phy_copy.access.lane_mask = 0x1 << (start_lane/4);
    551 
    552     PHYMOD_IF_ERR_RETURN(temod_rx_squelch_get(&pm_phy_copy.access, &enable));
    553 
    554     /* next check if PMD loopback is on */ 
    555     if (enable) {                           
    556         PHYMOD_IF_ERR_RETURN(eagle_pmd_loopback_get(&pm_phy_copy.access, &lb_enable));
    557         if (lb_enable) enable = 0;
    558     }
    559 
    560     power->rx = (enable == 1)? phymodPowerOff: phymodPowerOn;
    561     PHYMOD_IF_ERR_RETURN(temod_tx_squelch_get(&pm_phy_copy.access, &enable));
    562     power->tx = (enable == 1)? phymodPowerOff: phymodPowerOn;
    563     return PHYMOD_E_NONE;
    564 }
    565 
    566 int qsgmiie_phy_tx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t tx_control)
    567 {
    568     switch (tx_control) {
    569     case phymodTxTrafficDisable:
    570         PHYMOD_IF_ERR_RETURN(tqmod_tx_lane_control_set(&phy->access, TEMOD_TX_LANE_TRAFFIC_DISABLE));
    571         break;
    572     case phymodTxTrafficEnable:
    573         PHYMOD_IF_ERR_RETURN(tqmod_tx_lane_control_set(&phy->access, TEMOD_TX_LANE_TRAFFIC_ENABLE));
    574         break;
    575     case phymodTxReset:
    576         PHYMOD_IF_ERR_RETURN(tqmod_tx_lane_control_set(&phy->access, TEMOD_TX_LANE_RESET));
    577         break;
    578     case phymodTxSquelchOn:
    579         PHYMOD_IF_ERR_RETURN(tqmod_tx_squelch_set(&phy->access, 1));
    580         break;
    581     case phymodTxSquelchOff:
    582         PHYMOD_IF_ERR_RETURN(tqmod_tx_squelch_set(&phy->access, 0));
    583         break;
    584     default:
    585         break;
    586     }
    587     return PHYMOD_E_NONE;
    588     
    589 }
    590 
    591 
    592 int qsgmiie_phy_tx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t* tx_control)
    593 {
    594     int enable, reset, tx_lane;
    595     uint32_t lb_enable;
    596     phymod_phy_access_t pm_phy_copy;
    597     int start_lane, num_lane;
    598 
    599     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
    600     /* next program the tx fir taps and driver current based on the input */
    601     PHYMOD_IF_ERR_RETURN
    602         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    603 
    604     PHYMOD_IF_ERR_RETURN(tqmod_tx_squelch_get(&phy->access, &enable));
    605 
    606     pm_phy_copy.access.lane_mask = 0x1 << (start_lane/4);
    607     /* next check if PMD loopback is on */ 
    608     if (enable) {                           
    609         PHYMOD_IF_ERR_RETURN(eagle_pmd_loopback_get(&pm_phy_copy.access, &lb_enable));
    610         if (lb_enable) enable = 0;
    611     }
    612 
    613     if(enable) {
    614         *tx_control = phymodTxSquelchOn;
    615     } else {
    616         PHYMOD_IF_ERR_RETURN(tqmod_tx_lane_control_get(&phy->access, &reset, &tx_lane));
    617         if (!reset) {
    618             *tx_control = phymodTxReset;
    619         } else if (!tx_lane) {
    620             *tx_control = phymodTxTrafficDisable;
    621         } else {
    622             *tx_control = phymodTxTrafficEnable;
    623         }
    624     }
    625     return PHYMOD_E_NONE;
    626 }
    627 
    628 /*Rx control*/
    629 int qsgmiie_phy_rx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t rx_control)
    630 {
    631     phymod_phy_access_t pm_phy_copy;
    632     int start_lane, num_lane, i;
    633 
    634     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
    635     /* next program the tx fir taps and driver current based on the input */
    636     PHYMOD_IF_ERR_RETURN
    637         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    638 
    639     pm_phy_copy.access.lane_mask = 0x1 << start_lane;
    640 
    641     switch (rx_control) {
    642     case phymodRxReset:
    643         PHYMOD_IF_ERR_RETURN(tqmod_rx_lane_control_set(&phy->access, 1));
    644         break;
    645     case phymodRxSquelchOn:
    646         for (i = 0; i < num_lane; i++) {
    647             if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    648                 continue;
    649             }
    650             pm_phy_copy.access.lane_mask = 1 << (start_lane + i);
    651             PHYMOD_IF_ERR_RETURN(tqmod_rx_squelch_set(&pm_phy_copy.access, 1));
    652         }
    653         break;
    654     case phymodRxSquelchOff:
    655         for (i = 0; i < num_lane; i++) {
    656             if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    657                 continue;
    658             }
    659             pm_phy_copy.access.lane_mask = 1 << (start_lane + i);
    660             PHYMOD_IF_ERR_RETURN(tqmod_rx_squelch_set(&pm_phy_copy.access, 0));
    661         }
    662         break;
    663     default:
    664         break;
    665     }
    666     return PHYMOD_E_NONE;
    667 }
    668 
    669 int qsgmiie_phy_rx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t* rx_control)
    670 {
    671     int enable, reset;
    672     uint32_t lb_enable;
    673     phymod_phy_access_t pm_phy_copy;
    674     int start_lane, num_lane;
    675 
    676     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
    677     /* next program the tx fir taps and driver current based on the input */
    678     PHYMOD_IF_ERR_RETURN
    679         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    680 
    681     PHYMOD_IF_ERR_RETURN(tqmod_rx_squelch_get(&phy->access, &enable));
    682 
    683     pm_phy_copy.access.lane_mask = 0x1 << (start_lane/4);
    684     /* next check if PMD loopback is on */ 
    685     if (enable) {                           
    686         PHYMOD_IF_ERR_RETURN(eagle_pmd_loopback_get(&pm_phy_copy.access, &lb_enable));
    687         if (lb_enable) enable = 0;
    688     }
    689     if(enable) {
    690         *rx_control = phymodRxSquelchOn;
    691     } else {
    692         PHYMOD_IF_ERR_RETURN(tqmod_rx_lane_control_get(&phy->access, &reset));
    693         if (reset == 0) {
    694             *rx_control = phymodRxReset;
    695         } else {
    696             *rx_control = phymodRxSquelchOff;
    697         }
    698     }
    699     return PHYMOD_E_NONE;
    700 }
    701 
    702 STATIC
    703 int _qsgmiie_speed_id_interface_config_get(const phymod_phy_access_t* phy, int speed_id, phymod_phy_inf_config_t* config)
    704 {
    705     switch (speed_id) {
    706     case 0x0:
    707         config->data_rate = 10;
    708         break;
    709     case 0x1:
    710         config->data_rate = 100;
    711         break;
    712     case 0x2:
    713         config->data_rate = 1000;
    714         break;
    715     default:
    716         config->data_rate = 0;
    717         break;
    718     }
    719     config->interface_type = phymodInterfaceSGMII;
    720 
    721     return PHYMOD_E_NONE;
    722 }
    723 
    724 
    725 int qsgmiie_phy_interface_config_set(const phymod_phy_access_t* phy, uint32_t flags, const phymod_phy_inf_config_t* config)
    726 {
    727 
    728     PHYMOD_IF_ERR_RETURN
    729         (tqmod_set_spd_intf(&phy->access, config->data_rate));
    730 
    731     return PHYMOD_E_NONE;
    732 
    733 }
    734 
    735 int qsgmiie_phy_interface_config_get(const phymod_phy_access_t* phy, 
    736                                      uint32_t flags,
    737                                      phymod_ref_clk_t ref_clock, 
    738                                      phymod_phy_inf_config_t* config)
    739 {
    740     int speed_id;
    741 
    742     config->ref_clock = ref_clock;
    743 
    744     PHYMOD_IF_ERR_RETURN
    745         (tqmod_speed_id_get(&phy->access, &speed_id));
    746 
    747     PHYMOD_IF_ERR_RETURN
    748         (_qsgmiie_speed_id_interface_config_get(phy, speed_id, config));         
    749 
    750     return PHYMOD_E_NONE;
    751 }
    752 
    753 int qsgmiie_phy_autoneg_ability_set(const phymod_phy_access_t* phy, const phymod_autoneg_ability_t* an_ability)
    754 {
    755     tqmod_an_ability_t value; 
    756     int start_lane, num_lane;
    757     phymod_phy_access_t phy_copy;
    758 
    759     /* next program the tx fir taps and driver current based on the input */
    760     PHYMOD_IF_ERR_RETURN
    761         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    762 
    763     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    764     phy_copy.access.lane_mask = 0x1 << start_lane;
    765 
    766     PHYMOD_MEMSET(&value, 0x0, sizeof(value));
    767 
    768     /* check if sgmii  or not */
    769     if (PHYMOD_AN_CAP_SGMII_GET(an_ability)) {
    770         switch (an_ability->sgmii_speed) {
    771         case phymod_CL37_SGMII_10M:
    772             value.cl37_adv.cl37_sgmii_speed = TEMOD_CL37_SGMII_10M;
    773             break;
    774         case phymod_CL37_SGMII_100M:
    775             value.cl37_adv.cl37_sgmii_speed = TEMOD_CL37_SGMII_100M;
    776             break;
    777         case phymod_CL37_SGMII_1000M:
    778             value.cl37_adv.cl37_sgmii_speed = TEMOD_CL37_SGMII_1000M;
    779             break;
    780         default:
    781             value.cl37_adv.cl37_sgmii_speed = TEMOD_CL37_SGMII_1000M;
    782             break;
    783         }
    784     }
    785 
    786     /* next check pause */
    787     if (PHYMOD_AN_CAP_SYMM_PAUSE_GET(an_ability)) {
    788         value.cl37_adv.an_pause = TEMOD_SYMM_PAUSE;
    789     } else if (PHYMOD_AN_CAP_ASYM_PAUSE_GET(an_ability)) {
    790         value.cl37_adv.an_pause = TEMOD_ASYM_PAUSE;
    791     }
    792 
    793 
    794     return PHYMOD_E_NONE;
    795 
    796 }
    797 
    798 int qsgmiie_phy_autoneg_ability_get(const phymod_phy_access_t* phy, phymod_autoneg_ability_t* an_ability_get_type)
    799 {
    800         
    801     tqmod_an_ability_t value;
    802     phymod_phy_access_t phy_copy;
    803     int start_lane, num_lane;
    804 
    805     PHYMOD_IF_ERR_RETURN
    806         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    807     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    808     phy_copy.access.lane_mask = 0x1 << start_lane;
    809     PHYMOD_MEMSET(&value, 0x0, sizeof(value));
    810      
    811 /*    PHYMOD_IF_ERR_RETURN
    812         (tqmod_autoneg_local_ability_get(&phy_copy.access, &value));*/
    813     value.cl37_adv.cl37_sgmii_speed  = TEMOD_CL37_SGMII_10M |
    814                                   TEMOD_CL37_SGMII_100M |
    815                                   TEMOD_CL37_SGMII_1000M;
    816     value.cl37_adv.an_pause = TEMOD_NO_PAUSE | TEMOD_ASYM_PAUSE;
    817     switch (value.cl37_adv.an_pause) {
    818     case TEMOD_ASYM_PAUSE:
    819         PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get_type);
    820         break;
    821     case TEMOD_SYMM_PAUSE:
    822         PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get_type);
    823         break;
    824     default:
    825         break;
    826     } 
    827     return PHYMOD_E_NONE;
    828     
    829 }
    830 
    831 
    832 int qsgmiie_phy_autoneg_set(const phymod_phy_access_t* phy, const phymod_autoneg_control_t* an)
    833 {
    834         
    835     phymod_firmware_lane_config_t firmware_lane_config;
    836     int start_lane, num_lane;
    837     phymod_phy_access_t phy_copy;
    838     tqmod_an_control_t an_control;
    839     int enable;
    840 
    841     /* next program the tx fir taps and driver current based on the input */
    842     PHYMOD_IF_ERR_RETURN
    843         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    844 
    845     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    846     phy_copy.access.lane_mask = 0x1 << start_lane;
    847 
    848     an_control.enable       = an->enable;
    849     an_control.an_property_type = 0x0;   /* for now disable */  
    850     switch (an->an_mode) {
    851     case phymod_AN_MODE_CL73:
    852         an_control.an_type = TEMOD_AN_MODE_CL73;
    853         break;
    854     case phymod_AN_MODE_CL37:
    855         an_control.an_type = TEMOD_AN_MODE_CL37;
    856         break;
    857     case phymod_AN_MODE_CL73BAM:
    858         an_control.an_type = TEMOD_AN_MODE_CL73BAM;
    859         break;
    860     case phymod_AN_MODE_CL37BAM:
    861         an_control.an_type = TEMOD_AN_MODE_CL37BAM;
    862         break;
    863     case phymod_AN_MODE_HPAM:
    864         an_control.an_type = TEMOD_AN_MODE_HPAM;
    865         break;
    866     case phymod_AN_MODE_SGMII:
    867         an_control.an_type = TEMOD_AN_MODE_SGMII;
    868         break;
    869     default:
    870         return PHYMOD_E_PARAM;
    871     }
    872     enable = an_control.enable;
    873 
    874     /* make sure the firmware config is set to an eenabled */
    875     phy_copy.access.lane_mask = 0x1 << (start_lane / 4);
    876     PHYMOD_IF_ERR_RETURN
    877         (eagle_lane_soft_reset_release(&phy_copy.access, 0));
    878 
    879 
    880     PHYMOD_IF_ERR_RETURN
    881         (qsgmiie_phy_firmware_lane_config_get(&phy_copy, &firmware_lane_config));
    882     if (an->enable) {
    883         firmware_lane_config.AnEnabled = 1;
    884         firmware_lane_config.LaneConfigFromPCS = 1;
    885     } else {
    886         firmware_lane_config.AnEnabled = 0;
    887         firmware_lane_config.LaneConfigFromPCS = 0;
    888     }
    889     PHYMOD_IF_ERR_RETURN
    890         (qsgmiie_phy_firmware_lane_config_set(&phy_copy, firmware_lane_config));
    891 
    892     PHYMOD_IF_ERR_RETURN
    893         (eagle_lane_soft_reset_release(&phy_copy.access, 1));
    894 
    895     phy_copy.access.lane_mask = 0x1 << start_lane;
    896     PHYMOD_IF_ERR_RETURN
    897         (tqmod_autoneg_set(&phy_copy.access, &enable));       
    898 
    899     return PHYMOD_E_NONE;
    900     
    901 }
    902 
    903 int qsgmiie_phy_autoneg_get(const phymod_phy_access_t* phy, phymod_autoneg_control_t* an, uint32_t* an_done)
    904 {
    905         
    906     tqmod_an_control_t an_control;
    907     phymod_phy_access_t phy_copy;
    908     int start_lane, num_lane; 
    909 /*    int an_complete = 0;*/
    910 
    911     /* next program the tx fir taps and driver current based on the input */
    912     PHYMOD_IF_ERR_RETURN
    913         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    914 
    915     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    916     phy_copy.access.lane_mask = 0x1 << start_lane;
    917 
    918     PHYMOD_MEMSET(&an_control, 0x0,  sizeof(tqmod_an_control_t));
    919 /*    PHYMOD_IF_ERR_RETURN
    920         (temod_autoneg_control_get(&phy_copy.access, &an_control, &an_complete));*/
    921     
    922     if (an_control.enable) {
    923         an->enable = 1;
    924         *an_done = 0; 
    925     } else {
    926         an->enable = 0;
    927     }                
    928     return PHYMOD_E_NONE;
    929 }
    930 
    931 int qsgmiie_core_init(const phymod_core_access_t* core, const phymod_core_init_config_t* init_config, const phymod_core_status_t* core_status)
    932 {
    933     phymod_phy_access_t phy_access, phy_access_copy;
    934     phymod_core_access_t  core_copy;
    935     phymod_firmware_core_config_t  firmware_core_config_tmp;
    936 #if 0
    937     temod_an_init_t an; 
    938 #endif
    939 
    940     TSCE_CORE_TO_PHY_ACCESS(&phy_access, core);
    941     phy_access_copy = phy_access;
    942     PHYMOD_MEMCPY(&core_copy, core, sizeof(core_copy));
    943     core_copy.access.lane_mask = 0x1;
    944         phy_access_copy = phy_access;
    945         phy_access_copy.access = core->access;
    946         phy_access_copy.access.lane_mask = 0x1;
    947         phy_access_copy.type = core->type;
    948 
    949     PHYMOD_IF_ERR_RETURN
    950         (temod_pmd_reset_seq(&core_copy.access, core_status->pmd_active));
    951 
    952     /* need to set the heart beat default is for 156.25M */
    953     if (init_config->interface.ref_clock == phymodRefClk125Mhz) {
    954         /* we need to set the ref clock config differently */
    955     }
    956     if (_qsgmiie_core_firmware_load(&core_copy, init_config->firmware_load_method, init_config->firmware_loader)) {
    957         PHYMOD_DEBUG_ERROR(("devad 0x%"PRIx32" lane 0x%"PRIx32": UC firmware-load failed\n", core->access.addr, core->access.lane_mask));  
    958         PHYMOD_IF_ERR_RETURN (PHYMOD_E_INIT);
    959     }
    960     /* next we need to check if the load is correct or not */
    961     if (eagle_tsc_ucode_load_verify(&core_copy.access, (uint8_t *) &tsce_ucode, tsce_ucode_len)) {
    962         PHYMOD_DEBUG_ERROR(("devad 0x%"PRIx32" lane 0x%"PRIx32": UC load-verify failed\n", core->access.addr, core->access.lane_mask));  
    963         PHYMOD_IF_ERR_RETURN (PHYMOD_E_INIT);
    964     }
    965 
    966     PHYMOD_IF_ERR_RETURN
    967         (eagle_pmd_ln_h_rstb_pkill_override( &phy_access_copy.access, 0x1));
    968 
    969     /* next we need to set the uc active and release uc */
    970     PHYMOD_IF_ERR_RETURN
    971         (eagle_uc_active_set(&core_copy.access ,1)); 
    972     /* release the uc reset */
    973     PHYMOD_IF_ERR_RETURN
    974         (eagle_uc_reset(&core_copy.access ,1)); 
    975     /* we need to wait at least 10ms for the uc to settle */
    976     PHYMOD_USLEEP(10000);
    977 
    978     /* poll the ready bit in 10 ms */
    979     PHYMOD_IF_ERR_RETURN
    980         (eagle_tsc_poll_uc_dsc_ready_for_cmd_equals_1(&phy_access_copy.access, 1));
    981 
    982     PHYMOD_IF_ERR_RETURN(
    983         eagle_pmd_ln_h_rstb_pkill_override( &phy_access_copy.access, 0x0));
    984 
    985     /* plldiv CONFIG */
    986     PHYMOD_IF_ERR_RETURN
    987         (eagle_pll_mode_set(&core->access, 0x9));
    988 
    989     /* now config the lane mapping and polarity */
    990     PHYMOD_IF_ERR_RETURN
    991         (qsgmiie_core_lane_map_set(core, &init_config->lane_map));
    992 #if 0
    993   /* NEED TO REVISIT */
    994     PHYMOD_IF_ERR_RETURN
    995         (temod_autoneg_set_init(&core->access, &an));
    996 #endif
    997 /*    PHYMOD_IF_ERR_RETURN
    998         (temod_autoneg_timer_init(&core->access));*/
    999     PHYMOD_IF_ERR_RETURN
   1000         (temod_master_port_num_set(&core->access, 0));
   1001     /* don't overide the fw that set in config set if not specified */
   1002     firmware_core_config_tmp = init_config->firmware_core_config;
   1003     firmware_core_config_tmp.CoreConfigFromPCS = 0;
   1004     /* set the vco rate to be default at 10.0000G */
   1005     firmware_core_config_tmp.VcoRate = 0x12;
   1006 
   1007     PHYMOD_IF_ERR_RETURN
   1008         (qsgmiie_phy_firmware_core_config_set(&phy_access_copy, firmware_core_config_tmp)); 
   1009 
   1010     /* release core soft reset */
   1011     PHYMOD_IF_ERR_RETURN
   1012         (eagle_core_soft_reset_release(&core_copy.access, 1));
   1013         
   1014     return PHYMOD_E_NONE;
   1015         
   1016 }
   1017 
   1018 
   1019 int qsgmiie_phy_init(const phymod_phy_access_t* phy, const phymod_phy_init_config_t* init_config)
   1020 {
   1021         
   1022     const phymod_access_t *pm_acc = &phy->access;
   1023     phymod_phy_access_t pm_phy_copy;
   1024     int start_lane, num_lane, i;
   1025     int an_en=init_config->an_en;
   1026     int lane_bkup;
   1027     phymod_polarity_t tmp_pol;
   1028 
   1029     PHYMOD_MEMSET(&tmp_pol, 0x0, sizeof(tmp_pol));
   1030     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
   1031 
   1032     /* next program the tx fir taps and driver current based on the input */
   1033     PHYMOD_IF_ERR_RETURN
   1034         (phymod_util_lane_config_get(pm_acc, &start_lane, &num_lane));
   1035 
   1036     /* Enable autoneg for QSGMII pcs*/
   1037     PHYMOD_IF_ERR_RETURN
   1038        (tqmod_autoneg_set(&pm_phy_copy.access, &an_en)); 
   1039 
   1040    /* exit if lane number >4 (for pmd and tsce)*/
   1041    if(start_lane>4) 
   1042       return PHYMOD_E_NONE;
   1043     /* per lane based reset release */
   1044     PHYMOD_IF_ERR_RETURN
   1045         (tqmod_pmd_x4_reset(pm_acc));
   1046 
   1047     /* poll for per lane uc_dsc_ready */
   1048     lane_bkup = pm_phy_copy.access.lane_mask;
   1049     for (i = 0; i < num_lane; i++) {
   1050         pm_phy_copy.access.lane_mask = 1 << (start_lane + i);
   1051         PHYMOD_IF_ERR_RETURN
   1052             (eagle_lane_soft_reset_release(&pm_phy_copy.access, 1));
   1053     }
   1054     pm_phy_copy.access.lane_mask = lane_bkup;
   1055 
   1056     /* program the rx/tx polarity */
   1057     for (i = 0; i < num_lane; i++) {
   1058         pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane);
   1059         tmp_pol.tx_polarity = (init_config->polarity.tx_polarity) >> i & 0x1;
   1060         tmp_pol.rx_polarity = (init_config->polarity.rx_polarity) >> i & 0x1;
   1061         PHYMOD_IF_ERR_RETURN
   1062             (qsgmiie_phy_polarity_set(&pm_phy_copy, &tmp_pol));
   1063     }
   1064 
   1065     for (i = 0; i < num_lane; i++) {
   1066         pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane);
   1067         PHYMOD_IF_ERR_RETURN
   1068             (qsgmiie_phy_tx_set(&pm_phy_copy, &init_config->tx[i]));
   1069     }
   1070 
   1071     pm_phy_copy.access.lane_mask = 0x1;
   1072 
   1073     /*PHYMOD_IF_ERR_RETURN
   1074         (temod_update_port_mode(pm_acc, &pll_restart));*/
   1075 
   1076     PHYMOD_IF_ERR_RETURN
   1077         (tqmod_rx_lane_control_set(pm_acc, 1));
   1078     PHYMOD_IF_ERR_RETURN
   1079         (tqmod_tx_lane_control_set(pm_acc, TQMOD_TX_LANE_RESET_TRAFFIC_ENABLE));         /* TX_LANE_CONTROL */
   1080 
   1081         
   1082     for (i = 0; i < num_lane; i++) {
   1083         pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane);
   1084     PHYMOD_IF_ERR_RETURN
   1085         (tqmod_txfir_tx_disable_set(&pm_phy_copy.access));
   1086 
   1087     PHYMOD_IF_ERR_RETURN
   1088         (tqmod_pmd_osmode_set(&pm_phy_copy.access, 0x1));
   1089 
   1090     PHYMOD_IF_ERR_RETURN
   1091         (tqmod_init_pcs_ilkn(&pm_phy_copy.access));
   1092 
   1093     }
   1094         
   1095     return PHYMOD_E_NONE;
   1096     
   1097 }
   1098 
   1099 
   1100 int qsgmiie_phy_loopback_set(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t enable)
   1101 {
   1102     int start_lane, num_lane;
   1103     int rv = PHYMOD_E_NONE;
   1104     phymod_phy_access_t phy_copy;
   1105 
   1106     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1107 
   1108     /* next figure out the lane num and start_lane based on the input */
   1109     PHYMOD_IF_ERR_RETURN
   1110         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
   1111 
   1112     switch (loopback) {
   1113     case phymodLoopbackGlobal :
   1114     case phymodLoopbackGlobalPMD :
   1115         phy_copy.access.lane_mask = 0x1 << (start_lane / 4);
   1116         PHYMOD_IF_ERR_RETURN(eagle_tsc_dig_lpbk(&phy_copy.access, (uint8_t) enable));
   1117         PHYMOD_IF_ERR_RETURN(eagle_pmd_force_signal_detect(&phy_copy.access, (int) enable));
   1118         break;
   1119     case phymodLoopbackRemotePMD :
   1120         phy_copy.access.lane_mask = 0x1 << (start_lane / 4);
   1121         PHYMOD_IF_ERR_RETURN(eagle_tsc_rmt_lpbk(&phy_copy.access, (uint8_t)enable));
   1122         break;
   1123     case phymodLoopbackRemotePCS :
   1124         PHYMOD_IF_ERR_RETURN(temod_rx_loopback_control(&phy->access, enable, enable, enable)); /* RAVI */
   1125         break;
   1126     default :
   1127         break;
   1128     }             
   1129     return rv;
   1130     return PHYMOD_E_NONE;
   1131     
   1132 }
   1133 
   1134 int qsgmiie_phy_loopback_get(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t* enable)
   1135 {
   1136     int start_lane, num_lane;
   1137     phymod_phy_access_t phy_copy;
   1138 
   1139     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1140 
   1141     /* next figure out the lane num and start_lane based on the input */
   1142     PHYMOD_IF_ERR_RETURN
   1143         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
   1144 
   1145     switch (loopback) {
   1146     case phymodLoopbackGlobal :
   1147     case phymodLoopbackGlobalPMD :
   1148         phy_copy.access.lane_mask = 0x1 << (start_lane / 4);
   1149         PHYMOD_IF_ERR_RETURN(eagle_pmd_loopback_get(&phy_copy.access, enable));
   1150         break;
   1151     case phymodLoopbackRemotePMD :
   1152         phy_copy.access.lane_mask = 0x1 << (start_lane / 4);
   1153         PHYMOD_IF_ERR_RETURN(eagle_tsc_rmt_lpbk_get(&phy_copy.access, enable));
   1154         break;
   1155     case phymodLoopbackRemotePCS :
   1156         /* PHYMOD_IF_ERR_RETURN(temod_rx_loopback_control(&phy->access, enable, enable, enable)); */ /* RAVI */
   1157         break;
   1158     default :
   1159         break;
   1160     } 
   1161                 
   1162     return PHYMOD_E_NONE;
   1163 }
   1164 
   1165 
   1166 int qsgmiie_phy_rx_pmd_locked_get(const phymod_phy_access_t* phy, uint32_t* rx_seq_done)
   1167 {
   1168     int start_lane, num_lane;
   1169     phymod_phy_access_t phy_copy;
   1170 
   1171     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1172 
   1173     /* next figure out the lane num and start_lane based on the input */
   1174     PHYMOD_IF_ERR_RETURN
   1175         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
   1176         
   1177     phy_copy.access.lane_mask = 0x1 << (start_lane/4);
   1178     
   1179     PHYMOD_IF_ERR_RETURN(temod_pmd_lock_get(&phy_copy.access, rx_seq_done));
   1180 
   1181         
   1182     return PHYMOD_E_NONE;
   1183     
   1184 }
   1185 
   1186 
   1187 int qsgmiie_phy_link_status_get(const phymod_phy_access_t* phy, uint32_t* link_status)
   1188 {
   1189         
   1190    PHYMOD_IF_ERR_RETURN(tqmod_get_pcs_link_status(&phy->access, link_status));    
   1191         
   1192     return PHYMOD_E_NONE;
   1193     
   1194 }
   1195 
   1196 
   1197 STATIC 
   1198 int qsgmiie_phy_reg_is_pcs_get(uint32_t reg_addr, int* is_qsgmii_pcs_reg) {
   1199 
   1200     *is_qsgmii_pcs_reg = (PHY_REG_ADDR_DEVAD(reg_addr) == 0) && 
   1201         ((IS_QSGMII_REGISTER(reg_addr)) || (QSGMII_REG_ADDR_REG(reg_addr) < 0x10));
   1202     return PHYMOD_E_NONE; 
   1203 }
   1204 
   1205 int qsgmiie_phy_reg_read(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t* val)
   1206 {
   1207     int start_lane, num_lane, is_qsgmii_pcs;
   1208     phymod_phy_access_t phy_copy;
   1209 
   1210     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1211 
   1212     /* next figure out the lane num and start_lane based on the input */
   1213     PHYMOD_IF_ERR_RETURN
   1214         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
   1215 
   1216     PHYMOD_IF_ERR_RETURN
   1217         (qsgmiie_phy_reg_is_pcs_get(reg_addr, &is_qsgmii_pcs));
   1218 
   1219     if (!is_qsgmii_pcs) {
   1220         phy_copy.access.lane_mask = 0x1 << (start_lane/4);
   1221     }
   1222 
   1223     PHYMOD_IF_ERR_RETURN
   1224         (phymod_tsc_iblk_read(&phy_copy.access, reg_addr, val));
   1225 
   1226     return PHYMOD_E_NONE;
   1227 }
   1228 
   1229 int qsgmiie_phy_reg_write(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t val)
   1230 {
   1231     int start_lane, num_lane, is_qsgmii_pcs;
   1232     phymod_phy_access_t phy_copy;
   1233 
   1234     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1235 
   1236     /* next figure out the lane num and start_lane based on the input */
   1237     PHYMOD_IF_ERR_RETURN
   1238         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
   1239         
   1240     PHYMOD_IF_ERR_RETURN
   1241         (qsgmiie_phy_reg_is_pcs_get(reg_addr, &is_qsgmii_pcs));
   1242 
   1243     if (!is_qsgmii_pcs) {
   1244         phy_copy.access.lane_mask = 0x1 << (start_lane/4);
   1245     }
   1246 
   1247     PHYMOD_IF_ERR_RETURN
   1248         (phymod_tsc_iblk_write(&phy_copy.access, reg_addr, val));
   1249 
   1250     return PHYMOD_E_NONE;
   1251 }
   1252 
   1253 int qsgmiie_phy_rx_signal_detect_get(const phymod_phy_access_t* phy, uint32_t* value)
   1254 {
   1255     uint32_t local_rx_signal_det;
   1256     int start_lane, num_lane, i;
   1257 
   1258     *value = 1;
   1259 
   1260     PHYMOD_IF_ERR_RETURN
   1261         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
   1262 
   1263     for (i = 0; i < num_lane; i++) {
   1264         if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
   1265             continue;
   1266         }
   1267         PHYMOD_IF_ERR_RETURN
   1268             (eagle_tsc_signal_detect(&phy->access, &local_rx_signal_det));
   1269         *value = *value & local_rx_signal_det;
   1270     }
   1271 
   1272     return PHYMOD_E_NONE;
   1273 }
   1274 
   1275 int qsgmiie_phy_rx_ppm_get(const phymod_phy_access_t* phy, int16_t* rx_ppm)
   1276 {
   1277     int start_lane, num_lane;
   1278     phymod_phy_access_t pm_phy_copy;
   1279 
   1280     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
   1281 
   1282     PHYMOD_IF_ERR_RETURN
   1283         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
   1284 
   1285     pm_phy_copy.access.lane_mask = 1 << start_lane;
   1286     PHYMOD_IF_ERR_RETURN
   1287         (eagle_tsc_rx_ppm(&pm_phy_copy.access, rx_ppm));
   1288 
   1289     return PHYMOD_E_NONE;
   1290 }
   1291