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

memtune.c (172564B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File:        memtune.c
      8  * Purpose:     External memory interface tuning routines.
      9  * Notes:       Framework for memory tuning sequences.
     10  */
     11 
     12 #include <soc/defs.h>
     13 #include <shared/bsl.h>
     14 #include <soc/cm.h>
     15 #include <soc/debug.h>
     16 #include <soc/error.h>
     17 #include <soc/cmic.h>
     18 #include <soc/mem.h>
     19 #include <soc/memtune.h>
     20 #include <soc/er_tcam.h>
     21 
     22 #include <shared/alloc.h>
     23 
     24 #if defined(BCM_TRIUMPH_SUPPORT)
     25 
     26 #ifdef BCM_TRIUMPH_SUPPORT
     27 #include <soc/triumph.h>
     28 #endif /* BCM_TRIUMPH_SUPPORT */
     29 
     30 #ifndef NO_MEMTUNE
     31 STATIC int
     32 _mem_config_set(char *name, char *value)
     33 {
     34     if (soc_mem_config_set) {
     35         return soc_mem_config_set(name, value);
     36     }
     37     return SOC_E_UNAVAIL;
     38 }
     39 #endif
     40 
     41 #ifdef BCM_TRIUMPH_SUPPORT
     42 STATIC int
     43 _soc_tr_ddr_phase_sel_prog_hw_cb(soc_memtune_data_t *mt_data)
     44 {
     45     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
     46     soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data;
     47     soc_reg_t reg;
     48     uint32 oval, rval, addr;
     49 
     50     reg = tr_mt_data->config_reg3;
     51     if (mt_ctrl->phase_sel_cur != -1) {
     52         addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0);
     53         SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
     54         oval = rval;
     55         soc_reg_field_set(mt_ctrl->unit, reg, &rval, PHASE_SELf,
     56                           mt_ctrl->phase_sel_cur);
     57         soc_reg_field_set(mt_ctrl->unit, reg, &rval, OVRD_SM_ENf, 1);
     58         if (rval != oval) {
     59             SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval));
     60         }
     61     }
     62 
     63     return SOC_E_NONE;
     64 }
     65 
     66 STATIC int
     67 _soc_tr_ddr_latency_prog_hw_cb(soc_memtune_data_t *mt_data)
     68 {
     69     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
     70     soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data;
     71     soc_reg_t reg;
     72     uint32 oval, rval, addr, sel_early2, sel_early1;
     73 
     74     /* EM latency setting */
     75     if (mt_ctrl->em_latency_cur != -1) {
     76         reg = tr_mt_data->tmode0;
     77         addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0);
     78         SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
     79         oval = rval;
     80         soc_reg_field_set(mt_ctrl->unit, reg, &rval, EM_LATENCYf,
     81                           mt_ctrl->em_latency_cur & 0x7);
     82         if (soc_reg_field_valid(mt_ctrl->unit, reg, EM_LATENCY8f)) {
     83             soc_reg_field_set(mt_ctrl->unit, reg, &rval, EM_LATENCY8f,
     84                               mt_ctrl->em_latency_cur >> 3);
     85         }
     86         if (rval != oval) {
     87             SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval));
     88         }
     89     }
     90 
     91     /* DDR latency setting */
     92     if (mt_ctrl->ddr_latency_cur != -1) {
     93         /*
     94          * DDR latency settings
     95          * if latency == 0, select result from 2 steps earlier
     96          * if latency == 1, select result from 1 step earlier
     97          * if latency == 2, select regular result
     98          */
     99         sel_early1 = 0;
    100         sel_early2 = 0;
    101         if (mt_ctrl->ddr_latency_cur == 0) {
    102             sel_early2 = 1;
    103         } else if (mt_ctrl->ddr_latency_cur == 1) {
    104             sel_early1 = 1;
    105         }
    106 
    107         reg = tr_mt_data->config_reg2;
    108         addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0);
    109         SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
    110         oval = rval;
    111         if (mt_data->slice_mask & 0x1) {
    112             soc_reg_field_set(mt_ctrl->unit, reg, &rval, SEL_EARLY2_0f,
    113                               sel_early2);
    114             soc_reg_field_set(mt_ctrl->unit, reg, &rval, SEL_EARLY1_0f,
    115                               sel_early1);
    116         }
    117         if (mt_data->slice_mask & 0x2) {
    118             soc_reg_field_set(mt_ctrl->unit, reg, &rval, SEL_EARLY2_1f,
    119                               sel_early2);
    120             soc_reg_field_set(mt_ctrl->unit, reg, &rval, SEL_EARLY1_1f,
    121                               sel_early1);
    122         }
    123         if (rval != oval) {
    124             SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval));
    125         }
    126     }
    127 
    128     return SOC_E_NONE;
    129 }
    130 
    131 STATIC int
    132 _soc_tr_ddr_txrx_prog_hw_cb(soc_memtune_data_t *mt_data)
    133 {
    134     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
    135     soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data;
    136     soc_reg_t reg;
    137     uint32 oval, rval, addr;
    138 
    139     reg = tr_mt_data->config_reg1;
    140     addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0);
    141     SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
    142     oval = rval;
    143 
    144     /* TX phase offset settings */
    145     if (mt_ctrl->tx_offset_cur != -1) {
    146         soc_reg_field_set(mt_ctrl->unit, reg, &rval, DLL90_OFFSET_TXf,
    147                           mt_ctrl->tx_offset_cur & 0x0f);
    148         soc_reg_field_set(mt_ctrl->unit, reg, &rval, DLL90_OFFSET_TX4f,
    149                           mt_ctrl->tx_offset_cur >> 4);
    150     }
    151 
    152     /* RX phase offset settings */
    153     if (mt_ctrl->rx_offset_cur != -1) {
    154         soc_reg_field_set(mt_ctrl->unit, reg, &rval, DLL90_OFFSET_QKf,
    155                           mt_ctrl->rx_offset_cur & 0xf);
    156         soc_reg_field_set(mt_ctrl->unit, reg, &rval, DLL90_OFFSET_QKBf,
    157                           mt_ctrl->rx_offset_cur & 0xf);
    158         soc_reg_field_set(mt_ctrl->unit, reg, &rval, DLL90_OFFSET_QK4f,
    159                           mt_ctrl->rx_offset_cur >> 4);
    160         soc_reg_field_set(mt_ctrl->unit, reg, &rval, DLL90_OFFSET_QKB4f,
    161                           mt_ctrl->rx_offset_cur >> 4);
    162     }
    163 
    164     if (rval != oval) {
    165         SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval));
    166     }
    167 
    168     return SOC_E_NONE;
    169 }
    170 
    171 STATIC int
    172 _soc_tr_ddr_nops_prog_hw_cb(soc_memtune_data_t *mt_data)
    173 {
    174     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
    175     soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data;
    176     soc_reg_t reg;
    177     uint32 oval, rval, addr;
    178 
    179     reg = tr_mt_data->sram_ctl;
    180     addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0);
    181     SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
    182     oval = rval;
    183     if (mt_ctrl->r2w_nops_cur != -1) {
    184         soc_reg_field_set(mt_ctrl->unit, reg, &rval, NUM_R2W_NOPSf,
    185                           mt_ctrl->r2w_nops_cur);
    186     }
    187     if (mt_ctrl->w2r_nops_cur != -1) {
    188         soc_reg_field_set(mt_ctrl->unit, reg, &rval, NUM_W2R_NOPSf,
    189                           mt_ctrl->w2r_nops_cur);
    190     }
    191     if (rval != oval) {
    192         SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval));
    193     }
    194 
    195     return SOC_E_NONE;
    196 }
    197 
    198 STATIC int
    199 _soc_tr_ddr_per_rx_cb(soc_memtune_data_t *mt_data)
    200 {
    201     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
    202     soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data;
    203     soc_reg_t reg;
    204     uint32 rval, addr;
    205 
    206     reg = tr_mt_data->config_reg1;
    207     addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0);
    208     SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
    209     soc_reg_field_set(mt_ctrl->unit, reg, &rval, EN_RDFIFOf, 0);
    210     SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval));
    211     soc_reg_field_set(mt_ctrl->unit, reg, &rval, EN_RDFIFOf, 1);
    212     SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval));
    213 
    214     return SOC_E_NONE;
    215 }
    216 
    217 STATIC int
    218 _soc_tr_tcam_invert_clk_prog_hw_cb(soc_memtune_data_t *mt_data)
    219 {
    220     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
    221     soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data;
    222     soc_reg_t reg;
    223     uint32 oval, rval, addr;
    224 
    225     reg = tr_mt_data->config_reg3;
    226     addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0);
    227     SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
    228     oval = rval;
    229     if (mt_ctrl->invert_txclk_cur != -1) {
    230         soc_reg_field_set(mt_ctrl->unit, reg, &rval, INVERT_TXCLKf,
    231                           mt_ctrl->invert_txclk_cur);
    232     }
    233     if (mt_ctrl->invert_rxclk_cur != -1) {
    234         soc_reg_field_set(mt_ctrl->unit, reg, &rval, INVERT_RXCLKf,
    235                           mt_ctrl->invert_rxclk_cur);
    236     }
    237     if (rval != oval) {
    238         SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval));
    239     }
    240 
    241     return SOC_E_NONE;
    242 }
    243 
    244 STATIC int
    245 _soc_tr_tcam_txrx_prog_hw_cb(soc_memtune_data_t *mt_data)
    246 {
    247     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
    248     soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data;
    249     soc_reg_t reg;
    250     uint32 oval, rval, addr;
    251 
    252     reg = tr_mt_data->config_reg1;
    253     addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0);
    254     SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
    255     oval = rval;
    256     if (mt_ctrl->tx_offset_cur != -1) {
    257         soc_reg_field_set(mt_ctrl->unit, reg, &rval, VCDL_TX_OFFSETf,
    258                           mt_ctrl->tx_offset_cur & 0x1f);
    259         soc_reg_field_set(mt_ctrl->unit, reg, &rval, MSBMIDL_OFFSET_TXf,
    260                           mt_ctrl->tx_offset_cur >> 5);
    261     }
    262     if (mt_ctrl->rx_offset_cur != -1) {
    263         soc_reg_field_set(mt_ctrl->unit, reg, &rval, VCDL_RX_OFFSETf,
    264                           mt_ctrl->rx_offset_cur & 0x1f);
    265         soc_reg_field_set(mt_ctrl->unit, reg, &rval, MSBMIDL_OFFSET_RXf,
    266                           mt_ctrl->rx_offset_cur >> 5);
    267     }
    268     if (rval != oval) {
    269         SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval));
    270     }
    271 
    272     return SOC_E_NONE;
    273 }
    274 
    275 STATIC int
    276 _soc_tr_tcam_dpeo_rbus_prog_hw_cb(soc_memtune_data_t *mt_data)
    277 {
    278     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
    279     soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data;
    280     soc_reg_t reg;
    281     uint32 oval, rval, addr;
    282 
    283     reg = tr_mt_data->config_reg3;
    284     addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0);
    285     SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
    286     oval = rval;
    287     if (mt_ctrl->fcd_dpeo_cur != -1) {
    288         /*
    289          * DPEO_0 is connected to DPEO pin of first TCAM
    290          * DPEO_1 is connected to DPEO pin of optional second TCAM
    291          */
    292         if (!mt_ctrl->dpeo_sel_cur) {
    293             soc_reg_field_set(mt_ctrl->unit, reg, &rval, FCD_DPEO_0f,
    294                               mt_ctrl->fcd_dpeo_cur);
    295         } else {
    296             soc_reg_field_set(mt_ctrl->unit, reg, &rval, FCD_DPEO_1f,
    297                               mt_ctrl->fcd_dpeo_cur);
    298         }
    299     }
    300     if (mt_ctrl->fcd_rbus_cur != -1) {
    301         /* use fcd_rbus + 1 for FCD_SMFL_0 and FCD_SMFL_1 */
    302         soc_reg_field_set(mt_ctrl->unit, reg, &rval, FCD_SMFL_0f,
    303                           mt_ctrl->fcd_rbus_cur + 1);
    304         soc_reg_field_set(mt_ctrl->unit, reg, &rval, FCD_SMFL_1f,
    305                           mt_ctrl->fcd_rbus_cur + 1);
    306         /* use same value for FCD_RBUS and FCD_RV */
    307         soc_reg_field_set(mt_ctrl->unit, reg, &rval, FCD_RBUSf,
    308                           mt_ctrl->fcd_rbus_cur);
    309         soc_reg_field_set(mt_ctrl->unit, reg, &rval, FCD_RVf,
    310                           mt_ctrl->fcd_rbus_cur);
    311     }
    312     if (rval != oval) {
    313         SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval));
    314     }
    315 
    316     reg = tr_mt_data->etc_ctl;
    317     addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0);
    318     SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
    319     oval = rval;
    320     if (mt_ctrl->rbus_sync_dly_cur != -1) {
    321         soc_reg_field_set(mt_ctrl->unit, reg, &rval, RBUS_SYNC_DLYf,
    322                           mt_ctrl->rbus_sync_dly_cur);
    323     }
    324     if (mt_ctrl->dpeo_sync_dly_cur != -1) {
    325         soc_reg_field_set(mt_ctrl->unit, reg, &rval, DPEO_SYNC_DLYf,
    326                           mt_ctrl->dpeo_sync_dly_cur);
    327     }
    328     if (rval != oval) {
    329         SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval));
    330     }
    331 
    332     return SOC_E_NONE;
    333 }
    334 
    335 STATIC int
    336 _soc_tr_tcam_per_tx_cb(soc_memtune_data_t *mt_data)
    337 {
    338     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
    339     uint32 rval;
    340 
    341     if (SAL_BOOT_SIMULATION) {
    342         return SOC_E_NONE;
    343     }
    344 
    345     /*
    346      * Following is the notes from DE for TCAM reset:
    347      * Without this fix
    348      * - we see flaky extt result for 1 board which has
    349      * 36Mb__MCM_ext_tcam Eye will be completely 0 and then switch to normal
    350      * (even for same rc)
    351      * Why does it work?
    352      * - My guess is that changing of tx, disturbs the clock going to ext_tcam
    353      * and can throw PLL in ext_tcam off, and more so for dual-die ext_tcam
    354      */
    355     /* coverity[result_independent_of_operands] */
    356     SOC_IF_ERROR_RETURN(READ_CMIC_SOFT_RESET_REGr(mt_ctrl->unit, &rval));
    357     soc_reg_field_set(mt_ctrl->unit, CMIC_SOFT_RESET_REGr, &rval,
    358                       EXT_TCAM_RSTf, 1);
    359     /* coverity[result_independent_of_operands] */
    360     SOC_IF_ERROR_RETURN(WRITE_CMIC_SOFT_RESET_REGr(mt_ctrl->unit, rval));
    361     sal_usleep(1000);
    362     soc_reg_field_set(mt_ctrl->unit, CMIC_SOFT_RESET_REGr, &rval,
    363                       EXT_TCAM_RSTf, 0);
    364     /* coverity[result_independent_of_operands] */
    365     SOC_IF_ERROR_RETURN(WRITE_CMIC_SOFT_RESET_REGr(mt_ctrl->unit, rval));
    366     sal_usleep(1000);
    367 
    368     ((soc_tcam_info_t *)SOC_CONTROL(mt_ctrl->unit)->tcam_info)->num_tcams = 0;
    369 
    370     return SOC_E_NONE;
    371 }
    372 
    373 STATIC int
    374 _soc_tr_tcam_per_rx_cb(soc_memtune_data_t *mt_data)
    375 {
    376     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
    377     uint32 rval;
    378 
    379     if (SAL_BOOT_SIMULATION) {
    380         return SOC_E_NONE;
    381     }
    382 
    383     /*
    384      * Notes from DE for TCAM_PHY reset:
    385      * Without this fix
    386      * - we will see intermittent hard-failures in middle of tcam eye
    387      *   which leads to change in Tcam area when extt is run severa times
    388      * Why does it work?
    389      * - My guess is that changing of rx, changes the rx_clock in
    390      *   tcam_phy and disturbs the FIFO synchronizer logic
    391      */
    392     /* coverity[result_independent_of_operands] */
    393     SOC_IF_ERROR_RETURN(READ_CMIC_SOFT_RESET_REGr(mt_ctrl->unit, &rval));
    394     soc_reg_field_set(mt_ctrl->unit, CMIC_SOFT_RESET_REGr, &rval,
    395                       CMIC_TCAM_RST_Lf, 0);
    396     /* coverity[result_independent_of_operands] */
    397     SOC_IF_ERROR_RETURN(WRITE_CMIC_SOFT_RESET_REGr(mt_ctrl->unit, rval));
    398     sal_usleep(10);
    399     soc_reg_field_set(mt_ctrl->unit, CMIC_SOFT_RESET_REGr, &rval,
    400                       CMIC_TCAM_RST_Lf, 1);
    401     /* coverity[result_independent_of_operands] */
    402     SOC_IF_ERROR_RETURN(WRITE_CMIC_SOFT_RESET_REGr(mt_ctrl->unit, rval));
    403     sal_usleep(10);
    404 
    405     return SOC_E_NONE;
    406 }
    407 
    408 STATIC int
    409 _soc_tr_sram_tune_test_cb(soc_memtune_data_t *mt_data)
    410 {
    411     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
    412     tr_ext_sram_bist_t *sram_bist = mt_ctrl->sram_bist;
    413     int loop_mode, i;
    414 
    415     sram_bist->w2r_nops = mt_ctrl->w2r_nops_cur;
    416     sram_bist->r2w_nops = mt_ctrl->r2w_nops_cur;
    417     sram_bist->bg_tcam_loop_count = 1;
    418 
    419     for (i = 0; i < mt_data->test_count; i++) {
    420         for (loop_mode = 1; loop_mode < 4; loop_mode++) {
    421             if (loop_mode == 1) { /* RR */
    422                 sram_bist->loop_mode = 0; /* WW */
    423                 SOC_IF_ERROR_RETURN
    424                     (soc_triumph_ext_sram_enable_set(mt_ctrl->unit,
    425                                                      mt_data->sub_interface,
    426                                                      TRUE, TRUE));
    427                 SOC_IF_ERROR_RETURN
    428                     (soc_triumph_ext_sram_bist_setup(mt_ctrl->unit,
    429                                                      mt_data->sub_interface,
    430                                                      sram_bist));
    431                 SOC_IF_ERROR_RETURN
    432                     (soc_triumph_ext_sram_op(mt_ctrl->unit,
    433                                              mt_data->sub_interface,
    434                                              sram_bist, NULL));
    435             }
    436             sram_bist->loop_mode = loop_mode;
    437             SOC_IF_ERROR_RETURN
    438                 (soc_triumph_ext_sram_enable_set(mt_ctrl->unit,
    439                                                  mt_data->sub_interface,
    440                                                  TRUE, TRUE));
    441             SOC_IF_ERROR_RETURN
    442                 (soc_triumph_ext_sram_bist_setup(mt_ctrl->unit,
    443                                                  mt_data->sub_interface,
    444                                                  sram_bist));
    445             SOC_IF_ERROR_RETURN
    446                 (soc_triumph_ext_sram_op(mt_ctrl->unit, mt_data->sub_interface,
    447                                          sram_bist, NULL));
    448             SOC_IF_ERROR_RETURN
    449                 (soc_triumph_ext_sram_enable_set(mt_ctrl->unit,
    450                                                  mt_data->sub_interface,
    451                                                  FALSE, FALSE));
    452             if (sram_bist->err_cnt) {
    453                 mt_ctrl->cur_fail_count++;
    454                 if (mt_ctrl->cur_fail_count >= mt_data->max_fail_count) {
    455                     return SOC_E_NONE;
    456                 }
    457                 continue;
    458             }
    459         }
    460     }
    461 
    462     if (mt_ctrl->cur_fail_count == 0) {
    463         SOC_IF_ERROR_RETURN
    464             (soc_triumph_ext_sram_enable_set(mt_ctrl->unit,
    465                                              mt_data->sub_interface,
    466                                              TRUE, TRUE));
    467         sram_bist->loop_mode = 3; /* WW_RR */
    468         sram_bist->bg_tcam_loop_count =
    469             mt_data->bg_tcam_bist ? mt_data->bg_tcam_loop_count : 1;
    470         SOC_IF_ERROR_RETURN
    471             (soc_triumph_ext_sram_bist_setup(mt_ctrl->unit,
    472                                              mt_data->sub_interface,
    473                                              sram_bist));
    474         SOC_IF_ERROR_RETURN
    475             (soc_triumph_ext_sram_op(mt_ctrl->unit, mt_data->sub_interface,
    476                                      sram_bist, NULL));
    477         SOC_IF_ERROR_RETURN
    478             (soc_triumph_ext_sram_enable_set(mt_ctrl->unit,
    479                                              mt_data->sub_interface,
    480                                              FALSE, FALSE));
    481         if (sram_bist->err_cnt) {
    482             mt_ctrl->cur_fail_count++;
    483         }
    484     }
    485 
    486     return SOC_E_NONE;
    487 }
    488 
    489 STATIC int
    490 _soc_tr_tcam_tune_test_cb(soc_memtune_data_t *mt_data)
    491 {
    492     soc_tcam_info_t *tcam_info;
    493     soc_tcam_partition_t *partitions;
    494     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
    495     soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data;
    496     uint32 rval;
    497     int rv, addr, i;
    498     uint32 exp_dpeo_rise, exp_dpeo_fall;
    499     uint32 pattern[4];
    500     uint32 data[8], data_miss[8];
    501     int index, exp_result0[2], exp_result1[2], result0, result1, valid;
    502     uint32 mask[4];
    503 
    504     tcam_info = SOC_CONTROL(mt_ctrl->unit)->tcam_info;
    505     partitions = tcam_info->partitions;
    506 
    507     addr = soc_reg_addr(mt_ctrl->unit, tr_mt_data->inst_status, REG_PORT_ANY,
    508                         0);
    509 
    510     switch (mt_data->sub_interface) {
    511     case 0: /* DBUS */
    512         pattern[0] = 0xffffffff;
    513         pattern[1] = 0x00000000;
    514         pattern[2] = 0x55555555;
    515         pattern[3] = 0xaaaaaaaa;
    516         mask[0] = mask[1] = mask[2] = mask[3] = 0;
    517 
    518         /* Use the last few entries in the firts block of the first device */
    519         index = 16380;
    520         for (i = 0; i < 4; i ++) {
    521             data[0] = 0;
    522             data[1] = pattern[i] & 0xff;
    523             data[2] = data[3] = pattern[i];
    524             SOC_IF_ERROR_RETURN
    525                 (soc_tcam_write_entry(mt_ctrl->unit, TCAM_PARTITION_DEV0_TBL72,
    526                                       index + i, mask, data));
    527         }
    528         for (i = 0; i < 4; i ++) {
    529             rv = soc_tcam_read_entry(mt_ctrl->unit, TCAM_PARTITION_DEV0_TBL72,
    530                                      index + i, mask, data, &valid);
    531             SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
    532             if (rv < 0 || (rval & tr_mt_data->dbus_fail_mask)) {
    533                 mt_ctrl->cur_fail_count = mt_data->test_count;
    534                 mt_ctrl->cur_fail_reason = 0x10000;
    535                 mt_ctrl->cur_fail_detail0 = rval;
    536                 break;
    537             }
    538             if (data[1] != (pattern[i] & 0xff) || data[2] != pattern[i] ||
    539                 data[3] != pattern[i]) {
    540                 mt_ctrl->cur_fail_count = mt_data->test_count;
    541                 mt_ctrl->cur_fail_reason = 0x20000;
    542                 mt_ctrl->cur_fail_detail0 = i;
    543                 break;
    544             }
    545         }
    546         if (mt_ctrl->cur_fail_count) {
    547             break;
    548         }
    549 
    550         if (tcam_info->num_tcams == 1 || tcam_info->monolith_dev) {
    551             /* not MCM device */
    552             break;
    553         }
    554 
    555         /* Use the last few entries in the first block of the second device */
    556         index = 16380;
    557         for (i = 0; i < 4; i ++) {
    558             data[0] = 0;
    559             data[1] = pattern[i] & 0xff;
    560             data[2] = data[3] = pattern[i];
    561             SOC_IF_ERROR_RETURN
    562                 (soc_tcam_write_entry(mt_ctrl->unit, TCAM_PARTITION_DEV1_TBL72,
    563                                       index + i, mask, data));
    564         }
    565         for (i = 0; i < 4; i ++) {
    566             rv = soc_tcam_read_entry(mt_ctrl->unit, TCAM_PARTITION_DEV1_TBL72,
    567                                      index + i, mask, data, &valid);
    568             SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
    569             if (rv < 0 || (rval & tr_mt_data->dbus_fail_mask)) {
    570                 mt_ctrl->cur_fail_count = mt_data->test_count;
    571                 mt_ctrl->cur_fail_reason = 0x10001;
    572                 mt_ctrl->cur_fail_detail0 = rval;
    573                 break;
    574             }
    575             if (data[1] != (pattern[i] & 0xff) || data[2] != pattern[i] ||
    576                 data[3] != pattern[i]) {
    577                 mt_ctrl->cur_fail_count = mt_data->test_count;
    578                 mt_ctrl->cur_fail_reason = 0x20001;
    579                 mt_ctrl->cur_fail_detail0 = i;
    580                 break;
    581             }
    582         }
    583         break;
    584 
    585     case 1: /* DBUS_out (DPEO) */
    586         sal_memset(data, 0, sizeof(data));
    587         data[0] = data[4] = 0xabcd;
    588         SOC_IF_ERROR_RETURN
    589             (soc_tr_tcam_type1_memtest_dpeo(mt_ctrl->unit, 2, 0x3, data));
    590         SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
    591         /*
    592          * DPEO_0 is connected to DPEO pin of first TCAM
    593          * DPEO_1 is connected to DPEO pin of optional second TCAM
    594          */
    595         if (!mt_ctrl->dpeo_sel_cur) { /* DPEO_0 */
    596             exp_dpeo_rise = 1;
    597             exp_dpeo_fall = 1;
    598         } else { /* DPEO_1 */
    599             exp_dpeo_rise = 2;
    600             exp_dpeo_fall = 2;
    601         }
    602         if (!soc_reg_field_get(mt_ctrl->unit, tr_mt_data->inst_status, rval,
    603                                SEQ_DPEO_ERRf) ||
    604             soc_reg_field_get(mt_ctrl->unit, tr_mt_data->inst_status, rval,
    605                               DPEO_RISEf) != exp_dpeo_rise ||
    606             soc_reg_field_get(mt_ctrl->unit, tr_mt_data->inst_status, rval,
    607                               DPEO_FALLf) != exp_dpeo_fall) {
    608             mt_ctrl->cur_fail_count = mt_data->test_count;
    609             mt_ctrl->cur_fail_detail0 = rval;
    610         }
    611         break;
    612 
    613     case 2: /* RBUS */
    614         if (mt_data->mask[0] == 0xffffffff) {
    615             sal_memset(mask, 0, sizeof(mask));
    616             sal_memset(data, 0, sizeof(data));
    617             /* all '1's for lower 72-bit, all '0's for upper 72-bit */
    618             data[5] = 0xff;
    619             data[6] = data[7] = 0xffffffff;
    620         } else {
    621             sal_memcpy(mask, mt_data->mask, sizeof(mask));
    622             sal_memcpy(data, mt_data->data, sizeof(data));
    623         }
    624         sal_memcpy(data_miss, data, sizeof(data_miss));
    625         data_miss[7] ^= 1; /* use a bogus key to cause a miss */
    626 
    627         /* first do a search miss, ignore result index */
    628         rv = soc_tcam_search_entry(mt_ctrl->unit, TCAM_PARTITION_DEV0_TBL72,
    629                                    TCAM_PARTITION_DEV0_TBL144, data_miss,
    630                                    &result0, &result1);
    631         if (SOC_FAILURE(rv) && rv != SOC_E_NOT_FOUND) {
    632             return rv;
    633         }
    634         /* then do a search hit, ignore result index, only check for status */
    635         rv = soc_tcam_search_entry(mt_ctrl->unit, TCAM_PARTITION_DEV0_TBL72,
    636                                    TCAM_PARTITION_DEV0_TBL144, data,
    637                                    &result0, &result1);
    638         if (SOC_FAILURE(rv) && rv != SOC_E_NOT_FOUND) {
    639             return rv;
    640         }
    641         SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
    642         if (rval & tr_mt_data->rbus_fail_mask) {
    643             mt_ctrl->cur_fail_count = mt_data->test_count;
    644             mt_ctrl->cur_fail_reason = 0x10000;
    645             mt_ctrl->cur_fail_detail0 = rval;
    646             break;
    647         }
    648         if ((rval & tr_mt_data->rbus_valid_mask) !=
    649             tr_mt_data->rbus_valid_mask) {
    650             mt_ctrl->cur_fail_count = mt_data->test_count;
    651             mt_ctrl->cur_fail_reason = 0x20000;
    652             mt_ctrl->cur_fail_detail0 = rval;
    653             break;
    654         }
    655 
    656         if (!partitions[TCAM_PARTITION_DEV1_TBL72].num_entries ||
    657             !partitions[TCAM_PARTITION_DEV1_TBL144].num_entries) {
    658             /* not MCM device */
    659             break;
    660         }
    661 
    662         /* first do a search miss, ignore result index */
    663         rv = soc_tcam_search_entry(mt_ctrl->unit, TCAM_PARTITION_DEV1_TBL72,
    664                                    TCAM_PARTITION_DEV1_TBL144, data_miss,
    665                                    &result0, &result1);
    666         if (SOC_FAILURE(rv) && rv != SOC_E_NOT_FOUND) {
    667             return rv;
    668         }
    669         /* then do a search hit, ignore result index, only check for status */
    670         rv = soc_tcam_search_entry(mt_ctrl->unit, TCAM_PARTITION_DEV1_TBL72,
    671                                    TCAM_PARTITION_DEV1_TBL144, data,
    672                                    &result0, &result1);
    673         if (SOC_FAILURE(rv) && rv != SOC_E_NOT_FOUND) {
    674             return rv;
    675         }
    676         SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
    677         if (rval & tr_mt_data->rbus_fail_mask) {
    678             mt_ctrl->cur_fail_count = mt_data->test_count;
    679             mt_ctrl->cur_fail_reason = 0x10001;
    680             mt_ctrl->cur_fail_detail0 = rval;
    681             break;
    682         }
    683         if ((rval & tr_mt_data->rbus_valid_mask) !=
    684             tr_mt_data->rbus_valid_mask) {
    685             mt_ctrl->cur_fail_count = mt_data->test_count;
    686             mt_ctrl->cur_fail_reason = 0x20001;
    687             mt_ctrl->cur_fail_detail0 = rval;
    688             break;
    689         }
    690         break;
    691 
    692     case 3: /* search test */
    693         /* No reset on simulation, put test entry at index 0 to avoid hitting
    694          * leftover entries */
    695         index = SAL_BOOT_SIMULATION ? 0 : 0x1555;
    696         if (mt_data->mask[0] == 0xffffffff) {
    697             sal_memset(mask, 0, sizeof(mask));
    698             sal_memset(data, 0, sizeof(data));
    699             /* all '1's for lower 72-bit, all '0's for upper 72-bit */
    700             data[5] = 0xff;
    701             data[6] = data[7] = 0xffffffff;
    702         } else {
    703             sal_memcpy(mask, mt_data->mask, sizeof(mask));
    704             sal_memcpy(data, mt_data->data, sizeof(data));
    705         }
    706 
    707         exp_result0[0] = partitions[TCAM_PARTITION_DEV0_TBL72].tcam_base +
    708             (index  << partitions[TCAM_PARTITION_DEV0_TBL72].tcam_width_shift);
    709         exp_result1[0] = partitions[TCAM_PARTITION_DEV0_TBL144].tcam_base +
    710             (index  <<
    711              partitions[TCAM_PARTITION_DEV0_TBL144].tcam_width_shift);
    712         exp_result0[1] = partitions[TCAM_PARTITION_DEV1_TBL72].tcam_base +
    713             (index  << partitions[TCAM_PARTITION_DEV1_TBL72].tcam_width_shift);
    714         exp_result1[1] = partitions[TCAM_PARTITION_DEV1_TBL144].tcam_base +
    715             (index  <<
    716              partitions[TCAM_PARTITION_DEV1_TBL144].tcam_width_shift);
    717 
    718         for (i = 0; i < mt_data->test_count; i++) {
    719             rv = soc_tcam_search_entry(mt_ctrl->unit,
    720                                        TCAM_PARTITION_DEV0_TBL72,
    721                                        TCAM_PARTITION_DEV0_TBL144,
    722                                        data, &result0, &result1);
    723             SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
    724             if (rv < 0 || (rval & tr_mt_data->rbus_fail_mask)) {
    725                 mt_ctrl->cur_fail_count++;
    726                 mt_ctrl->cur_fail_reason = 0x10000;
    727                 mt_ctrl->cur_fail_detail0 = rval;
    728                 continue;
    729             }
    730 
    731             if (result0 != exp_result0[0] || result1 != exp_result1[0]) {
    732                 mt_ctrl->cur_fail_count++;
    733                 mt_ctrl->cur_fail_reason = 0x20000;
    734                 mt_ctrl->cur_fail_detail0 = result0;
    735                 mt_ctrl->cur_fail_detail1 = result1;
    736                 continue;
    737             }
    738 
    739             rv = soc_triumph_tcam_search_bist(mt_ctrl->unit,
    740                                               TCAM_PARTITION_DEV0_TBL72,
    741                                               TCAM_PARTITION_DEV0_TBL144,
    742                                               data,
    743                                               exp_result0[0], exp_result1[0],
    744                                               mt_data->tcam_loop_count);
    745             if (rv < 0) {
    746                 mt_ctrl->cur_fail_count++;
    747                 mt_ctrl->cur_fail_reason = 0x30000;
    748                 continue;
    749             }
    750 
    751             if (!partitions[TCAM_PARTITION_DEV1_TBL72].num_entries ||
    752                 !partitions[TCAM_PARTITION_DEV1_TBL144].num_entries) {
    753                 /* not MCM device */
    754                 continue;
    755             }
    756 
    757             rv = soc_tcam_search_entry(mt_ctrl->unit,
    758                                        TCAM_PARTITION_DEV1_TBL72,
    759                                        TCAM_PARTITION_DEV1_TBL144,
    760                                        data, &result0, &result1);
    761             SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
    762             if (rv < 0 || (rval & tr_mt_data->rbus_fail_mask)) {
    763                 mt_ctrl->cur_fail_count++;
    764                 mt_ctrl->cur_fail_reason = 0x10001;
    765                 continue;
    766             }
    767 
    768             if (result0 != exp_result0[1] || result1 != exp_result1[1]) {
    769                 mt_ctrl->cur_fail_count++;
    770                 mt_ctrl->cur_fail_reason = 0x20001;
    771                 mt_ctrl->cur_fail_detail0 = result0;
    772                 mt_ctrl->cur_fail_detail1 = result1;
    773                 continue;
    774             }
    775 
    776             rv = soc_triumph_tcam_search_bist(mt_ctrl->unit,
    777                                               TCAM_PARTITION_DEV1_TBL72,
    778                                               TCAM_PARTITION_DEV1_TBL144,
    779                                               data,
    780                                               exp_result0[1], exp_result1[1],
    781                                               mt_data->tcam_loop_count);
    782             if (rv < 0) {
    783                 mt_ctrl->cur_fail_count++;
    784                 mt_ctrl->cur_fail_reason = 0x30001;
    785                 continue;
    786             }
    787         }
    788 
    789         break;
    790 
    791     default:
    792         break;
    793     }
    794 
    795     return SOC_E_NONE;
    796 }
    797 
    798 STATIC int
    799 _soc_tr_tune_generate_config(soc_memtune_data_t *mt_data)
    800 {
    801 #ifndef NO_MEMTUNE
    802     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
    803     soc_memtune_result_t *result;
    804     uint32 rval, val, pvt_val;
    805     char name_str[23], val_str[11];
    806     int use_midl;
    807 
    808     pvt_val = 0;
    809     if (mt_ctrl->odtres_val != -1) {
    810         pvt_val |= SOC_TR_MEMTUNE_OVRD_ODTRES_MASK <<
    811             SOC_TR_MEMTUNE_OVRD_ODTRES_SHIFT;
    812         pvt_val |= (mt_ctrl->odtres_val & SOC_TR_MEMTUNE_ODTRES_MASK) <<
    813             SOC_TR_MEMTUNE_ODTRES_SHIFT;
    814     }
    815     if (mt_ctrl->ndrive_val != -1 && mt_ctrl->pdrive_val != -1) {
    816         pvt_val |= SOC_TR_MEMTUNE_OVRD_DRIVER_MASK <<
    817             SOC_TR_MEMTUNE_OVRD_DRIVER_SHIFT;
    818         pvt_val |= (mt_ctrl->pdrive_val & SOC_TR_MEMTUNE_PDRIVE_MASK) <<
    819             SOC_TR_MEMTUNE_PDRIVE_SHIFT;
    820         pvt_val |= (mt_ctrl->ndrive_val & SOC_TR_MEMTUNE_NDRIVE_MASK) <<
    821             SOC_TR_MEMTUNE_NDRIVE_SHIFT;
    822     }
    823     if (mt_ctrl->slew_val != -1) {
    824         pvt_val |= SOC_TR_MEMTUNE_OVRD_SLEW_MASK <<
    825             SOC_TR_MEMTUNE_OVRD_SLEW_SHIFT;
    826         pvt_val |= (mt_ctrl->slew_val & SOC_TR_MEMTUNE_SLEW_MASK) <<
    827             SOC_TR_MEMTUNE_SLEW_SHIFT;
    828     }
    829 
    830     switch (mt_data->interface) {
    831     case SOC_MEM_INTERFACE_SRAM:
    832         val = 0;
    833         if (mt_ctrl->phase_sel_cur != -1) {
    834             val |= SOC_TR_MEMTUNE_OVRD_SM_MASK <<
    835                 SOC_TR_MEMTUNE_OVRD_SM_SHIFT;
    836             val |= (mt_ctrl->phase_sel_cur & SOC_TR_MEMTUNE_PHASE_SEL_MASK) <<
    837                 SOC_TR_MEMTUNE_PHASE_SEL_SHIFT;
    838         }
    839         if (mt_ctrl->ddr_latency_cur != -1) {
    840             val |=
    841                 (mt_ctrl->ddr_latency_cur & SOC_TR_MEMTUNE_DDR_LATENCY_MASK) <<
    842                 SOC_TR_MEMTUNE_DDR_LATENCY_SHIFT;
    843         }
    844 
    845         sal_sprintf(val_str, "0x%08x",
    846                     SOC_TR_MEMTUNE_CONFIG_VALID_MASK |
    847                     val |
    848                     /* use 0 in the 3-bit field to represent EM_LATENCY is 8 */
    849                     ((mt_ctrl->em_latency_cur &
    850                       SOC_TR_MEMTUNE_EM_LATENCY_MASK) <<
    851                      SOC_TR_MEMTUNE_EM_LATENCY_SHIFT) |
    852                     ((mt_ctrl->tx_offset_cur &
    853                       SOC_TR_MEMTUNE_DDR_TX_OFFSET_MASK) <<
    854                      SOC_TR_MEMTUNE_DDR_TX_OFFSET_SHIFT) |
    855                     ((mt_ctrl->rx_offset_cur &
    856                       SOC_TR_MEMTUNE_DDR_RX_OFFSET_MASK) <<
    857                      SOC_TR_MEMTUNE_DDR_RX_OFFSET_SHIFT) |
    858                     ((mt_ctrl->w2r_nops_cur & SOC_TR_MEMTUNE_W2R_NOPS_MASK) <<
    859                      SOC_TR_MEMTUNE_W2R_NOPS_SHIFT) |
    860                     ((mt_ctrl->r2w_nops_cur & SOC_TR_MEMTUNE_R2W_NOPS_MASK) <<
    861                      SOC_TR_MEMTUNE_R2W_NOPS_SHIFT) |
    862                     ((mt_data->freq & SOC_TR_MEMTUNE_DDR_FREQ_MASK) <<
    863                      SOC_TR_MEMTUNE_DDR_FREQ_SHIFT));
    864         sal_sprintf(name_str, "%s%d.%d", spn_EXT_SRAM_TUNING,
    865                     mt_data->sub_interface, mt_ctrl->unit);
    866         if (_mem_config_set(name_str, val_str) < 0) {
    867             return SOC_E_MEMORY;
    868         }
    869         if (pvt_val) {
    870             sal_sprintf(val_str, "0x%08x",
    871                         SOC_TR_MEMTUNE_CONFIG_VALID_MASK | pvt_val);
    872             sal_sprintf(name_str, "%s%d.%d", spn_EXT_SRAM_PVT,
    873                         mt_data->sub_interface, mt_ctrl->unit);
    874             if (_mem_config_set(name_str, val_str) < 0) {
    875                 return SOC_E_MEMORY;
    876             }
    877         }
    878         if (mt_ctrl->tx_offset_min == mt_ctrl->tx_offset_max ||
    879             mt_ctrl->rx_offset_min == mt_ctrl->rx_offset_max) {
    880             break;
    881         }
    882         if (mt_ctrl->phase_sel_cur != -1) {
    883             result = mt_ctrl->ps_data[mt_ctrl->phase_sel_cur];
    884         } else {
    885             result = mt_ctrl->ps_data[0];
    886         }
    887         sal_sprintf(val_str, "0x%08x",
    888                     SOC_TR_MEMTUNE_CONFIG_VALID_MASK |
    889                     ((result->width & SOC_TR_MEMTUNE_STATS_WIDTH_MASK) <<
    890                      SOC_TR_MEMTUNE_STATS_WIDTH_SHIFT) |
    891                     ((result->height & SOC_TR_MEMTUNE_STATS_HEIGHT_MASK) <<
    892                      SOC_TR_MEMTUNE_STATS_HEIGHT_SHIFT) |
    893                     ((result->fail_count & SOC_TR_MEMTUNE_STATS_FAIL_MASK) <<
    894                      SOC_TR_MEMTUNE_STATS_FAIL_SHIFT));
    895         sal_sprintf(name_str, "%s%d.%d", spn_EXT_SRAM_TUNING_STATS,
    896                     mt_data->sub_interface, mt_ctrl->unit);
    897         if (_mem_config_set(name_str, val_str) < 0) {
    898             return SOC_E_MEMORY;
    899         }
    900         break;
    901     case SOC_MEM_INTERFACE_TCAM:
    902         SOC_IF_ERROR_RETURN(READ_ETU_DDR72_CONFIG_REG1_ISr(mt_ctrl->unit,
    903                                                            &rval));
    904         use_midl =
    905             soc_reg_field_get(mt_ctrl->unit, ETU_DDR72_CONFIG_REG1_ISr, rval,
    906                               MIDL_TX_ENf) &&
    907             soc_reg_field_get(mt_ctrl->unit, ETU_DDR72_CONFIG_REG1_ISr, rval,
    908                               SEL_TX_CLKDLY_BLKf) ? 1 : 0;
    909         sal_sprintf(val_str, "0x%08x",
    910                     SOC_TR_MEMTUNE_CONFIG_VALID_MASK |
    911                     ((mt_ctrl->fcd_dpeo_cur & SOC_TR_MEMTUNE_FCD_DPEO_MASK) <<
    912                      SOC_TR_MEMTUNE_FCD_DPEO_SHIFT) |
    913                     ((mt_ctrl->dpeo_sync_dly_cur &
    914                       SOC_TR_MEMTUNE_DPEO_SYNC_DLY_MASK) <<
    915                      SOC_TR_MEMTUNE_DPEO_SYNC_DLY_SHIFT) |
    916                     ((mt_ctrl->fcd_rbus_cur & SOC_TR_MEMTUNE_FCD_RBUS_MASK) <<
    917                      SOC_TR_MEMTUNE_FCD_RBUS_SHIFT) |
    918                     ((mt_ctrl->rbus_sync_dly_cur &
    919                       SOC_TR_MEMTUNE_RBUS_SYNC_DLY_MASK) <<
    920                      SOC_TR_MEMTUNE_RBUS_SYNC_DLY_SHIFT));
    921         sal_sprintf(name_str, "%s0.%d", spn_EXT_TCAM_TUNING, mt_ctrl->unit);
    922         if (_mem_config_set(name_str, val_str) < 0) {
    923             return SOC_E_MEMORY;
    924         }
    925         val = 0;
    926         if (mt_ctrl->invert_txclk_cur != -1) {
    927             val |= (mt_ctrl->invert_txclk_cur &
    928                     SOC_TR_MEMTUNE_INVERT_TXCLK_MASK) <<
    929                 SOC_TR_MEMTUNE_INVERT_TXCLK_SHIFT;
    930         }
    931         if (mt_ctrl->invert_rxclk_cur != -1) {
    932             val |= (mt_ctrl->invert_rxclk_cur &
    933                     SOC_TR_MEMTUNE_INVERT_RXCLK_MASK) <<
    934                 SOC_TR_MEMTUNE_INVERT_RXCLK_SHIFT;
    935         }
    936         sal_sprintf(val_str, "0x%08x",
    937                     SOC_TR_MEMTUNE_CONFIG_VALID_MASK |
    938                     val |
    939                     ((mt_ctrl->tx_offset_cur &
    940                       SOC_TR_MEMTUNE_TCAM_TX_OFFSET_MASK) <<
    941                      SOC_TR_MEMTUNE_TCAM_TX_OFFSET_SHIFT) |
    942                     ((mt_ctrl->rx_offset_cur &
    943                       SOC_TR_MEMTUNE_TCAM_RX_OFFSET_MASK) <<
    944                      SOC_TR_MEMTUNE_TCAM_RX_OFFSET_SHIFT) |
    945                     ((mt_data->freq &
    946                       SOC_TR_MEMTUNE_TCAM_FREQ_MASK) <<
    947                      SOC_TR_MEMTUNE_TCAM_FREQ_SHIFT) |
    948                     ((use_midl & SOC_TR_MEMTUNE_USE_MIDL_MASK) <<
    949                      SOC_TR_MEMTUNE_USE_MIDL_SHIFT));
    950         sal_sprintf(name_str, "%s1.%d", spn_EXT_TCAM_TUNING, mt_ctrl->unit);
    951         if (_mem_config_set(name_str, val_str) < 0) {
    952             return SOC_E_MEMORY;
    953         }
    954         if (pvt_val) {
    955             sal_sprintf(val_str, "0x%08x",
    956                         SOC_TR_MEMTUNE_CONFIG_VALID_MASK | pvt_val);
    957             sal_sprintf(name_str, "%s.%d", spn_EXT_TCAM_PVT, mt_ctrl->unit);
    958             if (_mem_config_set(name_str, val_str) < 0) {
    959                 return SOC_E_MEMORY;
    960             }
    961         }
    962         if (mt_ctrl->tx_offset_min == mt_ctrl->tx_offset_max ||
    963             mt_ctrl->rx_offset_min == mt_ctrl->rx_offset_max) {
    964             break;
    965         }
    966         if (mt_ctrl->invert_txclk_cur != -1 &&
    967             mt_ctrl->invert_rxclk_cur != -1) {
    968             result = &mt_ctrl->result[mt_ctrl->invert_txclk_cur * 2 +
    969                                       mt_ctrl->invert_rxclk_cur];
    970         } else {
    971             result = &mt_ctrl->result[0];
    972         }
    973         sal_sprintf(val_str, "0x%08x",
    974                     SOC_TR_MEMTUNE_CONFIG_VALID_MASK |
    975                     ((result->width & SOC_TR_MEMTUNE_STATS_WIDTH_MASK) <<
    976                      SOC_TR_MEMTUNE_STATS_WIDTH_SHIFT) |
    977                     ((result->height & SOC_TR_MEMTUNE_STATS_HEIGHT_MASK) <<
    978                      SOC_TR_MEMTUNE_STATS_HEIGHT_SHIFT) |
    979                     ((result->fail_count & SOC_TR_MEMTUNE_STATS_FAIL_MASK) <<
    980                      SOC_TR_MEMTUNE_STATS_FAIL_SHIFT));
    981         sal_sprintf(name_str, "%s.%d", spn_EXT_TCAM_TUNING_STATS,
    982                     mt_ctrl->unit);
    983         if (_mem_config_set(name_str, val_str) < 0) {
    984             return SOC_E_MEMORY;
    985         }
    986         break;
    987     default:
    988         break;
    989     }
    990 #endif /* NO_MEMTUNE */
    991 
    992     return SOC_E_NONE;
    993 }
    994 #endif /* BCM_TRIUMPH_SUPPORT */
    995 
    996 #define ABS(n) (((n) < 0) ? -(n) : (n))
    997 
    998 STATIC void
    999 _soc_memtune_get_txrx_area(soc_memtune_data_t *mt_data,
   1000                            int tx_offset, int rx_offset,
   1001                            int *width, int *height)
   1002 {
   1003     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
   1004     int best_area, best_shape, area, shape;
   1005     int dt, dr, max_dt, max_dr, index, num_rx;
   1006 
   1007     num_rx = mt_ctrl->rx_offset_max - mt_ctrl->rx_offset_min + 1;
   1008     index = (tx_offset - mt_ctrl->tx_offset_min) * num_rx +
   1009             rx_offset - mt_ctrl->rx_offset_min;
   1010     if (mt_ctrl->fail_array[index] > 0) {
   1011         *width = *height = 0;
   1012         return;
   1013     }
   1014 
   1015     max_dt = (mt_ctrl->tx_offset_max - mt_ctrl->tx_offset_min) / 2 + 1;
   1016     for (dt = 1; dt < max_dt; dt++) {
   1017         if (tx_offset - dt < mt_ctrl->tx_offset_min ||
   1018             tx_offset + dt > mt_ctrl->tx_offset_max ||
   1019             mt_ctrl->fail_array[index - dt * num_rx] > 0 ||
   1020             mt_ctrl->fail_array[index + dt * num_rx] > 0) {
   1021             max_dt = dt;
   1022             break;
   1023         }
   1024     }
   1025 
   1026     max_dr = (mt_ctrl->rx_offset_max - mt_ctrl->rx_offset_min) / 2 + 1;
   1027     for (dr = 1; dr < max_dr; dr++) {
   1028         if (rx_offset - dr < mt_ctrl->rx_offset_min ||
   1029             rx_offset + dr > mt_ctrl->rx_offset_max ||
   1030             mt_ctrl->fail_array[index - dr] > 0 ||
   1031             mt_ctrl->fail_array[index + dr] > 0) {
   1032             max_dr = dr;
   1033             break;
   1034         }
   1035     }
   1036 
   1037     area = max_dr * 2 - 1;
   1038     shape = area - 1;
   1039     best_area = area;
   1040     best_shape = shape;
   1041     *width = area;
   1042     *height = 1;
   1043 
   1044     for (dt = 1; dt < max_dt; dt++) {
   1045         for (dr = 1; dr < max_dr; dr++) {
   1046             if (mt_ctrl->fail_array[index - dt * num_rx - dr] > 0 ||
   1047                 mt_ctrl->fail_array[index - dt * num_rx + dr] > 0 ||
   1048                 mt_ctrl->fail_array[index + dt * num_rx - dr] > 0 ||
   1049                 mt_ctrl->fail_array[index + dt * num_rx + dr] > 0) {
   1050                 max_dr = dr;
   1051                 break;
   1052             }
   1053         }
   1054 
   1055         dr--;
   1056         area = (dt * 2 + 1) * (dr * 2 + 1);
   1057         shape = ABS(dt - dr) * 2;
   1058         if (area > best_area ||
   1059             (area == best_area && shape < best_shape)) {
   1060             best_area = area;
   1061             best_shape = shape;
   1062             *width = dr * 2 + 1;
   1063             *height = dt * 2 + 1;
   1064         }
   1065     }
   1066 }
   1067 
   1068 STATIC int
   1069 _soc_memtune_txrx_analyze(soc_memtune_data_t *mt_data)
   1070 {
   1071     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
   1072     soc_memtune_result_t *result;
   1073     int offset_count, fail_count;
   1074     int index, tx_offset, rx_offset;
   1075     int area, shape, width, height;
   1076     int best_area, best_shape, best_width, best_height;
   1077     char buf[128];
   1078     int buf_index;
   1079 
   1080     offset_count = (mt_ctrl->tx_offset_max - mt_ctrl->tx_offset_min + 1) *
   1081                    (mt_ctrl->rx_offset_max - mt_ctrl->rx_offset_min + 1);
   1082     fail_count = 0;
   1083     index = 0;
   1084     for (tx_offset = mt_ctrl->tx_offset_min;
   1085          tx_offset <= mt_ctrl->tx_offset_max; tx_offset++) {
   1086         for (rx_offset = mt_ctrl->rx_offset_min;
   1087              rx_offset <= mt_ctrl->rx_offset_max; rx_offset++) {
   1088             if (mt_ctrl->fail_array[index] > 0) {
   1089                 fail_count++;
   1090             }
   1091             index++;
   1092         }
   1093     }
   1094 
   1095     if (mt_ctrl->flags & (SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL_MATRIX |
   1096                           SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS)) {
   1097         buf_index = sal_sprintf(buf, "unit %d %s interface",
   1098                                 mt_ctrl->unit, mt_ctrl->intf_name);
   1099         switch (mt_data->interface) {
   1100         case SOC_MEM_INTERFACE_SRAM:
   1101             if (mt_ctrl->em_latency_cur != -1) {
   1102                 buf_index += sal_sprintf(&buf[buf_index], " em_latency=%d",
   1103                                          mt_ctrl->em_latency_cur);
   1104             }
   1105             if (mt_ctrl->ddr_latency_cur != -1) {
   1106                 buf_index += sal_sprintf(&buf[buf_index], " ddr_latency=%d",
   1107                                          mt_ctrl->ddr_latency_cur);
   1108             }
   1109             break;
   1110         case SOC_MEM_INTERFACE_TCAM:
   1111             if (mt_ctrl->invert_txclk_cur != -1) {
   1112                 buf_index += sal_sprintf(&buf[buf_index], " invert_txclk=%d",
   1113                                          mt_ctrl->invert_txclk_cur);
   1114             }
   1115             if (mt_ctrl->invert_rxclk_cur != -1) {
   1116                 buf_index += sal_sprintf(&buf[buf_index], " invert_rxclk=%d",
   1117                                          mt_ctrl->invert_rxclk_cur);
   1118             }
   1119             break;
   1120         default:
   1121             break;
   1122         }
   1123     }
   1124 
   1125     if (fail_count == offset_count) {
   1126         if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL_MATRIX) {
   1127             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1128                                 "Memory tuning %s failure count: all fail\n"), buf));
   1129         }
   1130         result = &mt_ctrl->result[mt_ctrl->result_count];
   1131         result->fail_count = fail_count;
   1132         mt_ctrl->result_count++;
   1133         return SOC_E_NONE;
   1134     }
   1135 
   1136     /* Print failure matrix */
   1137     if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL_MATRIX) {
   1138         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1139                             "Memory tuning %s failure count:\n"), buf));
   1140         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1141                             "TX (vertical axis) range: %d - %d, "
   1142                             "RX (horizontal axis) range: %d - %d\n"),
   1143                  mt_ctrl->tx_offset_min, mt_ctrl->tx_offset_max,
   1144                  mt_ctrl->rx_offset_min, mt_ctrl->rx_offset_max));
   1145         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1146                             "        |")));
   1147         for (index = mt_ctrl->rx_offset_min; index <= mt_ctrl->rx_offset_max;
   1148              index++) {
   1149             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1150                                 "%4d\t"), index));
   1151         }
   1152         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1153                             "\n--------+")));
   1154         for (rx_offset = mt_ctrl->rx_offset_min;
   1155              rx_offset <= mt_ctrl->rx_offset_max; rx_offset++) {
   1156             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1157                                 "--------")));
   1158         }
   1159         index = 0;
   1160         for (tx_offset = mt_ctrl->tx_offset_min;
   1161              tx_offset <= mt_ctrl->tx_offset_max; tx_offset++) {
   1162             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1163                                 "\n     %2d |"), tx_offset));
   1164             for (rx_offset = mt_ctrl->rx_offset_min;
   1165                  rx_offset <= mt_ctrl->rx_offset_max; rx_offset++) {
   1166                 if (mt_ctrl->fail_array[index] >= 0) {
   1167                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1168                                         "%4d\t"), mt_ctrl->fail_array[index]));
   1169                 } else {
   1170                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1171                                         " (%d)\t"), -mt_ctrl->fail_array[index]));
   1172                 }
   1173                 index++;
   1174             }
   1175         }
   1176         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1177                             "\n")));
   1178     }
   1179 
   1180     if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS) {
   1181         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1182                             "Memory tuning %s analysis "
   1183                             "[box area, abs(width - height)]:\n"), buf));
   1184         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1185                             "        |")));
   1186         for (index = mt_ctrl->rx_offset_min; index <= mt_ctrl->rx_offset_max;
   1187              index++) {
   1188             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1189                                 "%4d\t"), index));
   1190         }
   1191         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1192                             "\n--------+")));
   1193         for (rx_offset = mt_ctrl->rx_offset_min;
   1194              rx_offset <= mt_ctrl->rx_offset_max; rx_offset++) {
   1195             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1196                                 "--------")));
   1197         }
   1198     }
   1199 
   1200     best_area = 0;
   1201     best_shape = mt_ctrl->tx_offset_max + mt_ctrl->rx_offset_max;
   1202     best_width = 0;
   1203     best_height = 0;
   1204 
   1205     for (tx_offset = mt_ctrl->tx_offset_min;
   1206          tx_offset <= mt_ctrl->tx_offset_max; tx_offset++) {
   1207         if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS) {
   1208             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1209                                 "\n     %2d |"), tx_offset));
   1210         }
   1211         for (rx_offset = mt_ctrl->rx_offset_min;
   1212              rx_offset <= mt_ctrl->rx_offset_max; rx_offset++) {
   1213             _soc_memtune_get_txrx_area(mt_data, tx_offset, rx_offset,
   1214                                        &width, &height);
   1215             area = width * height;
   1216             shape = ABS(width - height);
   1217             if (area != 0) {
   1218                 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS) {
   1219                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1220                                         "%3d,%1d\t"), area, shape));
   1221                 }
   1222                 if (area > best_area ||
   1223                     (area == best_area && shape < best_shape)) {
   1224                     best_area = area;
   1225                     best_shape = shape;
   1226                     best_width = width;
   1227                     best_height = height;
   1228                     mt_ctrl->tx_offset_cur = tx_offset;
   1229                     mt_ctrl->rx_offset_cur = rx_offset;
   1230                 }
   1231             } else {
   1232                 if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS) {
   1233                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1234                                         "  *,*\t")));
   1235                 }
   1236             }
   1237         }
   1238     }
   1239     if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS) {
   1240         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1241                             "\n")));
   1242     }
   1243 
   1244     result = &mt_ctrl->result[mt_ctrl->result_count];
   1245 
   1246     result->fail_count = fail_count;
   1247     if (best_area != 0) {
   1248         /* save the stats and TX/RX settings for this result */
   1249         result->width = best_width;
   1250         result->height = best_height;
   1251         result->tx_offset = mt_ctrl->tx_offset_cur;
   1252         result->rx_offset = mt_ctrl->rx_offset_cur;
   1253     }
   1254 
   1255     mt_ctrl->result_count++;
   1256 
   1257     return SOC_E_NONE;
   1258 }
   1259 
   1260 #define BACKSPACE               "\010"
   1261 STATIC int
   1262 _soc_memtune_phase_sel_compare(soc_memtune_data_t *mt_data)
   1263 {
   1264     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
   1265     soc_memtune_result_t *ps_data;
   1266     int area[4], adj_area[4], shape, side;
   1267     int best_area, best_shape, best_side, best_adj_area;
   1268     int i, index;
   1269 
   1270     for (i = mt_ctrl->phase_sel_min; i <= mt_ctrl->phase_sel_max; i++) {
   1271         area[i] = mt_ctrl->ps_data[i]->width * mt_ctrl->ps_data[i]->height;
   1272     }
   1273     for (i = mt_ctrl->phase_sel_min; i <= mt_ctrl->phase_sel_max; i++) {
   1274         /* For each of the phase_sel values, get a sum of the
   1275          * areas of the 2 neighboring phase_sel values. Later,
   1276          * if 2 phase_sel values are found to have the same area/shape,
   1277          * preference is given to the one with better neighbors.
   1278          */
   1279         adj_area[i] = area[i];
   1280         index = i == mt_ctrl->phase_sel_min ? mt_ctrl->phase_sel_max : i - 1;
   1281         if (mt_ctrl->ps_data[index]->ddr_latency ==
   1282             mt_ctrl->ps_data[i]->ddr_latency &&
   1283             mt_ctrl->ps_data[index]->em_latency ==
   1284             mt_ctrl->ps_data[i]->em_latency) {
   1285             adj_area[i] += area[index];
   1286         }
   1287         index = i == mt_ctrl->phase_sel_max ? mt_ctrl->phase_sel_min : i + 1;
   1288         if (mt_ctrl->ps_data[index]->ddr_latency ==
   1289             mt_ctrl->ps_data[i]->ddr_latency &&
   1290             mt_ctrl->ps_data[index]->em_latency ==
   1291             mt_ctrl->ps_data[i]->em_latency) {
   1292             adj_area[i] += area[index];
   1293         }
   1294     }
   1295 
   1296     best_side = 0;
   1297     best_adj_area = 0;
   1298     best_area = 0;
   1299     best_shape = 0;
   1300     mt_ctrl->phase_sel_cur = 0;
   1301     for (i = mt_ctrl->phase_sel_min; i <= mt_ctrl->phase_sel_max; i++) {
   1302         ps_data = mt_ctrl->ps_data[i];
   1303         if (ps_data->width > ps_data->height) {
   1304             side = ps_data->height;
   1305             shape = ps_data->width - ps_data->height;
   1306         } else {
   1307             side = ps_data->width;
   1308             shape = ps_data->height - ps_data->width;
   1309         }
   1310         if (!area[i]) {
   1311             continue;
   1312         }
   1313         if (side < best_side) {
   1314             continue;
   1315         } else if (side == best_side) {
   1316             if (adj_area[i] < best_adj_area) {
   1317                 continue;
   1318             } else if (adj_area[i] == best_adj_area) {
   1319                 if (area[i] < best_area) {
   1320                     continue;
   1321                 } else if (area[i] == best_area) {
   1322                     if (shape >= best_shape) {
   1323                         continue;
   1324                     }
   1325                 }
   1326             }
   1327         }
   1328 
   1329         best_side = side;
   1330     /*    coverity[uninit_use : FALSE]    */
   1331         best_adj_area = adj_area[i];
   1332         best_area = area[i];
   1333         best_shape = shape;
   1334         mt_ctrl->phase_sel_cur = i;
   1335     }
   1336 
   1337     return SOC_E_NONE;
   1338 }
   1339 
   1340 STATIC int
   1341 _soc_memtune_ddr_single_test(soc_memtune_data_t *mt_data)
   1342 {
   1343     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
   1344     int rv;
   1345 
   1346     mt_ctrl->cur_fail_count = 0;
   1347 
   1348     rv = (*mt_ctrl->test_fn)(mt_data);
   1349 
   1350     if (rv < 0) {
   1351         LOG_ERROR(BSL_LS_SOC_MEMTUNE,
   1352                   (BSL_META_U(mt_ctrl->unit,
   1353                               "unit %d %s test failure: %s\n"),
   1354                    mt_ctrl->unit, mt_ctrl->intf_name, soc_errmsg(rv)));
   1355         return rv;
   1356     }
   1357 
   1358     if ((!(mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_PASS) &&
   1359          mt_ctrl->cur_fail_count != mt_data->test_count) ||
   1360         (!(mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL) &&
   1361          mt_ctrl->cur_fail_count == mt_data->test_count)) {
   1362         return SOC_E_NONE;
   1363     }
   1364 
   1365     if (mt_ctrl->phase_sel_cur != -1) {
   1366         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1367                             "Phase select=%d "), mt_ctrl->phase_sel_cur));
   1368     }
   1369     if (mt_ctrl->em_latency_cur != -1) {
   1370         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1371                             "EM lat=%d "), mt_ctrl->em_latency_cur));
   1372     }
   1373     if (mt_ctrl->ddr_latency_cur != -1) {
   1374         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1375                             "DDR lat=%d "), mt_ctrl->ddr_latency_cur));
   1376     }
   1377     if (mt_ctrl->tx_offset_cur != -1) {
   1378         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1379                             "TX offset=%d "), mt_ctrl->tx_offset_cur));
   1380     }
   1381     if (mt_ctrl->rx_offset_cur != -1) {
   1382         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1383                             "RX offset=%d "), mt_ctrl->rx_offset_cur));
   1384     }
   1385     if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_NOPS) {
   1386         if (mt_ctrl->r2w_nops_cur != -1) {
   1387             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1388                                 "R2W nops=%d "), mt_ctrl->r2w_nops_cur));
   1389         }
   1390         if (mt_ctrl->w2r_nops_cur != -1) {
   1391             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1392                                 "W2R nops=%d "), mt_ctrl->w2r_nops_cur));
   1393         }
   1394     }
   1395     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1396                         ": Fail count=%d\n"), mt_ctrl->cur_fail_count));
   1397 
   1398     return SOC_E_NONE;
   1399 }
   1400 
   1401 STATIC int
   1402 _soc_memtune_ddr_main(soc_memtune_data_t *mt_data)
   1403 {
   1404     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
   1405     soc_memtune_result_t *result;
   1406     int rv, success, offset_count, old_result_count, index, i;
   1407     char progress_symbol;
   1408 
   1409     if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_TEST_NAME) {
   1410         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1411                             "Memory tuning test: %s interface:\n"),
   1412                  mt_ctrl->intf_name));
   1413     }
   1414 
   1415     if (mt_data->manual_settings) {
   1416         mt_ctrl->phase_sel_cur = mt_data->man_phase_sel;
   1417         mt_ctrl->em_latency_cur = mt_data->man_em_latency;
   1418         mt_ctrl->ddr_latency_cur = mt_data->man_ddr_latency;
   1419         mt_ctrl->tx_offset_cur = mt_data->man_tx_offset;
   1420         mt_ctrl->rx_offset_cur = mt_data->man_rx_offset;
   1421         mt_ctrl->w2r_nops_cur = mt_data->man_w2r_nops;
   1422         mt_ctrl->r2w_nops_cur = mt_data->man_r2w_nops;
   1423         mt_ctrl->cur_fail_count = 0;
   1424 
   1425         (*mt_ctrl->prog_hw3_fn)(mt_data); /* phase */
   1426         (*mt_ctrl->prog_hw2_fn)(mt_data); /* latency */
   1427         (*mt_ctrl->prog_hw1_fn)(mt_data); /* TX/RX */
   1428         if (*mt_ctrl->per_tx_fn != NULL) {
   1429             (*mt_ctrl->per_tx_fn)(mt_data);
   1430         }
   1431         if (*mt_ctrl->per_rx_fn != NULL) {
   1432             (*mt_ctrl->per_rx_fn)(mt_data);
   1433         }
   1434 
   1435         SOC_IF_ERROR_RETURN(_soc_memtune_ddr_single_test(mt_data));
   1436         if (mt_ctrl->cur_fail_count == 0 && mt_data->config) {
   1437 #ifdef BCM_TRIUMPH_SUPPORT
   1438             if (soc_feature(mt_ctrl->unit, soc_feature_esm_support)) {
   1439                 SOC_IF_ERROR_RETURN(_soc_tr_tune_generate_config(mt_data));
   1440             }
   1441 #endif /* BCM_TRIUMPH_SUPPORT */
   1442         }
   1443         return SOC_E_NONE;
   1444     }
   1445 
   1446     offset_count = (mt_ctrl->tx_offset_max - mt_ctrl->tx_offset_min + 1) *
   1447                    (mt_ctrl->rx_offset_max - mt_ctrl->rx_offset_min + 1);
   1448     mt_ctrl->fail_array = sal_alloc(offset_count * sizeof(int),
   1449                                     "memtune working data");
   1450     if (mt_ctrl->fail_array == NULL) {
   1451         return SOC_E_MEMORY;
   1452     }
   1453     sal_memset(mt_ctrl->fail_array, 0, offset_count * sizeof(int));
   1454 
   1455     mt_ctrl->w2r_nops_cur = mt_ctrl->w2r_nops_max;
   1456     mt_ctrl->r2w_nops_cur = mt_ctrl->r2w_nops_max;
   1457     mt_ctrl->result_count = 0;
   1458 
   1459     for (mt_ctrl->phase_sel_cur = mt_ctrl->phase_sel_min;
   1460          mt_ctrl->phase_sel_cur <= mt_ctrl->phase_sel_max;
   1461          mt_ctrl->phase_sel_cur++) {
   1462         if (mt_ctrl->phase_sel_cur != -1) {
   1463             (*mt_ctrl->prog_hw3_fn)(mt_data); /* phase */
   1464         }
   1465 
   1466         old_result_count = mt_ctrl->result_count;
   1467         progress_symbol = '-';
   1468         if (mt_data->do_txrx_first) {
   1469             for (mt_ctrl->tx_offset_cur = mt_ctrl->tx_offset_min;
   1470                  mt_ctrl->tx_offset_cur <= mt_ctrl->tx_offset_max;
   1471                  mt_ctrl->tx_offset_cur++) {
   1472                 for (mt_ctrl->rx_offset_cur = mt_ctrl->rx_offset_min;
   1473                      mt_ctrl->rx_offset_cur <= mt_ctrl->rx_offset_max;
   1474                      mt_ctrl->rx_offset_cur++) {
   1475                     (*mt_ctrl->prog_hw1_fn)(mt_data); /* TX/RX */
   1476                     if (mt_ctrl->rx_offset_cur == mt_ctrl->rx_offset_min) {
   1477                         if (*mt_ctrl->per_tx_fn != NULL) {
   1478                             (*mt_ctrl->per_tx_fn)(mt_data);
   1479                         }
   1480                     }
   1481                     if (*mt_ctrl->per_rx_fn != NULL) {
   1482                         (*mt_ctrl->per_rx_fn)(mt_data);
   1483                     }
   1484                     for (mt_ctrl->em_latency_cur = mt_ctrl->em_latency_min;
   1485                          mt_ctrl->em_latency_cur <= mt_ctrl->em_latency_max;
   1486                          mt_ctrl->em_latency_cur++) {
   1487                         for (mt_ctrl->ddr_latency_cur =
   1488                                  mt_ctrl->ddr_latency_min;
   1489                              mt_ctrl->ddr_latency_cur <=
   1490                                  mt_ctrl->ddr_latency_max;
   1491                              mt_ctrl->ddr_latency_cur++) {
   1492                             if (mt_ctrl->flags &
   1493                                 SOC_MEMTUNE_CTRL_FLAGS_SHOW_PROGRESS) {
   1494                                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1495                                                     "%c" BACKSPACE), progress_symbol));
   1496                                 progress_symbol ^= '-' ^ '|';
   1497                             }
   1498                             (*mt_ctrl->prog_hw2_fn)(mt_data); /* latency */
   1499                             rv = _soc_memtune_ddr_single_test(mt_data);
   1500                             if (SOC_FAILURE(rv)) { /* fail unexpected */
   1501                                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1502                                                     " " BACKSPACE)));
   1503                                 sal_free(mt_ctrl->fail_array);
   1504                                 return rv;
   1505                             }
   1506                             if (mt_ctrl->cur_fail_count == 0) {
   1507                                 break;
   1508                             }
   1509                         } /* mt_ctrl->ddr_latency_cur loop */
   1510                         if (mt_ctrl->cur_fail_count == 0) {
   1511                             break;
   1512                         }
   1513                     } /* mt_ctrl->em_latency_cur loop */
   1514                     index = (mt_ctrl->tx_offset_cur - mt_ctrl->tx_offset_min) *
   1515                         (mt_ctrl->rx_offset_max - mt_ctrl->rx_offset_min + 1) +
   1516                         mt_ctrl->rx_offset_cur - mt_ctrl->rx_offset_min;
   1517                     if (mt_ctrl->cur_fail_count > 0) {
   1518                         mt_ctrl->fail_array[index] = mt_ctrl->cur_fail_count;
   1519                     } else {
   1520                         mt_ctrl->fail_array[index] = -mt_ctrl->em_latency_cur;
   1521                     }
   1522                 } /* mt_ctrl->rx_offset_cur loop */
   1523             } /* mt_ctrl->tx_offset_cur loop */
   1524             if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_PROGRESS) {
   1525                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1526                                     " " BACKSPACE)));
   1527             }
   1528 
   1529             /* Analyze and print result matrix */
   1530             result = &mt_ctrl->result[mt_ctrl->result_count];
   1531             mt_ctrl->em_latency_cur = -1;
   1532             mt_ctrl->ddr_latency_cur = -1;
   1533             _soc_memtune_txrx_analyze(mt_data);
   1534             result->phase_sel = mt_ctrl->phase_sel_cur;
   1535             result->em_latency = -1;
   1536             result->ddr_latency = -1;
   1537         } else {
   1538             for (mt_ctrl->em_latency_cur = mt_ctrl->em_latency_min;
   1539                  mt_ctrl->em_latency_cur <= mt_ctrl->em_latency_max;
   1540                  mt_ctrl->em_latency_cur++) {
   1541                 for (mt_ctrl->ddr_latency_cur = mt_ctrl->ddr_latency_min;
   1542                      mt_ctrl->ddr_latency_cur <= mt_ctrl->ddr_latency_max;
   1543                      mt_ctrl->ddr_latency_cur++) {
   1544                     success = FALSE;
   1545                     for (mt_ctrl->tx_offset_cur = mt_ctrl->tx_offset_min;
   1546                          mt_ctrl->tx_offset_cur <= mt_ctrl->tx_offset_max;
   1547                          mt_ctrl->tx_offset_cur++) {
   1548                         for (mt_ctrl->rx_offset_cur = mt_ctrl->rx_offset_min;
   1549                              mt_ctrl->rx_offset_cur <= mt_ctrl->rx_offset_max;
   1550                              mt_ctrl->rx_offset_cur++) {
   1551                             if (mt_ctrl->flags &
   1552                                 SOC_MEMTUNE_CTRL_FLAGS_SHOW_PROGRESS) {
   1553                                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1554                                                     "%c" BACKSPACE), progress_symbol));
   1555                                 progress_symbol ^= '-' ^ '|';
   1556                             }
   1557                             (*mt_ctrl->prog_hw2_fn)(mt_data); /* latency */
   1558                             (*mt_ctrl->prog_hw1_fn)(mt_data); /* TX/RX */
   1559                             if (mt_ctrl->rx_offset_cur ==
   1560                                 mt_ctrl->rx_offset_min) {
   1561                                 if (*mt_ctrl->per_tx_fn != NULL) {
   1562                                     (*mt_ctrl->per_tx_fn)(mt_data);
   1563                                 }
   1564                             }
   1565                             if (*mt_ctrl->per_rx_fn != NULL) {
   1566                                 (*mt_ctrl->per_rx_fn)(mt_data);
   1567                             }
   1568                             rv = _soc_memtune_ddr_single_test(mt_data);
   1569                             if (SOC_FAILURE(rv)) { /* fail unexpected */
   1570                                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1571                                                     " " BACKSPACE)));
   1572                                 sal_free(mt_ctrl->fail_array);
   1573                                 return rv;
   1574                             }
   1575                             index = (mt_ctrl->tx_offset_cur -
   1576                                      mt_ctrl->tx_offset_min) *
   1577                                 (mt_ctrl->rx_offset_max -
   1578                                  mt_ctrl->rx_offset_min + 1) +
   1579                                 mt_ctrl->rx_offset_cur -
   1580                                 mt_ctrl->rx_offset_min;
   1581                             mt_ctrl->fail_array[index] =
   1582                                 mt_ctrl->cur_fail_count;
   1583                             if (mt_ctrl->cur_fail_count == 0) {
   1584                                 success = TRUE;
   1585                             }
   1586                         } /* mt_ctrl->rx_offset_cur loop */
   1587                     } /* mt_ctrl->tx_offset_cur loop */
   1588                     if (success) {
   1589                         if (mt_ctrl->flags &
   1590                             SOC_MEMTUNE_CTRL_FLAGS_SHOW_PROGRESS) {
   1591                             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1592                                                 " " BACKSPACE)));
   1593                         }
   1594 
   1595                         /* Analyze and print result matrix */
   1596                         result = &mt_ctrl->result[mt_ctrl->result_count];
   1597                         _soc_memtune_txrx_analyze(mt_data);
   1598                         result->phase_sel = mt_ctrl->phase_sel_cur;
   1599                         result->em_latency = mt_ctrl->em_latency_cur;
   1600                         result->ddr_latency = mt_ctrl->ddr_latency_cur;
   1601                         if (!mt_data->test_all_latency) {
   1602                             goto loop_done;
   1603                         }
   1604                     }
   1605                 } /* mt_ctrl->ddr_latency_cur loop */
   1606             } /* mt_ctrl->em_latency_cur loop */
   1607 
   1608             /* If nothing is passed for any EM_LATENCY, DDR_LATENCY setting */
   1609             if (mt_ctrl->result_count == old_result_count) {
   1610                 result = &mt_ctrl->result[mt_ctrl->result_count];
   1611                 _soc_memtune_txrx_analyze(mt_data);
   1612                 result->phase_sel = mt_ctrl->phase_sel_cur;
   1613             }
   1614         }
   1615 
   1616     loop_done:
   1617         index = mt_ctrl->phase_sel_cur == -1 ? 0 : mt_ctrl->phase_sel_cur;
   1618         mt_ctrl->ps_data[index] = &mt_ctrl->result[old_result_count];
   1619         for (i = old_result_count + 1; i < mt_ctrl->result_count; i++) {
   1620             if (mt_ctrl->ps_data[index]->width *
   1621                 mt_ctrl->ps_data[index]->height <
   1622                 mt_ctrl->result[i].width * mt_ctrl->result[i].height) {
   1623                 mt_ctrl->ps_data[index] = &mt_ctrl->result[i];
   1624             }
   1625         }
   1626     }
   1627 
   1628     if (mt_ctrl->phase_sel_min != -1) {
   1629         /* Select the best result from 4 different phase */
   1630         _soc_memtune_phase_sel_compare(mt_data);
   1631         result = mt_ctrl->ps_data[mt_ctrl->phase_sel_cur];
   1632 
   1633         /* Program phase setting from the best result */
   1634         (*mt_ctrl->prog_hw3_fn)(mt_data); /* phase */
   1635     } else {
   1636         mt_ctrl->phase_sel_cur = mt_ctrl->phase_sel_min;
   1637         result = mt_ctrl->ps_data[0];
   1638     }
   1639 
   1640     if (result->fail_count != offset_count) {
   1641         /* Program latency setting if do_txrx_first is FALSE */
   1642         if (result->em_latency != -1 || result->ddr_latency != -1) {
   1643             mt_ctrl->em_latency_cur = result->em_latency;
   1644             mt_ctrl->ddr_latency_cur = result->ddr_latency;
   1645             (*mt_ctrl->prog_hw2_fn)(mt_data); /* latency */
   1646         }
   1647         /* Program TX/RX setting from the best result */
   1648         mt_ctrl->tx_offset_cur = result->tx_offset;
   1649         mt_ctrl->rx_offset_cur = result->rx_offset;
   1650         (*mt_ctrl->prog_hw1_fn)(mt_data); /* TX/RX */
   1651         if (*mt_ctrl->per_tx_fn != NULL) {
   1652             (*mt_ctrl->per_tx_fn)(mt_data);
   1653         }
   1654         if (*mt_ctrl->per_rx_fn != NULL) {
   1655             (*mt_ctrl->per_rx_fn)(mt_data);
   1656         }
   1657         /* Find latency setting if do_txrx_first is TRUE */
   1658         if (result->em_latency == -1 && result->ddr_latency == -1) {
   1659             for (mt_ctrl->em_latency_cur = mt_ctrl->em_latency_min;
   1660                  mt_ctrl->em_latency_cur <= mt_ctrl->em_latency_max;
   1661                  mt_ctrl->em_latency_cur++) {
   1662                 for (mt_ctrl->ddr_latency_cur = mt_ctrl->ddr_latency_min;
   1663                      mt_ctrl->ddr_latency_cur <= mt_ctrl->ddr_latency_max;
   1664                      mt_ctrl->ddr_latency_cur++) {
   1665                     (*mt_ctrl->prog_hw2_fn)(mt_data); /* latency */
   1666                     rv = _soc_memtune_ddr_single_test(mt_data);
   1667                     if (SOC_FAILURE(rv)) { /* fail unexpected */
   1668                         sal_free(mt_ctrl->fail_array);
   1669                         return rv;
   1670                     }
   1671                     if (mt_ctrl->cur_fail_count == 0) {
   1672                         result->ddr_latency = mt_ctrl->ddr_latency_cur;
   1673                         break;
   1674                     }
   1675                 } /* mt_ctrl->ddr_latency_cur loop */
   1676                 if (mt_ctrl->cur_fail_count == 0) {
   1677                     result->em_latency = mt_ctrl->em_latency_cur;
   1678                     break;
   1679                 }
   1680             } /* mt_ctrl->em_latency_cur loop */
   1681         }
   1682 
   1683         /* Tune number of nop between write-to-read and read-to-write */
   1684         if (mt_ctrl->w2r_nops_min != mt_ctrl->w2r_nops_max &&
   1685             mt_ctrl->r2w_nops_min != mt_ctrl->r2w_nops_max) {
   1686             mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_NOPS;
   1687             success = FALSE;
   1688             for (mt_ctrl->w2r_nops_cur = mt_ctrl->w2r_nops_min;
   1689                  mt_ctrl->w2r_nops_cur <= mt_ctrl->w2r_nops_max;
   1690                  mt_ctrl->w2r_nops_cur++) {
   1691                 for (mt_ctrl->r2w_nops_cur = mt_ctrl->r2w_nops_max;
   1692                      mt_ctrl->r2w_nops_cur >= mt_ctrl->r2w_nops_min;
   1693                      mt_ctrl->r2w_nops_cur--) {
   1694                     if (*mt_ctrl->prog_hw4_fn != NULL) {
   1695                         (*mt_ctrl->prog_hw4_fn)(mt_data);  /* nops */
   1696                     }
   1697                     rv = _soc_memtune_ddr_single_test(mt_data);
   1698                     if (SOC_FAILURE(rv)) { /* fail unexpected */
   1699                         sal_free(mt_ctrl->fail_array);
   1700                         return rv;
   1701                     }
   1702                     if (mt_ctrl->cur_fail_count == 0) {
   1703                         success = TRUE;
   1704                         continue;
   1705                     }
   1706                     if (mt_ctrl->r2w_nops_cur < mt_ctrl->r2w_nops_max) {
   1707                         mt_ctrl->r2w_nops_cur++;
   1708                     }
   1709                     break;
   1710                 }
   1711                 if (mt_ctrl->r2w_nops_cur < mt_ctrl->r2w_nops_min) {
   1712                     mt_ctrl->r2w_nops_cur++;
   1713                 }
   1714                 if (success) {
   1715                     break;
   1716                 }
   1717             }
   1718             if (success) {
   1719                 if (mt_ctrl->r2w_nops_cur < 1) {
   1720                     mt_ctrl->r2w_nops_cur = 1; /* hardware interprets 0 as 4 */
   1721                 }
   1722                 if (*mt_ctrl->prog_hw4_fn != NULL) {
   1723                     (*mt_ctrl->prog_hw4_fn)(mt_data);  /* nops */
   1724                 }
   1725             } else { /* should not be here */
   1726                 mt_ctrl->r2w_nops_cur = mt_ctrl->r2w_nops_max;
   1727                 mt_ctrl->w2r_nops_cur = mt_ctrl->w2r_nops_max;
   1728             }
   1729             mt_ctrl->flags &= ~SOC_MEMTUNE_CTRL_FLAGS_SHOW_NOPS;
   1730         }
   1731 
   1732         if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SELECTION) {
   1733             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1734                                 "Memory tuning selection: ")));
   1735             if (mt_ctrl->phase_sel_cur != -1) {
   1736                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1737                                     "Phase sel=%d "), mt_ctrl->phase_sel_cur));
   1738             }
   1739             if (mt_ctrl->em_latency_cur != -1) {
   1740                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1741                                     "EM lat=%d "), mt_ctrl->em_latency_cur));
   1742             }
   1743             if (mt_ctrl->ddr_latency_cur != -1) {
   1744                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1745                                     "DDR lat=%d "), mt_ctrl->ddr_latency_cur));
   1746             }
   1747             if (mt_ctrl->tx_offset_cur != -1) {
   1748                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1749                                     "TX offset=%d "), mt_ctrl->tx_offset_cur));
   1750             }
   1751             if (mt_ctrl->rx_offset_cur != -1) {
   1752                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1753                                     "RX offset=%d "), mt_ctrl->rx_offset_cur));
   1754             }
   1755             if (mt_ctrl->w2r_nops_cur != -1) {
   1756                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1757                                     "W2R nops=%d "), mt_ctrl->w2r_nops_cur));
   1758             }
   1759             if (mt_ctrl->r2w_nops_cur != -1) {
   1760                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1761                                     "R2W nops=%d "), mt_ctrl->r2w_nops_cur));
   1762             }
   1763             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1764                                 "\n")));
   1765         }
   1766     }
   1767 
   1768     if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY) {
   1769         if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY_HEADER) {
   1770             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1771                                 "\n Interface  , Area , Width , Height , PS ,"
   1772                                 "  TX ,  RX , Lat , Em , Pass , Fail")));
   1773             if (soc_feature(mt_ctrl->unit, soc_feature_esm_support)) {
   1774                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1775                                     " , Freq , Tb , Sb , Dac")));
   1776             }
   1777             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1778                                 "\n")));
   1779         }
   1780 
   1781         for (i = 0; i < mt_ctrl->result_count; i++) {
   1782             result = &mt_ctrl->result[i];
   1783 
   1784             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1785                                 " %10s , %4d ,  %3d  ,  %3d   ,"),
   1786                      mt_ctrl->intf_name, result->width * result->height,
   1787                      result->width, result->height));
   1788             if (result->phase_sel != -1) {
   1789                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1790                                     "  %1d ,"), result->phase_sel));
   1791             } else {
   1792                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1793                                     " ** ,")));
   1794             }
   1795             if (result->fail_count != offset_count) {
   1796                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1797                                     "  %2d ,  %2d ,"),
   1798                          result->tx_offset, result->rx_offset));
   1799                 if (result->ddr_latency != -1) {
   1800                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1801                                         " %2d  ,"), result->ddr_latency));
   1802                 } else {
   1803                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1804                                         " **  ,")));
   1805                 }
   1806                 if (result->em_latency != -1) {
   1807                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1808                                         " %2d ,"),
   1809                              result->em_latency));
   1810                 } else {
   1811                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1812                                         " ** ,")));
   1813                 }
   1814             } else {
   1815                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1816                                     "  ** ,  ** , **  , ** ,")));
   1817             }
   1818             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1819                                 " %4d , %4d"),
   1820                      offset_count - result->fail_count,
   1821                      result->fail_count));
   1822             if (soc_feature(mt_ctrl->unit, soc_feature_esm_support)) {
   1823                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1824                                     " ,  %3d ,  %c ,  %c ,"),
   1825                          mt_data->freq,
   1826                          mt_data->bg_tcam_bist ? 'Y' : 'N',
   1827                          mt_data->bg_sram_bist ? 'Y' : 'N'));
   1828                 if (mt_ctrl->dac_value != -1) {
   1829                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1830                                         "  %2d"), mt_ctrl->dac_value));
   1831                 } else {
   1832                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1833                                         "  **")));
   1834                 }
   1835             }
   1836             index = result->phase_sel == -1 ? 0 : result->phase_sel;
   1837             if (result != mt_ctrl->ps_data[index]) {
   1838                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1839                                     " (ignored)\n")));
   1840             } else if (result->fail_count != offset_count &&
   1841                        mt_ctrl->phase_sel_cur != -1 &&
   1842                        result == mt_ctrl->ps_data[mt_ctrl->phase_sel_cur]) {
   1843                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1844                                     " <\n")));
   1845             } else {
   1846                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1847                                     "\n")));
   1848             }
   1849         }
   1850     }
   1851 
   1852     if ((mt_ctrl->phase_sel_min != -1) &&
   1853         (mt_ctrl->phase_sel_cur != -1)) {
   1854         result = mt_ctrl->ps_data[mt_ctrl->phase_sel_cur];
   1855     } else {
   1856         result = mt_ctrl->ps_data[0];
   1857     }
   1858     if (result->fail_count == offset_count) {
   1859         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1860                             "ERROR - no passing \"eye\" was found, \n"
   1861                             "please contact your Field Applications Engineer or "
   1862                             "Sales Manager\n"
   1863                             "for additional assistance.\n")));
   1864         rv = SOC_E_FAIL;
   1865     } else {
   1866         if (result->height < mt_ctrl->tx_pass_threshold ||
   1867             result->width < mt_ctrl->rx_pass_threshold) {
   1868             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   1869                                 "!!! SRAM tuning result does not pass qualified "
   1870                                 "threshold !!!\n")));
   1871         }
   1872         rv = SOC_E_NONE;
   1873         if (mt_data->config) {
   1874 #ifdef BCM_TRIUMPH_SUPPORT
   1875             if (soc_feature(mt_ctrl->unit, soc_feature_esm_support)) {
   1876                 rv = _soc_tr_tune_generate_config(mt_data);
   1877             }
   1878 #endif
   1879             if (rv < 0) {
   1880                 LOG_ERROR(BSL_LS_SOC_MEMTUNE,
   1881                           (BSL_META_U(mt_ctrl->unit,
   1882                                       "unit %d %s fail to generate config: %s\n"),
   1883                            mt_ctrl->unit, mt_ctrl->intf_name,
   1884                            soc_errmsg(rv)));
   1885             }
   1886         }
   1887     }
   1888 
   1889     sal_free(mt_ctrl->fail_array);
   1890     return rv;
   1891 }
   1892 
   1893 #ifdef BCM_TRIUMPH_SUPPORT
   1894 STATIC int
   1895 _soc_memtune_tcam_single_test(soc_memtune_data_t *mt_data)
   1896 {
   1897     soc_tcam_info_t *tcam_info;
   1898     soc_tcam_partition_t *partitions;
   1899     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
   1900     soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data;
   1901     char *fail_name, fail_reason[80];
   1902     int rv, index;
   1903     uint32 addr, rval, mask[8], data[8];
   1904     int do_init;
   1905 
   1906     tcam_info = SOC_CONTROL(mt_ctrl->unit)->tcam_info;
   1907     partitions = tcam_info->partitions;
   1908     do_init = tcam_info->num_tcams <= 0 ? TRUE : FALSE;
   1909 
   1910     mt_ctrl->dpeo_sync_dly_cur = -1;
   1911     mt_ctrl->fcd_dpeo_cur = -1;
   1912     mt_ctrl->rbus_sync_dly_cur = -1;
   1913     mt_ctrl->fcd_rbus_cur = -1;
   1914     fail_name = NULL;
   1915     fail_reason[0] = '\0';
   1916 
   1917     /* DBUS */
   1918     mt_data->sub_interface = 0;
   1919     rv = (*mt_ctrl->prog_hw1_fn)(mt_data); /* dpeo/rbus */
   1920     if (rv < 0) {
   1921         LOG_ERROR(BSL_LS_SOC_MEMTUNE,
   1922                   (BSL_META_U(mt_ctrl->unit,
   1923                               "%s prog hardware failure: %s\n"),
   1924                               mt_ctrl->intf_name,
   1925                    soc_errmsg(rv)));
   1926         return rv;
   1927     }
   1928 
   1929     if (do_init) {
   1930         for (index = 0; index < TCAM_PARTITION_COUNT; index++) {
   1931             tcam_info->partitions[index].num_entries = 0;
   1932         }
   1933         partitions[TCAM_PARTITION_DEV0_TBL72].num_entries = 16384;
   1934         partitions[TCAM_PARTITION_DEV0_TBL144].num_entries = 8192;
   1935         partitions[TCAM_PARTITION_DEV1_TBL72].num_entries = 16384;
   1936         partitions[TCAM_PARTITION_DEV1_TBL144].num_entries = 8192;
   1937         soc_tcam_init(mt_ctrl->unit);
   1938         mt_ctrl->do_setup_for_rbus_test = TRUE;
   1939     }
   1940 
   1941     mt_ctrl->cur_fail_count = 0;
   1942     rv = (*mt_ctrl->test_fn)(mt_data);
   1943     if (rv < 0) {
   1944         LOG_ERROR(BSL_LS_SOC_MEMTUNE,
   1945                   (BSL_META_U(mt_ctrl->unit,
   1946                               "%s dbus test failure: %s\n"),
   1947                               mt_ctrl->intf_name, soc_errmsg(rv)));
   1948         return rv;
   1949     }
   1950     if (mt_ctrl->cur_fail_count) {
   1951         fail_name = "DBUS";
   1952         switch (mt_ctrl->cur_fail_reason & 0xffff0000) {
   1953         case 0x10000:
   1954             sal_sprintf(fail_reason, "bank %d error bit assert (0x%08x)",
   1955                         mt_ctrl->cur_fail_reason & 0xf,
   1956                         mt_ctrl->cur_fail_detail0);
   1957             break;
   1958         case 0x20000:
   1959             sal_sprintf(fail_reason, "bank %d entry %d mismatch",
   1960                         mt_ctrl->cur_fail_reason & 0xf,
   1961                         mt_ctrl->cur_fail_detail0);
   1962             break;
   1963         default:
   1964             return SOC_E_INTERNAL;
   1965         }
   1966         goto done;
   1967     }
   1968 
   1969     /* DBUS_out (DPEO) */
   1970     addr = soc_reg_addr(mt_ctrl->unit, tr_mt_data->etc_ctl, REG_PORT_ANY, 0);
   1971     SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
   1972     soc_reg_field_set(mt_ctrl->unit, tr_mt_data->etc_ctl, &rval,
   1973                       OUT_DPR_ODD_FALLf, 3);
   1974     soc_reg_field_set(mt_ctrl->unit, tr_mt_data->etc_ctl, &rval,
   1975                       OUT_DPR_ODD_RISEf, 3);
   1976     SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval));
   1977 
   1978     mt_data->sub_interface = 1;
   1979     for (mt_ctrl->dpeo_sync_dly_cur = mt_ctrl->dpeo_sync_dly_min;
   1980          mt_ctrl->dpeo_sync_dly_cur <= mt_ctrl->dpeo_sync_dly_max;
   1981          mt_ctrl->dpeo_sync_dly_cur++) {
   1982         for (mt_ctrl->fcd_dpeo_cur = mt_ctrl->fcd_dpeo_min;
   1983              mt_ctrl->fcd_dpeo_cur <= mt_ctrl->fcd_dpeo_max;
   1984              mt_ctrl->fcd_dpeo_cur++) {
   1985             rv = (*mt_ctrl->prog_hw1_fn)(mt_data);  /* dpeo/rbus */
   1986             if (rv < 0) {
   1987                 LOG_ERROR(BSL_LS_SOC_MEMTUNE,
   1988                           (BSL_META_U(mt_ctrl->unit,
   1989                                       "%s prog hardware failure: "
   1990                                       "%s\n"),
   1991                            mt_ctrl->intf_name,
   1992                            soc_errmsg(rv)));
   1993                 return rv;
   1994             }
   1995             mt_ctrl->cur_fail_count = 0;
   1996             rv = (*mt_ctrl->test_fn)(mt_data);
   1997             if (rv < 0) {
   1998                 LOG_ERROR(BSL_LS_SOC_MEMTUNE,
   1999                           (BSL_META_U(mt_ctrl->unit,
   2000                                       "%s dpeo test failure: %s\n"),
   2001                                       mt_ctrl->intf_name,
   2002                            soc_errmsg(rv)));
   2003                 return rv;
   2004             }
   2005             if (mt_ctrl->cur_fail_count == 0) {
   2006                 break;
   2007             }
   2008         } /* mt_ctrl->fcd_dpeo_cur loop */
   2009         if (mt_ctrl->cur_fail_count == 0) {
   2010             break;
   2011         }
   2012     } /* mt_ctrl->dpeo_sync_dly_cur loop */
   2013     addr = soc_reg_addr(mt_ctrl->unit, tr_mt_data->etc_ctl, REG_PORT_ANY, 0);
   2014     SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
   2015     soc_reg_field_set(mt_ctrl->unit, tr_mt_data->etc_ctl, &rval,
   2016                       OUT_DPR_ODD_FALLf, 0);
   2017     soc_reg_field_set(mt_ctrl->unit, tr_mt_data->etc_ctl, &rval,
   2018                       OUT_DPR_ODD_RISEf, 0);
   2019     SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval));
   2020     if (mt_ctrl->cur_fail_count) {
   2021         fail_name = "DPEO";
   2022         sal_sprintf(fail_reason, "error bit assert (0x%08x)",
   2023                     mt_ctrl->cur_fail_detail0);
   2024         goto done;
   2025     }
   2026 
   2027     /* setup for RBUS test */
   2028     if (mt_ctrl->do_setup_for_rbus_test) {
   2029         if (!do_init) {
   2030             soc_tcam_init(mt_ctrl->unit);
   2031         }
   2032         mt_ctrl->do_setup_for_rbus_test = FALSE;
   2033         sal_memset(mask, 0, sizeof(mask));
   2034         sal_memset(data, 0, sizeof(data));
   2035 
   2036         /* No reset on simulation, put test entry at index 0 to avoid hitting
   2037          * leftover entries */
   2038         index = SAL_BOOT_SIMULATION ? 0 : 0x1555;
   2039         if (mt_data->mask[0] == 0xffffffff) {
   2040             /* all '1's for lower 72-bit, all '0's for upper 72-bit */
   2041             data[5] = 0xff;
   2042             data[6] = data[7] = 0xffffffff;
   2043         } else {
   2044             sal_memcpy(mask, mt_data->mask, sizeof(mask));
   2045             sal_memcpy(data, mt_data->data, sizeof(data));
   2046         }
   2047         soc_tcam_write_entry(mt_ctrl->unit, TCAM_PARTITION_DEV0_TBL72, index,
   2048                              &mask[4], &data[4]);
   2049         soc_tcam_write_entry(mt_ctrl->unit, TCAM_PARTITION_DEV0_TBL144, index,
   2050                              mask, data);
   2051         if (partitions[TCAM_PARTITION_DEV1_TBL72].num_entries) {
   2052             soc_tcam_write_entry(mt_ctrl->unit, TCAM_PARTITION_DEV1_TBL72,
   2053                                  index, &mask[4], &data[4]);
   2054         }
   2055         if (partitions[TCAM_PARTITION_DEV1_TBL144].num_entries) {
   2056             soc_tcam_write_entry(mt_ctrl->unit, TCAM_PARTITION_DEV1_TBL144,
   2057                                  index, mask, data);
   2058         }
   2059     }
   2060 
   2061     addr = soc_reg_addr(mt_ctrl->unit, tr_mt_data->etc_ctl, REG_PORT_ANY, 0);
   2062     SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
   2063     soc_reg_field_set(mt_ctrl->unit, tr_mt_data->etc_ctl, &rval, IN_SMFL00f,
   2064                       0);
   2065     SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval));
   2066 
   2067     mt_data->sub_interface = 2;
   2068     for (mt_ctrl->rbus_sync_dly_cur = mt_ctrl->rbus_sync_dly_min;
   2069          mt_ctrl->rbus_sync_dly_cur <= mt_ctrl->rbus_sync_dly_max;
   2070          mt_ctrl->rbus_sync_dly_cur++) {
   2071         for (mt_ctrl->fcd_rbus_cur = mt_ctrl->fcd_rbus_min;
   2072              mt_ctrl->fcd_rbus_cur <= mt_ctrl->fcd_rbus_max;
   2073              mt_ctrl->fcd_rbus_cur++) {
   2074             rv = (*mt_ctrl->prog_hw1_fn)(mt_data);  /* dpeo/rbus */
   2075             if (rv < 0) {
   2076                 LOG_ERROR(BSL_LS_SOC_MEMTUNE,
   2077                           (BSL_META_U(mt_ctrl->unit,
   2078                                       "%s prog hardware failure: "
   2079                                       "%s\n"),
   2080                            mt_ctrl->intf_name,
   2081                            soc_errmsg(rv)));
   2082                 return rv;
   2083             }
   2084             mt_ctrl->cur_fail_count = 0;
   2085             rv = (*mt_ctrl->test_fn)(mt_data);
   2086             if (rv < 0) {
   2087                 LOG_ERROR(BSL_LS_SOC_MEMTUNE,
   2088                           (BSL_META_U(mt_ctrl->unit,
   2089                                       "%s rbus test failure: %s\n"),
   2090                                       mt_ctrl->intf_name,
   2091                            soc_errmsg(rv)));
   2092                 return rv;
   2093             }
   2094             if (mt_ctrl->cur_fail_count == 0) {
   2095                 break;
   2096             }
   2097         }
   2098         if (mt_ctrl->cur_fail_count == 0) {
   2099             break;
   2100         }
   2101     }
   2102     addr = soc_reg_addr(mt_ctrl->unit, tr_mt_data->etc_ctl, REG_PORT_ANY, 0);
   2103     SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
   2104     soc_reg_field_set(mt_ctrl->unit, tr_mt_data->etc_ctl, &rval, IN_SMFL00f,
   2105                       1);
   2106     SOC_IF_ERROR_RETURN(soc_reg32_write(mt_ctrl->unit, addr, rval));
   2107     if (mt_ctrl->cur_fail_count) {
   2108         fail_name = "RBUS";
   2109         switch (mt_ctrl->cur_fail_reason & 0xffff0000) {
   2110         case 0x10000:
   2111             sal_sprintf(fail_reason, "bank %d error bit assert (0x%08x)",
   2112                         mt_ctrl->cur_fail_reason & 0xf,
   2113                         mt_ctrl->cur_fail_detail0);
   2114             break;
   2115         case 0x20000:
   2116             sal_sprintf(fail_reason, "bank %d valid bit not assert (0x%08x)",
   2117                         mt_ctrl->cur_fail_reason & 0xf,
   2118                         mt_ctrl->cur_fail_detail0);
   2119             break;
   2120         default:
   2121             return SOC_E_INTERNAL;
   2122         }
   2123         goto done;
   2124     }
   2125 
   2126     /* search test */
   2127     mt_data->sub_interface = 3;
   2128     mt_ctrl->cur_fail_count = 0;
   2129     rv = (*mt_ctrl->test_fn)(mt_data);
   2130     if (rv < 0) {
   2131         LOG_ERROR(BSL_LS_SOC_MEMTUNE,
   2132                   (BSL_META_U(mt_ctrl->unit,
   2133                               "%s search test failure: %s\n"),
   2134                               mt_ctrl->intf_name, soc_errmsg(rv)));
   2135         return rv;
   2136     }
   2137 
   2138     if (mt_ctrl->cur_fail_count) {
   2139         fail_name = "search";
   2140         switch (mt_ctrl->cur_fail_reason & 0xffff0000) {
   2141         case 0x10000:
   2142             sal_sprintf(fail_reason, "bank %d status=0x%08x, fail count=%d",
   2143                         mt_ctrl->cur_fail_reason & 0xf,
   2144                         mt_ctrl->cur_fail_detail0,
   2145                         mt_ctrl->cur_fail_count);
   2146             break;
   2147         case 0x20000:
   2148             sal_sprintf(fail_reason, "bank %d index mismatch (0x%x/0x%x), "
   2149                         "fail count=%d",
   2150                         mt_ctrl->cur_fail_reason & 0xf,
   2151                         mt_ctrl->cur_fail_detail0,
   2152                         mt_ctrl->cur_fail_detail1,
   2153                         mt_ctrl->cur_fail_count);
   2154             break;
   2155         case 0x30000:
   2156             sal_sprintf(fail_reason, "bank %d BIST search fail, fail count=%d",
   2157                         mt_ctrl->cur_fail_reason & 0xf,
   2158                         mt_ctrl->cur_fail_count);
   2159             break;
   2160         default:
   2161             return SOC_E_INTERNAL;
   2162         }
   2163         goto done;
   2164     }
   2165 
   2166  done:
   2167     if ((!(mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_PASS) &&
   2168          mt_ctrl->cur_fail_count < mt_data->test_count) ||
   2169         (!(mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL) &&
   2170          mt_ctrl->cur_fail_count >= mt_data->test_count)) {
   2171         return SOC_E_NONE;
   2172     }
   2173 
   2174     if (mt_ctrl->tx_offset_cur != -1) {
   2175         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2176                             "TX offset=%d "), mt_ctrl->tx_offset_cur));
   2177     }
   2178     if (mt_ctrl->rx_offset_cur != -1) {
   2179         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2180                             "RX offset=%d "), mt_ctrl->rx_offset_cur));
   2181     }
   2182     if (mt_ctrl->dpeo_sync_dly_cur != -1) {
   2183         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2184                             "DPEO_SYNC_DLY=%d "), mt_ctrl->dpeo_sync_dly_cur));
   2185     }
   2186     if (mt_ctrl->fcd_dpeo_cur != -1) {
   2187         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2188                             "FCD_DPEO=%d "), mt_ctrl->fcd_dpeo_cur));
   2189     }
   2190     if (mt_ctrl->rbus_sync_dly_cur != -1) {
   2191         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2192                             "RBUS_SYNC_DLY=%d "), mt_ctrl->rbus_sync_dly_cur));
   2193     }
   2194     if (mt_ctrl->fcd_rbus_cur != -1) {
   2195         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2196                             "FCD_RBUS=%d "), mt_ctrl->fcd_rbus_cur));
   2197     }
   2198     if (fail_name) {
   2199         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2200                             ": %s test FAIL %s\n"), fail_name, fail_reason));
   2201     } else {
   2202         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2203                             ": Fail count=%d\n"), mt_ctrl->cur_fail_count));
   2204     }
   2205 
   2206     return SOC_E_NONE;
   2207 }
   2208 
   2209 STATIC int
   2210 _soc_memtune_tcam_main(soc_memtune_data_t *mt_data)
   2211 {
   2212     soc_tcam_info_t *tcam_info;
   2213     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
   2214     soc_memtune_result_t *result;
   2215     int rv, offset_count, index, i;
   2216 
   2217     tcam_info = SOC_CONTROL(mt_ctrl->unit)->tcam_info;
   2218 
   2219     if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_TEST_NAME) {
   2220         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2221                             "TCAM tuning test:%s interface:\n"),
   2222                  mt_ctrl->intf_name));
   2223     }
   2224 
   2225     /* No TCAM reset on simulation, only need to re-init TCAM to setup
   2226      * partitions used by test */
   2227     if (SAL_BOOT_SIMULATION) {
   2228         tcam_info->num_tcams = -1;
   2229     }
   2230 
   2231     offset_count = (mt_ctrl->tx_offset_max - mt_ctrl->tx_offset_min + 1) *
   2232                    (mt_ctrl->rx_offset_max - mt_ctrl->rx_offset_min + 1);
   2233     mt_ctrl->fail_array = sal_alloc(offset_count * sizeof(int),
   2234                                     "memtune working data");
   2235     if (mt_ctrl->fail_array == NULL) {
   2236         return SOC_E_MEMORY;
   2237     }
   2238     sal_memset(mt_ctrl->fail_array, 0, offset_count * sizeof(int));
   2239 
   2240     mt_ctrl->do_setup_for_rbus_test = FALSE;
   2241     mt_ctrl->result_count = 0;
   2242 
   2243     for (mt_ctrl->invert_txclk_cur = mt_ctrl->invert_txclk_min;
   2244          mt_ctrl->invert_txclk_cur <= mt_ctrl->invert_txclk_max;
   2245          mt_ctrl->invert_txclk_cur++) {
   2246         for (mt_ctrl->invert_rxclk_cur = mt_ctrl->invert_rxclk_min;
   2247              mt_ctrl->invert_rxclk_cur <= mt_ctrl->invert_rxclk_max;
   2248              mt_ctrl->invert_rxclk_cur++) {
   2249             if (mt_ctrl->invert_txclk_cur != -1 &&
   2250                 mt_ctrl->invert_rxclk_cur != -1) {
   2251                 (*mt_ctrl->prog_hw3_fn)(mt_data); /* clock invert */
   2252             }
   2253             for (mt_ctrl->tx_offset_cur = mt_ctrl->tx_offset_min;
   2254                  mt_ctrl->tx_offset_cur <= mt_ctrl->tx_offset_max;
   2255                  mt_ctrl->tx_offset_cur++) {
   2256                 for (mt_ctrl->rx_offset_cur = mt_ctrl->rx_offset_min;
   2257                      mt_ctrl->rx_offset_cur <= mt_ctrl->rx_offset_max;
   2258                      mt_ctrl->rx_offset_cur++) {
   2259                     (*mt_ctrl->prog_hw2_fn)(mt_data); /* TX/RX */
   2260                     if (mt_ctrl->rx_offset_cur == mt_ctrl->rx_offset_min) {
   2261                         if (*mt_ctrl->per_tx_fn != NULL) {
   2262                             (*mt_ctrl->per_tx_fn)(mt_data);
   2263                         }
   2264                     }
   2265                     if (*mt_ctrl->per_rx_fn != NULL) {
   2266                         (*mt_ctrl->per_rx_fn)(mt_data);
   2267                     }
   2268                     rv = _soc_memtune_tcam_single_test(mt_data);
   2269                     if (SOC_FAILURE(rv)) { /* fail unexpected */
   2270                         sal_free(mt_ctrl->fail_array);
   2271                         return rv;
   2272                     }
   2273                     index = (mt_ctrl->tx_offset_cur - mt_ctrl->tx_offset_min) *
   2274                         (mt_ctrl->rx_offset_max - mt_ctrl->rx_offset_min + 1) +
   2275                         mt_ctrl->rx_offset_cur - mt_ctrl->rx_offset_min;
   2276                     mt_ctrl->fail_array[index] = mt_ctrl->cur_fail_count;
   2277                 } /* mt_ctrl->rx_offset_cur loop */
   2278             } /* mt_ctrl->tx_offset_cur loop */
   2279             result = &mt_ctrl->result[mt_ctrl->result_count];
   2280             result->invert_txclk = mt_ctrl->invert_txclk_cur;
   2281             result->invert_rxclk = mt_ctrl->invert_rxclk_cur;
   2282             /* Analyze and print result matrix */
   2283             _soc_memtune_txrx_analyze(mt_data);
   2284             result->dpeo_sync_dly = mt_ctrl->dpeo_sync_dly_cur;
   2285             result->fcd_dpeo = mt_ctrl->fcd_dpeo_cur;
   2286             result->rbus_sync_dly = mt_ctrl->rbus_sync_dly_cur;
   2287             result->fcd_rbus = mt_ctrl->fcd_rbus_cur;
   2288         } /* mt_ctrl->invert_rxclk_cur loop */
   2289     } /* mt_ctrl->invert_txclk_cur loop */
   2290 
   2291     if (mt_ctrl->invert_txclk_min != -1 && mt_ctrl->invert_rxclk_min != -1) {
   2292         result = &mt_ctrl->result[0];
   2293         for (i = 1; i < 4; i++) {
   2294             if (result->width * result->height <
   2295                 mt_ctrl->result[i].width * mt_ctrl->result[i].height) {
   2296                 result = &mt_ctrl->result[i];
   2297             }
   2298         }
   2299         mt_ctrl->invert_txclk_cur = result->invert_txclk;
   2300         mt_ctrl->invert_rxclk_cur = result->invert_rxclk;
   2301 
   2302         /* Program clock invert setting from the best result */
   2303         (*mt_ctrl->prog_hw3_fn)(mt_data);  /* clock invert */
   2304     } else {
   2305         mt_ctrl->invert_txclk_cur = mt_ctrl->invert_txclk_min;
   2306         mt_ctrl->invert_rxclk_cur = mt_ctrl->invert_rxclk_min;
   2307         result = &mt_ctrl->result[0];
   2308     }
   2309 
   2310     if (result->fail_count != offset_count) {
   2311         /* Program TX/RX setting from the best result */
   2312         mt_ctrl->tx_offset_cur = result->tx_offset;
   2313         mt_ctrl->rx_offset_cur = result->rx_offset;
   2314         (*mt_ctrl->prog_hw2_fn)(mt_data);  /* TX/RX */
   2315         if (*mt_ctrl->per_tx_fn != NULL) {
   2316             (*mt_ctrl->per_tx_fn)(mt_data);
   2317         }
   2318         if (*mt_ctrl->per_rx_fn != NULL) {
   2319             (*mt_ctrl->per_rx_fn)(mt_data);
   2320         }
   2321         rv = _soc_memtune_tcam_single_test(mt_data);
   2322         if (SOC_FAILURE(rv) || mt_ctrl->cur_fail_count) {
   2323             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2324                                 "!!! TCAM tuning FAIL --- unstable result !!!\n")));
   2325             result->fail_count = offset_count;
   2326         } else {
   2327             if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SELECTION) {
   2328                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2329                                     "TCAM tuning selection: ")));
   2330                 if (mt_ctrl->invert_txclk_cur != -1) {
   2331                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2332                                         "invert_txclk=%d "),
   2333                              mt_ctrl->invert_txclk_cur));
   2334                 }
   2335                 if (mt_ctrl->invert_rxclk_cur != -1) {
   2336                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2337                                         "invert_rxclk=%d "),
   2338                              mt_ctrl->invert_rxclk_cur));
   2339                 }
   2340                 if (mt_ctrl->tx_offset_cur != -1) {
   2341                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2342                                         "TX offset=%d "), mt_ctrl->tx_offset_cur));
   2343                 }
   2344                 if (mt_ctrl->rx_offset_cur != -1) {
   2345                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2346                                         "RX offset=%d "), mt_ctrl->rx_offset_cur));
   2347                 }
   2348                 if (mt_ctrl->dpeo_sync_dly_cur != -1) {
   2349                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2350                                         "dpeo_sync_dly=%d "),
   2351                              mt_ctrl->dpeo_sync_dly_cur));
   2352                 }
   2353                 if (mt_ctrl->fcd_dpeo_cur != -1) {
   2354                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2355                                         "fcd_dpeo=%d "), mt_ctrl->fcd_dpeo_cur));
   2356                 }
   2357                 if (mt_ctrl->rbus_sync_dly_cur != -1) {
   2358                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2359                                         "rbus_sync_dly=%d "),
   2360                              mt_ctrl->rbus_sync_dly_cur));
   2361                 }
   2362                 if (mt_ctrl->fcd_rbus_cur != -1) {
   2363                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2364                                         "fcd_rbus=%d "), mt_ctrl->fcd_rbus_cur));
   2365                 }
   2366                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2367                                     "\n")));
   2368             }
   2369         }
   2370     }
   2371 
   2372     if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY) {
   2373         if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY_HEADER) {
   2374             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2375                                 "\n Interface  ,  Area , Width , Height ,"
   2376                                 " Tc , Rc ,  TX ,  RX , Pass , Fail ,"
   2377                                 " Freq , Sb , Dac , Dist\n")));
   2378         }
   2379         for (i = 0; i < mt_ctrl->result_count; i++) {
   2380             result = &mt_ctrl->result[i];
   2381 
   2382             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2383                                 " %10s , %4d  ,  %3d  ,  %3d   ,"),
   2384                      mt_ctrl->intf_name, result->width * result->height,
   2385                      result->width, result->height));
   2386             if (result->invert_txclk != -1) {
   2387                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2388                                     " %c  ,"), result->invert_txclk ? 'I' : ' '));
   2389             } else {
   2390                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2391                                     " ** ,")));
   2392             }
   2393             if (result->invert_rxclk != -1) {
   2394                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2395                                     " %c  ,"), result->invert_rxclk ? 'I' : ' '));
   2396             } else {
   2397                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2398                                     " ** ,")));
   2399             }
   2400             if (result->fail_count != offset_count) {
   2401                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2402                                     "  %2d ,  %2d ,"),
   2403                          result->tx_offset, result->rx_offset));
   2404             } else {
   2405                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2406                                     "  ** ,  ** ,")));
   2407             }
   2408             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2409                                 " %4d , %4d ,  %3d ,  %c ,"),
   2410                      offset_count - result->fail_count, result->fail_count,
   2411                      mt_data->freq,
   2412                      mt_data->bg_sram_bist ? 'Y' : 'N'));
   2413             if (mt_ctrl->dac_value != -1) {
   2414                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2415                                     "  %2d ,"), mt_ctrl->dac_value));
   2416             } else {
   2417                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2418                                     "  ** ,")));
   2419             }
   2420             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2421                                 "  %2d"), mt_ctrl->ptr_dist));
   2422             if (result->fail_count != offset_count &&
   2423                 mt_ctrl->invert_txclk_cur != -1 &&
   2424                 result->invert_txclk == mt_ctrl->invert_txclk_cur &&
   2425                 mt_ctrl->invert_rxclk_cur != -1 &&
   2426                 result->invert_rxclk == mt_ctrl->invert_rxclk_cur) {
   2427                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2428                                     " <\n")));
   2429             } else {
   2430                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2431                                     "\n")));
   2432             }
   2433         }
   2434     }
   2435 
   2436     if (result->fail_count == offset_count) {
   2437         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2438                             "ERROR - no passing \"eye\" was found, \n"
   2439                             "please contact your Field Applications Engineer or "
   2440                             "Sales Manager\n"
   2441                             "for additional assistance.\n")));
   2442         rv = SOC_E_FAIL;
   2443     } else {
   2444         if (result->height < mt_ctrl->tx_pass_threshold ||
   2445             result->width < mt_ctrl->rx_pass_threshold) {
   2446             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   2447                                 "!!! TCAM tuning result does not pass qualified "
   2448                                 "threshold !!!\n")));
   2449         }
   2450         rv = SOC_E_NONE;
   2451         if (mt_data->config) {
   2452             rv = _soc_tr_tune_generate_config(mt_data);
   2453             if (rv < 0) {
   2454                 LOG_ERROR(BSL_LS_SOC_MEMTUNE,
   2455                           (BSL_META_U(mt_ctrl->unit,
   2456                                       "%s fail to generate config: %s\n"),
   2457                            mt_ctrl->intf_name,
   2458                            soc_errmsg(rv)));
   2459             }
   2460         }
   2461     }
   2462 
   2463     sal_free(mt_ctrl->fail_array);
   2464     return rv;
   2465 }
   2466 #endif /* BCM_TRIUMPH_SUPPORT */
   2467 
   2468 #ifdef BCM_TRIUMPH_SUPPORT
   2469 STATIC int
   2470 _soc_tr_mem_interface_tune_setup(soc_memtune_data_t *mt_data)
   2471 {
   2472     soc_memtune_ctrl_t  *mt_ctrl = mt_data->mt_ctrl;
   2473     soc_tr_memtune_data_t *tr_mt_data = mt_ctrl->data;
   2474     uint32 rval;
   2475     uint16 dev_id;
   2476     uint8 rev_id;
   2477 
   2478     soc_cm_get_id(mt_ctrl->unit, &dev_id, &rev_id);
   2479 
   2480     switch (mt_data->interface) {
   2481     case SOC_MEM_INTERFACE_SRAM:
   2482         switch (mt_data->sub_interface) {
   2483         case 0:
   2484             mt_ctrl->intf_name = "SRAM0";
   2485             tr_mt_data->config_reg1 = ES0_DDR36_CONFIG_REG1_ISr;
   2486             tr_mt_data->config_reg2 = ES0_DDR36_CONFIG_REG2_ISr;
   2487             tr_mt_data->config_reg3 = ES0_DDR36_CONFIG_REG3_ISr;
   2488             tr_mt_data->status_reg2 = ES0_DDR36_STATUS_REG2_ISr;
   2489             tr_mt_data->mode = ES0_DTU_MODEr;
   2490             tr_mt_data->tmode0 = ES0_DTU_LTE_TMODE0r;
   2491             tr_mt_data->tmode0_other_sram = ES1_DTU_LTE_TMODE0r;
   2492             tr_mt_data->sram_ctl = ES0_SRAM_CTLr;
   2493             break;
   2494         case 1:
   2495             mt_ctrl->intf_name = "SRAM1";
   2496             tr_mt_data->config_reg1 = ES1_DDR36_CONFIG_REG1_ISr;
   2497             tr_mt_data->config_reg2 = ES1_DDR36_CONFIG_REG2_ISr;
   2498             tr_mt_data->config_reg3 = ES1_DDR36_CONFIG_REG3_ISr;
   2499             tr_mt_data->status_reg2 = ES1_DDR36_STATUS_REG2_ISr;
   2500             tr_mt_data->mode = ES1_DTU_MODEr;
   2501             tr_mt_data->tmode0 = ES1_DTU_LTE_TMODE0r;
   2502             tr_mt_data->tmode0_other_sram = ES0_DTU_LTE_TMODE0r;
   2503             tr_mt_data->sram_ctl = ES1_SRAM_CTLr;
   2504             break;
   2505         default:
   2506             return SOC_E_PARAM;
   2507         }
   2508 
   2509         if ((SOC_IS_TRIUMPH(mt_ctrl->unit) && rev_id >= BCM56624_B2_REV_ID) ||
   2510             SOC_IS_TRIUMPH2(mt_ctrl->unit)) {
   2511             mt_ctrl->tx_pass_threshold = 9;
   2512             mt_ctrl->rx_pass_threshold = 11;
   2513         }
   2514 
   2515         if (soc_feature(mt_ctrl->unit, soc_feature_esm_rxfifo_resync)) {
   2516             mt_data->phase_sel_ovrd = FALSE;
   2517         }
   2518 
   2519         mt_ctrl->prog_hw1_fn = _soc_tr_ddr_txrx_prog_hw_cb;
   2520         mt_ctrl->prog_hw2_fn = _soc_tr_ddr_latency_prog_hw_cb;
   2521         mt_ctrl->prog_hw3_fn = _soc_tr_ddr_phase_sel_prog_hw_cb;
   2522         mt_ctrl->prog_hw4_fn = _soc_tr_ddr_nops_prog_hw_cb;
   2523         if (soc_feature(mt_ctrl->unit, soc_feature_esm_rxfifo_resync)) {
   2524             mt_ctrl->per_rx_fn = _soc_tr_ddr_per_rx_cb;
   2525         }
   2526         mt_ctrl->test_fn = _soc_tr_sram_tune_test_cb;
   2527 
   2528         mt_ctrl->phase_sel_min =
   2529             mt_data->phase_sel_ovrd ? SOC_TR_PHASE_SEL_MIN : -1;
   2530         mt_ctrl->phase_sel_max =
   2531             mt_data->phase_sel_ovrd ? SOC_TR_PHASE_SEL_MAX : -1;
   2532         mt_ctrl->em_latency_min = SOC_TR_EM_LATENCY_MIN;
   2533         if (soc_reg_field_valid(mt_ctrl->unit, tr_mt_data->tmode0,
   2534                                 EM_LATENCY8f)) {
   2535             mt_ctrl->em_latency_max = SOC_TR_EM_LATENCY_MAX;;
   2536         } else {
   2537             mt_ctrl->em_latency_max = 7;
   2538         }
   2539         if (mt_data->man_em_latency != -1) {
   2540             mt_ctrl->em_latency_min = mt_data->man_em_latency;
   2541             mt_ctrl->em_latency_max = mt_data->man_em_latency;
   2542         }
   2543         if (soc_reg_field_valid(mt_ctrl->unit, tr_mt_data->config_reg2,
   2544                                 SEL_EARLY1_0f)) {
   2545             mt_ctrl->ddr_latency_min = SOC_TR_DDR_LATENCY_MIN;
   2546             mt_ctrl->ddr_latency_max = SOC_TR_DDR_LATENCY_MAX;
   2547             if (mt_data->man_ddr_latency != -1) {
   2548                 mt_ctrl->ddr_latency_min = mt_data->man_ddr_latency;
   2549                 mt_ctrl->ddr_latency_max = mt_data->man_ddr_latency;
   2550             }
   2551         } else {
   2552             mt_ctrl->ddr_latency_min = -1;
   2553             mt_ctrl->ddr_latency_max = -1;
   2554             mt_data->man_ddr_latency = -1;
   2555         }
   2556         mt_ctrl->tx_offset_min = SOC_TR_SRAM_TX_OFFSET_MIN;
   2557         mt_ctrl->tx_offset_max = SOC_TR_SRAM_TX_OFFSET_MAX;
   2558         if (mt_data->man_tx_offset != -1) {
   2559             mt_ctrl->tx_offset_min = mt_data->man_tx_offset;
   2560             mt_ctrl->tx_offset_max = mt_data->man_tx_offset;
   2561         }
   2562         mt_ctrl->rx_offset_min = SOC_TR_SRAM_RX_OFFSET_MIN;
   2563         mt_ctrl->rx_offset_max = SOC_TR_SRAM_RX_OFFSET_MAX;
   2564         if (mt_data->man_rx_offset != -1) {
   2565             mt_ctrl->rx_offset_min = mt_data->man_rx_offset;
   2566             mt_ctrl->rx_offset_max = mt_data->man_rx_offset;
   2567         }
   2568         mt_ctrl->w2r_nops_min = SOC_TR_SRAM_W2R_NOPS_MIN;
   2569         mt_ctrl->w2r_nops_max = SOC_TR_SRAM_W2R_NOPS_MAX;
   2570         mt_ctrl->r2w_nops_min = SOC_TR_SRAM_R2W_NOPS_MIN;
   2571         mt_ctrl->r2w_nops_max = SOC_TR_SRAM_R2W_NOPS_MAX;
   2572         break;
   2573 
   2574     case SOC_MEM_INTERFACE_TCAM:
   2575         mt_ctrl->intf_name = "TCAM";
   2576         tr_mt_data->config_reg1 = ETU_DDR72_CONFIG_REG1_ISr;
   2577         tr_mt_data->config_reg3 = ETU_DDR72_CONFIG_REG3_ISr;
   2578         tr_mt_data->etc_ctl = ETC_CTLr;
   2579         tr_mt_data->inst_status = ETU_ET_INST_STATUSr;
   2580         tr_mt_data->dbus_fail_mask = 0;
   2581         soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status,
   2582                           &tr_mt_data->dbus_fail_mask, SEQ_DPEO_ERRf, 1);
   2583         soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status,
   2584                           &tr_mt_data->dbus_fail_mask, DPEO_RISEf, 1);
   2585         soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status,
   2586                           &tr_mt_data->dbus_fail_mask, DPEO_FALLf, 1);
   2587         soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status,
   2588                           &tr_mt_data->dbus_fail_mask, DPRERR0f, 1);
   2589         soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status,
   2590                           &tr_mt_data->dbus_fail_mask, DPRERR1f, 1);
   2591         tr_mt_data->rbus_fail_mask = 0;
   2592         soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status,
   2593                           &tr_mt_data->rbus_fail_mask, SEQ_DPEO_ERRf, 1);
   2594         soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status,
   2595                           &tr_mt_data->rbus_fail_mask, RDACKf, 1);
   2596         soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status,
   2597                           &tr_mt_data->rbus_fail_mask, DPEO_RISEf, 1);
   2598         soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status,
   2599                           &tr_mt_data->rbus_fail_mask, DPEO_FALLf, 1);
   2600         soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status,
   2601                           &tr_mt_data->rbus_fail_mask, DPRERR0f, 1);
   2602         soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status,
   2603                           &tr_mt_data->rbus_fail_mask, DPRERR1f, 1);
   2604         tr_mt_data->rbus_valid_mask = 0;
   2605         soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status,
   2606                           &tr_mt_data->rbus_valid_mask, RBUS0_VALIDf, 1);
   2607         soc_reg_field_set(mt_ctrl->unit, tr_mt_data->inst_status,
   2608                           &tr_mt_data->rbus_valid_mask, RBUS1_VALIDf, 1);
   2609 
   2610         if ((SOC_IS_TRIUMPH(mt_ctrl->unit) && rev_id >= BCM56624_B2_REV_ID) ||
   2611             SOC_IS_TRIUMPH2(mt_ctrl->unit)) {
   2612             mt_ctrl->tx_pass_threshold = 11;
   2613             mt_ctrl->rx_pass_threshold = 11;
   2614         }
   2615 
   2616         mt_ctrl->prog_hw1_fn = _soc_tr_tcam_dpeo_rbus_prog_hw_cb;
   2617         mt_ctrl->prog_hw2_fn = _soc_tr_tcam_txrx_prog_hw_cb;
   2618         mt_ctrl->prog_hw3_fn = _soc_tr_tcam_invert_clk_prog_hw_cb;
   2619         mt_ctrl->per_tx_fn = _soc_tr_tcam_per_tx_cb;
   2620         mt_ctrl->per_rx_fn = _soc_tr_tcam_per_rx_cb;
   2621         mt_ctrl->test_fn = _soc_tr_tcam_tune_test_cb;
   2622 
   2623         SOC_IF_ERROR_RETURN
   2624             (READ_ETU_DDR72_CONFIG_REG3_ISr(mt_ctrl->unit, &rval));
   2625         if (soc_reg_field_valid(mt_ctrl->unit, ETU_DDR72_CONFIG_REG3_ISr,
   2626                                 INVERT_TXCLKf)) {
   2627             if (mt_data->phase_sel_ovrd) {
   2628                 mt_ctrl->invert_txclk_min = SOC_TR_TCAM_INVERT_TXCLK_MIN;
   2629                 mt_ctrl->invert_txclk_max = SOC_TR_TCAM_INVERT_TXCLK_MAX;
   2630             } else {
   2631                 mt_ctrl->invert_txclk_min =
   2632                     mt_ctrl->invert_txclk_max =
   2633                     soc_reg_field_get(mt_ctrl->unit, ETU_DDR72_CONFIG_REG3_ISr,
   2634                                       rval, INVERT_TXCLKf);
   2635             }
   2636         } else {
   2637             mt_ctrl->invert_txclk_min = -1;
   2638             mt_ctrl->invert_txclk_max = -1;
   2639         }
   2640         if (soc_reg_field_valid(mt_ctrl->unit, ETU_DDR72_CONFIG_REG3_ISr,
   2641                                 INVERT_RXCLKf)) {
   2642             if (mt_data->phase_sel_ovrd) {
   2643                 mt_ctrl->invert_rxclk_min = SOC_TR_TCAM_INVERT_RXCLK_MIN;
   2644                 mt_ctrl->invert_rxclk_max = SOC_TR_TCAM_INVERT_RXCLK_MAX;
   2645             } else {
   2646                 mt_ctrl->invert_rxclk_min =
   2647                     mt_ctrl->invert_rxclk_max =
   2648                     soc_reg_field_get(mt_ctrl->unit, ETU_DDR72_CONFIG_REG3_ISr,
   2649                                       rval, INVERT_RXCLKf);
   2650             }
   2651         } else {
   2652             mt_ctrl->invert_rxclk_min = -1;
   2653             mt_ctrl->invert_rxclk_max = -1;
   2654         }
   2655         SOC_IF_ERROR_RETURN
   2656             (READ_ETU_DDR72_CONFIG_REG1_ISr(mt_ctrl->unit, &rval));
   2657         mt_ctrl->tx_offset_min = SOC_TR_TCAM_TX_OFFSET_MIN;
   2658         if (soc_reg_field_get(mt_ctrl->unit, ETU_DDR72_CONFIG_REG1_ISr,
   2659                               rval, MIDL_TX_ENf) &&
   2660             soc_reg_field_get(mt_ctrl->unit, ETU_DDR72_CONFIG_REG1_ISr,
   2661                               rval, SEL_TX_CLKDLY_BLKf)) {
   2662             mt_ctrl->tx_offset_max = SOC_TR_TCAM_MIDL_TX_OFFSET_MAX;
   2663         } else {
   2664             mt_ctrl->tx_offset_max = SOC_TR_TCAM_VCDL_TX_OFFSET_MAX;
   2665         }
   2666         if (mt_data->man_tx_offset != -1) {
   2667             mt_ctrl->tx_offset_min = mt_data->man_tx_offset;
   2668             mt_ctrl->tx_offset_max = mt_data->man_tx_offset;
   2669         }
   2670         mt_ctrl->rx_offset_min = SOC_TR_TCAM_RX_OFFSET_MIN;
   2671         if (soc_reg_field_get(mt_ctrl->unit, ETU_DDR72_CONFIG_REG1_ISr,
   2672                               rval, MIDL_RX_ENf) &&
   2673             soc_reg_field_get(mt_ctrl->unit, ETU_DDR72_CONFIG_REG1_ISr,
   2674                               rval, SEL_RX_CLKDLY_BLKf)) {
   2675             mt_ctrl->rx_offset_max = SOC_TR_TCAM_MIDL_RX_OFFSET_MAX;
   2676         } else {
   2677             mt_ctrl->rx_offset_max = SOC_TR_TCAM_VCDL_RX_OFFSET_MAX;
   2678         }
   2679         if (mt_data->man_rx_offset != -1) {
   2680             mt_ctrl->rx_offset_min = mt_data->man_rx_offset;
   2681             mt_ctrl->rx_offset_max = mt_data->man_rx_offset;
   2682         }
   2683 
   2684         mt_ctrl->dpeo_sel_cur = 0; /* do DPEO_0 only */
   2685         mt_ctrl->dpeo_sync_dly_min = SOC_TR_DPEO_SYNC_DLY_MIN;
   2686         mt_ctrl->dpeo_sync_dly_max = SOC_TR_DPEO_SYNC_DLY_MAX;
   2687         mt_ctrl->fcd_dpeo_min = SOC_TR_FCD_DPEO_MIN;
   2688         mt_ctrl->fcd_dpeo_max = SOC_TR_FCD_DPEO_MAX;
   2689 
   2690         mt_ctrl->rbus_sync_dly_min = SOC_TR_RBUS_SYNC_DLY_MIN;
   2691         mt_ctrl->rbus_sync_dly_max = SOC_TR_RBUS_SYNC_DLY_MAX;
   2692         mt_ctrl->fcd_rbus_min = SOC_TR_FCD_RBUS_MIN;
   2693         mt_ctrl->fcd_rbus_max = SOC_TR_FCD_RBUS_MAX;
   2694         break;
   2695 
   2696     default:
   2697         return SOC_E_PARAM;
   2698     }
   2699 
   2700     if (mt_ctrl->tx_pass_threshold >
   2701         mt_ctrl->tx_offset_max - mt_ctrl->tx_offset_min + 1) {
   2702         mt_ctrl->tx_pass_threshold = 0;
   2703     }
   2704     if (mt_ctrl->rx_pass_threshold >
   2705         mt_ctrl->rx_offset_max - mt_ctrl->rx_offset_min + 1) {
   2706         mt_ctrl->rx_pass_threshold = 0;
   2707     }
   2708 
   2709     return SOC_E_NONE;
   2710 }
   2711 
   2712 STATIC int
   2713 _soc_tr_mem_interface_tune(int unit, soc_memtune_data_t *mt_data)
   2714 {
   2715     soc_tcam_info_t *tcam_info;
   2716     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
   2717     soc_tr_memtune_data_t *tr_mt_data;
   2718     tr_ext_sram_bist_t *sram_bist, bg_sram_bist;
   2719     soc_reg_t reg;
   2720     uint32 addr, rval, sub_interface_mask;
   2721     int rv, i;
   2722 
   2723     tcam_info = SOC_CONTROL(unit)->tcam_info;
   2724     if (tcam_info == NULL) {
   2725         return SOC_E_INIT;
   2726     }
   2727 
   2728     tr_mt_data = sal_alloc(sizeof(soc_tr_memtune_data_t),
   2729                            "memtune working data");
   2730     if (!tr_mt_data) {
   2731         return SOC_E_MEMORY;
   2732     }
   2733     sal_memset(tr_mt_data, 0, sizeof(soc_tr_memtune_data_t));
   2734     mt_ctrl->data = tr_mt_data;
   2735 
   2736     sram_bist = sal_alloc(sizeof(tr_ext_sram_bist_t), "memtune working data");
   2737     if (!sram_bist) {
   2738         return SOC_E_MEMORY;
   2739     }
   2740     sal_memset(sram_bist, 0, sizeof(tr_ext_sram_bist_t));
   2741     mt_ctrl->sram_bist = sram_bist;
   2742 
   2743     if (mt_data->bg_sram_bist) {
   2744         sal_memset(&bg_sram_bist, 0, sizeof(bg_sram_bist));
   2745         if (mt_data->bg_d0r_0 == 0xffffffff) {
   2746             bg_sram_bist.d0r_0 = bg_sram_bist.d0r_1 = 0x3ffff;
   2747             bg_sram_bist.d0f_0 = bg_sram_bist.d0f_1 = 0;
   2748             bg_sram_bist.d1r_0 = bg_sram_bist.d1r_1 = 0x3ffff;
   2749             bg_sram_bist.d1f_0 = bg_sram_bist.d1f_1 = 0;
   2750         } else {
   2751             bg_sram_bist.d0r_0 = mt_data->bg_d0r_0 & 0x3ffff;
   2752             bg_sram_bist.d0r_1 = mt_data->bg_d0r_1 & 0x3ffff;
   2753             bg_sram_bist.d0f_0 = mt_data->bg_d0f_0 & 0x3ffff;
   2754             bg_sram_bist.d0f_1 = mt_data->bg_d0f_1 & 0x3ffff;
   2755             bg_sram_bist.d1r_0 = mt_data->bg_d1r_0 & 0x3ffff;
   2756             bg_sram_bist.d1r_1 = mt_data->bg_d1r_1 & 0x3ffff;
   2757             bg_sram_bist.d1f_0 = mt_data->bg_d1f_0 & 0x3ffff;
   2758             bg_sram_bist.d1f_1 = mt_data->bg_d1f_1 & 0x3ffff;
   2759         }
   2760         if (mt_data->bg_adr0 == -1) {
   2761             bg_sram_bist.adr0 = 0x0;   /* starting address */
   2762         } else {
   2763             bg_sram_bist.adr0 = mt_data->bg_adr0 & 0x3ffffe;
   2764         }
   2765         if (mt_data->bg_adr1 == -1 || mt_data->bg_adr_mode == 3) {
   2766             bg_sram_bist.adr1 = 0x10;  /* end address */
   2767         } else {
   2768             bg_sram_bist.adr1 = mt_data->bg_adr1 & 0x3ffffe;
   2769         }
   2770         if (mt_data->bg_loop_mode == -1) {
   2771             bg_sram_bist.loop_mode = 3; /* WW_RR */
   2772         } else {
   2773             bg_sram_bist.loop_mode = mt_data->bg_loop_mode & 3;
   2774         }
   2775         if (mt_data->bg_adr_mode == -1) {
   2776             bg_sram_bist.adr_mode = 2; /* from ADR0 to ADR1 w/ step of 2 */
   2777         } else {
   2778             bg_sram_bist.adr_mode = mt_data->bg_adr_mode & 3;
   2779         }
   2780         bg_sram_bist.em_latency = -1;
   2781         bg_sram_bist.w2r_nops = -1;
   2782         bg_sram_bist.r2w_nops = -1;
   2783     }
   2784 
   2785     switch (mt_data->interface) {
   2786     case SOC_MEM_INTERFACE_SRAM:
   2787         if (mt_data->sub_interface > 1) {
   2788             return SOC_E_PARAM;
   2789         } else if (mt_data->sub_interface < 0) {
   2790             sub_interface_mask = 0x3;
   2791         } else {
   2792             sub_interface_mask = 1 << mt_data->sub_interface;
   2793         }
   2794 
   2795         /* (Optionally) program frequency */
   2796         if (mt_data->freq != -1) {
   2797             (void)soc_triumph_esm_init_set_sram_freq(unit, mt_data->freq);
   2798         } else {
   2799             mt_data->freq = tcam_info->sram_freq;
   2800             if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SETTING) {
   2801                 LOG_CLI((BSL_META_U(unit,
   2802                                     "Using SRAM frequency %d\n"),
   2803                          tcam_info->sram_freq));
   2804             }
   2805         }
   2806 
   2807         rv = SOC_E_NONE;
   2808         for (i = 0; i < 2; i++) {
   2809             if (!(sub_interface_mask & (1 << i))) {
   2810                 continue;
   2811             }
   2812             mt_data->sub_interface = i;
   2813             SOC_IF_ERROR_RETURN
   2814                 (_soc_tr_mem_interface_tune_setup(mt_data));
   2815 
   2816             /* Setup sram_bist control structure
   2817              *          --   ---------   ---------   ---------   ---------   --
   2818              *            \ /         \ /         \ /         \ /         \ /
   2819              * DQ[35:18]   X   D0R_1   X   D0F_1  X    D1R_1   X   D1F_1   X
   2820              *            / \         / \         / \         / \         / \
   2821              *          --   ---------   ---------   ---------   ---------   --
   2822              *
   2823              *          --   ---------   ---------   ---------   ---------   --
   2824              *            \ /         \ /         \ /         \ /         \ /
   2825              * DQ[17:0]    X   D0R_0   X   D0F_0   X   D1R_0   X   D1F_0   X
   2826              *            / \         / \         / \         / \         / \
   2827              *          --   ---------   ---------   ---------   ---------   --
   2828              */
   2829             if (mt_data->d0r_0 == 0xffffffff) {
   2830                 sram_bist->d1r_0 = sram_bist->d0r_0 = 0xffffffff & 0x3ffff;
   2831                 sram_bist->d1r_1 = sram_bist->d0r_1 = 0x55555555 & 0x3ffff;
   2832                 sram_bist->d1f_0 = sram_bist->d0f_0 = 0x00000000 & 0x3ffff;
   2833                 sram_bist->d1f_1 = sram_bist->d0f_1 = 0xaaaaaaaa & 0x3ffff;
   2834             } else {
   2835                 sram_bist->d0r_0 = mt_data->d0r_0 & 0x3ffff;
   2836                 sram_bist->d0r_1 = mt_data->d0r_1 & 0x3ffff;
   2837                 sram_bist->d0f_0 = mt_data->d0f_0 & 0x3ffff;
   2838                 sram_bist->d0f_1 = mt_data->d0f_1 & 0x3ffff;
   2839                 sram_bist->d1r_0 = mt_data->d1r_0 & 0x3ffff;
   2840                 sram_bist->d1r_1 = mt_data->d1r_1 & 0x3ffff;
   2841                 sram_bist->d1f_0 = mt_data->d1f_0 & 0x3ffff;
   2842                 sram_bist->d1f_1 = mt_data->d1f_1 & 0x3ffff;
   2843             }
   2844             if (mt_data->adr0 == -1) {
   2845                 sram_bist->adr0 = 0x0;   /* starting address */
   2846             } else {
   2847                 sram_bist->adr0 = mt_data->adr0 & 0x3ffffe;
   2848             }
   2849             if (mt_data->adr1 == -1 || mt_data->adr_mode == 3) {
   2850                 sram_bist->adr1 = 0x10;  /* end address */
   2851             } else {
   2852                 sram_bist->adr1 = mt_data->adr1 & 0x3ffffe;
   2853             }
   2854             if (mt_data->adr_mode == -1) {
   2855                 sram_bist->adr_mode = 2; /* from ADR0 to ADR1 w/ step of 2 */
   2856             } else {
   2857                 sram_bist->adr_mode = mt_data->adr_mode & 3;
   2858             }
   2859             sram_bist->wdoebr = -1;
   2860             sram_bist->em_latency = -1;
   2861             sram_bist->w2r_nops = -1;
   2862             sram_bist->r2w_nops = -1;
   2863             SOC_IF_ERROR_RETURN
   2864                 (soc_triumph_ext_sram_bist_setup(unit, mt_data->sub_interface,
   2865                                                  sram_bist));
   2866 
   2867             /*
   2868              * Following sram bist registers has been set properly,
   2869              * don't touch them during test to save time:
   2870              * D0R_0, D0R_1, D0F_0, D0F_1, D1R_0, D1R_1, D1F_0, D1F_1,
   2871              * ADR0, ADR1, TMODE1
   2872              */
   2873             sram_bist->d0r_0 = 0xffffffff;
   2874             sram_bist->d1r_0 = 0xffffffff;
   2875             sram_bist->adr0 = -1;
   2876             sram_bist->adr1 = -1;
   2877             sram_bist->wdoebr = -1;
   2878 
   2879             /* Get BIASGEN DAC_VALUE */
   2880             reg = tr_mt_data->config_reg3;
   2881             addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0);
   2882             SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &rval));
   2883             mt_ctrl->dac_value = -1;
   2884             if (soc_reg_field_get(unit, reg, rval, BIASGEN_DAC_ENf)) {
   2885                 mt_ctrl->dac_value = soc_reg_field_get(unit, reg, rval,
   2886                                                        BIASGEN_DAC_CTRLf);
   2887             }
   2888 
   2889             /* Optionally do PVT compensation */
   2890             mt_ctrl->odtres_val = -1;
   2891             mt_ctrl->pdrive_val = -1;
   2892             mt_ctrl->ndrive_val = -1;
   2893             mt_ctrl->slew_val = -1;
   2894             if (mt_data->do_pvt_comp) {
   2895                 reg = tr_mt_data->config_reg2;
   2896                 SOC_IF_ERROR_RETURN(soc_triumph_esm_init_pvt_comp(unit, i));
   2897                 addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0);
   2898                 SOC_IF_ERROR_RETURN(soc_reg32_read(unit, addr, &rval));
   2899                 if (soc_reg_field_get(unit, reg, rval, OVRD_EN_ODTRES_PVTf)) {
   2900                     mt_ctrl->odtres_val = soc_reg_field_get(unit, reg, rval,
   2901                                                             PVT_ODTRES_VALf);
   2902                 }
   2903                 if (soc_reg_field_get(unit, reg, rval, OVRD_EN_DRIVER_PVTf)) {
   2904                     mt_ctrl->pdrive_val = soc_reg_field_get(unit, reg, rval,
   2905                                                             PVT_PDRIVE_VALf);
   2906                     mt_ctrl->ndrive_val = soc_reg_field_get(unit, reg, rval,
   2907                                                             PVT_NDRIVE_VALf);
   2908                 }
   2909                 if (soc_reg_field_get(unit, reg, rval, OVRD_EN_SLEW_PVTf)) {
   2910                     mt_ctrl->slew_val = soc_reg_field_get(unit, reg, rval,
   2911                                                           PVT_SLEW_VALf);
   2912                 }
   2913             }
   2914 
   2915             /* Optionally setup background TCAM BIST */
   2916             if (mt_data->bg_tcam_bist) {
   2917                 LOG_CLI((BSL_META_U(unit,
   2918                                     "Do TCAM BIST loop count %d\n"),
   2919                          mt_data->bg_tcam_loop_count));
   2920                 SOC_IF_ERROR_RETURN
   2921                     (soc_tr_tcam_type1_memtest_dpeo(unit, 8,
   2922                                                     mt_data->bg_tcam_oemap,
   2923                                                     mt_data->bg_tcam_data));
   2924                 rval = 0;
   2925                 soc_reg_field_set(unit, ETU_LTE_BIST_CTLr, &rval,
   2926                                   RD_EN_BIST_RSLTSf, 1);
   2927                 soc_reg_field_set(unit, ETU_LTE_BIST_CTLr, &rval, LOOP_COUNTf,
   2928                                   mt_data->bg_tcam_loop_count);
   2929                 SOC_IF_ERROR_RETURN(WRITE_ETU_LTE_BIST_CTLr(unit, rval));
   2930             }
   2931 
   2932             /* Optionally do background BIST on the other SRAM interface */
   2933             if (mt_data->bg_sram_bist) {
   2934                 LOG_CLI((BSL_META_U(unit,
   2935                                     "Do SRAM BIST on SRAM%d with loop mode %d\n"),
   2936                          mt_data->sub_interface ^ 1,
   2937                          bg_sram_bist.loop_mode));
   2938                 soc_triumph_ext_sram_enable_set(unit,
   2939                                                 mt_data->sub_interface ^ 1,
   2940                                                 TRUE, TRUE);
   2941                 soc_triumph_ext_sram_bist_setup(unit,
   2942                                                 mt_data->sub_interface ^ 1,
   2943                                                 &bg_sram_bist);
   2944 
   2945                 reg = tr_mt_data->tmode0_other_sram;
   2946                 addr = soc_reg_addr(unit, reg, REG_PORT_ANY, 0);
   2947                 rv = soc_reg32_read(unit, addr, &rval);
   2948                 if (SOC_SUCCESS(rv)) {
   2949                     soc_reg_field_set(unit, reg, &rval, START_LAB_TESTf, 1);
   2950                     soc_reg_field_set(unit, reg, &rval, FOREVERf, 1);
   2951                     (void)soc_reg32_write(unit, addr, rval);
   2952                 }
   2953             }
   2954 
   2955             rv = _soc_memtune_ddr_main(mt_data);
   2956 
   2957             if (mt_data->bg_sram_bist) {
   2958                 soc_reg_field_set(unit, reg, &rval, FOREVERf, 0);
   2959                 (void)soc_reg32_write(unit, addr, rval);
   2960                 soc_triumph_ext_sram_enable_set(unit,
   2961                                                 mt_data->sub_interface ^ 1,
   2962                                                 FALSE, TRUE);
   2963             }
   2964 
   2965             if (mt_data->bg_tcam_bist) {
   2966                 rval = 0;
   2967                 soc_reg_field_set(unit, ETU_LTE_BIST_CTLr, &rval, LOOP_COUNTf,
   2968                                   1);
   2969                 SOC_IF_ERROR_RETURN(WRITE_ETU_LTE_BIST_CTLr(unit, rval));
   2970             }
   2971 
   2972             if (SOC_FAILURE(rv)) {
   2973                 break;
   2974             }
   2975         }
   2976         break;
   2977 
   2978     case SOC_MEM_INTERFACE_TCAM:
   2979         if (mt_data->sub_interface > 3) {
   2980             return SOC_E_PARAM;
   2981         }
   2982         mt_data->sub_interface = 0;
   2983         SOC_IF_ERROR_RETURN(_soc_tr_mem_interface_tune_setup(mt_data));
   2984 
   2985         if (mt_data->freq != -1) {
   2986             (void)soc_triumph_esm_init_set_tcam_freq(mt_ctrl->unit,
   2987                                                      mt_data->freq);
   2988         } else {
   2989             mt_data->freq = tcam_info->tcam_freq;
   2990             if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SETTING) {
   2991                 LOG_CLI((BSL_META_U(unit,
   2992                                     "Using TCAM frequency %d\n"),
   2993                          tcam_info->tcam_freq));
   2994             }
   2995         }
   2996 
   2997         SOC_IF_ERROR_RETURN(READ_ETU_DDR72_CONFIG_REG2_ISr(unit, &rval));
   2998         mt_ctrl->dac_value = -1;
   2999         if (soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG2_ISr, rval,
   3000                               BIASGEN_DAC_ENf)) {
   3001             mt_ctrl->dac_value =
   3002                 soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG2_ISr, rval,
   3003                                   BIASGEN_DAC_CTRLf);
   3004         }
   3005 
   3006         SOC_IF_ERROR_RETURN(READ_ETU_DDR72_CONFIG_REG1_ISr(unit, &rval));
   3007         mt_ctrl->ptr_dist =
   3008             soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG1_ISr, rval,
   3009                               SEL_WRFIFO_PTR_CLKf);
   3010 
   3011         mt_ctrl->odtres_val = -1;
   3012         mt_ctrl->pdrive_val = -1;
   3013         mt_ctrl->ndrive_val = -1;
   3014         mt_ctrl->slew_val = -1;
   3015         if (mt_data->do_pvt_comp) {
   3016             SOC_IF_ERROR_RETURN(soc_triumph_esm_init_pvt_comp(unit, 2));
   3017             SOC_IF_ERROR_RETURN
   3018                 (READ_ETU_DDR72_CONFIG_REG2_ISr(unit, &rval));
   3019             if (soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG2_ISr, rval,
   3020                                   OVRD_EN_ODTRES_PVTf)) {
   3021                 mt_ctrl->odtres_val =
   3022                     soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG2_ISr,
   3023                                       rval, PVT_ODTRES_VALf);
   3024             }
   3025             if (soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG2_ISr, rval,
   3026                                   OVRD_EN_DRIVER_PVTf)) {
   3027                 mt_ctrl->pdrive_val =
   3028                     soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG2_ISr,
   3029                                       rval, PVT_PDRIVE_VALf);
   3030                 mt_ctrl->ndrive_val =
   3031                     soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG2_ISr,
   3032                                       rval, PVT_NDRIVE_VALf);
   3033             }
   3034             if (soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG2_ISr, rval,
   3035                                   OVRD_EN_SLEW_PVTf)) {
   3036                 mt_ctrl->slew_val =
   3037                     soc_reg_field_get(unit, ETU_DDR72_CONFIG_REG2_ISr,
   3038                                       rval, PVT_SLEW_VALf);
   3039             }
   3040         }
   3041 
   3042         if (mt_data->bg_sram_bist) {
   3043             LOG_CLI((BSL_META_U(unit,
   3044                                 "Do SRAM BIST on both SRAM with loop mode %d\n"),
   3045                      bg_sram_bist.loop_mode));
   3046             soc_triumph_ext_sram_enable_set(unit, 0, TRUE, TRUE);
   3047             soc_triumph_ext_sram_bist_setup(unit, 0, &bg_sram_bist);
   3048             SOC_IF_ERROR_RETURN(READ_ES0_DTU_LTE_TMODE0r(unit, &rval));
   3049             soc_reg_field_set(unit, ES0_DTU_LTE_TMODE0r, &rval,
   3050                               START_LAB_TESTf, 1);
   3051             soc_reg_field_set(unit, ES0_DTU_LTE_TMODE0r, &rval, FOREVERf, 1);
   3052             SOC_IF_ERROR_RETURN(WRITE_ES0_DTU_LTE_TMODE0r(unit, rval));
   3053 
   3054             soc_triumph_ext_sram_enable_set(unit, 1, TRUE, TRUE);
   3055             soc_triumph_ext_sram_bist_setup(unit, 1, &bg_sram_bist);
   3056             SOC_IF_ERROR_RETURN(READ_ES1_DTU_LTE_TMODE0r(unit, &rval));
   3057             soc_reg_field_set(unit, ES1_DTU_LTE_TMODE0r, &rval,
   3058                               START_LAB_TESTf, 1);
   3059             soc_reg_field_set(unit, ES1_DTU_LTE_TMODE0r, &rval, FOREVERf, 1);
   3060             SOC_IF_ERROR_RETURN(WRITE_ES1_DTU_LTE_TMODE0r(unit, rval));
   3061         }
   3062 
   3063         rv = _soc_memtune_tcam_main(mt_data);
   3064 
   3065         if (mt_data->bg_sram_bist) {
   3066             SOC_IF_ERROR_RETURN(READ_ES0_DTU_LTE_TMODE0r(unit, &rval));
   3067             soc_reg_field_set(unit, ES0_DTU_LTE_TMODE0r, &rval, FOREVERf, 0);
   3068             SOC_IF_ERROR_RETURN(WRITE_ES0_DTU_LTE_TMODE0r(unit, rval));
   3069             soc_triumph_ext_sram_enable_set(unit, 0, FALSE, TRUE);
   3070 
   3071             SOC_IF_ERROR_RETURN(READ_ES1_DTU_LTE_TMODE0r(unit, &rval));
   3072             soc_reg_field_set(unit, ES1_DTU_LTE_TMODE0r, &rval, FOREVERf, 0);
   3073             SOC_IF_ERROR_RETURN(WRITE_ES1_DTU_LTE_TMODE0r(unit, rval));
   3074             soc_triumph_ext_sram_enable_set(unit, 1, FALSE, TRUE);
   3075         }
   3076 
   3077         break;
   3078     default:
   3079         return SOC_E_UNAVAIL;
   3080     }
   3081 
   3082     return rv;
   3083 }
   3084 #endif /* BCM_TRIUMPH_SUPPORT */
   3085 
   3086 int
   3087 soc_mem_interface_tune(int unit, soc_memtune_data_t *mt_data)
   3088 {
   3089     soc_memtune_ctrl_t *mt_ctrl;
   3090     int rv = SOC_E_NONE;
   3091 
   3092     mt_ctrl = sal_alloc(sizeof(soc_memtune_ctrl_t), "memtune working data");
   3093     if (!mt_ctrl) {
   3094         return SOC_E_MEMORY;
   3095     }
   3096     sal_memset(mt_ctrl, 0, sizeof(soc_memtune_ctrl_t));
   3097     mt_ctrl->unit = unit;
   3098     mt_data->mt_ctrl = mt_ctrl;
   3099 
   3100     if (mt_data->verbose) {
   3101         mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_TEST_NAME |
   3102             SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY |
   3103             SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY_HEADER |
   3104             SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL_MATRIX |
   3105             SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS |
   3106             SOC_MEMTUNE_CTRL_FLAGS_SHOW_SELECTION |
   3107             SOC_MEMTUNE_CTRL_FLAGS_SHOW_PASS |
   3108             SOC_MEMTUNE_CTRL_FLAGS_SHOW_SETTING;
   3109         if (!mt_data->suppress_fail) {
   3110             mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL;
   3111         }
   3112     }
   3113     if (mt_data->summary) {
   3114         mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY;
   3115     }
   3116     if (mt_data->summary_header) {
   3117         mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY_HEADER;
   3118     }
   3119     if (mt_data->show_matrix) {
   3120         mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL_MATRIX |
   3121             SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS |
   3122             SOC_MEMTUNE_CTRL_FLAGS_SHOW_SELECTION;
   3123     }
   3124     if (mt_data->show_progress) {
   3125         mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_PROGRESS;
   3126     }
   3127 
   3128 #ifdef BCM_TRIUMPH_SUPPORT
   3129     if (soc_feature(unit, soc_feature_esm_support)) {
   3130         rv = _soc_tr_mem_interface_tune(unit, mt_data);
   3131     }
   3132 #endif /* BCM_TRIUMPH_SUPPORT */
   3133 
   3134     if (mt_ctrl->data) {
   3135         sal_free(mt_ctrl->data);
   3136     }
   3137     if (mt_ctrl->sram_bist) {
   3138         sal_free(mt_ctrl->sram_bist);
   3139     }
   3140     sal_free(mt_ctrl);
   3141 
   3142     return rv;
   3143 }
   3144 
   3145 #ifdef BCM_TRIUMPH_SUPPORT
   3146 STATIC int
   3147 _soc_tr_memtune_lvl2_tcam_bist_setup(soc_memtune_data_t *mt_data)
   3148 {
   3149     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
   3150     uint32 oe_map, data[32], rval;
   3151     int i;
   3152 
   3153     sal_memset(data, 0, sizeof(data));
   3154 
   3155 #define SETUP_72BIT_DATA(name,index,d0_msb,d1,d2_lsb) \
   3156     name[index * 4] = d2_lsb; \
   3157     name[index * 4 + 1] = d1; \
   3158     name[index * 4 + 2] = d0_msb;
   3159     switch (mt_data->tcam_data_choice) {
   3160     case 0:
   3161         oe_map = 0xff;
   3162         SETUP_72BIT_DATA(data, 0, 0xa5, 0xa5a5a5a5, 0xa5a5a5a5);
   3163         SETUP_72BIT_DATA(data, 1, 0x5a, 0x5a5a5a5a, 0x5a5a5a5a);
   3164         SETUP_72BIT_DATA(data, 2, 0x00, 0x00000000, 0x00000000);
   3165         SETUP_72BIT_DATA(data, 3, 0x22, 0x22222222, 0x22222222);
   3166         SETUP_72BIT_DATA(data, 4, 0xff, 0xffffffff, 0xffffffff);
   3167         SETUP_72BIT_DATA(data, 5, 0x44, 0x44444444, 0x44444444);
   3168         SETUP_72BIT_DATA(data, 6, 0x01, 0x23456789, 0x01234567);
   3169         SETUP_72BIT_DATA(data, 7, 0x76, 0x54321098, 0x76543210);
   3170         break;
   3171     case 1:
   3172         oe_map = 0xff;
   3173         SETUP_72BIT_DATA(data, 0, 0x00, 0x00000000, 0x00000000);
   3174         SETUP_72BIT_DATA(data, 1, 0xff, 0xffffffff, 0xffffffff);
   3175         SETUP_72BIT_DATA(data, 2, 0x00, 0x00000000, 0x00000000);
   3176         SETUP_72BIT_DATA(data, 3, 0xff, 0xffffffff, 0xffffffff);
   3177         SETUP_72BIT_DATA(data, 4, 0x00, 0x00000000, 0x00000000);
   3178         SETUP_72BIT_DATA(data, 5, 0xff, 0xffffffff, 0xffffffff);
   3179         SETUP_72BIT_DATA(data, 6, 0x00, 0x00000000, 0x00000000);
   3180         SETUP_72BIT_DATA(data, 7, 0xff, 0xffffffff, 0xffffffff);
   3181         break;
   3182     case 2:
   3183         oe_map = 0xff;
   3184         SETUP_72BIT_DATA(data, 0, 0xa5, 0xa5a5a5a5, 0xa5a5a5a5);
   3185         SETUP_72BIT_DATA(data, 1, 0x5a, 0x5a5a5a5a, 0x5a5a5a5a);
   3186         SETUP_72BIT_DATA(data, 2, 0xa5, 0xa5a5a5a5, 0xa5a5a5a5);
   3187         SETUP_72BIT_DATA(data, 3, 0x5a, 0x5a5a5a5a, 0x5a5a5a5a);
   3188         SETUP_72BIT_DATA(data, 4, 0xa5, 0xa5a5a5a5, 0xa5a5a5a5);
   3189         SETUP_72BIT_DATA(data, 5, 0x5a, 0x5a5a5a5a, 0x5a5a5a5a);
   3190         SETUP_72BIT_DATA(data, 6, 0xa5, 0xa5a5a5a5, 0xa5a5a5a5);
   3191         SETUP_72BIT_DATA(data, 7, 0x5a, 0x5a5a5a5a, 0x5a5a5a5a);
   3192         break;
   3193     case 3:
   3194         oe_map = 0xff;
   3195         SETUP_72BIT_DATA(data, 0, 0x00, 0x00000000, 0x00000000);
   3196         SETUP_72BIT_DATA(data, 1, 0x00, 0x00000000, 0x00000000);
   3197         SETUP_72BIT_DATA(data, 2, 0x00, 0x00000000, 0x00000000);
   3198         SETUP_72BIT_DATA(data, 3, 0x00, 0x00000000, 0x00000000);
   3199         SETUP_72BIT_DATA(data, 4, 0x00, 0x00000000, 0x00000000);
   3200         SETUP_72BIT_DATA(data, 5, 0x00, 0x00000000, 0x00000000);
   3201         SETUP_72BIT_DATA(data, 6, 0x00, 0x00000000, 0x00000000);
   3202         SETUP_72BIT_DATA(data, 7, 0x00, 0x00000000, 0x00000000);
   3203         break;
   3204     case 4:
   3205         oe_map = 0xff;
   3206         SETUP_72BIT_DATA(data, 0, 0xaa, 0xaaaaaaaa, 0xaaaaaaaa);
   3207         SETUP_72BIT_DATA(data, 1, 0x55, 0x55555555, 0x55555555);
   3208         SETUP_72BIT_DATA(data, 2, 0xaa, 0xaaaaaaaa, 0xaaaaaaaa);
   3209         SETUP_72BIT_DATA(data, 3, 0x55, 0x55555555, 0x55555555);
   3210         SETUP_72BIT_DATA(data, 4, 0xaa, 0xaaaaaaaa, 0xaaaaaaaa);
   3211         SETUP_72BIT_DATA(data, 5, 0x55, 0x55555555, 0x55555555);
   3212         SETUP_72BIT_DATA(data, 6, 0xaa, 0xaaaaaaaa, 0xaaaaaaaa);
   3213         SETUP_72BIT_DATA(data, 7, 0x55, 0x55555555, 0x55555555);
   3214         break;
   3215     case 5:
   3216         oe_map = 0xff;
   3217         SETUP_72BIT_DATA(data, 0, 0xff, 0xffffffff, 0xffffffff);
   3218         SETUP_72BIT_DATA(data, 1, 0xff, 0xffffffff, 0xffffffff);
   3219         SETUP_72BIT_DATA(data, 2, 0xff, 0xffffffff, 0xffffffff);
   3220         SETUP_72BIT_DATA(data, 3, 0xff, 0xffffffff, 0xffffffff);
   3221         SETUP_72BIT_DATA(data, 4, 0xff, 0xffffffff, 0xffffffff);
   3222         SETUP_72BIT_DATA(data, 5, 0xff, 0xffffffff, 0xffffffff);
   3223         SETUP_72BIT_DATA(data, 6, 0xff, 0xffffffff, 0xffffffff);
   3224         SETUP_72BIT_DATA(data, 7, 0xff, 0xffffffff, 0xffffffff);
   3225         break;
   3226     case 6:
   3227         oe_map = 0x55;
   3228         SETUP_72BIT_DATA(data, 0, 0xff, 0xffffffff, 0xffffffff);
   3229         SETUP_72BIT_DATA(data, 2, 0xff, 0xffffffff, 0xffffffff);
   3230         SETUP_72BIT_DATA(data, 4, 0xff, 0xffffffff, 0xffffffff);
   3231         SETUP_72BIT_DATA(data, 6, 0xff, 0xffffffff, 0xffffffff);
   3232         break;
   3233     case 7:
   3234         oe_map = 0x55;
   3235         SETUP_72BIT_DATA(data, 0, 0x00, 0x00000000, 0x00000000);
   3236         SETUP_72BIT_DATA(data, 2, 0x00, 0x00000000, 0x00000000);
   3237         SETUP_72BIT_DATA(data, 4, 0x00, 0x00000000, 0x00000000);
   3238         SETUP_72BIT_DATA(data, 6, 0x00, 0x00000000, 0x00000000);
   3239         break;
   3240     case 8:
   3241         oe_map = 0xff;
   3242         SETUP_72BIT_DATA(data, 0, 0x00, 0x0000000f, 0xffffffff);
   3243         SETUP_72BIT_DATA(data, 1, 0x00, 0x00000000, 0x00000000);
   3244         SETUP_72BIT_DATA(data, 2, 0x00, 0x0000000f, 0xffffffff);
   3245         SETUP_72BIT_DATA(data, 3, 0x00, 0x00000000, 0x00000000);
   3246         SETUP_72BIT_DATA(data, 4, 0x00, 0x0000000f, 0xffffffff);
   3247         SETUP_72BIT_DATA(data, 5, 0x00, 0x00000000, 0x00000000);
   3248         SETUP_72BIT_DATA(data, 6, 0x00, 0x0000000f, 0xffffffff);
   3249         SETUP_72BIT_DATA(data, 7, 0x00, 0x00000000, 0x00000000);
   3250         break;
   3251     case 81:
   3252         oe_map = 0xff;
   3253         SETUP_72BIT_DATA(data, 0, 0xff, 0xfffffff0, 0x00000000);
   3254         SETUP_72BIT_DATA(data, 1, 0x00, 0x00000000, 0x00000000);
   3255         SETUP_72BIT_DATA(data, 2, 0xff, 0xfffffff0, 0x00000000);
   3256         SETUP_72BIT_DATA(data, 3, 0x00, 0x00000000, 0x00000000);
   3257         SETUP_72BIT_DATA(data, 4, 0xff, 0xfffffff0, 0x00000000);
   3258         SETUP_72BIT_DATA(data, 5, 0x00, 0x00000000, 0x00000000);
   3259         SETUP_72BIT_DATA(data, 6, 0xff, 0xfffffff0, 0x00000000);
   3260         SETUP_72BIT_DATA(data, 7, 0x00, 0x00000000, 0x00000000);
   3261         break;
   3262     case 200:
   3263         oe_map = 0xff;
   3264         SETUP_72BIT_DATA(data, 0, 0x00, 0x00000000, 0x00000000);
   3265         SETUP_72BIT_DATA(data, 1, 0x6d, 0xb6df6db6, 0xdb6fd6db);
   3266         SETUP_72BIT_DATA(data, 2, 0x00, 0x00000000, 0x00000000);
   3267         SETUP_72BIT_DATA(data, 3, 0x6d, 0xb6df6db6, 0xdb6fd6db);
   3268         SETUP_72BIT_DATA(data, 4, 0x00, 0x00000000, 0x00000000);
   3269         SETUP_72BIT_DATA(data, 5, 0x6d, 0xb6df6db6, 0xdb6fd6db);
   3270         SETUP_72BIT_DATA(data, 6, 0x00, 0x00000000, 0x00000000);
   3271         SETUP_72BIT_DATA(data, 7, 0x6d, 0xb6df6db6, 0xdb6fd6db);
   3272         break;
   3273     case 2000:
   3274         oe_map = 0;
   3275         break;
   3276     default:
   3277         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3278                             "Unknown TcamDataChoice %d\n"), mt_data->tcam_data_choice));
   3279         return SOC_E_PARAM;
   3280     }
   3281 #undef SETUP_72BIT_DATA
   3282 
   3283     if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SETTING) {
   3284         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3285                             "TCAM setting:\n")));
   3286         for (i = 0; i < 8; i++) {
   3287             if (oe_map & (1 << i)) {
   3288                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3289                                     "  K%d: %02x-%08x-%08x OE: ENABLE\n"),
   3290                          i, data[i * 4 + 2], data[i * 4 + 1], data[i * 4]));
   3291             } else {
   3292                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3293                                     "  K%d: zz-zzzzzzzz-zzzzzzzz OE: DISABLE\n"), i));
   3294             }
   3295         }
   3296     }
   3297     SOC_IF_ERROR_RETURN
   3298         (soc_tr_tcam_type1_memtest_dpeo(mt_ctrl->unit, 8, oe_map, data));
   3299 
   3300     rval = 0;
   3301     soc_reg_field_set(mt_ctrl->unit, ETU_LTE_BIST_CTLr, &rval,
   3302                       RD_EN_BIST_RSLTSf, 1);
   3303     soc_reg_field_set(mt_ctrl->unit, ETU_LTE_BIST_CTLr, &rval, LOOP_COUNTf,
   3304                       mt_data->tcam_loop_count);
   3305     SOC_IF_ERROR_RETURN(WRITE_ETU_LTE_BIST_CTLr(mt_ctrl->unit, rval));
   3306 
   3307     return SOC_E_NONE;
   3308 }
   3309 
   3310 STATIC int
   3311 _soc_tr_memtune_lvl2_sram_bist_setup(soc_memtune_data_t *mt_data)
   3312 {
   3313     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
   3314     tr_ext_sram_bist_t sram_bist;
   3315     soc_reg_t reg;
   3316     int addr;
   3317     uint32 rval;
   3318 
   3319     sal_memset(&sram_bist, 0, sizeof(sram_bist));
   3320 
   3321 #define SPLIT_36BIT_DATA(name,d0_msb,d1_lsb) \
   3322     name## _0 = (d1_lsb) & 0x3ffff; \
   3323     name## _1 = ((d0_msb & 0xf) << 14) | ((d1_lsb & 0xfffc0000) >> 18);
   3324     switch (mt_data->sram_data_choice) {
   3325     case -1:
   3326         SPLIT_36BIT_DATA(sram_bist.d0r, 0x1, 0x23456789);
   3327         SPLIT_36BIT_DATA(sram_bist.d0f, 0xa, 0xbcdef012);
   3328         SPLIT_36BIT_DATA(sram_bist.d1r, 0x3, 0x456789ab);
   3329         SPLIT_36BIT_DATA(sram_bist.d1f, 0xc, 0xdef01234);
   3330         break;
   3331     case 0:
   3332         SPLIT_36BIT_DATA(sram_bist.d0r, 0x5, 0x55555555);
   3333         SPLIT_36BIT_DATA(sram_bist.d0f, 0xa, 0xaaaaaaaa);
   3334         SPLIT_36BIT_DATA(sram_bist.d1r, 0x5, 0x55555555);
   3335         SPLIT_36BIT_DATA(sram_bist.d1f, 0xa, 0xaaaaaaaa);
   3336         break;
   3337     case 1:
   3338         SPLIT_36BIT_DATA(sram_bist.d0r, 0xf, 0xffffffff);
   3339         SPLIT_36BIT_DATA(sram_bist.d0f, 0x0, 0x00000000);
   3340         SPLIT_36BIT_DATA(sram_bist.d1r, 0xf, 0xffffffff);
   3341         SPLIT_36BIT_DATA(sram_bist.d1f, 0x0, 0x00000000);
   3342         break;
   3343     case 2:
   3344         SPLIT_36BIT_DATA(sram_bist.d0r, 0xf, 0xffffffff);
   3345         SPLIT_36BIT_DATA(sram_bist.d0f, 0xf, 0xffffffff);
   3346         SPLIT_36BIT_DATA(sram_bist.d1r, 0x0, 0x00000000);
   3347         SPLIT_36BIT_DATA(sram_bist.d1f, 0x0, 0x00000000);
   3348         break;
   3349     case 3:
   3350         SPLIT_36BIT_DATA(sram_bist.d0r, 0x0, 0x00000000);
   3351         SPLIT_36BIT_DATA(sram_bist.d0f, 0x0, 0x00000000);
   3352         SPLIT_36BIT_DATA(sram_bist.d1r, 0xf, 0xffffffff);
   3353         SPLIT_36BIT_DATA(sram_bist.d1f, 0xf, 0xffffffff);
   3354         break;
   3355     case 4:
   3356         SPLIT_36BIT_DATA(sram_bist.d0r, 0x0, 0x00000000);
   3357         SPLIT_36BIT_DATA(sram_bist.d0f, 0x0, 0x00000000);
   3358         SPLIT_36BIT_DATA(sram_bist.d1r, 0x0, 0x00000000);
   3359         SPLIT_36BIT_DATA(sram_bist.d1f, 0x0, 0x00000000);
   3360         break;
   3361     case 5:
   3362         SPLIT_36BIT_DATA(sram_bist.d0r, 0xf, 0xffffffff);
   3363         SPLIT_36BIT_DATA(sram_bist.d0f, 0xf, 0xffffffff);
   3364         SPLIT_36BIT_DATA(sram_bist.d1r, 0xf, 0xffffffff);
   3365         SPLIT_36BIT_DATA(sram_bist.d1f, 0xf, 0xffffffff);
   3366         break;
   3367     case 6:
   3368         SPLIT_36BIT_DATA(sram_bist.d0r, 0xf, 0xfffc1020);
   3369         SPLIT_36BIT_DATA(sram_bist.d0f, 0x0, 0x00000000);
   3370         SPLIT_36BIT_DATA(sram_bist.d1r, 0xf, 0xfffc1020);
   3371         SPLIT_36BIT_DATA(sram_bist.d1f, 0x0, 0x00000000);
   3372         break;
   3373     case 7:
   3374         SPLIT_36BIT_DATA(sram_bist.d0r, 0x0, 0x00000000);
   3375         SPLIT_36BIT_DATA(sram_bist.d0f, 0x0, 0x00000000);
   3376         SPLIT_36BIT_DATA(sram_bist.d1r, 0x0, 0x00000000);
   3377         SPLIT_36BIT_DATA(sram_bist.d1f, 0xf, 0xffffffff);
   3378         break;
   3379     case 8:
   3380         SPLIT_36BIT_DATA(sram_bist.d0r, 0xf, 0xffffffff);
   3381         SPLIT_36BIT_DATA(sram_bist.d0f, 0xf, 0xffffffff);
   3382         SPLIT_36BIT_DATA(sram_bist.d1r, 0xf, 0xffffffff);
   3383         SPLIT_36BIT_DATA(sram_bist.d1f, 0x0, 0x00000000);
   3384         break;
   3385     default:
   3386         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3387                             "Unknown SramDataChoice %d\n"), mt_data->sram_data_choice));
   3388         return SOC_E_PARAM;
   3389     }
   3390 #undef SPLIT_36BIT_DATA
   3391 
   3392     switch (mt_data->alt_adr) {
   3393     case 0: /* ADR0:0 ADR1:78, INC2 */
   3394         sram_bist.adr1 = 78;
   3395         sram_bist.adr_mode = 2;
   3396         break;
   3397     case 1: /* ADR0:0 ADR1:0x3ffffe, ALT_A0A1 */
   3398         sram_bist.adr1 = 0x3ffffe;
   3399         break;
   3400     case 2: /* ADR0:0 ADR1:2, ALT_A0A1 */
   3401         sram_bist.adr1 = 2;
   3402         break;
   3403     case 3: /* ADR0:0x3ffffe ADR1:0, ALT_A0A1 */
   3404         sram_bist.adr0 = 0x3ffffe;
   3405         break;
   3406     default:
   3407         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3408                             "Unknown AltAdr %d\n"), mt_data->alt_adr));
   3409         return SOC_E_PARAM;
   3410     }
   3411 
   3412     sram_bist.wdoebr = -1;
   3413     sram_bist.em_latency = -1;
   3414 
   3415     if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SETTING) {
   3416         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3417                             "SRAM setting:\n")));
   3418         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3419                             "  D0R:%05x-%05x D0F:%05x-%05x D1R:%05x-%05x "
   3420                             "D1F:%05x-%05x\n"),
   3421                  sram_bist.d0r_1, sram_bist.d0r_0,
   3422                  sram_bist.d0f_1, sram_bist.d0f_0,
   3423                  sram_bist.d1r_1, sram_bist.d1r_0,
   3424                  sram_bist.d1f_1, sram_bist.d1f_0));
   3425         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3426                             "  ADR0:%05x ADR1:%05x ADR_MODE:%d\n"),
   3427                  sram_bist.adr0, sram_bist.adr1, sram_bist.adr_mode));
   3428     }
   3429 
   3430     if (mt_data->loop_mode[0] != 4) {
   3431         reg = ES0_SRAM_CTLr;
   3432         addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0);
   3433         SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
   3434         sram_bist.w2r_nops =
   3435             soc_reg_field_get(mt_ctrl->unit, reg, rval, NUM_W2R_NOPSf);
   3436         sram_bist.r2w_nops =
   3437             soc_reg_field_get(mt_ctrl->unit, reg, rval, NUM_R2W_NOPSf);
   3438 
   3439         if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SETTING) {
   3440             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3441                                 "  (SRAM0) W2R_NOPS:%d R2W_NOPS:%d LOOP_MODE: %d\n"),
   3442                      sram_bist.w2r_nops, sram_bist.r2w_nops,
   3443                      mt_data->loop_mode[0]));
   3444         }
   3445         SOC_IF_ERROR_RETURN
   3446             (soc_triumph_ext_sram_bist_setup(mt_ctrl->unit, 0, &sram_bist));
   3447     }
   3448 
   3449     if (mt_data->loop_mode[1] != 4) {
   3450         reg = ES1_SRAM_CTLr;
   3451         addr = soc_reg_addr(mt_ctrl->unit, reg, REG_PORT_ANY, 0);
   3452         SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
   3453         sram_bist.w2r_nops =
   3454             soc_reg_field_get(mt_ctrl->unit, reg, rval, NUM_W2R_NOPSf);
   3455         sram_bist.r2w_nops =
   3456             soc_reg_field_get(mt_ctrl->unit, reg, rval, NUM_R2W_NOPSf);
   3457 
   3458         if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SETTING) {
   3459             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3460                                 "  (SRAM1) W2R_NOPS:%d R2W_NOPS:%d LOOP_MODE: %d\n"),
   3461                      sram_bist.w2r_nops, sram_bist.r2w_nops,
   3462                      mt_data->loop_mode[1]));
   3463         }
   3464         SOC_IF_ERROR_RETURN
   3465             (soc_triumph_ext_sram_bist_setup(mt_ctrl->unit, 1, &sram_bist));
   3466     }
   3467 
   3468     return SOC_E_NONE;
   3469 }
   3470 
   3471 STATIC int
   3472 _soc_tr_memtune_lvl2_test(soc_memtune_data_t *mt_data, int *fail_count)
   3473 {
   3474     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
   3475     tr_ext_sram_bist_t sram_bist[2], *sram_bist_ptr, *opt_sram_bist_ptr;
   3476     int i, count, start, end, done;
   3477 
   3478     if (mt_data->loop_mode[0] == 4) {
   3479         start = end = 1;
   3480         sram_bist_ptr = &sram_bist[1];
   3481         opt_sram_bist_ptr = NULL;
   3482     } else if (mt_data->loop_mode[1] == 4) {
   3483         start = end = 0;
   3484         sram_bist_ptr = &sram_bist[0];
   3485         opt_sram_bist_ptr = NULL;
   3486     } else {
   3487         start = 0;
   3488         end = 1;
   3489         sram_bist_ptr = &sram_bist[0];
   3490         opt_sram_bist_ptr = &sram_bist[1];
   3491     }
   3492 
   3493     for (i = start; i <= end; i++) {
   3494         sal_memset(&sram_bist[i], 0, sizeof(tr_ext_sram_bist_t));
   3495 
   3496         /*
   3497          * Following sram bist registers has been set properly,
   3498          * don't touch them during test to save time:
   3499          * D0R_0, D0R_1, D0F_0, D0F_1, D1R_0, D1R_1, D1F_0, D1F_1,
   3500          * ADR0, ADR1, TMODE1
   3501          */
   3502         sram_bist[i].d0r_0 = 0xffffffff;
   3503         sram_bist[i].d1r_0 = 0xffffffff;
   3504         sram_bist[i].adr0 = -1;
   3505         sram_bist[i].adr1 = -1;
   3506         sram_bist[i].wdoebr = -1;
   3507         sram_bist[i].em_latency = -1;
   3508         sram_bist[i].r2w_nops = -1;
   3509         sram_bist[i].w2r_nops = -1;
   3510 
   3511         sram_bist[i].bg_tcam_loop_count = mt_data->tcam_loop_count;
   3512     }
   3513 
   3514     for (count = 0; count < mt_data->test_count; count++) {
   3515         for (i = start; i <= end; i++) {
   3516             if (mt_data->loop_mode[i] == 1) /* RR */ {
   3517                 sram_bist[i].loop_mode = 0; /* WW */
   3518                 SOC_IF_ERROR_RETURN
   3519                     (soc_triumph_ext_sram_enable_set(mt_ctrl->unit, i, TRUE,
   3520                                                      TRUE));
   3521                 SOC_IF_ERROR_RETURN
   3522                     (soc_triumph_ext_sram_bist_setup(mt_ctrl->unit, i,
   3523                                                      &sram_bist[i]));
   3524                 SOC_IF_ERROR_RETURN
   3525                     (soc_triumph_ext_sram_op(mt_ctrl->unit, i, &sram_bist[i],
   3526                                              NULL));
   3527             }
   3528             sram_bist[i].loop_mode = mt_data->loop_mode[i];
   3529             SOC_IF_ERROR_RETURN
   3530                 (soc_triumph_ext_sram_enable_set(mt_ctrl->unit, i, TRUE,
   3531                                                  TRUE));
   3532             SOC_IF_ERROR_RETURN
   3533                 (soc_triumph_ext_sram_bist_setup(mt_ctrl->unit, i,
   3534                                                  &sram_bist[i]));
   3535         }
   3536 
   3537         SOC_IF_ERROR_RETURN
   3538             (soc_triumph_ext_sram_op(mt_ctrl->unit, start, sram_bist_ptr,
   3539                                      opt_sram_bist_ptr));
   3540         if (mt_data->ok_on_both_pass && start != end) {
   3541             sram_bist[0].err_cnt += sram_bist[1].err_cnt;
   3542             sram_bist[1].err_cnt = sram_bist[0].err_cnt;
   3543         }
   3544 
   3545         done = FALSE;
   3546         for (i = start; i <= end; i++) {
   3547             SOC_IF_ERROR_RETURN
   3548                 (soc_triumph_ext_sram_enable_set(mt_ctrl->unit, i, FALSE,
   3549                                                  FALSE));
   3550             if (sram_bist[i].err_cnt) {
   3551                 fail_count[i]++;
   3552                 if (fail_count[i] >= mt_data->max_fail_count) {
   3553                     done = TRUE;
   3554                 }
   3555             }
   3556         }
   3557         if (done) {
   3558             break;
   3559         }
   3560     }
   3561 
   3562     return SOC_E_NONE;
   3563 }
   3564 
   3565 STATIC int
   3566 _soc_tr_mem_interface_tune_lvl2(soc_memtune_data_t *mt_data)
   3567 {
   3568     soc_tcam_info_t *tcam_info;
   3569     soc_memtune_ctrl_t *mt_ctrl = mt_data->mt_ctrl;
   3570     soc_tr_memtune_data_t *tr_mt_data;
   3571     soc_memtune_result_t *result;
   3572     int offset_count[2], index[2];
   3573     int tx_offset[2], tx_offset_cur[2], tx_offset_min[2], tx_offset_max[2];
   3574     int rx_offset[2], rx_offset_cur[2], rx_offset_min[2], rx_offset_max[2];
   3575     int em_latency[2], em_latency_cur[2], em_latency_min[2], em_latency_max[2];
   3576     int last_tx_offset[2], last_rx_offset[2];
   3577     int tx_pass_threshold[2], rx_pass_threshold[2];
   3578     int fail_count[2];
   3579     int has_fail[2];
   3580     int delta_max;
   3581     static const struct {
   3582         soc_reg_t tmode0;
   3583         soc_reg_t config_reg1;
   3584     } ddr_reg[2] = {
   3585         {
   3586             ES0_DTU_LTE_TMODE0r,
   3587             ES0_DDR36_CONFIG_REG1_ISr
   3588         },
   3589         {
   3590             ES1_DTU_LTE_TMODE0r,
   3591             ES1_DDR36_CONFIG_REG1_ISr
   3592         },
   3593     };
   3594     int addr, dt, dr, i, start, end;
   3595     uint32 rval;
   3596     int sram_data_choice, alt_adr, loop_mode[2], tcam_loop_count, test_count;
   3597 
   3598     if (mt_data->loop_mode[0] < 0 || mt_data->loop_mode[0] > 4) {
   3599         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3600                             "Unknown LoopMode %d\n"), mt_data->loop_mode[0]));
   3601         return SOC_E_PARAM;
   3602     }
   3603 
   3604     if (mt_data->loop_mode[1] < 0 || mt_data->loop_mode[1] > 4) {
   3605         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3606                             "Unknown LoopMode %d\n"), mt_data->loop_mode[1]));
   3607         return SOC_E_PARAM;
   3608     }
   3609 
   3610     start = 0;
   3611     end = 1;
   3612     if (mt_data->loop_mode[0] == 4) {
   3613         if (mt_data->loop_mode[1] == 4) {
   3614             return SOC_E_NONE; /* do nothing */
   3615         } else {
   3616             start++;
   3617         }
   3618     } else if (mt_data->loop_mode[1] == 4) {
   3619         end--;
   3620     }
   3621 
   3622     tcam_info = SOC_CONTROL(mt_ctrl->unit)->tcam_info;
   3623     if (tcam_info == NULL) {
   3624         return SOC_E_INIT;
   3625     }
   3626 
   3627     tr_mt_data = sal_alloc(sizeof(soc_tr_memtune_data_t),
   3628                            "memtune working data");
   3629     if (!tr_mt_data) {
   3630         return SOC_E_MEMORY;
   3631     }
   3632     sal_memset(tr_mt_data, 0, sizeof(soc_tr_memtune_data_t));
   3633     mt_ctrl->data = tr_mt_data;
   3634 
   3635     mt_data->interface = SOC_MEM_INTERFACE_SRAM;
   3636     mt_data->sub_interface = 0; /* any legal value to allow setup to pass */
   3637     mt_data->man_em_latency = -1;
   3638     mt_data->man_ddr_latency = -1;
   3639     mt_data->man_tx_offset = -1;
   3640     mt_data->man_rx_offset = -1;
   3641     _soc_tr_mem_interface_tune_setup(mt_data);
   3642     mt_ctrl->em_latency_cur = -1;
   3643     mt_ctrl->ddr_latency_cur = -1;
   3644     mt_ctrl->phase_sel_cur = -1;
   3645 
   3646     em_latency_min[0] = em_latency_max[0] = -1;
   3647     em_latency_min[1] = em_latency_max[1] = -1;
   3648     has_fail[0] = has_fail[1] = FALSE;
   3649 
   3650     for (i = start; i <= end; i++) {
   3651         if (mt_data->tx_offset[i] != -1 || mt_data->rx_offset[i] != -1) {
   3652             if (mt_data->tx_offset[i] < mt_ctrl->tx_offset_min ||
   3653                 mt_data->tx_offset[i] > mt_ctrl->tx_offset_max ||
   3654                 mt_data->rx_offset[i] < mt_ctrl->rx_offset_min ||
   3655                 mt_data->rx_offset[i] > mt_ctrl->rx_offset_max) {
   3656                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3657                                     "Invalid TX/RX value %d/%d\n"),
   3658                          mt_data->tx_offset[i], mt_data->rx_offset[i]));
   3659                 return SOC_E_PARAM;
   3660             }
   3661             tx_offset[i] = mt_data->tx_offset[i];
   3662             rx_offset[i] = mt_data->rx_offset[i];
   3663         } else {
   3664             /* Get current TX/RX offset setting as center of sweep test */
   3665             addr = soc_reg_addr(mt_ctrl->unit, ddr_reg[i].config_reg1,
   3666                                 REG_PORT_ANY, 0);
   3667             SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
   3668             tx_offset[i] =
   3669                 soc_reg_field_get(mt_ctrl->unit, ddr_reg[i].config_reg1, rval,
   3670                                   DLL90_OFFSET_TXf) |
   3671                 (soc_reg_field_get(mt_ctrl->unit, ddr_reg[i].config_reg1, rval,
   3672                                    DLL90_OFFSET_TX4f) << 4);
   3673             rx_offset[i] =
   3674                 soc_reg_field_get(mt_ctrl->unit, ddr_reg[i].config_reg1, rval,
   3675                                   DLL90_OFFSET_QKf) |
   3676                 (soc_reg_field_get(mt_ctrl->unit, ddr_reg[i].config_reg1, rval,
   3677                                    DLL90_OFFSET_QK4f) << 4);
   3678         }
   3679 
   3680         addr = soc_reg_addr(mt_ctrl->unit, ddr_reg[i].tmode0, REG_PORT_ANY, 0);
   3681         SOC_IF_ERROR_RETURN(soc_reg32_read(mt_ctrl->unit, addr, &rval));
   3682         em_latency[i] =
   3683             soc_reg_field_get(mt_ctrl->unit, ddr_reg[i].tmode0, rval,
   3684                               EM_LATENCYf);
   3685         if (soc_reg_field_valid(mt_ctrl->unit, ddr_reg[i].tmode0,
   3686                                 EM_LATENCY8f) &&
   3687             soc_reg_field_get(mt_ctrl->unit, ddr_reg[i].tmode0, rval,
   3688                               EM_LATENCY8f)) {
   3689             em_latency[i] |= 8;
   3690         }
   3691 
   3692         /* Find out the min/max range of the sweeping window, the specified
   3693          * delta may include TX/RX points beyond the physical range supported
   3694          * by hardware */
   3695         tx_offset_min[i] = mt_ctrl->tx_offset_min;
   3696         if (tx_offset[i] - mt_data->delta[i] >= tx_offset_min[i]) {
   3697             tx_offset_min[i] = tx_offset[i] - mt_data->delta[i];
   3698         }
   3699         tx_offset_max[i] = mt_ctrl->tx_offset_max;
   3700         if (tx_offset[i] + mt_data->delta[i] <= tx_offset_max[i]) {
   3701             tx_offset_max[i] = tx_offset[i] + mt_data->delta[i];
   3702         }
   3703         rx_offset_min[i] = mt_ctrl->rx_offset_min;
   3704         if (rx_offset[i] - mt_data->delta[i] >= rx_offset_min[i]) {
   3705             rx_offset_min[i] = rx_offset[i] - mt_data->delta[i];
   3706         }
   3707         rx_offset_max[i] = mt_ctrl->rx_offset_max;
   3708         if (rx_offset[i] + mt_data->delta[i] <= rx_offset_max[i]) {
   3709             rx_offset_max[i] = rx_offset[i] + mt_data->delta[i];
   3710         }
   3711         offset_count[i] = (tx_offset_max[i] - tx_offset_min[i] + 1) *
   3712             (rx_offset_max[i] - rx_offset_min[i] + 1);
   3713 
   3714         if (mt_data->test_all_latency) {
   3715             em_latency_min[i] = mt_ctrl->em_latency_min;
   3716             em_latency_max[i] = mt_ctrl->em_latency_max;
   3717         }
   3718 
   3719         /* Set passing threshold if the sweeping window is larger than the
   3720          * size of qualified window */
   3721         tx_pass_threshold[i] = mt_ctrl->tx_pass_threshold;
   3722         if (tx_pass_threshold[i] > tx_offset_max[i] - tx_offset_min[i] + 1) {
   3723             tx_pass_threshold[i] = 0;
   3724         }
   3725         rx_pass_threshold[i] = mt_ctrl->rx_pass_threshold;
   3726         if (rx_pass_threshold[i] > rx_offset_max[i] - rx_offset_min[i] + 1) {
   3727             rx_pass_threshold[i] = 0;
   3728         }
   3729     }
   3730 
   3731     /* Setup TCAM BIST */
   3732     SOC_IF_ERROR_RETURN(_soc_tr_memtune_lvl2_tcam_bist_setup(mt_data));
   3733 
   3734     sram_data_choice = mt_data->sram_data_choice;
   3735     alt_adr = mt_data->alt_adr;
   3736     loop_mode[0] = mt_data->loop_mode[0];
   3737     loop_mode[1] = mt_data->loop_mode[1];
   3738     tcam_loop_count = mt_data->tcam_loop_count;
   3739     test_count = mt_data->test_count;
   3740 
   3741     last_tx_offset[0] = last_tx_offset[1] = -1;
   3742     last_rx_offset[0] = last_rx_offset[1] = -1;
   3743     delta_max = mt_data->delta[0] > mt_data->delta[1] ?
   3744         mt_data->delta[0] : mt_data->delta[1];
   3745     for (dt = -delta_max; dt <= delta_max; dt++) {
   3746         for (dr = -delta_max; dr <= delta_max; dr++) {
   3747             for (i = start; i <= end; i++) {
   3748                 /* Find out the actual TX/RX setting for testing, this can be
   3749                  * different from the "intended" sweeping point
   3750                  * (center +/- delta). For example, if the point after moving
   3751                  * delta steps from center is out of supported min/max range,
   3752                  * the actual tx (or rx) setting for testing will be at the
   3753                  * valid window edge of that direction */
   3754                 if (tx_offset[i] + dt < tx_offset_min[i]) {
   3755                     tx_offset_cur[i] = tx_offset_min[i];
   3756                 } else if (tx_offset[i] + dt > tx_offset_max[i]) {
   3757                     tx_offset_cur[i] = tx_offset_max[i];
   3758                 } else {
   3759                     tx_offset_cur[i] = tx_offset[i] + dt;
   3760                 }
   3761                 if (rx_offset[i] + dr < rx_offset_min[i]) {
   3762                     rx_offset_cur[i] = rx_offset_min[i];
   3763                 } else if (rx_offset[i] + dr > rx_offset_max[i]) {
   3764                     rx_offset_cur[i] = rx_offset_max[i];
   3765                 } else {
   3766                     rx_offset_cur[i] = rx_offset[i] + dr;
   3767                 }
   3768                 if (tx_offset[i] + dt != tx_offset_cur[i] ||
   3769                     rx_offset[i] + dr != rx_offset_cur[i]) {
   3770                     /* Do not record result if the "intended" sweeping point
   3771                      * is not the actual TX/RX setting for testing */
   3772                     index[i] = -1;
   3773                 } else {
   3774                     index[i] = (tx_offset_cur[i] - tx_offset_min[i]) *
   3775                         (rx_offset_max[i] - rx_offset_min[i] + 1) +
   3776                         rx_offset_cur[i] - rx_offset_min[i];
   3777                     if (mt_data->fail_array[i][index[i]] > 0) {
   3778                         has_fail[i] = TRUE;
   3779                         if (mt_data->fail_array[i][index[i]] >=
   3780                             mt_data->max_fail_count) {
   3781                             /* Do not record result if the currently
   3782                              * accumulated error count has already exceeded
   3783                              * the specified max fail count */
   3784                             index[i] = -1;
   3785                         }
   3786                     }
   3787                 }
   3788             }
   3789 
   3790             if (index[start] == -1 && index[end] == -1) {
   3791                 /* If none of the interface needs to record the result
   3792                  * go to next TX/RX */
   3793                 continue;
   3794             }
   3795 
   3796             for (i = start; i <= end; i++) {
   3797                 em_latency_cur[i] = -1;
   3798                 /* If the TX/RX setting is the same as last test, no need to
   3799                  * reporgram TX/RX in hardware */
   3800                 if (tx_offset_cur[i] == last_tx_offset[i] &&
   3801                     rx_offset_cur[i] == last_rx_offset[i]) {
   3802                     continue;
   3803                 }
   3804                 mt_ctrl->tx_offset_cur = tx_offset_cur[i];
   3805                 mt_ctrl->rx_offset_cur = rx_offset_cur[i];
   3806                 tr_mt_data->config_reg1 = ddr_reg[i].config_reg1;
   3807                 (*mt_ctrl->prog_hw1_fn)(mt_data); /* TX/RX */
   3808                 if (tx_offset_cur[i] != last_tx_offset[i]) {
   3809                     if (*mt_ctrl->per_tx_fn != NULL) {
   3810                         (*mt_ctrl->per_tx_fn)(mt_data);
   3811                     }
   3812                 }
   3813                 if (rx_offset_cur[i] != last_rx_offset[i]) {
   3814                     if (*mt_ctrl->per_rx_fn != NULL) {
   3815                         (*mt_ctrl->per_rx_fn)(mt_data);
   3816                     }
   3817                 }
   3818                 last_tx_offset[i] = tx_offset_cur[i];
   3819                 last_rx_offset[i] = rx_offset_cur[i];
   3820 
   3821                 if (em_latency_min[i] == -1) {
   3822                     continue;
   3823                 }
   3824 
   3825                 /* Find EM_LATENCY for the TX/RX setting */
   3826                 for (mt_ctrl->em_latency_cur = em_latency_min[i];
   3827                      mt_ctrl->em_latency_cur <= em_latency_max[i];
   3828                      mt_ctrl->em_latency_cur++) {
   3829                     tr_mt_data->tmode0 = ddr_reg[i].tmode0;
   3830                     (*mt_ctrl->prog_hw2_fn)(mt_data); /* latency */
   3831                     mt_data->sram_data_choice = -1;
   3832                     mt_data->alt_adr = 2;
   3833                     mt_data->loop_mode[i] = 1;
   3834                     mt_data->loop_mode[i ^ 1] = 4;
   3835                     mt_data->tcam_loop_count = 1;
   3836                     mt_data->test_count = 1;
   3837                     SOC_IF_ERROR_RETURN
   3838                         (_soc_tr_memtune_lvl2_sram_bist_setup(mt_data));
   3839 
   3840                     fail_count[i] = 0;
   3841                     _soc_tr_memtune_lvl2_test(mt_data, fail_count);
   3842 
   3843                     if (fail_count[i] == 0) {
   3844                         em_latency_cur[i] = mt_ctrl->em_latency_cur;
   3845                         break;
   3846                     }
   3847                 }
   3848             }
   3849 
   3850             /* Setup user-specified test parameters in hardware */
   3851             mt_data->sram_data_choice = sram_data_choice;
   3852             mt_data->alt_adr = alt_adr;
   3853             mt_data->loop_mode[0] = loop_mode[0];
   3854             mt_data->loop_mode[1] = loop_mode[1];
   3855             mt_data->tcam_loop_count = tcam_loop_count;
   3856             mt_data->test_count = test_count;
   3857             SOC_IF_ERROR_RETURN(_soc_tr_memtune_lvl2_sram_bist_setup(mt_data));
   3858 
   3859             /* Do user-specified test */
   3860             for (i = start; i <= end; i++) {
   3861                 fail_count[i] = 0;
   3862             }
   3863             _soc_tr_memtune_lvl2_test(mt_data, fail_count);
   3864 
   3865             if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL ||
   3866                 mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_PASS) {
   3867                 for (i = start; i <= end; i++) {
   3868                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3869                                         "SRAM%d TX=%d RX=%d "), i,
   3870                              tx_offset_cur[i], rx_offset_cur[i]));
   3871                     if (em_latency_cur[i] != -1) {
   3872                         LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3873                                             "EM lat=%d "), em_latency_cur[i]));
   3874                     }
   3875                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3876                                         ": Fail count=%d "), fail_count[i]));
   3877                 }
   3878                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3879                                     "\n")));
   3880             }
   3881 
   3882             for (i = start; i <= end; i++) {
   3883                 if (index[i] == -1) {
   3884                     continue;
   3885                 }
   3886                 if (mt_data->fail_array[i][index[i]] <= 0) {
   3887                     if (fail_count[i] == 0 && em_latency_cur[i] != -1) {
   3888                         mt_data->fail_array[i][index[i]] = -em_latency_cur[i];
   3889                     } else {
   3890                         mt_data->fail_array[i][index[i]] = fail_count[i];
   3891                     }
   3892                 } else {
   3893                     mt_data->fail_array[i][index[i]] += fail_count[i];
   3894                 }
   3895                 if (fail_count[i] > 0) {
   3896                     has_fail[i] = TRUE;
   3897                     if (mt_data->fail_array[i][index[i]] >
   3898                         mt_data->max_fail_count) {
   3899                         mt_data->fail_array[i][index[i]] =
   3900                             mt_data->max_fail_count;
   3901                     }
   3902                 }
   3903             }
   3904         }
   3905     }
   3906 
   3907     /* Clear TCAM BIST setting */
   3908     rval = 0;
   3909     soc_reg_field_set(mt_ctrl->unit, ETU_LTE_BIST_CTLr, &rval, LOOP_COUNTf, 1);
   3910     (void)WRITE_ETU_LTE_BIST_CTLr(mt_ctrl->unit, rval);
   3911 
   3912     for (i = start; i <= end; i++) {
   3913         /* When sweeping only one SRAM, no analysis on the non-sweeping SRAM */
   3914         if (mt_data->delta[i] == 0 && mt_data->delta[i ^ 1] != 0) {
   3915             continue;
   3916         }
   3917         mt_ctrl->tx_offset_cur = tx_offset[i];
   3918         mt_ctrl->rx_offset_cur = rx_offset[i];
   3919         mt_ctrl->intf_name = i == 0 ? "SRAM0" : "SRAM1";
   3920         mt_ctrl->result_count = 0;
   3921         result = &mt_ctrl->result[mt_ctrl->result_count];
   3922         if (!has_fail[i]) {
   3923             /* All tested TX/RX passes, no need to analyze */
   3924             mt_ctrl->tx_offset_cur = (tx_offset_min[i] + tx_offset_max[i]) / 2;
   3925             mt_ctrl->rx_offset_cur = (rx_offset_min[i] + rx_offset_max[i]) / 2;
   3926             result->fail_count = 0;
   3927             result->width = rx_offset_max[i] - rx_offset_min[i] + 1;
   3928             result->height = tx_offset_max[i] - tx_offset_min[i] + 1;
   3929             if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL_MATRIX) {
   3930                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3931                                     "Memory tuning %s interface"),
   3932                          mt_ctrl->intf_name));
   3933                 if (mt_ctrl->em_latency_cur != -1) {
   3934                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3935                                         " em_latency=%d"), mt_ctrl->em_latency_cur));
   3936                 }
   3937                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3938                                     " failure count: all pass\n")));
   3939             }
   3940         } else {
   3941             /* Analyze and print result matrix */
   3942             mt_ctrl->tx_offset_min = tx_offset_min[i];
   3943             mt_ctrl->tx_offset_max = tx_offset_max[i];
   3944             mt_ctrl->rx_offset_min = rx_offset_min[i];
   3945             mt_ctrl->rx_offset_max = rx_offset_max[i];
   3946             mt_ctrl->fail_array = mt_data->fail_array[i];
   3947             _soc_memtune_txrx_analyze(mt_data);
   3948         }
   3949 
   3950         if (result->fail_count == offset_count[i] ||
   3951             mt_data->restore_txrx_after_test) {
   3952             /* Test fail, or restore TX/RX flag is set */
   3953             mt_ctrl->tx_offset_cur = tx_offset[i];
   3954             mt_ctrl->rx_offset_cur = rx_offset[i];
   3955         }
   3956 
   3957         /* Restore TX/RX in hardware */
   3958         tr_mt_data->config_reg1 = ddr_reg[i].config_reg1;
   3959         (*mt_ctrl->prog_hw1_fn)(mt_data); /* TX/RX */
   3960         if (*mt_ctrl->per_tx_fn != NULL) {
   3961             (*mt_ctrl->per_tx_fn)(mt_data);
   3962         }
   3963         if (*mt_ctrl->per_rx_fn != NULL) {
   3964             (*mt_ctrl->per_rx_fn)(mt_data);
   3965         }
   3966 
   3967         /* Find EM_LATENCY for the TX/RX setting */
   3968         if (em_latency_min[i] != -1) {
   3969             for (em_latency_cur[i] = em_latency_min[i];
   3970                  em_latency_cur[i] <= em_latency_max[i]; em_latency_cur[i]++) {
   3971                 mt_ctrl->em_latency_cur = em_latency_cur[i];
   3972                 tr_mt_data->tmode0 = ddr_reg[i].tmode0;
   3973                 (*mt_ctrl->prog_hw2_fn)(mt_data); /* latency */
   3974 
   3975                 mt_data->sram_data_choice = -1;
   3976                 mt_data->alt_adr = 2;
   3977                 mt_data->loop_mode[i] = 1;
   3978                 mt_data->loop_mode[i ^ 1] = 4;
   3979                 mt_data->tcam_loop_count = 1;
   3980                 mt_data->test_count = 1;
   3981                 SOC_IF_ERROR_RETURN
   3982                     (_soc_tr_memtune_lvl2_sram_bist_setup(mt_data));
   3983 
   3984                 fail_count[i] = 0;
   3985                 _soc_tr_memtune_lvl2_test(mt_data, fail_count);
   3986                 if (fail_count[i] == 0) {
   3987                     break;
   3988                 }
   3989             }
   3990         }
   3991 
   3992         if (result->fail_count == offset_count[i]) {
   3993             LOG_CLI((BSL_META_U(mt_ctrl->unit,
   3994                                 "ERROR - no passing \"eye\" was found, \n"
   3995                                 "please contact your Field Applications "
   3996                                 "Engineer or Sales Manager\n"
   3997                                 "for additional assistance.\n")));
   3998         } else {
   3999             if (mt_ctrl->flags & SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY) {
   4000                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   4001                                     "%s OldTX=%d OldRX=%d "),
   4002                          mt_ctrl->intf_name, tx_offset[i], rx_offset[i]));
   4003                 if (em_latency_min[i] != -1) {
   4004                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   4005                                         "OldEmLat=%d "), em_latency[i]));
   4006                 }
   4007                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   4008                                     "NewTX=%d NewRX=%d "),
   4009                          mt_ctrl->tx_offset_cur, mt_ctrl->rx_offset_cur));
   4010                 if (em_latency_min[i] != -1) {
   4011                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   4012                                         "NewEmLat=%d "), mt_ctrl->em_latency_cur));
   4013                 }
   4014                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   4015                                     "Delta=%d "), mt_data->delta[i]));
   4016                 if (result->fail_count == 0) {
   4017                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   4018                                         "no failure seen in tested points\n")));
   4019                 } else {
   4020                     LOG_CLI((BSL_META_U(mt_ctrl->unit,
   4021                                         "Area=%d Width=%d Height=%d\n"),
   4022                              result->width * result->height,
   4023                              result->width, result->height));
   4024                 }
   4025             }
   4026 
   4027             if (result->fail_count > 0 &&
   4028                 (result->height < tx_pass_threshold[i] ||
   4029                  result->width < rx_pass_threshold[i])) {
   4030                 LOG_CLI((BSL_META_U(mt_ctrl->unit,
   4031                                     "ERROR - \"eye\" of size %d * %d is smaller "
   4032                                     "than minimum size of %d * %d,\n"
   4033                                     "please contact your Field Applications "
   4034                                     "Engineer or Sales Manager\n"
   4035                                     "for additional assistance.\n"),
   4036                          result->height, result->width,
   4037                          mt_ctrl->tx_pass_threshold,
   4038                          mt_ctrl->rx_pass_threshold));
   4039             }
   4040 
   4041 #ifndef NO_MEMTUNE
   4042             if (mt_data->config) {
   4043                 char name_str[24], val_str[11];
   4044                 sal_sprintf(name_str, "%s%d.%d", spn_EXT_SRAM_TUNING, i,
   4045                             mt_ctrl->unit);
   4046                 rval = soc_property_get(mt_ctrl->unit, name_str, 0);
   4047                 /* use 0 in the 3-bit field to represent EM_LATENCY is 8 */
   4048                 if (em_latency_min[i] != -1) {
   4049                     rval &= ~(SOC_TR_MEMTUNE_EM_LATENCY_MASK <<
   4050                               SOC_TR_MEMTUNE_EM_LATENCY_SHIFT);
   4051                     rval |= ((mt_ctrl->em_latency_cur &
   4052                               SOC_TR_MEMTUNE_EM_LATENCY_MASK) <<
   4053                              SOC_TR_MEMTUNE_EM_LATENCY_SHIFT);
   4054                 }
   4055                 rval &= ~(SOC_TR_MEMTUNE_DDR_TX_OFFSET_MASK <<
   4056                           SOC_TR_MEMTUNE_DDR_TX_OFFSET_SHIFT);
   4057                 rval |= ((mt_ctrl->tx_offset_cur &
   4058                           SOC_TR_MEMTUNE_DDR_TX_OFFSET_MASK) <<
   4059                          SOC_TR_MEMTUNE_DDR_TX_OFFSET_SHIFT);
   4060                 rval &= ~(SOC_TR_MEMTUNE_DDR_RX_OFFSET_MASK <<
   4061                           SOC_TR_MEMTUNE_DDR_RX_OFFSET_SHIFT);
   4062                 rval |= ((mt_ctrl->rx_offset_cur &
   4063                           SOC_TR_MEMTUNE_DDR_RX_OFFSET_MASK) <<
   4064                          SOC_TR_MEMTUNE_DDR_RX_OFFSET_SHIFT);
   4065                 sal_sprintf(val_str, "0x%08x", rval);
   4066                 if (_mem_config_set(name_str, val_str) < 0) {
   4067                     return SOC_E_MEMORY;
   4068                 }
   4069                 sal_sprintf(name_str, "%s%d.%d", spn_EXT_SRAM_TUNING2_STATS, i,
   4070                             mt_ctrl->unit);
   4071                 rval = SOC_TR_MEMTUNE_CONFIG_VALID_MASK |
   4072                     ((result->width & SOC_TR_MEMTUNE_STATS_WIDTH_MASK) <<
   4073                      SOC_TR_MEMTUNE_STATS_WIDTH_SHIFT) |
   4074                     ((result->height & SOC_TR_MEMTUNE_STATS_HEIGHT_MASK) <<
   4075                      SOC_TR_MEMTUNE_STATS_HEIGHT_SHIFT) |
   4076                     ((result->fail_count &
   4077                       SOC_TR_MEMTUNE_STATS_FAIL_MASK) <<
   4078                      SOC_TR_MEMTUNE_STATS_FAIL_SHIFT);
   4079                 sal_sprintf(val_str, "0x%08x", rval);
   4080                 if (_mem_config_set(name_str, val_str) < 0) {
   4081                     return SOC_E_MEMORY;
   4082                 }
   4083             }
   4084 #endif /* NO_MEMTUNE */
   4085         }
   4086     }
   4087 
   4088     mt_data->sram_data_choice = sram_data_choice;
   4089     mt_data->alt_adr = alt_adr;
   4090     mt_data->loop_mode[0] = loop_mode[0];
   4091     mt_data->loop_mode[1] = loop_mode[1];
   4092     mt_data->tcam_loop_count = tcam_loop_count;
   4093     mt_data->test_count = test_count;
   4094 
   4095     return SOC_E_NONE;
   4096 }
   4097 #endif /* BCM_TRIUMPH_SUPPORT */
   4098 
   4099 int
   4100 soc_mem_interface_tune_lvl2(int unit, soc_memtune_data_t *mt_data)
   4101 {
   4102     soc_memtune_ctrl_t *mt_ctrl;
   4103     int rv = SOC_E_NONE;
   4104 
   4105     mt_ctrl = sal_alloc(sizeof(soc_memtune_ctrl_t), "memtune working data");
   4106     if (!mt_ctrl) {
   4107         return SOC_E_MEMORY;
   4108     }
   4109     sal_memset(mt_ctrl, 0, sizeof(soc_memtune_ctrl_t));
   4110     mt_ctrl->unit = unit;
   4111     mt_data->mt_ctrl = mt_ctrl;
   4112 
   4113     if (mt_data->verbose) {
   4114         mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_TEST_NAME |
   4115             SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY |
   4116             SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL_MATRIX |
   4117             SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS |
   4118             SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL |
   4119             SOC_MEMTUNE_CTRL_FLAGS_SHOW_PASS |
   4120             SOC_MEMTUNE_CTRL_FLAGS_SHOW_SETTING;
   4121     }
   4122     if (mt_data->summary) {
   4123         mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_SUMMARY;
   4124     }
   4125     if (mt_data->show_setting) {
   4126         mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_SETTING;
   4127     }
   4128     if (mt_data->show_matrix) {
   4129         mt_ctrl->flags |= SOC_MEMTUNE_CTRL_FLAGS_SHOW_FAIL_MATRIX |
   4130             SOC_MEMTUNE_CTRL_FLAGS_SHOW_ANALYSIS;
   4131     }
   4132 
   4133 #ifdef BCM_TRIUMPH_SUPPORT
   4134     if (soc_feature(unit, soc_feature_esm_support)) {
   4135         rv = _soc_tr_mem_interface_tune_lvl2(mt_data);
   4136     }
   4137 #endif /* BCM_TRIUMPH_SUPPORT */
   4138 
   4139     if (mt_ctrl->data) {
   4140         sal_free(mt_ctrl->data);
   4141     }
   4142     sal_free(mt_ctrl);
   4143 
   4144     return rv;
   4145 }
   4146 #endif /* BCM_TRIUMPH_SUPPORT */