[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/bsp/dramk_2731/dramc_pi_main.c b/src/bsp/dramk_2731/dramc_pi_main.c
new file mode 100755
index 0000000..0871d7c
--- /dev/null
+++ b/src/bsp/dramk_2731/dramc_pi_main.c
@@ -0,0 +1,2758 @@
+/*----------------------------------------------------------------------------*
+ * Copyright Statement:                                                       *
+ *                                                                            *
+ *   This software/firmware and related documentation ("MediaTek Software")   *
+ * are protected under international and related jurisdictions'copyright laws *
+ * as unpublished works. The information contained herein is confidential and *
+ * proprietary to MediaTek Inc. Without the prior written permission of       *
+ * MediaTek Inc., any reproduction, modification, use or disclosure of        *
+ * MediaTek Software, and information contained herein, in whole or in part,  *
+ * shall be strictly prohibited.                                              *
+ * MediaTek Inc. Copyright (C) 2010. All rights reserved.                     *
+ *                                                                            *
+ *   BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND     *
+ * AGREES TO THE FOLLOWING:                                                   *
+ *                                                                            *
+ *   1)Any and all intellectual property rights (including without            *
+ * limitation, patent, copyright, and trade secrets) in and to this           *
+ * Software/firmware and related documentation ("MediaTek Software") shall    *
+ * remain the exclusive property of MediaTek Inc. Any and all intellectual    *
+ * property rights (including without limitation, patent, copyright, and      *
+ * trade secrets) in and to any modifications and derivatives to MediaTek     *
+ * Software, whoever made, shall also remain the exclusive property of        *
+ * MediaTek Inc.  Nothing herein shall be construed as any transfer of any    *
+ * title to any intellectual property right in MediaTek Software to Receiver. *
+ *                                                                            *
+ *   2)This MediaTek Software Receiver received from MediaTek Inc. and/or its *
+ * representatives is provided to Receiver on an "AS IS" basis only.          *
+ * MediaTek Inc. expressly disclaims all warranties, expressed or implied,    *
+ * including but not limited to any implied warranties of merchantability,    *
+ * non-infringement and fitness for a particular purpose and any warranties   *
+ * arising out of course of performance, course of dealing or usage of trade. *
+ * MediaTek Inc. does not provide any warranty whatsoever with respect to the *
+ * software of any third party which may be used by, incorporated in, or      *
+ * supplied with the MediaTek Software, and Receiver agrees to look only to   *
+ * such third parties for any warranty claim relating thereto.  Receiver      *
+ * expressly acknowledges that it is Receiver's sole responsibility to obtain *
+ * from any third party all proper licenses contained in or delivered with    *
+ * MediaTek Software.  MediaTek is not responsible for any MediaTek Software  *
+ * releases made to Receiver's specifications or to conform to a particular   *
+ * standard or open forum.                                                    *
+ *                                                                            *
+ *   3)Receiver further acknowledge that Receiver may, either presently       *
+ * and/or in the future, instruct MediaTek Inc. to assist it in the           *
+ * development and the implementation, in accordance with Receiver's designs, *
+ * of certain softwares relating to Receiver's product(s) (the "Services").   *
+ * Except as may be otherwise agreed to in writing, no warranties of any      *
+ * kind, whether express or implied, are given by MediaTek Inc. with respect  *
+ * to the Services provided, and the Services are provided on an "AS IS"      *
+ * basis. Receiver further acknowledges that the Services may contain errors  *
+ * that testing is important and it is solely responsible for fully testing   *
+ * the Services and/or derivatives thereof before they are used, sublicensed  *
+ * or distributed. Should there be any third party action brought against     *
+ * MediaTek Inc. arising out of or relating to the Services, Receiver agree   *
+ * to fully indemnify and hold MediaTek Inc. harmless.  If the parties        *
+ * mutually agree to enter into or continue a business relationship or other  *
+ * arrangement, the terms and conditions set forth herein shall remain        *
+ * effective and, unless explicitly stated otherwise, shall prevail in the    *
+ * event of a conflict in the terms in any agreements entered into between    *
+ * the parties.                                                               *
+ *                                                                            *
+ *   4)Receiver's sole and exclusive remedy and MediaTek Inc.'s entire and    *
+ * cumulative liability with respect to MediaTek Software released hereunder  *
+ * will be, at MediaTek Inc.'s sole discretion, to replace or revise the      *
+ * MediaTek Software at issue.                                                *
+ *                                                                            *
+ *   5)The transaction contemplated hereunder shall be construed in           *
+ * accordance with the laws of Singapore, excluding its conflict of laws      *
+ * principles.  Any disputes, controversies or claims arising thereof and     *
+ * related thereto shall be settled via arbitration in Singapore, under the   *
+ * then current rules of the International Chamber of Commerce (ICC).  The    *
+ * arbitration shall be conducted in English. The awards of the arbitration   *
+ * shall be final and binding upon both parties and shall be entered and      *
+ * enforceable in any court of competent jurisdiction.                        *
+ *---------------------------------------------------------------------------*/
+
+//=============================================================================
+//  Include Files
+//=============================================================================
+#if (FOR_DV_SIMULATION_USED==0 && SW_CHANGE_FOR_SIMULATION==0)
+#if __ETT__
+#include <common.h>
+#include <ett_common.h>
+#include <api.h>
+#endif
+#endif
+
+//#if (FOR_DV_SIMULATION_USED==0)
+#include "emi.h"
+//#endif
+#include "dramc_common.h"
+#include "dramc_pi_api.h"
+#include "x_hal_io.h"
+
+//=============================================================================
+//  Definition
+//=============================================================================
+
+//=============================================================================
+//  Global Variables
+//=============================================================================
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+   SAVE_TIME_FOR_CALIBRATION_T SavetimeData;
+#endif
+
+DRAM_DFS_FREQUENCY_TABLE_T gFreqTbl[DRAM_DFS_SHUFFLE_MAX] = {
+    {LP4_HIGHEST_FREQSEL, LP4_HIGHEST_FREQ, DRAM_DFS_SHUFFLE_1},
+};
+
+DRAM_DFS_FREQUENCY_TABLE_T gFreqTbl_LP3[DRAM_DFS_SHUFFLE_MAX] = {
+    {LP3_DDR1066,  533, DRAM_DFS_SHUFFLE_1},
+};
+
+DRAMC_CTX_T *psCurrDramCtx;
+
+#if defined(DDR_INIT_TIME_PROFILING) || (__ETT__ && SUPPORT_SAVE_TIME_FOR_CALIBRATION)
+DRAMC_CTX_T gTimeProfilingDramCtx;
+U8 gtime_profiling_flag = 0;
+#endif
+
+#if (!__ETT__ && ENABLE_LP3_SW==0)
+// Preloader which does not support LP3
+// scy: reduce code size by removing unused LPDDR3 structure
+#else
+DRAMC_CTX_T DramCtx_LPDDR3 =
+{
+  CHANNEL_SINGLE, // Channel number
+  CHANNEL_A,          // DRAM_CHANNEL
+  RANK_DUAL,        //DRAM_RANK_NUMBER_T
+  RANK_0,               //DRAM_RANK_T
+#if DUAL_FREQ_K
+  LP3_DDR1066,
+#else
+#if __FLASH_TOOL_DA__
+  LP3_DDR1066,
+#else
+  //LP3_DDR1333,  //LP3_DDR1866,
+  LP3_DDR1066,
+#endif
+#endif
+  DRAM_DFS_SHUFFLE_1,
+  TYPE_LPDDR3,        // DRAM_DRAM_TYPE_T
+  FSP_0 , //// DRAM Fast switch point type, only for LP4, useless in LP3
+  ODT_OFF,
+  {CBT_NORMAL_MODE, CBT_NORMAL_MODE}, //only for LP4, useless in LP3
+  {DBI_OFF,DBI_OFF},
+  {DBI_OFF,DBI_OFF},
+  DATA_WIDTH_32BIT,     // DRAM_DATA_WIDTH_T
+  DEFAULT_TEST2_1_CAL,    // test2_1;
+  DEFAULT_TEST2_2_CAL,    // test2_2;
+  TEST_XTALK_PATTERN,     // test_pattern;
+  533,                  // frequency
+  533,                  // freqGroup
+  0x88, //vendor_id initial value
+  REVISION_ID_MAGIC, //revision id
+  0xff, //density
+  {0,0},
+  0,  // ucnum_dlycell_perT;
+  0,  // u2DelayCellTimex100;
+
+  DISABLE_VREF_SCAN,  // enable_cbt_scan_vref;
+  DISABLE_VREF_SCAN,  // enable_rx_scan_vref;
+  DISABLE_VREF_SCAN,   // enable_tx_scan_vref;
+#if PRINT_CALIBRATION_SUMMARY
+    //aru4CalResultFlag[CHANNEL_NUM][RANK_MAX]
+    {{0,0},  {0,0}},
+    //aru4CalExecuteFlag[CHANNEL_NUM][RANK_MAX]
+    {{0,0},  {0,0}},
+#endif
+#if WRITE_LEVELING_MOVE_DQS_INSTEAD_OF_CLK
+  {{0,0}, {0,0}}, //BOOL arfgWriteLevelingInitShif;
+#endif
+#if TX_PERBIT_INIT_FLOW_CONTROL
+  {{FALSE, FALSE}, {FALSE, FALSE}},//BOOL fgTXPerbifInit;
+#endif
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+     FALSE, //femmc_Ready
+     0,
+     0,
+     0,
+     &SavetimeData,
+#endif
+#if (fcFOR_CHIP_ID == fcLaurel)
+    0,  //bDLP3
+#endif
+#if defined(SLT) || (FT_DSIM_USED)
+    0,  //shuffle_index
+#endif
+    TRUE,   //u1PHYPLLEn
+};
+#endif
+
+DRAMC_CTX_T DramCtx_LPDDR4 =
+{
+  CHANNEL_DUAL, // Channel number
+  CHANNEL_A,          // DRAM_CHANNEL
+  RANK_DUAL,        //DRAM_RANK_NUMBER_T
+  RANK_0,               //DRAM_RANK_T
+
+#ifdef MTK_FIXDDR1600_SUPPORT
+  LP4_DDR1600,
+#else
+#if DUAL_FREQ_K
+  LP4_LOWEST_FREQSEL, // Darren: it will be overwritten by gFreqTbl[DRAM_DFS_SHUFFLE_3].freq_sel (Init_DRAM)
+#else
+#if __FLASH_TOOL_DA__
+  LP4_DDR1600,
+#else
+
+#if EMI_LPBK_USE_THROUGH_IO
+  LP4_DDR1600,
+#else
+  LP4_DDR3200,
+#endif
+
+
+#endif
+#endif
+#endif
+  DRAM_DFS_SHUFFLE_1,
+  TYPE_LPDDR4X,        // DRAM_DRAM_TYPE_T
+  FSP_0 , //// DRAM Fast switch point type, only for LP4, useless in LP3
+  ODT_OFF,
+  {CBT_NORMAL_MODE, CBT_NORMAL_MODE},  // bring up LP4X rank0 & rank1 use normal mode
+#if ENABLE_READ_DBI
+  {DBI_OFF,DBI_ON},  //read DBI
+#else
+  {DBI_OFF,DBI_OFF}, //read DBI
+#endif
+#if ENABLE_WRITE_DBI
+  {DBI_OFF,DBI_ON},  // write DBI
+#else
+  {DBI_OFF,DBI_OFF},  // write DBI
+#endif
+  DATA_WIDTH_16BIT,     // DRAM_DATA_WIDTH_T
+  DEFAULT_TEST2_1_CAL,    // test2_1;
+  DEFAULT_TEST2_2_CAL,    // test2_2;
+  TEST_XTALK_PATTERN,     // test_pattern;
+  1600,                  // frequency
+  1600,                  // freqGroup
+  0x88, //vendor_id initial value
+  REVISION_ID_MAGIC, //revision id
+  0xff, //density
+  {0,0},
+  0,  // ucnum_dlycell_perT;
+  0,  // u2DelayCellTimex100;
+
+  ENABLE,   // enable_cbt_scan_vref;
+  ENABLE,  // enable_rx_scan_vref;
+  ENABLE,   // enable_tx_scan_vref;
+
+#if PRINT_CALIBRATION_SUMMARY
+   //aru4CalResultFlag[CHANNEL_NUM][RANK_MAX]
+   {{0,0,}, {0,0}},
+   //aru4CalExecuteFlag[CHANNEL_NUM][RANK_MAX]
+   {{0,0,}, {0,0}},
+#endif
+#if WRITE_LEVELING_MOVE_DQS_INSTEAD_OF_CLK
+  {{0,0}, {0,0}}, //BOOL arfgWriteLevelingInitShif;
+#endif
+#if TX_PERBIT_INIT_FLOW_CONTROL
+  {{FALSE, FALSE}, {FALSE, FALSE}},//BOOL fgTXPerbifInit;
+#endif
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+     FALSE, //femmc_Ready
+     0,
+     0,
+     0,
+     &SavetimeData,
+#endif
+#if (fcFOR_CHIP_ID == fcLaurel)
+    0,  //bDLP3
+#endif
+#if defined(SLT) || (FT_DSIM_USED)
+    0,  //shuffle_index
+#endif
+    TRUE,   //u1PHYPLLEn
+};
+
+U8 gfirst_init_flag = 0;
+//=============================================================================
+//  External references
+//=============================================================================
+#if __ETT__
+extern int global_which_test;
+#endif
+
+#if !__ETT__ && defined(DDR_RESERVE_MODE)
+extern u32 g_ddr_reserve_ta_err;
+#endif
+
+extern U8 gu1MR23Done;
+extern U8 ucg_num_dlycell_perT_all[DRAM_DFS_SHUFFLE_MAX][CHANNEL_NUM];
+extern U16 u2gdelay_cell_ps_all[DRAM_DFS_SHUFFLE_MAX][CHANNEL_NUM];
+
+extern int complex_mem_test(unsigned long start, unsigned int len);
+extern void EMI_Init(DRAMC_CTX_T *p);
+extern void EMI_Init2(void);
+
+extern U16 gu2MR0_Value[RANK_MAX];  /*read only mode register*/
+
+/*
+ * LP4 table
+ *  [0] 3200
+ *  [1] 3200
+ *  [2] 2400
+ *  [3] 1600
+ * LP3 table
+ *  [0] 1866
+ *  [1] 1600
+ *  [2] 1600
+ *  [3] 1200
+ */
+#define STD_LP4_VCORE_KOPP0	800000
+#define STD_LP4_VCORE_KOPP1	750000
+#define STD_LP4_VCORE_KOPP2	700000
+#define STD_LP4_VCORE_KOPP3	700000
+#define STD_LP3_VCORE_KOPP0	800000
+#define STD_LP3_VCORE_KOPP1	750000
+#define STD_LP3_VCORE_KOPP2	750000
+#define STD_LP3_VCORE_KOPP3	700000
+#ifdef DRAM_HQA
+#if __ETT__
+extern unsigned int hqa_LP4_vcore_kopp0;
+extern unsigned int hqa_LP4_vcore_kopp1;
+extern unsigned int hqa_LP4_vcore_kopp2;
+extern unsigned int hqa_LP4_vcore_kopp3;
+extern unsigned int hqa_LP3_vcore_kopp0;
+extern unsigned int hqa_LP3_vcore_kopp1;
+extern unsigned int hqa_LP3_vcore_kopp2;
+extern unsigned int hqa_LP3_vcore_kopp3;
+#define VCORE_KOPP_BY_FREQ(F, D)	hqa_##D##_vcore_kopp##F
+#else
+#define VCORE_KOPP_BY_FREQ(F, D)	HQA_VCORE_KOPP(F, D)
+#endif
+#else
+#define VCORE_KOPP_BY_FREQ(F, D)	STD_##D##_VCORE_KOPP##F
+#endif
+
+void vSetVcoreByFreq(DRAMC_CTX_T *p)
+{
+#ifndef MT2731_FPGA
+#if (FOR_DV_SIMULATION_USED==0 && SW_CHANGE_FOR_SIMULATION==0)
+#if __FLASH_TOOL_DA__
+	dramc_set_vcore_voltage(800000);
+#else
+	unsigned int vcore, vdram, vddq;
+#ifdef DRAM_HQA
+	unsigned int vio18;
+	vio18 = HQA_VIO18;
+#endif
+
+	vcore = vdram = vddq = 0;
+
+#if defined(DRAM_HQA) && defined(__ETT__)
+	hqa_set_voltage_by_freq(p, &vio18, &vcore, &vdram, &vddq);
+#else
+#ifdef VCORE_BIN
+	vcore = (get_vcore_uv_table(0) + get_vcore_uv_table(1)) >> 1;
+#else
+	if(u1IsLP4Family(p->dram_type))
+	// LP4X
+		vcore = (SEL_PREFIX_VCORE(LP4, KOPP0) + SEL_PREFIX_VCORE(LP4, KOPP1)) >> 1;
+	else
+	// LP2
+		vcore = (SEL_PREFIX_VCORE(LP2, KOPP0) + SEL_PREFIX_VCORE(LP2, KOPP1)) >> 1;
+#endif
+#endif
+
+#ifdef LAST_DRAMC
+	update_last_dramc_k_voltage(p, vcore);
+#endif
+
+#if defined(DRAM_HQA)
+	if (vio18)
+		dramc_set_vdd1_voltage(p->dram_type, vio18);
+#endif
+
+	if (vcore)
+		dramc_set_vcore_voltage(vcore);
+
+#if defined(DRAM_HQA)
+	if (vdram)
+		dramc_set_vdd2_voltage(p->dram_type, vdram);
+
+	if (u1IsLP4Family(p->dram_type)) {
+		if (vddq)
+			dramc_set_vddq_voltage(p->dram_type, vddq);
+	}
+#endif
+
+#ifndef DDR_INIT_TIME_PROFILING
+	printf("Read voltage for %d\n", p->frequency);
+	printf("Vio18 = %d\n", dramc_get_vdd1_voltage());
+	printf("Vcore = %d\n", dramc_get_vcore_voltage());
+	printf("Vdram = %d\n", dramc_get_vdd2_voltage(p->dram_type));
+
+	if (u1IsLP4Family(p->dram_type))
+		printf("Vddq = %d\n", dramc_get_vddq_voltage(p->dram_type));
+#endif
+#endif
+#endif
+#endif
+}
+
+U32 vGetVoltage(DRAMC_CTX_T *p, U32 get_voltage_type)
+{
+#if (defined(DRAM_HQA) || defined(__ETT__)) && (FOR_DV_SIMULATION_USED == 0)
+    if (get_voltage_type==0)
+        return dramc_get_vcore_voltage();
+
+    if (get_voltage_type==1)
+        return dramc_get_vdd2_voltage(p->dram_type);
+
+    if (get_voltage_type==2)
+        return dramc_get_vddq_voltage(p->dram_type);
+
+    if (get_voltage_type==3)
+        return dramc_get_vdd1_voltage();
+#endif
+
+    return 0;
+}
+
+#ifdef FOR_HQA_TEST_USED
+VCORE_DELAYCELL_T gVcoreDelayCellTable[42]={ {606250, 1071},
+                                                                       {612500, 1032},
+                                                                       {618750, 1019},
+                                                                       {625000, 1007},
+                                                                       {631250, 995},
+                                                                       {637500, 983},
+                                                                       {643750, 972},
+                                                                       {650000, 960},
+                                                                       {656250, 946},
+                                                                       {662500, 932},
+                                                                       {668750, 919},
+                                                                       {675000, 905},
+                                                                       {681250, 892},
+                                                                       {687500, 886},
+                                                                       {693750, 880},
+                                                                       {700000, 868},
+                                                                       {706250, 856},
+                                                                       {712500, 850},
+                                                                       {718750, 844},
+                                                                       {725000, 833},
+                                                                       {731250, 822},
+                                                                       {737500, 817},
+                                                                       {743750, 811},
+                                                                       {750000, 801},
+                                                                       {756250, 791},
+                                                                       {762500, 781},
+                                                                       {768750, 776},
+                                                                       {775000, 771},
+                                                                       {781250, 767},
+                                                                       {787500, 762},
+                                                                       {793750, 753},
+                                                                       {800000, 749},
+                                                                       {806250, 744},
+                                                                       {812500, 735},
+                                                                       {818750, 731},
+                                                                       {825000, 726},
+                                                                       {831250, 722},
+                                                                       {837500, 718},
+                                                                       {843750, 714},
+                                                                       {850000, 710},
+                                                                       {856250, 702},
+                                                                       {862500, 694} };
+
+void GetVcoreDelayCellTimeFromTable(DRAMC_CTX_T *p)
+{
+    U32 channel_i, i;
+    U32 get_vcore = 0;
+    U16 u2gdelay_cell_ps = 0;
+    U8 u1delay_cell_cnt = 0;
+    VCORE_DELAYCELL_T *pVcoreDelayCellTable;
+
+#if (defined(DRAM_HQA) || defined(__ETT__)) && (FOR_DV_SIMULATION_USED == 0)
+    get_vcore = dramc_get_vcore_voltage();
+#endif
+
+    pVcoreDelayCellTable = (VCORE_DELAYCELL_T *)gVcoreDelayCellTable;
+    u1delay_cell_cnt = sizeof(gVcoreDelayCellTable)/sizeof(gVcoreDelayCellTable[0]);
+
+    for(i=0; i<u1delay_cell_cnt; i++)
+    {
+        if (get_vcore >= pVcoreDelayCellTable[i].u2Vcore) u2gdelay_cell_ps = pVcoreDelayCellTable[i].u2DelayCell;
+    }
+
+    mcSHOW_DBG_MSG(("[GetVcoreDelayCellTimeFromTable(%d)] VCore=%d(x100), DelayCell=%d(x100)\n", u1delay_cell_cnt, get_vcore, u2gdelay_cell_ps));
+
+    for(channel_i=CHANNEL_A; channel_i < p->support_channel_num; channel_i++)
+    {
+        u2gdelay_cell_ps_all[get_shuffleIndex_by_Freq(p)][u1ChannelSet[channel_i]] = u2gdelay_cell_ps;
+    }
+}
+
+#endif
+
+void mem_test_address_calculation(DRAMC_CTX_T * p, unsigned long uiSrcAddr, unsigned long *pu4Dest)
+{
+#if __ETT__
+    *pu4Dest = uiSrcAddr - RANK0_START_VA + RANK1_START_VA;
+#else
+    *pu4Dest = uiSrcAddr + p->ranksize[RANK_0];
+#endif
+}
+
+
+#if CPU_RW_TEST_AFTER_K || ENABLE_SLT
+void vDramCPUReadWriteTestAfterCalibration(DRAMC_CTX_T *p)
+{
+    U8 u1DumpInfo=0, u1RankIdx;
+    unsigned long uiLen, count, uiFixedAddr, uiRankdAddr[RANK_MAX];
+    U32 pass_count, err_count;
+#if EMI_LPBK_DRAM_USED==1
+    uiLen = 0xffff;
+#else
+    uiLen = 0x44000;    //saint 0xffff;
+#endif
+
+#if GATING_ONLY_FOR_DEBUG
+    DramcGatingDebugInit(p);
+#endif
+
+    uiRankdAddr[0] = DDR_BASE;
+    mem_test_address_calculation(p, DDR_BASE, &uiRankdAddr[1]);
+
+    for(u1RankIdx =0; u1RankIdx< p->support_rank_num; u1RankIdx++)
+    {
+        u1DumpInfo=0;
+        err_count=0;
+        pass_count=0;
+
+#if !__ETT__
+	// scy: not to test rank1 (wrong addr 0x0000_0000)
+	if (u1RankIdx >= 1)
+		continue;
+#endif
+
+        #if GATING_ONLY_FOR_DEBUG
+        DramcGatingDebugRankSel(p, u1RankIdx);
+        #endif
+
+        uiFixedAddr = uiRankdAddr[u1RankIdx];
+
+        for (count= 0; count<uiLen; count+=4)
+        {
+            *(volatile unsigned int   *)(count +uiFixedAddr) = count + (0x5a5a <<16);
+        }
+
+        for (count=0; count<uiLen; count+=4)
+        {
+            if (*(volatile unsigned int   *)(count +uiFixedAddr) != count + (0x5a5a <<16))
+            {
+                //mcSHOW_DBG_MSG(("[Fail] Addr %xh = %xh\n",count, *(volatile unsigned int   *)(count)));
+                err_count++;
+            }
+            else
+                pass_count ++;
+        }
+
+#if RUNTIME_SHMOO_RELEATED_FUNCTION && SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        if (err_count==0)
+        {
+#if __ETT__
+            mcSHOW_ERR_MSG(("CH %c,RANK %d,BYTE %d,VRANGE %d,VREF %d,PI %d,MEM_RESULT PASS\n",
+                p->pSavetimeData->Runtime_Shmoo_para.TX_Channel == 0 ? 'A' : 'B',
+                p->pSavetimeData->Runtime_Shmoo_para.TX_Rank,
+                p->pSavetimeData->Runtime_Shmoo_para.TX_Byte,
+                p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Range,
+                p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Value,
+                p->pSavetimeData->Runtime_Shmoo_para.TX_PI_delay-p->pSavetimeData->Runtime_Shmoo_para.TX_Original_PI_delay));
+#else
+            mcSHOW_ERR_MSG(("CH %c,RANK %d,BYTE %d,VRANGE %d,VREF %d,PI %d,MEM_RESULT PASS\n",
+                p->pSavetimeData->Runtime_Shmoo_para.TX_Channel == 0 ? 'A' : 'B',
+                p->pSavetimeData->Runtime_Shmoo_para.TX_Rank,
+                p->pSavetimeData->Runtime_Shmoo_para.TX_Byte,
+                p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Range,
+                p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Value,
+                p->pSavetimeData->Runtime_Shmoo_para.TX_PI_delay-p->pSavetimeData->Runtime_Shmoo_para.TX_Original_PI_delay));
+#endif
+        }
+#else
+        if(err_count)
+        {
+            mcSHOW_DBG_MSG(("[MEM_TEST] Rank %d Fail.", u1RankIdx));
+            u1DumpInfo =1;
+#if defined(SLT) || (ENABLE_SLT == 1)
+            while(1);
+#endif
+        }
+        else
+        {
+            mcSHOW_DBG_MSG(("[MEM_TEST] Rank %d OK.", u1RankIdx));
+        }
+        mcSHOW_DBG_MSG(("(uiFixedAddr 0x%x, Pass count =%d, Fail count =%d)\n",
+		(unsigned int)(uiFixedAddr & 0xFFFFFFFF), pass_count, err_count));
+#endif
+    }
+
+    if(u1DumpInfo)
+    {
+        // Read gating error flag
+        #if (FOR_DV_SIMULATION_USED==0 && SW_CHANGE_FOR_SIMULATION==0)
+        DramcDumpDebugInfo(p);
+        #endif
+    }
+
+    #if GATING_ONLY_FOR_DEBUG
+    DramcGatingDebugExit(p);
+    #endif
+}
+#endif
+
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+#if !EMMC_READY
+u32 g_dram_save_time_init_done[DRAM_DFS_SHUFFLE_MAX]={0};
+SAVE_TIME_FOR_CALIBRATION_T SaveTimeDataByShuffle[DRAM_DFS_SHUFFLE_MAX];
+#endif
+
+DRAM_STATUS_T DramcSave_Time_For_Cal_End(DRAMC_CTX_T *p)
+{
+    if(!u1IsLP4Family(p->dram_type))
+        return DRAM_FAIL;
+
+    if(u1IsLP4Family(p->dram_type) && (p->femmc_Ready==0))
+    {
+        #if EMMC_READY
+        write_offline_dram_calibration_data(p->shu_type, p->pSavetimeData);
+        mcSHOW_DBG_MSG(("[FAST_K] Save calibration result to emmc\n"));
+        #else
+        g_dram_save_time_init_done[p->shu_type] =1;
+        memcpy(&(SaveTimeDataByShuffle[p->shu_type]), p->pSavetimeData, sizeof(SAVE_TIME_FOR_CALIBRATION_T));
+        mcSHOW_DBG_MSG(("[FAST_K] Save calibration result to SW memory\n"));
+        #endif
+    }
+    else
+    {
+        mcSHOW_DBG_MSG(("[FAST_K] Bypass saving calibration result to emmc\n"));
+    }
+
+	return DRAM_OK;
+}
+
+DRAM_STATUS_T DramcSave_Time_For_Cal_Init(DRAMC_CTX_T *p)
+{
+    if(!u1IsLP4Family(p->dram_type))
+        return DRAM_FAIL;
+
+    // Parepare fask k data
+    #if EMMC_READY
+    // scy: only need to read emmc one time for each boot-up
+    //if (g_dram_save_time_init_done == 1)
+    //    return DRAM_OK;
+    //else
+    //    g_dram_save_time_init_done = 1;
+    if(read_offline_dram_calibration_data(p->shu_type, p->pSavetimeData)<0)
+    {
+        p->femmc_Ready=0;
+        memset(p->pSavetimeData, 0, sizeof(SAVE_TIME_FOR_CALIBRATION_T));
+    }
+    else
+    {
+        p->femmc_Ready=1;
+    }
+
+    #else //EMMC is not avaliable, load off-line data
+
+    if(g_dram_save_time_init_done[p->shu_type] ==0)
+    {
+        p->femmc_Ready=0;
+        memset(p->pSavetimeData, 0, sizeof(SAVE_TIME_FOR_CALIBRATION_T));
+    }
+    else
+    {
+        memcpy(p->pSavetimeData, &(SaveTimeDataByShuffle[p->shu_type]), sizeof(SAVE_TIME_FOR_CALIBRATION_T));
+        p->femmc_Ready=1;
+    }
+    #endif
+
+    if(p->femmc_Ready==1)
+    {
+        if(p->frequency < 1600)
+        {   // freq < 1600, TX and RX tracking are disable. Therefore, bypass calibration.
+            p->Bypass_RDDQC=1;
+            p->Bypass_RXWINDOW=1;
+            p->Bypass_TXWINDOW=1;
+        }
+        else
+        {
+            p->Bypass_RDDQC=0;
+            p->Bypass_RXWINDOW=0;
+            p->Bypass_TXWINDOW=0;
+        }
+
+#if RUNTIME_SHMOO_RELEATED_FUNCTION
+        p->Bypass_RDDQC=1;
+        p->Bypass_RXWINDOW=1;
+        p->Bypass_TXWINDOW=1;
+#endif
+    }
+
+#if EMMC_READY
+    mcSHOW_DBG_MSG(("[FAST_K] DramcSave_Time_For_Cal_Init SHU%d, femmc_Ready=%d\n", p->shu_type, p->femmc_Ready));
+#else
+    mcSHOW_DBG_MSG(("[FAST_K] DramcSave_Time_For_Cal_Init SHU%d, Init_done=%d, femmc_Ready=%d\n", p->shu_type, g_dram_save_time_init_done[p->shu_type], p->femmc_Ready));
+#endif
+    mcSHOW_DBG_MSG(("[FAST_K] Bypass_RDDQC %d, Bypass_RXWINDOW=%d, Bypass_TXWINDOW=%d\n", p->Bypass_RDDQC, p->Bypass_RXWINDOW, p->Bypass_TXWINDOW));
+
+    return DRAM_OK;
+}
+
+
+#endif
+
+U8 gGet_MDL_Used_Flag=0;
+void Set_MDL_Used_Flag(U8 value)
+{
+    gGet_MDL_Used_Flag = value;
+}
+
+U8 Get_MDL_Used_Flag(void)
+{
+    return gGet_MDL_Used_Flag;
+}
+
+#if TX_K_DQM_WITH_WDBI
+void vSwitchWriteDBISettings(DRAMC_CTX_T *p, U8 u1OnOff)
+{
+    S8 u1TXShiftUI;
+
+    u1TXShiftUI = (u1OnOff) ? -8 : 8;
+    DramcWriteMinus1MCKForWriteDBI(p, u1TXShiftUI); //Tx DQ/DQM -1 MCK for write DBI ON
+
+    SetDramModeRegForWriteDBIOnOff(p, u1OnOff);
+    DramcWriteDBIOnOff(p, u1OnOff);
+}
+#endif
+
+static void vCalibration_Flow_LP4(DRAMC_CTX_T *p)
+{
+    U8 u1RankMax;
+    S8 s1RankIdx;
+    //DRAM_STATUS_T VrefStatus;
+
+#ifdef DDR_INIT_TIME_PROFILING
+    U32 CPU_Cycle;
+    TimeProfileBegin();
+#endif
+
+#if ENABLE_PHY_RX_INPUT_OFFSET  // skip when bring up
+    ///TODO: no shuffle, only need to do once under highest freq.
+    if(p->frequency == u2DFSGetHighestFreq(p))
+    DramcRXInputBufferOffsetCal(p);
+
+#ifdef DDR_INIT_TIME_PROFILING
+    CPU_Cycle=TimeProfileEnd();
+    mcSHOW_TIME_MSG(("\tRX input cal takes %d us\n", CPU_Cycle));
+    TimeProfileBegin();
+#endif
+#endif
+
+
+#if GATING_ADJUST_TXDLY_FOR_TRACKING
+    DramcRxdqsGatingPreProcess(p);
+#endif
+
+    if (p->support_rank_num==RANK_DUAL)
+        u1RankMax = RANK_MAX;
+    else
+        u1RankMax = RANK_1;
+
+    //vAutoRefreshSwitch(p, DISABLE); //auto refresh is set as disable in LP4_DramcSetting, so don't need to disable again
+
+#if ENABLE_CA_TRAINING
+    for(s1RankIdx=RANK_0; s1RankIdx<u1RankMax; s1RankIdx++)
+    {
+        vSetRank(p, s1RankIdx);
+    #if PINMUX_AUTO_TEST_PER_BIT_CA
+        CheckCAPinMux(p);
+    #endif
+        CmdBusTrainingLP4(p);
+
+#if EYESCAN_LOG
+        print_EYESCAN_LOG_message(p, 0); //draw CBT eyescan
+#endif
+#ifdef DDR_INIT_TIME_PROFILING
+        CPU_Cycle=TimeProfileEnd();
+        mcSHOW_TIME_MSG(("\tRank %d CBT takes %d us\n", s1RankIdx, CPU_Cycle));
+        TimeProfileBegin();
+#endif
+    }
+
+    vSetRank(p, RANK_0);
+
+#if DUAL_FREQ_K
+    No_Parking_On_CLRPLL(p);
+#endif
+#endif //ENABLE_CA_TRAINING
+
+    for(s1RankIdx=RANK_0; s1RankIdx<u1RankMax; s1RankIdx++)
+    {
+        vSetRank(p, s1RankIdx);
+
+#ifdef DEVIATION
+        {
+            U16 u2RXVrefDefault;
+            u2RXVrefDefault = vGetRXVrefDefault(p);
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ5), u2RXVrefDefault, SHU1_B0_DQ5_RG_RX_ARDQ_VREF_SEL_B0);  // LP4 and LP4x with term: 0xe
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ5), u2RXVrefDefault, SHU1_B1_DQ5_RG_RX_ARDQ_VREF_SEL_B1);  // LP4 and LP4x with term: 0xe
+        }
+#endif
+
+//#if ENABLE_LP4_ZQ_CAL
+        //DramcZQCalibration(p); //ZQ calibration should be done before CBT and operated at low frequency, so it is moved to mode register init
+//#endif
+
+        #if ENABLE_WRITE_LEVELING
+        DramcWriteLeveling((DRAMC_CTX_T *) p);//Dram will be reset when finish write leveling
+
+        #ifdef DDR_INIT_TIME_PROFILING
+        CPU_Cycle=TimeProfileEnd();
+        mcSHOW_TIME_MSG(("\tRank %d Write leveling takes %d us\n", s1RankIdx, CPU_Cycle));
+        TimeProfileBegin();
+        #endif
+        #endif
+
+        #if LJPLL_FREQ_DEBUG_LOG
+        DDRPhyFreqMeter();
+    #endif
+
+        vAutoRefreshSwitch(p, ENABLE); //when doing gating, RX and TX calibration, auto refresh should be enable
+
+        DramcRxdqsGatingCal(p);
+
+        #ifdef DDR_INIT_TIME_PROFILING
+        CPU_Cycle=TimeProfileEnd();
+        mcSHOW_TIME_MSG(("\tRank %d Gating takes %d us\n", s1RankIdx, CPU_Cycle));
+        TimeProfileBegin();
+        #endif
+
+    #if LJPLL_FREQ_DEBUG_LOG
+        DDRPhyFreqMeter();
+    #endif
+
+    #if PINMUX_AUTO_TEST_PER_BIT_RX
+        CheckRxPinMux(p);
+    #endif
+        DramcRxWindowPerbitCal((DRAMC_CTX_T *) p, 0);
+
+    #ifdef DDR_INIT_TIME_PROFILING
+        CPU_Cycle=TimeProfileEnd();
+        mcSHOW_TIME_MSG(("\tRank %d RX RDDQC takes %d us\n", s1RankIdx, CPU_Cycle));
+        TimeProfileBegin();
+    #endif
+
+    #if LJPLL_FREQ_DEBUG_LOG
+        DDRPhyFreqMeter();
+    #endif
+
+#if MRW_CHECK_ONLY
+        mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
+#endif
+#if TX_K_DQM_WITH_WDBI
+        //DramcWriteDBIOnOff() control both rank, need to recover for rank1 tx calibration
+        DramcWriteDBIOnOff(p, 0);
+#endif
+        DramcTxWindowPerbitCal((DRAMC_CTX_T *) p, TX_DQ_DQS_MOVE_DQ_DQM, DISABLE_VREF_SCAN);  //Vref scan disable
+        {
+            DramcTxWindowPerbitCal((DRAMC_CTX_T *) p, TX_DQ_DQS_MOVE_DQ_ONLY, p->enable_tx_scan_vref);
+        }
+    #if PINMUX_AUTO_TEST_PER_BIT_TX
+        CheckTxPinMux(p);
+    #endif
+        DramcTxWindowPerbitCal((DRAMC_CTX_T *) p, TX_DQ_DQS_MOVE_DQ_ONLY, DISABLE_VREF_SCAN);
+
+#if TX_K_DQM_WITH_WDBI
+        #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        if(p->Bypass_TXWINDOW==0) //if bypass TX K, DQM will be calculate form DQ. (no need to K DQM)
+        #endif
+        {
+            if ((p->DBI_W_onoff[p->dram_fsp]==DBI_ON))
+            {
+                // K DQM with DBI_ON, and check DQM window spec.
+                //mcSHOW_DBG_MSG(("[TX_K_DQM_WITH_WDBI] Step1: K DQM with DBI_ON, and check DQM window spec.\n\n"));
+                vSwitchWriteDBISettings(p, DBI_ON);
+                DramcTxWindowPerbitCal((DRAMC_CTX_T *) p, TX_DQ_DQS_MOVE_DQM_ONLY, DISABLE_VREF_SCAN);
+                vSwitchWriteDBISettings(p, DBI_OFF);
+            }
+        }
+#endif
+
+#if EYESCAN_LOG
+        Dramc_K_TX_EyeScan_Log(p);
+        print_EYESCAN_LOG_message(p, 2); //draw TX eyescan
+#endif
+
+        #ifdef DDR_INIT_TIME_PROFILING
+        CPU_Cycle=TimeProfileEnd();
+        mcSHOW_TIME_MSG(("\tRank %d TX calibration takes %d us\n", s1RankIdx, CPU_Cycle));
+        TimeProfileBegin();
+        #endif
+
+        #if LJPLL_FREQ_DEBUG_LOG
+            DDRPhyFreqMeter();
+        #endif
+
+        DramcRxdatlatCal((DRAMC_CTX_T *) p);
+
+        #ifdef DDR_INIT_TIME_PROFILING
+        CPU_Cycle=TimeProfileEnd();
+        mcSHOW_TIME_MSG(("\tRank %d Datlat takes %d us\n", s1RankIdx, CPU_Cycle));
+        TimeProfileBegin();
+        #endif
+
+        #if LJPLL_FREQ_DEBUG_LOG
+            DDRPhyFreqMeter();
+        #endif
+
+        DramcRxWindowPerbitCal((DRAMC_CTX_T *) p, 1);
+
+        #ifdef DDR_INIT_TIME_PROFILING
+        CPU_Cycle=TimeProfileEnd();
+        mcSHOW_TIME_MSG(("\tRank %d RX calibration takes %d us\n", s1RankIdx, CPU_Cycle));
+        TimeProfileBegin();
+        #endif
+       // DramcRxdqsGatingCal(p);
+
+#if EYESCAN_LOG
+        print_EYESCAN_LOG_message(p, 1); //draw RX eyescan
+#endif
+
+#if TX_OE_CALIBATION
+        DramcTxOECalibration(p);
+#endif
+
+        vAutoRefreshSwitch(p, DISABLE); //After gating, Rx and Tx calibration, auto refresh should be disable
+
+        #if ENABLE_TX_TRACKING
+        #if 0 /* Starting from Vinson, no need to pre-calculate MR23 for different freqs */
+        if(gu1MR23Done==FALSE)
+        {
+            DramcDQSOSCAuto(p);
+        }
+        #endif
+        DramcDQSOSCAuto(p);
+        DramcDQSOSCMR23(p);
+        DramcDQSOSCSetMR18MR19(p);
+        #endif
+    }
+    vSetRank(p, RANK_0); // Set p's rank back to 0 (Avoids unexpected auto-rank offset calculation in u4RegBaseAddrTraslate())
+
+    #if ENABLE_TX_TRACKING
+    DramcDQSOSCShuSettings(p);
+    #endif
+
+#if GATING_ADJUST_TXDLY_FOR_TRACKING
+        DramcRxdqsGatingPostProcess(p);
+#endif
+
+    if (p->support_rank_num==RANK_DUAL)
+    {
+        DramcDualRankRxdatlatCal(p);
+    }
+
+#if LJPLL_FREQ_DEBUG_LOG
+        DDRPhyFreqMeter();
+#endif
+
+    #ifdef DDR_INIT_TIME_PROFILING
+    CPU_Cycle=TimeProfileEnd();
+    mcSHOW_TIME_MSG(("\tMisc takes %d us\n\n", s1RankIdx, CPU_Cycle));
+    #endif
+}
+
+#if ENABLE_LP3_SW
+DRAM_STATUS_T CATrainingLP3(DRAMC_CTX_T *p);
+static void vCalibration_Flow_LP3(DRAMC_CTX_T *p)
+{
+    U8 u1RankMax;
+    S8 s1RankIdx;
+
+#ifdef DDR_INIT_TIME_PROFILING
+    U32 CPU_Cycle;
+    TimeProfileBegin();
+#endif
+
+    //vAutoRefreshSwitch(p, DISABLE); //auto refresh is set as disable in LP3_DramcSetting, so don't need to disable again
+#if (fcFOR_CHIP_ID == fcLaurel)
+#if 0
+#if ENABLE_CA_TRAINING  // skip when bring up
+    vSetRank(p, RANK_0);
+#if PINMUX_AUTO_TEST_PER_BIT_CA
+    CheckCAPinMux_LP3(p);
+#endif
+    CATrainingLP3(p);
+    #if CA_TRAINING_K_RANK1_ENABLE //if dual rank K is enable, rank 0 and 1 both should do CA training
+        if (p->support_rank_num==RANK_DUAL)
+        {
+            vSetRank(p, RANK_1);
+        #if PINMUX_AUTO_TEST_PER_BIT_CA
+            CheckCAPinMux_LP3(p);
+        #endif
+            CATrainingLP3(p);
+            vSetRank(p, RANK_0);
+            //CATrainingLP3PostProcess(p); //set final CLK and CA delay as the result of averge delay of rank0 and rank1
+        }
+    #endif
+#endif // end of ENABLE_CA_TRAINING
+
+#if LP3_MR_INIT_AFTER_CA_TRAIN
+    u1PrintModeRegWrite =1;
+    DramcModeRegInit_LP3(p, FALSE); // set mode register without reset dram.
+    u1PrintModeRegWrite =0;
+#endif
+#endif
+#endif
+
+#ifdef DDR_INIT_TIME_PROFILING
+    CPU_Cycle=TimeProfileEnd();
+    mcSHOW_TIME_MSG(("\tDRAMC CA train takes %d us\n", CPU_Cycle));
+    TimeProfileBegin();
+#endif
+
+#if GATING_ADJUST_TXDLY_FOR_TRACKING
+    DramcRxdqsGatingPreProcess(p);
+#endif
+
+        if (p->support_rank_num==RANK_DUAL)
+            u1RankMax = RANK_MAX;
+        else
+            u1RankMax = RANK_1;
+
+        for(s1RankIdx=RANK_0; s1RankIdx<u1RankMax; s1RankIdx++)
+        {
+            vSetRank(p, s1RankIdx);
+
+            vAutoRefreshSwitch(p, DISABLE); //If auto refresh don't disable at begin, auto refresh will be enable when K rank1 CAtraining and write leveling
+
+        #if (fcFOR_CHIP_ID == fcLaurel)
+            #if 0
+            if((p->support_rank_num==RANK_SINGLE) || ((p->support_rank_num==RANK_DUAL) && (s1RankIdx == RANK_0)))
+            {
+                #if ENABLE_WRITE_LEVELING
+                    DramcWriteLeveling((DRAMC_CTX_T *) p);//Dram will be reset when finish write leveling
+                #endif
+
+                #ifdef DDR_INIT_TIME_PROFILING
+                    CPU_Cycle=TimeProfileEnd();
+                    mcSHOW_TIME_MSG(("\tRank %d Write leveling takes %d us\n", s1RankIdx, CPU_Cycle));
+                    TimeProfileBegin();
+                #endif
+            }
+            #endif
+        #endif
+
+        vAutoRefreshSwitch(p, ENABLE); //when doing gating, RX and TX calibration, auto refresh should be enable
+
+        #if LJPLL_FREQ_DEBUG_LOG
+            DDRPhyFreqMeter();
+        #endif
+
+            DramcRxdqsGatingCal(p);
+
+        #ifdef DDR_INIT_TIME_PROFILING
+            CPU_Cycle=TimeProfileEnd();
+            mcSHOW_TIME_MSG(("\tRank %d Gating takes %d us\n", s1RankIdx, CPU_Cycle));
+            TimeProfileBegin();
+        #endif
+
+        #if LJPLL_FREQ_DEBUG_LOG
+            DDRPhyFreqMeter();
+        #endif
+
+            DramcRxdatlatCal((DRAMC_CTX_T *) p);
+
+        #ifdef DDR_INIT_TIME_PROFILING
+            CPU_Cycle=TimeProfileEnd();
+            mcSHOW_TIME_MSG(("\tRank %d Datlat takes %d us\n\r", s1RankIdx, CPU_Cycle));
+            TimeProfileBegin();
+        #endif
+
+        #if LJPLL_FREQ_DEBUG_LOG
+            DDRPhyFreqMeter();
+        #endif
+
+        #ifndef LP3_DUAL_RANK_RX_K
+            if(s1RankIdx == RANK_0)
+        #endif
+            {
+            #if PINMUX_AUTO_TEST_PER_BIT_RX_LP3
+                CheckRxPinMux(p);
+            #endif
+                DramcRxWindowPerbitCal((DRAMC_CTX_T *) p, 1);
+
+            #ifdef DDR_INIT_TIME_PROFILING
+                CPU_Cycle=TimeProfileEnd();
+                mcSHOW_TIME_MSG(("\tRank %d RX takes %d us\n", s1RankIdx, CPU_Cycle));
+                TimeProfileBegin();
+            #endif
+            }
+
+        #ifndef LP3_DUAL_RANK_TX_K
+            if(s1RankIdx==RANK_0)
+        #endif
+            {
+                DramcTxWindowPerbitCal((DRAMC_CTX_T *) p, TX_DQ_DQS_MOVE_DQ_DQM, DISABLE_VREF_SCAN);
+                #ifdef DDR_INIT_TIME_PROFILING
+                CPU_Cycle=TimeProfileEnd();
+                mcSHOW_TIME_MSG(("\tRank %d TX takes %d us\n", s1RankIdx, CPU_Cycle));
+                TimeProfileBegin();
+                #endif
+            }
+        }
+
+        vSetRank(p, RANK_0);
+
+    #if GATING_ADJUST_TXDLY_FOR_TRACKING
+            DramcRxdqsGatingPostProcess(p);
+    #endif
+
+        if (p->support_rank_num==RANK_DUAL)
+        {
+            DramcDualRankRxdatlatCal(p);
+        }
+
+#if LJPLL_FREQ_DEBUG_LOG
+        DDRPhyFreqMeter();
+#endif
+
+    vAutoRefreshSwitch(p, DISABLE); //After gating, Rx and Tx calibration, auto refresh should be disable
+
+#ifdef DDR_INIT_TIME_PROFILING
+    CPU_Cycle=TimeProfileEnd();
+    mcSHOW_TIME_MSG(("\tMisc takes %d us\n\n", s1RankIdx, CPU_Cycle));
+#endif
+}
+#endif
+
+
+static void vDramCalibrationSingleChannel(DRAMC_CTX_T *p)
+{
+#if 0 //!__ETT__
+    /*
+     * Since DRAM calibration will cost much time,
+     * kick wdt here to prevent watchdog timeout.
+     * Sagy: Mask for the fcLaurel at the beginning
+     */
+#if (FOR_DV_SIMULATION_USED==0 && SW_CHANGE_FOR_SIMULATION==0)
+    mtk_wdt_restart();
+#endif
+#endif
+
+    if(u1IsLP4Family(p->dram_type))
+        vCalibration_Flow_LP4(p);
+#if ENABLE_LP3_SW
+    else
+        vCalibration_Flow_LP3(p);
+#endif
+}
+
+static void vDramCalibrationAllChannel(DRAMC_CTX_T *p)
+{
+    U8 channel_idx, rank_idx;
+
+#ifdef DDR_INIT_TIME_PROFILING
+    U32 u4low_tick0, u4high_tick0, u4low_tick1, u4high_tick1;
+#if __ETT__
+    u4low_tick0 = GPT_GetTickCount(&u4high_tick0);
+#else
+    u4low_tick0 = get_timer(0);
+#endif
+#endif
+
+    for(channel_idx=CHANNEL_A; channel_idx<p->support_channel_num; channel_idx++)
+    {
+        vSetPHY2ChannelMapping(p, u1ChannelSet[channel_idx]);// when switching channel, must update PHY to Channel Mapping
+        vDramCalibrationSingleChannel(p);
+    }
+
+    vSetPHY2ChannelMapping(p, u1ChannelSet[0]);
+
+#if PRINT_CALIBRATION_SUMMARY
+    vPrintCalibrationResult(p);
+#endif
+
+#ifdef FOR_HQA_TEST_USED
+    #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+    if(p->femmc_Ready==1)
+    {
+        mcSHOW_DBG_MSG(("\nCalibration fast K is enable, cannot show HQA measurement information\n"));
+    }
+    else
+    #endif
+        print_HQA_measure_message(p);
+#endif
+
+#ifdef DEVIATION
+    if(p->frequency == u2DFSGetHighestFreq(p))
+    {
+        vSetDeviationVariable();
+    }
+#endif
+
+    /* Enable/Disable calibrated rank's DBI function accordingly */
+#if ENABLE_READ_DBI
+	//Read DBI ON
+	vSetRank(p, RANK_0);
+	vSetPHY2ChannelMapping(p, u1ChannelSet[0]);
+
+	DramcReadDBIOnOff(p, p->DBI_R_onoff[p->dram_fsp]);
+#endif
+
+#if ENABLE_WRITE_DBI
+    //Write DBI ON
+    for(channel_idx=CHANNEL_A; channel_idx<p->support_channel_num; channel_idx++)
+    {
+        vSetPHY2ChannelMapping(p, u1ChannelSet[channel_idx]);
+
+        for(rank_idx=RANK_0; rank_idx<RANK_MAX; rank_idx++)
+        {
+            vSetRank(p, rank_idx);
+            DramcWriteMinus1MCKForWriteDBI(p, -8); //Tx DQ/DQM -1 MCK for write DBI ON
+        }
+        vSetRank(p, RANK_0);
+    }
+    vSetPHY2ChannelMapping(p, u1ChannelSet[0]);
+
+    DramcWriteDBIOnOff(p, p->DBI_W_onoff[p->dram_fsp]);
+
+    // Improve Write DBI Power
+    ApplyWriteDBIPowerImprove(p, ENABLE);
+
+    #if ENABLE_WRITE_DBI_Protect
+    ApplyWriteDBIProtect(p, ENABLE);
+    #endif
+#endif
+
+#ifdef DDR_INIT_TIME_PROFILING
+#if __ETT__
+    u4low_tick1 = GPT_GetTickCount(&u4high_tick1);
+    mcSHOW_TIME_MSG(("  (4) vDramCalibrationAllChannel() take %d ms\n\r",((u4low_tick1-u4low_tick0)*76)/1000000));
+#else
+    u4low_tick1 = get_timer(u4low_tick0);
+    mcSHOW_TIME_MSG(("  (4) vDramCalibrationAllChannel() take %d ms\n\r",u4low_tick1));
+#endif
+#endif
+}
+
+
+static void vCalibration_Flow_For_MDL(DRAMC_CTX_T *p)
+{
+    U8 u1RankMax;
+    S8 s1RankIdx;
+
+    if(u1IsLP4Family(p->dram_type))
+    {
+#if GATING_ADJUST_TXDLY_FOR_TRACKING
+        DramcRxdqsGatingPreProcess(p);
+#endif
+
+        if (p->support_rank_num==RANK_DUAL)
+            u1RankMax = RANK_MAX;
+        else
+            u1RankMax = RANK_1;
+
+        for(s1RankIdx=RANK_0; s1RankIdx<u1RankMax; s1RankIdx++)
+        {
+            vSetRank(p, s1RankIdx);
+
+            vAutoRefreshSwitch(p, ENABLE); //when doing gating, RX and TX calibration, auto refresh should be enable
+            DramcRxdqsGatingCal(p);
+            DramcRxWindowPerbitCal((DRAMC_CTX_T *) p, 0);
+
+#if MRW_CHECK_ONLY
+            mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
+#endif
+            vAutoRefreshSwitch(p, DISABLE); //After gating, Rx and Tx calibration, auto refresh should be disable
+        }
+
+        vSetRank(p, RANK_0); // Set p's rank back to 0 (Avoids unexpected auto-rank offset calculation in u4RegBaseAddrTraslate())
+
+#if GATING_ADJUST_TXDLY_FOR_TRACKING
+         DramcRxdqsGatingPostProcess(p);
+#endif
+    }
+    else // LP3
+    {
+       vDramCalibrationSingleChannel(p);  ///TODO: vCalibration_Flow_For_MDL for LP3
+    }
+}
+
+
+int GetDramInforAfterCalByMRR(DRAMC_CTX_T *p, DRAM_INFO_BY_MRR_T *DramInfo)
+{
+    U8 u1ChannelIdx, u1RankIdx, u1DieNumber=0;
+    U16 u2Density;
+    U64 u8Size = 0, u8Size_backup = 0;
+    U64 u8ChannelSize;
+    U32 u4ChannelNumber=1, u4RankNumber=1;
+
+    if (p->revision_id != REVISION_ID_MAGIC)
+        return 0;
+
+    vSetPHY2ChannelMapping(p, u1ChannelSet[0]);
+
+    // Read MR5 for Vendor ID
+    DramcModeRegReadByRank(p, RANK_0, 5, &(p->vendor_id));// for byte mode, don't show value of another die.
+    p->vendor_id &= 0xFF;
+    mcSHOW_DBG_MSG(("[GetDramInforAfterCalByMRR] Vendor %x.\n", p->vendor_id));
+    // Read MR6 for Revision ID
+    DramcModeRegReadByRank(p, RANK_0, 6, &(p->revision_id));// for byte mode, don't show value of another die.
+    mcSHOW_DBG_MSG(("[GetDramInforAfterCalByMRR] Revision %x.\n", p->revision_id));
+
+    if(DramInfo != NULL)
+    {
+        DramInfo->u2MR5VendorID = p->vendor_id;
+        DramInfo->u2MR6RevisionID = p->revision_id;
+#ifdef DRAM_ADAPTIVE
+        DramInfo->u4RankNum = p->support_rank_num;
+#endif
+        for(u1ChannelIdx=0; u1ChannelIdx<(p->support_channel_num); u1ChannelIdx++)
+            for(u1RankIdx =0; u1RankIdx<RANK_MAX; u1RankIdx++)
+                DramInfo->u8MR8Density[u1ChannelSet[u1ChannelIdx]][u1RankIdx] =0;
+    }
+
+     // Read MR8 for dram density
+    for(u1ChannelIdx=0; u1ChannelIdx<(p->support_channel_num); u1ChannelIdx++)
+        for(u1RankIdx =0; u1RankIdx<(p->support_rank_num); u1RankIdx++)
+        {
+            #if 0//PRINT_CALIBRATION_SUMMARY
+            if((p->aru4CalExecuteFlag[u1ChannelIdx][u1RankIdx] !=0)  && \
+                (p->aru4CalResultFlag[u1ChannelIdx][u1RankIdx]==0))
+            #endif
+            {
+                vSetPHY2ChannelMapping(p, u1ChannelSet[u1ChannelIdx]);
+                DramcModeRegReadByRank(p, u1RankIdx, 0, &(gu2MR0_Value[u1RankIdx]));
+                mcSHOW_DBG_MSG(("MR0 0x%x\n", gu2MR0_Value[u1RankIdx]));
+                DramcModeRegReadByRank(p, u1RankIdx, 8, &u2Density);
+                mcSHOW_DBG_MSG(("MR8 %x\n", u2Density));
+#ifdef DRAM_ADAPTIVE
+                if ((u2Density & 0x1) && !u1IsLP4Family(p->dram_type))
+                    DramInfo->u4BankMode = BANK_TYPE_S2;
+                else
+                    DramInfo->u4BankMode = BANK_TYPE_S4;
+#endif
+                u1DieNumber =1;
+                if(p->dram_type == TYPE_LPDDR3)
+                {
+                    if(((u2Density >> 6) & 0x3)==1) //OP[7:6] =0, x16 (2 die)
+                        u1DieNumber =2;
+                } else if (u1IsLP4Family(p->dram_type)) {
+                    if(((u2Density >> 6) & 0x3) == 1) //OP[7:6] =0, x16 (normal mode)
+                        u1DieNumber =2;
+                }
+#ifdef DRAM_ADAPTIVE
+                if (DramInfo != NULL)
+                    DramInfo->u1DieNum[u1RankIdx] = u1DieNumber;
+#endif
+                u2Density = (u2Density>>2)&0xf;
+
+                if (u1IsLP4Family(p->dram_type))
+                {
+            	    switch(u2Density)
+            	    {
+            	        ///TODO: Darren, please check the value of u8Size.
+            	        case 0x0:
+            	            u8Size = 0x20000000;  //4Gb
+            	            //DBG_MSG("[EMI]DRAM density = 4Gb\n");
+            	            break;
+            	        case 0x1:
+            	            u8Size = 0x30000000;  //6Gb
+            	            //DBG_MSG("[EMI]DRAM density = 6Gb\n");
+            	            break;
+            	        case 0x2:
+            	            u8Size = 0x40000000;  //8Gb
+            	            //DBG_MSG("[EMI]DRAM density = 8Gb\n");
+            	            break;
+            	        case 0x3:
+            	            u8Size = 0x60000000;  //12Gb
+            	            //DBG_MSG("[EMI]DRAM density = 12Gb\n");
+            	            break;
+            	        case 0x4:
+            	            u8Size = 0x80000000;  //16Gb
+            	            //DBG_MSG("[EMI]DRAM density = 16Gb\n");
+            	            break;
+            	        case 0x5:
+            	            u8Size = 0xc0000000; //24Gb
+            	            //DBG_MSG("[EMI]DRAM density = 24Gb\n");
+            	            break;
+            	        case 0x6:
+            	            u8Size = 0x100000000L; //32Gb
+            	            //DBG_MSG("[EMI]DRAM density = 32Gb\n");
+            	            break;
+            	        default:
+            	            u8Size = 0; //reserved
+            	    }
+                }
+#if ENABLE_LP3_SW
+                else
+                {
+                    switch(u2Density)
+                    {
+                        case 0x0:
+                            u8Size = 0x800000;  //64Mb
+                            //DBG_MSG("[EMI]DRAM density = 64Mb\n");
+                            break;
+                        case 0x1:
+                            u8Size = 0x1000000;  //128Mb
+                            //DBG_MSG("[EMI]DRAM density = 128Mb\n");
+                            break;
+                        case 0x2:
+                            u8Size = 0x2000000;  //256Mb
+                            //DBG_MSG("[EMI]DRAM density = 256Mb\n");
+                            break;
+                        case 0x3:
+                            u8Size = 0x4000000;  //512Mb
+                            //DBG_MSG("[EMI]DRAM density = 512Mb\n");
+                            break;
+                        case 0x4:
+                            u8Size = 0x8000000;  //1Gb
+                            //DBG_MSG("[EMI]DRAM density = 1Gb\n");
+                            break;
+                        case 0x5:
+                            u8Size = 0x10000000;  //2Gb
+                            //DBG_MSG("[EMI]DRAM density = 2Gb\n");
+                            break;
+                        case 0x6:
+                            u8Size = 0x20000000;  //4Gb
+                            //DBG_MSG("[EMI]DRAM density = 4Gb\n");
+                            break;
+                        case 0xE:
+                            u8Size = 0x30000000;  //6Gb
+                            //DBG_MSG("[EMI]DRAM density = 6Gb\n");
+                            break;
+                        case 0x7:
+                            u8Size = 0x40000000;  //8Gb
+                            //DBG_MSG("[EMI]DRAM density = 8Gb\n");
+                            break;
+                        case 0xD:
+                            u8Size = 0x60000000;  //12Gb
+                            //DBG_MSG("[EMI]DRAM density = 12Gb\n");
+                            break;
+                        case 0x8:
+                            u8Size = 0x80000000;  //16Gb
+                            //DBG_MSG("[EMI]DRAM density = 16Gb\n");
+                            break;
+                        //case 0x9:
+                            //u8Size = 0x100000000L; //32Gb
+                            //DBG_MSG("[EMI]DRAM density = 32Gb\n");
+                            //break;
+                        default:
+                            u8Size = 0; //reserved
+                    }
+                }
+#endif /* ENABLE_LP3_SW */
+                if (u8Size_backup < u8Size) // find max dram size for vDramcACTimingOptimize
+                {
+                    u8Size_backup = u8Size;
+                    p->density = u2Density;
+                }
+
+                u8Size *= u1DieNumber;
+                u8ChannelSize = u8Size;
+                u4ChannelNumber = p->support_channel_num;
+
+                if (p->support_rank_num==RANK_DUAL)
+                {
+                    u4RankNumber = 2;
+                }
+
+                p->ranksize[u1RankIdx] = (u8ChannelSize/u4RankNumber)*u4ChannelNumber;
+
+                if(DramInfo != NULL)
+                    DramInfo->u8MR8Density[u1ChannelSet[u1ChannelIdx]][u1RankIdx] = u8Size;
+         }
+        mcSHOW_DBG_MSG(("BankMode = %s\n", DramInfo->u4BankMode == BANK_TYPE_S2 ? "S2" : "S4" ));
+        mcSHOW_DBG_MSG(("CH%d, RK%d, DieNum %d, Density %llx, RKsize %llx.\n", u1ChannelSet[u1ChannelIdx], u1RankIdx, u1DieNumber, u8Size, p->ranksize[u1RankIdx]));
+        }
+
+    vSetPHY2ChannelMapping(p, u1ChannelSet[0]);
+
+    return 0;
+}
+
+#if ENABLE_RANK_NUMBER_AUTO_DETECTION
+void DramRankNumberDetection(DRAMC_CTX_T *p)
+{
+    U8 u1RankBak;
+
+    u1RankBak = u1GetRank(p);  // backup current rank setting
+
+    vSetPHY2ChannelMapping(p, u1ChannelSet[0]); // when switching channel, must update PHY to Channel Mapping
+    vSetRank(p, RANK_1);
+
+    if(DramcWriteLeveling((DRAMC_CTX_T *) p) == DRAM_OK)//Dram will be reset when finish write leveling
+    {
+        p->support_rank_num = RANK_DUAL;
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RSTMASK), 0, RSTMASK_RSV_DRAM_SUPPORT_RANK_NUM);  //keep support_rank_num to reserved rg
+    }
+    else
+    {
+        p->support_rank_num = RANK_SINGLE;
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RSTMASK), 1, RSTMASK_RSV_DRAM_SUPPORT_RANK_NUM);  //keep support_rank_num to reserved rg
+    }
+    mcSHOW_DBG_MSG(("[RankNumberDetection] %d\n", p->support_rank_num));
+
+    vSetRank(p, u1RankBak);  // restore rank setting
+}
+#endif
+
+U8 gPRE_MIOCK_JMETER_HQA_USED_flag=0;
+void Set_PRE_MIOCK_JMETER_HQA_USED_flag(U8 value)
+{
+    gPRE_MIOCK_JMETER_HQA_USED_flag = value;
+}
+U8 Get_PRE_MIOCK_JMETER_HQA_USED_flag(void)
+{
+    return gPRE_MIOCK_JMETER_HQA_USED_flag;
+}
+
+#ifdef ENABLE_MIOCK_JMETER
+void PRE_MIOCK_JMETER_HQA_USED(DRAMC_CTX_T *p)
+{
+    U32 backup_freq_sel, backup_channel;
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+    U32 channel_idx;
+
+    if(p->femmc_Ready==1)
+    {
+        for(channel_idx=CHANNEL_A; channel_idx<p->support_channel_num; channel_idx++)
+        {
+            //for (shuffleIdx = DRAM_DFS_SHUFFLE_1; shuffleIdx < DRAM_DFS_SHUFFLE_MAX; shuffleIdx++)
+            {
+                ucg_num_dlycell_perT_all[p->shu_type][u1ChannelSet[channel_idx]] = p->pSavetimeData->ucnum_dlycell_perT;
+                u2gdelay_cell_ps_all[p->shu_type][u1ChannelSet[channel_idx]] = p->pSavetimeData->u2DelayCellTimex100;
+            }
+        }
+
+        p->ucnum_dlycell_perT = p->pSavetimeData->ucnum_dlycell_perT;
+        p->u2DelayCellTimex100 = p->pSavetimeData->u2DelayCellTimex100;
+        return;
+    }
+#endif
+
+
+    backup_freq_sel = p->freq_sel;
+    backup_channel = p->channel;
+
+    mcSHOW_DBG_MSG3(("[JMETER_HQA]\n"));
+    Set_PRE_MIOCK_JMETER_HQA_USED_flag(1);
+
+    vSetPHY2ChannelMapping(p, u1ChannelSet[0]);
+    DramcMiockJmeterHQA(p);
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+    if(p->femmc_Ready==0)
+    {
+        #if 0
+        for(channel_idx=CHANNEL_A; channel_idx<p->support_channel_num; channel_idx++)
+        {
+            for (shuffleIdx = DRAM_DFS_SHUFFLE_1; shuffleIdx < DRAM_DFS_SHUFFLE_MAX; shuffleIdx++)
+            {
+                p->pSavetimeData->ucg_num_dlycell_perT_all[channel_idx] = ucg_num_dlycell_perT_all[p->shu_type][channel_idx];
+                p->pSavetimeData->u2gdelay_cell_ps_all[channel_idx] = u2gdelay_cell_ps_all[p->shu_type][channel_idx];
+            }
+        }
+        #endif
+        p->pSavetimeData->ucnum_dlycell_perT = p->ucnum_dlycell_perT;
+        p->pSavetimeData->u2DelayCellTimex100 = p->u2DelayCellTimex100;
+    }
+#endif
+    vSetPHY2ChannelMapping(p, backup_channel);
+
+    #if 0
+    p->freq_sel = LP4_DDR2667;
+    DDRPhyFreqSel(p, p->freq_sel);
+    vSetVcoreByFreq(p);
+    DramcInit((DRAMC_CTX_T *) p);
+    for(channel_idx=CHANNEL_A; channel_idx<p->support_channel_num; channel_idx++)
+    {
+        vSetPHY2ChannelMapping(p, channel_idx);
+        DramcMiockJmeterHQA(p);
+    }
+    vSetPHY2ChannelMapping(p, backup_channel);
+    #endif
+
+    Set_PRE_MIOCK_JMETER_HQA_USED_flag(0);
+
+    p->freq_sel = backup_freq_sel;
+}
+#endif
+
+#if RUNTIME_SHMOO_RELEATED_FUNCTION && SUPPORT_SAVE_TIME_FOR_CALIBRATION
+void RunTime_Shmoo_update_parameters(DRAMC_CTX_T *p)
+{
+
+    U8 backup_channel, backup_rank;
+    U16 tx_pi_delay, tx_dqm_pi_delay;
+    U8 ui_large_value, ui_small_value, pi_value;
+    U8 ui_dqm_large_value, ui_dqm_small_value, pi_dqm_value;
+#if 0
+    U8 ui_oen_large_value, ui_oen_small_value, pi_oen_value;
+    U8 ui_dqm_oen_large_value, ui_dqm_oen_small_value, pi_dqm_oen_value;
+#endif
+
+    backup_channel = p->channel;
+    backup_rank = p->rank;
+
+    p->channel = RUNTIME_SHMOO_TEST_CHANNEL;
+    p->rank = RUNTIME_SHMOO_TEST_RANK;
+
+    if (RUNTIME_SHMOO_TEST_BYTE == 0)
+    {
+        tx_pi_delay = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), SHURK0_SELPH_DQ0_TXDLY_DQ0) * 256 +
+                      u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2), SHURK0_SELPH_DQ2_DLY_DQ0) * 32 +
+                      u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+
+        tx_dqm_pi_delay = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), SHURK0_SELPH_DQ1_TXDLY_DQM0) * 256 +
+                          u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3), SHURK0_SELPH_DQ3_DLY_DQM0) * 32 +
+                          u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+    }
+    else
+    {
+        tx_pi_delay = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), SHURK0_SELPH_DQ0_TXDLY_DQ1) * 256 +
+                      u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2), SHURK0_SELPH_DQ2_DLY_DQ1) * 32 +
+                      u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), SHU1_R0_B1_DQ7_RK0_ARPI_DQ_B1);
+
+        tx_dqm_pi_delay = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), SHURK0_SELPH_DQ1_TXDLY_DQM1) * 256 +
+                          u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3), SHURK0_SELPH_DQ3_DLY_DQM1) * 32 +
+                          u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), SHU1_R0_B1_DQ7_RK0_ARPI_DQM_B1);
+    }
+
+    mcSHOW_ERR_MSG(("fra femmc_Ready = %d ==\n",p->femmc_Ready));
+
+    if (p->femmc_Ready==0 ||
+ ((p->pSavetimeData->Runtime_Shmoo_para.TX_Channel!=RUNTIME_SHMOO_TEST_CHANNEL) || (p->pSavetimeData->Runtime_Shmoo_para.TX_Rank!=RUNTIME_SHMOO_TEST_RANK) || (p->pSavetimeData->Runtime_Shmoo_para.TX_Byte!=RUNTIME_SHMOO_TEST_BYTE))) //first K
+    {
+        p->pSavetimeData->Runtime_Shmoo_para.flag= 0; //on going
+        p->pSavetimeData->Runtime_Shmoo_para.TX_PI_delay = tx_pi_delay-32+RUNTIME_SHMOO_TEST_PI_DELAY_START;
+        p->pSavetimeData->Runtime_Shmoo_para.TX_Original_PI_delay = p->pSavetimeData->Runtime_Shmoo_para.TX_PI_delay;
+        p->pSavetimeData->Runtime_Shmoo_para.TX_DQM_PI_delay = tx_dqm_pi_delay-32+RUNTIME_SHMOO_TEST_PI_DELAY_START;
+        p->pSavetimeData->Runtime_Shmoo_para.TX_Original_DQM_PI_delay = p->pSavetimeData->Runtime_Shmoo_para.TX_DQM_PI_delay;
+        if (RUNTIME_SHMOO_TEST_VREF_START<51)
+        {
+            p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Range = 0;
+            p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Value = RUNTIME_SHMOO_TEST_VREF_START;
+        }
+        else
+        {
+            p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Range = 1;
+            p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Value = RUNTIME_SHMOO_TEST_VREF_START-51+21;
+        }
+        p->pSavetimeData->Runtime_Shmoo_para.TX_Channel = RUNTIME_SHMOO_TEST_CHANNEL;
+        p->pSavetimeData->Runtime_Shmoo_para.TX_Rank = RUNTIME_SHMOO_TEST_RANK;
+        p->pSavetimeData->Runtime_Shmoo_para.TX_Byte = RUNTIME_SHMOO_TEST_BYTE;
+    }
+    else  if (dramc_get_rshmoo_step())
+    {
+        p->pSavetimeData->Runtime_Shmoo_para.TX_PI_delay += RUNTIME_SHMOO_TEST_PI_DELAY_STEP;
+        if (p->pSavetimeData->Runtime_Shmoo_para.TX_PI_delay > p->pSavetimeData->Runtime_Shmoo_para.TX_Original_PI_delay+RUNTIME_SHMOO_TEST_PI_DELAY_END)
+        {
+            p->pSavetimeData->Runtime_Shmoo_para.TX_PI_delay = p->pSavetimeData->Runtime_Shmoo_para.TX_Original_PI_delay;
+            p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Value += RUNTIME_SHMOO_TEST_VREF_STEP;
+
+            if ((p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Value+p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Range*30) > RUNTIME_SHMOO_TEST_VREF_END)
+            {
+                p->pSavetimeData->Runtime_Shmoo_para.flag= 0xff; //test finish
+            }
+            else
+            {
+                if (p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Range==0)
+                {
+                    if (p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Value > 50)
+                    {
+                        p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Range = 1;
+                        p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Value -= 30;
+                    }
+                }
+            }
+        }
+
+        p->pSavetimeData->Runtime_Shmoo_para.TX_DQM_PI_delay += RUNTIME_SHMOO_TEST_PI_DELAY_STEP;
+        if (p->pSavetimeData->Runtime_Shmoo_para.TX_DQM_PI_delay > p->pSavetimeData->Runtime_Shmoo_para.TX_Original_DQM_PI_delay+RUNTIME_SHMOO_TEST_PI_DELAY_END)
+        {
+            p->pSavetimeData->Runtime_Shmoo_para.TX_DQM_PI_delay = p->pSavetimeData->Runtime_Shmoo_para.TX_Original_DQM_PI_delay;
+        }
+    }
+
+    mcSHOW_ERR_MSG(("Fra RunTime Shmoo CH%d, Rank%d, Byte%d\n",RUNTIME_SHMOO_TEST_CHANNEL, RUNTIME_SHMOO_TEST_RANK, RUNTIME_SHMOO_TEST_BYTE ));
+
+    if (p->pSavetimeData->Runtime_Shmoo_para.flag != 0xff)
+    {
+#if __ETT__
+        mcSHOW_ERR_MSG(("Fra RunTime Shmoo original K TX Vref = (%d, %d)\n", (u1MR14Value[RUNTIME_SHMOO_TEST_CHANNEL][RUNTIME_SHMOO_TEST_RANK][p->dram_fsp]>>6) & 1, u1MR14Value[RUNTIME_SHMOO_TEST_CHANNEL][RUNTIME_SHMOO_TEST_RANK][p->dram_fsp] & 0x3f));
+        mcSHOW_ERR_MSG(("Fra RunTime Shmoo original K TX Byte%d PI Delay = %d\n", RUNTIME_SHMOO_TEST_BYTE, p->pSavetimeData->Runtime_Shmoo_para.TX_Original_PI_delay+32-RUNTIME_SHMOO_TEST_PI_DELAY_START));
+
+        mcSHOW_ERR_MSG(("Fra RunTime Shmoo TX Vref = (%d, %d)\n", p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Range, p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Value));
+        mcSHOW_ERR_MSG(("Fra RunTime Shmoo TX Byte%d PI Delay = %d\n", RUNTIME_SHMOO_TEST_BYTE, p->pSavetimeData->Runtime_Shmoo_para.TX_PI_delay-p->pSavetimeData->Runtime_Shmoo_para.TX_Original_PI_delay));
+#else
+        mcSHOW_ERR_MSG(("Fra RunTime Shmoo original K TX Vref = (%d, %d)\n", (u1MR14Value[RUNTIME_SHMOO_TEST_CHANNEL][RUNTIME_SHMOO_TEST_RANK][p->dram_fsp]>>6) & 1, u1MR14Value[RUNTIME_SHMOO_TEST_CHANNEL][RUNTIME_SHMOO_TEST_RANK][p->dram_fsp] & 0x3f));
+        mcSHOW_ERR_MSG(("Fra RunTime Shmoo original K TX Byte%d PI Delay = %d\n", RUNTIME_SHMOO_TEST_BYTE, p->pSavetimeData->Runtime_Shmoo_para.TX_Original_PI_delay+32-RUNTIME_SHMOO_TEST_PI_DELAY_START));
+
+        mcSHOW_ERR_MSG(("Fra RunTime Shmoo TX Vref = (%d, %d)\n", p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Range, p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Value));
+        mcSHOW_ERR_MSG(("Fra RunTime Shmoo TX Byte%d PI Delay = %d\n", RUNTIME_SHMOO_TEST_BYTE, p->pSavetimeData->Runtime_Shmoo_para.TX_PI_delay-p->pSavetimeData->Runtime_Shmoo_para.TX_Original_PI_delay));
+#endif
+
+        TxWinTransferDelayToUIPI(p, TX_DQ_DQS_MOVE_DQ_DQM, p->pSavetimeData->Runtime_Shmoo_para.TX_PI_delay, 1, &ui_large_value, &ui_small_value, &pi_value);
+        TxWinTransferDelayToUIPI(p, TX_DQ_DQS_MOVE_DQ_DQM, p->pSavetimeData->Runtime_Shmoo_para.TX_DQM_PI_delay, 1, &ui_dqm_large_value, &ui_dqm_small_value, &pi_dqm_value);
+#if 0
+        TxWinTransferDelayToUIPI(p, p->pSavetimeData->Runtime_Shmoo_para.TX_PI_delay-TX_DQ_OE_SHIFT*32, 0, 0, &ui_oen_large_value, &ui_oen_small_value, &pi_oen_value);
+        TxWinTransferDelayToUIPI(p, p->pSavetimeData->Runtime_Shmoo_para.TX_DQM_PI_delay-TX_DQ_OE_SHIFT*32, 0, 0, &ui_dqm_oen_large_value, &ui_dqm_oen_small_value, &pi_dqm_oen_value);
+
+        if (RUNTIME_SHMOO_TEST_BYTE == 0)
+        {
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), P_Fld(ui_large_value, SHURK0_SELPH_DQ0_TXDLY_DQ0) | \
+                                                                            P_Fld(ui_oen_large_value, SHURK0_SELPH_DQ0_TXDLY_OEN_DQ0));
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2), P_Fld(ui_small_value, SHURK0_SELPH_DQ2_DLY_DQ0) | \
+                                                                            P_Fld(ui_oen_small_value, SHURK0_SELPH_DQ2_DLY_OEN_DQ0));
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), pi_value, SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+
+#if 1 //DQM move together
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), P_Fld(ui_dqm_large_value, SHURK0_SELPH_DQ1_TXDLY_DQM0) | \
+                                                                            P_Fld(ui_dqm_oen_large_value, SHURK0_SELPH_DQ1_TXDLY_OEN_DQM0));
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3), P_Fld(ui_dqm_small_value, SHURK0_SELPH_DQ3_DLY_DQM0) | \
+                                                                            P_Fld(ui_dqm_oen_small_value, SHURK0_SELPH_DQ3_DLY_OEN_DQM0));
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), pi_dqm_value, SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+#endif
+        }
+        else
+        {
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), P_Fld(ui_large_value, SHURK0_SELPH_DQ0_TXDLY_DQ1) | \
+                                                                             P_Fld(ui_oen_large_value, SHURK0_SELPH_DQ0_TXDLY_OEN_DQ1));
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2), P_Fld(ui_small_value, SHURK0_SELPH_DQ2_DLY_DQ1) | \
+                                                                             P_Fld(ui_oen_small_value, SHURK0_SELPH_DQ2_DLY_OEN_DQ1));
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), pi_value, SHU1_R0_B1_DQ7_RK0_ARPI_DQ_B1);
+
+#if 1 //DQM move together
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), P_Fld(ui_dqm_large_value, SHURK0_SELPH_DQ1_TXDLY_DQM1) | \
+                                                                            P_Fld(ui_dqm_oen_large_value, SHURK0_SELPH_DQ1_TXDLY_OEN_DQM1));
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3), P_Fld(ui_dqm_small_value, SHURK0_SELPH_DQ3_DLY_DQM1) | \
+                                                                            P_Fld(ui_dqm_oen_small_value, SHURK0_SELPH_DQ3_DLY_OEN_DQM1));
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), pi_dqm_value, SHU1_R0_B1_DQ7_RK0_ARPI_DQM_B1);
+#endif
+        }
+#else
+        if (RUNTIME_SHMOO_TEST_BYTE == 0)
+        {
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), ui_large_value, SHURK0_SELPH_DQ0_TXDLY_DQ0);
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2), ui_small_value, SHURK0_SELPH_DQ2_DLY_DQ0);
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), pi_value, SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), ui_dqm_large_value, SHURK0_SELPH_DQ1_TXDLY_DQM0);
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3), ui_dqm_small_value, SHURK0_SELPH_DQ3_DLY_DQM0);
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), pi_dqm_value, SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+        }
+        else
+        {
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), ui_large_value, SHURK0_SELPH_DQ0_TXDLY_DQ1);
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2), ui_small_value, SHURK0_SELPH_DQ2_DLY_DQ1);
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), pi_value, SHU1_R0_B1_DQ7_RK0_ARPI_DQ_B1);
+
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), ui_dqm_large_value, SHURK0_SELPH_DQ1_TXDLY_DQM1);
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3), ui_dqm_small_value, SHURK0_SELPH_DQ3_DLY_DQM1);
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), pi_dqm_value, SHU1_R0_B1_DQ7_RK0_ARPI_DQM_B1);
+        }
+#endif
+        DramcTXSetVref(p, p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Range, p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Value);
+    }
+
+    //save parameters to eMMC
+#if EMMC_READY
+    write_offline_dram_calibration_data(p->shu_type, p->pSavetimeData);
+#endif
+    mcSHOW_ERR_MSG(("Fra Save calibration result to emmc\n"));
+
+    //copy parameters to memory for kernel test script used
+    //wait for YiRong's SRAM copy function
+    dramc_set_rshmoo_info(p->pSavetimeData->Runtime_Shmoo_para.TX_Rank, p->pSavetimeData->Runtime_Shmoo_para.TX_Channel,
+        p->pSavetimeData->Runtime_Shmoo_para.TX_Byte, p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Range, p->pSavetimeData->Runtime_Shmoo_para.TX_Vref_Value,
+        p->pSavetimeData->Runtime_Shmoo_para.TX_PI_delay-p->pSavetimeData->Runtime_Shmoo_para.TX_Original_PI_delay, 1, (p->pSavetimeData->Runtime_Shmoo_para.flag == 0xff) ? 1 : 0);
+
+
+    //DLL all off from Justin
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_CA_DLL_ARPI2), 0x0, CA_DLL_ARPI2_RG_ARDLL_PHDET_EN_CA);
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B0_DLL_ARPI2), 0x0, B0_DLL_ARPI2_RG_ARDLL_PHDET_EN_B0);
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B1_DLL_ARPI2), 0x0, B1_DLL_ARPI2_RG_ARDLL_PHDET_EN_B1);
+
+    p->channel = backup_channel;
+    p->rank = backup_rank;
+}
+#endif
+
+#ifdef FIRST_BRING_UP
+void Test_Broadcast_Feature(DRAMC_CTX_T *p)
+{
+    U32 u4RegBackupAddress[] =
+    {
+        (DRAMC_REG_SHURK0_DQSIEN),
+        (DRAMC_REG_SHURK0_DQSIEN+SHIFT_TO_CHB_ADDR),
+
+        (DDRPHY_B0_DQ0),
+        (DDRPHY_B0_DQ0+SHIFT_TO_CHB_ADDR),
+    };
+    U32 read_value;
+    U8 backup_broadcast;
+
+    backup_broadcast = GetDramcBroadcast();
+
+    DramcBroadcastOnOff(DRAMC_BROADCAST_OFF);
+
+    DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+    DramcBroadcastOnOff(DRAMC_BROADCAST_ON);
+
+    vIO32Write4B(DRAMC_REG_SHURK0_DQSIEN, 0xA55A00FF);
+    vIO32Write4B(DDRPHY_B0_DQ0, 0xA55A00FF);
+
+    read_value = u4IO32Read4B(DRAMC_REG_SHURK0_DQSIEN+SHIFT_TO_CHB_ADDR);
+    if (read_value != 0xA55A00FF)
+    {
+        mcSHOW_ERR_MSG(("Check Erro! Broad Cast CHA RG to CHB Fail!!\n"));
+        while(1);
+    }
+
+    read_value = u4IO32Read4B(DDRPHY_B0_DQ0+SHIFT_TO_CHB_ADDR);
+    if (read_value != 0xA55A00FF)
+    {
+        mcSHOW_ERR_MSG(("Check Erro! Broad Cast CHA RG to CHB Fail!!\n"));
+        while(1);
+    }
+
+    DramcBroadcastOnOff(DRAMC_BROADCAST_OFF);
+
+    DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+    DramcBroadcastOnOff(backup_broadcast);
+}
+#endif
+
+U8 u1TestLLL=0;
+
+#if ENABLE_SLT
+#define SLT_MEM_TEST_LOOP       10
+
+static void do_dram_test_after_k(DRAMC_CTX_T *p)
+{
+    U8 loop = 0;
+
+    while (loop < SLT_MEM_TEST_LOOP) {
+        mcSHOW_DBG_MSG(("\n[SLT][TA2_TEST] #%d\n", loop + 1));
+        TA2_Test_Run_Time_HW(p);
+
+        mcSHOW_DBG_MSG(("\n[SLT][MEM_TEST] #%d\n", loop + 1));
+        vDramCPUReadWriteTestAfterCalibration(p);
+
+        loop++;
+    }
+}
+#endif
+
+int Init_DRAM(DRAM_DRAM_TYPE_T dram_type, DRAM_CBT_MODE_EXTERN_T dram_cbt_mode_extern, DRAM_INFO_BY_MRR_T *DramInfo, U8 get_mdl_used)
+{
+    #if !SW_CHANGE_FOR_SIMULATION
+
+    DRAMC_CTX_T * p;
+
+#ifdef DDR_INIT_TIME_PROFILING
+    U32 CPU_Cycle;
+    TimeProfileBegin();
+#endif
+
+    if(u1IsLP4Family(dram_type))
+    {
+        psCurrDramCtx = &DramCtx_LPDDR4;
+    }
+    else
+    {
+#if (!__ETT__ && ENABLE_LP3_SW==0)
+#if (FOR_DV_SIMULATION_USED==0 && SW_CHANGE_FOR_SIMULATION==0)
+// Preloader which does not support LP3
+// scy: reduce code size by removing unused LPDDR3 structure
+	mcSHOW_DBG_MSG(("[Init_DRAM] LPDDR3 not supported\n"));
+	ASSERT(0);
+#endif
+#else
+        psCurrDramCtx = &DramCtx_LPDDR3;
+#endif
+    }
+
+#if defined(DDR_INIT_TIME_PROFILING) || (__ETT__ && SUPPORT_SAVE_TIME_FOR_CALIBRATION)
+    if (gtime_profiling_flag == 0)
+    {
+        memcpy(&gTimeProfilingDramCtx, psCurrDramCtx, sizeof(DRAMC_CTX_T));
+        gtime_profiling_flag = 1;
+    }
+
+    p = &gTimeProfilingDramCtx;
+    gfirst_init_flag = 0;
+
+    if(u1IsLP4Family(p->dram_type))
+        DramcConfInfraReset(p);
+#else
+    p = psCurrDramCtx;
+#endif
+
+    Set_MDL_Used_Flag(get_mdl_used);
+
+    #if 0//__ETT__
+        if(u1IsLP4Family(p->dram_type))        //ETT, LPDDR4 and 4x
+        {
+            p->dram_type = LP4_DRAM_TYPE_SELECT;
+            p->dram_cbt_mode[RANK_0] = LP4_CBT_MODE;
+            p->dram_cbt_mode[RANK_1] = LP4_CBT_MODE;
+        }
+        else  //Preloader & ETTLPDDR3
+    #endif
+        {
+            p->dram_type = dram_type;
+
+            /* Convert DRAM_CBT_MODE_EXTERN_T to DRAM_CBT_MODE_T */
+            switch ((int)dram_cbt_mode_extern)
+            {
+                case CBT_R0_R1_NORMAL:
+                    p->dram_cbt_mode[RANK_0] = CBT_NORMAL_MODE;
+                    p->dram_cbt_mode[RANK_1] = CBT_NORMAL_MODE;
+                    break;
+                case CBT_R0_R1_BYTE:
+                    p->dram_cbt_mode[RANK_0] = CBT_BYTE_MODE1;
+                    p->dram_cbt_mode[RANK_1] = CBT_BYTE_MODE1;
+                    break;
+                case CBT_R0_NORMAL_R1_BYTE:
+                    p->dram_cbt_mode[RANK_0] = CBT_NORMAL_MODE;
+                    p->dram_cbt_mode[RANK_1] = CBT_BYTE_MODE1;
+                    break;
+                case CBT_R0_BYTE_R1_NORMAL:
+                    p->dram_cbt_mode[RANK_0] = CBT_BYTE_MODE1;
+                    p->dram_cbt_mode[RANK_1] = CBT_NORMAL_MODE;
+                    break;
+                default:
+                    mcSHOW_ERR_MSG(("Error!"));
+                    break;
+            }
+
+            mcSHOW_DBG_MSG2(("dram_cbt_mode_extern: %d\n"
+                              "dram_cbt_mode [RK0]: %d, [RK1]: %d\n",
+                              (int)dram_cbt_mode_extern, p->dram_cbt_mode[RANK_0], p->dram_cbt_mode[RANK_1]));
+        }
+
+        if(u1IsLP4Family(p->dram_type))
+        {
+            DramcBroadcastOnOff(DRAMC_BROADCAST_ON);   //LP4 broadcast on
+        }
+        else
+        {
+            DramcBroadcastOnOff(DRAMC_BROADCAST_OFF);  //LP3 broadcast off
+        }
+
+        if (gfirst_init_flag == 0)
+        {
+            MPLLInit();
+            Global_Option_Init(p);
+            gfirst_init_flag = 1;
+        }
+		Global_Option_Init2(p);	// setting according to emi_settings
+
+#ifdef FIRST_BRING_UP
+        Test_Broadcast_Feature(p);
+#endif
+
+#if (FOR_DV_SIMULATION_USED==0 && SW_CHANGE_FOR_SIMULATION==0)
+        {
+            U8 backup_broadcast;
+            backup_broadcast = GetDramcBroadcast();
+            EMI_Init(p);
+            DramcBroadcastOnOff(backup_broadcast);
+        }
+#endif
+
+
+      mcSHOW_DBG_MSG(("\n\n[Bianco] ETT version 0.0.0.1\n dram_type %d, R0 cbt_mode %d, R1 cbt_mode %d VENDOR=%d\n\n", p->dram_type, p->dram_cbt_mode[RANK_0], p->dram_cbt_mode[RANK_1], p->vendor_id));
+
+      vDramcInit_PreSettings(p);
+
+      // DramC & PHY init for all channels
+      #if DUAL_FREQ_K
+      SPM_Pinmux_Setting(p);
+      if(u1IsLP4Family(p->dram_type))
+          p->freq_sel = gFreqTbl[DRAM_DFS_SHUFFLE_1].freq_sel;
+      #endif
+
+      //===  First frequency ======
+      DDRPhyFreqSel(p, p->freq_sel);
+      vSetVcoreByFreq(p);
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+      DramcSave_Time_For_Cal_Init(p);
+#endif
+#ifndef LOOPBACK_TEST
+#if EMI_LPBK_DRAM_USED //saint remove sw imp cal
+      if (p->dram_type == TYPE_LPDDR4)
+      {
+          DramcSwImpedanceCal(p,1, 1);  //within term
+      }
+      else if (p->dram_type == TYPE_LPDDR4X)
+      {
+          DramcSwImpedanceCal(p,1, 0);  //without term
+          DramcSwImpedanceCal(p,1, 1);  //within term
+      }
+      else
+      {
+        //TYPE_LPDDR4P, TYPE_LPDDR3
+          DramcSwImpedanceCal(p,1, 0);  //without term
+      }
+
+      //update ODTP/ODTN of term to unterm
+      DramcUpdateImpedanceTerm2UnTerm(p);
+#endif
+#endif
+#ifdef DDR_INIT_TIME_PROFILING
+      CPU_Cycle=TimeProfileEnd();
+      mcSHOW_TIME_MSG(("(0)Pre_Init + SwImdepance takes %d ms\n\r", CPU_Cycle/1000));
+#endif
+
+#ifdef DUMP_INIT_RG_LOG_TO_DE
+        gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag = 1;
+#endif
+
+      DFSInitForCalibration(p);
+
+#if defined(SLT)
+      O1Path_Test(p);
+#endif
+
+#ifdef TEST_MODE_MRS
+    if(global_which_test  == 0)
+      TestModeTestMenu();
+#endif
+
+#ifdef ENABLE_POST_PACKAGE_REPAIR
+#ifdef SKH_POST_PACKAGE_REPAIR_LP3 //LP3
+      PostPackageRepair();
+#endif
+#endif
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        if (p->femmc_Ready==1)
+        {
+            p->support_rank_num = p->pSavetimeData->support_rank_num;
+        }
+        else
+#endif
+        {
+#if ENABLE_RANK_NUMBER_AUTO_DETECTION  // only need to do this when DUAL_RANK_ENABLE is 1
+            if (Get_MDL_Used_Flag()==GET_MDL_USED)
+            {
+                DramRankNumberDetection(p);
+                DFSInitForCalibration(p);  // Restore setting after rank dection (especially DQ= DQS+16)
+            }
+#endif
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+            p->pSavetimeData->support_rank_num = p->support_rank_num;
+#endif
+        }
+
+        #if (FOR_DV_SIMULATION_USED==0 && SW_CHANGE_FOR_SIMULATION==0)
+        U8 backup_broadcast;
+        backup_broadcast = GetDramcBroadcast();
+        EMI_Init2();
+        DramcBroadcastOnOff(backup_broadcast);
+        #endif
+
+#if defined(SLT) && (EMI_LPBK_DRAM_USED == 0)
+        EMI_LPBK_memory_test(p);
+#endif
+
+        if (Get_MDL_Used_Flag()==GET_MDL_USED)
+        {
+            // only K CHA to save time
+            vSetPHY2ChannelMapping(p, u1ChannelSet[0]);
+            vCalibration_Flow_For_MDL(p); // currently for LP4
+            GetDramInforAfterCalByMRR(p, DramInfo);
+            return 0;
+        }
+        else //NORMAL_USED
+        {
+            vDramCalibrationAllChannel(p);
+            GetDramInforAfterCalByMRR(p, DramInfo);
+            vDramcACTimingOptimize(p);
+        }
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        DramcSave_Time_For_Cal_End(p);
+#endif
+
+#if (ENABLE_SLT == 1)
+    vApplyConfigAfterCalibration(p);
+    do_dram_test_after_k(p);
+
+    /* cal 2400 */
+    DDRPhyFreqSel(p, LP4_MIDDLE_FREQSEL);
+    vSetVcoreByFreq(p);
+    DFSInitForCalibration(p);
+    vDramCalibrationAllChannel(p);
+    vDramcACTimingOptimize(p);
+#endif
+
+#if DUAL_FREQ_K
+    if(u1IsLP4Family(p->dram_type))
+    {
+    #ifdef MTK_FIXDDR1600_SUPPORT
+        DramcSaveToShuffleReg(p, DRAM_DFS_SHUFFLE_1, DRAM_DFS_SHUFFLE_2);
+        DramcSaveToShuffleReg(p, DRAM_DFS_SHUFFLE_1, DRAM_DFS_SHUFFLE_3);
+    #else
+        DramcSaveToShuffleReg(p, DRAM_DFS_SHUFFLE_1, DRAM_DFS_SHUFFLE_3); //Darren NOTE: Please take care of gFreqTbl table when you update SHUFFLE_X
+
+    //===  Second frequency ======
+        DDRPhyFreqSel(p, gFreqTbl[DRAM_DFS_SHUFFLE_2].freq_sel);
+        vSetVcoreByFreq(p);
+        #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        DramcSave_Time_For_Cal_Init(p);
+        #endif
+        DFSInitForCalibration(p);
+        vDramCalibrationAllChannel(p);
+        vDramcACTimingOptimize(p);
+        DramcSaveToShuffleReg(p, DRAM_DFS_SHUFFLE_1, DRAM_DFS_SHUFFLE_2); //Darren NOTE: Please take care of gFreqTbl table when you update SHUFFLE_X
+        #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        DramcSave_Time_For_Cal_End(p);
+        #endif
+
+        //===  Third frequency ======
+        DDRPhyFreqSel(p, gFreqTbl[DRAM_DFS_SHUFFLE_1].freq_sel);
+        vSetVcoreByFreq(p);
+        #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        DramcSave_Time_For_Cal_Init(p);
+        #endif
+        DFSInitForCalibration(p);
+        vDramCalibrationAllChannel(p);
+        vDramcACTimingOptimize(p);
+        #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        DramcSave_Time_For_Cal_End(p);
+        #endif
+    #endif
+    }
+    else
+    {
+    #if 0
+        DramcSaveToShuffleReg(p, DRAM_DFS_SHUFFLE_1, DRAM_DFS_SHUFFLE_3);
+        DramcSaveToShuffleReg(p, DRAM_DFS_SHUFFLE_1, DRAM_DFS_SHUFFLE_2);
+    #else
+        DramcSaveToShuffleReg(p, DRAM_DFS_SHUFFLE_1, DRAM_DFS_SHUFFLE_3);   //save 1333 0.74V shuffle_2
+
+        DDRPhyFreqSel(p, LP3_DDR1600);
+        vSetVcoreByFreq(p);
+        DFSInitForCalibration(p);
+        vDramCalibrationAllChannel(p);
+        DramcSaveToShuffleReg(p, DRAM_DFS_SHUFFLE_1, DRAM_DFS_SHUFFLE_2);   //save 1333 0.74V shuffle_3
+
+        DDRPhyFreqSel(p, LP3_DDR1866);
+        vSetVcoreByFreq(p);
+        DFSInitForCalibration(p);
+        vDramCalibrationAllChannel(p);
+    #endif
+    }
+#endif
+
+#ifdef DDR_INIT_TIME_PROFILING
+    TimeProfileBegin();
+#endif
+
+    vApplyConfigAfterCalibration(p);
+
+#ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+    while (1) ;
+#endif
+
+#ifdef ENABLE_POST_PACKAGE_REPAIR //LP4
+#ifdef POST_PACKAGE_REPAIR_LP4
+    PostPackageRepair();
+#endif
+#endif
+
+#if 0//TX_OE_CALIBATION, for DMA test
+    U8 u1ChannelIdx, u1RankIdx;
+    for(u1ChannelIdx=0; u1ChannelIdx<(p->support_channel_num); u1ChannelIdx++)
+        for(u1RankIdx =0; u1RankIdx<(p->support_rank_num); u1RankIdx++)
+        {
+            vSetPHY2ChannelMapping(p, u1ChannelIdx);
+            vSetRank(p, u1RankIdx);
+            DramcTxOECalibration(p);
+        }
+
+    vSetPHY2ChannelMapping(p, CHANNEL_A);
+    vSetRank(p,RANK_0);
+
+    U32 u4err_value;
+    DramcDmaEngine((DRAMC_CTX_T *)p, 0x50000000, 0x60000000, 0xff00, 8, DMA_PREPARE_DATA_ONLY, p->support_channel_num);
+    u4err_value= DramcDmaEngine((DRAMC_CTX_T *)p, 0x50000000, 0x60000000, 0xff00, 8, DMA_CHECK_DATA_ACCESS_AND_COMPARE, p->support_channel_num);
+    mcSHOW_DBG_MSG(("DramC_TX_OE_Calibration  0x%X\n", u4err_value));
+#endif
+
+#if RUNTIME_SHMOO_RELEATED_FUNCTION && SUPPORT_SAVE_TIME_FOR_CALIBRATION
+    DramcRunTimeShmooRG_BackupRestore(p);
+#endif
+
+#if RUNTIME_SHMOO_RELEATED_FUNCTION && SUPPORT_SAVE_TIME_FOR_CALIBRATION
+    RunTime_Shmoo_update_parameters(p);
+#endif
+
+#if !LCPLL_IC_SCAN
+#if (FOR_DV_SIMULATION_USED==0 && SW_CHANGE_FOR_SIMULATION==0)
+    print_DBG_info(p);
+    Dump_EMIRegisters(p);
+#endif
+#endif
+
+#if 0
+    DramcRegDump(p);
+#endif
+
+// ETT_NO_DRAM #endif
+
+#if ETT_NO_DRAM
+    //NoDramDramcRegDump(p);
+    NoDramRegFill();
+#endif
+
+#if (DVT_TEST_DUMMY_RD_SIDEBAND_FROM_SPM && defined(DUMMY_READ_FOR_TRACKING))
+    DramcDummyReadForTrackingEnable(p);
+    mcSHOW_DBG_MSG(("DUMMY_READ_FOR_TRACKING: ON\n"));
+
+    //Disable auto refresh: set R_DMREFDIS=1
+    vAutoRefreshSwitch(p, DISABLE);
+
+    while(1)
+    {
+        mcSHOW_DBG_MSG(("\ndummy read is 1us ===\n"));
+        DVS_DMY_RD_ENTR(p);
+        mcDELAY_MS(5000);
+        mcSHOW_DBG_MSG(("\ndummy read is 4us ===\n"));
+        DVS_DMY_RD_EXIT(p);
+        mcDELAY_MS(5000);
+    }
+#endif
+
+    #if DRAMC_MODEREG_CHECK
+    DramcModeReg_Check(p);
+    #endif
+
+    #if TA2_RW_TEST_AFTER_K
+    mcSHOW_DBG_MSG(("\n[TA2_TEST]\n"));
+    TA2_Test_Run_Time_HW(p);
+    #endif
+
+    #if CPU_RW_TEST_AFTER_K
+    mcSHOW_DBG_MSG(("\n[MEM_TEST] 02: After DFS, before run time config\n"));
+    vDramCPUReadWriteTestAfterCalibration(p);
+    #endif
+
+
+    // when time profiling multi times, SW impedance tracking will fail when trakcing enable.
+    // ignor SW impedance tracking when doing time profling
+#if __ETT__
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+    if(!(u1IsLP4Family(p->dram_type) && (p->femmc_Ready==0)))
+#elif defined(DDR_INIT_TIME_PROFILING)
+    if(u2TimeProfileCnt == (DDR_INIT_TIME_PROFILING_TEST_CNT-1)) //last time of loop
+#endif
+#endif
+    {
+        mcSHOW_DBG_MSG(("\n\nSettings after calibration\n\n"));
+        DramcRunTimeConfig(p);
+    }
+
+    #if TA2_RW_TEST_AFTER_K
+    mcSHOW_DBG_MSG(("\n[TA2_TEST]\n"));
+    TA2_Test_Run_Time_HW(p);
+    #endif
+
+    #if CPU_RW_TEST_AFTER_K
+    mcSHOW_DBG_MSG(("\n[MEM_TEST] 03: After run time config\n"));
+    vDramCPUReadWriteTestAfterCalibration(p);
+    #endif
+
+#if (ENABLE_SLT == 1)
+    do_dram_test_after_k(p);
+#endif
+
+#if (__ETT__ && CPU_RW_TEST_AFTER_K)
+    /* 0x46000000 is LK base addr */
+//while(1)
+{
+    int s4value;
+    //if ((s4value = complex_mem_test (0x46000000, 0x2000)) == 0)
+    if ((s4value = complex_mem_test (0x40024000, 0x20000)) == 0)
+    {
+        mcSHOW_DBG_MSG(("1st complex R/W mem test pass\n"));
+    }
+    else
+    {
+        mcSHOW_DBG_MSG(("1st complex R/W mem test fail :-%d\n", -s4value));
+#if defined(SLT)
+        while(1);
+#endif
+    }
+}
+#endif
+
+#if MRW_CHECK_ONLY
+    vPrintFinalModeRegisterSetting(p);
+#endif
+
+#ifdef DDR_INIT_TIME_PROFILING
+    CPU_Cycle=TimeProfileEnd();
+    mcSHOW_TIME_MSG(("(5) After calibration takes %d ms\n\r", CPU_Cycle/1000));
+#endif  // end of DDR_INIT_TIME_PROFILING
+
+#if defined(SLT)
+    SLT_Test_DFS_Freq_Meter_Memory_Test(p);
+#endif
+
+/* cc add. For FASTK, psCurrDramCtx and p are different  Sync data back in case mismatch */
+#if defined(DDR_INIT_TIME_PROFILING) || (__ETT__ && SUPPORT_SAVE_TIME_FOR_CALIBRATION)
+    if (gtime_profiling_flag == 1)
+    {
+        memcpy(psCurrDramCtx, p, sizeof(DRAMC_CTX_T));
+    }
+#endif
+
+#endif//SW_CHANGE_FOR_SIMULATION
+    return 0;
+}
+
+
+#if (FOR_DV_SIMULATION_USED!=0)
+void DPI_main(void)
+{
+    DRAMC_CTX_T DramConfig;
+
+    DramConfig.channel = CHANNEL_A;
+    DramConfig.support_rank_num = RANK_DUAL;
+    // DramRank
+    DramConfig.rank = RANK_0;
+    // DRAM type
+    DramConfig.dram_type = TYPE_LPDDR3;
+    // DRAM Fast switch point type, only for LP4, useless in LP3
+    DramConfig.dram_fsp = FSP_0;
+    // IC and DRAM read DBI
+    DramConfig.DBI_R_onoff[FSP_0] = DBI_OFF;             // only for LP4, uesless in LP3
+    DramConfig.DBI_R_onoff[FSP_1] = DBI_ON;              // only for LP4, uesless in LP3
+    // IC and DRAM write DBI
+    DramConfig.DBI_W_onoff[FSP_0] = DBI_OFF;             // only for LP4, uesless in LP3
+    DramConfig.DBI_W_onoff[FSP_1] = DBI_ON;              // only for LP4, uesless in LP3
+    // bus width
+    DramConfig.data_width = DATA_WIDTH_32BIT;
+    // DRAMC internal test engine-2 parameters in calibration
+    DramConfig.test2_1 = DEFAULT_TEST2_1_CAL;
+    DramConfig.test2_2 = DEFAULT_TEST2_2_CAL;
+    // DRAMC test pattern in calibration
+    DramConfig.test_pattern = TEST_XTALK_PATTERN;
+    // DRAMC operation clock frequency in MHz
+    DramConfig.frequency = 800;
+    // Switch to ENABLE or DISABLE low frequency write and high frequency read
+    DramConfig.u2DelayCellTimex100 = 0;
+
+    DramConfig.enable_rx_scan_vref =DISABLE_VREF_SCAN;
+    DramConfig.enable_tx_scan_vref =DISABLE_VREF_SCAN;
+    //DramConfig.dynamicODT = DISABLE;
+
+    printf("main functino start!\n");
+
+    Init_DRAM(DramConfig.dram_type, CBT_R0_R1_NORMAL, NULL, NORMAL_USED);
+}
+
+#define DV_SIMULATION_INIT_C    1
+#define DV_SIMULATION_BEFORE_K  1
+#define DV_SIMULATION_MIOCKJMETER  0
+#define DV_SIMULATION_SW_IMPED 0
+#define DV_SIMULATION_LP4_ZQ 0
+#define DV_SIMULATION_CA_TRAINING 0
+#define DV_SIMULATION_WRITE_LEVELING  0
+#define DV_SIMULATION_GATING 0
+#define DV_SIMULATION_DATLAT 0
+#define DV_SIMULATION_RX_PERBIT    0
+#define DV_SIMULATION_TX_PERBIT    0 // Please enable with write leveling
+#define DV_SIMULATION_AFTER_K   1
+#define DV_SIMULATION_DBI_ON   0
+#define DV_SIMULATION_RUNTIME_CONFIG 0
+#define DV_SIMULATION_RUN_TIME_MRW 0
+U8 gu1BroadcastIsLP4 = TRUE;
+
+#if ENABLE_LP3_SW
+void DPI_SW_main_LP3(DRAMC_CTX_T *DramConfig)
+{
+    int ii;
+
+    U8 gu1BroadcastIsLP4 = FALSE;
+    DramConfig->channel = CHANNEL_A;
+    DramConfig->support_rank_num = RANK_DUAL;
+    // DramRank
+    DramConfig->rank = RANK_0;
+    DramConfig->freq_sel = LP3_DDR1066;
+    // DRAM type
+    DramConfig->dram_type = TYPE_LPDDR3;
+    // DRAM Fast switch point type, only for LP4, useless in LP3
+    DramConfig->dram_fsp = FSP_0;
+    // DRAM CBT mode, only for LP4, useless in LP3
+    DramConfig->dram_cbt_mode[RANK_0] = CBT_NORMAL_MODE;
+    DramConfig->dram_cbt_mode[RANK_1] = CBT_NORMAL_MODE;
+    // IC and DRAM read DBI
+    DramConfig->DBI_R_onoff[FSP_0] = DBI_OFF;   // only for LP4, uesless in LP3
+    DramConfig->DBI_R_onoff[FSP_1] = DBI_OFF;   // only for LP4, uesless in LP3
+    // IC and DRAM write DBI
+    DramConfig->DBI_W_onoff[FSP_0] = DBI_OFF;   // only for LP4, uesless in LP3
+    DramConfig->DBI_W_onoff[FSP_1] = DBI_OFF;   // only for LP4, uesless in LP3
+    // bus width
+    DramConfig->data_width = DATA_WIDTH_32BIT;
+    // DRAMC internal test engine-2 parameters in calibration
+    DramConfig->test2_1 = DEFAULT_TEST2_1_CAL;
+    DramConfig->test2_2 = DEFAULT_TEST2_2_CAL;
+    // DRAMC test pattern in calibration
+    DramConfig->test_pattern = TEST_XTALK_PATTERN;
+    // DRAMC operation clock frequency in MHz
+    DramConfig->frequency = 533;
+    // Switch to ENABLE or DISABLE low frequency write and high frequency read
+    DramConfig->u2DelayCellTimex100 = 0;
+
+    DramConfig->enable_rx_scan_vref =DISABLE_VREF_SCAN;
+    DramConfig->enable_tx_scan_vref =DISABLE_VREF_SCAN;
+    //Cervino and Merlot have DLP3, need to give it initial value
+    DramConfig->bDLP3 = 0;
+
+    DramcBroadcastOnOff(DRAMC_BROADCAST_OFF);  //LP3 broadcast off
+
+    Global_Option_Init(DramConfig);
+    Global_Option_Init2(DramConfig);
+
+    vDramcInit_PreSettings(DramConfig);
+
+    DDRPhyFreqSel(DramConfig, DramConfig->freq_sel);
+
+    vSetPHY2ChannelMapping(DramConfig, DramConfig->channel);
+
+    #if DV_SIMULATION_SW_IMPED
+    //TYPE_LPDDR4P, TYPE_LPDDR3
+    DramcSwImpedanceCal(DramConfig, 1, 0);  //without term
+    //update ODTP/ODTN of term to unterm
+    DramcUpdateImpedanceTerm2UnTerm(DramConfig);
+    #endif
+
+
+#if DV_SIMULATION_INIT_C
+    DramcInit(DramConfig);
+    #if DV_SIMULATION_MIOCKJMETER
+    #ifdef ENABLE_MIOCK_JMETER
+    DramcMiockJmeter(DramConfig);
+    #endif
+    #endif
+#endif
+
+#if WRITE_LEVELING_MOVE_DQS_INSTEAD_OF_CLK
+    memset(DramConfig->arfgWriteLevelingInitShif, FALSE, sizeof(DramConfig->arfgWriteLevelingInitShif));
+    //>fgWriteLevelingInitShif= FALSE;
+#endif
+#if TX_PERBIT_INIT_FLOW_CONTROL
+    memset(DramConfig->fgTXPerbifInit, FALSE, sizeof(DramConfig->fgTXPerbifInit));
+#endif
+
+#if DV_SIMULATION_BEFORE_K
+    vApplyConfigBeforeCalibration(DramConfig);
+    //vMR2InitForSimulationTest(DramConfig);
+#endif
+
+    vAutoRefreshSwitch(DramConfig, DISABLE);
+
+#if DV_SIMULATION_CA_TRAINING
+    vSetRank(DramConfig, RANK_0);
+    CATrainingLP3(DramConfig);
+#endif
+
+#if DV_SIMULATION_GATING
+    DramcRxdqsGatingPreProcess(DramConfig);
+#endif
+
+    for(ii=RANK_0; ii<RANK_MAX; ii++)
+    {
+        vSetRank(DramConfig, ii);
+
+        vAutoRefreshSwitch(DramConfig, DISABLE);
+
+        #if DV_SIMULATION_WRITE_LEVELING
+        if(ii==RANK_0)
+            DramcWriteLeveling(DramConfig);
+        #endif
+
+        vAutoRefreshSwitch(DramConfig, ENABLE);
+
+
+        #if DV_SIMULATION_GATING
+            DramcRxdqsGatingCal(DramConfig);
+        #endif
+
+        #if DV_SIMULATION_DATLAT
+            // RX Datlat calibration of single rank
+            DramcRxdatlatCal(DramConfig);
+        #endif
+
+        #if DV_SIMULATION_RX_PERBIT
+            DramcRxWindowPerbitCal(DramConfig, 1);
+        #endif
+
+        #if DV_SIMULATION_TX_PERBIT
+            DramcTxWindowPerbitCal(DramConfig, TX_DQ_DQS_MOVE_DQ_DQM, DISABLE_VREF_SCAN);
+        #endif
+    }
+
+    vSetRank(DramConfig, RANK_0);
+#if DV_SIMULATION_GATING
+    DramcRxdqsGatingPostProcess(DramConfig);
+#endif
+
+#if DV_SIMULATION_DATLAT
+    DramcDualRankRxdatlatCal(DramConfig);
+#endif
+
+#if DV_SIMULATION_AFTER_K
+    vApplyConfigAfterCalibration(DramConfig);
+#endif
+
+}
+#endif
+
+void DPI_SW_main_LP4(DRAMC_CTX_T *DramConfig)
+{
+    int ii;
+    DRAM_STATUS_T VrefStatus;
+
+    U8 gu1BroadcastIsLP4 = TRUE;
+    DramConfig->support_channel_num = CHANNEL_SINGLE;
+    DramConfig->channel = CHANNEL_A;
+    DramConfig->support_rank_num = RANK_DUAL;
+    // DramRank
+    DramConfig->rank = RANK_0;
+    DramConfig->freq_sel = LP4_DDR2400;
+    DramConfig->shu_type = DRAM_DFS_SHUFFLE_1;
+    // DRAM type
+    DramConfig->dram_type = TYPE_LPDDR4X;
+    // DRAM Fast switch point type, only for LP4, useless in LP3
+    DramConfig->dram_fsp = FSP_0;
+    // DRAM CBT mode, only for LP4, useless in LP3
+    DramConfig->dram_cbt_mode[RANK_0] = CBT_NORMAL_MODE;
+    //DramConfig->dram_cbt_mode[RANK_1] = CBT_BYTE_MODE1;
+    DramConfig->dram_cbt_mode[RANK_1] = CBT_NORMAL_MODE;
+    // IC and DRAM read DBI
+    DramConfig->DBI_R_onoff[FSP_0] = DBI_OFF;        // only for LP4, uesless in LP3
+    DramConfig->DBI_R_onoff[FSP_1] = DBI_OFF;         // only for LP4, uesless in LP3
+    #if ENABLE_READ_DBI
+    DramConfig->DBI_R_onoff[FSP_1] = DBI_ON;         // only for LP4, uesless in LP3
+    #else
+    DramConfig->DBI_R_onoff[FSP_1] = DBI_OFF;        // only for LP4, uesless in LP3
+    #endif
+    // IC and DRAM write DBI
+    DramConfig->DBI_W_onoff[FSP_0] = DBI_OFF;        // only for LP4, uesless in LP3
+    DramConfig->DBI_W_onoff[FSP_1] = DBI_OFF;         // only for LP4, uesless in LP3
+    #if ENABLE_WRITE_DBI
+    DramConfig->DBI_W_onoff[FSP_1] = DBI_ON;         // only for LP4, uesless in LP3
+    #else
+    DramConfig->DBI_W_onoff[FSP_1] = DBI_OFF;         // only for LP4, uesless in LP3
+    #endif
+    // bus width
+    DramConfig->data_width = DATA_WIDTH_16BIT;
+    // DRAMC internal test engine-2 parameters in calibration
+    DramConfig->test2_1 = DEFAULT_TEST2_1_CAL;
+    DramConfig->test2_2 = DEFAULT_TEST2_2_CAL;
+    // DRAMC test pattern in calibration
+    DramConfig->test_pattern = TEST_XTALK_PATTERN;
+    // DRAMC operation clock frequency in MHz
+    DramConfig->frequency = 1200;
+    // u2DelayCellTimex100
+    DramConfig->u2DelayCellTimex100 = 0;
+    DramConfig->vendor_id = 0x1;
+    DramConfig->density = 0;
+    //DramConfig->ranksize = {0,0};
+
+    DramConfig->enable_cbt_scan_vref = DISABLE_VREF_SCAN;
+    DramConfig->enable_rx_scan_vref = DISABLE_VREF_SCAN;
+    DramConfig->enable_tx_scan_vref = DISABLE_VREF_SCAN;
+
+    DramcBroadcastOnOff(DRAMC_BROADCAST_ON); //LP4 broadcast on
+
+    Global_Option_Init(DramConfig);
+    Global_Option_Init2(DramConfig);
+
+    vDramcInit_PreSettings(DramConfig);
+
+    DDRPhyFreqSel(DramConfig, DramConfig->freq_sel);
+
+    vSetPHY2ChannelMapping(DramConfig, DramConfig->channel);
+
+#if DV_SIMULATION_SW_IMPED
+    if (DramConfig->dram_type == TYPE_LPDDR4X)
+    {
+        DramcSwImpedanceCal(DramConfig,1, 0);  //without term
+    }
+    DramcSwImpedanceCal(DramConfig,1, 1);  //within term
+    //update ODTP/ODTN of term to unterm
+    DramcUpdateImpedanceTerm2UnTerm(DramConfig);
+#endif
+
+
+#if DV_SIMULATION_INIT_C
+    DramcInit(DramConfig);
+    vSetPHY2ChannelMapping(DramConfig, u1ChannelSet[0]);
+    #if DV_SIMULATION_MIOCKJMETER
+    #ifdef ENABLE_MIOCK_JMETER
+    DramcMiockJmeter(DramConfig);
+    #endif
+    #endif
+    #if ENABLE_RX_TRACKING_LP4
+    DramcRxInputDelayTrackingInit_byFreq(DramConfig);
+    DramcRxInputDelayTrackingInit_Common(DramConfig);
+    DramcRxInputDelayTrackingHW(DramConfig);
+    #endif
+#endif
+
+
+#if WRITE_LEVELING_MOVE_DQS_INSTEAD_OF_CLK
+    memset(DramConfig->arfgWriteLevelingInitShif, FALSE, sizeof(DramConfig->arfgWriteLevelingInitShif));
+    //>fgWriteLevelingInitShif= FALSE;
+#endif
+#if TX_PERBIT_INIT_FLOW_CONTROL
+    memset(DramConfig->fgTXPerbifInit, FALSE, sizeof(DramConfig->fgTXPerbifInit));
+#endif
+
+#if DV_SIMULATION_BEFORE_K
+    vApplyConfigBeforeCalibration(DramConfig);
+    //vMR2InitForSimulationTest(DramConfig);
+#endif
+
+#if DV_SIMULATION_GATING
+DramcRxdqsGatingPreProcess(DramConfig);
+#endif
+
+#if 0//DV_SIMULATION_LP4_ZQ
+    DramcZQCalibration(DramConfig);
+#endif
+
+#if 0//DV_SIMULATION_CA_TRAINING
+    vSetRank(DramConfig, RANK_0);
+    CmdBusTrainingLP4(DramConfig);
+#endif
+
+    vAutoRefreshSwitch(DramConfig, DISABLE);
+
+    #if DV_SIMULATION_CA_TRAINING
+        for(ii=RANK_0; ii<RANK_MAX; ii++)
+        {
+            vSetRank(DramConfig, ii);
+            CmdBusTrainingLP4(DramConfig);
+
+
+        }
+        vSetRank(DramConfig, RANK_0);
+
+        #if DUAL_FREQ_K
+        No_Parking_On_CLRPLL(DramConfig);
+        #endif
+    #endif
+
+    for(ii=RANK_0; ii<RANK_MAX; ii++)
+    {
+        vSetRank(DramConfig, ii);
+
+        #if DV_SIMULATION_WRITE_LEVELING
+        //if (ii==RANK_1)
+        DramcWriteLeveling(DramConfig);
+        #endif
+
+        vAutoRefreshSwitch(DramConfig, ENABLE);
+
+        #if DV_SIMULATION_GATING
+        // Gating calibration of single rank
+        DramcRxdqsGatingCal(DramConfig);
+        #endif
+
+        #if DV_SIMULATION_RX_PERBIT
+        DramcRxWindowPerbitCal(DramConfig, 0);
+        #endif
+
+        #if DV_SIMULATION_TX_PERBIT
+        DramcTxWindowPerbitCal(DramConfig, TX_DQ_DQS_MOVE_DQ_DQM, DISABLE_VREF_SCAN);
+        VrefStatus = DramcTxWindowPerbitCal((DRAMC_CTX_T *) DramConfig, TX_DQ_DQS_MOVE_DQ_ONLY,DramConfig->enable_tx_scan_vref);
+        #endif
+
+        #if DV_SIMULATION_DATLAT
+        // RX Datlat calibration of single rank
+        DramcRxdatlatCal(DramConfig);
+        #endif
+
+        #if DV_SIMULATION_RX_PERBIT
+        DramcRxWindowPerbitCal(DramConfig, 1);
+        #endif
+
+        #if 0//DV_SIMULATION_TX_PERBIT
+        DramcTxOECalibration(DramConfig);
+        #endif
+
+        #if DV_SIMULATION_DBI_ON
+            #if ENABLE_READ_DBI
+            //Read DBI ON
+            SetDramModeRegForReadDBIOnOff(DramConfig, DramConfig->DBI_R_onoff[DramConfig->dram_fsp]);
+            #endif
+
+            #if ENABLE_WRITE_DBI
+            //Write DBI ON
+            DramcWriteMinus1MCKForWriteDBI(DramConfig, -8); //Tx DQ/DQM -1 MCK for write DBI ON
+            SetDramModeRegForWriteDBIOnOff(DramConfig, DramConfig->DBI_W_onoff[DramConfig->dram_fsp]);
+            #endif
+        #endif
+    }
+
+    vSetRank(DramConfig, RANK_0);
+#if DV_SIMULATION_GATING
+    DramcRxdqsGatingPostProcess(DramConfig);
+#endif
+
+#if DV_SIMULATION_DATLAT
+    DramcDualRankRxdatlatCal(DramConfig);
+#endif
+
+#if DV_SIMULATION_AFTER_K
+    vApplyConfigAfterCalibration(DramConfig);
+#endif
+
+    #if DV_SIMULATION_DBI_ON
+        #if ENABLE_READ_DBI
+        DramcReadDBIOnOff(DramConfig, DramConfig->DBI_R_onoff[DramConfig->dram_fsp]);
+        #endif
+
+        #if ENABLE_WRITE_DBI
+        DramcWriteDBIOnOff(DramConfig, DramConfig->DBI_W_onoff[DramConfig->dram_fsp]);
+        #endif
+    #endif
+
+#if DV_SIMULATION_RUN_TIME_MRW
+    enter_pasr_dpd_config(0, 0xFF);
+#endif
+
+#if DV_SIMULATION_RUNTIME_CONFIG
+    DramcRunTimeConfig(DramConfig);
+#endif
+
+}
+
+#endif
+
+