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

merlin16.c (54843B)


      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_util.h>
     14 #include <phymod/phymod_debug.h>
     15 #include <phymod/chip/merlin16.h>
     16 #include <phymod/phymod_acc.h>
     17 #include <phymod/chip/bcmi_tsce16_xgxs_defs.h>
     18 #include "../../merlin16/tier1/merlin16_cfg_seq.h"
     19 #include "../../merlin16/tier1/merlin16_enum.h"
     20 #include "../../merlin16/tier1/merlin16_common.h"
     21 #include "../../merlin16/tier1/merlin16_interface.h"
     22 #include "../../merlin16/tier1/merlin16_dependencies.h"
     23 #include "../../merlin16/tier1/merlin16_debug_functions.h"
     24 #include "../../merlin16/tier1/merlin16_internal.h"
     25 
     26 #define MERLIN16_MODEL         0x23
     27 #define MERLIN16_PHY_ALL_LANES 0xf
     28 #define MERLIN16_NOF_LANES_IN_CORE 4
     29 
     30 #define MERLIN16_CORE_TO_PHY_ACCESS(_phy_access, _core_access) \
     31     do{\
     32         PHYMOD_MEMCPY(&(_phy_access)->access, &(_core_access)->access, sizeof((_phy_access)->access));\
     33         (_phy_access)->type           = (_core_access)->type; \
     34         (_phy_access)->port_loc       = (_core_access)->port_loc; \
     35         (_phy_access)->device_op_mode = (_core_access)->device_op_mode; \
     36         (_phy_access)->access.lane_mask = MERLIN16_PHY_ALL_LANES; \
     37     }while(0)
     38 
     39 #define MERLIN16_NOF_DFES 5
     40 
     41 #define MERILIN16_PMD_CRC_UCODE  1
     42 /* uController's firmware */
     43 extern unsigned char merlin16_ucode[];
     44 extern unsigned short merlin16_ucode_ver;
     45 extern unsigned short merlin16_ucode_crc;
     46 extern unsigned short merlin16_ucode_len;
     47 
     48 
     49 /*Initialize phymod module*/
     50 int merlin16_core_identify(const phymod_core_access_t* core, uint32_t core_id, uint32_t* is_identified)
     51 {
     52     merlin16_rev_id0_t rev_id0;
     53     merlin16_rev_id1_t rev_id1;
     54     const phymod_access_t *pm_acc = &core->access;
     55     *is_identified = 0;
     56 
     57     PHYMOD_IF_ERR_RETURN(merlin16_identify(pm_acc, &rev_id0, &rev_id1));
     58     if (rev_id0.revid_model == MERLIN16_MODEL) {
     59         *is_identified = 1;
     60     }
     61 
     62     return PHYMOD_E_NONE;
     63 }
     64 
     65 /*Retrive core information*/
     66 int merlin16_core_info_get(const phymod_core_access_t* core, phymod_core_info_t* info)
     67 {
     68     info->core_version = phymodCoreVersionMerlin16;
     69     PHYMOD_STRNCPY(info->name, "Merlin16", PHYMOD_STRLEN("Merlin16") + 1);
     70     info->phy_id0 = 0;
     71     info->phy_id1= 0;
     72 
     73     return PHYMOD_E_NONE;
     74 }
     75 
     76 /*Set\get lane mapping*/
     77 int merlin16_core_lane_map_set(const phymod_core_access_t* core, const phymod_lane_map_t* lane_map)
     78 {
     79     /*Just suport lane address mapping, not support lane swapping*/
     80     return PHYMOD_E_NONE;
     81 }
     82 int merlin16_core_lane_map_get(const phymod_core_access_t* core, phymod_lane_map_t* lane_map)
     83 {
     84     /*Just suport lane address mapping, not support lane swapping*/
     85     return PHYMOD_E_NONE;
     86 }
     87 
     88 /*Reset Core*/
     89 int merlin16_core_reset_set(const phymod_core_access_t* core, phymod_reset_mode_t reset_mode, phymod_reset_direction_t direction)
     90 {
     91     return PHYMOD_E_NONE;
     92 }
     93 int merlin16_core_reset_get(const phymod_core_access_t* core, phymod_reset_mode_t reset_mode, phymod_reset_direction_t* direction)
     94 {
     95     return PHYMOD_E_NONE;
     96 }
     97 
     98 /*Retrive firmware information*/
     99 int merlin16_core_firmware_info_get(const phymod_core_access_t* core, phymod_core_firmware_info_t* fw_info)
    100 {
    101     return PHYMOD_E_NONE;
    102 }
    103 
    104 /*Start\Stop the sequencer*/
    105 int merlin16_core_pll_sequencer_restart(const phymod_core_access_t* core, uint32_t flags, phymod_sequencer_operation_t operation)
    106 {
    107     return PHYMOD_E_NONE;
    108 }
    109 
    110 /*Wait for core event*/
    111 int merlin16_core_wait_event(const phymod_core_access_t* core, phymod_core_event_t event, uint32_t timeout)
    112 {
    113     return PHYMOD_E_NONE;
    114 }
    115 
    116 /* re-tune rx path*/
    117 int merlin16_phy_rx_restart(const phymod_phy_access_t* phy)
    118 {
    119     phymod_phy_access_t phy_copy;
    120     int start_lane, num_lane, i;
    121 
    122     PHYMOD_IF_ERR_RETURN
    123         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    124     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    125 
    126     for (i = 0; i < num_lane; i++) {
    127         if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    128             continue;
    129         }
    130         phy_copy.access.lane_mask = 1 << (start_lane + i);
    131 
    132         PHYMOD_IF_ERR_RETURN(merlin16_rx_restart(&phy_copy.access, 1));
    133     }
    134     return PHYMOD_E_NONE;
    135 }
    136 
    137 /*Set phy polarity*/
    138 int merlin16_phy_polarity_set(const phymod_phy_access_t* phy, const phymod_polarity_t* polarity)
    139 {
    140     phymod_phy_access_t phy_copy;
    141     int start_lane, num_lane, i;
    142 
    143     PHYMOD_IF_ERR_RETURN
    144         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    145     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    146 
    147     for (i = 0; i < num_lane; i++) {
    148         if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    149             continue;
    150         }
    151         phy_copy.access.lane_mask = 1 << (start_lane + i);
    152 
    153         PHYMOD_IF_ERR_RETURN
    154             (merlin16_polarity_set(&phy_copy.access, polarity->tx_polarity, polarity->rx_polarity));
    155     }
    156 
    157     return PHYMOD_E_NONE;
    158 }
    159 int merlin16_phy_polarity_get(const phymod_phy_access_t* phy, phymod_polarity_t* polarity)
    160 {
    161     PHYMOD_IF_ERR_RETURN
    162         (merlin16_polarity_get(&phy->access, &polarity->tx_polarity, &polarity->rx_polarity));
    163 
    164     return PHYMOD_E_NONE;
    165 }
    166 
    167 /*Set\Get TX Parameters*/
    168 int merlin16_phy_tx_set(const phymod_phy_access_t* phy, const phymod_tx_t* tx)
    169 {
    170     phymod_phy_access_t phy_copy;
    171     int start_lane, num_lane, i;
    172 
    173     PHYMOD_IF_ERR_RETURN
    174         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    175     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    176 
    177     for (i = 0; i < num_lane; i++) {
    178         if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    179             continue;
    180         }
    181         phy_copy.access.lane_mask = 1 << (start_lane + i);
    182 
    183         PHYMOD_IF_ERR_RETURN
    184             (merlin16_apply_txfir_cfg(&phy_copy.access, (int8_t)tx->pre, (int8_t)tx->main, (int8_t)tx->post, (int8_t)tx->post2));
    185     }
    186 
    187     return PHYMOD_E_NONE;
    188 }
    189 int merlin16_phy_tx_get(const phymod_phy_access_t* phy, phymod_tx_t* tx)
    190 {
    191     int8_t value = 0;
    192 
    193     PHYMOD_IF_ERR_RETURN
    194         (merlin16_read_tx_afe(&phy->access, TX_AFE_PRE, &value));
    195     tx->pre = value;
    196     PHYMOD_IF_ERR_RETURN
    197         (merlin16_read_tx_afe(&phy->access, TX_AFE_MAIN, &value));
    198     tx->main = value;
    199     PHYMOD_IF_ERR_RETURN
    200         (merlin16_read_tx_afe(&phy->access, TX_AFE_POST1, &value));
    201     tx->post = value;
    202     PHYMOD_IF_ERR_RETURN
    203         (merlin16_read_tx_afe(&phy->access, TX_AFE_POST2, &value));
    204     tx->post2 = value;
    205 
    206     return PHYMOD_E_NONE;
    207 }
    208 
    209 /*Request for default TX parameters configuration per media type*/
    210 int merlin16_phy_media_type_tx_get(const phymod_phy_access_t* phy, phymod_media_typed_t media, phymod_tx_t* tx)
    211 {
    212     switch (media) {
    213     case phymodMediaTypeChipToChip:
    214         tx->pre   = 0x0;
    215         tx->main  = 0x32;
    216         tx->post  = 0xa;
    217         tx->post2 = 0x0;
    218         break;
    219     case phymodMediaTypeShort:
    220         tx->pre   = 0x0;
    221         tx->main  = 0x32;
    222         tx->post  = 0xa;
    223         tx->post2 = 0x0;
    224         break;
    225     case phymodMediaTypeMid:
    226         tx->pre   = 0x0;
    227         tx->main  = 0x32;
    228         tx->post  = 0xa;
    229         tx->post2 = 0x0;
    230         break;
    231     case phymodMediaTypeLong:
    232         tx->pre   = 0x0;
    233         tx->main  = 0x32;
    234         tx->post  = 0xa;
    235         tx->post2 = 0x0;
    236         break;
    237     default:
    238         tx->pre   = 0x0;
    239         tx->main  = 0x32;
    240         tx->post  = 0xa;
    241         tx->post2 = 0x0;
    242         break;
    243     }
    244 
    245     return PHYMOD_E_NONE;
    246 }
    247 
    248 
    249 /*Set\Get TX override Parameters*/
    250 int merlin16_phy_tx_override_set(const phymod_phy_access_t* phy, const phymod_tx_override_t* tx_override)
    251 {
    252     phymod_phy_access_t phy_copy;
    253     int start_lane, num_lane, i;
    254 
    255     PHYMOD_IF_ERR_RETURN
    256         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    257     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    258 
    259     for (i = 0; i < num_lane; i++) {
    260         if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    261             continue;
    262         }
    263         phy_copy.access.lane_mask = 1 << (start_lane + i);
    264 
    265         PHYMOD_IF_ERR_RETURN
    266             (merlin16_tx_pi_freq_override(&phy_copy.access,
    267                                         tx_override->phase_interpolator.enable,
    268                                         tx_override->phase_interpolator.value));
    269     }
    270 
    271     return PHYMOD_E_NONE;
    272 }
    273 int merlin16_phy_tx_override_get(const phymod_phy_access_t* phy, phymod_tx_override_t* tx_override)
    274 {
    275     return PHYMOD_E_NONE;
    276 }
    277 
    278 /*Set\Get RX Parameters*/
    279 int merlin16_phy_rx_set(const phymod_phy_access_t* phy, const phymod_rx_t* rx)
    280 {
    281     uint32_t i;
    282     phymod_phy_access_t phy_copy;
    283     int start_lane, num_lane, lane;
    284 
    285     PHYMOD_IF_ERR_RETURN
    286         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    287     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    288 
    289     /*params check*/
    290     if((rx->num_of_dfe_taps == 0) || (rx->num_of_dfe_taps < MERLIN16_NOF_DFES)){
    291         PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("illegal number of DFEs to set %u"), rx->num_of_dfe_taps));
    292     }
    293 
    294     for (lane = 0; lane < num_lane; lane++) {
    295         if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + lane)) {
    296             continue;
    297         }
    298         phy_copy.access.lane_mask = 1 << (start_lane + lane);
    299 
    300         /*vga set*/
    301         if (rx->vga.enable) {
    302             /* first stop the rx adaption */
    303             PHYMOD_IF_ERR_RETURN(merlin16_stop_rx_adaptation(&phy_copy.access, 1));
    304             PHYMOD_IF_ERR_RETURN(merlin16_write_rx_afe(&phy_copy.access, RX_AFE_VGA, rx->vga.value));
    305         } else {
    306             PHYMOD_IF_ERR_RETURN(merlin16_stop_rx_adaptation(&phy_copy.access, 0));
    307         }
    308 
    309         /*dfe set*/
    310         for (i = 0 ; i < rx->num_of_dfe_taps ; i++){
    311             if(rx->dfe[i].enable){
    312                 PHYMOD_IF_ERR_RETURN(merlin16_stop_rx_adaptation(&phy_copy.access, 1));
    313                 switch (i) {
    314                     case 0:
    315                         PHYMOD_IF_ERR_RETURN(merlin16_write_rx_afe(&phy_copy.access, RX_AFE_DFE1, rx->dfe[i].value));
    316                         break;
    317                     case 1:
    318                         PHYMOD_IF_ERR_RETURN(merlin16_write_rx_afe(&phy_copy.access, RX_AFE_DFE2, rx->dfe[i].value));
    319                         break;
    320                     case 2:
    321                         PHYMOD_IF_ERR_RETURN(merlin16_write_rx_afe(&phy_copy.access, RX_AFE_DFE3, rx->dfe[i].value));
    322                         break;
    323                     case 3:
    324                         PHYMOD_IF_ERR_RETURN(merlin16_write_rx_afe(&phy_copy.access, RX_AFE_DFE4, rx->dfe[i].value));
    325                         break;
    326                     case 4:
    327                         PHYMOD_IF_ERR_RETURN(merlin16_write_rx_afe(&phy_copy.access, RX_AFE_DFE5, rx->dfe[i].value));
    328                         break;
    329                     default:
    330                         return PHYMOD_E_PARAM;
    331                 }
    332             } else {
    333                 PHYMOD_IF_ERR_RETURN(merlin16_stop_rx_adaptation(&phy_copy.access, 0));
    334             }
    335 
    336 
    337         }
    338 
    339         /*peaking filter set*/
    340         if(rx->peaking_filter.enable){
    341             /* first stop the rx adaption */
    342             PHYMOD_IF_ERR_RETURN(merlin16_stop_rx_adaptation(&phy_copy.access, 1));
    343             PHYMOD_IF_ERR_RETURN(merlin16_write_rx_afe(&phy_copy.access, RX_AFE_PF, rx->peaking_filter.value));
    344         } else {
    345             PHYMOD_IF_ERR_RETURN(merlin16_stop_rx_adaptation(&phy_copy.access, 0));
    346         }
    347 
    348         if(rx->low_freq_peaking_filter.enable){
    349             /* first stop the rx adaption */
    350             PHYMOD_IF_ERR_RETURN(merlin16_stop_rx_adaptation(&phy_copy.access, 1));
    351             PHYMOD_IF_ERR_RETURN(merlin16_write_rx_afe(&phy_copy.access, RX_AFE_PF2, rx->low_freq_peaking_filter.value));
    352         } else {
    353             PHYMOD_IF_ERR_RETURN(merlin16_stop_rx_adaptation(&phy_copy.access, 0));
    354         }
    355     }
    356 
    357     return PHYMOD_E_NONE;
    358 }
    359 
    360 int merlin16_phy_rx_get(const phymod_phy_access_t* phy, phymod_rx_t* rx)
    361 {
    362     int8_t val;
    363 
    364     PHYMOD_IF_ERR_RETURN
    365         (merlin16_read_rx_afe(&phy->access, RX_AFE_PF, &val));
    366     rx->peaking_filter.value = val;
    367 
    368     PHYMOD_IF_ERR_RETURN
    369         (merlin16_read_rx_afe(&phy->access, RX_AFE_PF2, &val));
    370     rx->low_freq_peaking_filter.value = val;
    371 
    372     PHYMOD_IF_ERR_RETURN
    373         (merlin16_read_rx_afe(&phy->access, RX_AFE_VGA, &val));
    374     rx->vga.value = val;
    375 
    376     PHYMOD_IF_ERR_RETURN
    377         (merlin16_read_rx_afe(&phy->access, RX_AFE_DFE1, &val));
    378     rx->dfe[0].value = val;
    379 
    380     PHYMOD_IF_ERR_RETURN
    381         (merlin16_read_rx_afe(&phy->access, RX_AFE_DFE2, &val));
    382     rx->dfe[1].value = val;
    383 
    384     PHYMOD_IF_ERR_RETURN
    385         (merlin16_read_rx_afe(&phy->access, RX_AFE_DFE3, &val));
    386     rx->dfe[2].value = val;
    387 
    388     PHYMOD_IF_ERR_RETURN
    389         (merlin16_read_rx_afe(&phy->access, RX_AFE_DFE4, &val));
    390     rx->dfe[3].value = val;
    391 
    392     PHYMOD_IF_ERR_RETURN
    393         (merlin16_read_rx_afe(&phy->access, RX_AFE_DFE5, &val));
    394     rx->dfe[4].value = val;
    395 
    396     rx->num_of_dfe_taps = 5;
    397     rx->dfe[0].enable = 1;
    398     rx->dfe[1].enable = 1;
    399     rx->dfe[2].enable = 1;
    400     rx->dfe[3].enable = 1;
    401     rx->dfe[4].enable = 1;
    402     rx->vga.enable = 1;
    403     rx->low_freq_peaking_filter.enable = 1;
    404     rx->peaking_filter.enable = 1;
    405 
    406     return PHYMOD_E_NONE;
    407 }
    408 
    409 
    410 /*Reset phy*/
    411 int merlin16_phy_reset_set(const phymod_phy_access_t* phy, const phymod_phy_reset_t* reset)
    412 {
    413     uint32_t rst, rst_rx, rst_tx;
    414     int start_lane, num_lane, i;
    415     phymod_phy_access_t phy_copy;
    416 
    417     PHYMOD_IF_ERR_RETURN
    418         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    419     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    420 
    421     if (reset->rx == reset->tx) {
    422         PHYMOD_IF_ERR_RETURN(merlin16_tx_lane_soft_reset_release_get(&phy_copy.access, &rst_tx));
    423         PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_soft_reset_release_get(&phy_copy.access, &rst_rx));
    424         for (i = 0; i < num_lane; i++) {
    425             if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    426                 continue;
    427             }
    428             phy_copy.access.lane_mask = 1 << (start_lane + i);
    429             /*If tx is in reset, release tx lane*/
    430             if (rst_tx == 0) {
    431                 PHYMOD_IF_ERR_RETURN(merlin16_tx_lane_soft_reset_release(&phy_copy.access, 1));
    432                 PHYMOD_USLEEP(10);
    433             }
    434             /*If rx is in reset, release rx lane*/
    435             if (rst_rx == 0) {
    436                 PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_soft_reset_release(&phy_copy.access, 1));
    437                 PHYMOD_USLEEP(10);
    438             }
    439             switch (reset->tx) {
    440                 case phymodResetDirectionIn:
    441                     PHYMOD_IF_ERR_RETURN(merlin16_lane_soft_reset_release(&phy_copy.access, 0));
    442                     break;
    443                 case phymodResetDirectionOut:
    444                     PHYMOD_IF_ERR_RETURN(merlin16_lane_soft_reset_release(&phy_copy.access, 1));
    445                     break;
    446                 case phymodResetDirectionInOut:
    447                     PHYMOD_IF_ERR_RETURN(merlin16_lane_soft_reset_release(&phy_copy.access, 0));
    448                     PHYMOD_USLEEP(10);
    449                     PHYMOD_IF_ERR_RETURN(merlin16_lane_soft_reset_release(&phy_copy.access, 1));
    450                     break;
    451                 default:
    452                     break;
    453             }
    454         }
    455     } else {
    456         PHYMOD_IF_ERR_RETURN(merlin16_lane_soft_reset_release_get(&phy->access, &rst));
    457         for (i = 0; i < num_lane; i++) {
    458             if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    459                 continue;
    460             }
    461             phy_copy.access.lane_mask = 1 << (start_lane + i);
    462             /*If ln_rst is is in reset , release ln_rst first*/
    463             if (rst == 0) {
    464                 PHYMOD_IF_ERR_RETURN(merlin16_lane_soft_reset_release(&phy_copy.access, 1));
    465                 PHYMOD_USLEEP(10);
    466             }
    467             switch (reset->tx) {
    468                 case phymodResetDirectionIn:
    469                     PHYMOD_IF_ERR_RETURN(merlin16_tx_lane_soft_reset_release(&phy_copy.access, 0));
    470                     break;
    471                 case phymodResetDirectionOut:
    472                     PHYMOD_IF_ERR_RETURN(merlin16_tx_lane_soft_reset_release(&phy_copy.access, 1));
    473                     break;
    474                 case phymodResetDirectionInOut:
    475                     PHYMOD_IF_ERR_RETURN(merlin16_tx_lane_soft_reset_release(&phy_copy.access, 0));
    476                     PHYMOD_USLEEP(10);
    477                     PHYMOD_IF_ERR_RETURN(merlin16_tx_lane_soft_reset_release(&phy_copy.access, 1));
    478                     break;
    479                 default:
    480                     break;
    481             }
    482             switch (reset ->rx) {
    483                 case phymodResetDirectionIn:
    484                     PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_soft_reset_release(&phy_copy.access, 0));
    485                     break;
    486                 case phymodResetDirectionOut:
    487                     PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_soft_reset_release(&phy_copy.access, 1));
    488                     break;
    489                 case phymodResetDirectionInOut:
    490                     PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_soft_reset_release(&phy_copy.access, 0));
    491                     PHYMOD_USLEEP(10);
    492                     PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_soft_reset_release(&phy_copy.access, 1));
    493                     break;
    494                 default:
    495                     break;
    496             }
    497         }
    498     }
    499 
    500     return PHYMOD_E_NONE;
    501 }
    502 
    503 
    504 int merlin16_phy_reset_get(const phymod_phy_access_t* phy, phymod_phy_reset_t* reset)
    505 {
    506     uint32_t rst, rst_rx, rst_tx;
    507     PHYMOD_IF_ERR_RETURN(merlin16_lane_soft_reset_release_get(&phy->access, &rst));
    508     if(rst == 0) {
    509        reset->tx = phymodResetDirectionIn;
    510        reset->rx = phymodResetDirectionIn;
    511     } else {
    512        PHYMOD_IF_ERR_RETURN(merlin16_tx_lane_soft_reset_release_get(&phy->access, &rst_tx));
    513        PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_soft_reset_release_get(&phy->access, &rst_rx));
    514        if (rst_tx == 0) {
    515            reset->tx = phymodResetDirectionIn;
    516        } else {
    517            reset->tx = phymodResetDirectionOut;
    518        }
    519 
    520        if(rst_rx == 0) {
    521            reset->rx = phymodResetDirectionIn;
    522        } else {
    523            reset->rx = phymodResetDirectionOut;
    524        }
    525     }
    526 
    527     return PHYMOD_E_NONE;
    528 }
    529 
    530 
    531 /*Control phy power*/
    532 int merlin16_phy_power_set(const phymod_phy_access_t* phy, const phymod_phy_power_t* power)
    533 {
    534     enum srds_core_pwrdn_mode_enum mode;
    535     phymod_phy_access_t phy_copy;
    536     int start_lane, num_lane, i;
    537 
    538     PHYMOD_IF_ERR_RETURN
    539         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    540     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    541 
    542     for (i = 0; i < num_lane; i++) {
    543         if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    544             continue;
    545         }
    546         phy_copy.access.lane_mask = 1 << (start_lane + i);
    547 
    548         if ((power->tx == phymodPowerOff) && (power->rx == phymodPowerNoChange)) {
    549                 /*disable tx on the PMD side */
    550                 mode = PWRDN_TX;
    551                 PHYMOD_IF_ERR_RETURN(merlin16_lane_pwrdn(&phy_copy.access, mode));
    552         }
    553         if ((power->tx == phymodPowerOn) && (power->rx == phymodPowerNoChange)) {
    554                 /*enable tx on the PMD side */
    555                 PHYMOD_IF_ERR_RETURN(merlin16_pwrdn_set(&phy_copy.access, 1, 0));
    556         }
    557         if ((power->tx == phymodPowerNoChange) && (power->rx == phymodPowerOff)) {
    558                 /*disable rx on the PMD side */
    559                 mode = PWRDN_RX;
    560                 PHYMOD_IF_ERR_RETURN(merlin16_lane_pwrdn(&phy_copy.access, mode));
    561         }
    562         if ((power->tx == phymodPowerNoChange) && (power->rx == phymodPowerOn)) {
    563                 PHYMOD_IF_ERR_RETURN(merlin16_pwrdn_set(&phy_copy.access, 0, 0));
    564                 /*enable rx on the PMD side */
    565         }
    566         if ((power->tx == phymodPowerOn) && (power->rx == phymodPowerOn)) {
    567                 mode = PWR_ON;
    568                 PHYMOD_IF_ERR_RETURN(merlin16_lane_pwrdn(&phy_copy.access, mode));
    569         }
    570         if ((power->tx == phymodPowerOff) && (power->rx == phymodPowerOff)) {
    571                 /* Both Tx and Rx power down */
    572                 mode = PWRDN;
    573                 PHYMOD_IF_ERR_RETURN(merlin16_lane_pwrdn(&phy_copy.access, mode));
    574         }
    575     }
    576     return PHYMOD_E_NONE;
    577 }
    578 
    579 
    580 int merlin16_phy_power_get(const phymod_phy_access_t* phy, phymod_phy_power_t* power)
    581 {
    582     power_status_t pwrdn;
    583     PHYMOD_IF_ERR_RETURN(merlin16_pwrdn_get(&phy->access, &pwrdn));
    584     power->rx = (pwrdn.rx_s_pwrdn == 0)? phymodPowerOn: phymodPowerOff;
    585     power->tx = (pwrdn.tx_s_pwrdn == 0)? phymodPowerOn: phymodPowerOff;
    586     return PHYMOD_E_NONE;
    587 }
    588 
    589 /*TX transmission control*/
    590 int merlin16_phy_tx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t tx_control)
    591 {
    592     phymod_phy_access_t phy_copy;
    593     int start_lane, num_lane, i;
    594 
    595     PHYMOD_IF_ERR_RETURN
    596         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    597     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    598 
    599     switch (tx_control)
    600     {
    601         case phymodTxSquelchOn:
    602             for (i = 0; i < num_lane; i++) {
    603                 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    604                     continue;
    605                 }
    606                 phy_copy.access.lane_mask = 1 << (start_lane + i);
    607                 PHYMOD_IF_ERR_RETURN(merlin16_tx_disable(&phy_copy.access, 1));
    608             }
    609             break;
    610         case phymodTxSquelchOff:
    611             for (i = 0; i < num_lane; i++) {
    612                 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    613                     continue;
    614                 }
    615                 phy_copy.access.lane_mask = 1 << (start_lane + i);
    616                 PHYMOD_IF_ERR_RETURN(merlin16_tx_disable(&phy_copy.access, 0));
    617             }
    618             break;
    619         default:
    620             PHYMOD_DEBUG_ERROR(("This control is NOT SUPPORTED!! (eagle_phy_tx_lane_control_set) \n"));
    621             break;
    622     }
    623 
    624     return PHYMOD_E_NONE;
    625 
    626 }
    627 
    628 int merlin16_phy_tx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_tx_lane_control_t* tx_control)
    629 {
    630     uint32_t enable;
    631 
    632     PHYMOD_IF_ERR_RETURN(merlin16_tx_disable_get(&phy->access, &enable));
    633 
    634     if(enable){
    635       *tx_control = phymodTxSquelchOn;
    636     } else {
    637       *tx_control = phymodTxSquelchOff;
    638     }
    639 
    640     return PHYMOD_E_NONE;
    641 
    642 }
    643 
    644 /*Rx control*/
    645 int merlin16_phy_rx_lane_control_set(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t rx_control)
    646 {
    647     phymod_phy_access_t phy_copy;
    648     int start_lane, num_lane, i;
    649 
    650     PHYMOD_IF_ERR_RETURN
    651         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    652     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    653 
    654     switch (rx_control)
    655     {
    656         case phymodRxSquelchOn:
    657             for (i = 0; i < num_lane; i++) {
    658                 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    659                     continue;
    660                 }
    661                 phy_copy.access.lane_mask = 1 << (start_lane + i);
    662                 PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_control_set(&phy_copy.access, 1));
    663             }
    664             break;
    665         case phymodRxSquelchOff:
    666             for (i = 0; i < num_lane; i++) {
    667                 if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    668                     continue;
    669                 }
    670                 phy_copy.access.lane_mask = 1 << (start_lane + i);
    671                 PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_control_set(&phy_copy.access, 0));
    672             }
    673             break;
    674         default:
    675             PHYMOD_DEBUG_ERROR(("This control is NOT SUPPORTED!! (eagle_phy_rx_lane_control_set) \n"));
    676             break;
    677     }
    678 
    679     return PHYMOD_E_NONE;
    680 }
    681 
    682 
    683 int merlin16_phy_rx_lane_control_get(const phymod_phy_access_t* phy, phymod_phy_rx_lane_control_t* rx_control)
    684 {
    685 
    686     uint32_t enable;
    687 
    688     PHYMOD_IF_ERR_RETURN(merlin16_rx_lane_control_get(&phy->access, &enable));
    689 
    690     if(enable){
    691       *rx_control = phymodRxSquelchOn;
    692     } else {
    693       *rx_control = phymodRxSquelchOff;
    694     }
    695 
    696     return PHYMOD_E_NONE;
    697 
    698 }
    699 
    700 int merlin16_phy_firmware_core_config_set(const phymod_phy_access_t* phy, phymod_firmware_core_config_t fw_config)
    701 {
    702     struct merlin16_uc_core_config_st serdes_firmware_core_config;
    703     PHYMOD_MEMSET(&serdes_firmware_core_config, 0, sizeof(serdes_firmware_core_config));
    704     serdes_firmware_core_config.field.core_cfg_from_pcs = fw_config.CoreConfigFromPCS;
    705     serdes_firmware_core_config.field.vco_rate = fw_config.VcoRate;
    706 
    707     PHYMOD_IF_ERR_RETURN(merlin16_INTERNAL_set_uc_core_config(&phy->access, serdes_firmware_core_config));
    708     return PHYMOD_E_NONE;
    709 }
    710 
    711 int merlin16_phy_firmware_core_config_get(const phymod_phy_access_t* phy, phymod_firmware_core_config_t* fw_config)
    712 {
    713     struct merlin16_uc_core_config_st serdes_firmware_core_config;
    714     PHYMOD_IF_ERR_RETURN(merlin16_get_uc_core_config(&phy->access, &serdes_firmware_core_config));
    715     PHYMOD_MEMSET(fw_config, 0, sizeof(*fw_config));
    716     fw_config->CoreConfigFromPCS = serdes_firmware_core_config.field.core_cfg_from_pcs;
    717     fw_config->VcoRate = serdes_firmware_core_config.field.vco_rate;
    718     return PHYMOD_E_NONE;
    719 }
    720 
    721 int merlin16_phy_firmware_lane_config_get(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t* fw_config)
    722 {
    723     struct merlin16_uc_lane_config_st serdes_firmware_config;
    724     PHYMOD_MEMSET(&serdes_firmware_config, 0x0, sizeof(serdes_firmware_config));
    725 
    726     PHYMOD_IF_ERR_RETURN(merlin16_get_uc_lane_cfg(&phy->access, &serdes_firmware_config));
    727     PHYMOD_MEMSET(fw_config, 0, sizeof(*fw_config));
    728     fw_config->LaneConfigFromPCS = serdes_firmware_config.field.lane_cfg_from_pcs;
    729     fw_config->AnEnabled         = serdes_firmware_config.field.an_enabled;
    730     fw_config->DfeOn             = serdes_firmware_config.field.dfe_on;
    731     fw_config->ForceBrDfe        = serdes_firmware_config.field.force_brdfe_on;
    732     fw_config->Cl72AutoPolEn     = serdes_firmware_config.field.cl72_auto_polarity_en;
    733     fw_config->Cl72RestTO        = serdes_firmware_config.field.cl72_restart_timeout_en;
    734     fw_config->ScramblingDisable = serdes_firmware_config.field.scrambling_dis;
    735     fw_config->UnreliableLos     = serdes_firmware_config.field.unreliable_los;
    736     fw_config->MediaType         = serdes_firmware_config.field.media_type;
    737     fw_config->Cl72AutoPolEn     = serdes_firmware_config.field.cl72_auto_polarity_en;
    738     fw_config->Cl72RestTO        = serdes_firmware_config.field.cl72_restart_timeout_en;
    739 
    740     return PHYMOD_E_NONE;
    741 }
    742 
    743 STATIC
    744 int _merlin16_phy_firmware_lane_config_set(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t fw_config)
    745 {
    746     struct merlin16_uc_lane_config_st serdes_firmware_config;
    747     phymod_phy_access_t phy_copy;
    748     int start_lane, num_lane, i;
    749     /* uint32_t rst_status; */
    750     uint32_t is_warm_boot;
    751 
    752     PHYMOD_MEMSET(&serdes_firmware_config, 0x0, sizeof(serdes_firmware_config));
    753     PHYMOD_IF_ERR_RETURN
    754         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    755     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    756 
    757     for (i = 0; i < num_lane; i++) {
    758         if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    759             continue;
    760         }
    761         phy_copy.access.lane_mask = 1 << (start_lane + i);
    762         serdes_firmware_config.field.lane_cfg_from_pcs = fw_config.LaneConfigFromPCS;
    763         serdes_firmware_config.field.an_enabled        = fw_config.AnEnabled;
    764         serdes_firmware_config.field.dfe_on            = fw_config.DfeOn;
    765         serdes_firmware_config.field.force_brdfe_on    = fw_config.ForceBrDfe;
    766         /* serdes_firmware_config.field.cl72_emulation_en = fw_config.Cl72Enable; */
    767         serdes_firmware_config.field.scrambling_dis    = fw_config.ScramblingDisable;
    768         serdes_firmware_config.field.unreliable_los    = fw_config.UnreliableLos;
    769         serdes_firmware_config.field.media_type        = fw_config.MediaType;
    770         serdes_firmware_config.field.cl72_auto_polarity_en   = fw_config.Cl72AutoPolEn;
    771         serdes_firmware_config.field.cl72_restart_timeout_en = fw_config.Cl72RestTO;
    772 
    773         PHYMOD_IF_ERR_RETURN(PHYMOD_IS_WRITE_DISABLED(&phy_copy.access, &is_warm_boot));
    774 
    775         if (!is_warm_boot) {
    776             /* PHYMOD_IF_ERR_RETURN(merlin16_lane_soft_reset_read(&phy_copy.access, &rst_status)); */
    777             /* if (rst_status) */ PHYMOD_IF_ERR_RETURN (merlin16_lane_soft_reset_release(&phy_copy.access, 0));
    778             PHYMOD_IF_ERR_RETURN(merlin16_set_uc_lane_cfg(&phy_copy.access, serdes_firmware_config));
    779             /* if (rst_status) */ PHYMOD_IF_ERR_RETURN (merlin16_lane_soft_reset_release(&phy_copy.access, 1));
    780         }
    781     }
    782 
    783     return PHYMOD_E_NONE;
    784 }
    785 
    786 int merlin16_phy_firmware_lane_config_set(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t fw_config)
    787 {
    788     phymod_phy_access_t phy_copy;
    789     int start_lane, num_lane, i;
    790 
    791     PHYMOD_IF_ERR_RETURN
    792         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    793     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
    794 
    795     /*Hold the per lne soft reset bit*/
    796     for (i = 0; i < num_lane; i++) {
    797         if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    798             continue;
    799         }
    800         phy_copy.access.lane_mask = 1 << (start_lane + i);
    801         PHYMOD_IF_ERR_RETURN
    802             (merlin16_lane_soft_reset_release(&phy_copy.access, 0));
    803     }
    804 
    805     PHYMOD_IF_ERR_RETURN
    806          (_merlin16_phy_firmware_lane_config_set(phy, fw_config));
    807     /*Hold the per lne soft reset bit*/
    808     for (i = 0; i < num_lane; i++) {
    809         if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    810             continue;
    811         }
    812         phy_copy.access.lane_mask = 1 << (start_lane + i);
    813         PHYMOD_IF_ERR_RETURN
    814             (merlin16_lane_soft_reset_release(&phy_copy.access, 1));
    815     }
    816 
    817     return PHYMOD_E_NONE;
    818 }
    819 
    820 
    821 /*Set the interface mode, speed and other configuration related to interface.*/
    822 int merlin16_phy_interface_config_set(const phymod_phy_access_t* phy, uint32_t flags, const phymod_phy_inf_config_t* config)
    823 {
    824     uint32_t new_pll_div;
    825     int16_t  new_os_mode = 0;
    826     phymod_phy_access_t pm_phy_copy;
    827     int start_lane=0, num_lane, i;
    828     uint32_t current_pll_div;
    829     phymod_firmware_lane_config_t firmware_lane_config;
    830     enum merlin16_pll_refclk_enum refclk = MERLIN16_PLL_REFCLK_156P25MHZ;
    831 
    832 #ifdef PHYMOD_DIAG
    833     const phymod_access_t *pm_acc;
    834     pm_acc = &phy->access;
    835     PHYMOD_VDBG(DBG_SPD, pm_acc, ("%-22s: p=%p adr=%0"PRIx32" lmask=%0"PRIx32" speed=%0d intf=%0d(%s) flags=%0x\n",
    836       __func__, (void *)pm_acc, pm_acc->addr, pm_acc->lane_mask, config->data_rate, config->interface_type,
    837                                   phymod_interface_t_mapping[config->interface_type].key, flags));
    838 #endif
    839 
    840     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
    841     PHYMOD_MEMSET(&firmware_lane_config, 0x0, sizeof(firmware_lane_config));
    842 
    843     /* end of special mode */
    844     firmware_lane_config.MediaType = 0;
    845 
    846     /* next program the tx fir taps and driver current based on the input */
    847     PHYMOD_IF_ERR_RETURN
    848         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
    849 
    850 
    851     /* Hold the per lne soft reset bit */
    852     for (i = 0; i < num_lane; i++) {
    853         if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    854             continue;
    855         }
    856         pm_phy_copy.access.lane_mask = 1 << (start_lane + i);
    857         PHYMOD_IF_ERR_RETURN
    858             (merlin16_lane_soft_reset_release(&pm_phy_copy.access, 0));
    859     }
    860 
    861     pm_phy_copy.access.lane_mask = 0x1 << start_lane;
    862     PHYMOD_IF_ERR_RETURN
    863         (merlin16_phy_firmware_lane_config_get(&pm_phy_copy, &firmware_lane_config));
    864 
    865     firmware_lane_config.AnEnabled = 0;
    866     firmware_lane_config.LaneConfigFromPCS = 0;
    867     firmware_lane_config.DfeOn = 1;
    868     firmware_lane_config.LpDfeOn = 0;
    869     firmware_lane_config.Cl72RestTO = 1;
    870     if (config->data_rate < 10000) {
    871         firmware_lane_config.DfeOn = 0;
    872     }
    873     if (PHYMOD_INTF_MODES_FIBER_GET(config)) {
    874         firmware_lane_config.MediaType = phymodFirmwareMediaTypeOptics;
    875     } else if (PHYMOD_INTF_MODES_COPPER_GET(config)) {
    876         firmware_lane_config.MediaType = phymodFirmwareMediaTypeCopperCable;
    877     } else {
    878         firmware_lane_config.MediaType = phymodFirmwareMediaTypePcbTraceBackPlane;
    879     }
    880 
    881     /* get the current PLL setting */
    882     pm_phy_copy.access.lane_mask = 1 << start_lane;
    883     PHYMOD_IF_ERR_RETURN
    884         (merlin16_INTERNAL_read_pll_div(&pm_phy_copy.access, &current_pll_div));
    885 
    886     /*Get new pll div through ref_clk and data rate*/
    887     PHYMOD_IF_ERR_RETURN
    888         (merlin16_get_pll_vco_osmode(config, &new_pll_div, &new_os_mode));
    889 
    890     /* if pll change is enabled. new_pll_div is the reg vector value */
    891     if ((current_pll_div != new_pll_div) && (PHYMOD_INTF_F_DONT_TURN_OFF_PLL & flags)) {
    892         PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG,
    893                                (_PHYMOD_MSG("pll has to change for speed_set from %u to %u but DONT_TURN_OFF_PLL flag is enabled"),
    894                                  (unsigned int)current_pll_div, (unsigned int)new_pll_div));
    895     }
    896 
    897     /* pll switch is required and expected */
    898     if((current_pll_div != new_pll_div) && !(PHYMOD_INTF_F_DONT_TURN_OFF_PLL & flags)) {
    899         PHYMOD_IF_ERR_RETURN
    900             (merlin16_core_soft_reset_release(&pm_phy_copy.access, 0));
    901 
    902         switch (config->ref_clock) {
    903             case phymodRefClk156Mhz:
    904                  refclk = MERLIN16_PLL_REFCLK_156P25MHZ;
    905                  break;
    906             case phymodRefClk125Mhz:
    907                  refclk = MERLIN16_PLL_REFCLK_125MHZ;
    908                  break;
    909             case phymodRefClk161Mhz:
    910                  refclk = MERLIN16_PLL_REFCLK_161P1328125MHZ;
    911                  break;
    912             default:
    913                  refclk = MERLIN16_PLL_REFCLK_156P25MHZ;
    914                  break;
    915         }
    916         /* set the PLL divider */
    917         PHYMOD_IF_ERR_RETURN
    918             (merlin16_configure_pll_refclk_div(&pm_phy_copy.access, refclk, new_pll_div));
    919 
    920         PHYMOD_IF_ERR_RETURN
    921             (merlin16_core_soft_reset_release(&pm_phy_copy.access, 1));
    922     }
    923 
    924     /*Set os mode*/
    925     for (i = 0; i < num_lane; i++) {
    926         if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    927             continue;
    928         }
    929         pm_phy_copy.access.lane_mask = 0x1 << (start_lane + i);
    930         PHYMOD_IF_ERR_RETURN
    931              (merlin16_osmode_set(&pm_phy_copy.access, new_os_mode));
    932     }
    933 
    934     for (i = 0; i < num_lane; i++) {
    935         if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    936             continue;
    937         }
    938         pm_phy_copy.access.lane_mask = 0x1 << (start_lane + i);
    939         PHYMOD_IF_ERR_RETURN
    940              (_merlin16_phy_firmware_lane_config_set(&pm_phy_copy, firmware_lane_config));
    941     }
    942 
    943     /* release the per lne soft reset bit */
    944     for (i = 0; i < num_lane; i++) {
    945         if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
    946             continue;
    947         }
    948         pm_phy_copy.access.lane_mask = 1 << (start_lane + i);
    949         PHYMOD_IF_ERR_RETURN
    950             (merlin16_lane_soft_reset_release(&pm_phy_copy.access, 1));
    951     }
    952 
    953     return PHYMOD_E_NONE;
    954 }
    955 
    956 STATIC
    957 int _merlin16_pll_multiplier_get(uint32_t pll_div, uint32_t *pll_multiplier)
    958 {
    959     switch (pll_div) {
    960         case MERLIN16_PLL_DIV_70: *pll_multiplier = 70;
    961             break;
    962         case MERLIN16_PLL_DIV_66: *pll_multiplier = 66;
    963             break;
    964         case MERLIN16_PLL_DIV_64: *pll_multiplier = 64;
    965             break;
    966         case MERLIN16_PLL_DIV_60: *pll_multiplier = 60;
    967             break;
    968         case MERLIN16_PLL_DIV_92: *pll_multiplier = 92;
    969             break;
    970         case MERLIN16_PLL_DIV_80: *pll_multiplier = 80;
    971             break;
    972         case MERLIN16_PLL_DIV_54P4: *pll_multiplier = 54.4;
    973             break;
    974         default: return PHYMOD_E_NONE;
    975             break;
    976     }
    977     return PHYMOD_E_NONE;
    978 }
    979 
    980 STATIC
    981 int _merlin16_actual_osr_get(int16_t osr_mode, int* actual_os)
    982 {
    983     switch(osr_mode) {
    984         case 0: *actual_os = 1; break;
    985         case 1: *actual_os = 2; break;
    986         case 2: *actual_os = 3; break;
    987         case 4: *actual_os = 4; break;
    988         case 5: *actual_os = 5; break;
    989         case 7: *actual_os = 8; break;
    990         case 8: *actual_os = 8 + 1/4; break;
    991         case 9: *actual_os = 10; break;
    992         default:
    993             PHYMOD_RETURN_WITH_ERR(PHYMOD_E_INTERNAL, (_PHYMOD_MSG("unsupported OS mode %d"), osr_mode));
    994     }
    995     return PHYMOD_E_NONE;
    996 }
    997 
    998 
    999 int merlin16_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)
   1000 {
   1001     int osr_mode;
   1002     uint32_t pll_div;
   1003     uint32_t pll_multiplier = 1, refclk;
   1004     phymod_phy_access_t phy_copy;
   1005     int actual_osr;
   1006 
   1007     config->ref_clock = ref_clock;
   1008 
   1009     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1010     phy_copy.access.lane_mask = 0x1;
   1011 
   1012     PHYMOD_IF_ERR_RETURN
   1013         (merlin16_osr_mode_get(&phy->access, &osr_mode));
   1014     PHYMOD_IF_ERR_RETURN
   1015         (merlin16_INTERNAL_read_pll_div(&phy_copy.access, &pll_div));
   1016     PHYMOD_IF_ERR_RETURN
   1017         (_merlin16_pll_multiplier_get(pll_div, &pll_multiplier));
   1018 
   1019     if (ref_clock == phymodRefClk156Mhz) {
   1020         refclk = 15625;
   1021     } else if (ref_clock == phymodRefClk125Mhz) {
   1022         refclk = 12500;
   1023     } else {
   1024         PHYMOD_RETURN_WITH_ERR(PHYMOD_E_INTERNAL,  (_PHYMOD_MSG("Unknown refclk")));
   1025     }
   1026 
   1027     PHYMOD_IF_ERR_RETURN(_merlin16_actual_osr_get(osr_mode, &actual_osr));
   1028 
   1029     config->data_rate = (refclk*pll_multiplier)/(100*actual_osr);
   1030     config->interface_type = phymodInterfaceBypass;
   1031 
   1032     if(osr_mode == 1) {
   1033         PHYMOD_INTF_MODES_OS2_SET(config);
   1034     }
   1035 
   1036     return PHYMOD_E_NONE;
   1037 }
   1038 
   1039 
   1040 /*Set\Get CL72*/
   1041 int merlin16_phy_cl72_set(const phymod_phy_access_t* phy, uint32_t cl72_en)
   1042 {
   1043     struct merlin16_uc_lane_config_st serdes_firmware_config;
   1044     phymod_phy_access_t phy_copy;
   1045     int start_lane, num_lane, i;
   1046 #ifdef PHYMOD_DIAG
   1047     const phymod_access_t *pm_acc;
   1048 #endif    
   1049 
   1050     PHYMOD_IF_ERR_RETURN
   1051         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
   1052     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1053 
   1054 #ifdef PHYMOD_DIAG
   1055     pm_acc = &phy->access;
   1056     PHYMOD_VDBG(DBG_CL72, pm_acc, ("%-22s: p=%p adr=%0"PRIx32" lmask=%0"PRIx32" cl72_en=%d\n",
   1057                 __func__, (void *)pm_acc, pm_acc->addr, pm_acc->lane_mask, (int)cl72_en));
   1058 #endif
   1059 
   1060     PHYMOD_IF_ERR_RETURN(merlin16_get_uc_lane_cfg(&phy->access, &serdes_firmware_config));
   1061 
   1062     if (serdes_firmware_config.field.dfe_on == 0) {
   1063       PHYMOD_DEBUG_ERROR(("ERROR :: DFE is off : Can not start CL72 with no DFE\n"));
   1064       return PHYMOD_E_CONFIG;
   1065     }
   1066 
   1067     for (i = 0; i < num_lane; i++) {
   1068         if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
   1069             continue;
   1070         }
   1071         phy_copy.access.lane_mask = 1 << (start_lane + i);
   1072         PHYMOD_IF_ERR_RETURN
   1073             (merlin16_clause72_control(&phy_copy.access, cl72_en));
   1074     }
   1075     return PHYMOD_E_NONE;
   1076 }
   1077 
   1078 int merlin16_phy_cl72_get(const phymod_phy_access_t* phy, uint32_t* cl72_en)
   1079 {
   1080     uint32_t local_en;;
   1081     PHYMOD_IF_ERR_RETURN
   1082         (merlin16_pmd_cl72_enable_get(&phy->access, &local_en));
   1083     *cl72_en = local_en;
   1084     return PHYMOD_E_NONE;
   1085 }
   1086 
   1087 
   1088 /*Get CL72 status*/
   1089 int merlin16_phy_cl72_status_get(const phymod_phy_access_t* phy, phymod_cl72_status_t* status)
   1090 {
   1091     uint32_t local_status;
   1092     PHYMOD_IF_ERR_RETURN
   1093         (merlin16_pmd_cl72_receiver_status(&phy->access, &local_status));
   1094     status->locked = local_status;
   1095     return PHYMOD_E_NONE;
   1096 }
   1097 
   1098 /*Set\Get autoneg*/
   1099 int merlin16_phy_autoneg_ability_set(const phymod_phy_access_t* phy, const phymod_autoneg_ability_t* an_ability_set_type)
   1100 {
   1101     /* Not supported */
   1102     PHYMOD_DEBUG_ERROR(("This function is NOT SUPPORTED!! (merlin16_phy_autoneg_ability_set) \n"));
   1103     return PHYMOD_E_NONE;
   1104 
   1105 }
   1106 int merlin16_phy_autoneg_ability_get(const phymod_phy_access_t* phy, phymod_autoneg_ability_t* an_ability_get_type)
   1107 {
   1108     /* Not supported */
   1109     PHYMOD_DEBUG_ERROR(("This function is NOT SUPPORTED!! (merlin16_phy_autoneg_ability_get) \n"));
   1110 
   1111     return PHYMOD_E_NONE;
   1112 }
   1113 
   1114 /*Set\Get autoneg*/
   1115 int merlin16_phy_autoneg_set(const phymod_phy_access_t* phy, const phymod_autoneg_control_t* an)
   1116 {
   1117     /* Not supported */
   1118     PHYMOD_DEBUG_ERROR(("This function is NOT SUPPORTED!! (merlin16_phy_autoneg_set) \n"));
   1119 
   1120     return PHYMOD_E_NONE;
   1121 }
   1122 int merlin16_phy_autoneg_get(const phymod_phy_access_t* phy, phymod_autoneg_control_t* an, uint32_t* an_done)
   1123 {
   1124     /* Not supported */
   1125     PHYMOD_DEBUG_ERROR(("This function is NOT SUPPORTED!! (merlin16_phy_autoneg_get) \n"));
   1126 
   1127     return PHYMOD_E_NONE;
   1128 }
   1129 
   1130 /*Get Autoneg status*/
   1131 int merlin16_phy_autoneg_status_get(const phymod_phy_access_t* phy, phymod_autoneg_status_t* status)
   1132 {
   1133     /* Not supported */
   1134     PHYMOD_DEBUG_ERROR(("This function is NOT SUPPORTED!! (merlin16_phy_autoneg_status_get) \n"));
   1135 
   1136     return PHYMOD_E_NONE;
   1137 }
   1138 
   1139 /* load tsce fw. the fw_loader parameter is valid just for external fw load */
   1140 STATIC
   1141 int _merlin16_core_firmware_load(const phymod_core_access_t* core, phymod_firmware_load_method_t load_method, phymod_firmware_loader_f fw_loader)
   1142 {
   1143 #ifdef PHYMOD_DIAG
   1144     const phymod_access_t *pm_acc;
   1145     pm_acc = &core->access;
   1146     PHYMOD_VDBG(DBG_CFG, pm_acc,
   1147        ("%-22s: p=%p adr=%0"PRIx32" lmask=%0"PRIx32" load_meth=%0d",
   1148         __func__, (void *)pm_acc, pm_acc->addr, pm_acc->lane_mask, (int)load_method));
   1149 #endif
   1150 
   1151     switch (load_method) {
   1152     case phymodFirmwareLoadMethodInternal:
   1153         PHYMOD_IF_ERR_RETURN(merlin16_ucode_mdio_load(&core->access, merlin16_ucode, merlin16_ucode_len));
   1154         break;
   1155     case phymodFirmwareLoadMethodExternal:
   1156         PHYMOD_NULL_CHECK(fw_loader);
   1157         PHYMOD_IF_ERR_RETURN(merlin16_ucode_pram_load_pre(&core->access));
   1158         PHYMOD_IF_ERR_RETURN(fw_loader(core, merlin16_ucode_len, merlin16_ucode));
   1159         PHYMOD_IF_ERR_RETURN(merlin16_ucode_pram_load_post(&core->access));
   1160         break;
   1161     case phymodFirmwareLoadMethodNone:
   1162         break;
   1163     default:
   1164         PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("illegal fw load method %u"), load_method));
   1165     }
   1166     return PHYMOD_E_NONE;
   1167 }
   1168 
   1169 STATIC
   1170 int _merlin16_core_init_pass1(const phymod_core_access_t* core,
   1171                           const phymod_core_init_config_t* init_config,
   1172                           const phymod_core_status_t* core_status)
   1173 {
   1174     phymod_phy_access_t phy_access, phy_access_copy;
   1175     phymod_core_access_t  core_copy;
   1176     uint32_t  uc_active = 0;
   1177     int i, start_lane, num_lane;
   1178 
   1179     MERLIN16_CORE_TO_PHY_ACCESS(&phy_access, core);
   1180     PHYMOD_MEMCPY(&core_copy, core, sizeof(core_copy));
   1181     core_copy.access.lane_mask = 0x1;
   1182 
   1183     phy_access_copy = phy_access;
   1184     phy_access_copy.access = core->access;
   1185     phy_access_copy.access.lane_mask = 0x1;
   1186     phy_access_copy.type = core->type;
   1187 
   1188     /*
   1189      * First step to program merlin16 is to do power reset. That is to
   1190      * program field POR_H_RSTB and CORE_DP_H_RSTB in register PMD_X1_CTL
   1191      */
   1192     PHYMOD_IF_ERR_RETURN
   1193         (merlin16_pmd_reset_seq(&core_copy.access, core_status->pmd_active));
   1194 
   1195     PHYMOD_IF_ERR_RETURN
   1196         (phymod_util_lane_config_get(&phy_access.access, &start_lane, &num_lane));
   1197 
   1198     /*
   1199      * Before programming the PMD lane address map register, the PMD lanes
   1200      * have to be reset. Without do this, writing the PMD lane address map
   1201      * regsiter will not take effect, meaning the reading value != writing
   1202      * value.
   1203      */
   1204     for (i = 0; i < MERLIN16_NOF_LANES_IN_CORE; i++) {
   1205         phy_access.access.lane_mask = 1 << (start_lane + i);
   1206         PHYMOD_IF_ERR_RETURN
   1207             (merlin16_lane_hard_soft_reset_release(&phy_access.access, 0));
   1208         PHYMOD_IF_ERR_RETURN
   1209             (merlin16_lane_soft_reset_release(&phy_access.access, 0));
   1210 
   1211         PHYMOD_IF_ERR_RETURN
   1212             (merlin16_lane_hard_soft_reset_release(&phy_access.access, 1));
   1213         PHYMOD_IF_ERR_RETURN
   1214             (merlin16_lane_soft_reset_release(&phy_access.access, 1));
   1215     }
   1216 
   1217     PHYMOD_IF_ERR_RETURN(merlin16_uc_active_get(&core_copy.access, &uc_active));
   1218     if (uc_active) {
   1219         return(PHYMOD_E_NONE);
   1220     }
   1221 
   1222     /* need to set the heart beat default is for 156.25M */
   1223     PHYMOD_IF_ERR_RETURN (merlin16_refclk_set(&core_copy.access, init_config->interface.ref_clock));
   1224 
   1225     /*
   1226      * In 28nm TSCE code the lane map programming was done in core_init_pass2.
   1227      * Now it is moved to pass1 because merlin16 requires that PMD lane address
   1228      * map be done before loading the uCode. Notice that before programming the
   1229      * PMD lane address map, lane and lane DP has to be reset by calling
   1230      * temod16_pmd_x4_reset().
   1231      */
   1232     PHYMOD_IF_ERR_RETURN
   1233         (merlin16_core_lane_map_set(&core_copy, &init_config->lane_map));
   1234 
   1235     if (init_config->firmware_load_method != phymodFirmwareLoadMethodNone) {
   1236         if (_merlin16_core_firmware_load(&core_copy, init_config->firmware_load_method, init_config->firmware_loader)) {
   1237             PHYMOD_DEBUG_ERROR(("devad 0x%"PRIx32" lane 0x%"PRIx32": UC firmware-load failed\n", core->access.addr, core->access.lane_mask));
   1238             PHYMOD_IF_ERR_RETURN (PHYMOD_E_INIT);
   1239         }
   1240 
   1241     }
   1242 
   1243     PHYMOD_IF_ERR_RETURN
   1244         (merlin16_pmd_ln_h_rstb_pkill_override(&phy_access_copy.access, 0x1));
   1245     PHYMOD_IF_ERR_RETURN
   1246         (merlin16_uc_reset(&phy_access_copy.access, 0));
   1247     PHYMOD_IF_ERR_RETURN
   1248         (merlin16_wait_uc_active(&phy_access_copy.access));
   1249 
   1250     /* Initialize software information table for the micro */
   1251     PHYMOD_IF_ERR_RETURN
   1252         (merlin16_init_merlin16_info(&core_copy.access));
   1253 
   1254     if (init_config->firmware_load_method != phymodFirmwareLoadMethodNone) {
   1255         if (PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY_GET(init_config)) {
   1256             PHYMOD_IF_ERR_RETURN
   1257                 (merlin16_start_ucode_crc_calc(&core_copy.access, merlin16_ucode_len));
   1258         }
   1259     }
   1260 
   1261     return (PHYMOD_E_NONE);
   1262 }
   1263 
   1264 STATIC
   1265 int _merlin16_core_init_pass2(const phymod_core_access_t* core,
   1266                             const phymod_core_init_config_t* init_config,
   1267                             const phymod_core_status_t* core_status)
   1268 {
   1269     phymod_phy_access_t phy_access, phy_access_copy;
   1270     phymod_core_access_t  core_copy;
   1271     phymod_firmware_core_config_t  firmware_core_config_tmp;
   1272 
   1273     MERLIN16_CORE_TO_PHY_ACCESS(&phy_access, core);
   1274     PHYMOD_MEMCPY(&core_copy, core, sizeof(core_copy));
   1275     core_copy.access.lane_mask = 0x1;
   1276 
   1277     phy_access_copy = phy_access;
   1278     phy_access_copy.access = core->access;
   1279     phy_access_copy.access.lane_mask = 0x1;
   1280     phy_access_copy.type = core->type;
   1281 
   1282     if (init_config->firmware_load_method != phymodFirmwareLoadMethodNone) {
   1283         if (PHYMOD_CORE_INIT_F_FIRMWARE_LOAD_VERIFY_GET(init_config)) {
   1284             PHYMOD_IF_ERR_RETURN
   1285                 (merlin16_check_ucode_crc(&core_copy.access, merlin16_ucode_crc, 250));
   1286         }
   1287     }
   1288 
   1289     PHYMOD_IF_ERR_RETURN(
   1290         merlin16_pmd_ln_h_rstb_pkill_override( &phy_access_copy.access, 0x0));
   1291 
   1292     phy_access_copy.access.lane_mask = 0x1;
   1293 
   1294     PHYMOD_IF_ERR_RETURN
   1295         (merlin16_core_soft_reset_release(&core_copy.access, 0));
   1296 
   1297     /* After loading the PMD uCode, PLL needs to be configured. */
   1298     PHYMOD_IF_ERR_RETURN
   1299         (merlin16_configure_pll_refclk_div(&phy_access_copy.access, MERLIN16_PLL_REFCLK_156P25MHZ,
   1300                                                MERLIN16_PLL_DIV_66));
   1301 
   1302     PHYMOD_IF_ERR_RETURN
   1303         (merlin16_phy_firmware_core_config_get(&phy_access_copy, &firmware_core_config_tmp));
   1304     firmware_core_config_tmp.CoreConfigFromPCS = 0;
   1305 
   1306     PHYMOD_IF_ERR_RETURN
   1307         (merlin16_phy_firmware_core_config_set(&phy_access_copy, firmware_core_config_tmp));
   1308 
   1309     /*
   1310      * After programming the PMD PLL, we need to release the core reset and lane reset.
   1311      * Core reset is done below, and lane reset is done in tsce16_phy_init() by calling
   1312      * temod16_pmd_x4_reset().
   1313      */
   1314     PHYMOD_IF_ERR_RETURN
   1315         (merlin16_core_soft_reset_release(&core_copy.access, 1));
   1316 
   1317     return PHYMOD_E_NONE;
   1318 }
   1319 
   1320 /*Core Initialization*/
   1321 int merlin16_core_init(const phymod_core_access_t* core, const phymod_core_init_config_t* init_config, const phymod_core_status_t* core_status)
   1322 {
   1323     if ( (!PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config) &&
   1324           !PHYMOD_CORE_INIT_F_EXECUTE_PASS2_GET(init_config)) ||
   1325         PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config)) {
   1326         PHYMOD_IF_ERR_RETURN
   1327             (_merlin16_core_init_pass1(core, init_config, core_status));
   1328 
   1329         if (PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config)) {
   1330             return PHYMOD_E_NONE;
   1331         }
   1332     }
   1333 
   1334     if ( (!PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config) &&
   1335           !PHYMOD_CORE_INIT_F_EXECUTE_PASS2_GET(init_config)) ||
   1336         PHYMOD_CORE_INIT_F_EXECUTE_PASS2_GET(init_config)) {
   1337         PHYMOD_IF_ERR_RETURN
   1338             (_merlin16_core_init_pass2(core, init_config, core_status));
   1339     }
   1340 
   1341     return PHYMOD_E_NONE;
   1342 
   1343 }
   1344 
   1345 
   1346 /*Phy Initialization*/
   1347 int merlin16_phy_init(const phymod_phy_access_t* phy, const phymod_phy_init_config_t* init_config)
   1348 {
   1349     const phymod_access_t *pm_acc = &phy->access;
   1350     phymod_phy_access_t pm_phy_copy;
   1351     int start_lane, num_lane, i;
   1352     phymod_polarity_t tmp_pol;
   1353 #ifdef PHYMOD_DIAG
   1354     PHYMOD_VDBG(DBG_CFG, pm_acc, ("%-22s: p=%p adr=%0"PRIx32" lmask=%0"PRIx32"\n",
   1355                 __func__, (void *)pm_acc, pm_acc->addr, pm_acc->lane_mask));
   1356 #endif
   1357     PHYMOD_MEMSET(&tmp_pol, 0x0, sizeof(tmp_pol));
   1358     PHYMOD_MEMCPY(&pm_phy_copy, phy, sizeof(pm_phy_copy));
   1359 
   1360     /* next program the tx fir taps and driver current based on the input */
   1361     PHYMOD_IF_ERR_RETURN
   1362         (phymod_util_lane_config_get(pm_acc, &start_lane, &num_lane));
   1363 
   1364     /* per lane based reset release */
   1365     for (i = 0; i < num_lane; i++) {
   1366         PHYMOD_IF_ERR_RETURN
   1367             (merlin16_lane_hard_soft_reset_release(&pm_phy_copy.access, 0));
   1368         PHYMOD_IF_ERR_RETURN
   1369             (merlin16_lane_hard_soft_reset_release(&pm_phy_copy.access, 1));
   1370 
   1371         PHYMOD_IF_ERR_RETURN
   1372             (merlin16_lane_soft_reset_release(&pm_phy_copy.access, 0));
   1373         PHYMOD_IF_ERR_RETURN
   1374             (merlin16_lane_soft_reset_release(&pm_phy_copy.access, 1));
   1375     }
   1376 
   1377     /* program the rx/tx polarity */
   1378     for (i = 0; i < num_lane; i++) {
   1379         if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
   1380             continue;
   1381         }
   1382         pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane);
   1383         tmp_pol.tx_polarity = (init_config->polarity.tx_polarity) >> i & 0x1;
   1384         tmp_pol.rx_polarity = (init_config->polarity.rx_polarity) >> i & 0x1;
   1385         PHYMOD_IF_ERR_RETURN
   1386             (merlin16_phy_polarity_set(&pm_phy_copy, &tmp_pol));
   1387     }
   1388 
   1389     for (i = 0; i < num_lane; i++) {
   1390         if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
   1391             continue;
   1392         }
   1393         pm_phy_copy.access.lane_mask = 0x1 << (i + start_lane);
   1394         PHYMOD_IF_ERR_RETURN
   1395             (merlin16_phy_tx_set(&pm_phy_copy, &init_config->tx[i]));
   1396     }
   1397 
   1398     /* next check if pcs-bypass mode  */
   1399     if (PHYMOD_DEVICE_OP_MODE_PCS_BYPASS_GET(phy->device_op_mode)) {
   1400         PHYMOD_IF_ERR_RETURN
   1401             (merlin16_pmd_tx_disable_pin_dis_set(&phy->access, 1));
   1402     }
   1403 
   1404     return PHYMOD_E_NONE;
   1405 }
   1406 
   1407 
   1408 /*Set\get loopback mode*/
   1409 int merlin16_phy_loopback_set(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t enable)
   1410 {
   1411     int start_lane, num_lane, i;
   1412     phymod_phy_access_t phy_copy;
   1413     const phymod_access_t *pm_acc;
   1414 
   1415     pm_acc = &phy->access;
   1416 #ifdef PHYMOD_DIAG
   1417     PHYMOD_VDBG(DBG_LPK, pm_acc, ("%-22s: p=%p adr=%0"PRIx32" lmask=%0"PRIx32" lpbk=%0d(%s) en=%0d\n",
   1418               __func__, (void *)pm_acc, pm_acc->addr, pm_acc->lane_mask, loopback,
   1419                             phymod_loopback_mode_t_mapping[loopback].key, enable));
   1420 #endif
   1421     PHYMOD_MEMCPY(&phy_copy, phy, sizeof(phy_copy));
   1422 
   1423     /* next figure out the lane num and start_lane based on the input */
   1424     PHYMOD_IF_ERR_RETURN
   1425         (phymod_util_lane_config_get(&phy->access, &start_lane, &num_lane));
   1426 
   1427     switch (loopback) {
   1428     case phymodLoopbackGlobal:
   1429         break;
   1430     case phymodLoopbackGlobalPMD:
   1431         for (i = 0; i < num_lane; i++) {
   1432             if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
   1433                 continue;
   1434             }
   1435             phy_copy.access.lane_mask = 0x1 << (i + start_lane);
   1436             PHYMOD_IF_ERR_RETURN(merlin16_pmd_loopback_set(&phy->access, enable));
   1437         }
   1438         break;
   1439     case phymodLoopbackRemotePMD:
   1440         for (i = 0; i < num_lane; i++) {
   1441             if (!PHYMOD_LANEPBMP_MEMBER(phy->access.lane_mask, start_lane + i)) {
   1442                 continue;
   1443             }
   1444             PHYMOD_IF_ERR_RETURN(merlin16_rmt_lpbk(&phy->access, enable));
   1445         }
   1446         break;
   1447     case phymodLoopbackRemotePCS:
   1448         PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG,
   1449                                (_PHYMOD_MSG("PCS Remote LoopBack not supported")));
   1450         break;
   1451     default:
   1452         break;
   1453     }
   1454 
   1455     return PHYMOD_E_NONE;
   1456 }
   1457 
   1458 int merlin16_phy_loopback_get(const phymod_phy_access_t* phy, phymod_loopback_mode_t loopback, uint32_t* enable)
   1459 {
   1460     *enable = 0;
   1461 
   1462     switch (loopback) {
   1463     case phymodLoopbackGlobal :
   1464         break;
   1465     case phymodLoopbackGlobalPMD :
   1466         PHYMOD_IF_ERR_RETURN(merlin16_pmd_loopback_get(&phy->access, enable));
   1467         break;
   1468     case phymodLoopbackRemotePMD :
   1469         PHYMOD_IF_ERR_RETURN(merlin16_rmt_lpbk_get(&phy->access, enable));
   1470         break;
   1471     case phymodLoopbackRemotePCS :
   1472         PHYMOD_RETURN_WITH_ERR(PHYMOD_E_CONFIG,
   1473                                (_PHYMOD_MSG("PCS Remote LoopBack not supported")));
   1474         break;
   1475     default :
   1476         break;
   1477     }
   1478     return PHYMOD_E_NONE;
   1479 }
   1480 
   1481 
   1482 /*Get rx pmd locked indication*/
   1483 int merlin16_phy_rx_pmd_locked_get(const phymod_phy_access_t* phy, uint32_t* rx_pmd_locked)
   1484 {
   1485     uint8_t rx_lock;
   1486     PHYMOD_IF_ERR_RETURN(merlin16_pmd_lock_status(&phy->access, &rx_lock));
   1487     *rx_pmd_locked = (uint32_t)rx_lock;
   1488 
   1489     return PHYMOD_E_NONE;
   1490 }
   1491 
   1492 /*Get link up status indication*/
   1493 int merlin16_phy_link_status_get(const phymod_phy_access_t* phy, uint32_t* link_status)
   1494 {
   1495     unsigned char rx_lock;
   1496     PHYMOD_IF_ERR_RETURN(merlin16_pmd_lock_status(&phy->access, &rx_lock));
   1497     *link_status = (uint32_t ) rx_lock;
   1498 
   1499     return PHYMOD_E_NONE;
   1500 }
   1501 
   1502 /*Read phymod register*/
   1503 int merlin16_phy_reg_read(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t* val)
   1504 {
   1505     PHYMOD_IF_ERR_RETURN(phymod_tsc_iblk_read(&phy->access, reg_addr, val));
   1506     return PHYMOD_E_NONE;
   1507 }
   1508 
   1509 
   1510 /*Write phymod register*/
   1511 int merlin16_phy_reg_write(const phymod_phy_access_t* phy, uint32_t reg_addr, uint32_t val)
   1512 {
   1513     PHYMOD_IF_ERR_RETURN(phymod_tsc_iblk_write(&phy->access, reg_addr, val));
   1514     return PHYMOD_E_NONE;
   1515 }
   1516