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_pcieg3_config.c (28381B)


      1 /***********************************************************************************
      2  ***********************************************************************************
      3  *  File Name     :  merlin16_pcieg3_config.c                                           *
      4  *  Created On    :  03 Nov 2015                                                   *
      5  *  Created By    :  Brent Roberts                                                 *
      6  *  Description   :  APIs for Serdes IPs                                           *
      7  *  Revision      :    *
      8  *                                                                                 *
      9  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
     10  * 
     11  * Copyright 2007-2019 Broadcom Inc. All rights reserved.                                                           *
     12  *  No portions of this material may be reproduced in any form without             *
     13  *  the written permission of:                                                     *
     14  *      Broadcom Corporation                                                       *
     15  *      5300 California Avenue                                                     *
     16  *      Irvine, CA  92617                                                          *
     17  *                                                                                 *
     18  *  All information contained in this document is Broadcom Corporation             *
     19  *  company private proprietary, and trade secret.                                 *
     20  */
     21 
     22 /** @file merlin16_pcieg3_config.c
     23  * Implementation of API config functions
     24  */
     25 
     26 #include "merlin16_pcieg3_config.h"
     27 #include "merlin16_pcieg3_access.h"
     28 #include "merlin16_pcieg3_common.h"
     29 #include "merlin16_pcieg3_functions.h"
     30 #include "merlin16_pcieg3_internal.h"
     31 #include "merlin16_pcieg3_internal_error.h"
     32 #include "merlin16_pcieg3_select_defns.h"
     33 #include "merlin16_pcieg3_enum.h"
     34 #include "merlin16_pcieg3_dependencies.h"
     35 
     36 /* If SERDES_EVAL is defined, then is_ate_log_enabled() is queried to *\
     37 \* know whether to log ATE.  merlin16_pcieg3_access.h provides that function.  */
     38 
     39 /*******************************/
     40 /*  Stop/Resume RX Adaptation  */
     41 /*******************************/
     42 
     43 err_code_t merlin16_pcieg3_stop_rx_adaptation(srds_access_t *sa__, uint8_t enable) {
     44 
     45   if (enable) {
     46     return(merlin16_pcieg3_pmd_uc_control(sa__, CMD_UC_CTRL_STOP_GRACEFULLY,GRACEFUL_STOP_TIME));
     47   }
     48   else {
     49     return(merlin16_pcieg3_pmd_uc_control(sa__, CMD_UC_CTRL_RESUME,50));
     50   }
     51 }
     52 
     53 err_code_t merlin16_pcieg3_request_stop_rx_adaptation(srds_access_t *sa__) {
     54 
     55   return(merlin16_pcieg3_pmd_uc_control_return_immediate(sa__, CMD_UC_CTRL_STOP_GRACEFULLY));
     56 }
     57 
     58 /**********************/
     59 /*  uCode CRC Verify  */
     60 /**********************/
     61 
     62 err_code_t merlin16_pcieg3_ucode_crc_verify(srds_access_t *sa__, uint16_t ucode_len,uint16_t expected_crc_value) {
     63     uint16_t calc_crc;
     64     EFUN(merlin16_pcieg3_pmd_uc_cmd_with_data(sa__, CMD_CALC_CRC,0,ucode_len,200));
     65 
     66     ESTM(calc_crc = rd_uc_dsc_data());
     67     if(calc_crc != expected_crc_value) {
     68         EFUN_PRINTF(("Microcode CRC did not match expected=%04x : calculated=%04x\n",expected_crc_value, calc_crc));
     69         return(_error(ERR_CODE_UC_CRC_NOT_MATCH));
     70     } else {
     71         EFUN_PRINTF(("Microcode CRC Matched expected=0x%04X\n",expected_crc_value));
     72     }
     73 
     74     return(ERR_CODE_NONE);
     75 }
     76 
     77 err_code_t merlin16_pcieg3_start_ucode_crc_calc(srds_access_t *sa__, uint16_t ucode_len) {
     78     EFUN(merlin16_pcieg3_pmd_uc_cmd_with_data_return_immediate(sa__, CMD_CALC_CRC, 0, ucode_len)); /* Invoke Calculate CRC command and return control immediately */
     79     return(ERR_CODE_NONE);
     80 }
     81 
     82 err_code_t merlin16_pcieg3_check_ucode_crc(srds_access_t *sa__, uint16_t expected_crc_value, uint32_t timeout_ms) {
     83     uint16_t calc_crc;
     84     err_code_t err_code;
     85 
     86     err_code = merlin16_pcieg3_INTERNAL_poll_uc_dsc_ready_for_cmd_equals_1(sa__, timeout_ms, CMD_CALC_CRC); /* Poll for uc_dsc_ready_for_cmd = 1 to indicate merlin16_pcieg3 ready for command */
     87     if (err_code) {
     88       EFUN_PRINTF(("ERROR : DSC ready for command timed out. Previous uC command not finished yet\n"));
     89       return (err_code);
     90     }
     91     ESTM(calc_crc = rd_uc_dsc_data());
     92     if(calc_crc != expected_crc_value) {
     93         EFUN_PRINTF(("UC CRC did not match expected=%04x : calculated=%04x\n",expected_crc_value, calc_crc));
     94         return(_error(ERR_CODE_UC_CRC_NOT_MATCH));
     95     }
     96 
     97     return(ERR_CODE_NONE);
     98 }
     99 
    100 
    101 /*--------------------------------------------*/
    102 /*  APIs to Enable or Disable datapath reset  */
    103 /*--------------------------------------------*/
    104 
    105 err_code_t merlin16_pcieg3_tx_dp_reset(srds_access_t *sa__, uint8_t enable) {
    106     if (enable) {
    107         EFUN(wr_tx_ln_dp_s_rstb(0x0));
    108     } else {
    109         EFUN(wr_tx_ln_dp_s_rstb(0x1));
    110         EFUN(wr_tx_uc_ack_lane_dp_reset(0x1));
    111         EFUN(wr_tx_uc_ack_lane_cfg_done(0x1));
    112     }
    113     return ERR_CODE_NONE;
    114 }
    115 
    116 err_code_t merlin16_pcieg3_rx_dp_reset(srds_access_t *sa__, uint8_t enable) {
    117     if (enable) {
    118         EFUN(wr_rx_ln_dp_s_rstb(0x0));
    119     } else {
    120         EFUN(wr_rx_ln_dp_s_rstb(0x1));
    121     }
    122     return ERR_CODE_NONE;
    123 }
    124 
    125 err_code_t merlin16_pcieg3_core_dp_reset(srds_access_t *sa__, uint8_t enable){
    126     if (enable) {
    127         EFUN(wrc_core_dp_s_rstb(0x0));
    128     } else {
    129         EFUN(wrc_core_dp_s_rstb(0x1));
    130     }
    131     return ERR_CODE_NONE;
    132 }
    133 
    134 /********************************/
    135 /*  Loading ucode through PRAM  */
    136 /********************************/
    137 
    138 err_code_t merlin16_pcieg3_ucode_pram_load(srds_access_t *sa__, char const * ucode_image, uint16_t ucode_len) {
    139     uint16_t ucode_len_remainder = ((ucode_len + 3) & 0xFFFC) - ucode_len;
    140 
    141     if(!ucode_image) {
    142         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    143     }
    144 
    145     if (ucode_len > UCODE_MAX_SIZE) {                       /* uCode size should be less than UCODE_MAX_SIZE  */
    146         return (_error(ERR_CODE_INVALID_UCODE_LEN));
    147     }
    148 
    149     EFUN(wrc_micro_master_clk_en(0x1));                     /* Enable clock to microcontroller subsystem */
    150     EFUN(wrc_micro_master_rstb(0x1));                       /* De-assert reset to microcontroller sybsystem */
    151     EFUN(wrc_micro_master_rstb(0x0));                       /* Assert reset to microcontroller sybsystem - Toggling reset*/
    152     EFUN(wrc_micro_master_rstb(0x1));                       /* De-assert reset to microcontroller sybsystem */
    153 
    154     EFUN(wrc_micro_ra_init(0x1));                           /* Set initialization command to initialize code RAM */
    155     EFUN(merlin16_pcieg3_INTERNAL_poll_micro_ra_initdone(sa__, 250));/* Poll for micro_ra_initdone = 1 to indicate initialization done */
    156     EFUN(wrc_micro_ra_init(0x0));                           /* Clear initialization command */
    157 
    158 
    159     EFUN(wrc_micro_pramif_ahb_wraddr_msw(0x0000));
    160     EFUN(wrc_micro_pramif_ahb_wraddr_lsw(0x0000));
    161     EFUN(wrc_micro_pram_if_rstb(1));
    162     EFUN(wrc_micro_pramif_en(1));
    163 
    164     /* Wait 8 pram clocks */
    165     EFUN(USR_DELAY_US(1));
    166     
    167     /* write ucode into pram */
    168     while (ucode_len > 0) {
    169         EFUN(merlin16_pcieg3_pmd_wr_pram(sa__, *ucode_image));
    170         --ucode_len;
    171         ++ucode_image;
    172     }
    173     
    174     /* Pad to 32 bits */
    175     while (ucode_len_remainder > 0) {
    176         EFUN(merlin16_pcieg3_pmd_wr_pram(sa__, 0));
    177         --ucode_len_remainder;
    178     }
    179     
    180     /* Wait 8 pram clocks */
    181     EFUN(USR_DELAY_US(1));
    182 
    183 
    184     EFUN(wrc_micro_pramif_en(0));
    185     EFUN(wrc_micro_core_clk_en(1));
    186    /* EFUN(wrc_micro_core_rstb(1)); */
    187     return(ERR_CODE_NONE);
    188 }
    189 
    190 
    191 /************************/
    192 /*  Serdes API Version  */
    193 /************************/
    194 
    195 err_code_t merlin16_pcieg3_version(uint32_t *api_version) {
    196 
    197     if(!api_version) {
    198         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    199     }
    200     *api_version = 0xA10700;
    201     return (ERR_CODE_NONE);
    202 }
    203 
    204 /*****************/
    205 /*  PMD_RX_LOCK  */
    206 /*****************/
    207 
    208 err_code_t merlin16_pcieg3_pmd_lock_status(srds_access_t *sa__, uint8_t *pmd_rx_lock) {
    209     if(!pmd_rx_lock) {
    210         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    211     }
    212     ESTM(*pmd_rx_lock = rd_pmd_rx_lock());
    213     return (ERR_CODE_NONE);
    214 }
    215 
    216 /**********************************/
    217 /*  Serdes TX disable/RX Restart  */
    218 /**********************************/
    219 
    220 err_code_t merlin16_pcieg3_tx_disable(srds_access_t *sa__, uint8_t enable) {
    221 
    222   if (enable) {
    223     EFUN(wr_sdk_tx_disable(0x1));
    224   }
    225   else {
    226     EFUN(wr_sdk_tx_disable(0x0));
    227   }
    228   return(ERR_CODE_NONE);
    229 }
    230 
    231 
    232 /******************************************************/
    233 /*  Single function to set/get all RX AFE parameters  */
    234 /******************************************************/
    235 
    236 err_code_t merlin16_pcieg3_write_rx_afe(srds_access_t *sa__, enum srds_rx_afe_settings_enum param, int8_t val) {
    237   /* Assumes the micro is not actively tuning */
    238 
    239     switch(param) {
    240     case RX_AFE_PF:
    241         return(merlin16_pcieg3_INTERNAL_set_rx_pf_main(sa__, val));
    242 
    243     case RX_AFE_PF2:
    244         return(merlin16_pcieg3_INTERNAL_set_rx_pf2(sa__, val));
    245 
    246     case RX_AFE_VGA:
    247       return(merlin16_pcieg3_INTERNAL_set_rx_vga(sa__, val));
    248 
    249     case RX_AFE_DFE1:
    250         return(merlin16_pcieg3_INTERNAL_set_rx_dfe1(sa__, val));
    251 
    252     case RX_AFE_DFE2:
    253         return(merlin16_pcieg3_INTERNAL_set_rx_dfe2(sa__, val));
    254 
    255     case RX_AFE_DFE3:
    256         return(merlin16_pcieg3_INTERNAL_set_rx_dfe3(sa__, val));
    257 
    258     case RX_AFE_DFE4:
    259         return(merlin16_pcieg3_INTERNAL_set_rx_dfe4(sa__, val));
    260 
    261     case RX_AFE_DFE5:
    262         return(merlin16_pcieg3_INTERNAL_set_rx_dfe5(sa__, val));
    263 
    264     default:
    265         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    266     }
    267 }
    268 
    269 
    270 err_code_t merlin16_pcieg3_read_rx_afe(srds_access_t *sa__, enum srds_rx_afe_settings_enum param, int8_t *val) {
    271   /* Assumes the micro is not actively tuning */
    272     if(!val) {
    273         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    274     }
    275 
    276     switch(param) {
    277     case RX_AFE_PF:
    278         EFUN(merlin16_pcieg3_INTERNAL_get_rx_pf_main(sa__, val));
    279         break;
    280     case RX_AFE_PF2:
    281         EFUN(merlin16_pcieg3_INTERNAL_get_rx_pf2(sa__, val));
    282         break;
    283     case RX_AFE_VGA:
    284         EFUN(merlin16_pcieg3_INTERNAL_get_rx_vga(sa__, val));
    285       break;
    286 
    287     case RX_AFE_DFE1:
    288         EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe1(sa__, val));
    289         break;
    290     case RX_AFE_DFE2:
    291         EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe2(sa__, val));
    292         break;
    293     case RX_AFE_DFE3:
    294         EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe3(sa__, val));
    295         break;
    296     case RX_AFE_DFE4:
    297         EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe4(sa__, val));
    298         break;
    299     case RX_AFE_DFE5:
    300         EFUN(merlin16_pcieg3_INTERNAL_get_rx_dfe5(sa__, val));
    301         break;
    302     default:
    303         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    304     }
    305 
    306     return(ERR_CODE_NONE);
    307 }
    308 
    309 
    310 /**********************************************/
    311 /*  Loopback and Ultra-Low Latency Functions  */
    312 /**********************************************/
    313 
    314 
    315 
    316 /********************************/
    317 /*  TX_PI Fixed Frequency Mode  */
    318 /********************************/
    319 
    320 /* TX_PI Frequency Override (Fixed Frequency Mode) */
    321 err_code_t merlin16_pcieg3_tx_pi_freq_override(srds_access_t *sa__, uint8_t enable, int16_t freq_override_val) {
    322     if (enable) {
    323         EFUN(wr_tx_pi_en(0x1));                              /* TX_PI enable :            0 = disabled, 1 = enabled */
    324         EFUN(wr_tx_pi_freq_override_en(0x1));                /* Fixed freq mode enable:   0 = disabled, 1 = enabled */
    325         EFUN(wr_tx_pi_freq_override_val(freq_override_val)); /* Fixed Freq Override Value (+/-8192) */
    326     }
    327     else {
    328         EFUN(wr_tx_pi_freq_override_val(0));                 /* Fixed Freq Override Value to 0 */
    329         EFUN(wr_tx_pi_freq_override_en(0x0));                /* Fixed freq mode enable:   0 = disabled, 1 = enabled */
    330         EFUN(wr_tx_pi_en(0x0));                              /* TX_PI enable :            0 = disabled, 1 = enabled */
    331     }
    332   return (ERR_CODE_NONE);
    333 }
    334 /*********************************/
    335 /*  uc_active and uc_reset APIs  */
    336 /*********************************/
    337 
    338 /* Enable or Disable the uC reset */
    339 err_code_t merlin16_pcieg3_uc_reset(srds_access_t *sa__, uint8_t enable) {
    340   if (enable) {
    341     /* Assert micro reset and reset all micro registers (all non-status registers written to default value) */
    342     EFUN(wrc_micro_core_clk_en(0x0));                     /* Disable clock to M0 core */
    343 
    344     EFUN(wrc_micro_master_clk_en(0x0));                   /* Disable clock to microcontroller subsystem */
    345     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD200, 0x0000));
    346     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD201, 0x0000));
    347     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD202, 0x0000));
    348     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD204, 0x0000));
    349     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD205, 0x0000));
    350     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD206, 0x0000));
    351     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD207, 0x0000));
    352     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD208, 0x0000));
    353     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD209, 0x0000));
    354     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD20A, 0x0000));
    355     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD20B, 0x0000));
    356     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD20C, 0x0000));
    357     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD20D, 0x0000));
    358     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD20E, 0x0000));
    359     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD211, 0x0000));
    360     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD212, 0x0000));
    361     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD213, 0x0000));
    362     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD214, 0x0000));
    363     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD215, 0x0000));
    364     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD216, 0x0007));
    365     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD217, 0x0000));
    366     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD218, 0x0000));
    367     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD219, 0x0000));
    368     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD21A, 0x0000));
    369     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD21B, 0x0000));
    370     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD220, 0x0000));
    371     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD221, 0x0000));
    372     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD224, 0x0000));
    373 
    374     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD225, 0x8301));
    375 
    376     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD226, 0x0000));
    377     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD228, 0x0101));
    378     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD229, 0x0000));
    379     EFUN(merlin16_pcieg3_pmd_wr_reg(sa__, 0xD22A, 0x0000));  
    380   }
    381   else {
    382     /* De-assert micro reset - Start executing code */
    383     EFUN(wrc_micro_master_clk_en (0x1));             /* Enable clock to microcontroller subsystem */
    384     EFUN(wrc_micro_master_rstb   (0x1));             /* De-assert reset to microcontroller sybsystem */
    385     EFUN(wrc_micro_ra_init       (0x2));             /* Write command for data RAM initialization */
    386     EFUN(merlin16_pcieg3_INTERNAL_poll_micro_ra_initdone(sa__, 250)); /* Poll status of data RAM initialization */
    387     EFUN(wrc_micro_ra_init       (0x0));             /* Clear command for data RAM initialization */
    388     EFUN(wrc_micro_core_clk_en   (0x1));            /* Enable clock to M0 core */
    389     EFUN(wrc_micro_core_rstb     (0x1));
    390   }
    391  return (ERR_CODE_NONE);
    392 }
    393 
    394 
    395 
    396 err_code_t merlin16_pcieg3_init_merlin16_pcieg3_info(srds_access_t *sa__) {
    397     merlin16_pcieg3_info_t * const merlin16_pcieg3_info_ptr = merlin16_pcieg3_INTERNAL_get_merlin16_pcieg3_info_ptr();
    398     uint32_t info_table[INFO_TABLE_END / sizeof(uint32_t)];
    399     uint32_t info_table_signature;
    400     uint8_t  info_table_version;
    401 
    402     ENULL_MEMSET(merlin16_pcieg3_info_ptr, 0, sizeof(merlin16_pcieg3_info_t));
    403 
    404     if (merlin16_pcieg3_info_ptr == 0) {
    405         EFUN_PRINTF(("ERROR:  Info table pointer is null.\n"));
    406         return (_error(ERR_CODE_INFO_TABLE_ERROR));
    407     }
    408 
    409     EFUN(merlin16_pcieg3_rdblk_uc_prog_ram(sa__, (uint8_t *)info_table, INFO_TABLE_RAM_BASE, INFO_TABLE_END));
    410 
    411     info_table_signature = info_table[INFO_TABLE_OFFS_SIGNATURE / sizeof(uint32_t)];
    412     info_table_version = (uint8_t)(info_table_signature >> 24);
    413     if (((info_table_signature & 0x00FFFFFF) != 0x666E49)
    414         || (!(   ((info_table_version >= 0x32) && (info_table_version <= 0x39))
    415               || ((info_table_version >= 0x41) && (info_table_version <= 0x5A))))) {
    416         return (_error(ERR_CODE_INFO_TABLE_ERROR));
    417     }
    418     
    419     merlin16_pcieg3_info_ptr->lane_count = info_table[INFO_TABLE_OFFS_OTHER_SIZE / sizeof(uint32_t)] & 0xFF;
    420     merlin16_pcieg3_info_ptr->trace_memory_descending_writes = ((info_table[INFO_TABLE_OFFS_OTHER_SIZE / sizeof(uint32_t)] & 0x1000000) != 0);
    421 
    422     merlin16_pcieg3_info_ptr->core_var_ram_size = (info_table[INFO_TABLE_OFFS_OTHER_SIZE / sizeof(uint32_t)] >> 8) & 0xFF;
    423 
    424     merlin16_pcieg3_info_ptr->lane_var_ram_size = (info_table[INFO_TABLE_OFFS_TRACE_LANE_MEM_SIZE / sizeof(uint32_t)] >> 16) & 0xFFFF;
    425 
    426     merlin16_pcieg3_info_ptr->diag_mem_ram_size = (info_table[INFO_TABLE_OFFS_TRACE_LANE_MEM_SIZE / sizeof(uint32_t)] & 0xFFFF) / merlin16_pcieg3_info_ptr->lane_count;
    427     merlin16_pcieg3_info_ptr->trace_mem_ram_size = (info_table[INFO_TABLE_OFFS_TRACE_LANE_MEM_SIZE / sizeof(uint32_t)] & 0xFFFF);
    428     
    429     merlin16_pcieg3_info_ptr->diag_mem_ram_base = info_table[INFO_TABLE_OFFS_TRACE_MEM_PTR / sizeof(uint32_t)];
    430     merlin16_pcieg3_info_ptr->trace_mem_ram_base = merlin16_pcieg3_info_ptr->diag_mem_ram_base;
    431     
    432     merlin16_pcieg3_info_ptr->core_var_ram_base = info_table[INFO_TABLE_OFFS_CORE_MEM_PTR / sizeof(uint32_t)];
    433     
    434     merlin16_pcieg3_info_ptr->micro_var_ram_base = info_table[INFO_TABLE_OFFS_MICRO_MEM_PTR / sizeof(uint32_t)];
    435     merlin16_pcieg3_info_ptr->micro_var_ram_size = (info_table[INFO_TABLE_OFFS_OTHER_SIZE_2 / sizeof(uint32_t)] >> 4) & 0xFF;
    436 
    437     merlin16_pcieg3_info_ptr->lane_var_ram_base = info_table[INFO_TABLE_OFFS_LANE_MEM_PTR / sizeof(uint32_t)];
    438 
    439     
    440 
    441     if (info_table_version < 0x34) {
    442         merlin16_pcieg3_info_ptr->micro_count = 1;
    443     } else {
    444         merlin16_pcieg3_info_ptr->micro_count = info_table[INFO_TABLE_OFFS_OTHER_SIZE_2 / sizeof(uint32_t)] & 0xF;
    445     }
    446     merlin16_pcieg3_info_ptr->grp_ram_size = 0;
    447     merlin16_pcieg3_info_ptr->signature = SRDS_INFO_SIGNATURE;
    448     return (ERR_CODE_NONE);
    449 }
    450 
    451 
    452 /***********************************************/
    453 /*  Microcode Load into Program RAM Functions  */
    454 /***********************************************/
    455 
    456 /* uCode Load through Register (MDIO) Interface [Return Val = Error_Code (0 = PASS)] */
    457 err_code_t merlin16_pcieg3_ucode_mdio_load(srds_access_t *sa__, uint8_t *ucode_image, uint16_t ucode_len) {
    458     uint16_t   ucode_len_padded, count = 0;
    459     uint16_t   wrdata_lsw;
    460     uint8_t    wrdata_lsb;
    461 
    462     if(!ucode_image) {
    463         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    464     }
    465 
    466     if (ucode_len > UCODE_MAX_SIZE) {                     /* uCode size should be less than UCODE_MAX_SIZE  */
    467         return (_error(ERR_CODE_INVALID_UCODE_LEN));
    468     }
    469 
    470     EFUN(wrc_micro_master_clk_en(0x1));                   /* Enable clock to microcontroller subsystem */
    471     EFUN(wrc_micro_master_rstb(0x1));                     /* De-assert reset to microcontroller sybsystem */
    472     EFUN(wrc_micro_master_rstb(0x0));                     /* Assert reset to microcontroller sybsystem - Toggling reset*/
    473     EFUN(wrc_micro_master_rstb(0x1));                     /* De-assert reset to microcontroller sybsystem */
    474 
    475     EFUN(wrc_micro_ra_init(0x1));                         /* Set initialization command to initialize code RAM */
    476     EFUN(merlin16_pcieg3_INTERNAL_poll_micro_ra_initdone(sa__, 250)); /* Poll for micro_ra_initdone = 1 to indicate initialization done */
    477     EFUN(wrc_micro_ra_init(0x0));                         /* Clear initialization command */
    478 
    479     ucode_len_padded = ((ucode_len + 3) & 0xFFFC);        /* Aligning ucode size to 4-byte boundary */
    480 
    481     /* Code to Load microcode */
    482     EFUN(wrc_micro_autoinc_wraddr_en(0x1));               /* To auto increment RAM write address */
    483     EFUN(wrc_micro_ra_wrdatasize(0x1));                   /* Select 16bit transfers */
    484     EFUN(wrc_micro_ra_wraddr_msw(0x0));                   /* Upper 16bits of start address of Program RAM where the ucode is to be loaded */
    485     EFUN(wrc_micro_ra_wraddr_lsw(0x0));                   /* Lower 16bits of start address of Program RAM where the ucode is to be loaded */
    486 
    487     do {                                                  /* ucode_image loaded 16bits at a time */
    488         wrdata_lsb = (count < ucode_len) ? ucode_image[count] : 0x0; /* wrdata_lsb read from ucode_image; zero padded to 4byte boundary */
    489         count++;
    490         wrdata_lsw = (count < ucode_len) ? ucode_image[count] : 0x0; /* wrdata_msb read from ucode_image; zero padded to 4byte boundary */
    491         count++;
    492         wrdata_lsw = ((wrdata_lsw << 8) | wrdata_lsb);               /* 16bit wrdata_lsw formed from 8bit msb and lsb values read from ucode_image */
    493         EFUN(wrc_micro_ra_wrdata_lsw(wrdata_lsw));                   /* Program RAM lower 16bits write data */
    494     }   while (count < ucode_len_padded);                 /* Loop repeated till entire image loaded (upto the 4byte boundary) */
    495 
    496     EFUN(wrc_micro_ra_wrdatasize(0x2));                   /* Select 32bit transfers as default */
    497     EFUN(wrc_micro_core_clk_en(0x1));                     /* Enable clock to M0 core */
    498     /* EFUN(wrc_micro_core_rstb(0x1)); */                 /* De-assert reset to micro to start executing microcode */
    499     return (ERR_CODE_NONE);                               /* NO Errors while loading microcode (uCode Load PASS) */
    500   }
    501 
    502 
    503 /* Read-back uCode from Program RAM and verify against ucode_image [Return Val = Error_Code (0 = PASS)]  */
    504 err_code_t merlin16_pcieg3_ucode_load_verify(srds_access_t *sa__, uint8_t *ucode_image, uint16_t ucode_len) {
    505 
    506     uint16_t ucode_len_padded, count = 0;
    507     uint16_t rddata_lsw;
    508     uint16_t data_lsw;
    509     uint8_t  rddata_lsb;
    510 
    511     if(!ucode_image) {
    512         return(_error(ERR_CODE_BAD_PTR_OR_INVALID_INPUT));
    513     }
    514 
    515     ucode_len_padded = ((ucode_len + 3) & 0xFFFC);        /* Aligning ucode size to 4-byte boundary */
    516 
    517     if (ucode_len_padded > UCODE_MAX_SIZE) {              /* uCode size should be less than UCODE_MAX_SIZE */
    518         return (_error(ERR_CODE_INVALID_UCODE_LEN));
    519     }
    520 
    521     EFUN(wrc_micro_autoinc_rdaddr_en(0x1));               /* To auto increment RAM read address */
    522     EFUN(wrc_micro_ra_rddatasize(0x1));                   /* Select 16bit transfers */
    523     EFUN(wrc_micro_ra_rdaddr_msw(0x0));                   /* Upper 16bits of start address of Program RAM from where to read ucode */
    524     EFUN(wrc_micro_ra_rdaddr_lsw(0x0));                   /* Lower 16bits of start address of Program RAM from where to read ucode */
    525 
    526     do {                                                  /* ucode_image read 16bits at a time */
    527         rddata_lsb = (count < ucode_len) ? ucode_image[count] : 0x0; /* rddata_lsb read from ucode_image; zero padded to 4byte boundary */
    528         count++;
    529         rddata_lsw = (count < ucode_len) ? ucode_image[count] : 0x0; /* rddata_msb read from ucode_image; zero padded to 4byte boundary */
    530         count++;
    531         rddata_lsw = ((rddata_lsw << 8) | rddata_lsb);               /* 16bit rddata_lsw formed from 8bit msb and lsb values read from ucode_image */
    532                                                                      /* Compare Program RAM ucode to ucode_image (Read to micro_ra_rddata_lsw reg auto-increments the ram_address) */
    533         ESTM(data_lsw = rdc_micro_ra_rddata_lsw());
    534         if (data_lsw != rddata_lsw) {
    535             EFUN_PRINTF(("Ucode_Load_Verify_FAIL: Addr = 0x%x: Read_data = 0x%x :  Expected_data = 0x%x \n",(count-2),data_lsw,rddata_lsw));
    536             return (_error(ERR_CODE_UCODE_VERIFY_FAIL));             /* Verify uCode FAIL */
    537         }
    538 
    539     } while (count < ucode_len_padded);                   /* Loop repeated till entire image loaded (upto the 4byte boundary) */
    540 
    541     EFUN(wrc_micro_ra_rddatasize(0x2));                   /* Select 32bit transfers ad default */
    542     return (ERR_CODE_NONE);                               /* Verify uCode PASS */
    543 }
    544 
    545 /******************************************************************/
    546 /*  APIs to Align TX clocks                                       */
    547 /******************************************************************/
    548 err_code_t merlin16_pcieg3_tx_clock_align(srds_access_t *sa__, int num_lanes, int enable) {
    549     int current_lane, lane;
    550     
    551     ESTM(current_lane = merlin16_pcieg3_get_lane(sa__));
    552 
    553     for(lane = 0;lane<num_lanes;++lane) {
    554         EFUN(merlin16_pcieg3_set_lane(sa__,lane));
    555         if(enable) {
    556             if(lane == current_lane) {              /* Current Lane should be the master lane */
    557                 EFUN(wr_ams_tx_sel_txmaster(1));    /* Select one lane as txmaster. For all other lanes, this should be 0. */
    558                 EFUN(wr_ams_tx_pd_phasedet(0));     /* 1 - TCA PD powerdown, 0 - enable PD  (enable only for the slave lanes) */
    559             } else {
    560            /* Initial TX lane clock phase alignment. Program following registers only for slave lanes, master lane registers should not be programmed (can be kept in default values). */
    561                 EFUN(wr_tx_pi_pd_bypass_vco(1));        /* for quick phase lock time */
    562                 EFUN(wr_tx_pi_pd_bypass_flt(1));      /*  for quick phase lock time */
    563                 EFUN(wr_tx_pi_ext_pd_sel(0));         /*  selects PD path based on tx_pi_repeater_mode_en */
    564                 EFUN(wr_tx_pi_repeater_mode_en(1));   /*  selects external PD from afe as input to tx_pi */
    565                 EFUN(wr_tx_pi_en(1));                 /*  Enable TX_PI    */
    566                 EFUN(wr_tx_pi_jitter_filter_en(0));   /*  turn off frequency lock for tx_pi as all te tclk clocks are derived from VCO and same frequency */
    567                 EFUN(wr_tx_pi_ext_ctrl_en(1));        /*  turn on PD path to TX_PI to lock the clocks */
    568                 EFUN(USR_DELAY_US(25));                   /*  wait for the slave lane clocks to lock to the master lane clock */
    569                 EFUN(wr_tx_pi_ext_phase_bwsel_integ(3)); /*  0 to 7: higher value means faster lock time */
    570                 EFUN(wr_tx_pi_pd_bypass_vco(0));         /*  disable filter bypass for more accurate lock */
    571                 EFUN(wr_tx_pi_pd_bypass_flt(0));         /*  disable filter bypass for more accurate lock */
    572                 EFUN(USR_DELAY_US(60));                   /*  wait for the slave lane clocks to lock to the master lane clock withing 1/16th of UI. */
    573                 /* that all TX lane clocks are correct frequency and aligned together within 1/16th of UI. */
    574             }
    575         
    576         } else {
    577             if(lane == current_lane) {              /* Current Lane should be the master lane */
    578                 EFUN(wr_ams_tx_sel_txmaster(0));    /* Select one lane as txmaster. For all other lanes, this should be 0. */
    579                 EFUN(wr_ams_tx_pd_phasedet(1));     /* 1 - TCA PD powerdown, 0 - enable PD  (enable only for the slave lanes) */
    580             } else {
    581            /* Initial TX lane clock phase alignment. Program following registers only for slave lanes, master lane registers should not be programmed (can be kept in default values). */
    582                 EFUN(wr_tx_pi_pd_bypass_vco(0));         /* for quick phase lock time */
    583                 EFUN(wr_tx_pi_pd_bypass_flt(0));      /*  for quick phase lock time */
    584                 EFUN(wr_tx_pi_ext_pd_sel(0));         /*  selects PD path based on tx_pi_repeater_mode_en */
    585                 EFUN(wr_tx_pi_repeater_mode_en(1));   /*  selects external PD from afe as input to tx_pi */
    586                 EFUN(wr_tx_pi_en(0));                 /*  Enable TX_PI    */
    587                 EFUN(wr_tx_pi_jitter_filter_en(0));   /*  turn off frequency lock for tx_pi as all te tclk clocks are derived from VCO and same frequency */
    588                 EFUN(wr_tx_pi_ext_ctrl_en(0));        /*  turn on PD path to TX_PI to lock the clocks */
    589                 EFUN(wr_tx_pi_ext_phase_bwsel_integ(0)); /*  0 to 7: higher value means faster lock time */
    590                 EFUN(wr_tx_pi_pd_bypass_vco(0));         /*  disable filter bypass for more accurate lock */
    591                 /* that all TX lane clocks are correct frequency and aligned together within 1/16th of UI. */
    592             }
    593 
    594         }
    595     }
    596     EFUN(merlin16_pcieg3_set_lane(sa__,current_lane)); /* return lane to previous state */
    597     return(ERR_CODE_NONE);
    598  }
    599 
    600 
    601