[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/bsp/dramk_2731/dramc_pi_calibration_api.c b/src/bsp/dramk_2731/dramc_pi_calibration_api.c
new file mode 100755
index 0000000..a6df28f
--- /dev/null
+++ b/src/bsp/dramk_2731/dramc_pi_calibration_api.c
@@ -0,0 +1,17629 @@
+/*----------------------------------------------------------------------------*
+ * 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.                        *
+ *---------------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------------
+ *
+ * $Author: jc.wu $
+ * $Date: 2012/6/5 $
+ * $RCSfile: pi_calibration_api.c,v $
+ * $Revision: #5 $
+ *
+ *---------------------------------------------------------------------------*/
+
+/** @file pi_calibration_api.c
+ *  Basic DRAMC calibration API implementation
+ */
+
+//-----------------------------------------------------------------------------
+// Include files
+//-----------------------------------------------------------------------------
+//#include "..\Common\pd_common.h"
+#include "dramc_common.h"
+#include "x_hal_io.h"
+#include "dramc_pi_api.h"
+//#include "DramC_reg.h"
+//#include "System_reg.h"
+
+#if 1//REG_ACCESS_PORTING_DGB
+U8 RegLogEnable=0;
+#endif
+
+#if REG_SHUFFLE_REG_CHECK
+U8 ShuffleRegCheck =0;
+#endif
+
+#define CATRAINING_NUM_LP3      10
+#define CATRAINING_NUM_LP4      6
+#define CATRAINING_NUM          10
+#define LP3_DIE_NUM_MAX         2
+
+#define MAX_CA_PI_DELAY         95  //63+32
+#define MAX_CS_PI_DELAY         63
+#define MAX_CLK_PI_DELAY        31
+
+#define PASS_RANGE_NA   0x7fff
+#define CATRAINING_PASS_RANGE_NA 0x7f
+
+
+#if (SW_CHANGE_FOR_SIMULATION ||FOR_DV_SIMULATION_USED)
+#define RX_VREF_RANGE_BEGIN       0
+#define RX_VREF_RANGE_END          2
+#define RX_VREF_RANGE_STEP         2
+#else
+#define RX_VREF_RANGE_BEGIN_ODT_OFF     16
+#define RX_VREF_RANGE_BEGIN_ODT_ON      6
+#define RX_VREF_RANGE_END          31   //bit5 useless (Justin)   //field is 6 bit, but can only use 0~31
+#define RX_VREF_RANGE_STEP         1
+#endif
+
+//-----------------------------------------------------------------------------
+// Global variables
+//-----------------------------------------------------------------------------
+static U8 fgwrlevel_done = 0;
+
+#if defined(RELEASE)
+U8 gEye_Scan_color_flag = 0;
+U8 gCBT_EYE_Scan_flag = 0;
+U8 gCBT_EYE_Scan_only_higheset_freq_flag = 1;
+U8 gRX_EYE_Scan_flag = 0;
+U8 gRX_EYE_Scan_only_higheset_freq_flag = 1;
+U8 gTX_EYE_Scan_flag = 1;
+U8 gTX_EYE_Scan_only_higheset_freq_flag = 1;
+#else
+U8 gEye_Scan_color_flag = 1;
+U8 gCBT_EYE_Scan_flag = 0;
+U8 gCBT_EYE_Scan_only_higheset_freq_flag = 1;
+U8 gRX_EYE_Scan_flag = 0;
+U8 gRX_EYE_Scan_only_higheset_freq_flag = 1;
+U8 gTX_EYE_Scan_flag = 0;
+U8 gTX_EYE_Scan_only_higheset_freq_flag = 1;
+#endif
+
+#ifdef FOR_HQA_REPORT_USED
+U8 gHQALog_flag = 0;
+#endif
+
+U8 *u1ChannelSet;
+const U8 u1LP4Channel[] =
+{
+    CHANNEL_B
+}; //0:CHA, 1:CHB, 2:CHC, 3:CHD
+#if ENABLE_LP3_SW
+const U8 u1LP3Channel[] =
+{
+    CHANNEL_A
+}; //0:CHA, 1:CHB, 2:CHC, 3:CHD
+#endif
+
+U16 gu2MR0_Value[RANK_MAX] = {0xffff, 0xffff};
+U8 u1MR01Value[FSP_MAX];
+U8 u1MR02Value[FSP_MAX];
+U8 u1MR03Value[FSP_MAX];
+U8 u1MR13Value;
+
+U8 u1MR12Value[CHANNEL_NUM][RANK_MAX][FSP_MAX];
+U8 u1MR14Value[CHANNEL_NUM][RANK_MAX][FSP_MAX];
+
+#if MRW_CHECK_ONLY
+U16 u2MRRecord[CHANNEL_NUM][RANK_MAX][FSP_MAX][MR_NUM];
+#endif
+
+U8 gCBT_VREF_RANGE_SEL;
+U8 gCBT_VREF_RANGE_BEGIN;
+U8 gCBT_VREF_RANGE_END;
+U8 gCBT_VREF_RANGE_STEP;
+
+U8 gu1LP3DieNum[2]; // 2 rank may have different die number
+
+//U8 gu1MR23Done = FALSE; /* Not used starting from Vinson (all freqs use MR23=0x3F) */
+U8 gu1MR23[CHANNEL_NUM][RANK_MAX];
+/* DQSOSCTHRD_INC & _DEC are 12 bits (Starting from Vinson) */
+U16 gu2DQSOSCTHRD_INC[CHANNEL_NUM][RANK_MAX];
+U16 gu2DQSOSCTHRD_DEC[CHANNEL_NUM][RANK_MAX];
+U16 gu2MR18[CHANNEL_NUM][RANK_MAX]; /* Stores MRR MR18 (DQS ocillator count - MSB) */
+U16 gu2MR19[CHANNEL_NUM][RANK_MAX]; /* Stores MRR MR19 (DQS ocillator count - LSB) */
+U16 gu2DQSOSC[CHANNEL_NUM][RANK_MAX]; /* Stores tDQSOSC results */
+U16 gu2DQSOscCnt[CHANNEL_NUM][RANK_MAX][2];
+
+#define CBT_WORKAROUND_O1_SWAP 0 // set default clk and ca value
+
+static S32 CATrain_CmdDelay[CHANNEL_NUM][RANK_MAX];
+static U32 CATrain_CsDelay[CHANNEL_NUM][RANK_MAX];
+static S32 CATrain_ClkDelay[CHANNEL_NUM][RANK_MAX];
+static S32 wrlevel_dqs_final_delay[DQS_NUMBER]; // 3 is channel number
+static U16 u2rx_window_sum;
+static U8 ucg_num_dlycell_perT = 49; //from 60807
+U16 u2gdelay_cell_ps;
+U8 ucg_num_dlycell_perT_all[DRAM_DFS_SHUFFLE_MAX][CHANNEL_NUM];///TODO: to be removed by Francis
+U16 u2gdelay_cell_ps_all[DRAM_DFS_SHUFFLE_MAX][CHANNEL_NUM];///TODO: to be removed by Francis
+U32 u4gVcore[DRAM_DFS_SHUFFLE_MAX];
+
+U32 gDramcSwImpedanceResule[2][4]={{0,0,0,0},{0,0,0,0}};//ODT_ON/OFF x DRVP/DRVN/ODTP/ODTN
+#if APPLY_SIGNAL_WAVEFORM_SETTINGS_ADJUST
+S8  gDramcSwImpedanceAdjust[2][4]={{0,0,0,0},{0,0,0,0}};//ODT_ON/OFF x DRVP/DRVN/ODTP/ODTN
+S8  gDramcDqOdtRZQAdjust=-1;
+S8  gDramcMR03PDDSAdjust[FSP_MAX]={-1,-1};
+S8  gDramcMR22SoCODTAdjust[FSP_MAX]={-1,-1};
+#endif
+S8 iFirstCAPass[RANK_MAX][LP3_DIE_NUM_MAX][CATRAINING_NUM], iLastCAPass[RANK_MAX][LP3_DIE_NUM_MAX][CATRAINING_NUM];  // 2 die.
+
+S16 gu2RX_DQS_Duty_Offset[DQS_NUMBER][2];
+
+#ifdef FOR_HQA_TEST_USED
+U16 gFinalCBTVrefCA[CHANNEL_NUM][RANK_MAX];
+U16 gFinalCBTCA[CHANNEL_NUM][RANK_MAX][10];
+U16 gFinalRXPerbitWin[CHANNEL_NUM][RANK_MAX][DQ_DATA_WIDTH];
+U16 gFinalTXPerbitWin[CHANNEL_NUM][RANK_MAX][DQ_DATA_WIDTH];
+U16 gFinalTXPerbitWin_min_max[CHANNEL_NUM][RANK_MAX];
+U16 gFinalTXPerbitWin_min_margin[CHANNEL_NUM][RANK_MAX];
+U16 gFinalTXPerbitWin_min_margin_bit[CHANNEL_NUM][RANK_MAX];
+S8 gFinalClkDuty[CHANNEL_NUM];
+U32 gFinalClkDutyMinMax[CHANNEL_NUM][2];
+S8 gFinalDQSDuty[CHANNEL_NUM][DQS_NUMBER];
+U32 gFinalDQSDutyMinMax[CHANNEL_NUM][DQS_NUMBER][2];
+#endif
+U8 gFinalCBTVrefDQ[CHANNEL_NUM][RANK_MAX];
+U8 gFinalRXVrefDQ[CHANNEL_NUM][RANK_MAX];
+U8 gFinalTXVrefDQ[CHANNEL_NUM][RANK_MAX];
+
+#if EYESCAN_LOG
+#define VREF_TOTAL_NUM_WITH_RANGE 51+30 //range0 0~50 + range1 21~50
+#define EYESCAN_BROKEN_NUM 3
+#define EYESCAN_DATA_INVALID 0x7fff
+S16  gEyeScan_Min[VREF_TOTAL_NUM_WITH_RANGE][DQ_DATA_WIDTH_LP4][EYESCAN_BROKEN_NUM];
+S16  gEyeScan_Max[VREF_TOTAL_NUM_WITH_RANGE][DQ_DATA_WIDTH_LP4][EYESCAN_BROKEN_NUM];
+U16  gEyeScan_CaliDelay[DQS_NUMBER];
+U8  gEyeScan_WinSize[VREF_TOTAL_NUM_WITH_RANGE][DQ_DATA_WIDTH_LP4];
+S8  gEyeScan_DelayCellPI[DQ_DATA_WIDTH_LP4];
+U8  gEyeScan_ContinueVrefHeight[DQ_DATA_WIDTH_LP4];
+U16  gEyeScan_TotalPassCount[DQ_DATA_WIDTH_LP4];
+#endif
+
+#ifdef DEVIATION
+U8 gSetSpecificedVref_Enable[3]={0};
+U8 gSetSpecificedVref_Type=0;
+U8 gSetSpecificedVref_All_ChRk[3]={0};
+U8 gSetSpecificedVref_Channel[3]={0};
+U8 gSetSpecificedVref_Rank[3]={0};
+S8 gSetSpecificedVref_Vref_Offset[3]={0};
+#endif
+
+extern const U8 uiLPDDR4_MRR_Mapping_POP[CHANNEL_NUM][16];
+#if ENABLE_LP3_SW
+extern const U8 uiLPDDR3_O1_Mapping_POP[32];
+extern const U8 uiLPDDR3_O1_Mapping_POP_DLP3[32];
+#endif
+extern const U8 uiLPDDR4_O1_Mapping_POP[CHANNEL_NUM][16];
+
+extern DRAM_DFS_FREQUENCY_TABLE_T gFreqTbl[];
+extern DRAM_DFS_FREQUENCY_TABLE_T gFreqTbl_LP3[];
+
+extern const U16 gRXVref_Voltage_Table_LP4[RX_VREF_RANGE_END+1];
+extern const U16 gVref_Voltage_Table_LP4X[VREF_RANGE_MAX][VREF_VOLTAGE_TABLE_NUM];
+extern const U16 gVref_Voltage_Table_LP4[VREF_RANGE_MAX][VREF_VOLTAGE_TABLE_NUM];
+
+
+static void dle_factor_handler(DRAMC_CTX_T *p, U8 curr_val, U8 pip_num);
+U8 GetCmdBusTrainingVrefPinMuxRevertValue(DRAMC_CTX_T *p, U8 u1VrefLevel);
+U8 get_shuffleIndex_by_Freq(DRAMC_CTX_T *p); //Retrieve LP4's shuffle index from gFreqTbl
+
+void vInitGlobalVariablesByCondition(DRAM_DRAM_TYPE_T dram_type)
+{
+    U8 u1CHIdx, u1RankIdx, u1FSPIdx;
+#if MRW_CHECK_ONLY
+    U8 u1MRIdx;
+#endif
+    U8 u1Vref_Unterm;
+
+    u1MR01Value[FSP_0] = 0x26;
+    u1MR01Value[FSP_1] = 0x56;
+
+    if(dram_type==TYPE_LPDDR4)
+        u1Vref_Unterm = 0x4d; //LP4
+    else
+        u1Vref_Unterm = 0x5d; //LP4X
+
+    memset(u1MR12Value, u1Vref_Unterm, sizeof(u1MR12Value));
+
+    for(u1FSPIdx=0; u1FSPIdx<FSP_MAX; u1FSPIdx++)
+    {
+        u1MR02Value[u1FSPIdx]=0x1a;
+        u1MR03Value[u1FSPIdx]=0x31;
+    }
+
+    for(u1CHIdx=0; u1CHIdx<CHANNEL_NUM; u1CHIdx++)
+        for(u1RankIdx=0; u1RankIdx< RANK_MAX; u1RankIdx++)
+            for(u1FSPIdx=0; u1FSPIdx<FSP_MAX; u1FSPIdx++)
+            {
+                // MR14 default value, LP4 default 0x4d, LP4X 0x5d
+                u1MR14Value[u1CHIdx][u1RankIdx][u1FSPIdx] = (u1FSPIdx==FSP_0) ? u1Vref_Unterm : 0x10;
+                #if MRW_CHECK_ONLY
+                for(u1MRIdx=0; u1MRIdx<MR_NUM; u1MRIdx++)
+                    u2MRRecord[u1CHIdx][u1RankIdx][u1FSPIdx][u1MRIdx] =0xffff;
+                #endif
+            }
+
+    memset(gu1MR23, 0x3F, sizeof(gu1MR23)); /* MR23 should be 0x3F for all freqs (Starting from Vinson) */
+    memset(gu2DQSOSCTHRD_INC, 0x6, sizeof(gu2DQSOSCTHRD_INC));
+    memset(gu2DQSOSCTHRD_DEC, 0x4, sizeof(gu2DQSOSCTHRD_DEC));
+    memset(gu2RX_DQS_Duty_Offset, 0, sizeof(gu2RX_DQS_Duty_Offset));
+
+
+}
+
+void vSetChannelNumber(DRAMC_CTX_T *p)
+{
+    if(u1IsLP4Family(p->dram_type))
+    {
+        u1ChannelSet = (U8 *)u1LP4Channel;
+        #if (!FOR_DV_SIMULATION_USED)
+        p->support_channel_num = sizeof(u1LP4Channel)/sizeof(U8); // 2 channel
+        #else
+        p->support_channel_num = CHANNEL_SINGLE;
+        #endif
+    }
+#if ENABLE_LP3_SW
+    else //LP3
+    {
+        u1ChannelSet = (U8 *)u1LP3Channel;
+        p->support_channel_num = sizeof(u1LP3Channel)/sizeof(U8);
+    }
+#endif /* ENABLE_LP3_SW */
+}
+
+void vSetRankNumber(DRAMC_CTX_T *p)
+{
+    if (u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RSTMASK), RSTMASK_RSV_DRAM_SUPPORT_RANK_NUM) == 0)
+    {
+        p->support_rank_num =RANK_DUAL;
+    }
+    else
+    {
+        p->support_rank_num =RANK_SINGLE;
+    }
+}
+
+void vSetPHY2ChannelMapping(DRAMC_CTX_T *p, U8 u1Channel)
+{
+    p->channel =u1Channel;
+}
+
+
+U8 vGetPHY2ChannelMapping(DRAMC_CTX_T *p)
+{
+    return p->channel;
+}
+
+void vSetRank(DRAMC_CTX_T *p, U8 ucRank)
+{
+    p->rank = ucRank;
+}
+
+U8 u1GetRank(DRAMC_CTX_T *p)
+{
+    return p->rank;
+}
+
+/* vGet_Dram_CBT_Mode
+ * Due to current HW design (both ranks share the same set of ACTiming regs), mixed
+ * mode LP4 now uses byte mode ACTiming settings. This means most calibration steps
+ * should use byte mode code flow.
+ * Note: The below items must have per-rank settings (Don't use this function)
+ * 1. CBT training 2. TX tracking
+ */
+DRAM_CBT_MODE_T vGet_Dram_CBT_Mode(DRAMC_CTX_T *p)
+{
+    if(p->dram_cbt_mode[RANK_0] == CBT_NORMAL_MODE && p->dram_cbt_mode[RANK_1] == CBT_NORMAL_MODE)
+    {
+        return CBT_NORMAL_MODE;
+    }
+    else // For Mixed mode & Byte mode LP4
+    {
+        return CBT_BYTE_MODE1;
+    }
+}
+
+#if PRINT_CALIBRATION_SUMMARY
+void vSetCalibrationResult(DRAMC_CTX_T *p, U8 ucCalType, U8 ucResult)
+{
+    p->aru4CalExecuteFlag[p->channel][p->rank] |= (1<<ucCalType); // ececution done
+    if (ucResult == DRAM_OK)  // Calibration OK
+    {
+        p->aru4CalResultFlag[p->channel][p->rank] &= (~(1<<ucCalType));
+    }
+    else  //Calibration fail
+    {
+        p->aru4CalResultFlag[p->channel][p->rank] |= (1<<ucCalType);
+    }
+}
+
+#if 0  //no use now, disable for saving code size.
+void vGetCalibrationResult_All(DRAMC_CTX_T *p, U8 u1Channel, U8 u1Rank, U8 u1FreqType, U32 *u4CalExecute, U32 *u4CalResult)
+{
+    *u4CalExecute = p->aru4CalExecuteFlag[u1Channel][u1Rank];
+    *u4CalResult = p->aru4CalResultFlag[u1Channel][u1Rank];
+}
+
+void vGetCalibrationResult(DRAMC_CTX_T *p, U8 ucCalType, U8 *ucCalExecute, U8 *ucCalResult)
+{
+    U32 ucCalResult_All, ucCalExecute_All;
+
+    ucCalExecute_All = p->aru4CalExecuteFlag[p->channel][p->rank];
+    ucCalResult_All = p->aru4CalResultFlag[p->channel][p->rank];
+
+    *ucCalExecute = (U8)((ucCalExecute_All >>ucCalType) & 0x1);
+    *ucCalResult =  (U8)((ucCalResult_All >>ucCalType) & 0x1);
+}
+#endif
+
+const char *szCalibStatusName[DRAM_CALIBRATION_MAX]=
+{
+    "ZQ Calibration",
+    "SW Impedance",
+    "CA Training",
+    "Write leveling",
+    "RX DQS gating",
+    "RX DATLAT",
+    "RX DQ/DQS(RDDQC)",
+    "RX DQ/DQS(Engine)",
+    "TX DQ/DQS",
+};
+
+void vPrintCalibrationResult(DRAMC_CTX_T *p)
+{
+    U8 ucCHIdx, ucRankIdx, ucCalIdx;
+    U32 ucCalResult_All, ucCalExecute_All;
+    U8 ucCalResult, ucCalExecute;
+    U8 u1CalibrationFail;
+
+    mcSHOW_DBG_MSG(("\n\n[Calibration Summary] Freqency %d\n", p->frequency));
+
+    //for(ucFreqIdx=0; ucFreqIdx<DRAM_DFS_SHUFFLE_MAX; ucFreqIdx++)
+    {
+        //mcSHOW_DBG_MSG(("==Freqency = %d==\n", get_Freq_by_shuffleIndex(p,ucFreqIdx)));
+        for(ucCHIdx=0; ucCHIdx<p->support_channel_num; ucCHIdx++)
+        {
+            for(ucRankIdx=0; ucRankIdx<p->support_rank_num; ucRankIdx++)
+            {
+                u1CalibrationFail =0;
+                ucCalExecute_All = p->aru4CalExecuteFlag[u1ChannelSet[ucCHIdx]][ucRankIdx];
+                ucCalResult_All = p->aru4CalResultFlag[u1ChannelSet[ucCHIdx]][ucRankIdx];
+                mcSHOW_DBG_MSG(("CH %d, Rank %d\n", u1ChannelSet[ucCHIdx], ucRankIdx));
+                //mcSHOW_DBG_MSG(("[vPrintCalibrationResult] Channel = %d, Rank= %d, Freq.= %d, (ucCalExecute_All 0x%x, ucCalResult_All 0x%x)\n", ucCHIdx, ucRankIdx, ucFreqIdx, ucCalExecute_All, ucCalResult_All));
+
+                for(ucCalIdx =0; ucCalIdx<DRAM_CALIBRATION_MAX; ucCalIdx++)
+                {
+                    ucCalExecute = (U8)((ucCalExecute_All >>ucCalIdx) & 0x1);
+                    ucCalResult =  (U8)((ucCalResult_All >>ucCalIdx) & 0x1);
+
+                    if(ucCalExecute==1 && ucCalResult ==1) // excuted and fail
+                    {
+                        u1CalibrationFail =1;
+                        mcSHOW_DBG_MSG(("%s: %s\n", szCalibStatusName[ucCalIdx], ((ucCalResult == 0) ? "OK" : "Fail")));
+                    }
+                }
+
+                if(u1CalibrationFail ==0)
+                {
+                    mcSHOW_DBG_MSG(("All Pass.\n"));
+                }
+                mcSHOW_DBG_MSG(("\n"));
+            }
+        }
+    }
+
+    memset(p->aru4CalResultFlag, 0, sizeof(p->aru4CalResultFlag));
+    memset(p->aru4CalExecuteFlag, 0, sizeof(p->aru4CalExecuteFlag));
+}
+#endif
+
+void vPrintCalibrationBasicInfo(DRAMC_CTX_T *p)
+{
+#if __ETT__
+    mcSHOW_DBG_MSG(("===============================================================================\n"
+                    "Dram Type= %d, Freq= %u, FreqGroup= %u, CH_%d, rank %d\n"
+                    "fsp= %d, odt_onoff= %d, Byte mode= %d\n"
+                    "===============================================================================\n",
+                        p->dram_type, DDRPhyFMeter(), p->freqGroup, p->channel, p->rank,
+                        p->dram_fsp, p->odt_onoff, p->dram_cbt_mode[p->rank]));
+#else
+    mcSHOW_DBG_MSG(("===============================================================================\n"
+                    "Dram Type= %d, Freq= %u, CH_%d, rank %d\n"
+                    "fsp= %d, odt_onoff= %d, Byte mode= %d\n"
+                    "===============================================================================\n",
+                        p->dram_type, DDRPhyFMeter(), p->channel, p->rank,
+                        p->dram_fsp, p->odt_onoff, p->dram_cbt_mode[p->rank]));
+#endif
+}
+
+#if VENDER_JV_LOG
+void vPrintCalibrationBasicInfo_ForJV(DRAMC_CTX_T *p)
+{
+    mcSHOW_DBG_MSG5(("\n\nDram type:"));
+
+    switch(p->dram_type)
+    {
+#if ENABLE_LP3_SW
+        case TYPE_LPDDR3:
+            mcSHOW_DBG_MSG5(("LPDDR3\t"));
+            break;
+#endif /* ENABLE_LP3_SW */
+        case TYPE_LPDDR4:
+            mcSHOW_DBG_MSG5(("LPDDR4\t"));
+            break;
+
+        case TYPE_LPDDR4X:
+            mcSHOW_DBG_MSG5(("LPDDR4X\t"));
+            break;
+
+        case TYPE_LPDDR4P:
+            mcSHOW_DBG_MSG5(("LPDDR4P\t"));
+            break;
+    }
+
+    mcSHOW_DBG_MSG5(("Freq: %d, FreqGroup %u, channel %d, rank %d\n"
+                     "dram_fsp= %d, odt_onoff= %d, Byte mode= %d\n\n",
+                                        p->frequency, p->freqGroup, p->channel, p->rank,
+                                        p->dram_fsp, p->odt_onoff, p->dram_cbt_mode[p->rank]));
+
+    return;
+}
+#endif
+
+#ifdef DEVIATION
+void DeviationAddVrefOffset(U8 k_type, U16 *u2FinalRange, U16 *u2FinalVref, S8 Vref_Offset)
+{
+    S16 temp_vref_value;
+
+    if (k_type==1)
+    {
+        temp_vref_value = *u2FinalVref + Vref_Offset;
+        if (temp_vref_value < 0)
+        {
+            *u2FinalVref = 0;
+        }
+        else if (temp_vref_value < RX_VREF_RANGE_END)
+        {
+            *u2FinalVref = temp_vref_value;
+        }
+        else
+        {
+            *u2FinalVref = RX_VREF_RANGE_END;
+        }
+    }
+    else
+    {
+        temp_vref_value = (*u2FinalRange*30) + *u2FinalVref + Vref_Offset;
+        if (temp_vref_value < 0)
+        {
+            *u2FinalRange = 0;
+            *u2FinalVref = 0;
+        }
+        else if (temp_vref_value <=50)
+        {
+            *u2FinalRange = 0;
+            *u2FinalVref = temp_vref_value;
+        }
+        else if (temp_vref_value < 81)
+        {
+            *u2FinalRange = 1;
+            *u2FinalVref = temp_vref_value - 30;
+        }
+        else
+        {
+            *u2FinalRange = 1;
+            *u2FinalVref = 50;
+        }
+    }
+}
+#endif
+
+#if (__ETT__ || ENABLE_LP3_SW)
+//for LP3 read register in different byte
+U32 u4IO32ReadFldAlign_Phy_Byte2(DRAMC_CTX_T *p, U8 ucByteIdx, U32 reg32, U32 fld)
+{
+    U32 offset=0;
+    U32 except_offset=0;
+
+#if (fcFOR_CHIP_ID == fcLaurel)
+    if(reg32<Channel_A_PHY_AO_BASE_VIRTUAL)
+    {
+       mcSHOW_DBG_MSG(("\n[ReadFldAlign_Phy_Byte] wrong addr 0x%x\n", reg32));
+       #if (FOR_DV_SIMULATION_USED==0 && SW_CHANGE_FOR_SIMULATION==0)
+       ASSERT(0);
+       #endif
+    }
+
+    reg32 &= 0xffff;
+
+    if (reg32 >= (DDRPHY_SHU1_R0_B0_DQ0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_SHU1_R0_B1_DQ0-DDRPHY_AO_BASE_ADDR))
+    {
+        offset = 0x50;
+        ///TODO: BE CAREFUL. CLK (PHY) -> DQS (DRAM)
+        if (reg32 >= (DDRPHY_SHU1_R0_B0_DQ0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_SHU1_R0_B0_DQ6-DDRPHY_AO_BASE_ADDR))
+        {
+            except_offset = 0x0;
+        }
+        else
+        {
+            except_offset = 0x8;
+        }
+    }
+    else if (reg32 >= (DDRPHY_R0_B0_RXDVS0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_R0_B1_RXDVS0-DDRPHY_AO_BASE_ADDR))
+    {
+        offset = 0x80;
+        except_offset = 0;
+    }
+    else if (reg32 >= (DDRPHY_SHU1_B0_DQ0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_SHU1_B1_DQ0-DDRPHY_AO_BASE_ADDR))
+    {
+        offset = 0x80;
+        except_offset = 0;
+    }
+    else if (reg32 >= (DDRPHY_B0_DLL_ARPI0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_B1_DLL_ARPI0-DDRPHY_AO_BASE_ADDR))
+    {
+        offset = 0x80;
+        except_offset = 0;
+    }
+    else
+    {
+        offset = 0x0;
+        except_offset = 0;
+    }
+
+    switch(ucByteIdx)
+    {
+        case 0:
+            return u4IO32ReadFldAlign(reg32+Channel_B_PHY_AO_BASE_VIRTUAL+offset, fld); //CHB_B1
+            break;
+        case 1:
+            if(reg32==(DDRPHY_SHU1_R0_B0_DQ7&0xffff) && fld==SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0)
+            {
+                fld=SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS;
+            }
+            return u4IO32ReadFldAlign(reg32+Channel_B_PHY_AO_BASE_VIRTUAL+(offset<<1)+except_offset, fld); //CHB_CA
+            break;
+        case 2:
+            return u4IO32ReadFldAlign(reg32+Channel_A_PHY_AO_BASE_VIRTUAL+offset, fld);   //CHA_B1
+            break;
+        case 3:
+            return u4IO32ReadFldAlign(reg32+Channel_B_PHY_AO_BASE_VIRTUAL, fld); //CHB_B0
+            break;
+        default:
+            mcSHOW_DBG_MSG(("\n[ReadFldAlign_Phy_Byte] wrong index of ucByteIdx !!!\n"));
+            break;
+    }
+#endif
+
+    #if (FOR_DV_SIMULATION_USED==0 && SW_CHANGE_FOR_SIMULATION==0)
+    ASSERT(0);
+    #endif
+}
+#endif
+
+#if ENABLE_LP3_SW
+//for LP3 write register in different byte
+void vIO32WriteFldAlign_Phy_Byte2(DRAMC_CTX_T *p, U8 ucByteIdx, U32 reg32, U32 val32, U32 fld)
+{
+#if (fcFOR_PINMUX == fcLaurel)
+    U32 offset=0;
+    U32 except_offset=0;
+
+    if(reg32 < Channel_A_PHY_AO_BASE_VIRTUAL)
+    {
+        mcSHOW_DBG_MSG(("\n[WriteFldAlign_Phy_Byte] wrong addr 0x%x\n", reg32));
+        return;
+    }
+    reg32 &= 0xffff;
+    if (reg32 >= (DDRPHY_SHU1_R0_B0_DQ0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_SHU1_R0_B1_DQ0-DDRPHY_AO_BASE_ADDR))
+    {
+        offset = 0x50;
+        ///TODO: BE CAREFUL. CLK (PHY) -> DQS (DRAM)
+        if (reg32 >= (DDRPHY_SHU1_R0_B0_DQ0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_SHU1_R0_B0_DQ6-DDRPHY_AO_BASE_ADDR))
+        {
+            except_offset = 0x0;
+        }
+        else
+        {
+            except_offset = 0x8;
+        }
+    }
+    else if (reg32 >= (DDRPHY_R0_B0_RXDVS0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_R0_B1_RXDVS0-DDRPHY_AO_BASE_ADDR))
+    {
+        offset = 0x80;
+        except_offset = 0x0;
+    }
+    else if (reg32 >= (DDRPHY_SHU1_B0_DQ0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_SHU1_B1_DQ0-DDRPHY_AO_BASE_ADDR))
+    {
+        offset = 0x80;
+        except_offset = 0;
+    }
+    else if (reg32 >= (DDRPHY_B0_DLL_ARPI0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_B1_DLL_ARPI0-DDRPHY_AO_BASE_ADDR))
+    {
+        offset = 0x80;
+        except_offset = 0;
+    }
+    else
+    {
+        offset = 0x0;
+        except_offset = 0;
+    }
+
+    switch(ucByteIdx)
+    {
+        case 0:
+            vIO32WriteFldAlign(reg32+Channel_B_PHY_AO_BASE_VIRTUAL+offset, val32, fld); //CHB_B1
+            break;
+        case 1:
+            if(reg32==(DDRPHY_SHU1_R0_B0_DQ7&0xffff) && fld==SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0)
+            {
+                fld=SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS;
+            }
+            vIO32WriteFldAlign(reg32+Channel_B_PHY_AO_BASE_VIRTUAL+(offset<<1)+except_offset, val32, fld); //CHB_CA
+            break;
+        case 2:
+            vIO32WriteFldAlign(reg32+Channel_A_PHY_AO_BASE_VIRTUAL+offset, val32, fld); //CHA_B1
+            break;
+        case 3:
+            vIO32WriteFldAlign(reg32+Channel_B_PHY_AO_BASE_VIRTUAL, val32, fld); //CHB_B0
+            break;
+        default:
+            mcSHOW_DBG_MSG(("\n[WriteFldAlign_Phy_Byte] wrong index of ucByteIdx !!!\n"));
+#if (FOR_DV_SIMULATION_USED==0 && SW_CHANGE_FOR_SIMULATION==0)
+            ASSERT(0);
+#endif
+            break;
+    }
+#endif
+}
+#endif /* ENABLE_LP3_SW */
+
+// for LP3 to control all PHY of single channel
+void vIO32WriteFldAlign_Phy_All2(DRAMC_CTX_T *p, U32 reg32, U32 val32, U32 fld)
+{
+    U8 ucCHIdx;
+
+    if(reg32<Channel_A_PHY_AO_BASE_VIRTUAL)
+    {
+        mcSHOW_DBG_MSG(("\n[WriteFldAlign_Phy_All] wrong addr 0x%x\n", reg32));
+        return;
+    }
+
+    reg32 &= 0xffff;
+
+    for(ucCHIdx=0; ucCHIdx<CHANNEL_NUM; ucCHIdx++)
+    {
+        vIO32WriteFldAlign(reg32+Channel_A_PHY_AO_BASE_VIRTUAL+0x10000*ucCHIdx, val32, fld);
+    }
+}
+
+void vApplyConfigAfterCalibration(DRAMC_CTX_T *p)
+{
+    U8 shu_index;
+/*================================
+    PHY RX Settings
+==================================*/
+
+    if(u1IsLP4Family(p->dram_type))
+    {
+        vIO32WriteFldAlign_All(DDRPHY_MISC_CG_CTRL4, 0x11400000, MISC_CG_CTRL4_R_PHY_MCK_CG_CTRL);
+        vIO32WriteFldAlign_All(DRAMC_REG_REFCTRL1, 0x0, REFCTRL1_SREF_CG_OPT);
+        vIO32WriteFldAlign_All(DRAMC_REG_SHUCTRL, 0x0, SHUCTRL_DVFS_CG_OPT);
+
+        /* Burst mode settings are removed from here due to
+         *  1. Set in UpdateInitialSettings_LP4
+         *  2. DQS Gating ensures new burst mode is switched when to done
+         *     (or doesn't switch gatingMode at all, depending on "LP4_GATING_OLD_BURST_MODE")
+         */
+
+        vIO32WriteFldAlign_All(DDRPHY_CA_CMD6, 0x0, CA_CMD6_RG_RX_ARCMD_RES_BIAS_EN);
+#if 0
+        vIO32WriteFldAlign_All(DDRPHY_B0_DQ6, 0x0, B0_DQ6_RG_TX_ARDQ_OE_EXT_DIS_B0);
+        vIO32WriteFldAlign_All(DDRPHY_B1_DQ6, 0x0, B1_DQ6_RG_TX_ARDQ_OE_EXT_DIS_B1);
+        vIO32WriteFldAlign_All(DDRPHY_CA_CMD6, 0x0, CA_CMD6_RG_TX_ARCMD_OE_EXT_DIS);
+#endif
+
+#if ENABLE_WRITE_DBI
+        EnableDRAMModeRegWriteDBIAfterCalibration(p);
+#endif
+
+#if ENABLE_READ_DBI
+        EnableDRAMModeRegReadDBIAfterCalibration(p);
+#endif
+
+        // Set VRCG{MR13[3]} to 0 both to DRAM and DVFS
+        SetMr13VrcgToNormalOperation(p);
+
+    }
+#if ENABLE_LP3_SW
+    else
+    {   //pulse mode
+        vIO32WriteFldAlign_All(DDRPHY_B0_DQ9, 0x0, B0_DQ9_RG_RX_ARDQS0_DQSIENMODE_B0);
+        vIO32WriteFldAlign_All(DDRPHY_B1_DQ9, 0x0, B1_DQ9_RG_RX_ARDQS0_DQSIENMODE_B1);
+        vIO32WriteFldAlign_All(DDRPHY_CA_CMD10, 0x0, CA_CMD10_RG_RX_ARCLK_DQSIENMODE);
+
+        vIO32WriteFldAlign_All(DDRPHY_B0_DQ6, 0x0, B0_DQ6_RG_RX_ARDQ_BIAS_VREF_SEL_B0);
+        vIO32WriteFldAlign_All(DDRPHY_B1_DQ6, 0x0, B1_DQ6_RG_RX_ARDQ_BIAS_VREF_SEL_B1);
+        vIO32WriteFldAlign_All(DDRPHY_CA_CMD6, 0x0, CA_CMD6_RG_RX_ARCMD_BIAS_VREF_SEL);
+
+#if 0
+        vIO32WriteFldAlign_All(DDRPHY_B0_DQ6, 0x1, B0_DQ6_RG_TX_ARDQ_OE_EXT_DIS_B0);
+        vIO32WriteFldAlign_All(DDRPHY_B1_DQ6, 0x1, B1_DQ6_RG_TX_ARDQ_OE_EXT_DIS_B1);
+        vIO32WriteFldAlign_All(DDRPHY_CA_CMD6, 0x1, CA_CMD6_RG_TX_ARCMD_OE_EXT_DIS);
+#endif
+
+    }
+#endif /* ENABLE_LP3_SW */
+
+        //DA mode
+        vIO32WriteFldAlign_All(DDRPHY_B0_DQ6, 0x0, B0_DQ6_RG_RX_ARDQ_BIAS_PS_B0);
+        vIO32WriteFldAlign_All(DDRPHY_B1_DQ6, 0x0, B1_DQ6_RG_RX_ARDQ_BIAS_PS_B1);
+        vIO32WriteFldAlign_All(DDRPHY_CA_CMD6, 0x0, CA_CMD6_RG_RX_ARCMD_BIAS_PS);
+
+        vIO32WriteFldAlign_All(DDRPHY_B0_DQ6, 0x1, B0_DQ6_RG_RX_ARDQ_RPRE_TOG_EN_B0);
+        vIO32WriteFldAlign_All(DDRPHY_B1_DQ6, 0x1, B1_DQ6_RG_RX_ARDQ_RPRE_TOG_EN_B1);
+        vIO32WriteFldAlign_All(DDRPHY_CA_CMD6, 0x1, CA_CMD6_RG_RX_ARCMD_RPRE_TOG_EN);
+
+
+/*================================
+    IMPCAL Settings
+==================================*/
+    vIO32WriteFldMulti_All(DRAMC_REG_IMPCAL, P_Fld(0, IMPCAL_IMPCAL_IMPPDP) | P_Fld(0, IMPCAL_IMPCAL_IMPPDN));    //RG_RIMP_BIAS_EN and RG_RIMP_VREF_EN move to IMPPDP and IMPPDN
+    vIO32WriteFldAlign_All(DDRPHY_MISC_IMP_CTRL0, 0, MISC_IMP_CTRL0_RG_IMP_EN);
+
+/*================================
+    MR1
+==================================*/
+
+    //MR1 op[7]=0 already be setted at end of gating calibration, no need to set here again
+/*
+    u1MR01Value[p->dram_fsp] &= 0x7f;
+    DramcModeRegWrite(p, 1, u1MR01Value[p->dram_fsp]);
+*/
+    //Prevent M_CK OFF because of hardware auto-sync
+    vIO32WriteFldAlign_All(DDRPHY_MISC_CG_CTRL0, 0, Fld(4,0));
+
+    //DFS- fix Gating Tracking settings
+    vIO32WriteFldAlign_All(DDRPHY_MISC_CTRL0, 0, MISC_CTRL0_R_STBENCMP_DIV4CK_EN);
+    vIO32WriteFldAlign_All(DDRPHY_MISC_CTRL1, 0, MISC_CTRL1_R_DMSTBENCMP_RK_OPT);
+
+    ///TODO: Disable MR4 MR18/MR19, TxHWTracking, Dummy RD - for DFS workaround
+    vIO32WriteFldAlign_All(DRAMC_REG_SPCMDCTRL, 0x1, SPCMDCTRL_REFRDIS);    //MR4 Disable
+    vIO32WriteFldAlign_All(DRAMC_REG_DQSOSCR, 0x1, DQSOSCR_DQSOSCRDIS);  //MR18, MR19 Disable
+    for(shu_index = DRAM_DFS_SHUFFLE_1; shu_index < DRAM_DFS_SHUFFLE_MAX; shu_index++)
+	  vIO32WriteFldAlign_All(DRAMC_REG_SHU_SCINTV + SHU_GRP_DRAMC_OFFSET*shu_index, 0x1, SHU_SCINTV_DQSOSCENDIS);
+    //vIO32WriteFldAlign_All(DRAMC_REG_SHU_SCINTV, 0x1, SHU_SCINTV_DQSOSCENDIS);
+    //vIO32WriteFldAlign_All(DRAMC_REG_SHU2_SCINTV, 0x1, SHU2_SCINTV_DQSOSCENDIS);
+    //vIO32WriteFldAlign_All(DRAMC_REG_SHU3_SCINTV, 0x1, SHU3_SCINTV_DQSOSCENDIS);
+    vIO32WriteFldMulti_All(DRAMC_REG_DUMMY_RD, P_Fld(0x0, DUMMY_RD_DUMMY_RD_EN)
+                                            | P_Fld(0x1, DUMMY_RD_SREF_DMYRD_EN)
+                                            | P_Fld(0x0, DUMMY_RD_DQSG_DMYRD_EN)
+                                            | P_Fld(0x0, DUMMY_RD_DMY_RD_DBG));
+#if APPLY_LP4_POWER_INIT_SEQUENCE
+    //CKE dynamic
+#if ENABLE_TMRRI_NEW_MODE
+    CKEFixOnOff(p, CKE_WRITE_TO_ALL_RANK, CKE_DYNAMIC, CKE_WRITE_TO_ALL_CHANNEL);
+#else
+    CKEFixOnOff(p, RANK_0, CKE_DYNAMIC, CKE_WRITE_TO_ALL_CHANNEL);
+#endif
+
+    //// Enable  HW MIOCK control to make CLK dynamic
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 0, DRAMC_PD_CTRL_MIOCKCTRLOFF);
+#endif
+
+    //close eyescan to save power
+    vIO32WriteFldMulti_All(DRAMC_REG_EYESCAN, P_Fld(0x0, EYESCAN_EYESCAN_DQS_SYNC_EN)
+                                        | P_Fld(0x0, EYESCAN_EYESCAN_NEW_DQ_SYNC_EN)
+                                        | P_Fld(0x0, EYESCAN_EYESCAN_DQ_SYNC_EN));
+
+    /* TESTAGENT2 */
+    vIO32WriteFldAlign_All(DRAMC_REG_TEST2_4, 4, TEST2_4_TESTAGENTRKSEL); // Rank selection is controlled by Test Agent
+}
+
+#if defined(LOOPBACK_TEST) || (EMI_LPBK_DRAM_USED==0)
+void DramcLoopbackTest_settings(DRAMC_CTX_T *p, U8 u1Type)
+{
+
+    //close DCM, or DQ no clock
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 0, MISC_CTRL1_R_DMDQSIENCG_EN);
+
+    if (u1Type==1) //external loop back
+    {
+        //IOBIAS settings
+        vIO32WriteFldAlign_All(DDRPHY_B0_DQ6, 1, B0_DQ6_RG_RX_ARDQ_BIAS_PS_B0);
+        vIO32WriteFldAlign_All(DDRPHY_B1_DQ6, 1, B1_DQ6_RG_RX_ARDQ_BIAS_PS_B1);
+        vIO32WriteFldAlign_All(DDRPHY_CA_CMD6, 1, CA_CMD6_RG_RX_ARCMD_BIAS_PS);
+
+        //after initial, must set 0 of PHY registers
+        vIO32WriteFldMulti_All(DDRPHY_B0_DQ3, P_Fld(0, B0_DQ3_RG_RX_ARDQS0_SWAP_EN_B0) | P_Fld(0, B0_DQ3_RG_RX_ARDQ_OFFC_EN_B0) | P_Fld(0, B0_DQ3_RG_RX_ARDQ_SMT_EN_B0));
+        vIO32WriteFldMulti_All(DDRPHY_B1_DQ3, P_Fld(0, B1_DQ3_RG_RX_ARDQS0_SWAP_EN_B1) | P_Fld(0, B1_DQ3_RG_RX_ARDQ_OFFC_EN_B1) | P_Fld(0, B1_DQ3_RG_RX_ARDQ_SMT_EN_B1));
+        vIO32WriteFldMulti_All(DDRPHY_CA_CMD3, P_Fld(0, CA_CMD3_RG_RX_ARCLK_SWAP_EN) | P_Fld(0, CA_CMD3_RG_RX_ARCMD_OFFC_EN) | P_Fld(0, CA_CMD3_RG_RX_ARCMD_SMT_EN));
+
+        //after initial, must set 1 of PHY registers
+        vIO32WriteFldMulti_All(DDRPHY_B0_DQ3, P_Fld(1, B0_DQ3_RG_RX_ARDQ_STBENCMP_EN_B0) | P_Fld(1, B0_DQ3_RG_RX_ARDQ_IN_BUFF_EN_B0) | P_Fld(1, B0_DQ3_RG_RX_ARDQS0_IN_BUFF_EN_B0) | P_Fld(1, B0_DQ3_RG_ARDQ_RESETB_B0));
+        vIO32WriteFldAlign_All(DDRPHY_B0_DQ9, 1, B0_DQ9_RG_RX_ARDQ_STBEN_RESETB_B0);
+        vIO32WriteFldAlign_All(DDRPHY_B0_DQ5, 1, B0_DQ5_RG_RX_ARDQ_VREF_EN_B0);
+        vIO32WriteFldMulti_All(DDRPHY_B0_DQ6, P_Fld(1, B0_DQ6_RG_RX_ARDQ_BIAS_EN_B0) | P_Fld(1, B0_DQ6_RG_RX_ARDQ_RES_BIAS_EN_B0));
+
+        vIO32WriteFldMulti_All(DDRPHY_B1_DQ3, P_Fld(1, B1_DQ3_RG_RX_ARDQ_STBENCMP_EN_B1) | P_Fld(1, B1_DQ3_RG_RX_ARDQ_IN_BUFF_EN_B1) | P_Fld(1, B1_DQ3_RG_RX_ARDQS0_IN_BUFF_EN_B1) | P_Fld(1, B1_DQ3_RG_ARDQ_RESETB_B1));
+        vIO32WriteFldAlign_All(DDRPHY_B1_DQ9, 1, B1_DQ9_RG_RX_ARDQ_STBEN_RESETB_B1);
+        vIO32WriteFldAlign_All(DDRPHY_B1_DQ5, 1, B1_DQ5_RG_RX_ARDQ_VREF_EN_B1);
+        vIO32WriteFldMulti_All(DDRPHY_B1_DQ6, P_Fld(1, B1_DQ6_RG_RX_ARDQ_BIAS_EN_B1) | P_Fld(1, B1_DQ6_RG_RX_ARDQ_RES_BIAS_EN_B1));
+
+        vIO32WriteFldMulti_All(DDRPHY_CA_CMD3, P_Fld(1, CA_CMD3_RG_RX_ARCMD_STBENCMP_EN) | P_Fld(1, CA_CMD3_RG_RX_ARCMD_IN_BUFF_EN) | P_Fld(1, CA_CMD3_RG_RX_ARCLK_IN_BUFF_EN) | P_Fld(1, CA_CMD3_RG_ARCMD_RESETB));
+        vIO32WriteFldAlign_All(DDRPHY_CA_CMD10, 1, CA_CMD10_RG_RX_ARCMD_STBEN_RESETB);
+        vIO32WriteFldAlign_All(DDRPHY_CA_CMD5, 1, CA_CMD5_RG_RX_ARCMD_VREF_EN);
+        vIO32WriteFldMulti_All(DDRPHY_CA_CMD6, P_Fld(1, CA_CMD6_RG_RX_ARCMD_BIAS_EN) | P_Fld(1, CA_CMD6_RG_RX_ARCMD_RES_BIAS_EN));
+    }
+}
+#endif
+
+
+void vResetDelayChainBeforeCalibration(DRAMC_CTX_T *p)
+{
+    U8 u1RankIdx, u1RankIdxBak;
+
+    u1RankIdxBak = u1GetRank(p);
+
+    for(u1RankIdx=RANK_0; u1RankIdx<RANK_MAX; u1RankIdx++)
+    {
+        vSetRank(p, u1RankIdx);
+        vIO32WriteFldMulti_All(DDRPHY_SHU1_R0_CA_CMD0, P_Fld(0x0, SHU1_R0_CA_CMD0_RK0_TX_ARCA5_DLY)
+                | P_Fld(0x0, SHU1_R0_CA_CMD0_RK0_TX_ARCA4_DLY)
+                | P_Fld(0x0, SHU1_R0_CA_CMD0_RK0_TX_ARCA3_DLY)
+                | P_Fld(0x0, SHU1_R0_CA_CMD0_RK0_TX_ARCA2_DLY)
+                | P_Fld(0x0, SHU1_R0_CA_CMD0_RK0_TX_ARCA1_DLY)
+                | P_Fld(0x0, SHU1_R0_CA_CMD0_RK0_TX_ARCA0_DLY));
+        vIO32WriteFldMulti_All(DDRPHY_SHU1_R0_B0_DQ0, P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ7_DLY_B0)
+                | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ6_DLY_B0)
+                | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ5_DLY_B0)
+                | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ4_DLY_B0)
+                | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ3_DLY_B0)
+                | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ2_DLY_B0)
+                | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ1_DLY_B0)
+                | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ0_DLY_B0));
+        vIO32WriteFldMulti_All(DDRPHY_SHU1_R0_B1_DQ0, P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ7_DLY_B1)
+                | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ6_DLY_B1)
+                | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ5_DLY_B1)
+                | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ4_DLY_B1)
+                | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ3_DLY_B1)
+                | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ2_DLY_B1)
+                | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ1_DLY_B1)
+                | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ0_DLY_B1));
+        vIO32WriteFldAlign_All(DDRPHY_SHU1_R0_B0_DQ1, 0x0, SHU1_R0_B0_DQ1_RK0_TX_ARDQM0_DLY_B0);
+        vIO32WriteFldAlign_All(DDRPHY_SHU1_R0_B1_DQ1, 0x0, SHU1_R0_B1_DQ1_RK0_TX_ARDQM0_DLY_B1);
+    }
+
+    vSetRank(p, u1RankIdxBak);
+}
+
+
+void vApplyConfigBeforeCalibration(DRAMC_CTX_T *p)
+{
+    U8 shu_index;
+    U8 u1RankIdx, u1RankIdxBak;
+    u1RankIdxBak = u1GetRank(p);
+
+#if 0//ENABLE_LP3_SW
+    if(p->dram_type == TYPE_LPDDR3)
+    {
+        vIO32WriteFldAlign(DDRPHY_SHU1_B1_DLL0, 0x6, SHU1_B1_DLL0_RG_ARDLL_GAIN_B1);
+        vIO32WriteFldAlign(DDRPHY_SHU1_CA_DLL0+(SHIFT_TO_CHB_ADDR), 0x6, SHU1_CA_DLL0_RG_ARDLL_GAIN_CA);
+        vIO32WriteFldAlign(DDRPHY_SHU1_B0_DLL0+(SHIFT_TO_CHB_ADDR), 0x6, SHU1_B0_DLL0_RG_ARDLL_GAIN_B0);
+        vIO32WriteFldAlign(DDRPHY_SHU1_B1_DLL0+(SHIFT_TO_CHB_ADDR), 0x6, SHU1_B1_DLL0_RG_ARDLL_GAIN_B1);
+    }
+#endif
+
+    //Clk free run
+#if (SW_CHANGE_FOR_SIMULATION==0)
+    EnableDramcPhyDCM(p, 0);
+#endif
+
+    //Set LP3/LP4 Rank0/1 CA/TX delay chain to 0
+#if (FOR_DV_SIMULATION_USED==0)
+    //CA0~9 per bit delay line -> CHA_CA0 CHA_CA3 CHA_B0_DQ6 CHA_B0_DQ7 CHA_B0_DQ2 CHA_B0_DQ5 CHA_B0_DQ4 CHA_B0_DQ1 CHA_B0_DQ0 CHA_B0_DQ3
+    vResetDelayChainBeforeCalibration(p);
+#endif
+
+    //MR4 refresh cnt set to 0x1ff (2ms update)
+    vIO32WriteFldAlign_All(DRAMC_REG_SHU_CONF3, 0x1ff, SHU_CONF3_REFRCNT);
+
+    //The counter for Read MR4 cannot be reset after SREF if DRAMC no power down.
+    vIO32WriteFldAlign_All(DRAMC_REG_SPCMDCTRL, 1, SPCMDCTRL_SRFMR4_CNTKEEP_B);
+
+    //---- ZQ CS init --------
+    vIO32WriteFldAlign_All(DRAMC_REG_SHU_SCINTV, 0x1B, SHU_SCINTV_TZQLAT); //ZQ Calibration Time, unit: 38.46ns, tZQCAL min is 1 us. need to set larger than 0x1b
+    for(shu_index = DRAM_DFS_SHUFFLE_1; shu_index < DRAM_DFS_SHUFFLE_MAX; shu_index++)
+        vIO32WriteFldAlign_All(DRAMC_REG_SHU_CONF3 + SHU_GRP_DRAMC_OFFSET*shu_index, 0x1ff, SHU_CONF3_ZQCSCNT); //Every refresh number to issue ZQCS commands, only for DDR3/LPDDR2/LPDDR3/LPDDR4
+    //vIO32WriteFldAlign_All(DRAMC_REG_SHU_CONF3, 0x1ff, SHU_CONF3_ZQCSCNT); //Every refresh number to issue ZQCS commands, only for DDR3/LPDDR2/LPDDR3/LPDDR4
+    //vIO32WriteFldAlign_All(DRAMC_REG_SHU2_CONF3, 0x1ff, SHU_CONF3_ZQCSCNT); //Every refresh number to issue ZQCS commands, only for DDR3/LPDDR2/LPDDR3/LPDDR4
+    //vIO32WriteFldAlign_All(DRAMC_REG_SHU3_CONF3, 0x1ff, SHU_CONF3_ZQCSCNT); //Every refresh number to issue ZQCS commands, only for DDR3/LPDDR2/LPDDR3/LPDDR4
+    vIO32WriteFldAlign_All(DRAMC_REG_DRAMCTRL, 0, DRAMCTRL_ZQCALL);  // HW send ZQ command for both rank, disable it due to some dram only have 1 ZQ pin for two rank.
+
+    //Dual channel ZQCS interlace,  0: disable, 1: enable
+    if(p->support_channel_num==CHANNEL_SINGLE)
+    {
+        //single channel, ZQCSDUAL=0, ZQCSMASK=0
+        vIO32WriteFldMulti(DRAMC_REG_ZQCS, P_Fld(0, ZQCS_ZQCSDUAL)| P_Fld(0x0, ZQCS_ZQCSMASK));
+    }
+    else if(p->support_channel_num==CHANNEL_DUAL)
+    {
+        // HW ZQ command is channel interleaving since 2 channel share the same ZQ pin.
+        #ifdef ZQCS_ENABLE_LP4
+        // dual channel, ZQCSDUAL =1, and CHA ZQCSMASK=0, CHB ZQCSMASK=1
+        vIO32WriteFldMulti_All(DRAMC_REG_ZQCS, P_Fld(1, ZQCS_ZQCSDUAL) | \
+                                               P_Fld(0, ZQCS_ZQCSMASK_OPT) | \
+                                               P_Fld(0, ZQCS_ZQMASK_CGAR) | \
+                                               P_Fld(0, ZQCS_ZQCS_MASK_SEL_CGAR));
+
+        // DRAMC CHA(CHN0):ZQCSMASK=1, DRAMC CHB(CHN1):ZQCSMASK=0.
+        // ZQCSMASK setting: (Ch A, Ch B) = (1,0) or (0,1)
+        // if CHA.ZQCSMASK=1, and then set CHA.ZQCALDISB=1 first, else set CHB.ZQCALDISB=1 first
+        vIO32WriteFldAlign(DRAMC_REG_ZQCS + (CHANNEL_A<< POS_BANK_NUM), 1, ZQCS_ZQCSMASK);
+        vIO32WriteFldAlign(DRAMC_REG_ZQCS + SHIFT_TO_CHB_ADDR, 0, ZQCS_ZQCSMASK);
+
+        // DRAMC CHA(CHN0):ZQCS_ZQCS_MASK_SEL=0, DRAMC CHB(CHN1):ZQCS_ZQCS_MASK_SEL=0.
+        vIO32WriteFldAlign_All(DRAMC_REG_ZQCS, 0, ZQCS_ZQCS_MASK_SEL);
+        #endif
+    }
+
+    // Disable LP3 HW ZQ
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), 0, SPCMDCTRL_ZQCSDISB);   //LP3 ZQCSDISB=0
+    // Disable LP4 HW ZQ
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), 0, SPCMDCTRL_ZQCALDISB);  //LP4 ZQCALDISB=0
+    // ---- End of ZQ CS init -----
+
+    #if ENABLE_TX_TRACKING
+    vIO32WriteFldAlign_All(DRAMC_REG_DQSOSCR, p->dram_cbt_mode[RANK_0],DQSOSCR_RK0_BYTE_MODE);
+    vIO32WriteFldAlign_All(DRAMC_REG_DQSOSCR, p->dram_cbt_mode[RANK_1],DQSOSCR_RK1_BYTE_MODE);
+    #endif
+    //Disable write-DBI of DRAMC (Avoids pre-defined data pattern being modified)
+    DramcWriteDBIOnOff(p, DBI_OFF);
+    //Disable read-DBI of DRAMC (Avoids pre-defined data pattern being modified)
+    DramcReadDBIOnOff(p, DBI_OFF);
+    //disable MR4 read, REFRDIS=1
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), 1, SPCMDCTRL_REFRDIS);
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 0x1, DQSOSCR_DQSOSCRDIS);  //MR18, MR19 Disable
+    for(shu_index = DRAM_DFS_SHUFFLE_1; shu_index < DRAM_DFS_SHUFFLE_MAX; shu_index++)
+        vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV) + SHU_GRP_DRAMC_OFFSET*shu_index, 0x1, SHU_SCINTV_DQSOSCENDIS);
+    //vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV), 0x1, SHU_SCINTV_DQSOSCENDIS);
+    //vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_SHU2_SCINTV), 0x1, SHU2_SCINTV_DQSOSCENDIS);
+    //vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_SHU3_SCINTV), 0x1, SHU3_SCINTV_DQSOSCENDIS);
+    vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DRAMC_REG_DUMMY_RD), P_Fld(0x0, DUMMY_RD_DUMMY_RD_EN)
+                                            | P_Fld(0x0, DUMMY_RD_SREF_DMYRD_EN)
+                                            | P_Fld(0x0, DUMMY_RD_DQSG_DMYRD_EN)
+                                            | P_Fld(0x0, DUMMY_RD_DMY_RD_DBG));
+
+    // Disable HW gating tracking first, 0x1c0[31], need to disable both UI and PI tracking or the gating delay reg won't be valid.
+    DramcHWGatingOnOff(p, 0);
+
+    // Disable gating debug
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_STBCAL2), 0, STBCAL2_STB_GERRSTOP);
+
+    for(u1RankIdx=RANK_0; u1RankIdx<RANK_MAX; u1RankIdx++)
+    {
+        vSetRank(p, u1RankIdx);
+
+        // Disable RX delay tracking
+        vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2), 0x0, R0_B0_RXDVS2_R_RK0_RX_DLY_RIS_TRACK_GATE_ENA_B0);
+        vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2), 0x0, R0_B1_RXDVS2_R_RK0_RX_DLY_RIS_TRACK_GATE_ENA_B1);
+
+        vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2), 0x0, R0_B0_RXDVS2_R_RK0_RX_DLY_FAL_TRACK_GATE_ENA_B0);
+        vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2), 0x0, R0_B1_RXDVS2_R_RK0_RX_DLY_FAL_TRACK_GATE_ENA_B1);
+
+        //RX delay mux, delay vlaue from reg.
+        vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2), 0x0, R0_B0_RXDVS2_R_RK0_DVS_MODE_B0);
+        vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2), 0x0, R0_B1_RXDVS2_R_RK0_DVS_MODE_B1);
+        vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_CA_RXDVS2), 0x0, R0_CA_RXDVS2_R_RK0_DVS_MODE_CA);
+    }
+    vSetRank(p, u1RankIdxBak);
+
+    // ARPI_DQ SW mode mux, TX DQ use 1: PHY Reg 0: DRAMC Reg
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 1, MISC_CTRL1_R_DMARPIDQ_SW);
+
+    // Set to all-bank refresh
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0),  0, REFCTRL0_PBREFEN);
+
+    // set MRSRK to 0, MPCRKEN always set 1 (Derping)
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_MRS), 0, MRS_MRSRK);
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_MPC_OPTION), 1, MPC_OPTION_MPCRKEN);
+
+    //RG mode
+    vIO32WriteFldAlign_All(DDRPHY_B0_DQ6, 0x1, B0_DQ6_RG_RX_ARDQ_BIAS_PS_B0);
+    vIO32WriteFldAlign_All(DDRPHY_B1_DQ6, 0x1, B1_DQ6_RG_RX_ARDQ_BIAS_PS_B1);
+    vIO32WriteFldAlign_All(DDRPHY_CA_CMD6, 0x1, CA_CMD6_RG_RX_ARCMD_BIAS_PS);
+
+#if ENABLE_RX_TRACKING_LP4
+    if(u1IsLP4Family(p->dram_type))
+    {
+        DramcRxInputDelayTrackingInit_byFreq(p);
+    }
+#endif
+
+#ifdef LOOPBACK_TEST
+#ifdef LPBK_INTERNAL_EN
+    DramcLoopbackTest_settings(p, 0);   //0: internal loopback test 1: external loopback test
+#else
+    DramcLoopbackTest_settings(p, 1);   //0: internal loopback test 1: external loopback test
+#endif
+#endif
+
+#if EMI_LPBK_DRAM_USED==0
+    DramcLoopbackTest_settings(p, 0);
+#endif
+
+#if ENABLE_TMRRI_NEW_MODE
+    SetCKE2RankIndependent(p);
+#endif
+
+#ifdef DUMMY_READ_FOR_TRACKING
+    if (u1IsLP4Family(p->dram_type))
+    {
+        vIO32WriteFldAlign_All(DRAMC_REG_DUMMY_RD, 1, DUMMY_RD_DMY_RD_RX_TRACK);
+    }
+#endif
+
+    vIO32WriteFldAlign_All(DRAMC_REG_DRSCTRL, 1, DRSCTRL_DRSDIS);
+
+#ifdef IMPEDANCE_TRACKING_ENABLE
+    if(u1IsLP4Family(p->dram_type))
+    {
+        // set correct setting to control IMPCAL HW Tracking in shuffle RG
+        // if p->freq >= 1333, enable IMP HW tracking(SHU1_DRVING1_DIS_IMPCAL_HW=0), else SHU1_DRVING1_DIS_IMPCAL_HW = 1
+        U8 u1DisImpHw;
+
+        u1DisImpHw = (p->frequency >= 1200)?0:1;
+        vIO32WriteFldAlign_All(DRAMC_REG_SHU1_DRVING1, u1DisImpHw, SHU1_DRVING1_DIS_IMPCAL_HW);
+    }
+    else
+    {
+        vIO32WriteFldAlign_All(DRAMC_REG_SHU1_DRVING1, 1, SHU1_DRVING1_DIS_IMPCAL_HW);
+    }
+#else
+    vIO32WriteFldAlign_All(DRAMC_REG_SHU1_DRVING1, 1, SHU1_DRVING1_DIS_IMPCAL_HW);
+    vIO32WriteFldAlign_All(DRAMC_REG_SHU1_DRVING1, 1, SHU1_DRVING1_DIS_IMP_ODTN_TRACK);
+#endif
+}
+
+
+//Reset PHY to prevent glitch when change DQS gating delay or RX DQS input delay
+// [Lynx] Everest : cannot reset single channel. All DramC and All Phy have to reset together.
+void DramPhyReset(DRAMC_CTX_T *p)
+{
+    // Everest change reset order : reset DQS before DQ, move PHY reset to final.
+    if(u1IsLP4Family(p->dram_type))
+    {
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DDRCONF0), 1, DDRCONF0_RDATRST);// read data counter reset
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 1, MISC_CTRL1_R_DMPHYRST);
+
+        //RG_ARCMD_RESETB & RG_ARDQ_RESETB_B0/1 only reset once at init, Justin Chan.
+        ///TODO: need to confirm RG_ARCMD_RESETB & RG_ARDQ_RESETB_B0/1 is reset at mem.c
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ9), P_Fld(0, B0_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B0) |P_Fld(0, B0_DQ9_RG_RX_ARDQ_STBEN_RESETB_B0));
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ9), P_Fld(0, B1_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B1) |P_Fld(0, B1_DQ9_RG_RX_ARDQ_STBEN_RESETB_B1));
+        #ifdef LOOPBACK_TEST
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_CA_CMD10), P_Fld(0, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB) | P_Fld(0, CA_CMD10_RG_RX_ARCMD_STBEN_RESETB));
+        #endif
+
+#if EMI_LPBK_USE_LP3_PINMUX
+vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD10), P_Fld(0, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB) | P_Fld(0, CA_CMD10_RG_RX_ARCMD_STBEN_RESETB));
+vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD10), P_Fld(0, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB) | P_Fld(0, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB));
+#endif
+        mcDELAY_US(1);//delay 10ns
+        #ifdef LOOPBACK_TEST
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_CA_CMD10), P_Fld(1, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB) | P_Fld(1, CA_CMD10_RG_RX_ARCMD_STBEN_RESETB));
+        #endif
+
+#if EMI_LPBK_USE_LP3_PINMUX
+vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD10), P_Fld(1, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB) | P_Fld(1, CA_CMD10_RG_RX_ARCMD_STBEN_RESETB));
+vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD10), P_Fld(1, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB) | P_Fld(1, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB));
+#endif
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ9), P_Fld(1, B1_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B1) | P_Fld(1, B1_DQ9_RG_RX_ARDQ_STBEN_RESETB_B1));
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ9), P_Fld(1, B0_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B0) |P_Fld(1, B0_DQ9_RG_RX_ARDQ_STBEN_RESETB_B0));
+
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 0, MISC_CTRL1_R_DMPHYRST);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DDRCONF0), 0, DDRCONF0_RDATRST);// read data counter reset
+    }
+#if ENABLE_LP3_SW
+    else //LPDDR3
+    {
+        // Everest change : must reset all dramC and PHY together.
+        vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DDRCONF0), 1, DDRCONF0_RDATRST);// read data counter reset
+        vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 1, MISC_CTRL1_R_DMPHYRST);
+
+        //RG_ARCMD_RESETB & RG_ARDQ_RESETB_B0/1 only reset once at init, Justin Chan.
+        ///TODO: need to confirm RG_ARCMD_RESETB & RG_ARDQ_RESETB_B0/1 is reset at mem.c
+        //only in LP3 due to DQ pinmux to CA
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD10), P_Fld(0, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB) |P_Fld(0, CA_CMD10_RG_RX_ARCMD_STBEN_RESETB));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ9), P_Fld(0, B0_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B0) |P_Fld(0, B0_DQ9_RG_RX_ARDQ_STBEN_RESETB_B0));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ9), P_Fld(0, B1_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B1) |P_Fld(0, B1_DQ9_RG_RX_ARDQ_STBEN_RESETB_B1));
+        mcDELAY_US(1);//delay 10ns
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ9), P_Fld(1, B1_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B1) |P_Fld(1, B1_DQ9_RG_RX_ARDQ_STBEN_RESETB_B1));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ9), P_Fld(1, B0_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B0) |P_Fld(1, B0_DQ9_RG_RX_ARDQ_STBEN_RESETB_B0));
+        //only in LP3 due to DQ pinmux to CA
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD10), P_Fld(1, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB) | P_Fld(1, CA_CMD10_RG_RX_ARCMD_STBEN_RESETB));
+        vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 0, MISC_CTRL1_R_DMPHYRST);
+        vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DDRCONF0), 0, DDRCONF0_RDATRST);// read data counter reset
+    }
+#endif
+
+}
+
+
+void DramEyeStbenReset(DRAMC_CTX_T *p)
+{
+    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_GDDR3CTL1), 1, GDDR3CTL1_RDATRST);// read data counter reset
+
+    if(u1IsLP4Family(p->dram_type))
+    {
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 0, B0_DQ5_RG_RX_ARDQ_EYE_STBEN_RESETB_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 0, B1_DQ5_RG_RX_ARDQ_EYE_STBEN_RESETB_B1);
+
+        mcDELAY_US(1);//delay 10ns
+
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_EYE_STBEN_RESETB_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_EYE_STBEN_RESETB_B1);
+    }
+#if ENABLE_LP3_SW
+    else //LPDDR3
+    {
+        vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 0, B0_DQ5_RG_RX_ARDQ_EYE_STBEN_RESETB_B0);
+        vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 0, B1_DQ5_RG_RX_ARDQ_EYE_STBEN_RESETB_B1);
+        vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 0, CA_CMD5_RG_RX_ARCMD_EYE_STBEN_RESETB); //only in LP3 due to DQ pinmux to CA
+
+        mcDELAY_US(1);//delay 10ns
+
+        vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_EYE_STBEN_RESETB_B0);
+        vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_EYE_STBEN_RESETB_B1);
+        vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 1, CA_CMD5_RG_RX_ARCMD_EYE_STBEN_RESETB);//only in LP3 due to DQ pinmux to CA
+    }
+#endif
+}
+
+#if 0
+DRAM_STATUS_T DramcRankSwap(DRAMC_CTX_T *p, U8 u1Rank)
+{
+    U8 u1Multi;
+
+#if 0
+    if (p->support_rank_num > 1)
+        u1Multi = 1;
+    else
+        u1Multi = 0;
+#else
+    //RANK_DUAL or RANK_SINGLE, all set RKMODE to 1
+    u1Multi = 1;
+#endif
+
+    mcSHOW_DBG_MSG(("[RankSwap] Rank num %d, (Multi %d), Rank %d\n", p->support_rank_num, u1Multi, u1Rank));
+    //mcFPRINTF((fp_A60501, "[DramcRankSwap] Rank number %d, (u1Multi %d), Rank %d\n", p->support_rank_num, u1Multi, u1Rank));
+
+    //Set to non-zero for multi-rank
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), u1Multi, RKCFG_RKMODE);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), u1Rank, RKCFG_RKSWAP);
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), u1Rank, RKCFG_TXRANK); //use other rank's setting //TXRANK should be set before TXRANKFIX
+
+    if (u1Rank == 0)
+    {
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANKFIX);
+    }
+    else
+    {
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 1, RKCFG_TXRANKFIX);
+    }
+
+    return DRAM_OK;
+}
+#endif
+
+DRAM_STATUS_T DramcStartDQSOSC(DRAMC_CTX_T *p)
+{
+    U32 u4Response;
+    U32 u4TimeCnt;
+
+    u4TimeCnt = TIME_OUT_CNT;
+    mcSHOW_DBG_MSG(("[DQSOSC]\n"));
+
+    //R_DMDQSOSCENEN, 0x1E4[10]=1 for DQSOSC Start
+    //Wait dqsoscen_response=1 (dramc_conf_nao, 0x3b8[29])
+    //R_DMDQSOSCENEN, 0x1E4[10]=0
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_DQSOSCENEN);
+    do
+    {
+        u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_DQSOSCEN_RESPONSE);
+        u4TimeCnt --;
+        mcDELAY_US(1);
+    }while((u4Response==0) &&(u4TimeCnt>0));
+
+    if(u4TimeCnt==0)//time out
+    {
+        mcSHOW_DBG_MSG(("Start fail (time out)\n"));
+        //mcFPRINTF((fp_A60501, "[DramcStartDQSOSC]  Start fail (time out)\n"));
+        return DRAM_FAIL;
+    }
+    else
+    {
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_DQSOSCENEN);
+    }
+
+    return DRAM_OK;
+}
+
+
+DRAM_STATUS_T DramcDQSOSCAuto(DRAMC_CTX_T *p)
+{
+    U8 u1MR23 = gu1MR23[p->channel][p->rank], shu_index;
+    U16 u2MR18, u2MR19;
+    U16 u2DQSCnt;
+    U16 u2DQSOsc[2];
+    U32 u4RegBak[3];
+
+#if MRW_CHECK_ONLY
+    mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
+#endif
+
+    u4RegBak[0] = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_MRS));
+    u4RegBak[1] = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL));
+    u4RegBak[2] = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL));
+
+    //!!R_DMMRSRK(R_DMMPCRKEN=1) specify rank0 or rank1
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_DQSOSC2RK);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRS), u1GetRank(p), MRS_MRSRK);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MPC_OPTION), 1, MPC_OPTION_MPCRKEN);
+
+    //LPDDR4-3200,     PI resolution = tCK/64 =9.76ps
+    //Only if MR23>=16, then error < PI resolution.
+    //Set MR23 == 0x3f, stop after 63*16 clock
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRS), u1GetRank(p), MRS_MRSRK);
+    DramcModeRegWrite(p, 23, u1MR23);
+
+    //SW mode
+    for(shu_index = DRAM_DFS_SHUFFLE_1; shu_index < DRAM_DFS_SHUFFLE_MAX; shu_index++)
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV) + SHU_GRP_DRAMC_OFFSET*shu_index, 1, SHU_SCINTV_DQSOSCENDIS);
+    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV), 1, SHU_SCINTV_DQSOSCENDIS);
+    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU2_SCINTV), 1, SHU2_SCINTV_DQSOSCENDIS);
+    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU3_SCINTV), 1, SHU3_SCINTV_DQSOSCENDIS);
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 1, DRAMC_PD_CTRL_MIOCKCTRLOFF);   //MIOCKCTRLOFF=1
+
+    CKEFixOnOff(p, p->rank, CKE_FIXON, CKE_WRITE_TO_ONE_CHANNEL);
+
+    DramcStartDQSOSC(p);
+    mcDELAY_US(1);
+#if ENABLE_TMRRI_NEW_MODE
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRS), u1GetRank(p), MRS_MRSRK);
+#else
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRS), u1GetRank(p), MRS_MRRRK);
+#endif
+    DramcModeRegRead(p, 18, &u2MR18);
+    DramcModeRegRead(p, 19, &u2MR19);
+
+
+#if (SW_CHANGE_FOR_SIMULATION==0)
+    //B0
+    u2DQSCnt = (u2MR18 & 0x00FF) | ((u2MR19 & 0x00FF) <<8);
+    if(u2DQSCnt !=0)
+        u2DQSOsc[0] = u1MR23*16*1000000/(2 * u2DQSCnt * p->frequency); //tDQSOSC = 16*MR23*tCK/2*count
+    else
+        u2DQSOsc[0] = 0;
+
+    //B1
+    u2DQSCnt = (u2MR18 >> 8) | ((u2MR19 & 0xFF00));
+    if(u2DQSCnt !=0)
+        u2DQSOsc[1] = u1MR23*16*1000000/(2 * u2DQSCnt * p->frequency); //tDQSOSC = 16*MR23*tCK/2*count
+    else
+        u2DQSOsc[1] = 0;
+    mcSHOW_DBG_MSG(("[DQSOSCAuto] RK%d, (LSB)MR18= 0x%x, (MSB)MR19= 0x%x, tDQSOscB0 = %d ps tDQSOscB1 = %d ps\n", u1GetRank(p), u2MR18, u2MR19, u2DQSOsc[0], u2DQSOsc[1]));
+#endif
+
+    gu2MR18[p->channel][p->rank] = u2MR18;
+    gu2MR19[p->channel][p->rank] = u2MR19;
+    gu2DQSOSC[p->channel][p->rank] = u2DQSOsc[0];
+
+    if(u2DQSOsc[1]!=0 && u2DQSOsc[1]<u2DQSOsc[0])
+        gu2DQSOSC[p->channel][p->rank] = u2DQSOsc[1];
+
+    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_MRS), u4RegBak[0]);
+    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), u4RegBak[1]);
+    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL), u4RegBak[2]);
+
+    /* Starting from Vinson, MR23 should be 0x3F for all case ("HW tracking modify" DVT)
+     * -> Value is already set in during gu1MR23 array init
+     * The below code snippet is used for KIBO/Alaska/Whitney E2 projects
+     * (Adjusts MR23 according to freq, since back then _INC _DEC bit's weren't sufficient)
+     */
+#if 0
+    if(gu1MR23Done==FALSE)
+    {
+        DRAM_CHANNEL_T chIdx = CHANNEL_A;
+        DRAM_RANK_T rankIdx = RANK_0;
+        if(gu2DQSOSC[p->channel][p->rank]>500)
+        {
+            u1MR23 = 0x30;
+        }
+        else if(gu2DQSOSC[p->channel][p->rank]>350)
+        {
+            u1MR23 = 0x20;
+        }
+        else
+        {
+            u1MR23 = 0x10;
+        }
+        for(chIdx=CHANNEL_A; chIdx<p->support_channel_num; chIdx++)
+        {
+            for(rankIdx=RANK_0; rankIdx<RANK_MAX; rankIdx++)
+            {
+                gu1MR23[chIdx][rankIdx] = u1MR23;
+            }
+        }
+        mcSHOW_DBG_MSG(("Update MR23=%d\n", u1MR23));
+        gu1MR23Done = TRUE;
+    }
+#endif
+
+    return DRAM_OK;
+}
+
+#if 1
+/* Using gu2DQSOSC results calculated from DramcDQSOSCAuto
+ * -> calculate DQSOSCTHRD_INC, DQSOSCTHRD_DEC
+ * _INC, _DEC formulas are extracted from "Verification plan of Vinson LPDDR4 HW TX Tracking" doc
+ */
+DRAM_STATUS_T DramcDQSOSCMR23(DRAMC_CTX_T *p)
+{
+#if (SW_CHANGE_FOR_SIMULATION==0)
+#if 1
+    /* Preloader doesn't support floating point numbers -> Manually expand/simpify _INC, _DEC formula */
+    U8 u1MR23 = gu1MR23[p->channel][p->rank];
+    U16 u2DQSOSC = gu2DQSOSC[p->channel][p->rank];
+    U32 u4tCK = 1000000 / p->frequency;
+
+    if(u2DQSOSC !=0)
+    {
+        gu2DQSOSCTHRD_INC[p->channel][p->rank] = (3 * u1MR23 * u4tCK * u4tCK) / (u2DQSOSC * u2DQSOSC * 20);
+        gu2DQSOSCTHRD_DEC[p->channel][p->rank] = (u1MR23 * u4tCK * u4tCK) / (u2DQSOSC * u2DQSOSC * 10);
+    }
+#else
+    /* Formulas implemented directly as mentioned (using floating point numbers) */
+    #define DQSOSC_ALPHA 0.2
+    /*
+     * actualAlpha, tickTime, goldenMR23 formulas are extracted from
+     * "Vinson HW TX Tracking Modify" DVT document's excel file
+     */
+    float actualAlpha = DQSOSC_ALPHA/((1600/(float)p->frequency)*(1600/(float)p->frequency)); //DDR3200's alpha = 0.2, use it as base
+    float tickTime = (1/(float)p->frequency)*1000000;
+    float goldenMR23 = (2*4/DQSOSC_ALPHA)*(((float)u2DQSOSC/tickTime)*((float)u2DQSOSC/tickTime));
+
+    /* (Floating point + 0.5) and truncated into unsigned integer -> roundup floating point number */
+    gu2DQSOSCTHRD_INC[p->channel][p->rank] = (5*1.2*((float)u4MR23/goldenMR23)+0.5);
+    gu2DQSOSCTHRD_DEC[p->channel][p->rank] = (5*0.8*((float)u4MR23/goldenMR23)+0.5);
+#endif
+    mcSHOW_DBG_MSG(("CH%d_RK%d: MR19=0x%X, MR18=0x%X, DQSOSC=%d, MR23=%u, INC=%u, DEC=%u\n", p->channel, p->rank,
+                    gu2MR19[p->channel][p->rank], gu2MR18[p->channel][p->rank], gu2DQSOSC[p->channel][p->rank],
+                    u1MR23, gu2DQSOSCTHRD_INC[p->channel][p->rank], gu2DQSOSCTHRD_DEC[p->channel][p->rank]));
+#endif
+    return DRAM_OK;
+}
+#else
+/* Used for previous projects (before Vinson) */
+DRAM_STATUS_T DramcDQSOSCMR23(DRAMC_CTX_T *p)
+{
+#if (SW_CHANGE_FOR_SIMULATION==0)
+    U16 u2DQSOSC = gu2DQSOSC[p->channel][p->rank];
+    U32 u4tCK = 1000000/p->frequency;
+    U32 u4RunTime = (32*4*5*(u2DQSOSC*u2DQSOSC)/(u4tCK*u4tCK))+1;
+    //U32 u4MR23 = (u4RunTime/16)+1;
+    U32 u4MR23 = gu1MR23[p->channel][p->rank];
+
+    gu2DQSOSCTHRD_INC[p->channel][p->rank] = (6*u4MR23*16)/(u4RunTime);
+    gu2DQSOSCTHRD_DEC[p->channel][p->rank] = (4*u4MR23*16)/(u4RunTime);
+    mcSHOW_DBG_MSG(("CH%d_RK%d: MR19=%X, MR18=%X, DQSOSC=%d, Runtime=%d, MR23=%d, INC=%d, DEC=%d\n",
+        p->channel, p->rank, gu2MR19[p->channel][p->rank], gu2MR18[p->channel][p->rank], gu2DQSOSC[p->channel][p->rank],
+        u4RunTime,u4MR23, gu2DQSOSCTHRD_INC[p->channel][p->rank], gu2DQSOSCTHRD_DEC[p->channel][p->rank]));
+#endif
+    return DRAM_OK;
+}
+#endif
+
+/* Sets DQSOSC_BASE for specified rank/byte */
+DRAM_STATUS_T DramcDQSOSCSetMR18MR19(DRAMC_CTX_T *p)
+{
+    U16 u2DQSOscCnt[2];
+    DramcDQSOSCAuto(p);
+
+    //B0
+    gu2DQSOscCnt[p->channel][p->rank][0] = u2DQSOscCnt[0] = (gu2MR18[p->channel][p->rank] & 0x00FF) | ((gu2MR19[p->channel][p->rank] & 0x00FF) <<8);
+    //B1
+    gu2DQSOscCnt[p->channel][p->rank][1] = u2DQSOscCnt[1] = (gu2MR18[p->channel][p->rank] >> 8) | ((gu2MR19[p->channel][p->rank] & 0xFF00));
+
+    if((p->dram_cbt_mode[p->rank]==CBT_NORMAL_MODE) && (gu2DQSOscCnt[p->channel][p->rank][1]==0))
+    {
+        gu2DQSOscCnt[p->channel][p->rank][1] = u2DQSOscCnt[1] = u2DQSOscCnt[0];
+    }
+
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_DQSOSC), P_Fld(u2DQSOscCnt[0], SHU1RK0_DQSOSC_DQSOSC_BASE_RK0)| P_Fld(u2DQSOscCnt[1], SHU1RK0_DQSOSC_DQSOSC_BASE_RK0_B1));
+
+    mcSHOW_DBG_MSG(("CH%d RK%d: MR19=%X, MR18=%X\n", p->channel, p->rank, gu2MR19[p->channel][p->rank], gu2MR18[p->channel][p->rank]));
+    return DRAM_OK;
+}
+
+DRAM_STATUS_T DramcDQSOSCShuSettings(DRAMC_CTX_T *p)
+{
+    U16 u2PRDCNT = 0x3FF;
+    U16 u2DQSOSCENCNT = 0x1FF;
+    U16 u2Thrd_inc, u2Thrd_dec;
+    U8 u1FILT_PITHRD = 0;
+    U8 u1W2R_SEL = 0;
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV),  0x0, SHU_SCINTV_DQS2DQ_SHU_PITHRD);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK0_DQSOSC),  0x0, RK0_DQSOSC_R_DMDQS2DQ_FILT_OPT);
+    if(p->frequency<=400)
+    {
+        u1FILT_PITHRD = 0x4;
+        u1W2R_SEL = 0x5;
+    }
+    else if(p->frequency<=600)
+    {
+        u1FILT_PITHRD = 0x6;
+        u1W2R_SEL = 0x5;
+    }
+    else if(p->frequency<=800)
+    {
+        u1FILT_PITHRD = 0x7;
+        u1W2R_SEL = 0x5;
+    }
+    else if(p->frequency<=1200)
+    {
+        u1FILT_PITHRD = 0xb;
+        u1W2R_SEL = 0x2;
+    }
+    else if(p->frequency<=1333)
+    {
+        u1FILT_PITHRD = 0xc;
+        u1W2R_SEL = 0x2;
+    }
+    else if(p->frequency<=1600)
+    {
+        u1FILT_PITHRD = 0xE;
+        u1W2R_SEL = 0x2;
+    }
+    else if(p->frequency<=1866)
+    {
+        u1FILT_PITHRD = 0x12;
+        u1W2R_SEL = 0x2;
+    }
+    else    //4266
+    {
+        u1FILT_PITHRD = 0x15;
+        u1W2R_SEL = 0x2;
+    }
+
+    u2PRDCNT = (gu1MR23[p->channel][RANK_0]/4)+3;
+    if (p->support_rank_num==RANK_DUAL)
+    {
+        if(gu1MR23[p->channel][RANK_0]>gu1MR23[p->channel][RANK_1])
+            u2PRDCNT = (gu1MR23[p->channel][RANK_0]/4)+3;
+        else
+            u2PRDCNT = (gu1MR23[p->channel][RANK_1]/4)+3;
+    }
+
+    //Don't power down dram during DQS interval timer run time, (MR23[7:0] /4) + (tOSCO/MCK unit/16)
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1_DQSOSC_PRD), u2PRDCNT, SHU1_DQSOSC_PRD_DQSOSC_PRDCNT);
+
+    //set tOSCO constraint to read MR18/MR19, should be > 40ns/MCK
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_DQSOSCR), ((p->frequency-1)/100)+1, SHU_DQSOSCR_DQSOSCRCNT);//unit: MCK to meet spec. tOSCO
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV),  u1FILT_PITHRD, SHU_SCINTV_DQS2DQ_FILT_PITHRD);
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU1_WODT),  P_Fld(u1W2R_SEL, SHU1_WODT_TXUPD_W2R_SEL) | P_Fld(0x0, SHU1_WODT_TXUPD_SEL));
+
+    /* Starting from Vinson, DQSOSCTHRD_INC & _DEC is split into RK0 and RK1 */
+    //Rank 0
+    u2Thrd_inc = gu2DQSOSCTHRD_INC[p->channel][RANK_0];
+    u2Thrd_dec = gu2DQSOSCTHRD_DEC[p->channel][RANK_0];
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_DQSOSCTHRD), u2Thrd_inc, SHU_DQSOSCTHRD_DQSOSCTHRD_INC_RK0);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_DQSOSCTHRD), u2Thrd_dec, SHU_DQSOSCTHRD_DQSOSCTHRD_DEC_RK0);
+
+    //Rank 1
+    u2Thrd_inc = gu2DQSOSCTHRD_INC[p->channel][RANK_1];
+    u2Thrd_dec = gu2DQSOSCTHRD_DEC[p->channel][RANK_1];
+    /* DQSOSCTHRD_INC_RK1 is split into 2 register fields (starting from Vinson) */
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_DQSOSCTHRD), (u2Thrd_inc & 0x0FF), SHU_DQSOSCTHRD_DQSOSCTHRD_INC_RK1_7TO0);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1_DQSOSC_PRD), ((u2Thrd_inc & 0xF00) >> 8), SHU1_DQSOSC_PRD_DQSOSCTHRD_INC_RK1_11TO8);
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1_DQSOSC_PRD), u2Thrd_dec, SHU1_DQSOSC_PRD_DQSOSCTHRD_DEC_RK1);
+
+    //set interval to do MPC(start DQSOSC) command, and dramc send DQSOSC start to rank0/1/2 at the same time
+    //TX tracking period unit: 3.9us
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_DQSOSCR2), u2DQSOSCENCNT, SHU_DQSOSCR2_DQSOSCENCNT);
+
+    return DRAM_OK;
+}
+
+void DramcHwDQSOSCSetFreqRatio(DRAMC_CTX_T *p)
+{
+#if 0
+    //for SHUFFLE_1
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_RK2_DQSOSC), P_Fld((U16)(gFreqTbl[1].frequency*8/gFreqTbl[0].frequency), RK2_DQSOSC_FREQ_RATIO_TX_0)
+                                                            | P_Fld((U16)(gFreqTbl[2].frequency*8/gFreqTbl[0].frequency), RK2_DQSOSC_FREQ_RATIO_TX_1));
+    //for SHUFFLE_2
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_RK2_DQSOSC), P_Fld((U16)(gFreqTbl[0].frequency*8/gFreqTbl[1].frequency), RK2_DQSOSC_FREQ_RATIO_TX_3)
+                                                            | P_Fld((U16)(gFreqTbl[2].frequency*8/gFreqTbl[1].frequency), RK2_DQSOSC_FREQ_RATIO_TX_4));
+    //for SHUFFLE_3
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_RK2_DUMMY_RD_BK), P_Fld((U16)(gFreqTbl[0].frequency*8/gFreqTbl[2].frequency), RK2_DUMMY_RD_BK_FREQ_RATIO_TX_6)
+                                                            | P_Fld((U16)(gFreqTbl[1].frequency*8/gFreqTbl[2].frequency), RK2_DUMMY_RD_BK_FREQ_RATIO_TX_7));
+
+    //for SHUFFLE_4
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_PRE_TDQSCK1), P_Fld(1, PRE_TDQSCK1_SHU_PRELOAD_TX_HW)
+                                                            | P_Fld(0, PRE_TDQSCK1_SHU_PRELOAD_TX_START)
+                                                            | P_Fld(0, PRE_TDQSCK1_SW_UP_TX_NOW_CASE));
+
+#endif
+    mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_0=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DQSOSC), RK2_DQSOSC_FREQ_RATIO_TX_0)));
+    mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_1=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DQSOSC), RK2_DQSOSC_FREQ_RATIO_TX_1)));
+    mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_2=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DQSOSC), RK2_DQSOSC_FREQ_RATIO_TX_2)));
+    mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_3=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DQSOSC), RK2_DQSOSC_FREQ_RATIO_TX_3)));
+    mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_4=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DQSOSC), RK2_DQSOSC_FREQ_RATIO_TX_4)));
+    mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_5=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DQSOSC), RK2_DQSOSC_FREQ_RATIO_TX_5)));
+    mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_6=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DUMMY_RD_BK), RK2_DUMMY_RD_BK_FREQ_RATIO_TX_6)));
+    mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_7=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DUMMY_RD_BK), RK2_DUMMY_RD_BK_FREQ_RATIO_TX_7)));
+    mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_8=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DUMMY_RD_BK), RK2_DUMMY_RD_BK_FREQ_RATIO_TX_8)));
+    mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_9=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DQSOSC), RK2_DQSOSC_FREQ_RATIO_TX_0)));
+    mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_9=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PRE_TDQSCK1), PRE_TDQSCK1_FREQ_RATIO_TX_9)));
+    mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_10=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PRE_TDQSCK1), PRE_TDQSCK1_FREQ_RATIO_TX_10)));
+    mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_11=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PRE_TDQSCK1), PRE_TDQSCK1_FREQ_RATIO_TX_11)));
+}
+
+void DramcHwDQSOSC(DRAMC_CTX_T *p)
+{
+    U8 shu_index;
+    DRAM_RANK_T rank_bak = u1GetRank(p);
+    DRAM_CHANNEL_T ch_bak = p->channel;
+
+    DramcHwDQSOSCSetFreqRatio(p);
+
+    //DQSOSC MPC command violation
+#if ENABLE_TMRRI_NEW_MODE
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MPC_OPTION), 1, MPC_OPTION_MPC_BLOCKALE_OPT);
+#else
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MPC_OPTION), 0, MPC_OPTION_MPC_BLOCKALE_OPT);
+#endif
+
+    //DQS2DQ UI/PI setting controlled by HW
+    #if ENABLE_SW_TX_TRACKING
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 1, MISC_CTRL1_R_DMARPIDQ_SW);
+    #else
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 0, MISC_CTRL1_R_DMARPIDQ_SW);
+    #endif
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 1, DQSOSCR_ARUIDQ_SW);
+
+    //Set dqsosc oscillator run time by MRW
+    //write RK0 MR23
+    #if 0
+    U8 u1MR23 = 0x3F;
+    vSetRank(p, RANK_0);
+    vSetPHY2ChannelMapping(p, CHANNEL_A);
+    DramcModeRegWrite(p, 23, u1MR23);
+    vSetPHY2ChannelMapping(p, CHANNEL_B);
+    DramcModeRegWrite(p, 23, u1MR23);
+    //write RK1 MR23
+    vSetRank(p, RANK_1);
+    vSetPHY2ChannelMapping(p, CHANNEL_A);
+    DramcModeRegWrite(p, 23, u1MR23);
+    vSetPHY2ChannelMapping(p, CHANNEL_B);
+    DramcModeRegWrite(p, 23, u1MR23);
+    #endif
+
+    //Enable HW read MR18/MR19 for each rank
+    #if ENABLE_SW_TX_TRACKING
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 1, DQSOSCR_DQSOSCRDIS);
+    #else
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 0, DQSOSCR_DQSOSCRDIS);
+    #endif
+
+    vSetRank(p, RANK_0);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK0_DQSOSC), 1, RK0_DQSOSC_DQSOSCR_RK0EN);
+    if (p->support_rank_num == RANK_DUAL)
+    {
+        vSetRank(p, RANK_1);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK1_DQSOSC), 1, RK1_DQSOSC_DQSOSCR_RK1EN);
+    }
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRSCTRL), 1, DRSCTRL_DRSCLR_RK0_EN); //Set as 1 to fix issue of single rank, dual rank can also be enable
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 1, DQSOSCR_DQSOSC_CALEN);
+
+    //enable DQSOSC HW mode
+    #if ENABLE_SW_TX_TRACKING
+    for(shu_index = DRAM_DFS_SHUFFLE_1; shu_index < DRAM_DFS_SHUFFLE_MAX; shu_index++)
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV) + SHU_GRP_DRAMC_OFFSET*shu_index, 1, SHU_SCINTV_DQSOSCENDIS);
+    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV), 1, SHU_SCINTV_DQSOSCENDIS);
+    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU2_SCINTV), 1, SHU2_SCINTV_DQSOSCENDIS);
+    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU3_SCINTV), 1, SHU3_SCINTV_DQSOSCENDIS);
+    #else
+    for(shu_index = DRAM_DFS_SHUFFLE_1; shu_index < DRAM_DFS_SHUFFLE_MAX; shu_index++)
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV) + SHU_GRP_DRAMC_OFFSET*shu_index, 0, SHU_SCINTV_DQSOSCENDIS);
+    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV), 0, SHU_SCINTV_DQSOSCENDIS);
+    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU2_SCINTV), 0, SHU2_SCINTV_DQSOSCENDIS);
+    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU3_SCINTV), 0, SHU3_SCINTV_DQSOSCENDIS);
+    #endif
+
+    vSetRank(p, rank_bak);
+    vSetPHY2ChannelMapping(p, ch_bak);
+}
+
+#if ENABLE_SW_TX_TRACKING & __ETT__
+void DramcSWTxTracking(DRAMC_CTX_T *p)
+{
+    U8 u1MR4OnOff = 1;
+    U8 rankIdx = RANK_0;
+    U8 u1ShuLevel = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHUSTATUS), SHUSTATUS_SHUFFLE_LEVEL);
+    U16 u2DramcOffset = SHU_GRP_DRAMC_OFFSET * u1ShuLevel;
+    U16 u2MR1819_Base[CHANNEL_NUM][RANK_MAX][2];
+    U16 u2MR1819_Runtime[CHANNEL_NUM][RANK_MAX][2];
+    U16 u2DQSOSC_INC[RANK_MAX] = {6}, u2DQSOSC_DEC[RANK_MAX] = {4};
+    U8 u1AdjPI[RANK_MAX][2];
+    U8 u1OriginalPI_DQ[DRAM_DFS_SHUFFLE_MAX][RANK_MAX][2];
+    U8 u1UpdatedPI_DQ[DRAM_DFS_SHUFFLE_MAX][RANK_MAX][2];
+    U8 u1OriginalPI_DQM[DRAM_DFS_SHUFFLE_MAX][RANK_MAX][2];
+    U8 u1UpdatedPI_DQM[DRAM_DFS_SHUFFLE_MAX][RANK_MAX][2];
+    U8 u1FreqRatioTX[DRAM_DFS_SHUFFLE_MAX];
+    U8 shuIdx=0;
+
+    for(shuIdx=0; shuIdx<DRAM_DFS_SHUFFLE_MAX; shuIdx++)
+    {
+        u1FreqRatioTX[shuIdx] = (gFreqTbl[shuIdx].frequency*8/gFreqTbl[u1ShuLevel].frequency);
+        mcSHOW_DBG_MSG(("[SWTxTracking] ShuLevel=%d, Ratio[%d]=%d", u1ShuLevel, shuIdx, u1FreqRatioTX[shuIdx]));
+    }
+
+    vSetRank(p, RANK_0);
+
+    /* Starting from Vinson, DQSOSCTHRD_INC & _DEC is split into RK0 and RK1 */
+    //Rank 0
+    u2DQSOSC_INC[RANK_0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_DQSOSCTHRD) + u2DramcOffset, SHU_DQSOSCTHRD_DQSOSCTHRD_INC_RK0);
+    u2DQSOSC_DEC[RANK_0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_DQSOSCTHRD) + u2DramcOffset, SHU_DQSOSCTHRD_DQSOSCTHRD_DEC_RK0);
+
+
+    /* DQSOSCTHRD_INC_RK1 is split into 2 register fields (starting from Vinson) */
+    //Rank 1
+    u2DQSOSC_INC[RANK_1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1_DQSOSC_PRD) + u2DramcOffset, SHU1_DQSOSC_PRD_DQSOSCTHRD_INC_RK1_11TO8);
+    u2DQSOSC_INC[RANK_1] = u2DQSOSC_INC[RANK_1] << 8; /* Shift [3:0] to correct position [11:8] */
+    u2DQSOSC_INC[RANK_1] = u2DQSOSC_INC[RANK_1] | u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_DQSOSCTHRD) + u2DramcOffset, SHU_DQSOSCTHRD_DQSOSCTHRD_INC_RK1_7TO0);
+
+    u2DQSOSC_DEC[RANK_1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1_DQSOSC_PRD) + u2DramcOffset, SHU1_DQSOSC_PRD_DQSOSCTHRD_DEC_RK1);
+
+    for(shuIdx=0; shuIdx<DRAM_DFS_SHUFFLE_MAX; shuIdx++)
+    {
+        u1OriginalPI_DQ[shuIdx][RANK_0][0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_PI)+(SHU_GRP_DRAMC_OFFSET * shuIdx), SHU1RK0_PI_RK0_ARPI_DQ_B0);
+        u1OriginalPI_DQ[shuIdx][RANK_0][1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_PI)+(SHU_GRP_DRAMC_OFFSET * shuIdx), SHU1RK0_PI_RK0_ARPI_DQ_B1);
+        u1OriginalPI_DQ[shuIdx][RANK_1][0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK1_PI)+(SHU_GRP_DRAMC_OFFSET * shuIdx), SHU1RK1_PI_RK1_ARPI_DQ_B0);
+        u1OriginalPI_DQ[shuIdx][RANK_1][1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK1_PI)+(SHU_GRP_DRAMC_OFFSET * shuIdx), SHU1RK1_PI_RK1_ARPI_DQ_B1);
+
+        u1OriginalPI_DQM[shuIdx][RANK_0][0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_PI)+(SHU_GRP_DRAMC_OFFSET * shuIdx), SHU1RK0_PI_RK0_ARPI_DQM_B0);
+        u1OriginalPI_DQM[shuIdx][RANK_0][1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_PI)+(SHU_GRP_DRAMC_OFFSET * shuIdx), SHU1RK0_PI_RK0_ARPI_DQM_B1);
+        u1OriginalPI_DQM[shuIdx][RANK_1][0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK1_PI)+(SHU_GRP_DRAMC_OFFSET * shuIdx), SHU1RK1_PI_RK1_ARPI_DQM_B0);
+        u1OriginalPI_DQM[shuIdx][RANK_1][1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK1_PI)+(SHU_GRP_DRAMC_OFFSET * shuIdx), SHU1RK1_PI_RK1_ARPI_DQM_B1);
+    }
+
+    u2MR1819_Base[p->channel][RANK_0][0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_DQSOSC)+u2DramcOffset, SHU1RK0_DQSOSC_DQSOSC_BASE_RK0);
+    u2MR1819_Base[p->channel][RANK_0][1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_DQSOSC)+u2DramcOffset, SHU1RK0_DQSOSC_DQSOSC_BASE_RK0_B1);
+    u2MR1819_Base[p->channel][RANK_1][0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK1_DQSOSC)+u2DramcOffset, SHU1RK1_DQSOSC_DQSOSC_BASE_RK1);
+    u2MR1819_Base[p->channel][RANK_1][1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK1_DQSOSC)+u2DramcOffset, SHU1RK1_DQSOSC_DQSOSC_BASE_RK1_B1);
+
+    u1MR4OnOff = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), SPCMDCTRL_REFRDIS);
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), 1, SPCMDCTRL_REFRDIS);
+    for(rankIdx=RANK_0; rankIdx<p->support_rank_num; rankIdx++)
+    {
+        U8 byteIdx=0;
+
+        vSetRank(p, rankIdx);
+        DramcDQSOSCAuto(p);
+        u2MR1819_Runtime[p->channel][p->rank][0] = (gu2MR18[p->channel][p->rank] & 0x00FF) | ((gu2MR19[p->channel][p->rank] & 0x00FF) <<8);
+        if(p->dram_cbt_mode[p->rank]==CBT_BYTE_MODE1)
+        {
+            u2MR1819_Runtime[p->channel][p->rank][1] = (gu2MR18[p->channel][p->rank] >> 8) | ((gu2MR19[p->channel][p->rank] & 0xFF00));
+        }
+        else
+        {
+            u2MR1819_Runtime[p->channel][p->rank][1] = u2MR1819_Runtime[p->channel][p->rank][0];
+        }
+        //INC : MR1819>base. PI-
+        //DEC : MR1819<base. PI+
+        for(byteIdx=0; byteIdx<2; byteIdx++)
+        {
+            U16 deltaMR1819=0;
+
+            if(u2MR1819_Runtime[p->channel][p->rank][byteIdx] >= u2MR1819_Base[p->channel][p->rank][byteIdx])
+            {
+                deltaMR1819  = u2MR1819_Runtime[p->channel][p->rank][byteIdx] - u2MR1819_Base[p->channel][p->rank][byteIdx];
+                u1AdjPI[rankIdx][byteIdx] = deltaMR1819/u2DQSOSC_INC[rankIdx];
+                for(shuIdx=0; shuIdx<DRAM_DFS_SHUFFLE_MAX; shuIdx++)
+                {
+                    u1UpdatedPI_DQ[shuIdx][rankIdx][byteIdx] = u1OriginalPI_DQ[shuIdx][rankIdx][byteIdx] - (u1AdjPI[rankIdx][byteIdx]*u1FreqRatioTX[shuIdx]/u1FreqRatioTX[u1ShuLevel]);
+                    u1UpdatedPI_DQM[shuIdx][rankIdx][byteIdx] = u1OriginalPI_DQM[shuIdx][rankIdx][byteIdx] - (u1AdjPI[rankIdx][byteIdx]*u1FreqRatioTX[shuIdx]/u1FreqRatioTX[u1ShuLevel]);
+                    mcSHOW_DBG_MSG(("SHU%u CH%d RK%d B%d, Base=%X Runtime=%X delta=%d INC=%d PI=0x%B Adj=%d newPI=0x%B\n", shuIdx, p->channel, u1GetRank(p), byteIdx
+                            , u2MR1819_Base[p->channel][p->rank][byteIdx], u2MR1819_Runtime[p->channel][p->rank][byteIdx], deltaMR1819, u2DQSOSC_INC[rankIdx]
+                            , u1OriginalPI_DQ[shuIdx][rankIdx][byteIdx], (u1AdjPI[rankIdx][byteIdx]*u1FreqRatioTX[shuIdx]/u1FreqRatioTX[u1ShuLevel]), u1UpdatedPI_DQ[shuIdx][rankIdx][byteIdx]));
+                }
+            }
+            else
+            {
+                deltaMR1819  = u2MR1819_Base[p->channel][p->rank][byteIdx] - u2MR1819_Runtime[p->channel][p->rank][byteIdx];
+                u1AdjPI[rankIdx][byteIdx] = deltaMR1819/u2DQSOSC_DEC[rankIdx];
+                for(shuIdx=0; shuIdx<DRAM_DFS_SHUFFLE_MAX; shuIdx++)
+                {
+                    u1UpdatedPI_DQ[shuIdx][rankIdx][byteIdx] = u1OriginalPI_DQ[shuIdx][rankIdx][byteIdx] + (u1AdjPI[rankIdx][byteIdx]*u1FreqRatioTX[shuIdx]/u1FreqRatioTX[u1ShuLevel]);
+                    u1UpdatedPI_DQM[shuIdx][rankIdx][byteIdx] = u1OriginalPI_DQM[shuIdx][rankIdx][byteIdx] + (u1AdjPI[rankIdx][byteIdx]*u1FreqRatioTX[shuIdx]/u1FreqRatioTX[u1ShuLevel]);
+                    mcSHOW_DBG_MSG(("SHU%u CH%d RK%d B%d, Base=%X Runtime=%X delta=%d DEC=%d PI=0x%B Adj=%d newPI=0x%B\n", shuIdx, p->channel,u1GetRank(p), byteIdx
+                            , u2MR1819_Base[p->channel][p->rank][byteIdx], u2MR1819_Runtime[p->channel][p->rank][byteIdx], deltaMR1819, u2DQSOSC_DEC[rankIdx]
+                            , u1OriginalPI_DQ[shuIdx][rankIdx][byteIdx], (u1AdjPI[rankIdx][byteIdx]*u1FreqRatioTX[shuIdx]/u1FreqRatioTX[u1ShuLevel]), u1UpdatedPI_DQ[shuIdx][rankIdx][byteIdx]));
+                }
+            }
+        }
+    }
+
+    vSetRank(p, RANK_0);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 1, DQSOSCR_TXUPDMODE);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 1, DQSOSCR_MANUTXUPD);
+
+    for(shuIdx=0; shuIdx<DRAM_DFS_SHUFFLE_MAX; shuIdx++)
+    {
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7)+(SHU_GRP_DDRPHY_OFFSET * shuIdx), P_Fld(u1UpdatedPI_DQ[shuIdx][RANK_0][0], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0)
+                                                                 | P_Fld(u1UpdatedPI_DQM[shuIdx][RANK_0][0], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0));
+
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7)+(SHU_GRP_DDRPHY_OFFSET * shuIdx), P_Fld(u1UpdatedPI_DQ[shuIdx][RANK_0][1], SHU1_R0_B1_DQ7_RK0_ARPI_DQ_B1)
+                                                                 | P_Fld(u1UpdatedPI_DQM[shuIdx][RANK_0][1], SHU1_R0_B1_DQ7_RK0_ARPI_DQM_B1));
+
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R1_B0_DQ7)+(SHU_GRP_DDRPHY_OFFSET * shuIdx), P_Fld(u1UpdatedPI_DQ[shuIdx][RANK_1][0], SHU1_R1_B0_DQ7_RK1_ARPI_DQ_B0)
+                                                                 | P_Fld(u1UpdatedPI_DQM[shuIdx][RANK_1][0], SHU1_R1_B0_DQ7_RK1_ARPI_DQM_B0));
+
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R1_B1_DQ7)+(SHU_GRP_DDRPHY_OFFSET * shuIdx), P_Fld(u1UpdatedPI_DQ[shuIdx][RANK_1][1], SHU1_R1_B1_DQ7_RK1_ARPI_DQ_B1)
+                                                                 | P_Fld(u1UpdatedPI_DQM[shuIdx][RANK_1][1], SHU1_R1_B1_DQ7_RK1_ARPI_DQM_B1));
+    }
+
+    while(u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MISC_STATUSA),MISC_STATUSA_MANUTXUPD_DONE)!=1)
+    {
+        mcDELAY_US(1);
+    }
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 0, DQSOSCR_TXUPDMODE);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 0, DQSOSCR_MANUTXUPD);
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), u1MR4OnOff, SPCMDCTRL_REFRDIS);
+}
+#endif
+
+#if ENABLE_RX_TRACKING_LP4
+void DramcRxInputDelayTrackingInit_Common(DRAMC_CTX_T *p)
+{
+    U8 ii, backup_rank;
+
+    backup_rank = u1GetRank(p);
+
+    //Enable RX_FIFO macro DIV4 clock CG
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_MISC_CG_CTRL1), 0xffffffff, MISC_CG_CTRL1_R_DVS_DIV4_CG_CTRL);
+
+    //DVS mode to RG mode
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2),0x0, R0_B0_RXDVS2_R_RK0_DVS_MODE_B0);
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2),0x0, R0_B1_RXDVS2_R_RK0_DVS_MODE_B1);
+
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R1_B0_RXDVS2),0x0, R1_B0_RXDVS2_R_RK1_DVS_MODE_B0);
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R1_B1_RXDVS2),0x0, R1_B1_RXDVS2_R_RK1_DVS_MODE_B1);
+
+    //Tracking lead/lag counter >> Rx DLY adjustment fixed to 1
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B0_RXDVS0),0x0, B0_RXDVS0_R_DMRXDVS_CNTCMP_OPT_B0);
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B1_RXDVS0),0x0, B1_RXDVS0_R_DMRXDVS_CNTCMP_OPT_B1);
+
+    //DQIEN pre-state option to block update for RX ASVA  1-2
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B0_RXDVS0),0x1, B0_RXDVS0_R_DMRXDVS_DQIENPRE_OPT_B0);
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B1_RXDVS0),0x1, B1_RXDVS0_R_DMRXDVS_DQIENPRE_OPT_B1);
+
+    //Turn off F_DLY individual calibration option (CTO_AGENT_RDAT cannot separate DR/DF error)
+    //tracking rising and update rising/falling together
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2),0x0, R0_B0_RXDVS2_R_RK0_DVS_FDLY_MODE_B0);
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2),0x0, R0_B1_RXDVS2_R_RK0_DVS_FDLY_MODE_B1);
+
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R1_B0_RXDVS2),0x0, R1_B0_RXDVS2_R_RK1_DVS_FDLY_MODE_B0);
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R1_B1_RXDVS2),0x0, R1_B1_RXDVS2_R_RK1_DVS_FDLY_MODE_B1);
+
+    for(ii=RANK_0; ii<RANK_MAX; ii++)
+    {
+        vSetRank(p, ii);
+
+        //DQ/DQM/DQS DLY MAX/MIN value under Tracking mode
+        /* Byte 0 */
+#if (fcFOR_CHIP_ID == fcLaurel)
+        /* DQS, DQ, DQM (DQ, DQM are tied together now) -> controlled using DQM MAX_MIN */
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS7), P_Fld(0x0, R0_B0_RXDVS7_RG_RK0_ARDQ_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS7_RG_RK0_ARDQ_MAX_DLY_B0)
+                                                                  | P_Fld(0x0, R0_B0_RXDVS7_RG_RK0_ARDQS0_MIN_DLY_B0) | P_Fld(0x7f, R0_B0_RXDVS7_RG_RK0_ARDQS0_MAX_DLY_B0));
+#else
+        /* Previous design DQ, DQM MAX/MIN are controlled using different register fields */
+        /* DQM, DQS */
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS7), P_Fld(0x0, R0_B0_RXDVS7_RG_RK0_ARDQ_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS7_RG_RK0_ARDQ_MAX_DLY_B0)
+                                                                  | P_Fld(0x0, R0_B0_RXDVS7_RG_RK0_ARDQS0_MIN_DLY_B0) | P_Fld(0x7f, R0_B0_RXDVS7_RG_RK0_ARDQS0_MAX_DLY_B0));
+        /* DQ */
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS3), P_Fld(0x0, R0_B0_RXDVS3_RG_RK0_ARDQ0_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS3_RG_RK0_ARDQ0_MAX_DLY_B0));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS3), P_Fld(0x0, R0_B0_RXDVS3_RG_RK0_ARDQ1_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS3_RG_RK0_ARDQ1_MAX_DLY_B0));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS4), P_Fld(0x0, R0_B0_RXDVS4_RG_RK0_ARDQ2_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS4_RG_RK0_ARDQ2_MAX_DLY_B0));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS4), P_Fld(0x0, R0_B0_RXDVS4_RG_RK0_ARDQ3_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS4_RG_RK0_ARDQ3_MAX_DLY_B0));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS5), P_Fld(0x0, R0_B0_RXDVS5_RG_RK0_ARDQ4_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS5_RG_RK0_ARDQ4_MAX_DLY_B0));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS5), P_Fld(0x0, R0_B0_RXDVS5_RG_RK0_ARDQ5_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS5_RG_RK0_ARDQ5_MAX_DLY_B0));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS6), P_Fld(0x0, R0_B0_RXDVS6_RG_RK0_ARDQ6_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS6_RG_RK0_ARDQ6_MAX_DLY_B0));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS6), P_Fld(0x0, R0_B0_RXDVS6_RG_RK0_ARDQ7_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS6_RG_RK0_ARDQ7_MAX_DLY_B0));
+#endif
+
+        /* Byte 1 */
+#if (fcFOR_CHIP_ID == fcLaurel)
+        /* DQS, DQ, DQM (DQ, DQM are tied together now) -> controlled using DQM MAX_MIN */
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS7), P_Fld(0x0, R0_B1_RXDVS7_RG_RK0_ARDQ_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS7_RG_RK0_ARDQ_MAX_DLY_B1)
+                                                                  | P_Fld(0x0, R0_B1_RXDVS7_RG_RK0_ARDQS0_MIN_DLY_B1) | P_Fld(0x7f, R0_B1_RXDVS7_RG_RK0_ARDQS0_MAX_DLY_B1));
+#else
+        /* Previous design DQ, DQM MAX/MIN are controlled using different register fields */
+        /* DQM, DQS */
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS7), P_Fld(0x0, R0_B1_RXDVS7_RG_RK0_ARDQ_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS7_RG_RK0_ARDQ_MAX_DLY_B1)
+                                                                  | P_Fld(0x0, R0_B1_RXDVS7_RG_RK0_ARDQS0_MIN_DLY_B1) | P_Fld(0x7f, R0_B1_RXDVS7_RG_RK0_ARDQS0_MAX_DLY_B1));
+        /* DQ */
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS3), P_Fld(0x0, R0_B1_RXDVS3_RG_RK0_ARDQ0_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS3_RG_RK0_ARDQ0_MAX_DLY_B1));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS3), P_Fld(0x0, R0_B1_RXDVS3_RG_RK0_ARDQ1_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS3_RG_RK0_ARDQ1_MAX_DLY_B1));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS4), P_Fld(0x0, R0_B1_RXDVS4_RG_RK0_ARDQ2_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS4_RG_RK0_ARDQ2_MAX_DLY_B1));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS4), P_Fld(0x0, R0_B1_RXDVS4_RG_RK0_ARDQ3_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS4_RG_RK0_ARDQ3_MAX_DLY_B1));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS5), P_Fld(0x0, R0_B1_RXDVS5_RG_RK0_ARDQ4_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS5_RG_RK0_ARDQ4_MAX_DLY_B1));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS5), P_Fld(0x0, R0_B1_RXDVS5_RG_RK0_ARDQ5_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS5_RG_RK0_ARDQ5_MAX_DLY_B1));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS6), P_Fld(0x0, R0_B1_RXDVS6_RG_RK0_ARDQ6_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS6_RG_RK0_ARDQ6_MAX_DLY_B1));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS6), P_Fld(0x0, R0_B1_RXDVS6_RG_RK0_ARDQ7_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS6_RG_RK0_ARDQ7_MAX_DLY_B1));
+#endif
+
+        //Threshold for LEAD/LAG filter
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS1), P_Fld(0x2, R0_B0_RXDVS1_R_RK0_B0_DVS_TH_LEAD) | P_Fld(0x2, R0_B0_RXDVS1_R_RK0_B0_DVS_TH_LAG));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS1), P_Fld(0x2, R0_B1_RXDVS1_R_RK0_B1_DVS_TH_LEAD) | P_Fld(0x2, R0_B1_RXDVS1_R_RK0_B1_DVS_TH_LAG));
+
+        //DQ/DQS Rx DLY adjustment for tracking mode
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2), P_Fld(0x0, R0_B0_RXDVS2_R_RK0_RX_DLY_RIS_DQ_SCALE_B0) | P_Fld(0x0, R0_B0_RXDVS2_R_RK0_RX_DLY_RIS_DQS_SCALE_B0));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2), P_Fld(0x0, R0_B1_RXDVS2_R_RK0_RX_DLY_RIS_DQ_SCALE_B1) | P_Fld(0x0, R0_B1_RXDVS2_R_RK0_RX_DLY_RIS_DQS_SCALE_B1));
+
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2), P_Fld(0x0, R0_B0_RXDVS2_R_RK0_RX_DLY_FAL_DQ_SCALE_B0) | P_Fld(0x0, R0_B0_RXDVS2_R_RK0_RX_DLY_FAL_DQS_SCALE_B0));
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2), P_Fld(0x0, R0_B1_RXDVS2_R_RK0_RX_DLY_FAL_DQ_SCALE_B1) | P_Fld(0x0, R0_B1_RXDVS2_R_RK0_RX_DLY_FAL_DQS_SCALE_B1));
+    }
+
+    vSetRank(p, backup_rank);
+}
+#endif
+
+void DramcRxInputDelayTrackingInit_byFreq(DRAMC_CTX_T *p)
+{
+    U8 u1DVS_Delay;
+    //Monitor window size setting
+    //DDRPHY.SHU*_B*_DQ5.RG_RX_ARDQS0_DVS_DLY_B* (suggested value from A-PHY owner)
+//WHITNEY_TO_BE_PORTING
+#if (fcFOR_CHIP_ID == fcLaurel)
+    //          Speed   Voltage     DVS_DLY
+    //======================================
+    //SHU1      3200    0.8V        3
+    //SHU2      2667    0.8V-0.7V   4
+    //SHU3      1600    0.7V-0.65V  5
+    if(p->freqGroup == 2132)
+    {
+        u1DVS_Delay =2;
+    }
+    else
+    if(p->freqGroup == 1866)
+    {
+        u1DVS_Delay =3;
+    }
+    else
+    if(p->freqGroup == 1600)
+    {
+        u1DVS_Delay =3;
+    }
+    else if(p->freqGroup == 1333 || p->freqGroup == 1200)
+    {
+        u1DVS_Delay =4;
+    }
+    else// if(p->freqGroup == 800)
+    {
+        u1DVS_Delay =5;
+    }
+#endif
+
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ5), u1DVS_Delay, SHU1_B0_DQ5_RG_RX_ARDQS0_DVS_DLY_B0);
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ5), u1DVS_Delay, SHU1_B1_DQ5_RG_RX_ARDQS0_DVS_DLY_B1);
+
+    /* Bianco HW design issue: run-time PBYTE flag will lose it's function and become per-bit -> set to 0 */
+    vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ7), P_Fld(0x0, SHU1_B0_DQ7_R_DMRXDVS_PBYTE_FLAG_OPT_B0)
+                                                            | P_Fld(0x0, SHU1_B0_DQ7_R_DMRXDVS_PBYTE_DQM_EN_B0));
+    vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ7), P_Fld(0x0, SHU1_B1_DQ7_R_DMRXDVS_PBYTE_FLAG_OPT_B1)
+                                                            | P_Fld(0x0, SHU1_B1_DQ7_R_DMRXDVS_PBYTE_DQM_EN_B1));
+}
+
+#if ENABLE_RX_TRACKING_LP4
+void DramcRxInputDelayTrackingHW(DRAMC_CTX_T *p)
+{
+    DRAM_CHANNEL_T channel_bak = p->channel;
+    //UINT8 updateDone=0;
+    //U16 u2DVS_TH=0x0;
+    //U16 u2MinDly=0x14;
+    //U16 u2MaxDly=0x30;
+    U8 ii, backup_rank;
+
+    vSetPHY2ChannelMapping(p, CHANNEL_A);
+    backup_rank = u1GetRank(p);
+
+    //Rx DLY tracking setting (Static)
+    vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_B0_RXDVS0),
+                                           P_Fld(1, B0_RXDVS0_R_RX_DLY_TRACK_SPM_CTRL_B0) |
+                                           P_Fld(0, B0_RXDVS0_R_RX_RANKINCTL_B0)|
+                                           P_Fld(1, B0_RXDVS0_R_RX_RANKINSEL_B0));
+
+    vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_B1_RXDVS0),
+                                           P_Fld(1, B1_RXDVS0_R_RX_DLY_TRACK_SPM_CTRL_B1) |
+                                           P_Fld(0, B1_RXDVS0_R_RX_RANKINCTL_B1)|
+                                           P_Fld(1, B1_RXDVS0_R_RX_RANKINSEL_B1));
+
+#if (fcFOR_CHIP_ID == fcLaurel)
+    vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ9), P_Fld(0x1, B0_DQ9_R_DMRXDVS_RDSEL_LAT_B0 | P_Fld(0, B0_DQ9_R_DMRXDVS_VALID_LAT_B0)));
+    vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ9), P_Fld(0x1, B1_DQ9_R_DMRXDVS_RDSEL_LAT_B1) | P_Fld(0, B1_DQ9_R_DMRXDVS_VALID_LAT_B1));
+    vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD10), P_Fld(0,CA_CMD10_R_DMRXDVS_RDSEL_LAT_CA) | P_Fld(0, CA_CMD10_R_DMRXDVS_VALID_LAT_CA));
+
+    /* DMRXTRACK_DQM_B* (rxdly_track SM DQM enable) -> need to be set to 1 if R_DBI is on
+     *  They are shuffle regs -> move setting to DramcSetting_Olympus_LP4_ByteMode()
+     */
+
+    //Enable A-PHY DVS LEAD/LAG
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 0x1, B0_DQ5_RG_RX_ARDQS0_DVS_EN_B0);
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 0x1, B1_DQ5_RG_RX_ARDQS0_DVS_EN_B1);
+#else
+    vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_MISC_RXDVS2), P_Fld(0x1, MISC_RXDVS2_R_RXDVS_RDSEL_TOG_LAT)
+                                                            | P_Fld(0x2, MISC_RXDVS2_R_RXDVS_RDSEL_BUS_LAT));
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 0x0, MISC_CTRL1_R_DMDQMDBI);
+
+    //Enable A-PHY DVS LEAD/LAG
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 0x1, B0_DQ5_RG_RX_ARDQS0_DVS_EN_B0);
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 0x1, B1_DQ5_RG_RX_ARDQS0_DVS_EN_B1);
+#endif
+
+    //Rx DLY tracking function CG enable
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B0_RXDVS0), 0x1, B0_RXDVS0_R_RX_DLY_TRACK_CG_EN_B0);
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B1_RXDVS0), 0x1, B1_RXDVS0_R_RX_DLY_TRACK_CG_EN_B1);
+
+    //Rx DLY tracking lead/lag counter enable
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B0_RXDVS0), 0x1, B0_RXDVS0_R_RX_DLY_TRACK_ENA_B0);
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B1_RXDVS0), 0x1, B1_RXDVS0_R_RX_DLY_TRACK_ENA_B1);
+
+    for(ii=RANK_0; ii<RANK_MAX; ii++)
+    {
+        vSetRank(p, ii);
+
+        //Rx DLY tracking update enable (HW mode)
+        #if 0
+        vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2), 0x2, R0_B0_RXDVS2_R_RK0_DVS_MODE_B0);
+        vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2), 0x2, R0_B1_RXDVS2_R_RK0_DVS_MODE_B1);
+
+        vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2), 0x1, R0_B0_RXDVS2_R_RK0_RX_DLY_RIS_TRACK_GATE_ENA_B0);
+        vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2), 0x1, R0_B1_RXDVS2_R_RK0_RX_DLY_RIS_TRACK_GATE_ENA_B1);
+
+        vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2), 0x1, R0_B0_RXDVS2_R_RK0_RX_DLY_FAL_TRACK_GATE_ENA_B0);
+        vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2), 0x1, R0_B1_RXDVS2_R_RK0_RX_DLY_FAL_TRACK_GATE_ENA_B1);
+        #else
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2),
+                                               P_Fld(2, R0_B0_RXDVS2_R_RK0_DVS_MODE_B0) |
+                                               P_Fld(1, R0_B0_RXDVS2_R_RK0_RX_DLY_RIS_TRACK_GATE_ENA_B0)|
+                                               P_Fld(1, R0_B0_RXDVS2_R_RK0_RX_DLY_FAL_TRACK_GATE_ENA_B0));
+
+        vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2),
+                                               P_Fld(2, R0_B1_RXDVS2_R_RK0_DVS_MODE_B1) |
+                                               P_Fld(1, R0_B1_RXDVS2_R_RK0_RX_DLY_RIS_TRACK_GATE_ENA_B1)|
+                                               P_Fld(1, R0_B1_RXDVS2_R_RK0_RX_DLY_FAL_TRACK_GATE_ENA_B1));
+        #endif
+    }
+
+    vSetRank(p, backup_rank);
+
+#if 0
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B0_RXDVS0),0x1, B0_RXDVS0_R_RX_DLY_RK_OPT_B0);
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B1_RXDVS0),0x1, B1_RXDVS0_R_RX_DLY_RK_OPT_B1);
+
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 1, MISC_CTRL1_R_HWSAVE_MODE_ENA);
+#endif
+
+    vSetPHY2ChannelMapping(p, channel_bak);
+}
+#endif
+
+
+#if SIMULATION_LP4_ZQ
+//-------------------------------------------------------------------------
+/** DramcZQCalibration
+ *  start Dram ZQ calibration.
+ *  @param p                Pointer of context created by DramcCtxCreate.
+ *  @retval status          (DRAM_STATUS_T): DRAM_OK or DRAM_FAIL
+ */
+//-------------------------------------------------------------------------
+DRAM_STATUS_T DramcZQCalibration(DRAMC_CTX_T *p)
+{
+    U32 u4Response;
+    U32 u4TimeCnt = TIME_OUT_CNT;
+    U32 u4RegBackupAddress[] = {DRAMC_REG_ADDR(DRAMC_REG_MRS), DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), DRAMC_REG_ADDR(DRAMC_REG_CKECTRL)};
+
+    // Backup rank, CKE fix on/off, HW MIOCK control settings
+    DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+    mcSHOW_DBG_MSG3(("[ZQCalibration]\n"));
+    mcFPRINTF((fp_A60501, "[ZQCalibration]\n"));
+
+    // Disable HW MIOCK control to make CLK always on
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 1, DRAMC_PD_CTRL_MIOCKCTRLOFF);
+    mcDELAY_US(1);
+
+    //if CKE2RANK=1, only need to set CKEFIXON, it will apply to both rank.
+    CKEFixOnOff(p, p->rank, CKE_FIXON, CKE_WRITE_TO_ONE_CHANNEL);
+
+    //Use rank swap or MRSRK to select rank
+    //DramcRankSwap(p, p->rank);
+    //!!R_DMMRSRK(R_DMMPCRKEN=1) specify rank0 or rank1
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRS), u1GetRank(p), MRS_MRSRK);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MPC_OPTION), 1, MPC_OPTION_MPCRKEN);
+
+    //ZQCAL Start
+    //R_DMZQCEN, 0x1E4[4]=1 for ZQCal Start
+    //Wait zqc_response=1 (dramc_conf_nao, 0x3b8[4])
+    //R_DMZQCEN, 0x1E4[4]=0
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_ZQCEN);
+    do
+    {
+        u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_ZQC_RESPONSE);
+        u4TimeCnt --;
+        mcDELAY_US(1);  // Wait tZQCAL(min) 1us or wait next polling
+
+        mcSHOW_DBG_MSG3(("%d- ", u4TimeCnt));
+        mcFPRINTF((fp_A60501, "%d- ", u4TimeCnt));
+    }while((u4Response==0) &&(u4TimeCnt>0));
+
+    if(u4TimeCnt==0)//time out
+    {
+        vSetCalibrationResult(p, DRAM_CALIBRATION_ZQ, DRAM_FAIL);
+        mcSHOW_DBG_MSG(("ZQCAL Start fail (time out)\n"));
+        mcFPRINTF((fp_A60501, "ZQCAL Start fail (time out)\n"));
+        return DRAM_FAIL;
+    }
+    else
+    {
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_ZQCEN);
+    }
+
+    // [JC] delay tZQCAL
+    mcDELAY_US(1);
+    u4TimeCnt = TIME_OUT_CNT;
+
+    //ZQCAL Latch
+    //R_DMZQLATEN, 0x1E4[6]=1 for ZQCal latch
+    //Wait zqlat_response=1 (dramc_conf_nao, 0x3b8[28])
+    //R_DMZQLATEN, 0x1E4[6]=0
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_ZQLATEN);
+    do
+    {
+        u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_ZQLAT_RESPONSE);
+        u4TimeCnt --;
+        mcDELAY_US(1);// Wait tZQLAT 30ns or wait next polling
+
+        mcSHOW_DBG_MSG3(("%d=", u4TimeCnt));
+        mcFPRINTF((fp_A60501, "%d= ", u4TimeCnt));
+    }while((u4Response==0) &&(u4TimeCnt>0));
+
+    if(u4TimeCnt==0)//time out
+    {
+        vSetCalibrationResult(p, DRAM_CALIBRATION_ZQ, DRAM_FAIL);
+        mcSHOW_DBG_MSG(("ZQCAL Latch fail (time out)\n"));
+        mcFPRINTF((fp_A60501, "ZQCAL Latch fail (time out)\n"));
+        return DRAM_FAIL;
+    }
+    else
+    {
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_ZQLATEN);
+    }
+
+    // [JC] delay tZQLAT
+    mcDELAY_US(1);
+
+    // Restore rank, CKE fix on, HW MIOCK control settings
+    DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+    vSetCalibrationResult(p, DRAM_CALIBRATION_ZQ, DRAM_OK);
+    mcSHOW_DBG_MSG3(("\n[DramcZQCalibration] Done\n\n"));
+    mcFPRINTF((fp_A60501, "\n[DramcZQCalibration] Done\n\n"));
+
+    return DRAM_OK;
+}
+#endif
+
+#if SIMULATION_RX_INPUT_BUF
+//-------------------------------------------------------------------------
+/** DramcSwImpedanceCal
+ *  start TX OCD impedance calibration.
+ *  @param p                Pointer of context created by DramcCtxCreate.
+ *  @param  apply           (U8): 0 don't apply the register we set  1 apply the register we set ,default don't apply.
+ *  @retval status          (DRAM_STATUS_T): DRAM_OK or DRAM_FAIL
+ */
+//-------------------------------------------------------------------------
+static U8 RXInputBuf_DelayExchange(S8 iOfst)
+{
+    U8 u1Value;
+
+    if(iOfst <0)
+    {
+        u1Value = 0x8 | (-iOfst);
+    }
+    else
+    {
+        u1Value = iOfst;
+    }
+
+    return u1Value;
+}
+
+// cannot be simulated in DV or DSim, it's analog feature.
+DRAM_STATUS_T DramcRXInputBufferOffsetCal(DRAMC_CTX_T *p)
+{
+    U16 u2RXVrefDefault;
+    U32 u4RegBackupAddress[] =
+    {
+        (DRAMC_REG_ADDR(DDRPHY_B0_DQ5)),
+        (DRAMC_REG_ADDR(DDRPHY_B1_DQ5)),
+        (DRAMC_REG_ADDR(DDRPHY_B0_DQ6)),
+        (DRAMC_REG_ADDR(DDRPHY_B1_DQ6)),
+        (DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ5)),
+        (DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ5)),
+        (DRAMC_REG_ADDR(DDRPHY_B0_DQ3)),
+        (DRAMC_REG_ADDR(DDRPHY_B1_DQ3)),
+        (DRAMC_REG_ADDR(DRAMC_REG_PADCTRL)),
+    };
+    S8 iOffset, iDQFlagChange[16], iDQMFlagChange[2];
+    U32 u4Value, u4RestltDQ[2], u4RestltDQM[2];
+    U8 u1BitIdx, u1ByteIdx, u1FinishCount, u1DQFinalFlagChange[16], u1DQMFinalFlagChange[2];
+
+    mcSHOW_DBG_MSG(("\n[RXInputBufferOffsetCal]\n"));
+    mcFPRINTF((fp_A60501, "\n[RXInputBufferOffsetCal] \n"));
+
+    if(!u1IsLP4Family(p->dram_type))
+    {
+        //RX offset calibration(LP4 only)
+        mcSHOW_ERR_MSG(("LP3 no need\n"));
+        return DRAM_FAIL;
+    }
+
+    //Back up dramC register
+    DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PADCTRL), 0xf, PADCTRL_FIXDQIEN);
+
+    //Enable BIAS (RG_RX_*RDQ*_RES_BIAS_EN_B), RG_RX_*_BIAS_PS* =    2'b01(RG mode)
+    //Select VREF, for LPDDR4 set RG_RX_*DQ_DDR4_SEL_* =1, RG_RX_*DQ_DDR3_SEL_* =0
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ6),
+                                        P_Fld(1, B0_DQ6_RG_RX_ARDQ_BIAS_PS_B0) |
+                                        P_Fld(1, B0_DQ6_RG_RX_ARDQ_RES_BIAS_EN_B0) |
+                                        P_Fld(0, B0_DQ6_RG_RX_ARDQ_DDR3_SEL_B0) |
+                                        P_Fld(1, B0_DQ6_RG_RX_ARDQ_DDR4_SEL_B0));
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ6),
+                                        P_Fld(1, B1_DQ6_RG_RX_ARDQ_BIAS_PS_B1) |
+                                        P_Fld(1, B1_DQ6_RG_RX_ARDQ_RES_BIAS_EN_B1)  |
+                                        P_Fld(0, B1_DQ6_RG_TX_ARDQ_DDR3_SEL_B1) |
+                                        P_Fld(1, B1_DQ6_RG_TX_ARDQ_DDR4_SEL_B1));
+
+    //Enable VREF, (RG_RX_*DQ_VREF_EN_* =1)
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_VREF_EN_B0);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_VREF_EN_B1);
+
+    //Set Vref voltage: LP4 with termination  SEL[4:0] = 01110 (0xe) (refer to Vref default table)
+    //Only need to set Vref with term, only K rx input offset at highest freq.
+    //Need to set according to ODT on/off.
+    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
+
+    // Wait 1us.
+    mcDELAY_US(1);
+
+    //Enable RX input buffer (RG_RX_*DQ_IN_BUFF_EN_* =1, DA_RX_*DQ_IN_GATE_EN_* =1)
+    //Enable RX input buffer offset calibration (RG_RX_*DQ_OFFC_EN_*=1)
+    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PADCTRL), 0xf, PADCTRL_FIXDQIEN); // same as DA_RX_*DQ_IN_GATE_EN_*=1, Keep DQ input always ON. ==> Note: Do not enable again.
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ3), P_Fld(1, B0_DQ3_RG_RX_ARDQ_IN_BUFF_EN_B0) | P_Fld(1, B0_DQ3_RG_RX_ARDQ_OFFC_EN_B0));
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ3), P_Fld(1, B1_DQ3_RG_RX_ARDQ_IN_BUFF_EN_B1) | P_Fld(1, B1_DQ3_RG_RX_ARDQ_OFFC_EN_B1));
+
+    // SW parameter initialization
+    u1FinishCount =0;
+    iDQMFlagChange[0] = 0x7f;
+    iDQMFlagChange[1] = 0x7f;
+
+    for(u1BitIdx=0; u1BitIdx< 16; u1BitIdx++)
+    {
+        iDQFlagChange[u1BitIdx] = 0x7f; //initial as invalid
+    }
+
+    //Sweep RX offset calibration code (RG_RX_*DQ*_OFFC<3:0>), the MSB is sign bit, sweep the code from -7(1111) to +7(0111)
+    for(iOffset=-7; iOffset<7; iOffset++)
+    {
+        u4Value = RXInputBuf_DelayExchange(iOffset);
+
+        #ifdef ETT_PRINT_FORMAT
+        mcSHOW_DBG_MSG(("iOffset= %d, u4Value=%d,", iOffset, u4Value));
+        #else
+        mcSHOW_DBG_MSG(("iOffset= %2d, u4Value=%2d,", iOffset, u4Value));
+        #endif
+        mcFPRINTF((fp_A60501, "iOffset= %2d, u4Value=%2d,", iOffset, u4Value));
+
+         //Delay of DQM0.
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ1), u4Value, B0_DQ1_RG_RX_ARDQM0_OFFC_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ1), u4Value, B1_DQ1_RG_RX_ARDQM0_OFFC_B1);
+
+         //Delay of DQ0~DQ7.
+        u4Value = u4Value |(u4Value<<4) |(u4Value<<8) |(u4Value<<12) |(u4Value<<16) |(u4Value<<20) |(u4Value<<24) |(u4Value<<28);
+        vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_B0_DQ0), u4Value);
+        vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_B1_DQ0), u4Value);
+
+        //For each code sweep, wait 0.1us to check the flag.
+        mcDELAY_US(1);
+
+        //Check offset flag of DQ (RGS_*DQ*_OFFSET_FLAG_*), the value will be from 1(-7) to 0(+7). Record the value when the flag becomes "0".
+        //Flag bit0 is for DQ0,  Flag bit15 for DQ15
+        u4RestltDQ[0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_PHY_RGS_DQ), MISC_PHY_RGS_DQ_RGS_ARDQ_OFFSET_FLAG_B0);
+        u4RestltDQ[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_PHY_RGS_DQ), MISC_PHY_RGS_DQ_RGS_ARDQ_OFFSET_FLAG_B1);
+        u4RestltDQ[0] |= (u4RestltDQ[1] <<8);
+
+        mcSHOW_DBG_MSG(("RestltDQ (B1)0x%x (B0)0x%x, ", u4RestltDQ[1], u4RestltDQ[0]));
+        mcFPRINTF((fp_A60501, "RestltDQ (B1)0x%x (B0)0x%x, ", u4RestltDQ[1], u4RestltDQ[0]));
+
+        for(u1BitIdx= 0; u1BitIdx <16; u1BitIdx++)
+        {
+            if(iDQFlagChange[u1BitIdx] == 0x7f) //invalid
+            {
+                u4Value = (u4RestltDQ[0] >> u1BitIdx) & 0x1;
+
+                if(u4Value ==0) // 1 -> 0
+                {
+                    iDQFlagChange[u1BitIdx] = iOffset;
+                    u1FinishCount ++;
+                }
+            }
+        }
+
+        //Check offset flag of DQM (RGS_*DQ*_OFFSET_FLAG_*), the value will be from 1(-7) to 0(+7). Record the value when the flag becomes "0".
+        u4RestltDQM[0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_PHY_RGS_DQ), MISC_PHY_RGS_DQ_RGS_ARDQM0_OFFSET_FLAG_B0);
+        u4RestltDQM[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_PHY_RGS_DQ), MISC_PHY_RGS_DQ_RGS_ARDQM0_OFFSET_FLAG_B1);
+
+        mcSHOW_DBG_MSG(("RestltDQM (B1)= 0x%x, (B0)= 0x%x\n", u4RestltDQM[1], u4RestltDQM[0]));
+        mcFPRINTF((fp_A60501, "RestltDQM (B1)= 0x%x, (B0)= 0x%x\n", u4RestltDQM[1], u4RestltDQM[0]));
+
+        for(u1ByteIdx= 0; u1ByteIdx <2; u1ByteIdx++)
+        {
+            if(iDQMFlagChange[u1ByteIdx]== 0x7f) //invalid
+            {
+                if(u4RestltDQM[u1ByteIdx]==0)// 1 -> 0
+                {
+                    iDQMFlagChange[u1ByteIdx]= iOffset;
+                    u1FinishCount++;
+                }
+            }
+        }
+
+        if(u1FinishCount==18) // (DQ8 bits, DQM 1bit, total 9 bits.) x2 bytes
+        {
+            break; //all bits done, early break
+        }
+    }
+
+    mcSHOW_DBG_MSG(("\nResult DQ\n"
+                    "\t0\t1\t2\t3\t4\t5\t6\t7\n"
+                    "Byte 0\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n"
+                    "Byte 1\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n"
+                    "Result DQM [0] %d, [1] %d\n",
+                        iDQFlagChange[0], iDQFlagChange[1], iDQFlagChange[2], iDQFlagChange[3],
+                        iDQFlagChange[4], iDQFlagChange[5], iDQFlagChange[6], iDQFlagChange[7],
+                        iDQFlagChange[8], iDQFlagChange[9], iDQFlagChange[10], iDQFlagChange[11],
+                        iDQFlagChange[12], iDQFlagChange[13], iDQFlagChange[14],iDQFlagChange[15],
+                        iDQMFlagChange[0], iDQMFlagChange[1]));
+
+    mcFPRINTF((fp_A60501,"Result DQ [0]%d [1]%d [2]%d [3]%d [4]%d [5]%d [6]%d [7]%d\n", \
+                                        iDQFlagChange[0], iDQFlagChange[1], iDQFlagChange[2], iDQFlagChange[3], \
+                                        iDQFlagChange[4], iDQFlagChange[5], iDQFlagChange[6],iDQFlagChange[7]));
+
+    mcFPRINTF((fp_A60501, "Result DQ Byte 1 [0]%d [1]%d [2]%d [3]%d [4]%d [5]%d [6]%d [7]%d\n", \
+                                        iDQFlagChange[8], iDQFlagChange[9], iDQFlagChange[10], iDQFlagChange[11], \
+                                        iDQFlagChange[12], iDQFlagChange[13], iDQFlagChange[14],iDQFlagChange[15]));
+
+    mcFPRINTF((fp_A60501, "Result DQM[0] %d, Result DQM[1] %d,\n", iDQMFlagChange[0], iDQMFlagChange[1]));
+
+    //Restore setting registers
+    DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+    // Change the offset value according to register format
+    for(u1BitIdx= 0; u1BitIdx <16; u1BitIdx++)
+    {
+        u1DQFinalFlagChange[u1BitIdx] = RXInputBuf_DelayExchange(iDQFlagChange[u1BitIdx]);
+    }
+    u1DQMFinalFlagChange[0]= RXInputBuf_DelayExchange(iDQMFlagChange[0]);
+    u1DQMFinalFlagChange[1]= RXInputBuf_DelayExchange(iDQMFlagChange[1]);
+
+    //Apply the code recorded.
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ1), u1DQMFinalFlagChange[0], B0_DQ1_RG_RX_ARDQM0_OFFC_B0);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ1), u1DQMFinalFlagChange[1], B1_DQ1_RG_RX_ARDQM0_OFFC_B1);
+
+    u4Value = u1DQFinalFlagChange[0] |(u1DQFinalFlagChange[1]<<4) |(u1DQFinalFlagChange[2]<<8) |(u1DQFinalFlagChange[3]<<12) | \
+                    (u1DQFinalFlagChange[4]<<16) |(u1DQFinalFlagChange[5]<<20) |(u1DQFinalFlagChange[6]<<24) |(u1DQFinalFlagChange[7]<<28);
+    vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_B0_DQ0), u4Value);
+
+    u4Value = u1DQFinalFlagChange[8] |(u1DQFinalFlagChange[9]<<4) |(u1DQFinalFlagChange[10]<<8) |(u1DQFinalFlagChange[11]<<12) | \
+                    (u1DQFinalFlagChange[12]<<16) |(u1DQFinalFlagChange[13]<<20) |(u1DQFinalFlagChange[14]<<24) |(u1DQFinalFlagChange[15]<<28);
+    vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_B1_DQ0), u4Value);
+
+    // Disable RX input buffer offset calibration (RG_RX_*DQ_OFFC_EN_*=0)
+    //U32 u4AddrOfst = 0x50;
+    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_TXDQ3+u4AddrOfst), 0, TXDQ3_RG_RX_ARDQ_OFFC_EN_B0);
+
+    #if 0
+    mcSHOW_DBG_MSG(("Register DQ [0]%d [1]%d [2]%d [3]%d [4]%d [5]%d [6]%d [7]%d\n", \
+                                        u1DQFinalFlagChange[0], u1DQFinalFlagChange[1], u1DQFinalFlagChange[2], u1DQFinalFlagChange[3], \
+                                        u1DQFinalFlagChange[4], u1DQFinalFlagChange[5], u1DQFinalFlagChange[6],u1DQFinalFlagChange[7]));
+    mcFPRINTF((fp_A60501,"Register DQ [0]%d [1]%d [2]%d [3]%d [4]%d [5]%d [6]%d [7]%d\n", \
+                                        u1DQFinalFlagChange[0], u1DQFinalFlagChange[1], u1DQFinalFlagChange[2], u1DQFinalFlagChange[3], \
+                                        u1DQFinalFlagChange[4], u1DQFinalFlagChange[5], u1DQFinalFlagChange[6],u1DQFinalFlagChange[7]));
+    mcSHOW_DBG_MSG(("Register DQM %d\n", u1DQMFinalFlagChange));
+    mcFPRINTF((fp_A60501, "Register DQM %d\n", u1DQMFinalFlagChange));
+    #endif
+    mcSHOW_DBG_MSG3(("[DramcRXInputBufferOffsetCal] Done\n"));
+    mcFPRINTF((fp_A60501, "[DramcRXInputBufferOffsetCal] Done\n"));
+
+    return DRAM_OK;
+}
+#endif
+
+//-------------------------------------------------------------------------
+/** DramcSwImpedanceCal
+ *  start TX OCD impedance calibration.
+ *  @param p                Pointer of context created by DramcCtxCreate.
+ *  @param  apply           (U8): 0 don't apply the register we set  1 apply the register we set ,default don't apply.
+ *  @retval status          (DRAM_STATUS_T): DRAM_OK or DRAM_FAIL
+ */
+//-------------------------------------------------------------------------
+#define HYNIX_IMPX_ADJUST 0
+#if HYNIX_IMPX_ADJUST
+U32 ImpedanceAdjustment_Hynix(U32 u4OriValue, U8 u1Div)
+{
+    U32 u4RODT;
+    U32 u4AdjustValue;
+
+    if(u1Div >0)
+    {
+        u4RODT = 240/u1Div;
+        u4AdjustValue = 60 *(u4OriValue+2)/u4RODT -2;
+    }
+    else
+    {
+        u4RODT =0;
+        u4AdjustValue = u4OriValue;
+    }
+
+    mcSHOW_DBG_MSG(("ODTN Change by Tool, 240 div %d =%d, After adjustment ODTN=%d\n\n", u1Div, u4RODT, u4AdjustValue));
+
+    return u4AdjustValue;
+}
+#endif
+
+/* Impedance have a total of 19 steps, but the HW value mapping to hardware is 0~15, 29~31
+* This function adjusts passed value u1ImpVal by adjust step count "u1AdjStepCnt"
+* After adjustment, if value is 1. Too large (val > 31) -> set to max 31
+*                               2. Too small (val < 0) -> set to min 0
+*                               3. Value is between 15 & 29, adjust accordingly ( 15 < value < 29 )
+* returns: Impedance value after adjustment
+*/
+static U32 SwImpedanceAdjust(U32 u4ImpVal, S8 s1StepCnt)
+{
+    S32 S4ImpedanceTemp = (S32)u4ImpVal;
+
+   // Perform impedance value adjustment
+    S4ImpedanceTemp += s1StepCnt;
+    /* After adjustment, if value is 1. Too large (val > 31) -> set to max 31
+     *                               2. Too small (val < 0) -> set to min 0
+     *                               3. Value is between 15 & 29, adjust accordingly ( 15 < value < 29 )
+     */
+    if ((S4ImpedanceTemp > 15) && (S4ImpedanceTemp < 29)) //Value is between 15 & 29 ( 15 < value < 29)
+    {
+        S4ImpedanceTemp = S4ImpedanceTemp - 16 + 29;
+    }
+
+    if (S4ImpedanceTemp > 31) //Value after adjustment too large -> set to max 31
+    {
+        S4ImpedanceTemp = 31;
+    }
+    else if (S4ImpedanceTemp < 0) //Value after adjustment too small -> set to min 0
+    {
+        S4ImpedanceTemp = 0;
+    }
+
+    return (U32)S4ImpedanceTemp;
+}
+
+#if SIMULATION_SW_IMPED
+void DramcSwImpedanceSaveRegister(DRAMC_CTX_T *p, U8 ca_term_option, U8 dq_term_option, U8 save_to_where)
+{
+    U8 backup_broadcast;
+
+    backup_broadcast = GetDramcBroadcast();
+
+    if(u1IsLP4Family(p->dram_type))
+    {
+         DramcBroadcastOnOff(DRAMC_BROADCAST_ON);
+         //DQ
+         vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING1 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVP], SHU1_DRVING1_DQDRVP2) | P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVN], SHU1_DRVING1_DQDRVN2));
+         vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING2 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVP], SHU1_DRVING2_DQDRVP1) | P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVN], SHU1_DRVING2_DQDRVN1) | P_Fld((!dq_term_option), SHU1_DRVING2_DIS_IMPCAL_ODT_EN));
+         vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING3 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][ODTP], SHU1_DRVING3_DQODTP2) | P_Fld(gDramcSwImpedanceResule[dq_term_option][ODTN], SHU1_DRVING3_DQODTN2));
+         vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING4 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][ODTP], SHU1_DRVING4_DQODTP1) | P_Fld(gDramcSwImpedanceResule[dq_term_option][ODTN], SHU1_DRVING4_DQODTN1));
+
+         //DQS
+         vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING1 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVP], SHU1_DRVING1_DQSDRVP2) | P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVN], SHU1_DRVING1_DQSDRVN2));
+         vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING1 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVP], SHU1_DRVING1_DQSDRVP1) | P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVN], SHU1_DRVING1_DQSDRVN1));
+         vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING3 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][ODTP], SHU1_DRVING3_DQSODTP2) | P_Fld(gDramcSwImpedanceResule[dq_term_option][ODTN], SHU1_DRVING3_DQSODTN2));
+         vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING3 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][ODTP], SHU1_DRVING3_DQSODTP) | P_Fld(gDramcSwImpedanceResule[dq_term_option][ODTN], SHU1_DRVING3_DQSODTN));
+
+         //CMD & CLK
+         vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING2 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[ca_term_option][DRVP], SHU1_DRVING2_CMDDRVP2) | P_Fld(gDramcSwImpedanceResule[ca_term_option][DRVN], SHU1_DRVING2_CMDDRVN2));
+         vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING2 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[ca_term_option][DRVP], SHU1_DRVING2_CMDDRVP1) | P_Fld(gDramcSwImpedanceResule[ca_term_option][DRVN], SHU1_DRVING2_CMDDRVN1));
+         vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING4 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[ca_term_option][ODTP], SHU1_DRVING4_CMDODTP2) | P_Fld(gDramcSwImpedanceResule[ca_term_option][ODTN], SHU1_DRVING4_CMDODTN2));
+         vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING4 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[ca_term_option][ODTP], SHU1_DRVING4_CMDODTP1) | P_Fld(gDramcSwImpedanceResule[ca_term_option][ODTN], SHU1_DRVING4_CMDODTN1));
+
+         //RG_TX_*RCKE_DRVP/RG_TX_*RCKE_DRVN doesn't set, so set 0xA first
+         vIO32WriteFldAlign((DDRPHY_SHU1_CA_CMD11 + save_to_where * SHU_GRP_DDRPHY_OFFSET), gDramcSwImpedanceResule[ca_term_option][DRVP], SHU1_CA_CMD11_RG_TX_ARCKE_DRVP);
+         vIO32WriteFldAlign((DDRPHY_SHU1_CA_CMD11 + save_to_where * SHU_GRP_DDRPHY_OFFSET), gDramcSwImpedanceResule[ca_term_option][DRVN], SHU1_CA_CMD11_RG_TX_ARCKE_DRVN);
+
+         //CKE
+         // CKE is full swing.
+         // LP4/LP4X set DRVP/DRVN as LP3's default value
+         // DRVP=8
+         // DRVN=9
+         //DRVP[4:0] = RG_TX_ARCMD_PU_PRE<1:0>, RG_TX_ARCLK_DRVN_PRE<2:0>
+         vIO32WriteFldAlign((DDRPHY_SHU1_CA_CMD3 + save_to_where * SHU_GRP_DDRPHY_OFFSET), (8>>3)&0x3, SHU1_CA_CMD3_RG_TX_ARCMD_PU_PRE);
+         vIO32WriteFldAlign((DDRPHY_SHU1_CA_CMD0 + save_to_where * SHU_GRP_DDRPHY_OFFSET), 8&0x7, SHU1_CA_CMD0_RG_TX_ARCLK_DRVN_PRE);
+         //DRVN[4:0] = RG_ARCMD_REV<12:8>
+         #if (fcFOR_CHIP_ID == fcLaurel)
+         DramcBroadcastOnOff(DRAMC_BROADCAST_OFF);
+         vIO32WriteFldAlign_All((DDRPHY_SHU1_CA_DLL1 + save_to_where * SHU_GRP_DDRPHY_OFFSET), 9, RG_ARCMD_REV_BIT_1208_TX_CKE_DRVN);
+         DramcBroadcastOnOff(DRAMC_BROADCAST_ON);
+         #endif
+
+    }
+#if ENABLE_LP3_SW
+    else
+    {
+         //DQ
+         vIO32WriteFldMulti_All((DRAMC_REG_SHU1_DRVING1 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVP], SHU1_DRVING1_DQDRVP2) | P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVN], SHU1_DRVING1_DQDRVN2));
+         vIO32WriteFldMulti_All((DRAMC_REG_SHU1_DRVING2 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVP], SHU1_DRVING2_DQDRVP1) | P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVN], SHU1_DRVING2_DQDRVN1) | P_Fld((!dq_term_option), SHU1_DRVING2_DIS_IMPCAL_ODT_EN));
+
+         //DQS
+         vIO32WriteFldMulti_All((DRAMC_REG_SHU1_DRVING1 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVP], SHU1_DRVING1_DQSDRVP2) | P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVN], SHU1_DRVING1_DQSDRVN2));
+         vIO32WriteFldMulti_All((DRAMC_REG_SHU1_DRVING1 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVP], SHU1_DRVING1_DQSDRVP1) | P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVN], SHU1_DRVING1_DQSDRVN1));
+
+         //CMD & CLK
+         vIO32WriteFldMulti_All((DRAMC_REG_SHU1_DRVING2 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[ca_term_option][DRVP], SHU1_DRVING2_CMDDRVP2) | P_Fld(gDramcSwImpedanceResule[ca_term_option][DRVN], SHU1_DRVING2_CMDDRVN2));
+         vIO32WriteFldMulti_All((DRAMC_REG_SHU1_DRVING2 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[ca_term_option][DRVP], SHU1_DRVING2_CMDDRVP1) | P_Fld(gDramcSwImpedanceResule[ca_term_option][DRVN], SHU1_DRVING2_CMDDRVN1));
+
+
+         //CKE
+         // CKE is full swing.
+         // LP3 CKE DRVP/DRVN is same above
+         //DRVP[4:0] = RG_TX_ARCMD_PU_PRE<1:0>, RG_TX_ARCLK_DRVN_PRE<2:0>
+         vIO32WriteFldAlign_All((DDRPHY_SHU1_CA_CMD3 + save_to_where * SHU_GRP_DDRPHY_OFFSET), (gDramcSwImpedanceResule[dq_term_option][DRVP]>>3)&0x3, SHU1_CA_CMD3_RG_TX_ARCMD_PU_PRE);
+         vIO32WriteFldAlign_All((DDRPHY_SHU1_CA_CMD0 + save_to_where * SHU_GRP_DDRPHY_OFFSET), gDramcSwImpedanceResule[dq_term_option][DRVP]&0x7, SHU1_CA_CMD0_RG_TX_ARCLK_DRVN_PRE);
+         //DRVN[4:0] = RG_ARCMD_REV<12:8>
+         #if (fcFOR_CHIP_ID == fcLaurel)
+         vIO32WriteFldAlign_All((DDRPHY_SHU1_CA_DLL1 + save_to_where * SHU_GRP_DDRPHY_OFFSET), gDramcSwImpedanceResule[dq_term_option][DRVN], RG_ARCMD_REV_BIT_1208_TX_CKE_DRVN);
+         #endif
+    }
+#endif /* ENABLE_LP3_SW */
+    DramcBroadcastOnOff(backup_broadcast);
+}
+
+//-------------------------------------------------------------------------
+/** vImpCalVrefSel
+ *  Set IMP_VREF_SEL for DRVP, DRVN, Run-time/Tracking
+ *  (Refer to "IMPCAL Settings" document register "RG_RIMP_VREF_SEL" settings)
+ *  @param p                Pointer of context created by DramcCtxCreate.
+ *  @param  term_option     (U8): pass term_option (odt_on/off) for LP4X
+ *  @param  u1ImpCalStage   (U8): During DRVP, DRVN, run-time/tracking stages
+ *                                some vref_sel values are different
+ */
+//-------------------------------------------------------------------------
+/* Definitions to make IMPCAL_VREF_SEL function more readable */
+#define IMPCAL_STAGE_DRVP     1
+#define IMPCAL_STAGE_DRVN     2
+#define IMPCAL_STAGE_TRACKING 3
+
+/* LP3 IMP_VREF_SEL ============================== */
+#define IMP_LP3_VREF_SEL               0x2b
+
+/* LP4 IMP_VREF_SEL ============================== */
+#define IMP_LP4_VREF_SEL               0x1b
+
+/* LP4X IMP_VREF_SEL ============================== */
+#define IMP_LP4X_TERM_VREF_SEL     0x1b
+
+/* LP4X IMP_VREF_SEL w/o term ==== */
+#if (ENABLE_DQ3200_UNTERM == 1)
+    #define IMP_DRVP_LP4X_UNTERM_VREF_SEL   0x3a
+    #define IMP_DRVN_LP4X_UNTERM_VREF_SEL   0x2a
+    #define IMP_TRACK_LP4X_UNTERM_VREF_SEL  0x3a
+#else
+    #define IMP_DRVP_LP4X_UNTERM_VREF_SEL   0x1a
+    #define IMP_DRVN_LP4X_UNTERM_VREF_SEL   0x16
+    #define IMP_TRACK_LP4X_UNTERM_VREF_SEL  0x1a
+#endif
+
+/* LP4P IMP_VREF_SEL ============================== */
+#define IMP_DRVP_LP4P_VREF_SEL        0x13
+#define IMP_DRVN_LP4P_VREF_SEL        0xf
+#define IMP_TRACK_LP4P_VREF_SEL       0x13
+
+/* Refer to "IMPCAL Settings" document register "RG_RIMP_VREF_SEL" settings */
+static void vImpCalVrefSel(DRAMC_CTX_T *p, U8 term_option, U8 u1ImpCalStage)
+{
+    U8 u1RegTmpValue = 0;
+
+    if (p->dram_type == TYPE_LPDDR4)
+    {
+        u1RegTmpValue = IMP_LP4_VREF_SEL;
+    }
+    else if (p->dram_type == TYPE_LPDDR4X)
+    {
+        if (term_option == 1) // w/i term
+        {
+            u1RegTmpValue = IMP_LP4X_TERM_VREF_SEL;
+        }
+        else // w/o term
+        {
+            if (u1ImpCalStage == IMPCAL_STAGE_DRVP) // OCDP
+            {
+                u1RegTmpValue = IMP_DRVP_LP4X_UNTERM_VREF_SEL;
+            }
+            else if (u1ImpCalStage == IMPCAL_STAGE_DRVN) // ODTN
+            {
+                u1RegTmpValue = IMP_DRVN_LP4X_UNTERM_VREF_SEL;
+            }
+            else // IMPCAL_STAGE_TRACKING (Tracking)
+            {
+                u1RegTmpValue = IMP_TRACK_LP4X_UNTERM_VREF_SEL;
+            }
+        }
+    }
+    else if (p->dram_type == TYPE_LPDDR4P)
+    {
+        if (u1ImpCalStage == IMPCAL_STAGE_DRVP) // OCDP
+        {
+            u1RegTmpValue = IMP_DRVP_LP4P_VREF_SEL;
+        }
+        else if (u1ImpCalStage == IMPCAL_STAGE_DRVN) // OCDN
+        {
+            u1RegTmpValue = IMP_DRVN_LP4P_VREF_SEL;
+        }
+        else // IMPCAL_STAGE_TRACKING (Tracking)
+        {
+            u1RegTmpValue = IMP_TRACK_LP4P_VREF_SEL;
+        }
+    }
+    else // TYPE_LPDDR3
+    {
+        u1RegTmpValue = IMP_LP3_VREF_SEL;
+    }
+
+    // dbg msg after vref_sel selection
+    mcSHOW_DBG_MSG3(("[vImpCalVrefSel] IMP_VREF_SEL 0x%x, IMPCAL stage:%u, term_option:%u\n",
+                      u1RegTmpValue, u1ImpCalStage, term_option));
+
+    /* Set IMP_VREF_SEL register field's value */
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD11), u1RegTmpValue, SHU1_CA_CMD11_RG_RIMP_VREF_SEL); /*fra : fix single channel b */
+
+    return;
+}
+
+DRAM_STATUS_T DramcSwImpedanceCal(DRAMC_CTX_T *p, U8 u1Para, U8 term_option)
+{
+    U32 u4ImpxDrv, u4ImpCalResult;
+    U32 u4DRVP_Result =0xff,u4ODTN_Result =0xff, u4DRVN_Result =0xff;
+    U32 u4BaklReg_DRAMC_REG_IMPCAL;
+    U8 u1RegTmpValue;
+    U8 backup_channel;
+    U8 backup_broadcast;
+
+    backup_broadcast = GetDramcBroadcast();
+
+    DramcBroadcastOnOff(DRAMC_BROADCAST_OFF);
+
+    // Darren
+    vIO32WriteFldMulti_All(DDRPHY_MISC_SPM_CTRL1, P_Fld(0x0, MISC_SPM_CTRL1_RG_ARDMSUS_10) | P_Fld(0x0, MISC_SPM_CTRL1_RG_ARDMSUS_10_B0)
+                                           | P_Fld(0x0, MISC_SPM_CTRL1_RG_ARDMSUS_10_B1) | P_Fld(0x0, MISC_SPM_CTRL1_RG_ARDMSUS_10_CA));
+
+    vIO32WriteFldAlign_All(DDRPHY_MISC_SPM_CTRL2, 0x0, MISC_SPM_CTRL2_PHY_SPM_CTL2);
+    vIO32WriteFldAlign_All(DDRPHY_MISC_SPM_CTRL0, 0x0, MISC_SPM_CTRL0_PHY_SPM_CTL0);
+
+    //Disable IMP HW Tracking
+    //Hw Imp tracking disable for all channels Because SwImpCal will be K again when resume from DDR reserved mode
+    vIO32WriteFldAlign_All(DRAMC_REG_IMPCAL, 0, IMPCAL_IMPCAL_HW);
+
+    backup_channel = p->channel;
+
+#if (fcFOR_PINMUX == fcLaurel)
+    if(u1IsLP4Family(p->dram_type))
+    {
+        vSetPHY2ChannelMapping(p, CHANNEL_B);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL0), 0x1, MISC_CTRL0_IMPCAL_CHAB_EN);//switch to CHB
+    }
+    else //LP3
+    {
+        vSetPHY2ChannelMapping(p, CHANNEL_A);
+    }
+#endif
+
+    //Register backup
+    //u4BaklReg_DDRPHY_MISC_IMP_CTRL0 = u4IO32Read4B((DDRPHY_MISC_IMP_CTRL0));
+    //u4BaklReg_DDRPHY_MISC_IMP_CTRL1 = u4IO32Read4B((DDRPHY_MISC_IMP_CTRL1));
+    u4BaklReg_DRAMC_REG_IMPCAL = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL));
+
+    /* Set IMP_VREF_SEL value for DRVP */
+    vImpCalVrefSel(p, term_option, IMPCAL_STAGE_DRVP);
+
+    if(u1IsLP4Family(p->dram_type))
+    {
+    	//RG_IMPCAL_VREF_SEL (now set in vImpCalVrefSel())
+    	//RG_IMPCAL_LP3_EN=0, RG_IMPCAL_LP4_EN=1
+#if 0
+        vIO32WriteFldMulti( (DDRPHY_MISC_IMP_CTRL1), P_Fld(1, MISC_IMP_CTRL1_RG_RIMP_BIAS_EN) | \
+        					P_Fld(0, MISC_IMP_CTRL1_RG_RIMP_PRE_EN) | P_Fld(1, MISC_IMP_CTRL1_RG_RIMP_VREF_EN));
+#else
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1), P_Fld(0, MISC_IMP_CTRL1_RG_RIMP_PRE_EN));
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), P_Fld(0, IMPCAL_IMPCAL_CALI_ENN) | P_Fld(1, IMPCAL_IMPCAL_IMPPDP) | \
+                            P_Fld(1, IMPCAL_IMPCAL_IMPPDN));    //RG_RIMP_BIAS_EN and RG_RIMP_VREF_EN move to IMPPDP and IMPPDN
+#endif
+    	vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0), P_Fld(1, MISC_IMP_CTRL0_RG_IMP_EN) | \
+    						P_Fld(0, MISC_IMP_CTRL0_RG_RIMP_DDR3_SEL) | P_Fld(1, MISC_IMP_CTRL0_RG_RIMP_DDR4_SEL));
+    }
+#if ENABLE_LP3_SW
+    else //LPDDR3
+    {
+    	//RG_IMPCAL_VREF_SEL (now set in vImpCalVrefSel())
+    	//RG_IMPCAL_LP3_EN=0, RG_IMPCAL_LP4_EN=1
+        //RG_IMPCAL_ODT_EN=0
+#if 0
+        vIO32WriteFldMulti((DDRPHY_MISC_IMP_CTRL1), P_Fld(0, MISC_IMP_CTRL1_RG_RIMP_ODT_EN)| P_Fld(1, MISC_IMP_CTRL1_RG_RIMP_BIAS_EN) | \
+        					P_Fld(0, MISC_IMP_CTRL1_RG_RIMP_PRE_EN) | P_Fld(1, MISC_IMP_CTRL1_RG_RIMP_VREF_EN));
+#else
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1), P_Fld(0, MISC_IMP_CTRL1_RG_RIMP_PRE_EN));
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), P_Fld(0, IMPCAL_IMPCAL_CALI_ENN) | P_Fld(1, IMPCAL_IMPCAL_IMPPDP) | \
+                            P_Fld(1, IMPCAL_IMPCAL_IMPPDN));    //RG_RIMP_BIAS_EN and RG_RIMP_VREF_EN move to IMPPDP and IMPPDN, ODT_EN move to CALI_ENN
+#endif
+    	vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0), P_Fld(1, MISC_IMP_CTRL0_RG_IMP_EN) | \
+    						P_Fld(1, MISC_IMP_CTRL0_RG_RIMP_DDR3_SEL) | P_Fld(0, MISC_IMP_CTRL0_RG_RIMP_DDR4_SEL));
+
+        #ifdef ETT_PRINT_FORMAT
+    	mcSHOW_DBG_MSG2(("0x%X=0x%X\n", DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1), u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1))));
+    	mcSHOW_DBG_MSG2(("0x%X=0x%X\n", DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0), u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0))));
+        #else
+    	mcSHOW_DBG_MSG2(("0x%8x=0x%8x\n", DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1), u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1))));
+    	mcSHOW_DBG_MSG2(("0x%8x=0x%8x\n", DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0), u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0))));
+        #endif
+    }
+#endif
+	mcDELAY_US(1);
+
+    // K pull up
+    mcSHOW_DBG_MSG2(("\n\tK DRVP\n"));
+    mcFPRINTF((fp_A60501, "\n\tK DRVP\n"));
+    //PUCMP_EN=1
+    //ODT_EN=0
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), 1, IMPCAL_IMPCAL_CALI_EN);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), 1, IMPCAL_IMPCAL_CALI_ENP);  //PUCMP_EN move to CALI_ENP
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), 0, IMPCAL_IMPCAL_CALI_ENN);  //ODT_EN move to CALI_ENN
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU_IMPCAL1), P_Fld(0, SHU_IMPCAL1_IMPDRVN)|P_Fld(0, SHU_IMPCAL1_IMPDRVP));
+
+    //DRVP=0
+    //DRV05=1
+#if (fcFOR_CHIP_ID == fcLaurel)
+    if(p->dram_type == TYPE_LPDDR4)
+    {
+        u1RegTmpValue = 1;//LP4P_EN=0, DRV05=1
+    }
+    else  //TYPE_LPDDR4X || TYPE_LPDDR4P
+    {
+        u1RegTmpValue = 0;//LP4P_EN=1, DRV05=1
+    }
+#endif
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD11), u1RegTmpValue, SHU1_CA_CMD11_RG_RIMP_REV); /* fra : fix single channel b */
+
+    //OCDP Flow
+    //If RGS_TX_OCD_IMPCALOUTX=0
+    //RG_IMPX_DRVP++;
+    //Else save and keep RG_IMPX_DRVP value, and assign to DRVP
+    for(u4ImpxDrv=0; u4ImpxDrv<32; u4ImpxDrv++)
+    {
+        if(u4ImpxDrv==16) //0~15, 29~31
+            u4ImpxDrv = 29;
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_IMPCAL1), u4ImpxDrv, SHU_IMPCAL1_IMPDRVP);
+        mcDELAY_US(1);
+        u4ImpCalResult = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_PHY_RGS_CMD), MISC_PHY_RGS_CMD_RGS_RIMPCALOUT);
+        mcSHOW_DBG_MSG2(("1. OCD DRVP=%d CALOUT=%d\n", u4ImpxDrv, u4ImpCalResult));
+        mcFPRINTF((fp_A60501, "1. OCD DRVP=%d CALOUT=%d\n", u4ImpxDrv, u4ImpCalResult));
+
+        if((u4ImpCalResult ==1) && (u4DRVP_Result == 0xff))//first found
+        {
+            u4DRVP_Result = u4ImpxDrv;
+            mcSHOW_DBG_MSG2(("\n1. OCD DRVP calibration OK! DRVP=%d\n\n", u4DRVP_Result));
+            mcFPRINTF((fp_A60501, "\n1. OCD DRVP calibration OK! DRVP=%d\n\n", u4DRVP_Result));
+            break;
+        }
+    }
+
+    //LP4: ODTN calibration, LP3: DRVN calibration
+    mcSHOW_DBG_MSG2(("\n\n\tK ODTN\n"));
+    mcFPRINTF((fp_A60501, "\n\tK ODTN\n"));
+
+
+    /* Set IMP_VREF_SEL value for DRVN */
+    vImpCalVrefSel(p, term_option, IMPCAL_STAGE_DRVN);
+
+    //PUCMP_EN=0
+    //LPDDR4 : ODT_EN=1
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), 0, IMPCAL_IMPCAL_CALI_ENP);  //PUCMP_EN move to CALI_ENP
+
+    if(p->dram_type == TYPE_LPDDR4 || p->dram_type == TYPE_LPDDR4X)
+    {
+        if (term_option == 1)
+        {
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), 1, IMPCAL_IMPCAL_CALI_ENN);  //ODT_EN move to CALI_ENN
+        }
+    }
+
+    //DRVP=DRVP_FINAL
+    //DRVN=0
+    //DRV05=1
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU_IMPCAL1), P_Fld(u4DRVP_Result, SHU_IMPCAL1_IMPDRVP) | P_Fld(0, SHU_IMPCAL1_IMPDRVN));
+
+#if (fcFOR_CHIP_ID == fcLaurel)
+    if(p->dram_type == TYPE_LPDDR4)
+    {
+        u1RegTmpValue = 1;//LP4P_EN=0, DRV05=1
+    }
+    else  //TYPE_LPDDR4X || TYPE_LPDDR4P
+    {
+        u1RegTmpValue = 3;//LP4P_EN=1, DRV05=3
+    }
+#endif
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD11), u1RegTmpValue, SHU1_CA_CMD11_RG_RIMP_REV);  /*Fra : A, B write same value to avoid dram init A broadcast to B when single CHB */
+
+
+
+    //If RGS_TX_OCD_IMPCALOUTX=1
+    //RG_IMPX_DRVN++;
+    //Else save RG_IMPX_DRVN value and assign to DRVN
+    for(u4ImpxDrv=0; u4ImpxDrv<32 ; u4ImpxDrv++)
+    {
+        if(u4ImpxDrv==16) //0~15, 29~31
+            u4ImpxDrv = 29;
+
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_IMPCAL1), u4ImpxDrv, SHU_IMPCAL1_IMPDRVN);
+        mcDELAY_US(1);
+        u4ImpCalResult = u4IO32ReadFldAlign((DDRPHY_MISC_PHY_RGS_CMD), MISC_PHY_RGS_CMD_RGS_RIMPCALOUT);
+        mcSHOW_DBG_MSG2(("3. OCD ODTN=%d ,CALOUT=%d\n", u4ImpxDrv, u4ImpCalResult));
+        mcFPRINTF((fp_A60501, "3. OCD ODTN=%d ,CALOUT=%d\n", u4ImpxDrv, u4ImpCalResult));
+
+        if((u4ImpCalResult ==0) &&(u4ODTN_Result == 0xff))//first found
+        {
+            u4ODTN_Result = u4ImpxDrv;
+            mcSHOW_DBG_MSG2(("\n3. OCD ODTN calibration OK! ODTN=%d\n\n", u4ODTN_Result));
+            mcFPRINTF((fp_A60501, "\n3. OCD ODTN calibration OK! ODTN=%d\n\n", u4ODTN_Result));
+            break;
+        }
+    }
+
+    //Register Restore
+    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), u4BaklReg_DRAMC_REG_IMPCAL);
+    //vIO32Write4B((DDRPHY_MISC_IMP_CTRL0), u4BaklReg_DDRPHY_MISC_IMP_CTRL0);
+    //vIO32Write4B((DDRPHY_MISC_IMP_CTRL1), u4BaklReg_DDRPHY_MISC_IMP_CTRL1);
+
+
+/*** default value if K fail
+    LP3:  DRVP=8, DRVN=9
+    LP4:  DRVP=6, DRVN=9, ODTN=14
+    LP4X(UT): DRVP=12, DRVN=9
+    LP4X(T):  DRVP=5, DRVN=9, ODTN=14
+    LP4P: DRVP=8, DRVN=10
+***/
+    if(u1IsLP4Family(p->dram_type))
+    {
+#if (fcFOR_CHIP_ID == fcLaurel)
+        u4DRVN_Result = 9; //fixed value from DE YingMin Liao
+#endif
+
+        if(u4DRVP_Result==0xff)
+        {
+            mcFPRINTF((fp_A60501, "\n[CHIP_SCAN]1. OCD DRVP calibration FAIL! \n\n"));
+#if (fcFOR_CHIP_ID == fcLaurel)
+            u4DRVP_Result = 31;
+#endif
+        }
+        if(u4ODTN_Result==0xff || u4DRVP_Result==0xff)
+        {
+            mcFPRINTF((fp_A60501, "\n[CHIP_SCAN]3. OCD ODTN calibration FAIL! \n\n"));
+#if (fcFOR_CHIP_ID == fcLaurel)
+            u4ODTN_Result = 31;
+#endif
+        }
+
+        mcSHOW_DBG_MSG(("[SwImpedanceCal] DRVP=%d, DRVN=%d, ODTN=%d\n", u4DRVP_Result, u4DRVN_Result, u4ODTN_Result));
+        mcFPRINTF((fp_A60501, "[SwImpedanceCal] DRVP=%d, DRVN=%d, ODTN=%d\n", u4DRVP_Result, u4DRVN_Result, u4ODTN_Result));
+
+        #if 0//HYNIX_IMPX_ADJUST
+        if(u1Para)
+        {
+            u4ODTN_Result= ImpedanceAdjustment_Hynix(u4ODTN_Result, u1Para);
+        }
+        #endif
+
+        if((p->dram_type == TYPE_LPDDR4X || p->dram_type == TYPE_LPDDR4P) && (term_option ==0))
+        {
+            gDramcSwImpedanceResule[term_option][DRVP] = u4DRVP_Result;
+            gDramcSwImpedanceResule[term_option][DRVN] = u4ODTN_Result;    //Justin : LP4X unterm DRVN is ODTN * 2
+            gDramcSwImpedanceResule[term_option][ODTP] = 0;
+            gDramcSwImpedanceResule[term_option][ODTN] = 15;    //Justin : LP4X unterm, ODTN is useless
+        }
+        else
+        {
+            gDramcSwImpedanceResule[term_option][DRVP] = (u4DRVP_Result<=3) ? (u4DRVP_Result * 3) : u4DRVP_Result;
+            gDramcSwImpedanceResule[term_option][DRVN] = (u4DRVN_Result<=3) ? (u4DRVN_Result * 3) : u4DRVN_Result;
+            gDramcSwImpedanceResule[term_option][ODTP] = 0;
+            gDramcSwImpedanceResule[term_option][ODTN] = (u4ODTN_Result<=3) ? (u4ODTN_Result * 3) : u4ODTN_Result;
+        }
+    }
+#if ENABLE_LP3_SW
+    else  //LPDDR3
+    {
+        u4DRVN_Result = u4ODTN_Result;
+        if(u4DRVN_Result==0xff || u4DRVP_Result==0xff)
+        {
+            u4DRVP_Result = 8;
+        	u4DRVN_Result = 9;
+		}
+
+        gDramcSwImpedanceResule[term_option][DRVP] = (u4DRVP_Result<=3) ? (u4DRVP_Result * 3) : u4DRVP_Result;
+        gDramcSwImpedanceResule[term_option][DRVN] = (u4DRVN_Result<=3) ? (u4DRVN_Result * 3) : u4DRVN_Result;
+        gDramcSwImpedanceResule[term_option][ODTP] = 0;
+        gDramcSwImpedanceResule[term_option][ODTN] = (u4ODTN_Result<=3) ? (u4ODTN_Result * 3) : u4ODTN_Result;
+    }
+#endif
+
+    /* Set IMP_VREF_SEL value for TRACKING/RUN-TIME */
+    vImpCalVrefSel(p, term_option, IMPCAL_STAGE_TRACKING);
+
+#if RUNTIME_SHMOO_RELEATED_FUNCTION && SUPPORT_SAVE_TIME_FOR_CALIBRATION
+    {
+        U8 u1drv;
+        {
+            for (u1drv=0; u1drv<4; u1drv++)
+            {
+                if(p->femmc_Ready==0)
+                    p->pSavetimeData->u1SwImpedanceResule[term_option][u1drv] = gDramcSwImpedanceResule[term_option][u1drv];
+                else
+                    gDramcSwImpedanceResule[term_option][u1drv] = p->pSavetimeData->u1SwImpedanceResule[term_option][u1drv];
+            }
+        }
+    }
+#endif
+    mcSHOW_DBG_MSG(("term_option=%d, Reg: DRVP=%d, DRVN=%d, ODTN=%d\n", term_option, gDramcSwImpedanceResule[term_option][DRVP],
+                                        gDramcSwImpedanceResule[term_option][DRVN], gDramcSwImpedanceResule[term_option][ODTN]));
+
+#if APPLY_SIGNAL_WAVEFORM_SETTINGS_ADJUST
+    if((p->dram_type == TYPE_LPDDR4X || p->dram_type == TYPE_LPDDR4P) && (term_option ==0))
+    {
+        gDramcSwImpedanceResule[term_option][DRVP] = SwImpedanceAdjust(gDramcSwImpedanceResule[term_option][DRVP], gDramcSwImpedanceAdjust[term_option][DRVP]);
+        gDramcSwImpedanceResule[term_option][DRVN] = SwImpedanceAdjust(gDramcSwImpedanceResule[term_option][DRVN], gDramcSwImpedanceAdjust[term_option][ODTN]);
+    }
+    else
+    {
+        gDramcSwImpedanceResule[term_option][DRVP] = SwImpedanceAdjust(gDramcSwImpedanceResule[term_option][DRVP], gDramcSwImpedanceAdjust[term_option][DRVP]);
+        gDramcSwImpedanceResule[term_option][ODTN] = SwImpedanceAdjust(gDramcSwImpedanceResule[term_option][ODTN], gDramcSwImpedanceAdjust[term_option][ODTN]);
+    }
+
+    mcSHOW_DBG_MSG(("term_option=%d, Reg: DRVP=%d, DRVN=%d, ODTN=%d (After Adjust)\n", term_option, gDramcSwImpedanceResule[term_option][DRVP],
+                                        gDramcSwImpedanceResule[term_option][DRVN], gDramcSwImpedanceResule[term_option][ODTN]));
+#endif
+
+#if SIMULATION_SW_IMPED && ENABLE_LP3_SW
+    //LP3 updates impedance parameters to shuffle "SaveRegister" here, un-term only
+    if(p->dram_type == TYPE_LPDDR3)
+        DramcSwImpedanceSaveRegister(p, term_option, term_option, DRAM_DFS_SHUFFLE_1);
+#endif
+
+
+#if defined(SLT)
+    if (gDramcSwImpedanceResule[term_option][DRVP] >= 31 && (term_option ==1) ) {
+        mcSHOW_DBG_MSG(("SLT_BIN2\n"));
+        while(1);
+    }
+#endif
+
+
+    vSetCalibrationResult(p, DRAM_CALIBRATION_SW_IMPEDANCE, DRAM_OK);
+    mcSHOW_DBG_MSG3(("[DramcSwImpedanceCal] Done\n\n"));
+    mcFPRINTF((fp_A60501, "[DramcSwImpedanceCal] Done\n\n"));
+
+    vSetPHY2ChannelMapping(p, backup_channel);
+    DramcBroadcastOnOff(backup_broadcast);
+
+    return DRAM_OK;
+}
+#endif //SIMULATION_SW_IMPED
+
+void DramcUpdateImpedanceTerm2UnTerm(DRAMC_CTX_T *p)
+{
+    gDramcSwImpedanceResule[ODT_OFF][ODTP] = gDramcSwImpedanceResule[ODT_ON][ODTP];
+    gDramcSwImpedanceResule[ODT_OFF][ODTN] = gDramcSwImpedanceResule[ODT_ON][ODTN];
+}
+
+#ifdef ENABLE_HW_IMPCAL
+DRAM_STATUS_T DramcHwImpedanceCal(DRAMC_CTX_T *p, U8 u1Para, U8 term_option)
+{
+    U32 u4ImpxDrv, u4ImpCalResult;
+    U32 u4DRVP_Result =0xff,u4ODTN_Result =0xff, u4DRVN_Result =0xff;
+    U32 u4BaklReg_DDRPHY_MISC_IMP_CTRL0, u4BaklReg_DDRPHY_MISC_IMP_CTRL1, u4BaklReg_DRAMC_REG_IMPCAL;
+    U32 u4BaklReg_DRAMC_REG_REFCTRL0;
+    U8 u1ByteIdx, u1RegTmpValue;
+    U8 backup_channel;
+    U8 backup_broadcast;
+
+    backup_broadcast = GetDramcBroadcast();
+
+    DramcBroadcastOnOff(DRAMC_BROADCAST_OFF);
+
+    // Darren
+    vIO32WriteFldMulti_All(DDRPHY_MISC_SPM_CTRL1, P_Fld(0x0, MISC_SPM_CTRL1_RG_ARDMSUS_10) | P_Fld(0x0, MISC_SPM_CTRL1_RG_ARDMSUS_10_B0)
+                                           | P_Fld(0x0, MISC_SPM_CTRL1_RG_ARDMSUS_10_B1) | P_Fld(0x0, MISC_SPM_CTRL1_RG_ARDMSUS_10_CA));
+
+    vIO32WriteFldAlign_All(DDRPHY_MISC_SPM_CTRL2, 0x0, MISC_SPM_CTRL2_PHY_SPM_CTL2);
+    vIO32WriteFldAlign_All(DDRPHY_MISC_SPM_CTRL0, 0x0, MISC_SPM_CTRL0_PHY_SPM_CTL0);
+
+    //Disable IMP HW Tracking
+    vIO32WriteFldAlign_All(DRAMC_REG_IMPCAL, 0, IMPCAL_IMPCAL_HW);
+
+    backup_channel = p->channel;
+    vSetPHY2ChannelMapping(p, CHANNEL_A);
+
+    //Register backup
+    //u4BaklReg_DDRPHY_MISC_IMP_CTRL0 = u4IO32Read4B((DDRPHY_MISC_IMP_CTRL0));
+    //u4BaklReg_DDRPHY_MISC_IMP_CTRL1 = u4IO32Read4B((DDRPHY_MISC_IMP_CTRL1));
+    u4BaklReg_DRAMC_REG_IMPCAL = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL));
+    u4BaklReg_DRAMC_REG_REFCTRL0 = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0));
+
+    //enable autorefresh
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0), 0, REFCTRL0_REFDIS); //REFDIS=0, enable autorefresh
+
+    //Basic setup
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA2), 0x7, SHU_SELPH_CA2_TXDLY_CMD);
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1), 0, MISC_IMP_CTRL1_RG_RIMP_PRE_EN);
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), P_Fld(0, IMPCAL_IMPCAL_IMPPDP) |
+                        P_Fld(0, IMPCAL_IMPCAL_IMPPDN) |
+                        P_Fld(0, IMPCAL_IMPCAL_CALI_ENP) |
+                        P_Fld(0, IMPCAL_IMPCAL_CALI_ENN) |
+                        P_Fld(0, IMPCAL_IMPCAL_CALI_EN) |
+                        //P_Fld(0, IMPCAL_IMPCAL_DRVUPOPT) |    // for Cannon project
+                        P_Fld(1, IMPCAL_IMPCAL_NEW_OLD_SL) |    //Impedance tracking form, 0: old, 1:new.
+                        P_Fld(1, IMPCAL_IMPCAL_SWVALUE_EN));    //Impedance tracking DRVP, DRVN initial value from SW setting
+
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU_IMPCAL1), P_Fld(0, SHU_IMPCAL1_IMPDRVP) |   //Set SW calibration value & HW initial calibration value for OCDP
+                        P_Fld(3, SHU_IMPCAL1_IMPCALCNT) |  //hw impcal interval (unit: the number of refresh)
+                        P_Fld(7, SHU_IMPCAL1_IMPCAL_CHKCYCLE)); //hw impcal calibration to check CMPOOUT
+
+    /* Set IMP_VREF_SEL value for DRVP */
+    vImpCalVrefSel(p, term_option, IMPCAL_STAGE_DRVP);
+
+#if (fcFOR_CHIP_ID == fcLaurel)
+    if(p->dram_type == TYPE_LPDDR4)
+    {
+        u1RegTmpValue = 1;//LP4P_EN=0, DRV05=1
+    }
+    else  //TYPE_LPDDR4X || TYPE_LPDDR4P
+    {
+        u1RegTmpValue = 0;//LP4P_EN=1, DRV05=1
+    }
+#endif
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD11), u1RegTmpValue, SHU1_CA_CMD11_RG_RIMP_REV);
+
+    if(u1IsLP4Family(p->dram_type))
+    {
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0), P_Fld(0, MISC_IMP_CTRL0_RG_IMP_EN) | \
+                            P_Fld(0, MISC_IMP_CTRL0_RG_RIMP_DDR3_SEL) | \
+                            P_Fld(1, MISC_IMP_CTRL0_RG_RIMP_DDR4_SEL));
+    }
+#if ENABLE_LP3_SW
+    else //LPDDR3
+    {
+        //enable auto refresh process for LP3
+        //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0), 1, REFCTRL0_REFDIS);
+        //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 1, DRAMC_PD_CTRL_DCMREF_OPT);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL), 1, CKECTRL_CKEFIXON);
+        //mcDELAY_US(1);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL), 0, CKECTRL_CKEFIXON);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0), 1, REFCTRL0_REFFRERUN);
+        //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_ACTIM3), 0x70, SHU_ACTIM3_REFCNT);
+        //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0), 0, REFCTRL0_REFDIS);
+
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_IMPCAL1), 0x1F, SHU_IMPCAL1_IMPDRVN);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1_DRVING2), 1, SHU1_DRVING2_DIS_IMPCAL_ODT_EN);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1_DRVING1), 0x1, SHU1_DRVING1_DIS_IMP_ODTN_TRACK);
+
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0), P_Fld(0, MISC_IMP_CTRL0_RG_IMP_EN) | \
+                            P_Fld(1, MISC_IMP_CTRL0_RG_RIMP_DDR3_SEL) | \
+                            P_Fld(0, MISC_IMP_CTRL0_RG_RIMP_DDR4_SEL));
+
+        #ifdef ETT_PRINT_FORMAT
+    	mcSHOW_DBG_MSG2(("0x%X=0x%X\n", DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1), u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1))));
+    	mcSHOW_DBG_MSG2(("0x%X=0x%X\n", DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0), u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0))));
+        #else
+    	mcSHOW_DBG_MSG2(("0x%8x=0x%8x\n", DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1), u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1))));
+    	mcSHOW_DBG_MSG2(("0x%8x=0x%8x\n", DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0), u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0))));
+        #endif
+    }
+#endif
+
+    //Enable HW Imp tracking for calibration (SW impcal switch, 0: SW. 1:HW.)
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), 1, IMPCAL_IMPCAL_HW);
+#if ENABLE_LP3_SW
+    if(p->dram_type == TYPE_LPDDR3)
+    {
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), 1, IMPCAL_IMPCAL_EN);  //lp3 needed
+    }
+#endif
+
+    {
+        U8 DQ_DRVP,DQ_ODTN;
+        int u1Dly_cnt = 0;
+
+        while (2000>(u1Dly_cnt++))
+        {
+            if(u1IsLP4Family(p->dram_type))
+            {
+                DQ_DRVP = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL_STATUS2), IMPCAL_STATUS2_DRVPDQ_SAVE1);
+                DQ_ODTN = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL_STATUS2), IMPCAL_STATUS2_DRVNDQ_SAVE1);
+            }
+#if ENABLE_LP3_SW
+            else
+            {
+                DQ_DRVP = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CMDDRV_STATUS), CMDDRV_STATUS_DRVPDQ_1);
+                DQ_ODTN = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CMDDRV_STATUS), CMDDRV_STATUS_DRVNDQ_1);
+            }
+#endif
+            if (DQ_DRVP!=0 && DQ_ODTN!=0)
+            {
+                u4DRVP_Result = DQ_DRVP;
+                u4ODTN_Result = DQ_ODTN;
+                break;
+            }
+            mcDELAY_US(1);
+        }
+    }
+
+    //Register Restore
+    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), u4BaklReg_DRAMC_REG_IMPCAL);
+    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0), u4BaklReg_DRAMC_REG_REFCTRL0);
+
+
+/*** default value if K fail
+    LP3:  DRVP=8, DRVN=9
+    LP4:  DRVP=6, DRVN=9, ODTN=14
+    LP4X(UT): DRVP=12, DRVN=9
+    LP4X(T):  DRVP=5, DRVN=9, ODTN=14
+    LP4P: DRVP=8, DRVN=10
+***/
+    if(u1IsLP4Family(p->dram_type))
+    {
+#if (fcFOR_CHIP_ID == fcLaurel)
+        u4DRVN_Result = 9; //fixed value from DE YingMin Liao
+#endif
+
+        if(u4DRVP_Result==0xff)
+        {
+            mcFPRINTF((fp_A60501, "\n[CHIP_SCAN]1. OCD DRVP calibration FAIL! \n\n"));
+#if (fcFOR_CHIP_ID == fcLaurel)
+            u4DRVP_Result = 31;
+#endif
+        }
+        if(u4ODTN_Result==0xff || u4DRVP_Result==0xff)
+        {
+            mcFPRINTF((fp_A60501, "\n[CHIP_SCAN]3. OCD ODTN calibration FAIL! \n\n"));
+#if (fcFOR_CHIP_ID == fcLaurel)
+            u4ODTN_Result = 31;
+#endif
+        }
+
+        mcSHOW_DBG_MSG(("[HwImpedanceCal] DRVP=%d, DRVN=%d, ODTN=%d\n", u4DRVP_Result, u4DRVN_Result, u4ODTN_Result));
+        mcFPRINTF((fp_A60501, "[HwImpedanceCal] DRVP=%d, DRVN=%d, ODTN=%d\n", u4DRVP_Result, u4DRVN_Result, u4ODTN_Result));
+
+        #if 0//HYNIX_IMPX_ADJUST
+        if(u1Para)
+        {
+            u4ODTN_Result= ImpedanceAdjustment_Hynix(u4ODTN_Result, u1Para);
+        }
+        #endif
+
+        if((p->dram_type == TYPE_LPDDR4X || p->dram_type == TYPE_LPDDR4P) && (term_option ==0))
+        {
+            gDramcSwImpedanceResule[term_option][DRVP] = u4DRVP_Result;
+            gDramcSwImpedanceResule[term_option][DRVN] = u4ODTN_Result;    //Justin : LP4X unterm DRVN is ODTN * 2
+            gDramcSwImpedanceResule[term_option][ODTP] = 0;
+            gDramcSwImpedanceResule[term_option][ODTN] = 15;    //Justin : LP4X unterm, ODTN is useless
+        }
+        else
+        {
+            gDramcSwImpedanceResule[term_option][DRVP] = (u4DRVP_Result<=3) ? (u4DRVP_Result * 3) : u4DRVP_Result;
+            gDramcSwImpedanceResule[term_option][DRVN] = (u4DRVN_Result<=3) ? (u4DRVN_Result * 3) : u4DRVN_Result;
+            gDramcSwImpedanceResule[term_option][ODTP] = 0;
+            gDramcSwImpedanceResule[term_option][ODTN] = (u4ODTN_Result<=3) ? (u4ODTN_Result * 3) : u4ODTN_Result;
+        }
+    }
+#if ENABLE_LP3_SW
+    else  //LPDDR3
+    {
+        u4DRVN_Result = u4ODTN_Result;
+        if(u4DRVN_Result==0xff || u4DRVP_Result==0xff)
+        {
+            u4DRVP_Result = 8;
+            u4DRVN_Result = 9;
+		}
+
+        gDramcSwImpedanceResule[term_option][DRVP] = (u4DRVP_Result<=3) ? (u4DRVP_Result * 3) : u4DRVP_Result;
+        gDramcSwImpedanceResule[term_option][DRVN] = (u4DRVN_Result<=3) ? (u4DRVN_Result * 3) : u4DRVN_Result;
+        gDramcSwImpedanceResule[term_option][ODTP] = 0;
+        gDramcSwImpedanceResule[term_option][ODTN] = (u4ODTN_Result<=3) ? (u4ODTN_Result * 3) : u4ODTN_Result;
+    }
+#endif
+
+    /* Set IMP_VREF_SEL value for TRACKING/RUN-TIME */
+    vImpCalVrefSel(p, term_option, IMPCAL_STAGE_TRACKING);
+
+#if RUNTIME_SHMOO_RELEATED_FUNCTION && SUPPORT_SAVE_TIME_FOR_CALIBRATION
+    {
+        U8 u1drv;
+        {
+            for (u1drv=0; u1drv<4; u1drv++)
+            {
+                if(p->femmc_Ready==0)
+                    p->pSavetimeData->u1SwImpedanceResule[term_option][u1drv] = gDramcSwImpedanceResule[term_option][u1drv];
+                else
+                    gDramcSwImpedanceResule[term_option][u1drv] = p->pSavetimeData->u1SwImpedanceResule[term_option][u1drv];
+            }
+        }
+    }
+#endif
+    mcSHOW_DBG_MSG(("term_option=%d, Reg: DRVP=%d, DRVN=%d, ODTN=%d\n", term_option, gDramcSwImpedanceResule[term_option][0],
+                                        gDramcSwImpedanceResule[term_option][1], gDramcSwImpedanceResule[term_option][ODTN]));
+
+#if APPLY_SIGNAL_WAVEFORM_SETTINGS_ADJUST
+        if((p->dram_type == TYPE_LPDDR4X || p->dram_type == TYPE_LPDDR4P) && (term_option ==0))
+        {
+            gDramcSwImpedanceResule[term_option][DRVP] = SwImpedanceAdjust(gDramcSwImpedanceResule[term_option][DRVP], gDramcSwImpedanceAdjust[term_option][DRVP]);
+            gDramcSwImpedanceResule[term_option][DRVN] = SwImpedanceAdjust(gDramcSwImpedanceResule[term_option][DRVN], gDramcSwImpedanceAdjust[term_option][ODTN]);
+        }
+        else
+        {
+            gDramcSwImpedanceResule[term_option][DRVP] = SwImpedanceAdjust(gDramcSwImpedanceResule[term_option][DRVP], gDramcSwImpedanceAdjust[term_option][DRVP]);
+            gDramcSwImpedanceResule[term_option][ODTN] = SwImpedanceAdjust(gDramcSwImpedanceResule[term_option][ODTN], gDramcSwImpedanceAdjust[term_option][ODTN]);
+        }
+
+        mcSHOW_DBG_MSG(("term_option=%d, Reg: DRVP=%d, DRVN=%d, ODTN=%d (After Adjust)\n", term_option, gDramcSwImpedanceResule[term_option][DRVP],
+                                            gDramcSwImpedanceResule[term_option][DRVN], gDramcSwImpedanceResule[term_option][ODTN]));
+#endif
+
+#if SIMULATION_SW_IMPED && ENABLE_LP3_SW
+        //LP3 updates impedance parameters to shuffle "SaveRegister" here, un-term only
+        if(p->dram_type == TYPE_LPDDR3)
+            DramcSwImpedanceSaveRegister(p, term_option, term_option, DRAM_DFS_SHUFFLE_1);
+#endif
+
+
+#if defined(SLT)
+        if (gDramcSwImpedanceResule[term_option][DRVP] >= 31 && (term_option ==1) ) {
+            mcSHOW_DBG_MSG(("SLT_BIN2\n"));
+            while(1);
+        }
+#endif
+
+    vSetCalibrationResult(p, DRAM_CALIBRATION_SW_IMPEDANCE, DRAM_OK);
+    mcSHOW_DBG_MSG3(("[DramcSwImpedanceCal] Done\n\n"));
+    mcFPRINTF((fp_A60501, "[DramcSwImpedanceCal] Done\n\n"));
+
+    vSetPHY2ChannelMapping(p, backup_channel);
+    DramcBroadcastOnOff(backup_broadcast);
+
+    return DRAM_OK;
+}
+#endif
+
+#if 0
+void Dram_Reset(DRAMC_CTX_T *p)
+{
+    // This function is implemented based on DE's bring up flow for DRAMC
+    #if !SW_CHANGE_FOR_SIMULATION
+    if(p->dram_type == TYPE_LPDDR3)
+        DramcModeRegInit_LP3(p);
+    else
+        DramcModeRegInit_LP4(p);
+    #endif
+
+    ///TODO: update MR2(WL& RL) from AC timing table
+}
+#endif
+
+
+void O1PathOnOff(DRAMC_CTX_T *p, U8 u1OnOff)
+{
+    U8 u1FixDQIEN = 0;
+
+    if (u1IsLP4Family(p->dram_type))
+    {
+        u1FixDQIEN = (u1OnOff == ENABLE) ? 3 : 0;
+        vIO32WriteFldAlign_All(DRAMC_REG_PADCTRL, u1FixDQIEN, PADCTRL_FIXDQIEN);
+
+        vIO32WriteFldAlign_All(DDRPHY_B0_DQ5, u1OnOff, B0_DQ5_RG_RX_ARDQ_EYE_VREF_EN_B0);
+        vIO32WriteFldAlign_All(DDRPHY_B1_DQ5, u1OnOff, B1_DQ5_RG_RX_ARDQ_EYE_VREF_EN_B1);
+        vIO32WriteFldAlign_All(DDRPHY_B0_DQ3, u1OnOff, B0_DQ3_RG_RX_ARDQ_SMT_EN_B0);
+        vIO32WriteFldAlign_All(DDRPHY_B1_DQ3, u1OnOff, B1_DQ3_RG_RX_ARDQ_SMT_EN_B1);
+    }
+    #if ENABLE_LP3_SW
+    else
+    {
+        u1FixDQIEN = (u1OnOff == ENABLE) ? 15 : 0;
+        vIO32WriteFldAlign_All(DRAMC_REG_PADCTRL, u1FixDQIEN, PADCTRL_FIXDQIEN);
+
+        vIO32WriteFldAlign(DDRPHY_B1_DQ5, u1OnOff, B1_DQ5_RG_RX_ARDQ_EYE_VREF_EN_B1);                     //CHA B1
+        vIO32WriteFldAlign(DDRPHY_B0_DQ5 + SHIFT_TO_CHB_ADDR, u1OnOff, B0_DQ5_RG_RX_ARDQ_EYE_VREF_EN_B0);   //CHB B0
+        vIO32WriteFldAlign(DDRPHY_CA_CMD5 + SHIFT_TO_CHB_ADDR, u1OnOff, CA_CMD5_RG_RX_ARCMD_EYE_VREF_EN);   //CHB CA
+        vIO32WriteFldAlign(DDRPHY_B1_DQ5 + SHIFT_TO_CHB_ADDR, u1OnOff, B1_DQ5_RG_RX_ARDQ_EYE_VREF_EN_B1);   //CHB B1
+
+        vIO32WriteFldAlign(DDRPHY_B1_DQ3, u1OnOff, B1_DQ3_RG_RX_ARDQ_SMT_EN_B1);                      //CHA B1
+        vIO32WriteFldAlign(DDRPHY_B0_DQ3 + SHIFT_TO_CHB_ADDR, u1OnOff, B0_DQ3_RG_RX_ARDQ_SMT_EN_B0);    //CHB B0
+        vIO32WriteFldAlign(DDRPHY_CA_CMD3 + SHIFT_TO_CHB_ADDR, u1OnOff, CA_CMD3_RG_RX_ARCMD_SMT_EN);    //CHB CA
+        vIO32WriteFldAlign(DDRPHY_B1_DQ3 + SHIFT_TO_CHB_ADDR, u1OnOff, B1_DQ3_RG_RX_ARDQ_SMT_EN_B1);    //CHB B1
+    }
+    #endif
+    mcDELAY_US(1);
+}
+
+void CATrainingPosCal(DRAMC_CTX_T *p, U8* pu1LP3DieNum, S8* ps1CAMacroDelay, S8 *ps1CACenterDiff)
+{
+    U8 u1RankIdx, u1DieIdx, u1CAIdx, u1MacroIdx, u1MacroNum;
+    S8 s1Intersect_min_byMacro[2], s1Intersect_max_byMacro[2];
+    S8 s1Intersect_min_byBit[CATRAINING_NUM], s1Intersect_max_byBit[CATRAINING_NUM], s1CACenter_min[2];//, s1CACenter[CATRAINING_NUM];
+    S8 s1TempFirstPass, s1TempLastPass;
+    U8 u1PerBitDelayCellEnable =0, u1CABitNum=0;
+    S8 s1CACenter[CATRAINING_NUM];
+
+    if (!u1IsLP4Family(p->dram_type))
+    {
+#if LP3_CA_PER_BIT
+        u1PerBitDelayCellEnable =1;
+#endif
+        u1CABitNum = 10;
+    }
+
+    if (u1IsLP4Family(p->dram_type))
+    {
+#if CA_PER_BIT_DELAY_CELL
+        u1PerBitDelayCellEnable =1;
+#endif
+        u1CABitNum =6;
+    }
+
+    mcSHOW_DBG_MSG(("\n[CATrainingPosCal] consider %d rank data\n", p->rank +1));
+
+    for(u1MacroIdx =0; u1MacroIdx <2; u1MacroIdx++)
+    {
+        s1Intersect_min_byMacro[u1MacroIdx] = -127; // 127
+        s1Intersect_max_byMacro[u1MacroIdx] = 127; //-127
+        s1CACenter_min[u1MacroIdx] = 0x7f;
+    }
+
+    for(u1CAIdx=0; u1CAIdx < u1CABitNum; u1CAIdx++)
+    {
+        s1Intersect_min_byBit[u1CAIdx] = -127; // 127
+        s1Intersect_max_byBit[u1CAIdx] = 127; //-127
+
+        if (u1IsLP4Family(p->dram_type))
+        {
+            u1MacroIdx=0;
+        }
+        else //LP3
+        {
+            if(u1CAIdx==0 || u1CAIdx==1)
+            {
+                u1MacroIdx=0;
+            }
+            else
+                u1MacroIdx=1;
+        }
+
+        for(u1RankIdx=RANK_0; u1RankIdx<(p->rank+1); u1RankIdx++)
+        {
+            for(u1DieIdx=0; u1DieIdx< pu1LP3DieNum[u1RankIdx]; u1DieIdx++)
+            {
+                s1TempFirstPass = iFirstCAPass[u1RankIdx][u1DieIdx][u1CAIdx];
+                s1TempLastPass = iLastCAPass[u1RankIdx][u1DieIdx][u1CAIdx];
+                //mcSHOW_DBG_MSG(("RK%d, Die%d ,CA%d,iFirstCAPass = %d, iLastCAPass=%d \n",u1RankIdx, u1DieIdx, u1CAIdx, s1TempFirstPass, s1TempLastPass));
+
+                // Intersection by Macro
+                if(s1TempFirstPass > s1Intersect_min_byMacro[u1MacroIdx])
+                    s1Intersect_min_byMacro[u1MacroIdx] = s1TempFirstPass;
+
+                if(s1TempLastPass < s1Intersect_max_byMacro[u1MacroIdx])
+                    s1Intersect_max_byMacro[u1MacroIdx] = s1TempLastPass;
+
+                // intersection by CA bit
+                if(s1TempFirstPass > s1Intersect_min_byBit[u1CAIdx])
+                    s1Intersect_min_byBit[u1CAIdx] = s1TempFirstPass;
+
+                if(s1TempLastPass < s1Intersect_max_byBit[u1CAIdx])
+                    s1Intersect_max_byBit[u1CAIdx] = s1TempLastPass;
+            }
+        }
+
+        s1CACenter[u1CAIdx] = (s1Intersect_min_byBit[u1CAIdx] +s1Intersect_max_byBit[u1CAIdx])/2;
+
+        if(s1CACenter[u1CAIdx] < s1CACenter_min[u1MacroIdx])
+            s1CACenter_min[u1MacroIdx] = s1CACenter[u1CAIdx];
+    }
+
+    // If CA perbit, choose min CA PI of all bits.
+    // If CA perbyte, choose middle position of intersenction range of all bits.
+    if(u1IsLP4Family(p->dram_type))
+    {
+        u1MacroNum=1;
+    }
+    else //LP3
+    {
+        u1MacroNum=2;
+    }
+
+    // CA perbit enable
+    if(u1PerBitDelayCellEnable && (p->u2DelayCellTimex100 !=0))
+    {
+        for(u1MacroIdx =0; u1MacroIdx<u1MacroNum; u1MacroIdx++)
+        {
+            #if LP3_CATRAING_SHIFT_CLK_PI
+            if(u1IsLP4Family(p->dram_type))
+            #endif
+            {
+                if(s1CACenter_min[u1MacroIdx] <0) //don't move clk
+                {
+                    //mcSHOW_DBG_MSG(("warning : Macro%d minimum CA PI delay is %d(<0) and changed to 0\n", u1MacroIdx, s1CACenter_min[u1MacroIdx]));
+                    s1CACenter_min[u1MacroIdx] =0;
+                }
+            }
+
+            ps1CAMacroDelay[u1MacroIdx] = s1CACenter_min[u1MacroIdx];
+        }
+
+        mcSHOW_DBG_MSG(("u2DelayCellTimex100 = %d/100 ps\n", p->u2DelayCellTimex100));
+
+        for(u1CAIdx=0; u1CAIdx < u1CABitNum; u1CAIdx++)
+        {
+            if(u1IsLP4Family(p->dram_type))
+            {
+                u1MacroIdx=0;
+            }
+            else //LP3
+            {
+                if(u1CAIdx==0 || u1CAIdx==1)
+                {
+                    u1MacroIdx=0;
+                }
+                else
+                    u1MacroIdx=1;
+            }
+
+
+            #if LP3_CATRAING_SHIFT_CLK_PI
+            if(u1IsLP4Family(p->dram_type) && s1CACenter[u1CAIdx] <0) //don't move clk
+            #else
+            if(s1CACenter[u1CAIdx] <0) //don't move clk
+            #endif
+            {
+                s1CACenter[u1CAIdx] =0;
+                ps1CACenterDiff[u1CAIdx]=0;
+            }
+            else
+            {
+                ps1CACenterDiff[u1CAIdx] = s1CACenter[u1CAIdx] - s1CACenter_min[u1MacroIdx];
+            }
+
+            mcSHOW_DBG_MSG(("CA%d delay=%d (%d~%d),", u1CAIdx, s1CACenter[u1CAIdx], s1Intersect_min_byBit[u1CAIdx], s1Intersect_max_byBit[u1CAIdx]));
+            mcSHOW_DBG_MSG(("Diff = %d PI ", ps1CACenterDiff[u1CAIdx]));
+            ps1CACenterDiff[u1CAIdx] = (ps1CACenterDiff[u1CAIdx]*100000000/(p->frequency<<6))/p->u2DelayCellTimex100;
+            mcSHOW_DBG_MSG(("(%d cell)", ps1CACenterDiff[u1CAIdx]));
+
+            if(ps1CACenterDiff[u1CAIdx]>15)
+            {
+                mcSHOW_DBG_MSG(("[WARNING] CA%d delay cell %d >15, adjust to 15 cell", u1CAIdx, ps1CACenterDiff[u1CAIdx]));
+                ps1CACenterDiff[u1CAIdx] =15;
+            }
+
+            mcSHOW_DBG_MSG(("\n"));
+        }
+
+        for(u1MacroIdx =0; u1MacroIdx < u1MacroNum; u1MacroIdx++)
+        {
+            mcSHOW_DBG_MSG(("\nCA PerBit enable=%d, Macro%d, CA PI delay=%d\n", u1PerBitDelayCellEnable, u1MacroIdx, ps1CAMacroDelay[u1MacroIdx]));
+        }
+    }
+    else //CA perbyte
+    {
+        for(u1MacroIdx =0; u1MacroIdx < u1MacroNum; u1MacroIdx++)
+        {
+            ps1CAMacroDelay[u1MacroIdx] = (s1Intersect_min_byMacro[u1MacroIdx] +s1Intersect_max_byMacro[u1MacroIdx])/2;
+
+            if(ps1CAMacroDelay[u1MacroIdx] <0)//don't move clk
+            {
+                //mcSHOW_DBG_MSG(("warning : CA PI delay is %d(<0) and changed to 0\n", ps1CAMacroDelay[u1MacroIdx]));
+                ps1CAMacroDelay[u1MacroIdx] =0;
+            }
+            mcSHOW_DBG_MSG(("CA PerBit enable=%d, Macro%d, CA PI delay=%d (%d~%d)\n", u1PerBitDelayCellEnable, u1MacroIdx, ps1CAMacroDelay[u1MacroIdx], s1Intersect_min_byMacro[u1MacroIdx], s1Intersect_max_byMacro[u1MacroIdx]));
+        }
+    }
+}
+
+#if PINMUX_AUTO_TEST_PER_BIT_CA
+void CheckCADelayCell(DRAMC_CTX_T *p)
+{
+    DRAM_CHANNEL_T channel_bak = p->channel;
+    DRAM_RANK_T rank_bak = p->rank;
+
+    vSetPHY2ChannelMapping(p, CHANNEL_A);
+    vSetRank(p, RANK_0);
+    mcSHOW_DBG_MSG(("CA_delay_cell CHA R0[%X] CHB R0[%X] CHA R1[%X] CHB R1[%X]\n",
+    u4IO32Read4B(DDRPHY_SHU1_R0_CA_CMD0),
+    u4IO32Read4B(DDRPHY_SHU1_R0_CA_CMD0 + SHIFT_TO_CHB_ADDR),
+    u4IO32Read4B(DDRPHY_SHU1_R0_CA_CMD0 + 0x100),
+    u4IO32Read4B(DDRPHY_SHU1_R0_CA_CMD0 + SHIFT_TO_CHB_ADDR + 0x100)));
+    vSetPHY2ChannelMapping(p, channel_bak);
+    vSetRank(p, rank_bak);
+
+    return;
+}
+
+U16 gFinalCAPerbitFirstPass[CHANNEL_NUM][RANK_MAX][CATRAINING_NUM_LP4];
+void CheckCAPinMux(DRAMC_CTX_T *p)
+{
+    U8 u1CAIndex[CATRAINING_NUM_LP4] = {0};
+    U8 u1CAdelay[CATRAINING_NUM_LP4] = {0};
+    int i = 0;
+    int j = 0;
+    U8 u1Min = 0xff;
+    U8 u1MinIdx = 0;
+
+    for(i = 0; i<CATRAINING_NUM_LP4; i++)
+    {
+        memset(u1CAdelay, 0, sizeof(u1CAdelay));
+        u1CAdelay[i] = 0xf;
+
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), p->rank, RKCFG_TXRANK);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 1, RKCFG_TXRANKFIX);
+
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD0), P_Fld(u1CAdelay[5], SHU1_R0_CA_CMD0_RK0_TX_ARCA5_DLY)
+                | P_Fld(u1CAdelay[4], SHU1_R0_CA_CMD0_RK0_TX_ARCA4_DLY)
+                | P_Fld(u1CAdelay[3], SHU1_R0_CA_CMD0_RK0_TX_ARCA3_DLY)
+                | P_Fld(u1CAdelay[2], SHU1_R0_CA_CMD0_RK0_TX_ARCA2_DLY)
+                | P_Fld(u1CAdelay[1], SHU1_R0_CA_CMD0_RK0_TX_ARCA1_DLY)
+                | P_Fld(u1CAdelay[0], SHU1_R0_CA_CMD0_RK0_TX_ARCA0_DLY));
+        CmdBusTrainingLP4(p);
+
+        u1Min = 0xff;
+        for(j = 0; j<CATRAINING_NUM_LP4; j++)
+        {
+            if(gFinalCAPerbitFirstPass[p->channel][p->rank][j] <= u1Min)
+            {
+                u1Min = gFinalCAPerbitFirstPass[p->channel][p->rank][j];
+                u1MinIdx = j;
+            }
+        }
+        u1CAIndex[i] = u1MinIdx;
+    }
+    for(i = 0; i<CATRAINING_NUM_LP4; i++)
+    {
+        mcSHOW_DBG_MSG(("CH[%d] Rank[%d] APHY_CA[%d]-->DRAM(->MRR->DRAMC)[%d]\n", p->channel, p->rank, i, u1CAIndex[i]));
+        if(u1CAIndex[i] != uiLPDDR4_CA_Mapping_POP[p->channel][i])
+        {
+            mcSHOW_DBG_MSG(("!Not mapping with CA mapping table\n"));
+            while(1);
+        }
+    }
+    memset(u1CAdelay, 0, sizeof(u1CAdelay));
+    vIO32WriteFldMulti_All(DDRPHY_SHU1_R0_CA_CMD0, P_Fld(u1CAdelay[5], SHU1_R0_CA_CMD0_RK0_TX_ARCA5_DLY)
+                | P_Fld(u1CAdelay[4], SHU1_R0_CA_CMD0_RK0_TX_ARCA4_DLY)
+                | P_Fld(u1CAdelay[3], SHU1_R0_CA_CMD0_RK0_TX_ARCA3_DLY)
+                | P_Fld(u1CAdelay[2], SHU1_R0_CA_CMD0_RK0_TX_ARCA2_DLY)
+                | P_Fld(u1CAdelay[1], SHU1_R0_CA_CMD0_RK0_TX_ARCA1_DLY)
+                | P_Fld(u1CAdelay[0], SHU1_R0_CA_CMD0_RK0_TX_ARCA0_DLY));
+    return;
+}
+
+#if ENABLE_LP3_SW
+DRAM_STATUS_T CATrainingLP3(DRAMC_CTX_T *p);
+int gFinalCAPerbitFirstPass_LP3[RANK_MAX][CATRAINING_NUM_LP3];
+void CheckCAPinMux_LP3(DRAMC_CTX_T *p)
+{
+    U8 u1CAIndex[CATRAINING_NUM_LP3] = {0};
+    U8 u1CAdelay[CATRAINING_NUM_LP3] = {0};
+    int i = 0;
+    int j = 0;
+    int iMin = 0xff;
+    U8 u1MinIdx = 0;
+    int iOriFirstPass[CATRAINING_NUM_LP3] = {0};
+
+    CATrainingLP3(p);
+    for(j = 0; j < CATRAINING_NUM_LP3; j++)
+    {
+       iOriFirstPass[j] = gFinalCAPerbitFirstPass_LP3[p->rank][j];
+       mcSHOW_DBG_MSG(("### Ori first pass %d = [%d]\n", j, iOriFirstPass[j]));
+    }
+
+    for(i = 0; i < CATRAINING_NUM_LP3; i++)
+    {
+        memset(u1CAdelay, 0, sizeof(u1CAdelay));
+        u1CAdelay[i] = 0xf;
+        mcSHOW_DBG_MSG(("### Set delay cell of CA[%d]\n", i));
+
+		vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD0), P_Fld(u1CAdelay[0], SHU1_R0_CA_CMD0_RK0_TX_ARCA1_DLY) |
+			P_Fld(u1CAdelay[1], SHU1_R0_CA_CMD0_RK0_TX_ARCA3_DLY));
+		vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ0), P_Fld(u1CAdelay[2], SHU1_R0_B0_DQ0_RK0_TX_ARDQ5_DLY_B0) |
+			P_Fld(u1CAdelay[3], SHU1_R0_B0_DQ0_RK0_TX_ARDQ7_DLY_B0) |
+			P_Fld(u1CAdelay[4], SHU1_R0_B0_DQ0_RK0_TX_ARDQ2_DLY_B0) |
+			P_Fld(u1CAdelay[5], SHU1_R0_B0_DQ0_RK0_TX_ARDQ0_DLY_B0) |
+			P_Fld(u1CAdelay[6], SHU1_R0_B0_DQ0_RK0_TX_ARDQ4_DLY_B0) |
+			P_Fld(u1CAdelay[7], SHU1_R0_B0_DQ0_RK0_TX_ARDQ6_DLY_B0) |
+			P_Fld(u1CAdelay[8], SHU1_R0_B0_DQ0_RK0_TX_ARDQ1_DLY_B0) |
+			P_Fld(u1CAdelay[9], SHU1_R0_B0_DQ0_RK0_TX_ARDQ3_DLY_B0));
+
+        CATrainingLP3(p);
+
+        iMin = 0xff;
+        for(j = 0; j < CATRAINING_NUM_LP3; j++)
+        {
+            //mcSHOW_DBG_MSG(("###CA[%d] ori=[%d] first_pass=[%d]\n", j, iOriFirstPass[j], gFinalCAPerbitFirstPass[p->rank][j]));
+            if((gFinalCAPerbitFirstPass_LP3[p->rank][j] - iOriFirstPass[j]) <= iMin)
+            {
+                iMin = gFinalCAPerbitFirstPass_LP3[p->rank][j] - iOriFirstPass[j];
+                u1MinIdx = j;
+                mcSHOW_DBG_MSG(( "[%d]enter %d %d \n", j, (gFinalCAPerbitFirstPass_LP3[p->rank][j] - iOriFirstPass[j]), iMin));
+            }
+        }
+        u1CAIndex[i] = u1MinIdx;
+        //mcSHOW_DBG_MSG(("### u1CAIndex = %d\n", u1CAIndex[i]));
+    }
+
+    for(i = 0; i < CATRAINING_NUM_LP3; i++)
+    {
+        mcSHOW_DBG_MSG(("CH[%d] Rank[%d] APHY_CA[%d]-->DRAM(->O1)[%d]\n", p->channel, p->rank, i, u1CAIndex[i]));
+        if(u1CAIndex[i] != i)
+        {
+            mcSHOW_DBG_MSG(("!Not mapping with CA mapping table\n"));
+            while(1);
+        }
+    }
+
+    memset(u1CAdelay, 0, sizeof(u1CAdelay));
+	vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD0), P_Fld(u1CAdelay[0], SHU1_R0_CA_CMD0_RK0_TX_ARCA1_DLY) |
+		P_Fld(u1CAdelay[1], SHU1_R0_CA_CMD0_RK0_TX_ARCA3_DLY));
+	vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ0), P_Fld(u1CAdelay[2], SHU1_R0_B0_DQ0_RK0_TX_ARDQ5_DLY_B0) |
+		P_Fld(u1CAdelay[3], SHU1_R0_B0_DQ0_RK0_TX_ARDQ7_DLY_B0) |
+		P_Fld(u1CAdelay[4], SHU1_R0_B0_DQ0_RK0_TX_ARDQ2_DLY_B0) |
+		P_Fld(u1CAdelay[5], SHU1_R0_B0_DQ0_RK0_TX_ARDQ0_DLY_B0) |
+		P_Fld(u1CAdelay[6], SHU1_R0_B0_DQ0_RK0_TX_ARDQ4_DLY_B0) |
+		P_Fld(u1CAdelay[7], SHU1_R0_B0_DQ0_RK0_TX_ARDQ6_DLY_B0) |
+		P_Fld(u1CAdelay[8], SHU1_R0_B0_DQ0_RK0_TX_ARDQ1_DLY_B0) |
+		P_Fld(u1CAdelay[9], SHU1_R0_B0_DQ0_RK0_TX_ARDQ3_DLY_B0));
+    return;
+}
+#endif
+#endif
+
+#if PINMUX_AUTO_TEST_PER_BIT_RX
+U8 gRX_check_per_bit_flag = 0;
+U8 gRX_Check_per_bit_idx = 0;
+U16 gFinalRXPerbitWinSiz[CHANNEL_NUM][DQ_DATA_WIDTH];
+void CheckRXDelayCell(DRAMC_CTX_T *p)
+{
+    int ii;
+    for (ii = 0; ii < 4; ii++)
+    {
+        mcSHOW_DBG_MSG2(("#### B0[%x] B1[%x]", u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2 + ii*4)), u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2 + ii*4))));
+    }
+}
+
+
+void SetRxPerBitDelayCellForPinMuxCheck(DRAMC_CTX_T *p, U8 U1bitIdx)
+{
+    U32 u4delay = 0x3f;
+    switch(U1bitIdx)
+    {
+        case 0:
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2),
+                P_Fld(u4delay, SHU1_R0_B0_DQ2_RK0_RX_ARDQ0_R_DLY_B0) |
+                P_Fld(u4delay, SHU1_R0_B0_DQ2_RK0_RX_ARDQ0_F_DLY_B0));//bit0
+            break;
+        case 1:
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2),
+                P_Fld(u4delay, SHU1_R0_B0_DQ2_RK0_RX_ARDQ1_R_DLY_B0) |
+                P_Fld(u4delay, SHU1_R0_B0_DQ2_RK0_RX_ARDQ1_F_DLY_B0));//bit1
+            break;
+        case 2:
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ3),
+                P_Fld(u4delay, SHU1_R0_B0_DQ3_RK0_RX_ARDQ2_R_DLY_B0) |
+                P_Fld(u4delay, SHU1_R0_B0_DQ3_RK0_RX_ARDQ2_F_DLY_B0)); //bit2
+            break;
+        case 3:
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ3),
+                P_Fld(u4delay, SHU1_R0_B0_DQ3_RK0_RX_ARDQ3_R_DLY_B0) |
+                P_Fld(u4delay, SHU1_R0_B0_DQ3_RK0_RX_ARDQ3_F_DLY_B0)); //bit3
+            break;
+        case 4:
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ4),
+                P_Fld(0x3f, SHU1_R0_B0_DQ4_RK0_RX_ARDQ4_R_DLY_B0) |
+                P_Fld(0x3f, SHU1_R0_B0_DQ4_RK0_RX_ARDQ4_F_DLY_B0)); //bit4
+            break;
+        case 5:
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ4),
+                P_Fld(u4delay, SHU1_R0_B0_DQ4_RK0_RX_ARDQ5_R_DLY_B0) |
+                P_Fld(u4delay, SHU1_R0_B0_DQ4_RK0_RX_ARDQ5_F_DLY_B0)); //bit5
+            break;
+        case 6:
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ5),
+                P_Fld(u4delay, SHU1_R0_B0_DQ5_RK0_RX_ARDQ6_R_DLY_B0) |
+                P_Fld(u4delay, SHU1_R0_B0_DQ5_RK0_RX_ARDQ6_F_DLY_B0)); //bit6
+            break;
+        case 7:
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ5),
+                P_Fld(u4delay, SHU1_R0_B0_DQ5_RK0_RX_ARDQ7_R_DLY_B0) |
+                P_Fld(u4delay, SHU1_R0_B0_DQ5_RK0_RX_ARDQ7_F_DLY_B0)); //bit7
+            break;
+        case 8:
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2),
+                P_Fld(u4delay, SHU1_R0_B1_DQ2_RK0_RX_ARDQ0_R_DLY_B1) |
+                P_Fld(u4delay, SHU1_R0_B1_DQ2_RK0_RX_ARDQ0_F_DLY_B1)); //bit8
+            break;
+        case 9:
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2),
+                P_Fld(u4delay, SHU1_R0_B1_DQ2_RK0_RX_ARDQ1_R_DLY_B1) |
+                P_Fld(u4delay, SHU1_R0_B1_DQ2_RK0_RX_ARDQ1_F_DLY_B1)); //bit9
+            break;
+        case 10:
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ3),
+                P_Fld(u4delay, SHU1_R0_B1_DQ3_RK0_RX_ARDQ2_R_DLY_B1) |
+                P_Fld(u4delay, SHU1_R0_B1_DQ3_RK0_RX_ARDQ2_F_DLY_B1)); //bit10
+            break;
+        case 11:
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ3),
+                P_Fld(u4delay, SHU1_R0_B1_DQ3_RK0_RX_ARDQ3_R_DLY_B1) |
+                P_Fld(u4delay, SHU1_R0_B1_DQ3_RK0_RX_ARDQ3_F_DLY_B1)); //bit 11
+            break;
+        case 12:
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ4),
+                P_Fld(u4delay, SHU1_R0_B1_DQ4_RK0_RX_ARDQ4_R_DLY_B1) |
+                P_Fld(u4delay, SHU1_R0_B1_DQ4_RK0_RX_ARDQ4_F_DLY_B1)); //bit 12
+            break;
+        case 13:
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ4),
+                P_Fld(u4delay, SHU1_R0_B1_DQ4_RK0_RX_ARDQ5_R_DLY_B1) |
+                P_Fld(u4delay, SHU1_R0_B1_DQ4_RK0_RX_ARDQ5_F_DLY_B1)); //bit 13
+            break;
+        case 14:
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ5),
+                P_Fld(u4delay, SHU1_R0_B1_DQ5_RK0_RX_ARDQ6_R_DLY_B1) |
+                P_Fld(u4delay, SHU1_R0_B1_DQ5_RK0_RX_ARDQ6_F_DLY_B1)); //bit 14
+            break;
+        case 15:
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ5),
+                P_Fld(u4delay, SHU1_R0_B1_DQ5_RK0_RX_ARDQ7_R_DLY_B1) |
+                P_Fld(u4delay, SHU1_R0_B1_DQ5_RK0_RX_ARDQ7_F_DLY_B1)); //bit 15
+            break;
+        default:
+            mcSHOW_DBG_MSG(("Not assign correct index\n"));
+    }
+}
+
+void CheckRxPinMux(DRAMC_CTX_T *p)//By view of DRAM in LP4
+{
+    U8 u1RxIndex[DQ_DATA_WIDTH_LP4] = {0};
+    int i = 0;
+    int j = 0;
+    gRX_check_per_bit_flag = 1;
+
+    U16 u2Min = 0xffff;
+    U8 u1MinIdx = 0;
+
+    for (i=0; i < DQ_DATA_WIDTH_LP4; i+=1)
+    {
+        gRX_Check_per_bit_idx = i;
+
+        DramcRxWindowPerbitCal(p, 0);//RDDQC
+
+        u2Min = 0xffff;
+        for(j = 0; j < DQ_DATA_WIDTH_LP4; j++)
+        {
+            if(gFinalRXPerbitWinSiz[p->channel][j] <= u2Min)
+            {
+                u2Min = gFinalRXPerbitWinSiz[p->channel][j];
+                u1MinIdx = j;
+            }
+        }
+        u1RxIndex[i] = u1MinIdx;
+    }
+
+    for(i = 0; i < DQ_DATA_WIDTH_LP4; i++)
+    {
+        mcSHOW_DBG_MSG(("CH[%d] Rank[%d] APHY_RX[%d]-->DRAMC(-->RDDQC-->O1)[%d]\n", p->channel, p->rank, i, u1RxIndex[i]));
+        if(u1RxIndex[i] != i)
+        {
+            mcSHOW_DBG_MSG(("!RX APHY DRAMC DQ is not mapping directly\n"));
+            while(1);
+        }
+    }
+    gRX_check_per_bit_flag = 0;
+    return;
+}
+#endif
+
+#if PINMUX_AUTO_TEST_PER_BIT_RX_LP3
+U8 gRX_check_per_bit_flag = 0;
+U8 gRX_Check_per_bit_idx = 0;
+U16 gFinalRXPerbitWinSiz[CHANNEL_NUM][DQ_DATA_WIDTH];
+void Set_RX_DQ_DelayLine_Phy_Byte(DRAMC_CTX_T *p, U8 u1ByteIdx, U8 value[8]);
+void SetRxPerBitDelayCellForPinMuxCheckLp3(DRAMC_CTX_T *p, U8 U1bitIdx, S16 iDelay)
+{
+    DRAM_CHANNEL_T backup_channel;
+    backup_channel = p->channel;
+    S8 dl_value[8] = {0};
+    U8 u1ByteIdx = U1bitIdx / 8;
+    U8 u1BitIdxInByte = U1bitIdx % 8;
+    int i = 0;
+
+    mcSHOW_DBG_MSG(("get gRX_Check_per_bit_idx: %d ==> ByteIdx: %d, BitIdx: %d\n", U1bitIdx, u1ByteIdx, u1BitIdxInByte));
+
+    for(i=0; i < 8; i++)
+    {
+        dl_value[i] = (i != u1BitIdxInByte) ? iDelay : 0x3f;//Set delay cell of specific bit to max, others keep original value
+    }
+
+    Set_RX_DQ_DelayLine_Phy_Byte(p, u1ByteIdx, dl_value);//View of DRAMC
+
+    p->channel = backup_channel;
+    return;
+}
+
+void CheckRxPinMux(DRAMC_CTX_T *p)//By view of DRAMC in LP3
+{
+    U8 u1RxIndex[DQ_DATA_WIDTH] = {0};
+    int i = 0;
+    int j = 0;
+    gRX_check_per_bit_flag = 1;
+    U16 u2Min = 0xffff;
+    U8 u1MinIdx = 0;
+
+    for (i=0; i < DQ_DATA_WIDTH; i+=1)
+    {
+        gRX_Check_per_bit_idx = i;
+
+        mcSHOW_DBG_MSG(("Set DQ[%d] delay cell to max\n", i));
+        DramcRxWindowPerbitCal(p, 1);//LP3 only for TA2
+
+        u2Min = 0xffff;
+        for(j = 0; j < DQ_DATA_WIDTH; j++)
+        {
+            if(u2Min >= gFinalRXPerbitWinSiz[p->channel][j])
+            {
+                u2Min = gFinalRXPerbitWinSiz[p->channel][j];
+                u1MinIdx = j;
+            }
+        }
+        u1RxIndex[i] = u1MinIdx;
+    }
+
+    mcSHOW_DBG_MSG(("CH[%d] Rank[%d]\n", p->channel, p->rank));
+    bool is_wrong = false;
+    for(i = 0; i < DQ_DATA_WIDTH; i++)
+    {
+        mcSHOW_DBG_MSG(("APHY_RX[%d] by DRAMC order-->DRAMC(-->TA2)[%d] TA2_answer[%d]\n", i, u1RxIndex[i], i));
+        if(u1RxIndex[i] != i)
+        {
+            if((u1GetRank(p) == RANK_0) && ((i == 9) || (i == 12)))//check pinmux table, DRAMC DQ9 = MCP DQ10; DRAMC DQ12 = MCP DQ12
+            {
+                mcSHOW_DBG_MSG(("!Rank0 BRCKE0 of APHY will effect DQ10 && DQ12 of MCP\n"));
+            }
+            else
+            {
+                mcSHOW_DBG_MSG(("!RX APHY DRAMC DQ is not mapping directly\n"));
+                is_wrong = true;
+                //Since BRCKE0 of APHY will effect DQ10 && DQ12 of MCP
+            }
+        }
+
+    }
+    if (is_wrong == true)
+    {
+        while(1);
+    }
+
+    gRX_check_per_bit_flag = 0;
+    return;
+}
+#endif // PINMUX_AUTO_TEST_PER_BIT_RX_LP3
+
+#if PINMUX_AUTO_TEST_PER_BIT_TX
+U8 gTX_check_per_bit_flag = 0;
+U16 gFinalTXPerbitFirstPass[CHANNEL_NUM][DQ_DATA_WIDTH];
+void CheckTxPinMux(DRAMC_CTX_T *p)
+{
+    U8 u1Txdelay[16] = {0};
+    U8 u1TxIndex[16] = {0};
+    int i = 0;
+    int j = 0;
+    gTX_check_per_bit_flag = 1;
+    U16 u2Min = 0xffff;
+    U8 u1MinIdx = 0;
+
+    for(i = 0; i < DQ_DATA_WIDTH_LP4; i++)
+    {
+        memset(u1Txdelay, 0, sizeof(u1Txdelay));
+        u1Txdelay[i] = 0xf;
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ0), P_Fld(u1Txdelay[7], SHU1_R0_B0_DQ0_RK0_TX_ARDQ7_DLY_B0)
+            | P_Fld(u1Txdelay[6], SHU1_R0_B0_DQ0_RK0_TX_ARDQ6_DLY_B0)
+            | P_Fld(u1Txdelay[5], SHU1_R0_B0_DQ0_RK0_TX_ARDQ5_DLY_B0)
+            | P_Fld(u1Txdelay[4], SHU1_R0_B0_DQ0_RK0_TX_ARDQ4_DLY_B0)
+            | P_Fld(u1Txdelay[3], SHU1_R0_B0_DQ0_RK0_TX_ARDQ3_DLY_B0)
+            | P_Fld(u1Txdelay[2], SHU1_R0_B0_DQ0_RK0_TX_ARDQ2_DLY_B0)
+            | P_Fld(u1Txdelay[1], SHU1_R0_B0_DQ0_RK0_TX_ARDQ1_DLY_B0)
+            | P_Fld(u1Txdelay[0], SHU1_R0_B0_DQ0_RK0_TX_ARDQ0_DLY_B0));
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ0), P_Fld(u1Txdelay[15], SHU1_R0_B1_DQ0_RK0_TX_ARDQ7_DLY_B1)
+            | P_Fld(u1Txdelay[14], SHU1_R0_B1_DQ0_RK0_TX_ARDQ6_DLY_B1)
+            | P_Fld(u1Txdelay[13], SHU1_R0_B1_DQ0_RK0_TX_ARDQ5_DLY_B1)
+            | P_Fld(u1Txdelay[12], SHU1_R0_B1_DQ0_RK0_TX_ARDQ4_DLY_B1)
+            | P_Fld(u1Txdelay[11], SHU1_R0_B1_DQ0_RK0_TX_ARDQ3_DLY_B1)
+            | P_Fld(u1Txdelay[10], SHU1_R0_B1_DQ0_RK0_TX_ARDQ2_DLY_B1)
+            | P_Fld(u1Txdelay[9], SHU1_R0_B1_DQ0_RK0_TX_ARDQ1_DLY_B1)
+            | P_Fld(u1Txdelay[8], SHU1_R0_B1_DQ0_RK0_TX_ARDQ0_DLY_B1));
+        DramcTxWindowPerbitCal(p, TX_DQ_DQS_MOVE_DQ_ONLY, FALSE);
+        mcSHOW_DBG_MSG(("set 1 ranks set:0xf\n"));
+
+        u2Min = 0xffff;
+        for(j = 0; j < DQ_DATA_WIDTH_LP4; j++)
+        {
+            if(gFinalTXPerbitFirstPass[p->channel][j] <= u2Min)
+            {
+                u2Min = gFinalTXPerbitFirstPass[p->channel][j];
+                u1MinIdx = j;
+            }
+        }
+        u1TxIndex[i] = u1MinIdx;
+    }
+
+    for(i = 0; i < DQ_DATA_WIDTH_LP4; i++)
+    {
+        mcSHOW_DBG_MSG(("CH[%d] Rank[%d] APHY_TX[%d]-->DRAMC(->TA2->)[%d]\n", p->channel, p->rank, i, u1TxIndex[i]));
+        if(u1TxIndex[i] != i)
+        {
+            mcSHOW_DBG_MSG(("!TX APHY DRAMC DQ is not mapping directly\n"));
+            while(1);
+        }
+    }
+    gTX_check_per_bit_flag = 0;
+    return;
+}
+#endif
+
+void CATrainingSetPerBitDelayCell(DRAMC_CTX_T *p, S8 *ps1CACenterDiff)
+{
+    // Need to porting for each project according to LP3 pinmux table
+    #if (fcFOR_CHIP_ID == fcLaurel)
+    #if LP3_CA_PER_BIT
+    if(!u1IsLP4Family(p->dram_type))
+    {
+        //DRAM CA0/1 delay cell
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD0), P_Fld(ps1CACenterDiff[0], SHU1_R0_CA_CMD0_RK0_TX_ARCA1_DLY)|
+                                                                   P_Fld(ps1CACenterDiff[1], SHU1_R0_CA_CMD0_RK0_TX_ARCA3_DLY));
+
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ0), P_Fld(ps1CACenterDiff[2], SHU1_R0_B0_DQ0_RK0_TX_ARDQ5_DLY_B0)|
+                                                                  P_Fld(ps1CACenterDiff[3], SHU1_R0_B0_DQ0_RK0_TX_ARDQ7_DLY_B0)|
+                                                                  P_Fld(ps1CACenterDiff[4], SHU1_R0_B0_DQ0_RK0_TX_ARDQ2_DLY_B0)|
+                                                                  P_Fld(ps1CACenterDiff[5], SHU1_R0_B0_DQ0_RK0_TX_ARDQ0_DLY_B0)|
+                                                                  P_Fld(ps1CACenterDiff[6], SHU1_R0_B0_DQ0_RK0_TX_ARDQ4_DLY_B0)|
+                                                                  P_Fld(ps1CACenterDiff[7], SHU1_R0_B0_DQ0_RK0_TX_ARDQ6_DLY_B0)|
+                                                                  P_Fld(ps1CACenterDiff[8], SHU1_R0_B0_DQ0_RK0_TX_ARDQ1_DLY_B0)|
+                                                                  P_Fld(ps1CACenterDiff[9], SHU1_R0_B0_DQ0_RK0_TX_ARDQ3_DLY_B0));
+    }
+    #endif// end of LP3_CA_PER_BIT
+
+    #if CA_PER_BIT_DELAY_CELL
+    U8 uiCA;
+    U8 *uiLPDDR_CA_Mapping = (U8 *)uiLPDDR4_CA_Mapping_POP[p->channel];
+
+    if(u1IsLP4Family(p->dram_type))
+    {
+        for (uiCA=0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+        {
+            //mcSHOW_DBG_MSG(("CA%d dly line = %d cells \n", uiLPDDR_CA_Mapping[uiCA], ps1CACenterDiff[uiCA]));
+            #if EYESCAN_LOG
+            gEyeScan_DelayCellPI[uiCA] = (S8) ps1CACenterDiff[uiCA];
+            #endif
+        }
+
+        // Set CA perbit delay line calibration results
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD0),  P_Fld(ps1CACenterDiff[uiLPDDR_CA_Mapping[0]], SHU1_R0_CA_CMD0_RK0_TX_ARCA0_DLY) | \
+                                                                    P_Fld(ps1CACenterDiff[uiLPDDR_CA_Mapping[1]], SHU1_R0_CA_CMD0_RK0_TX_ARCA1_DLY) | \
+                                                                    P_Fld(ps1CACenterDiff[uiLPDDR_CA_Mapping[2]], SHU1_R0_CA_CMD0_RK0_TX_ARCA2_DLY) | \
+                                                                    P_Fld(ps1CACenterDiff[uiLPDDR_CA_Mapping[3]], SHU1_R0_CA_CMD0_RK0_TX_ARCA3_DLY) | \
+                                                                    P_Fld(ps1CACenterDiff[uiLPDDR_CA_Mapping[4]], SHU1_R0_CA_CMD0_RK0_TX_ARCA4_DLY) | \
+                                                                    P_Fld(ps1CACenterDiff[uiLPDDR_CA_Mapping[5]], SHU1_R0_CA_CMD0_RK0_TX_ARCA5_DLY) );
+    }
+    #endif
+    #endif
+}
+
+#if ENABLE_LP3_SW
+#if SIMULATION_LP3_CA_TRAINING
+//-------------------------------------------------------------------------
+/** DramcCATraining
+ *  start the calibrate the skew between Clk pin and CAx pins.
+ *  @param p                Pointer of context created by DramcCtxCreate.
+ *  @retval status          (DRAM_STATUS_T): DRAM_OK or DRAM_FAIL
+ */
+//-------------------------------------------------------------------------
+#define MAX_CLKO_DELAY         31
+
+static DRAM_STATUS_T CATrainingEntry(DRAMC_CTX_T *p, U32 uiMR41, U32 u4GoldenPattern)
+{
+    //CA_TRAINING_BEGIN:
+
+    // CS extent enable (need DRAM to support)
+    // for testing
+#if CA_TRAINING_K_RANK1_ENABLE
+    if(p->rank == RANK_1)
+    {
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRS), p->rank, MRS_MRSRK);
+
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), P_Fld(0, RKCFG_CS0FORCE)|P_Fld(0, RKCFG_CS2RANK)); //cannot enable before any MRW command
+    }
+#endif
+
+#if (FOR_DV_SIMULATION_USED==0)
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 1, CATRAINING1_CATRAINCSEXT);
+#endif
+
+    // CKE high, CKE must be driven HIGH prior to issuance of the MRW41 and MRW48 command
+    CKEFixOnOff(p, p->rank, CKE_FIXON, CKE_WRITE_TO_ONE_CHANNEL);
+
+    // Hold the CA bus stable for at least one cycle.
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 1, CATRAINING1_CATRAINMRS);
+
+    mcDELAY_US(1);
+
+    // Enter MR 41/MR48
+    // Set MA & OP.
+    if (uiMR41)
+    {
+        DramcModeRegWrite(p, 41, 0xa4);    //MR41=0xa4 CA Training Mode enable
+    }
+    else
+    {
+        DramcModeRegWrite(p, 48, 0xc0);    //MR48=0xc0 CA Training Mode enable
+    }
+
+    // Disable CA bus stable.
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 0, CATRAINING1_CATRAINMRS);
+
+    // Wait tCACKEL(10 tck) before CKE low
+    mcDELAY_US(1);
+
+    // CKE low
+    CKEFixOnOff(p, p->rank, CKE_FIXOFF, CKE_WRITE_TO_ONE_CHANNEL);
+
+    // Set CA0~CA3, CA5~CA8 rising/falling golden value.
+    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING2), u4GoldenPattern);
+
+#if CA_TRAINING_K_RANK1_ENABLE
+    if(p->rank == RANK_1)
+    {
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), P_Fld(1, RKCFG_CS0FORCE)| P_Fld(1, RKCFG_CS2RANK)); //enable to force CS switch to rank1
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 1, RKCFG_TXRANK); //TXRANKFIX should be write after TXRANK or the rank will be fix at rank 1
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 1, RKCFG_TXRANKFIX); //enable to switch to rank1
+    }
+#endif
+
+
+    // Wait tCAENT(10 tck) before pattern output
+    mcDELAY_US(1);
+
+    return DRAM_OK;
+}
+
+
+static S32 CheckCATrainingTransition(U32 uiCA, U32 capattern, U32 uiRisingEdge, U32 uiFallingEdge)
+{
+    S32 iPass=0;
+    U32 iii;
+
+    if (capattern == 0x55555555)
+    {
+         if ((uiRisingEdge!=0) && (uiFallingEdge==0))
+         {
+             iPass = 1;
+         }
+         else
+         {
+             iPass = 0;
+         }
+    }
+    else if (capattern == 0xaaaaaaaa)
+    {
+        if ((uiRisingEdge==0) && (uiFallingEdge!=0))
+        {
+            iPass = 1;
+        }
+        else
+        {
+            iPass = 0;
+        }
+    }
+    else if (capattern == 0x99999999)
+    {
+        iii = uiCA;
+        if (iii>=5) iii-=5;
+
+        if ((iii & 1) == 0)
+        {
+            if ((uiRisingEdge!=0) && (uiFallingEdge==0))
+            {
+                iPass = 1;
+            }
+            else
+            {
+                iPass = 0;
+            }
+        }
+        else
+        {
+            if ((uiRisingEdge==0) && (uiFallingEdge!=0))
+            {
+                iPass = 1;
+            }
+            else
+            {
+                iPass = 0;
+            }
+        }
+    }
+    else if (capattern == 0x66666666)
+    {
+        iii = uiCA;
+        if (iii>=5) iii-=5;
+
+        if ((iii & 1) == 0)
+        {
+            if ((uiRisingEdge==0) && (uiFallingEdge!=0))
+            {
+                iPass = 1;
+            }
+            else
+            {
+                iPass = 0;
+            }
+        }
+        else
+        {
+            if ((uiRisingEdge!=0) && (uiFallingEdge==0))
+            {
+                iPass = 1;
+            }
+            else
+            {
+                iPass = 0;
+            }
+        }
+    }
+
+    return iPass;
+}
+
+
+static void CATrainingExit(DRAMC_CTX_T *p)
+{
+#if CA_TRAINING_K_RANK1_ENABLE
+    if(p->rank == RANK_1) //disable setting of CS and TX rank sel switch to rank1 before leaving CA training
+    {
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), P_Fld(0, RKCFG_CS0FORCE)| P_Fld(0, RKCFG_CS2RANK));
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANK); //TXRANKFIX should be write after TXRANK or the rank will be fix at rank 1
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANKFIX); //enable to switch to rank1
+    }
+#endif
+
+    CKEFixOnOff(p, p->rank, CKE_FIXON, CKE_WRITE_TO_ONE_CHANNEL);
+    mcDELAY_US(1);
+
+    // CS extent enable
+    // for testing
+#if (FOR_DV_SIMULATION_USED==0)
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 1, CATRAINING1_CATRAINCSEXT);
+#endif
+
+    // Hold the CA bus stable for at least one cycle.
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 1, CATRAINING1_CATRAINMRS);
+
+    mcDELAY_US(1);
+
+    // MR42 to leave CA training.
+    DramcModeRegWrite(p, 42, 0xa8);    //MR42=0xa8 CA Training Mode disable
+
+    // Disable the hold the CA bus stable for at least one cycle.
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 0, CATRAINING1_CATRAINMRS);
+
+    // CS extent disable
+    // for testing
+#if (FOR_DV_SIMULATION_USED==0)
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 0, CATRAINING1_CATRAINCSEXT);
+#endif
+}
+
+void CATrainingDelayCompare(DRAMC_CTX_T *p, U32 uiMR41, U32 u4GoldenPattern, U8 u1LP3DieNum, U32 delayinecompare_flag)
+{
+    U8 *uiLPDDR_O1_Mapping = NULL, u1DieIdx;
+//    U32 u4O1Data[DQS_NUMBER];
+    U8 u1Offset;
+    U32 uiTemp, uiCA, uiRisingEdge, uiFallingEdge, uiFinishCount;
+    S32 iPass, iDelay, iDelay_Start, iDelay_End;
+
+    S32 iCenter[LP3_DIE_NUM_MAX][CATRAINING_NUM] = {0};
+
+    #if (fcFOR_CHIP_ID == fcLaurel)
+    if(p->bDLP3)
+    {
+        uiLPDDR_O1_Mapping = (U8 *)uiLPDDR3_O1_Mapping_POP_DLP3;
+    }
+    else
+    #endif
+    {
+        uiLPDDR_O1_Mapping = (U8 *)uiLPDDR3_O1_Mapping_POP;
+    }
+
+    // Calculate the middle range & max middle.
+    mcSHOW_DBG_MSG(("\n[CA Training]\n"));
+    vPrintCalibrationBasicInfo(p);
+
+    mcFPRINTF((fp_A60501, "\n1. CA training window before adjustment.\n"));
+    mcFPRINTF((fp_A60501, "x=Pass window CA(max~min) Clk(min~max) center. \n"));
+    if(uiMR41)
+    {
+        mcSHOW_DBG_MSG(("y=CA0~CA3, CA5~8\n\n"));
+        mcFPRINTF((fp_A60501, "y=CA0~CA3, CA5~8\n\n"));
+    }
+    else//MR48
+    {
+        mcSHOW_DBG_MSG(("y=CA4 CA9\n\n"));
+        mcFPRINTF((fp_A60501, "y=CA4 CA9\n\n"));
+    }
+
+    uiFinishCount = 0;
+
+    for (u1DieIdx=0; u1DieIdx<LP3_DIE_NUM_MAX; u1DieIdx++)
+    {
+        for (uiCA=0; uiCA<CATRAINING_NUM; uiCA++)
+        {
+            if(uiMR41 && ((uiCA==4) || (uiCA==9)))  // MR41 is for CA0~3, CA5~8
+            {
+                continue;
+            }
+            else if((uiMR41==0) && ((uiCA!=4) && (uiCA!=9)))// MR48 is for CA4, CA9
+            {
+                continue;
+            }
+
+             iLastCAPass[p->rank][u1DieIdx][uiCA] = CATRAINING_PASS_RANGE_NA;
+             iFirstCAPass[p->rank][u1DieIdx][uiCA] = CATRAINING_PASS_RANGE_NA;
+        }
+    }
+
+    if (delayinecompare_flag == 0)
+    {
+#if (fcFOR_PINMUX == fcLaurel)
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), 0, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD);    //CA0~1 CA_PI_Delay
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), 0, SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);       //CA2~9 CA_PI_Delay
+#endif
+    }
+
+    if (delayinecompare_flag == 0)
+    {
+        iDelay_Start = -(MAX_CLK_PI_DELAY/2);
+        /* [Justin May 19, 2017 7:13 PM]SW modification is required if the final CMD/CS PI code=32~63
+         HW bug: LP3 CA/CS delay cannot >31 PI. if larger than 31PI, use UI instead.
+         The problem will be fixed in Cannon and can change iDelay_End back to 63 */
+        iDelay_End = MAX_CA_PI_DELAY;
+    }
+    else
+    {
+        iDelay_Start = 0;
+        iDelay_End = MAX_CLK_PI_DELAY;
+    }
+
+    // Delay clock output delay to do CA training in order to get the pass window.
+    for (iDelay= iDelay_Start; iDelay <= iDelay_End; iDelay++)
+    {
+        if (delayinecompare_flag == 0)
+        {
+            if(iDelay <=0)
+            {    //Set CLK delay
+                  vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), -iDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK); //clock_PI_Delay
+            }
+            else
+            {    // Set CA output delay
+#if (fcFOR_PINMUX == fcLaurel)
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), iDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD);    //CA0~1 CA_PI_Delay
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), iDelay, SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);       //CA2~9 CA_PI_Delay
+#endif
+            }
+        }
+        else
+        {
+             // set CLK PI value
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), iDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK);    //clock_PI_Delay
+        }
+
+        // CA training pattern output enable
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 1, CATRAINING1_CATRAINEN);
+        // delay 2 DRAM clock cycle
+        mcDELAY_US(1);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 0, CATRAINING1_CATRAINEN);
+
+
+        // Wait tADR(20ns) before CA sampled values available in DQ.
+        mcDELAY_US(1);
+
+        // Get DQ value.
+        uiTemp = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_DQO1));
+
+        #ifdef ETT_PRINT_FORMAT
+        mcSHOW_DBG_MSG3(("%d, DQ_O1 0x%x| ", iDelay, uiTemp));
+        #else
+        mcSHOW_DBG_MSG3(("delay %3d, DQ_O1 0x%8x| Pass ", iDelay, uiTemp));
+        #endif
+        mcFPRINTF((fp_A60501, "delay %3d, DQ_O1 0x%8x| Pass ", iDelay, uiTemp));
+
+        // Compare with golden value.
+        for (u1DieIdx=0; u1DieIdx<u1LP3DieNum; u1DieIdx++)
+        {
+            if(u1LP3DieNum>1)
+            {
+                mcSHOW_DBG_MSG3(("|D%d  ",u1DieIdx));
+            }
+
+            for (uiCA=0; uiCA<CATRAINING_NUM; uiCA++)
+            {
+                if(uiMR41 && ((uiCA==4) || (uiCA==9)))  // MR41 is for CA0~3, CA5~8
+                {
+                    continue;
+                }
+                else if((uiMR41==0) && ((uiCA!=4) && (uiCA!=9)))// MR48 is for CA4, CA8
+                {
+                    continue;
+                }
+
+                u1Offset = 16 * u1DieIdx;
+                //if ( (iFirstCAPass[p->rank][u1DieIdx][uiCA]==CATRAINING_PASS_RANGE_NA) || (iLastCAPass[p->rank][u1DieIdx][uiCA]==CATRAINING_PASS_RANGE_NA)) //marked fo debug
+                {
+                    if (uiCA<4)   //CA0~3
+                    {
+                            uiRisingEdge = uiTemp & ((0x01 << uiLPDDR_O1_Mapping[(uiCA << 1) + u1Offset]));
+                            uiFallingEdge = uiTemp & ((0x01 << uiLPDDR_O1_Mapping[(uiCA << 1) + 1 + u1Offset]));
+                    }
+                    else if((uiCA==4) || (uiCA==9))
+                    {
+                            uiRisingEdge = uiTemp & ((0x01 << uiLPDDR_O1_Mapping[(uiCA == 4) ? 0 + u1Offset: 8 + u1Offset]));
+                            uiFallingEdge = uiTemp & ((0x01 << uiLPDDR_O1_Mapping[(uiCA == 4) ? 1 + u1Offset : 9 + u1Offset]));
+                    }
+                    else//CA5~8
+                    {
+                            uiRisingEdge = uiTemp & ((0x01 << uiLPDDR_O1_Mapping[((uiCA - 1) << 1) + u1Offset]));
+                            uiFallingEdge = uiTemp & ((0x01 << uiLPDDR_O1_Mapping[((uiCA - 1) << 1) + 1 + u1Offset]));
+                    }
+
+                    iPass = CheckCATrainingTransition(uiCA, u4GoldenPattern, uiRisingEdge, uiFallingEdge);
+                    mcSHOW_DBG_MSG3(("%d ", iPass));
+                    mcFPRINTF((fp_A60501, "%d ", iPass));
+
+                    if (iFirstCAPass[p->rank][u1DieIdx][uiCA]==CATRAINING_PASS_RANGE_NA)
+                    {
+                        if (iPass == 1)
+                        {
+                            iFirstCAPass[p->rank][u1DieIdx][uiCA] = iDelay;
+                        }
+                    }
+                    else
+                    {
+                        if (iLastCAPass[p->rank][u1DieIdx][uiCA]==CATRAINING_PASS_RANGE_NA)
+                        {
+                            if (iPass == 0)
+                            {
+                                if((iDelay-iFirstCAPass[p->rank][u1DieIdx][uiCA]) < 8)  // prevent glitch
+                                {
+                                    iFirstCAPass[p->rank][u1DieIdx][uiCA]=CATRAINING_PASS_RANGE_NA;
+                                    continue;
+                                }
+
+                                uiFinishCount++;
+                                iLastCAPass[p->rank][u1DieIdx][uiCA] = iDelay-1;
+
+                                iCenter[u1DieIdx][uiCA] = (iLastCAPass[p->rank][u1DieIdx][uiCA] + iFirstCAPass[p->rank][u1DieIdx][uiCA]) >>1;
+                            }
+                            else
+                            {
+                                if (iDelay==MAX_CA_PI_DELAY)
+                                {
+                                    uiFinishCount++;
+                                    iLastCAPass[p->rank][u1DieIdx][uiCA] = iDelay;
+
+                                    iCenter[u1DieIdx][uiCA] = (iLastCAPass[p->rank][u1DieIdx][uiCA] + iFirstCAPass[p->rank][u1DieIdx][uiCA]) >>1;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // Wait tCACD(22clk) before output CA pattern to DDR again..
+        mcDELAY_US(1);
+
+        mcSHOW_DBG_MSG3(("\n"));
+        mcFPRINTF((fp_A60501, "\n"));
+
+        if((uiMR41 && (uiFinishCount==(8*u1LP3DieNum))) || ((uiMR41==0) && (uiFinishCount==(2*u1LP3DieNum))))
+        {
+            mcSHOW_DBG_MSG(("Early break, MR41=%d FinishCount=%d\n", uiMR41, uiFinishCount));
+            mcFPRINTF((fp_A60501, "Early break, uiMR41=%d\n", uiMR41));
+            break;
+        }
+    }
+
+
+    vSetCalibrationResult(p, DRAM_CALIBRATION_CA_TRAIN, DRAM_OK); // set default result OK, udpate status when per bit fail
+
+    if (delayinecompare_flag == 1)
+    {
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), 0, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK);
+    }
+
+    for(u1DieIdx=0; u1DieIdx<u1LP3DieNum; u1DieIdx++)
+    {
+        for (uiCA=0; uiCA<CATRAINING_NUM; uiCA++)
+        {
+            if(uiMR41 && ((uiCA==4) || (uiCA==9)))  // MR41 is for CA0~3, CA5~8
+            {
+                continue;
+            }
+            else if((uiMR41==0) && ((uiCA!=4) && (uiCA!=9)))// MR48 is for CA4, CA9
+            {
+                continue;
+            }
+
+        #ifdef FOR_HQA_TEST_USED
+            gFinalCBTCA[p->channel][p->rank][uiCA] = (iLastCAPass[p->rank][u1DieIdx][uiCA] - iFirstCAPass[p->rank][u1DieIdx][uiCA])+(iLastCAPass[p->rank][u1DieIdx][uiCA]==iFirstCAPass[p->rank][u1DieIdx][uiCA]?0:1);
+        #endif
+        #if PINMUX_AUTO_TEST_PER_BIT_CA
+            gFinalCAPerbitFirstPass_LP3[p->rank][uiCA] = iFirstCAPass[p->rank][0][uiCA];//only use die0
+        #endif
+
+            if(u1LP3DieNum ==1)
+            {
+            #ifdef ETT_PRINT_FORMAT
+                    mcSHOW_DBG_MSG(("CA%d  (%d~%d) %d,\n", uiCA, iFirstCAPass[p->rank][u1DieIdx][uiCA], iLastCAPass[p->rank][u1DieIdx][uiCA], iCenter[u1DieIdx][uiCA]));
+            #else
+                    mcSHOW_DBG_MSG(("CA%3d   Pass(%3d~%3d)  Center %3d,\n", uiCA, iFirstCAPass[p->rank][u1DieIdx][uiCA], iLastCAPass[p->rank][u1DieIdx][uiCA], iCenter[u1DieIdx][uiCA]));
+            #endif
+                    mcFPRINTF((fp_A60501, "CA%4d Pass(%3d~%3d) Center %3d,\n", uiCA, iFirstCAPass[p->rank][u1DieIdx][uiCA], iLastCAPass[p->rank][u1DieIdx][uiCA], iCenter[u1DieIdx][uiCA]));
+            }
+
+            if(iLastCAPass[p->rank][u1DieIdx][uiCA]==CATRAINING_PASS_RANGE_NA)  // no CA window found
+            {
+                vSetCalibrationResult(p, DRAM_CALIBRATION_CA_TRAIN, DRAM_FAIL);
+            }
+        }
+    }
+
+
+    if(u1LP3DieNum>1)
+    {
+        for (uiCA=0; uiCA<CATRAINING_NUM; uiCA++)
+        {
+            if(uiMR41 && ((uiCA==4) || (uiCA==9)))  // MR41 is for CA0~3, CA5~8
+            {
+                continue;
+            }
+            else if((uiMR41==0) && ((uiCA!=4) && (uiCA!=9)))// MR48 is for CA4, CA9
+            {
+                continue;
+            }
+
+            mcSHOW_DBG_MSG(("CA%d |D0 (%d~%d) %d |D1 (%d~%d) %d\n", uiCA, iFirstCAPass[p->rank][0][uiCA], iLastCAPass[p->rank][0][uiCA], iCenter[0][uiCA], \
+                    iFirstCAPass[p->rank][1][uiCA], iLastCAPass[p->rank][1][uiCA], iCenter[1][uiCA]));
+        }
+    }
+
+    // CS extent disable
+    // for testing
+#if (FOR_DV_SIMULATION_USED==0)
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 0, CATRAINING1_CATRAINCSEXT);
+#endif
+
+    // Wait tCACKEN (10ck)
+    mcDELAY_US(1);
+
+    if((uiMR41 && (uiFinishCount<8)) || ((uiMR41==0) && (uiFinishCount<2)))
+    {
+        mcSHOW_DBG_MSG(("Error: some bits have abnormal window, uiMR41=%d, FinishCount=%d\n", uiMR41, uiFinishCount));
+        mcFPRINTF((fp_A60501, "Error: some bits have abnormal window, uiMR41=%d, FinishCount=%d\n", uiMR41, uiFinishCount));
+    }
+}
+
+DRAM_STATUS_T CATrainingLP3(DRAMC_CTX_T *p)
+{
+    U32 uiMR41;
+    U32 u4RegBackupAddress[] =
+    {
+        (DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL)),
+        (DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0)),
+        (DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL)),
+        (DRAMC_REG_ADDR(DRAMC_REG_CKECTRL)),
+        (DRAMC_REG_ADDR(DRAMC_REG_MRS)),
+    };
+    S8 iFinalCACLK[2];
+    S8 s1CACenterDiff[CATRAINING_NUM]={0}; //for LP3_CA_PER_BIT
+    U32 module_i;
+    U8  backup_rank, rank_i;
+
+#if LP3_CATRAING_SHIFT_CLK_PI
+    U8 u1CLK_Shift_PI = 0;
+#endif
+
+    //  01010101b -> 10101010b : Golden value = 1001100110011001b=0x9999
+    //  11111111b -> 00000000b : Golden value = 0101010101010101b=0x5555
+    U32 u4GoldenPattern =0x55555555;
+    //U32 u4GoldenPattern =0xA6AAA6AA;
+
+    backup_rank = u1GetRank(p);
+
+    mcSHOW_DBG_MSG(("\n[CATrainingLP3]\n"));
+    mcFPRINTF((fp_A60501, "\n[CATrainingLP3]\n"));
+    #if MRW_CHECK_ONLY
+    mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
+    #endif
+
+    if(p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+        gu1LP3DieNum[p->rank] =2;
+    else
+        gu1LP3DieNum[p->rank] =1;
+
+    // Fix ODT off. A60501 disable ODT in the init code. So no need to do the following code.
+    //uiReg54h=u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WODT), WODT_WODTFIXOFF);
+    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WODT), 1, WODT_WODTFIXOFF);// According to Derping, should set to 1 to disable ODT.
+
+    // Let MIO_CK always ON.
+    DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+    vAutoRefreshSwitch(p, DISABLE); //When doing CA training, should make sure that auto refresh is disable
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 1, DRAMC_PD_CTRL_MIOCKCTRLOFF);   //MIOCKCTRLOFF=1
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 0, DRAMC_PD_CTRL_PHYCLKDYNGEN); // set R_DMPHYCLKDYNGEN=0
+
+
+#ifdef CA_LAG_CK
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), SHU_SELPH_CA7_DLY_RA2) - 1, SHU_SELPH_CA7_DLY_RA2);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), SHU_SELPH_CA7_DLY_RA3) - 1, SHU_SELPH_CA7_DLY_RA3);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), SHU_SELPH_CA7_DLY_RA4) - 1, SHU_SELPH_CA7_DLY_RA4);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), SHU_SELPH_CA7_DLY_RA5) - 1, SHU_SELPH_CA7_DLY_RA5);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), SHU_SELPH_CA7_DLY_RA6) - 1, SHU_SELPH_CA7_DLY_RA6);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), SHU_SELPH_CA7_DLY_RA7) - 1, SHU_SELPH_CA7_DLY_RA7);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA8), u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA8), SHU_SELPH_CA8_DLY_RA8) - 1, SHU_SELPH_CA8_DLY_RA8);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA8), u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA8), SHU_SELPH_CA8_DLY_RA9) - 1, SHU_SELPH_CA8_DLY_RA9);
+#endif
+
+#if LP3_CA_PER_BIT
+    CATrainingSetPerBitDelayCell(p, s1CACenterDiff); //reset delay to 0
+#endif
+
+
+    // Step 1.1 : let IO to O1 path valid
+    O1PathOnOff(p, 1);
+
+    // ----- MR41, CA0~3, CA5~8 -------
+    uiMR41 = 1;
+    CATrainingEntry(p, uiMR41, u4GoldenPattern);  //MR41
+    CATrainingDelayCompare(p, uiMR41, u4GoldenPattern, gu1LP3DieNum[p->rank], 0);
+
+    // ----- MR48, CA4 and 9 -------
+    uiMR41 = 0;
+    CATrainingEntry(p, uiMR41, u4GoldenPattern);  //MR48
+    CATrainingDelayCompare(p, uiMR41, u4GoldenPattern, gu1LP3DieNum[p->rank], 0);
+
+    CATrainingPosCal(p, gu1LP3DieNum, iFinalCACLK, s1CACenterDiff);
+
+#if LP3_CATRAING_SHIFT_CLK_PI
+    if((iFinalCACLK[0] <-LP3_CATRAING_SHIFT_CLK_PI) || (iFinalCACLK[1] <-LP3_CATRAING_SHIFT_CLK_PI))
+    {
+        u1CLK_Shift_PI = LP3_CATRAING_SHIFT_CLK_PI <<1; // if delay <-8, CLK += 16
+    }
+    else if((iFinalCACLK[0] <0) || (iFinalCACLK[1] <0))
+    {
+        u1CLK_Shift_PI = LP3_CATRAING_SHIFT_CLK_PI ; // if delay <0, CLK += 8
+    }
+    else
+        u1CLK_Shift_PI = 0;
+
+
+    if(u1CLK_Shift_PI >0)
+    {
+        mcSHOW_ERR_MSG(("\n\n[WARNING] CA Center < 0, CLK shif +%d PI\n", u1CLK_Shift_PI));
+        mcSHOW_ERR_MSG(("Origin  CA min0 = %d, CA min1 = %d\n\n", iFinalCACLK[0],  iFinalCACLK[1]));
+
+        iFinalCACLK[0] += u1CLK_Shift_PI;
+        iFinalCACLK[1] += u1CLK_Shift_PI;
+
+        mcSHOW_ERR_MSG(("Updated min0 = %d, CA min1 = %d\n\n", iFinalCACLK[0],  iFinalCACLK[1]));
+    }
+#endif
+
+    for(module_i=0; module_i<2; module_i++)
+    {
+        if(iFinalCACLK[module_i] <0) //don't move clk
+        {
+            mcSHOW_DBG_MSG(("warning : Macro%d minimum CA PI delay is %d(<0) and changed to 0\n", module_i, iFinalCACLK[module_i]));
+            iFinalCACLK[module_i] =0;
+        }
+    }
+
+
+    #ifdef ETT_PRINT_FORMAT
+    mcSHOW_DBG_MSG(("\nGoldenPattern 0x%X\n", u4GoldenPattern));
+    #else
+    mcSHOW_DBG_MSG(("\nGoldenPattern 0x%x\n", u4GoldenPattern));
+    #endif
+
+    #if REG_SHUFFLE_REG_CHECK
+    ShuffleRegCheck =1;
+    #endif
+
+    /* p->rank = RANK_0, save to Reg Rank0 and Rank1, p->rank = RANK_1, save to Reg Rank1 */
+    for(rank_i=RANK_0; rank_i<backup_rank+1; rank_i++)
+    {
+        // no need to enter self refresh before setting CLK under CA training mode
+        #if LP3_CATRAING_SHIFT_CLK_PI
+        CATrain_ClkDelay[p->channel][rank_i] = u1CLK_Shift_PI;
+        CATrain_CsDelay[p->channel][rank_i] = u1CLK_Shift_PI;
+        #else
+        CATrain_ClkDelay[p->channel][rank_i] = 0;
+        CATrain_CsDelay[p->channel][rank_i] = 0;
+        #endif
+
+        vSetRank(p, rank_i);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), iFinalCACLK[0], SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), iFinalCACLK[1], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), CATrain_ClkDelay[p->channel][rank_i] , SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), CATrain_CsDelay[p->channel][rank_i] , SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS);
+
+        for(module_i=0; module_i<2; module_i++)
+        {
+            mcSHOW_DBG_MSG(("Rank%d, Macro%d Clk dly: %d, CA dly: %d, CS dly: %d\n", rank_i, module_i, CATrain_ClkDelay[p->channel][rank_i], iFinalCACLK[module_i], CATrain_CsDelay[p->channel][rank_i]));
+            mcFPRINTF((fp_A60501, "Rank%d, Macro%d Clk dly: %d, CA dly: %d, CS dly: %d\n\n", rank_i, module_i, CATrain_ClkDelay[p->channel][rank_i], iFinalCACLK[module_i], CATrain_CsDelay[p->channel][rank_i]));
+        }
+
+        #if LP3_CA_PER_BIT
+        CATrainingSetPerBitDelayCell(p, s1CACenterDiff);
+        #endif
+    }
+    vSetRank(p, backup_rank);
+
+    #if REG_SHUFFLE_REG_CHECK
+    ShuffleRegCheck =0;
+    #endif
+
+    CATrainingExit(p);
+
+    // Disable fix DQ input enable.  Disable IO to O1 path
+    O1PathOnOff(p, 0);
+
+    // NO need to disable CKE high and back to dynamic when calibration
+    //CKEFixOnOff(p, CKE_DYNAMIC, CKE_WRITE_TO_ONE_CHANNEL);
+
+    // Restore the registers' values.
+    DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+    mcSHOW_DBG_MSG(("\n\n"));
+
+    return DRAM_OK;
+}
+#endif
+#endif //SIMULATION_LP3_CA_TRAINING
+
+
+#if SIMUILATION_LP4_CBT
+//-------------------------------------------------------------------------
+/** CmdBusTrainingLP4
+ *  start the calibrate the skew between (1) Clk pin and CAx pins. (2) Clk and CS pin (3)Vref(ca) driving
+ *  @param p                Pointer of context created by DramcCtxCreate.
+ *  @retval status          (DRAM_STATUS_T): DRAM_OK or DRAM_FAIL
+ */
+//-------------------------------------------------------------------------
+static void insertionSort(S32 a[], S32 array_size)
+{
+     S32 i, j, index;
+     for (i = 1; i < array_size; ++i)
+     {
+          index = a[i];
+          for (j = i; j > 0 && a[j-1] > index; j--)
+               a[j] = a[j-1];
+
+          a[j] = index;
+     }
+}
+
+void CBT_Switch_Freq(DRAMC_CTX_T *p, U8 freq)
+{
+#if DUAL_FREQ_K
+#if (fcFOR_CHIP_ID == fcLaurel)
+    if(freq==CBT_LOW_FREQ)
+    {
+        CBT_DramcDFSDirectJump(p, (DRAM_DFS_SHUFFLE_MAX-1));
+    }
+    else
+    {
+        CBT_DramcDFSDirectJump(p, DRAM_DFS_SHUFFLE_1);
+    }
+#else
+    #error Need check of the DRAM_DFS_SHUFFLE_X for your chip !!!
+#endif
+    //DDRPhyFreqMeter();
+#endif
+}
+
+static void vSetDramMRCBTOnOff(DRAMC_CTX_T *p, U8 u1OnOff, U8 operating_fsp)
+{
+    if(u1OnOff)
+    {
+        u1MR13Value |= 0x1; //MR13 OP[0]=1, enable CBT
+
+        // op[7] = !(p->dram_fsp), dram will switch to another FSP_OP automatically
+        if(operating_fsp)
+            u1MR13Value &= 0x7f; // OP[7] =0;
+        else
+            u1MR13Value |= 0x80; // OP[7] =1;
+
+        if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+        {
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 1, WRITE_LEV_BYTEMODECBTEN);    //BYTEMODECBTEN=1
+        }
+    }
+    else
+    {
+        u1MR13Value &= 0xfe; //MR13 OP[0]=0, disable CBT
+
+        if(operating_fsp)
+            u1MR13Value |= 0x80; // OP[7] =1;
+        else
+            u1MR13Value &= 0x7f; // OP[7] =0;
+    }
+    DramcModeRegWriteByRank(p, p->rank, 13, u1MR13Value);
+}
+
+void CBTEntry(DRAMC_CTX_T *p, U8 operating_fsp, U16 operation_frequency)
+{
+        //Write (DRAMC_AO_BASE+ 0xE<<2) [25] = 1b0 // disable dramc DCMEN
+        //Write (DRAMC_AO_BASE+ 0xE<<2) [30] = 1b0 // set R_DMPHYCLKDYNGEN=0
+        //Write (DRAMC_AO_BASE+ 0x80<<2) [29] = 1b0 // set R_DMDQSIENCG_NORMAL_EN=0
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), P_Fld(0, DRAMC_PD_CTRL_PHYCLKDYNGEN)| P_Fld(0, DRAMC_PD_CTRL_DCMEN));
+
+
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_STBCAL), 0, STBCAL_DQSIENCG_NORMAL_EN);
+
+        //Step 0.0 CKE go high (Release R_DMCKEFIXOFF, R_DMCKEFIXON=1)
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 1, DRAMC_PD_CTRL_MIOCKCTRLOFF);   //MIOCKCTRLOFF=1
+
+        CKEFixOnOff(p, p->rank, CKE_FIXON, CKE_WRITE_TO_ONE_CHANNEL);
+
+        //Step 0: MRW MR13 OP[0]=1 to enable CBT
+        vSetDramMRCBTOnOff(p, ENABLE, operating_fsp);
+
+        //Step 0.1: before CKE low, Let DQS=0 by R_DMwrite_level_en=1, spec: DQS_t has to retain a low level during tDQSCKE period
+        if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE)
+        {
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 1, WRITE_LEV_WRITE_LEVEL_EN);
+        }
+
+        mcDELAY_US(1);
+
+        //Step 1.0: let CKE go low
+        CKEFixOnOff(p, p->rank, CKE_FIXOFF, CKE_WRITE_TO_ONE_CHANNEL);
+
+
+        // Step 1.1 : let IO to O1 path valid
+        if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE)
+        {
+            // Let R_DMFIXDQIEN1=1 (byte1), 0xd8[13]  ==> Note: Do not enable again.
+            //Currently set in O1PathOnOff
+            //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PADCTRL), 0x3, PADCTRL_FIXDQIEN);
+
+            // Let DDRPHY RG_RX_ARDQ_SMT_EN_B1=1 (byte1)
+            //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ3), 1, B1_DQ3_RG_RX_ARDQ_SMT_EN_B1);
+            O1PathOnOff(p, 1);
+        }
+
+        if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+        {
+            // let IO to O1 path valid by DDRPHY RG_RX_ARDQ_SMT_EN_B0=1
+            //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ3), 1, B0_DQ3_RG_RX_ARDQ_SMT_EN_B0);
+            O1PathOnOff(p, 1);
+        }
+}
+
+void CBTExit(DRAMC_CTX_T *p, U8 operating_fsp, U8 operation_frequency)
+{
+        if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE || p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+        {
+            //Step 1: CKE go high (Release R_DMCKEFIXOFF, R_DMCKEFIXON=1)
+            CKEFixOnOff(p, p->rank, CKE_FIXON, CKE_WRITE_TO_ONE_CHANNEL);
+
+            //Step 2:wait tCATX, wait tFC
+            mcDELAY_US(1);
+
+            //Step 3: MRW to command bus training exit (MR13 OP[0]=0 to disable CBT)
+            vSetDramMRCBTOnOff(p, DISABLE, operating_fsp);
+        }
+
+        //Step 4:
+        //Disable O1 path output
+        if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE)
+        {
+            //Let DDRPHY RG_RX_ARDQ_SMT_EN_B1=0
+            //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ3), 0, B1_DQ3_RG_RX_ARDQ_SMT_EN_B1);
+            O1PathOnOff(p, 0);
+
+            //Let FIXDQIEN1=0 ==> Note: Do not enable again.
+            //Moved into O1PathOnOff
+            //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PADCTRL), 0, PADCTRL_FIXDQIEN);
+        }
+
+        if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+        {
+            //Let DDRPHY RG_RX_ARDQ_SMT_EN_B0=0
+            //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ3), 0, B0_DQ3_RG_RX_ARDQ_SMT_EN_B0);
+            O1PathOnOff(p, 0);
+
+            //Disable Byte mode CBT enable bit
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 0, WRITE_LEV_BYTEMODECBTEN);    //BYTEMODECBTEN=0
+        }
+}
+
+static void CBTSetFSP(DRAMC_CTX_T *p, U8 operating_fsp, U8 final_set_flag)
+{
+    if(operating_fsp==FSP_0)
+    {
+        u1MR13Value &= ~(1<<6); //OP[6], fsp_wr=0
+        u1MR13Value &= 0x7f; // OP[7] =0;
+    }
+    else
+    {
+#if (DUAL_FREQ_K)
+        if (final_set_flag==0)
+        {
+        u1MR13Value |= (1<<6); //OP[6], fsp_wr=1
+        u1MR13Value &= 0x7f;  // OP[7] =0;
+        }
+        else
+        {
+        u1MR13Value |= (1<<6); //OP[6], fsp_wr=1
+        u1MR13Value |= 0x80;  // OP[7] =1;
+        }
+#else
+        u1MR13Value |= (1<<6); //OP[6], fsp_wr=1
+        u1MR13Value |= 0x80;  // OP[7] =1;
+#endif
+    }
+
+    DramcModeRegWriteByRank(p, p->rank, 13, u1MR13Value);
+}
+
+static void CBTSetVref(DRAMC_CTX_T *p, U32 u2VrefLevel, U8 operating_fsp, U8 final_set_flag)
+{
+    U32 u4DbgValue;
+    U8 u1VrefValue_pinmux;
+
+    u1VrefValue_pinmux = (GetCmdBusTrainingVrefPinMuxRevertValue(p, u2VrefLevel) & 0x3f);
+
+#if !REDUCE_LOG_FOR_PRELOADER
+    mcSHOW_DBG_MSG(("\nCH_%d, RK_%d, Range=%d, VrefValue_pinmux = 0x%x\n",p->channel, p->rank, gCBT_VREF_RANGE_SEL, u1VrefValue_pinmux));
+#endif
+    mcFPRINTF((fp_A60501, "\nCBTSetVref = 0x%x\n", u2VrefLevel));
+
+
+    if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE && final_set_flag==0)
+    {
+        u1MR12Value[p->channel][p->rank][operating_fsp] = ((gCBT_VREF_RANGE_SEL&0x1) <<6) | u1VrefValue_pinmux;
+
+        //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), ((gCBT_VREF_RANGE_SEL&0x1) <<6) | (u2VrefLevel & 0x3f), WRITE_LEV_DMVREFCA);  //MR12, bit[25:20]=OP[5:0]  bit 26=OP[6]
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), u2VrefLevel, WRITE_LEV_DMVREFCA);  //MR12, bit[25:20]=OP[5:0]  bit 26=OP[6]
+
+         //DQS_SEL=1, DQS_B1_G=1, Toggle R_DMDQS_WLEV (1 to 0)
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 1 , WRITE_LEV_DQS_SEL);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 0xa , WRITE_LEV_DQSBX_G);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 1 , WRITE_LEV_DQS_WLEV);
+        mcDELAY_US(1);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 0, WRITE_LEV_DQS_WLEV);
+
+    }
+    else
+    {
+    u4DbgValue = (((gCBT_VREF_RANGE_SEL&0x1) <<6) | (u2VrefLevel & 0x3f));
+    u1MR12Value[p->channel][p->rank][operating_fsp] = u4DbgValue;
+    mcSHOW_DBG_MSG3(("u4DbgValue = 0x%x\n", u4DbgValue));
+
+    DramcModeRegWriteByRank(p, p->rank, 12, u4DbgValue);
+    }
+
+    //wait tVREF_LONG
+    mcDELAY_US(1);
+}
+
+static U32 CBTDelayCACLKCompare(DRAMC_CTX_T *p, S32 iDelay)
+{
+    U32 u4Result=0, u4Result0=0, u4Ready;
+    U32 u4TimeCnt;
+
+    u4TimeCnt = TIME_OUT_CNT;
+    if(iDelay < 0)
+    {   //Set CLK delay
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), P_Fld(0, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD) |
+                                                                   P_Fld(-iDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK) |
+                                                                   P_Fld(-iDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS));
+    }
+    else if(iDelay>=64)
+    {   //Set CA output delay + 2UI
+        DramcCmdUIDelaySetting(p, 2);
+
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), P_Fld(iDelay-64, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD) |
+                                                                  P_Fld(CLK_SHIFT_PI_DELAY, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK) |
+                                                                  P_Fld(0, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS));
+    }
+    else
+    {   //Set CA output delay
+        DramcCmdUIDelaySetting(p, 0);
+
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), P_Fld(iDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD) |
+                                                                   P_Fld(CLK_SHIFT_PI_DELAY, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK) |
+                                                                   P_Fld(0, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS));
+    }
+
+    //Let R_DMTESTCATRAIN=1 to enable HW CAPAT Generator
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 1, CATRAINING1_TESTCATRAIN);
+
+    //Check CA training compare ready (dramc_conf_nao 0x3fc , CATRAIN_CMP_CPT)
+    do
+    {
+        u4Ready = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TCMDO1LAT), TCMDO1LAT_CATRAIN_CMP_CPT);
+        u4TimeCnt --;
+        mcDELAY_US(1);
+    }while((u4Ready==0) &&(u4TimeCnt>0));
+
+    if(u4TimeCnt==0)//time out
+    {
+        mcSHOW_DBG_MSG(("[CBTDelayCACLKCompare] Resp fail (time out)\n"));
+        mcFPRINTF((fp_A60501, "[CBTDelayCACLKCompare] Resp fail (time out)\n"));
+        //return DRAM_FAIL;
+    }
+
+    //Get CA training compare result (dramc_conf_nao 0x3fc , CATRAIN_CMP_ERR)
+        if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE)
+        {
+            u4Result = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TCMDO1LAT), TCMDO1LAT_CATRAIN_CMP_ERR);
+        }
+        else
+        {
+            u4Result0 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TCMDO1LAT), TCMDO1LAT_CATRAIN_CMP_ERR0);
+//            mcSHOW_DBG_MSG(("[Francis] TCMDO1LAT_CATRAIN_CMP_ERR0=0x%x\n", u4Result0));
+            u4Result = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TCMDO1LAT), TCMDO1LAT_CATRAIN_CMP_ERR);
+//            mcSHOW_DBG_MSG(("[Francis] TCMDO1LAT_CATRAIN_CMP_ERR=0x%x\n", u4Result));
+        }
+
+    //Let R_DMTESTCATRAIN=0 to disable HW CAPAT Generator
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 0, CATRAINING1_TESTCATRAIN);
+
+    return (u4Result|u4Result0); // return pattern compre result
+}
+
+
+static U32 CBTDelayCSCompare(DRAMC_CTX_T *p, U32 uiDelay)
+{
+    U8 *uiLPDDR_O1_Mapping = NULL;
+    U32 u4Result, u4Ready;
+    U32 u4TimeCnt;
+    U32 u4dq_o1;
+    U32 u4byte_index;
+
+    u4TimeCnt = TIME_OUT_CNT;
+
+    if (u1IsLP4Family(p->dram_type))
+    {
+        uiLPDDR_O1_Mapping = (U8 *)uiLPDDR4_O1_Mapping_POP[p->channel];
+    }
+#if ENABLE_LP3_SW
+    else
+    {
+        #if (fcFOR_CHIP_ID == fcLaurel)
+        if(p->bDLP3)
+        {
+            uiLPDDR_O1_Mapping = (U8 *)uiLPDDR3_O1_Mapping_POP_DLP3;
+        }
+        else
+        #endif
+        {
+            uiLPDDR_O1_Mapping = (U8 *)uiLPDDR3_O1_Mapping_POP;
+        }
+    }
+#endif /* ENABLE_LP3_SW */
+
+    //Set CS output delay
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), uiDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS);
+    //Step 5: toggle CS/CA for CS training by R_DMTCMDEN (wait dramc_nao tcmd_response=1, disable R_DMTCMDEN), 0x1e4[5]
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_TCMDEN);
+    do
+    {
+        u4Ready = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_TCMD_RESPONSE);
+        u4TimeCnt --;
+        mcDELAY_US(1);
+    }while((u4Ready==0) &&(u4TimeCnt>0));
+
+
+    if(u4TimeCnt==0)//time out
+    {
+        mcSHOW_DBG_MSG(("[CBTDelayCSCompare] Resp fail (time out)\n"));
+        mcFPRINTF((fp_A60501, "[CBTDelayCSCompare] Resp fail (time out)\n"));
+        //return DRAM_FAIL;
+    }
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_TCMDEN);
+
+    //Step 6: check CS training result on DQ[13:8] by O1, DDRPHYCFG 0xF80
+    //Expected CA value is h2a (CA pulse width is 6UI, CS pulse is 1UI)
+    u4dq_o1 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_DQO1), MISC_DQO1_DQO1_RO);
+    u4Result = 0;
+    for(u4byte_index=8; u4byte_index<=13; u4byte_index++)
+    {
+        u4Result |= (((u4dq_o1 & (1<<uiLPDDR_O1_Mapping[u4byte_index])) >> (uiLPDDR_O1_Mapping[u4byte_index])) << (u4byte_index-8));
+    }
+    mcSHOW_DBG_MSG3(("CS Dly = %d, Result=0x%x\n", uiDelay, u4Result));
+    return u4Result; // return pattern compre result
+}
+
+#if 0  //for CBT CS test
+static U32 CBTDelayCSCompare2(DRAMC_CTX_T *p)
+{
+    U32 u4err_value, uiDelay;
+
+    for (uiDelay=0; uiDelay<=MAX_CS_PI_DELAY; uiDelay++)
+    {
+        // Set CS output delay
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_ARPI_CMD), uiDelay, ARPI_CMD_DA_ARPI_CS);
+        u4err_value= TestEngineCompare(p);
+        mcSHOW_DBG_MSG(("CBTDelayCSCompare2= %3d, u4err_value=0x%2x\n", uiDelay, u4err_value));
+    }
+
+    return DRAM_OK; // return pattern compre result
+}
+#endif
+
+#if 0
+void DramcCmdBusTrainingPostProcess(DRAMC_CTX_T *p)
+{
+    S32 iCSFinalClkDelay, iCSFinalCmdDelay, iCSFinalCSDelay;
+    U8 backup_rank, irank;
+
+    // CBT Rank0/1 must set Clk/CA/CS the same from Wei-Jen
+
+    mcSHOW_DBG_MSG(("[DramcCmdBusTrainingPostProcess] p->frequency=%d\n", p->frequency));
+
+    backup_rank = u1GetRank(p);
+
+    iCSFinalClkDelay= (CATrain_ClkDelay[p->channel][RANK_0] + CATrain_ClkDelay[p->channel][RANK_1])/2;
+    CATrain_ClkDelay[p->channel][RANK_0] = iCSFinalClkDelay;
+    CATrain_ClkDelay[p->channel][RANK_1] = iCSFinalClkDelay;
+
+    iCSFinalCmdDelay= (CATrain_CmdDelay[p->channel][RANK_0] + CATrain_CmdDelay[p->channel][RANK_1])/2;
+    CATrain_CmdDelay[p->channel][RANK_0] = iCSFinalCmdDelay;
+    CATrain_CmdDelay[p->channel][RANK_1] = iCSFinalCmdDelay;
+
+    iCSFinalCSDelay= (CATrain_CsDelay[p->channel][RANK_0] + CATrain_CsDelay[p->channel][RANK_1])/2;
+    CATrain_CsDelay[p->channel][RANK_0] = iCSFinalCSDelay;
+    CATrain_CsDelay[p->channel][RANK_1] = iCSFinalCSDelay;
+
+    for(irank=RANK_0; irank<=RANK_1; irank++)
+    {
+        vSetRank(p, irank);
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), P_Fld(iCSFinalClkDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK) |
+                                                                    P_Fld(iCSFinalCmdDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD) |
+                                                                    P_Fld(iCSFinalCSDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS));
+    }
+
+    mcSHOW_DBG_MSG(("Clk Dly = %d\nCmd Dly = %d\nCS Dly = %d\n", iCSFinalClkDelay, iCSFinalCmdDelay, iCSFinalCSDelay));
+
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+    if(p->femmc_Ready==0)
+    {
+        p->pSavetimeData->u1CBTClkDelay_Save[p->channel][RANK_0]= iCSFinalClkDelay;
+        p->pSavetimeData->u1CBTClkDelay_Save[p->channel][RANK_1]= iCSFinalClkDelay;
+
+        p->pSavetimeData->u1CBTCmdDelay_Save[p->channel][RANK_0]= iCSFinalCmdDelay;
+        p->pSavetimeData->u1CBTCmdDelay_Save[p->channel][RANK_1]= iCSFinalCmdDelay;
+
+        p->pSavetimeData->u1CBTCsDelay_Save[p->channel][RANK_0]= iCSFinalCSDelay;
+        p->pSavetimeData->u1CBTCsDelay_Save[p->channel][RANK_1]= iCSFinalCSDelay;
+    }
+#endif
+
+    vSetRank(p, backup_rank);
+}
+#endif
+
+static void CBTAdjustCS(DRAMC_CTX_T *p)
+{
+    S32 iFirstCSPass, iLastCSPass, iCSFinalDelay;//iCSCenter
+    U32 uiDelay, u4ValueReadBack, u4CSWinSize;
+    U8 backup_rank, rank_i;
+
+    backup_rank = u1GetRank(p);
+
+#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_CBT)
+    if(p->femmc_Ready==1)
+    {
+        iCSFinalDelay=p->pSavetimeData->u1CBTCsDelay_Save[p->channel][p->rank];
+    }
+    else
+#endif
+    {
+        iFirstCSPass = -1;
+        iLastCSPass = -1;
+
+        for (uiDelay=0; uiDelay<=MAX_CS_PI_DELAY; uiDelay++)
+        {
+            u4ValueReadBack = CBTDelayCSCompare(p, uiDelay);
+
+            if(iFirstCSPass == -1)
+            {
+                if(u4ValueReadBack== 0x2a)  // compare pass
+                {
+                    iFirstCSPass = uiDelay;
+                }
+            }
+            else if(iLastCSPass == -1)
+            {
+                if(u4ValueReadBack != 0x2a)  // compare fail
+                {
+                    iLastCSPass = uiDelay-1;
+                }
+                else if (uiDelay ==MAX_CS_PI_DELAY)
+                {
+                    iLastCSPass = uiDelay;
+                }
+            }
+
+            // Wait time before output CS pattern to DDR again.. (Review this if need to save time)
+            mcDELAY_US(1);
+        }
+
+        u4CSWinSize = iLastCSPass - iFirstCSPass + (iLastCSPass==iFirstCSPass?0:1);
+
+        if(u4CSWinSize > ((MAX_CS_PI_DELAY+1)>>1))  // if winSize >32, CS delay= winSize -32.
+        {
+            iCSFinalDelay = u4CSWinSize -((MAX_CS_PI_DELAY+1)>>1);
+        }
+        else  ///TODO: need to delay CLK?  A60817 and A60501 cannot move CLK PI due to multi_phase problem.
+        {
+            iCSFinalDelay =0;
+        }
+
+        CATrain_CsDelay[p->channel][p->rank] = iCSFinalDelay;
+        mcSHOW_DBG_MSG(("\nCS Dly= %d (%d-%d-32)\n", iCSFinalDelay, iLastCSPass, iFirstCSPass));
+        mcFPRINTF((fp_A60501, "\nCS Dly= %d (%d-%d-32)\n", iCSFinalDelay, iLastCSPass, iFirstCSPass));
+
+        // if dual rank, use average position of both rank
+        if(backup_rank == RANK_1)
+        {
+            iCSFinalDelay = (CATrain_CsDelay[p->channel][RANK_0] + CATrain_CsDelay[p->channel][RANK_1])/2;
+        }
+    }
+    //Set CS output delay after training
+    /* p->rank = RANK_0, save to Reg Rank0 and Rank1, p->rank = RANK_1, save to Reg Rank1 */
+    for(rank_i=RANK_0; rank_i<backup_rank+1; rank_i++)
+    {
+        vSetRank(p, rank_i);
+
+        #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        if(p->femmc_Ready==0)
+        {
+            p->pSavetimeData->u1CBTCsDelay_Save[p->channel][p->rank]= iCSFinalDelay;
+        }
+        #endif
+
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), iCSFinalDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS);
+        CATrain_CsDelay[p->channel][rank_i]= iCSFinalDelay;
+        //mcSHOW_DBG_MSG(("\n[CBTAdjustCS] RK%d ,CS Dly: %d\n",rank_i, iCSFinalDelay));
+    }
+    vSetRank(p, backup_rank);
+}
+
+static void CBTSetCACLKResult(DRAMC_CTX_T *p, S8 s1FinalCACLK, S8 *ps1CACenterDiff)
+{
+    U8 backup_rank, rank_i;
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+    U8 uiCA;
+#endif
+
+    backup_rank = u1GetRank(p);
+
+    /* p->rank = RANK_0, save to Reg Rank0 and Rank1, p->rank = RANK_1, save to Reg Rank1 */
+    for(rank_i=RANK_0; rank_i<backup_rank+1; rank_i++)
+    {
+        vSetRank(p, rank_i);
+
+        #if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_CBT)
+        if(p->femmc_Ready==1)
+        {
+            CATrain_ClkDelay[p->channel][p->rank]=p->pSavetimeData->u1CBTClkDelay_Save[p->channel][p->rank];
+            CATrain_CmdDelay[p->channel][p->rank]=p->pSavetimeData->u1CBTCmdDelay_Save[p->channel][p->rank];
+
+            #if CA_PER_BIT_DELAY_CELL
+            for (uiCA = 0; uiCA < CATRAINING_NUM_LP4; uiCA++)
+            {
+                ps1CACenterDiff[uiCA] = p->pSavetimeData->u1CBTCA_PerBit_DelayLine_Save[p->channel][p->rank][uiCA];
+            }
+            #endif
+
+            vSetCalibrationResult(p, DRAM_CALIBRATION_CA_TRAIN, DRAM_OK); // set default result OK, udpate status when per bit fail
+        }
+        else
+        #endif
+        {
+            CATrain_ClkDelay[p->channel][p->rank] = CLK_SHIFT_PI_DELAY;
+
+            if(s1FinalCACLK<0)
+            {
+                CATrain_CmdDelay[p->channel][p->rank] = 0;
+            }
+            else
+            {
+                if(s1FinalCACLK>=64)
+                    CATrain_CmdDelay[p->channel][p->rank] = s1FinalCACLK-64;
+                else
+                    CATrain_CmdDelay[p->channel][p->rank] = s1FinalCACLK;
+            }
+        }
+
+        //mcSHOW_DBG_MSG(("[CBTSetCACLKResult]Rank%d, Clk dly= %d, CA dly= %d\n", rank_i,  CATrain_ClkDelay[p->channel][p->rank], CATrain_CmdDelay[p->channel][p->rank]));
+        //mcFPRINTF((fp_A60501, "[CBTSetCACLKResult]Rank%d, Clk dly= %d, CA dly= %d\n", rank_i,  CATrain_ClkDelay[p->channel][p->rank], CATrain_CmdDelay[p->channel][p->rank]));
+        if(s1FinalCACLK<64)
+    	{
+            DramcCmdUIDelaySetting(p, 0);
+    	}
+        else
+        {
+            DramcCmdUIDelaySetting(p, 2);
+        }
+
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), P_Fld(CATrain_CmdDelay[p->channel][p->rank], SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD) |
+                                                                    P_Fld(CATrain_ClkDelay[p->channel][p->rank], SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK));
+
+        #if CA_PER_BIT_DELAY_CELL
+        CATrainingSetPerBitDelayCell(p, ps1CACenterDiff);
+        #endif
+
+
+        #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        if(p->femmc_Ready==0)
+        {
+            p->pSavetimeData->u1CBTClkDelay_Save[p->channel][p->rank]= CATrain_ClkDelay[p->channel][p->rank];
+            p->pSavetimeData->u1CBTCmdDelay_Save[p->channel][p->rank]= CATrain_CmdDelay[p->channel][p->rank];
+
+            #if CA_PER_BIT_DELAY_CELL
+            for (uiCA = 0; uiCA < CATRAINING_NUM_LP4; uiCA++)
+            {
+                p->pSavetimeData->u1CBTCA_PerBit_DelayLine_Save[p->channel][p->rank][uiCA] = ps1CACenterDiff[uiCA];
+            }
+
+#endif
+        }
+        #endif
+    }
+
+    vSetRank(p, backup_rank);
+
+#if EYESCAN_LOG
+    gEyeScan_CaliDelay[0] = CATrain_CmdDelay[p->channel][p->rank] + (CBT_MOVE_CA_INSTEAD_OF_CLK==0?MAX_CLK_PI_DELAY:0);
+#endif
+}
+
+
+U8 GetCmdBusTrainingVrefPinMuxValue(DRAMC_CTX_T *p, U8 u1VrefLevel)
+{
+    U8 u2VrefBit, u2Vref_new, u2Vref_org;
+
+    if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1) return ((gCBT_VREF_RANGE_SEL&0x1) <<6) | (u1VrefLevel & 0x3f);
+
+
+    u2Vref_new = 0;
+    u2Vref_org = ((gCBT_VREF_RANGE_SEL&0x1) <<6) | (u1VrefLevel & 0x3f);
+    for (u2VrefBit = 0; u2VrefBit < 8; u2VrefBit++)
+    {
+//        mcSHOW_DBG_MSG(("=== u2VrefBit: %d, %d\n",u2VrefBit,uiLPDDR4_O1_Mapping_POP[p->channel][u2VrefBit]));
+        if (u2Vref_org & (1 << u2VrefBit))
+        {
+            u2Vref_new |=  (1 << uiLPDDR4_O1_Mapping_POP[p->channel][u2VrefBit]);
+//            mcSHOW_DBG_MSG(("=== u2VrefBit: %d, %d, u2Vref_org: %x, u2Vref_new: 0x%x\n",u2VrefBit,uiLPDDR4_O1_Mapping_POP[p->channel][u2VrefBit],u2Vref_org,u2Vref_new));
+        }
+    }
+
+    mcSHOW_DBG_MSG3(("=== u2Vref_new: 0x%x --> 0x%x\n",u2Vref_org,u2Vref_new));
+
+    return u2Vref_new;
+}
+
+U8 GetCmdBusTrainingVrefPinMuxRevertValue(DRAMC_CTX_T *p, U8 u1VrefLevel)
+{
+    U8 u2VrefBit, u2Vref_new, u2Vref_org;
+
+    if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1) return u1VrefLevel;
+
+    u2Vref_new = 0;
+    u2Vref_org = u1VrefLevel;
+    for (u2VrefBit = 0; u2VrefBit < 8; u2VrefBit++)
+    {
+        u2Vref_new |=  ((u2Vref_org>>uiLPDDR4_O1_Mapping_POP[p->channel][u2VrefBit])&1) << u2VrefBit;
+    }
+
+    mcSHOW_DBG_MSG3(("=== Revert u2Vref_new: 0x%x --> 0x%x\n",u2Vref_org,u2Vref_new));
+
+    return u2Vref_new;
+}
+
+
+DRAM_STATUS_T CmdBusTrainingLP4(DRAMC_CTX_T *p)
+{
+    U16 u1VrefLevel, uiFinalVref;
+    U32 u4CompareResult;
+    PASS_WIN_DATA_T FinalWinPerCA[CATRAINING_NUM_LP4];
+    U32 uiCA, uiFinishCount, uiTemp;
+    S16 iDelay;
+#if CBT_SPEED_UP_CALIBRATION
+    U8 all_first_pass_flag=0, already_speed_up_flag=0;
+#endif
+
+    S32 iFirstPass_temp[CATRAINING_NUM_LP4], iLastPass_temp[CATRAINING_NUM_LP4];
+    U32 uiCAWinSum, uiCAWinSumMax;
+    //S32 iCACenter[CATRAINING_NUM_LP4] = {0}, iCACenterSum = 0, iCAFinalCenter[CATRAINING_NUM_LP4] = {0};
+    U8 operating_fsp;
+    U16 operation_frequency;
+    U8 irange, irange_start, irange_end;
+    U16 uiFinalRange=0;
+    U8 u1CBTEyeScanEnable;
+
+    S8 iFinalCACLK;
+    S8 s1CACenterDiff[CATRAINING_NUM]={0}; //for CA_PER_BIT
+
+#if EYESCAN_LOG
+    U8 EyeScan_index[CATRAINING_NUM_LP4];
+#endif
+    U32 u4RegBackupAddress[] =
+    {
+        (DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL)),
+        (DRAMC_REG_ADDR(DRAMC_REG_STBCAL)),
+        (DRAMC_REG_ADDR(DRAMC_REG_CKECTRL)),
+        (DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV)),
+        (DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0)),
+        (DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL)),
+    };
+
+#if MRW_CHECK_ONLY
+    mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
+#endif
+
+    u1CBTEyeScanEnable = (gCBT_EYE_Scan_flag==1 && ((gCBT_EYE_Scan_only_higheset_freq_flag==1 && p->frequency == u2DFSGetHighestFreq(p)) || gCBT_EYE_Scan_only_higheset_freq_flag==0));
+
+#if EYESCAN_LOG
+    U32 u1vrefidx, ii;
+
+    if (u1IsLP4Family(p->dram_type))
+    {
+        for(u1vrefidx=0; u1vrefidx<VREF_TOTAL_NUM_WITH_RANGE;u1vrefidx++)
+        {
+            for (uiCA = 0; uiCA < CATRAINING_NUM_LP4; uiCA++)
+            {
+                for(ii=0; ii<EYESCAN_BROKEN_NUM; ii++)
+                {
+                    gEyeScan_Min[u1vrefidx][uiCA][ii] = EYESCAN_DATA_INVALID;
+                    gEyeScan_Max[u1vrefidx][uiCA][ii] = EYESCAN_DATA_INVALID;
+                }
+
+                FinalWinPerCA[uiCA].first_pass = EYESCAN_DATA_INVALID;
+                FinalWinPerCA[uiCA].last_pass = EYESCAN_DATA_INVALID;
+                FinalWinPerCA[uiCA].win_center = 0;
+                FinalWinPerCA[uiCA].win_size = 0;
+            }
+        }
+    }
+#endif
+
+    //Back up dramC register
+    DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+    vAutoRefreshSwitch(p, DISABLE); //When doing CA training, should make sure that auto refresh is disable
+
+    //tx_rank_sel is selected by SW //Lewis@20180509: tx_rank_sel is selected by SW in CBT if TMRRI design has changed.
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), p->rank, RKCFG_TXRANK);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 1, RKCFG_TXRANKFIX); //TXRANKFIX should be write after TXRANK
+
+    //SW variable initialization
+    uiCAWinSumMax=0;
+    uiFinalVref=u1MR12Value[p->channel][p->rank][p->dram_fsp] & 0x3f;
+    iFinalCACLK=0;
+    operating_fsp = p->dram_fsp;
+    operation_frequency = p->frequency;
+    #if CA_PER_BIT_DELAY_CELL
+    CATrainingSetPerBitDelayCell(p, s1CACenterDiff);
+    #endif
+
+
+    if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE)
+    {
+        //switch to low freq
+        if (operating_fsp == FSP_1)
+        {
+            CBT_Switch_Freq(p, CBT_LOW_FREQ);
+        }
+        //Step 1: Enter Command Bus Training Mode
+        CBTEntry(p, operating_fsp, operation_frequency);
+        //Step 2: wait tCAENT
+        mcDELAY_US(1);
+        //switch to high freq
+        if (operating_fsp == FSP_1)
+        {
+            CBT_Switch_Freq(p, CBT_HIGH_FREQ);
+        }
+    }
+
+#if PINMUX_AUTO_TEST_PER_BIT_CA
+#if ENABLE_LPDDR4
+    CheckCADelayCell(p);
+#endif
+#endif
+
+#if VENDER_JV_LOG
+    vPrintCalibrationBasicInfo_ForJV(p);
+#else
+    vPrintCalibrationBasicInfo(p);
+#endif
+
+    //Step 3: set CBT range, verify range and setp
+#if (SW_CHANGE_FOR_SIMULATION ||FOR_DV_SIMULATION_USED)
+    gCBT_VREF_RANGE_SEL = 0;  //MR12,OP[6]
+    irange_start=irange_end=0;
+    gCBT_VREF_RANGE_BEGIN = 0;
+    gCBT_VREF_RANGE_END = 2; // binary 110010
+    gCBT_VREF_RANGE_STEP = 2;
+#else
+    gCBT_VREF_RANGE_SEL = 1;  //MR12,OP[6]
+    irange_start=irange_end=1;
+    gCBT_VREF_RANGE_STEP = 2;
+
+    if (p->enable_cbt_scan_vref == DISABLE_VREF_SCAN)
+    {
+        gCBT_VREF_RANGE_BEGIN = (u1MR12Value[p->channel][p->rank][p->dram_fsp] & 0x3f);
+        gCBT_VREF_RANGE_END = gCBT_VREF_RANGE_BEGIN;
+    }
+    else
+    {
+        if (p->dram_type == TYPE_LPDDR4)
+        {
+            //range 1
+            gCBT_VREF_RANGE_BEGIN = 13 - 5; // 300/1100(VDDQ) = 27.2%
+            gCBT_VREF_RANGE_END = 13 + 5;
+        }
+        else
+        {
+            //range 1
+            gCBT_VREF_RANGE_BEGIN = 27 - 5; // 290/600(VDDQ)=48.3%
+            gCBT_VREF_RANGE_END = 27 + 5;
+        }
+    }
+#endif
+
+    if (u1CBTEyeScanEnable)
+    {
+        irange_start = 0;
+        irange_end = 1;
+    }
+
+    for(irange=irange_start; irange<=irange_end; irange++)
+    {
+        if (u1CBTEyeScanEnable)
+        {
+            gCBT_VREF_RANGE_SEL = irange;
+            gCBT_VREF_RANGE_BEGIN = 0;
+            gCBT_VREF_RANGE_END = 50;
+            gCBT_VREF_RANGE_STEP = 1;
+
+            if (gCBT_VREF_RANGE_SEL == 1)
+            {
+                gCBT_VREF_RANGE_BEGIN = 21;
+            }
+        }
+
+#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_VREF_CAL)
+        if(p->femmc_Ready==1)
+        {
+            mcSHOW_DBG_MSG(("\n[FAST_K] BYPASS_VREF_CAL CBT\n"));
+        }
+        else
+#endif
+        {
+            for(u1VrefLevel = gCBT_VREF_RANGE_BEGIN; u1VrefLevel<=gCBT_VREF_RANGE_END; u1VrefLevel+=gCBT_VREF_RANGE_STEP)
+            {
+#if EYESCAN_LOG
+                for (uiCA = 0; uiCA < CATRAINING_NUM_LP4; uiCA++)
+                {
+                   gEyeScan_DelayCellPI[uiCA] = 0;
+                   EyeScan_index[uiCA] = 0;
+                }
+#endif
+
+                //VREFCA = you want
+                {
+                    if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+                    {
+#if (FOR_DV_SIMULATION_USED==0)
+                        //switch to low freq
+                        if (operating_fsp == FSP_1)
+                        {
+                            CBT_Switch_Freq(p, CBT_LOW_FREQ);
+                        }
+#endif
+                        CBTSetFSP(p, operating_fsp, 0);
+                    }
+                    CBTSetVref(p, GetCmdBusTrainingVrefPinMuxValue(p, u1VrefLevel), operating_fsp, 0);
+                }
+
+#if VENDER_JV_LOG
+                mcSHOW_DBG_MSG5(("\n\tLP4 CBT VrefRange %d, VrefLevel=%d\n", gCBT_VREF_RANGE_SEL, u1VrefLevel));
+#endif
+                if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+                {
+                    //Step 1: Enter Command Bus Training Mode
+                    CBTEntry(p, operating_fsp, operation_frequency);
+                    //Step 2: wait tCAENT
+                    mcDELAY_US(1);
+
+#if (FOR_DV_SIMULATION_USED==0)
+                    //switch to high freq
+                    if (operating_fsp == FSP_1)
+                    {
+                        CBT_Switch_Freq(p, CBT_HIGH_FREQ);
+                    }
+#endif
+                }
+                // Delay CA output delay to do CA training in order to get the pass window.
+                // moving CA relative to CK and repeating until CA is centered on the latching edge of CK
+                // Note  !!!!!!!!!!!!!!!!!!!!!!!
+                // Assume : Leave clk as the init value and adjust CA delay only can find out each CA window including of the left boundary.
+                // If NOT, we may need to off-line adjust 0x404 SELPH2_TXDLY_CMD
+                // SW variable initialization
+                uiFinishCount = 0;
+                uiCAWinSum = 0;
+#if CBT_SPEED_UP_CALIBRATION
+                already_speed_up_flag = 0;
+#endif
+                for (uiCA=0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+                {
+                     iLastPass_temp[uiCA] = PASS_RANGE_NA;
+                     iFirstPass_temp[uiCA] = PASS_RANGE_NA;
+                }
+
+#if CBT_MOVE_CA_INSTEAD_OF_CLK
+                for (iDelay=0; iDelay<=MAX_CA_PI_DELAY; iDelay++)
+#else
+                for (iDelay= (-MAX_CLK_PI_DELAY); iDelay<=MAX_CA_PI_DELAY; iDelay++)
+#endif
+                {
+                    u4CompareResult= CBTDelayCACLKCompare(p, iDelay);
+
+                    //Wait tCACD(22clk) before output CA pattern to DDR again..
+                    mcDELAY_US(1);
+
+                    mcSHOW_DBG_MSG3(("CBTDelayCACLK Delay= %d, CompareResult 0x%x\n", iDelay, u4CompareResult));
+                    mcFPRINTF((fp_A60501, "CBTDelayCACLK Delay = %d, CompareResult 0x%x\n", iDelay, u4CompareResult));
+
+                    for (uiCA=0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+                    {
+                        if((iFirstPass_temp[uiCA] != PASS_RANGE_NA) && (iLastPass_temp[uiCA] != PASS_RANGE_NA))
+                        {
+                            continue;
+                        }
+
+                        uiTemp = (u4CompareResult >>uiCA) & 0x1; //Get Each bit of CA result
+
+                        if(iFirstPass_temp[uiCA] == PASS_RANGE_NA)
+                        {
+                            if(uiTemp==0) //compare correct: pass
+                            {
+                                iFirstPass_temp[uiCA] = iDelay;
+                            }
+                        }
+                        else if(iLastPass_temp[uiCA] == PASS_RANGE_NA)
+                        {
+                            if(uiTemp==1) //compare error : fail
+                            {
+                                #if CBT_SPEED_UP_CALIBRATION
+                                if (already_speed_up_flag==1)
+                                {
+                                    // fra : if test fail after first step of speed up, then show warning message
+                                    mcSHOW_ERR_MSG(("[CBT] CA=%d, fail after speed up! iDelay=%d !!\n", uiCA, iDelay));
+                                    #if __ETT__
+                                    while(1);
+                                    #endif
+                                }
+                                #endif
+
+                                if ((iDelay-iFirstPass_temp[uiCA]) < 5) //prevent glitch
+                                {
+                                    iFirstPass_temp[uiCA] = PASS_RANGE_NA;
+                                    continue;
+                                }
+
+                                iLastPass_temp[uiCA] = (iDelay-1);
+                            }
+                            else if (iDelay==MAX_CA_PI_DELAY)
+                            {
+                                iLastPass_temp[uiCA] = iDelay;
+                            }
+
+                            if(iLastPass_temp[uiCA] !=PASS_RANGE_NA)
+                            {
+                                uiFinishCount++;
+                                uiCAWinSum += (iLastPass_temp[uiCA] -iFirstPass_temp[uiCA]); //Sum of CA Windows for vref selection
+                                //iCACenter[uiCA] = (iLastPass_temp[uiCA] +iFirstPass_temp[uiCA])>>1; //window center of each CA bit
+                                //iCACenterSum += iCACenter[uiCA];
+#if !REDUCE_LOG_FOR_PRELOADER
+                                mcSHOW_DBG_MSG(("\n[CA %d] Center %d (%d~%d)\n", uiCA, iCACenter[uiCA] , iFirstPass_temp[uiCA], iLastPass_temp[uiCA]));
+#endif
+#if EYESCAN_LOG
+                                if (EyeScan_index[uiCA] < EYESCAN_BROKEN_NUM)
+                                {
+                                    gEyeScan_Min[u1VrefLevel+irange*30][uiCA][EyeScan_index[uiCA]] = iFirstPass_temp[uiCA]+(CBT_MOVE_CA_INSTEAD_OF_CLK==0?MAX_CLK_PI_DELAY:0);
+                                    gEyeScan_Max[u1VrefLevel+irange*30][uiCA][EyeScan_index[uiCA]] = iLastPass_temp[uiCA]+(CBT_MOVE_CA_INSTEAD_OF_CLK==0?MAX_CLK_PI_DELAY:0);
+                                    mcSHOW_DBG_MSG3(("u2VrefLevel=%d, u2VrefRange=%d, %d, uiCA=%d, index=%d (%d, %d)==\n",u1VrefLevel, irange, u1VrefLevel+irange*30, uiCA, EyeScan_index[uiCA], gEyeScan_Min[u1VrefLevel+irange*30][uiCA][EyeScan_index[uiCA]], gEyeScan_Max[u1VrefLevel+irange*30][uiCA][EyeScan_index[uiCA]]));
+                                    EyeScan_index[uiCA]=EyeScan_index[uiCA]+1;
+                                }
+#endif
+                            }
+                        }
+                    }
+
+
+#if CBT_SPEED_UP_CALIBRATION
+                    if (!u1CBTEyeScanEnable)
+                    {
+                        if (already_speed_up_flag==0)
+                        {
+                            all_first_pass_flag=0;
+                            for (uiCA = 0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+                            {
+                            if (iFirstPass_temp[uiCA] != PASS_RANGE_NA && (iDelay-iFirstPass_temp[uiCA]) >= 5) //prevent glitch
+                                {
+                                    all_first_pass_flag|=1<<uiCA;
+                                }
+                            }
+
+                            if (all_first_pass_flag==0x3f)
+                            {
+                                // fra : speed up 30 steps to save K time
+                                iDelay+=30;
+                                already_speed_up_flag = 1;
+                            }
+                        }
+                        else
+                        {
+                            already_speed_up_flag=2; //the check fail of first step after already speed up done.
+                        }
+                    }
+#endif
+
+                    if(uiFinishCount == CATRAINING_NUM_LP4)
+                        break;
+               }
+#if VENDER_JV_LOG
+                for (uiCA=0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+                {
+                    mcSHOW_DBG_MSG5(("CBT Bit%d, CA window %d ps\n", uiCA, (iLastPass_temp[uiCA]-iFirstPass_temp[uiCA]+1)*1000000/p->frequency/64));
+                }
+#endif
+
+                //set CK/CS pi delay to 0 and set CA pi delay to center
+                #if CBT_MOVE_CA_INSTEAD_OF_CLK
+                vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), P_Fld(0x20, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD) | P_Fld(CLK_SHIFT_PI_DELAY, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK) | P_Fld(0, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS));
+                #else
+                vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), P_Fld(0, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD) | P_Fld(CLK_SHIFT_PI_DELAY, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK) | P_Fld(0, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS));
+                #endif
+
+#if !REDUCE_LOG_FOR_PRELOADER
+                mcSHOW_DBG_MSG(("\n[CmdBusTrainingLP4] CAWinSum: %d\n", uiCAWinSum));
+#endif
+                if(uiCAWinSum > uiCAWinSumMax)
+                {
+                    uiCAWinSumMax =uiCAWinSum;
+                    uiFinalVref = u1VrefLevel;
+                    if (u1CBTEyeScanEnable) uiFinalRange = gCBT_VREF_RANGE_SEL;
+
+                    for (uiCA=0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+                    {
+                        FinalWinPerCA[uiCA].first_pass = iFirstPass_temp[uiCA];
+                        FinalWinPerCA[uiCA].last_pass = iLastPass_temp[uiCA];
+                    }
+                }
+
+#if EYESCAN_LOG
+                for (uiCA=0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+                {
+                    gEyeScan_WinSize[u1VrefLevel+irange*30][uiCA] = (iLastPass_temp[uiCA] - iFirstPass_temp[uiCA])+(iLastPass_temp[uiCA]==iFirstPass_temp[uiCA]?0:1);
+                }
+#endif
+                if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+                {
+#if (FOR_DV_SIMULATION_USED==0)
+                    //switch to low freq
+                    if (operating_fsp == FSP_1)
+                    {
+                        CBT_Switch_Freq(p, CBT_LOW_FREQ);
+                    }
+#endif
+                    //Step 1: Enter Command Bus Training Mode
+                    CBTExit(p, operating_fsp, operation_frequency);
+                    //Step 2: wait tCAENT
+                    mcDELAY_US(1);
+                }
+
+                if (gCBT_EYE_Scan_flag == 0)
+                {
+                    if(uiCAWinSum < (uiCAWinSumMax*95/100))
+                    {
+                        mcSHOW_DBG_MSG(("\nCBT Vref found, early break!\n"));
+                        break;//max vref found, early break;
+                    }
+                }
+            }
+        }
+    }
+
+    if (u1CBTEyeScanEnable)
+        gCBT_VREF_RANGE_SEL = uiFinalRange;
+
+#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_VREF_CAL)
+    if(p->femmc_Ready==0)
+#endif
+    {
+        for (uiCA=0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+        {
+            FinalWinPerCA[uiCA].win_center = (FinalWinPerCA[uiCA].first_pass +  FinalWinPerCA[uiCA].last_pass)/2;
+            FinalWinPerCA[uiCA].win_size = (FinalWinPerCA[uiCA].last_pass - FinalWinPerCA[uiCA].first_pass)+(FinalWinPerCA[uiCA].last_pass==FinalWinPerCA[uiCA].first_pass?0:1);
+
+        #if 1//CA_PER_BIT_DELAY_CELL
+            iFirstCAPass[p->rank][0][uiCA] = FinalWinPerCA[uiCA].first_pass;
+            iLastCAPass[p->rank][0][uiCA] = FinalWinPerCA[uiCA].last_pass;
+        #endif
+
+        #ifdef FOR_HQA_TEST_USED
+            gFinalCBTCA[p->channel][p->rank][uiCA] = FinalWinPerCA[uiCA].win_size;
+        #endif
+
+        #if PINMUX_AUTO_TEST_PER_BIT_CA
+            gFinalCAPerbitFirstPass[p->channel][p->rank][uiCA] = FinalWinPerCA[uiCA].first_pass;
+        #endif
+
+            mcSHOW_DBG_MSG(("[CA %d] Center %d (%d~%d) winsize %d\n", uiCA, FinalWinPerCA[uiCA].win_center , FinalWinPerCA[uiCA].first_pass, FinalWinPerCA[uiCA].last_pass, FinalWinPerCA[uiCA].win_size));
+        }
+
+#ifdef FOR_HQA_REPORT_USED
+        if (gHQALog_flag==1)
+        {
+            mcSHOW_DBG_MSG(("\n"));
+            for (uiCA=0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+            {
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_2, "CA_Center", uiCA, FinalWinPerCA[uiCA].win_center, NULL);
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_2, "CA_Window", uiCA, FinalWinPerCA[uiCA].win_size, NULL);
+            }
+        }
+#endif
+
+        #if 1//CA_PER_BIT_DELAY_CELL
+        // LP4 has already consider two dies. No more position calculation of 2 dies.
+        gu1LP3DieNum[p->rank] =1;
+        CATrainingPosCal(p, gu1LP3DieNum, &iFinalCACLK, s1CACenterDiff);
+        #else
+        #if SW_CHANGE_FOR_SIMULATION
+            iFinalCACLK =(int)((float) iCACenterSum/(float)CATRAINING_NUM_LP4);
+            #else
+            iFinalCACLK = iCACenterSum/CATRAINING_NUM_LP4;
+            #endif
+        #endif
+    }
+
+#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_VREF_CAL)
+    if(p->femmc_Ready==1 )
+    {
+        uiFinalVref = p->pSavetimeData->u1CBTVref_Save[p->channel][p->rank];
+    }
+#endif
+
+#ifdef DEVIATION
+    if (p->frequency == u2DFSGetHighestFreq(p) && gSetSpecificedVref_Enable[0]==ENABLE && ((p->channel==gSetSpecificedVref_Channel[0] && p->rank==gSetSpecificedVref_Rank[0]) || gSetSpecificedVref_All_ChRk[0]==ENABLE))
+    {
+        uiFinalRange = gCBT_VREF_RANGE_SEL;
+        DeviationAddVrefOffset(0, &uiFinalRange, &uiFinalVref, gSetSpecificedVref_Vref_Offset[0]);
+        gCBT_VREF_RANGE_SEL = (U8) uiFinalRange;
+    }
+#endif
+
+    //Set Vref after trainging
+    if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+    {
+#if (FOR_DV_SIMULATION_USED==0)
+        //switch to low freq
+        if (operating_fsp == FSP_1)
+        {
+            CBT_Switch_Freq(p, CBT_LOW_FREQ);
+        }
+#endif
+        CBTSetFSP(p, operating_fsp, 1);
+        CBTSetVref(p, GetCmdBusTrainingVrefPinMuxValue(p,uiFinalVref), operating_fsp, 1);
+    }
+    else
+    {
+        CBTSetVref(p, GetCmdBusTrainingVrefPinMuxValue(p,uiFinalVref), operating_fsp, 0);  //Francis, normol mode go DQ pin set vref, don't set final_set_flag here
+    }
+
+    mcSHOW_DBG_MSG(("\nVref(ca) range %d: %d\n", gCBT_VREF_RANGE_SEL, uiFinalVref));
+    mcFPRINTF((fp_A60501, "\nVref(ca) is Range %d: %d\n", gCBT_VREF_RANGE_SEL, uiFinalVref));
+#if VENDER_JV_LOG
+    mcSHOW_DBG_MSG5(("\nVref(ca) range %d: %d\n", gCBT_VREF_RANGE_SEL, uiFinalVref));
+#endif
+
+#ifdef FOR_HQA_TEST_USED
+    gFinalCBTVrefCA[p->channel][p->rank] = uiFinalVref & 0x3f;
+#endif
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+    if(p->femmc_Ready==0)
+    {
+        p->pSavetimeData->u1CBTVref_Save[p->channel][p->rank]= uiFinalVref;
+    }
+#endif
+
+    if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+    {
+        //Step 1: Enter Command Bus Training Mode
+        CBTEntry(p, operating_fsp, operation_frequency);
+        //Step 2: wait tCAENT
+        mcDELAY_US(1);
+
+#if (FOR_DV_SIMULATION_USED==0)
+        //switch to high freq
+        if (operating_fsp == FSP_1)
+        {
+            CBT_Switch_Freq(p, CBT_HIGH_FREQ);
+        }
+#endif
+    }
+
+    //Set CLK and CA delay in CBT mode to prevent dram abnormal.
+    CBTSetCACLKResult(p, iFinalCACLK, s1CACenterDiff);
+
+    //wait tVREF_LONG
+    mcDELAY_US(1);
+
+    //-------------  CS and CLK ----------
+    CBTAdjustCS(p);
+
+//-------  Going to exit Command bus training(CBT) mode.-------------
+#if (FOR_DV_SIMULATION_USED==0)
+    //switch to low freq
+    if (operating_fsp == FSP_1)
+    {
+        CBT_Switch_Freq(p, CBT_LOW_FREQ);
+    }
+#endif
+
+#if EYESCAN_LOG || defined(FOR_HQA_TEST_USED)
+    gFinalCBTVrefDQ[p->channel][p->rank] = uiFinalVref;
+#endif
+
+    CBTExit(p, operating_fsp, operation_frequency);
+
+    if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE)
+    {
+        CBTSetFSP(p, operating_fsp, 1);
+        CBTSetVref(p, uiFinalVref, operating_fsp, 1); //francis, normal mode go MR12 set vref again, set final_set_flag to force to MR12 flow
+    }
+
+#if (FOR_DV_SIMULATION_USED==0)
+    //switch to high freq
+    if (operating_fsp == FSP_1)
+    {
+        CBT_Switch_Freq(p, CBT_HIGH_FREQ);
+    }
+#endif
+
+    if((p->rank+1) == p->support_rank_num)  // both rank calibration done.
+    {
+        mcSHOW_DBG_MSG(("\n[CmdBusTrainingLP4] Final result for both ranks\nClk dly= %d PI\nCA  dly= %d PI\nCS  dly= %d PI\n\n", CATrain_ClkDelay[p->channel][p->rank], CATrain_CmdDelay[p->channel][p->rank],  CATrain_CsDelay[p->channel][p->rank]));
+        mcFPRINTF((fp_A60501, "\n[CmdBusTrainingLP4] Final result for both ranks\nClk dly= %d PI\nCA dly= %d PI\nCS dly=%d PI\n\n", CATrain_ClkDelay[p->channel][p->rank], CATrain_CmdDelay[p->channel][p->rank],  CATrain_CsDelay[p->channel][p->rank]));
+    }
+    mcSHOW_DBG_MSG3(("\n[CmdBusTrainingLP4] Done\n"));
+    mcFPRINTF((fp_A60501, "\n[CmdBusTrainingLP4] Done\n"));
+
+    //tx_rank_sel is selected by HW //Lewis@20180509: tx_rank_sel is selected by SW in CBT if TMRRI design has changed.
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANK);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANKFIX); //TXRANKFIX should be write after TXRANK
+
+    //Restore setting registers
+    DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+    return DRAM_OK;
+}
+#endif //SIMUILATION_LP4_CBT
+
+//-------------------------------------------------------------------------
+/** DramcWriteLeveling
+ *  start Write Leveling Calibration.
+ *  @param p                Pointer of context created by DramcCtxCreate.
+ *  @param  apply           (U8): 0 don't apply the register we set  1 apply the register we set ,default don't apply.
+ *  @retval status          (DRAM_STATUS_T): DRAM_OK or DRAM_FAIL
+ */
+//-------------------------------------------------------------------------
+#define WRITE_LEVELING_MOVD_DQS 1//UI
+
+
+// NOT suitable for Gating delay
+static DRAM_STATUS_T ExecuteMoveDramCDelay(DRAMC_CTX_T *p, REG_TRANSFER_T regs[], S8 iShiftUI)
+{
+    S32 s4HighLevelDelay, s4DelaySum;
+    U32 u4Tmp0p5T, u4Tmp2T;
+    U8 ucDataRateDivShift = 0;
+    DRAM_STATUS_T MoveResult;
+
+    if (u1IsLP4Family(p->dram_type))
+    {
+        ucDataRateDivShift = 3;
+    }
+#if ENABLE_LP3_SW
+    else
+    {
+        ucDataRateDivShift = 2;
+    }
+#endif /* ENABLE_LP3_SW */
+
+    u4Tmp0p5T = u4IO32ReadFldAlign(DRAMC_REG_ADDR(regs[0].u4Addr), regs[0].u4Fld) & (~(1<<ucDataRateDivShift));
+    u4Tmp2T = u4IO32ReadFldAlign(DRAMC_REG_ADDR(regs[1].u4Addr), regs[1].u4Fld);
+    //mcSHOW_DBG_MSG(("\n[MoveDramC_Orz]  u4Tmp2T:%d,  u4Tmp0p5T: %d,\n",  u4Tmp2T, u4Tmp0p5T));
+    //mcFPRINTF((fp_A60501, "\n[MoveDramC_Orz]  u4Tmp2T:%d,  u4Tmp0p5T: %d,\n",  u4Tmp2T, u4Tmp0p5T));
+
+    s4HighLevelDelay = (u4Tmp2T <<ucDataRateDivShift) + u4Tmp0p5T;
+    s4DelaySum = (s4HighLevelDelay + iShiftUI);
+    //mcSHOW_DBG_MSG(("\n[MoveDramC_Orz]  s4HighLevelDealy(%d) +  iShiftUI(%d) = %d\n",  s4HighLevelDelay, iShiftUI, s4DelaySum));
+
+    if(s4DelaySum < 0)
+    {
+        u4Tmp0p5T =0;
+        u4Tmp2T=0;
+        MoveResult =  DRAM_FAIL;
+        //mcSHOW_ERR_MSG(("\n[MoveDramC_Orz]  s4HighLevelDealy(%d) +  iShiftUI(%d) is small than 0!!\n",  s4HighLevelDelay, iShiftUI));
+    }
+    else
+    {
+        u4Tmp2T = s4DelaySum >> ucDataRateDivShift;
+        u4Tmp0p5T = s4DelaySum - (u4Tmp2T <<ucDataRateDivShift);
+        MoveResult = DRAM_OK;
+    }
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(regs[0].u4Addr), u4Tmp0p5T, regs[0].u4Fld);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(regs[1].u4Addr), u4Tmp2T, regs[1].u4Fld);
+    //mcSHOW_DBG_MSG(("\n[MoveDramC_Orz]  Final ==> u4Tmp2T:%d,  u4Tmp0p5T: %d,\n",  u4Tmp2T, u4Tmp0p5T));
+    //mcFPRINTF((fp_A60501, "\n[MoveDramC_Orz]  Final ==> u4Tmp2T:%d,  u4Tmp0p5T: %d,\n",  u4Tmp2T, u4Tmp0p5T));
+
+    return MoveResult;
+}
+
+void MoveDramC_TX_DQS(DRAMC_CTX_T *p, U8 u1ByteIdx, S8 iShiftUI)
+{
+    REG_TRANSFER_T TransferReg[2];
+
+    //mcSHOW_DBG_MSG(("\n[MoveDramC_TX_DQS] Byte %d, iShiftUI %d\n", u1ByteIdx, iShiftUI));
+
+    switch(u1ByteIdx)
+    {
+        case 0:
+            // DQS0
+            TransferReg[0].u4Addr = DRAMC_REG_SHU_SELPH_DQS1;
+            TransferReg[0].u4Fld =SHU_SELPH_DQS1_DLY_DQS0;
+            TransferReg[1].u4Addr = DRAMC_REG_SHU_SELPH_DQS0;
+            TransferReg[1].u4Fld =SHU_SELPH_DQS0_TXDLY_DQS0;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+            break;
+
+        case 1:
+            // DQS1
+            TransferReg[0].u4Addr = DRAMC_REG_SHU_SELPH_DQS1;
+            TransferReg[0].u4Fld =SHU_SELPH_DQS1_DLY_DQS1;
+            TransferReg[1].u4Addr = DRAMC_REG_SHU_SELPH_DQS0;
+            TransferReg[1].u4Fld =SHU_SELPH_DQS0_TXDLY_DQS1;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+            break;
+
+        case 2:
+            // DQS2
+            TransferReg[0].u4Addr = DRAMC_REG_SHU_SELPH_DQS1;
+            TransferReg[0].u4Fld =SHU_SELPH_DQS1_DLY_DQS2;
+            TransferReg[1].u4Addr = DRAMC_REG_SHU_SELPH_DQS0;
+            TransferReg[1].u4Fld =SHU_SELPH_DQS0_TXDLY_DQS2;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+            break;
+
+        case 3:
+            // DQS3
+            TransferReg[0].u4Addr = DRAMC_REG_SHU_SELPH_DQS1;
+            TransferReg[0].u4Fld =SHU_SELPH_DQS1_DLY_DQS3;
+            TransferReg[1].u4Addr = DRAMC_REG_SHU_SELPH_DQS0;
+            TransferReg[1].u4Fld =SHU_SELPH_DQS0_TXDLY_DQS3;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+            break;
+
+            default:
+                break;
+    }
+}
+
+void MoveDramC_TX_DQS_OEN(DRAMC_CTX_T *p, U8 u1ByteIdx, S8 iShiftUI)
+{
+    REG_TRANSFER_T TransferReg[2];
+
+    //mcSHOW_DBG_MSG(("\n[MoveDramC_TX_DQS_OEN] Byte %d, iShiftUI %d\n", u1ByteIdx, iShiftUI));
+
+    switch(u1ByteIdx)
+    {
+        case 0:
+            // DQS_OEN_0
+            TransferReg[0].u4Addr = DRAMC_REG_SHU_SELPH_DQS1;
+            TransferReg[0].u4Fld =SHU_SELPH_DQS1_DLY_OEN_DQS0;
+            TransferReg[1].u4Addr = DRAMC_REG_SHU_SELPH_DQS0;
+            TransferReg[1].u4Fld =SHU_SELPH_DQS0_TXDLY_OEN_DQS0;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+            break;
+
+        case 1:
+            // DQS_OEN_1
+            TransferReg[0].u4Addr = DRAMC_REG_SHU_SELPH_DQS1;
+            TransferReg[0].u4Fld =SHU_SELPH_DQS1_DLY_OEN_DQS1;
+            TransferReg[1].u4Addr = DRAMC_REG_SHU_SELPH_DQS0;
+            TransferReg[1].u4Fld =SHU_SELPH_DQS0_TXDLY_OEN_DQS1;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+            break;
+
+        case 2:
+            // DQS_OEN_2
+            TransferReg[0].u4Addr = DRAMC_REG_SHU_SELPH_DQS1;
+            TransferReg[0].u4Fld =SHU_SELPH_DQS1_DLY_OEN_DQS2;
+            TransferReg[1].u4Addr = DRAMC_REG_SHU_SELPH_DQS0;
+            TransferReg[1].u4Fld =SHU_SELPH_DQS0_TXDLY_OEN_DQS2;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+            break;
+
+        case 3:
+            // DQS_OEN_3
+            TransferReg[0].u4Addr = DRAMC_REG_SHU_SELPH_DQS1;
+            TransferReg[0].u4Fld =SHU_SELPH_DQS1_DLY_OEN_DQS3;
+            TransferReg[1].u4Addr = DRAMC_REG_SHU_SELPH_DQS0;
+            TransferReg[1].u4Fld =SHU_SELPH_DQS0_TXDLY_OEN_DQS3;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+            break;
+
+            default:
+                break;
+    }
+}
+
+
+void MoveDramC_TX_DQ(DRAMC_CTX_T *p, U8 u1ByteIdx, S8 iShiftUI)
+{
+    REG_TRANSFER_T TransferReg[2];
+
+    //mcSHOW_DBG_MSG(("\n[MoveDramC_TX_DQ] Byte %d, iShiftUI %d\n", u1ByteIdx, iShiftUI));
+
+    switch(u1ByteIdx)
+    {
+        case 0:
+            // DQM0
+            TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+            TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_DQM0;
+            TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+            TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_DQM0;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+
+            // DQ0
+            TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+            TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_DQ0;
+            TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+            TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_DQ0;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+        break;
+
+        case 1:
+            // DQM1
+            TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+            TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_DQM1;
+            TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+            TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_DQM1;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+            // DQ1
+            TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+            TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_DQ1;
+            TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+            TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_DQ1;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+        break;
+
+        case 2:
+            // DQM2
+            TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+            TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_DQM2;
+            TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+            TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_DQM2;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+            // DQ2
+            TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+            TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_DQ2;
+            TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+            TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_DQ2;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+        break;
+
+        case 3:
+            // DQM3
+            TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+            TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_DQM3;
+            TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+            TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_DQM3;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+            // DQ3
+            TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+            TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_DQ3;
+            TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+            TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_DQ3;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+        break;
+    }
+}
+
+void MoveDramC_TX_DQ_OEN(DRAMC_CTX_T *p, U8 u1ByteIdx, S8 iShiftUI)
+{
+    REG_TRANSFER_T TransferReg[2];
+
+    //mcSHOW_DBG_MSG(("\n[MoveDramC_TX_DQ_OEN] Byte %d, iShiftUI %d\n", u1ByteIdx, iShiftUI));
+
+    switch(u1ByteIdx)
+    {
+        case 0:
+            // DQM_OEN_0
+            TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+            TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_OEN_DQM0;
+            TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+            TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_OEN_DQM0;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+            // DQ_OEN_0
+            TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+            TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_OEN_DQ0;
+            TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+            TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_OEN_DQ0;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+        break;
+
+        case 1:
+            // DQM_OEN_1
+            TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+            TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_OEN_DQM1;
+            TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+            TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_OEN_DQM1;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+             // DQ_OEN_1
+            TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+            TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_OEN_DQ1;
+            TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+            TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_OEN_DQ1;
+             ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+        break;
+
+        case 2:
+            // DQM_OEN_2
+            TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+            TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_OEN_DQM2;
+            TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+            TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_OEN_DQM2;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+            // DQ_OEN_2
+            TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+            TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_OEN_DQ2;
+            TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+            TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_OEN_DQ2;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+        break;
+
+        case 3:
+            // DQM_OEN_3
+            TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+            TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_OEN_DQM3;
+            TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+            TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_OEN_DQM3;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+            // DQ_OEN_3
+            TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+            TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_OEN_DQ3;
+            TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+            TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_OEN_DQ3;
+            ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+        break;
+    }
+}
+
+#if ENABLE_LP3_SW
+//for LPDDR3 DQ delay line used
+void Set_RX_DQ_DelayLine_Phy_Byte(DRAMC_CTX_T *p, U8 u1ByteIdx, U8 value[8])
+{
+    DRAM_CHANNEL_T backup_channel;
+    backup_channel = p->channel;
+
+#if (fcFOR_PINMUX == fcLaurel)
+
+    switch(u1ByteIdx)
+    {
+        case 0:
+            p->channel = CHANNEL_B;
+            //DQ0 -> BRDQ0_B1   //DQ3 -> BRDQ1_B1
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2),
+                    P_Fld(value[0], SHU1_R0_B1_DQ2_RK0_RX_ARDQ0_F_DLY_B1) |
+                    P_Fld(value[0], SHU1_R0_B1_DQ2_RK0_RX_ARDQ0_R_DLY_B1) |
+                    P_Fld(value[3], SHU1_R0_B1_DQ2_RK0_RX_ARDQ1_F_DLY_B1) |
+                    P_Fld(value[3], SHU1_R0_B1_DQ2_RK0_RX_ARDQ1_R_DLY_B1) );
+            //DQ7 -> BRDQ2_B1   //DQ1 -> BRDQ3_B1
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ3),
+                    P_Fld(value[7], SHU1_R0_B1_DQ3_RK0_RX_ARDQ2_F_DLY_B1) |
+                    P_Fld(value[7], SHU1_R0_B1_DQ3_RK0_RX_ARDQ2_R_DLY_B1) |
+                    P_Fld(value[1], SHU1_R0_B1_DQ3_RK0_RX_ARDQ3_F_DLY_B1) |
+                    P_Fld(value[1], SHU1_R0_B1_DQ3_RK0_RX_ARDQ3_R_DLY_B1) );
+            //DQ2 -> BRDQ4_B1   //DQ6 -> BRDQ5_B1
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ4),
+                    P_Fld(value[2], SHU1_R0_B1_DQ4_RK0_RX_ARDQ4_F_DLY_B1) |
+                    P_Fld(value[2], SHU1_R0_B1_DQ4_RK0_RX_ARDQ4_R_DLY_B1) |
+                    P_Fld(value[6], SHU1_R0_B1_DQ4_RK0_RX_ARDQ5_F_DLY_B1) |
+                    P_Fld(value[6], SHU1_R0_B1_DQ4_RK0_RX_ARDQ5_R_DLY_B1));
+            //DQ5 -> BRDQ6_B1   //DQ4 -> BRDQ7_B1
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ5),
+                    P_Fld(value[5], SHU1_R0_B1_DQ5_RK0_RX_ARDQ6_F_DLY_B1) |
+                    P_Fld(value[5], SHU1_R0_B1_DQ5_RK0_RX_ARDQ6_R_DLY_B1) |
+                    P_Fld(value[4], SHU1_R0_B1_DQ5_RK0_RX_ARDQ7_F_DLY_B1) |
+                    P_Fld(value[4], SHU1_R0_B1_DQ5_RK0_RX_ARDQ7_R_DLY_B1));
+            break;
+        case 1:
+            p->channel = CHANNEL_B;
+            //DQ5 -> BRCA0     //DQ1 -> BRCA1
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD2),
+                    P_Fld(value[5], SHU1_R0_CA_CMD2_RG_RK0_RX_ARCA0_F_DLY) |
+                    P_Fld(value[5], SHU1_R0_CA_CMD2_RG_RK0_RX_ARCA0_R_DLY) |
+                    P_Fld(value[1], SHU1_R0_CA_CMD2_RG_RK0_RX_ARCA1_F_DLY) |
+                    P_Fld(value[1], SHU1_R0_CA_CMD2_RG_RK0_RX_ARCA1_R_DLY));
+            //DQ4 -> BRCA2     //DQ6 -> BRCA3
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD3),
+                    P_Fld(value[4], SHU1_R0_CA_CMD3_RG_RK0_RX_ARCA2_F_DLY) |
+                    P_Fld(value[4], SHU1_R0_CA_CMD3_RG_RK0_RX_ARCA2_R_DLY) |
+                    P_Fld(value[6], SHU1_R0_CA_CMD3_RG_RK0_RX_ARCA3_F_DLY) |
+                    P_Fld(value[6], SHU1_R0_CA_CMD3_RG_RK0_RX_ARCA3_R_DLY));
+            //DQ2 -> BRCA4     //DQ7 -> BRCS5
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD4),
+                    P_Fld(value[2], SHU1_R0_CA_CMD4_RG_RK0_RX_ARCA4_F_DLY) |
+                    P_Fld(value[2], SHU1_R0_CA_CMD4_RG_RK0_RX_ARCA4_R_DLY) |
+                    P_Fld(value[7], SHU1_R0_CA_CMD4_RG_RK0_RX_ARCA5_F_DLY) |
+                    P_Fld(value[7], SHU1_R0_CA_CMD4_RG_RK0_RX_ARCA5_R_DLY));
+            //DQ3 -> BRCKE0    //DQ0 -> BRCKE1
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD5),
+                    P_Fld(value[3], SHU1_R0_CA_CMD5_RG_RK0_RX_ARCKE0_F_DLY) |
+                    P_Fld(value[3], SHU1_R0_CA_CMD5_RG_RK0_RX_ARCKE0_R_DLY) |
+                    P_Fld(value[0], SHU1_R0_CA_CMD5_RG_RK0_RX_ARCKE1_F_DLY) |
+                    P_Fld(value[0], SHU1_R0_CA_CMD5_RG_RK0_RX_ARCKE1_R_DLY));
+
+            break;
+       case 2:
+            p->channel = CHANNEL_A;
+            //DQ1 -> ARDQ0_B1   //DQ0 -> ARDQ1_B1
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2),
+                    P_Fld(value[1], SHU1_R0_B1_DQ2_RK0_RX_ARDQ0_F_DLY_B1) |
+                    P_Fld(value[1], SHU1_R0_B1_DQ2_RK0_RX_ARDQ0_R_DLY_B1) |
+                    P_Fld(value[0], SHU1_R0_B1_DQ2_RK0_RX_ARDQ1_F_DLY_B1) |
+                    P_Fld(value[0], SHU1_R0_B1_DQ2_RK0_RX_ARDQ1_R_DLY_B1));
+            //DQ4 -> ARDQ2_B1   //DQ5 -> ARDQ3_B1
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ3),
+                    P_Fld(value[4], SHU1_R0_B1_DQ3_RK0_RX_ARDQ2_F_DLY_B1) |
+                    P_Fld(value[4], SHU1_R0_B1_DQ3_RK0_RX_ARDQ2_R_DLY_B1) |
+                    P_Fld(value[5], SHU1_R0_B1_DQ3_RK0_RX_ARDQ3_F_DLY_B1) |
+                    P_Fld(value[5], SHU1_R0_B1_DQ3_RK0_RX_ARDQ3_R_DLY_B1));
+            //DQ2 -> ARDQ4_B1   //DQ6 -> ARDQ5_B1
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ4),
+                    P_Fld(value[2], SHU1_R0_B1_DQ4_RK0_RX_ARDQ4_F_DLY_B1) |
+                    P_Fld(value[2], SHU1_R0_B1_DQ4_RK0_RX_ARDQ4_R_DLY_B1) |
+                    P_Fld(value[6], SHU1_R0_B1_DQ4_RK0_RX_ARDQ5_F_DLY_B1) |
+                    P_Fld(value[6], SHU1_R0_B1_DQ4_RK0_RX_ARDQ5_R_DLY_B1));
+            //DQ3 -> ARDQ6_B1   //DQ7 -> ARDQ7_B1
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ5),
+                    P_Fld(value[3], SHU1_R0_B1_DQ5_RK0_RX_ARDQ6_F_DLY_B1) |
+                    P_Fld(value[3], SHU1_R0_B1_DQ5_RK0_RX_ARDQ6_R_DLY_B1) |
+                    P_Fld(value[7], SHU1_R0_B1_DQ5_RK0_RX_ARDQ7_F_DLY_B1) |
+                    P_Fld(value[7], SHU1_R0_B1_DQ5_RK0_RX_ARDQ7_R_DLY_B1));
+            break;
+       case 3:
+            p->channel = CHANNEL_B;
+            //DQ5 -> BRDQ0_B0   //DQ0 -> BRDQ1_B0
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2),
+                    P_Fld(value[5], SHU1_R0_B0_DQ2_RK0_RX_ARDQ0_F_DLY_B0) |
+                    P_Fld(value[5], SHU1_R0_B0_DQ2_RK0_RX_ARDQ0_R_DLY_B0) |
+                    P_Fld(value[0], SHU1_R0_B0_DQ2_RK0_RX_ARDQ1_F_DLY_B0) |
+                    P_Fld(value[0], SHU1_R0_B0_DQ2_RK0_RX_ARDQ1_R_DLY_B0));
+            //DQ6 -> BRDQ2_B0  //DQ4 -> BRDQ3_B0
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ3),
+                    P_Fld(value[6], SHU1_R0_B0_DQ3_RK0_RX_ARDQ2_F_DLY_B0) |
+                    P_Fld(value[6], SHU1_R0_B0_DQ3_RK0_RX_ARDQ2_R_DLY_B0) |
+                    P_Fld(value[4], SHU1_R0_B0_DQ3_RK0_RX_ARDQ3_F_DLY_B0) |
+                    P_Fld(value[4], SHU1_R0_B0_DQ3_RK0_RX_ARDQ3_R_DLY_B0));
+            //DQ3 -> BRDQ4_B0  //DQ7 -> BRDQ5_B0
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ4),
+                    P_Fld(value[3], SHU1_R0_B0_DQ4_RK0_RX_ARDQ4_F_DLY_B0) |
+                    P_Fld(value[3], SHU1_R0_B0_DQ4_RK0_RX_ARDQ4_R_DLY_B0) |
+                    P_Fld(value[7], SHU1_R0_B0_DQ4_RK0_RX_ARDQ5_F_DLY_B0) |
+                    P_Fld(value[7], SHU1_R0_B0_DQ4_RK0_RX_ARDQ5_R_DLY_B0));
+            //DQ2 -> BRDQ6_B0  //DQ1 -> BRDQ7_B0
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ5),
+                    P_Fld(value[2], SHU1_R0_B0_DQ5_RK0_RX_ARDQ6_F_DLY_B0) |
+                    P_Fld(value[2], SHU1_R0_B0_DQ5_RK0_RX_ARDQ6_R_DLY_B0) |
+                    P_Fld(value[1], SHU1_R0_B0_DQ5_RK0_RX_ARDQ7_F_DLY_B0) |
+                    P_Fld(value[1], SHU1_R0_B0_DQ5_RK0_RX_ARDQ7_R_DLY_B0));
+            break;
+
+    }
+#endif
+    p->channel = backup_channel;
+}
+
+//for LPDDR3 DQM delay line used
+void Set_RX_DQM_DelayLine_Phy_Byte(DRAMC_CTX_T *p, U8 u1ByteIdx, S8 value)
+{
+    DRAM_CHANNEL_T backup_channel;
+    backup_channel = p->channel;
+
+#if (fcFOR_PINMUX == fcLaurel)
+    switch(u1ByteIdx)
+    {
+        case 0:
+            p->channel = CHANNEL_B;
+            //DQM0 -> BRDQM0_B1
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ6), P_Fld(value, SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_F_DLY_B1) | P_Fld(value, SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_R_DLY_B1));
+            break;
+        case 1:
+            p->channel = CHANNEL_B;
+            //DQM1 -> BRCS0
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD6), P_Fld(value, SHU1_R0_CA_CMD6_RG_RK0_RX_ARCS0_F_DLY) | P_Fld(value, SHU1_R0_CA_CMD6_RG_RK0_RX_ARCS0_R_DLY));
+            break;
+       case 2:
+            p->channel = CHANNEL_A;
+            //DQM2 -> ARDQM0_B1
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ6), P_Fld(value, SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_F_DLY_B1) | P_Fld(value, SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_R_DLY_B1));
+            break;
+       case 3:
+            p->channel = CHANNEL_B;
+            //DQM3 -> BRDQM0_B0
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6), P_Fld(value, SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_F_DLY_B0) | P_Fld(value, SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_R_DLY_B0));
+            break;
+
+    }
+#endif
+
+    p->channel = backup_channel;
+}
+#endif
+
+#if SIMULATION_WRITE_LEVELING
+#if WRITE_LEVELING_MOVE_DQS_INSTEAD_OF_CLK
+void WriteLevelingMoveDQSInsteadOfCLK(DRAMC_CTX_T *p)
+{
+    U8 u1ByteIdx;
+    U8 backup_rank, ii;
+
+    backup_rank = u1GetRank(p);
+
+    for(u1ByteIdx =0 ; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+    {
+        MoveDramC_TX_DQS(p, u1ByteIdx, -WRITE_LEVELING_MOVD_DQS);
+        MoveDramC_TX_DQS_OEN(p, u1ByteIdx, -WRITE_LEVELING_MOVD_DQS);
+
+        for(ii=RANK_0; ii<RANK_MAX; ii++)
+        {
+            vSetRank(p, ii);
+            MoveDramC_TX_DQ(p, u1ByteIdx, -WRITE_LEVELING_MOVD_DQS);
+            MoveDramC_TX_DQ_OEN(p, u1ByteIdx, -WRITE_LEVELING_MOVD_DQS);
+        }
+        vSetRank(p, backup_rank);
+    }
+}
+#endif
+
+
+//static void vSetDramMRWriteLevelingOnOff(DRAMC_CTX_T *p, U8 u1OnOff)
+void vSetDramMRWriteLevelingOnOff(DRAMC_CTX_T *p, U8 u1OnOff)
+{
+    // MR2 OP[7] to enable/disable write leveling
+    if(u1OnOff)
+        u1MR02Value[p->dram_fsp] |= 0x80;  // OP[7] WR LEV =1
+    else
+        u1MR02Value[p->dram_fsp] &= 0x7f;  // OP[7] WR LEV =0
+
+    DramcModeRegWriteByRank(p, p->rank, 2, u1MR02Value[p->dram_fsp]);
+}
+
+#define DQS_DUTY_MEASURE_WITH_WRITE_LEVELING 0
+DRAM_STATUS_T DramcWriteLeveling(DRAMC_CTX_T *p)
+{
+// Note that below procedure is based on "ODT off"
+    DRAM_STATUS_T KResult= DRAM_FAIL;
+
+    U32 u4value=0, u4dq_o1=0;
+    U8 byte_i, ucsample_count;
+    S32 ii;
+    U8 ucsample_status[DQS_NUMBER], ucdq_o1_perbyte[DQS_NUMBER], ucdq_o1_index[DQS_NUMBER];
+    DRAM_RANK_T backup_rank;
+
+    S32 wrlevel_dq_delay[DQS_NUMBER]; // 3 is channel number
+#if ENABLE_LP3_SW
+    S32 wrlevel_dqs_delay[DQS_NUMBER]; // 3 is channel number
+#endif
+
+    #if WRITE_LEVELING_MOVE_DQS_INSTEAD_OF_CLK
+    S32 i4PIBegin, i4PIEnd;
+    U8 u1PIStep;
+    #endif
+
+    #if DQS_DUTY_MEASURE_WITH_WRITE_LEVELING
+    U16 u2TriggerCnt;
+    #endif
+
+    // error handling
+    if (!p)
+    {
+        mcSHOW_ERR_MSG(("context NULL\n"));
+        return DRAM_FAIL;
+    }
+
+    U32 u4RegBackupAddress[] =
+    {
+        (DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0)),
+        (DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL)),
+        (DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL)),
+        (DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV)),
+        (DRAMC_REG_ADDR(DRAMC_REG_CKECTRL)),
+    };
+
+#if MRW_CHECK_ONLY
+    mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
+#endif
+
+    vPrintCalibrationBasicInfo(p);
+
+    fgwrlevel_done = 0;
+    backup_rank = u1GetRank(p);
+
+    #if CBT_WORKAROUND_O1_SWAP
+    if(u1IsLP4Family(p->dram_type))
+    {
+        CATrain_CmdDelay[p->channel][p->rank] = 0;//u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_ARPI_CMD), ARPI_CMD_DA_ARPI_CMD);
+        CATrain_CsDelay[p->channel][p->rank] = 0;//u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_ARPI_CMD), ARPI_CMD_DA_ARPI_CS);
+        CATrain_ClkDelay[p->channel][p->rank] = 0;//u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_ARPI_CMD), ARPI_CMD_DA_ARPI_CK);
+    }
+    #endif
+
+    //DramcRankSwap(p, p->rank);
+    //tx_rank_sel is selected by SW //Lewis@20180604: tx_rank_sel is selected by SW in WL if TMRRI design has changed.
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), p->rank, RKCFG_TXRANK);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 1, RKCFG_TXRANKFIX); //TXRANKFIX should be write after TXRANK
+
+    // DQ mapping
+    ///!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+    /// Note : uiLPDDR_O1_Mapping_POP, need to take care mapping in real chip, but not in test chip.
+    /// Everest : there is bit swap inside single byte. PHY & DRAM is 1-1 byte mapping, no swap.
+    for (byte_i=0; byte_i<(p->data_width/DQS_BIT_NUMBER); byte_i++)
+    {
+        ucdq_o1_index[byte_i] = byte_i*8;
+    }
+
+#ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+    U8 u1GUMP_INIT_RG_LOG_TO_DE_bak = gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag;
+    gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag=0;
+#endif
+
+#if REG_ACCESS_PORTING_DGB
+    RegLogEnable =1;
+    mcSHOW_DBG_MSG(("\n[REG_ACCESS_PORTING_FUNC] DramcWriteLeveling\n"));
+    mcFPRINTF((fp_A60501, "\n[REG_ACCESS_PORTING_FUNC] DramcWriteLeveling\n"));
+#endif
+
+    // backup mode settings
+    DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+    vAutoRefreshSwitch(p, DISABLE); //When doing CA training, should make sure that auto refresh is disable
+
+    #if WRITE_LEVELING_MOVE_DQS_INSTEAD_OF_CLK
+    if(p->arfgWriteLevelingInitShif[p->channel][p->rank] ==FALSE)
+    {
+        WriteLevelingMoveDQSInsteadOfCLK(p);
+        //p->arfgWriteLevelingInitShif[p->channel][p->rank] =TRUE;
+        p->arfgWriteLevelingInitShif[p->channel][RANK_0] =TRUE;
+        p->arfgWriteLevelingInitShif[p->channel][RANK_1] =TRUE;
+        #if TX_PERBIT_INIT_FLOW_CONTROL
+        // both 2 rank use one write leveling result, TX need to udpate.
+        p->fgTXPerbifInit[p->channel][RANK_0]= FALSE;
+        p->fgTXPerbifInit[p->channel][RANK_1]= FALSE;
+        #endif
+
+        mcSHOW_DBG_MSG3(("WriteLevelingMoveDQSInsteadOfCLK\n"));
+        mcFPRINTF((fp_A60501, "WriteLevelingMoveDQSInsteadOfCLK\n"));
+    }
+    #endif
+
+#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_WRITELEVELING)
+	if(p->femmc_Ready==1)
+	{
+  		wrlevel_dqs_final_delay[0] =p->pSavetimeData->u1WriteLeveling_bypass_Save[p->channel][p->rank][0];
+  		wrlevel_dqs_final_delay[1] =p->pSavetimeData->u1WriteLeveling_bypass_Save[p->channel][p->rank][1];
+
+        ucsample_count = 0xff;
+        KResult = DRAM_OK;
+        vSetCalibrationResult(p, DRAM_CALIBRATION_WRITE_LEVEL, DRAM_OK);
+	}
+    else
+#endif
+    {
+        //write leveling mode initialization
+        //REFCNT_FR_CLK = 0 (0x1dc[23:16]), ADVREFEN = 0 (0x44[30]), (CONF2_REFCNT =0)
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 1, DRAMC_PD_CTRL_MIOCKCTRLOFF);   //MIOCKCTRLOFF=1
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 0, DRAMC_PD_CTRL_PHYCLKDYNGEN);   //PHYCLKDYNGEN=0
+
+        //Make CKE fixed at 1 (Don't enter power down, Put this before issuing MRS): CKEFIXON = 1
+        CKEFixOnOff(p, p->rank, CKE_FIXON, CKE_WRITE_TO_ONE_CHANNEL);
+
+        //PHY RX Setting for Write Leveling
+        //Let IO toO1 path valid, Enable SMT_EN
+        O1PathOnOff(p, 1);
+
+        // enable DDR write leveling mode:  issue MR2[7] to enable write leveling (refer to DEFAULT MR2 value)
+        vSetDramMRWriteLevelingOnOff(p, ENABLE);
+
+        //wait tWLDQSEN (25 nCK / 25ns) after enabling write leveling mode (DDR3 / LPDDDR3)
+        mcDELAY_US(1);
+
+        //Set {R_DQS_B3_G R_DQS_B2_G R_DQS_B1_G R_DQS_B0_G}=1010: 0x13c[4:1] (this depends on sel_ph setting)
+        //Enable Write leveling: 0x13c[0]
+        //vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEVELING), P_Fld(0xa, WRITE_LEVELING_DQSBX_G)|P_Fld(1, WRITE_LEVELING_WRITE_LEVEL_EN));
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 0xa, WRITE_LEV_DQSBX_G);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 1, WRITE_LEV_WRITE_LEVEL_EN);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 1, WRITE_LEV_CBTMASKDQSOE);
+
+        // select DQS
+#if ENABLE_LP3_SW
+        if(p->dram_type == TYPE_LPDDR3)
+        {
+            u4value = 0xf;//select byte 0.1.2.3
+        }
+        else  //LPDDR4
+#endif /* ENABLE_LP3_SW */
+        {
+            u4value = 0x3;//select byte 0.1
+        }
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), u4value, WRITE_LEV_DQS_SEL);
+
+        // wait tWLMRD (40 nCL / 40 ns) before DQS pulse (DDR3 / LPDDR3)
+        mcDELAY_US(1);
+
+        //Proceed write leveling...
+        //Initilize sw parameters
+        for (ii=0; ii < (S32)(p->data_width/DQS_BIT_NUMBER); ii++)
+        {
+            ucsample_status[ii] = 0;
+            wrlevel_dqs_final_delay[ii] = 0;
+        }
+
+        //used for WL done status
+        // each bit of sample_cnt represents one-byte WL status
+        // 1: done or N/A. 0: NOK
+        if ((p->data_width == DATA_WIDTH_16BIT))
+        {
+            ucsample_count = 0xfc;
+        }
+        else
+        {
+            ucsample_count = 0xf0;
+        }
+
+        mcSHOW_DBG_MSG(("[Write Leveling]\n"));
+        mcSHOW_DBG_MSG(("delay  byte0  byte1  byte2  byte3\n\n"));
+
+        mcFPRINTF((fp_A60501, "\n\tdramc_write_leveling_swcal\n"));
+        mcFPRINTF((fp_A60501, "delay  byte0  byte1  byte2  byte3\n\n"));
+
+        // Set DQS output delay to 0
+        if(u1IsLP4Family(p->dram_type))
+        {
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), 0, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);  //rank0, byte0, DQS delay
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), 0, SHU1_R0_B1_DQ7_RK0_ARPI_PBYTE_B1);  //rank0, byte1, DQS delay
+        }
+#if ENABLE_LP3_SW
+        else
+        {
+            vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), 0, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+            vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), 0, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+            vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), 0, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+            vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), 0, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+        }
+#endif
+        #if WRITE_LEVELING_MOVE_DQS_INSTEAD_OF_CLK
+        i4PIBegin = WRITE_LEVELING_MOVD_DQS*32 -MAX_CLK_PI_DELAY-1;
+        #endif
+
+        #if (fcFOR_CHIP_ID == fcLaurel)
+        i4PIBegin += 10;  // for save time
+        #endif
+
+        i4PIEnd = 63; // SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0: 6 bits
+
+        #if DQS_DUTY_MEASURE_WITH_WRITE_LEVELING
+        if(p->channel==CHANNEL_A && p->frequency == u2DFSGetHighestFreq(p))
+            u1PIStep =2;
+        else
+        #endif
+            u1PIStep =1;
+
+        #if  WRITE_LEVELING_MOVE_DQS_INSTEAD_OF_CLK
+        for (ii=i4PIBegin; ii<i4PIEnd; ii+=u1PIStep)
+        #else
+        for (ii=(-MAX_CLK_PI_DELAY); ii<=MAX_TX_DQSDLY_TAPS; ii++)
+        #endif
+        {
+            #if DQS_DUTY_MEASURE_WITH_WRITE_LEVELING
+            if(u1PIStep==2)
+                mcDELAY_MS(10000);
+            #endif
+
+            if (ii <= 0)
+            {
+                // Adjust Clk output delay.
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), -ii, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK);
+            }
+            else
+            {
+                // Adjust DQS output delay.
+                // PI (TX DQ/DQS adjust at the same time)
+                if(u1IsLP4Family(p->dram_type))
+                {
+                    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ii, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);  //rank0, byte0, DQS delay
+                    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), ii, SHU1_R0_B1_DQ7_RK0_ARPI_PBYTE_B1);  //rank0, byte1, DQS delay
+                }
+#if ENABLE_LP3_SW
+                else
+                {
+                    vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ii, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+                    vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ii, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+                    vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ii, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+                    vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ii, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+                }
+#endif
+            }
+
+            //Trigger DQS pulse, R_DQS_WLEV: 0x13c[8] from 1 to 0
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 1, WRITE_LEV_DQS_WLEV);
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 0, WRITE_LEV_DQS_WLEV);
+
+            #if DQS_DUTY_MEASURE_WITH_WRITE_LEVELING
+            if(u1PIStep==2)
+            {
+                for(u2TriggerCnt=0; u2TriggerCnt<10000; u2TriggerCnt++)
+                {
+                    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 1, WRITE_LEV_DQS_WLEV);
+                    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 0, WRITE_LEV_DQS_WLEV);
+                }
+            }
+            #endif
+
+            //wait tWLO (7.5ns / 20ns) before output (DDR3 / LPDDR3)
+            mcDELAY_US(1);
+
+            //Read DQ_O1 from register
+            if(u1IsLP4Family(p->dram_type))
+            {
+                u4dq_o1 = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_DQO1));
+            }
+#if ENABLE_LP3_SW
+            else //LPRRR3
+            {
+                // Get DQ value.
+                u4dq_o1 = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_DQO1));
+                //mcSHOW_DBG_MSG2(("DQ_O1: 0x%x\n", u4dq_o1));
+            }
+#endif
+            #ifdef ETT_PRINT_FORMAT
+            mcSHOW_DBG_MSG2(("%d    ", ii));
+            #else
+            mcSHOW_DBG_MSG2(("%2d    ", ii));
+            #endif
+            mcFPRINTF((fp_A60501, "%2d    ", ii));
+
+            //mcSHOW_DBG_MSG(("0x%x    ", u4dq_o1));
+            //mcFPRINTF((fp_A60501, "0x%x    ", u4dq_o1));
+
+            for (byte_i = 0; byte_i < (p->data_width/DQS_BIT_NUMBER);  byte_i++)
+            {
+                ucdq_o1_perbyte[byte_i] = (U8)((u4dq_o1>>ucdq_o1_index[byte_i]) & 0xff);         // ==> TOBEREVIEW
+
+                mcSHOW_DBG_MSG2(("%x   ", ucdq_o1_perbyte[byte_i]));
+                mcFPRINTF((fp_A60501, "%x    ", ucdq_o1_perbyte[byte_i]));
+
+                if ((ucsample_status[byte_i]==0) && (ucdq_o1_perbyte[byte_i]==0))
+                {
+                    ucsample_status[byte_i] = 1;
+                }
+                else if ((ucsample_status[byte_i]>=1) && (ucdq_o1_perbyte[byte_i] ==0))
+                {
+                    ucsample_status[byte_i] = 1;
+                }
+                else if ((ucsample_status[byte_i]>=1) && (ucdq_o1_perbyte[byte_i] !=0))
+                {
+                    ucsample_status[byte_i]++;
+                }
+                //mcSHOW_DBG_MSG(("(%x) ", ucsample_status[byte_i]));
+
+                if((ucsample_count &(0x01 << byte_i))==0)// result not found of byte yet
+                {
+                    #if  WRITE_LEVELING_MOVE_DQS_INSTEAD_OF_CLK
+                    if((ucsample_status[byte_i] ==8) || ((ii==i4PIEnd-1) && (ucsample_status[byte_i] >1)))
+                    #else
+                    if((ucsample_status[byte_i] ==8) || ((ii==MAX_TX_DQSDLY_TAPS)&& (ucsample_status[byte_i] >1)))
+                    #endif
+                    {
+                        wrlevel_dqs_final_delay[byte_i] = ii -ucsample_status[byte_i] +2;
+                        ucsample_count |= (0x01 << byte_i);
+                        //mcSHOW_DBG_MSG(("(record %d) ", wrlevel_dqs_final_delay[byte_i]));
+                    }
+                }
+            }
+            mcSHOW_DBG_MSG2(("\n"));
+            mcFPRINTF((fp_A60501, "\n"));
+
+            #if !DQS_DUTY_MEASURE_WITH_WRITE_LEVELING
+            if (ucsample_count == 0xff)
+                break;  // all byte found, early break.
+            #endif
+        }
+    }
+
+    if (ucsample_count == 0xff)
+    {
+        // all bytes are done
+        fgwrlevel_done= 1;
+        KResult = DRAM_OK;
+    }
+    else
+    {
+        KResult = DRAM_FAIL;
+    }
+
+    vSetCalibrationResult(p, DRAM_CALIBRATION_WRITE_LEVEL, KResult);
+
+    mcSHOW_DBG_MSG2(("pass bytecount = 0x%x (0xff: all bytes pass) \n\n", ucsample_count));
+    mcFPRINTF((fp_A60501, "pass bytecount = 0x%x (0xff: all bytes pass)\n\n", ucsample_count));
+#if 0
+    U32 u4value1=0
+    S32 ClockDelayMax = MAX_TX_DQSDLY_TAPS;
+
+    for (byte_i = 0; byte_i < (p->data_width/DQS_BIT_NUMBER);  byte_i++)
+    {
+        if (ClockDelayMax > wrlevel_dqs_final_delay[byte_i])
+        {
+            ClockDelayMax = wrlevel_dqs_final_delay[byte_i];
+        }
+    }
+
+    if (ClockDelayMax > 0)
+    {
+        ClockDelayMax = 0;
+    }
+    else
+    {
+        ClockDelayMax = -ClockDelayMax;
+    }
+
+    vPrintCalibrationBasicInfo(p);
+
+    mcSHOW_DBG_MSG(("WL Clk dly = %d, CA clk dly = %d\n", ClockDelayMax, CATrain_ClkDelay[p->channel][p->rank]));
+    mcFPRINTF((fp_A60501, "WL Clk dly = %d, CA clk dly = %d\n", ClockDelayMax, CATrain_ClkDelay[p->channel][p->rank]));
+
+    // Adjust Clk & CA if needed
+    if (CATrain_ClkDelay[p->channel][p->rank] < ClockDelayMax)
+    {
+        S32 Diff = ClockDelayMax - CATrain_ClkDelay[p->channel][p->rank];
+        mcSHOW_DBG_MSG(("CA adjust %d taps\n", Diff));
+        // Write shift value into CA output delay.
+        if(u1IsLP4Family(p->dram_type))
+        {
+            u4value = CATrain_CmdDelay[p->channel][p->rank];
+            u4value += Diff;
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), u4value, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD);
+        }
+#if ENABLE_LP3_SW
+        else
+        {
+#if (fcFOR_PINMUX == fcLaurel)
+            for(ii=p->rank; ii<RANK_MAX; ii++)
+            {
+                vSetRank(p,ii);
+                u4value = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD);
+                u4value += Diff;
+                //default value in init() is 0x10 , vIO32Write4B(mcSET_DDRPHY_REG_ADDR_CHC(0x0458), 0x00100000);   // Partickl
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), u4value, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD);
+
+                u4value1 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+                u4value1 += Diff;
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), u4value1, SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+            }
+            vSetRank(p, backup_rank);
+#endif
+        }
+#endif
+        mcSHOW_DBG_MSG(("Update CA PI Dly Macro0 = %d, Macro1 = %d\n", u4value, u4value1));
+        mcFPRINTF((fp_A60501, "Update CA PI Dly Macro0 = %d, Macro1 = %d\n", u4value, u4value1));
+
+        // Write shift value into CS output delay.
+        if(u1IsLP4Family(p->dram_type))
+        {
+            //u4value = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_ARPI_CMD), ARPI_CMD_DA_ARPI_CS);
+            u4value = CATrain_CsDelay[p->channel][p->rank];
+            u4value += Diff;
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), u4value, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS);
+            mcSHOW_DBG_MSG(("Update CS Dly = %d\n", u4value));
+            mcFPRINTF((fp_A60501, "Update CS Dly = %d\n", u4value));
+        }
+#if ENABLE_LP3_SW
+        else
+        {
+#if (fcFOR_PINMUX == fcLaurel)
+            for(ii=p->rank; ii<RANK_MAX; ii++)
+            {
+                vSetRank(p,ii);
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), ClockDelayMax, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS);
+                mcSHOW_DBG_MSG(("Update CS Dly = %d\n", ClockDelayMax));
+                mcFPRINTF((fp_A60501, "Update CS Dly = %d\n", ClockDelayMax));
+            }
+            vSetRank(p, backup_rank);
+#endif
+        }
+#endif
+    }
+    else
+    {
+        mcSHOW_DBG_MSG(("No need to update CA/CS dly (CLK dly smaller than CA training)\n"));
+        ClockDelayMax = CATrain_ClkDelay[p->channel][p->rank];
+    }
+
+    //DramcEnterSelfRefresh(p, 1);  //enter self refresh mode when changing CLK
+    // Write max center value into Clk output delay.
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), ClockDelayMax, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK);
+    //DramcEnterSelfRefresh(p, 0);
+
+    mcFPRINTF((fp_A60501, "Final Clk output dly = %d\n", ClockDelayMax));
+    mcSHOW_DBG_MSG(("Final Clk output dly = %d\n", ClockDelayMax));
+    //mcSHOW_DBG_MSG(("After adjustment...\n"));
+#endif
+    for (byte_i = 0; byte_i < (p->data_width/DQS_BIT_NUMBER);  byte_i++)
+    {
+    #if 0
+        wrlevel_dqs_final_delay[byte_i] += (ClockDelayMax);
+    #endif
+        mcSHOW_DBG_MSG(("DQS%d dly: %d\n", byte_i, wrlevel_dqs_final_delay[byte_i]));
+        mcFPRINTF((fp_A60501, "DQS%d dly: %d\n", byte_i, wrlevel_dqs_final_delay[byte_i]));
+
+#ifdef FOR_HQA_TEST_USED
+        HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT1, "WriteLeveling_DQS", byte_i, wrlevel_dqs_final_delay[byte_i], NULL);
+#endif
+    }
+
+	#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+	if(p->femmc_Ready==0)
+	{
+   		p->pSavetimeData->u1WriteLeveling_bypass_Save[p->channel][p->rank][0]=wrlevel_dqs_final_delay[0];
+   		p->pSavetimeData->u1WriteLeveling_bypass_Save[p->channel][p->rank][1]=wrlevel_dqs_final_delay[1];
+	}
+	#endif
+    // write leveling done, mode settings recovery if necessary
+    // recover mode registers : issue MR2[7] to disable write leveling (refer to DEFAULT MR2 value)
+    vSetDramMRWriteLevelingOnOff(p, DISABLE);
+
+    // restore registers.
+    DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+    //Disable DQ_O1, SELO1ASO=0 for power saving
+    O1PathOnOff(p, 0);
+    if(u1IsLP4Family(p->dram_type))
+    {
+        #if REG_SHUFFLE_REG_CHECK
+        ShuffleRegCheck =1;
+        #endif
+
+        // set to best values for  DQS
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dqs_final_delay[0], SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), wrlevel_dqs_final_delay[1], SHU1_R0_B1_DQ7_RK0_ARPI_PBYTE_B1);
+
+        for(byte_i = 0; byte_i < (p->data_width/DQS_BIT_NUMBER);  byte_i++)
+        {
+            wrlevel_dq_delay[byte_i] = wrlevel_dqs_final_delay[byte_i] + 0x10;
+            if(wrlevel_dq_delay[byte_i] >= 0x40) //ARPI_DQ_B* is 6 bits, max 0x40
+            {
+                wrlevel_dq_delay[byte_i] -= 0x40;
+                MoveDramC_TX_DQ(p, byte_i, 2);
+                MoveDramC_TX_DQ_OEN(p, byte_i, 2);
+            }
+        }
+
+    #ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+        gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag = u1GUMP_INIT_RG_LOG_TO_DE_bak;
+    #endif
+
+        // set to best values for  DQM, DQ
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7),
+                                        P_Fld(wrlevel_dq_delay[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0) |
+                                        P_Fld(wrlevel_dq_delay[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0));
+
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7),
+                                        P_Fld(wrlevel_dq_delay[1], SHU1_R0_B1_DQ7_RK0_ARPI_DQM_B1) |
+                                        P_Fld(wrlevel_dq_delay[1], SHU1_R0_B1_DQ7_RK0_ARPI_DQ_B1));
+
+        #if REG_SHUFFLE_REG_CHECK
+        ShuffleRegCheck =0;
+        #endif
+    }
+#if ENABLE_LP3_SW
+    else //LPDDR3
+    {
+        #if REG_SHUFFLE_REG_CHECK
+        ShuffleRegCheck =1;
+        #endif
+
+        for(byte_i=0; byte_i<(p->data_width/DQS_BIT_NUMBER); byte_i++)
+        {
+            if(wrlevel_dqs_final_delay[byte_i] >= 0x40) //ARPI_PBYTE_B* is 6 bits, max 0x40
+            {
+                wrlevel_dqs_final_delay[byte_i] -= 0x40;
+                MoveDramC_TX_DQS(p, byte_i, 2);
+                MoveDramC_TX_DQS_OEN(p, byte_i, 2);
+            }
+            wrlevel_dqs_delay[byte_i] = wrlevel_dqs_final_delay[byte_i];
+        }
+
+#ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+    gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag = u1GUMP_INIT_RG_LOG_TO_DE_bak;
+#endif
+
+#if 1
+        /* p->rank = RANK_0, save to Reg Rank0 and Rank1, p->rank = RANK_1, save to Reg Rank1 */
+        for(ii=p->rank; ii<RANK_MAX; ii++)
+        {
+            vSetRank(p,ii);
+
+            // set to best values for  DQS
+            vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dqs_delay[0], SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+            vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dqs_delay[1], SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+            vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dqs_delay[2], SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+            vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dqs_delay[3], SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+        }
+        vSetRank(p,backup_rank);
+#else
+        // set to best values for  DQS
+        vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dqs_delay[0], SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+        vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dqs_delay[1], SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+        vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dqs_delay[2], SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+        vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dqs_delay[3], SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+#endif
+
+
+        #if 1//EVEREST_CHANGE_OF_PHY_PBYTE
+        //Evereest new change, ARPI_DQ_RK0_ARPI_PBYTE_B* only move DQS, not including of DQM&DQ anymore.
+        //Add move DQ, DQ= DQS+0x10, after cali.  take care diff. UI. with DQS
+        for(byte_i=0; byte_i<(p->data_width/DQS_BIT_NUMBER); byte_i++)
+        {
+            wrlevel_dq_delay[byte_i] = wrlevel_dqs_final_delay[byte_i] + 0x10;
+            if(wrlevel_dq_delay[byte_i] >= 0x40) //ARPI_DQ_B* is 6 bits, max 0x40
+            {
+                wrlevel_dq_delay[byte_i] -= 0x40;
+                MoveDramC_TX_DQ(p, byte_i, 2);
+                MoveDramC_TX_DQ_OEN(p, byte_i, 2);
+            }
+        }
+
+#if 1
+        /* p->rank = RANK_0, save to Reg Rank0 and Rank1, p->rank = RANK_1, save to Reg Rank1 */
+        for(ii=p->rank; ii<RANK_MAX; ii++)
+        {
+            vSetRank(p,ii);
+
+            // set to best values for  DQ/DQM/DQ_OEN/DQM_OEN
+            vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+            vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[1], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+            vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[2], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+            vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[3], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+
+            vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+            vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[1], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+            vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[2], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+            vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[3], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+        }
+        vSetRank(p,backup_rank);
+#else
+        // set to best values for  DQ/DQM/DQ_OEN/DQM_OEN
+        vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+        vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[1], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+        vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[2], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+        vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[3], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+
+
+        vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+#if (FOR_DV_SIMULATION_USED!=0)
+        vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[1], SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS);
+        vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[2], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+
+#else
+        vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[1], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+        vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[2], SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS);
+#endif
+        vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[3], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+#endif
+
+        #endif
+
+        #if REG_SHUFFLE_REG_CHECK
+        ShuffleRegCheck =0;
+        #endif
+    }
+#endif
+    //DramcRankSwap(p, RANK_0);
+    //tx_rank_sel is selected by HW
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANK);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANKFIX); //TXRANKFIX should be write after TXRANK
+
+#if REG_ACCESS_PORTING_DGB
+    RegLogEnable =0;
+#endif
+    mcSHOW_DBG_MSG3(("[DramcWriteLeveling] Done\n\n"));
+    mcFPRINTF((fp_A60501, "[DramcWriteLeveling] Done\n\n"));
+
+    return KResult;
+}
+#endif //SIMULATION_WRITE_LEVELING
+
+
+#if SIMULATION_GATING
+//LP3 RODT is not enable, don't need to set the RODT settings.
+//LP4 RODT range is very large(5ns),  no need to adjust with gating position
+//0x860	SHU_ODTCTRL	32	ODT CONTROL REGISTER
+//                         31	31	RODTE	RW	PUBLIC	1'b1
+// 	 	 	 	30	30	RODTE2	RW	PUBLIC	1'b1
+// 	 	 	 	7	4	RODT	RW	PUBLIC	4'bx= DQSINCTL or -1
+#if ENABLE_RODT_TRACKING
+#define GATING_RODT_LATANCY_EN 0  //disable when RODT tracking enable
+#else
+#define GATING_RODT_LATANCY_EN 1  //Need to enable when RODT enable
+#endif
+
+#define GATING_PATTERN_NUM_LP4 0x23
+#define GATING_GOLDEND_DQSCNT_LP4 0x4646
+
+#define GATING_PATTERN_NUM_LP3 0x46
+#define GATING_GOLDEND_DQSCNT_LP3 0x2323
+
+#define GATING_TXDLY_CHNAGE  1 //Gating txdly chcange & RANKINCTL setting
+
+#if SW_CHANGE_FOR_SIMULATION
+#define ucRX_DLY_DQSIENSTB_LOOP 32
+#define ucRX_DQS_CTL_LOOP 8
+#endif
+
+#if GATING_ADJUST_TXDLY_FOR_TRACKING
+U8 u1TXDLY_Cal_min =0xff, u1TXDLY_Cal_max=0;
+U8 ucbest_coarse_tune2T_backup[RANK_MAX][DQS_NUMBER];
+U8 ucbest_coarse_tune0p5T_backup[RANK_MAX][DQS_NUMBER];
+U8 ucbest_coarse_tune2T_P1_backup[RANK_MAX][DQS_NUMBER];
+U8 ucbest_coarse_tune0p5T_P1_backup[RANK_MAX][DQS_NUMBER];
+#endif
+
+// Use gating old burst mode to find gating window boundary
+// Set the begining of window as new burst mode gating window center.
+#define LP4_GATING_OLD_BURST_MODE 1
+#define LP4_GATING_LEAD_LAG_FLAG_JUDGE LP4_GATING_OLD_BURST_MODE
+
+/* Current function is for LP4 only
+ * u1Mode decides old or new length modes (7UI, 8UI) should be used
+ * 0: OLD 8UI mode (not extend 2T RD preamble)
+ * 1: NEW 7UI mode (extend 2T RD preamble) (DQS_GW_7UI defined)
+ *    NEW 8UI mode (extend 2T RD preamble) (DQS_GW_7UI not defined)
+ */
+void DramcGatingMode(DRAMC_CTX_T *p, U8 u1Mode)
+{
+    // mode 0:  old burst mode
+    // mode 1:  7UI or 8UI gating window length mode (depends on if DQS_GW_7UI is defined)
+#if (fcFOR_CHIP_ID == fcLaurel)
+    /* There are currently 2 ways to set GatingMode (sets different registers)
+     * 1. Alaska
+     * 2. Bianco, Whitney, Kibo+(Olympus)
+     */
+    U8 u1VrefSel = 0, u1BurstE2 = 0;
+
+    //mcSHOW_DBG_MSG3(("[GatingMode] "));
+    if (u1Mode == 0) /* old mode */
+    {
+        u1VrefSel = 0;
+        u1BurstE2 = 0;
+        //mcSHOW_DBG_MSG3(("old 8UI\n"));
+    }
+    else /* 7UI or 8UI gating window length mode */
+    {
+#ifdef DQS_GW_7UI
+        u1VrefSel = 2;
+        u1BurstE2 = 1;
+        //mcSHOW_DBG_MSG3(("new 7UI\n"));
+#else
+        u1VrefSel = 1;
+        u1BurstE2 = 0;
+        //mcSHOW_DBG_MSG3(("new 8UI\n"));
+#endif
+    }
+
+    /* BIAS_VREF_SEL is used as switch for old, new burst modes */
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ6), u1VrefSel, B0_DQ6_RG_RX_ARDQ_BIAS_VREF_SEL_B0);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ6), u1VrefSel, B1_DQ6_RG_RX_ARDQ_BIAS_VREF_SEL_B1);
+#endif /* fcFOR_CHIP_ID */
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ9), 1, B0_DQ9_RG_RX_ARDQS0_DQSIENMODE_B0);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ9), 1, B1_DQ9_RG_RX_ARDQS0_DQSIENMODE_B1);
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_STBCAL1), u1BurstE2, STBCAL1_DQSIEN_7UI_EN);
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_STBCAL), 1, STBCAL_DQSIENMODE_SELPH);
+
+    /* Perform reset (makes sure PHY's behavior works as the above setting) */
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ9), P_Fld(0, B0_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B0) |P_Fld(0, B0_DQ9_RG_RX_ARDQ_STBEN_RESETB_B0));
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ9), P_Fld(0, B1_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B1) |P_Fld(0, B1_DQ9_RG_RX_ARDQ_STBEN_RESETB_B1));
+    mcDELAY_US(1);//delay 10ns
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ9), P_Fld(1, B1_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B1) |P_Fld(1, B1_DQ9_RG_RX_ARDQ_STBEN_RESETB_B1));
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ9), P_Fld(1, B0_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B0) |P_Fld(1, B0_DQ9_RG_RX_ARDQ_STBEN_RESETB_B0));
+    //DramPhyReset(p);
+#if __ETT__
+    if (u1IsLP4Family(p->dram_type) == FALSE)
+    {  // GatingMode() is designed for LP4 only (only resets current channel PHY)
+        mcSHOW_ERR_MSG(("GatingMode err!(LP4 only)\n"));
+    }
+#endif
+}
+
+U8 u1GetGatingStartPos(DRAMC_CTX_T *p)
+{
+    const U8 au1MR2MappingToRL[2][8] = {{6, 10, 14, 20, 24, 28, 32, 36},   /*normal mode*/
+                                        {6, 10, 16, 22, 26, 32, 36, 40}};  /*byte mode*/
+
+    U8 u1MR0_LatencyMode;
+    U8 u1MR2RLValue = u1MR02Value[p->dram_fsp] & 0x7; /*MR2 Op[2:0]*/
+    U8 u1RX_Path_delay_UI, u1RealRL,u1StartUI, u1ExtraMCKfor1_4mode;
+    U8 u1MCK2CK_UI, u1ReadDQSINCTL, u1DQSINCTL_UI;
+    U8 u4TDQSCK_UI_min = 1500 * p->frequency *2/ 1000000;
+ /* 1500ps = ? UI */
+
+    if(gu2MR0_Value[p->rank] == 0xffff)  /*MR0 is not ready*/
+    {
+        u1MR0_LatencyMode = CBT_NORMAL_MODE;
+    }
+    else
+    {
+        u1MR0_LatencyMode = (gu2MR0_Value[p->rank]>>1) & 0x1; /*MR0 OP[1],  0:normal mode,  1:byte mode*/
+    }
+
+    u1RealRL = au1MR2MappingToRL[u1MR0_LatencyMode][u1MR2RLValue];
+
+    if(0) /*(vGet_Div_Mode(p) == DIV4_MODE)*/
+    {
+        u1MCK2CK_UI = 4;
+        u1ExtraMCKfor1_4mode = 1;
+    }
+    else
+    {
+        u1MCK2CK_UI = 8;
+        u1ExtraMCKfor1_4mode = 0;
+    }
+
+    /* RX_Path_delay_UI = RL*2 + tDQSCK_UI<1500~3500ps> - PHY_interanl<skip 30ps> - GatingAheadDQS<2UI> + if(1:4 mod)+1MCK */
+    u1RX_Path_delay_UI = (u1RealRL<<1) + u4TDQSCK_UI_min - 2 + (u1MCK2CK_UI*u1ExtraMCKfor1_4mode);
+
+    u1ReadDQSINCTL = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_DQSCTL), SHURK0_DQSCTL_DQSINCTL);
+    u1DQSINCTL_UI = u1ReadDQSINCTL * u1MCK2CK_UI;
+
+    if((u1RX_Path_delay_UI-3) >= u1DQSINCTL_UI)
+        u1StartUI = (u1RX_Path_delay_UI -3) - u1DQSINCTL_UI; /* gating start calibration position = gating min position(1500ns) -3UI */
+    else
+    {
+        u1StartUI =0;
+        mcSHOW_ERR_MSG(("GatingStartPos err! Need to fine-tune default DQSINCTL value.\n(RX_Path_delay_UI %d) < DQSINCTL_UI %d)\n", u1RX_Path_delay_UI, u1DQSINCTL_UI));
+        #if __ETT__
+        while(1);
+        #endif
+    }
+
+    mcSHOW_DBG_MSG(("[GatingStartPos] MR0_LatencyMode %d, u1RealRL %d , u4TDQSCK_UI_min %d, 1:4ExtraMCK %d\n", u1MR0_LatencyMode, u1RealRL, u4TDQSCK_UI_min, u1ExtraMCKfor1_4mode));
+    mcSHOW_DBG_MSG(("RX_Path_delay_UI(%d) -3 - DQSINCTL_UI(%d) = u1StartUI(%d)\n", u1RX_Path_delay_UI, u1DQSINCTL_UI, u1StartUI));
+
+    return u1StartUI;
+}
+
+
+DRAM_STATUS_T DramcRxdqsGatingCal(DRAMC_CTX_T *p)
+{
+        #if !SW_CHANGE_FOR_SIMULATION
+        U8 ucRX_DLY_DQSIENSTB_LOOP,ucRX_DQS_CTL_LOOP;
+        #endif
+        U32 u4value, u4all_result_R=0, u4all_result_F=0, u4err_value;
+        U8 ucpass_begin[DQS_NUMBER] = {0}, ucpass_count[DQS_NUMBER] = {0}, ucCurrentPass;
+        U8 ucmin_coarse_tune2T[DQS_NUMBER] = {0}, ucmin_coarse_tune0p5T[DQS_NUMBER] = {0}, ucmin_fine_tune[DQS_NUMBER] = {0};
+        U8 ucpass_count_1[DQS_NUMBER] = {0}, ucmin_coarse_tune2T_1[DQS_NUMBER] = {0}, ucmin_coarse_tune0p5T_1[DQS_NUMBER] = {0}, ucmin_fine_tune_1[DQS_NUMBER] = {0};
+        U8 dqs_i=0,  ucdly_coarse_large, ucdly_coarse_0p5T, ucdly_fine_xT, ucDQS_GW_FINE_STEP;
+        U8 ucdqs_result_R, ucdqs_result_F, uctmp_offset, uctmp_value;
+        U8 ucbest_fine_tune[DQS_NUMBER] = {0}, ucbest_coarse_tune0p5T[DQS_NUMBER] = {0}, ucbest_coarse_tune2T[DQS_NUMBER] = {0};
+        U8 ucbest_fine_tune_P1[DQS_NUMBER] = {0}, ucbest_coarse_tune0p5T_P1[DQS_NUMBER] = {0}, ucbest_coarse_tune2T_P1[DQS_NUMBER] = {0};
+
+        U8 ucFreqDiv;
+        U8 ucdly_coarse_large_P1, ucdly_coarse_0p5T_P1;
+
+    #if GATING_ADJUST_TXDLY_FOR_TRACKING
+        U8 u1TX_dly_DQSgated = 0;
+    #endif
+
+    #if GATING_RODT_LATANCY_EN
+        U8 ucdly_coarse_large_RODT, ucdly_coarse_0p5T_RODT;
+        U8 ucdly_coarse_large_RODT_P1 = 0, ucdly_coarse_0p5T_RODT_P1 = 0;
+        U8 ucbest_coarse_large_RODT[DQS_NUMBER] = {0}, ucbest_coarse_0p5T_RODT[DQS_NUMBER] = {0};
+        U8 ucbest_coarse_large_RODT_P1[DQS_NUMBER] = {0}, ucbest_coarse_0p5T_RODT_P1[DQS_NUMBER] = {0};
+    #endif
+        U8 ucCoarseTune=0, ucCoarseStart=8, ucCoarseEnd=8;
+#if ENABLE_LP3_SW
+        U32 LP3_DataPerByte[DQS_NUMBER] = {0};
+#endif
+        U32 u4DebugCnt[DQS_NUMBER] = {0};
+        U16 u2DebugCntPerByte;
+
+        #if LP4_GATING_LEAD_LAG_FLAG_JUDGE
+        U8 u1DQS_lead[DQS_NUMBER] = {0}, u1DQS_lag[DQS_NUMBER] = {0}, u1DQS_high[DQS_NUMBER] = {0}, u1DQS_transition[DQS_NUMBER] = {0}, u1DQSGatingFound[DQS_NUMBER] = {0};
+        U8 ucdly_coarse_large_leadLag[DQS_NUMBER] = {0}, ucdly_coarse_0p5T_leadLag[DQS_NUMBER] = {0}, ucdly_fine_tune_leadLag[DQS_NUMBER] = {0};
+        #endif
+
+        U8 u1PassByteCount=0;
+
+       #if 0///SUPPORT_SAVE_TIME_FOR_CALIBRATION
+	  U8 ucpass_offset=0;
+         U8 ucpass_count_0_temp=0;
+         U8 ucpass_count_1_temp=0;
+         U8 ucCoarseTune_offset=0;
+         U8 minpasscount=0;
+       #endif
+
+        // error handling
+        if (!p)
+        {
+            mcSHOW_ERR_MSG(("context NULL\n"));
+            return DRAM_FAIL;
+        }
+
+        U32 u4RegBackupAddress[] =
+        {
+            (DRAMC_REG_ADDR(DRAMC_REG_STBCAL)),
+            (DRAMC_REG_ADDR(DRAMC_REG_STBCAL1)),
+            (DRAMC_REG_ADDR(DRAMC_REG_DDRCONF0)),
+            (DRAMC_REG_ADDR(DRAMC_REG_SPCMD)),
+            (DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0)),
+        #if LP4_GATING_OLD_BURST_MODE
+            (DRAMC_REG_ADDR(DDRPHY_B0_DQ6)),
+            (DRAMC_REG_ADDR(DDRPHY_B1_DQ6)),
+        #else
+            (DRAMC_REG_ADDR(DDRPHY_B0_DQ7)),
+            (DRAMC_REG_ADDR(DDRPHY_B1_DQ7)),
+        #endif
+        };
+
+
+        //Register backup
+        DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+        //Justin: DQ_REV_B*[5] =1, select RX gating mode to prevent 0.5T fake gating window behind real window.
+        if(u1IsLP4Family(p->dram_type))
+        {
+            #if MRW_CHECK_ONLY
+            mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
+            #endif
+            /* LP4: Disable(set to 0) "RX DQS ISI pulse CG function" during gating window calibration (must set to 1 when done) */
+            RxDQSIsiPulseCG(p, DISABLE);
+
+            #if LP4_GATING_OLD_BURST_MODE
+            #if !LP4_GATING_LEAD_LAG_FLAG_JUDGE
+            DramcGatingMode(p, 0);
+            #endif
+            u1MR01Value[p->dram_fsp] |= 0x80;
+            DramcModeRegWriteByRank(p, p->rank, 1, u1MR01Value[p->dram_fsp]);
+            #else
+             vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ7), P_Fld( 1, B0_DQ7_RG_TX_ARDQS_PULL_UP_B0) | P_Fld( 1, B0_DQ7_RG_TX_ARDQSB_PULL_DN_B0));
+             vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ7), P_Fld( 1, B1_DQ7_RG_TX_ARDQS0_PULL_UP_B1) | P_Fld( 1, B1_DQ7_RG_TX_ARDQS0B_PULL_DN_B1));
+            #endif
+        }
+        #if 0 // LP3: Since it is always set to 1 (should be set during initial register settings, comment out here to save code size
+        else
+        {
+            /* LP3: Always enable(set to 1) "RX DQS ISI pulse CG function" */
+            RxDQSIsiPulseCG(p, ENABLE);
+        }
+        #endif
+
+         //Disable perbank refresh, use all bank refresh, currently DUT problem
+         vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0),  0, REFCTRL0_PBREFEN);
+
+        // Disable HW gating first, 0x1c0[31], need to disable both UI and PI tracking or the gating delay reg won't be valid.
+        DramcHWGatingOnOff(p, 0);
+
+        //If DQS ring counter is different as our expectation, error flag is asserted and the status is in ddrphycfg 0xFC0 ~ 0xFCC
+        //Enable this function by R_DMSTBENCMPEN=1 (0x348[18])
+        //Set R_DMSTBCNT_LATCH_EN=1, 0x348[11]
+        //Set R_DM4TO1MODE=0, 0x54[11]
+        //Clear error flag by ddrphycfg 0x5c0[1] R_DMPHYRST
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_STBCAL1), 1, STBCAL1_STBENCMPEN);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_STBCAL1), 1, STBCAL1_STBCNT_LATCH_EN);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DDRCONF0), 0, DDRCONF0_DM4TO1MODE);
+
+        //enable &reset DQS counter
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_DQSGCNTEN);
+        mcDELAY_US(4);//wait 1 auto refresh after DQS Counter enable
+
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_DQSGCNTRST);
+        mcDELAY_US(1);//delay 2T
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_DQSGCNTRST);
+
+        if(u1IsLP4Family(p->dram_type))
+        {
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), u1GetRank(p), MISC_CTRL1_R_DMSTBENCMP_RK_OPT);
+            DramcEngine2Init(p, 0x55000000, 0xaa000000 |GATING_PATTERN_NUM_LP4, TEST_AUDIO_PATTERN, 0);
+        }
+#if ENABLE_LP3_SW
+        else
+        {
+            vIO32WriteFldAlign_All(DDRPHY_MISC_CTRL1, u1GetRank(p), MISC_CTRL1_R_DMSTBENCMP_RK_OPT);
+            DramcEngine2Init(p, 0x55000000, 0xaa000000 |GATING_PATTERN_NUM_LP3, TEST_AUDIO_PATTERN, 0);
+        }
+#endif
+
+        #if 0 // Array initialization are now performed during declaration
+        //Initialize variables
+        for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+        {
+            ucpass_begin[dqs_i] = 0;
+            ucpass_count[dqs_i] = 0;
+            #if LP4_GATING_LEAD_LAG_FLAG_JUDGE
+            u1DQS_lead[dqs_i] = 0;
+            u1DQS_lag[dqs_i]   = 0;
+            u1DQS_high[dqs_i] = 0;
+            u1DQS_transition[dqs_i] =0;
+
+            ucdly_coarse_large_leadLag[dqs_i] = 0;
+            ucdly_coarse_0p5T_leadLag[dqs_i] = 0;
+            ucdly_fine_tune_leadLag[dqs_i] = 0;
+            #endif
+        }
+        #endif
+        #if !SW_CHANGE_FOR_SIMULATION
+        ucRX_DLY_DQSIENSTB_LOOP= 32;// PI fine tune 0->31
+        ucRX_DQS_CTL_LOOP = 8; // Since Everest, no matter LP3 or LP4. ucRX_DQS_CTL_LOOP is 8.
+        #endif
+
+        #ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+        U8 u1GUMP_INIT_RG_LOG_TO_DE_bak = gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag;
+        gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag=0;
+        #endif
+
+        mcSHOW_DBG_MSG2(("[Gating]\n"));
+        vPrintCalibrationBasicInfo(p);
+
+        if(u1IsLP4Family(p->dram_type))
+        {
+            ucFreqDiv= 4;
+            ucDQS_GW_FINE_STEP = DQS_GW_FINE_STEP;
+
+            /* ucCoarseStart
+             * 1. Depends on current freq's DQSINCTL setting
+             * 2. Preserves ~4UI before actual DQS delay value
+             */
+
+		ucCoarseStart = u1GetGatingStartPos(p);
+
+#if SPECIAL_WORKAROUND_FOR_LP4
+            //for Biwin/LongSys DRAM special workaround
+            if (p->dram_type == TYPE_LPDDR4)
+            {
+                ucCoarseStart -= 8;
+                ucCoarseEnd = ucCoarseStart + 28; // for Hynix LP4
+            }
+            else
+#endif
+            ucCoarseEnd = ucCoarseStart + 12;
+
+            if (Get_MDL_Used_Flag()==GET_MDL_USED)
+                ucCoarseEnd+=8; // extend gating calibration range if wrong byte/normal setting
+        }
+#if ENABLE_LP3_SW
+        else //LPDDR3
+        {
+            ucFreqDiv= 2;
+            ucDQS_GW_FINE_STEP = DQS_GW_FINE_STEP;
+
+            if(p->frequency >= 933)     //1600
+                ucCoarseStart = 8;
+            else if(p->frequency >= 800)     //1600
+                ucCoarseStart = 8;
+            else if(p->frequency >= 600)  //1333, 1200
+                ucCoarseStart = 8;
+            else //if(p->frequency >= 533)  //933
+                ucCoarseStart = 6;
+
+            #if 0//FOR_DV_SIMULATION_USED
+                    if(ucCoarseStart >=5)
+                        ucCoarseStart -=5;
+                    else
+                        ucCoarseStart=0;
+            #endif
+
+            ucCoarseEnd = ucCoarseStart+12;
+        }
+#endif
+
+    #if GATING_RODT_LATANCY_EN  //LP3 RODT is not enable, don't need to set the RODT settings.
+        // Fix build warning, initialize variables.
+        ucdly_coarse_large_RODT = 0;
+        ucdly_coarse_0p5T_RODT = 0;
+
+        if (u1IsLP4Family(p->dram_type))
+        {
+            ucdly_coarse_large_RODT_P1 = 4;
+            ucdly_coarse_0p5T_RODT_P1 = 4;
+        }
+#if ENABLE_LP3_SW
+        else
+        {
+            ucdly_coarse_large_RODT_P1 = 2;
+            ucdly_coarse_0p5T_RODT_P1 = 2;
+        }
+#endif /* ENABLE_LP3_SW */
+
+        // 1.   DQSG latency =
+        // (1)   R_DMR*DQSINCTL[3:0] (MCK) +
+        // (2)   selph_TX_DLY[2:0] (MCK) +
+        // (3)   selph_dly[2:0] (UI)
+
+        // 2.   RODT latency =
+        // (1)   R_DMTRODT[3:0] (MCK) +
+        // (2)   selph_TX_DLY[2:0] (MCK) +
+        // (3)   selph_dly[2:0] (UI)
+
+        #if 0
+        if(u1IsLP4Family(p->dram_type))
+        {
+            //R_DMTRODT[3:0] (MCK)  = R_DMR*DQSINCTL[3:0] (MCK)
+            //if(p->rank == RANK_0)
+            {
+                u4value = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_DQSCTL), SHURK0_DQSCTL_DQSINCTL);
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_ODTCTRL), u4value, SHU_ODTCTRL_RODT);
+            }
+            #if 0 //R1DQSINCTL and R2DQSINCTL is useless on A-PHY. Only need to set RODT once.
+            else //rank1
+            {
+                u4value = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSCTL2), DQSCTL2_R1DQSINCTL);
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DDR2CTL), u4value & 0x7, DDR2CTL_RODT);//R_DMTRODT[2:0]
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DDR2CTL), (u4value >>3), DDR2CTL_RODT3);//R_DMTRODT[3]
+            }
+            #endif
+        }
+    #endif
+    #endif
+
+#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_GatingCal)
+	if(p->femmc_Ready==1)
+    {
+        mcSHOW_DBG_MSG2(("[bypass Gating]\n"));
+	}
+	else
+#endif
+	{
+        for (ucCoarseTune = ucCoarseStart; ucCoarseTune < ucCoarseEnd; ucCoarseTune += DQS_GW_COARSE_STEP)
+        {
+            ucdly_coarse_large      = ucCoarseTune / ucRX_DQS_CTL_LOOP;
+            ucdly_coarse_0p5T      = ucCoarseTune % ucRX_DQS_CTL_LOOP;
+
+            ucdly_coarse_large_P1 = (ucCoarseTune + ucFreqDiv) / ucRX_DQS_CTL_LOOP;
+            ucdly_coarse_0p5T_P1 =(ucCoarseTune + ucFreqDiv) % ucRX_DQS_CTL_LOOP;
+
+        #if GATING_RODT_LATANCY_EN  //LP3 RODT is not enable, don't need to set the RODT settings.
+            if(u1IsLP4Family(p->dram_type))
+            {
+                u4value = (ucdly_coarse_large <<3)+ucdly_coarse_0p5T;
+
+                if(u4value>=11)
+                {
+                    u4value -=11;
+                    ucdly_coarse_large_RODT     = u4value>>3;
+                    ucdly_coarse_0p5T_RODT     = u4value -(ucdly_coarse_large_RODT<<3);
+
+                    u4value = (ucdly_coarse_large <<3)+ucdly_coarse_0p5T -11;
+                    ucdly_coarse_large_RODT_P1     = u4value>>3;
+                    ucdly_coarse_0p5T_RODT_P1     = u4value -(ucdly_coarse_large_RODT_P1<<3);
+                }
+                else
+                {
+                    ucdly_coarse_large_RODT = 0;
+                    ucdly_coarse_0p5T_RODT = 0;
+
+                    ucdly_coarse_large_RODT_P1 = 4;
+                    ucdly_coarse_0p5T_RODT_P1 = 4;
+
+                    mcSHOW_ERR_MSG(("[RxdqsGatingCal] Error: ucdly_coarse_large_RODT[%d] is already 0. RODT cannot be -11 UI\n", dqs_i));
+                    mcFPRINTF((fp_A60501, "[RxdqsGatingCal] Error: ucdly_coarse_large_RODT[%d] is already 0. RODT cannot be -11 UI\n", dqs_i));
+                }
+            }
+        #endif
+
+            //DramPhyCGReset(p, 1);// need to reset when UI update or PI change >=2
+
+            // 4T or 2T coarse tune
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQSG0), \
+                                        P_Fld((U32) ucdly_coarse_large, SHURK0_SELPH_DQSG0_TX_DLY_DQS0_GATED)| \
+                                        P_Fld((U32) ucdly_coarse_large, SHURK0_SELPH_DQSG0_TX_DLY_DQS1_GATED)| \
+                                        P_Fld((U32) ucdly_coarse_large, SHURK0_SELPH_DQSG0_TX_DLY_DQS2_GATED)| \
+                                        P_Fld((U32) ucdly_coarse_large, SHURK0_SELPH_DQSG0_TX_DLY_DQS3_GATED)| \
+                                        P_Fld((U32) ucdly_coarse_large_P1, SHURK0_SELPH_DQSG0_TX_DLY_DQS0_GATED_P1)| \
+                                        P_Fld((U32) ucdly_coarse_large_P1, SHURK0_SELPH_DQSG0_TX_DLY_DQS1_GATED_P1)| \
+                                        P_Fld((U32) ucdly_coarse_large_P1, SHURK0_SELPH_DQSG0_TX_DLY_DQS2_GATED_P1)| \
+                                        P_Fld((U32) ucdly_coarse_large_P1, SHURK0_SELPH_DQSG0_TX_DLY_DQS3_GATED_P1));
+
+            // 0.5T coarse tune
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQSG1), \
+                                        P_Fld((U32) ucdly_coarse_0p5T, SHURK0_SELPH_DQSG1_REG_DLY_DQS0_GATED)| \
+                                        P_Fld((U32) ucdly_coarse_0p5T, SHURK0_SELPH_DQSG1_REG_DLY_DQS1_GATED)| \
+                                        P_Fld((U32) ucdly_coarse_0p5T, SHURK0_SELPH_DQSG1_REG_DLY_DQS2_GATED)| \
+                                        P_Fld((U32) ucdly_coarse_0p5T, SHURK0_SELPH_DQSG1_REG_DLY_DQS3_GATED)| \
+                                        P_Fld((U32) ucdly_coarse_0p5T_P1, SHURK0_SELPH_DQSG1_REG_DLY_DQS0_GATED_P1)| \
+                                        P_Fld((U32) ucdly_coarse_0p5T_P1, SHURK0_SELPH_DQSG1_REG_DLY_DQS1_GATED_P1)| \
+                                        P_Fld((U32) ucdly_coarse_0p5T_P1, SHURK0_SELPH_DQSG1_REG_DLY_DQS2_GATED_P1)| \
+                                        P_Fld((U32) ucdly_coarse_0p5T_P1, SHURK0_SELPH_DQSG1_REG_DLY_DQS3_GATED_P1));
+
+        #if GATING_RODT_LATANCY_EN  //LP3 RODT is not enable, don't need to set the RODT settings.
+            if(u1IsLP4Family(p->dram_type))
+            {
+                vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_ODTEN0), \
+                                            P_Fld((U32) ucdly_coarse_large_RODT, SHURK0_SELPH_ODTEN0_TXDLY_B0_RODTEN)| \
+                                            P_Fld((U32) ucdly_coarse_large_RODT, SHURK0_SELPH_ODTEN0_TXDLY_B1_RODTEN)| \
+                                            P_Fld((U32) ucdly_coarse_large_RODT, SHURK0_SELPH_ODTEN0_TXDLY_B2_RODTEN)| \
+                                            P_Fld((U32) ucdly_coarse_large_RODT, SHURK0_SELPH_ODTEN0_TXDLY_B3_RODTEN)| \
+                                            P_Fld((U32) ucdly_coarse_large_RODT_P1, SHURK0_SELPH_ODTEN0_TXDLY_B0_RODTEN_P1)| \
+                                            P_Fld((U32) ucdly_coarse_large_RODT_P1, SHURK0_SELPH_ODTEN0_TXDLY_B1_RODTEN_P1)| \
+                                            P_Fld((U32) ucdly_coarse_large_RODT_P1, SHURK0_SELPH_ODTEN0_TXDLY_B2_RODTEN_P1)| \
+                                            P_Fld((U32) ucdly_coarse_large_RODT_P1, SHURK0_SELPH_ODTEN0_TXDLY_B3_RODTEN_P1));
+
+                vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_ODTEN1), \
+                                            P_Fld((U32) ucdly_coarse_0p5T_RODT, SHURK0_SELPH_ODTEN1_DLY_B0_RODTEN)| \
+                                            P_Fld((U32) ucdly_coarse_0p5T_RODT, SHURK0_SELPH_ODTEN1_DLY_B1_RODTEN)| \
+                                            P_Fld((U32) ucdly_coarse_0p5T_RODT, SHURK0_SELPH_ODTEN1_DLY_B2_RODTEN)| \
+                                            P_Fld((U32) ucdly_coarse_0p5T_RODT, SHURK0_SELPH_ODTEN1_DLY_B3_RODTEN)| \
+                                            P_Fld((U32) ucdly_coarse_0p5T_RODT_P1, SHURK0_SELPH_ODTEN1_DLY_B0_RODTEN_P1)| \
+                                            P_Fld((U32) ucdly_coarse_0p5T_RODT_P1, SHURK0_SELPH_ODTEN1_DLY_B1_RODTEN_P1)| \
+                                            P_Fld((U32) ucdly_coarse_0p5T_RODT_P1, SHURK0_SELPH_ODTEN1_DLY_B2_RODTEN_P1)| \
+                                            P_Fld((U32) ucdly_coarse_0p5T_RODT_P1, SHURK0_SELPH_ODTEN1_DLY_B3_RODTEN_P1));
+
+                //mcSHOW_DBG_MSG2(("RODT delay(2T, 0.5T) = (%d, %d)\n", ucdly_coarse_large_RODT, ucdly_coarse_0p5T_RODT));
+                //mcFPRINTF((fp_A60501,"RODT delay(2T, 0.5T) = (%d, %d)\n", ucdly_coarse_large_RODT, ucdly_coarse_0p5T_RODT));
+            }
+        #endif
+
+            for (ucdly_fine_xT=DQS_GW_FINE_START; ucdly_fine_xT<DQS_GW_FINE_END; ucdly_fine_xT+=ucDQS_GW_FINE_STEP)
+            {
+                #if LP4_GATING_LEAD_LAG_FLAG_JUDGE
+                if(u1IsLP4Family(p->dram_type))
+                {
+                    DramcGatingMode(p, 0);
+                }
+                #endif
+
+                //ok we set a coarse/fine tune value already
+                u4value = ucdly_fine_xT | (ucdly_fine_xT<<8) | (ucdly_fine_xT<<16) | (ucdly_fine_xT<<24);
+                vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_DQSIEN), u4value);
+
+                //reset phy, reset read data counter
+                DramPhyReset(p);
+
+                //reset DQS counter
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_DQSGCNTRST);
+                mcDELAY_US(1);//delay 2T
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_DQSGCNTRST);
+
+                // enable TE2, audio pattern
+                DramcEngine2Run(p, TE_OP_READ_CHECK, TEST_AUDIO_PATTERN);
+
+                if(u1IsLP4Family(p->dram_type))
+                {
+                    u4all_result_R = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_STBERR_RK0_R), MISC_STBERR_RK0_R_STBERR_RK0_R);
+                    u4all_result_F = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_STBERR_RK0_F), MISC_STBERR_RK0_F_STBERR_RK0_F);
+               }
+                #if ENABLE_LP3_SW
+                else //LPDDR3
+                {
+                    LP3_DataPerByte[0] = u4IO32ReadFldAlign(DDRPHY_MISC_STBERR_RK0_R, MISC_STBERR_RK0_R_STBERR_RK0_R);  // CHA for B0 and B1
+                    LP3_DataPerByte[1] = u4IO32ReadFldAlign(DDRPHY_MISC_STBERR_RK0_R+SHIFT_TO_CHB_ADDR, MISC_STBERR_RK0_R_STBERR_RK0_R);// CHB for B2 and B3
+                    u4all_result_R = LP3_DataPerByte[0] | (LP3_DataPerByte[1] <<16);
+
+                    LP3_DataPerByte[0] = u4IO32ReadFldAlign(DDRPHY_MISC_STBERR_RK0_F, MISC_STBERR_RK0_F_STBERR_RK0_F);  // CHA for B0 and B1
+                    LP3_DataPerByte[1] = u4IO32ReadFldAlign(DDRPHY_MISC_STBERR_RK0_F+SHIFT_TO_CHB_ADDR, MISC_STBERR_RK0_F_STBERR_RK0_F);// CHB for B2 and B3
+                    u4all_result_F = LP3_DataPerByte[0] | (LP3_DataPerByte[1] <<16);
+                }
+                #endif
+
+                 //read DQS counter
+                u4DebugCnt[0] = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_DQSGNWCNT0));
+                u4DebugCnt[1] = (u4DebugCnt[0] >> 16) & 0xffff;
+                u4DebugCnt[0] &= 0xffff;
+#if ENABLE_LP3_SW
+                if(p->dram_type == TYPE_LPDDR3)
+                {
+                    u4DebugCnt[2] = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_DQSGNWCNT1));
+                    u4DebugCnt[3] = (u4DebugCnt[2] >> 16) & 0xffff;
+                    u4DebugCnt[2] &= 0xffff;
+                }
+#endif /* ENABLE_LP3_SW */
+                 u4err_value =0;
+
+                #if LP4_GATING_LEAD_LAG_FLAG_JUDGE
+                if(u1IsLP4Family(p->dram_type))
+                {
+                    DramcGatingMode(p, 1);
+                    DramcEngine2Run(p, TE_OP_READ_CHECK, TEST_AUDIO_PATTERN);// trigger read to make lead/lag flag update.
+
+                    for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+                    {
+                        if(u1DQSGatingFound[dqs_i]==1)
+                        {
+                            continue;
+                        }
+
+                        if(dqs_i==0)
+                        {
+                            u1DQS_lead[0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_PHY_RGS_STBEN_B0), MISC_PHY_RGS_STBEN_B0_AD_RX_ARDQS0_STBEN_LEAD_B0);
+                            u1DQS_lag[0]   = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_PHY_RGS_STBEN_B0), MISC_PHY_RGS_STBEN_B0_AD_RX_ARDQS0_STBEN_LAG_B0);
+                        }
+                        else //dqs1
+                        {
+                            u1DQS_lead[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_PHY_RGS_STBEN_B1), MISC_PHY_RGS_STBEN_B1_AD_RX_ARDQS0_STBEN_LEAD_B1);
+                            u1DQS_lag[1]   = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_PHY_RGS_STBEN_B1), MISC_PHY_RGS_STBEN_B1_AD_RX_ARDQS0_STBEN_LAG_B1);
+                        }
+
+                        if((u1DQS_lead[dqs_i]==1) && (u1DQS_lag[dqs_i]==1))
+                        {
+                            u1DQS_high[dqs_i] ++;
+                            //mcSHOW_DBG_MSG2(("[Byte %d] Lead/lag falling high (%d)\n", dqs_i,u1DQS_high[dqs_i]));
+                        }
+
+                        if(u1DQS_high[dqs_i] *ucDQS_GW_FINE_STEP >16)//>16 PI prevent glitch
+                        {
+                            if((u1DQS_lead[dqs_i]==1) && (u1DQS_lag[dqs_i]==1))
+                            {
+                                ucdly_coarse_large_leadLag[dqs_i] = ucdly_coarse_large;
+                                ucdly_coarse_0p5T_leadLag[dqs_i] = ucdly_coarse_0p5T;
+                                ucdly_fine_tune_leadLag[dqs_i] = ucdly_fine_xT;
+                                u1DQS_transition[dqs_i] =1;
+                            }
+                            else if(((u1DQS_lead[dqs_i]==1) && (u1DQS_lag[dqs_i]==0)) ||((u1DQS_lead[dqs_i]==0) && (u1DQS_lag[dqs_i]==1)))
+                            {
+                                if(u1DQS_transition[dqs_i] ==1)
+                                {
+                                    mcSHOW_DBG_MSG(("[Byte %d] Lead/lag falling Transition (%d, %d, %d)\n", dqs_i,ucdly_coarse_large_leadLag[dqs_i], ucdly_coarse_0p5T_leadLag[dqs_i], ucdly_fine_tune_leadLag[dqs_i]));
+                                }
+                                u1DQS_transition[dqs_i] ++;
+                            }
+                            else if((u1DQS_lead[dqs_i]==0) && (u1DQS_lag[dqs_i]==0))
+                            {
+                                mcSHOW_DBG_MSG(("[Byte %d] Lead/lag Transition tap number (%d)\n", dqs_i, u1DQS_transition[dqs_i]));
+                                u1DQS_high[dqs_i] =0;
+                             }
+                        }
+                    }
+                }
+                #endif
+
+                 /*TINFO="%2d  %2d  %2d |(B3->B0) 0x%4x, 0x%4x, 0x%4x, 0x%4x | %2x %2x  %2x %2x  %2x %2x  %2x %2x | 0x%8x\n", ucdly_coarse_large, ucdly_coarse_0p5T, ucdly_fine_xT, \
+                                                      u4DebugCnt[3], u4DebugCnt[2], u4DebugCnt[1], u4DebugCnt[0], \
+                                                       (u4all_result_F>>24)&0xff, (u4all_result_R>>24)&0xff, \
+                                                       (u4all_result_F>>16)&0xff, (u4all_result_R>>16)&0xff, \
+                                                       (u4all_result_F>>8)&0xff,   (u4all_result_R>>8)&0xff, \
+                                                       (u4all_result_F)&0xff,         (u4all_result_R)&0xff,    u4err_value*/
+
+                #ifdef ETT_PRINT_FORMAT
+                #if 0
+                mcSHOW_DBG_MSG(("%d  %d  %d |(B3->B0) 0x%H, 0x%H, 0x%H, 0x%H | %B %B  %B %B  %B %B  %B %B | B0(%d, %d) B1(%d, %d) |0x%X\n",
+                                                       ucdly_coarse_large, ucdly_coarse_0p5T, ucdly_fine_xT, \
+                                                       u4DebugCnt[3], u4DebugCnt[2], u4DebugCnt[1], u4DebugCnt[0], \
+                                                       (u4all_result_F>>24)&0xff, (u4all_result_R>>24)&0xff, \
+                                                       (u4all_result_F>>16)&0xff, (u4all_result_R>>16)&0xff, \
+                                                       (u4all_result_F>>8)&0xff,   (u4all_result_R>>8)&0xff, \
+                                                       (u4all_result_F)&0xff,         (u4all_result_R)&0xff,
+                                                       #if LP4_GATING_LEAD_LAG_FLAG_JUDGE
+                                                       u1DQS_lead[0], u1DQS_lag[0], u1DQS_lead[1], u1DQS_lag[1],
+                                                       #else
+                                                       0,0,0,0,
+                                                       #endif
+                                                        u4err_value));
+                #else
+                mcSHOW_DBG_MSG(("%d %d %d |", ucdly_coarse_large, ucdly_coarse_0p5T, ucdly_fine_xT ));
+
+                for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+                {
+                    mcSHOW_DBG_MSG(("%X ", u4DebugCnt[dqs_i]));
+                }
+                mcSHOW_DBG_MSG((" |"));
+                for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+                {
+                    mcSHOW_DBG_MSG(("(%X %X)", (u4all_result_F>>(DQS_BIT_NUMBER*dqs_i)) & 0xff, (u4all_result_R>>(DQS_BIT_NUMBER*dqs_i)) & 0xff));
+                }
+
+                #if LP4_GATING_LEAD_LAG_FLAG_JUDGE
+                mcSHOW_DBG_MSG((" |"));
+                for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+                {
+                    mcSHOW_DBG_MSG(("(%d %d)", u1DQS_lead[dqs_i], u1DQS_lag[dqs_i]));
+                }
+                #endif
+
+                mcSHOW_DBG_MSG2(("| %X", u4err_value));
+                mcSHOW_DBG_MSG(("\n"));
+                #endif
+
+                #else
+                mcSHOW_DBG_MSG(("%2d  %2d  %2d |(B3->B0) 0x%4x, 0x%4x, 0x%4x, 0x%4x | %2x %2x  %2x %2x  %2x %2x  %2x %2x | 0x%8x\n", ucdly_coarse_large, ucdly_coarse_0p5T, ucdly_fine_xT, \
+                                                      u4DebugCnt[3], u4DebugCnt[2], u4DebugCnt[1], u4DebugCnt[0], \
+                                                       (u4all_result_F>>24)&0xff, (u4all_result_R>>24)&0xff, \
+                                                       (u4all_result_F>>16)&0xff, (u4all_result_R>>16)&0xff, \
+                                                       (u4all_result_F>>8)&0xff,   (u4all_result_R>>8)&0xff, \
+                                                       (u4all_result_F)&0xff,         (u4all_result_R)&0xff,    u4err_value));
+
+                #endif
+
+                 mcFPRINTF((fp_A60501,"%2d  %2d  %2d |(B3->B0) 0x%4x, 0x%4x, 0x%4x, 0x%4x | (B3->B0) %2x %2x  %2x %2x  %2x %2x  %2x %2x | 0x%8x\n", ucdly_coarse_large, ucdly_coarse_0p5T, ucdly_fine_xT, \
+                                                    u4DebugCnt[3], u4DebugCnt[2], u4DebugCnt[1], u4DebugCnt[0], \
+                                                     (u4all_result_F>>24)&0xff, (u4all_result_R>>24)&0xff, \
+                                                     (u4all_result_F>>16)&0xff, (u4all_result_R>>16)&0xff, \
+                                                     (u4all_result_F>>8)&0xff,   (u4all_result_R>>8)&0xff, \
+                                                     (u4all_result_F)&0xff,         (u4all_result_R)&0xff,    u4err_value));
+
+                //find gating window pass range per DQS separately
+                for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+                {
+                    if(u1PassByteCount  & (1<<dqs_i))
+                    {
+                        // real window found, break to prevent finding fake window.
+                        continue;
+                    }
+                    //get dqs error result
+                    ucdqs_result_R = (U8)((u4all_result_R>>(8*dqs_i))&0xff);
+                    ucdqs_result_F = (U8)((u4all_result_F>>(8*dqs_i))&0xff);
+                    u2DebugCntPerByte =(U16) u4DebugCnt[dqs_i];
+
+                    // check if current tap is pass
+                    ucCurrentPass =0;
+                    if(u1IsLP4Family(p->dram_type))
+                    {
+                       if((ucdqs_result_R==0) && (ucdqs_result_F==0) && (u2DebugCntPerByte==GATING_GOLDEND_DQSCNT_LP4))
+                            ucCurrentPass =1;
+                    }
+                    #if ENABLE_LP3_SW
+                    else //LPDDR3
+                    {
+                        if((ucdqs_result_R==0) && (ucdqs_result_F==0) && (u2DebugCntPerByte==GATING_GOLDEND_DQSCNT_LP3))
+                        {
+                                ucCurrentPass =1;
+                                ucDQS_GW_FINE_STEP = 1;
+                        }
+                    }
+                    #endif
+
+                    //if current tap is pass
+                    if (ucCurrentPass)
+                    {
+                        if (ucpass_begin[dqs_i]==0)
+                        {
+                            //no pass tap before , so it is the begining of pass range
+                            ucpass_begin[dqs_i] = 1;
+                            ucpass_count_1[dqs_i] = 0;
+                            ucmin_coarse_tune2T_1[dqs_i] = ucdly_coarse_large;
+                            ucmin_coarse_tune0p5T_1[dqs_i] = ucdly_coarse_0p5T;
+                            ucmin_fine_tune_1[dqs_i] = ucdly_fine_xT;
+
+                            /*TINFO="[Byte %d]First pass (%d, %d, %d)\n", dqs_i,ucdly_coarse_large, ucdly_coarse_0p5T, ucdly_fine_xT*/
+                            mcSHOW_DBG_MSG2(("[Byte %d]First pass (%d, %d, %d)\n", dqs_i, ucdly_coarse_large, ucdly_coarse_0p5T, ucdly_fine_xT));
+                        }
+
+                        if (ucpass_begin[dqs_i]==1)
+                        {
+                            //incr pass tap number
+                            ucpass_count_1[dqs_i]++;
+                        }
+
+#if LP4_GATING_LEAD_LAG_FLAG_JUDGE
+                        // Francis add to prevent lead/lag transition miss judgement
+                        if (u1IsLP4Family(p->dram_type) && (ucpass_begin[dqs_i] == 1) && (ucpass_count_1[dqs_i]*ucDQS_GW_FINE_STEP > 32))
+                        {
+                            u1DQSGatingFound[dqs_i] =1;
+                        }
+
+                        if (u1IsLP4Family(p->dram_type) && (ucpass_count_1[0]*ucDQS_GW_FINE_STEP > 32) && (ucpass_count_1[1]*ucDQS_GW_FINE_STEP > 32))
+                        {
+                            // if all bytes gating windows > 1UI, then early break;
+                            mcSHOW_DBG_MSG2(("All bytes gating window > 1UI, Early break!\n"));
+                            mcFPRINTF((fp_A60501, "All bytes gating window > 1UI, Early break!\n"));
+                            ucdly_fine_xT = DQS_GW_FINE_END;//break loop
+                            ucCoarseTune = ucCoarseEnd;      //break loop
+
+                        }
+#endif
+                    }
+                    else // current tap is fail
+                    {
+                        if (ucpass_begin[dqs_i]==1)
+                        {
+                            //at the end of pass range
+                            ucpass_begin[dqs_i] = 0;
+
+                            //save the max range settings, to avoid glitch
+                            if (ucpass_count_1[dqs_i] > ucpass_count[dqs_i])
+                            {
+                                ucmin_coarse_tune2T[dqs_i] = ucmin_coarse_tune2T_1[dqs_i];
+                                ucmin_coarse_tune0p5T[dqs_i] = ucmin_coarse_tune0p5T_1[dqs_i];
+                                ucmin_fine_tune[dqs_i] = ucmin_fine_tune_1[dqs_i];
+                                ucpass_count[dqs_i] = ucpass_count_1[dqs_i];
+
+#if ENABLE_LP3_SW
+                                //LP3 CHB_CA didn't has lead/lag RG, use SW workaround
+                                if (!u1IsLP4Family(p->dram_type))
+                                {
+                                    if (ucpass_count_1[dqs_i] >= 70) // if didn't check fail region and pass UI more than 2UI, then workaround back to 2UI
+                                    {
+                                        ucpass_count_1[dqs_i] = 64; // 2UI
+                                        ucpass_count[dqs_i] = ucpass_count_1[dqs_i];
+                                    }
+                                }
+#endif
+
+                                /*TINFO="[Byte %d]Bigger pass win(%d, %d, %d)  Pass tap=%d\n", \
+                                    dqs_i, ucmin_coarse_tune2T_1[dqs_i], ucmin_coarse_tune0p5T_1[dqs_i], ucmin_fine_tune_1[dqs_i], ucpass_count_1[dqs_i]*/
+                                mcSHOW_DBG_MSG(("[Byte %d]Bigger pass win(%d, %d, %d)  Pass tap=%d\n", \
+                                    dqs_i, ucmin_coarse_tune2T_1[dqs_i], ucmin_coarse_tune0p5T_1[dqs_i], ucmin_fine_tune_1[dqs_i], ucpass_count_1[dqs_i]));
+
+                                // LP4 pass window around 6 UI(burst mode), set 1~3 UI is pass
+                                // LP3 pass window around 2 UI(pause mode), set 1~3 UI is pass
+                                if((ucpass_count_1[dqs_i]*ucDQS_GW_FINE_STEP > 32) && (ucpass_count_1[dqs_i]*ucDQS_GW_FINE_STEP < 96))
+                                {
+                                    u1PassByteCount  |= (1<<dqs_i);
+                                }
+
+                                if(((u1IsLP4Family(p->dram_type)) && (u1PassByteCount==0x3)) || ((p->dram_type==TYPE_LPDDR3) && (u1PassByteCount==0xf)))
+                                {
+                                    mcSHOW_DBG_MSG2(("All bytes gating window pass Done, Early break!\n"));
+                                    mcFPRINTF((fp_A60501, "All bytes gating window pass Done, Early break!\n"));
+                                    ucdly_fine_xT = DQS_GW_FINE_END;//break loop
+                                    ucCoarseTune = ucCoarseEnd;      //break loop
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        DramcEngine2End(p);
+
+#if !SW_CHANGE_FOR_SIMULATION
+            vSetCalibrationResult(p, DRAM_CALIBRATION_GATING, DRAM_OK);
+#endif
+
+        //check if there is no pass taps for each DQS
+        for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+        {
+            if (ucpass_count[dqs_i]==0)
+            {
+#if LP4_GATING_LEAD_LAG_FLAG_JUDGE==0
+                /*TINFO="error, no pass taps in DQS_%d !!!\n", dqs_i*/
+                mcSHOW_ERR_MSG(("error, no pass taps in DQS_%d!\n", dqs_i));
+                mcFPRINTF((fp_A60501, "error, no pass taps in DQS_%d!\n", dqs_i));
+                #if !SW_CHANGE_FOR_SIMULATION
+                vSetCalibrationResult(p, DRAM_CALIBRATION_GATING, DRAM_FAIL);
+                #endif
+#endif
+            }
+        }
+
+        #if LP4_GATING_OLD_BURST_MODE
+        if(u1IsLP4Family(p->dram_type))
+        {
+            //Set the gating window begin as gating position
+            //ucpass_count[0]=0;
+            //ucpass_count[1]=0;
+
+            //Set the gating window end-2UI as gating position
+            ucpass_count[0] <<=1;
+            ucpass_count[1] <<=1;
+        }
+        #else
+        if(u1IsLP4Family(p->dram_type))
+        {
+            // LP4 burst mode, may find 6 UI. The 2 UI of the begining may not work.
+            //if gating window > 5UI, skip the first 2 UI.
+            if((ucpass_count_1[0]*ucDQS_GW_FINE_STEP > 160) &&(ucpass_count_1[1]*ucDQS_GW_FINE_STEP > 160))
+            {
+                mcSHOW_DBG_MSG2(("If gating window > 4.5UI, skip the first 2 UI! \n"));
+                mcFPRINTF((fp_A60501, "If gating window > 4.5UI, skip the first 2 UI!\n"));
+
+                for (dqs_i=0; dqs_i<2; dqs_i++)
+                {
+                    ucmin_coarse_tune0p5T[dqs_i] +=2;
+
+                    if(ucmin_coarse_tune0p5T[dqs_i] > ucRX_DQS_CTL_LOOP)
+                    {
+                        ucmin_coarse_tune0p5T[dqs_i] -= ucRX_DQS_CTL_LOOP;
+                        ucmin_coarse_tune2T[dqs_i] +=1;
+                    }
+                    mcSHOW_DBG_MSG2(("Change Byte%d Window begin to (%d, %d)\n", dqs_i, ucmin_coarse_tune2T[dqs_i], ucmin_coarse_tune0p5T[dqs_i]));
+                    mcFPRINTF((fp_A60501, "Change Byte%d Window begin to (%d, %d)\n", dqs_i ucmin_coarse_tune2T[dqs_i], ucmin_coarse_tune0p5T[dqs_i]));
+                }
+            }
+        }
+        #endif
+}
+        //find center of each byte
+        for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+        {
+#if SW_CHANGE_FOR_SIMULATION  // simulation cannot support %
+        // -- PI for Phase0 & Phase1 --
+            uctmp_offset = ucpass_count[dqs_i]*ucDQS_GW_FINE_STEP/2;
+            uctmp_value = ucmin_fine_tune[dqs_i]+uctmp_offset;
+            ucbest_fine_tune[dqs_i] = uctmp_value - (uctmp_value/ucRX_DLY_DQSIENSTB_LOOP) * ucRX_DLY_DQSIENSTB_LOOP;
+            ucbest_fine_tune_P1[dqs_i] = ucbest_fine_tune[dqs_i];
+
+        // coarse tune 0.5T for Phase 0
+            uctmp_offset = uctmp_value / ucRX_DLY_DQSIENSTB_LOOP;
+            uctmp_value = ucmin_coarse_tune0p5T[dqs_i]+uctmp_offset;
+            ucbest_coarse_tune0p5T[dqs_i] = uctmp_value - (uctmp_value/ucRX_DQS_CTL_LOOP) * ucRX_DQS_CTL_LOOP;
+
+        // coarse tune 2T for Phase 0
+            uctmp_offset = uctmp_value/ucRX_DQS_CTL_LOOP;
+            ucbest_coarse_tune2T[dqs_i] = ucmin_coarse_tune2T[dqs_i]+uctmp_offset;
+
+        // coarse tune 0.5T for Phase 1
+            uctmp_value = ucbest_coarse_tune0p5T[dqs_i]+ ucFreqDiv;
+            ucbest_coarse_tune0p5T_P1[dqs_i] = uctmp_value - (uctmp_value/ ucRX_DQS_CTL_LOOP) *ucRX_DQS_CTL_LOOP;
+
+        // coarse tune 2T for Phase 1
+            uctmp_offset = uctmp_value/ucRX_DQS_CTL_LOOP;
+            ucbest_coarse_tune2T_P1[dqs_i] = ucbest_coarse_tune2T[dqs_i]+uctmp_offset;
+#else
+
+     #if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_GatingCal)
+		if(p->femmc_Ready==1)
+       	{
+            ucmin_coarse_tune2T[dqs_i]=p->pSavetimeData->u1Gating2T_Save[p->channel][p->rank][dqs_i];
+            ucmin_coarse_tune0p5T[dqs_i]=p->pSavetimeData->u1Gating05T_Save[p->channel][p->rank][dqs_i];
+            ucmin_fine_tune[dqs_i]=p->pSavetimeData->u1Gatingfine_tune_Save[p->channel][p->rank][dqs_i];
+            ucpass_count[dqs_i]=p->pSavetimeData->u1Gatingucpass_count_Save[p->channel][p->rank][dqs_i];
+            vSetCalibrationResult(p, DRAM_CALIBRATION_GATING, DRAM_OK);
+		}
+		else
+#endif
+        {
+
+        #if LP4_GATING_LEAD_LAG_FLAG_JUDGE
+        if(u1IsLP4Family(p->dram_type))
+            {
+                ucpass_count[dqs_i] = u1DQS_transition[dqs_i];
+                ucmin_fine_tune[dqs_i] = ucdly_fine_tune_leadLag[dqs_i];
+                ucmin_coarse_tune0p5T[dqs_i] = ucdly_coarse_0p5T_leadLag[dqs_i];
+                ucmin_coarse_tune2T[dqs_i] = ucdly_coarse_large_leadLag[dqs_i];
+            }
+    #endif
+        }
+
+     #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+		if(p->femmc_Ready==0)
+         {
+		p->pSavetimeData->u1Gating2T_Save[p->channel][p->rank][dqs_i]=ucmin_coarse_tune2T[dqs_i];
+		p->pSavetimeData->u1Gating05T_Save[p->channel][p->rank][dqs_i]=ucmin_coarse_tune0p5T[dqs_i];
+		p->pSavetimeData->u1Gatingfine_tune_Save[p->channel][p->rank][dqs_i]=ucmin_fine_tune[dqs_i];
+		p->pSavetimeData->u1Gatingucpass_count_Save[p->channel][p->rank][dqs_i]=ucpass_count[dqs_i];
+            // mcSHOW_DBG_MSG(("save Gating\n"));
+     	}
+     #endif
+        // -- PI for Phase0 & Phase1 --
+            #if (LP4_GATING_END_MINUS2UI==1 && LP4_GATING_OLD_BURST_MODE==0)
+            mcSHOW_DBG_MSG(("ucpass_count[dqs_i]*ucDQS_GW_FINE_STEP=%d\n", (ucpass_count[dqs_i]*ucDQS_GW_FINE_STEP)));
+            if((ucpass_count[dqs_i]*ucDQS_GW_FINE_STEP)<128)//window size < 4UI : select center
+            {
+                uctmp_offset = ucpass_count[dqs_i]*ucDQS_GW_FINE_STEP/2;
+            }
+            else // select window_end-2UI
+            {
+                uctmp_offset = (ucpass_count[dqs_i]*ucDQS_GW_FINE_STEP) - 64;
+            }
+            #else
+            uctmp_offset = ucpass_count[dqs_i]*ucDQS_GW_FINE_STEP/2;
+            #endif
+
+            uctmp_value = ucmin_fine_tune[dqs_i]+uctmp_offset;
+            ucbest_fine_tune[dqs_i] = uctmp_value% ucRX_DLY_DQSIENSTB_LOOP;
+            ucbest_fine_tune_P1[dqs_i] = ucbest_fine_tune[dqs_i];
+
+        // coarse tune 0.5T for Phase 0
+            uctmp_offset = uctmp_value / ucRX_DLY_DQSIENSTB_LOOP;
+            uctmp_value = ucmin_coarse_tune0p5T[dqs_i]+uctmp_offset;
+            ucbest_coarse_tune0p5T[dqs_i] = uctmp_value% ucRX_DQS_CTL_LOOP;
+
+        // coarse tune 2T for Phase 0
+            uctmp_offset = uctmp_value/ucRX_DQS_CTL_LOOP;
+            ucbest_coarse_tune2T[dqs_i] = ucmin_coarse_tune2T[dqs_i]+uctmp_offset;
+
+        // coarse tune 0.5T for Phase 1
+            uctmp_value = ucbest_coarse_tune0p5T[dqs_i]+ ucFreqDiv;
+            ucbest_coarse_tune0p5T_P1[dqs_i] = uctmp_value% ucRX_DQS_CTL_LOOP;
+
+        // coarse tune 2T for Phase 1
+            uctmp_offset = uctmp_value/ucRX_DQS_CTL_LOOP;
+            ucbest_coarse_tune2T_P1[dqs_i] = ucbest_coarse_tune2T[dqs_i]+uctmp_offset;
+#endif
+        }
+
+        mcSHOW_DBG_MSG3(("\n\tdqs input gating window, final dly value\n\n"));
+
+        //mcSHOW_DBG_MSG(("test2_1: 0x%x, test2_2: 0x%x, test pattern: %d\n",  p->test2_1,p->test2_2, p->test_pattern));
+        //mcSHOW_DBG_MSG3(("\tdqs input gating window, best dly value\n\n"));
+
+
+        mcFPRINTF((fp_A60501, "\n\tdqs input gating window, final dly value\n\n"));
+        //mcFPRINTF((fp_A60501, "test2_1: 0x%x, test2_2: 0x%x, test pattern: %d\n",  p->test2_1,p->test2_2, p->test_pattern));
+        mcFPRINTF((fp_A60501, "\tdqs input gating window, best dly value\n\n"));
+
+        if(u1IsLP4Family(p->dram_type))
+        {
+            for (dqs_i=2; dqs_i<4; dqs_i++)  // LP4, DQ byte 2 and byte 3 are useless, set gating result as 0.
+            {
+                ucbest_coarse_tune2T[dqs_i] = ucbest_coarse_tune0p5T[dqs_i] = ucbest_fine_tune[dqs_i]= 0;
+                ucbest_coarse_tune2T_P1[dqs_i] = ucbest_coarse_tune0p5T_P1[dqs_i] = ucbest_fine_tune_P1[dqs_i]= 0;
+
+                #if GATING_ADJUST_TXDLY_FOR_TRACKING
+                    ucbest_coarse_tune2T_backup[p->rank][dqs_i] = ucbest_coarse_tune0p5T_backup[p->rank][dqs_i] = 0;
+                    ucbest_coarse_tune2T_P1_backup[p->rank][dqs_i] = ucbest_coarse_tune0p5T_P1_backup[p->rank][dqs_i] = 0;
+                #endif
+            }
+        }
+
+        for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+        {
+            #ifdef FOR_HQA_REPORT_USED
+                        HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0, "Gating_Center_2T", dqs_i, ucbest_coarse_tune2T[dqs_i], NULL);
+                        HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0, "Gating_Center_05T", dqs_i, ucbest_coarse_tune0p5T[dqs_i], NULL);
+                        HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0, "Gating_Center_PI", dqs_i, ucbest_fine_tune[dqs_i], NULL);
+            #endif
+
+            /*TINFO="best DQS%d delay(2T, 0.5T, PI) = (%d, %d, %d)\n", dqs_i, ucbest_coarse_tune2T[dqs_i], ucbest_coarse_tune0p5T[dqs_i], ucbest_fine_tune[dqs_i]*/
+            mcSHOW_DBG_MSG(("\nbest DQS%d dly(2T, 0.5T, PI) = (%d, %d, %d)\n", dqs_i, ucbest_coarse_tune2T[dqs_i], ucbest_coarse_tune0p5T[dqs_i], ucbest_fine_tune[dqs_i]));
+            mcFPRINTF((fp_A60501,"best DQS%d dly(2T, 0.5T, PI) = (%d, %d, %d)\n", dqs_i, ucbest_coarse_tune2T[dqs_i], ucbest_coarse_tune0p5T[dqs_i], ucbest_fine_tune[dqs_i]));
+            #if GATING_ADJUST_TXDLY_FOR_TRACKING
+            // find min gating TXDLY (should be in P0)
+            if (u1IsLP4Family(p->dram_type))
+            {
+                u1TX_dly_DQSgated =ucbest_coarse_tune2T[dqs_i];
+            }
+#if ENABLE_LP3_SW
+            else
+            {
+                u1TX_dly_DQSgated  = ((ucbest_coarse_tune2T[dqs_i] <<1)|((ucbest_coarse_tune0p5T[dqs_i] >>2)&0x1));
+            }
+#endif /* ENABLE_LP3_SW */
+
+            if(u1TX_dly_DQSgated < u1TXDLY_Cal_min)
+                u1TXDLY_Cal_min = u1TX_dly_DQSgated;
+
+            ucbest_coarse_tune0p5T_backup[p->rank][dqs_i] = ucbest_coarse_tune0p5T[dqs_i];
+            ucbest_coarse_tune2T_backup[p->rank][dqs_i] = ucbest_coarse_tune2T[dqs_i];
+            #endif
+        }
+
+        mcSHOW_DBG_MSG(("\n\n"));
+        mcFPRINTF((fp_A60501,"\n\n"));
+
+        for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+        {
+            /*TINFO="best DQS%d P1 delay(2T, 0.5T, PI) = (%d, %d, %d)\n", dqs_i, ucbest_coarse_tune2T_P1[dqs_i], ucbest_coarse_tune0p5T_P1[dqs_i], ucbest_fine_tune[dqs_i]*/
+            mcSHOW_DBG_MSG(("\nbest DQS%d P1 dly(2T, 0.5T, PI) = (%d, %d, %d)\n", dqs_i, ucbest_coarse_tune2T_P1[dqs_i], ucbest_coarse_tune0p5T_P1[dqs_i], ucbest_fine_tune[dqs_i]));
+            mcFPRINTF((fp_A60501,"best DQS%d P1 dly(2T, 0.5T, PI) = (%d, %d, %d)\n", dqs_i, ucbest_coarse_tune2T_P1[dqs_i], ucbest_coarse_tune0p5T_P1[dqs_i], ucbest_fine_tune[dqs_i]));
+
+            #if GATING_ADJUST_TXDLY_FOR_TRACKING
+            // find max gating TXDLY (should be in P1)
+
+            if (u1IsLP4Family(p->dram_type))
+            {
+                u1TX_dly_DQSgated  = ucbest_coarse_tune2T_P1[dqs_i];
+            }
+#if ENABLE_LP3_SW
+            else
+            {
+                u1TX_dly_DQSgated  = ((ucbest_coarse_tune2T_P1[dqs_i] <<1)|((ucbest_coarse_tune0p5T_P1[dqs_i] >>2)&0x1));
+            }
+#endif /* ENABLE_LP3_SW */
+
+            if(u1TX_dly_DQSgated > u1TXDLY_Cal_max)
+                u1TXDLY_Cal_max = u1TX_dly_DQSgated;
+
+            ucbest_coarse_tune0p5T_P1_backup[p->rank][dqs_i] = ucbest_coarse_tune0p5T_P1[dqs_i];
+            ucbest_coarse_tune2T_P1_backup[p->rank][dqs_i] = ucbest_coarse_tune2T_P1[dqs_i];
+            #endif
+        }
+
+        mcSHOW_DBG_MSG(("\n\n"));
+        mcFPRINTF((fp_A60501,"\n\n"));
+
+        //Restore registers
+        DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+#ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+    gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag = u1GUMP_INIT_RG_LOG_TO_DE_bak;
+#endif
+
+        #if LP4_GATING_OLD_BURST_MODE
+        if(u1IsLP4Family(p->dram_type))
+        {
+            #if !LP4_GATING_LEAD_LAG_FLAG_JUDGE
+            DramcGatingMode(p, 1);
+            #endif
+            //MR1 OP[7]=0;
+            u1MR01Value[p->dram_fsp] &= 0x7f;
+            DramcModeRegWriteByRank(p, p->rank, 1, u1MR01Value[p->dram_fsp]);
+        }
+        #endif
+
+        /* LP3/4: Set ARDQ_RPRE_TOG_EN must be 1 after gating window calibration */
+        RxDQSIsiPulseCG(p, ENABLE);
+
+        #if REG_SHUFFLE_REG_CHECK
+        ShuffleRegCheck =1;
+        #endif
+
+        // 4T or 2T coarse tune
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQSG0), \
+                                    P_Fld((U32) ucbest_coarse_tune2T[0], SHURK0_SELPH_DQSG0_TX_DLY_DQS0_GATED)| \
+                                    P_Fld((U32) ucbest_coarse_tune2T[1], SHURK0_SELPH_DQSG0_TX_DLY_DQS1_GATED)| \
+                                    P_Fld((U32) ucbest_coarse_tune2T[2], SHURK0_SELPH_DQSG0_TX_DLY_DQS2_GATED)| \
+                                    P_Fld((U32) ucbest_coarse_tune2T[3], SHURK0_SELPH_DQSG0_TX_DLY_DQS3_GATED)| \
+                                    P_Fld((U32) ucbest_coarse_tune2T_P1[0], SHURK0_SELPH_DQSG0_TX_DLY_DQS0_GATED_P1)| \
+                                    P_Fld((U32) ucbest_coarse_tune2T_P1[1], SHURK0_SELPH_DQSG0_TX_DLY_DQS1_GATED_P1)| \
+                                    P_Fld((U32) ucbest_coarse_tune2T_P1[2], SHURK0_SELPH_DQSG0_TX_DLY_DQS2_GATED_P1)| \
+                                    P_Fld((U32) ucbest_coarse_tune2T_P1[3], SHURK0_SELPH_DQSG0_TX_DLY_DQS3_GATED_P1));
+
+        // 0.5T coarse tune
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQSG1), \
+                                    P_Fld((U32) ucbest_coarse_tune0p5T[0], SHURK0_SELPH_DQSG1_REG_DLY_DQS0_GATED)| \
+                                    P_Fld((U32) ucbest_coarse_tune0p5T[1], SHURK0_SELPH_DQSG1_REG_DLY_DQS1_GATED)| \
+                                    P_Fld((U32) ucbest_coarse_tune0p5T[2], SHURK0_SELPH_DQSG1_REG_DLY_DQS2_GATED)| \
+                                    P_Fld((U32) ucbest_coarse_tune0p5T[3], SHURK0_SELPH_DQSG1_REG_DLY_DQS3_GATED)| \
+                                    P_Fld((U32) ucbest_coarse_tune0p5T_P1[0], SHURK0_SELPH_DQSG1_REG_DLY_DQS0_GATED_P1)| \
+                                    P_Fld((U32) ucbest_coarse_tune0p5T_P1[1], SHURK0_SELPH_DQSG1_REG_DLY_DQS1_GATED_P1)| \
+                                    P_Fld((U32) ucbest_coarse_tune0p5T_P1[2], SHURK0_SELPH_DQSG1_REG_DLY_DQS2_GATED_P1)| \
+                                    P_Fld((U32) ucbest_coarse_tune0p5T_P1[3], SHURK0_SELPH_DQSG1_REG_DLY_DQS3_GATED_P1));
+
+
+    #if GATING_RODT_LATANCY_EN    //LP3 RODT is not enable, don't need to set the RODT settings.
+        // RODT = Gating - 11UI,
+    if(u1IsLP4Family(p->dram_type))
+        {
+            for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+            {
+                uctmp_value = (ucbest_coarse_tune2T[dqs_i] <<3)+ucbest_coarse_tune0p5T[dqs_i];
+
+                if(uctmp_value>=11)
+                {
+                    //P0
+                    uctmp_value -=11;
+                    ucbest_coarse_large_RODT[dqs_i] = uctmp_value >>3;
+                    ucbest_coarse_0p5T_RODT[dqs_i]  = uctmp_value - (ucbest_coarse_large_RODT[dqs_i] <<3);
+
+                    //P1
+                    uctmp_value = (ucbest_coarse_tune2T_P1[dqs_i] <<3)+ucbest_coarse_tune0p5T_P1[dqs_i] -11;
+                    ucbest_coarse_large_RODT_P1[dqs_i] = uctmp_value >>3;
+                    ucbest_coarse_0p5T_RODT_P1[dqs_i]  = uctmp_value - (ucbest_coarse_large_RODT_P1[dqs_i] <<3);
+
+                    mcSHOW_DBG_MSG2(("\nbest RODT dly(2T, 0.5T) = (%d, %d)\n", ucbest_coarse_large_RODT[dqs_i], ucbest_coarse_0p5T_RODT[dqs_i]));
+                    mcFPRINTF((fp_A60501,"best RODT dly(2T, 0.5T) = (%d, %d)\n", ucbest_coarse_large_RODT[dqs_i], ucbest_coarse_0p5T_RODT[dqs_i]));
+                }
+                else //if(ucbest_coarse_tune2T[0] ==0)  //shouble not happen,  just only protect this happen
+                {
+                    //P0
+                    ucbest_coarse_large_RODT[dqs_i] =0;
+                    ucbest_coarse_0p5T_RODT[dqs_i] = 0;
+                    //P1
+                    ucbest_coarse_large_RODT_P1[dqs_i] =4;
+                    ucbest_coarse_0p5T_RODT_P1[dqs_i] = 4;
+
+                    mcSHOW_ERR_MSG(("[RxdqsGatingCal] Error: ucbest_coarse_tune2T[%d] is already 0. RODT cannot be -1 UI\n", dqs_i));
+                    mcFPRINTF((fp_A60501, "[RxdqsGatingCal] Error: ucbest_coarse_tune2T[%d] is already 0. RODT cannot be -1 UI\n", dqs_i));
+                }
+            }
+
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_ODTEN0), \
+                                        P_Fld((U32) ucbest_coarse_large_RODT[0], SHURK0_SELPH_ODTEN0_TXDLY_B0_RODTEN)| \
+                                        P_Fld((U32) ucbest_coarse_large_RODT[1], SHURK0_SELPH_ODTEN0_TXDLY_B1_RODTEN)| \
+                                        P_Fld((U32) ucbest_coarse_large_RODT[2], SHURK0_SELPH_ODTEN0_TXDLY_B2_RODTEN)| \
+                                        P_Fld((U32) ucbest_coarse_large_RODT[3], SHURK0_SELPH_ODTEN0_TXDLY_B3_RODTEN)| \
+                                        P_Fld((U32) ucbest_coarse_large_RODT_P1[0], SHURK0_SELPH_ODTEN0_TXDLY_B0_RODTEN_P1)| \
+                                        P_Fld((U32) ucbest_coarse_large_RODT_P1[1], SHURK0_SELPH_ODTEN0_TXDLY_B1_RODTEN_P1)| \
+                                        P_Fld((U32) ucbest_coarse_large_RODT_P1[2], SHURK0_SELPH_ODTEN0_TXDLY_B2_RODTEN_P1)| \
+                                        P_Fld((U32) ucbest_coarse_large_RODT_P1[3], SHURK0_SELPH_ODTEN0_TXDLY_B3_RODTEN_P1));
+
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_ODTEN1), \
+                                        P_Fld((U32) ucbest_coarse_0p5T_RODT[0], SHURK0_SELPH_ODTEN1_DLY_B0_RODTEN)| \
+                                        P_Fld((U32) ucbest_coarse_0p5T_RODT[1], SHURK0_SELPH_ODTEN1_DLY_B1_RODTEN)| \
+                                        P_Fld((U32) ucbest_coarse_0p5T_RODT[2], SHURK0_SELPH_ODTEN1_DLY_B2_RODTEN)| \
+                                        P_Fld((U32) ucbest_coarse_0p5T_RODT[3], SHURK0_SELPH_ODTEN1_DLY_B3_RODTEN)| \
+                                        P_Fld((U32) ucbest_coarse_0p5T_RODT_P1[0], SHURK0_SELPH_ODTEN1_DLY_B0_RODTEN_P1)| \
+                                        P_Fld((U32) ucbest_coarse_0p5T_RODT_P1[1], SHURK0_SELPH_ODTEN1_DLY_B1_RODTEN_P1)| \
+                                        P_Fld((U32) ucbest_coarse_0p5T_RODT_P1[2], SHURK0_SELPH_ODTEN1_DLY_B2_RODTEN_P1)| \
+                                        P_Fld((U32) ucbest_coarse_0p5T_RODT_P1[3], SHURK0_SELPH_ODTEN1_DLY_B3_RODTEN_P1));
+        }
+    #endif
+
+        // Set Fine Tune Value to registers
+        u4value = ucbest_fine_tune[0] | (ucbest_fine_tune[1]<<8) | (ucbest_fine_tune[2]<<16) | (ucbest_fine_tune[3]<<24);
+        vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_DQSIEN), u4value);
+
+    #if REG_SHUFFLE_REG_CHECK
+        ShuffleRegCheck =0;
+    #endif
+
+        //mcDELAY_US(1);//delay 2T
+        //DramPhyCGReset(p, 0);
+        DramPhyReset(p);   //reset phy, reset read data counter
+
+        /*TINFO="[DramcRxdqsGatingCal] Done\n"*/
+        mcSHOW_DBG_MSG3(("[DramcRxdqsGatingCal] Done\n\n"));
+        mcFPRINTF((fp_A60501, "[DramcRxdqsGatingCal] Done\n\n"));
+
+        return DRAM_OK;
+        // log example
+        /*
+    0   1  12 |(B3->B0) 0x   0, 0x1211, 0x1212, 0x1211 | (B3->B0) 11 11  11 11  11 11  11 11 | 0xffffffff
+    0   1  16 |(B3->B0) 0x   0, 0x1211, 0x1212, 0x1211 | (B3->B0) 11 11  11 11  11 11  11 11 | 0xffffffff
+    0   1  20 |(B3->B0) 0x   0, 0x1211, 0x1212, 0x1211 | (B3->B0) 11 11  11 11  11 11  11 11 | 0xffffffff
+    0   1  24 |(B3->B0) 0x   0, 0x1211, 0x1212, 0x1211 | (B3->B0) 11 11  11 11  11 11  11 11 | 0xffffffff
+    0   1  28 |(B3->B0) 0x   0, 0x1211, 0x1212, 0x1211 | (B3->B0) 11 11  11 11  11 11  11 11 | 0xffffffff
+    0   2   0 |(B3->B0) 0x   0, 0x1d1c, 0x1212, 0x1211 | (B3->B0) 11 11  11 11  11 11  11 11 | 0xffffffff
+    0   2   4 |(B3->B0) 0x   0, 0x2324, 0x1212, 0x1413 | (B3->B0) 11 11   0  0  11 11  11 11 | 0xffffffff
+    0   2   8 |(B3->B0) 0x   0, 0x2323, 0x1212, 0x2222 | (B3->B0)  0  0   0  0  11 11  11 11 | 0xff00ffff
+    0   2  12 |(B3->B0) 0x   0, 0x2323, 0x1211, 0x2323 | (B3->B0)  0  0   0  0  11 11   0  0 | 0x    ffff
+    0   2  16 |(B3->B0) 0x   0, 0x2323, 0x 504, 0x2324 | (B3->B0)  0  0   0  0  11 11   0  0 | 0x    ff00
+    0   2  20 |(B3->B0) 0x   0, 0x2323, 0x 303, 0x2323 | (B3->B0)  0  0   0  0   1  1   0  0 | 0x    ff00
+    0   2  24 |(B3->B0) 0x   0, 0x2323, 0x2324, 0x2323 | (B3->B0)  0  0   0  0   0  0   0  0 | 0x       0
+    0   2  28 |(B3->B0) 0x   0, 0x2323, 0x2323, 0x2323 | (B3->B0)  0  0   0  0   0  0   0  0 | 0x       0
+    0   3   0 |(B3->B0) 0x   0, 0x2323, 0x2323, 0x2323 | (B3->B0)  0  0   0  0   0  0   0  0 | 0x       0
+    0   3   4 |(B3->B0) 0x   0, 0x2323, 0x2323, 0x2323 | (B3->B0)  0  0   0  0   0  0   0  0 | 0x       0
+    0   3   8 |(B3->B0) 0x   0, 0x2323, 0x2323, 0x2323 | (B3->B0)  0  0   0  0   0  0   0  0 | 0x       0
+    0   3  12 |(B3->B0) 0x   0, 0x2323, 0x2323, 0x2323 | (B3->B0)  0  0   0  0   0  0   0  0 | 0x       0
+    0   3  16 |(B3->B0) 0x   0, 0x2323, 0x2323, 0x2323 | (B3->B0)  0  0   0  0   0  0   0  0 | 0x       0
+    0   3  20 |(B3->B0) 0x   0, 0x2323, 0x2323, 0x2323 | (B3->B0)  0  0   0  0   0  0   0  0 | 0x       0
+    0   3  24 |(B3->B0) 0x   0, 0x2323, 0x2323, 0x2323 | (B3->B0)  0  0   0  0   0  0   0  0 | 0x       0
+    0   3  28 |(B3->B0) 0x   0, 0x2323, 0x2323, 0x2323 | (B3->B0)  0  0   0  0   0  0   0  0 | 0x       0
+    1   0   0 |(B3->B0) 0x   0, 0x2120, 0x2323, 0x2323 | (B3->B0) 11 11  11 11   0  0   0  0 | 0xffff0000
+    1   0   4 |(B3->B0) 0x   0, 0x2323, 0x2323, 0x1212 | (B3->B0) 11 11   0  0   0  0  11 11 | 0xffff00ff
+    1   0   8 |(B3->B0) 0x   0, 0x2324, 0x2323, 0x2323 | (B3->B0)  0  0   0  0   0  0   0  0 | 0xffff00ff
+    1   0  12 |(B3->B0) 0x   0, 0x2323, 0x2323, 0x2323 | (B3->B0)  0  0   0  0   0  0   0  0 | 0xffff00ff
+    1   0  16 |(B3->B0) 0x   0, 0x2323, 0x1f1f, 0x2323 | (B3->B0)  0  0   0  0  11 11   0  0 | 0xffffffff
+    1   0  20 |(B3->B0) 0x   0, 0x2323, 0x2324, 0x2323 | (B3->B0)  0  0   0  0   0  0   0  0 | 0xffffffff
+    1   0  24 |(B3->B0) 0x   0, 0x2323, 0x2323, 0x2323 | (B3->B0)  0  0   0  0   0  0   0  0 | 0xffffffff
+    1   0  28 |(B3->B0) 0x   0, 0x2322, 0x2324, 0x2323 | (B3->B0) 11 11  11 11   0  0   0  0 | 0x    ffff
+    1   1   0 |(B3->B0) 0x   0, 0x2322, 0x2324, 0x2323 | (B3->B0) 11 11  11 11   0  0   0  0 | 0xffffffff
+    1   1   4 |(B3->B0) 0x   0, 0x2323, 0x2324, 0x2322 | (B3->B0) 11 11  11 11   0  0  11 11 | 0xffffff00
+    1   1   8 |(B3->B0) 0x   0, 0x2323, 0x2324, 0x2322 | (B3->B0) 11 11  11 11  11 11  11 11 | 0xffffffff
+    1   1  12 |(B3->B0) 0x   0, 0x2323, 0x2323, 0x2323 | (B3->B0) 11 11  11 11  11 11  11 11 | 0xffffffff
+    1   1  16 |(B3->B0) 0x   0, 0x2323, 0x2322, 0x2323 | (B3->B0) 11 11  11 11  11 11  11 11 | 0xffffffff
+    1   1  20 |(B3->B0) 0x   0, 0x2323, 0x2323, 0x2323 | (B3->B0) 11 11  11 11  11 11  11 11 | 0xffffffff
+    1   1  24 |(B3->B0) 0x   0, 0x2323, 0x2323, 0x2323 | (B3->B0) 11 11  11 11  11 11  11 11 | 0xffffffff
+    1   1  28 |(B3->B0) 0x   0, 0x2323, 0x2323, 0x2323 | (B3->B0) 11 11  11 11  11 11  11 11 | 0xffffffff
+    1   2   0 |(B3->B0) 0x   0, 0x1a1b, 0x2323, 0x2323 | (B3->B0) 11 11  11 11  11 11  11 11 | 0xffffffff
+    1   2   4 |(B3->B0) 0x   0, 0x1a1b, 0x2323, 0x1e1f | (B3->B0)  0  0  11 11  11 11   0  0 | 0xffffffff
+
+   ===============================================================================
+       dqs input gating widnow, final delay value
+       channel=2(2:cha, 3:chb)
+   ===============================================================================
+   test2_1: 0x55000000, test2_2: 0xaa000400, test pattern: 5
+   dqs input gating widnow, best delay value
+   ===============================================================================
+   best DQS0 delay(2T, 0.5T, PI) = (0, 3, 12)
+   best DQS1 delay(2T, 0.5T, PI) = (0, 3, 22)
+   best DQS2 delay(2T, 0.5T, PI) = (0, 3, 4)
+   best DQS3 delay(2T, 0.5T, PI) = (0, 3, 4)
+   ===============================================================================
+   best DQS0 P1 delay(2T, 0.5T, PI) = (1, 1, 12)
+   best DQS1 P1 delay(2T, 0.5T, PI) = (1, 1, 22)
+   best DQS2 P1 delay(2T, 0.5T, PI) = (1, 1, 4)
+   best DQS3 P1 delay(2T, 0.5T, PI) = (1, 1, 4)
+   ===============================================================================
+   [DramcRxdqsGatingCal] ====Done====
+
+*/
+}
+
+#if GATING_ADJUST_TXDLY_FOR_TRACKING
+void DramcRxdqsGatingPostProcess(DRAMC_CTX_T *p)
+{
+    U8 dqs_i;
+#if ENABLE_LP3_SW
+    U8 u1RankRxDVS=0;
+#endif
+    U8 u1RankIdx, u1RankMax;
+    S8 s1ChangeDQSINCTL;
+    U32 backup_rank;
+    U32 u4ReadDQSINCTL, u4ReadTXDLY[RANK_MAX][DQS_NUMBER], u4ReadTXDLY_P1[RANK_MAX][DQS_NUMBER], u4RankINCTL_ROOT, u4XRTR2R, reg_TX_dly_DQSgated_min = 0;
+
+    backup_rank = u1GetRank(p);
+
+#ifdef XRTR2R_PERFORM_ENHANCE_DQSG_RX_DLY
+    if (u1IsLP4Family(p->dram_type))
+    {
+        // wei-jen: DQSgated_min should be 2 when freq >= 1333, 1 when freq < 1333
+        if (p->frequency >= 1333)
+        {
+            reg_TX_dly_DQSgated_min = 2;
+        }
+        else
+        {
+            reg_TX_dly_DQSgated_min = 1;
+        }
+    }
+#if ENABLE_LP3_SW
+    else
+    {
+        // 1866,1600,1333,1200  : reg_TX_dly_DQSgated (min) =2
+        reg_TX_dly_DQSgated_min = 2;
+    }
+#endif /* ENABLE_LP3_SW */
+#else
+    if (u1IsLP4Family(p->dram_type))
+    {
+        // wei-jen: DQSgated_min should be 3 when freq >= 1333, 2 when freq < 1333
+        if (p->frequency >= 1333)
+        {
+            reg_TX_dly_DQSgated_min = 3;
+        }
+        else
+        {
+            reg_TX_dly_DQSgated_min = 2;
+        }
+    }
+#if ENABLE_LP3_SW
+    else
+    {
+        // 800  : reg_TX_dly_DQSgated (min) =2
+        // 1066 : reg_TX_dly_DQSgated (min) =2
+        // 1270 : reg_TX_dly_DQSgated (min) =2
+        // 1600 : reg_TX_dly_DQSgated (min) =3
+        // 1866 : reg_TX_dly_DQSgated (min) =3
+        if(p->frequency < 700)
+        {
+            reg_TX_dly_DQSgated_min = 2;
+        }
+        else
+        {
+            reg_TX_dly_DQSgated_min = 3;
+        }
+    }
+#endif /* ENABLE_LP3_SW */
+#endif
+#if ENABLE_LP3_SW
+    // === Begin of DVS setting =====
+    //RANKRXDVS = reg_TX_dly_DQSgated (min) -1 = Roundup(tDQSCKdiff/MCK)
+    if (!u1IsLP4Family(p->dram_type))
+    {
+        if(reg_TX_dly_DQSgated_min>1)
+        {
+            u1RankRxDVS = reg_TX_dly_DQSgated_min -1;
+        }
+        else
+        {
+            u1RankRxDVS=0;
+            mcSHOW_ERR_MSG(("[RxdqsGatingPostProcess] u1RankRxDVS <1,  Please check!\n"));
+        }
+    }
+#endif
+//Sylvia MP setting is switched to new mode, so RANKRXDVS can be set as 0 (review by HJ Huang)
+#if 0
+    if(u1IsLP4Family(p->dram_type))
+    {
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ7), u1RankRxDVS, SHU1_B0_DQ7_R_DMRANKRXDVS_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ7), u1RankRxDVS, SHU1_B1_DQ7_R_DMRANKRXDVS_B1);
+    }
+#endif
+#if ENABLE_LP3_SW
+        for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+        {
+            vIO32WriteFldAlign_Phy_Byte(dqs_i, DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ7), u1RankRxDVS, SHU1_B0_DQ7_R_DMRANKRXDVS_B0);
+        }
+#endif /* ENABLE_LP3_SW */
+    // === End of DVS setting =====
+
+    s1ChangeDQSINCTL = reg_TX_dly_DQSgated_min- u1TXDLY_Cal_min;
+
+    mcSHOW_DBG_MSG(("[RxdqsGatingPostProcess] freq %d\n"
+                    "ChangeDQSINCTL %d, reg_TX_dly_DQSgated_min %d, u1TXDLY_Cal_min %d\n",
+                        p->frequency,
+                        s1ChangeDQSINCTL, reg_TX_dly_DQSgated_min, u1TXDLY_Cal_min));
+
+    if(s1ChangeDQSINCTL!=0)  // need to change DQSINCTL and TXDLY of each byte
+    {
+        u1TXDLY_Cal_min += s1ChangeDQSINCTL;
+        u1TXDLY_Cal_max += s1ChangeDQSINCTL;
+
+        if (p->support_rank_num==RANK_DUAL)
+            u1RankMax = RANK_MAX;
+        else
+             u1RankMax =RANK_1;
+
+        for(u1RankIdx=0; u1RankIdx<u1RankMax; u1RankIdx++)
+        {
+            mcSHOW_DBG_MSG2(("Rank: %d\n", u1RankIdx));
+
+            for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+            {
+                if(u1IsLP4Family(p->dram_type))
+                {
+                    u4ReadTXDLY[u1RankIdx][dqs_i]= ucbest_coarse_tune2T_backup[u1RankIdx][dqs_i];
+                    u4ReadTXDLY_P1[u1RankIdx][dqs_i]= ucbest_coarse_tune2T_P1_backup[u1RankIdx][dqs_i];
+
+                    u4ReadTXDLY[u1RankIdx][dqs_i] += s1ChangeDQSINCTL;
+                    u4ReadTXDLY_P1[u1RankIdx][dqs_i] += s1ChangeDQSINCTL;
+
+                    ucbest_coarse_tune2T_backup[u1RankIdx][dqs_i] = u4ReadTXDLY[u1RankIdx][dqs_i];
+                    ucbest_coarse_tune2T_P1_backup[u1RankIdx][dqs_i] = u4ReadTXDLY_P1[u1RankIdx][dqs_i];
+                }
+                else
+                {
+                    u4ReadTXDLY[u1RankIdx][dqs_i]= ((ucbest_coarse_tune2T_backup[u1RankIdx][dqs_i]<<1) + ((ucbest_coarse_tune0p5T_backup[u1RankIdx][dqs_i]>>2) & 0x1));
+                    u4ReadTXDLY_P1[u1RankIdx][dqs_i]= ((ucbest_coarse_tune2T_P1_backup[u1RankIdx][dqs_i]<<1) + ((ucbest_coarse_tune0p5T_P1_backup[u1RankIdx][dqs_i]>>2) & 0x1));
+
+                    u4ReadTXDLY[u1RankIdx][dqs_i] += s1ChangeDQSINCTL;
+                    u4ReadTXDLY_P1[u1RankIdx][dqs_i] += s1ChangeDQSINCTL;
+
+                    ucbest_coarse_tune2T_backup[u1RankIdx][dqs_i] = (u4ReadTXDLY[u1RankIdx][dqs_i] >>1);
+                    ucbest_coarse_tune0p5T_backup[u1RankIdx][dqs_i] = ((u4ReadTXDLY[u1RankIdx][dqs_i] & 0x1) <<2)+(ucbest_coarse_tune0p5T_backup[u1RankIdx][dqs_i] & 0x3);
+
+                    ucbest_coarse_tune2T_P1_backup[u1RankIdx][dqs_i] = (u4ReadTXDLY_P1[u1RankIdx][dqs_i] >>1);
+                    ucbest_coarse_tune0p5T_P1_backup[u1RankIdx][dqs_i] = ((u4ReadTXDLY_P1[u1RankIdx][dqs_i] & 0x1)<<2) +(ucbest_coarse_tune0p5T_P1_backup[u1RankIdx][dqs_i] & 0x3);
+                }
+                mcSHOW_DBG_MSG(("best DQS%d dly(2T, 0.5T) = (%d, %d)\n", dqs_i, ucbest_coarse_tune2T_backup[u1RankIdx][dqs_i], ucbest_coarse_tune0p5T_backup[u1RankIdx][dqs_i]));
+            }
+
+            for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+            {
+                mcSHOW_DBG_MSG(("best DQS%d P1 dly(2T, 0.5T) = (%d, %d)\n", dqs_i, ucbest_coarse_tune2T_P1_backup[u1RankIdx][dqs_i], ucbest_coarse_tune0p5T_P1_backup[u1RankIdx][dqs_i]));
+            }
+        }
+
+        for(u1RankIdx=0; u1RankIdx<u1RankMax; u1RankIdx++)
+        {
+            vSetRank(p, u1RankIdx);
+            // 4T or 2T coarse tune
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQSG0), \
+                                    P_Fld((U32) ucbest_coarse_tune2T_backup[u1RankIdx][0], SHURK0_SELPH_DQSG0_TX_DLY_DQS0_GATED)| \
+                                    P_Fld((U32) ucbest_coarse_tune2T_backup[u1RankIdx][1], SHURK0_SELPH_DQSG0_TX_DLY_DQS1_GATED)| \
+                                    P_Fld((U32) ucbest_coarse_tune2T_backup[u1RankIdx][2], SHURK0_SELPH_DQSG0_TX_DLY_DQS2_GATED)| \
+                                    P_Fld((U32) ucbest_coarse_tune2T_backup[u1RankIdx][3], SHURK0_SELPH_DQSG0_TX_DLY_DQS3_GATED)| \
+                                    P_Fld((U32) ucbest_coarse_tune2T_P1_backup[u1RankIdx][0], SHURK0_SELPH_DQSG0_TX_DLY_DQS0_GATED_P1)| \
+                                    P_Fld((U32) ucbest_coarse_tune2T_P1_backup[u1RankIdx][1], SHURK0_SELPH_DQSG0_TX_DLY_DQS1_GATED_P1)| \
+                                    P_Fld((U32) ucbest_coarse_tune2T_P1_backup[u1RankIdx][2], SHURK0_SELPH_DQSG0_TX_DLY_DQS2_GATED_P1)| \
+                                    P_Fld((U32) ucbest_coarse_tune2T_P1_backup[u1RankIdx][3], SHURK0_SELPH_DQSG0_TX_DLY_DQS3_GATED_P1));
+
+                // 0.5T coarse tune
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQSG1), \
+                                    P_Fld((U32) ucbest_coarse_tune0p5T_backup[u1RankIdx][0], SHURK0_SELPH_DQSG1_REG_DLY_DQS0_GATED)| \
+                                    P_Fld((U32) ucbest_coarse_tune0p5T_backup[u1RankIdx][1], SHURK0_SELPH_DQSG1_REG_DLY_DQS1_GATED)| \
+                                    P_Fld((U32) ucbest_coarse_tune0p5T_backup[u1RankIdx][2], SHURK0_SELPH_DQSG1_REG_DLY_DQS2_GATED)| \
+                                    P_Fld((U32) ucbest_coarse_tune0p5T_backup[u1RankIdx][3], SHURK0_SELPH_DQSG1_REG_DLY_DQS3_GATED)| \
+                                    P_Fld((U32) ucbest_coarse_tune0p5T_P1_backup[u1RankIdx][0], SHURK0_SELPH_DQSG1_REG_DLY_DQS0_GATED_P1)| \
+                                    P_Fld((U32) ucbest_coarse_tune0p5T_P1_backup[u1RankIdx][1], SHURK0_SELPH_DQSG1_REG_DLY_DQS1_GATED_P1)| \
+                                    P_Fld((U32) ucbest_coarse_tune0p5T_P1_backup[u1RankIdx][2], SHURK0_SELPH_DQSG1_REG_DLY_DQS2_GATED_P1)| \
+                                    P_Fld((U32) ucbest_coarse_tune0p5T_P1_backup[u1RankIdx][3], SHURK0_SELPH_DQSG1_REG_DLY_DQS3_GATED_P1));
+        }
+    }
+    vSetRank(p, backup_rank);
+
+    u4ReadDQSINCTL = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_DQSCTL), SHURK0_DQSCTL_DQSINCTL);
+    u4ReadDQSINCTL -= s1ChangeDQSINCTL;
+
+    #if ENABLE_READ_DBI
+    U32 u4ReadRODT;
+    if(p->DBI_R_onoff[p->dram_fsp])
+    {
+      u4ReadDQSINCTL++;
+      u4ReadRODT = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_ODTCTRL), SHU_ODTCTRL_RODT);
+      vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_ODTCTRL), u4ReadRODT+1, SHU_ODTCTRL_RODT); //update RODT value when READ_DBI is on
+    }
+    #endif
+
+#ifdef XRTR2R_PERFORM_ENHANCE_DQSG_RX_DLY
+    // Wei-Jen: RANKINCTL_RXDLY = RANKINCTL = RankINCTL_ROOT = u4ReadDQSINCTL-2, if XRTR2R_PERFORM_ENHANCE_DQSG_RX_DLY enable
+    // Wei-Jen: New algorithm : u4ReadDQSINCTL-2 >= 0
+    if(u4ReadDQSINCTL>=2)
+    {
+        u4RankINCTL_ROOT = u4ReadDQSINCTL-2;
+    }
+    else
+    {
+        u4RankINCTL_ROOT=0;
+        mcSHOW_ERR_MSG(("u4RankINCTL_ROOT <2, Please check\n"));
+#if (__ETT__)
+        while(1);
+#endif
+    }
+#else
+    //Modify for corner IC failed at HQA test XTLV
+    if(u4ReadDQSINCTL>=3)
+    {
+        u4RankINCTL_ROOT = u4ReadDQSINCTL-3;
+    }
+    else
+    {
+        u4RankINCTL_ROOT=0;
+        mcSHOW_ERR_MSG(("u4RankINCTL_ROOT <3, Risk for supporting 1066/RL8\n"));
+    }
+#endif
+
+    //DQSINCTL
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_DQSCTL), u4ReadDQSINCTL, SHURK0_DQSCTL_DQSINCTL);  //Rank0 DQSINCTL
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK1_DQSCTL), u4ReadDQSINCTL, SHURK1_DQSCTL_R1DQSINCTL); //Rank1 DQSINCTL
+
+    //No need to update RODT. If we update RODT, also need to update SELPH_ODTEN0_TXDLY
+    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_ODTCTRL), u4ReadDQSINCTL, SHU_ODTCTRL_RODT);           //RODT = DQSINCTL
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_RANKCTL), u4ReadDQSINCTL, SHU_RANKCTL_RANKINCTL_PHY);  //RANKINCTL_PHY = DQSINCTL
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_RANKCTL), u4RankINCTL_ROOT, SHU_RANKCTL_RANKINCTL);  //RANKINCTL= DQSINCTL -3
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_RANKCTL), u4RankINCTL_ROOT, SHU_RANKCTL_RANKINCTL_ROOT1);  //RANKINCTL_ROOT1= DQSINCTL -3
+#ifdef XRTR2R_PERFORM_ENHANCE_DQSG_RX_DLY
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_RANKCTL), u4RankINCTL_ROOT, SHU_RANKCTL_RANKINCTL_RXDLY);
+
+    u4XRTR2R= u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_ACTIM_XRT), SHU_ACTIM_XRT_XRTR2R);
+
+    mcSHOW_DBG_MSG2(("TX_dly_DQSgated check: min %d  max %d, ChangeDQSINCTL=%d\n", u1TXDLY_Cal_min, u1TXDLY_Cal_max, s1ChangeDQSINCTL));
+    mcSHOW_DBG_MSG2(("DQSINCTL=%d, RANKINCTL=%d, u4XRTR2R=%d\n", u4ReadDQSINCTL, u4RankINCTL_ROOT, u4XRTR2R));
+
+#else
+    //XRTR2R=A-phy forbidden margin(6T) + reg_TX_dly_DQSgated (max) +Roundup(tDQSCKdiff/MCK+0.25MCK)+1(05T sel_ph margin)-1(forbidden margin overlap part)
+    //Roundup(tDQSCKdiff/MCK+1UI) =1~2 all LP3 and LP4 timing
+    //u4XRTR2R= 8 + u1TXDLY_Cal_max;  // 6+ u1TXDLY_Cal_max +2
+
+    //Modify for corner IC failed at HQA test XTLV @ 3200MHz
+    u4XRTR2R= 8 + u1TXDLY_Cal_max + 1;  // 6+ u1TXDLY_Cal_max +2
+    if (u4XRTR2R > 12)
+    {
+        u4XRTR2R= 12;
+        mcSHOW_ERR_MSG(("XRTR2R > 12, Max value is 12\n"));
+    }
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_ACTIM_XRT), u4XRTR2R, SHU_ACTIM_XRT_XRTR2R);
+
+    mcSHOW_DBG_MSG2(("TX_dly_DQSgated check: min %d  max %d, ChangeDQSINCTL=%d\n", u1TXDLY_Cal_min, u1TXDLY_Cal_max, s1ChangeDQSINCTL));
+    mcSHOW_DBG_MSG2(("DQSINCTL=%d, RANKINCTL=%d, u4XRTR2R=%d\n", u4ReadDQSINCTL, u4RankINCTL_ROOT, u4XRTR2R));
+
+#endif
+
+#if 0//ENABLE_RODT_TRACKING
+    //Because Kibo+,WE2,Bianco,Vinson...or behind project support WDQS, they need to apply the correct new setting
+    //The following 2 items are indepentent
+    //1. if TX_WDQS on(by vendor_id) or p->odt_onoff = 1, ROEN/RODTE/RODTE2 = 1
+    //2. if ENABLE_RODT_TRACKING on, apply new setting and RODTEN_MCK_MODESEL = ROEN
+    // LP4 support only
+    if (u1IsLP4Family(p->dram_type))
+    {
+        U8 u1ReadROEN;
+        u1ReadROEN = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_ODTCTRL), SHU_ODTCTRL_ROEN);
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU_RODTENSTB), P_Fld(0xff, SHU_RODTENSTB_RODTENSTB_EXT)|\
+                                                                P_Fld(9, SHU_RODTENSTB_RODTENSTB_OFFSET)|\
+                                                                P_Fld(u1ReadROEN, SHU_RODTENSTB_RODTEN_MCK_MODESEL));
+    }
+#endif
+#ifdef XRTR2W_PERFORM_ENHANCE_RODTEN
+    // LP4 support only
+    if (u1IsLP4Family(p->dram_type))
+    {
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU_RODTENSTB), P_Fld(0x0fff, SHU_RODTENSTB_RODTENSTB_EXT)|\
+                                                                P_Fld(1, SHU_RODTENSTB_RODTEN_P1_ENABLE)|\
+                                                                P_Fld(1, SHU_RODTENSTB_RODTEN_MCK_MODESEL));
+    }
+#endif
+
+
+    vSetRank(p, backup_rank);
+
+
+}
+#endif
+
+
+#if GATING_ADJUST_TXDLY_FOR_TRACKING
+void DramcRxdqsGatingPreProcess(DRAMC_CTX_T *p)
+{
+    u1TXDLY_Cal_min =0xff;
+    u1TXDLY_Cal_max=0;
+}
+#endif
+#endif //SIMULATION_GATING
+
+//-------------------------------------------------------------------------
+/** DramcRxWindowPerbitCal (v2 version)
+ *  start the rx dqs perbit sw calibration.
+ *  @param p                Pointer of context created by DramcCtxCreate.
+ *  @retval status          (DRAM_STATUS_T): DRAM_OK or DRAM_FAIL
+ */
+//-------------------------------------------------------------------------
+// default RX vref is 0xe=14
+static void DramcRxWinRDDQCInit(DRAMC_CTX_T *p)
+{
+    U8 *uiLPDDR_MRR_Mapping;
+    U16 temp_value=0;
+    U8 MR_GOLDEN_MR15_GOLDEN_value=0, MR_GOLDEN_MR20_GOLDEN_value=0;
+    int i;
+
+    //U8 u1ReadDBIbak[2];
+    //U32 u4MRS_reg_bak;
+
+    // Disable Read DBI
+    //u1ReadDBIbak[0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ7), SHU1_B0_DQ7_R_DMDQMDBI_SHU_B0);
+    //u1ReadDBIbak[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ7), SHU1_B1_DQ7_R_DMDQMDBI_SHU_B1);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ7),  0, SHU1_B0_DQ7_R_DMDQMDBI_SHU_B0);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ7),  0, SHU1_B1_DQ7_R_DMDQMDBI_SHU_B1);
+    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), 1, SPCMDCTRL_RDDQCDIS); Moved to "DramcRxWinRDDQCRun()"
+
+    //u4MRS_reg_bak = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_MRS));
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRS), u1GetRank(p), MRS_MRSRK);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MPC_OPTION), 1, MPC_OPTION_MPCRKEN);
+    uiLPDDR_MRR_Mapping = (U8 *)uiLPDDR4_MRR_Mapping_POP[p->channel];
+
+    for(i=0; i<16; i++)
+    {
+        temp_value |= ((0x5555 >> i) & 0x1) << uiLPDDR_MRR_Mapping[i];
+    }
+    MR_GOLDEN_MR15_GOLDEN_value = (U8) temp_value & 0xff;
+    MR_GOLDEN_MR20_GOLDEN_value = (U8) (temp_value>>8) & 0xff;
+    //Set golden pattern from Shih-hsiu's suggestion. 2016/3/25 04:43pm, RE: [Olympus] RX per bit calibration.
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_MR_GOLDEN), P_Fld(MR_GOLDEN_MR15_GOLDEN_value, MR_GOLDEN_MR15_GOLDEN) | P_Fld(MR_GOLDEN_MR20_GOLDEN_value, MR_GOLDEN_MR20_GOLDEN));
+
+    //MPC_RDDQC_SET_MRS
+    //Write MR32 DQ calibration pattern A //skip it if you want default 5Ah
+    //Write MR40 DQ calibration pattern B //skip it if you want default 3Ch
+    //Write MR15 low byte inverter for DQ calibration (byte 0) //skip it if you want default 55h
+    //Write MR20 uper byte inverter for DQ calibration (byte 1) //skip it if you want default aah
+    //DramcModeRegWrite(p, 32, 0x86);
+    //DramcModeRegWrite(p, 40, 0xC9);
+    //DramcModeRegWrite(p, 32, 0xaa);
+    //DramcModeRegWrite(p, 32, 0xbb);
+}
+
+/* Issue "RD DQ Calibration"
+ * 1. RDDQCEN = 1 for RDDQC
+ * 2. RDDQCDIS = 1 to stop RDDQC burst
+ * 3. Wait rddqc_response = 1
+ * 4. Read compare result
+ * 5. RDDQCEN = 0
+ * 6. RDDQCDIS = 0 (Stops RDDQC request)
+ */
+static U32 DramcRxWinRDDQCRun(DRAMC_CTX_T *p)
+{
+    U32 u4Result, u4Response;
+    U32 u4TimeCnt= TIME_OUT_CNT;
+
+    //Issue RD DQ calibration
+    //R_DMRDDQCEN, 0x1E4[7]=1 for RDDQC,  R_DMRDDQCDIS, 0x1EC[26]=1 to stop RDDQC burst
+    //Wait rddqc_response=1, (dramc_conf_nao, 0x3b8[31])
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), 1, SPCMDCTRL_RDDQCDIS);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_RDDQCEN);
+    do
+    {
+        u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_RDDQC_RESPONSE);
+        u4TimeCnt --;
+        mcDELAY_US(1);
+    }while((u4Response ==0) &&(u4TimeCnt>0));
+
+    if(u4TimeCnt==0)//time out
+    {
+        mcSHOW_DBG_MSG(("[RxWinRDDQC] Resp fail (time out)\n"));
+        mcFPRINTF((fp_A60501, "[RxWinRDDQC] Resp fail (time out)\n"));
+        //return DRAM_FAIL;
+    }
+
+    //Then read RDDQC compare result (dramc_conf_nao, 0x36c)
+    u4Result = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_RDQC_CMP));
+    //R_DMRDDQCEN, 0x1E4[7]=0
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_RDDQCEN);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), 0, SPCMDCTRL_RDDQCDIS);
+
+    return u4Result;
+}
+
+static void DramcRxWinRDDQCEnd(DRAMC_CTX_T *p)
+{
+    //Recover Read DBI
+    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ7),  p->DBI_R_onoff, SHU1_B0_DQ7_R_DMDQMDBI_SHU_B0);
+    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ7),  p->DBI_R_onoff, SHU1_B1_DQ7_R_DMDQMDBI_SHU_B1);
+
+    // Recover MPC Rank
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRS), 0, MRS_MRSRK);
+}
+
+#ifdef MPC_SW_FIFO
+void DramcMPC_FIFO(DRAMC_CTX_T *p)
+{
+    U32 u4Result3,u4Result2,u4Result1,u4Result0;
+	U32 u4Result, u4Response;
+    U32 u4TimeCnt= TIME_OUT_CNT;
+    U32 u4RegBackupAddress[] =
+    {
+        (DRAMC_REG_ADDR(DRAMC_REG_LBWDAT3)),
+        (DRAMC_REG_ADDR(DRAMC_REG_LBWDAT2)),
+        (DRAMC_REG_ADDR(DRAMC_REG_LBWDAT1)),
+        (DRAMC_REG_ADDR(DRAMC_REG_LBWDAT0)),
+        (DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0)),
+        (DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL)),
+        (DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV)),
+        (DRAMC_REG_ADDR(DRAMC_REG_PERFCTL0)),
+    };
+
+
+    mcSHOW_DBG_MSG(("[DramcMPC_FIFO]\n"));
+ 	//Register backup
+    DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+	//WRFIFO and RDFIFO's golden data
+	vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_LBWDAT3), 0xAAAAAAAA, LBWDAT3_LBWDATA3);
+	vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_LBWDAT2), 0x55555555, LBWDAT2_LBWDATA2);
+	vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_LBWDAT1), 0xAAAAAAAA, LBWDAT1_LBWDATA1);
+	vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_LBWDAT0), 0x55555555, LBWDAT0_LBWDATA0);
+
+	u4Result3 = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_LBWDAT3));
+	mcSHOW_DBG_MSG(("DRAMC_REG_LBWDAT3: 0x%x\n", u4Result3));
+	mcFPRINTF((fp_A60501, "DRAMC_REG_LBWDAT3: 0x%x\n", u4Result3));
+	u4Result2 = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_LBWDAT2));
+	mcSHOW_DBG_MSG(("DRAMC_REG_LBWDAT2: 0x%x\n", u4Result2));
+	mcFPRINTF((fp_A60501, "DRAMC_REG_LBWDAT2: 0x%x\n", u4Result2));
+	u4Result1 = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_LBWDAT1));
+	mcSHOW_DBG_MSG(("DRAMC_REG_LBWDAT1: 0x%x\n", u4Result1));
+	mcFPRINTF((fp_A60501, "DRAMC_REG_LBWDAT1: 0x%x\n", u4Result1));
+	u4Result0 = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_LBWDAT0));
+	mcSHOW_DBG_MSG(("DRAMC_REG_LBWDAT0: 0x%x\n", u4Result0));
+	mcFPRINTF((fp_A60501, "DRAMC_REG_LBWDAT0: 0x%x\n", u4Result0));
+
+
+	//Other command is not valid during "WRFIFO and RDFIFO"  period.
+	//Disable auto refresh: set R_DMREFDIS=1
+    vAutoRefreshSwitch(p, DISABLE);
+	//Disable MR4: set R_DMREFRDIS=1
+	vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), 1, SPCMDCTRL_REFRDIS);
+	//Disable ZQCAL/ZQLAT command: set R_DMZQCALDISB=0
+	vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), 0, SPCMDCTRL_ZQCALDISB);
+
+
+	//When R_DMWRFIFOEN=1, MPC WRFIFO can send single request or 5 requests by R_DMRDDQC_INTV[1:0] (0x8C8[12:11])
+	//Set R_DMRDDQC_INTV=2'b00 and Set R_DMWRFIO_MODE2 = 1'b0 for single MPC WRFIFO (single mode)
+	//Set R_DMRDDQC_INTV=2'b01 and Set R_DMWRFIO_MODE2 = 1'b1 for five MPC WRFIFO (burst mode)
+	vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV), 0, SHU_SCINTV_RDDQC_INTV);
+	vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PERFCTL0), 0, PERFCTL0_WRFIO_MODE2);
+
+
+    //Issue MPC RD FIFO
+    //R_DMWRFIFOEN, 0x0C[31]=1 for WR FIFO
+	vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PERFCTL0), 1, PERFCTL0_WRFIFOEN);
+
+	//Wait wrfifo_response=1 (dramc_conf_nao, 0x88[31])
+    do
+    {
+        u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_WRFIFO_RESPONSE);
+        u4TimeCnt --;
+        mcDELAY_US(1);
+    }while((u4Response ==0) &&(u4TimeCnt>0));
+
+    if(u4TimeCnt==0)//time out
+    {
+        mcSHOW_DBG_MSG(("[DramcMPC_FIFO] Resp fail (time out)\n"));
+        mcFPRINTF((fp_A60501, "[DramcMPC_FIFO] Resp fail (time out)\n"));
+        //return DRAM_FAIL;
+    }
+
+    //R_DMWRFIFOEN, 0x0C[31]=0
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PERFCTL0), 0, PERFCTL0_WRFIFOEN);
+
+
+
+	//Issue MPC RD FIFO
+    //R_DMRDFIFOEN, 0x0C[30]=1 for RD FIFO
+	vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PERFCTL0), 1, PERFCTL0_RDFIFOEN);
+
+	//Wait wrfifo_response=1 (dramc_conf_nao, 0x88[31])
+    do
+    {
+        u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_RDFIFO_RESPONSE);
+        u4TimeCnt --;
+        mcDELAY_US(1);
+    }while((u4Response ==0) &&(u4TimeCnt>0));
+
+    if(u4TimeCnt==0)//time out
+    {
+        mcSHOW_DBG_MSG(("[DramcMPC_FIFO] Resp fail (time out)\n"));
+        mcFPRINTF((fp_A60501, "[DramcMPC_FIFO] Resp fail (time out)\n"));
+        //return DRAM_FAIL;
+    }
+
+    //Then read RDFIFO compare result (dramc_conf_nao, 0x124)
+    //Must do WRFIO first, then do RDFIFO, then compare it.
+    u4Result = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_CMP_ERR));
+	mcSHOW_DBG_MSG(("[DramcMPC_FIFO] Read RDFIFO compare result: 0x%x\n", u4Result));
+
+    //R_DMRDFIFOEN, 0x0C[30]=0
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PERFCTL0), 0, PERFCTL0_RDFIFOEN);
+
+	//Restore registers
+    DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+}
+#endif
+
+#ifdef ENABLE_POST_PACKAGE_REPAIR
+U8 global_sk_ppr_channel[SK_CHANNEL_BITS] = {0, 1}; //CHB //base on SK hynix_Repair_Guide_20180411.pdf
+U8 global_sk_ppr_rank[SK_RANK_BITS] = {0, 1}; //R1 of fail IC
+U8 global_sk_ppr_bank[SK_BANK_BITS] = {0, 0, 0, 0, 1, 0, 0, 0}; //Bank 4
+U8 global_sk_ppr_byte[SK_BYTE_BITS] = {0};
+U8 global_sk_ppr_row[SK_ROW_BITS] = {0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1}; //0x7154
+U8 global_sk_vendor_id = VENDOR_HYNIX;
+
+#ifdef POST_PACKAGE_REPAIR_LP4
+U8 TrasformToFailAddr(U8 *pArray ,U8 u1Size)
+{
+    U8 ucIdx = 0;
+    U8 ucFailAddr = 0xff;
+
+    for(ucIdx=0; ucIdx<u1Size; ucIdx++)//could only allow one channel/rank/bank wrong
+    {
+        if(pArray[ucIdx] == 1)
+        {
+            ucFailAddr = ucIdx;
+            break;
+        }
+    }
+
+    return ucFailAddr;
+}
+
+
+void DramcPostPackageRepair(DRAMC_CTX_T *p)
+{
+    U32 u4Response=0;
+    U32 u4TimeCnt= TIME_OUT_CNT;
+    U16 u2Value=0;
+    U16 u2FailRow = 0;
+    U8 ucFailChannel = 0xff;
+    U8 ucFailRK = 0xff;
+    U8 ucFailBK = 0xff;
+    U8 ucIdx = 0;
+
+    ucFailChannel = TrasformToFailAddr(global_sk_ppr_channel, SK_CHANNEL_BITS);
+    ucFailRK = TrasformToFailAddr(global_sk_ppr_rank, SK_RANK_BITS);
+    ucFailBK = TrasformToFailAddr(global_sk_ppr_bank, SK_BANK_BITS);
+    if((ucFailChannel == 0xff) || (ucFailRK == 0xff) || (ucFailBK == 0xff))
+    {
+        mcSHOW_ERR_MSG(("PPR Not assign channel/rank/bank!!\n"));
+        return;
+    }
+
+    for(ucIdx=0; ucIdx<SK_ROW_BITS; ucIdx++)//could only allow one bank wrong
+    {
+        u2FailRow += (global_sk_ppr_row[ucIdx] << ucIdx);
+    }
+
+    vSetPHY2ChannelMapping(p, ucFailChannel);//Based on usage; fail IC 1-18, LP4 need to assign channel && rank
+    vSetRank(p, ucFailRK);//Based on usage; fail IC 1-18, LP4 need to assign channel && rank
+
+    mcSHOW_DBG_MSG(("ucFailBK=0x%x, u2FailRow=0x%x\n", ucFailBK, u2FailRow));
+    mcSHOW_DBG_MSG(("[DramcPostPackageRepair]\n"
+                    "\n\tFreq=%d, CH=%d, Rank=%d\n", p->frequency, p->channel, p->rank));
+    mcFPRINTF((fp_A60501, "[DramcPostPackageRepair]"
+                          "\n\tFreq=%d, CH=%d, Rank=%d\n", p->frequency, p->channel, p->rank));
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRS), u1GetRank(p), MRS_MRSRK);
+
+    //1.DRAMC DCM freerun,
+    //R_DMDCMEN2(dramc conf AO 0x38[1])=0
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 0, DRAMC_PD_CTRL_DCMEN2);
+
+    //2.PHY DCM freerun,
+    //R_DMPHYCLKDYNGEN(dramc conf AO 0x38[30])=0
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 0, DRAMC_PD_CTRL_PHYCLKDYNGEN);
+
+    //3.Dram clock freerun,
+    //R_DMMIOCKCTRLOFF(dramc	conf AO 0x38[26])=1
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 1, DRAMC_PD_CTRL_MIOCKCTRLOFF);
+
+#if MRW_CHECK_ONLY
+    mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
+#endif
+
+    //MR25 contains one bit of readout per bank indicating that at least one resource is available for Post Package Repair programming.
+    DramcModeRegRead(p, 25, &u2Value);
+    mcSHOW_DBG_MSG(("Before PostPackageRepair, MR25 = 0x%x\n", u2Value & 0xFF));
+    mcFPRINTF((fp_A60501, "Before PostPackageRepair, MR25 = 0x%x\n", u2Value & 0xFF));
+
+    //4.Fix CKE0 and CKE1 be high,
+    //R_DMCKEFIXON(dramc conf AO 0x24[6], CKECTRL.CKEFIXON)=1
+    //R_DMCKE1FIXON(dramc conf AO 0x24[4], CKECTRL.CKE1FIXON)=1
+    CKEFixOnOff(p, CKE_WRITE_TO_ALL_RANK, CKE_FIXON, CKE_WRITE_TO_ALL_CHANNEL);
+
+    //Step 0: disable refresh for PPR
+    //Let R_DMREFDIS=1
+    vAutoRefreshSwitch(p, DISABLE);
+
+    //Step 1: before enter PPR mode, all banks must be precharged
+    //Set R_DMPREAEN=1
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_PREAEN);
+    mcDELAY_US(1);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_PREAEN);
+
+    //wait dramc_conf_nao.prea_response=1
+    u4TimeCnt= TIME_OUT_CNT;
+    u4Response = 0;
+    do
+    {
+        u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_PREA_RESPONSE);
+        u4TimeCnt --;
+        mcDELAY_US(1);
+    }while((u4Response ==0) &&(u4TimeCnt>0));
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_PREAEN);
+
+    if(u4TimeCnt==0)//time out
+    {
+        mcSHOW_DBG_MSG(("dramc_conf_nao.prea_response fail (time out)\n"));
+        mcFPRINTF((fp_A60501, "dramc_conf_nao.prea_response fail (time out)\n"));
+        //return DRAM_FAIL;
+    }
+
+    //Step 2: enter PPR mode
+    if(global_sk_vendor_id == VENDOR_HYNIX) //Skhynix Manufacturer ID
+    {
+        //Skhynix DRAM PPR Enable Sequence
+        //Assumption: MR3 OP<2> - LOW
+        //Skhynix 2z 6Gb/4Gb LPDDR4x PPR Guard key
+        //PPR Guard Key, MR9 with following OP codes : B8 - E8 - 98 - BF - EF - 9F - B9 - E9 - 99 - 84 - A2 - 81
+        //Skhynix 2z 8Gb LPDDR4x PPR Guard key
+        //PPR Guard Key, MR9 with following OP codes : CD - AD -FD -C9 -A9 -F9 -C7 -A7 -F7
+        DramcModeRegWrite(p, 9, 0xB8);
+        DramcModeRegWrite(p, 9, 0xE8);
+        DramcModeRegWrite(p, 9, 0x98);
+        DramcModeRegWrite(p, 9, 0xBF);
+        DramcModeRegWrite(p, 9, 0xEF);
+        DramcModeRegWrite(p, 9, 0x9F);
+        DramcModeRegWrite(p, 9, 0xB9);
+        DramcModeRegWrite(p, 9, 0xE9);
+        DramcModeRegWrite(p, 9, 0x99);
+        DramcModeRegWrite(p, 9, 0x84);
+        DramcModeRegWrite(p, 9, 0xA2);
+        DramcModeRegWrite(p, 9, 0x81);
+    }
+
+    //Set MR4[4]=1: PPR entry
+    DramcModeRegWrite(p, 4, 0x10);
+
+    //Step 3: wait tMRD
+    //mcDELAY_US(1000);
+    mcDELAY_MS(1000);
+
+    //Step 4: issue ACT command with fail row address
+    //Set R_DMACTEN_ROW, R_DMACTEN_BK, then set R_DMACTEN,
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MPC_OPTION), 1, MPC_OPTION_MPCRKEN);
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PPR_CTRL), u2FailRow, PPR_CTRL_ACTEN_ROW);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PPR_CTRL), ucFailBK, PPR_CTRL_ACTEN_BK);
+    mcSHOW_DBG_MSG(("PPR, Fail Row = 0x%x,  Fail Bank = 0x%x\n", u2FailRow, ucFailBK));
+    mcFPRINTF((fp_A60501, "PPR, Fail Row = 0x%x,  Fail Bank = 0x%x\n", u2FailRow, ucFailBK));
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_ACTEN);
+    mcDELAY_US(1);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_ACTEN);
+
+    //wait dramc_conf_nao.act_response=1
+    u4TimeCnt= TIME_OUT_CNT;
+    u4Response=0;
+    do
+    {
+        u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_ACT_RESPONSE);
+        u4TimeCnt --;
+        mcDELAY_US(1);
+    }while((u4Response ==0) &&(u4TimeCnt>0));
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_ACTEN);
+
+    if(u4TimeCnt==0)//time out
+    {
+        mcSHOW_DBG_MSG(("dramc_conf_nao.act_response fail (time out)\n"));
+        mcFPRINTF((fp_A60501, "dramc_conf_nao.act_response fail (time out)\n"));
+        //return DRAM_FAIL;
+    }
+
+    //Step 5: wait tPGM to allow DRAM repair internally
+    mcDELAY_MS(3000);
+
+    //Step 6: issue PRE
+    //Set R_DMPREAEN=1
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_PREAEN);
+    mcDELAY_US(1);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_PREAEN);
+
+    //wait dramc_conf_nao.prea_response=1
+    u4TimeCnt= TIME_OUT_CNT;
+    u4Response=0;
+    do
+    {
+        u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_PREA_RESPONSE);
+        u4TimeCnt --;
+        mcDELAY_US(1);
+    }while((u4Response ==0) &&(u4TimeCnt>0));
+
+    if(u4TimeCnt==0)//time out
+    {
+        mcSHOW_DBG_MSG(("dramc_conf_nao.prea_response fail (time out)\n"));
+        mcFPRINTF((fp_A60501, "dramc_conf_nao.prea_response fail (time out)\n"));
+        //return DRAM_FAIL;
+    }
+
+    //Step 7: wait tPGM_Exit
+    //mcDELAY_US(1000);
+    mcDELAY_MS(1000);
+
+    //Step 8: exit PPR
+    //Set MR4[4]=0: PPR exit
+    DramcModeRegWrite(p, 4, 0x0);
+
+    //Step 9: wait tPGMPST, them dram is ready for any valid command
+    //mcDELAY_US(1000);
+    mcDELAY_MS(1000);
+
+    //MR25 contains one bit of readout per bank indicating that at least one resource is available for Post Package Repair programming.
+    DramcModeRegRead(p, 25, &u2Value);
+    mcSHOW_DBG_MSG(("After PostPackageRepair, MR25 = 0x%x\n", u2Value & 0xFF));
+    mcFPRINTF((fp_A60501, "After PostPackageRepair, MR25 = 0x%x\n", u2Value & 0xFF));
+}
+#endif
+
+#ifdef SKH_POST_PACKAGE_REPAIR_LP3
+static void DramcModeRegWriteByRankUsDelay(DRAMC_CTX_T *p, U8 u1MRIdx, U8 u1Value, U8 u1Delay)
+{
+    DramcModeRegWriteByRank(p, p->rank, u1MRIdx, u1Value);
+    mcDELAY_US(u1Delay);
+    mcSHOW_DBG_MSG(("SKPPR R<%d> MR<%d> Value<%x> delay<%d>\n", p->rank, u1MRIdx, u1Value, u1Delay));
+
+    return;
+}
+
+
+void SkRepairSequenceOp0(DRAMC_CTX_T *p)
+{
+    DRAM_RANK_T eOriRank = u1GetRank(p);
+    U8 u1Mr9_Op = 0;
+    int i = 0;
+    U8 u1RankIdx = 0;
+    U8 u1DQ = ((global_sk_ppr_byte[0] == 1) || (global_sk_ppr_byte[2] == 1)) ? 0 : 1;
+    U8 u1BK[3] = {0};
+
+    for(i = 0; i<=SK_BANK_BITS; i++)
+    {
+        if(global_sk_ppr_bank[i] == 1)
+        {
+            u1BK[0] = i & 1;
+            u1BK[1] = (i >> 1) & 1;
+            u1BK[2] = (i >> 2) & 1;
+            break;
+        }
+    }
+    mcSHOW_DBG_MSG(("SKPPR BK0<%d> BK1<%d> BK2<%d>\n", u1BK[0], u1BK[1], u1BK[2]));
+
+    for(u1RankIdx=0; u1RankIdx<(U8)p->support_rank_num; u1RankIdx++)
+    {
+        if(global_sk_ppr_rank[u1RankIdx] == 1)
+        {
+            vSetRank(p, u1RankIdx);
+
+            //Iput Entry Code
+            DramcModeRegWriteByRankUsDelay(p, 9, 0xB0, 3);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0xE0, 3);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0x90, 3);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0xC8, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0x90, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0x8B, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0xE0, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0xD8, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0x88, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0x93, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0xE0, 25);
+
+            //Input Fail Addr.
+            u1Mr9_Op = ((u1DQ << 1) |
+                        (u1BK[0] << 2) |
+                        (1 << 3) |
+                        (global_sk_ppr_row[12] << 4) |
+                        (global_sk_ppr_row[8] << 5) |
+                        (global_sk_ppr_row[4] << 6) |
+                        (1 << 7));
+            DramcModeRegWriteByRankUsDelay(p, 9, u1Mr9_Op, 25);
+
+            u1Mr9_Op = ((u1BK[2] << 1) |
+                        (global_sk_ppr_row[14] << 2) |
+                        (global_sk_ppr_row[11] << 4) |
+                        (global_sk_ppr_row[7] << 5) |
+                        (global_sk_ppr_row[3] << 6));
+            DramcModeRegWriteByRankUsDelay(p, 9, u1Mr9_Op, 25);
+
+            u1Mr9_Op = ((u1BK[1] << 1) |
+                        (1 << 2) |
+                        (1 << 3) |
+                        (global_sk_ppr_row[10] << 4) |
+                        (global_sk_ppr_row[6] << 5) |
+                        (global_sk_ppr_row[2] << 6));
+            DramcModeRegWriteByRankUsDelay(p, 9, u1Mr9_Op, 25);
+
+            u1Mr9_Op = ((1 << 2) |
+                        (global_sk_ppr_row[9] << 4) |
+                        (global_sk_ppr_row[5] << 5) |
+                        (global_sk_ppr_row[1] << 6) |
+                        (1 << 7));
+            DramcModeRegWriteByRankUsDelay(p, 9, u1Mr9_Op, 25);
+
+            //Input additional TM
+            DramcModeRegWriteByRankUsDelay(p, 9, 0xD4, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0x84, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0xE3, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0xE0, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0xB4, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0x8C, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0x87, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0xE0, 25);
+
+            //Execute SKH Repair
+            mcSHOW_DBG_MSG(("36 loop Start\n"));
+            for(i=0; i<36; i++) //36 LOOP
+            {
+                DramcModeRegWriteByRankUsDelay(p, 9, 0xC4, 25);
+                DramcModeRegWriteByRankUsDelay(p, 9, 0x9C, 25);
+                DramcModeRegWriteByRankUsDelay(p, 9, 0x93, 25);
+                DramcModeRegWriteByRankUsDelay(p, 9, 0xE0, 25);
+            }
+            mcSHOW_DBG_MSG(("36 loop Stop\n"));
+
+            //Exit SKH repair mode
+            DramcModeRegWriteByRankUsDelay(p, 9, 0x00, 25);
+        }
+    }
+
+    vSetRank(p, (U8)eOriRank);
+    return;
+}
+
+
+void SkRepairSequenceOp1(DRAMC_CTX_T *p)
+{
+    DRAM_RANK_T eOriRank = u1GetRank(p);
+    U8 u1Mr9_Op = 0;
+    int i = 0;
+    U8 u1RankIdx = 0;
+    U8 u1DQ = ((global_sk_ppr_byte[0] == 1) || (global_sk_ppr_byte[2] == 1)) ? 0 : 1;
+    U8 u1BK[3] = {0};
+
+    for(i = 0; i<=SK_BANK_BITS; i++)
+    {
+        if((global_sk_ppr_bank[0] == 1) || (global_sk_ppr_bank[1] == 1))
+        {
+            u1BK[2] = 0;
+            u1BK[1] = 0;
+        }
+        else if((global_sk_ppr_bank[2] == 1) || (global_sk_ppr_bank[3] == 1))
+        {
+            u1BK[2] = 0;
+            u1BK[1] = 1;
+        }
+        else if((global_sk_ppr_bank[4] == 1) || (global_sk_ppr_bank[5] == 1))
+        {
+            u1BK[2] = 1;
+            u1BK[1] = 0;
+        }
+        else if((global_sk_ppr_bank[6] == 1) || (global_sk_ppr_bank[7] == 1))
+        {
+            u1BK[2] = 1;
+            u1BK[1] = 1;
+        }
+    }
+    mcSHOW_DBG_MSG(("SKPPR BK0<%d> BK1<%d> BK2<%d>\n", u1BK[0], u1BK[1], u1BK[2]));
+
+    for(u1RankIdx=0; u1RankIdx<(U8)p->support_rank_num; u1RankIdx++)
+    {
+        if(global_sk_ppr_rank[u1RankIdx] == 1)
+        {
+            vSetRank(p, u1RankIdx);
+
+            //Iput Entry Code
+            DramcModeRegWriteByRankUsDelay(p, 9, 0xB0, 3);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0xE0, 3);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0x90, 3);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0xA8, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0x8E, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0x83, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0xA8, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0x84, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0x86, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0x83, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0xA8, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0x90, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0x9E, 25);
+            DramcModeRegWriteByRankUsDelay(p, 9, 0x83, 25);
+
+            //Input Fail Addr.
+            u1Mr9_Op = ((global_sk_ppr_row[12] << 1) |
+                        (global_sk_ppr_row[11] << 3) |
+                        (global_sk_ppr_row[10] << 5) |
+                        (u1DQ << 6) |
+                        (global_sk_ppr_row[9] << 7));
+            DramcModeRegWriteByRankUsDelay(p, 9, u1Mr9_Op, 25);
+
+            u1Mr9_Op = ((global_sk_ppr_row[8] << 1) |
+                        (global_sk_ppr_row[7] << 3) |
+                        (u1BK[2] << 4) |
+                        (global_sk_ppr_row[6] << 5) |
+                        (u1BK[1] << 6)|
+                        (global_sk_ppr_row[5] << 7));
+            DramcModeRegWriteByRankUsDelay(p, 9, u1Mr9_Op, 25);
+
+            u1Mr9_Op = ((global_sk_ppr_row[14]) |
+                        (global_sk_ppr_row[4] << 1) |
+                        (global_sk_ppr_row[13]  << 2) |
+                        (global_sk_ppr_row[3]  << 3) |
+                        (global_sk_ppr_row[2] << 5) |
+                        (global_sk_ppr_row[1] << 7));
+            DramcModeRegWriteByRankUsDelay(p, 9, u1Mr9_Op, 25);
+
+            u1Mr9_Op = 0xD2;
+            DramcModeRegWriteByRankUsDelay(p, 9, u1Mr9_Op, 25);
+
+            //Execute SKH Repair
+            for(i=0; i<36; i++) //36 LOOP
+            {
+                DramcModeRegWriteByRankUsDelay(p, 9, 0xAC, 10);
+                DramcModeRegWriteByRankUsDelay(p, 9, 0x88, 10);
+                DramcModeRegWriteByRankUsDelay(p, 9, 0x86, 10);
+                DramcModeRegWriteByRankUsDelay(p, 9, 0x83, 10);
+            }
+            //Exit SKH repair mode
+            DramcModeRegWriteByRankUsDelay(p, 9, 0x00, 10);
+        }
+    }
+
+    vSetRank(p, (U8)eOriRank);
+    return;
+}
+
+
+static U32 u4SKPostPackageRepairBackupAddress[] =
+{
+    (DRAMC_REG_DRAMC_PD_CTRL),
+    (DRAMC_REG_REFCTRL0),
+    (DRAMC_REG_SPCMDCTRL),
+    (DRAMC_REG_SHU_SCINTV),
+    (DRAMC_REG_SHU2_SCINTV),
+    (DRAMC_REG_SHU3_SCINTV)
+};
+
+
+void SkPostPackageRepairLP3(DRAMC_CTX_T *p) //Backup restore
+{
+    //DRAM_CHANNEL_T eOriChannel = vGetPHY2ChannelMapping(p);
+    //DRAM_RANK_T eOriRank = u1GetRank(p);
+    U16 u2Mr7Op = 0;
+
+    mcSHOW_DBG_MSG(("SKPPR\n"
+                    "\nFreq=%d, CH=%d, Rank=%d\n", p->frequency, p->channel, p->rank));
+
+    //Backup regs
+    DramcBackupRegisters(p, u4SKPostPackageRepairBackupAddress, sizeof(u4SKPostPackageRepairBackupAddress)/sizeof(U32));
+
+    //DRAMC DCM freerun,
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 0, DRAMC_PD_CTRL_DCMEN2);
+
+    //PHY DCM freerun,
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 0, DRAMC_PD_CTRL_PHYCLKDYNGEN);
+
+    //Dram clock freerun,
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 1, DRAMC_PD_CTRL_MIOCKCTRLOFF);
+
+    //Fix CKE0 and CKE1 be high,
+    CKEFixOnOff(p, CKE_WRITE_TO_ALL_RANK, CKE_FIXON, CKE_WRITE_TO_ALL_CHANNEL);
+
+    //All banks must be precharged
+    //Enter_Precharge_All(p);
+    //vIO32WriteFldAlign(DRAMC_REG_SPCMD, 0, SPCMD_PREAEN);
+
+    //Disable MR4, refresh, ZQ_Cal, TX
+    vIO32WriteFldAlign(DRAMC_REG_REFCTRL0, 1, REFCTRL0_REFDIS);
+    vIO32WriteFldAlign(DRAMC_REG_SPCMDCTRL, 1, SPCMDCTRL_REFRDIS);
+    vIO32WriteFldAlign(DRAMC_REG_SPCMDCTRL, 0, SPCMDCTRL_ZQCSDISB);
+    vIO32WriteFldAlign(DRAMC_REG_SHU_SCINTV, 1, SHU_SCINTV_DQSOSCENDIS);
+    vIO32WriteFldAlign(DRAMC_REG_SHU2_SCINTV, 1, SHU2_SCINTV_DQSOSCENDIS);
+    vIO32WriteFldAlign(DRAMC_REG_SHU3_SCINTV, 1, SHU3_SCINTV_DQSOSCENDIS);
+
+    DramcModeRegReadByRank(p, RANK_0, 7, &u2Mr7Op);//CHA R0
+    u2Mr7Op &= 0xff;
+    mcSHOW_DBG_MSG(("Before SKPPR, MR7 = 0x%x\n", u2Mr7Op));//0: 1st 8G 1: 2rd 8G
+
+    if(u2Mr7Op == 0)
+    {
+        SkRepairSequenceOp0(p);
+    }
+    else
+    {
+        SkRepairSequenceOp1(p);
+    }
+    //Restore regs
+    DramcRestoreRegisters(p, u4SKPostPackageRepairBackupAddress, sizeof(u4SKPostPackageRepairBackupAddress)/sizeof(U32));
+    return;
+}
+#endif //SKH_POST_PACKAGE_REPAIR_LP3
+
+
+extern DRAMC_CTX_T DramCtx_LPDDR4;
+extern DRAMC_CTX_T DramCtx_LPDDR3;
+void PostPackageRepair(void)
+{
+    BOOL bLp4 = u1IsLP4Family(mt_get_dram_type_from_hw_trap());
+    DRAMC_CTX_T *p = (bLp4) ? (&DramCtx_LPDDR4) : (&DramCtx_LPDDR3);
+    DRAM_CHANNEL_T eOriChannel = vGetPHY2ChannelMapping(p);
+    DRAM_RANK_T eOriRank = u1GetRank(p);
+
+    if(bLp4)//Based on VDRAM to decide the DRAM type
+    {
+#ifdef POST_PACKAGE_REPAIR_LP4
+        DramcPostPackageRepair(p);
+#endif
+    }
+    else
+    {   // LPDDR3
+#ifdef SKH_POST_PACKAGE_REPAIR_LP3
+        p->support_rank_num = RANK_DUAL;//Based on usage
+        SkPostPackageRepairLP3(p);
+#endif
+    }
+
+    vSetRank(p, eOriRank);
+    vSetPHY2ChannelMapping(p, eOriChannel);
+    return;
+}
+#endif //ENABLE_POST_PACKAGE_REPAIR
+
+
+static void SetRxDqDqsDelay(DRAMC_CTX_T *p, S16 iDelay)
+{
+    U8 ii;
+    U32 u4value;
+#if ENABLE_LP3_SW
+    U8 dl_value[8];
+    U8 u1ByteIdx;
+#endif
+
+    if (iDelay <=0)
+    {
+        if(u1IsLP4Family(p->dram_type))
+        {
+            // Set DQS delay
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6), \
+                                    P_Fld((-iDelay+gu2RX_DQS_Duty_Offset[0][0]),SHU1_R0_B0_DQ6_RK0_RX_ARDQS0_R_DLY_B0) |P_Fld((-iDelay+gu2RX_DQS_Duty_Offset[0][1]),SHU1_R0_B0_DQ6_RK0_RX_ARDQS0_F_DLY_B0));
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ6), \
+                            P_Fld((-iDelay+gu2RX_DQS_Duty_Offset[1][0]),SHU1_R0_B1_DQ6_RK0_RX_ARDQS0_R_DLY_B1) |P_Fld((-iDelay+gu2RX_DQS_Duty_Offset[1][1]),SHU1_R0_B1_DQ6_RK0_RX_ARDQS0_F_DLY_B1));
+        }
+#if ENABLE_LP3_SW
+        else
+        {
+            for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+            {
+                vIO32WriteFldAlign_Phy_Byte(u1ByteIdx, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6), -iDelay, SHU1_R0_B0_DQ6_RK0_RX_ARDQS0_R_DLY_B0);
+                vIO32WriteFldAlign_Phy_Byte(u1ByteIdx, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6), -iDelay, SHU1_R0_B0_DQ6_RK0_RX_ARDQS0_F_DLY_B0);
+            }
+        }
+#endif
+
+        DramPhyReset(p);
+    }
+    else
+    {
+        // Adjust DQM output delay.
+        if(u1IsLP4Family(p->dram_type))
+        {
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6), \
+                                    P_Fld(iDelay,SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_R_DLY_B0) |P_Fld(iDelay,SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_F_DLY_B0));
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ6), \
+                            P_Fld(iDelay,SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_R_DLY_B1) |P_Fld(iDelay,SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_F_DLY_B1));
+        }
+        #if ENABLE_LP3_SW
+        else
+        {
+            for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+            {
+                Set_RX_DQM_DelayLine_Phy_Byte(p, u1ByteIdx, iDelay);
+            }
+        }
+        #endif
+
+        DramPhyReset(p);
+
+        // Adjust DQ output delay.
+        if(u1IsLP4Family(p->dram_type))
+        {
+            u4value = ((U32) iDelay) | (((U32)iDelay)<<8) | (((U32)iDelay)<<16) | (((U32)iDelay)<<24);
+            for (ii=0; ii<4; ii++)
+            {
+                vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2+ ii*4), u4value);//DQ0~DQ7
+                vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2+ ii*4), u4value);//DQ8~DQ15
+            }
+
+        #if PINMUX_AUTO_TEST_PER_BIT_RX
+            if(gRX_check_per_bit_flag)
+            {
+                SetRxPerBitDelayCellForPinMuxCheck(p, gRX_Check_per_bit_idx);
+                //CheckRXDelayCell(p);
+            }
+        #endif
+
+        }
+    #if ENABLE_LP3_SW
+        else//LPDDR3
+        {
+            //every 2bit dq have the same delay register address
+            for (u1ByteIdx=0; u1ByteIdx<DQS_NUMBER; u1ByteIdx++)
+            {
+                dl_value[0] = iDelay;
+                dl_value[1] = iDelay;
+                dl_value[2] = iDelay;
+                dl_value[3] = iDelay;
+                dl_value[4] = iDelay;
+                dl_value[5] = iDelay;
+                dl_value[6] = iDelay;
+                dl_value[7] = iDelay;
+
+                Set_RX_DQ_DelayLine_Phy_Byte(p, u1ByteIdx, dl_value);
+            }
+        #if PINMUX_AUTO_TEST_PER_BIT_RX_LP3
+            if(gRX_check_per_bit_flag)
+            {
+                SetRxPerBitDelayCellForPinMuxCheckLp3(p, gRX_Check_per_bit_idx, iDelay);
+                //CheckRXDelayCell(p);
+            }
+        #endif
+        }
+    #endif
+    }
+}
+
+
+#if SIMULATION_RX_PERBIT
+
+#define RX_DELAY_PRE_CAL 1
+#if RX_DELAY_PRE_CAL
+S16 s2RxDelayPreCal=PASS_RANGE_NA;
+#endif
+DRAM_STATUS_T DramcRxWindowPerbitCal(DRAMC_CTX_T *p, U8 u1UseTestEngine)
+{
+    U8 ii, u1BitIdx, u1ByteIdx;
+    U8 ucbit_first, ucbit_last;
+    S16 iDelay=0, u4DelayBegin=0, u4DelayEnd, u4DelayStep=1;
+    S16 iDutyOffset=0, u4DutyOffsetBegin, u4DutyOffsetEnd, u4DutyOffsetStep=4;
+    U32 uiFinishCount;
+    U32 u4err_value, u4fail_bit;
+    PASS_WIN_DATA_T WinPerBit[DQ_DATA_WIDTH], FinalWinPerBit[DQ_DATA_WIDTH];
+    S32 iDQSDlyPerbyte[DQS_NUMBER], iDQMDlyPerbyte[DQS_NUMBER];//, iFinalDQSDly[DQS_NUMBER];
+    U8 u1VrefScanEnable;
+    U16 u2VrefLevel, u2TempWinSum, u2TmpDQMSum, u2FinalVref=0xe;
+    U16 u2VrefBegin, u2VrefEnd, u2VrefStep;
+    U32 u4AddrOfst = 0x50;
+    U8  u1RXEyeScanEnable;
+#if ENABLE_LP3_SW
+    U8 dl_value[8]={0,0,0,0,0,0,0,0};
+#endif
+    U8 backup_rank;
+
+#if 0//PPORT_SAVE_TIME_FOR_CALIBRATION
+   S16 u1minfirst_pass=0xff,u1minlast_pass=0xff,u4Delayoffset;
+   U8  u1AllBitPassCount;
+#endif
+
+#if EYESCAN_LOG
+    U8 EyeScan_index[DQ_DATA_WIDTH_LP4];
+    U8 u1pass_in_this_vref_flag[DQ_DATA_WIDTH_LP4];
+#endif
+
+
+#if REG_ACCESS_PORTING_DGB
+    RegLogEnable =1;
+    mcSHOW_DBG_MSG(("\n[REG_ACCESS_PORTING_FUNC] DramcRxWindowPerbitCal\n"));
+    mcFPRINTF((fp_A60501, "\n[REG_ACCESS_PORTING_FUNC] DramcRxWindowPerbitCal\n"));
+#endif
+
+    // error handling
+    if (!p)
+    {
+        mcSHOW_ERR_MSG(("context NULL\n"));
+        return DRAM_FAIL;
+    }
+
+#ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+    U8 u1GUMP_INIT_RG_LOG_TO_DE_bak = gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag;
+    gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag=0;
+#endif
+
+    backup_rank = u1GetRank(p);
+
+    u1RXEyeScanEnable = (gRX_EYE_Scan_flag==1 && ((gRX_EYE_Scan_only_higheset_freq_flag==1 && p->frequency == u2DFSGetHighestFreq(p)) || gRX_EYE_Scan_only_higheset_freq_flag==0));
+
+#if EYESCAN_LOG
+    U32 u1vrefidx;
+
+    if (u1IsLP4Family(p->dram_type))
+    {
+        for(u1vrefidx=0; u1vrefidx<RX_VREF_RANGE_END+1;u1vrefidx++)
+        {
+            for (u1BitIdx = 0; u1BitIdx < DQ_DATA_WIDTH_LP4; u1BitIdx++)
+            {
+                for(ii=0; ii<EYESCAN_BROKEN_NUM; ii++)
+                {
+                    gEyeScan_Min[u1vrefidx][u1BitIdx][ii] = EYESCAN_DATA_INVALID;
+                    gEyeScan_Max[u1vrefidx][u1BitIdx][ii] = EYESCAN_DATA_INVALID;
+
+                    gEyeScan_ContinueVrefHeight[u1BitIdx] = 0;
+                    gEyeScan_TotalPassCount[u1BitIdx] = 0;
+                }
+            }
+        }
+    }
+#endif
+
+
+    //defult set result fail. When window found, update the result as oK
+    if(u1UseTestEngine)
+    {
+        vSetCalibrationResult(p, DRAM_CALIBRATION_RX_PERBIT, DRAM_FAIL);
+        DramcEngine2Init(p, p->test2_1, p->test2_2, p->test_pattern, 0);
+    }
+    else
+    {
+        vSetCalibrationResult(p, DRAM_CALIBRATION_RX_RDDQC, DRAM_FAIL);
+        DramcRxWinRDDQCInit(p);
+    }
+
+
+    // for loop, different Vref,
+    u2rx_window_sum = 0;
+
+    if(u1IsLP4Family(p->dram_type) && (u1UseTestEngine==1) && (p->enable_rx_scan_vref==ENABLE) && (p->rank==RANK_0)) //only apply RX Vref Scan for Rank 0 (Rank 0 and 1 use the same Vref reg)
+        u1VrefScanEnable =1;
+    else
+        u1VrefScanEnable =0;
+
+    if (gRX_EYE_Scan_flag==1 && u1VrefScanEnable==0)
+    {
+        if(u1IsLP4Family(p->dram_type) && (u1UseTestEngine==1) && (p->enable_rx_scan_vref==ENABLE) && (p->rank==RANK_1)) //also need to K rank1 for debug
+            u1VrefScanEnable =1;
+    }
+
+
+    #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+    if(p->femmc_Ready==1 && (p->Bypass_RDDQC || p->Bypass_RXWINDOW))
+    {
+        mcSHOW_DBG_MSG(("[FAST_K] Bypass RX Calibration\n"));
+    }
+    else
+    #endif
+    {
+#if VENDER_JV_LOG
+#if 0 //BU don't want customer knows our RX's ability
+        if(u1UseTestEngine ==1)
+            vPrintCalibrationBasicInfo_ForJV(p);
+#endif
+#else
+        vPrintCalibrationBasicInfo(p);
+#endif
+        mcSHOW_DBG_MSG2(("Start DQ dly to find pass range UseTestEngine =%d\n", u1UseTestEngine));
+        mcSHOW_DBG_MSG2(("x-axis: bit #, y-axis: DQ dly (%d~%d)\n", (-MAX_RX_DQSDLY_TAPS), MAX_RX_DQDLY_TAPS));
+        mcFPRINTF((fp_A60501, "Start RX DQ/DQS calibration UseTestEngine =%d\n", u1UseTestEngine));
+        mcFPRINTF((fp_A60501, "x-axis is bit #; y-axis is DQ delay\n"));
+    }
+
+    mcSHOW_DBG_MSG(("RX Vref Scan = %d\n", u1VrefScanEnable));
+    mcFPRINTF((fp_A60501, "RX Vref Scan= %d\n", u1VrefScanEnable));
+
+    if(u1VrefScanEnable)
+    {
+        #if (SW_CHANGE_FOR_SIMULATION ||FOR_DV_SIMULATION_USED)
+        u2VrefBegin =RX_VREF_RANGE_BEGIN;
+        #else
+        if (gRX_EYE_Scan_flag==0)
+        {
+            if(p->odt_onoff)
+            {
+                u2VrefBegin = RX_VREF_RANGE_BEGIN_ODT_ON;
+            }
+            else
+            {
+                u2VrefBegin = RX_VREF_RANGE_BEGIN_ODT_OFF;
+            }
+        }
+        else
+            u2VrefBegin = 0;//Lewis@20160817: Enlarge RX Vref range for eye scan
+        #endif
+
+        u2VrefEnd =RX_VREF_RANGE_END;
+        u2VrefStep=RX_VREF_RANGE_STEP;
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_VREF_EN_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_VREF_EN_B1);
+    }
+    else //LPDDR3 or diable RX Vref
+    {
+        u2VrefBegin = 0;
+        u2VrefEnd = 0; // SEL[4:0] = 01110
+        u2VrefStep =1; //don't care, just make for loop break;
+    }
+
+    #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+    if(p->femmc_Ready==1 && (p->Bypass_RDDQC || p->Bypass_RXWINDOW))
+    {
+        if(u1VrefScanEnable)
+        {
+            // load RX Vref from eMMC
+            #if ( SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_VREF_CAL)
+       		//u2VrefBegin = p->pSavetimeData->u1RxWinPerbitVref_Save[p->channel];
+       		//u2VrefEnd=u2VrefBegin+1;
+       		u2FinalVref = p->pSavetimeData->u1RxWinPerbitVref_Save[p->channel];
+            #endif
+        }
+
+        // load RX DQS and DQM delay from eMMC
+        for (u1ByteIdx=0; u1ByteIdx<DQS_NUMBER_LP4; u1ByteIdx++)
+        {
+            iDQSDlyPerbyte[u1ByteIdx]= p->pSavetimeData->u1RxWinPerbit_DQS[p->channel][p->rank][u1ByteIdx];
+            iDQMDlyPerbyte[u1ByteIdx]= p->pSavetimeData->u1RxWinPerbit_DQM[p->channel][p->rank][u1ByteIdx];
+        }
+
+        // load RX DQ delay from eMMC
+        for (u1BitIdx=0; u1BitIdx<16; u1BitIdx++)
+        {
+            FinalWinPerBit[u1BitIdx].best_dqdly= p->pSavetimeData->u1RxWinPerbit_DQ[p->channel][p->rank][u1BitIdx];
+        }
+
+        if(u1UseTestEngine)
+            vSetCalibrationResult(p, DRAM_CALIBRATION_RX_PERBIT, DRAM_OK);
+        else
+            vSetCalibrationResult(p, DRAM_CALIBRATION_RX_RDDQC, DRAM_OK);
+    }
+    else
+    #endif
+    {
+        if(u1IsLP4Family(p->dram_type))
+        {
+            #if RX_DELAY_PRE_CAL
+            if(u1UseTestEngine==0)
+            #endif
+            {
+                if(p->frequency >=1600)
+                {
+                    u4DelayBegin= -26;
+                }
+                else if(p->frequency >= 1140)
+                {
+                    u4DelayBegin= -30;
+                }
+                else if(p->frequency >=800)
+                {
+                    u4DelayBegin= -48;
+                }
+                else
+                {
+                    u4DelayBegin= -MAX_RX_DQSDLY_TAPS;
+                }
+
+                s2RxDelayPreCal =PASS_RANGE_NA;
+            }
+            #if RX_DELAY_PRE_CAL
+            else
+            {
+                u4DelayBegin = s2RxDelayPreCal -10;  // for test engine
+            }
+            #endif
+
+            //mcSHOW_DBG_MSG(("RX_DELAY_PRE_CAL: RX delay begin = %d\n", u4DelayBegin));
+
+            u4DelayEnd = MAX_RX_DQDLY_TAPS;
+
+            if(p->frequency <850)
+                u4DelayStep =2;  //1600
+            else
+                u4DelayStep =1;//2667, 3200
+
+            if(u1UseTestEngine==0) //if RDDQD, roughly calibration
+                u4DelayStep <<= 1;
+        }
+        #if ENABLE_LP3_SW
+        else
+        {
+            if(p->frequency >=933)
+            {
+                u4DelayBegin= -48;
+            }
+            else if(p->frequency >=600)
+            {
+                u4DelayBegin= -70;
+            }
+            else if(p->frequency >=450)
+            {
+                u4DelayBegin= -110;
+            }
+            else
+            {
+                u4DelayBegin= -MAX_RX_DQSDLY_TAPS;
+            }
+            u4DelayEnd = MAX_RX_DQDLY_TAPS;
+
+            if(p->frequency <600)
+                u4DelayStep =2;  //1066
+            else
+                u4DelayStep =1;//1600, 1270
+        }
+        #endif
+
+        u4DutyOffsetBegin = 0;
+        u4DutyOffsetEnd = 0;
+        u4DutyOffsetStep = 1;
+
+        #if !REDUCE_LOG_FOR_PRELOADER
+        mcSHOW_DBG_MSG(("\nRX DQS R/F Scan, iDutyOffset= %d\n", iDutyOffset));
+        mcFPRINTF((fp_A60501, "\nRX DQS R/F Scan, iDutyOffset= %d\n", iDutyOffset));
+        #endif
+
+        for(u2VrefLevel = u2VrefBegin; u2VrefLevel <= u2VrefEnd; u2VrefLevel += u2VrefStep)
+        {
+            if(u1VrefScanEnable ==1)
+            {
+                #if !REDUCE_LOG_FOR_PRELOADER
+                mcSHOW_DBG_MSG(("\n\tRX VrefLevel=%d\n", u2VrefLevel));
+                mcFPRINTF((fp_A60501, "\n\tRX VrefLevel=%d\n", u2VrefLevel));
+                #endif
+#if 0
+                #if VENDER_JV_LOG
+                if(u1UseTestEngine ==1)
+                mcSHOW_DBG_MSG5(("\n\tRX VrefLevel=%d\n", u2VrefLevel));
+                #endif
+#endif
+
+                //Set RX Vref Here
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ5), u2VrefLevel, SHU1_B0_DQ5_RG_RX_ARDQ_VREF_SEL_B0);  // LP4 and LP4x with term: 0xe
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ5), u2VrefLevel, SHU1_B1_DQ5_RG_RX_ARDQ_VREF_SEL_B1);  // LP4 and LP4x with term: 0xe
+            }
+
+            // 1.delay DQ ,find the pass widnow (left boundary).
+            // 2.delay DQS find the pass window (right boundary).
+            // 3.Find the best DQ / DQS to satify the middle value of the overall pass window per bit
+            // 4.Set DQS delay to the max per byte, delay DQ to de-skew
+
+            for (iDutyOffset=u4DutyOffsetBegin; iDutyOffset<=u4DutyOffsetEnd; iDutyOffset+=u4DutyOffsetStep)
+            {
+                // initialize parameters
+                u2TempWinSum =0;
+                uiFinishCount =0;
+
+                for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+                {
+                    WinPerBit[u1BitIdx].first_pass = (S16)PASS_RANGE_NA;
+                    WinPerBit[u1BitIdx].last_pass = (S16)PASS_RANGE_NA;
+                    FinalWinPerBit[u1BitIdx].first_pass = (S16)PASS_RANGE_NA;
+                    FinalWinPerBit[u1BitIdx].last_pass = (S16)PASS_RANGE_NA;
+
+                    #if EYESCAN_LOG
+                    if (u1IsLP4Family(p->dram_type))
+                    {
+                        gEyeScan_CaliDelay[u1BitIdx/8] = 0;
+                        gEyeScan_DelayCellPI[u1BitIdx] = 0;
+                        EyeScan_index[u1BitIdx] = 0;
+                        u1pass_in_this_vref_flag[u1BitIdx] = 0;
+                    }
+                    #endif
+                }
+
+                // Adjust DQM output delay to 0
+                if(u1IsLP4Family(p->dram_type))
+                {
+                    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6), \
+                                            P_Fld(0, SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_R_DLY_B0) |P_Fld(0, SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_F_DLY_B0));
+                    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ6), \
+                                    P_Fld(0,SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_R_DLY_B1) |P_Fld(0, SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_F_DLY_B1));
+                }
+                #if ENABLE_LP3_SW
+                else
+                {
+                    for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+                    {
+                        Set_RX_DQM_DelayLine_Phy_Byte(p, u1ByteIdx, 0);
+                    }
+                }
+                #endif
+
+                // Adjust DQ output delay to 0
+                //every 2bit dq have the same delay register address
+                if(u1IsLP4Family(p->dram_type))
+                {
+                    for (ii=0; ii<4; ii++)
+                    {
+                        vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2+ ii*4), 0);//DQ0~DQ7
+                        vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2+ ii*4), 0);//DQ8~DQ15
+                    }
+                }
+                #if ENABLE_LP3_SW
+                else//LPDDR3
+                {
+                    for (u1ByteIdx=0; u1ByteIdx<DQS_NUMBER; u1ByteIdx++)
+                    {
+                        Set_RX_DQ_DelayLine_Phy_Byte(p, u1ByteIdx, dl_value);
+                    }
+                }
+                #endif
+
+                for (iDelay=u4DelayBegin; iDelay<=u4DelayEnd; iDelay+= u4DelayStep)
+                {
+                    SetRxDqDqsDelay(p, iDelay);
+
+                    if(u1UseTestEngine)
+                    {
+                        u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, p->test_pattern);
+                    }
+                    else
+                    {
+                        u4err_value = DramcRxWinRDDQCRun(p);
+                    }
+
+                    if((u1VrefScanEnable==0) || u1RXEyeScanEnable)
+                    {
+                        #ifdef ETT_PRINT_FORMAT
+                        if(u4err_value !=0)
+                        {
+                            mcSHOW_DBG_MSG2(("%d, [0]", iDelay));
+                        }
+                        #else
+                        mcSHOW_DBG_MSG2(("iDelay= %4d, [0]", iDelay));
+                        #endif
+                        mcFPRINTF((fp_A60501, "iDelay= %4d, [0]", iDelay));
+                        //mcSHOW_DBG_MSG2(("u4err_value %x, u1MRRValue %x\n", u4err_value, u1MRRValue));
+                        //mcFPRINTF((fp_A60501, "u4err_value!!  %x", u4err_value));
+                    }
+
+                    // check fail bit ,0 ok ,others fail
+                    for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+                    {
+                        u4fail_bit = u4err_value&((U32)1<<u1BitIdx);
+
+                        if(WinPerBit[u1BitIdx].first_pass== PASS_RANGE_NA)
+                        {
+                            if(u4fail_bit==0) //compare correct: pass
+                            {
+                                WinPerBit[u1BitIdx].first_pass = iDelay;
+
+                                #if RX_DELAY_PRE_CAL
+                                if(u1UseTestEngine==0 && (s2RxDelayPreCal ==PASS_RANGE_NA))
+                                {
+                                    s2RxDelayPreCal = iDelay;
+                                }
+
+                                if(u1UseTestEngine==1 && iDelay==u4DelayBegin)
+                                {
+                                    mcSHOW_ERR_MSG(("RX_DELAY_PRE_CAL: Warning, possible miss RX window boundary\n"));
+                                    #if __ETT__
+                                    while(1);
+                                    #endif
+                                }
+
+                                #endif
+
+                                #if EYESCAN_LOG
+                                if (u1IsLP4Family(p->dram_type))
+                                {
+                                    u1pass_in_this_vref_flag[u1BitIdx]=1;
+                                }
+                                #endif
+                            }
+                        }
+                        else if(WinPerBit[u1BitIdx].last_pass == PASS_RANGE_NA)
+                        {
+                            //mcSHOW_DBG_MSG(("fb%d \n", u4fail_bit));
+
+                            if(u4fail_bit !=0) //compare error : fail
+                            {
+                                WinPerBit[u1BitIdx].last_pass  = (iDelay-1);
+                            }
+                            else if (iDelay==u4DelayEnd)
+                            {
+                                WinPerBit[u1BitIdx].last_pass  = iDelay;
+                            }
+
+                            if(WinPerBit[u1BitIdx].last_pass  !=PASS_RANGE_NA)
+                            {
+                                if((WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass) >= (FinalWinPerBit[u1BitIdx].last_pass -FinalWinPerBit[u1BitIdx].first_pass))
+                                {
+                                    #if 0 //for debug
+                                    if(FinalWinPerBit[u1BitIdx].last_pass != PASS_RANGE_NA)
+                                    {
+                                        mcSHOW_DBG_MSG2(("Bit[%d] Bigger window update %d > %d\n", u1BitIdx, \
+                                            (WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass), (FinalWinPerBit[u1BitIdx].last_pass -FinalWinPerBit[u1BitIdx].first_pass)));
+                                        mcFPRINTF((fp_A60501,"Bit[%d] Bigger window update %d > %d\n", u1BitIdx, \
+                                            (WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass), (FinalWinPerBit[u1BitIdx].last_pass -FinalWinPerBit[u1BitIdx].first_pass)));
+                                    }
+                                    #endif
+
+                                    //if window size bigger than 7, consider as real pass window. If not, don't update finish counte and won't do early break;
+                                    if((WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass) >7)
+                                        uiFinishCount |= (1<<u1BitIdx);
+
+                                    //update bigger window size
+                                    FinalWinPerBit[u1BitIdx].first_pass = WinPerBit[u1BitIdx].first_pass;
+                                    FinalWinPerBit[u1BitIdx].last_pass = WinPerBit[u1BitIdx].last_pass;
+                                }
+
+                                #if EYESCAN_LOG
+                                if(u1UseTestEngine && u1IsLP4Family(p->dram_type))
+                                {
+                                    if (EyeScan_index[u1BitIdx] < EYESCAN_BROKEN_NUM)
+                                    {
+                                        gEyeScan_Min[u2VrefLevel][u1BitIdx][EyeScan_index[u1BitIdx]] = WinPerBit[u1BitIdx].first_pass;
+                                        gEyeScan_Max[u2VrefLevel][u1BitIdx][EyeScan_index[u1BitIdx]] = WinPerBit[u1BitIdx].last_pass;
+                                        mcSHOW_DBG_MSG3(("u2VrefLevel=%d, u1BitIdx=%d, index=%d (%d, %d)==\n",u2VrefLevel, u1BitIdx, EyeScan_index[u1BitIdx], gEyeScan_Min[u2VrefLevel][u1BitIdx][EyeScan_index[u1BitIdx]], gEyeScan_Max[u2VrefLevel][u1BitIdx][EyeScan_index[u1BitIdx]]));
+                                        EyeScan_index[u1BitIdx]=EyeScan_index[u1BitIdx]+1;
+                                    }
+                                }
+                                #endif
+
+                                //reset tmp window
+                                WinPerBit[u1BitIdx].first_pass = PASS_RANGE_NA;
+                                WinPerBit[u1BitIdx].last_pass = PASS_RANGE_NA;
+                            }
+                        }
+
+                        if((u1VrefScanEnable==0) || u1RXEyeScanEnable)
+                        {
+                            #ifdef ETT_PRINT_FORMAT
+                            if(u4err_value !=0)
+                            #endif
+                            {
+                                if(u1BitIdx%DQS_BIT_NUMBER ==0)
+                                {
+                                    mcSHOW_DBG_MSG2((" "));
+                                    mcFPRINTF((fp_A60501, " "));
+                                }
+
+                                if (u4fail_bit == 0)
+                                {
+                                    mcSHOW_DBG_MSG2(("o"));
+                                    mcFPRINTF((fp_A60501, "o"));
+                                    #if EYESCAN_LOG
+                                    if (u1IsLP4Family(p->dram_type))
+                                    {
+                                         gEyeScan_TotalPassCount[u1BitIdx]+=u4DelayStep;
+                                    }
+                                    #endif
+                                }
+                                else
+                                {
+                                    mcSHOW_DBG_MSG2(("x"));
+                                    mcFPRINTF((fp_A60501, "x"));
+                                }
+                            }
+#if EYESCAN_LOG
+                            #ifdef ETT_PRINT_FORMAT
+                            else
+                            #endif
+                            {
+                                if (u1IsLP4Family(p->dram_type))
+                                {
+                                    gEyeScan_TotalPassCount[u1BitIdx]+=u4DelayStep;
+                                }
+                           }
+#endif
+                        }
+                    }
+
+                    if((u1VrefScanEnable==0)  || u1RXEyeScanEnable)
+                    {
+                        #ifdef ETT_PRINT_FORMAT
+                        if(u4err_value !=0)
+                        #endif
+                        {
+                            mcSHOW_DBG_MSG2((" [MSB]\n"));
+                            mcFPRINTF((fp_A60501, " [MSB]\n"));
+                        }
+                    }
+
+                    //if all bits widnow found and all bits turns to fail again, early break;
+                    if((u1IsLP4Family(p->dram_type) &&(uiFinishCount == 0xffff)) || \
+                        ((p->dram_type == TYPE_LPDDR3) &&(uiFinishCount == 0xffffffff)))
+                    {
+                        if(u1UseTestEngine)
+                            vSetCalibrationResult(p, DRAM_CALIBRATION_RX_PERBIT, DRAM_OK);
+                        else
+                            vSetCalibrationResult(p, DRAM_CALIBRATION_RX_RDDQC, DRAM_OK);
+
+                        if((u1VrefScanEnable==0)  || u1RXEyeScanEnable)
+                        {
+                            if((u1IsLP4Family(p->dram_type) &&((u4err_value&0xffff) == 0xffff)) ||
+                                ((p->dram_type == TYPE_LPDDR3) &&(u4err_value == 0xffffffff)))
+                                {
+                                        #if !REDUCE_LOG_FOR_PRELOADER
+                                        mcSHOW_DBG_MSG(("\nRX all bits window found, early break!\n"));
+                                        #endif
+                                        break;  //early break
+                                }
+                        }
+                    }
+                }
+
+                for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+                {
+                    FinalWinPerBit[u1BitIdx].win_size = FinalWinPerBit[u1BitIdx].last_pass - FinalWinPerBit[u1BitIdx].first_pass + (FinalWinPerBit[u1BitIdx].last_pass==FinalWinPerBit[u1BitIdx].first_pass?0:1);
+
+                #if (PINMUX_AUTO_TEST_PER_BIT_RX | PINMUX_AUTO_TEST_PER_BIT_RX_LP3)
+                    gFinalRXPerbitWinSiz[p->channel][u1BitIdx] = FinalWinPerBit[u1BitIdx].win_size;
+                #endif
+
+                    u2TempWinSum += FinalWinPerBit[u1BitIdx].win_size;  //Sum of CA Windows for vref selection
+
+#if 0 //BU don't want customer knows our RX's ability
+                    #if VENDER_JV_LOG
+                    if(u1UseTestEngine ==1)
+                    {
+                        U8 shuffleIdx;
+                        shuffleIdx = get_shuffleIndex_by_Freq(p);
+                        mcSHOW_DBG_MSG5(("RX Bit%d, %d%%\n", u1BitIdx,  ((FinalWinPerBit[u1BitIdx].win_size*u2gdelay_cell_ps_all[shuffleIdx][0]*p->frequency*2)+(1000000-1))/1000000));
+                    }
+                    #endif
+#endif
+#if EYESCAN_LOG
+                    if (u1IsLP4Family(p->dram_type))
+                    {
+                        gEyeScan_WinSize[u2VrefLevel][u1BitIdx] = FinalWinPerBit[u1BitIdx].win_size;
+                    }
+#endif
+                }
+
+                #if 1//!REDUCE_LOG_FOR_PRELOADER
+                mcSHOW_DBG_MSG2(("RX Vref %d, Window Sum %d\n", u2VrefLevel, u2TempWinSum));
+                mcFPRINTF((fp_A60501, "RX Vref %d, Window Sum %d\n", u2VrefLevel, u2TempWinSum));
+                #endif
+
+                #if 0
+                if((u1IsLP4Family(p->dram_type) &&(u2TempWinSum <250)) || \
+                    ((p->dram_type == TYPE_LPDDR3) &&(u2TempWinSum <1100)))
+                {
+                        mcSHOW_DBG_MSG2(("\n\n[NOTICE] CH %d, TestEngine %d, RX_sum %d\n", p->channel, u1UseTestEngine, u2TempWinSum));
+                        mcFPRINTF((fp_A60501, "\n\n[NOTICE] CH %d, TestEngine %d, RX_sum %d\n", p->channel, u1UseTestEngine, u2TempWinSum));
+                }
+                #endif
+
+                if(u2TempWinSum >u2rx_window_sum)
+                {
+                    mcSHOW_DBG_MSG3(("\nBetter RX Vref found %d, Window Sum %d > %d\n", u2VrefLevel, u2TempWinSum, u2rx_window_sum));
+                    mcFPRINTF((fp_A60501, "\nBetter RX Vref found %d, Window Sum %d > %d\n", u2VrefLevel, u2TempWinSum, u2rx_window_sum));
+
+                    u2rx_window_sum =u2TempWinSum;
+                    u2FinalVref = u2VrefLevel;
+
+                    for (u1BitIdx=0; u1BitIdx<p->data_width; u1BitIdx++)
+                    {
+                        FinalWinPerBit[u1BitIdx].win_center = (FinalWinPerBit[u1BitIdx].last_pass + FinalWinPerBit[u1BitIdx].first_pass)>>1;     // window center of each DQ bit
+
+                        if((u1VrefScanEnable==0) || u1RXEyeScanEnable)
+                        {
+                            #ifdef ETT_PRINT_FORMAT
+                            mcSHOW_DBG_MSG(("iDelay=%d, Bit %d, Center %d (%d ~ %d) %d\n", iDelay, u1BitIdx, FinalWinPerBit[u1BitIdx].win_center, FinalWinPerBit[u1BitIdx].first_pass, FinalWinPerBit[u1BitIdx].last_pass, FinalWinPerBit[u1BitIdx].win_size));
+                            #else
+                            mcSHOW_DBG_MSG(("iDelay=%d, Bit %2d, Center %3d (%4d ~ %4d) %d\n", iDelay, u1BitIdx, FinalWinPerBit[u1BitIdx].win_center, FinalWinPerBit[u1BitIdx].first_pass, FinalWinPerBit[u1BitIdx].last_pass, FinalWinPerBit[u1BitIdx].win_size));
+                            #endif
+                            mcFPRINTF((fp_A60501, "iDelay=%d, Bit %2d, Center %3d (%4d ~ %4d)\n", iDelay, u1BitIdx, FinalWinPerBit[u1BitIdx].win_center, FinalWinPerBit[u1BitIdx].first_pass, FinalWinPerBit[u1BitIdx].last_pass, FinalWinPerBit[u1BitIdx].win_size));
+                        }
+
+#ifdef FOR_HQA_TEST_USED
+                        if(u1UseTestEngine ==1)
+                        {
+                            gFinalRXPerbitWin[p->channel][p->rank][u1BitIdx] = FinalWinPerBit[u1BitIdx].win_size;
+                        }
+#endif
+                    }
+                }
+            }
+
+#if EYESCAN_LOG
+            if (u1IsLP4Family(p->dram_type))
+            {
+                for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+                {
+                    if (u1pass_in_this_vref_flag[u1BitIdx]) gEyeScan_ContinueVrefHeight[u1BitIdx]++;  //count pass number of continue vref
+                }
+            }
+#endif
+
+            if((u2TempWinSum < (u2rx_window_sum*95/100)) && gRX_EYE_Scan_flag == 0)
+            {
+                mcSHOW_DBG_MSG(("\nRX Vref found, early break!\n"));
+                u2VrefLevel = u2VrefEnd;
+                break;//max vref found, early break;
+            }
+        }
+
+        if(u1UseTestEngine)
+        {
+            DramcEngine2End(p);
+        }
+        else
+        {
+            DramcRxWinRDDQCEnd(p);
+        }
+
+        // 3
+        //As per byte, check max DQS delay in 8-bit. Except for the bit of max DQS delay, delay DQ to fulfill setup time = hold time
+        for (u1ByteIdx = 0; u1ByteIdx < (p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+        {
+            u2TmpDQMSum =0;
+
+            ucbit_first =DQS_BIT_NUMBER*u1ByteIdx;
+            ucbit_last = DQS_BIT_NUMBER*u1ByteIdx+DQS_BIT_NUMBER-1;
+            iDQSDlyPerbyte[u1ByteIdx] = MAX_RX_DQSDLY_TAPS;
+
+            for (u1BitIdx = ucbit_first; u1BitIdx <= ucbit_last; u1BitIdx++)
+            {
+                // find out max Center value
+                if(FinalWinPerBit[u1BitIdx].win_center < iDQSDlyPerbyte[u1ByteIdx])
+                {
+                    iDQSDlyPerbyte[u1ByteIdx] = FinalWinPerBit[u1BitIdx].win_center;
+                }
+
+                //mcSHOW_DBG_MSG(("bit#%2d : center=(%2d)\n", u1BitIdx, FinalWinPerBit[u1BitIdx].win_center));
+                //mcFPRINTF((fp_A60501, "bit#%2d : center=(%2d)\n", u1BitIdx, FinalWinPerBit[u1BitIdx].win_center));
+            }
+
+            //mcSHOW_DBG_MSG(("----seperate line----\n"));
+            //mcFPRINTF((fp_A60501, "----seperate line----\n"));
+
+            if (iDQSDlyPerbyte[u1ByteIdx]  > 0)  // Delay DQS=0, Delay DQ only
+            {
+                iDQSDlyPerbyte[u1ByteIdx]  = 0;
+            }
+            else  //Need to delay DQS
+            {
+                iDQSDlyPerbyte[u1ByteIdx]  = -iDQSDlyPerbyte[u1ByteIdx] ;
+            }
+
+            // we delay DQ or DQS to let DQS sample the middle of rx pass window for all the 8 bits,
+            for (u1BitIdx = ucbit_first; u1BitIdx <= ucbit_last; u1BitIdx++)
+            {
+                FinalWinPerBit[u1BitIdx].best_dqdly = iDQSDlyPerbyte[u1ByteIdx] + FinalWinPerBit[u1BitIdx].win_center;
+                u2TmpDQMSum += FinalWinPerBit[u1BitIdx].best_dqdly;
+#if EYESCAN_LOG
+                if (u1IsLP4Family(p->dram_type))
+                {
+                    gEyeScan_DelayCellPI[u1BitIdx] = FinalWinPerBit[u1BitIdx].best_dqdly;
+                }
+#endif
+            }
+
+            // calculate DQM as average of 8 DQ delay
+            iDQMDlyPerbyte[u1ByteIdx] = u2TmpDQMSum/DQS_BIT_NUMBER;
+
+#ifdef FOR_HQA_REPORT_USED
+            HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0, "RX_Window_Center_DQS", u1ByteIdx, iDQSDlyPerbyte[u1ByteIdx], NULL);
+            HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0, "RX_Window_Center_DQM", u1ByteIdx, iDQMDlyPerbyte[u1ByteIdx], NULL);
+            for (u1BitIdx = ucbit_first; u1BitIdx <= ucbit_last; u1BitIdx++)
+            {
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT1, "RX_Window_Center_DQ", u1BitIdx, FinalWinPerBit[u1BitIdx].win_center, NULL);
+            }
+#endif
+        }
+    }
+
+#ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+    gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag = u1GUMP_INIT_RG_LOG_TO_DE_bak;
+#endif
+
+    //Set RX Final Vref Here
+    if(u1VrefScanEnable==1)
+    {
+#ifdef DEVIATION
+        if (p->frequency == u2DFSGetHighestFreq(p) && gSetSpecificedVref_Enable[1]==ENABLE && ((p->channel==gSetSpecificedVref_Channel[1]) || gSetSpecificedVref_All_ChRk[1]==ENABLE))
+        {
+            DeviationAddVrefOffset(1, NULL, &u2FinalVref, gSetSpecificedVref_Vref_Offset[1]);
+        }
+#endif
+
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ5), u2FinalVref, SHU1_B0_DQ5_RG_RX_ARDQ_VREF_SEL_B0);  // LP4 and LP4x with term: 0xe
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ5), u2FinalVref, SHU1_B1_DQ5_RG_RX_ARDQ_VREF_SEL_B1);  // LP4 and LP4x with term: 0xe
+
+        mcSHOW_DBG_MSG(("\nFinal RX Vref %d, apply to both rank0 and 1\n", u2FinalVref));
+        mcFPRINTF((fp_A60501, "\nFinal RX Vref %d, apply to both rank0 and 1\n", u2FinalVref));
+#if 0 //BU don't want customer knows our RX's ability
+#if VENDER_JV_LOG
+        mcSHOW_DBG_MSG5(("\nFinal RX Vref %d, apply to both rank0 and 1\n", u2FinalVref));
+#endif
+#endif
+
+        #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        if(p->femmc_Ready==0)
+        {
+        	p->pSavetimeData->u1RxWinPerbitVref_Save[p->channel]=u2FinalVref;
+        }
+        #endif
+
+        // When only calibrate RX Vref for Rank 0, apply the same value for Rank 1.
+        gFinalRXVrefDQ[p->channel][p->rank] = (U8) u2FinalVref;
+    }
+
+    #if REG_SHUFFLE_REG_CHECK
+    ShuffleRegCheck =1;
+    #endif
+
+    gu2RX_DQS_Duty_Offset[0][0]=gu2RX_DQS_Duty_Offset[0][1]=gu2RX_DQS_Duty_Offset[1][0]=gu2RX_DQS_Duty_Offset[1][1] = 0;
+
+    // set dqs delay, (dqm delay)
+    for (u1ByteIdx = 0; u1ByteIdx < (p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+    {
+        // Set DQS & DQM delay
+        if(u1IsLP4Family(p->dram_type))
+        {
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6+ u4AddrOfst*u1ByteIdx), \
+                P_Fld(((U32)iDQSDlyPerbyte[u1ByteIdx]+gu2RX_DQS_Duty_Offset[u1ByteIdx][0]),SHU1_R0_B0_DQ6_RK0_RX_ARDQS0_R_DLY_B0) |P_Fld(((U32)iDQSDlyPerbyte[u1ByteIdx]+gu2RX_DQS_Duty_Offset[u1ByteIdx][1]),SHU1_R0_B0_DQ6_RK0_RX_ARDQS0_F_DLY_B0) |
+                P_Fld(((U32)iDQMDlyPerbyte[u1ByteIdx]),SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_R_DLY_B0) |P_Fld(((U32)iDQMDlyPerbyte[u1ByteIdx]),SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_F_DLY_B0));
+
+            #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+            if(p->femmc_Ready==0)
+        	{
+        	    p->pSavetimeData->u1RxWinPerbit_DQS[p->channel][p->rank][u1ByteIdx]=(U32)iDQSDlyPerbyte[u1ByteIdx];
+             	p->pSavetimeData->u1RxWinPerbit_DQM[p->channel][p->rank][u1ByteIdx]=(U32)iDQMDlyPerbyte[u1ByteIdx];
+        	}
+            #endif
+        }
+#if ENABLE_LP3_SW
+        else
+        {
+            /* p->rank = RANK_0, save to Reg Rank0 and Rank1, p->rank = RANK_1, save to Reg Rank1 */
+            for(ii=p->rank; ii<RANK_MAX; ii++)
+            {
+                vSetRank(p,ii);
+                vIO32WriteFldAlign_Phy_Byte(u1ByteIdx, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6), (U32)iDQSDlyPerbyte[u1ByteIdx], SHU1_R0_B0_DQ6_RK0_RX_ARDQS0_R_DLY_B0);
+                vIO32WriteFldAlign_Phy_Byte(u1ByteIdx, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6), (U32)iDQSDlyPerbyte[u1ByteIdx], SHU1_R0_B0_DQ6_RK0_RX_ARDQS0_F_DLY_B0);
+                Set_RX_DQM_DelayLine_Phy_Byte(p, u1ByteIdx,(U32)iDQMDlyPerbyte[u1ByteIdx]);
+            }
+            vSetRank(p, backup_rank);
+        }
+#endif
+    }
+
+    #if REG_SHUFFLE_REG_CHECK
+    ShuffleRegCheck =0;
+    #endif
+
+    #if REG_SHUFFLE_REG_CHECK
+    ShuffleRegCheck =1;
+    #endif
+
+    // set dq delay
+    if(u1IsLP4Family(p->dram_type))
+    {
+        for (u1BitIdx=0; u1BitIdx<DQS_BIT_NUMBER; u1BitIdx+=2)
+        {
+             vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2+u1BitIdx*2), \
+                                            P_Fld(((U32)FinalWinPerBit[u1BitIdx].best_dqdly),SHU1_R0_B0_DQ2_RK0_RX_ARDQ0_R_DLY_B0) |\
+                                            P_Fld(((U32)FinalWinPerBit[u1BitIdx].best_dqdly),SHU1_R0_B0_DQ2_RK0_RX_ARDQ0_F_DLY_B0)| \
+                                            P_Fld(((U32)FinalWinPerBit[u1BitIdx+1].best_dqdly),SHU1_R0_B0_DQ2_RK0_RX_ARDQ1_R_DLY_B0) |\
+                                            P_Fld(((U32)FinalWinPerBit[u1BitIdx+1].best_dqdly),SHU1_R0_B0_DQ2_RK0_RX_ARDQ1_F_DLY_B0));
+
+             vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2+u1BitIdx*2), \
+                                            P_Fld(((U32)FinalWinPerBit[u1BitIdx+8].best_dqdly),SHU1_R0_B1_DQ2_RK0_RX_ARDQ0_R_DLY_B1) | \
+                                            P_Fld((U32)FinalWinPerBit[u1BitIdx+8].best_dqdly,SHU1_R0_B1_DQ2_RK0_RX_ARDQ0_F_DLY_B1)| \
+                                            P_Fld(((U32)FinalWinPerBit[u1BitIdx+9].best_dqdly),SHU1_R0_B1_DQ2_RK0_RX_ARDQ1_R_DLY_B1) |\
+                                            P_Fld((U32)FinalWinPerBit[u1BitIdx+9].best_dqdly,SHU1_R0_B1_DQ2_RK0_RX_ARDQ1_F_DLY_B1));
+
+            /*mcSHOW_DBG_MSG(("u1BitId %d  Addr 0x%2x = %2d %2d %2d %2d \n", u1BitIdx, DRAMC_REG_ADDR(DDRPHY_RXDQ1+u1BitIdx*2), \
+             *               FinalWinPerBit[u1BitIdx].best_dqdly, FinalWinPerBit[u1BitIdx+1].best_dqdly,  FinalWinPerBit[u1BitIdx+8].best_dqdly, FinalWinPerBit[u1BitIdx+9].best_dqdly));
+             */
+        }
+
+        #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        if(p->femmc_Ready==0)
+    	{
+            for (u1BitIdx=0; u1BitIdx<16; u1BitIdx++)
+        	{
+             	p->pSavetimeData->u1RxWinPerbit_DQ[p->channel][p->rank][u1BitIdx]=(U32)FinalWinPerBit[u1BitIdx].best_dqdly;
+
+          	}
+    	}
+        #endif
+    }
+#if ENABLE_LP3_SW
+    else //LPDDR3
+    {
+        /* p->rank = RANK_0, save to Reg Rank0 and Rank1, p->rank = RANK_1, save to Reg Rank1 */
+        for(ii=p->rank; ii<RANK_MAX; ii++)
+        {
+            vSetRank(p,ii);
+
+            //every 2bit dq have the same delay register address
+            for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+            {
+                    u1BitIdx = u1ByteIdx *DQS_BIT_NUMBER;
+
+                    dl_value[0] = FinalWinPerBit[u1BitIdx].best_dqdly;
+                    dl_value[1] = FinalWinPerBit[u1BitIdx+1].best_dqdly;
+                    dl_value[2] = FinalWinPerBit[u1BitIdx+2].best_dqdly;
+                    dl_value[3] = FinalWinPerBit[u1BitIdx+3].best_dqdly;
+                    dl_value[4] = FinalWinPerBit[u1BitIdx+4].best_dqdly;
+                    dl_value[5] = FinalWinPerBit[u1BitIdx+5].best_dqdly;
+                    dl_value[6] = FinalWinPerBit[u1BitIdx+6].best_dqdly;
+                    dl_value[7] = FinalWinPerBit[u1BitIdx+7].best_dqdly;
+                 Set_RX_DQ_DelayLine_Phy_Byte(p, u1ByteIdx, dl_value);
+            }
+        }
+        vSetRank(p, backup_rank);
+    }
+#endif
+
+    DramPhyReset(p);
+
+    vPrintCalibrationBasicInfo(p);
+
+#ifdef ETT_PRINT_FORMAT
+    if(u1IsLP4Family(p->dram_type))
+    {
+        mcSHOW_DBG_MSG(("DQS Delay:\nDQS0 = %d, DQS1 = %d\n"
+                        "DQM Delay:\nDQM0 = %d, DQM1 = %d\n",
+                            iDQSDlyPerbyte[0], iDQSDlyPerbyte[1],
+                            iDQMDlyPerbyte[0], iDQMDlyPerbyte[1]));
+    }
+#if ENABLE_LP3_SW
+    else
+    {
+        mcSHOW_DBG_MSG(("DQS Delay:\nDQS0 = %d, DQS1 = %d, DQS2 = %d, DQS3 = %d\n"
+                        "DQM Delay:\nDQM0 = %d, DQM1 = %d, DQM2 = %d, DQM3 = %d\n",
+                            iDQSDlyPerbyte[0], iDQSDlyPerbyte[1], iDQSDlyPerbyte[2], iDQSDlyPerbyte[3],
+                            iDQMDlyPerbyte[0], iDQMDlyPerbyte[1], iDQMDlyPerbyte[2], iDQMDlyPerbyte[3]));
+    }
+#endif /* ENABLE_LP3_SW */
+#else
+    if(u1IsLP4Family(p->dram_type))
+    {
+        mcSHOW_DBG_MSG(("DQS Delay:\nDQS0 = %2d, DQS1 = %2d\n"
+                        "DQM Delay:\nDQM0 = %2d, DQM1 = %2d\n",
+                            iDQSDlyPerbyte[0], iDQSDlyPerbyte[1],
+                            iDQMDlyPerbyte[0], iDQMDlyPerbyte[1]));
+    }
+#if ENABLE_LP3_SW
+    else
+    {
+        mcSHOW_DBG_MSG(("DQS Delay:\nDQS0 = %2d, DQS1 = %2d, DQS2 = %2d, DQS3 = %2d\n"
+                        "DQM Delay:\nDQM0 = %2d, DQM1 = %2d, DQM2 = %2d, DQM3 = %2d\n",
+                        iDQSDlyPerbyte[0], iDQSDlyPerbyte[1], iDQSDlyPerbyte[2], iDQSDlyPerbyte[3],
+                        iDQMDlyPerbyte[0], iDQMDlyPerbyte[1], iDQMDlyPerbyte[2], iDQMDlyPerbyte[3]));
+    }
+#endif /* ENABLE_LP3_SW */
+#endif
+    mcSHOW_DBG_MSG(("DQ Delay:\n"));
+
+    mcFPRINTF((fp_A60501, "\tdramc_rxdqs_perbit_swcal\n"));
+    mcFPRINTF((fp_A60501, "\tchannel=%d(1:cha) \n", p->channel));
+    mcFPRINTF((fp_A60501, "\tbus width=%d\n\n", p->data_width));
+
+    if(u1IsLP4Family(p->dram_type))
+    {
+        mcFPRINTF((fp_A60501, "DQS Delay:\n DQS0 = %2d DQS1 = %2d\n", iDQSDlyPerbyte[0], iDQSDlyPerbyte[1]));
+        mcFPRINTF((fp_A60501, "DQM Delay:\n DQM0 = %2d DQM1 = %2d\n", iDQMDlyPerbyte[0], iDQMDlyPerbyte[1]));
+    }
+#if ENABLE_LP3_SW
+    else
+    {
+        mcFPRINTF((fp_A60501, "DQS Delay:\n DQS0 = %2d DQS1 = %2d DQS2 = %2d DQS3 = %2d\n", iDQSDlyPerbyte[0], iDQSDlyPerbyte[1], iDQSDlyPerbyte[2], iDQSDlyPerbyte[3]));
+        mcFPRINTF((fp_A60501, "DQM Delay:\n DQM0 = %2d DQM1 = %2d DQM2 = %2d DQM3 = %2d\n", iDQMDlyPerbyte[0], iDQMDlyPerbyte[1], iDQMDlyPerbyte[2], iDQMDlyPerbyte[3]));
+    }
+#endif /* ENABLE_LP3_SW */
+    mcFPRINTF((fp_A60501, "DQ Delay:\n"));
+
+    for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx=u1BitIdx+4)
+    {
+    #ifdef ETT_PRINT_FORMAT
+        mcSHOW_DBG_MSG(("DQ%d =%d, DQ%d =%d, DQ%d =%d, DQ%d =%d\n", u1BitIdx, FinalWinPerBit[u1BitIdx].best_dqdly, u1BitIdx+1, FinalWinPerBit[u1BitIdx+1].best_dqdly, u1BitIdx+2, FinalWinPerBit[u1BitIdx+2].best_dqdly, u1BitIdx+3, FinalWinPerBit[u1BitIdx+3].best_dqdly));
+    #else
+        mcSHOW_DBG_MSG(("DQ%2d =%2d, DQ%2d =%2d, DQ%2d =%2d, DQ%2d =%2d\n", u1BitIdx, FinalWinPerBit[u1BitIdx].best_dqdly, u1BitIdx+1, FinalWinPerBit[u1BitIdx+1].best_dqdly, u1BitIdx+2, FinalWinPerBit[u1BitIdx+2].best_dqdly, u1BitIdx+3, FinalWinPerBit[u1BitIdx+3].best_dqdly));
+    #endif
+        mcFPRINTF((fp_A60501, "DQ%2d =%2d, DQ%2d =%2d, DQ%2d =%2d, DQ%2d=%2d\n", u1BitIdx, FinalWinPerBit[u1BitIdx].best_dqdly, u1BitIdx+1, FinalWinPerBit[u1BitIdx+1].best_dqdly, u1BitIdx+2, FinalWinPerBit[u1BitIdx+2].best_dqdly, u1BitIdx+3, FinalWinPerBit[u1BitIdx+3].best_dqdly));
+    }
+    mcSHOW_DBG_MSG(("\n\n"));
+    mcFPRINTF((fp_A60501, "\n\n"));
+
+    // BU request RX & TX window size log.
+#if 0//def RELEASE  // for parsing tool
+    if(u1UseTestEngine==1)
+    {
+        mcSHOW_DBG_MSG4(("RX CH%d R%d ,Freq %d\n", p->channel, p->rank, p->frequency));
+        for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+        {
+            mcSHOW_DBG_MSG4(("%d: %d\n", u1BitIdx, gFinalRXPerbitWin[p->channel][p->rank][u1BitIdx]));
+        }
+    }
+#endif
+
+    #if REG_SHUFFLE_REG_CHECK
+    ShuffleRegCheck =0;
+    #endif
+    mcSHOW_DBG_MSG3(("[DramcRxWindowPerbitCal] Done\n"));
+    mcFPRINTF((fp_A60501, "[DramcRxWindowPerbitCal] Done\n"));
+
+#if REG_ACCESS_PORTING_DGB
+    RegLogEnable =0;
+#endif
+
+return DRAM_OK;
+
+    // Log example  ==> Neec to update
+    /*
+------------------------------------------------------
+Start calculate dq time and dqs time /
+Find max DQS delay per byte / Adjust DQ delay to align DQS...
+------------------------------------------------------
+bit# 0 : dq time=11 dqs time= 8
+bit# 1 : dq time=11 dqs time= 8
+bit# 2 : dq time=11 dqs time= 6
+bit# 3 : dq time=10 dqs time= 8
+bit# 4 : dq time=11 dqs time= 8
+bit# 5 : dq time=10 dqs time= 8
+bit# 6 : dq time=11 dqs time= 8
+bit# 7 : dq time= 9 dqs time= 6
+----seperate line----
+bit# 8 : dq time=12 dqs time= 7
+bit# 9 : dq time=10 dqs time= 8
+bit#10 : dq time=11 dqs time= 8
+bit#11 : dq time=10 dqs time= 8
+bit#12 : dq time=11 dqs time= 8
+bit#13 : dq time=11 dqs time= 8
+bit#14 : dq time=11 dqs time= 8
+bit#15 : dq time=12 dqs time= 8
+----seperate line----
+bit#16 : dq time=11 dqs time= 7
+bit#17 : dq time=10 dqs time= 8
+bit#18 : dq time=11 dqs time= 7
+bit#19 : dq time=11 dqs time= 6
+bit#20 : dq time=10 dqs time= 9
+bit#21 : dq time=11 dqs time=10
+bit#22 : dq time=11 dqs time=10
+bit#23 : dq time= 9 dqs time= 9
+----seperate line----
+bit#24 : dq time=12 dqs time= 6
+bit#25 : dq time=13 dqs time= 6
+bit#26 : dq time=13 dqs time= 7
+bit#27 : dq time=11 dqs time= 7
+bit#28 : dq time=12 dqs time= 8
+bit#29 : dq time=10 dqs time= 8
+bit#30 : dq time=13 dqs time= 7
+bit#31 : dq time=11 dqs time= 8
+----seperate line----
+==================================================
+    dramc_rxdqs_perbit_swcal_v2
+    channel=2(2:cha, 3:chb) apply = 1
+==================================================
+DQS Delay :
+ DQS0 = 0 DQS1 = 0 DQS2 = 0 DQS3 = 0
+DQ Delay :
+DQ 0 =  1 DQ 1 =  1 DQ 2 =  2 DQ 3 =  1
+DQ 4 =  1 DQ 5 =  1 DQ 6 =  1 DQ 7 =  1
+DQ 8 =  2 DQ 9 =  1 DQ10 =  1 DQ11 =  1
+DQ12 =  1 DQ13 =  1 DQ14 =  1 DQ15 =  2
+DQ16 =  2 DQ17 =  1 DQ18 =  2 DQ19 =  2
+DQ20 =  0 DQ21 =  0 DQ22 =  0 DQ23 =  0
+DQ24 =  3 DQ25 =  3 DQ26 =  3 DQ27 =  2
+DQ28 =  2 DQ29 =  1 DQ30 =  3 DQ31 =  1
+_______________________________________________________________
+   */
+}
+#endif //SIMULATION_RX_PERBIT
+
+#if SIMULATION_DATLAT
+static void dle_factor_handler(DRAMC_CTX_T *p, U8 curr_val, U8 pip_num)
+{
+    U8 u1DATLAT_DSEL=0;
+    U8 u1DLECG_OptionEXT1 = 0;
+    U8 u1DLECG_OptionEXT2 = 0;
+    U8 u1DLECG_OptionEXT3 = 0;
+
+#if REG_ACCESS_PORTING_DGB
+    RegLogEnable =1;
+    mcSHOW_DBG_MSG(("\n[REG_ACCESS_PORTING_FUNC] dle_factor_handler\n"));
+    mcFPRINTF((fp_A60501, "\n[REG_ACCESS_PORTING_FUNC] dle_factor_handler\n"));
+#endif
+
+    #if REG_SHUFFLE_REG_CHECK
+    ShuffleRegCheck =1;
+    #endif
+
+    if(curr_val<2)
+        curr_val =2;
+
+#if RX_PIPE_BYPASS_EN
+    /* if rx pipe bypass en, then datlat will less 1 pipe. So DSEL minus 1, not minus 2 */
+    u1DATLAT_DSEL = curr_val - 1;
+#else
+    u1DATLAT_DSEL = curr_val - 2;
+#endif
+
+    // Datlat_dsel = datlat -1, only 1 TX pipe
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU_CONF1),
+                                        P_Fld(curr_val, SHU_CONF1_DATLAT) |
+                                        P_Fld(u1DATLAT_DSEL, SHU_CONF1_DATLAT_DSEL) |
+                                        P_Fld(u1DATLAT_DSEL, SHU_CONF1_DATLAT_DSEL_PHY));
+
+    //(>=8 & <14) set EXT1 =1, EXT2=0, EXT3=0
+    //(>= 14 & <19) set EXT1=1, EXT2=1, EXT3=0
+    //(>=19) set EXT1=1, EXT2=1, EXT3=1
+    u1DLECG_OptionEXT1 = (curr_val >= 8)? (1): (0);
+    u1DLECG_OptionEXT2 = (curr_val >= 14)? (1): (0);
+    u1DLECG_OptionEXT3 = (curr_val >= 19)? (1): (0);
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU_PIPE), P_Fld(u1DLECG_OptionEXT1, SHU_PIPE_READ_START_EXTEND1)
+                | P_Fld(u1DLECG_OptionEXT1, SHU_PIPE_DLE_LAST_EXTEND1)
+                | P_Fld((u1DLECG_OptionEXT2), SHU_PIPE_READ_START_EXTEND2)
+                | P_Fld((u1DLECG_OptionEXT2), SHU_PIPE_DLE_LAST_EXTEND2)
+                | P_Fld((u1DLECG_OptionEXT3), SHU_PIPE_READ_START_EXTEND3)
+                | P_Fld((u1DLECG_OptionEXT3), SHU_PIPE_DLE_LAST_EXTEND3));
+
+    #if REG_SHUFFLE_REG_CHECK
+    ShuffleRegCheck =0;
+    #endif
+
+    DramPhyReset(p);
+
+#if REG_ACCESS_PORTING_DGB
+    RegLogEnable =0;
+#endif
+}
+
+//-------------------------------------------------------------------------
+/** Dramc_ta2_rx_scan
+ */
+//-------------------------------------------------------------------------
+static U32 Dramc_ta2_rx_scan(DRAMC_CTX_T *p, U8 u1UseTestEngine)
+{
+    U32 ii, u4err_value;
+    S16 iDelay;
+#if ENABLE_LP3_SW
+    U8 u1ByteIdx;
+    U8 dl_value[8]={0,0,0,0,0,0,0,0};
+#endif
+
+    // reg backup
+#if 0
+        U32 u4RegBak_DDRPHY_RXDQ_RK0[DQS_NUMBER][5];  // rank 0
+        for (ii=0; ii<5; ii++)
+        {
+            if(u1IsLP4Family(p->dram_type))
+            {
+                u4RegBak_DDRPHY_RXDQ_RK0[0][ii] =(u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2+ii*4), PHY_FLD_FULL)); // rank 0, byte 0
+                u4RegBak_DDRPHY_RXDQ_RK0[1][ii] =(u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2+ii*4), PHY_FLD_FULL)); // rank 0, byte 1
+            }
+#if ENABLE_LP3_SW
+            else //LPDDR3 , only record rank 0, will not modify rank1
+            {
+#if 0 //LP3 no need to backup DQ delay line reg
+                for(u1ByteIdx=0; u1ByteIdx<4; u1ByteIdx++)
+                {
+                    u4RegBak_DDRPHY_RXDQ_RK0[u1ByteIdx][ii] =u4IO32ReadFldAlign_Phy_Byte(u1ByteIdx, DRAMC_REG_ADDR(DDRPHY_SHU2_R0_B0_DQ2+ii*4), PHY_FLD_FULL);
+                }
+#endif
+            }
+#endif
+        }
+#endif
+
+        // Adjust DQM output delay to 0
+        if(u1IsLP4Family(p->dram_type))
+        {
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6), \
+                                P_Fld(0,SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_R_DLY_B0) |P_Fld(0, SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_F_DLY_B0));
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ6), \
+                                P_Fld(0,SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_R_DLY_B1) |P_Fld(0, SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_F_DLY_B1));
+        }
+#if ENABLE_LP3_SW
+        else
+        {
+            for(u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+            {
+                Set_RX_DQM_DelayLine_Phy_Byte(p, u1ByteIdx, 0);
+            }
+        }
+#endif
+
+        // Adjust DQ output delay to 0
+        //every 2bit dq have the same delay register address
+        if(u1IsLP4Family(p->dram_type))
+        {
+            for (ii=0; ii<4; ii++)
+            {
+                vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2+ii*4), 0);  //DQ0~DQ7
+                vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2+ii*4), 0);//DQ8~DQ15
+            }
+        }
+#if ENABLE_LP3_SW
+        else //LPDDR3
+        {
+            for (u1ByteIdx=0; u1ByteIdx<DQS_NUMBER; u1ByteIdx++)
+            {
+                Set_RX_DQ_DelayLine_Phy_Byte(p, u1ByteIdx, dl_value);
+            }
+        }
+#endif
+
+        if(u1UseTestEngine)
+            DramcEngine2Init(p, p->test2_1, p->test2_2, p->test_pattern, 0);
+
+       // quick rx dqs search
+       //mcSHOW_DBG_MSG(("quick rx dqs search\n"));
+       //mcFPRINTF((fp_A60817, "quick rx dqs search\n", iDelay));
+       for (iDelay=-32; iDelay<=32; iDelay+=4)
+       {
+           //mcSHOW_DBG_MSG(("%2d, ", iDelay));
+           //mcFPRINTF((fp_A60817,"%2d, ", iDelay));
+           SetRxDqDqsDelay(p, iDelay);
+
+           if(u1UseTestEngine)
+           {
+               u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, p->test_pattern);
+           }
+           else
+           {
+               //sagy: no definition of DramcRxWinRDDQC, u4err_value = DramcRxWinRDDQC(p);
+           }
+
+            if(u4err_value ==0)// rx dqs found.
+                break;
+        }
+
+        if(u1UseTestEngine)
+            DramcEngine2End(p);
+
+        #ifdef ETT_PRINT_FORMAT
+        mcSHOW_DBG_MSG(("RX DQS dly = %d, ", iDelay));
+        #else
+        mcSHOW_DBG_MSG(("RX DQS dly = %2d, ", iDelay));
+        #endif
+        mcFPRINTF((fp_A60501, "RX DQS dly = %2d, ", iDelay));
+
+#if 0
+        // restore registers
+        for (ii=0; ii<5; ii++)
+        {
+            if(u1IsLP4Family(p->dram_type))
+            {
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2+ ii*4), u4RegBak_DDRPHY_RXDQ_RK0[0][ii] , PHY_FLD_FULL);
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2+ ii*4), u4RegBak_DDRPHY_RXDQ_RK0[1][ii] , PHY_FLD_FULL);
+            }
+#if ENABLE_LP3_SW
+            else //LPDDR3
+             {
+#if 0 //LP3 no need to restore backup DQ delay line reg
+                for(u1ByteIdx=0; u1ByteIdx<4; u1ByteIdx++)
+                {
+                     vIO32WriteFldAlign_Phy_Byte(u1ByteIdx, DRAMC_REG_ADDR(DDRPHY_SHU2_R0_B0_DQ2+ ii*4), u4RegBak_DDRPHY_RXDQ_RK0[u1ByteIdx][ii] , PHY_FLD_FULL);
+                }
+#endif
+            }
+#endif
+        }
+#endif
+
+        return u4err_value;
+}
+
+
+static U8 aru1RxDatlatResult[CHANNEL_NUM][RANK_MAX];
+
+U8 DramcRxdatlatScan(DRAMC_CTX_T *p, DRAM_DATLAT_CALIBRATION_TYTE_T use_rxtx_scan)
+{
+    U8 ii;
+    U32 u4prv_register_080;
+    U32 u4err_value= 0xffffffff;
+    U8 ucfirst, ucbegin, ucsum, ucbest_step, ucpipe_num =0;
+    U16 u2DatlatBegin;
+
+    // error handling
+    if (!p)
+    {
+        mcSHOW_ERR_MSG(("context NULL\n"));
+        return DRAM_FAIL;
+    }
+#if REG_ACCESS_PORTING_DGB
+    RegLogEnable =1;
+    mcSHOW_DBG_MSG(("\n[REG_ACCESS_PORTING_FUNC]   DramcRxdatlatCal\n"));
+    mcFPRINTF((fp_A60501, "\n[REG_ACCESS_PORTING_FUNC]   DramcRxdatlatCal\n"));
+#endif
+
+    mcSHOW_DBG_MSG(("\n[DATLAT]\n"
+                    "Freq=%d, CH%d RK%d, use_rxtx_scan=%d\n\n",
+                         p->frequency, p->channel, p->rank, use_rxtx_scan));
+
+    mcFPRINTF((fp_A60501, "\n\tDATLAT calibration\n"));
+    mcFPRINTF((fp_A60501, "\tch=%d(1:cha), rank=%d, use_rxtx_scan=%d\n\n",
+                             p->channel, p->rank, use_rxtx_scan));
+
+    // [11:10] DQIENQKEND 01 -> 00 for DATLAT calibration issue, DQS input enable will refer to DATLAT
+    // if need to enable this (for power saving), do it after all calibration done
+    //u4prv_register_0d8 = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_MCKDLY));
+    //vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_PADCTRL), P_Fld(0, PADCTRL_DQIENQKEND) | P_Fld(0, PADCTRL_DQIENLATEBEGIN));
+
+    // pre-save
+    // 0x07c[6:4]   DATLAT bit2-bit0
+    u4prv_register_080 = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_CONF1));
+
+    // init best_step to default
+    ucbest_step = (U8) u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_CONF1), SHU_CONF1_DATLAT);
+    mcSHOW_DBG_MSG(("DATLAT Default: 0x%x\n", ucbest_step));
+    mcFPRINTF((fp_A60501, "DATLAT Default: 0x%x\n", ucbest_step));
+
+#ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+    U8 u1GUMP_INIT_RG_LOG_TO_DE_bak = gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag;
+    gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag=0;
+#endif
+
+    // 1.set DATLAT 0-15 (0-21 for MT6595)
+    // 2.enable engine1 or engine2
+    // 3.check result  ,3~4 taps pass
+    // 4.set DATLAT 2nd value for optimal
+
+    // Initialize
+    ucfirst = 0xff;
+    ucbegin = 0;
+    ucsum = 0;
+
+    DramcEngine2Init(p, p->test2_1, p->test2_2, p->test_pattern, 0);
+#if (FOR_DV_SIMULATION_USED==0)
+		u2DatlatBegin=7;
+#else
+		u2DatlatBegin=0;
+#endif
+
+    #if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_DATLAT)
+	if(p->femmc_Ready==1)
+	{
+        ucbest_step = p->pSavetimeData->u1RxDatlat_Save[p->channel][p->rank];
+    }
+    else
+    #endif
+    {
+        for (ii = u2DatlatBegin; ii < DATLAT_TAP_NUMBER; ii++)
+        {
+            // 1
+            dle_factor_handler(p, ii, ucpipe_num);
+
+            // 2
+            if(use_rxtx_scan == fcDATLAT_USE_DEFAULT)
+            {
+                u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, p->test_pattern);
+            }
+#if ENABLE_LP3_SW
+            else  //if(use_rxtx_scan == fcDATLAT_USE_RX_SCAN)//LPDDR3, LP4 Should not enter if datlat calibration is after RDDQC
+            {
+                u4err_value = Dramc_ta2_rx_scan(p, 1);
+            }
+#endif
+
+            // 3
+            if (u4err_value == 0)
+            {
+                if (ucbegin == 0)
+                {
+                    // first tap which is pass
+                    ucfirst = ii;
+                    ucbegin = 1;
+                }
+                if (ucbegin == 1)
+                {
+                    ucsum++;
+
+                    if(ucsum >4)
+                        break;  //early break.
+                }
+            }
+            else
+            {
+                if (ucbegin == 1)
+                {
+                    // pass range end
+                    ucbegin = 0xff;
+                }
+            }
+
+            #ifdef ETT_PRINT_FORMAT
+            mcSHOW_DBG_MSG(("%d, 0x%X, sum=%d\n", ii, u4err_value, ucsum));
+            #else
+            mcSHOW_DBG_MSG(("TAP=%2d, err_value=0x%8x,  sum=%d\n", ii, u4err_value, ucsum));
+            #endif
+            mcFPRINTF((fp_A60501, "TAP=%2d, err_value=0x%8x, begin=%d, first=%3d, sum=%d\n", ii, u4err_value, ucbegin, ucfirst, ucsum));
+        }
+
+        DramcEngine2End(p);
+
+        // 4
+        if (ucsum == 0)
+        {
+            mcSHOW_ERR_MSG(("no DATLAT taps pass, DATLAT calibration fail!\n"));
+        }
+        else if (ucsum <= 3)
+        {
+            ucbest_step = ucfirst + (ucsum>>1);
+        }
+        else // window is larger htan 3
+        {
+            ucbest_step = ucfirst + 2;
+        }
+    }
+    aru1RxDatlatResult[p->channel][p->rank] = ucbest_step;
+
+   #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+	if(p->femmc_Ready==0)
+    {
+        p->pSavetimeData->u1RxDatlat_Save[p->channel][p->rank] = ucbest_step;
+    }
+   #endif
+
+    mcSHOW_DBG_MSG(("best_step=%d\n\n", ucbest_step));
+    mcFPRINTF((fp_A60501, "best_step=%d\n", ucbest_step));
+
+
+#ifdef FOR_HQA_TEST_USED
+    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "DATLAT", 0, ucbest_step, NULL);
+#endif
+
+#ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+    gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag = u1GUMP_INIT_RG_LOG_TO_DE_bak;
+#endif
+
+    #if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_DATLAT)
+	if(p->femmc_Ready==1)
+	{
+        dle_factor_handler(p, ucbest_step, ucpipe_num);
+        vSetCalibrationResult(p, DRAM_CALIBRATION_DATLAT, DRAM_OK);
+	}
+    else
+    #endif
+    {
+        if(ucsum <4)
+        {
+            mcSHOW_DBG_MSG2(("[NOTICE] CH%d, DatlatSum %d\n", p->channel, ucsum));
+            mcFPRINTF((fp_A60501, "[NOTICE] CH%d, DatlatSum  %d\n", p->channel, ucsum));
+        }
+
+        if (ucsum == 0)
+        {
+            mcSHOW_ERR_MSG(("DATLAT calibration fail, write back to default values!\n"));
+            vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_CONF1), u4prv_register_080);
+            vSetCalibrationResult(p, DRAM_CALIBRATION_DATLAT, DRAM_FAIL);
+        }
+        else
+        {
+            dle_factor_handler(p, ucbest_step, ucpipe_num);
+            vSetCalibrationResult(p, DRAM_CALIBRATION_DATLAT, DRAM_OK);
+        }
+    }
+    // [11:10] DQIENQKEND 01 -> 00 for DATLAT calibration issue, DQS input enable will refer to DATLAT
+    // if need to enable this (for power saving), do it after all calibration done
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_PADCTRL), P_Fld(1, PADCTRL_DQIENQKEND) | P_Fld(1, PADCTRL_DQIENLATEBEGIN));
+
+    mcSHOW_DBG_MSG3(("[DramcRxdatlatCal] Done\n"));
+    mcFPRINTF((fp_A60501, "[DramcRxdatlatCal] Done\n"));
+
+#if REG_ACCESS_PORTING_DGB
+    RegLogEnable =0;
+#endif
+
+    return ucsum;
+}
+
+void DramcRxdatlatCal(DRAMC_CTX_T *p)
+{
+    U8 u1DatlatWindowSum;
+
+    u1DatlatWindowSum = DramcRxdatlatScan(p, fcDATLAT_USE_DEFAULT);
+
+    if((p->dram_type == TYPE_LPDDR3) &&(u1DatlatWindowSum <5))
+    {
+        mcSHOW_DBG_MSG(("\nDatlatWindowSum %d too small(<5), Start RX + Datlat scan\n", u1DatlatWindowSum));
+        DramcRxdatlatScan(p, fcDATLAT_USE_RX_SCAN);
+    }
+}
+
+DRAM_STATUS_T DramcDualRankRxdatlatCal(DRAMC_CTX_T *p)
+{
+    U8 u1FinalDatlat, u1Datlat0, u1Datlat1;
+
+    u1Datlat0 = aru1RxDatlatResult[p->channel][0];
+    u1Datlat1 = aru1RxDatlatResult[p->channel][1];
+
+    if(u1Datlat0> u1Datlat1)
+    {
+        u1FinalDatlat= u1Datlat0;
+    }
+    else
+    {
+        u1FinalDatlat= u1Datlat1;
+    }
+
+    #if ENABLE_READ_DBI
+    if(p->DBI_R_onoff[p->dram_fsp])
+    {
+      u1FinalDatlat++;
+    }
+    #endif
+
+    dle_factor_handler(p, u1FinalDatlat, 3);
+    mcSHOW_DBG_MSG(("[DualRankRxdatlatCal] RK0: %d, RK1: %d, Final_Datlat %d\n", u1Datlat0, u1Datlat1, u1FinalDatlat));
+    mcFPRINTF((fp_A60501, "[DualRankRxdatlatCal] RK0: %d, RK1: %d, Final_Datlat %d\n", u1Datlat0, u1Datlat1, u1FinalDatlat));
+
+    return DRAM_OK;
+
+}
+#endif //SIMULATION_DATLAT
+
+#if SIMULATION_TX_PERBIT
+
+#if TX_OE_CALIBATION
+#define TX_OE_PATTERN_USE_TA2 1
+#define TX_OE_SCAN_FULL_RANGE 0
+
+void DramcTxOECalibration(DRAMC_CTX_T *p)
+{
+    U8 u1ByteIdx, ucBegin[2]={0}, ucEnd[2]={0xff, 0xff}, ucbest_step[2];
+    //U8 ucbegin=0xff, , ucfirst, ucsum, ucbest_step;
+    U32 u4RegValue_TXDLY, u4RegValue_dly, u4err_value;
+    U16 u2Delay, u2TempVirtualDelay, u2SmallestVirtualDelay=0xffff;
+    U16 u2DQOEN_DelayBegin, u2DQEN_DelayEnd;
+    U8 ucdq_ui_large_bak[DQS_NUMBER], ucdq_ui_small_bak[DQS_NUMBER];
+    U8 ucdq_oen_ui_large[2], ucdq_oen_ui_small[2];
+    U8 ucdq_current_ui_large, ucdq_current_ui_small;
+    //U8 ucdq_ui_large_reg_value=0xff, ucdq_ui_small_reg_value=0xff;
+
+    if(!u1IsLP4Family(p->dram_type))
+        return; //only apply in LP4
+
+    #if TX_OE_PATTERN_USE_TA2
+    mcSHOW_DBG_MSG(("\n[DramC_TX_OE_Calibration] TA2\n"));
+    #else
+    mcSHOW_DBG_MSG(("\n[DramC_TX_OE_Calibration] DMA\n"));
+    #endif
+
+    #ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+    U8 u1GUMP_INIT_RG_LOG_TO_DE_bak = gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag;
+    gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag=0;
+    #endif
+
+
+#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION)
+    if(p->femmc_Ready==1)
+    {
+        for(u1ByteIdx=0; u1ByteIdx<DQS_NUMBER_LP4; u1ByteIdx++)
+        {
+            ucdq_oen_ui_large[u1ByteIdx]= p->pSavetimeData->u1TX_OE_DQ_MCK[p->channel][p->rank][u1ByteIdx];
+            ucdq_oen_ui_small[u1ByteIdx]= p->pSavetimeData->u1TX_OE_DQ_UI[p->channel][p->rank][u1ByteIdx];
+        }
+    }
+    else
+#endif
+    {
+        u4RegValue_TXDLY= u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0));
+        u4RegValue_dly= u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2));
+
+        // find smallest DQ byte delay
+        for(u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+        {
+            ucdq_ui_large_bak[u1ByteIdx] = (u4RegValue_TXDLY >> (u1ByteIdx*4)) &0x7;
+            ucdq_ui_small_bak[u1ByteIdx] = (u4RegValue_dly >> (u1ByteIdx*4)) &0x7;
+
+            u2TempVirtualDelay = (ucdq_ui_large_bak[u1ByteIdx] <<3) + ucdq_ui_small_bak[u1ByteIdx];
+            if(u2TempVirtualDelay < u2SmallestVirtualDelay)
+            {
+                u2SmallestVirtualDelay = u2TempVirtualDelay;
+            }
+
+            mcSHOW_DBG_MSG(("Original DQ_B%d (%d %d) =%d, OEN = %d\n", u1ByteIdx, ucdq_ui_large_bak[u1ByteIdx], ucdq_ui_small_bak[u1ByteIdx], u2TempVirtualDelay, u2TempVirtualDelay-TX_DQ_OE_SHIFT_LP4));
+        }
+
+        #if TX_OE_PATTERN_USE_TA2
+        DramcEngine2Init(p, p->test2_1, p->test2_2, TEST_AUDIO_PATTERN, 0);
+        #else
+        DramcDmaEngine((DRAMC_CTX_T *)p, 0x50000000, 0x60000000, 0xff00, 8, DMA_PREPARE_DATA_ONLY, p->support_channel_num);
+        #endif
+
+        #if TX_OE_SCAN_FULL_RANGE
+        // -17~+8 UI
+        if(u2SmallestVirtualDelay >= 17)
+            u2DQOEN_DelayBegin = u2SmallestVirtualDelay -17;
+        else
+            u2DQOEN_DelayBegin =0;
+
+        u2DQEN_DelayEnd = u2DQOEN_DelayBegin +25;
+
+        #else // reduce range to speed up
+        if(u2SmallestVirtualDelay >= 7)
+            u2DQOEN_DelayBegin = u2SmallestVirtualDelay -7;
+        else
+            u2DQOEN_DelayBegin =0;
+
+        u2DQEN_DelayEnd = u2DQOEN_DelayBegin +10;
+        #endif
+
+        for (u2Delay = u2DQOEN_DelayBegin; u2Delay <= u2DQEN_DelayEnd; u2Delay++)
+        {
+            ucdq_current_ui_large= (u2Delay >>3);
+            ucdq_current_ui_small = u2Delay & 0x7;
+            //mcSHOW_DBG_MSG(("\nucdq_oen_ui %d %d ", ucdq_oen_ui_large, ucdq_oen_ui_small));
+
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), \
+                                            P_Fld(ucdq_current_ui_large, SHURK0_SELPH_DQ0_TXDLY_OEN_DQ0) | \
+                                            P_Fld(ucdq_current_ui_large, SHURK0_SELPH_DQ0_TXDLY_OEN_DQ1) );
+
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), \
+                                            P_Fld(ucdq_current_ui_large, SHURK0_SELPH_DQ1_TXDLY_OEN_DQM0) | \
+                                            P_Fld(ucdq_current_ui_large, SHURK0_SELPH_DQ1_TXDLY_OEN_DQM1));
+
+            // DLY_DQ[2:0]
+           vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2), \
+                                            P_Fld(ucdq_current_ui_small, SHURK0_SELPH_DQ2_DLY_OEN_DQ0) | \
+                                            P_Fld(ucdq_current_ui_small, SHURK0_SELPH_DQ2_DLY_OEN_DQ1) );
+
+             // DLY_DQM[2:0]
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3), \
+                                             P_Fld(ucdq_current_ui_small, SHURK0_SELPH_DQ3_DLY_OEN_DQM0) | \
+                                             P_Fld(ucdq_current_ui_small, SHURK0_SELPH_DQ3_DLY_OEN_DQM1));
+
+            #if TX_OE_PATTERN_USE_TA2
+            u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, TEST_AUDIO_PATTERN);
+            #else
+            u4err_value= DramcDmaEngine((DRAMC_CTX_T *)p, 0x50000000, 0x60000000, 0xff00, 8, DMA_CHECK_DATA_ACCESS_AND_COMPARE, p->support_channel_num);
+            #endif
+
+            // 3
+            for(u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+            {
+                if (((u4err_value >> (u1ByteIdx<<3)) & 0xff) == 0)
+                {
+                    if(ucBegin[u1ByteIdx]==0)
+                        ucBegin[u1ByteIdx]=1;
+
+                    ucEnd[u1ByteIdx] = u2Delay;
+                }
+            }
+
+#ifdef ETT_PRINT_FORMAT
+            mcSHOW_DBG_MSG(("%d, 0x%X, End_B0=%d End_B1=%d\n", u2Delay, u4err_value, ucEnd[0], ucEnd[1]));
+#else
+            mcSHOW_DBG_MSG(("TAP=%2d, err_value=0x%8x, End_B0=%d End_B1=%d\n", u2Delay, u4err_value, ucEnd[0], ucEnd[1]));
+#endif
+            mcFPRINTF((fp_A60501, "TAP=%2d, err_value=0x%8x, End_B0=%d End_B1=%d\n", u2Delay, u4err_value, ucEnd[0], ucEnd[1]));
+
+            if(((u4err_value & 0xffff) !=0) && ucBegin[0]==1 && ucBegin[1]==1)
+                break; // early break;
+        }
+
+        #if TX_OE_PATTERN_USE_TA2
+        DramcEngine2End(p);
+        #endif
+
+        // 4
+        for(u1ByteIdx=0; u1ByteIdx<DQS_NUMBER_LP4; u1ByteIdx++)
+        {
+            if (ucEnd[u1ByteIdx] == 0xff)
+            {
+                ucbest_step[u1ByteIdx] = u2SmallestVirtualDelay - TX_DQ_OE_SHIFT_LP4;  //bakcup original delay, will be uesed if Pass window not found.
+                mcSHOW_ERR_MSG(("Byte %d no TX OE taps pass, calibration fail!\n", u1ByteIdx));
+            }
+            else // window is larger htan 3
+            {
+                ucbest_step[u1ByteIdx] = ucEnd[u1ByteIdx] - 3;
+            }
+            mcSHOW_DBG_MSG(("Byte%d end_step=%d  best_step=%d\n", u1ByteIdx, ucEnd[u1ByteIdx], ucbest_step[u1ByteIdx]));
+            mcFPRINTF((fp_A60501, "Byte%d first_step=%d best_step=%d\n", u1ByteIdx, ucEnd[u1ByteIdx], ucbest_step[u1ByteIdx]));
+
+            ucdq_oen_ui_large[u1ByteIdx]= (ucbest_step[u1ByteIdx] >>3);
+            ucdq_oen_ui_small[u1ByteIdx] = ucbest_step[u1ByteIdx] & 0x7;
+        }
+    }
+
+    #ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+    gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag = u1GUMP_INIT_RG_LOG_TO_DE_bak;
+    #endif
+
+    for(u1ByteIdx=0; u1ByteIdx<DQS_NUMBER_LP4; u1ByteIdx++)
+    {
+        mcSHOW_DBG_MSG(("Byte%d TX OE(2T, 0.5T) = (%d, %d)\n", u1ByteIdx, ucdq_oen_ui_large[u1ByteIdx], ucdq_oen_ui_small[u1ByteIdx]));
+    }
+    mcSHOW_DBG_MSG(("\n\n"));
+
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), \
+                                    P_Fld(ucdq_oen_ui_large[0], SHURK0_SELPH_DQ0_TXDLY_OEN_DQ0) | \
+                                    P_Fld(ucdq_oen_ui_large[1], SHURK0_SELPH_DQ0_TXDLY_OEN_DQ1));
+
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), \
+                                    P_Fld(ucdq_oen_ui_large[0], SHURK0_SELPH_DQ1_TXDLY_OEN_DQM0) | \
+                                    P_Fld(ucdq_oen_ui_large[1], SHURK0_SELPH_DQ1_TXDLY_OEN_DQM1));
+    // DLY_DQ[2:0]
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2), \
+                                    P_Fld(ucdq_oen_ui_small[0], SHURK0_SELPH_DQ2_DLY_OEN_DQ0) | \
+                                    P_Fld(ucdq_oen_ui_small[1], SHURK0_SELPH_DQ2_DLY_OEN_DQ1) );
+     // DLY_DQM[2:0]
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3), \
+                                     P_Fld(ucdq_oen_ui_small[0], SHURK0_SELPH_DQ3_DLY_OEN_DQM0) | \
+                                     P_Fld(ucdq_oen_ui_small[1], SHURK0_SELPH_DQ3_DLY_OEN_DQM1));
+
+    #if (SUPPORT_SAVE_TIME_FOR_CALIBRATION)
+    if(p->femmc_Ready==0)
+    {
+        for(u1ByteIdx=0; u1ByteIdx<DQS_NUMBER_LP4; u1ByteIdx++)
+        {
+            p->pSavetimeData->u1TX_OE_DQ_MCK[p->channel][p->rank][u1ByteIdx] = ucdq_oen_ui_large[u1ByteIdx];
+            p->pSavetimeData->u1TX_OE_DQ_UI[p->channel][p->rank][u1ByteIdx] = ucdq_oen_ui_small[u1ByteIdx];
+        }
+    }
+    #endif
+
+}
+#endif
+
+
+
+//=============================================================
+///// DramC TX perbi calibration ----------Begin--------------
+//=============================================================
+//-------------------------------------------------------------------------
+/** DramcTxWindowPerbitCal (v2)
+ *  TX DQS per bit SW calibration.
+ *  @param p                Pointer of context created by DramcCtxCreate.
+ *  @param  apply           (U8): 0 don't apply the register we set  1 apply the register we set ,default don't apply.
+ *  @retval status          (DRAM_STATUS_T): DRAM_OK or DRAM_FAIL
+ */
+//-------------------------------------------------------------------------
+#if (SW_CHANGE_FOR_SIMULATION ||FOR_DV_SIMULATION_USED)
+#define TX_VREF_RANGE_BEGIN       0
+#define TX_VREF_RANGE_END           2 // binary 110010
+#define TX_VREF_RANGE_STEP         2
+#else
+#define TX_VREF_RANGE_BEGIN       16
+#define TX_VREF_RANGE_END           50 // binary 110010
+#define TX_VREF_RANGE_STEP         2
+#endif
+
+#define TX_DQ_UI_TO_PI_TAP         64 // 1 PI = tCK/64, total 128 PI, 1UI = 32 PI
+#define LP4_TX_VREF_DATA_NUM 50
+#define LP4_TX_VREF_PASS_CONDITION 0
+#define LP4_TX_VREF_BOUNDARY_NOT_READY 0xff
+
+typedef struct _PASS_WIN_DATA_BY_VREF_T
+{
+    U16 u2VrefUsed;
+    U16 u2WinSum_byVref;
+    U16 u2MinWinSize_byVref;
+} PASS_WIN_DATA_BY_VREF_T;
+
+U16 u2TX_DQ_PreCal_LP4[DQS_NUMBER];  // LP4 only
+
+
+void TxWinTransferDelayToUIPI(DRAMC_CTX_T *p, DRAM_TX_PER_BIT_CALIBRATION_TYTE_T calType, U16 uiDelay, U8 u1AdjustPIToCenter, U8* pu1UILarge_DQ, U8* pu1UISmall_DQ, U8* pu1PI, U8* pu1UILarge_DQOE, U8* pu1UISmall_DQOE)
+{
+    U8 u1Small_ui_to_large, u1PI, u164PIto1UI;
+    U16 u2TmpValue;
+
+#if (fcFOR_PINMUX == fcLaurel) //LP2 is full rate
+    //in LP4, 8 small UI =  1 large UI
+    //in LP3, 4 small UI =  1 large UI
+    if(u1IsLP4Family(p->dram_type))
+    {
+        u1Small_ui_to_large =  3;
+        u164PIto1UI = 1;
+    }
+    else //LPDDR3
+    {
+        u1Small_ui_to_large =  2;
+        u164PIto1UI = 0;
+    }
+#endif
+
+    if(pu1PI != NULL)
+    {
+        #if 0
+        u1PI = uiDelay% TX_DQ_UI_TO_PI_TAP;
+        #else
+        u1PI = uiDelay & (TX_DQ_UI_TO_PI_TAP-1);
+        #endif
+
+        *pu1PI =u1PI;
+    }
+
+    u2TmpValue = (uiDelay /TX_DQ_UI_TO_PI_TAP)<<u164PIto1UI;
+
+    if(u1AdjustPIToCenter && (pu1PI!=NULL))
+    {
+        if(u1PI<10)
+        {
+            u1PI += (TX_DQ_UI_TO_PI_TAP)>>1;
+            u2TmpValue --;
+        }
+        else if(u1PI>TX_DQ_UI_TO_PI_TAP-10)
+        {
+            u1PI -= (TX_DQ_UI_TO_PI_TAP)>>1;
+            u2TmpValue ++;
+        }
+
+        *pu1PI =u1PI;
+    }
+
+    #if 0
+    *pu1UISmall_DQ = u2TmpValue % u1Small_ui_to_large;
+    *pu1UILarge_DQ = u2TmpValue / u1Small_ui_to_large;
+    #else
+    *pu1UISmall_DQ = u2TmpValue - ((u2TmpValue >> u1Small_ui_to_large) <<u1Small_ui_to_large);
+    *pu1UILarge_DQ = (u2TmpValue >> u1Small_ui_to_large);
+    #endif
+
+    // calculate DQ OE according to DQ UI
+    if(u1IsLP4Family(p->dram_type))
+    {
+        u2TmpValue -= TX_DQ_OE_SHIFT_LP4;
+
+        if(((u1MR03Value[p->dram_fsp]&0x80)>>7)==1) //if WDBI is on, OE_DLY don't need to shift 1 MCK with DLY
+        {
+            u2TmpValue += 8;
+        }
+
+    }
+    else
+    {
+        u2TmpValue -= TX_DQ_OE_SHIFT_LP3;
+    }
+
+    *pu1UISmall_DQOE = u2TmpValue - ((u2TmpValue >> u1Small_ui_to_large) <<u1Small_ui_to_large);
+    *pu1UILarge_DQOE = (u2TmpValue >> u1Small_ui_to_large);
+}
+
+static void TxPrintWidnowInfo(DRAMC_CTX_T *p, PASS_WIN_DATA_T WinPerBitData[])
+{
+    U8 u1BitIdx;
+
+    for (u1BitIdx = 0; u1BitIdx < DQS_BIT_NUMBER; u1BitIdx++)
+    {
+    #ifdef ETT_PRINT_FORMAT
+        mcSHOW_DBG_MSG(("TX Bit%d (%d~%d) %d %d,   Bit%d (%d~%d) %d %d,", \
+            u1BitIdx, WinPerBitData[u1BitIdx].first_pass, WinPerBitData[u1BitIdx].last_pass, WinPerBitData[u1BitIdx].win_size, WinPerBitData[u1BitIdx].win_center, \
+            u1BitIdx+8, WinPerBitData[u1BitIdx+8].first_pass, WinPerBitData[u1BitIdx+8].last_pass, WinPerBitData[u1BitIdx+8].win_size, WinPerBitData[u1BitIdx+8].win_center));
+    #else
+        mcSHOW_DBG_MSG(("TX Bit%2d (%2d~%2d) %2d %2d,   Bit%2d (%2d~%2d) %2d %2d,", \
+            u1BitIdx, WinPerBitData[u1BitIdx].first_pass, WinPerBitData[u1BitIdx].last_pass, WinPerBitData[u1BitIdx].win_size, WinPerBitData[u1BitIdx].win_center, \
+            u1BitIdx+8, WinPerBitData[u1BitIdx+8].first_pass, WinPerBitData[u1BitIdx+8].last_pass, WinPerBitData[u1BitIdx+8].win_size, WinPerBitData[u1BitIdx+8].win_center));
+    #endif
+        mcFPRINTF((fp_A60501,"TX Bit%2d (%2d~%2d) %2d %2d,   Bit%2d (%2d~%2d) %2d %2d,", \
+            u1BitIdx, WinPerBitData[u1BitIdx].first_pass, WinPerBitData[u1BitIdx].last_pass, WinPerBitData[u1BitIdx].win_size, WinPerBitData[u1BitIdx].win_center, \
+            u1BitIdx+8, WinPerBitData[u1BitIdx+8].first_pass, WinPerBitData[u1BitIdx+8].last_pass, WinPerBitData[u1BitIdx+8].win_size, WinPerBitData[u1BitIdx+8].win_center));
+
+        if(u1IsLP4Family(p->dram_type))
+        {
+            mcSHOW_DBG_MSG(("\n"));
+            mcFPRINTF((fp_A60501,"\n"));
+        }
+    #if ENABLE_LP3_SW
+        else //LPDDR3
+        {
+        #ifdef ETT_PRINT_FORMAT
+            mcSHOW_DBG_MSG(("  %d (%d~%d) %d %d,   %d (%d~%d) %d %d\n", \
+                u1BitIdx+16, WinPerBitData[u1BitIdx+16].first_pass, WinPerBitData[u1BitIdx+16].last_pass, WinPerBitData[u1BitIdx+16].win_size, WinPerBitData[u1BitIdx+16].win_center, \
+                u1BitIdx+24, WinPerBitData[u1BitIdx+24].first_pass, WinPerBitData[u1BitIdx+24].last_pass, WinPerBitData[u1BitIdx+24].win_size, WinPerBitData[u1BitIdx+24].win_center ));
+        #else
+            mcSHOW_DBG_MSG(("  %2d (%2d~%2d) %2d %2d,   %2d (%2d~%2d) %2d %2d\n", \
+                u1BitIdx+16, WinPerBitData[u1BitIdx+16].first_pass, WinPerBitData[u1BitIdx+16].last_pass, WinPerBitData[u1BitIdx+16].win_size, WinPerBitData[u1BitIdx+16].win_center, \
+                u1BitIdx+24, WinPerBitData[u1BitIdx+24].first_pass, WinPerBitData[u1BitIdx+24].last_pass, WinPerBitData[u1BitIdx+24].win_size, WinPerBitData[u1BitIdx+24].win_center ));
+        #endif
+
+            mcFPRINTF((fp_A60501,"  %2d (%2d~%2d) %2d %2d,   %2d (%2d~%2d) %2d %2d\n", \
+                u1BitIdx+16, WinPerBitData[u1BitIdx+16].first_pass, WinPerBitData[u1BitIdx+16].last_pass, WinPerBitData[u1BitIdx+16].win_size, WinPerBitData[u1BitIdx+16].win_center, \
+                u1BitIdx+24, WinPerBitData[u1BitIdx+24].first_pass, WinPerBitData[u1BitIdx+24].last_pass, WinPerBitData[u1BitIdx+24].win_size, WinPerBitData[u1BitIdx+24].win_center ));
+        }
+    #endif//ENABLE_LP3_SW
+    }
+    mcSHOW_DBG_MSG(("\n"));
+    mcFPRINTF((fp_A60501,"\n"));
+}
+
+
+static void TXPerbitCalibrationInit(DRAMC_CTX_T *p, U8 calType)
+{
+    //Set TX delay chain to 0
+    if(u1IsLP4Family(p->dram_type) && (calType !=TX_DQ_DQS_MOVE_DQM_ONLY))
+    {
+    #if 1
+    #if PINMUX_AUTO_TEST_PER_BIT_TX
+        if(gTX_check_per_bit_flag == 1)
+        {
+            //not reset delay cell
+        }
+        else
+    #endif
+        {
+            vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ0), 0);
+            vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ0), 0);
+        }
+    #else
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ0), P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ7_DLY_B0)
+            | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ6_DLY_B0)
+            | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ5_DLY_B0)
+            | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ4_DLY_B0)
+            | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ3_DLY_B0)
+            | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ2_DLY_B0)
+            | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ1_DLY_B0)
+            | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ0_DLY_B0));
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ0), P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ7_DLY_B1)
+            | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ6_DLY_B1)
+            | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ5_DLY_B1)
+            | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ4_DLY_B1)
+            | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ3_DLY_B1)
+            | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ2_DLY_B1)
+            | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ1_DLY_B1)
+            | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ0_DLY_B1));
+    #endif
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ1), 0x0, SHU1_R0_B0_DQ1_RK0_TX_ARDQM0_DLY_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ1), 0x0, SHU1_R0_B1_DQ1_RK0_TX_ARDQM0_DLY_B1);
+    }
+
+
+    //Use HW TX tracking value
+    //R_DMARPIDQ_SW :drphy_conf (0x170[7])(default set 1)
+    //   0: DQS2DQ PI setting controlled by HW
+    //R_DMARUIDQ_SW : Dramc_conf(0x156[15])(default set 1)
+    //    0: DQS2DQ UI setting controlled by HW
+    ///TODO: need backup original setting?
+    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 1, MISC_CTRL1_R_DMARPIDQ_SW);
+    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 1, DQSOSCR_ARUIDQ_SW);
+
+}
+
+#define TX_TDQS2DQ_PRE_CAL 1
+#if TX_TDQS2DQ_PRE_CAL
+U16 u2DQS2DQ_Pre_Cal[CHANNEL_NUM][RANK_MAX]={0};
+#endif
+
+static void TXScanRange_PI(DRAMC_CTX_T *p, DRAM_TX_PER_BIT_CALIBRATION_TYTE_T calType, U16 *pu2Begin, U16 *pu2End)
+{
+    U8 u1MCK2UI, u1ByteIdx, u1UI2PI;
+    U32 u4RegValue_TXDLY, u4RegValue_dly;
+    U8 ucdq_ui_large_bak[DQS_NUMBER], ucdq_ui_small_bak[DQS_NUMBER];
+    U16 u2TempVirtualDelay, u2SmallestVirtualDelay=0xffff;
+    U16 u2DQDelayBegin=0, u2DQDelayEnd=0, u2TX_DQ_PreCal_LP4_Samll;
+
+    u4RegValue_TXDLY= u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_DQS0));
+    u4RegValue_dly= u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_DQS1));
+
+#if (fcFOR_PINMUX == fcLaurel) //LP2 is full rate
+    if(u1IsLP4Family(p->dram_type))
+    {
+        u1MCK2UI= 3;
+        u1UI2PI = 5;
+    }
+    else
+    {
+        u1MCK2UI =2;
+        u1UI2PI = 6;
+    }
+#endif
+
+    // find smallest DQS delay
+    for(u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+    {
+        ucdq_ui_large_bak[u1ByteIdx] = (u4RegValue_TXDLY >> (u1ByteIdx<<2)) &0x7;// MCK
+        ucdq_ui_small_bak[u1ByteIdx] = (u4RegValue_dly >> (u1ByteIdx<<2)) &0x7;// UI
+        //wrlevel_dqs_final_delay[u1ByteIdx]  ==> PI
+
+        //LP4 : Virtual Delay = 256 * MCK + 32*UI + PI;
+        //LP3 : Virtual Delay = 128 * MCK + 32*UI + PI;
+        u2TempVirtualDelay = (((ucdq_ui_large_bak[u1ByteIdx] <<u1MCK2UI) + ucdq_ui_small_bak[u1ByteIdx])<<u1UI2PI) + wrlevel_dqs_final_delay[u1ByteIdx];
+        if(u2TempVirtualDelay < u2SmallestVirtualDelay)
+        {
+            u2SmallestVirtualDelay = u2TempVirtualDelay;
+        }
+
+        /*mcSHOW_DBG_MSG2(("Original DQS_B%d VirtualDelay %d = (%d %d %d)\n", u1ByteIdx, u2TempVirtualDelay,\
+         *                ucdq_ui_large_bak[u1ByteIdx], ucdq_ui_small_bak[u1ByteIdx], wrlevel_dqs_final_delay[u1ByteIdx]));
+         */
+    }
+
+    if(u1IsLP4Family(p->dram_type))
+    {
+        // (1)LP4 will calibration DQM at the first time, K full range, and then rember the TX position.
+        // (2)The sencod time will calibrate DQ+Vref, reference TX postion of (1)
+        if(calType==TX_DQ_DQS_MOVE_DQ_DQM)
+        {
+            u2DQDelayBegin = u2SmallestVirtualDelay;
+
+            #if TX_TDQS2DQ_PRE_CAL
+            if(p->frequency == LP4_LOWEST_FREQ)
+            {
+                // Save first freqency DQS2DQ, but skip MDL_UESED. Therefore, clean this value.
+                u2DQS2DQ_Pre_Cal[p->channel][p->rank]=0;
+            }
+            else if(u2DQS2DQ_Pre_Cal[p->channel][p->rank]> 0)
+            {
+                mcSHOW_DBG_MSG(("TX_TDQS2DQ_PRE_CAL : change DQ begin %d -->", u2DQDelayBegin));
+                u2DQDelayBegin += (u2DQS2DQ_Pre_Cal[p->channel][p->rank]* p->frequency /1000);
+                mcSHOW_DBG_MSG(("%d\n", u2DQDelayBegin));
+            }
+            #endif
+            u2DQDelayEnd = u2DQDelayBegin + 256;
+        }
+        else //if(calType==TX_DQ_DQS_MOVE_DQ_ONLY)
+        {
+            if(u2TX_DQ_PreCal_LP4[0] < u2TX_DQ_PreCal_LP4[1])
+                u2TX_DQ_PreCal_LP4_Samll = u2TX_DQ_PreCal_LP4[0];
+            else
+                u2TX_DQ_PreCal_LP4_Samll = u2TX_DQ_PreCal_LP4[1];
+
+            if(u2TX_DQ_PreCal_LP4_Samll >24)
+                u2DQDelayBegin = u2TX_DQ_PreCal_LP4_Samll-24;
+            else
+                u2DQDelayBegin =0;
+
+        #if TX_K_DQM_WITH_WDBI
+            if(calType==TX_DQ_DQS_MOVE_DQM_ONLY)
+            {
+                // DBI on, calibration range -1MCK
+                u2DQDelayBegin -=(1<<(u1MCK2UI+5));
+            }
+        #endif
+            u2DQDelayEnd = u2DQDelayBegin + 64;
+        }
+
+    }
+    else
+    {
+        u2DQDelayBegin = (u2SmallestVirtualDelay > 16)? (u2SmallestVirtualDelay - 16) : 0;
+        u2DQDelayEnd = u2SmallestVirtualDelay + 96;
+    }
+
+    *pu2Begin = u2DQDelayBegin;
+    *pu2End = u2DQDelayEnd;
+
+    #if 0//TX_TDQS2DQ_PRE_CAL
+    mcSHOW_DBG_MSG(("TXScanRange_PI %d~%d\n", u2DQDelayBegin,u2DQDelayEnd));
+    #endif
+}
+
+
+static void TXScanRange_Vref(DRAMC_CTX_T *p, U8 u1VrefScanEnable, U16* pu2Range, U16 *pu2Begin, U16 *pu2End, U16 *pu2Setp)
+{
+    U16 u2VrefBegin, u2VrefEnd;
+    U16 u2VrefRange=!p->odt_onoff;
+
+    if(u1VrefScanEnable==ENABLE_VREF_SCAN)
+    {
+    #if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_VREF_CAL)
+        if(p->femmc_Ready==1)
+        {
+            // if fast K, use TX Vref that saved.
+            u2VrefBegin = p->pSavetimeData->u1TxWindowPerbitVref_Save[p->channel][p->rank];
+            u2VrefEnd = u2VrefBegin+1;
+        }
+        else
+    #endif
+        {
+    		if (p->odt_onoff == ODT_OFF)
+            {
+                if (p->dram_type == TYPE_LPDDR4)
+                {
+                    //range 1
+                    u2VrefBegin = 13 - 5; // 300/1100(VDDQ) = 27.2%
+                    u2VrefEnd = 13 + 5;
+                }
+                else
+                {
+                    //range 1
+                    u2VrefBegin = 27 - 5; // 290/600(VDDQ)=48.3%
+                    u2VrefEnd = 27 + 5;
+                }
+            }
+            else
+            {
+                if (p->dram_type == TYPE_LPDDR4)
+                {
+                    // range 0
+                    u2VrefBegin = 12;
+                }
+                else
+                {
+                    // range 0
+                    u2VrefBegin = TX_VREF_RANGE_BEGIN;
+                }
+                u2VrefEnd = TX_VREF_RANGE_END;
+            }
+        }
+    }
+    else //LPDDR3, the for loop will only excute u2VrefLevel=TX_VREF_RANGE_END/2.
+    {
+        u2VrefBegin = 0;
+        u2VrefEnd = 0;
+    }
+
+    *pu2Range = u2VrefRange;
+    *pu2Begin = u2VrefBegin;
+    *pu2End = u2VrefEnd;
+    *pu2Setp = TX_VREF_RANGE_STEP;
+
+}
+
+static U16 TxChooseVref(DRAMC_CTX_T *p, PASS_WIN_DATA_BY_VREF_T pVrefInfo[], U8 u1VrefNum)
+{
+    U8 u1VrefIdx;
+    U16 u2MaxMinSize=0, u2MaxWinSum=0;
+    U16 u2FinalVref=0;
+
+#if LP4_TX_VREF_PASS_CONDITION
+    U8 u1TempPassNum=0;
+    U8 u1VrefPassBegin=LP4_TX_VREF_BOUNDARY_NOT_READY;
+    U8 u1VrefPassEnd=LP4_TX_VREF_BOUNDARY_NOT_READY;
+    U8 u1MaxVerfPassNum=0;
+    U8 u1VrefPassBegin_Final=LP4_TX_VREF_BOUNDARY_NOT_READY;
+    U8 u1VrefPassEnd_Final=LP4_TX_VREF_BOUNDARY_NOT_READY;
+#endif
+
+    for(u1VrefIdx=0; u1VrefIdx < u1VrefNum; u1VrefIdx++)
+    {
+        mcSHOW_DBG_MSG(("Vref=%d, minWin=%d, winSum=%d\n",
+            pVrefInfo[u1VrefIdx].u2VrefUsed,
+            pVrefInfo[u1VrefIdx].u2MinWinSize_byVref,
+            pVrefInfo[u1VrefIdx].u2WinSum_byVref));
+
+        #if LP4_TX_VREF_PASS_CONDITION
+        if((pVrefInfo[u1VrefIdx].u2MinWinSize_byVref > LP4_TX_VREF_PASS_CONDITION))
+        {
+            if(u1VrefPassBegin ==LP4_TX_VREF_BOUNDARY_NOT_READY)
+            {
+                u1VrefPassBegin = pVrefInfo[u1VrefIdx].u2VrefUsed;
+                u1TempPassNum =1;
+            }
+            else
+                u1TempPassNum ++;
+
+            if(u1VrefIdx==u1VrefNum-1)
+            {
+                u1VrefPassEnd = pVrefInfo[u1VrefIdx].u2VrefUsed;
+                if(u1TempPassNum > u1MaxVerfPassNum)
+                {
+                    u1VrefPassBegin_Final= u1VrefPassBegin;
+                    u1VrefPassEnd_Final = u1VrefPassEnd;
+                    u1MaxVerfPassNum= u1TempPassNum;
+                }
+            }
+        }
+        else
+        {
+            if((u1VrefPassBegin != LP4_TX_VREF_BOUNDARY_NOT_READY) && (u1VrefPassEnd==LP4_TX_VREF_BOUNDARY_NOT_READY))
+            {
+                u1VrefPassEnd = pVrefInfo[u1VrefIdx].u2VrefUsed-TX_VREF_RANGE_STEP;
+                if(u1TempPassNum > u1MaxVerfPassNum)
+                {
+                    u1VrefPassBegin_Final= u1VrefPassBegin;
+                    u1VrefPassEnd_Final = u1VrefPassEnd;
+                    u1MaxVerfPassNum= u1TempPassNum;
+                }
+                u1VrefPassBegin=0xff;
+                u1VrefPassEnd=0xff;
+                u1TempPassNum =0;
+            }
+        }
+        #endif
+    }
+
+    #if LP4_TX_VREF_PASS_CONDITION
+    //if((u1VrefPassBegin_Final !=LP4_TX_VREF_BOUNDARY_NOT_READY) && (u1VrefPassEnd_Final!=LP4_TX_VREF_BOUNDARY_NOT_READY))
+    if(u1MaxVerfPassNum>0)
+    {
+        // vref pass window found
+        u2FinalVref = (u1VrefPassBegin_Final + u1VrefPassEnd_Final) >>1;
+        mcSHOW_DBG_MSG(("[TxChooseVref] Window > %d, Vref (%d~%d), Final Vref %d\n",LP4_TX_VREF_PASS_CONDITION, u1VrefPassBegin_Final, u1VrefPassEnd_Final, u2FinalVref));
+    }
+    else
+    #endif
+    {
+        // not vref found
+        for(u1VrefIdx=0; u1VrefIdx < u1VrefNum; u1VrefIdx++)
+        {
+            if((pVrefInfo[u1VrefIdx].u2MinWinSize_byVref > u2MaxMinSize) ||
+                ((pVrefInfo[u1VrefIdx].u2MinWinSize_byVref == u2MaxMinSize) && (pVrefInfo[u1VrefIdx].u2WinSum_byVref > u2MaxWinSum)))
+            {
+                u2MaxMinSize = pVrefInfo[u1VrefIdx].u2MinWinSize_byVref;
+                u2MaxWinSum = pVrefInfo[u1VrefIdx].u2WinSum_byVref;
+                u2FinalVref = pVrefInfo[u1VrefIdx].u2VrefUsed;
+            }
+        }
+
+        mcSHOW_DBG_MSG(("[TxChooseVref] Min win %d, Win sum %d, Final Vref %d\n", u2MaxMinSize, u2MaxWinSum, u2FinalVref));
+    }
+
+    return u2FinalVref;
+}
+
+
+void DramcTXSetVref(DRAMC_CTX_T *p, U8 u1VrefRange, U8 u1VrefValue)
+{
+    U8 u1TempOPValue = ((u1VrefValue & 0x3f) | (u1VrefRange<<6));
+
+    u1MR14Value[p->channel][p->rank][p->dram_fsp] = u1TempOPValue;
+    DramcModeRegWriteByRank(p, p->rank, 14, u1TempOPValue);
+}
+
+
+static void TXSetFinalVref(DRAMC_CTX_T *p, U16 u2FinalRange, U16 u2FinalVref)
+{
+    // SET tx Vref (DQ) = u2FinalVref, LP3 no need to set this.
+    if(!u1IsLP4Family(p->dram_type))
+        return;
+
+    DramcTXSetVref(p, u2FinalRange, u2FinalVref);
+
+#ifdef FOR_HQA_TEST_USED
+    gFinalTXVrefDQ[p->channel][p->rank] = (U8) u2FinalVref;
+#endif
+
+#if VENDER_JV_LOG
+    mcSHOW_DBG_MSG5(("\nFinal TX Range %d Vref %d\n\n", u2FinalRange, u2FinalVref));
+#else
+    mcSHOW_DBG_MSG(("\nFinal TX Range %d Vref %d\n\n", u2FinalRange, u2FinalVref));
+    mcFPRINTF((fp_A60501, "\nFinal TX Range %d Vref %d\n\n", u2FinalRange, u2FinalVref));
+#endif
+}
+
+
+#if ENABLE_TX_TRACKING
+static void TXUpdateTXTracking(DRAMC_CTX_T *p, DRAM_TX_PER_BIT_CALIBRATION_TYTE_T calType, U8 ucdq_pi[], U8 ucdqm_pi[])
+{
+     if(u1IsLP4Family(p->dram_type) && (calType == TX_DQ_DQS_MOVE_DQ_ONLY ||calType ==TX_DQ_DQS_MOVE_DQM_ONLY))
+     {
+         //make a copy to dramc reg for TX DQ tracking used
+         if(calType ==TX_DQ_DQS_MOVE_DQ_ONLY)
+         {
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_PI),
+                            P_Fld(ucdq_pi[0], SHU1RK0_PI_RK0_ARPI_DQ_B0) | P_Fld(ucdq_pi[1], SHU1RK0_PI_RK0_ARPI_DQ_B1));
+
+            // Source DQ
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_DQS2DQ_CAL1),
+                                                    P_Fld(ucdq_pi[1], SHU1RK0_DQS2DQ_CAL1_BOOT_ORIG_UI_RK0_DQ1) |
+                                                    P_Fld(ucdq_pi[0], SHU1RK0_DQS2DQ_CAL1_BOOT_ORIG_UI_RK0_DQ0));
+            // Target DQ
+             vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_DQS2DQ_CAL2),
+                                                     P_Fld(ucdq_pi[1], SHU1RK0_DQS2DQ_CAL2_BOOT_TARG_UI_RK0_DQ1) |
+                                                     P_Fld(ucdq_pi[0], SHU1RK0_DQS2DQ_CAL2_BOOT_TARG_UI_RK0_DQ0));
+         }
+
+         //if(calType ==TX_DQ_DQS_MOVE_DQM_ONLY || (calType ==TX_DQ_DQS_MOVE_DQ_ONLY))
+         {
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_PI),
+                            P_Fld(ucdqm_pi[0], SHU1RK0_PI_RK0_ARPI_DQM_B0) | P_Fld(ucdqm_pi[1], SHU1RK0_PI_RK0_ARPI_DQM_B1));
+
+            // Target DQM
+             vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_DQS2DQ_CAL5),
+                                                 P_Fld(ucdqm_pi[1], SHU1RK0_DQS2DQ_CAL5_BOOT_TARG_UI_RK0_DQM1) |
+                                                 P_Fld(ucdqm_pi[0], SHU1RK0_DQS2DQ_CAL5_BOOT_TARG_UI_RK0_DQM0));
+         }
+     }
+
+
+#if 0// for LP3 , TX tracking will be disable, don't need to set DQ delay in DramC.
+     ///TODO: check LP3 byte mapping of dramC
+     vIO32WriteFldMulti(DRAMC_REG_SHU1RK0_PI+(CHANNEL_A<< POS_BANK_NUM), \
+                              P_Fld(ucdq_final_pi[0], SHU1RK0_PI_RK0_ARPI_DQ_B0) | P_Fld(ucdq_final_pi[1], SHU1RK0_PI_RK0_ARPI_DQ_B1));
+
+     vIO32WriteFldMulti(DRAMC_REG_SHU1RK0_PI+SHIFT_TO_CHB_ADDR, \
+                              P_Fld(ucdq_final_pi[2], SHU1RK0_PI_RK0_ARPI_DQ_B0) | P_Fld(ucdq_final_pi[3], SHU1RK0_PI_RK0_ARPI_DQ_B1));
+#endif
+
+}
+#endif //End ENABLE_TX_TRACKING
+
+
+static void TXSetDelayReg_DQ(DRAMC_CTX_T *p, U8 u1UpdateRegUI, U8 ucdq_ui_large[], U8 ucdq_oen_ui_large[], U8 ucdq_ui_small[], U8 ucdq_oen_ui_small[], U8 ucdql_pi[])
+{
+    if(u1UpdateRegUI)
+    {
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), \
+                                     P_Fld(ucdq_ui_large[0], SHURK0_SELPH_DQ0_TXDLY_DQ0) |
+                                     P_Fld(ucdq_ui_large[1], SHURK0_SELPH_DQ0_TXDLY_DQ1) |
+                                     P_Fld(ucdq_ui_large[2], SHURK0_SELPH_DQ0_TXDLY_DQ2) |
+                                     P_Fld(ucdq_ui_large[3], SHURK0_SELPH_DQ0_TXDLY_DQ3) |
+                                     P_Fld(ucdq_oen_ui_large[0], SHURK0_SELPH_DQ0_TXDLY_OEN_DQ0) |
+                                     P_Fld(ucdq_oen_ui_large[1], SHURK0_SELPH_DQ0_TXDLY_OEN_DQ1) |
+                                     P_Fld(ucdq_oen_ui_large[2], SHURK0_SELPH_DQ0_TXDLY_OEN_DQ2) |
+                                     P_Fld(ucdq_oen_ui_large[3], SHURK0_SELPH_DQ0_TXDLY_OEN_DQ3));
+
+        // DLY_DQ[2:0]
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2), \
+                                     P_Fld(ucdq_ui_small[0], SHURK0_SELPH_DQ2_DLY_DQ0) |
+                                     P_Fld(ucdq_ui_small[1], SHURK0_SELPH_DQ2_DLY_DQ1) |
+                                     P_Fld(ucdq_ui_small[2], SHURK0_SELPH_DQ2_DLY_DQ2) |
+                                     P_Fld(ucdq_ui_small[3], SHURK0_SELPH_DQ2_DLY_DQ3) |
+                                     P_Fld(ucdq_oen_ui_small[0], SHURK0_SELPH_DQ2_DLY_OEN_DQ0) |
+                                     P_Fld(ucdq_oen_ui_small[1], SHURK0_SELPH_DQ2_DLY_OEN_DQ1) |
+                                     P_Fld(ucdq_oen_ui_small[2], SHURK0_SELPH_DQ2_DLY_OEN_DQ2) |
+                                     P_Fld(ucdq_oen_ui_small[3], SHURK0_SELPH_DQ2_DLY_OEN_DQ3));
+    }
+
+    if(u1IsLP4Family(p->dram_type))
+    {
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdql_pi[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), ucdql_pi[1], SHU1_R0_B1_DQ7_RK0_ARPI_DQ_B1);
+    }
+    #if ENABLE_LP3_SW
+    else
+    {
+        vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdql_pi[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+        vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdql_pi[1], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+        vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdql_pi[2], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+        vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdql_pi[3], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+    }
+    #endif
+}
+
+
+static void TXSetDelayReg_DQM(DRAMC_CTX_T *p, U8 u1UpdateRegUI, U8 ucdqm_ui_large[], U8 ucdqm_oen_ui_large[], U8 ucdqm_ui_small[], U8 ucdqm_oen_ui_small[], U8 ucdqm_pi[])
+{
+    if(u1UpdateRegUI)
+    {
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1),
+                                     P_Fld(ucdqm_ui_large[0], SHURK0_SELPH_DQ1_TXDLY_DQM0) |
+                                     P_Fld(ucdqm_ui_large[1], SHURK0_SELPH_DQ1_TXDLY_DQM1) |
+                                     P_Fld(ucdqm_ui_large[2], SHURK0_SELPH_DQ1_TXDLY_DQM2) |
+                                     P_Fld(ucdqm_ui_large[3], SHURK0_SELPH_DQ1_TXDLY_DQM3) |
+                                     P_Fld(ucdqm_oen_ui_large[0], SHURK0_SELPH_DQ1_TXDLY_OEN_DQM0) |
+                                     P_Fld(ucdqm_oen_ui_large[1], SHURK0_SELPH_DQ1_TXDLY_OEN_DQM1) |
+                                     P_Fld(ucdqm_oen_ui_large[2], SHURK0_SELPH_DQ1_TXDLY_OEN_DQM2) |
+                                     P_Fld(ucdqm_oen_ui_large[3], SHURK0_SELPH_DQ1_TXDLY_OEN_DQM3));
+
+         // DLY_DQM[2:0]
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3),
+                                     P_Fld(ucdqm_ui_small[0], SHURK0_SELPH_DQ3_DLY_DQM0) |
+                                     P_Fld(ucdqm_ui_small[1], SHURK0_SELPH_DQ3_DLY_DQM1) |
+                                     P_Fld(ucdqm_ui_small[2], SHURK0_SELPH_DQ3_DLY_DQM2) |
+                                     P_Fld(ucdqm_ui_small[3], SHURK0_SELPH_DQ3_DLY_DQM3) |
+                                     P_Fld(ucdqm_oen_ui_small[0], SHURK0_SELPH_DQ3_DLY_OEN_DQM0) |
+                                     P_Fld(ucdqm_oen_ui_small[1], SHURK0_SELPH_DQ3_DLY_OEN_DQM1) |
+                                     P_Fld(ucdqm_oen_ui_small[2], SHURK0_SELPH_DQ3_DLY_OEN_DQM2) |
+                                     P_Fld(ucdqm_oen_ui_small[3], SHURK0_SELPH_DQ3_DLY_OEN_DQM3));
+    }
+
+    if(u1IsLP4Family(p->dram_type))
+    {
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdqm_pi[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), ucdqm_pi[1], SHU1_R0_B1_DQ7_RK0_ARPI_DQM_B1);
+    }
+    #if ENABLE_LP3_SW
+    else
+    {
+        vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdqm_pi[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+        vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdqm_pi[1], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+        vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdqm_pi[2], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+        vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdqm_pi[3], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+    }
+    #endif
+}
+
+DRAM_STATUS_T DramcTxWindowPerbitCal(DRAMC_CTX_T *p, DRAM_TX_PER_BIT_CALIBRATION_TYTE_T calType, U8 u1VrefScanEnable)
+{
+    U8 u1BitTemp, u1BitIdx, u1ByteIdx, u1RankIdx, backup_rank;
+    U32 uiFinishCount;
+    PASS_WIN_DATA_T WinPerBit[DQ_DATA_WIDTH] = {{0,0,0,0,0}};
+    PASS_WIN_DATA_T VrefWinPerBit[DQ_DATA_WIDTH] = {{0,0,0,0,0}};
+    PASS_WIN_DATA_T FinalWinPerBit[DQ_DATA_WIDTH] = {{0,0,0,0,0}};
+
+    U16 uiDelay, u2DQDelayBegin, u2DQDelayEnd;
+
+    U8 ucdq_pi, ucdq_ui_small, ucdq_ui_large,ucdq_oen_ui_small, ucdq_oen_ui_large;
+    U8 ucdq_ui_small_reg_value, u1UpdateRegUI;  // for UI and TXDLY change check, if different , set reg.
+
+    U8 ucdq_reg_pi[DQS_NUMBER], ucdq_reg_ui_large[DQS_NUMBER], ucdq_reg_ui_small[DQS_NUMBER];
+    U8 ucdq_reg_oen_ui_large[DQS_NUMBER], ucdq_reg_oen_ui_small[DQS_NUMBER];
+
+    U8 ucdq_reg_dqm_pi[DQS_NUMBER] = {0}, ucdq_reg_dqm_ui_large[DQS_NUMBER] = {0}, ucdq_reg_dqm_ui_small[DQS_NUMBER] = {0};
+    U8 ucdq_reg_dqm_oen_ui_large[DQS_NUMBER] = {0}, ucdq_reg_dqm_oen_ui_small[DQS_NUMBER] = {0};
+
+    #if 1//TX_DQM_CALC_MAX_MIN_CENTER
+    U16 u2Center_min[DQS_NUMBER],u2Center_max[DQS_NUMBER];
+    #endif
+    U8 u1EnableDelayCell=0, u1DelayCellOfst[DQ_DATA_WIDTH]={0};
+    U32 u4err_value, u4fail_bit;
+    U16 u2FinalRange=0, u2FinalVref=0xd;
+    U16 u2VrefLevel, u2VrefBegin, u2VrefEnd, u2VrefStep;
+    U16 u2TempWinSum, u2MaxWindowSum=0;//, u2tx_window_sum[LP4_TX_VREF_DATA_NUM]={0};
+    U8 u1min_bit, u1min_winsize=0;
+    U8 u1VrefIdx =0;
+    U8 u1PIDiff;
+    PASS_WIN_DATA_BY_VREF_T VrefInfo[LP4_TX_VREF_DATA_NUM];
+
+    if (!p)
+    {
+        mcSHOW_ERR_MSG(("context NULL\n"));
+        return DRAM_FAIL;
+    }
+
+#if VENDER_JV_LOG
+    if((calType ==TX_DQ_DQS_MOVE_DQ_ONLY && u1IsLP4Family(p->dram_type)) || (calType ==TX_DQ_DQS_MOVE_DQ_DQM && !u1IsLP4Family(p->dram_type)))
+        vPrintCalibrationBasicInfo_ForJV(p);
+#else
+        vPrintCalibrationBasicInfo(p);
+#endif
+
+    backup_rank = u1GetRank(p);
+
+    TXPerbitCalibrationInit(p, calType);
+    TXScanRange_PI(p, calType, &u2DQDelayBegin, &u2DQDelayEnd);
+    TXScanRange_Vref(p, u1VrefScanEnable, &u2FinalRange, &u2VrefBegin, &u2VrefEnd, &u2VrefStep);
+
+#ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+    U8 u1GUMP_INIT_RG_LOG_TO_DE_bak = gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag;
+    gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag=0;
+#endif
+
+    vSetCalibrationResult(p, DRAM_CALIBRATION_TX_PERBIT, DRAM_FAIL);
+
+#if 0
+    mcSHOW_DBG_MSG(("[TxWindowPerbitCal] calType=%d, VrefScanEnable %d (Range %d,  VrefBegin %d, u2VrefEnd %d)\n"
+                    "\nBegin, DQ Scan Range %d~%d\n",
+                    calType, u1VrefScanEnable, u2FinalRange, u2VrefBegin, u2VrefEnd, u2DQDelayBegin, u2DQDelayEnd));
+
+    mcFPRINTF((fp_A60501, "[TxWindowPerbitCal] calType=%d, VrefScanEnable %d\n"
+                    "\nBegin, DQ Scan Range %d~%d\n",
+                    calType, u1VrefScanEnable, u2DQDelayBegin, u2DQDelayEnd));
+#endif
+
+    #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+    if(p->femmc_Ready==1 && (p->Bypass_TXWINDOW))
+    {
+        for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+        {
+            u2Center_min[u1ByteIdx]=p->pSavetimeData->u1TxCenter_min_Save[p->channel][p->rank][u1ByteIdx];
+            u2Center_max[u1ByteIdx]=p->pSavetimeData->u1TxCenter_max_Save[p->channel][p->rank][u1ByteIdx];
+
+            for (u1BitIdx=0; u1BitIdx<DQS_BIT_NUMBER; u1BitIdx++)
+            {
+                u1BitTemp = u1ByteIdx*DQS_BIT_NUMBER+u1BitIdx;
+                FinalWinPerBit[u1BitTemp].win_center= p->pSavetimeData->u1Txwin_center_Save[p->channel][p->rank][u1BitTemp];
+            }
+        }
+
+        vSetCalibrationResult(p, DRAM_CALIBRATION_TX_PERBIT, DRAM_OK);
+    }
+    else
+ 	#endif
+ 	{
+        DramcEngine2Init(p, p->test2_1, p->test2_2, p->test_pattern, 0);
+
+        for(u2VrefLevel = u2VrefBegin; u2VrefLevel <= u2VrefEnd; u2VrefLevel += u2VrefStep)
+        {
+            // SET tx Vref (DQ) here, LP3 no need to set this.
+            if(u1VrefScanEnable)
+            {
+                #if 0//(!REDUCE_LOG_FOR_PRELOADER)
+                mcSHOW_DBG_MSG(("\n\n\tLP4 TX VrefRange %d, VrefLevel=%d\n", u2FinalRange, u2VrefLevel));
+                mcFPRINTF((fp_A60501, "\n\n\tLP4 TX VrefRange %d,VrefLevel=%d\n", u2FinalRange, u2VrefLevel));
+                #endif
+
+                #if VENDER_JV_LOG
+                if(calType ==TX_DQ_DQS_MOVE_DQ_ONLY)
+                {
+                    mcSHOW_DBG_MSG5(("\n\n\tLP4 TX VrefRange %d, VrefLevel=%d\n", u2FinalRange, u2VrefLevel));
+                }
+                #endif
+
+                DramcTXSetVref(p, u2FinalRange, u2VrefLevel);
+            }
+            else
+            {
+                mcSHOW_DBG_MSG(("\n\n\tTX Vref Scan disable\n"));
+                mcFPRINTF((fp_A60501, "\n\n\tTX Vref Scan disable\n"));
+            }
+
+            // initialize parameters
+            uiFinishCount = 0;
+            u2TempWinSum =0;
+            ucdq_ui_small_reg_value = 0xff;
+
+            for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+            {
+                WinPerBit[u1BitIdx].first_pass = (S16)PASS_RANGE_NA;
+                WinPerBit[u1BitIdx].last_pass = (S16)PASS_RANGE_NA;
+                VrefWinPerBit[u1BitIdx].first_pass = (S16)PASS_RANGE_NA;
+                VrefWinPerBit[u1BitIdx].last_pass = (S16)PASS_RANGE_NA;
+            }
+
+            //Move DQ delay ,  1 PI = tCK/64, total 128 PI, 1UI = 32 PI
+            //For data rate 3200, max tDQS2DQ is 2.56UI (82 PI)
+            //For data rate 4266, max tDQS2DQ is 3.41UI (109 PI)
+            for (uiDelay = u2DQDelayBegin; uiDelay <u2DQDelayEnd; uiDelay++)
+            {
+                TxWinTransferDelayToUIPI(p, calType, uiDelay, 0, &ucdq_ui_large, &ucdq_ui_small, &ucdq_pi, &ucdq_oen_ui_large, &ucdq_oen_ui_small);
+
+                // Check if TX UI changed, if not change , don't need to set reg again
+                if(ucdq_ui_small_reg_value != ucdq_ui_small)
+                {
+                    u1UpdateRegUI=1;
+                    ucdq_ui_small_reg_value = ucdq_ui_small;
+                }
+                else
+                    u1UpdateRegUI=0;
+
+                for(u1ByteIdx=0; u1ByteIdx < DQS_NUMBER; u1ByteIdx++)
+                {
+                    if(u1UpdateRegUI)
+                    {
+                        ucdq_reg_ui_large[u1ByteIdx] = ucdq_ui_large;
+                        ucdq_reg_ui_small[u1ByteIdx] = ucdq_ui_small;
+                        ucdq_reg_oen_ui_large[u1ByteIdx] = ucdq_oen_ui_large;
+                        ucdq_reg_oen_ui_small[u1ByteIdx] = ucdq_oen_ui_small;
+
+                        ucdq_reg_dqm_ui_large[u1ByteIdx] = ucdq_ui_large;
+                        ucdq_reg_dqm_ui_small[u1ByteIdx] = ucdq_ui_small;
+                        ucdq_reg_dqm_oen_ui_large[u1ByteIdx] = ucdq_oen_ui_large;
+                        ucdq_reg_dqm_oen_ui_small[u1ByteIdx] = ucdq_oen_ui_small;
+                    }
+
+                    ucdq_reg_pi[u1ByteIdx] = ucdq_pi;
+                    ucdq_reg_dqm_pi[u1ByteIdx] = ucdq_pi;
+                }
+
+                if(calType ==TX_DQ_DQS_MOVE_DQ_ONLY || calType== TX_DQ_DQS_MOVE_DQ_DQM)
+                {
+                    TXSetDelayReg_DQ(p, u1UpdateRegUI, ucdq_reg_ui_large, ucdq_reg_oen_ui_large, ucdq_reg_ui_small, ucdq_reg_oen_ui_small, ucdq_reg_pi);
+                }
+
+                if(calType ==TX_DQ_DQS_MOVE_DQM_ONLY || calType== TX_DQ_DQS_MOVE_DQ_DQM)
+                {
+                    TXSetDelayReg_DQM(p, u1UpdateRegUI, ucdq_reg_dqm_ui_large, ucdq_reg_dqm_oen_ui_large, ucdq_reg_dqm_ui_small, ucdq_reg_dqm_oen_ui_small, ucdq_reg_dqm_pi);
+                }
+
+                // audio +xtalk pattern
+                //u4err_value=0;
+                DramcEngine2SetPat(p,TEST_AUDIO_PATTERN, 0,0);
+                u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, TEST_AUDIO_PATTERN);
+                DramcEngine2SetPat(p,TEST_XTALK_PATTERN, 0,0);
+                u4err_value |= DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, TEST_XTALK_PATTERN);
+
+                if(u1VrefScanEnable==0 && (calType != TX_DQ_DQS_MOVE_DQM_ONLY))
+                {
+                    //mcSHOW_DBG_MSG(("Delay=%3d |%2d %2d %3d| %2d %2d| 0x%8x [0]",uiDelay, ucdq_ui_large,ucdq_ui_small, ucdq_pi, ucdq_oen_ui_large,ucdq_oen_ui_small, u4err_value));
+                    #ifdef ETT_PRINT_FORMAT
+                    if(u4err_value !=0)
+                    {
+                        mcSHOW_DBG_MSG2(("%d |%d %d %d|[0]", uiDelay, ucdq_ui_large, ucdq_ui_small, ucdq_pi));
+                    }
+                    #else
+                    mcSHOW_DBG_MSG2(("Delay=%3d |%2d %2d %3d| 0x%8x [0]", uiDelay, ucdq_ui_large, ucdq_ui_small, ucdq_pi, u4err_value));
+                    #endif
+                    mcFPRINTF((fp_A60501, "Delay=%3d | %2d %2d %3d| 0x%8x [0]", uiDelay, ucdq_ui_large,ucdq_ui_small, ucdq_pi, u4err_value));
+                }
+
+                // check fail bit ,0 ok ,others fail
+                for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+                {
+                    u4fail_bit = u4err_value&((U32)1<<u1BitIdx);
+
+                    if(u1VrefScanEnable==0 && (calType != TX_DQ_DQS_MOVE_DQM_ONLY))
+                    {
+                        if(u4err_value != 0)
+                        {
+                            if(u1BitIdx%DQS_BIT_NUMBER ==0)
+                            {
+                                mcSHOW_DBG_MSG2((" "));
+                                mcFPRINTF((fp_A60501, " "));
+                            }
+
+                            if (u4fail_bit == 0)
+                            {
+                                mcSHOW_DBG_MSG2(("o"));
+                                mcFPRINTF((fp_A60501, "o"));
+                            }
+                            else
+                            {
+                                mcSHOW_DBG_MSG2(("x"));
+                                mcFPRINTF((fp_A60501, "x"));
+                            }
+                        }
+                    }
+
+                    if(WinPerBit[u1BitIdx].first_pass== PASS_RANGE_NA)
+                    {
+                        if(u4fail_bit==0) //compare correct: pass
+                        {
+                            WinPerBit[u1BitIdx].first_pass = uiDelay;
+
+                            #if TX_TDQS2DQ_PRE_CAL
+                            if((p->frequency == LP4_LOWEST_FREQ) && (u2DQS2DQ_Pre_Cal[p->channel][p->rank]==0))
+                            {
+                                u2DQS2DQ_Pre_Cal[p->channel][p->rank] = (uiDelay - u2DQDelayBegin) *850 / p->frequency;
+                            }
+
+                            if(uiDelay==u2DQDelayBegin)
+                            {
+                                mcSHOW_ERR_MSG(("TX_TDQS2DQ_PRE_CAL: Warning, possible miss TX window boundary\n"));
+                                #if __ETT__
+                                while(1);
+                                #endif
+                            }
+                            #endif
+                        }
+                    }
+                    else if(WinPerBit[u1BitIdx].last_pass == PASS_RANGE_NA)
+                    {
+                        if(u4fail_bit !=0) //compare error : fail
+                        {
+                            WinPerBit[u1BitIdx].last_pass  = (uiDelay-1);
+                        }
+                        else if (uiDelay==u2DQDelayEnd)
+                        {
+                            WinPerBit[u1BitIdx].last_pass  = uiDelay;
+                        }
+
+                        if(WinPerBit[u1BitIdx].last_pass  !=PASS_RANGE_NA)
+                        {
+                            if((WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass) >= (VrefWinPerBit[u1BitIdx].last_pass -VrefWinPerBit[u1BitIdx].first_pass))
+                            {
+                                if((VrefWinPerBit[u1BitIdx].last_pass != PASS_RANGE_NA) && (VrefWinPerBit[u1BitIdx].last_pass -VrefWinPerBit[u1BitIdx].first_pass)>0)
+                                {
+                                    mcSHOW_DBG_MSG2(("Bit[%d] Bigger window update %d > %d, window broken?\n", u1BitIdx, \
+                                        (WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass), (VrefWinPerBit[u1BitIdx].last_pass -VrefWinPerBit[u1BitIdx].first_pass)));
+                                    mcFPRINTF((fp_A60501,"Bit[%d] Bigger window update %d > %d\n", u1BitIdx, \
+                                        (WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass), (VrefWinPerBit[u1BitIdx].last_pass -VrefWinPerBit[u1BitIdx].first_pass)));
+
+                                }
+
+                                //if window size bigger than 7, consider as real pass window. If not, don't update finish counte and won't do early break;
+                                if((WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass) >7)
+                                    uiFinishCount |= (1<<u1BitIdx);
+
+                                //update bigger window size
+                                VrefWinPerBit[u1BitIdx].first_pass = WinPerBit[u1BitIdx].first_pass;
+                                VrefWinPerBit[u1BitIdx].last_pass = WinPerBit[u1BitIdx].last_pass;
+                            }
+
+                            //reset tmp window
+                            WinPerBit[u1BitIdx].first_pass = PASS_RANGE_NA;
+                            WinPerBit[u1BitIdx].last_pass = PASS_RANGE_NA;
+                        }
+                     }
+                }
+
+                if(u1VrefScanEnable==0 && (calType != TX_DQ_DQS_MOVE_DQM_ONLY))
+                {
+                    if(u4err_value != 0)
+                    {
+                        mcSHOW_DBG_MSG2((" [MSB]\n"));
+                        mcFPRINTF((fp_A60501, " [MSB]\n"));
+                    }
+                }
+
+                //if all bits widnow found and all bits turns to fail again, early break;
+                if((u1IsLP4Family(p->dram_type) &&(uiFinishCount == 0xffff)) || \
+                    ((p->dram_type == TYPE_LPDDR3) &&(uiFinishCount == 0xffffffff)))
+                    {
+                        vSetCalibrationResult(p, DRAM_CALIBRATION_TX_PERBIT, DRAM_OK);
+
+                        #if !REDUCE_LOG_FOR_PRELOADER
+                        #ifdef ETT_PRINT_FORMAT
+                        mcSHOW_DBG_MSG2(("TX calibration finding left boundary early break. PI DQ delay=0x%B\n", uiDelay));
+                        #else
+                        mcSHOW_DBG_MSG2(("TX calibration finding left boundary early break. PI DQ delay=0x%2x\n", uiDelay));
+                        #endif
+                        #endif
+                        break;  //early break
+                    }
+            }
+
+
+            // (1) calculate per bit window size
+            // (2) find out min win of all DQ bits
+            // (3) calculate perbit window center
+            u1min_winsize = 0xff;
+            u1min_bit = 0xff;
+            for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+            {
+                //if(VrefWinPerBit[u1BitIdx].last_pass == VrefWinPerBit[u1BitIdx].first_pass)
+                if(VrefWinPerBit[u1BitIdx].first_pass == PASS_RANGE_NA)
+                    VrefWinPerBit[u1BitIdx].win_size = 0;
+                else
+                    VrefWinPerBit[u1BitIdx].win_size= VrefWinPerBit[u1BitIdx].last_pass- VrefWinPerBit[u1BitIdx].first_pass +1;
+
+                if (VrefWinPerBit[u1BitIdx].win_size < u1min_winsize)
+                {
+                    u1min_bit = u1BitIdx;
+                    u1min_winsize = VrefWinPerBit[u1BitIdx].win_size;
+                }
+
+                u2TempWinSum += VrefWinPerBit[u1BitIdx].win_size;  //Sum of CA Windows for vref selection
+
+                #if VENDER_JV_LOG
+                if((calType ==TX_DQ_DQS_MOVE_DQ_ONLY && u1IsLP4Family(p->dram_type)) || (calType ==TX_DQ_DQS_MOVE_DQ_DQM && !u1IsLP4Family(p->dram_type)))
+                {
+                    mcSHOW_DBG_MSG5(("TX Bit%d, %d%%\n", u1BitIdx,  (VrefWinPerBit[u1BitIdx].win_size*100+31)/32));
+                }
+                #endif
+
+
+                // calculate per bit window position and print
+                VrefWinPerBit[u1BitIdx].win_center= (VrefWinPerBit[u1BitIdx].first_pass + VrefWinPerBit[u1BitIdx].last_pass) >> 1;
+
+            #if PINMUX_AUTO_TEST_PER_BIT_TX
+                gFinalTXPerbitFirstPass[p->channel][u1BitIdx] = VrefWinPerBit[u1BitIdx].first_pass;
+            #endif
+            }
+
+            mcSHOW_DBG_MSG3(("Min Bit=%d, winsize=%d\n",u1min_bit, u1min_winsize));
+            #if __ETT__
+            if(u1VrefScanEnable==0)
+            {
+                //mcSHOW_DBG_MSG(("\n\tCH=%d, VrefRange= %d, VrefLevel = %d\n", p->channel, u2FinalRange, u2VrefLevel));
+                //mcFPRINTF((fp_A60501,"\n\tchannel=%d(2:cha, 3:chb)  u2VrefLevel = %d\n", p->channel, u2VrefLevel));
+                TxPrintWidnowInfo(p, VrefWinPerBit);
+            }
+            #endif
+
+            if(u1VrefScanEnable==1)
+            {
+                if(u2TempWinSum > u2MaxWindowSum)
+                    u2MaxWindowSum= u2TempWinSum;
+
+                VrefInfo[u1VrefIdx].u2VrefUsed = u2VrefLevel;
+                VrefInfo[u1VrefIdx].u2MinWinSize_byVref= u1min_winsize;
+                VrefInfo[u1VrefIdx].u2WinSum_byVref = u2TempWinSum;
+                u1VrefIdx ++;
+            }
+
+            #if LP4_TX_VREF_PASS_CONDITION
+            if(u1VrefScanEnable && (u2TempWinSum < (u2MaxWindowSum*95/100)) &&(u1min_winsize < LP4_TX_VREF_PASS_CONDITION))
+            #else
+            if(u1VrefScanEnable && (u2TempWinSum < (u2MaxWindowSum*95/100)))
+            #endif
+            {
+                mcSHOW_DBG_MSG(("\nTX Vref early break, caculate TX vref\n"));
+                break;
+            }
+        }
+
+        DramcEngine2End(p);
+
+        if(u1VrefScanEnable==0)// ..if time domain (not vref scan) , calculate window center of all bits.
+        {
+            // Calculate the center of DQ pass window
+            // Record center sum of each byte
+            for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+            {
+                #if 1//TX_DQM_CALC_MAX_MIN_CENTER
+                u2Center_min[u1ByteIdx] = 0xffff;
+                u2Center_max[u1ByteIdx] = 0;
+                #endif
+
+                for (u1BitIdx=0; u1BitIdx<DQS_BIT_NUMBER; u1BitIdx++)
+                {
+                    u1BitTemp = u1ByteIdx * DQS_BIT_NUMBER + u1BitIdx;
+                    memcpy(FinalWinPerBit, VrefWinPerBit, sizeof(PASS_WIN_DATA_T)*DQ_DATA_WIDTH);
+
+                    if(FinalWinPerBit[u1BitTemp].win_center < u2Center_min[u1ByteIdx])
+                        u2Center_min[u1ByteIdx] = FinalWinPerBit[u1BitTemp].win_center;
+
+                    if(FinalWinPerBit[u1BitTemp].win_center > u2Center_max[u1ByteIdx])
+                        u2Center_max[u1ByteIdx] = FinalWinPerBit[u1BitTemp].win_center;
+
+                    #ifdef FOR_HQA_TEST_USED
+                    if((u1IsLP4Family(p->dram_type) && calType == TX_DQ_DQS_MOVE_DQ_ONLY && (u1VrefScanEnable==0))
+                        || (!u1IsLP4Family(p->dram_type) && (calType == TX_DQ_DQS_MOVE_DQ_DQM)))
+                    {
+                        gFinalTXPerbitWin[p->channel][p->rank][u1BitTemp] = FinalWinPerBit[u1BitTemp].win_size;
+                    }
+                    #endif
+                }
+            }
+
+            #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+            if(p->femmc_Ready==0)//save firtst run pass value
+            {
+                for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+                {
+                    if(calType == TX_DQ_DQS_MOVE_DQ_ONLY) // && u1VrefScanEnable==0
+                    {
+                        p->pSavetimeData->u1TxCenter_min_Save[p->channel][p->rank][u1ByteIdx]=u2Center_min[u1ByteIdx];
+                        p->pSavetimeData->u1TxCenter_max_Save[p->channel][p->rank][u1ByteIdx]=u2Center_max[u1ByteIdx];
+
+                        for (u1BitIdx=0; u1BitIdx<DQS_BIT_NUMBER; u1BitIdx++)
+                        {
+                            u1BitTemp = u1ByteIdx*DQS_BIT_NUMBER+u1BitIdx;
+                            p->pSavetimeData->u1Txwin_center_Save[p->channel][p->rank][u1BitTemp]=FinalWinPerBit[u1BitTemp].win_center;
+                        }
+                    }
+                }
+            }
+            #endif
+        }
+    }
+
+    // SET tx Vref (DQ) = u2FinalVref, LP3 no need to set this.
+    if(u1IsLP4Family(p->dram_type) && (u1VrefScanEnable!=DISABLE_VREF_SCAN))
+    {
+        #if SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_VREF_CAL
+        if(p->femmc_Ready==1 && (p->Bypass_TXWINDOW) && u1VrefScanEnable!=SET_VREF_AND_DISABLE_VREF_SCAN)
+        {
+            u2FinalVref = p->pSavetimeData->u1TxWindowPerbitVref_Save[p->channel][p->rank];
+        }
+        else
+        #endif
+        {
+            if (u1VrefScanEnable==ENABLE_VREF_SCAN)
+            {
+                u2FinalVref = TxChooseVref(p, VrefInfo, u1VrefIdx);
+
+#ifdef DEVIATION
+                if (p->frequency == u2DFSGetHighestFreq(p) && gSetSpecificedVref_Enable[2]==ENABLE && ((p->channel==gSetSpecificedVref_Channel[2] && p->rank==gSetSpecificedVref_Rank[2]) || gSetSpecificedVref_All_ChRk[2]==ENABLE))
+                {
+                    DeviationAddVrefOffset(2, &u2FinalRange, &u2FinalVref, gSetSpecificedVref_Vref_Offset[2]);
+                }
+#endif
+            }
+
+            #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+            if(p->femmc_Ready==0)////save firtst run Vref value
+            {
+                p->pSavetimeData->u1TxWindowPerbitVref_Save[p->channel][p->rank]=u2FinalVref;
+            }
+            #endif
+        }
+        #ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+        gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag = u1GUMP_INIT_RG_LOG_TO_DE_bak;
+        #endif
+
+        TXSetFinalVref(p, u2FinalRange, u2FinalVref);
+        return DRAM_OK;
+    }
+
+
+#ifdef FOR_HQA_TEST_USED
+    // LP4 DQ time domain || LP3 DQ_DQM time domain
+    if((u1IsLP4Family(p->dram_type) && (calType == TX_DQ_DQS_MOVE_DQ_ONLY)) ||
+        (!u1IsLP4Family(p->dram_type) && (calType == TX_DQ_DQS_MOVE_DQ_DQM)))
+    {
+        gFinalTXPerbitWin_min_max[p->channel][p->rank] = u1min_winsize;
+    }
+#endif
+
+    // LP3 only use "TX_DQ_DQS_MOVE_DQ_DQM" scan
+    // first freq 800(LP4-1600) doesn't support jitter meter(data < 1T), therefore, don't use delay cell
+    if((calType == TX_DQ_DQS_MOVE_DQ_ONLY) && (p->frequency >= gu4TermFreq) && (p->u2DelayCellTimex100!=0))
+    {
+        u1EnableDelayCell =1;
+        mcSHOW_DBG_MSG(("[TX_PER_BIT_DELAY_CELL] DelayCellTimex100 =%d/100 ps\n", p->u2DelayCellTimex100));
+    }
+
+    //Calculate the center of DQ pass window
+    //average the center delay
+    for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+    {
+        mcSHOW_DBG_MSG((" == TX Byte %d ==\n", u1ByteIdx));
+        if(u1EnableDelayCell==0)
+        {
+            uiDelay = ((u2Center_min[u1ByteIdx] + u2Center_max[u1ByteIdx])>>1); //(max +min)/2
+            u2TX_DQ_PreCal_LP4[u1ByteIdx] = uiDelay;  //LP4 only, for tDQS2DQ
+        }
+        else // if(calType == TX_DQ_DQS_MOVE_DQ_ONLY)
+        {
+            uiDelay = u2Center_min[u1ByteIdx];  // for DQ PI delay , will adjust with delay cell
+            u2TX_DQ_PreCal_LP4[u1ByteIdx] = ((u2Center_min[u1ByteIdx] + u2Center_max[u1ByteIdx])>>1);  // for DQM PI delay
+
+            #if 0//SUPPORT_SAVE_TIME_FOR_CALIBRATION//BYPASS_TX_PER_BIT_DELAY_CELL
+            if(p->femmc_Ready==1 && (p->Bypass_TXWINDOW))
+            {
+            	for (u1BitIdx = 0; u1BitIdx < DQS_BIT_NUMBER; u1BitIdx++)
+            	{
+            		u1BitTemp = u1ByteIdx*DQS_BIT_NUMBER+u1BitIdx;
+            		u1DelayCellOfst[u1BitTemp] = p->pSavetimeData->u1TX_PerBit_DelayLine_Save[p->channel][p->rank][u1BitTemp];
+            	}
+            }
+            else
+            #endif
+            {
+                // calculate delay cell perbit
+                for (u1BitIdx = 0; u1BitIdx < DQS_BIT_NUMBER; u1BitIdx++)
+                {
+                    u1BitTemp = u1ByteIdx*DQS_BIT_NUMBER+u1BitIdx;
+                    u1PIDiff = FinalWinPerBit[u1BitTemp].win_center - u2Center_min[u1ByteIdx];
+                    if(p->u2DelayCellTimex100 !=0)
+                    {
+                        u1DelayCellOfst[u1BitTemp] = (u1PIDiff*100000000/(p->frequency<<6))/p->u2DelayCellTimex100;
+                        #if 0//SUPPORT_SAVE_TIME_FOR_CALIBRATION
+                        p->pSavetimeData->u1TX_PerBit_DelayLine_Save[p->channel][p->rank][u1BitTemp] = u1DelayCellOfst[u1BitTemp];
+                        #endif
+                        mcSHOW_DBG_MSG(("u1DelayCellOfst[%d]=%d cells (%d PI)\n",  u1BitTemp, u1DelayCellOfst[u1BitTemp], u1PIDiff));
+                    }
+                    else
+                    {
+                        mcSHOW_ERR_MSG(("Error: Cell time (p->u2DelayCellTimex100) is 0 \n"));
+                        break;
+                    }
+                }
+            }
+        }
+
+        TxWinTransferDelayToUIPI(p, calType, uiDelay, 1, &ucdq_reg_ui_large[u1ByteIdx], &ucdq_reg_ui_small[u1ByteIdx], &ucdq_reg_pi[u1ByteIdx],\
+                                &ucdq_reg_oen_ui_large[u1ByteIdx], &ucdq_reg_oen_ui_small[u1ByteIdx]);
+
+        TxWinTransferDelayToUIPI(p, calType, u2TX_DQ_PreCal_LP4[u1ByteIdx], 1, &ucdq_reg_dqm_ui_large[u1ByteIdx], &ucdq_reg_dqm_ui_small[u1ByteIdx], &ucdq_reg_dqm_pi[u1ByteIdx],\
+                                &ucdq_reg_dqm_oen_ui_large[u1ByteIdx], &ucdq_reg_dqm_oen_ui_small[u1ByteIdx]);
+
+        if(calType ==TX_DQ_DQS_MOVE_DQ_ONLY || calType== TX_DQ_DQS_MOVE_DQ_DQM)
+        {
+            mcSHOW_DBG_MSG(("Update DQ  dly =%d (%d ,%d, %d)  DQ  OEN =(%d ,%d)\n",
+                            uiDelay, ucdq_reg_ui_large[u1ByteIdx], ucdq_reg_ui_small[u1ByteIdx], ucdq_reg_pi[u1ByteIdx],\
+                            ucdq_reg_oen_ui_large[u1ByteIdx], ucdq_reg_oen_ui_small[u1ByteIdx]));
+
+            mcFPRINTF((fp_A60501,"Byte%d, PI DQ dly %d\n",  u1ByteIdx, uiDelay));
+            mcFPRINTF((fp_A60501,"Final DQ PI dly(LargeUI, SmallUI, PI) =(%d ,%d, %d)\n", ucdq_reg_ui_large[u1ByteIdx], ucdq_reg_ui_small[u1ByteIdx], ucdq_reg_pi[u1ByteIdx]));
+            mcFPRINTF((fp_A60501,"OEN DQ PI dly(LargeUI, SmallUI, PI) =(%d ,%d, %d)\n\n", ucdq_reg_oen_ui_large[u1ByteIdx], ucdq_reg_oen_ui_small[u1ByteIdx], ucdq_reg_pi[u1ByteIdx]));
+        }
+
+        //if(calType ==TX_DQ_DQS_MOVE_DQM_ONLY || calType== TX_DQ_DQS_MOVE_DQ_DQM)
+        {
+            mcSHOW_DBG_MSG(("Update DQM dly =%d (%d ,%d, %d)  DQM OEN =(%d ,%d)",
+                    u2TX_DQ_PreCal_LP4[u1ByteIdx], ucdq_reg_dqm_ui_large[u1ByteIdx], ucdq_reg_dqm_ui_small[u1ByteIdx], ucdq_reg_dqm_pi[u1ByteIdx], \
+                    ucdq_reg_dqm_oen_ui_large[u1ByteIdx], ucdq_reg_dqm_oen_ui_small[u1ByteIdx]));
+        }
+        mcSHOW_DBG_MSG(("\n"));
+
+#ifdef FOR_HQA_REPORT_USED
+        if(calType == TX_DQ_DQS_MOVE_DQ_ONLY)
+        {
+            for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+            {
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT1, "TX_Window_Center_DQ", u1BitIdx, FinalWinPerBit[u1BitIdx].win_center, NULL);
+            }
+        }
+
+        if(calType == TX_DQ_DQS_MOVE_DQM_ONLY)
+        {
+            HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0, "TX_Window_Center_DQM", u1ByteIdx, u2TX_DQ_PreCal_LP4[u1ByteIdx], NULL);
+        }
+#if 0
+        HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT1, "TX_Window_Center_LargeUI", u1ByteIdx, ucdq_reg_ui_large[u1ByteIdx], NULL);
+        HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0, "TX_Window_Center_SmallUI", u1ByteIdx, ucdq_reg_ui_small[u1ByteIdx], NULL);
+        HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0, "TX_Window_Center_PI", u1ByteIdx, ucdq_reg_pi[u1ByteIdx], NULL);
+#endif
+#endif
+
+    }
+
+#ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+    gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag = u1GUMP_INIT_RG_LOG_TO_DE_bak;
+#endif
+
+#if REG_ACCESS_PORTING_DGB
+    RegLogEnable =1;
+#endif
+
+        /* p->rank = RANK_0, save to Reg Rank0 and Rank1, p->rank = RANK_1, save to Reg Rank1 */
+        for(u1RankIdx=p->rank; u1RankIdx<RANK_MAX; u1RankIdx++)
+        {
+            vSetRank(p,u1RankIdx);
+
+            if(calType ==TX_DQ_DQS_MOVE_DQ_ONLY || calType== TX_DQ_DQS_MOVE_DQ_DQM)
+            {
+                TXSetDelayReg_DQ(p, TRUE, ucdq_reg_ui_large, ucdq_reg_oen_ui_large, ucdq_reg_ui_small, ucdq_reg_oen_ui_small, ucdq_reg_pi);
+            }
+
+            TXSetDelayReg_DQM(p, TRUE, ucdq_reg_dqm_ui_large, ucdq_reg_dqm_oen_ui_large, ucdq_reg_dqm_ui_small, ucdq_reg_dqm_oen_ui_small, ucdq_reg_dqm_pi);
+
+
+             if(u1IsLP4Family(p->dram_type))
+             {
+                 if(u1EnableDelayCell)
+                 {
+                     vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ0),
+                                P_Fld(u1DelayCellOfst[7] , SHU1_R0_B0_DQ0_RK0_TX_ARDQ7_DLY_B0)
+                             | P_Fld(u1DelayCellOfst[6] , SHU1_R0_B0_DQ0_RK0_TX_ARDQ6_DLY_B0)
+                             | P_Fld(u1DelayCellOfst[5] , SHU1_R0_B0_DQ0_RK0_TX_ARDQ5_DLY_B0)
+                             | P_Fld(u1DelayCellOfst[4] , SHU1_R0_B0_DQ0_RK0_TX_ARDQ4_DLY_B0)
+                             | P_Fld(u1DelayCellOfst[3] , SHU1_R0_B0_DQ0_RK0_TX_ARDQ3_DLY_B0)
+                             | P_Fld(u1DelayCellOfst[2] , SHU1_R0_B0_DQ0_RK0_TX_ARDQ2_DLY_B0)
+                             | P_Fld(u1DelayCellOfst[1] , SHU1_R0_B0_DQ0_RK0_TX_ARDQ1_DLY_B0)
+                             | P_Fld(u1DelayCellOfst[0] , SHU1_R0_B0_DQ0_RK0_TX_ARDQ0_DLY_B0));
+                     vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ0),
+                                P_Fld(u1DelayCellOfst[15] , SHU1_R0_B1_DQ0_RK0_TX_ARDQ7_DLY_B1)
+                             | P_Fld(u1DelayCellOfst[14] , SHU1_R0_B1_DQ0_RK0_TX_ARDQ6_DLY_B1)
+                             | P_Fld(u1DelayCellOfst[13] , SHU1_R0_B1_DQ0_RK0_TX_ARDQ5_DLY_B1)
+                             | P_Fld(u1DelayCellOfst[12] , SHU1_R0_B1_DQ0_RK0_TX_ARDQ4_DLY_B1)
+                             | P_Fld(u1DelayCellOfst[11] , SHU1_R0_B1_DQ0_RK0_TX_ARDQ3_DLY_B1)
+                             | P_Fld(u1DelayCellOfst[10] , SHU1_R0_B1_DQ0_RK0_TX_ARDQ2_DLY_B1)
+                             | P_Fld(u1DelayCellOfst[9] , SHU1_R0_B1_DQ0_RK0_TX_ARDQ1_DLY_B1)
+                             | P_Fld(u1DelayCellOfst[8] , SHU1_R0_B1_DQ0_RK0_TX_ARDQ0_DLY_B1));
+                 }
+            }
+
+            #if ENABLE_TX_TRACKING
+            TXUpdateTXTracking(p, calType, ucdq_reg_pi, ucdq_reg_dqm_pi);
+            #endif
+        }
+
+        vSetRank(p, backup_rank);
+
+#if REG_ACCESS_PORTING_DGB
+    RegLogEnable =0;
+#endif
+
+    mcSHOW_DBG_MSG3(("[TxWindowPerbitCal] Done\n\n"));
+    mcFPRINTF((fp_A60501, "[TxWindowPerbitCal] Done\n\n"));
+
+    #if 0
+    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_PADCTL4), 1, PADCTL4_CKEFIXON);  // test only
+    #endif
+
+    return DRAM_OK;
+}
+#endif //SIMULATION_TX_PERBIT
+
+#if EYESCAN_LOG
+void Dramc_K_TX_EyeScan_Log(DRAMC_CTX_T *p)
+{
+    U8 ucindex, u1BitIdx, u1ByteIdx;
+    U8 ii, u1vrefidx;
+    PASS_WIN_DATA_T WinPerBit[DQ_DATA_WIDTH], VrefWinPerBit[DQ_DATA_WIDTH], FinalWinPerBit[DQ_DATA_WIDTH];
+    U16 tx_pi_delay[4], tx_dqm_pi_delay[4];
+    U16 u2DQDelayBegin, uiDelay;
+    U16 u2VrefLevel, u2VrefBegin, u2VrefEnd, u2VrefStep, u2VrefRange;
+    U8 ucdq_pi, ucdq_ui_small, ucdq_ui_large,ucdq_oen_ui_small, ucdq_oen_ui_large;
+    U32 uiFinishCount;
+    U16 u2TempWinSum, u2tx_window_sum=0;
+    U32 u4err_value, u4fail_bit;
+    #if 1//TX_DQM_CALC_MAX_MIN_CENTER
+    U16 u2Center_min[DQS_NUMBER],u2Center_max[DQS_NUMBER];
+    #endif
+
+    U16 TXPerbitWin_min_max = 0;
+    U32 min_bit, min_winsize;
+
+    U16 u2FinalVref=0xd;
+    U16 u2FinalRange=0;
+
+    U8 EyeScan_index[DQ_DATA_WIDTH];
+
+    U8 backup_u1MR14Value;
+    U8 u1pass_in_this_vref_flag[DQ_DATA_WIDTH];
+
+    U32 u4RegBackupAddress[] =
+    {
+        (DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0)),
+        (DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2)),
+        (DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1)),
+        (DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3)),
+        (DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7)),
+        (DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7)),
+    };
+
+    if(gTX_EYE_Scan_flag==0) return;
+
+    if (gTX_EYE_Scan_only_higheset_freq_flag==1 && p->frequency != u2DFSGetHighestFreq(p)) return;
+
+
+    //backup register value
+    DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+    backup_u1MR14Value = u1MR14Value[p->channel][p->rank][p->dram_fsp];
+
+    //set initial values
+    for(u1vrefidx=0; u1vrefidx<VREF_TOTAL_NUM_WITH_RANGE;u1vrefidx++)
+    {
+        for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+        {
+            for(ii=0; ii<EYESCAN_BROKEN_NUM; ii++)
+            {
+                gEyeScan_Min[u1vrefidx][u1BitIdx][ii] = EYESCAN_DATA_INVALID;
+                gEyeScan_Max[u1vrefidx][u1BitIdx][ii] = EYESCAN_DATA_INVALID;
+            }
+            gEyeScan_ContinueVrefHeight[u1BitIdx] = 0;
+            gEyeScan_TotalPassCount[u1BitIdx] = 0;
+        }
+    }
+
+    for(u1ByteIdx=0; u1ByteIdx < p->data_width/DQS_BIT_NUMBER; u1ByteIdx++)
+    {
+        if (u1ByteIdx == 0)
+        {
+            tx_pi_delay[u1ByteIdx] = 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[u1ByteIdx] = 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[u1ByteIdx] = 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[u1ByteIdx] = 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);
+        }
+    }
+
+    if (tx_pi_delay[0] < tx_pi_delay[1])
+    {
+        u2DQDelayBegin = tx_pi_delay[0]-32;
+    }
+    else
+    {
+        u2DQDelayBegin = tx_pi_delay[1]-32;
+    }
+
+    u2VrefRange = 0;
+    u2VrefBegin = 0;
+    u2VrefEnd = 50;
+    u2VrefStep = 1;
+
+    DramcEngine2Init(p, p->test2_1, p->test2_2, p->test_pattern, 0);
+
+    for(u2VrefLevel = u2VrefBegin; u2VrefLevel <= u2VrefEnd; u2VrefLevel += u2VrefStep)
+    {
+        //set vref
+//fra        u1MR14Value[p->channel][p->rank][p->dram_fsp] = (u2VrefLevel | (u2VrefRange<<6));
+        DramcModeRegWriteByRank(p, p->rank, 14, u2VrefLevel | (u2VrefRange<<6));
+
+        // initialize parameters
+        uiFinishCount = 0;
+        u2TempWinSum =0;
+
+        for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+        {
+            WinPerBit[u1BitIdx].first_pass = (S16)PASS_RANGE_NA;
+            WinPerBit[u1BitIdx].last_pass = (S16)PASS_RANGE_NA;
+            VrefWinPerBit[u1BitIdx].first_pass = (S16)PASS_RANGE_NA;
+            VrefWinPerBit[u1BitIdx].last_pass = (S16)PASS_RANGE_NA;
+
+            gEyeScan_DelayCellPI[u1BitIdx] = 0;
+
+            EyeScan_index[u1BitIdx] = 0;
+            u1pass_in_this_vref_flag[u1BitIdx] = 0;
+        }
+
+        for (uiDelay=0; uiDelay<64; uiDelay++)
+        {
+            TxWinTransferDelayToUIPI(p, TX_DQ_DQS_MOVE_DQ_DQM, tx_pi_delay[0]+uiDelay-32, 0, &ucdq_ui_large, &ucdq_ui_small, &ucdq_pi, &ucdq_oen_ui_large, &ucdq_oen_ui_small);
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), \
+                                             P_Fld(ucdq_ui_large, SHURK0_SELPH_DQ0_TXDLY_DQ0) | \
+                                             P_Fld(ucdq_oen_ui_large, SHURK0_SELPH_DQ0_TXDLY_OEN_DQ0));
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2), \
+                                             P_Fld(ucdq_ui_small, SHURK0_SELPH_DQ2_DLY_DQ0) | \
+                                             P_Fld(ucdq_oen_ui_small, SHURK0_SELPH_DQ2_DLY_OEN_DQ0));
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdq_pi, SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+
+            TxWinTransferDelayToUIPI(p, TX_DQ_DQS_MOVE_DQ_DQM, tx_pi_delay[1]+uiDelay-32, 0, &ucdq_ui_large, &ucdq_ui_small, &ucdq_pi, &ucdq_oen_ui_large, &ucdq_oen_ui_small);
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), \
+                                             P_Fld(ucdq_ui_large, SHURK0_SELPH_DQ0_TXDLY_DQ1) | \
+                                             P_Fld(ucdq_oen_ui_large, SHURK0_SELPH_DQ0_TXDLY_OEN_DQ1));
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2), \
+                                             P_Fld(ucdq_ui_small, SHURK0_SELPH_DQ2_DLY_DQ1) | \
+                                             P_Fld(ucdq_oen_ui_small, SHURK0_SELPH_DQ2_DLY_OEN_DQ1));
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), ucdq_pi, SHU1_R0_B1_DQ7_RK0_ARPI_DQ_B1);
+
+            TxWinTransferDelayToUIPI(p, TX_DQ_DQS_MOVE_DQ_DQM, tx_dqm_pi_delay[0]+uiDelay-32, 0, &ucdq_ui_large, &ucdq_ui_small, &ucdq_pi, &ucdq_oen_ui_large, &ucdq_oen_ui_small);
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), \
+                                            P_Fld(ucdq_ui_large, SHURK0_SELPH_DQ1_TXDLY_DQM0) | \
+                                            P_Fld(ucdq_oen_ui_large, SHURK0_SELPH_DQ1_TXDLY_OEN_DQM0));
+           vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3), \
+                                            P_Fld(ucdq_ui_small, SHURK0_SELPH_DQ3_DLY_DQM0) | \
+                                            P_Fld(ucdq_oen_ui_small, SHURK0_SELPH_DQ3_DLY_OEN_DQM0));
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdq_pi, SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+
+            TxWinTransferDelayToUIPI(p, TX_DQ_DQS_MOVE_DQ_DQM, tx_dqm_pi_delay[1]+uiDelay-32, 0, &ucdq_ui_large, &ucdq_ui_small, &ucdq_pi, &ucdq_oen_ui_large, &ucdq_oen_ui_small);
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), \
+                                             P_Fld(ucdq_ui_large, SHURK0_SELPH_DQ1_TXDLY_DQM1) | \
+                                             P_Fld(ucdq_oen_ui_large, SHURK0_SELPH_DQ1_TXDLY_OEN_DQM1));
+            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3), \
+                                             P_Fld(ucdq_ui_small, SHURK0_SELPH_DQ3_DLY_DQM1) | \
+                                             P_Fld(ucdq_oen_ui_small, SHURK0_SELPH_DQ3_DLY_OEN_DQM1));
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), ucdq_pi, SHU1_R0_B1_DQ7_RK0_ARPI_DQM_B1);
+
+
+             // audio +xtalk pattern
+            u4err_value=0;
+            DramcEngine2SetPat(p,TEST_AUDIO_PATTERN, 0,0);
+                u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, TEST_AUDIO_PATTERN);
+            DramcEngine2SetPat(p,TEST_XTALK_PATTERN, 0,0);
+                u4err_value |= DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, TEST_XTALK_PATTERN);
+
+            // check fail bit ,0 ok ,others fail
+            for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+            {
+                u4fail_bit = u4err_value&((U32)1<<u1BitIdx);
+
+                if (u4fail_bit == 0)
+                {
+                    gEyeScan_TotalPassCount[u1BitIdx]++;
+                }
+
+                if(WinPerBit[u1BitIdx].first_pass== PASS_RANGE_NA)
+                {
+                    if(u4fail_bit==0) //compare correct: pass
+                    {
+                        WinPerBit[u1BitIdx].first_pass = uiDelay;
+                        u1pass_in_this_vref_flag[u1BitIdx] = 1;
+                    }
+                }
+                else if(WinPerBit[u1BitIdx].last_pass == PASS_RANGE_NA)
+                {
+                    if(u4fail_bit !=0) //compare error : fail
+                    {
+                        WinPerBit[u1BitIdx].last_pass  = (uiDelay-1);
+                    }
+                    else if (uiDelay==64)
+                    {
+                        WinPerBit[u1BitIdx].last_pass  = uiDelay;
+                    }
+
+                    if(WinPerBit[u1BitIdx].last_pass  !=PASS_RANGE_NA)
+                    {
+                        if((WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass) >= (VrefWinPerBit[u1BitIdx].last_pass -VrefWinPerBit[u1BitIdx].first_pass))
+                        {
+                            //if window size bigger than 7, consider as real pass window. If not, don't update finish counte and won't do early break;
+                            if((WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass) >7)
+                                uiFinishCount |= (1<<u1BitIdx);
+
+                            //update bigger window size
+                            VrefWinPerBit[u1BitIdx].first_pass = WinPerBit[u1BitIdx].first_pass;
+                            VrefWinPerBit[u1BitIdx].last_pass = WinPerBit[u1BitIdx].last_pass;
+                        }
+
+#if EYESCAN_LOG
+                            if (EyeScan_index[u1BitIdx] < EYESCAN_BROKEN_NUM)
+                            {
+#if VENDER_JV_LOG || defined(RELEASE)
+                                gEyeScan_Min[u2VrefLevel+u2VrefRange*30][u1BitIdx][EyeScan_index[u1BitIdx]] = WinPerBit[u1BitIdx].first_pass;
+                                gEyeScan_Max[u2VrefLevel+u2VrefRange*30][u1BitIdx][EyeScan_index[u1BitIdx]] = WinPerBit[u1BitIdx].last_pass;
+#else
+                                gEyeScan_Min[u2VrefLevel+u2VrefRange*30][u1BitIdx][EyeScan_index[u1BitIdx]] = WinPerBit[u1BitIdx].first_pass + tx_pi_delay[u1BitIdx/8]-32;
+                                gEyeScan_Max[u2VrefLevel+u2VrefRange*30][u1BitIdx][EyeScan_index[u1BitIdx]] = WinPerBit[u1BitIdx].last_pass + tx_pi_delay[u1BitIdx/8]-32;
+#endif
+                                EyeScan_index[u1BitIdx]=EyeScan_index[u1BitIdx]+1;
+                            }
+#endif
+
+                        //reset tmp window
+                        WinPerBit[u1BitIdx].first_pass = PASS_RANGE_NA;
+                        WinPerBit[u1BitIdx].last_pass = PASS_RANGE_NA;
+                    }
+                 }
+               }
+        }
+
+        min_winsize = 0xffff;
+        min_bit = 0xff;
+        for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+        {
+            VrefWinPerBit[u1BitIdx].win_size = VrefWinPerBit[u1BitIdx].last_pass- VrefWinPerBit[u1BitIdx].first_pass +(VrefWinPerBit[u1BitIdx].last_pass==VrefWinPerBit[u1BitIdx].first_pass?0:1);
+
+            if (VrefWinPerBit[u1BitIdx].win_size < min_winsize)
+            {
+                min_bit = u1BitIdx;
+                min_winsize = VrefWinPerBit[u1BitIdx].win_size;
+            }
+
+            u2TempWinSum += VrefWinPerBit[u1BitIdx].win_size;  //Sum of CA Windows for vref selection
+
+#if EYESCAN_LOG
+            gEyeScan_WinSize[u2VrefLevel+u2VrefRange*30][u1BitIdx] = VrefWinPerBit[u1BitIdx].win_size;
+#endif
+
+#ifdef FOR_HQA_TEST_USED
+            if((((u1MR14Value[p->channel][p->rank][p->dram_fsp]>>6)&1) == u2VrefRange) && ((u1MR14Value[p->channel][p->rank][p->dram_fsp]&0x3f)==u2VrefLevel))
+            {
+                gFinalTXPerbitWin[p->channel][p->rank][u1BitIdx] = VrefWinPerBit[u1BitIdx].win_size;
+            }
+#endif
+        }
+
+        if ((min_winsize > TXPerbitWin_min_max) || ((min_winsize == TXPerbitWin_min_max) && (u2TempWinSum >u2tx_window_sum)))
+        {
+            TXPerbitWin_min_max = min_winsize;
+            u2tx_window_sum =u2TempWinSum;
+            u2FinalRange = u2VrefRange;
+            u2FinalVref = u2VrefLevel;
+
+            //Calculate the center of DQ pass window
+            // Record center sum of each byte
+            for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+            {
+        #if 1//TX_DQM_CALC_MAX_MIN_CENTER
+                u2Center_min[u1ByteIdx] = 0xffff;
+                u2Center_max[u1ByteIdx] = 0;
+        #endif
+
+                for (u1BitIdx=0; u1BitIdx<DQS_BIT_NUMBER; u1BitIdx++)
+                {
+                    ucindex = u1ByteIdx * DQS_BIT_NUMBER + u1BitIdx;
+                    FinalWinPerBit[ucindex].first_pass = VrefWinPerBit[ucindex].first_pass;
+                    FinalWinPerBit[ucindex].last_pass =  VrefWinPerBit[ucindex].last_pass;
+                    FinalWinPerBit[ucindex].win_size = VrefWinPerBit[ucindex].win_size;
+                    FinalWinPerBit[ucindex].win_center = (FinalWinPerBit[ucindex].first_pass + FinalWinPerBit[ucindex].last_pass) >> 1;
+
+                    if(FinalWinPerBit[ucindex].win_center < u2Center_min[u1ByteIdx])
+                        u2Center_min[u1ByteIdx] = FinalWinPerBit[ucindex].win_center;
+
+                    if(FinalWinPerBit[ucindex].win_center > u2Center_max[u1ByteIdx])
+                        u2Center_max[u1ByteIdx] = FinalWinPerBit[ucindex].win_center;
+                }
+            }
+        }
+
+
+        if(u2VrefRange==0 && u2VrefLevel ==50)
+        {
+            u2VrefRange = 1;
+            u2VrefLevel = 20;
+        }
+
+        for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+        {
+            if (u1pass_in_this_vref_flag[u1BitIdx]) gEyeScan_ContinueVrefHeight[u1BitIdx]++;  //count pass number of continue vref
+        }
+    }
+
+    DramcEngine2End(p);
+
+    //Calculate the center of DQ pass window
+    //average the center delay
+    for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+    {
+        uiDelay = ((u2Center_min[u1ByteIdx] + u2Center_max[u1ByteIdx])>>1); //(max +min)/2
+
+#if EYESCAN_LOG
+#if VENDER_JV_LOG || defined(RELEASE)
+        gEyeScan_CaliDelay[u1ByteIdx] = uiDelay;
+#else
+        gEyeScan_CaliDelay[u1ByteIdx] = uiDelay + tx_pi_delay[u1ByteIdx]-32;
+#endif
+#endif
+    }
+
+
+    //restore to orignal value
+    DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+    DramcModeRegWriteByRank(p, p->rank, 14, backup_u1MR14Value);
+    u1MR14Value[p->channel][p->rank][p->dram_fsp] = backup_u1MR14Value;
+
+}
+#endif
+
+
+#ifdef FOR_HQA_TEST_USED
+void HQA_measure_message_reset_all_data(DRAMC_CTX_T *p)
+{
+    U32 u1BitIdx, u1RankIdx, u1ChannelIdx;
+
+    for(u1ChannelIdx=CHANNEL_A; u1ChannelIdx<CHANNEL_NUM; u1ChannelIdx++)
+    {
+        for(u1RankIdx=RANK_0; u1RankIdx<RANK_MAX; u1RankIdx++)
+        {
+            for (u1BitIdx=0; u1BitIdx<p->data_width; u1BitIdx++)
+            {
+                gFinalRXPerbitWin[u1ChannelIdx][u1RankIdx][u1BitIdx] =0;
+                gFinalTXPerbitWin[u1ChannelIdx][u1RankIdx][u1BitIdx] =0;
+            }
+        }
+    }
+}
+#endif
+
+#ifdef FOR_HQA_REPORT_USED
+void print_EyeScanVcent_for_HQA_report_used(DRAMC_CTX_T *p, U8 print_type, U8 u1ChannelIdx, U8 u1RankIdx, U8 *EyeScanVcent, U8 EyeScanVcentUpperBound, U8 EyeScanVcentUpperBound_bit, U8 EyeScanVcentLowerBound, U8 EyeScanVcentLowerBound_bit)
+{
+    U32 uiCA, u1BitIdx;
+    U16 *pCBTVref_Voltage_Table[VREF_VOLTAGE_TABLE_NUM];
+    U16 *pTXVref_Voltage_Table[VREF_VOLTAGE_TABLE_NUM];
+    U8  CBTVrefRange;
+    U8  TXVrefRange;
+    U32 vddq;
+    U8 local_channel_num=2;
+    U8 shuffleIdx;
+    U8 u1CBTEyeScanEnable, u1RXEyeScanEnable, u1TXEyeScanEnable;
+
+	mcSHOW_DBG_MSG(("\n"));
+
+    if(u1IsLP4Family(p->dram_type))
+    {
+        local_channel_num = p->support_channel_num;
+    }
+    else
+    {
+        //LP3
+        local_channel_num = 1;
+    }
+
+    u1CBTEyeScanEnable = (gCBT_EYE_Scan_flag==1 && ((gCBT_EYE_Scan_only_higheset_freq_flag==1 && p->frequency == u2DFSGetHighestFreq(p)) || gCBT_EYE_Scan_only_higheset_freq_flag==0));
+    u1RXEyeScanEnable = (gRX_EYE_Scan_flag==1 && ((gRX_EYE_Scan_only_higheset_freq_flag==1 && p->frequency == u2DFSGetHighestFreq(p)) || gRX_EYE_Scan_only_higheset_freq_flag==0));
+    u1TXEyeScanEnable = (gTX_EYE_Scan_flag==1 && ((gTX_EYE_Scan_only_higheset_freq_flag==1 && p->frequency == u2DFSGetHighestFreq(p)) || gTX_EYE_Scan_only_higheset_freq_flag==0));
+
+    shuffleIdx = get_shuffleIndex_by_Freq(p);
+
+	if (gHQALog_flag==1 && print_type==0)
+	{
+        if (u1CBTEyeScanEnable)
+        {
+            if (p->dram_type == TYPE_LPDDR4)
+            {
+                pCBTVref_Voltage_Table[VREF_RANGE_0] = (U16 *)gVref_Voltage_Table_LP4[VREF_RANGE_0];
+                pCBTVref_Voltage_Table[VREF_RANGE_1] = (U16 *)gVref_Voltage_Table_LP4[VREF_RANGE_1];
+            }
+            if (p->dram_type == TYPE_LPDDR4X)
+            {
+                pCBTVref_Voltage_Table[VREF_RANGE_0] = (U16 *)gVref_Voltage_Table_LP4X[VREF_RANGE_0];
+                pCBTVref_Voltage_Table[VREF_RANGE_1] = (U16 *)gVref_Voltage_Table_LP4X[VREF_RANGE_1];
+            }
+
+            CBTVrefRange = (u1MR12Value[p->channel][p->rank][p->dram_fsp]>>6)&1;
+            vddq=vGetVoltage(p, 2)/1000; //mv
+
+            mcSHOW_DBG_MSG(("\n\n\n[HQA] information for measurement, "));
+            mcSHOW_DBG_MSG(("\tDram Data rate = %d\n",p->frequency*2));
+
+            mcSHOW_DBG_MSG(("CBT Eye Scan Vcent Voltage\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "CBT_Final_Vref Vcent", 0, pCBTVref_Voltage_Table[EyeScanVcent[0]][EyeScanVcent[1]]*vddq/100, NULL);
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "CBT_VdlVWHigh_Upper Vcent", 0, pCBTVref_Voltage_Table[EyeScanVcent[2]][EyeScanVcent[3]]*vddq/100, NULL);
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "CBT_VdlVWHigh_Lower Vcent", 0, pCBTVref_Voltage_Table[EyeScanVcent[4]][EyeScanVcent[5]]*vddq/100, NULL);
+
+            mcSHOW_DBG_MSG(("\n"));
+
+            mcSHOW_DBG_MSG(("CBT Eye Scan Vcent_UpperBound window\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "CBT_Vcent_UpperBound_Window", 0, EyeScanVcentUpperBound, NULL);
+            mcSHOW_DBG_MSG(("CBT Eye Scan Vcent_UpperBound_Window worse bit\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "CBT_Vcent_UpperBound_Window_bit", 0, EyeScanVcentUpperBound_bit, NULL);
+            mcSHOW_DBG_MSG(("CBT Eye Scan Vcent_UpperBound Min Window(%%)\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "CBT_Vcent_UpperBound_Window(%)", 0, (EyeScanVcentUpperBound * 100 + (u1IsLP4Family(p->dram_type)==1?63:31)) / (u1IsLP4Family(p->dram_type)==1?64:32), NULL);
+            mcSHOW_DBG_MSG(("CBT Eye Scan Vcent_UpperBound Min Window PASS/FAIL\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT4, "CBT_Vcent_UpperBound_Window_PF", 0, 0, (EyeScanVcentUpperBound * 100 + (u1IsLP4Family(p->dram_type)==1?63:31)) / (u1IsLP4Family(p->dram_type)==1?64:32) >= 25 ? "PASS" : "FAIL");
+
+            mcSHOW_DBG_MSG(("\n"));
+
+
+            mcSHOW_DBG_MSG(("CBT Eye Scan Vcent_LowerBound window\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "CBT_Vcent_LowerBound_Window", 0, EyeScanVcentLowerBound, NULL);
+            mcSHOW_DBG_MSG(("CBT Eye Scan Vcent_LowerBound_Window worse bit\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "CBT_Vcent_LowerBound_Window_bit", 0, EyeScanVcentLowerBound_bit, NULL);
+            mcSHOW_DBG_MSG(("CBT Eye Scan Vcent_UpperBound Min Window(%%)\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "CBT_Vcent_LowerBound_Window(%)", 0, (EyeScanVcentLowerBound * 100 + (u1IsLP4Family(p->dram_type)==1?63:31)) / (u1IsLP4Family(p->dram_type)==1?64:32), NULL);
+            mcSHOW_DBG_MSG(("CBT Eye Scan Vcent_LowerBound Min Window PASS/FAIL\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT4, "CBT_Vcent_LowerBound_Window_PF", 0, 0, (EyeScanVcentLowerBound * 100 + (u1IsLP4Family(p->dram_type)==1?63:31)) / (u1IsLP4Family(p->dram_type)==1?64:32) >= 25 ? "PASS" : "FAIL");
+
+            mcSHOW_DBG_MSG(("\n"));
+            mcSHOW_DBG_MSG(("CA Eye Scan per_bit window(%%)\n"));
+            for (uiCA=0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+            {
+#if EYESCAN_LOG
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_2, "CA_Perbit_Window(%)", uiCA, ((gEyeScan_WinSize[EyeScanVcent[0]*30+EyeScanVcent[1]][uiCA]) * 100 + 31) / 32, NULL);
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_2, "CA_Perbit_BestWindow(%)", uiCA, ((gEyeScan_WinSize[EyeScanVcent[10+uiCA*2]*30+EyeScanVcent[10+uiCA*2+1]][uiCA]) * 100 + 31) / 32, NULL);
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_2, "CA_Perbit_Window_Upperbond(%)", uiCA, ((gEyeScan_WinSize[EyeScanVcent[2]*30+EyeScanVcent[3]][uiCA]) * 100 + 31) / 32, NULL);
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_2, "CA_Perbit_Window_Lowerbond(%) ", uiCA, ((gEyeScan_WinSize[EyeScanVcent[4]*30+EyeScanVcent[5]][uiCA]) * 100 + 31) / 32, NULL);
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_2, "CA_Perbit_Eye_Height", uiCA, (gEyeScan_ContinueVrefHeight[uiCA]-1)*6*vddq/1000, NULL);
+//                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_2, "CA_Perbit_Eye_Area", uiCA, gEyeScan_TotalPassCount[uiCA]*1000*3*vddq/(32*DDRPhyFMeter()), NULL); //total count*1/32UI*(1/freq*10^6 ps)*(0.6%vddq)
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_2, "CA_Perbit_Eye_Area", uiCA, (gEyeScan_TotalPassCount[uiCA]*10*3*vddq/(32*DDRPhyFMeter()))*100, NULL); //total count*1/32UI*(1/freq*10^6 ps)*(0.6%vddq)
+#endif
+            }
+        }
+    }
+
+	if (gHQALog_flag==1 && print_type==1)
+	{
+        if (u1RXEyeScanEnable)
+        {
+            mcSHOW_DBG_MSG(("\n\n\n[HQA] information for measurement, "));
+            mcSHOW_DBG_MSG(("\tDram Data rate = %d\n",p->frequency*2));
+
+            mcSHOW_DBG_MSG(("RX Eye Scan Vcent Voltage\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "RX_Final_Vref Vcent", 0, gRXVref_Voltage_Table_LP4[EyeScanVcent[0]], NULL);
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "RX_VdlVWHigh_Upper Vcent", 0, gRXVref_Voltage_Table_LP4[EyeScanVcent[1]], NULL);
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "RX_VdlVWHigh_Lower Vcent", 0, gRXVref_Voltage_Table_LP4[EyeScanVcent[2]], NULL);
+
+            mcSHOW_DBG_MSG(("\n"));
+
+            mcSHOW_DBG_MSG(("RX Eye Scan Vcent_UpperBound window\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "RX_Vcent_UpperBound_Window", 0, EyeScanVcentUpperBound, NULL);
+            mcSHOW_DBG_MSG(("RX Eye Scan Vcent_UpperBound_Window worse bit\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "RX_Vcent_UpperBound_Window_bit", 0, EyeScanVcentUpperBound_bit, NULL);
+            mcSHOW_DBG_MSG(("RX Eye Scan Vcent_UpperBound Min Window(%%)\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "RX_Vcent_UpperBound_Window(%)", 0, ((EyeScanVcentUpperBound * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000, NULL);
+            mcSHOW_DBG_MSG(("RX Eye Scan Vcent_UpperBound Min Window PASS/FAIL\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT4, "RX_Vcent_UpperBound_Window_PF", 0, 0, ((EyeScanVcentUpperBound * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000 >= 20 ? "PASS" : "FAIL");
+
+            mcSHOW_DBG_MSG(("\n"));
+
+
+            mcSHOW_DBG_MSG(("RX Eye Scan Vcent_LowerBound window\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "RX_Vcent_LowerBound_Window", 0, EyeScanVcentLowerBound, NULL);
+            mcSHOW_DBG_MSG(("RX Eye Scan Vcent_LowerBound_Window worse bit\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "RX_Vcent_LowerBound_Window_bit", 0, EyeScanVcentLowerBound_bit, NULL);
+            mcSHOW_DBG_MSG(("RX Eye Scan Vcent_UpperBound Min Window(%%)\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "RX_Vcent_LowerBound_Window(%)", 0, ((EyeScanVcentLowerBound * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000, NULL);
+            mcSHOW_DBG_MSG(("RX Eye Scan Vcent_LowerBound Min Window PASS/FAIL\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT4, "RX_Vcent_LowerBound_Window_PF", 0, 0, ((EyeScanVcentLowerBound * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000 >= 20 ? "PASS" : "FAIL");
+
+
+            mcSHOW_DBG_MSG(("\n"));
+            mcSHOW_DBG_MSG(("RX Eye Scan per_bit window(%%)\n"));
+            for (u1BitIdx=0; u1BitIdx<p->data_width; u1BitIdx++)
+            {
+#if EYESCAN_LOG
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "RX_Perbit_Window(%)", u1BitIdx, ((gEyeScan_WinSize[EyeScanVcent[0]][u1BitIdx] * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000, NULL);
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "RX_Perbit_BestWindow(%)", u1BitIdx, ((gEyeScan_WinSize[EyeScanVcent[10+u1BitIdx]][u1BitIdx] * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000, NULL);
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "RX_Perbit_Window_Upperbond(%)", u1BitIdx, ((gEyeScan_WinSize[EyeScanVcent[1]][u1BitIdx] * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000, NULL);
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "RX_Perbit_Window_Lowerbond(%) ", u1BitIdx, ((gEyeScan_WinSize[EyeScanVcent[2]][u1BitIdx] * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000, NULL);
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "RX_Perbit_Eye_Height", u1BitIdx, (gEyeScan_ContinueVrefHeight[u1BitIdx]-1)*1330/100, NULL); //RX vref height 1225 ~ 1440, use 1330mv
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "RX_Perbit_Eye_Area", u1BitIdx, gEyeScan_TotalPassCount[u1BitIdx]*u2gdelay_cell_ps_all[get_shuffleIndex_by_Freq(p)][u1ChannelSet[0]]*133/1000, NULL); //total count*jitter metter delay cell*(1/freq*10^6 ps)*(1330mv)
+#endif
+            }
+        }
+    }
+
+	if (gHQALog_flag==1 && print_type==2)
+	{
+        if (u1TXEyeScanEnable)
+        {
+            if (p->dram_type == TYPE_LPDDR4)
+            {
+                pTXVref_Voltage_Table[VREF_RANGE_0] = (U16 *)gVref_Voltage_Table_LP4[VREF_RANGE_0];
+                pTXVref_Voltage_Table[VREF_RANGE_1] = (U16 *)gVref_Voltage_Table_LP4[VREF_RANGE_1];
+            }
+            if (p->dram_type == TYPE_LPDDR4X)
+            {
+                pTXVref_Voltage_Table[VREF_RANGE_0] = (U16 *)gVref_Voltage_Table_LP4X[VREF_RANGE_0];
+                pTXVref_Voltage_Table[VREF_RANGE_1] = (U16 *)gVref_Voltage_Table_LP4X[VREF_RANGE_1];
+            }
+
+            TXVrefRange = (u1MR14Value[p->channel][p->rank][p->dram_fsp]>>6)&1;
+            vddq=vGetVoltage(p, 2)/1000; //mv
+
+            mcSHOW_DBG_MSG(("\n\n\n[HQA] information for measurement, "));
+            mcSHOW_DBG_MSG(("\tDram Data rate = %d\n",p->frequency*2));
+
+            mcSHOW_DBG_MSG(("TX Eye Scan Vcent Voltage\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "TX_Final_Vref Vcent", 0, pTXVref_Voltage_Table[EyeScanVcent[0]][EyeScanVcent[1]]*vddq/100, NULL);
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "TX_VdlVWHigh_Upper Vcent", 0, pTXVref_Voltage_Table[EyeScanVcent[2]][EyeScanVcent[3]]*vddq/100, NULL);
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "TX_VdlVWHigh_Lower Vcent", 0, pTXVref_Voltage_Table[EyeScanVcent[4]][EyeScanVcent[5]]*vddq/100, NULL);
+
+            mcSHOW_DBG_MSG(("\n"));
+
+            mcSHOW_DBG_MSG(("TX Eye Scan Vcent_UpperBound window\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "TX_Vcent_UpperBound_Window", 0, EyeScanVcentUpperBound, NULL);
+            mcSHOW_DBG_MSG(("TX Eye Scan Vcent_UpperBound_Window worse bit\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "TX_Vcent_UpperBound_Window_bit", 0, EyeScanVcentUpperBound_bit, NULL);
+            mcSHOW_DBG_MSG(("TX Eye Scan Vcent_UpperBound Min Window(%%)\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "TX_Vcent_UpperBound_Window(%)", 0, (EyeScanVcentUpperBound * 100 + 31) / 32, NULL);
+            mcSHOW_DBG_MSG(("TX Eye Scan Vcent_UpperBound Min Window PASS/FAIL\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT4, "TX_Vcent_UpperBound_Window_PF", 0, 0, (EyeScanVcentUpperBound * 100 + 31) / 32 >= 20 ? "PASS" : "FAIL");
+
+            mcSHOW_DBG_MSG(("\n"));
+
+            mcSHOW_DBG_MSG(("TX Eye Scan Vcent_LowerBound window\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "TX_Vcent_LowerBound_Window", 0, EyeScanVcentLowerBound, NULL);
+            mcSHOW_DBG_MSG(("TX Eye Scan Vcent_LowerBound_Window worse bit\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "TX_Vcent_LowerBound_Window_bit", 0, EyeScanVcentLowerBound_bit, NULL);
+            mcSHOW_DBG_MSG(("TX Eye Scan Vcent_UpperBound Min Window(%%)\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "TX_Vcent_LowerBound_Window(%)", 0, (EyeScanVcentLowerBound * 100 + 31) / 32, NULL);
+            mcSHOW_DBG_MSG(("TX Eye Scan Vcent_LowerBound Min Window PASS/FAIL\n"));
+                    HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT4, "TX_Vcent_LowerBound_Window_PF", 0, 0, (EyeScanVcentLowerBound * 100 + 31) / 32 >= 20 ? "PASS" : "FAIL");
+
+            mcSHOW_DBG_MSG(("\n"));
+            mcSHOW_DBG_MSG(("TX Eye Scan per_bit window(%%)\n"));
+            for (u1BitIdx=0; u1BitIdx<p->data_width; u1BitIdx++)
+            {
+#if EYESCAN_LOG
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "TX_Perbit_Window(%)", u1BitIdx, ((gEyeScan_WinSize[EyeScanVcent[0]*30+EyeScanVcent[1]][u1BitIdx]) * 100 + 31) / 32, NULL);
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "TX_Perbit_BestWindow(%)", u1BitIdx, ((gEyeScan_WinSize[EyeScanVcent[10+u1BitIdx*2]*30+EyeScanVcent[10+u1BitIdx*2+1]][u1BitIdx]) * 100 + 31) / 32, NULL);
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "TX_Perbit_Window_Upperbond(%)", u1BitIdx, ((gEyeScan_WinSize[EyeScanVcent[2]*30+EyeScanVcent[3]][u1BitIdx]) * 100 + 31) / 32, NULL);
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "TX_Perbit_Window_Lowerbond(%) ", u1BitIdx, ((gEyeScan_WinSize[EyeScanVcent[4]*30+EyeScanVcent[5]][u1BitIdx]) * 100 + 31) / 32, NULL);
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "TX_Perbit_Eye_Height", u1BitIdx, (gEyeScan_ContinueVrefHeight[u1BitIdx]-1)*6*vddq/1000, NULL);
+//                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "TX_Perbit_Eye_Area", u1BitIdx, gEyeScan_TotalPassCount[u1BitIdx]*1000*3*vddq/(32*DDRPhyFMeter()), NULL); //total count*1/32UI*(1/freq*10^6 ps)*(0.6%vddq)
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "TX_Perbit_Eye_Area", u1BitIdx, (gEyeScan_TotalPassCount[u1BitIdx]*10*3*vddq/(32*DDRPhyFMeter()))*100, NULL); //total count*1/32UI*(1/freq*10^6 ps)*(0.6%vddq)
+#endif
+            }
+		}
+    }
+
+	mcSHOW_DBG_MSG(("\n"));
+}
+#endif
+
+
+#ifdef FOR_HQA_REPORT_USED
+void HQA_Log_Message_for_Report(DRAMC_CTX_T *p, U8 u1ChannelIdx, U8 u1RankIdx, U32 who_am_I, U8 *main_str, U8 byte_bit_idx, S32 value1, U8 *ans_str)
+{
+    // HQA_REPORT_FORMAT0 : [HQALOG] 3200 Gating_Center_2T Channel0 Rank0 Byte0 3
+    // HQA_REPORT_FORMAT0_1:[HQALOG] 3200 Gating_Center_2T Channel0 Rank0 Bit0 3
+    // HQA_REPORT_FORMAT0_2:[HQALOG] 3200 Gating_Center_2T Channel0 Rank0 CA0 3
+    // HQA_REPORT_FORMAT1 : [HQALOG] 3200 WriteLeveling_DQS0 Channel0 Rank0 35
+    // HQA_REPORT_FORMAT2 : [HQALOG] 3200 TX_Final_Vref Vcent Channel0 Rank0 16860
+    // HQA_REPORT_FORMAT3 : [HQALOG] 3200 DUTY CLK_MAX Channel0 5171
+    // HQA_REPORT_FORMAT4 : [HQALOG] 3200 TX_Vcent_LowerBound_Window_PF Channel0 Rank0 PASS
+    // HQA_REPORT_FORMAT5 : [HQALOG] 3200 AAAAAAAAAAAA BBBBB
+    // HQA_REPORT_FORMAT6 : [HQALOG] 3200 AAAAAAAAAAAA 0
+
+    if (gHQALog_flag==1)
+    {
+        mcSHOW_DBG_MSG(("[HQALOG] %d %s", p->frequency*2, main_str ));
+        switch (who_am_I)
+        {
+    		case HQA_REPORT_FORMAT1:
+    		     mcSHOW_DBG_MSG(("%d", byte_bit_idx));
+    			break;
+        }
+
+        if (who_am_I == HQA_REPORT_FORMAT3)
+        {
+            mcSHOW_DBG_MSG((" Channel%d ", u1ChannelIdx));
+        }
+        else if (who_am_I != HQA_REPORT_FORMAT5 && who_am_I != HQA_REPORT_FORMAT6)
+        {
+            mcSHOW_DBG_MSG((" Channel%d Rank%d ", u1ChannelIdx, u1RankIdx));
+        }
+
+    	switch (who_am_I)
+    	{
+    		case HQA_REPORT_FORMAT0:
+    			mcSHOW_DBG_MSG(("Byte%d %d\n", byte_bit_idx, value1));
+    			break;
+            case HQA_REPORT_FORMAT0_1:
+    			mcSHOW_DBG_MSG(("Bit%x %d\n", byte_bit_idx, value1));
+                break;
+            case HQA_REPORT_FORMAT0_2:
+    			mcSHOW_DBG_MSG(("CA%x %d\n", byte_bit_idx, value1));
+                break;
+    		case HQA_REPORT_FORMAT1:
+            case HQA_REPORT_FORMAT2:
+            case HQA_REPORT_FORMAT3:
+            case HQA_REPORT_FORMAT6:
+    			mcSHOW_DBG_MSG(("%d\n", value1));
+    			break;
+            case HQA_REPORT_FORMAT4:
+            case HQA_REPORT_FORMAT5:
+                mcSHOW_DBG_MSG((" %s\n", ans_str));
+                break;
+    	}
+    }
+}
+
+#endif
+
+
+#ifdef FOR_HQA_TEST_USED
+#ifdef RELEASE
+#undef mcSHOW_DBG_MSG
+#define mcSHOW_DBG_MSG(_x_)	opt_print _x_
+#endif
+void print_HQA_measure_message(DRAMC_CTX_T *p)
+{
+    U32 uiCA, u1BitIdx, u1RankIdx;
+    U32 min_ca_value[CHANNEL_NUM][RANK_MAX], min_ca_bit[CHANNEL_NUM][RANK_MAX];
+    U32 min_rx_value[CHANNEL_NUM][RANK_MAX], min_tx_value[CHANNEL_NUM][RANK_MAX];
+    U32 min_RX_DQ_bit[CHANNEL_NUM][RANK_MAX], min_TX_DQ_bit[CHANNEL_NUM][RANK_MAX];
+    U8 shuffleIdx, local_channel_num=2, shuffle_index;
+    U8 print_imp_option[2]={FALSE, FALSE};
+    U8 u1ChannelIdx, u1Channel;
+    int i;
+
+    mcSHOW_DBG_MSG(("\n\n\n[HQA] information for measurement, "));
+    mcSHOW_DBG_MSG(("\tDram Data rate = %d\n",p->frequency*2));
+    vPrintCalibrationBasicInfo(p);
+    mcSHOW_DBG_MSG(("[HQALOG] %d Frequency = %u\n", p->frequency*2, DDRPhyFMeter()));
+
+    shuffleIdx = get_shuffleIndex_by_Freq(p);
+
+    if(u1IsLP4Family(p->dram_type))
+    {
+        local_channel_num = p->support_channel_num;
+    }
+#if ENABLE_LP3_SW
+    else
+    {
+        //LP3
+        local_channel_num = 1;
+    }
+#endif
+
+    for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+    {
+        u1ChannelIdx = u1ChannelSet[u1Channel];
+
+        for(u1RankIdx=RANK_0; u1RankIdx<p->support_rank_num; u1RankIdx++)
+        {
+            min_ca_value[u1ChannelIdx][u1RankIdx] = 0xffff;
+            min_rx_value[u1ChannelIdx][u1RankIdx] = 0xffff;
+            min_tx_value[u1ChannelIdx][u1RankIdx] = 0xffff;
+            min_RX_DQ_bit[u1ChannelIdx][u1RankIdx] = 0xffff;
+            min_TX_DQ_bit[u1ChannelIdx][u1RankIdx] = 0xffff;
+
+            for (uiCA=0; uiCA<((u1IsLP4Family(p->dram_type)==1) ? CATRAINING_NUM_LP4 : CATRAINING_NUM_LP3); uiCA++)
+            {
+                if (gFinalCBTCA[u1ChannelIdx][u1RankIdx][uiCA] < min_ca_value[u1ChannelIdx][u1RankIdx])
+                {
+                    min_ca_value[u1ChannelIdx][u1RankIdx] = gFinalCBTCA[u1ChannelIdx][u1RankIdx][uiCA];
+                    min_ca_bit[u1ChannelIdx][u1RankIdx] = uiCA;
+                }
+            }
+
+            for (u1BitIdx=0; u1BitIdx<p->data_width; u1BitIdx++)
+            {
+                if (gFinalRXPerbitWin[u1ChannelIdx][u1RankIdx][u1BitIdx] < min_rx_value[u1ChannelIdx][u1RankIdx])
+                {
+                    min_rx_value[u1ChannelIdx][u1RankIdx] = gFinalRXPerbitWin[u1ChannelIdx][u1RankIdx][u1BitIdx];
+                    min_RX_DQ_bit[u1ChannelIdx][u1RankIdx] = u1BitIdx;
+                }
+                if (gFinalTXPerbitWin[u1ChannelIdx][u1RankIdx][u1BitIdx] < min_tx_value[u1ChannelIdx][u1RankIdx])
+                {
+                    min_tx_value[u1ChannelIdx][u1RankIdx] = gFinalTXPerbitWin[u1ChannelIdx][u1RankIdx][u1BitIdx];
+                    min_TX_DQ_bit[u1ChannelIdx][u1RankIdx] = u1BitIdx;
+                }
+            }
+        }
+    }
+
+
+    if (p->support_rank_num==RANK_DUAL)
+    {
+        //Preloader LP3 RX/TX only K Rank0, so Rank1 use Rank0's value
+        if(!u1IsLP4Family(p->dram_type))
+        {
+#ifndef LP3_DUAL_RANK_RX_K
+            min_rx_value[0][1] = min_rx_value[0][0];
+            min_RX_DQ_bit[0][1] = min_RX_DQ_bit[0][0];
+#endif
+
+#ifndef LP3_DUAL_RANK_TX_K
+            min_tx_value[0][1] = min_tx_value[0][0];
+            gFinalTXPerbitWin_min_max[0][1] = gFinalTXPerbitWin_min_max[0][0];
+            min_TX_DQ_bit[0][1] = min_TX_DQ_bit[0][0];
+#endif
+
+            #if 0//(TX_PER_BIT_DELAY_CELL==0)
+            gFinalTXPerbitWin_min_margin[0][1] = gFinalTXPerbitWin_min_margin[0][0];
+            gFinalTXPerbitWin_min_margin_bit[0][1] = gFinalTXPerbitWin_min_margin_bit[0][0];
+            #endif
+        }
+    }
+
+
+#if defined(DRAM_HQA)
+        mcSHOW_DBG_MSG(("[Read Voltage]\n"));
+    mcSHOW_DBG_MSG(("[HQALOG] %d Vcore_HQA = %d\n", p->frequency*2, vGetVoltage(p, 0)));
+
+        if (u1IsLP4Family(p->dram_type)) {
+            /* LPDDR4 */
+        mcSHOW_DBG_MSG(("[HQALOG] %d Vdram_HQA = %d\n", p->frequency*2, vGetVoltage(p, 1)));
+        mcSHOW_DBG_MSG(("[HQALOG] %d Vddq_HQA = %d\n", p->frequency*2, vGetVoltage(p, 2)));
+        mcSHOW_DBG_MSG(("[HQALOG] %d Vdd1_HQA = %d\n", p->frequency*2, vGetVoltage(p, 3)));
+        } else {
+            /* LPDDR3 */
+        mcSHOW_DBG_MSG(("[HQALOG] %d Vdram_HQA = %d\n", p->frequency*2, vGetVoltage(p, 1)));
+        mcSHOW_DBG_MSG(("[HQALOG] %d Vdd1_HQA = %d\n", p->frequency*2, vGetVoltage(p, 3)));
+        }
+        mcSHOW_DBG_MSG(("\n"));
+#endif
+
+    /*
+        [Impedance Calibration]
+
+        term_option=0
+        [HQALOG] Impedance term_option=0 DRVP 11
+        [HQALOG] Impedance term_option=0 DRVN 7
+
+        term_option=1
+        [HQALOG] Impedance term_option=1 DRVP 13
+        [HQALOG] Impedance term_option=1 ODTN 15
+    */
+    if (p->dram_type == TYPE_LPDDR4)
+    {
+        print_imp_option[1] = TRUE;
+    }
+    else if (p->dram_type == TYPE_LPDDR4X)
+    {
+        print_imp_option[0] = TRUE;
+        print_imp_option[1] = TRUE;
+    }
+    else
+    {
+      //TYPE_LPDDR4P, TYPE_LPDDR3
+      print_imp_option[0] = TRUE;
+    }
+
+#ifdef FOR_HQA_REPORT_USED
+if (gHQALog_flag==1)
+{
+    mcSHOW_DBG_MSG(("[Impedance Calibration]\n"));
+    for(i=0; i<2; i++)
+    {
+        mcSHOW_DBG_MSG(("term_option=%d\n", i));
+        if (print_imp_option[i]==FALSE || (print_imp_option[i]==TRUE && p->odt_onoff==ODT_OFF && i==1) || (print_imp_option[i]==TRUE && p->odt_onoff==ODT_ON && i==0))
+    {
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT5, i==0 ? "Impedance term_option=0 DRVP" : "Impedance term_option=1 DRVP", 0, 0, "NA");
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT5, i==0 ? "Impedance term_option=0 DRVN" : "Impedance term_option=1 ODTN", 0, 0, "NA");
+    }
+        else
+    {
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT6, i==0 ? "Impedance term_option=0 DRVP" : "Impedance term_option=1 DRVP", 0, gDramcSwImpedanceResule[i][DRVP], NULL);
+                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT6, i==0 ? "Impedance term_option=0 DRVN" : "Impedance term_option=1 ODTN", 0, i==0 ? gDramcSwImpedanceResule[i][DRVN] : gDramcSwImpedanceResule[i][ODTN], NULL);
+        }
+    }
+    mcSHOW_DBG_MSG(("\n"));
+}
+#endif
+
+
+
+
+if(u1IsLP4Family(p->dram_type))
+{
+    mcSHOW_DBG_MSG(("\n[Cmd Bus Training window]\n"));
+    if(u1IsLP4Family(p->dram_type))
+    {
+        mcSHOW_DBG_MSG(("VrefCA Range : %d\n", gCBT_VREF_RANGE_SEL));
+        /*
+         VrefCA
+             [HQALOG] 1600 VrefCA Channel0 Rank0 32
+             [HQALOG] 1600 VrefCA Channel0 Rank1 24
+             [HQALOG] 1600 VrefCA Channel1 Rank0 26
+             [HQALOG] 1600 VrefCA Channel1 Rank1 30
+         */
+        mcSHOW_DBG_MSG(("VrefCA\n"));
+        for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+        {
+            u1ChannelIdx = u1ChannelSet[u1Channel];
+
+            for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+            {
+                mcSHOW_DBG_MSG(("[HQALOG] %d VrefCA Channel%d "
+                                "Rank%d %d\n",
+                                p->frequency*2,
+                            u1ChannelIdx,
+                                u1RankIdx,
+                                gFinalCBTVrefCA[u1ChannelIdx][u1RankIdx]));
+            }
+        }
+    }
+
+#if 0//(SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_CBT)
+    if(p->femmc_Ready==1 )
+    {
+        mcSHOW_DBG_MSG(("\n[Cmd Bus Training window bypass calibration]\n"));
+    }
+    else
+#endif
+    {
+        /*
+         CA_Window
+             [HQALOG] 1600 CA_Window Channel0 Rank0 61(bit 2)
+             [HQALOG] 1600 CA_Window Channel0 Rank1 62(bit 1)
+             [HQALOG] 1600 CA_Window Channel1 Rank0 60(bit 5)
+             [HQALOG] 1600 CA_Window Channel1 Rank1 60(bit 5)
+         */
+        mcSHOW_DBG_MSG(("CA_Window\n"));
+#ifdef FOR_HQA_REPORT_USED
+if (gHQALog_flag==1)
+{
+        for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+        {
+            u1ChannelIdx = u1ChannelSet[u1Channel];
+
+            for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+            {
+                    HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT2, "CA_Window", 0, min_ca_value[u1ChannelIdx][u1RankIdx], NULL);
+                    HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT2, "CA_Window_bit", 0, min_ca_bit[u1ChannelIdx][u1RankIdx], NULL);
+            }
+        }
+        mcSHOW_DBG_MSG(("\n"));
+}
+else
+#endif
+{
+        for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+        {
+            u1ChannelIdx = u1ChannelSet[u1Channel];
+
+            for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+            {
+                mcSHOW_DBG_MSG(("[HQALOG] %d CA_Window Channel%d "
+                                "Rank%d %d (bit %d)\n",
+                                p->frequency*2,
+                                u1ChannelIdx,
+                                u1RankIdx,
+                                min_ca_value[u1ChannelIdx][u1RankIdx], min_ca_bit[u1ChannelIdx][u1RankIdx]));
+            }
+        }
+}
+
+        /*
+         CA Min Window(%)
+             [HQALOG] 1600 CA_Window(%) Channel0 Rank0 96%(PASS)
+             [HQALOG] 1600 CA_Window(%) Channel0 Rank1 97%(PASS)
+             [HQALOG] 1600 CA_Window(%) Channel1 Rank0 94%(PASS)
+             [HQALOG] 1600 CA_Window(%) Channel1 Rank1 94%(PASS)
+         */
+        mcSHOW_DBG_MSG(("CA Min Window(%%)\n"));
+#ifdef FOR_HQA_REPORT_USED
+if (gHQALog_flag==1)
+{
+        for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+        {
+            u1ChannelIdx = u1ChannelSet[u1Channel];
+
+            for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+            {
+                HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT2, "CA_Window(%)", 0, ((min_ca_value[u1ChannelIdx][u1RankIdx] * 100 + (u1IsLP4Family(p->dram_type)==1?63:31)) / (u1IsLP4Family(p->dram_type)==1?64:32)), NULL);
+                HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT4, "CA_Window_PF", 0, 0, ((((min_ca_value[u1ChannelIdx][u1RankIdx] * 100 + (u1IsLP4Family(p->dram_type)==1?63:31)) / (u1IsLP4Family(p->dram_type)==1?64:32)) >= 30) ? "PASS" : "FAIL"));
+            }
+        }
+        mcSHOW_DBG_MSG(("\n"));
+}
+else
+#endif
+{
+        for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+        {
+            u1ChannelIdx = u1ChannelSet[u1Channel];
+
+            for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+            {
+                mcSHOW_DBG_MSG(("[HQALOG] %d CA_Window(%%) Channel%d "
+                                "Rank%d %d%% (%s)\n",
+                                p->frequency*2,
+                                u1ChannelIdx,
+                                u1RankIdx,
+                                        ((min_ca_value[u1ChannelIdx][u1RankIdx] * 100 + (u1IsLP4Family(p->dram_type)==1?63:31)) / (u1IsLP4Family(p->dram_type)==1?64:32)),
+                                    ((((min_ca_value[u1ChannelIdx][u1RankIdx] * 100 + (u1IsLP4Family(p->dram_type)==1?63:31)) / (u1IsLP4Family(p->dram_type)==1?64:32)) >= 30) ? "PASS" : "FAIL")));
+            }
+        }
+}
+    }
+            mcSHOW_DBG_MSG(("\n"));
+}
+
+
+    /*
+    [RX minimum per bit window]
+    Delay cell measurement (/100ps)
+    [HQALOG] 3200 delaycell 892
+    */
+    mcSHOW_DBG_MSG(("\n[RX minimum per bit window]\n"));
+    mcSHOW_DBG_MSG(("Delaycell measurement(/100ps)\n"));
+#if !defined(RELEASE) && (VENDER_JV_LOG==0)
+    mcSHOW_DBG_MSG(("[HQALOG] %d delaycell %d\n",
+                    p->frequency*2,
+                    u2gdelay_cell_ps_all[shuffleIdx][u1ChannelSet[0]]));
+#endif
+    /*
+     VrefDQ
+         [HQALOG] 1600 VrefRX Channel0 24
+         [HQALOG] 1600 VrefRX Channel1 24
+     */
+
+    if(u1IsLP4Family(p->dram_type))
+    {
+        if (p->enable_rx_scan_vref == ENABLE)
+        {
+            mcSHOW_DBG_MSG(("VrefRX\n"));
+            if (gRX_EYE_Scan_flag==1)
+            {
+                for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+                {
+                    u1ChannelIdx = u1ChannelSet[u1Channel];
+
+                    for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+                    {
+                        mcSHOW_DBG_MSG(("[HQALOG] %d VrefRX Channel%d Rank%d %d\n",
+                                        p->frequency*2,
+                                        u1ChannelIdx,
+                                        u1RankIdx,
+                                        gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx]));
+                    }
+                }
+            }
+            else
+            {
+                for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+                {
+                    u1ChannelIdx = u1ChannelSet[u1Channel];
+
+                    mcSHOW_DBG_MSG(("[HQALOG] %d VrefRX Channel%d %d\n",
+                                    p->frequency*2,
+                                    u1ChannelIdx,
+                                    gFinalRXVrefDQ[u1ChannelIdx][RANK_0]));
+                }
+            }
+        }
+        else
+        {
+            mcSHOW_DBG_MSG(("RX DQ Vref Scan : Disable\n"));
+        }
+    }
+
+#if 0//(SUPPORT_SAVE_TIME_FOR_CALIBRATION )
+    if(p->femmc_Ready==1 && ( p->Bypass_RXWINDOW))
+ 	{
+        mcSHOW_DBG_MSG(("\n[RX minimum per bit window bypass calibration]\n"));
+ 	}
+    else
+#endif
+    {
+        /*
+         RX_Window
+             [HQALOG] 1600 RX_Window Channel0 Rank0 52(bit 2)
+             [HQALOG] 1600 RX_Window Channel0 Rank1 52(bit 2)
+             [HQALOG] 1600 RX_Window Channel1 Rank0 60(bit 12)
+             [HQALOG] 1600 RX_Window Channel1 Rank1 62(bit 9)
+         */
+        mcSHOW_DBG_MSG(("RX_Window\n"));
+#ifdef FOR_HQA_REPORT_USED
+if (gHQALog_flag==1)
+{
+        for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+        {
+            u1ChannelIdx = u1ChannelSet[u1Channel];
+
+            for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+            {
+                    HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT2, "RX_Window", 0, min_rx_value[u1ChannelIdx][u1RankIdx], NULL);
+                    HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT2, "RX_Window_bit", 0, min_RX_DQ_bit[u1ChannelIdx][u1RankIdx], NULL);
+            }
+        }
+}
+else
+#endif
+{
+        for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+        {
+            u1ChannelIdx = u1ChannelSet[u1Channel];
+
+            for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+            {
+                mcSHOW_DBG_MSG(("[HQALOG] %d RX_Window Channel%d "
+                                "Rank%d %d (bit %d)\n",
+                                p->frequency*2,
+                            u1ChannelIdx,
+                                u1RankIdx,
+                                min_rx_value[u1ChannelIdx][u1RankIdx], min_RX_DQ_bit[u1ChannelIdx][u1RankIdx]));
+            }
+        }
+}
+
+        /*
+         RX Min Window(%)
+             [HQALOG] 1600 RX_Window(%) Channel0 Rank0 43316/100ps(70%)(PASS)
+             [HQALOG] 1600 RX_Window(%) Channel0 Rank1 43316/100ps(70%)(PASS)
+             [HQALOG] 1600 RX_Window(%) Channel1 Rank0 49980/100ps(80%)(PASS)
+             [HQALOG] 1600 RX_Window(%) Channel1 Rank1 51646/100ps(83%)(PASS)
+         */
+        mcSHOW_DBG_MSG(("RX Window(%%)\n"));
+#ifdef FOR_HQA_REPORT_USED
+if (gHQALog_flag==1)
+{
+        for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+        {
+            u1ChannelIdx = u1ChannelSet[u1Channel];
+
+            for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+            {
+                    HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT2, "RX_Window(%)", 0, ((min_rx_value[u1ChannelIdx][u1RankIdx] * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000, NULL);
+                    HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT4, "RX_Window_PF", 0, 0, (min_rx_value[u1ChannelIdx][u1RankIdx] * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) / 1000000 >= 40 ? "PASS" : "FAIL");
+            }
+        }
+}
+else
+#endif
+{
+        for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+        {
+            u1ChannelIdx = u1ChannelSet[u1Channel];
+
+            for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+            {
+                mcSHOW_DBG_MSG(("[HQALOG] %d RX_Window(%%) Channel%d "
+                                "Rank%d "
+                                "%d/100ps (%d%%) (%s)\n",
+                                p->frequency*2,
+                                u1ChannelIdx,
+                                u1RankIdx,
+                                min_rx_value[u1ChannelIdx][u1RankIdx] * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx],
+                                ((min_rx_value[u1ChannelIdx][u1RankIdx] * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000,
+                                ((min_rx_value[u1ChannelIdx][u1RankIdx] * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000 >= 40 ? "PASS" : "FAIL"));
+            }
+        }
+}
+
+        mcSHOW_DBG_MSG(("\n"));
+    }
+
+
+
+
+
+
+    /* [TX minimum per bit window]
+     VrefDQ Range : 1
+     VrefDQ
+         [HQALOG] 1600 VrefTX Channel0 Rank0 30
+         [HQALOG] 1600 VrefTX Channel0 Rank1 25
+         [HQALOG] 1600 VrefTX Channel1 Rank0 24
+         [HQALOG] 1600 VrefTX Channel1 Rank1 23
+     */
+    mcSHOW_DBG_MSG(("\n[TX minimum per bit window]\n"));
+    if(u1IsLP4Family(p->dram_type))
+    {
+        if (p->enable_tx_scan_vref == ENABLE_VREF_SCAN)
+        {
+            mcSHOW_DBG_MSG(("VrefDQ Range : %d\n",(u1MR14Value[p->channel][p->rank][p->dram_fsp]>>6)&1));
+            mcSHOW_DBG_MSG(("VrefDQ\n"));
+            for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+            {
+                u1ChannelIdx = u1ChannelSet[u1Channel];
+
+                for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+                {
+                    mcSHOW_DBG_MSG(("[HQALOG] %d VrefDQ Channel%d "
+                                    "Rank%d %d\n",
+                                    p->frequency*2,
+                                    u1ChannelIdx,
+                                    u1RankIdx,
+                                    gFinalTXVrefDQ[u1ChannelIdx][u1RankIdx]));
+                }
+            }
+        }
+        else
+        {
+            mcSHOW_DBG_MSG(("TX DQ Vref Scan : Disable\n"));
+        }
+    }
+#if 0//(SUPPORT_SAVE_TIME_FOR_CALIBRATION )
+    if(p->femmc_Ready==1 && (p->Bypass_TXWINDOW))
+ 	{
+        mcSHOW_DBG_MSG(("\n[TX minimum per bit window bypass calibration]\n"));
+ 	}
+    else
+#endif
+    {
+        /*
+         TX_Window
+             [HQALOG] 1600 TX_Window Channel0 Rank0 25(bit 2)
+             [HQALOG] 1600 TX_Window Channel0 Rank1 25(bit 2)
+             [HQALOG] 1600 TX_Window Channel1 Rank0 22(bit 9)
+             [HQALOG] 1600 TX_Window Channel1 Rank1 23(bit 9)
+         */
+        mcSHOW_DBG_MSG(("TX_Window\n"));
+#ifdef FOR_HQA_REPORT_USED
+if (gHQALog_flag==1)
+{
+        for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+        {
+            u1ChannelIdx = u1ChannelSet[u1Channel];
+
+            for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+            {
+                    HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT2, "TX_Window", 0, gFinalTXPerbitWin_min_max[u1ChannelIdx][u1RankIdx], NULL);
+                    HQA_Log_Message_for_Report(p,u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT2, "TX_Window_bit", 0, min_TX_DQ_bit[u1ChannelIdx][u1RankIdx], NULL);
+            }
+        }
+}
+else
+#endif
+{
+        for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+        {
+            u1ChannelIdx = u1ChannelSet[u1Channel];
+
+            for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+            {
+                mcSHOW_DBG_MSG(("[HQALOG] %d TX_Window Channel%d "
+                                "Rank%d %d (bit %d)\n",
+                                p->frequency*2,
+                                u1ChannelIdx,
+                                u1RankIdx,
+                                gFinalTXPerbitWin_min_max[u1ChannelIdx][u1RankIdx], min_TX_DQ_bit[u1ChannelIdx][u1RankIdx]));
+            }
+        }
+}
+#if 0//(TX_PER_BIT_DELAY_CELL==0)
+        mcSHOW_DBG_MSG(("min DQ margin\n"));
+        for(u1ChannelIdx=CHANNEL_A; u1ChannelIdx<local_channel_num; u1ChannelIdx++)
+        {
+            for(u1RankIdx = RANK_0; u1RankIdx < 2; u1RankIdx++)
+            {
+                mcSHOW_DBG_MSG(("[HQALOG] %d min_DQ_margin Channel%d "
+                                "Rank%d %d (bit %d)\n",
+                                p->frequency*2,
+                                u1ChannelIdx,
+                                u1RankIdx,
+                                gFinalTXPerbitWin_min_margin[u1ChannelIdx][u1RankIdx], gFinalTXPerbitWin_min_margin_bit[u1ChannelIdx][u1RankIdx]));
+            }
+        }
+#endif
+
+
+        /*
+         TX Min Window(%)
+             [HQALOG] 1600 TX_Window(%) Channel0 Rank0 79%(PASS)
+             [HQALOG] 1600 TX_Window(%) Channel0 Rank1 79%(PASS)
+             [HQALOG] 1600 TX_Window(%) Channel1 Rank0 69%(PASS)
+             [HQALOG] 1600 TX_Window(%) Channel1 Rank1 72%(PASS)
+         */
+        mcSHOW_DBG_MSG(("TX Min Window(%%)\n"));
+#ifdef FOR_HQA_REPORT_USED
+if (gHQALog_flag==1)
+{
+        for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+        {
+            u1ChannelIdx = u1ChannelSet[u1Channel];
+
+            for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+            {
+                HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT2, "TX_Window(%)", 0, (min_tx_value[u1ChannelIdx][u1RankIdx] * 100 + 31) / (u1IsLP4Family(p->dram_type)==1?32:64), NULL);
+                HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT4, "TX_Window_PF", 0, 0, (min_tx_value[u1ChannelIdx][u1RankIdx] * 100 + 31) / (u1IsLP4Family(p->dram_type)==1?32:64) >= 45 ? "PASS" : "FAIL");
+            }
+        }
+}
+else
+#endif
+{
+        for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+        {
+            u1ChannelIdx = u1ChannelSet[u1Channel];
+
+            for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+            {
+                mcSHOW_DBG_MSG(("[HQALOG] %d TX_Window(%%) Channel%d "
+                                "Rank%d %d%% (%s)\n",
+                                p->frequency*2,
+                                u1ChannelIdx,
+                                u1RankIdx,
+                               (min_tx_value[u1ChannelIdx][u1RankIdx] * 100 + 31) / (u1IsLP4Family(p->dram_type)==1?32:64),
+                               (min_tx_value[u1ChannelIdx][u1RankIdx] * 100 + 31) / (u1IsLP4Family(p->dram_type)==1?32:64) >= 45 ? "PASS" : "FAIL"));
+            }
+        }
+}
+
+        mcSHOW_DBG_MSG(("\n"));
+    }
+
+
+
+        /*
+            [Duty Calibration]
+            CLK Duty Final Delay Cell
+            [HQALOG] DUTY CLK_Final_Delay Channel0 0
+            [HQALOG] DUTY CLK_Final_Delay Channel1 -2
+        */
+#if !defined(RELEASE) && (VENDER_JV_LOG==0)
+    if (u1IsLP4Family(p->dram_type))
+    {
+        mcSHOW_DBG_MSG(("[duty Calibration]\n"));
+        mcSHOW_DBG_MSG(("CLK Duty Final Delay Cell\n"));
+        for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+        {
+            u1ChannelIdx = u1ChannelSet[u1Channel];
+            mcSHOW_DBG_MSG(("[HQALOG] %d DUTY CLK_Final_Delay Channel%d %d\n", p->frequency*2, u1ChannelIdx, gFinalClkDuty[u1ChannelIdx]));
+        }
+
+        /*
+            CLK Duty MAX
+            [HQALOG] DUTY CLK_MAX Channel0 4765%(X100)
+            [HQALOG] DUTY CLK_MAX Channel1 5212%(X100)
+        */
+        mcSHOW_DBG_MSG(("CLK Duty MAX\n"));
+        for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+        {
+            u1ChannelIdx = u1ChannelSet[u1Channel];
+#ifdef FOR_HQA_REPORT_USED
+                if (gHQALog_flag==1)
+                {
+                    HQA_Log_Message_for_Report(p, u1ChannelIdx, 0, HQA_REPORT_FORMAT3, "DUTY CLK_MAX", 0, gFinalClkDutyMinMax[u1ChannelIdx][1], NULL);
+                }
+                else
+#endif
+                {
+                    mcSHOW_DBG_MSG(("[HQALOG] %d DUTY CLK_MAX Channel%d %d%%(X100)\n", p->frequency*2, u1ChannelIdx, gFinalClkDutyMinMax[u1ChannelIdx][1]));
+                }
+        }
+
+        /*
+            CLK Duty MIN
+            [HQALOG] DUTY CLK_MIN Channel0 4565%(X100)
+            [HQALOG] DUTY CLK_MIN Channel1 5012%(X100)
+        */
+        mcSHOW_DBG_MSG(("CLK Duty MIN\n"));
+        for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+        {
+            u1ChannelIdx = u1ChannelSet[u1Channel];
+#ifdef FOR_HQA_REPORT_USED
+            if (gHQALog_flag==1)
+            {
+                HQA_Log_Message_for_Report(p, u1ChannelIdx, 0, HQA_REPORT_FORMAT3, "DUTY CLK_MIN", 0, gFinalClkDutyMinMax[u1ChannelIdx][0], NULL);
+                HQA_Log_Message_for_Report(p, u1ChannelIdx, 0, HQA_REPORT_FORMAT3, "DUTY CLK_MAX-MIN", 0, gFinalClkDutyMinMax[u1ChannelIdx][1]-gFinalClkDutyMinMax[u1ChannelIdx][0], NULL);
+            }
+            else
+#endif
+            {
+                mcSHOW_DBG_MSG(("[HQALOG] %d DUTY CLK_MIN Channel%d %d%%(X100)\n", p->frequency*2, u1ChannelIdx, gFinalClkDutyMinMax[u1ChannelIdx][0]));
+            }
+        }
+
+        mcSHOW_DBG_MSG(("\n"));
+    }
+
+
+
+
+    /*
+        DQS Duty Final Delay Cell
+        [HQALOG] DUTY DQS_Final_Delay Channel0 DQS0 0
+        [HQALOG] DUTY DQS_Final_Delay Channel0 DQS1 1
+        [HQALOG] DUTY DQS_Final_Delay Channel1 DQS0 -2
+        [HQALOG] DUTY DQS_Final_Delay Channel1 DQS1 -1
+    */
+    if (u1IsLP4Family(p->dram_type))
+    {
+        mcSHOW_DBG_MSG(("DQS Duty Final Delay Cell\n"));
+        for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+        {
+            u1ChannelIdx = u1ChannelSet[u1Channel];
+
+            if (p->frequency == u2DFSGetHighestFreq(p))
+            {
+                mcSHOW_DBG_MSG(("[HQALOG] %d DUTY DQS_Final_Delay Channel%d DQS0 %d\n", p->frequency*2, u1ChannelIdx, gFinalDQSDuty[u1ChannelIdx][0]));
+                mcSHOW_DBG_MSG(("[HQALOG] %d DUTY DQS_Final_Delay Channel%d DQS1 %d\n", p->frequency*2, u1ChannelIdx, gFinalDQSDuty[u1ChannelIdx][1]));
+            }
+        }
+
+        /*
+            DQS Duty MAX
+            [HQALOG] DUTY DQS_MAX Channel0 DQS0 4765%(X100)
+            [HQALOG] DUTY DQS_MAX Channel0 DQS1 5212%(X100)
+            [HQALOG] DUTY DQS_MAX Channel1 DQS0 4765%(X100)
+            [HQALOG] DUTY DQS_MAX Channel1 DQS1 5212%(X100)
+        */
+        mcSHOW_DBG_MSG(("DQS Duty MAX\n"));
+        for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+        {
+            u1ChannelIdx = u1ChannelSet[u1Channel];
+#ifdef FOR_HQA_REPORT_USED
+                if (gHQALog_flag==1)
+                {
+                    HQA_Log_Message_for_Report(p, u1ChannelIdx, 0, HQA_REPORT_FORMAT0, "DUTY DQS_MAX", 0, gFinalDQSDutyMinMax[u1ChannelIdx][0][1], NULL);
+                    HQA_Log_Message_for_Report(p,u1ChannelIdx, 0, HQA_REPORT_FORMAT0, "DUTY DQS_MAX", 1, gFinalDQSDutyMinMax[u1ChannelIdx][1][1], NULL);
+                }
+                else
+#endif
+                {
+                    mcSHOW_DBG_MSG(("[HQALOG] %d DUTY DQS_MAX Channel%d DQS0 %d%%(X100)\n", p->frequency*2, u1ChannelIdx, gFinalDQSDutyMinMax[u1ChannelIdx][0][1]));
+                    mcSHOW_DBG_MSG(("[HQALOG] %d DUTY DQS_MAX Channel%d DQS1 %d%%(X100)\n", p->frequency*2, u1ChannelIdx, gFinalDQSDutyMinMax[u1ChannelIdx][1][1]));
+                }
+        }
+
+        /*
+            DQS Duty MIN
+            [HQALOG] DUTY DQS_MIN Channel0 DQS0 4765%(X100)
+            [HQALOG] DUTY DQS_MIN Channel0 DQS1 5212%(X100)
+            [HQALOG] DUTY DQS_MIN Channel1 DQS0 4765%(X100)
+            [HQALOG] DUTY DQS_MIN Channel1 DQS1 5212%(X100)
+        */
+        mcSHOW_DBG_MSG(("DQS Duty MIN\n"));
+        for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+        {
+            u1ChannelIdx = u1ChannelSet[u1Channel];
+#ifdef FOR_HQA_REPORT_USED
+            if (gHQALog_flag==1)
+            {
+                HQA_Log_Message_for_Report(p, u1ChannelIdx, 0, HQA_REPORT_FORMAT0, "DUTY DQS_MIN", 0, gFinalDQSDutyMinMax[u1ChannelIdx][0][0], NULL);
+                HQA_Log_Message_for_Report(p, u1ChannelIdx, 0, HQA_REPORT_FORMAT0, "DUTY DQS_MIN", 1, gFinalDQSDutyMinMax[u1ChannelIdx][1][0], NULL);
+                HQA_Log_Message_for_Report(p, u1ChannelIdx, 0, HQA_REPORT_FORMAT0, "DUTY DQS_MAX-MIN", 0, gFinalDQSDutyMinMax[u1ChannelIdx][0][1]-gFinalDQSDutyMinMax[u1ChannelIdx][0][0], NULL);
+                HQA_Log_Message_for_Report(p, u1ChannelIdx, 0, HQA_REPORT_FORMAT0, "DUTY DQS_MAX-MIN", 1, gFinalDQSDutyMinMax[u1ChannelIdx][1][1]-gFinalDQSDutyMinMax[u1ChannelIdx][1][0], NULL);
+            }
+            else
+#endif
+            {
+                mcSHOW_DBG_MSG(("[HQALOG] %d DUTY DQS_MIN Channel%d DQS0 %d%%(X100)\n", p->frequency*2, u1ChannelIdx, gFinalDQSDutyMinMax[u1ChannelIdx][0][0]));
+                mcSHOW_DBG_MSG(("[HQALOG] %d DUTY DQS_MIN Channel%d DQS1 %d%%(X100)\n", p->frequency*2, u1ChannelIdx, gFinalDQSDutyMinMax[u1ChannelIdx][1][0]));
+            }
+        }
+
+        mcSHOW_DBG_MSG(("\n"));
+    }
+#endif
+
+
+
+
+
+
+
+
+
+
+
+    #if defined(ENABLE_MIOCK_JMETER) && !defined(RELEASE)
+    //if(p->frequency == u2DFSGetHighestFreq(p))
+    {
+        if(u1IsLP4Family(p->dram_type))	//LP4 Series
+        {
+            mcSHOW_DBG_MSG(("\n[DramcMiockJmeter]\n"
+                        "Channel\tVCORE\t\t1 delay cell\n"));
+
+            for(shuffle_index=DRAM_DFS_SHUFFLE_1; shuffle_index<DRAM_DFS_SHUFFLE_MAX; shuffle_index++)
+            {
+                mcSHOW_DBG_MSG(("\nSHUFFLE %d\n", shuffle_index+1));
+
+                for (u1Channel = 0; u1Channel < local_channel_num; u1Channel++)
+                {
+                    u1ChannelIdx = u1ChannelSet[u1Channel];
+                    mcSHOW_DBG_MSG(("CH%d\t%d\t\t%d/100 ps\n", u1ChannelIdx, u4gVcore[shuffle_index], u2gdelay_cell_ps_all[shuffle_index][u1ChannelIdx]));
+                }
+            }
+        }
+    }
+    #endif
+
+    mcSHOW_DBG_MSG(("\n\n\n"));
+
+
+
+#if VENDER_JV_LOG
+    mcSHOW_DBG_MSG5(("\n\n\n[Summary] information for measurement\n"));
+    //mcSHOW_DBG_MSG5(("\tDram Data rate = %d\n",p->frequency*2));
+    vPrintCalibrationBasicInfo_ForJV(p);
+
+    if(u1IsLP4Family(p->dram_type))
+     {
+         mcSHOW_DBG_MSG5(("[Cmd Bus Training window]\n"));
+         mcSHOW_DBG_MSG5(("VrefCA Range : %d\n", gCBT_VREF_RANGE_SEL));
+#if CHANNEL_NUM==4
+        mcSHOW_DBG_MSG5(("CHA_VrefCA_Rank0   CHB_VrefCA_Rank0   CHC_VrefCA_Rank0    CHD_VrefCA_Rank0\n"));
+        mcSHOW_DBG_MSG5(("%d                 %d                 %d                  %d\n", gFinalCBTVrefCA[0][0], gFinalCBTVrefCA[1][0], gFinalCBTVrefCA[2][0], gFinalCBTVrefCA[3][0]));
+#else
+         mcSHOW_DBG_MSG5(("CHA_VrefCA_Rank0   CHB_VrefCA_Rank0\n"));
+         mcSHOW_DBG_MSG5(("%d                 %d\n", gFinalCBTVrefCA[0][0], gFinalCBTVrefCA[1][0]));
+#endif
+         mcSHOW_DBG_MSG5(("CHA_CA_window_Rank0   CHB_CA_winow_Rank0\n"));
+         mcSHOW_DBG_MSG5(("%d%%(bit %d)              %d%%(bit %d) \n\n",(min_ca_value[0][0]*100+63)/64, min_ca_bit[0][0],
+                                                                     (min_ca_value[1][0]*100+63)/64, min_ca_bit[1][0]));
+     }
+#if 0
+     else
+     {
+         mcSHOW_DBG_MSG5(("[CA Training window]\n"));
+         mcSHOW_DBG_MSG5(("CHA_CA_win_Rank0\n"));
+         mcSHOW_DBG_MSG5(("%d%%(bit %d)\n\n",(min_ca_value[0][0]*100+63)/64, min_ca_bit[0][0]));
+     }
+#endif
+
+     mcSHOW_DBG_MSG5(("[RX minimum per bit window]\n"));
+     if (p->enable_rx_scan_vref == ENABLE)
+     {
+#if CHANNEL_NUM==4
+        mcSHOW_DBG_MSG5(("CHA_VrefDQ    CHB_VrefDQ      CHC_VrefDQ      CHD_VrefDQ\n"));
+        mcSHOW_DBG_MSG5(("%d            %d              %d              %d \n", gFinalRXVrefDQ[CHANNEL_A][RANK_0], gFinalRXVrefDQ[CHANNEL_B][RANK_0], gFinalRXVrefDQ[CHANNEL_C][RANK_0], gFinalRXVrefDQ[CHANNEL_D][RANK_0]));
+#else
+         mcSHOW_DBG_MSG5(("CHA_VrefDQ   CHB_VrefDQ\n"));
+         mcSHOW_DBG_MSG5(("%d                 %d \n", gFinalRXVrefDQ[CHANNEL_A][RANK_0], gFinalRXVrefDQ[CHANNEL_B][RANK_0]));
+#endif
+     }
+     else
+     {
+         mcSHOW_DBG_MSG5(("RX DQ Vref Scan : Disable\n"));
+
+     }
+
+    if(u1IsLP4Family(p->dram_type))
+    {
+#if CHANNEL_NUM==4
+    mcSHOW_DBG_MSG5(("CHA_Rank0           CHA_Rank1           CHB_Rank0           CHB_Rank1         CHC_Rank0       CHC_Rank1       CHD_Rank0       CHD_Rank1\n"));
+    mcSHOW_DBG_MSG5(("%d%%(bit %d)         %d%%(bit %d)         %d%%(bit %d)         %d%%(bit %d)         %d%%(bit %d)         %d%%(bit %d)         %d%%(bit %d)         %d%%(bit %d)\n\n",
+                                    ((min_rx_value[0][0]*u2gdelay_cell_ps_all[shuffleIdx][0]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[0][0],
+                                    ((min_rx_value[0][1]*u2gdelay_cell_ps_all[shuffleIdx][0]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[0][1],
+                                    ((min_rx_value[1][0]*u2gdelay_cell_ps_all[shuffleIdx][1]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[1][0],
+                                    ((min_rx_value[1][1]*u2gdelay_cell_ps_all[shuffleIdx][1]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[1][1],
+                                    ((min_rx_value[2][0]*u2gdelay_cell_ps_all[shuffleIdx][2]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[2][0],
+                                    ((min_rx_value[2][1]*u2gdelay_cell_ps_all[shuffleIdx][2]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[2][1],
+                                    ((min_rx_value[3][0]*u2gdelay_cell_ps_all[shuffleIdx][3]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[3][0],
+                                    ((min_rx_value[3][1]*u2gdelay_cell_ps_all[shuffleIdx][3]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[3][1]));
+#else
+     mcSHOW_DBG_MSG5(("CHA_Rank0           CHA_Rank1           CHB_Rank0           CHB_Rank1\n"));
+     mcSHOW_DBG_MSG5(("%d%%(bit %d)         %d%%(bit %d)         %d%%(bit %d)         %d%%(bit %d)\n\n",
+                                     ((min_rx_value[0][0]*u2gdelay_cell_ps_all[shuffleIdx][0]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[0][0],
+                                     ((min_rx_value[0][1]*u2gdelay_cell_ps_all[shuffleIdx][0]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[0][1],
+                                     ((min_rx_value[1][0]*u2gdelay_cell_ps_all[shuffleIdx][1]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[1][0],
+                                     ((min_rx_value[1][1]*u2gdelay_cell_ps_all[shuffleIdx][1]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[1][1]));
+#endif
+    }
+    else
+    {
+        mcSHOW_DBG_MSG5(("CHA_Rank0           CHA_Rank1\n"));
+        mcSHOW_DBG_MSG5(("%d%%(bit %d)         %d%%(bit %d)\n\n",
+                                        ((min_rx_value[0][0]*u2gdelay_cell_ps_all[shuffleIdx][0]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[0][0],
+                                        ((min_rx_value[0][1]*u2gdelay_cell_ps_all[shuffleIdx][0]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[0][1]));
+    }
+
+
+     mcSHOW_DBG_MSG5(("[TX minimum per bit window]\n"));
+     if (p->enable_tx_scan_vref == ENABLE_VREF_SCAN)
+     {
+         mcSHOW_DBG_MSG5(("VrefDQ Range : %d\n",(u1MR14Value[p->channel][p->rank][p->dram_fsp]>>6)&1));
+#if CHANNEL_NUM==4
+        mcSHOW_DBG_MSG5(("CHA_VrefDQ_Rank0   CHA_VrefDQ_Rank1    CHB_VrefDQ_Rank0    CHB_VrefDQ_Rank1   CHC_VrefDQ_Rank0    CHC_VrefDQ_Rank1    CHD_VrefDQ_Rank0    CHD_VrefDQ_Rank1\n"));
+        mcSHOW_DBG_MSG5(("%d                 %d                  %d                  %d                 %d                  %d                  %d                  %d\n"
+                    , gFinalTXVrefDQ[0][0], gFinalTXVrefDQ[0][1], gFinalTXVrefDQ[1][0], gFinalTXVrefDQ[1][1]
+                    , gFinalTXVrefDQ[2][0], gFinalTXVrefDQ[2][1], gFinalTXVrefDQ[3][0], gFinalTXVrefDQ[3][1]
+                    ));
+#else
+         mcSHOW_DBG_MSG5(("CHA_VrefDQ_Rank0   CHA_VrefDQ_Rank1    CHB_VrefDQ_Rank0    CHB_VrefDQ_Rank1\n"));
+         mcSHOW_DBG_MSG5(("%d                  %d                   %d                   %d\n", gFinalTXVrefDQ[0][0], gFinalTXVrefDQ[0][1], gFinalTXVrefDQ[1][0], gFinalTXVrefDQ[1][1]));
+#endif
+     }
+     else
+     {
+         mcSHOW_DBG_MSG5(("TX DQ Vref Scan : Disable\n"));
+     }
+
+    if(u1IsLP4Family(p->dram_type))
+    {
+#if CHANNEL_NUM==4
+    mcSHOW_DBG_MSG5(("CHA_Rank0         CHA_Rank1           CHB_Rank0           CHB_Rank1       CHC_Rank0       CHC_Rank1       CHD_Rank0   CHD_Rank1\n"));
+    mcSHOW_DBG_MSG5(("%d%%               %d%%                 %d%%                 %d%%                 %d%%                 %d%%                 %d%%                 %d%%\n",
+                                        (min_tx_value[0][0]*100+31)/32,
+                                        (min_tx_value[0][1]*100+31)/32,
+                                        (min_tx_value[1][0]*100+31)/32,
+                                        (min_tx_value[1][1]*100+31)/32,
+                                        (min_tx_value[2][0]*100+31)/32,
+                                        (min_tx_value[2][1]*100+31)/32,
+                                        (min_tx_value[3][0]*100+31)/32,
+                                        (min_tx_value[3][1]*100+31)/32
+                                        ));
+#else
+     mcSHOW_DBG_MSG5(("CHA_Rank0           CHA_Rank1           CHB_Rank0           CHB_Rank1\n"));
+     mcSHOW_DBG_MSG5(("%d%%                %d%%                %d%%                %d%%\n",
+                                         (min_tx_value[0][0]*100+31)/32,
+                                         (min_tx_value[0][1]*100+31)/32,
+                                         (min_tx_value[1][0]*100+31)/32,
+                                         (min_tx_value[1][1]*100+31)/32));
+#endif
+    }
+    else
+    {
+     mcSHOW_DBG_MSG5(("CHA_Rank0           CHA_Rank1\n"));
+     mcSHOW_DBG_MSG5(("%d%%                %d%%\n",
+                                         (min_tx_value[0][0]*100+31)/32,
+                                         (min_tx_value[0][1]*100+31)/32));
+    }
+#endif
+
+
+    // reset all data
+    HQA_measure_message_reset_all_data(p);
+}
+#ifdef RELEASE
+#undef mcSHOW_DBG_MSG
+#define mcSHOW_DBG_MSG(_x_)
+#endif
+#endif
+
+
+#if EYESCAN_LOG
+#ifdef RELEASE
+#undef mcSHOW_DBG_MSG
+#define mcSHOW_DBG_MSG(_x_)	opt_print _x_
+#endif
+
+#if FOR_DV_SIMULATION_USED
+const U16 gRXVref_Voltage_Table_LP4[RX_VREF_RANGE_END+1]={0};
+#else
+const U16 gRXVref_Voltage_Table_LP4[RX_VREF_RANGE_END+1]={
+        1363,
+        2590,
+        3815,
+        5040,
+        6264,
+        7489,
+        8714,
+        9938,
+        11160,
+        12390,
+        13610,
+        14840,
+        16060,
+        17290,
+        18510,
+        19740,
+        20670,
+        22100,
+        23530,
+        24970,
+        26400,
+        27830,
+        29260,
+        30700,
+        32130,
+        33560,
+        34990,
+        36430,
+        37860,
+        39290,
+        40720,
+        42160
+};
+#endif
+const U16 gVref_Voltage_Table_LP4X[VREF_RANGE_MAX][VREF_VOLTAGE_TABLE_NUM]={
+    {1500,1560,1620,1680,1740,1800,1860,1920,1980,2040,2100,2160,2220,2280,2340,2400,2460,2510,2570,2630,2690,2750,2810,2870,2930,2990,3050,3110,3170,3230,3290,3350,3410,3470,3530,3590,3650,3710,3770,3830,3890,3950,4010,4070,4130,4190,4250,4310,4370,4430,4490},
+    {3290,3350,3410,3470,3530,3590,3650,3710,3770,3830,3890,3950,4010,4070,4130,4190,4250,4310,4370,4430,4490,4550,4610,4670,4730,4790,4850,4910,4970,5030,5090,5150,5210,5270,5330,5390,5450,5510,5570,5630,5690,5750,5810,5870,5930,5990,6050,6110,6170,6230,6290}
+};
+const U16 gVref_Voltage_Table_LP4[VREF_RANGE_MAX][VREF_VOLTAGE_TABLE_NUM]={
+    {1000,1040,1080,1120,1160,1200,1240,1280,1320,1360,1400,1440,1480,1520,1560,1600,1640,1680,1720,1760,1800,1840,1880,1920,1960,2000,2040,2080,2120,2160,2200,2240,2280,2320,2360,2400,2440,2480,2520,2560,2600,2640,2680,2720,2760,2800,2840,2880,2920,2960,3000},
+    {2200,2240,2280,2320,2360,2400,2440,2480,2520,2560,2600,2640,2680,2720,2760,2800,2840,2880,2920,2960,3000,3040,3080,3120,3160,3200,3240,3280,3320,3360,3400,3440,3480,3520,3560,3600,3640,3680,3720,3760,3880,3840,3880,3920,3960,4000,4040,4080,4120,4160,4200}
+};
+#define EyeScan_Pic_draw_line_Mirror 1
+#define EysScan_Pic_draw_1UI_line 1
+void EyeScan_Pic_draw_line(DRAMC_CTX_T *p, U8 draw_type, U8 u1VrefRange, U8 u1VrefIdx, U8 u1BitIdx, S16 u2DQDelayBegin, S16 u2DQDelayEnd, U8 u1FinalVrefRange, U16 Final_Vref_val, U8 VdlVWHigh_Upper_Vcent_Range, U32 VdlVWHigh_Upper_Vcent, U8 VdlVWHigh_Lower_Vcent_Range, U32 VdlVWHigh_Lower_Vcent, U16 FinalDQCaliDelay, S8 EyeScan_DelayCellPI_value, U16 delay_cell_ps, U16 Max_EyeScan_Min_val)
+{
+    int i;
+    int local_VrefIdx, local_Upper_Vcent, local_Lower_Vcent, local_Final_VrefIdx;
+    S8 EyeScan_Index;
+    S16 EyeScan_Min_val, EyeScan_Max_val, Final_EyeScan_Min_val=EYESCAN_DATA_INVALID, Final_EyeScan_Max_val=EYESCAN_DATA_INVALID, Final_EyeScan_winsize=1;
+    U16 *pVref_Voltage_Table[VREF_VOLTAGE_TABLE_NUM];
+    U32 PI_of_1_UI;
+
+    if (draw_type == 1)
+    {
+        pVref_Voltage_Table[VREF_RANGE_0]= (U16 *)gRXVref_Voltage_Table_LP4;
+        if(p->u2DelayCellTimex100!=0)
+        {
+            PI_of_1_UI = (50000000/(p->frequency*p->u2DelayCellTimex100));
+
+            FinalDQCaliDelay = (U16)EyeScan_DelayCellPI_value;
+            EyeScan_DelayCellPI_value = 0;
+        }
+        else
+        {
+            PI_of_1_UI = 0;
+            mcSHOW_ERR_MSG(("DelayCell is 0\n"));
+        }
+    }
+    else
+    {
+        if (p->dram_type == TYPE_LPDDR4)
+        {
+            pVref_Voltage_Table[VREF_RANGE_0] = (U16 *)gVref_Voltage_Table_LP4[VREF_RANGE_0];
+            pVref_Voltage_Table[VREF_RANGE_1] = (U16 *)gVref_Voltage_Table_LP4[VREF_RANGE_1];
+        }
+        if (p->dram_type == TYPE_LPDDR4X)
+        {
+            pVref_Voltage_Table[VREF_RANGE_0] = (U16 *)gVref_Voltage_Table_LP4X[VREF_RANGE_0];
+            pVref_Voltage_Table[VREF_RANGE_1] = (U16 *)gVref_Voltage_Table_LP4X[VREF_RANGE_1];
+        }
+
+        PI_of_1_UI = 32;
+    }
+
+    if (u1VrefRange==1 && u1VrefIdx <=20)
+    {
+        u1VrefRange=0;
+        u1VrefIdx += 30;
+    }
+    if (u1FinalVrefRange==1 && Final_Vref_val <=20)
+    {
+        u1FinalVrefRange=0;
+        Final_Vref_val += 30;
+    }
+    if (u1VrefRange != u1FinalVrefRange)
+    {
+        Final_Vref_val = 0xff;
+    }
+
+    local_Upper_Vcent = VdlVWHigh_Upper_Vcent_Range*VREF_VOLTAGE_TABLE_NUM+VdlVWHigh_Upper_Vcent;
+    local_Lower_Vcent = VdlVWHigh_Lower_Vcent_Range*VREF_VOLTAGE_TABLE_NUM+VdlVWHigh_Lower_Vcent;
+    local_VrefIdx = u1VrefRange*VREF_VOLTAGE_TABLE_NUM+u1VrefIdx;
+    local_Final_VrefIdx = u1FinalVrefRange*VREF_VOLTAGE_TABLE_NUM+Final_Vref_val;
+
+    if (VdlVWHigh_Upper_Vcent_Range==VREF_RANGE_1 && VdlVWHigh_Upper_Vcent<=20) local_Upper_Vcent = VdlVWHigh_Upper_Vcent_Range*VREF_VOLTAGE_TABLE_NUM+VdlVWHigh_Upper_Vcent-20;
+    if (VdlVWHigh_Lower_Vcent_Range==VREF_RANGE_1 && VdlVWHigh_Lower_Vcent<=20) local_Lower_Vcent = VdlVWHigh_Lower_Vcent_Range*VREF_VOLTAGE_TABLE_NUM+VdlVWHigh_Lower_Vcent-20;
+
+    mcSHOW_EYESCAN_MSG(("Vref-"));
+
+    if (draw_type == 1 && u1VrefIdx <= 7)
+    {
+        mcSHOW_EYESCAN_MSG((" "));
+    }
+
+    mcSHOW_EYESCAN_MSG(("%d.%d%d",pVref_Voltage_Table[u1VrefRange][u1VrefIdx]/100, ((pVref_Voltage_Table[u1VrefRange][u1VrefIdx]%100)/10), pVref_Voltage_Table[u1VrefRange][u1VrefIdx]%10));
+
+    if (draw_type == 1)
+    {
+        mcSHOW_EYESCAN_MSG(("m|"));
+    }
+    else
+    {
+        mcSHOW_EYESCAN_MSG(("%%|"));
+    }
+
+
+
+
+#if VENDER_JV_LOG || defined(RELEASE)
+#if EyeScan_Pic_draw_line_Mirror
+    EyeScan_DelayCellPI_value = 0-EyeScan_DelayCellPI_value;
+#endif
+#endif
+
+#if EyeScan_Pic_draw_line_Mirror
+    EyeScan_Index=EYESCAN_BROKEN_NUM-1;
+    EyeScan_Min_val = gEyeScan_Min[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+    EyeScan_Max_val = gEyeScan_Max[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+
+    while(EyeScan_Min_val==EYESCAN_DATA_INVALID && EyeScan_Index>0)
+    {
+        EyeScan_Index--;
+        EyeScan_Min_val = gEyeScan_Min[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+        EyeScan_Max_val = gEyeScan_Max[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+    }
+#else
+    EyeScan_Index=0;
+    EyeScan_Min_val = gEyeScan_Min[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+    EyeScan_Max_val = gEyeScan_Max[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+#endif
+
+    if ((EyeScan_Max_val - EyeScan_Min_val + 1) > Final_EyeScan_winsize)
+    {
+#if EyeScan_Pic_draw_line_Mirror
+        Final_EyeScan_Max_val = EyeScan_Max_val;
+        Final_EyeScan_Min_val = EyeScan_Min_val;
+#else
+        Final_EyeScan_Max_val = EyeScan_Max_val;
+        Final_EyeScan_Min_val = EyeScan_Min_val;
+#endif
+        Final_EyeScan_winsize =  (EyeScan_Max_val - EyeScan_Min_val + 1);
+    }
+
+#if VENDER_JV_LOG || defined(RELEASE)
+#if EyeScan_Pic_draw_line_Mirror
+    for(i=(Max_EyeScan_Min_val+PI_of_1_UI+EyeScan_DelayCellPI_value)*delay_cell_ps/100; i>(Max_EyeScan_Min_val+EyeScan_DelayCellPI_value)*delay_cell_ps/100; i-=10)
+#else
+    for(i=(Max_EyeScan_Min_val+EyeScan_DelayCellPI_value)*delay_cell_ps/100; i<(Max_EyeScan_Min_val+PI_of_1_UI+EyeScan_DelayCellPI_value)*delay_cell_ps/100; i+=10)
+#endif
+#else
+#if EyeScan_Pic_draw_line_Mirror
+    for(i=u2DQDelayEnd; i>=u2DQDelayBegin; i--)
+#else
+    for(i=u2DQDelayBegin; i<=u2DQDelayEnd; i++)
+#endif
+#endif
+    {
+
+#if VENDER_JV_LOG || defined(RELEASE)
+#if EyeScan_Pic_draw_line_Mirror
+        if (i<=((EyeScan_Min_val+EyeScan_DelayCellPI_value)*delay_cell_ps/100) && EyeScan_Index!= 0)
+        {
+            EyeScan_Index--;
+            EyeScan_Min_val = gEyeScan_Min[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+            EyeScan_Max_val = gEyeScan_Max[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+
+            if ((EyeScan_Max_val - EyeScan_Min_val + 1) > Final_EyeScan_winsize)
+            {
+                Final_EyeScan_Max_val = EyeScan_Max_val;
+                Final_EyeScan_Min_val = EyeScan_Min_val;
+                Final_EyeScan_winsize =  (EyeScan_Max_val - EyeScan_Min_val + 1);
+            }
+
+        }
+#endif
+#else
+#if EyeScan_Pic_draw_line_Mirror
+        if (i==(EyeScan_Min_val) && EyeScan_Index!= 0)
+        {
+            EyeScan_Index--;
+            EyeScan_Min_val = gEyeScan_Min[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+            EyeScan_Max_val = gEyeScan_Max[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+
+            if ((EyeScan_Max_val - EyeScan_Min_val + 1) > Final_EyeScan_winsize)
+            {
+                Final_EyeScan_Max_val = EyeScan_Max_val;
+                Final_EyeScan_Min_val = EyeScan_Min_val;
+                Final_EyeScan_winsize =  (EyeScan_Max_val - EyeScan_Min_val + 1);
+            }
+
+        }
+#endif
+#endif
+
+#if VENDER_JV_LOG || defined(RELEASE)
+        if (i>=((EyeScan_Min_val+EyeScan_DelayCellPI_value)*delay_cell_ps/100) && i<=((EyeScan_Max_val+EyeScan_DelayCellPI_value)*delay_cell_ps/100))
+#else
+        if (i>=(EyeScan_Min_val) && i<=(EyeScan_Max_val))
+#endif
+        {
+#if !VENDER_JV_LOG && !defined(RELEASE)
+            if (i==FinalDQCaliDelay+EyeScan_DelayCellPI_value) //Final DQ delay
+            {
+                if (gEye_Scan_color_flag)
+                {
+                    mcSHOW_EYESCAN_MSG(("\033[0;105mH\033[m"));
+                }
+                else
+                {
+                    mcSHOW_EYESCAN_MSG(("H"));
+                }
+            }
+            else
+            if (local_VrefIdx==local_Final_VrefIdx) //Final Vref
+            {
+                if (gEye_Scan_color_flag)
+                {
+                    mcSHOW_EYESCAN_MSG(("\033[0;105mV\033[m"));
+                }
+                else
+                {
+                    mcSHOW_EYESCAN_MSG(("V"));
+                }
+            }
+            else //spec in margin
+            if (local_VrefIdx<=local_Upper_Vcent && local_VrefIdx>=local_Lower_Vcent && i>=(FinalDQCaliDelay+EyeScan_DelayCellPI_value-3) && i<=(FinalDQCaliDelay+EyeScan_DelayCellPI_value+3))
+            {
+                if (gEye_Scan_color_flag)
+                {
+                    mcSHOW_EYESCAN_MSG(("\033[0;103mQ\033[m"));
+                }
+                else
+                {
+                    mcSHOW_EYESCAN_MSG(("Q"));
+                }
+            }
+            else //pass margin
+#endif
+            {
+#if VENDER_JV_LOG || defined(RELEASE)
+                if (gEye_Scan_color_flag)
+                {
+                    mcSHOW_EYESCAN_MSG(("\033[0;102mO\033[m"));
+                }
+                else
+                {
+                    mcSHOW_EYESCAN_MSG(("O"));
+                }
+#else
+                if (gEye_Scan_color_flag)
+                {
+                    mcSHOW_EYESCAN_MSG(("\033[0;102mO\033[m"));
+                }
+                else
+                {
+                    mcSHOW_EYESCAN_MSG(("O"));
+                }
+#endif
+            }
+        }
+        else
+        {
+#if !VENDER_JV_LOG && !defined(RELEASE)
+#if EysScan_Pic_draw_1UI_line
+            if (i==(int)(Max_EyeScan_Min_val) || i==(int)(Max_EyeScan_Min_val+PI_of_1_UI))
+            {
+                if (gEye_Scan_color_flag)
+                {
+                    mcSHOW_EYESCAN_MSG(("\033[0;107m.\033[m"));
+                }
+                else
+                {
+                    mcSHOW_EYESCAN_MSG(("."));
+                }
+            }
+            else
+#endif
+#endif
+            {
+                //not valid
+#if VENDER_JV_LOG || defined(RELEASE)
+                if (gEye_Scan_color_flag)
+                {
+                    mcSHOW_EYESCAN_MSG(("\033[0;100m.\033[m"));
+                }
+                else
+                {
+                    mcSHOW_EYESCAN_MSG(("."));
+                }
+#else
+                if (gEye_Scan_color_flag)
+                {
+                    mcSHOW_EYESCAN_MSG(("\033[0;100m.\033[m"));
+                }
+                else
+                {
+                    mcSHOW_EYESCAN_MSG(("."));
+                }
+#endif
+            }
+        }
+    }
+
+
+#if EyeScan_Pic_draw_line_Mirror
+    if (Final_EyeScan_Min_val!=EYESCAN_DATA_INVALID && Final_EyeScan_Max_val!=EYESCAN_DATA_INVALID)
+    {
+#if !VENDER_JV_LOG && !defined(RELEASE)
+        if (Final_EyeScan_Max_val>(FinalDQCaliDelay+EyeScan_DelayCellPI_value) && (FinalDQCaliDelay+EyeScan_DelayCellPI_value)>Final_EyeScan_Min_val)
+        {
+            mcSHOW_EYESCAN_MSG((" -%d ",(Final_EyeScan_Max_val-(FinalDQCaliDelay+EyeScan_DelayCellPI_value))));
+            mcSHOW_EYESCAN_MSG(("%d ", ((FinalDQCaliDelay+EyeScan_DelayCellPI_value)-Final_EyeScan_Min_val)));
+        }
+        else if (Final_EyeScan_Max_val>(FinalDQCaliDelay+EyeScan_DelayCellPI_value) && Final_EyeScan_Min_val>(FinalDQCaliDelay+EyeScan_DelayCellPI_value))
+        {
+            mcSHOW_EYESCAN_MSG((" -%d ",(Final_EyeScan_Max_val-Final_EyeScan_Min_val)));
+            mcSHOW_EYESCAN_MSG((" --- "));
+        }
+        else if ((FinalDQCaliDelay+EyeScan_DelayCellPI_value)>Final_EyeScan_Max_val && (FinalDQCaliDelay+EyeScan_DelayCellPI_value)>Final_EyeScan_Min_val)
+        {
+            mcSHOW_EYESCAN_MSG((" --- "));
+            mcSHOW_EYESCAN_MSG(("%d ", (Final_EyeScan_Max_val-Final_EyeScan_Min_val)));
+        }
+        else
+        {
+            mcSHOW_EYESCAN_MSG((" --- "));
+            mcSHOW_EYESCAN_MSG((" --- "));
+        }
+#endif
+        //window
+#if VENDER_JV_LOG || defined(RELEASE)
+        mcSHOW_EYESCAN_MSG(("%dps", Final_EyeScan_winsize*delay_cell_ps/100));
+#else
+        mcSHOW_EYESCAN_MSG(("%d", Final_EyeScan_winsize));
+#endif
+    }
+#else
+    if (Final_EyeScan_Max_val != Final_EyeScan_Min_val && Final_EyeScan_Max_val!=EYESCAN_DATA_INVALID)
+    {
+#if !VENDER_JV_LOG && !defined(RELEASE)
+        if (Final_EyeScan_Max_val>(FinalDQCaliDelay+EyeScan_DelayCellPI_value) && (FinalDQCaliDelay+EyeScan_DelayCellPI_value)>Final_EyeScan_Min_val)
+        {
+            mcSHOW_EYESCAN_MSG((" -%d ", ((FinalDQCaliDelay+EyeScan_DelayCellPI_value)-Final_EyeScan_Min_val)));
+            mcSHOW_EYESCAN_MSG(("%d ",(Final_EyeScan_Max_val-(FinalDQCaliDelay+EyeScan_DelayCellPI_value))));
+        }
+        else if (Final_EyeScan_Max_val>(FinalDQCaliDelay+EyeScan_DelayCellPI_value) && Final_EyeScan_Min_val>(FinalDQCaliDelay+EyeScan_DelayCellPI_value))
+        {
+            mcSHOW_EYESCAN_MSG((" --- "));
+            mcSHOW_EYESCAN_MSG(("%d ",(Final_EyeScan_Max_val-Final_EyeScan_Min_val)));
+        }
+        else if ((FinalDQCaliDelay+EyeScan_DelayCellPI_value)>Final_EyeScan_Max_val && (FinalDQCaliDelay+EyeScan_DelayCellPI_value)>Final_EyeScan_Min_val)
+        {
+            mcSHOW_EYESCAN_MSG((" -%d ", (Final_EyeScan_Max_val-Final_EyeScan_Min_val)));
+            mcSHOW_EYESCAN_MSG((" --- "));
+        }
+        else
+        {
+            mcSHOW_EYESCAN_MSG((" --- "));
+            mcSHOW_EYESCAN_MSG((" --- "));
+        }
+#endif
+        //window
+#if VENDER_JV_LOG || defined(RELEASE)
+        mcSHOW_EYESCAN_MSG(("%dps", Final_EyeScan_winsize*delay_cell_ps/100));
+#else
+        mcSHOW_EYESCAN_MSG(("%d", Final_EyeScan_winsize));
+#endif
+    }
+#endif
+
+    mcSHOW_EYESCAN_MSG(("\n"));
+
+
+}
+
+void print_EYESCAN_LOG_message(DRAMC_CTX_T *p, U8 print_type)
+{
+    U32 u1ChannelIdx=p->channel, u1RankIdx=p->rank;
+    S8 u1VrefIdx;
+    U8 u1VrefRange;
+    U8 u1BitIdx, u1CA;
+    U32 VdlVWTotal, Vcent_DQ;
+    U32 VdlVWHigh_Upper_Vcent=VREF_VOLTAGE_TABLE_NUM-1, VdlVWHigh_Lower_Vcent=0, VdlVWBest_Vcent=0;
+    U32 VdlVWHigh_Upper_Vcent_Range=1, VdlVWHigh_Lower_Vcent_Range=0, VdlVWBest_Vcent_Range=1;;
+    U8 Upper_Vcent_pass_flag=0, Lower_Vcent_pass_flag=0;
+    S32 i, vrefrange_i;
+    U8 local_channel_num=2;
+    U8 shuffleIdx;
+    U8 TXVrefRange, CBTVrefRange;
+    U32 vddq;
+    U8 Min_Value_1UI_Line;
+    S8 EyeScan_Index;
+    U16 *pVref_Voltage_Table[VREF_VOLTAGE_TABLE_NUM];
+    S8 EyeScan_DelayCellPI_value;
+    U8 EyeScanVcent[10+DQ_DATA_WIDTH_LP4*2], max_winsize;
+    U8 minCBTEyeScanVcentUpperBound=0xff, minCBTEyeScanVcentUpperBound_bit=0;
+    U8 minCBTEyeScanVcentLowerBound=0xff, minCBTEyeScanVcentLowerBound_bit=0;
+    U8 minRXEyeScanVcentUpperBound=0xff, minRXEyeScanVcentUpperBound_bit=0;
+    U8 minRXEyeScanVcentLowerBound=0xff, minRXEyeScanVcentLowerBound_bit=0;
+    U8 minTXEyeScanVcentUpperBound=0xff, minTXEyeScanVcentUpperBound_bit=0;
+    U8 minTXEyeScanVcentLowerBound=0xff, minTXEyeScanVcentLowerBound_bit=0;
+    U16 one_pi_ps=100000000/(p->frequency*2*32);
+    U8 u1CBTEyeScanEnable, u1RXEyeScanEnable, u1TXEyeScanEnable;
+
+    U16 u2DQDelayBegin, u2DQDelayEnd;
+
+    if(u1IsLP4Family(p->dram_type))
+    {
+        local_channel_num = p->support_channel_num;
+    }
+    else
+    {
+        //LP3
+        local_channel_num = 1;
+    }
+
+    if (p->dram_type == TYPE_LPDDR4)
+    {
+        pVref_Voltage_Table[VREF_RANGE_0] = (U16 *)gVref_Voltage_Table_LP4[VREF_RANGE_0];
+        pVref_Voltage_Table[VREF_RANGE_1] = (U16 *)gVref_Voltage_Table_LP4[VREF_RANGE_1];
+    }
+    if (p->dram_type == TYPE_LPDDR4X)
+    {
+        pVref_Voltage_Table[VREF_RANGE_0] = (U16 *)gVref_Voltage_Table_LP4X[VREF_RANGE_0];
+        pVref_Voltage_Table[VREF_RANGE_1] = (U16 *)gVref_Voltage_Table_LP4X[VREF_RANGE_1];
+    }
+
+    u1CBTEyeScanEnable = (gCBT_EYE_Scan_flag==1 && ((gCBT_EYE_Scan_only_higheset_freq_flag==1 && p->frequency == u2DFSGetHighestFreq(p)) || gCBT_EYE_Scan_only_higheset_freq_flag==0));
+    u1RXEyeScanEnable = (gRX_EYE_Scan_flag==1 && ((gRX_EYE_Scan_only_higheset_freq_flag==1 && p->frequency == u2DFSGetHighestFreq(p)) || gRX_EYE_Scan_only_higheset_freq_flag==0));
+    u1TXEyeScanEnable = (gTX_EYE_Scan_flag==1 && ((gTX_EYE_Scan_only_higheset_freq_flag==1 && p->frequency == u2DFSGetHighestFreq(p)) || gTX_EYE_Scan_only_higheset_freq_flag==0));
+
+
+
+
+/**************************************************************************************
+    CBT EYESCAN log
+***************************************************************************************/
+    if (p->frequency <=934) VdlVWTotal = 17500; //VcIVW 175mv
+    else if (p->frequency <= 1600) VdlVWTotal = 15500; //VcIVW 155mv
+    else VdlVWTotal = 14500; //VcIVW 145mv
+
+    CBTVrefRange = (u1MR12Value[p->channel][p->rank][p->dram_fsp]>>6)&1;
+
+#if !VENDER_JV_LOG && !defined(RELEASE)
+    if (print_type==0)
+    if (u1CBTEyeScanEnable)
+    {
+        mcSHOW_DBG_MSG(("[EYESCAN_LOG] CBT Window\n"));
+        vddq=vGetVoltage(p, 2)/1000; //mv
+        mcSHOW_DBG_MSG(("[EYESCAN_LOG] VDDQ=%dmV\n",vddq));
+//        for(u1ChannelIdx=CHANNEL_A; u1ChannelIdx<local_channel_num; u1ChannelIdx++)
+        {
+//            for(u1RankIdx = RANK_0; u1RankIdx < 2; u1RankIdx++)
+            {
+                mcSHOW_DBG_MSG(("[EYESCAN_LOG] CBT Channel%d Range %d Final_Vref Vcent=%d(%dmV(X100))\n",
+                                                        u1ChannelIdx,
+                                                        CBTVrefRange,
+                                                        gFinalCBTVrefDQ[u1ChannelIdx][u1RankIdx],
+                                                        pVref_Voltage_Table[CBTVrefRange][gFinalCBTVrefDQ[u1ChannelIdx][u1RankIdx]]*vddq/100));
+
+                Vcent_DQ = pVref_Voltage_Table[CBTVrefRange][gFinalCBTVrefDQ[u1ChannelIdx][u1RankIdx]]*vddq/100;
+
+                //find VdlVWHigh first
+                VdlVWHigh_Upper_Vcent_Range = 1;
+                VdlVWHigh_Upper_Vcent = VREF_VOLTAGE_TABLE_NUM-1;
+                vrefrange_i = CBTVrefRange;
+                for(i=(gFinalCBTVrefDQ[u1ChannelIdx][u1RankIdx]); i<VREF_VOLTAGE_TABLE_NUM; i++)
+                {
+                    if (((pVref_Voltage_Table[vrefrange_i][i]*vddq/100 - Vcent_DQ)) >= VdlVWTotal/2)
+                    {
+                        /* find VdlVWHigh upper bound */
+                        VdlVWHigh_Upper_Vcent = i;
+                        VdlVWHigh_Upper_Vcent_Range = vrefrange_i;
+                        break;
+                    }
+                    if (i==(VREF_VOLTAGE_TABLE_NUM-1) && vrefrange_i==0)
+                    {
+                        vrefrange_i=1;
+                        i=20;
+                    }
+    }
+                mcSHOW_DBG_MSG(("[EYESCAN_LOG] CBT VdlVWHigh_Upper Range=%d Vcent=%d(%dmV(X100))\n",
+                    VdlVWHigh_Upper_Vcent_Range,
+                    VdlVWHigh_Upper_Vcent,
+                    pVref_Voltage_Table[VdlVWHigh_Upper_Vcent_Range][VdlVWHigh_Upper_Vcent]*vddq/100));
+
+                //find VldVWLow first
+                VdlVWHigh_Lower_Vcent_Range = 0;
+                VdlVWHigh_Lower_Vcent = 0;
+                vrefrange_i = CBTVrefRange;
+                for(i=(gFinalCBTVrefDQ[u1ChannelIdx][u1RankIdx]); i>=0; i--)
+                {
+                    if (((Vcent_DQ - pVref_Voltage_Table[vrefrange_i][i]*vddq/100)) >= VdlVWTotal/2)
+                    {
+                        /* find VdlVWHigh lower bound */
+                        VdlVWHigh_Lower_Vcent = i;
+                        VdlVWHigh_Lower_Vcent_Range = vrefrange_i;
+                        break;
+                    }
+                    if (i<=21 && vrefrange_i==1)
+                    {
+                        vrefrange_i=0;
+                        i=VREF_VOLTAGE_TABLE_NUM-(21-i);
+                    }
+                }
+                mcSHOW_DBG_MSG(("[EYESCAN_LOG] CBT VdlVWHigh_Lower Range=%d Vcent=%d(%dmV(X100))\n",
+                    VdlVWHigh_Lower_Vcent_Range,
+                    VdlVWHigh_Lower_Vcent,
+                    pVref_Voltage_Table[VdlVWHigh_Lower_Vcent_Range][VdlVWHigh_Lower_Vcent]*vddq/100));
+
+#ifdef FOR_HQA_TEST_USED
+                EyeScanVcent[0] = CBTVrefRange;
+                EyeScanVcent[1] = gFinalCBTVrefDQ[u1ChannelIdx][u1RankIdx];
+                EyeScanVcent[2] = VdlVWHigh_Upper_Vcent_Range;
+                EyeScanVcent[3] = VdlVWHigh_Upper_Vcent;
+                EyeScanVcent[4] = VdlVWHigh_Lower_Vcent_Range;
+                EyeScanVcent[5] = VdlVWHigh_Lower_Vcent;
+#endif
+
+                shuffleIdx = get_shuffleIndex_by_Freq(p);
+
+    //            mcSHOW_DBG_MSG(("[EYESCAN_LOG] delay cell %d/100ps\n", u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx]));
+
+                for (u1CA=0; u1CA<CATRAINING_NUM_LP4; u1CA++)
+                {
+
+                    // compare Upper/Lower Vcent pass criterion is pass or fail?
+                    for(u1VrefIdx=gFinalCBTVrefDQ[u1ChannelIdx][u1RankIdx]+CBTVrefRange*30; u1VrefIdx<=(S8)(VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30); u1VrefIdx++)
+                    {
+                        Upper_Vcent_pass_flag = 0;
+                        for (EyeScan_Index=0; EyeScan_Index<EYESCAN_BROKEN_NUM; EyeScan_Index++)
+                        {
+                            if ((((gEyeScan_CaliDelay[0]+gEyeScan_DelayCellPI[u1CA]) - gEyeScan_Min[u1VrefIdx][u1CA][EyeScan_Index]) >=4 ) && ((gEyeScan_Max[u1VrefIdx][u1CA][EyeScan_Index] - (gEyeScan_CaliDelay[0]+gEyeScan_DelayCellPI[u1CA])) >=4 ))
+                            {
+                                Upper_Vcent_pass_flag = 1;
+                            }
+                        }
+                        if (Upper_Vcent_pass_flag == 0) break; // fail!!
+                    }
+                    for(u1VrefIdx=VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30; u1VrefIdx<=(S8)(gFinalCBTVrefDQ[u1ChannelIdx][u1RankIdx]+CBTVrefRange*30); u1VrefIdx++)
+                    {
+                        Lower_Vcent_pass_flag = 0;
+                        for (EyeScan_Index=0; EyeScan_Index<EYESCAN_BROKEN_NUM; EyeScan_Index++)
+                        {
+                            if ((((gEyeScan_CaliDelay[0]+gEyeScan_DelayCellPI[u1CA]) - gEyeScan_Min[u1VrefIdx][u1CA][EyeScan_Index]) >=4 ) && ((gEyeScan_Max[u1VrefIdx][u1CA][EyeScan_Index] - (gEyeScan_CaliDelay[0]+gEyeScan_DelayCellPI[u1CA])) >=4 ))
+                             {
+                                Lower_Vcent_pass_flag = 1;
+                            }
+                        }
+                        if (Lower_Vcent_pass_flag == 0) break; //fail!!
+                    }
+
+                    mcSHOW_DBG_MSG(("[EYESCAN_LOG] %d Channel%d Rank%d CA%d\tHigher VdlTW=%dPI(%d/100ps)(%s)\tLower VdlTW=%dpi(%d/100ps)(%s)\n",
+                        p->frequency*2,
+                        u1ChannelIdx,
+                        u1RankIdx,
+                        u1CA,
+                        gEyeScan_WinSize[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1CA],
+                        gEyeScan_WinSize[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1CA]*one_pi_ps,
+                        Upper_Vcent_pass_flag==1 ? "PASS" : "FAIL",
+                        gEyeScan_WinSize[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1CA],
+                        gEyeScan_WinSize[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1CA]*one_pi_ps,
+                        Lower_Vcent_pass_flag==1 ? "PASS" : "FAIL"
+                        ));
+
+#ifdef FOR_HQA_TEST_USED
+                    //find VdlVWBest Vref Range and Vref
+                    VdlVWBest_Vcent_Range = 1;
+                    VdlVWBest_Vcent = VREF_VOLTAGE_TABLE_NUM-1;
+                    vrefrange_i = 1;
+                    max_winsize = 0;
+                    for(i=VREF_VOLTAGE_TABLE_NUM-1; i>=0; i--)
+                    {
+                        if (gEyeScan_WinSize[i+vrefrange_i*30][u1CA] > max_winsize)
+                        {
+                            max_winsize = gEyeScan_WinSize[i+vrefrange_i*30][u1CA];
+                            VdlVWBest_Vcent_Range = vrefrange_i;
+                            VdlVWBest_Vcent = i;
+                        }
+                        if (i==21 && vrefrange_i==1)
+                        {
+                            vrefrange_i=0;
+                            i=VREF_VOLTAGE_TABLE_NUM;
+                        }
+                    }
+
+                    EyeScanVcent[10+u1CA*2] = VdlVWBest_Vcent_Range;
+                    EyeScanVcent[10+u1CA*2+1] = VdlVWBest_Vcent;
+#endif
+
+                    if (gEyeScan_WinSize[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1CA] < minCBTEyeScanVcentUpperBound)
+                    {
+                        minCBTEyeScanVcentUpperBound = gEyeScan_WinSize[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1CA];
+                        minCBTEyeScanVcentUpperBound_bit = u1CA;
+                    }
+                    if (gEyeScan_WinSize[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1CA] < minCBTEyeScanVcentLowerBound)
+                    {
+                        minCBTEyeScanVcentLowerBound = gEyeScan_WinSize[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1CA];
+                        minCBTEyeScanVcentLowerBound_bit = u1CA;
+                    }
+                }
+#ifdef FOR_HQA_TEST_USED
+#ifdef FOR_HQA_REPORT_USED
+                print_EyeScanVcent_for_HQA_report_used(p, print_type, u1ChannelIdx, u1RankIdx, EyeScanVcent, minCBTEyeScanVcentUpperBound, minCBTEyeScanVcentUpperBound_bit, minCBTEyeScanVcentLowerBound, minCBTEyeScanVcentLowerBound_bit);
+#endif
+#endif
+            }
+        }
+    }
+#endif
+
+
+
+
+
+    if (print_type==0)
+    if (u1CBTEyeScanEnable)
+    {
+        mcSHOW_DBG_MSG(("\n\n"));
+
+        for (u1CA=0; u1CA<CATRAINING_NUM_LP4; u1CA++)
+        {
+            EyeScan_Index = 0;
+
+#if EyeScan_Pic_draw_line_Mirror
+            EyeScan_DelayCellPI_value = 0-gEyeScan_DelayCellPI[u1CA];
+#else
+            EyeScan_DelayCellPI_value = gEyeScan_DelayCellPI[u1CA];
+#endif
+            Min_Value_1UI_Line = gEyeScan_CaliDelay[0]-16-EyeScan_DelayCellPI_value;
+
+
+            mcSHOW_EYESCAN_MSG(("[EYESCAN_LOG] CBT EYESCAN Channel%d, Rank%d, CA%d ===\n",p->channel, p->rank, u1CA));
+
+#if VENDER_JV_LOG || defined(RELEASE)
+            for(i=0; i<8+one_pi_ps*32/1000; i++) mcSHOW_EYESCAN_MSG((" "));
+            mcSHOW_EYESCAN_MSG(("window\n"));
+#else
+            for(i=0; i<8+one_pi_ps*32/1000; i++) mcSHOW_EYESCAN_MSG((" "));
+            mcSHOW_EYESCAN_MSG(("first last window\n"));
+#endif
+
+            u1VrefRange=1;
+            for (u1VrefIdx=VREF_VOLTAGE_TABLE_NUM-1; u1VrefIdx>=0; u1VrefIdx--)
+            {
+
+                    EyeScan_Pic_draw_line(p, 0, u1VrefRange, u1VrefIdx, u1CA, 0, 64, CBTVrefRange, gFinalCBTVrefDQ[u1ChannelIdx][u1RankIdx], VdlVWHigh_Upper_Vcent_Range, VdlVWHigh_Upper_Vcent, VdlVWHigh_Lower_Vcent_Range, VdlVWHigh_Lower_Vcent, gEyeScan_CaliDelay[0], gEyeScan_DelayCellPI[u1CA], one_pi_ps, Min_Value_1UI_Line);
+
+                    if (u1VrefRange==VREF_RANGE_1 && u1VrefIdx==21)
+                    {
+                        u1VrefRange=VREF_RANGE_0;
+                        u1VrefIdx=VREF_VOLTAGE_TABLE_NUM;
+                    }
+            }
+            mcSHOW_EYESCAN_MSG(("\n\n"));
+
+        }
+    }
+
+
+
+
+
+/**************************************************************************************
+    RX EYESCAN log
+***************************************************************************************/
+    if (p->frequency <=1600) VdlVWTotal = 10000; //14000; //140mv
+    else VdlVWTotal = 10000; //12000; //120mv
+
+#if !VENDER_JV_LOG && !defined(RELEASE)
+    if (print_type==1)
+    if (u1RXEyeScanEnable)
+    {
+        mcSHOW_DBG_MSG(("[EYESCAN_LOG] RX Window\n"));
+        {
+            mcSHOW_DBG_MSG(("[EYESCAN_LOG] RX Final_Vref Vcent Channel%d %d(%dmV(X100))\n",
+                                                    u1ChannelIdx,
+                                                    gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx],
+                                                    gRXVref_Voltage_Table_LP4[gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx]]));
+
+            Vcent_DQ = gRXVref_Voltage_Table_LP4[gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx]];
+
+            //find VdlVWHigh first
+            VdlVWHigh_Upper_Vcent_Range = 0;
+            VdlVWHigh_Upper_Vcent = RX_VREF_RANGE_END;
+            for(i=gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx]; i<=RX_VREF_RANGE_END; i++)
+            {
+                if (gRXVref_Voltage_Table_LP4[i] - Vcent_DQ >= VdlVWTotal/2)
+                {
+                    /* find VdlVWHigh upper bound */
+                    VdlVWHigh_Upper_Vcent = i;
+                    break;
+                }
+            }
+            mcSHOW_DBG_MSG(("[EYESCAN_LOG] RX VdlVWHigh_Upper Vcent=%d(%dmV(X100))\n", VdlVWHigh_Upper_Vcent, gRXVref_Voltage_Table_LP4[VdlVWHigh_Upper_Vcent]));
+
+            //find VldVWLow first
+            VdlVWHigh_Lower_Vcent_Range = 0;
+            VdlVWHigh_Lower_Vcent = 0;
+            for(i=gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx]; i>=0; i--)
+            {
+                if (Vcent_DQ - gRXVref_Voltage_Table_LP4[i] >= VdlVWTotal/2)
+                {
+                    /* find VdlVWHigh lower bound */
+                    VdlVWHigh_Lower_Vcent = i;
+                    break;
+                }
+            }
+            mcSHOW_DBG_MSG(("[EYESCAN_LOG] RX VdlVWHigh_Lower Vcent=%d(%dmV(X100))\n", VdlVWHigh_Lower_Vcent, gRXVref_Voltage_Table_LP4[VdlVWHigh_Lower_Vcent]));
+
+#ifdef FOR_HQA_TEST_USED
+            EyeScanVcent[0] = gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx];
+            EyeScanVcent[1] = VdlVWHigh_Upper_Vcent;
+            EyeScanVcent[2] = VdlVWHigh_Lower_Vcent;
+#endif
+
+            shuffleIdx = get_shuffleIndex_by_Freq(p);
+
+            mcSHOW_DBG_MSG(("[EYESCAN_LOG] delay cell %d/100ps\n", u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx]));
+
+            for (u1BitIdx=0; u1BitIdx<p->data_width; u1BitIdx++)
+            {
+                mcSHOW_DBG_MSG(("[EYESCAN_LOG] %d Channel%d Bit%d(DRAM DQ%d)\tHigher VdlTW=%d/100ps\tLower VdlTW=%d/100ps\n",
+                    p->frequency*2,
+                    u1ChannelIdx,
+                    u1BitIdx,
+                    uiLPDDR4_O1_Mapping_POP[p->channel][u1BitIdx],
+                    gEyeScan_WinSize[VdlVWHigh_Upper_Vcent][u1BitIdx]*u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx],
+                    gEyeScan_WinSize[VdlVWHigh_Lower_Vcent][u1BitIdx]*u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx]
+                    ));
+
+#ifdef FOR_HQA_TEST_USED
+                    //find VdlVWBest Vref Range and Vref
+                    VdlVWBest_Vcent = VREF_VOLTAGE_TABLE_NUM-1;
+                    max_winsize = 0;
+                    for(i=RX_VREF_RANGE_END; i>=0; i--)
+                    {
+                        if (gEyeScan_WinSize[i][u1BitIdx] > max_winsize)
+                        {
+                            max_winsize = gEyeScan_WinSize[i][u1BitIdx];
+                            VdlVWBest_Vcent = i;
+                        }
+                    }
+
+                    EyeScanVcent[10+u1BitIdx] = VdlVWBest_Vcent;
+#endif
+
+                if (gEyeScan_WinSize[VdlVWHigh_Upper_Vcent][u1BitIdx] < minRXEyeScanVcentUpperBound)
+                {
+                    minRXEyeScanVcentUpperBound = gEyeScan_WinSize[VdlVWHigh_Upper_Vcent][u1BitIdx];
+                    minRXEyeScanVcentUpperBound_bit = u1BitIdx;
+                }
+                if (gEyeScan_WinSize[VdlVWHigh_Lower_Vcent][u1BitIdx] < minRXEyeScanVcentLowerBound)
+                {
+                    minRXEyeScanVcentLowerBound = gEyeScan_WinSize[VdlVWHigh_Lower_Vcent][u1BitIdx];
+                    minRXEyeScanVcentLowerBound_bit = u1BitIdx;
+                }
+            }
+
+#ifdef FOR_HQA_TEST_USED
+#ifdef FOR_HQA_REPORT_USED
+            print_EyeScanVcent_for_HQA_report_used(p, print_type, u1ChannelIdx, u1RankIdx, EyeScanVcent, minRXEyeScanVcentUpperBound, minRXEyeScanVcentUpperBound_bit, minRXEyeScanVcentLowerBound, minRXEyeScanVcentLowerBound_bit);
+#endif
+#endif
+        }
+    }
+#endif
+
+
+
+    if (print_type==1)
+    if (u1RXEyeScanEnable)
+    {
+        int drawend, drawbegin;
+
+        mcSHOW_DBG_MSG(("\n\n"));
+
+        for (u1BitIdx=0; u1BitIdx<p->data_width; u1BitIdx++)
+        {
+            EyeScan_Index = 0;
+
+            Min_Value_1UI_Line = gEyeScan_DelayCellPI[u1BitIdx]-16;
+
+            mcSHOW_EYESCAN_MSG(("[EYESCAN_LOG] RX EYESCAN Channel%d, Rank%d, DQ%d ===\n",p->channel, p->rank, u1BitIdx));
+
+#if VENDER_JV_LOG || defined(RELEASE)
+            for(i=0; i<8+one_pi_ps*32/1000; i++) mcSHOW_EYESCAN_MSG((" "));
+            mcSHOW_EYESCAN_MSG(("window\n"));
+#else
+            for(i=0; i<8+one_pi_ps*32/1000; i++) mcSHOW_EYESCAN_MSG((" "));
+            mcSHOW_EYESCAN_MSG(("first last window\n"));
+#endif
+
+            drawbegin = -32 ;//gEyeScan_Min[gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx]][u1BitIdx][EyeScan_Index]-5;
+            drawend = 64;
+
+            u1VrefRange=0;
+            for (u1VrefIdx=RX_VREF_RANGE_END; u1VrefIdx>=0; u1VrefIdx--)
+            {
+//fra                    EyeScan_Pic_draw_line(p, 1, u1VrefRange, u1VrefIdx, u1BitIdx, p->odt_onoff==ODT_ON ? 0 : -32, 64, u1VrefRange, gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx], VdlVWHigh_Upper_Vcent_Range, VdlVWHigh_Upper_Vcent, VdlVWHigh_Lower_Vcent_Range, VdlVWHigh_Lower_Vcent, gEyeScan_CaliDelay[u1BitIdx/8], gEyeScan_DelayCellPI[u1BitIdx], one_pi_ps, Min_Value_1UI_Line);
+                    EyeScan_Pic_draw_line(p, 1, u1VrefRange, u1VrefIdx, u1BitIdx, drawbegin, drawend, u1VrefRange, gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx], VdlVWHigh_Upper_Vcent_Range, VdlVWHigh_Upper_Vcent, VdlVWHigh_Lower_Vcent_Range, VdlVWHigh_Lower_Vcent, gEyeScan_CaliDelay[u1BitIdx/8], gEyeScan_DelayCellPI[u1BitIdx], one_pi_ps, Min_Value_1UI_Line);
+            }
+            mcSHOW_EYESCAN_MSG(("\n\n"));
+
+        }
+//fra while(1);
+    }
+
+
+
+
+
+/**************************************************************************************
+    TX EYESCAN log
+***************************************************************************************/
+    TXVrefRange = (u1MR14Value[p->channel][p->rank][p->dram_fsp]>>6)&1;
+
+#if !VENDER_JV_LOG && !defined(RELEASE)
+    if (print_type==2)
+    if (u1TXEyeScanEnable)
+    {   U8 cal_length;
+        U16 finalTXVref;
+
+    if (print_type==2)
+    {
+            mcSHOW_DBG_MSG(("[EYESCAN_LOG] TX DQ Window\n"));
+            cal_length = p->data_width;
+            finalTXVref = gFinalTXVrefDQ[u1ChannelIdx][u1RankIdx];
+        }
+
+        vddq=vGetVoltage(p, 2)/1000; //mv
+        mcSHOW_DBG_MSG(("[EYESCAN_LOG] VDDQ=%dmV\n",vddq));
+//        for(u1ChannelIdx=CHANNEL_A; u1ChannelIdx<local_channel_num; u1ChannelIdx++)
+        {
+//            for(u1RankIdx = RANK_0; u1RankIdx < 2; u1RankIdx++)
+            {
+                if (print_type==2)
+                {
+                    mcSHOW_DBG_MSG(("[EYESCAN_LOG] TX Channel%d Range %d Final_Vref Vcent=%d(%dmV(X100))\n",
+                                                        u1ChannelIdx,
+                                                        TXVrefRange,
+                                                        gFinalTXVrefDQ[u1ChannelIdx][u1RankIdx],
+                                                        pVref_Voltage_Table[TXVrefRange][gFinalTXVrefDQ[u1ChannelIdx][u1RankIdx]]*vddq/100));
+
+                    Vcent_DQ = pVref_Voltage_Table[TXVrefRange][gFinalTXVrefDQ[u1ChannelIdx][u1RankIdx]]*vddq/100;
+                }
+
+                //find VdlVWHigh first
+                VdlVWHigh_Upper_Vcent_Range = 1;
+                VdlVWHigh_Upper_Vcent = VREF_VOLTAGE_TABLE_NUM-1;
+                vrefrange_i = TXVrefRange;
+                for(i=(finalTXVref); i<VREF_VOLTAGE_TABLE_NUM; i++)
+                {
+                    if (((pVref_Voltage_Table[vrefrange_i][i]*vddq/100 - Vcent_DQ)) >= VdlVWTotal/2)
+                    {
+                        /* find VdlVWHigh upper bound */
+                        VdlVWHigh_Upper_Vcent = i;
+                        VdlVWHigh_Upper_Vcent_Range = vrefrange_i;
+                        break;
+                    }
+                    if (i==(VREF_VOLTAGE_TABLE_NUM-1) && vrefrange_i==0)
+                    {
+                        vrefrange_i=1;
+                        i=20;
+                    }
+                }
+                mcSHOW_DBG_MSG(("[EYESCAN_LOG] TX VdlVWHigh_Upper Range=%d Vcent=%d(%dmV(X100))\n",
+                    VdlVWHigh_Upper_Vcent_Range,
+                    VdlVWHigh_Upper_Vcent,
+                    pVref_Voltage_Table[VdlVWHigh_Upper_Vcent_Range][VdlVWHigh_Upper_Vcent]*vddq/100));
+
+                //find VldVWLow first
+                VdlVWHigh_Lower_Vcent_Range = 0;
+                VdlVWHigh_Lower_Vcent = 0;
+                vrefrange_i = TXVrefRange;
+                for(i=(finalTXVref); i>=0; i--)
+                {
+                    if (((Vcent_DQ - pVref_Voltage_Table[vrefrange_i][i]*vddq/100)) >= VdlVWTotal/2)
+                    {
+                        /* find VdlVWHigh lower bound */
+                        VdlVWHigh_Lower_Vcent = i;
+                        VdlVWHigh_Lower_Vcent_Range = vrefrange_i;
+                        break;
+                    }
+                    if (i<=21 && vrefrange_i==1)
+                    {
+                        vrefrange_i=0;
+                        i=VREF_VOLTAGE_TABLE_NUM-(21-i);
+                    }
+                }
+                mcSHOW_DBG_MSG(("[EYESCAN_LOG] TX VdlVWHigh_Lower Range=%d Vcent=%d(%dmV(X100))\n",
+                    VdlVWHigh_Lower_Vcent_Range,
+                    VdlVWHigh_Lower_Vcent,
+                    pVref_Voltage_Table[VdlVWHigh_Lower_Vcent_Range][VdlVWHigh_Lower_Vcent]*vddq/100));
+
+#ifdef FOR_HQA_TEST_USED
+                EyeScanVcent[0] = TXVrefRange;
+                EyeScanVcent[1] = gFinalTXVrefDQ[u1ChannelIdx][u1RankIdx];
+                EyeScanVcent[2] = VdlVWHigh_Upper_Vcent_Range;
+                EyeScanVcent[3] = VdlVWHigh_Upper_Vcent;
+                EyeScanVcent[4] = VdlVWHigh_Lower_Vcent_Range;
+                EyeScanVcent[5] = VdlVWHigh_Lower_Vcent;
+#endif
+
+                shuffleIdx = get_shuffleIndex_by_Freq(p);
+
+    //            mcSHOW_DBG_MSG(("[EYESCAN_LOG] delay cell %d/100ps\n", u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx]));
+
+                for (u1BitIdx=0; u1BitIdx<cal_length; u1BitIdx++)
+                {
+
+                    // compare Upper/Lower Vcent pass criterion is pass or fail?
+#if 1
+                    for(u1VrefIdx=finalTXVref+TXVrefRange*30; u1VrefIdx<=(S8)(VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30); u1VrefIdx++)
+                    {
+                        Upper_Vcent_pass_flag = 0;
+                        for (EyeScan_Index=0; EyeScan_Index<EYESCAN_BROKEN_NUM; EyeScan_Index++)
+                        {
+                            if (print_type==2)
+                            if ((((gEyeScan_CaliDelay[u1BitIdx/8]+gEyeScan_DelayCellPI[u1BitIdx]) - gEyeScan_Min[u1VrefIdx][u1BitIdx][EyeScan_Index]) >=4 ) && ((gEyeScan_Max[u1VrefIdx][u1BitIdx][EyeScan_Index] - (gEyeScan_CaliDelay[u1BitIdx/8]+gEyeScan_DelayCellPI[u1BitIdx])) >=4 ))
+                            {
+                                Upper_Vcent_pass_flag = 1;
+                            }
+                        }
+                        if (Upper_Vcent_pass_flag == 0) break; // fail!!
+                    }
+                    for(u1VrefIdx=VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30; u1VrefIdx<=(S8)(finalTXVref+TXVrefRange*30); u1VrefIdx++)
+                    {
+                        Lower_Vcent_pass_flag = 0;
+                        for (EyeScan_Index=0; EyeScan_Index<EYESCAN_BROKEN_NUM; EyeScan_Index++)
+                        {
+                            if (print_type==2)
+                            if ((((gEyeScan_CaliDelay[u1BitIdx/8]+gEyeScan_DelayCellPI[u1BitIdx]) - gEyeScan_Min[u1VrefIdx][u1BitIdx][EyeScan_Index]) >=4 ) && ((gEyeScan_Max[u1VrefIdx][u1BitIdx][EyeScan_Index] - (gEyeScan_CaliDelay[u1BitIdx/8]+gEyeScan_DelayCellPI[u1BitIdx])) >=4 ))
+                            {
+                                Lower_Vcent_pass_flag = 1;
+                            }
+                        }
+                        if (Lower_Vcent_pass_flag == 0) break; //fail!!
+                    }
+
+#else
+                    Upper_Vcent_pass_flag = 0;
+                    Lower_Vcent_pass_flag = 0;
+                    for (EyeScan_Index=0; EyeScan_Index<EYESCAN_BROKEN_NUM; EyeScan_Index++)
+                    {
+                        if ((EyeScan_Min[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1BitIdx][EyeScan_Index] <= (EyeScan_CaliDelay[u1BitIdx/8]-4+EyeScan_DelayCellPI[u1BitIdx])) && ((EyeScan_CaliDelay[u1BitIdx/8]+4+EyeScan_DelayCellPI[u1BitIdx]) <= EyeScan_Max[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1BitIdx][EyeScan_Index]))
+                        {
+                            Upper_Vcent_pass_flag = 1;
+                        }
+
+                        if ((EyeScan_Min[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1BitIdx][EyeScan_Index] <= (EyeScan_CaliDelay[u1BitIdx/8]-4+EyeScan_DelayCellPI[u1BitIdx])) && ((EyeScan_CaliDelay[u1BitIdx/8]+4+EyeScan_DelayCellPI[u1BitIdx]) <= EyeScan_Max[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1BitIdx][EyeScan_Index]))
+                        {
+                            Lower_Vcent_pass_flag = 1;
+                        }
+                    }
+#endif
+
+#ifdef FOR_HQA_TEST_USED
+                    //find VdlVWBest Vref Range and Vref
+                    VdlVWBest_Vcent_Range = 1;
+                    VdlVWBest_Vcent = VREF_VOLTAGE_TABLE_NUM-1;
+                    vrefrange_i = 1;
+                    max_winsize = 0;
+                    for(i=VREF_VOLTAGE_TABLE_NUM-1; i>=0; i--)
+                    {
+                        if (gEyeScan_WinSize[i+vrefrange_i*30][u1BitIdx] > max_winsize)
+                        {
+                            max_winsize = gEyeScan_WinSize[i+vrefrange_i*30][u1BitIdx];
+                            VdlVWBest_Vcent_Range = vrefrange_i;
+                            VdlVWBest_Vcent = i;
+                        }
+                        if (i==21 && vrefrange_i==1)
+                        {
+                            vrefrange_i=0;
+                            i=VREF_VOLTAGE_TABLE_NUM;
+                        }
+                    }
+
+                    EyeScanVcent[10+u1BitIdx*2] = VdlVWBest_Vcent_Range;
+                    EyeScanVcent[10+u1BitIdx*2+1] = VdlVWBest_Vcent;
+#endif
+
+                    if (print_type==2)
+                    {
+                    mcSHOW_DBG_MSG(("[EYESCAN_LOG] %d Channel%d Rank%d Bit%d(DRAM DQ%d)\tHigher VdlTW=%dPI(%d/100ps)(%s)\tLower VdlTW=%dpi(%d/100ps)(%s)\n",
+                        p->frequency*2,
+                        u1ChannelIdx,
+                        u1RankIdx,
+                        u1BitIdx,
+                        uiLPDDR4_O1_Mapping_POP[p->channel][u1BitIdx],
+                        gEyeScan_WinSize[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1BitIdx],
+                        gEyeScan_WinSize[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1BitIdx]*one_pi_ps,
+                        Upper_Vcent_pass_flag==1 ? "PASS" : "FAIL",
+                        gEyeScan_WinSize[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1BitIdx],
+                        gEyeScan_WinSize[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1BitIdx]*one_pi_ps,
+                        Lower_Vcent_pass_flag==1 ? "PASS" : "FAIL"
+                        ));
+
+                    if (gEyeScan_WinSize[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1BitIdx] < minTXEyeScanVcentUpperBound)
+                    {
+                        minTXEyeScanVcentUpperBound = gEyeScan_WinSize[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1BitIdx];
+                        minTXEyeScanVcentUpperBound_bit = u1BitIdx;
+                    }
+                    if (gEyeScan_WinSize[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1BitIdx] < minTXEyeScanVcentLowerBound)
+                    {
+                        minTXEyeScanVcentLowerBound = gEyeScan_WinSize[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1BitIdx];
+                        minTXEyeScanVcentLowerBound_bit = u1BitIdx;
+                    }
+                }
+                }
+#ifdef FOR_HQA_TEST_USED
+#ifdef FOR_HQA_REPORT_USED
+                print_EyeScanVcent_for_HQA_report_used(p, print_type, u1ChannelIdx, u1RankIdx, EyeScanVcent, minTXEyeScanVcentUpperBound, minTXEyeScanVcentUpperBound_bit, minTXEyeScanVcentLowerBound, minTXEyeScanVcentLowerBound_bit);
+#endif
+#endif
+            }
+        }
+    }
+#endif
+
+
+    if (print_type==2)
+    if (u1TXEyeScanEnable)
+    {   U8 cal_length;
+
+        mcSHOW_DBG_MSG(("\n\n"));
+
+        if (print_type==2) cal_length = p->data_width;
+
+        if(gEyeScan_CaliDelay[0] <gEyeScan_CaliDelay[1])
+            u2DQDelayBegin = gEyeScan_CaliDelay[0]-24;
+        else
+            u2DQDelayBegin = gEyeScan_CaliDelay[1]-24;
+
+
+        u2DQDelayEnd = u2DQDelayBegin + 64;
+
+
+        for (u1BitIdx=0; u1BitIdx<cal_length; u1BitIdx++)
+        {
+            EyeScan_Index = 0;
+
+#if EyeScan_Pic_draw_line_Mirror
+            EyeScan_DelayCellPI_value = 0-gEyeScan_DelayCellPI[u1BitIdx];
+#else
+            EyeScan_DelayCellPI_value = gEyeScan_DelayCellPI[u1BitIdx];
+#endif
+            if (print_type==2) Min_Value_1UI_Line = gEyeScan_CaliDelay[u1BitIdx/8]-16-EyeScan_DelayCellPI_value;
+
+            if (print_type==2)
+            {
+                mcSHOW_EYESCAN_MSG(("[EYESCAN_LOG] TX DQ EYESCAN Channel%d, Rank%d, Bit%d(DRAM DQ%d) ===\n",p->channel, p->rank, u1BitIdx, uiLPDDR4_O1_Mapping_POP[p->channel][u1BitIdx]));
+            }
+
+#if VENDER_JV_LOG
+            for(i=0; i<8+one_pi_ps*32/1000; i++)
+            {
+                mcSHOW_DBG_MSG5((" "));
+            }
+            mcSHOW_EYESCAN_MSG(("window\n"));
+#else
+            for(i=0; i<15+u2DQDelayEnd-u2DQDelayBegin+2; i++) mcSHOW_DBG_MSG((" "));
+            mcSHOW_EYESCAN_MSG(("first last window\n"));
+#endif
+
+            u1VrefRange=VREF_RANGE_1;
+            for (u1VrefIdx=VREF_VOLTAGE_TABLE_NUM-1; u1VrefIdx>=0; u1VrefIdx--)
+            {
+                if (print_type == 2)
+                    EyeScan_Pic_draw_line(p, print_type, u1VrefRange, u1VrefIdx, u1BitIdx, u2DQDelayBegin, u2DQDelayEnd, TXVrefRange, gFinalTXVrefDQ[u1ChannelIdx][u1RankIdx], VdlVWHigh_Upper_Vcent_Range, VdlVWHigh_Upper_Vcent, VdlVWHigh_Lower_Vcent_Range, VdlVWHigh_Lower_Vcent, gEyeScan_CaliDelay[u1BitIdx/8], gEyeScan_DelayCellPI[u1BitIdx], one_pi_ps, Min_Value_1UI_Line);
+
+                    if (u1VrefRange==VREF_RANGE_1 && u1VrefIdx==21)
+                    {
+                        u1VrefRange=VREF_RANGE_0;
+                        u1VrefIdx=VREF_VOLTAGE_TABLE_NUM;
+                    }
+            }
+            mcSHOW_EYESCAN_MSG(("\n\n"));
+
+        }
+    }
+}
+#ifdef RELEASE
+#undef mcSHOW_DBG_MSG
+#define mcSHOW_DBG_MSG(_x_)
+#endif
+#endif
+
+
+
+
+
+
+
+
+//-------------------------------------------------------------------------
+/** DramcMiockJmeter
+ *  start MIOCK jitter meter.
+ *  @param p                Pointer of context created by DramcCtxCreate.
+ *  @param block_no         (U8): block 0 or 1.
+ *  @retval status          (DRAM_STATUS_T): DRAM_OK or DRAM_FAIL
+ */
+//-------------------------------------------------------------------------
+
+#ifdef ENABLE_MIOCK_JMETER
+DRAM_STATUS_T DramcMiockJmeter(DRAMC_CTX_T *p)
+{
+    U8 ucsearch_state, ucdqs_dly, fgcurrent_value, fginitial_value, ucstart_period=0, ucmiddle_period=0, ucend_period=0;
+    U32 u4sample_cnt, u4ones_cnt[DQS_NUMBER];
+    U16 u2real_freq, u2real_period;
+
+    U8 u1ShuLevel;
+    U32 u4PLL5_ADDR;
+    U32 u4PLL8_ADDR;
+    U32 u4CA_CMD6;
+    U32 u4SDM_PCW;
+    U32 u4PREDIV;
+    U32 u4POSDIV;
+    U32 u4CKDIV4;
+    U32 u4VCOFreq;
+    U32 u4DataRate;
+    U8 u1RxGatingPI=0, u1RxGatingPI_start=12, u1RxGatingPI_end=63;
+
+    // error handling
+    if (!p)
+    {
+        mcSHOW_ERR_MSG(("context NULL\n"));
+        return DRAM_FAIL;
+    }
+
+#if (fcFOR_CHIP_ID == fcLaurel)
+    if(u1IsLP4Family(p->dram_type))
+    {
+        u1RxGatingPI_start = 0; //0x10;
+        u1RxGatingPI_end = 63; //u1RxGatingPI_start + 1;
+    }
+    else
+    {
+        u1RxGatingPI_start = 10;
+        u1RxGatingPI_end = 63;
+    }
+#endif
+
+    u2gdelay_cell_ps=0;
+
+    U32 u4RegBackupAddress[] =
+    {
+        (DRAMC_REG_ADDR(DRAMC_REG_EYESCAN)),
+        (DRAMC_REG_ADDR(DRAMC_REG_STBCAL1)),
+        (DRAMC_REG_ADDR(DDRPHY_B0_DQ6)),
+        (DRAMC_REG_ADDR(DDRPHY_B1_DQ6)),
+        (DRAMC_REG_ADDR(DDRPHY_B0_DQ5)),
+        (DRAMC_REG_ADDR(DDRPHY_B1_DQ5)),
+        (DRAMC_REG_ADDR(DDRPHY_B0_DQ3)),
+        (DRAMC_REG_ADDR(DDRPHY_B1_DQ3)),
+        (DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ7)),
+        (DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ7)),
+        (DRAMC_REG_ADDR(DDRPHY_B0_DQ4)),
+        (DRAMC_REG_ADDR(DDRPHY_B1_DQ4)),
+        (DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1)),
+        (DRAMC_REG_ADDR(DRAMC_REG_SHURK0_DQSIEN)),
+        ((DDRPHY_CA_DLL_ARPI2)),
+        ((DDRPHY_B0_DLL_ARPI2)),
+        ((DDRPHY_B1_DLL_ARPI2)),
+        ((DDRPHY_CA_DLL_ARPI2)+SHIFT_TO_CHB_ADDR),
+        ((DDRPHY_B0_DLL_ARPI2)+SHIFT_TO_CHB_ADDR),
+        ((DDRPHY_B1_DLL_ARPI2)+SHIFT_TO_CHB_ADDR),
+    };
+
+#if ENABLE_LP3_SW
+    U32 u4RegBackupAddress_LP3[] =
+    {
+        (DRAMC_REG_ADDR(DRAMC_REG_EYESCAN)),
+        (DRAMC_REG_ADDR(DRAMC_REG_STBCAL1)),
+        (DRAMC_REG_ADDR(DRAMC_REG_SHURK0_DQSIEN)),
+
+        (DRAMC_REG_ADDR(DDRPHY_B0_DQ6)),
+        (DRAMC_REG_ADDR(DDRPHY_B1_DQ6)),
+        (DRAMC_REG_ADDR(DDRPHY_B0_DQ5)),
+        (DRAMC_REG_ADDR(DDRPHY_B1_DQ5)),
+        (DRAMC_REG_ADDR(DDRPHY_B0_DQ3)),
+        (DRAMC_REG_ADDR(DDRPHY_B1_DQ3)),
+        (DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ7)),
+        (DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ7)),
+        (DRAMC_REG_ADDR(DDRPHY_B0_DQ4)),
+        (DRAMC_REG_ADDR(DDRPHY_B1_DQ4)),
+        (DRAMC_REG_ADDR(DDRPHY_CA_CMD4)),
+        (DRAMC_REG_ADDR(DDRPHY_CA_CMD6)),
+        (DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1)),
+
+
+        (DRAMC_REG_ADDR(DDRPHY_B0_DQ6)+SHIFT_TO_CHB_ADDR),
+        (DRAMC_REG_ADDR(DDRPHY_B1_DQ6)+SHIFT_TO_CHB_ADDR),
+        (DRAMC_REG_ADDR(DDRPHY_B0_DQ5)+SHIFT_TO_CHB_ADDR),
+        (DRAMC_REG_ADDR(DDRPHY_B1_DQ5)+SHIFT_TO_CHB_ADDR),
+        (DRAMC_REG_ADDR(DDRPHY_B0_DQ3)+SHIFT_TO_CHB_ADDR),
+        (DRAMC_REG_ADDR(DDRPHY_B1_DQ3)+SHIFT_TO_CHB_ADDR),
+        (DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ7)+SHIFT_TO_CHB_ADDR),
+        (DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ7)+SHIFT_TO_CHB_ADDR),
+        (DRAMC_REG_ADDR(DDRPHY_B0_DQ4)+SHIFT_TO_CHB_ADDR),
+        (DRAMC_REG_ADDR(DDRPHY_B1_DQ4)+SHIFT_TO_CHB_ADDR),
+        (DRAMC_REG_ADDR(DDRPHY_CA_CMD4)+SHIFT_TO_CHB_ADDR),
+        (DRAMC_REG_ADDR(DDRPHY_CA_CMD6)+SHIFT_TO_CHB_ADDR),
+        (DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1)+SHIFT_TO_CHB_ADDR),
+
+        ((DDRPHY_CA_DLL_ARPI2)),
+        ((DDRPHY_B0_DLL_ARPI2)),
+        ((DDRPHY_B1_DLL_ARPI2)),
+        ((DDRPHY_CA_DLL_ARPI2)+SHIFT_TO_CHB_ADDR),
+        ((DDRPHY_B0_DLL_ARPI2)+SHIFT_TO_CHB_ADDR),
+        ((DDRPHY_B1_DLL_ARPI2)+SHIFT_TO_CHB_ADDR),
+    };
+#endif
+
+    //backup register value
+    if(u1IsLP4Family(p->dram_type))
+    {
+        DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+    }
+#if ENABLE_LP3_SW
+    else
+    {
+        DramcBackupRegisters(p, u4RegBackupAddress_LP3, sizeof(u4RegBackupAddress_LP3)/sizeof(U32));
+    }
+#endif
+
+    //DLL off to fix middle transion from high to low or low to high at high vcore
+    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);
+
+    if(u1IsLP4Family(p->dram_type))
+    {
+        //MCK4X CG
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 0, MISC_CTRL1_R_DMDQSIENCG_EN);
+
+        // Bypass DQS glitch-free mode
+        // RG_RX_*RDQ_EYE_DLY_DQS_BYPASS_B**
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ6), 1, B0_DQ6_RG_RX_ARDQ_EYE_DLY_DQS_BYPASS_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ6), 1, B1_DQ6_RG_RX_ARDQ_EYE_DLY_DQS_BYPASS_B1);
+
+        //Enable DQ eye scan
+        //RG_??_RX_EYE_SCAN_EN
+        //RG_??_RX_VREF_EN
+        //RG_??_RX_SMT_EN
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), 1, EYESCAN_RG_RX_EYE_SCAN_EN);
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), P_Fld(0x1, EYESCAN_EYESCAN_DQS_SYNC_EN)
+                                            | P_Fld(0x1, EYESCAN_EYESCAN_NEW_DQ_SYNC_EN)
+                                            | P_Fld(0x1, EYESCAN_EYESCAN_DQ_SYNC_EN));
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_EYE_EN_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_EYE_EN_B1);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_VREF_EN_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_VREF_EN_B1);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ3), 1, B0_DQ3_RG_RX_ARDQ_SMT_EN_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ3), 1, B1_DQ3_RG_RX_ARDQ_SMT_EN_B1);
+
+        //JM_SEL
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ6), 1, B0_DQ6_RG_RX_ARDQ_JM_SEL_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ6), 1, B1_DQ6_RG_RX_ARDQ_JM_SEL_B1);
+    }
+#if ENABLE_LP3_SW
+    else
+    {
+        //MCK4X CG
+        vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 0, MISC_CTRL1_R_DMDQSIENCG_EN);
+
+        // Bypass DQS glitch-free mode
+        // RG_RX_*RDQ_EYE_DLY_DQS_BYPASS_B**
+        vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ6), 1, B0_DQ6_RG_RX_ARDQ_EYE_DLY_DQS_BYPASS_B0);
+        vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ6), 1, B1_DQ6_RG_RX_ARDQ_EYE_DLY_DQS_BYPASS_B1);
+
+        //Enable DQ eye scan
+        //RG_??_RX_EYE_SCAN_EN
+        //RG_??_RX_VREF_EN
+        //RG_??_RX_SMT_EN
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), 1, EYESCAN_RG_RX_EYE_SCAN_EN);
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), P_Fld(0x1, EYESCAN_EYESCAN_DQS_SYNC_EN)
+                                            | P_Fld(0x1, EYESCAN_EYESCAN_NEW_DQ_SYNC_EN)
+                                            | P_Fld(0x1, EYESCAN_EYESCAN_DQ_SYNC_EN));
+        vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_EYE_EN_B0);
+        vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_EYE_EN_B1);
+        vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_VREF_EN_B0);
+        vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_VREF_EN_B1);
+        vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ3), 1, B0_DQ3_RG_RX_ARDQ_SMT_EN_B0);
+        vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ3), 1, B1_DQ3_RG_RX_ARDQ_SMT_EN_B1);
+
+        //JM_SEL
+        vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ6), 1, B0_DQ6_RG_RX_ARDQ_JM_SEL_B0);
+        vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ6), 1, B1_DQ6_RG_RX_ARDQ_JM_SEL_B1);
+        vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD6), 1, CA_CMD6_RG_RX_ARCMD_JM_SEL);
+    }
+#endif
+
+
+    //Enable MIOCK jitter meter mode ( RG_RX_MIOCK_JIT_EN=1)
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), 1, EYESCAN_RG_RX_MIOCK_JIT_EN);
+
+    //Disable DQ eye scan (b'1), for counter clear
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), 0, EYESCAN_RG_RX_EYE_SCAN_EN);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_STBCAL1), 0, STBCAL1_DQSERRCNT_DIS);
+
+    //Using test engine to switch back to RK0, or the gating PI cannont be adjust successfully.
+    DramcEngine2Run(p, TE_OP_READ_CHECK, p->test_pattern);
+
+    for (u1RxGatingPI=u1RxGatingPI_start; u1RxGatingPI<u1RxGatingPI_end; u1RxGatingPI+=4)
+    {
+        mcSHOW_DBG_MSG(("\n[DramcMiockJmeter] u1RxGatingPI = %d\n", u1RxGatingPI));
+
+        ucsearch_state = 0;
+
+        //to see 1T(H,L) or 1T(L,H) from delaycell=0 to 127
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_DQSIEN), P_Fld(u1RxGatingPI, SHURK0_DQSIEN_R0DQS0IEN) | P_Fld(u1RxGatingPI, SHURK0_DQSIEN_R0DQS1IEN)
+                    | P_Fld(u1RxGatingPI, SHURK0_DQSIEN_R0DQS2IEN) | P_Fld(u1RxGatingPI, SHURK0_DQSIEN_R0DQS3IEN));
+
+        for (ucdqs_dly=0; ucdqs_dly<128; ucdqs_dly++)
+        {
+
+            //Set DQS delay (RG_??_RX_DQS_EYE_DLY)
+            if(u1IsLP4Family(p->dram_type))
+            {
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ4), ucdqs_dly, B0_DQ4_RG_RX_ARDQS_EYE_R_DLY_B0);
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ4), ucdqs_dly, B0_DQ4_RG_RX_ARDQS_EYE_F_DLY_B0);
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ4), ucdqs_dly, B1_DQ4_RG_RX_ARDQS_EYE_R_DLY_B1);
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ4), ucdqs_dly, B1_DQ4_RG_RX_ARDQS_EYE_F_DLY_B1);
+            }
+#if ENABLE_LP3_SW
+            else //LPDDR3
+            {
+                vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ4), ucdqs_dly, B0_DQ4_RG_RX_ARDQS_EYE_R_DLY_B0);
+                vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ4), ucdqs_dly, B0_DQ4_RG_RX_ARDQS_EYE_F_DLY_B0);
+                vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ4), ucdqs_dly, B1_DQ4_RG_RX_ARDQS_EYE_R_DLY_B1);
+                vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ4), ucdqs_dly, B1_DQ4_RG_RX_ARDQS_EYE_F_DLY_B1);
+                vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD4), ucdqs_dly, CA_CMD4_RG_RX_ARCLK_EYE_R_DLY);
+                vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD4), ucdqs_dly, CA_CMD4_RG_RX_ARCLK_EYE_F_DLY);
+            }
+#endif
+            DramPhyReset(p);
+
+            //Reset eye scan counters (reg_sw_rst): 1 to 0
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), 1, EYESCAN_REG_SW_RST);
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), 0, EYESCAN_REG_SW_RST);
+
+            //Enable DQ eye scan (b'1)
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), 1, EYESCAN_RG_RX_EYE_SCAN_EN);
+
+            //2ns/sample, here we delay 1ms about 500 samples
+            mcDELAY_US(10);
+
+            //Disable DQ eye scan (b'1), for counter latch
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), 0, EYESCAN_RG_RX_EYE_SCAN_EN);
+
+            //Read the counter values from registers (toggle_cnt*, dqs_err_cnt*);
+            u4sample_cnt = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TOGGLE_CNT), TOGGLE_CNT_TOGGLE_CNT);
+            u4ones_cnt[0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQS0_ERR_CNT), DQS0_ERR_CNT_DQS0_ERR_CNT);
+            u4ones_cnt[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQS1_ERR_CNT), DQS1_ERR_CNT_DQS1_ERR_CNT);
+            u4ones_cnt[2] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQS2_ERR_CNT), DQS2_ERR_CNT_DQS2_ERR_CNT);
+            u4ones_cnt[3] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQS3_ERR_CNT), DQS3_ERR_CNT_DQS3_ERR_CNT);
+            #ifdef ETT_PRINT_FORMAT
+            mcSHOW_DBG_MSG(("%d : %d, %d, %d, %d, %d\n", ucdqs_dly, u4sample_cnt, u4ones_cnt[0],u4ones_cnt[1],u4ones_cnt[2],u4ones_cnt[3]));
+            #else
+            mcSHOW_DBG_MSG(("%3d : %8d, %8d, %8d, %8d, %8d\n", ucdqs_dly, u4sample_cnt, u4ones_cnt[0],u4ones_cnt[2],u4ones_cnt[3]));
+            #endif
+
+            /*
+            //Disable DQ eye scan (RG_RX_EYE_SCAN_EN=0, RG_RX_*RDQ_VREF_EN_B*=0, RG_RX_*RDQ_EYE_VREF_EN_B*=0, RG_RX_*RDQ_SMT_EN_B*=0)
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_STBCAL_F), 0, STBCAL_F_RG_EX_EYE_SCAN_EN);
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_EYE2), 0, EYE2_RG_RX_ARDQ_VREF_EN_B0);
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_EYEB1_2), 0, EYEB1_2_RG_RX_ARDQ_VREF_EN_B1);
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_EYE2), 0, EYE2_RG_RX_ARDQ_EYE_VREF_EN_B0);
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_EYEB1_2), 0, EYEB1_2_RG_RX_ARDQ_EYE_VREF_EN_B1);
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_TXDQ3), 0, TXDQ3_RG_RX_ARDQ_SMT_EN_B0);
+            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_RXDQ13),0, RXDQ13_RG_RX_ARDQ_SMT_EN_B1);
+            */
+
+            //change to boolean value
+            if (u4ones_cnt[0] < (u4sample_cnt/2))
+            {
+                fgcurrent_value = 0;
+            }
+            else
+            {
+                fgcurrent_value = 1;
+            }
+
+            #if 1//more than 1T data
+            {
+                if (ucsearch_state==0)
+                {
+                    //record initial value at the beginning
+                    fginitial_value = fgcurrent_value;
+                    ucsearch_state = 1;
+                }
+                else if (ucsearch_state==1)
+                {
+                    // check if change value
+                    if (fgcurrent_value != fginitial_value)
+                    {
+                        // start of the period
+                        fginitial_value = fgcurrent_value;
+                        ucstart_period = ucdqs_dly;
+                        ucsearch_state = 2;
+                    }
+                }
+                else if (ucsearch_state==2)
+                {
+                    // check if change value
+                    if (fgcurrent_value != fginitial_value)
+                    {
+                        fginitial_value = fgcurrent_value;
+                        ucmiddle_period = ucdqs_dly;
+                        ucsearch_state = 3;
+                    }
+                }
+                else if (ucsearch_state==3)
+                {
+                    // check if change value
+                    if (fgcurrent_value != fginitial_value)
+                    {
+                        // end of the period, break the loop
+                        ucend_period = ucdqs_dly;
+                        ucsearch_state = 4;
+                        break;
+                    }
+                }
+                else
+                {
+                    //nothing
+                }
+            }
+            #else //only 0.5T data
+            {
+                if (ucsearch_state==0)
+                {
+                    //record initial value at the beginning
+                    fginitial_value = fgcurrent_value;
+                    ucsearch_state = 1;
+                }
+                else if (ucsearch_state==1)
+                {
+                    // check if change value
+                    if (fgcurrent_value != fginitial_value)
+                    {
+                        // start of the period
+                        fginitial_value = fgcurrent_value;
+                        ucstart_period = ucdqs_dly;
+                        ucsearch_state = 2;
+                    }
+                }
+                else if (ucsearch_state==2)
+                {
+                    // check if change value
+                    if (fgcurrent_value != fginitial_value)
+                    {
+                        // end of the period, break the loop
+                        ucend_period = ucdqs_dly;
+                        ucsearch_state = 4;
+                       break;
+                    }
+                }
+            }
+            #endif
+        }
+
+        if((ucsearch_state==4) || (ucsearch_state==3))
+            break;
+    }
+
+    //restore to orignal value
+    if(u1IsLP4Family(p->dram_type))
+    {
+        DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+    }
+#if ENABLE_LP3_SW
+    else
+    {
+        DramcRestoreRegisters(p, u4RegBackupAddress_LP3, sizeof(u4RegBackupAddress_LP3)/sizeof(U32));
+    }
+#endif
+
+    if(ucsearch_state!=4)
+    {
+        if (ucsearch_state!=3)
+        {
+            mcSHOW_DBG_MSG(("\n\tMIOCK jitter meter - ch=%d\n", p->channel));
+            mcSHOW_DBG_MSG(("\tLess than 0.5T data. Cannot calculate delay cell time\n\n"));
+
+            ucg_num_dlycell_perT = 0;   //for LP3/4 lookup table used
+
+            return DRAM_FAIL;
+        }
+        else
+        {
+            //Calculate 1 delay cell = ? ps
+            // 1T = ? delay cell
+            ucg_num_dlycell_perT = (ucmiddle_period - ucstart_period)*2;
+            // 1T = ? ps
+        }
+    }
+    else
+    {
+        //Calculate 1 delay cell = ? ps
+        // 1T = ? delay cell
+        ucg_num_dlycell_perT = (ucend_period - ucstart_period);
+        // 1T = ? ps
+    }
+
+    u1ShuLevel = u4IO32ReadFldAlign(DRAMC_REG_SHUSTATUS, SHUSTATUS_SHUFFLE_LEVEL);
+    u4PLL5_ADDR = DDRPHY_SHU1_PLL5 + SHU_GRP_DDRPHY_OFFSET * u1ShuLevel;
+    u4PLL8_ADDR = DDRPHY_SHU1_PLL8 + SHU_GRP_DDRPHY_OFFSET * u1ShuLevel;
+    u4CA_CMD6 = DDRPHY_SHU1_CA_CMD6 + SHU_GRP_DDRPHY_OFFSET * u1ShuLevel;
+    u4SDM_PCW = u4IO32ReadFldAlign(u4PLL5_ADDR, SHU1_PLL5_RG_RPHYPLL_SDM_PCW);
+    u4PREDIV = u4IO32ReadFldAlign(u4PLL8_ADDR, SHU1_PLL8_RG_RPHYPLL_PREDIV);
+    u4POSDIV = u4IO32ReadFldAlign(u4PLL8_ADDR, SHU1_PLL8_RG_RPHYPLL_POSDIV);
+    u4CKDIV4 = u4IO32ReadFldAlign(u4CA_CMD6, SHU1_CA_CMD6_RG_ARPI_MIDPI_CKDIV4_EN_CA);
+    u4VCOFreq = ((52>>u4PREDIV)*(u4SDM_PCW>>8))>>u4POSDIV;
+    u4DataRate = u4VCOFreq>>u4CKDIV4;
+    u2real_freq = u4DataRate>>1;
+
+    u2real_period = (U16) (1000000/u2real_freq);
+    //calculate delay cell time
+
+    u2gdelay_cell_ps = u2real_period*100 / ucg_num_dlycell_perT;
+
+    if (ucsearch_state==4)
+    {
+        mcSHOW_DBG_MSG(("\n\tMIOCK jitter meter\tch=%d\n\n"
+                        "1T = (%d-%d) = %d dly cells\n"
+                        "Clock freq = %d MHz, period = %d ps, 1 dly cell = %d/100 ps\n",
+                            p->channel,
+                            ucend_period, ucstart_period, ucg_num_dlycell_perT,
+                            u2real_freq, u2real_period, u2gdelay_cell_ps));
+    }
+    else
+    {
+        mcSHOW_DBG_MSG(("\n\tMIOCK jitter meter\tch=%d\n\n"
+                        "1T = (%d-%d)*2 = %d dly cells\n"
+                        "Clock freq = %d MHz, period = %d ps, 1 dly cell = %d/100 ps\n",
+                            p->channel,
+                            ucmiddle_period, ucstart_period, ucg_num_dlycell_perT,
+                            u2real_freq, u2real_period, u2gdelay_cell_ps));
+    }
+
+    return DRAM_OK;
+
+// log example
+/* dly: sample_cnt   DQS0_cnt  DQS1_cnt
+    0 : 10962054,        0,        0
+    1 : 10958229,        0,        0
+    2 : 10961109,        0,        0
+    3 : 10946916,        0,        0
+    4 : 10955421,        0,        0
+    5 : 10967274,        0,        0
+    6 : 10893582,        0,        0
+    7 : 10974762,        0,        0
+    8 : 10990278,        0,        0
+    9 : 10972026,        0,        0
+   10 :  7421004,        0,        0
+   11 : 10943883,        0,        0
+   12 : 10984275,        0,        0
+   13 : 10955268,        0,        0
+   14 : 10960326,        0,        0
+   15 : 10952451,        0,        0
+   16 : 10956906,        0,        0
+   17 : 10960803,        0,        0
+   18 : 10944108,        0,        0
+   19 : 10959939,        0,        0
+   20 : 10959246,        0,        0
+   21 : 11002212,        0,        0
+   22 : 10919700,        0,        0
+   23 : 10977489,        0,        0
+   24 : 11009853,        0,        0
+   25 : 10991133,        0,        0
+   26 : 10990431,        0,        0
+   27 : 10970703,    11161,        0
+   28 : 10970775,   257118,        0
+   29 : 10934442,  9450467,        0
+   30 : 10970622, 10968475,        0
+   31 : 10968831, 10968831,        0
+   32 : 10956123, 10956123,        0
+   33 : 10950273, 10950273,        0
+   34 : 10975770, 10975770,        0
+   35 : 10983024, 10983024,        0
+   36 : 10981701, 10981701,        0
+   37 : 10936782, 10936782,        0
+   38 : 10889523, 10889523,        0
+   39 : 10985913, 10985913,    55562
+   40 : 10970235, 10970235,   272294
+   41 : 10996056, 10996056,  9322868
+   42 : 10972350, 10972350, 10969738
+   43 : 10963917, 10963917, 10963917
+   44 : 10967895, 10967895, 10967895
+   45 : 10961739, 10961739, 10961739
+   46 : 10937097, 10937097, 10937097
+   47 : 10937952, 10937952, 10937952
+   48 : 10926018, 10926018, 10926018
+   49 : 10943793, 10943793, 10943793
+   50 : 10954638, 10954638, 10954638
+   51 : 10968048, 10968048, 10968048
+   52 : 10944036, 10944036, 10944036
+   53 : 11012112, 11012112, 11012112
+   54 : 10969137, 10969137, 10969137
+   55 : 10968516, 10968516, 10968516
+   56 : 10952532, 10952532, 10952532
+   57 : 10985832, 10985832, 10985832
+   58 : 11002527, 11002527, 11002527
+   59 : 10950660, 10873571, 10950660
+   60 : 10949022, 10781797, 10949022
+   61 : 10974366, 10700617, 10974366
+   62 : 10972422,  1331974, 10972422
+   63 : 10926567,        0, 10926567
+   64 : 10961658,        0, 10961658
+   65 : 10978893,        0, 10978893
+   66 : 10962828,        0, 10962828
+   67 : 10957599,        0, 10957599
+   68 : 10969227,        0, 10969227
+   69 : 10960722,        0, 10960722
+   70 : 10970937,        0, 10963180
+   71 : 10962054,        0, 10711639
+   72 : 10954719,        0, 10612707
+   73 : 10958778,        0,   479589
+   74 : 10973898,        0,        0
+   75 : 11004156,        0,        0
+   76 : 10944261,        0,        0
+   77 : 10955340,        0,        0
+   78 : 10998153,        0,        0
+   79 : 10998774,        0,        0
+   80 : 10953234,        0,        0
+   81 : 10960020,        0,        0
+   82 : 10923831,        0,        0
+   83 : 10951362,        0,        0
+   84 : 10965249,        0,        0
+   85 : 10949103,        0,        0
+   86 : 10948707,        0,        0
+   87 : 10941147,        0,        0
+   88 : 10966572,        0,        0
+   89 : 10971333,        0,        0
+   90 : 10943721,        0,        0
+   91 : 10949337,        0,        0
+   92 : 10965942,        0,        0
+   93 : 10970397,        0,        0
+   94 : 10956429,        0,        0
+   95 : 10939896,        0,        0
+   96 : 10967112,        0,        0
+   97 : 10951911,        0,        0
+   98 : 10953702,        0,        0
+   99 : 10971090,        0,        0
+  100 : 10939590,        0,        0
+  101 : 10993392,        0,        0
+  102 : 10975932,        0,        0
+  103 : 10949499,    40748,        0
+  104 : 10962522,   258638,        0
+  105 : 10951524,   275292,        0
+  106 : 10982475,   417642,        0
+  107 : 10966887, 10564347,        0
+  ===============================================================================
+      MIOCK jitter meter - channel=0
+  ===============================================================================
+  1T = (107-29) = 78 delay cells
+  Clock frequency = 936 MHz, Clock period = 1068 ps, 1 delay cell = 13 ps
+*/
+}
+#endif
+
+
+
+
+#if ENABLE_DUTY_SCAN_V2
+
+#define DutyPrintAllLog         0
+#define DutyPrintCalibrationLog 1
+
+#define DUTY_OFFSET_START -8
+#define DUTY_OFFSET_END 8
+
+#define CLOCK_PI_START 0
+#define CLOCK_PI_END 63
+#define CLOCK_PI_STEP 2
+
+#define ClockDutyFailLowerBound 4500    // 45%
+#define ClockDutyFailUpperBound 5500    // 55%
+#define ClockDutyMiddleBound    5000    // 50%
+
+void DramcClockDutySetClkDelayCell(DRAMC_CTX_T *p, U8 u1RankIdx, S8 scDutyDelay, U8 use_rev_bit)
+{
+    U8 u1ShuffleIdx = 0;
+    U32 save_offset;
+    U8 ucDelay, ucDelayB;
+    U8 ucRev_Bit0=0, ucRev_Bit1=0;
+
+//    mcSHOW_DBG_MSG(("CH%d, Final CLK duty delay cell = %d\n", p->channel, scDutyDelay));
+
+    if (scDutyDelay<0)
+    {
+        ucDelay = -scDutyDelay;
+        ucDelayB = 0;
+
+        if (use_rev_bit)
+        {
+            ucRev_Bit0 = 1;
+            ucRev_Bit1 = 0;
+        }
+    }
+    else if (scDutyDelay>0)
+    {
+        ucDelay = 0;
+        ucDelayB= scDutyDelay;
+
+        if (use_rev_bit)
+        {
+            ucRev_Bit0 = 0;
+            ucRev_Bit1 = 1;
+        }
+    }
+    else
+    {
+        ucDelay = 0;
+        ucDelayB= 0;
+
+        if (use_rev_bit)
+        {
+            ucRev_Bit0 = 0;
+            ucRev_Bit1 = 0;
+        }
+    }
+
+#if DUTY_SCAN_V2_ONLY_K_HIGHEST_FREQ
+    for(u1ShuffleIdx = 0; u1ShuffleIdx<DRAM_DFS_SHUFFLE_MAX; u1ShuffleIdx++)
+#endif
+    {
+        save_offset = u1ShuffleIdx * SHU_GRP_DDRPHY_OFFSET + u1RankIdx*0x100;
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD1) + save_offset, P_Fld(ucDelay, SHU1_R0_CA_CMD1_RK0_TX_ARCLK_DLY) | P_Fld(ucDelay, SHU1_R0_CA_CMD1_RK0_TX_ARCLKB_DLY));
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD0) + save_offset, P_Fld(ucDelayB, SHU1_R0_CA_CMD0_RK0_TX_ARCLK_DLYB) | P_Fld(ucDelayB, SHU1_R0_CA_CMD0_RK0_TX_ARCLKB_DLYB));
+
+// Lau_rel like Mer_lot, no need to set this to big scale mode, just use small scale mode
+        save_offset = u1ShuffleIdx * SHU_GRP_DDRPHY_OFFSET;
+        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD3), P_Fld(ucRev_Bit0, SHU1_CA_CMD3_RG_TX_ARCMD_PU_BIT0) | P_Fld(ucRev_Bit1, SHU1_CA_CMD3_RG_TX_ARCMD_PU_BIT1));
+    }
+}
+
+void DQSDutyScan_SetDqsDelayCell(DRAMC_CTX_T *p, S8 *scDutyDelay, U8 use_rev_bit)
+{
+    U8 u1ShuffleIdx = 0, u1DQSIdx, u1RankIdx = 0;
+    U32 save_offset;
+    U8 u1Delay[2], u1DelayB[2];
+    U8 ucRev_Bit0[2]={0,0}, ucRev_Bit1[2]={0,0};
+
+//    mcSHOW_DBG_MSG(("CH%d, Final DQS0 duty delay cell = %d\n", p->channel, scDutyDelay[0]));
+//    mcSHOW_DBG_MSG(("CH%d, Final DQS1 duty delay cell = %d\n", p->channel, scDutyDelay[1]));
+
+    for(u1DQSIdx=0; u1DQSIdx<2; u1DQSIdx++)
+    {
+        if(scDutyDelay[u1DQSIdx] <0)
+        {
+            u1Delay[u1DQSIdx]  = -(scDutyDelay[u1DQSIdx]);
+            u1DelayB[u1DQSIdx]  =0;
+
+            if (use_rev_bit)
+            {
+                ucRev_Bit0[u1DQSIdx] = 1;
+                ucRev_Bit1[u1DQSIdx] = 0;
+            }
+        }
+        else if(scDutyDelay[u1DQSIdx] >0)
+        {
+            u1Delay[u1DQSIdx]  = 0;
+            u1DelayB[u1DQSIdx]  = scDutyDelay[u1DQSIdx];
+
+            if (use_rev_bit)
+            {
+                ucRev_Bit0[u1DQSIdx] = 0;
+                ucRev_Bit1[u1DQSIdx] = 1;
+            }
+        }
+        else
+        {
+            u1Delay[u1DQSIdx]  = 0;
+            u1DelayB[u1DQSIdx]  =0;
+
+            if (use_rev_bit)
+            {
+                ucRev_Bit0[u1DQSIdx] = 0;
+                ucRev_Bit1[u1DQSIdx] = 0;
+            }
+        }
+    }
+
+#if DUTY_SCAN_V2_ONLY_K_HIGHEST_FREQ
+    for(u1ShuffleIdx = 0; u1ShuffleIdx<DRAM_DFS_SHUFFLE_MAX; u1ShuffleIdx++)
+#endif
+    {
+        for(u1RankIdx = 0; u1RankIdx<RANK_MAX; u1RankIdx++)
+        {
+            for(u1DQSIdx = 0; u1DQSIdx<2; u1DQSIdx++)
+            {
+                save_offset = u1ShuffleIdx * SHU_GRP_DDRPHY_OFFSET + u1RankIdx*0x100 + u1DQSIdx*0x50;
+                vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ1) + save_offset, P_Fld(u1Delay[u1DQSIdx], SHU1_R0_B0_DQ1_RK0_TX_ARDQS0_DLY_B0) | P_Fld(u1Delay[u1DQSIdx], SHU1_R0_B0_DQ1_RK0_TX_ARDQS0B_DLY_B0));
+                vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ1) + save_offset, P_Fld(u1DelayB[u1DQSIdx], SHU1_R0_B0_DQ1_RK0_TX_ARDQS0_DLYB_B0) | P_Fld(u1DelayB[u1DQSIdx], SHU1_R0_B0_DQ1_RK0_TX_ARDQS0B_DLYB_B0));
+
+// Lau_rel like Mer_lot, no need to set this to big scale mode, just use small scale mode
+                    save_offset = u1ShuffleIdx * SHU_GRP_DDRPHY_OFFSET + u1DQSIdx*0x80;
+                    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DLL1) + save_offset, P_Fld(ucRev_Bit0[u1DQSIdx], RG_ARDQ_REV_BIT_00_DQS_MCK4X_DLY_EN) | P_Fld(ucRev_Bit1[u1DQSIdx], RG_ARDQ_REV_BIT_01_DQS_MCK4XB_DLY_EN));
+            }
+        }
+    }
+}
+
+
+void DQDQMDutyScan_SetDQDQMDelayCell(DRAMC_CTX_T *p, S8 *scDutyDelay, U8 use_rev_bit, U8 k_type)
+{
+    U8 u1ShuffleIdx = 0, u1DQSIdx;
+    U32 save_offset;
+    U8 u1Delay[2];
+    U8 ucRev_Bit0[2], ucRev_Bit1[2];
+
+//    mcSHOW_DBG_MSG(("CH%d, Final DQS0 duty delay cell = %d\n", p->channel, scDutyDelay[0]));
+//    mcSHOW_DBG_MSG(("CH%d, Final DQS1 duty delay cell = %d\n", p->channel, scDutyDelay[1]));
+
+    for(u1DQSIdx=0; u1DQSIdx<2; u1DQSIdx++)
+    {
+        if(scDutyDelay[u1DQSIdx] <0)
+        {
+            u1Delay[u1DQSIdx] = (-(scDutyDelay[u1DQSIdx])) | (1<<3); //sign bit
+
+            if (use_rev_bit)
+            {
+                ucRev_Bit0[u1DQSIdx] = 0;
+                ucRev_Bit1[u1DQSIdx] = 1;
+            }
+        }
+        else if(scDutyDelay[u1DQSIdx] >0)
+        {
+            u1Delay[u1DQSIdx] = scDutyDelay[u1DQSIdx];
+
+            if (use_rev_bit)
+            {
+                ucRev_Bit0[u1DQSIdx] = 1;
+                ucRev_Bit1[u1DQSIdx] = 0;
+            }
+        }
+        else
+        {
+            u1Delay[u1DQSIdx] = 0;
+
+            if (use_rev_bit)
+            {
+                ucRev_Bit0[u1DQSIdx] = 0;
+                ucRev_Bit1[u1DQSIdx] = 0;
+            }
+        }
+    }
+
+#if DUTY_SCAN_V2_ONLY_K_HIGHEST_FREQ
+    for(u1ShuffleIdx = 0; u1ShuffleIdx<DRAM_DFS_SHUFFLE_MAX; u1ShuffleIdx++)
+#endif
+    {
+        for(u1DQSIdx = 0; u1DQSIdx<2; u1DQSIdx++)
+        {
+            save_offset = u1ShuffleIdx * SHU_GRP_DDRPHY_OFFSET + u1DQSIdx*DDRPHY_AO_B0_B1_OFFSET_0X80;
+
+            if (k_type == DutyScan_Calibration_K_DQM)
+            {
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ10) + save_offset, u1Delay[u1DQSIdx], B0_DQ10_RG_ARDQ_DUTYREV_B0_DQM_DUTY_DELAY);
+
+// Lau_rel like Mer_lot, no need to set this to big scale mode, just use small scale mode
+//                vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ3) + save_offset, P_Fld(ucRev_Bit0[u1DQSIdx], SHU1_B0_DQ3_RG_TX_ARDQS0_PU_B0_BIT0)
+//                                                                        | P_Fld(ucRev_Bit1[u1DQSIdx], SHU1_B0_DQ3_RG_TX_ARDQS0_PU_B0_BIT1));
+            }
+
+            if ((k_type == DutyScan_Calibration_K_DQ) || (k_type == DutyScan_Calibration_K_DQM)) //DQM is special case
+            {
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ10) + save_offset, u1Delay[u1DQSIdx], B0_DQ10_RG_ARDQ_DUTYREV_B0_DQ_DUTY_DELAY);
+
+// Lau_rel like Mer_lot, no need to set this to big scale mode, just use small scale mode
+//                vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ3) + save_offset, P_Fld(ucRev_Bit0[u1DQSIdx], SHU1_B0_DQ3_RG_TX_ARDQS0_PU_PRE_B0_BIT0)
+//                                                                        | P_Fld(ucRev_Bit1[u1DQSIdx], SHU1_B0_DQ3_RG_TX_ARDQS0_PU_PRE_B0_BIT1));
+            }
+        }
+    }
+}
+
+
+// offset is not related to DQ/DQM/DQS
+// we have a circuit to measure duty, But this circuit is not very accurate
+// so we need to K offset of this circuit first
+// After we got this offset, then we can use it to measure duty
+// this offset can measure DQ/DQS/DQM, and every byte has this circuit, too.
+// B0/B1/CA all have one circuit.
+// CA's circuit can measure CLK duty
+// B0/B1's can measure DQ/DQM/DQS duty
+S8 DutyScan_Offset_Convert(U8 val)
+{
+    U8 calibration_sequence[15]={0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7};
+
+    return ((S8)(calibration_sequence[val]>8 ? 0-(calibration_sequence[val]&0x7) : calibration_sequence[val]));
+
+}
+void DutyScan_Offset_Calibration(DRAMC_CTX_T *p)
+{
+    U8 calibration_sequence[15]={0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7};
+    U8 i, read_val_b0, read_val_b1, read_val_ca;
+    U8 cal_i_b0=0xff, cal_i_b1=0xff, cal_i_ca=0xff;
+
+#if VENDER_JV_LOG
+        vPrintCalibrationBasicInfo_ForJV(p);
+#else
+        vPrintCalibrationBasicInfo(p);
+#endif
+
+#if DutyPrintCalibrationLog
+    mcSHOW_DBG_MSG(("[Duty_Offset_Calibration]\n\n"));
+#endif
+
+    //B0
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ6), P_Fld(1, B0_DQ6_RG_RX_ARDQ_LPBK_EN_B0) | P_Fld(0, B0_DQ6_RG_RX_ARDQ_DDR4_SEL_B0) | P_Fld(1, B0_DQ6_RG_RX_ARDQ_DDR3_SEL_B0));
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DLL1), P_Fld(1, RG_ARDQ_REV_BIT_20_DATA_SWAP_EN) | P_Fld(2, RG_ARDQ_REV_BIT_2221_DATA_SWAP));
+//    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ3), P_Fld(1, SHU1_B0_DQ3_DQ_REV_B0_BIT_06) | P_Fld(0, SHU1_B0_DQ3_DQ_REV_B0_BIT_05) | P_Fld(1, SHU1_B0_DQ3_DQ_REV_B0_BIT_04));
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ5), P_Fld(0, SHU1_B0_DQ5_RG_RX_ARDQ_VREF_BYPASS_B0) | P_Fld(0xB, SHU1_B0_DQ5_RG_RX_ARDQ_VREF_SEL_B0));
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ0), 1, SHU1_B0_DQ0_RG_TX_ARDQS0_DRVP_PRE_B0_BIT1);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ0), 0, B0_DQ0_RG_RX_ARDQ2_OFFC_B0);
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), P_Fld(1, B0_DQ5_RG_RX_ARDQ_VREF_EN_B0) | P_Fld(0x1, B0_DQ5_RG_RX_ARDQ_EYE_VREF_EN_B0));
+    mcDELAY_US(1);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ0), 1, SHU1_B0_DQ0_RG_TX_ARDQS0_DRVP_PRE_B0_BIT2);
+
+    //B1
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ6), P_Fld(1, B1_DQ6_RG_RX_ARDQ_LPBK_EN_B1) | P_Fld(0, B1_DQ6_RG_RX_ARDQ_DDR4_SEL_B1) | P_Fld(1, B1_DQ6_RG_RX_ARDQ_DDR3_SEL_B1));
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DLL1), P_Fld(1, RG_ARDQ_REV_BIT_20_DATA_SWAP_EN) | P_Fld(2, RG_ARDQ_REV_BIT_2221_DATA_SWAP));
+//    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ3), P_Fld(1, SHU1_B1_DQ3_DQ_REV_B1_BIT_06) | P_Fld(0, SHU1_B1_DQ3_DQ_REV_B1_BIT_05) | P_Fld(1, SHU1_B1_DQ3_DQ_REV_B1_BIT_04));
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ5), P_Fld(0, SHU1_B1_DQ5_RG_RX_ARDQ_VREF_BYPASS_B1) | P_Fld(0xB, SHU1_B1_DQ5_RG_RX_ARDQ_VREF_SEL_B1));
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ0), 1, SHU1_B1_DQ0_RG_TX_ARDQS0_DRVP_PRE_B1_BIT1);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ0), 0, B1_DQ0_RG_RX_ARDQ2_OFFC_B1);
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), P_Fld(1, B1_DQ5_RG_RX_ARDQ_VREF_EN_B1) | P_Fld(0x1, B1_DQ5_RG_RX_ARDQ_EYE_VREF_EN_B1));
+    mcDELAY_US(1);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ0), 1, SHU1_B1_DQ0_RG_TX_ARDQS0_DRVP_PRE_B1_BIT2);
+
+    //CA
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_CA_CMD6), P_Fld(1, CA_CMD6_RG_RX_ARCMD_LPBK_EN) | P_Fld(0, CA_CMD6_RG_RX_ARCMD_DDR4_SEL) | P_Fld(1, CA_CMD6_RG_RX_ARCMD_DDR3_SEL));
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_DLL1), P_Fld(1, RG_ARCMD_REV_BIT_20_DATA_SWAP_EN) | P_Fld(2, RG_ARCMD_REV_BIT_2221_DATA_SWAP));
+//    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD3), P_Fld(1, SHU1_CA_CMD3_ARCMD_REV_BIT_06) | P_Fld(0, SHU1_CA_CMD3_ARCMD_REV_BIT_05) | P_Fld(1, SHU1_CA_CMD3_ARCMD_REV_BIT_04));
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD5), P_Fld(0, SHU1_CA_CMD5_RG_RX_ARCMD_VREF_BYPASS) | P_Fld(0xB, SHU1_CA_CMD5_RG_RX_ARCMD_VREF_SEL));
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD0), 1, SHU1_CA_CMD0_RG_TX_ARCLK_DRVP_PRE_BIT1);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_CA_CMD0), 0, CA_CMD0_RG_RX_ARCA2_OFFC);
+    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_CA_CMD5), P_Fld(1, CA_CMD5_RG_RX_ARCMD_VREF_EN) | P_Fld(0x1, CA_CMD5_RG_RX_ARCMD_EYE_VREF_EN));
+    mcDELAY_US(1);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD0), 1, SHU1_CA_CMD0_RG_TX_ARCLK_DRVP_PRE_BIT2);
+
+    mcDELAY_US(1);
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ0), 1, SHU1_B0_DQ0_RG_TX_ARDQS0_DRVP_PRE_B0_BIT0);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ0), 1, SHU1_B1_DQ0_RG_TX_ARDQS0_DRVP_PRE_B1_BIT0);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD0), 1, SHU1_CA_CMD0_RG_TX_ARCLK_DRVP_PRE_BIT0);
+
+#if DutyPrintCalibrationLog
+    mcSHOW_DBG_MSG(("\tB0\tB1\tCA\n"));
+    mcSHOW_DBG_MSG(("===========================\n"));
+#endif
+
+    for(i=0; i<15; i++)
+    {
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ0), calibration_sequence[i], B0_DQ0_RG_RX_ARDQ2_OFFC_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ0), calibration_sequence[i], B1_DQ0_RG_RX_ARDQ2_OFFC_B1);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_CA_CMD0), calibration_sequence[i], CA_CMD0_RG_RX_ARCA2_OFFC);
+
+        mcDELAY_US(1);
+
+        read_val_b0 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_AD_RX_DQ_O1), MISC_AD_RX_DQ_O1_AD_RX_ARDQ_O1_B0_BIT2);
+        read_val_b1 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_AD_RX_DQ_O1), MISC_AD_RX_DQ_O1_AD_RX_ARDQ_O1_B1_BIT2);
+        read_val_ca = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_AD_RX_CMD_O1), MISC_AD_RX_CMD_O1_AD_RX_ARCA2_O1);
+
+#if DutyPrintCalibrationLog
+        mcSHOW_DBG_MSG(("%d\t%d\t%d\t%d\n", DutyScan_Offset_Convert(i), read_val_b0, read_val_b1, read_val_ca));
+#endif
+
+        if (read_val_b0 == 0 && cal_i_b0==0xff)
+        {
+            cal_i_b0 = i;
+        }
+
+        if (read_val_b1 == 0 && cal_i_b1==0xff)
+        {
+            cal_i_b1 = i;
+        }
+
+        if (read_val_ca == 0 && cal_i_ca==0xff)
+        {
+            cal_i_ca = i;
+        }
+    }
+
+    if (cal_i_b0==0 || cal_i_b1==0 || cal_i_ca==0)
+    {
+#if DutyPrintCalibrationLog
+        mcSHOW_ERR_MSG(("offset calibration i=-7 and AD_RX_*RDQ_O1_B*<2>/AD_RX_*RCA2_O1 ==0 !!\n"));
+#endif
+#if __ETT__
+        while(1);
+#endif
+    }
+    else
+    if ((read_val_b0==1 && cal_i_b0==0xff) || (read_val_b1==1 && cal_i_b1==0xff) || (read_val_ca==1 && cal_i_ca==0xff))
+    {
+#if DutyPrintCalibrationLog
+        mcSHOW_ERR_MSG(("offset calibration i=7 and AD_RX_*RDQ_O1_B*<2>/AD_RX_*RCA2_O1 ==1 !!\n"));
+#endif
+#if __ETT__
+        while(1);
+#endif
+
+    }
+    else
+    {
+#if DutyPrintCalibrationLog
+        mcSHOW_DBG_MSG(("===========================\n"));
+        mcSHOW_DBG_MSG(("\tB0:%d\tB1:%d\tCA:%d\n",DutyScan_Offset_Convert(cal_i_b0),DutyScan_Offset_Convert(cal_i_b1),DutyScan_Offset_Convert(cal_i_ca)));
+#endif
+    }
+
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ0), 0, SHU1_B0_DQ0_RG_TX_ARDQS0_DRVP_PRE_B0_BIT0);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ0), 0, SHU1_B1_DQ0_RG_TX_ARDQS0_DRVP_PRE_B1_BIT0);
+    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD0), 0, SHU1_CA_CMD0_RG_TX_ARCLK_DRVP_PRE_BIT0);
+
+    if (cal_i_b0!=0xff) vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ0), calibration_sequence[cal_i_b0], B0_DQ0_RG_RX_ARDQ2_OFFC_B0);
+    if (cal_i_b1!=0xff) vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ0), calibration_sequence[cal_i_b1], B1_DQ0_RG_RX_ARDQ2_OFFC_B1);
+    if (cal_i_ca!=0xff) vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_CA_CMD0), calibration_sequence[cal_i_ca], CA_CMD0_RG_RX_ARCA2_OFFC);
+
+    return;
+}
+
+#if defined(YH_SWEEP_IC)
+typedef struct _YH_SWEEP_IC_T
+{
+    U32 maxduty;
+    U32 minduty;
+    U32 dutydiff;
+    U32 avgduty;
+} YH_SWEEP_IC_T;
+
+YH_SWEEP_IC_T gYH_Sweep_IC_test_result[4][CHANNEL_NUM][DQS_NUMBER];
+
+#define YH_SWEEP_IC_PASS_CRITERIO 1 // 0: FT  1: SLT
+void YH_Sweep_IC_Print_Result(DRAMC_CTX_T *p)
+{
+    U8 u1ChannelIdx, u1ByteIdx, k_type;
+    U8 u1ByteIdxNum;
+
+    //  SLT:
+    //        CHB CLK duty max-min j5.3%: FAIL0
+    //        NDQS duty max-min j5.8%: FAIL1
+    //        NDQDQM maxduty j54.5% or min_duty<45.5% or max-min j5.8%: FAIL2
+
+    mcSHOW_ERR_MSG(("\n\n YH Sweep IC Print Result =========\n"));
+
+    for(k_type=0; k_type<4; k_type++)
+    {
+
+        if (k_type == DutyScan_Calibration_K_CLK) u1ByteIdxNum = 1;
+        else u1ByteIdxNum = 2;
+
+        for(u1ChannelIdx=0; u1ChannelIdx<CHANNEL_NUM; u1ChannelIdx++)
+                for(u1ByteIdx=0; u1ByteIdx<u1ByteIdxNum; u1ByteIdx++)
+                {
+                    if (k_type == DutyScan_Calibration_K_CLK && u1ChannelIdx == CHANNEL_B)
+                    {
+                        mcSHOW_ERR_MSG(("CH%d CLK max-min Duty %d%% : ",u1ChannelIdx, gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].dutydiff));
+#if YH_SWEEP_IC_PASS_CRITERIO
+                        if (gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].dutydiff > 530)
+#else
+                        if (gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].dutydiff > 450)
+#endif
+                        {
+                            mcSHOW_ERR_MSG(("FAIL0\n"));
+                        }
+                        else
+                        {
+                            mcSHOW_ERR_MSG(("PASS\n"));
+                        }
+                    }
+                    if (k_type == DutyScan_Calibration_K_DQS)
+                    {
+                        mcSHOW_ERR_MSG(("CH%d DQS Byte %d max-min Duty %d%% : ",u1ChannelIdx, u1ByteIdx, gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].dutydiff));
+#if YH_SWEEP_IC_PASS_CRITERIO
+                        if (gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].dutydiff > 580)
+#else
+                        if (gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].dutydiff > 500)
+#endif
+                        {
+                            mcSHOW_ERR_MSG(("FAIL1\n"));
+                        }
+                        else
+                        {
+                            mcSHOW_ERR_MSG(("PASS\n"));
+                        }
+                    }
+                    if (k_type == DutyScan_Calibration_K_DQ || k_type == DutyScan_Calibration_K_DQM)
+                    {
+                        mcSHOW_ERR_MSG(("CH%d %s Byte %d max Duty %d%%, min Duty %d%% : ",u1ChannelIdx, k_type == DutyScan_Calibration_K_DQ ? "DQ" : "DQM", u1ByteIdx, gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].maxduty, gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].minduty));
+#if YH_SWEEP_IC_PASS_CRITERIO
+                        if  (gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].minduty < 4550 || gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].maxduty > 5450 || gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].dutydiff > 580)
+#else
+                        if  (gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].minduty < 4600 || gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].maxduty > 5400 || gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].dutydiff > 500)
+#endif
+                        {
+                            mcSHOW_ERR_MSG(("FAIL2\n"));
+                        }
+                        else
+                        {
+                            mcSHOW_ERR_MSG(("PASS\n"));
+                        }
+                    }
+                }
+    }
+}
+#endif
+
+S8 gcFinal_K_CLK_delay_cell[CHANNEL_NUM][DQS_NUMBER];
+S8 gcFinal_K_DQS_delay_cell[CHANNEL_NUM][DQS_NUMBER];
+#if APPLY_DQDQM_DUTY_CALIBRATION
+S8 gcFinal_K_DQ_delay_cell[CHANNEL_NUM][DQS_NUMBER];
+S8 gcFinal_K_DQM_delay_cell[CHANNEL_NUM][DQS_NUMBER];
+#endif
+DRAM_STATUS_T DutyScan_Calibration_Flow(DRAMC_CTX_T *p, U8 k_type, U8 use_rev_bit)
+{
+    S8 scinner_duty_ofst, scFinal_clk_delay_cell[DQS_NUMBER]={0,0};
+    S8 scinner_duty_ofst_start = 0, scinner_duty_ofst_end = 0;
+    S32 s4PICnt, s4PIBegin, s4PIEnd, s4PICnt_mod64;
+    S8 i, swap_idx, ucdqs_i, ucdqs_i_count=2;
+    U8 ucDelay, ucDelayB;
+    U8 ucRev_Bit0=0, ucRev_Bit1=0;
+    U8 ucDelayDQDQM, ucRev_Bit0_DQDQM=0, ucRev_Bit1_DQDQM=0;
+    U32 u4DutyDiff, u4DutyDiff_Limit=900;
+
+    U8 vref_sel_value[2], cal_out_value;
+    S32 duty_value[2];
+    S32 final_duty;
+
+    U32 ucperiod_duty_max=0, ucperiod_duty_min=0xffffffff, ucperiod_duty_max_clk_dly=0, ucperiod_duty_min_clk_dly=0;
+    U32 ucperiod_duty_averige=0, ucFinal_period_duty_averige[DQS_NUMBER]={0,0}, ucmost_approach_50_percent=0xffffffff;
+    U32 ucFinal_period_duty_max[DQS_NUMBER] = {0,0}, ucFinal_period_duty_min[DQS_NUMBER] = {0,0};
+    U32 ucFinal_duty_max_clk_dly[DQS_NUMBER]={0},ucFinal_duty_min_clk_dly[DQS_NUMBER]={0};
+    U8 early_break_count=0;
+    U8 str_clk_duty[]="CLK", str_dqs_duty[]="DQS", str_dq_duty[]="DQ", str_dqm_duty[]="DQM";
+    U8 *str_who_am_I=str_clk_duty;
+
+    mcSHOW_ERR_MSG(("\n[DutyScan_Calibration_Flow] %s Calibration\n", use_rev_bit==0 ? "First" : "Second"));
+    mcSHOW_ERR_MSG(("\n[DutyScan_Calibration_Flow] k_type=%d, use_rev_bit=%d\n", k_type, use_rev_bit));
+    /*TINFO="\n[DutyScan_Calibration_Flow] k_type=%d\n", k_type */
+
+
+    if (k_type == DutyScan_Calibration_K_CLK)
+    {
+#if 0
+        // DQS duty test 3
+        //mcSHOW_ERR_MSG(("\n[*PHDET_EN*=0]\n"));
+        mcSHOW_ERR_MSG(("\n[*PI*RESETB*=0  *PHDET_EN*=0  *PI_RESETB*=1]\n"));
+        /*TINFO="\n[*PI*RESETB*=0  *PHDET_EN*=0  *PI_RESETB*=1]\n" */
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_CA_DLL_ARPI0), 0x0, CA_DLL_ARPI0_RG_ARPI_RESETB_CA);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_CA_DLL_ARPI2), 0x0, CA_DLL_ARPI2_RG_ARDLL_PHDET_EN_CA);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_CA_DLL_ARPI0), 0x1, CA_DLL_ARPI0_RG_ARPI_RESETB_CA);
+#else
+#if DutyPrintCalibrationLog
+        mcSHOW_ERR_MSG(("\n[  *PHDET_EN*=0  \n"));
+#endif
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_CA_DLL_ARPI2), 0x0, CA_DLL_ARPI2_RG_ARDLL_PHDET_EN_CA);
+#endif
+    }
+    else
+    {
+        // DQS duty test 3
+        //mcSHOW_ERR_MSG(("\n[*PHDET_EN*=0]\n"));
+#if DutyPrintCalibrationLog
+        mcSHOW_ERR_MSG(("[*PI*RESETB*=0  *PHDET_EN*=0  *PI_RESETB*=1]\n"));
+#endif
+        /*TINFO="[*PI*RESETB*=0  *PHDET_EN*=0  *PI_RESETB*=1]\n" */
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DLL_ARPI0), 0x0, B0_DLL_ARPI0_RG_ARPI_RESETB_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DLL_ARPI0), 0x0, B1_DLL_ARPI0_RG_ARPI_RESETB_B1);
+
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DLL_ARPI2), 0x0, B0_DLL_ARPI2_RG_ARDLL_PHDET_EN_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DLL_ARPI2), 0x0, B1_DLL_ARPI2_RG_ARDLL_PHDET_EN_B1);
+
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DLL_ARPI0), 0x1, B0_DLL_ARPI0_RG_ARPI_RESETB_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DLL_ARPI0), 0x1, B1_DLL_ARPI0_RG_ARPI_RESETB_B1);
+    }
+
+    //CLK Source Select (DQ/DQM/DQS/CLK)
+    if (k_type == DutyScan_Calibration_K_DQ) // K DQ
+    {
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ8), 0, B0_DQ8_RG_TX_ARDQ_CAP_DET_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DLL1), 0, RG_ARDQ_REV_BIT_06_MCK4X_SEL_DQ1);
+
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ8), 0, B1_DQ8_RG_TX_ARDQ_CAP_DET_B1);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DLL1), 0, RG_ARDQ_REV_BIT_06_MCK4X_SEL_DQ1);
+
+        ucdqs_i_count = 2;
+        str_who_am_I = (U8*)str_dq_duty;
+
+#if APPLY_DQDQM_DUTY_CALIBRATION
+        scinner_duty_ofst_start = -7;
+        scinner_duty_ofst_end = 7;
+#else
+        scinner_duty_ofst_start = 0;
+        scinner_duty_ofst_end = 0;
+#endif
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        p->pSavetimeData->u1dq_use_rev_bit = use_rev_bit;
+#endif
+    }
+    else if (k_type == DutyScan_Calibration_K_DQM) // K DQM
+    {
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ8), 0, B0_DQ8_RG_TX_ARDQ_CAP_DET_B0);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DLL1), 1, RG_ARDQ_REV_BIT_06_MCK4X_SEL_DQ1);
+
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ8), 0, B1_DQ8_RG_TX_ARDQ_CAP_DET_B1);
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DLL1), 1, RG_ARDQ_REV_BIT_06_MCK4X_SEL_DQ1);
+
+        ucdqs_i_count = 2;
+        str_who_am_I = (U8*)str_dqm_duty;
+
+#if APPLY_DQDQM_DUTY_CALIBRATION
+        scinner_duty_ofst_start = -7;
+        scinner_duty_ofst_end = 7;
+#else
+        scinner_duty_ofst_start = 0;
+        scinner_duty_ofst_end = 0;
+#endif
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        p->pSavetimeData->u1dqm_use_rev_bit = use_rev_bit;
+#endif
+    }
+    else if (k_type == DutyScan_Calibration_K_DQS) // K DQS
+    {
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ8), 1, B0_DQ8_RG_TX_ARDQ_CAP_DET_B0);
+
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ8), 1, B1_DQ8_RG_TX_ARDQ_CAP_DET_B1);
+
+        ucdqs_i_count = 2;
+        str_who_am_I = (U8*)str_dqs_duty;
+
+        scinner_duty_ofst_start = DUTY_OFFSET_START;
+        scinner_duty_ofst_end = DUTY_OFFSET_END;
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        p->pSavetimeData->u1dqs_use_rev_bit = use_rev_bit;
+#endif
+    }
+    else if (k_type == DutyScan_Calibration_K_CLK) // K CLK
+    {
+        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_CA_CMD9), 1, CA_CMD9_RG_TX_ARCMD_CAP_DET);
+
+        ucdqs_i_count = 1;
+        str_who_am_I = (U8*)str_clk_duty;
+
+        scinner_duty_ofst_start = DUTY_OFFSET_START;
+        scinner_duty_ofst_end = DUTY_OFFSET_END;
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        p->pSavetimeData->u1clk_use_rev_bit = use_rev_bit;
+#endif
+    }
+
+#if defined(YH_SWEEP_IC) || FT_DSIM_USED
+        scinner_duty_ofst_start=0;
+        scinner_duty_ofst_end=0;
+#endif
+
+#if (fcFOR_CHIP_ID == fcLaurel)
+    if (k_type == DutyScan_Calibration_K_CLK)
+    {
+        u4DutyDiff_Limit = 530;
+    }
+    else
+    {
+        u4DutyDiff_Limit = 580;
+    }
+#endif
+
+#if (fcFOR_CHIP_ID == fcLaurel)
+#if !defined(YH_SWEEP_IC)
+    if (k_type == DutyScan_Calibration_K_CLK && p->channel == CHANNEL_A)
+    {
+        s4PIBegin = 0;
+        s4PIEnd = 0;
+    }
+    else
+#endif
+#endif
+    {
+        s4PIBegin = CLOCK_PI_START;
+        s4PIEnd = CLOCK_PI_END;
+    }
+
+    for(ucdqs_i=0; ucdqs_i<ucdqs_i_count; ucdqs_i++)
+    {
+#if DutyPrintCalibrationLog
+        if (k_type == DutyScan_Calibration_K_CLK)
+        {
+            mcSHOW_ERR_MSG(("\n[CLK Duty scan]\n"));
+            /*TINFO="\n[CLK Duty scan]\n"*/
+        }
+        else
+        {
+            mcSHOW_ERR_MSG(("\n[%s B%d Duty scan]\n", str_who_am_I, ucdqs_i));
+            /*TINFO="\n[%s B%d Duty scan]\n", str_who_am_I, ucdqs_i */
+        }
+#endif
+
+        ucmost_approach_50_percent=0xffffffff;
+        early_break_count=0;
+
+        for(scinner_duty_ofst=scinner_duty_ofst_start; scinner_duty_ofst<=scinner_duty_ofst_end; scinner_duty_ofst++)
+        {
+            ucperiod_duty_max = 0;
+            ucperiod_duty_min = 100000;
+
+            if (scinner_duty_ofst<0)
+            {
+                ucDelay = -scinner_duty_ofst;
+                ucDelayB = 0;
+
+                if (use_rev_bit)
+                {
+                    ucRev_Bit0 = 1;
+                    ucRev_Bit1 = 0;
+                }
+
+                ucDelayDQDQM = (-scinner_duty_ofst) | (1<<3); //sign bit
+                ucRev_Bit0_DQDQM = 0;
+                ucRev_Bit1_DQDQM = 1;
+            }
+            else if (scinner_duty_ofst>0)
+            {
+                ucDelay = 0;
+                ucDelayB= scinner_duty_ofst;
+
+                if (use_rev_bit)
+                {
+                    ucRev_Bit0 = 0;
+                    ucRev_Bit1 = 1;
+                }
+
+                ucDelayDQDQM = scinner_duty_ofst;
+                ucRev_Bit0_DQDQM = 1;
+                ucRev_Bit1_DQDQM = 0;
+            }
+            else
+            {
+                ucDelay = 0;
+                ucDelayB= 0;
+
+                if (use_rev_bit)
+                {
+                    ucRev_Bit0 = 0;
+                    ucRev_Bit1 = 0;
+                }
+
+                ucDelayDQDQM = 0;
+                ucRev_Bit0_DQDQM = 0;
+                ucRev_Bit1_DQDQM = 0;
+            }
+
+            if (k_type == DutyScan_Calibration_K_DQS)
+            {
+                if (ucdqs_i==0)
+                {
+                    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ1), P_Fld(ucDelay, SHU1_R0_B0_DQ1_RK0_TX_ARDQS0_DLY_B0)
+                                                                                | P_Fld(ucDelay, SHU1_R0_B0_DQ1_RK0_TX_ARDQS0B_DLY_B0)
+                                                                                | P_Fld(ucDelayB, SHU1_R0_B0_DQ1_RK0_TX_ARDQS0_DLYB_B0)
+                                                                                | P_Fld(ucDelayB, SHU1_R0_B0_DQ1_RK0_TX_ARDQS0B_DLYB_B0));
+
+// Lau_rel like Mer_lot, no need to set this to big scale mode, just use small scale mode
+                    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DLL1), P_Fld(ucRev_Bit0, RG_ARDQ_REV_BIT_00_DQS_MCK4X_DLY_EN)
+                                                                            | P_Fld(ucRev_Bit1, RG_ARDQ_REV_BIT_01_DQS_MCK4XB_DLY_EN));
+
+                }
+                else
+                {
+                    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ1), P_Fld(ucDelay, SHU1_R0_B1_DQ1_RK0_TX_ARDQS0_DLY_B1)
+                                                                                | P_Fld(ucDelay, SHU1_R0_B1_DQ1_RK0_TX_ARDQS0B_DLY_B1)
+                                                                                | P_Fld(ucDelayB, SHU1_R0_B1_DQ1_RK0_TX_ARDQS0_DLYB_B1)
+                                                                                | P_Fld(ucDelayB, SHU1_R0_B1_DQ1_RK0_TX_ARDQS0B_DLYB_B1));
+
+// Lau_rel like Mer_lot, no need to set this to big scale mode, just use small scale mode
+                    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DLL1), P_Fld(ucRev_Bit0, RG_ARDQ_REV_BIT_00_DQS_MCK4X_DLY_EN)
+                                                                            | P_Fld(ucRev_Bit1, RG_ARDQ_REV_BIT_01_DQS_MCK4XB_DLY_EN));
+                }
+
+            }
+
+            if (k_type == DutyScan_Calibration_K_CLK)
+            {
+                vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD1), P_Fld(ucDelay, SHU1_R0_CA_CMD1_RK0_TX_ARCLK_DLY)
+                                                                            | P_Fld(ucDelay, SHU1_R0_CA_CMD1_RK0_TX_ARCLKB_DLY));
+                vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD0), P_Fld(ucDelayB, SHU1_R0_CA_CMD0_RK0_TX_ARCLK_DLYB)
+                                                                            | P_Fld(ucDelayB, SHU1_R0_CA_CMD0_RK0_TX_ARCLKB_DLYB));
+
+// Lau_rel like Mer_lot, no need to set this to big scale mode, just use small scale mode
+                vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD3), P_Fld(ucRev_Bit0, SHU1_CA_CMD3_RG_TX_ARCMD_PU_BIT0)
+                                                                        | P_Fld(ucRev_Bit1, SHU1_CA_CMD3_RG_TX_ARCMD_PU_BIT1));
+            }
+
+#if APPLY_DQDQM_DUTY_CALIBRATION
+            if (k_type == DutyScan_Calibration_K_DQ || k_type == DutyScan_Calibration_K_DQM)
+            {
+                if (ucdqs_i==0)
+                {
+                    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ10), ucDelayDQDQM, B0_DQ10_RG_ARDQ_DUTYREV_B0_DQ_DUTY_DELAY);
+
+// Lau_rel like Mer_lot, no need to set this to big scale mode, just use small scale mode
+//                    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ3), P_Fld(ucRev_Bit0_DQDQM, SHU1_B0_DQ3_RG_TX_ARDQS0_PU_PRE_B0_BIT0)
+//                                                                      | P_Fld(ucRev_Bit1_DQDQM, SHU1_B0_DQ3_RG_TX_ARDQS0_PU_PRE_B0_BIT1));
+                }
+                else
+                {
+                    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ10), ucDelayDQDQM, B0_DQ10_RG_ARDQ_DUTYREV_B0_DQ_DUTY_DELAY);
+
+// Lau_rel like Mer_lot, no need to set this to big scale mode, just use small scale mode
+//                    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ3), P_Fld(ucRev_Bit0_DQDQM, SHU1_B0_DQ3_RG_TX_ARDQS0_PU_PRE_B0_BIT0)
+//                                                                      | P_Fld(ucRev_Bit1_DQDQM, SHU1_B0_DQ3_RG_TX_ARDQS0_PU_PRE_B0_BIT1));
+                }
+            }
+#endif
+
+            for(s4PICnt=s4PIBegin; s4PICnt<=s4PIEnd; s4PICnt+=CLOCK_PI_STEP)
+            {
+                s4PICnt_mod64 = (s4PICnt+64)&0x3f;//s4PICnt_mod64 = (s4PICnt+64)%64;
+#if DutyPrintAllLog
+                //if(scinner_duty_ofst!=DUTY_OFFSET_START)
+                    mcSHOW_ERR_MSG(("PI= %d\n", s4PICnt_mod64));
+#endif
+
+                if (k_type == DutyScan_Calibration_K_DQS)
+                {
+                    if (ucdqs_i==0)
+                    {
+                        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), s4PICnt_mod64, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+                    }
+                    else
+                    {
+                        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), s4PICnt_mod64, SHU1_R0_B1_DQ7_RK0_ARPI_PBYTE_B1);
+                    }
+                }
+                else
+                if (k_type == DutyScan_Calibration_K_CLK)
+                {
+                    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), s4PICnt_mod64, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK);
+                }
+                else
+                if (k_type == DutyScan_Calibration_K_DQ)
+                {
+                    if (ucdqs_i==0)
+                    {
+                        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), s4PICnt_mod64, SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+                    }
+                    else
+                    {
+                        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), s4PICnt_mod64, SHU1_R0_B1_DQ7_RK0_ARPI_DQ_B1);
+                    }
+                }
+                else
+                if (k_type == DutyScan_Calibration_K_DQM)
+                {
+                    if (ucdqs_i==0)
+                    {
+                        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), s4PICnt_mod64, SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+                    }
+                    else
+                    {
+                        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), s4PICnt_mod64, SHU1_R0_B1_DQ7_RK0_ARPI_DQM_B1);
+                    }
+                }
+
+                for(swap_idx=0; swap_idx<2; swap_idx++)
+                {
+                    if (k_type == DutyScan_Calibration_K_CLK)
+                    {
+                        if (swap_idx==0)
+                        {
+                            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_DLL1), 2, RG_ARCMD_REV_BIT_2221_DATA_SWAP);
+                        }
+                        else
+                        {
+                            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_DLL1), 3, RG_ARCMD_REV_BIT_2221_DATA_SWAP);
+                        }
+
+                        vref_sel_value[swap_idx]= 0;
+                        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD5), vref_sel_value[swap_idx]>>1, SHU1_CA_CMD5_RG_RX_ARCMD_VREF_SEL);
+                        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD0), (vref_sel_value[swap_idx]&1)==1?0:1, SHU1_CA_CMD0_RG_TX_ARCLK_DRVP_PRE_BIT1);
+                    }
+                    else
+                    {
+                        if (ucdqs_i==0)
+                        {
+                            if (swap_idx==0)
+                            {
+                                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DLL1), 2, RG_ARDQ_REV_BIT_2221_DATA_SWAP);
+                            }
+                            else
+                            {
+                                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DLL1), 3, RG_ARDQ_REV_BIT_2221_DATA_SWAP);
+                            }
+
+                            vref_sel_value[swap_idx]= 0;
+                            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ5), vref_sel_value[swap_idx]>>1, SHU1_B0_DQ5_RG_RX_ARDQ_VREF_SEL_B0);
+                            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ0), (vref_sel_value[swap_idx]&1)==1?0:1, SHU1_B0_DQ0_RG_TX_ARDQS0_DRVP_PRE_B0_BIT1);
+                        }
+                        else
+                        {
+                            if (swap_idx==0)
+                            {
+                                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DLL1), 2, RG_ARDQ_REV_BIT_2221_DATA_SWAP);
+                            }
+                            else
+                            {
+                                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DLL1), 3, RG_ARDQ_REV_BIT_2221_DATA_SWAP);
+                            }
+
+                            vref_sel_value[swap_idx]= 0;
+                            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ5), vref_sel_value[swap_idx]>>1, SHU1_B1_DQ5_RG_RX_ARDQ_VREF_SEL_B1);
+                            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ0), (vref_sel_value[swap_idx]&1)==1?0:1, SHU1_B1_DQ0_RG_TX_ARDQS0_DRVP_PRE_B1_BIT1);
+                        }
+                    }
+
+                    for(i=5; i>=0; i--)
+                    {
+                        if (k_type == DutyScan_Calibration_K_CLK)
+                        {
+                            vref_sel_value[swap_idx] |= (1<<i);
+                            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD5), vref_sel_value[swap_idx]>>1, SHU1_CA_CMD5_RG_RX_ARCMD_VREF_SEL);
+                            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD0), (vref_sel_value[swap_idx]&1)==1?0:1, SHU1_CA_CMD0_RG_TX_ARCLK_DRVP_PRE_BIT1);
+
+                            mcDELAY_US(1);
+
+                            cal_out_value = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_AD_RX_CMD_O1), MISC_AD_RX_CMD_O1_AD_RX_ARCA2_O1);
+
+                            if (cal_out_value == 0)
+                            {
+                                vref_sel_value[swap_idx] &= ~(1<<i);
+                            }
+                        }
+                        else
+                        {
+                            if (ucdqs_i==0)
+                            {
+                                vref_sel_value[swap_idx] |= (1<<i);
+                                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ5), vref_sel_value[swap_idx]>>1, SHU1_B0_DQ5_RG_RX_ARDQ_VREF_SEL_B0);
+                                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ0), (vref_sel_value[swap_idx]&1)==1?0:1, SHU1_B0_DQ0_RG_TX_ARDQS0_DRVP_PRE_B0_BIT1);
+
+                                mcDELAY_US(1);
+
+                                cal_out_value = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_AD_RX_DQ_O1), MISC_AD_RX_DQ_O1_AD_RX_ARDQ_O1_B0_BIT2);
+                            }
+                            else
+                            {
+                                vref_sel_value[swap_idx] |= (1<<i);
+                                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ5), vref_sel_value[swap_idx]>>1, SHU1_B1_DQ5_RG_RX_ARDQ_VREF_SEL_B1);
+                                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ0), (vref_sel_value[swap_idx]&1)==1?0:1, SHU1_B1_DQ0_RG_TX_ARDQS0_DRVP_PRE_B1_BIT1);
+
+                                mcDELAY_US(1);
+
+                                cal_out_value = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_AD_RX_DQ_O1), MISC_AD_RX_DQ_O1_AD_RX_ARDQ_O1_B1_BIT2);
+                            }
+
+#if DutyPrintAllLog
+                            //mcSHOW_DBG_MSG(("Fra i=%d vref_sel_value[swap_idx]=%x, cal_out=%d\n",i, vref_sel_value[swap_idx], cal_out_value));
+#endif
+
+                            if (cal_out_value == 0)
+                            {
+                                vref_sel_value[swap_idx] &= ~(1<<i);
+                            }
+                        }
+                    }
+                }
+
+
+                for(swap_idx=0; swap_idx<2; swap_idx++)
+                {
+                    if (vref_sel_value[swap_idx]<=31)
+                    {
+                        duty_value[swap_idx] = (vref_sel_value[swap_idx]-23)*69+5050;
+                    }
+                    else
+                    {
+                        duty_value[swap_idx] = (vref_sel_value[swap_idx]-32)*55+5600;
+                    }
+                }
+
+#if DutyPrintAllLog
+                mcSHOW_ERR_MSG(("\t[%d][%d] B%d : Vref_Sel=0x%x, Swap Vref_Sel=0x%x\n", scinner_duty_ofst, s4PICnt, ucdqs_i, vref_sel_value[0], vref_sel_value[1]));
+                mcSHOW_ERR_MSG(("\t[%d][%d] B%d : duty_value=%d, Swap duty_value=%d\n", scinner_duty_ofst, s4PICnt, ucdqs_i, duty_value[0], duty_value[1]));
+#endif
+
+                final_duty = 5000+((duty_value[0]-duty_value[1])/2);
+
+                if (final_duty > (S32) ucperiod_duty_max)
+                {
+                    ucperiod_duty_max = final_duty;
+                    ucperiod_duty_max_clk_dly = s4PICnt;
+                }
+                if (final_duty < (S32) ucperiod_duty_min)
+                {
+                    ucperiod_duty_min = final_duty;
+                    ucperiod_duty_min_clk_dly = s4PICnt;
+                }
+
+#if DutyPrintAllLog
+                mcSHOW_ERR_MSG(("\t[%d][%d] B%d : Final_Duty=%d\n", scinner_duty_ofst, s4PICnt, ucdqs_i, final_duty));
+#endif
+            }
+
+
+
+            ucperiod_duty_averige = (ucperiod_duty_max + ucperiod_duty_min)>>1;
+
+#if DutyPrintCalibrationLog
+            if (k_type==DutyScan_Calibration_K_CLK)
+            {
+                mcSHOW_ERR_MSG(("[%d] CLK\n",scinner_duty_ofst));
+                /*TINFO="[%d] CLK\n",scinner_duty_ofst */
+            }
+            else
+            {
+                mcSHOW_ERR_MSG(("[%d] %s%d\n",scinner_duty_ofst, str_who_am_I, ucdqs_i));
+                /*TINFO="[%d] %s%d\n",scinner_duty_ofst, str_who_am_I, ucdqs_i */
+            }
+#endif
+
+#if DutyPrintCalibrationLog
+            mcSHOW_ERR_MSG(("\tMAX Duty = %d%%(X100), CLK PI=%d\n",ucperiod_duty_max, ucperiod_duty_max_clk_dly));
+            /*TINFO="\tMAX Duty = %d%%(X100), CLK PI=%d\n",ucperiod_duty_max, ucperiod_duty_max_clk_dly */
+            mcSHOW_ERR_MSG(("\tMIN Duty = %d%%(X100), CLK PI=%d\n",ucperiod_duty_min, ucperiod_duty_min_clk_dly));
+            /*TINFO="\tMIN Duty = %d%%(X100), CLK PI=%d\n",ucperiod_duty_min, ucperiod_duty_min_clk_dly */
+            mcSHOW_ERR_MSG(("\tAVG Duty = %d%%(X100)\n", ucperiod_duty_averige));
+            /*TINFO="\tAVG Duty = %d%%(X100)\n", ucperiod_duty_averige */
+#endif
+
+            if (ucperiod_duty_averige >= ClockDutyMiddleBound)
+            {
+                if ((scinner_duty_ofst<=0 && ((ucperiod_duty_averige-ClockDutyMiddleBound+(ucperiod_duty_max-ucperiod_duty_min)/2) <= ucmost_approach_50_percent)) ||
+                     (scinner_duty_ofst>0 && ((ucperiod_duty_averige-ClockDutyMiddleBound+(ucperiod_duty_max-ucperiod_duty_min)/2) < ucmost_approach_50_percent)))
+                {
+                    ucmost_approach_50_percent = ucperiod_duty_averige-ClockDutyMiddleBound+(ucperiod_duty_max-ucperiod_duty_min)/2;
+                    scFinal_clk_delay_cell[ucdqs_i] = scinner_duty_ofst;
+                    ucFinal_period_duty_averige[ucdqs_i] = ucperiod_duty_averige;
+                    ucFinal_period_duty_max[ucdqs_i] = ucperiod_duty_max;
+                    ucFinal_period_duty_min[ucdqs_i] = ucperiod_duty_min;
+                    ucFinal_duty_max_clk_dly[ucdqs_i] = ucperiod_duty_max_clk_dly;
+                    ucFinal_duty_min_clk_dly[ucdqs_i] = ucperiod_duty_min_clk_dly;
+#if DutyPrintCalibrationLog
+                    mcSHOW_ERR_MSG(("\t!!! ucmost_approach_50_percent = %d%%(X100) !!!\n",ucmost_approach_50_percent));
+                    /*TINFO="!!! ucmost_approach_50_percent = %d%%(X100) !!!\n",ucmost_approach_50_percent */
+#endif
+                    early_break_count = 0;
+                }
+                else
+                {
+                    if (scinner_duty_ofst>0) early_break_count ++;
+#if DutyPrintAllLog==0
+                    if (early_break_count>=2) break; //early break;
+#endif
+                }
+            }
+            else
+            {
+                if ((scinner_duty_ofst<=0 && ((ClockDutyMiddleBound-ucperiod_duty_averige+(ucperiod_duty_max-ucperiod_duty_min)/2) <= ucmost_approach_50_percent)) ||
+                    (scinner_duty_ofst>0 && ((ClockDutyMiddleBound-ucperiod_duty_averige+(ucperiod_duty_max-ucperiod_duty_min)/2) < ucmost_approach_50_percent)))
+                {
+                    ucmost_approach_50_percent = ClockDutyMiddleBound-ucperiod_duty_averige+(ucperiod_duty_max-ucperiod_duty_min)/2;
+                    scFinal_clk_delay_cell[ucdqs_i] = scinner_duty_ofst;
+                    ucFinal_period_duty_averige[ucdqs_i] = ucperiod_duty_averige;
+                    ucFinal_period_duty_max[ucdqs_i] = ucperiod_duty_max;
+                    ucFinal_period_duty_min[ucdqs_i] = ucperiod_duty_min;
+                    ucFinal_duty_max_clk_dly[ucdqs_i] = ucperiod_duty_max_clk_dly;
+                    ucFinal_duty_min_clk_dly[ucdqs_i] = ucperiod_duty_min_clk_dly;
+#if DutyPrintCalibrationLog
+                    mcSHOW_ERR_MSG(("\t!!! ucmost_approach_50_percent = %d%%(X100) !!!\n",ucmost_approach_50_percent));
+                    /*TINFO="!!! ucmost_approach_50_percent = %d%%(X100) !!!\n",ucmost_approach_50_percent */
+#endif
+                    early_break_count = 0;
+                }
+                else
+                {
+                    if (scinner_duty_ofst>0) early_break_count ++;
+#if DutyPrintAllLog==0
+                    if (early_break_count>=2) break; //early break;
+#endif
+                }
+            }
+
+#if DutyPrintCalibrationLog
+            mcSHOW_ERR_MSG(("\n"));
+            /*TINFO="\n" */
+#endif
+        }
+    }
+
+    for(ucdqs_i=0; ucdqs_i<ucdqs_i_count; ucdqs_i++)
+    {
+        //for SLT, use ERR_MSG to force print log
+        if (k_type == DutyScan_Calibration_K_CLK)
+        {
+            mcSHOW_ERR_MSG(("\n==%s ==\n", str_who_am_I, ucdqs_i));
+            /*TINFO="\n==%s ==\n", str_who_am_I */
+        }
+        else
+        {
+            mcSHOW_ERR_MSG(("\n==%s %d ==\n", str_who_am_I, ucdqs_i));
+            /*TINFO="\n==%s %d ==\n", str_who_am_I, ucdqs_i */
+        }
+        mcSHOW_ERR_MSG(("Final %s duty delay cell = %d\n", str_who_am_I, scFinal_clk_delay_cell[ucdqs_i]));
+        /*TINFO="Final %s duty delay cell = %d\n", str_who_am_I, scFinal_clk_delay_cell[ucdqs_i] */
+        mcSHOW_ERR_MSG(("[%d] MAX Duty = %d%%(X100), DQS PI = %d\n",scFinal_clk_delay_cell[ucdqs_i], ucFinal_period_duty_max[ucdqs_i], ucFinal_duty_max_clk_dly[ucdqs_i]));
+        /*TINFO="[%d] MAX Duty = %d%%(X100), DQS PI = %d\n",scFinal_clk_delay_cell[ucdqs_i], ucFinal_period_duty_max[ucdqs_i], ucFinal_duty_max_clk_dly[ucdqs_i] */
+        mcSHOW_ERR_MSG(("[%d] MIN Duty = %d%%(X100), DQS PI = %d\n",scFinal_clk_delay_cell[ucdqs_i], ucFinal_period_duty_min[ucdqs_i], ucFinal_duty_min_clk_dly[ucdqs_i]));
+        /*TINFO="[%d] MIN Duty = %d%%(X100), DQS PI = %d\n",scFinal_clk_delay_cell[ucdqs_i], ucFinal_period_duty_min[ucdqs_i], ucFinal_duty_min_clk_dly[ucdqs_i] */
+        mcSHOW_ERR_MSG(("[%d] AVG Duty = %d%%(X100)\n", scFinal_clk_delay_cell[ucdqs_i], ucFinal_period_duty_averige[ucdqs_i]));
+        /*TINFO="[%d] AVG Duty = %d%%(X100)\n", scFinal_clk_delay_cell[ucdqs_i], ucFinal_period_duty_averige[ucdqs_i] */
+    }
+
+#if FT_DSIM_USED
+    FT_Duty_Compare_PassFail(p->channel, k_type, ucFinal_period_duty_max[0] , ucFinal_period_duty_min[0],ucFinal_period_duty_max[1] , ucFinal_period_duty_min[1]);
+#else
+    for(ucdqs_i=0; ucdqs_i<ucdqs_i_count; ucdqs_i++)
+    {
+        u4DutyDiff = ucFinal_period_duty_max[ucdqs_i] - ucFinal_period_duty_min[ucdqs_i];
+
+#if DQS_DUTY_SLT_CONDITION_TEST
+        if (k_type == DutyScan_Calibration_K_CLK || (k_type == DutyScan_Calibration_K_DQS))
+        {
+            u4DQSDutyDiff_Rec[p->channel][ucdqs_i][u1GlobalTestCnt]=u4DutyDiff;
+
+            u4DQSDutyDutyDly[p->channel][ucdqs_i] = scFinal_clk_delay_cell[ucdqs_i];
+
+            if(u4DutyDiff > u4DQSDutyDiff_Max[p->channel][ucdqs_i])
+                u4DQSDutyDiff_Max[p->channel][ucdqs_i] = u4DutyDiff;
+
+            if(u4DutyDiff < u4DQSDutyDiff_Min[p->channel][ucdqs_i])
+                u4DQSDutyDiff_Min[p->channel][ucdqs_i] = u4DutyDiff;
+
+            u4DQSDutyDiff_Avrg[p->channel][ucdqs_i]  += u4DutyDiff;
+        }
+#endif
+
+#if defined(YH_SWEEP_IC)
+        gYH_Sweep_IC_test_result[k_type][p->channel][ucdqs_i].maxduty = ucFinal_period_duty_max[ucdqs_i];
+        gYH_Sweep_IC_test_result[k_type][p->channel][ucdqs_i].minduty = ucFinal_period_duty_min[ucdqs_i];
+        gYH_Sweep_IC_test_result[k_type][p->channel][ucdqs_i].dutydiff = u4DutyDiff;
+        gYH_Sweep_IC_test_result[k_type][p->channel][ucdqs_i].avgduty = ucFinal_period_duty_averige[ucdqs_i];
+#else
+        if ((((k_type == DutyScan_Calibration_K_CLK) || (k_type == DutyScan_Calibration_K_DQS)) && (u4DutyDiff < u4DutyDiff_Limit)) ||
+#if APPLY_DQDQM_DUTY_CALIBRATION
+           (((k_type == DutyScan_Calibration_K_DQ) || (k_type == DutyScan_Calibration_K_DQM)) && (u4DutyDiff < u4DutyDiff_Limit)))
+#else
+           (((k_type == DutyScan_Calibration_K_DQ) || (k_type == DutyScan_Calibration_K_DQM)) && ((u4DutyDiff < u4DutyDiff_Limit) && (ucFinal_period_duty_averige[ucdqs_i] >= 4550 && ucFinal_period_duty_averige[ucdqs_i] <= 5450))))
+#endif
+        {
+            if (k_type == DutyScan_Calibration_K_CLK)
+            {
+                mcSHOW_ERR_MSG(("\nCH%d %s Duty spec in!! Max-Min= %d%%\n",p->channel, str_who_am_I, u4DutyDiff));
+                /*TINFO="\nCH%d %s Duty spec in!! Max-Min= %d%%\n",p->channel, str_who_am_I, u4DutyDiff */
+            }
+            else
+            {
+                mcSHOW_ERR_MSG(("\nCH%d %s %d Duty spec in!! Max-Min= %d%%\n",p->channel, str_who_am_I, ucdqs_i, u4DutyDiff));
+                /*TINFO="\nCH%d %s %d Duty spec in!! Max-Min= %d%%\n",p->channel, str_who_am_I, ucdqs_i, u4DutyDiff */
+            }
+        }
+        else
+        {
+            if (k_type == DutyScan_Calibration_K_CLK)
+            {
+                mcSHOW_ERR_MSG(("\n\t\t\t\t\t\tCH%d %s Duty spec \033[1;32mout\033[m!! Max-Min= \033[1;32m%d%% >%d%%\033[m\n", p->channel, str_who_am_I, u4DutyDiff, u4DutyDiff_Limit));
+                /*TINFO="\nCH%d %s Duty spec out!! Max-Min= %d%% >8%%\n", p->channel, str_who_am_I, u4DutyDiff */
+            }
+            else
+            {
+                mcSHOW_ERR_MSG(("\n\t\t\t\t\t\tCH%d %s %d Duty spec \033[1;32mout\033[m!! Max-Min= \033[1;32m%d%% >%d%%\033[m\n", p->channel, str_who_am_I, ucdqs_i, u4DutyDiff, u4DutyDiff_Limit));
+                /*TINFO="\nCH%d %s %d Duty spec out!! Max-Min= %d%% >8%%\n", p->channel, str_who_am_I, ucdqs_i, u4DutyDiff */
+            }
+
+            #if defined(SLT)
+                    while(1); //stop here
+            #endif
+
+            #if __ETT__
+
+                #if DQS_DUTY_SLT_CONDITION_TEST
+                retStatus = DRAM_FAIL;
+                #else
+                    while(1); //stop here
+                #endif
+
+            #endif
+        }
+#endif
+    }
+
+#endif
+
+    if (k_type == DutyScan_Calibration_K_DQS)
+    {
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        if(p->femmc_Ready==0)
+        {
+            p->pSavetimeData->s1DQSDuty_clk_delay_cell[p->channel][0] = scFinal_clk_delay_cell[0];
+            p->pSavetimeData->s1DQSDuty_clk_delay_cell[p->channel][1] = scFinal_clk_delay_cell[1];
+        }
+#endif
+
+        // backup final values
+        gcFinal_K_DQS_delay_cell[p->channel][0] = scFinal_clk_delay_cell[0];
+        gcFinal_K_DQS_delay_cell[p->channel][1] = scFinal_clk_delay_cell[1];
+
+        DQSDutyScan_SetDqsDelayCell(p, scFinal_clk_delay_cell, use_rev_bit);
+
+#ifdef FOR_HQA_TEST_USED
+        gFinalDQSDuty[p->channel][0] = scFinal_clk_delay_cell[0];
+        gFinalDQSDuty[p->channel][1] = scFinal_clk_delay_cell[1];
+        gFinalDQSDutyMinMax[p->channel][0][0] = ucFinal_period_duty_min[0];
+        gFinalDQSDutyMinMax[p->channel][0][1] = ucFinal_period_duty_max[0];
+        gFinalDQSDutyMinMax[p->channel][1][0] = ucFinal_period_duty_min[1];
+        gFinalDQSDutyMinMax[p->channel][1][1] = ucFinal_period_duty_max[1];
+#endif
+    }
+
+    if (k_type == DutyScan_Calibration_K_CLK)
+    {
+        DramcClockDutySetClkDelayCell(p, RANK_0, scFinal_clk_delay_cell[0], use_rev_bit);
+        DramcClockDutySetClkDelayCell(p, RANK_1, scFinal_clk_delay_cell[0], use_rev_bit);
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        if(p->femmc_Ready==0)
+        {
+            p->pSavetimeData->s1ClockDuty_clk_delay_cell[p->channel][RANK_0] = scFinal_clk_delay_cell[0];
+            p->pSavetimeData->s1ClockDuty_clk_delay_cell[p->channel][RANK_1] = scFinal_clk_delay_cell[0];
+        }
+#endif
+
+        // backup final values
+        gcFinal_K_CLK_delay_cell[p->channel][0] = scFinal_clk_delay_cell[0];
+        gcFinal_K_CLK_delay_cell[p->channel][1] = scFinal_clk_delay_cell[1];
+
+#ifdef FOR_HQA_TEST_USED
+        gFinalClkDuty[p->channel] = scFinal_clk_delay_cell[0];
+        gFinalClkDutyMinMax[p->channel][0] = ucFinal_period_duty_min[0];
+        gFinalClkDutyMinMax[p->channel][1] = ucFinal_period_duty_max[0];
+#endif
+    }
+
+#if APPLY_DQDQM_DUTY_CALIBRATION
+    if (k_type == DutyScan_Calibration_K_DQ)
+    {
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        if(p->femmc_Ready==0)
+        {
+            p->pSavetimeData->s1DQDuty_clk_delay_cell[p->channel][0] = scFinal_clk_delay_cell[0];
+            p->pSavetimeData->s1DQDuty_clk_delay_cell[p->channel][1] = scFinal_clk_delay_cell[1];
+        }
+#endif
+
+        // backup final values
+        gcFinal_K_DQ_delay_cell[p->channel][0] = scFinal_clk_delay_cell[0];
+        gcFinal_K_DQ_delay_cell[p->channel][1] = scFinal_clk_delay_cell[1];
+
+        DQDQMDutyScan_SetDQDQMDelayCell(p, scFinal_clk_delay_cell, use_rev_bit, DutyScan_Calibration_K_DQ);
+    }
+
+    if (k_type == DutyScan_Calibration_K_DQM)
+    {
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+        if(p->femmc_Ready==0)
+        {
+            p->pSavetimeData->s1DQMDuty_clk_delay_cell[p->channel][0] = scFinal_clk_delay_cell[0];
+            p->pSavetimeData->s1DQMDuty_clk_delay_cell[p->channel][1] = scFinal_clk_delay_cell[1];
+        }
+#endif
+
+        // backup final values
+        gcFinal_K_DQM_delay_cell[p->channel][0] = scFinal_clk_delay_cell[0];
+        gcFinal_K_DQM_delay_cell[p->channel][1] = scFinal_clk_delay_cell[1];
+
+        DQDQMDutyScan_SetDQDQMDelayCell(p, scFinal_clk_delay_cell, use_rev_bit, DutyScan_Calibration_K_DQM);
+    }
+#endif
+
+    DramPhyReset(p);
+
+    mcSHOW_ERR_MSG(("[DutyScan_Calibration_Flow] ====Done====\n"));
+    /*TINFO="[DutyScan_Calibration_Flow] ====Done====\n" */
+
+    return DRAM_OK;
+}
+
+void DramcNewDutyCalibration(DRAMC_CTX_T *p)
+{
+    U8 u1backup_channel;
+
+#if(DQS_DUTY_SLT_CONDITION_TEST)
+        U16 u2TestCnt, u2FailCnt=0, u2TestCntTotal =20; //fra 400;
+        U8 u1ByteIdx, u1PI_FB;
+        U32 u4Variance;
+#endif
+    U8 use_rev_bit=0;
+
+    DRAM_STATUS_T u2FailStatusByCh[CHANNEL_NUM]={DRAM_OK,DRAM_OK};
+
+    //backup register value
+#if FT_DSIM_USED==0
+    U32 u4RegBackupAddress[] =
+    {
+        (DDRPHY_B0_DQ6),
+        (DDRPHY_SHU1_B0_DLL1),
+        (DDRPHY_SHU1_B0_DQ5),
+        (DDRPHY_SHU1_B0_DQ0),
+        (DDRPHY_B0_DQ0),
+        (DDRPHY_B0_DQ5),
+        (DDRPHY_B0_DQ8),
+        (DDRPHY_SHU1_R0_B0_DQ7),
+        (DDRPHY_B0_DLL_ARPI0),
+        (DDRPHY_B0_DLL_ARPI2),
+
+        (DDRPHY_B1_DQ6),
+        (DDRPHY_SHU1_B1_DLL1),
+        (DDRPHY_SHU1_B1_DQ5),
+        (DDRPHY_SHU1_B1_DQ0),
+        (DDRPHY_B1_DQ0),
+        (DDRPHY_B1_DQ5),
+        (DDRPHY_B1_DQ8),
+        (DDRPHY_SHU1_R0_B1_DQ7),
+        (DDRPHY_B1_DLL_ARPI0),
+        (DDRPHY_B1_DLL_ARPI2),
+
+
+        (DDRPHY_CA_CMD6),
+        (DDRPHY_SHU1_CA_DLL1),
+        (DDRPHY_SHU1_CA_CMD5),
+        (DDRPHY_SHU1_CA_CMD0),
+        (DDRPHY_CA_CMD0),
+        (DDRPHY_CA_CMD5),
+        (DDRPHY_CA_CMD9),
+//        (DDRPHY_SHU1_CA_CMD3),
+        (DDRPHY_SHU1_R0_CA_CMD9),
+        (DDRPHY_CA_DLL_ARPI0),
+        (DDRPHY_CA_DLL_ARPI2),
+
+
+
+        (DDRPHY_B0_DQ6 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_SHU1_B0_DLL1 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_SHU1_B0_DQ5 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_SHU1_B0_DQ0 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_B0_DQ0 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_B0_DQ5 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_B0_DQ8 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_SHU1_R0_B0_DQ7 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_B0_DLL_ARPI0 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_B0_DLL_ARPI2 + SHIFT_TO_CHB_ADDR),
+
+        (DDRPHY_B1_DQ6 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_SHU1_B1_DLL1 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_SHU1_B1_DQ5 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_SHU1_B1_DQ0 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_B1_DQ0 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_B1_DQ5 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_B1_DQ8 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_SHU1_R0_B1_DQ7 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_B1_DLL_ARPI0 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_B1_DLL_ARPI2 + SHIFT_TO_CHB_ADDR),
+
+
+        (DDRPHY_CA_CMD6 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_SHU1_CA_DLL1 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_SHU1_CA_CMD5 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_SHU1_CA_CMD0 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_CA_CMD0 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_CA_CMD5 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_CA_CMD9 + SHIFT_TO_CHB_ADDR),
+//        (DDRPHY_SHU1_CA_CMD3 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_SHU1_R0_CA_CMD9 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_CA_DLL_ARPI0 + SHIFT_TO_CHB_ADDR),
+        (DDRPHY_CA_DLL_ARPI2 + SHIFT_TO_CHB_ADDR)
+    };
+#endif
+
+#if !FT_DSIM_USED
+#if DUTY_SCAN_V2_ONLY_K_HIGHEST_FREQ
+    if((p->frequency == u2DFSGetHighestFreq(p)) && (Get_PRE_MIOCK_JMETER_HQA_USED_flag()==0))
+#else
+    if(Get_PRE_MIOCK_JMETER_HQA_USED_flag()==0)
+#endif
+#endif
+    {
+        if(u1IsLP4Family(p->dram_type))
+        {
+            U8 u1ChannelIdx;
+            u1backup_channel = vGetPHY2ChannelMapping(p);
+
+            #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+            if(p->femmc_Ready==1)
+            {
+                for(u1ChannelIdx=CHANNEL_A; u1ChannelIdx<p->support_channel_num; u1ChannelIdx++)
+                {
+                    vSetPHY2ChannelMapping(p, u1ChannelSet[u1ChannelIdx]);
+                    DramcClockDutySetClkDelayCell(p, RANK_0, p->pSavetimeData->s1ClockDuty_clk_delay_cell[p->channel][RANK_0], p->pSavetimeData->u1clk_use_rev_bit);
+                    DramcClockDutySetClkDelayCell(p, RANK_1, p->pSavetimeData->s1ClockDuty_clk_delay_cell[p->channel][RANK_1], p->pSavetimeData->u1clk_use_rev_bit);
+                    DQSDutyScan_SetDqsDelayCell(p, p->pSavetimeData->s1DQSDuty_clk_delay_cell[p->channel], p->pSavetimeData->u1dqs_use_rev_bit);
+                    #if APPLY_DQDQM_DUTY_CALIBRATION
+                    DQDQMDutyScan_SetDQDQMDelayCell(p, p->pSavetimeData->s1DQMDuty_clk_delay_cell[p->channel], p->pSavetimeData->u1dqm_use_rev_bit, DutyScan_Calibration_K_DQM);
+                    DQDQMDutyScan_SetDQDQMDelayCell(p, p->pSavetimeData->s1DQDuty_clk_delay_cell[p->channel], p->pSavetimeData->u1dq_use_rev_bit, DutyScan_Calibration_K_DQ);
+                    #endif
+                }
+                vSetPHY2ChannelMapping(p, u1backup_channel);
+                return;
+            }
+            else
+            #endif
+            {
+                //Clk free run
+                EnableDramcPhyDCM(p, 0);
+
+                for(u1ChannelIdx=CHANNEL_A; u1ChannelIdx<p->support_channel_num; u1ChannelIdx++)
+                {
+                    vSetPHY2ChannelMapping(p, u1ChannelSet[u1ChannelIdx]);
+
+                //Fix rank to rank0
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANK);
+                vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 1, RKCFG_TXRANKFIX);
+
+                    //backup register value
+                    #if FT_DSIM_USED==0
+                    DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+                    #endif
+
+                    DutyScan_Offset_Calibration(p);
+
+                            #if defined(YH_SWEEP_IC)
+                                if (p->channel == CHANNEL_B)
+                                {
+                                    u2FailStatusByCh[u1ChannelSet[u1ChannelIdx]]= DutyScan_Calibration_Flow(p, DutyScan_Calibration_K_CLK, 0);
+
+                                    if (gcFinal_K_CLK_delay_cell[p->channel][0] == 8 || gcFinal_K_CLK_delay_cell[p->channel][0] == -8)
+                                    {
+                                        u2FailStatusByCh[u1ChannelIdx]= DutyScan_Calibration_Flow(p, DutyScan_Calibration_K_CLK, 1);
+                                    }
+                                }
+                            #else
+                                u2FailStatusByCh[u1ChannelSet[u1ChannelIdx]]= DutyScan_Calibration_Flow(p, DutyScan_Calibration_K_CLK, 0);
+
+                                if (gcFinal_K_CLK_delay_cell[p->channel][0] == 8 || gcFinal_K_CLK_delay_cell[p->channel][0] == -8)
+                                {
+                                    u2FailStatusByCh[u1ChannelIdx]= DutyScan_Calibration_Flow(p, DutyScan_Calibration_K_CLK, 1);
+                                }
+                            #endif
+
+                                u2FailStatusByCh[u1ChannelSet[u1ChannelIdx]]= DutyScan_Calibration_Flow(p, DutyScan_Calibration_K_DQS, 0);
+                                use_rev_bit=0;
+
+                                if (gcFinal_K_DQS_delay_cell[p->channel][0] == 8 || gcFinal_K_DQS_delay_cell[p->channel][0] == -8 || gcFinal_K_DQS_delay_cell[p->channel][1] == 8 || gcFinal_K_DQS_delay_cell[p->channel][1] == -8)
+                                {
+                                    u2FailStatusByCh[u1ChannelIdx]= DutyScan_Calibration_Flow(p, DutyScan_Calibration_K_DQS, 1);
+                                    use_rev_bit=1;
+                                }
+
+                            #if defined(APPLY_DQDQM_DUTY_CALIBRATION)
+                                u2FailStatusByCh[u1ChannelSet[u1ChannelIdx]]|= DutyScan_Calibration_Flow(p, DutyScan_Calibration_K_DQM, 0);
+
+                                u2FailStatusByCh[u1ChannelSet[u1ChannelIdx]]|= DutyScan_Calibration_Flow(p, DutyScan_Calibration_K_DQ, 0);
+                            #endif
+                    #if FT_DSIM_USED==0
+                    //restore to orignal value
+                    DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+                    #endif
+
+                    //Set K DQS MCK4X_DLY_EN and MCK4XB_DLY_EN again, this is especially for K DQS because other bit fields need to be restored.
+                    DQSDutyScan_SetDqsDelayCell(p, gcFinal_K_DQS_delay_cell[p->channel], use_rev_bit);
+
+                    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANK);
+                    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANKFIX);
+                }
+            }
+
+            vSetPHY2ChannelMapping(p, u1backup_channel);
+        }
+
+#if !FT_DSIM_USED
+#if defined(YH_SWEEP_IC)
+        YH_Sweep_IC_Print_Result(p);
+        while(1); //stop here
+#endif
+#endif
+    }
+}
+#endif
+
+
+#ifdef ENABLE_MIOCK_JMETER
+/* "picoseconds per delay cell" depends on Vcore only (frequency doesn't matter)
+ * 1. Retrieve current freq's vcore voltage using pmic API
+ * 2. Perform delay cell time calculation (Bypass if shuffle vcore value is the same as before)
+ */
+static void GetVcoreDelayCellTime(DRAMC_CTX_T *p, U8 shuffleIdx)
+{
+    U32 channel_i;
+
+#if __ETT__
+    static U32 u4previousVcore = 0;
+
+#if (FOR_DV_SIMULATION_USED==0 && SW_CHANGE_FOR_SIMULATION==0)
+    u4gVcore[shuffleIdx] = pmic_vcore_voltage_read();
+#endif
+
+    /* delay cell calculation is skipped if vcore is same as previous shuffle's */
+    if (u4gVcore[shuffleIdx] != u4previousVcore)
+    {
+        u4previousVcore = u4gVcore[shuffleIdx];
+        DramcMiockJmeter(p);
+    }
+#else
+        DramcMiockJmeter(p);
+#endif
+
+    for(channel_i=CHANNEL_A; channel_i < p->support_channel_num; channel_i++)
+    {
+        ucg_num_dlycell_perT_all[shuffleIdx][u1ChannelSet[channel_i]] = ucg_num_dlycell_perT;
+        u2gdelay_cell_ps_all[shuffleIdx][u1ChannelSet[channel_i]] = u2gdelay_cell_ps;
+    }
+#if __ETT__
+    mcSHOW_DBG_MSG(("Freq=%d, CH_%d, VCORE=%d, cell=%d\n", p->frequency, p->channel, u4gVcore[shuffleIdx], u2gdelay_cell_ps_all[shuffleIdx][p->channel]));
+#endif
+
+    return;
+}
+
+
+void DramcMiockJmeterHQA(DRAMC_CTX_T *p)
+{
+    //do MiockJitterMeter@DDR2667
+    U8 shuffleIdx;
+
+    mcSHOW_DBG_MSG(("[MiockJmeterHQA]\n"));
+
+    shuffleIdx = get_shuffleIndex_by_Freq(p);
+
+    if (u1IsLP4Family(p->dram_type))
+    {
+        //if(p->channel == CHANNEL_A)
+        {
+            GetVcoreDelayCellTime(p, shuffleIdx);
+        }
+
+        if((p->support_channel_num != CHANNEL_SINGLE) || (u1ChannelSet[0] == CHANNEL_A))
+            u2gdelay_cell_ps_all[shuffleIdx][CHANNEL_B] = u2gdelay_cell_ps_all[shuffleIdx][CHANNEL_A];
+    }
+#if ENABLE_LP3_SW
+    else
+    {
+        GetVcoreDelayCellTime(p, shuffleIdx);
+    }
+#endif /* ENABLE_LP3_SW */
+
+#ifdef FOR_HQA_TEST_USED
+        if (ucg_num_dlycell_perT_all[shuffleIdx][p->channel] == 0) GetVcoreDelayCellTimeFromTable(p); //lookup table
+#endif
+
+    /* Use highest freq's delay cell time measurement results as reference */
+    p->ucnum_dlycell_perT = ucg_num_dlycell_perT_all[shuffleIdx][p->channel];
+    p->u2DelayCellTimex100 = u2gdelay_cell_ps_all[shuffleIdx][p->channel];
+    mcSHOW_DBG_MSG3(("DelayCellTimex100 CH_%d, (VCORE=%d, cell=%d)\n",p->channel, u4gVcore[shuffleIdx], p->u2DelayCellTimex100));
+}
+#endif //#ifdef ENABLE_MIOCK_JMETER
+
+void DramcWriteDBIOnOff(DRAMC_CTX_T *p, U8 onoff)
+{
+    // DRAMC Write-DBI On/Off
+    if(u1IsLP4Family(p->dram_type))
+    {
+        vIO32WriteFldAlign_All(DRAMC_REG_SHU1_WODT, onoff, SHU1_WODT_DBIWR);
+        mcSHOW_DBG_MSG(("DramC Write-DBI %s\n", ((onoff == DBI_ON) ? "on" : "off")));
+    }
+}
+
+void DramcReadDBIOnOff(DRAMC_CTX_T *p, U8 onoff)
+{
+    // DRAMC Read-DBI On/Off
+    if(u1IsLP4Family(p->dram_type))
+    {
+        vIO32WriteFldAlign_All(DDRPHY_SHU1_B0_DQ7, onoff, SHU1_B0_DQ7_R_DMDQMDBI_SHU_B0);
+        vIO32WriteFldAlign_All(DDRPHY_SHU1_B1_DQ7, onoff, SHU1_B1_DQ7_R_DMDQMDBI_SHU_B1);
+        mcSHOW_DBG_MSG(("DramC Read-DBI %s\n", ((onoff == DBI_ON) ? "on" : "off")));
+    }
+}
+#if ENABLE_READ_DBI
+void SetDramModeRegForReadDBIOnOff(DRAMC_CTX_T *p, U8 onoff)
+{
+    if(u1IsLP4Family(p->dram_type))
+	{
+#if MRW_CHECK_ONLY
+        mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
+#endif
+      //mcSHOW_DBG_MSG(("--Fsp%d --\n", p->dram_fsp));
+
+      //DRAM MR3[6] read-DBI On/Off
+      u1MR03Value[p->dram_fsp] = ((u1MR03Value[p->dram_fsp] & 0xbf) | (onoff<<6));
+      DramcModeRegWriteByRank(p, p->rank, 3, u1MR03Value[p->dram_fsp]);
+    }
+}
+#endif
+
+#if ENABLE_WRITE_DBI || TX_K_DQM_WITH_WDBI
+void DramcWriteMinus1MCKForWriteDBI(DRAMC_CTX_T *p, S8 iShiftUI)
+{
+  //U8 ucdq_ui_large_dqs0, ucdq_ui_large_dqs1;
+  //U8 ucdq_final_dqm_ui_large_dqs0, ucdq_final_dqm_ui_large_dqs1;
+  REG_TRANSFER_T TransferReg[2];
+
+  if((u1IsLP4Family(p->dram_type))&&(p->DBI_W_onoff[p->dram_fsp]))
+  {
+    //ucdq_ui_large_dqs0 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), SHURK0_SELPH_DQ0_TXDLY_DQ0);
+    //ucdq_ui_large_dqs1 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), SHURK0_SELPH_DQ0_TXDLY_DQ1);
+    //mcSHOW_DBG_MSG(("Before -1MCK, ucdq_final_ui_large_dqs0 = %d, ucdq_final_ui_large_dqs1 = %d\n", ucdq_ui_large_dqs0, ucdq_ui_large_dqs1));
+    // DQ0
+    TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+    TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_DQ0;
+    TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+    TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_DQ0;
+    ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+
+    // DQ1
+    TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+    TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_DQ1;
+    TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+    TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_DQ1;
+    ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+
+    //ucdq_ui_large_dqs0 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), SHURK0_SELPH_DQ0_TXDLY_DQ0);
+    //ucdq_ui_large_dqs1 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), SHURK0_SELPH_DQ0_TXDLY_DQ1);
+    //mcSHOW_DBG_MSG(("After  -1MCK, ucdq_final_ui_large_dqs0 = %d, ucdq_final_ui_large_dqs1 = %d\n", ucdq_ui_large_dqs0, ucdq_ui_large_dqs1));
+
+
+    //ucdq_final_dqm_ui_large_dqs0 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), SHURK0_SELPH_DQ1_TXDLY_DQM0);
+    //ucdq_final_dqm_ui_large_dqs1 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), SHURK0_SELPH_DQ1_TXDLY_DQM1);
+    //mcSHOW_DBG_MSG(("Before -1MCK, ucdq_final_dqm_ui_large_dqs0 = %d, ucdq_final_dqm_ui_large_dqs1 = %d\n", ucdq_final_dqm_ui_large_dqs0, ucdq_final_dqm_ui_large_dqs1));
+    // DQM0
+    TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+    TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_DQM0;
+    TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+    TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_DQM0;
+    ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+
+    // DQM1
+    TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+    TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_DQM1;
+    TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+    TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_DQM1;
+    ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+    //ucdq_final_dqm_ui_large_dqs0 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), SHURK0_SELPH_DQ1_TXDLY_DQM0);
+    //ucdq_final_dqm_ui_large_dqs1 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), SHURK0_SELPH_DQ1_TXDLY_DQM1);
+    //mcSHOW_DBG_MSG(("After  -1MCK, ucdq_final_dqm_ui_large_dqs0 = %d, ucdq_final_dqm_ui_large_dqs1 = %d\n", ucdq_final_dqm_ui_large_dqs0, ucdq_final_dqm_ui_large_dqs1));
+  }
+}
+
+void SetDramModeRegForWriteDBIOnOff(DRAMC_CTX_T *p, U8 onoff)
+{
+    if(u1IsLP4Family(p->dram_type))
+	{
+#if MRW_CHECK_ONLY
+        mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
+#endif
+        //DRAM MR3[7] write-DBI On/Off
+        u1MR03Value[p->dram_fsp] = ((u1MR03Value[p->dram_fsp] & 0x7F) | (onoff<<7));
+        DramcModeRegWriteByRank(p, p->rank, 3, u1MR03Value[p->dram_fsp]);
+    }
+}
+#endif
+
+#if (SW_CHANGE_FOR_SIMULATION || FOR_DV_SIMULATION_USED)
+void vMR2InitForSimulationTest(DRAMC_CTX_T *p)
+{
+    if(u1IsLP4Family(p->dram_type))
+    {
+    // Dram Init will set MR2's value
+    #if 0
+        if(p->frequency >HIGH_FREQ)
+        {
+            u1MR02Value[p->dram_fsp]  = 0x3f;
+        }
+        else if(p->frequency <=DUAL_FREQ_LOW_LP4)
+        {
+            u1MR02Value[p->dram_fsp]  = 0x1b;
+        }
+        else
+        {
+            u1MR02Value[p->dram_fsp]  = 0x2d;
+        }
+    #endif
+    }
+    #if ENABLE_LP3_SW
+    else
+    {
+        #if SUPPORT_LP3_800
+        if(p->frequency<=400)
+        {
+            u1MR02Value[p->dram_fsp] = 0x18;
+        }
+        else
+        #endif
+        if(p->frequency==533)
+        {
+            u1MR02Value[p->dram_fsp] = 0x16;
+        }
+        else if(p->frequency == 635)
+        {
+            u1MR02Value[p->dram_fsp] = 0x18;
+        }
+        else if(p->frequency == 800)
+        {
+            u1MR02Value[p->dram_fsp] = 0x1a;
+        }
+        else
+        {
+            u1MR02Value[p->dram_fsp] = 0x1c;
+        }
+    }
+    #endif
+}
+#endif
+
+#if ENABLE_WRITE_DBI_Protect
+void ApplyWriteDBIProtect(DRAMC_CTX_T *p, U8 onoff)
+{
+    U8 *uiLPDDR_O1_Mapping;
+    U16 Temp_PinMux_MaskWrite_WriteDBIOn=0;
+    U8 B0_PinMux_MaskWrite_WriteDBIOn=0, B1_PinMux_MaskWrite_WriteDBIOn=0;
+    int DQ_index;
+
+    if(u1IsLP4Family(p->dram_type))
+    {
+        uiLPDDR_O1_Mapping = (U8 *)uiLPDDR4_O1_Mapping_POP[p->channel];
+
+        // Write DMI/DBI Protect Function
+        // Byte0 can not have bit swap between Group1(DQ0/1) and Group2(DQ02~DQ07).
+        // Byte1 can not have bit swap between Group1(DQ8/9) and Group2(DQ10~DQ15).
+        // DBIWR_IMP_EN=1 and DBIWR_PINMUX_EN=1
+        // set DBIWR_OPTB0[7:0] meet with Byte0 pin MUX table.
+        // set DBIWR_OPTB1[7:0] meet with Byte1 pin MUX table.
+
+        for(DQ_index=0; DQ_index<16; DQ_index++)
+        {
+            Temp_PinMux_MaskWrite_WriteDBIOn |= ((0x7C7C >> uiLPDDR_O1_Mapping[DQ_index]) & 0x1) << DQ_index;
+        }
+        B1_PinMux_MaskWrite_WriteDBIOn = (U8)(Temp_PinMux_MaskWrite_WriteDBIOn>>8) & 0xff;
+        B0_PinMux_MaskWrite_WriteDBIOn = (U8) Temp_PinMux_MaskWrite_WriteDBIOn & 0xff;
+
+        vIO32WriteFldMulti_All(DRAMC_REG_ARBCTL, P_Fld(B1_PinMux_MaskWrite_WriteDBIOn, ARBCTL_DBIWR_OPT_B1)
+                                               | P_Fld(B0_PinMux_MaskWrite_WriteDBIOn, ARBCTL_DBIWR_OPT_B0)
+                                               | P_Fld(onoff, ARBCTL_DBIWR_PINMUX_EN)
+                                               | P_Fld(onoff, ARBCTL_DBIWR_IMP_EN));
+    }
+}
+#endif
+
+#if ENABLE_WRITE_DBI
+void ApplyWriteDBIPowerImprove(DRAMC_CTX_T *p, U8 onoff)
+{
+    // set DBIWR_IMP_EN = 1
+    // DBIWR_OPTB0[1:0]=0, DBIWR_OPT_B0[7]=0
+    // DBIWR_OPTB1[1:0]=0, DBIWR_OPT_B1[7]=0
+    if(u1IsLP4Family(p->dram_type))
+    {
+        vIO32WriteFldMulti_All(DRAMC_REG_ARBCTL, P_Fld(0, ARBCTL_DBIWR_OPT_bit15)
+                                           | P_Fld(0, ARBCTL_DBIWR_OPT_bit9_8)
+                                           | P_Fld(0, ARBCTL_DBIWR_OPT_bit7)
+                                           | P_Fld(0, ARBCTL_DBIWR_OPT_bit1_0)
+                                           | P_Fld(onoff, ARBCTL_DBIWR_IMP_EN));
+    }
+}
+#endif
+
+#if SW_CHANGE_FOR_SIMULATION
+void 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_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_NORMAL_MODE;
+    // IC and DRAM read DBI
+    DramConfig.DBI_R_onoff[FSP_0] = 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
+    #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_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;
+
+    DramConfig.enable_rx_scan_vref =DISABLE_VREF_SCAN;
+    DramConfig.enable_tx_scan_vref =DISABLE_VREF_SCAN;
+    //DramConfig.dynamicODT = DISABLE;
+
+    MPLLInit();
+
+    Global_Option_Init(&DramConfig);
+    Global_Option_Init2(&DramConfig);
+
+    // DramC & PHY init for all channels
+    DDRPhyFreqSel(&DramConfig, LP4_DDR1600);
+
+
+#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
+
+    DramcInit(&DramConfig);
+
+    vApplyConfigBeforeCalibration(&DramConfig);
+    vMR2InitForSimulationTest(&DramConfig);
+
+    vSetPHY2ChannelMapping(&DramConfig, DramConfig.channel);
+
+    #if SIMULATION_SW_IMPED
+    if (u1IsLP4Family(DramConfig.dram_type))
+    {
+        DramcSwImpedanceCal(&DramConfig,1, 1);  //within term
+        DramcSwImpedanceCal(&DramConfig,1, 0);  //without term
+    }
+#if ENABLE_LP3_SW
+    else
+    {
+        DramcSwImpedanceCal(&DramConfig,1, 1);  //within term
+    }
+#endif /* ENABLE_LP3_SW */
+    #endif
+
+
+#if SIMULATION_LP4_ZQ
+     if (DramConfig.dram_type == TYPE_LPDDR4 || DramConfig.dram_type == TYPE_LPDDR4X || DramConfig.dram_type == TYPE_LPDDR4P)
+     {
+         DramcZQCalibration(&DramConfig);
+     }
+#endif
+
+    if (u1IsLP4Family(DramConfig.dram_type))
+    {
+        #if SIMUILATION_LP4_CBT
+        CmdBusTrainingLP4(&DramConfig);
+        #endif
+    }
+#if ENABLE_LP3_SW
+    else
+    {
+        #if SIMULATION_LP3_CA_TRAINING
+        vSetRank(DramConfig, RANK_0);
+        CATrainingLP3(&DramConfig);
+        #endif
+    }
+#endif /* ENABLE_LP3_SW */
+
+#if SIMULATION_WRITE_LEVELING
+    DramcWriteLeveling(&DramConfig);
+#endif
+
+    #if SIMULATION_GATING
+    // Gating calibration of single rank
+    DramcRxdqsGatingCal(&DramConfig);
+
+    // Gating calibration of both rank
+    //DualRankDramcRxdqsGatingCal(&DramConfig);
+    #endif
+
+#if SIMUILATION_LP4_RDDQC
+    DramcRxWindowPerbitCal(&DramConfig, 0);
+#endif
+
+    #if SIMULATION_DATLAT
+    // RX Datlat calibration of single rank
+    DramcRxdatlatCal(&DramConfig);
+
+    // RX Datlat calibration of two rank
+    //DramcDualRankRxdatlatCal(&DramConfig);
+    #endif
+
+    #if SIMULATION_RX_PERBIT
+    DramcRxWindowPerbitCal(&DramConfig, 1);
+    #endif
+
+    #if SIMULATION_TX_PERBIT
+    DramcTxWindowPerbitCal(&DramConfig, TX_DQ_DQS_MOVE_DQ_DQM);
+    DramcTxWindowPerbitCal(&DramConfig, TX_DQ_DQS_MOVE_DQ_ONLY);
+    #endif
+
+    #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
+
+    #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 //SW_CHANGE_FOR_SIMULATION
+