/* SPDX-License-Identifier: BSD-3-Clause */

//-----------------------------------------------------------------------------
// Include files
//-----------------------------------------------------------------------------
#include "dramc_common.h"
#include "dramc_int_global.h"
#include "x_hal_io.h"
#include "sv_c_data_traffic.h"
#if (FOR_DV_SIMULATION_USED == 0)
#include "dramc_top.h"
#endif

#define BITMAP_BITS_MAX         128

#define MAX_CLK_PI_DELAY        31

#define PASS_RANGE_NA   0x7fff

#define DIE_NUM_MAX         1
static U8 fgwrlevel_done = 0;

#if __ETT__
U8 gETT_WHILE_1_flag = 1;
#endif
//#define CBT_NEW_PAT_DEBUG

U8 u1MR01Value[FSP_MAX];
U8 u1MR02Value[FSP_MAX];
U8 u1MR03Value[FSP_MAX];
U8 u1MR11Value[FSP_MAX];
U8 u1MR18Value[FSP_MAX];
U8 u1MR19Value[FSP_MAX];
U8 u1MR20Value[FSP_MAX];
U8 u1MR21Value[FSP_MAX];
U8 u1MR22Value[FSP_MAX];
U8 u1MR51Value[FSP_MAX];

U8 u1MR04Value[RANK_MAX];
U8 u1MR13Value[RANK_MAX];
U8 u1MR26Value[RANK_MAX];
U8 u1MR30Value[RANK_MAX];

U8 u1MR12Value[CHANNEL_NUM][RANK_MAX][FSP_MAX];
U8 u1MR14Value[CHANNEL_NUM][RANK_MAX][FSP_MAX];
U16 gu2MR0_Value[RANK_MAX] = {0xffff, 0xffff};

#if PINMUX_AUTO_TEST_PER_BIT_RX
S16 gFinalRXPerbitFirstPass[CHANNEL_NUM][DQ_DATA_WIDTH];
#endif
#if PINMUX_AUTO_TEST_PER_BIT_TX
S16 gFinalTXPerbitFirstPass[CHANNEL_NUM][DQ_DATA_WIDTH];
#endif
#if PINMUX_AUTO_TEST_PER_BIT_CA
S16 gFinalCAPerbitFirstPass[CHANNEL_NUM][RANK_MAX][CATRAINING_NUM_LP4];
#endif

#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_BYTE_NUMBER];
U32 gFinalDQSDutyMinMax[CHANNEL_NUM][DQS_BYTE_NUMBER][2];
#endif

U8 gFinalCBTVrefDQ[CHANNEL_NUM][RANK_MAX];
U8 gFinalRXVrefDQ[CHANNEL_NUM][RANK_MAX][2];
U8 gFinalTXVrefDQ[CHANNEL_NUM][RANK_MAX];

#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;
U8 gEye_Scan_unterm_highest_flag = 0;
#elif  (CFG_DRAM_LOG_TO_STORAGE)
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 = 1;
U8 gRX_EYE_Scan_only_higheset_freq_flag = 1;
U8 gTX_EYE_Scan_flag = 1;
U8 gTX_EYE_Scan_only_higheset_freq_flag = 1;
U8 gEye_Scan_unterm_highest_flag = 0;
#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;
U8 gEye_Scan_unterm_highest_flag = 0;
#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

#ifdef FOR_HQA_REPORT_USED
#if CFG_DRAM_LOG_TO_STORAGE
U8 gHQALog_flag = 1;
#else
U8 gHQALog_flag = 0;
#endif
U16 gHQALOG_RX_delay_cell_ps_075V = 0;
U8 gHQALog_SLT_BIN[DRAM_DFS_SRAM_MAX] = {0};
#endif

#if (TX_AUTO_K_SUPPORT && TX_AUTO_K_WORKAROUND)
U32 u4DQM_MCK_RK1_backup;
U32 u4DQM_UI_RK1_backup;
U32 u4DQM_PI_RK1_backup[2];
U32 u4DQ_MCK_RK1_backup;
U32 u4DQ_UI_RK1_backup;
U32 u4DQ_PI_RK1_backup[2];
#endif

#if SIMULATION_RX_DVS
U8 u1DVS_increase[RANK_MAX][DQS_BYTE_NUMBER];
#endif

//static U8 gu1DieNum[RANK_MAX];
static S32 CATrain_CmdDelay[CHANNEL_NUM][RANK_MAX];
static U32 CATrain_CsDelay[CHANNEL_NUM][RANK_MAX];
//static S8 iFirstCAPass[RANK_MAX][DIE_NUM_MAX][CATRAINING_NUM];
//static S8 iLastCAPass[RANK_MAX][DIE_NUM_MAX][CATRAINING_NUM];

static S32 wrlevel_dqs_final_delay[RANK_MAX][DQS_BYTE_NUMBER];
//static U16 u2rx_window_sum;


U8 gFinalRXVrefDQForSpeedUp[CHANNEL_NUM][RANK_MAX][2][2] = {0};
U32 gDramcImpedanceResult[IMP_VREF_MAX][IMP_DRV_MAX] = {{0,0,0,0},{0,0,0,0},{0,0,0,0}};

S16 gu2RX_DQS_Duty_Offset[DQS_BYTE_NUMBER][2];

#define RX_DELAY_PRE_CAL 1
#if RX_DELAY_PRE_CAL
S16 s2RxDelayPreCal=PASS_RANGE_NA;
#endif

#if MRW_CHECK_ONLY
U16 u2MRRecord[CHANNEL_NUM][RANK_MAX][FSP_MAX][MR_NUM];
#endif
#if MRW_CHECK_ONLY || MRW_BACKUP
U8 gFSPWR_Flag[RANK_MAX]={FSP_0};
#endif

#define IN_CBT  (0)
#define OUT_CBT (1)

#if PRINT_CALIBRATION_SUMMARY
static void vSetCalibrationResult(DRAMC_CTX_T *p, U8 ucCalType, U8 ucResult)
{
    U32 *Pointer_CalExecute,*Pointer_CalResult;
    if (ucCalType == DRAM_CALIBRATION_SW_IMPEDANCE)
    {
        Pointer_CalExecute = &p->SWImpCalExecute;
        Pointer_CalResult = &p->SWImpCalResult;
    }
    else
    {
        Pointer_CalExecute = &p->aru4CalExecuteFlag[p->channel][p->rank];
        Pointer_CalResult = &p->aru4CalResultFlag[p->channel][p->rank];
    }

    if (ucResult == DRAM_FAIL)
    {
        *Pointer_CalExecute |= (1<<ucCalType);
        *Pointer_CalResult |= (1<<ucCalType);
    }
    else if(ucResult == DRAM_OK)
    {
        *Pointer_CalExecute |= (1<<ucCalType);
        *Pointer_CalResult &= (~(1<<ucCalType));
    }
    else if(ucResult == DRAM_FAST_K)
    {
         *Pointer_CalExecute &= (~(1<<ucCalType));
         *Pointer_CalResult &= (~(1<<ucCalType));
    }
    else
    {
          *Pointer_CalExecute &= (~(1<<ucCalType));
          *Pointer_CalResult |= (1<<ucCalType);
    }
}

#if PRINT_CALIBRATION_SUMMARY_FASTK_CHECK
void Fast_K_CheckResult(DRAMC_CTX_T *p, U8 ucCalType)
{
    U32 CheckResult=0xFFFFFFFF;
    U32 debug_cnt[2], u4all_result_R, u4all_result_F;
    BOOL FastK_Check_flag=0;
    U32 *Pointer_FastKExecute,*Pointer_FastKResult;

    Pointer_FastKExecute = &p->FastKExecuteFlag[p->channel][p->rank];
    Pointer_FastKResult = &p->FastKResultFlag[p->channel][p->rank];

    if ((ucCalType==DRAM_CALIBRATION_TX_PERBIT)||(ucCalType==DRAM_CALIBRATION_DATLAT)||(ucCalType==DRAM_CALIBRATION_RX_PERBIT))
    {
        DramcEngine2Init(p, p->test2_1, p->test2_2, TEST_XTALK_PATTERN, 0, TE_NO_UI_SHIFT);
        CheckResult = DramcEngine2Run(p,TE_OP_WRITE_READ_CHECK , TEST_XTALK_PATTERN);
        DramcEngine2End(p);
        FastK_Check_flag=1;
    }
    else if (ucCalType==DRAM_CALIBRATION_RX_RDDQC)
    {
        DramcRxWinRDDQCInit(p);
        CheckResult = DramcRxWinRDDQCRun(p);
        DramcRxWinRDDQCEnd(p);
        FastK_Check_flag=1;
    }
    else if (ucCalType==DRAM_CALIBRATION_GATING)
    {
        DramcEngine2Init(p, 0x55000000, 0xaa000000 |0x23, TEST_AUDIO_PATTERN, 0, TE_NO_UI_SHIFT);


        DramPhyReset(p);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL2), 1,
                MISC_STBCAL2_DQSG_CNT_RST);
        mcDELAY_US(1);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL2), 0,
                MISC_STBCAL2_DQSG_CNT_RST);

        DramcEngine2Run(p, TE_OP_READ_CHECK, TEST_AUDIO_PATTERN);

        debug_cnt[0] = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_CAL_DQSG_CNT_B0));
        debug_cnt[1] = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_CAL_DQSG_CNT_B1));

        //mcSHOW_DBG_MSG((" 0x%X  ",u4DebugCnt))
        if (debug_cnt[0]==0x4646 && debug_cnt[1]==0x4646)
            CheckResult=0;

        DramcEngine2End(p);
        FastK_Check_flag=1;
    }


    if ((FastK_Check_flag==1)&&(CheckResult==0))
    {
        //mcSHOW_DBG_MSG((" [FAST K CHECK]->PASS\n"))
        *Pointer_FastKResult &= (~(1<<ucCalType));
        *Pointer_FastKExecute |= (1<<ucCalType);;
    }
    else if ((FastK_Check_flag==1)&&(CheckResult !=0))
    {
        //mcSHOW_DBG_MSG((" [FAST K CHECK]->FAIL\n"))
        *Pointer_FastKResult |= (1<<ucCalType);
        *Pointer_FastKExecute |= (1<<ucCalType);;
    }
}
#endif

const char *szCalibStatusName[DRAM_CALIBRATION_MAX]=
{
    "SW Impedance     ",
    "DUTY Scan        ",
    "ZQ Calibration   ",
    "Jitter Meter     ",
    "CBT Training     ",
    "Write leveling   ",
    "RX DQS gating    ",
    "RX IN BUFF OFFC  ",
    "RX DQ/DQS(RDDQC) ",
    "TX DQ/DQS        ",
    "RX DATLAT        ",
    "RX DQ/DQS(Engine)",
    "TX OE            ",
};

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_SRAM_MAX; ucFreqIdx++)
    {
        //mcSHOW_DBG_MSG(("==Freqency = %d==\n", get_FreqTbl_by_SRAMIndex(p,ucFreqIdx)->frequency));
        for(ucCHIdx=0; ucCHIdx<p->support_channel_num; ucCHIdx++)
        {
            for(ucRankIdx=0; ucRankIdx<p->support_rank_num; ucRankIdx++)
            {
                u1CalibrationFail =0;
                ucCalExecute_All = p->aru4CalExecuteFlag[ucCHIdx][ucRankIdx];
                ucCalResult_All = p->aru4CalResultFlag[ucCHIdx][ucRankIdx];
                mcSHOW_DBG_MSG(("CH %d, Rank %d\n", 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++)
                {
                    if(ucCalIdx==0)
                    {
                        ucCalExecute = (U8)p->SWImpCalExecute;
                        ucCalResult = (U8)p->SWImpCalResult;
                    }
                    else
                    {
                        ucCalExecute = (U8)((ucCalExecute_All >>ucCalIdx) & 0x1);
                        ucCalResult =  (U8)((ucCalResult_All >>ucCalIdx) & 0x1);
                    }

                    #if PRINT_CALIBRATION_SUMMARY_DETAIL
                    mcSHOW_DBG_MSG(("%s: ", szCalibStatusName[ucCalIdx]))
                    if(ucCalExecute==1 && ucCalResult ==1)
                    {
                        u1CalibrationFail =1;
                        mcSHOW_DBG_MSG(("%s\n", "@_@FAIL@_@"))
#if defined(SLT)
                        mcSHOW_ERR_MSG(("[dramc] DRAM_FATAL_ERR_FLAG = 0x00000001, line: %d\n",__LINE__));
                        while (1);
#endif
                    }
                    else if (ucCalExecute==1 && ucCalResult ==0)
                    {
                    	mcSHOW_DBG_MSG(("%s\n", "PASS"))
                    }
                    else if (ucCalExecute==0 && ucCalResult ==0)
                    {
                    	mcSHOW_DBG_MSG(("%s\n", "FAST K"))
                    }
                    else
                    {
                    	mcSHOW_DBG_MSG(("%s\n", "NO K"))
                    }

                    #else
                    if(ucCalExecute==1 && ucCalResult ==1)
                    {
                        u1CalibrationFail =1;
                        mcSHOW_DBG_MSG(("%s: %s\n", szCalibStatusName[ucCalIdx],"@_@FAIL@_@"))
#if defined(SLT)
                        mcSHOW_ERR_MSG(("[dramc] DRAM_FATAL_ERR_FLAG = 0x00000001, line: %d\n",__LINE__));
                        while (1);
#endif
                    }
                    #endif
                }

                if(u1CalibrationFail ==0)
                {
                	mcSHOW_DBG_MSG(("All Pass.\n"));
                }
                mcSHOW_DBG_MSG(("\n"));
            }
        }
    }

}
#endif

#ifdef DEVIATION
static void DeviationAddVrefOffset(U8 k_type, U16 *u2FinalRange, U16 *u2FinalVref, S8 Vref_Offset)
{
    S16 temp_vref_value;

    if (k_type==Deviation_RX)
    {
        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;
        }
    }
}
void SetDeviationVref(DRAMC_CTX_T *p)
{
    U8 u1ChannelIdx, u1RankIdx;
    U16 deviation_Vref, deviation_Vref_Range;
    U16 temp_Vref;
    U8 backup_channel, backup_rank;

    backup_channel = vGetPHY2ChannelMapping(p);
    backup_rank = u1GetRank(p);

    mcSHOW_DBG_MSG2(("[SetDeviationVref]\n"));
    for(u1ChannelIdx=0; u1ChannelIdx<p->support_channel_num; u1ChannelIdx++)
    {
        vSetPHY2ChannelMapping(p, u1ChannelIdx);
        for(u1RankIdx=0; u1RankIdx<p->support_rank_num; u1RankIdx++)
        {
            vSetRank(p, u1RankIdx);

            if (gSetSpecificedVref_Enable[Deviation_CA]==ENABLE && ((p->channel==gSetSpecificedVref_Channel[Deviation_CA] && p->rank==gSetSpecificedVref_Rank[Deviation_CA]) || gSetSpecificedVref_All_ChRk[Deviation_CA]==ENABLE))
            {
                deviation_Vref = u1MR12Value[p->channel][p->rank][p->dram_fsp]& 0x3f;
                deviation_Vref_Range = (u1MR12Value[p->channel][p->rank][p->dram_fsp]>>6)&0x1;
                DeviationAddVrefOffset(Deviation_CA, &deviation_Vref_Range, &deviation_Vref, gSetSpecificedVref_Vref_Offset[Deviation_CA]);
                temp_Vref= ((deviation_Vref & 0x3f)|((deviation_Vref_Range & 0x1) <<6));
                DramcModeRegWriteByRank(p, p->rank, 12,  temp_Vref);
                u1MR12Value[p->channel][p->rank][p->dram_fsp]=temp_Vref;
                mcSHOW_DBG_MSG2(("CBT Channel%d, Rank%d,  u1MR12Value = 0x%x\n", p->channel, p->rank, u1MR12Value[p->channel][p->rank][p->dram_fsp]));
            }

            if (gSetSpecificedVref_Enable[Deviation_TX]==ENABLE && ((p->channel==gSetSpecificedVref_Channel[Deviation_TX] && p->rank==gSetSpecificedVref_Rank[Deviation_TX]) || gSetSpecificedVref_All_ChRk[Deviation_TX]==ENABLE))
            {
                deviation_Vref = u1MR14Value[p->channel][p->rank][p->dram_fsp]& 0x3f;
                deviation_Vref_Range = (u1MR14Value[p->channel][p->rank][p->dram_fsp]>>6)&0x1;
                DeviationAddVrefOffset(Deviation_TX, &deviation_Vref_Range, &deviation_Vref, gSetSpecificedVref_Vref_Offset[Deviation_TX]);
                temp_Vref= ((deviation_Vref & 0x3f)|((deviation_Vref_Range & 0x1) <<6));
                DramcModeRegWriteByRank(p, p->rank, 14,  temp_Vref);
                u1MR14Value[p->channel][p->rank][p->dram_fsp]=temp_Vref;
                mcSHOW_DBG_MSG2(("TX Channel%d, Rank%d,  u1MR14Value = 0x%x\n", p->channel, p->rank, u1MR14Value[p->channel][p->rank][p->dram_fsp]));
            }


            if (gSetSpecificedVref_Enable[Deviation_RX]==ENABLE && ((p->channel==gSetSpecificedVref_Channel[Deviation_RX] && p->rank==gSetSpecificedVref_Rank[Deviation_RX]) || gSetSpecificedVref_All_ChRk[Deviation_RX]==ENABLE))
            {

                    deviation_Vref = gFinalRXVrefDQ[p->channel][p->rank][BYTE_0];
                    DeviationAddVrefOffset(Deviation_RX, NULL, &deviation_Vref, gSetSpecificedVref_Vref_Offset[Deviation_RX]);
                    gFinalRXVrefDQ[p->channel][p->rank][BYTE_0] = deviation_Vref;
                    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_PHY_VREF_SEL),
                            P_Fld(deviation_Vref, SHU_B0_PHY_VREF_SEL_RG_RX_ARDQ_VREF_SEL_LB_B0) |
                            P_Fld(deviation_Vref, SHU_B0_PHY_VREF_SEL_RG_RX_ARDQ_VREF_SEL_UB_B0));
                    mcSHOW_DBG_MSG2(("RX Channel%d, Rank%d,  RX Vref B0 = 0x%x\n", p->channel, p->rank, gFinalRXVrefDQ[p->channel][p->rank][BYTE_0]));


                    deviation_Vref = gFinalRXVrefDQ[p->channel][p->rank][BYTE_1];
                    DeviationAddVrefOffset(Deviation_RX, NULL, &deviation_Vref, gSetSpecificedVref_Vref_Offset[Deviation_RX]);
                    gFinalRXVrefDQ[p->channel][p->rank][BYTE_1] = deviation_Vref;
                    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_PHY_VREF_SEL),
                            P_Fld(deviation_Vref, SHU_B1_PHY_VREF_SEL_RG_RX_ARDQ_VREF_SEL_LB_B1) |
                            P_Fld(deviation_Vref, SHU_B1_PHY_VREF_SEL_RG_RX_ARDQ_VREF_SEL_UB_B1));
                    mcSHOW_DBG_MSG2(("RX Channel%d, Rank%d,  RX Vref B1 = 0x%x\n", p->channel, p->rank, gFinalRXVrefDQ[p->channel][p->rank][BYTE_1]));
            }
        }
    }
    vSetRank(p, backup_rank);
    vSetPHY2ChannelMapping(p, backup_channel);
}
#endif

void vInitGlobalVariablesByCondition(DRAMC_CTX_T *p)
{
    U8 u1CHIdx, u1RankIdx, u1FSPIdx;

    u1MR01Value[FSP_0] = 0x26;
    u1MR01Value[FSP_1] = 0x56;

    u1MR03Value[FSP_0] = 0x31;
    u1MR03Value[FSP_1] = 0x31;
#ifndef ENABLE_POST_PACKAGE_REPAIR
    u1MR03Value[FSP_0] |= 0x4;
    u1MR03Value[FSP_1] |= 0x4;
#endif
#if ENABLE_WRITE_POST_AMBLE_1_POINT_5_TCK
    u1MR03Value[FSP_1] |= 0x2;
#endif

    u1MR04Value[RANK_0] = 0x3;
    u1MR04Value[RANK_1] = 0x3;


    u1MR21Value[FSP_0] = 0x0;
    u1MR21Value[FSP_1] = 0x0;
    u1MR51Value[FSP_0] = 0x0;
    u1MR51Value[FSP_1] = 0x0;

    for (u1FSPIdx = 0; u1FSPIdx < p->support_fsp_num; u1FSPIdx++)
    {
        u1MR02Value[u1FSPIdx] = 0x1a;
    }

    for (u1CHIdx = 0; u1CHIdx < CHANNEL_NUM; u1CHIdx++)
        for (u1RankIdx = 0; u1RankIdx < RANK_MAX; u1RankIdx++)
            for (u1FSPIdx = 0; u1FSPIdx < p->support_fsp_num; u1FSPIdx++)
            {

                u1MR14Value[u1CHIdx][u1RankIdx][u1FSPIdx] = (u1FSPIdx == FSP_0)? 0x5d: 0x18;
                #if FSP1_CLKCA_TERM
                u1MR12Value[u1CHIdx][u1RankIdx][u1FSPIdx] = (u1FSPIdx == FSP_0)? 0x5d: 0x1b;
                #else
                u1MR12Value[u1CHIdx][u1RankIdx][u1FSPIdx] = 0x5d;
                #endif
                #if MRW_CHECK_ONLY
                for (u1MRIdx = 0; u1MRIdx < MR_NUM; u1MRIdx++)
                    u2MRRecord[u1CHIdx][u1RankIdx][u1FSPIdx][u1MRIdx] = 0xffff;
                #endif
            }

    memset(gu2RX_DQS_Duty_Offset, 0, sizeof(gu2RX_DQS_Duty_Offset));
}

const U8 uiLPDDR4_CA_DRAM_Pinmux[PINMUX_MAX][CHANNEL_NUM][6] =
{
    {

        {
			3, 1, 0, 5, 7, 4
        },

    #if (CHANNEL_NUM>1)

        {
			3, 2, 4, 0, 5, 1
        },
    #endif
    #if (CHANNEL_NUM>2)

        {
			3, 1, 0, 5, 7, 4
        },

        {
			3, 2, 4, 0, 5, 1
        },
    #endif
    },
    {

        {
            5, 2, 1, 3, 4, 0
        },

    #if (CHANNEL_NUM>1)

        {
            0, 2, 1, 3, 4, 5
        },
    #endif
    #if (CHANNEL_NUM>2)

        {
            0, 1, 2, 3, 4, 5
        },

        {
            0, 1, 2, 3, 4, 5
        },
    #endif
    },
    {

        {
            5, 4, 3, 2, 1, 0
        },

    #if (CHANNEL_NUM>1)

        {
            4, 5, 2, 0, 3, 1
        },
    #endif
    #if (CHANNEL_NUM>2)

        {
            5, 4, 0, 2, 1, 3
        },

        {
            3, 5, 2, 4, 0, 1
        },
    #endif
    },
    {

        {
            3, 0, 2, 4, 1, 5
        },

    #if (CHANNEL_NUM>1)

        {
            4, 1, 0, 2, 3, 5
        },
    #endif
    #if (CHANNEL_NUM>2)

        {
            5, 0, 4, 3, 1, 2
        },

        {
            2, 5, 3, 0, 4, 1
        },
    #endif
    },
};


const U8 uiLPDDR4_O1_DRAM_Pinmux[PINMUX_MAX][CHANNEL_NUM][16] =
{
    {

        {
            0, 1, 2, 3, 5, 7, 6, 4,
            9, 8, 13, 15, 10, 14, 11, 12
        },
        #if (CHANNEL_NUM>1)

        {
            0, 1, 5, 4, 3, 7, 6, 2,
            9, 8, 13, 14, 10, 15, 11, 12
        },
        #endif
        #if (CHANNEL_NUM>2)

        {
            0, 1, 2, 3, 5, 7, 6, 4,
            9, 8, 13, 15, 10, 14, 11, 12
        },

        {
			0, 1, 5, 4, 3, 7, 6, 2,
			9, 8, 13, 14, 10, 15, 11, 12
        },
        #endif
    },
    {

        {
            0, 1, 4, 3, 2, 5, 7, 6,
            9, 8, 10, 11, 14, 13, 15, 12
        },
        #if (CHANNEL_NUM>1)

        {
            0, 1, 2, 4, 5, 3, 7, 6,
            8, 9, 10, 11, 15, 14, 13, 12
        },
        #endif
        #if (CHANNEL_NUM>2)

        {
            0, 1, 2, 3, 4, 5, 6, 7,
            8, 9, 10, 11, 12, 13, 14, 15
        },

        {
            0, 1, 2, 3, 4, 5, 6, 7,
            8, 9, 10, 11, 12, 13, 14, 15
        },
        #endif
    },
    {

        {
            0, 1, 3, 6, 4, 7, 2, 5,
            8, 9, 10, 13, 11, 12, 15, 14
        },
        #if (CHANNEL_NUM>1)

        {
            0, 1, 4, 7, 3, 5, 6, 2,
            9, 8, 10, 12, 11, 14, 13, 15
        },
        #endif
        #if (CHANNEL_NUM>2)

        {
            1, 0, 3, 2, 4, 7, 6, 5,
            8, 9, 10, 14, 11, 15, 13, 12
        },

        {
            0, 1, 4, 7, 3, 5, 6, 2,
            9, 8, 10, 12, 11, 14, 13, 15
        },
        #endif
    },
    {

        {
            9, 8, 11, 10, 14, 15, 13, 12,
            0, 1, 7, 6, 4, 5, 2, 3
        },
        #if (CHANNEL_NUM>1)

        {
            8, 9, 11, 10, 12, 14, 13, 15,
            1, 0, 5, 6, 3, 2, 7, 4
        },
        #endif
        #if (CHANNEL_NUM>2)

        {
            0, 1, 7, 6, 4, 5, 2, 3,
            9, 8, 11, 10, 14, 15, 13, 12
        },

        {
            1, 0, 5, 6, 3, 2, 7, 4,
            8, 9, 11, 10, 12, 14, 13, 15
        },
        #endif
    },
};


#if (CA_PER_BIT_DELAY_CELL || PINMUX_AUTO_TEST_PER_BIT_CA)

U8 uiLPDDR4_CA_Mapping_POP[CHANNEL_NUM][6] =
{

    {
		2, 1, 0, 5, 3, 4
    },

#if (CHANNEL_NUM>1)

    {
	3, 5, 1, 0, 2, 4
    },
#endif
#if (CHANNEL_NUM>2)

    {
	2, 1, 0, 5, 3, 4
    },

    {
	3, 5, 1, 0, 2, 4
    },
#endif
};
#endif


U8 uiLPDDR4_O1_Mapping_POP[CHANNEL_NUM][16] =
{

    {
	0, 1, 2, 3, 5, 7, 6, 4,
	9, 8, 13, 15, 10, 14, 11, 12
    },
    #if (CHANNEL_NUM>1)

    {
	0, 1, 5, 4, 3, 7, 6, 2,
	9, 8, 13, 14, 10, 15, 11, 12
    },
    #endif
    #if (CHANNEL_NUM>2)

    {
	0, 1, 2, 3, 5, 7, 6, 4,
	9, 8, 13, 15, 10, 14, 11, 12
    },

    {
	0, 1, 5, 4, 3, 7, 6, 2,
	9, 8, 13, 14, 10, 15, 11, 12
    },
    #endif
};

#ifdef IMPEDANCE_TRACKING_ENABLE
static void ImpedanceTracking_DisImpHw_Setting(DRAMC_CTX_T *p, U8 u1DisImpHw)
{
    vIO32WriteFldMulti(DDRPHY_REG_MISC_SHU_IMPEDAMCE_UPD_DIS1, P_Fld(u1DisImpHw, MISC_SHU_IMPEDAMCE_UPD_DIS1_ODTN_UPD_DIS)
                                                                    | P_Fld(u1DisImpHw, MISC_SHU_IMPEDAMCE_UPD_DIS1_DRVN_UPD_DIS)
                                                                    | P_Fld(u1DisImpHw, MISC_SHU_IMPEDAMCE_UPD_DIS1_DRVP_UPD_DIS)
                                                                    | P_Fld(u1DisImpHw, MISC_SHU_IMPEDAMCE_UPD_DIS1_WCK_ODTN_UPD_DIS)
                                                                    | P_Fld(u1DisImpHw, MISC_SHU_IMPEDAMCE_UPD_DIS1_WCK_DRVN_UPD_DIS)
                                                                    | P_Fld(u1DisImpHw, MISC_SHU_IMPEDAMCE_UPD_DIS1_WCK_DRVP_UPD_DIS)
                                                                    | P_Fld(u1DisImpHw, MISC_SHU_IMPEDAMCE_UPD_DIS1_DQ_ODTN_UPD_DIS)
                                                                    | P_Fld(u1DisImpHw, MISC_SHU_IMPEDAMCE_UPD_DIS1_DQ_DRVN_UPD_DIS)
                                                                    | P_Fld(u1DisImpHw, MISC_SHU_IMPEDAMCE_UPD_DIS1_DQ_DRVP_UPD_DIS)
                                                                    | P_Fld(u1DisImpHw, MISC_SHU_IMPEDAMCE_UPD_DIS1_DQS_ODTN_UPD_DIS)
                                                                    | P_Fld(u1DisImpHw, MISC_SHU_IMPEDAMCE_UPD_DIS1_DQS_DRVN_UPD_DIS)
                                                                    | P_Fld(u1DisImpHw, MISC_SHU_IMPEDAMCE_UPD_DIS1_DQS_DRVP_UPD_DIS)
                                                                    | P_Fld(1, MISC_SHU_IMPEDAMCE_UPD_DIS1_WCK_DRVP_UPD_DIS)
                                                                    | P_Fld(1, MISC_SHU_IMPEDAMCE_UPD_DIS1_WCK_DRVN_UPD_DIS)
                                                                    | P_Fld(1, MISC_SHU_IMPEDAMCE_UPD_DIS1_WCK_ODTN_UPD_DIS));

#if (fcFOR_CHIP_ID == fc8195)

        if (p->DRAMPinmux == PINMUX_DSC){
            vIO32WriteFldAlign(DDRPHY_REG_MISC_SHU_IMPEDAMCE_UPD_DIS1, 1, MISC_SHU_IMPEDAMCE_UPD_DIS1_WCK_ODTN_UPD_DIS);
        }else{
            vIO32WriteFldAlign(DDRPHY_REG_MISC_SHU_IMPEDAMCE_UPD_DIS1, 0, MISC_SHU_IMPEDAMCE_UPD_DIS1_WCK_ODTN_UPD_DIS);
        }
#endif

    vIO32WriteFldAlign(DDRPHY_REG_SHU_MISC_IMPCAL1, (u1DisImpHw? 0x0:0x40), SHU_MISC_IMPCAL1_IMPCALCNT);
    vIO32WriteFldMulti(DDRPHY_REG_SHU_MISC_DRVING1, P_Fld(u1DisImpHw, SHU_MISC_DRVING1_DIS_IMPCAL_HW)
                                                   | P_Fld(u1DisImpHw, SHU_MISC_DRVING1_DIS_IMP_ODTN_TRACK));

    vIO32WriteFldAlign(DDRPHY_REG_SHU_MISC_DRVING2, u1DisImpHw, SHU_MISC_DRVING2_DIS_IMPCAL_ODT_EN);
    vIO32WriteFldAlign(DDRPHY_REG_SHU_CA_CMD12, u1DisImpHw, SHU_CA_CMD12_RG_RIMP_UNTERM_EN);

}
#endif

void vBeforeCalibration(DRAMC_CTX_T *p)
{
    BOOL isLP4_DSC = (p->DRAMPinmux == PINMUX_DSC)?1:0;

#if SIMULATION_RX_DVS || ENABLE_RX_TRACKING
    DramcRxInputDelayTrackingInit_byFreq(p);
#endif

    DramcHWGatingOnOff(p, 0);

    CKEFixOnOff(p, TO_ALL_RANK, CKE_FIXON, TO_ALL_CHANNEL);

#if ENABLE_TMRRI_NEW_MODE
    SetCKE2RankIndependent(p);
#endif


    vIO32WriteFldAlign_All(DRAMC_REG_SHU_TX_SET0, 0x0, SHU_TX_SET0_DBIWR);

#ifdef IMPEDANCE_TRACKING_ENABLE

    U8 u1DisImpHw;
    U32 u4TermFreq, u4WbrBackup;

        u4TermFreq = LP4_MRFSP_TERM_FREQ;

    u1DisImpHw = (p->frequency >= u4TermFreq)? 0: 1;

    u4WbrBackup = GetDramcBroadcast();
    DramcBroadcastOnOff(DRAMC_BROADCAST_ON);
    ImpedanceTracking_DisImpHw_Setting(p, u1DisImpHw);
    DramcBroadcastOnOff(u4WbrBackup);

#endif

    vIO32WriteFldMulti_All(DDRPHY_REG_MISC_CLK_CTRL, P_Fld(0, MISC_CLK_CTRL_DVFS_CLK_MEM_SEL)
                                                    | P_Fld(0, MISC_CLK_CTRL_DVFS_MEM_CK_MUX_UPDATE_EN));


    vIO32WriteFldMulti_All(DRAMC_REG_SHU_ZQ_SET0,
            P_Fld(0x1ff, SHU_ZQ_SET0_ZQCSCNT) |
            P_Fld(0x1b, SHU_ZQ_SET0_TZQLAT));

    if (p->support_channel_num == CHANNEL_SINGLE)
    {

        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_ZQ_SET0), P_Fld(0, ZQ_SET0_ZQCSDUAL) | P_Fld(0x0, ZQ_SET0_ZQCSMASK));
    }
    else if (p->support_channel_num == CHANNEL_DUAL)
    {

        #ifdef ZQCS_ENABLE_LP4


        vIO32WriteFldMulti_All(DRAMC_REG_ZQ_SET0, P_Fld(1, ZQ_SET0_ZQCSDUAL) |
                                               P_Fld(0, ZQ_SET0_ZQCSMASK_OPT) |
                                               P_Fld(0, ZQ_SET0_ZQMASK_CGAR) |
                                               P_Fld(0, ZQ_SET0_ZQCS_MASK_SEL_CGAR));


        vIO32WriteFldAlign(DRAMC_REG_ZQ_SET0 + (CHANNEL_A << POS_BANK_NUM), 1, ZQ_SET0_ZQCSMASK);
        vIO32WriteFldAlign(DRAMC_REG_ZQ_SET0 + SHIFT_TO_CHB_ADDR, 0, ZQ_SET0_ZQCSMASK);


        vIO32WriteFldAlign_All(DRAMC_REG_ZQ_SET0, 0, ZQ_SET0_ZQCS_MASK_SEL);
        #endif
    }
#if (CHANNEL_NUM > 2)
    else if (p->support_channel_num == CHANNEL_FOURTH)
    {

        #ifdef ZQCS_ENABLE_LP4


        vIO32WriteFldMulti_All(DRAMC_REG_ZQ_SET0, P_Fld(1, ZQ_SET0_ZQCSDUAL) |
                                               P_Fld(0, ZQ_SET0_ZQCALL) |
                                               P_Fld(0, ZQ_SET0_ZQ_SRF_OPT) |
                                               P_Fld(0, ZQ_SET0_ZQCSMASK_OPT) |
                                               P_Fld(0, ZQ_SET0_ZQMASK_CGAR) |
                                               P_Fld(0, ZQ_SET0_ZQCS_MASK_SEL_CGAR));


    #if fcFOR_CHIP_ID == fcPetrus
        vIO32WriteFldAlign(DRAMC_REG_ZQ_SET0 + (CHANNEL_A << POS_BANK_NUM), 1, ZQ_SET0_ZQCSMASK);
        vIO32WriteFldAlign(DRAMC_REG_ZQ_SET0 + (CHANNEL_B << POS_BANK_NUM), 0, ZQ_SET0_ZQCSMASK);
        vIO32WriteFldAlign(DRAMC_REG_ZQ_SET0 + (CHANNEL_C << POS_BANK_NUM), 0, ZQ_SET0_ZQCSMASK);
        vIO32WriteFldAlign(DRAMC_REG_ZQ_SET0 + (CHANNEL_D << POS_BANK_NUM), 1, ZQ_SET0_ZQCSMASK);
    #elif (fcFOR_CHIP_ID == fc8195)
        vIO32WriteFldAlign(DRAMC_REG_ZQ_SET0 + (CHANNEL_A << POS_BANK_NUM), 1, ZQ_SET0_ZQCSMASK);
        vIO32WriteFldAlign(DRAMC_REG_ZQ_SET0 + (CHANNEL_B << POS_BANK_NUM), 0, ZQ_SET0_ZQCSMASK);
        vIO32WriteFldAlign(DRAMC_REG_ZQ_SET0 + (CHANNEL_C << POS_BANK_NUM), 1, ZQ_SET0_ZQCSMASK);
        vIO32WriteFldAlign(DRAMC_REG_ZQ_SET0 + (CHANNEL_D << POS_BANK_NUM), 0, ZQ_SET0_ZQCSMASK);
    #endif


        vIO32WriteFldAlign_All(DRAMC_REG_ZQ_SET0, 0, ZQ_SET0_ZQCS_MASK_SEL);
        #endif
    }
#endif


    vIO32WriteFldAlign_All(DDRPHY_REG_SHU_B0_DQ2, 0, SHU_B0_DQ2_RG_ARPI_OFFSET_LAT_EN_B0);
    if (!isLP4_DSC)
        vIO32WriteFldAlign_All(DDRPHY_REG_SHU_B1_DQ2, 0, SHU_B1_DQ2_RG_ARPI_OFFSET_LAT_EN_B1);
    else
        vIO32WriteFldAlign_All(DDRPHY_REG_SHU_CA_CMD2, 0, SHU_CA_CMD2_RG_ARPI_OFFSET_LAT_EN_CA);

#if ENABLE_PA_IMPRO_FOR_TX_AUTOK
    vIO32WriteFldAlign_All(DRAMC_REG_DCM_SUB_CTRL, 0x0, DCM_SUB_CTRL_SUBCLK_CTRL_TX_AUTOK);
#endif

    #if ENABLE_PA_IMPRO_FOR_TX_TRACKING
    vIO32WriteFldAlign_All(DRAMC_REG_DCM_SUB_CTRL, 0, DCM_SUB_CTRL_SUBCLK_CTRL_TX_TRACKING);
    #endif

    vIO32WriteFldAlign_All(DRAMC_REG_DQSOSCR, 0x1, DQSOSCR_DQSOSCRDIS);

    vIO32WriteFldAlign_All(DRAMC_REG_REFCTRL0, 0x1, REFCTRL0_REFDIS);

    vIO32WriteFldAlign_All(DRAMC_REG_SHU_MATYPE, u1MaType, SHU_MATYPE_MATYPE);

    TX_Path_Algorithm(p);
}

void vAfterCalibration(DRAMC_CTX_T *p)
{

#if ENABLE_READ_DBI
    EnableDRAMModeRegReadDBIAfterCalibration(p);
#endif

#if ENABLE_WRITE_DBI
    EnableDRAMModeRegWriteDBIAfterCalibration(p);
#endif

    SetMr13VrcgToNormalOperation(p);


    CKEFixOnOff(p, TO_ALL_RANK, CKE_DYNAMIC, TO_ALL_CHANNEL);

    vIO32WriteFldAlign_All(DRAMC_REG_DUMMY_RD, p->support_rank_num, DUMMY_RD_RANK_NUM);

#if ENABLE_PER_BANK_REFRESH
    DramcSetPerBankRefreshMode(p);
#endif

#if FOR_DV_SIMULATION_USED == 1
    cal_sv_rand_args_t *psra = get_psra();

    if (psra) {
        u1MR03Value[p->dram_fsp] = psra->mr3_value;
    }
#endif


    vIO32WriteFldAlign_All(DDRPHY_REG_MISC_CG_CTRL7, 0, MISC_CG_CTRL7_CK_BFE_DCM_EN);


    vIO32WriteFldAlign_All(DRAMC_REG_TEST2_A4, 4, TEST2_A4_TESTAGENTRKSEL);
    vIO32WriteFldAlign_All(DRAMC_REG_TEST2_A2, 0x20, TEST2_A2_TEST2_OFF);


    vIO32WriteFldAlign_All(DDRPHY_REG_MISC_DUTYSCAN1, 0, MISC_DUTYSCAN1_DQSERRCNT_DIS);


    vIO32WriteFldAlign_All(DDRPHY_REG_MISC_CTRL1, 0, MISC_CTRL1_R_DMSTBENCMP_RK_OPT);
}

static void O1PathOnOff(DRAMC_CTX_T *p, U8 u1OnOff)
{
    BOOL isLP4_DSC = (p->DRAMPinmux == PINMUX_DSC)?1:0;
    #if 0
    const U32 u4O1RegBackupAddress[] =
    {
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_VREF)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_VREF)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_PHY_VREF_SEL)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_PHY_VREF_SEL)),
        (DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ5)),
        (DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ5))
    };
    #endif

    U8 u1VrefSel;

    if (u1OnOff == ON)
    {

        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_VREF), 1, SHU_B0_VREF_RG_RX_ARDQ_VREF_UNTERM_EN_B0);
        if (!isLP4_DSC)
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_VREF), 1, SHU_B1_VREF_RG_RX_ARDQ_VREF_UNTERM_EN_B1);
        else
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_VREF), 1, SHU_CA_VREF_RG_RX_ARCA_VREF_UNTERM_EN_CA);

        u1VrefSel = 0x37;

        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_PHY_VREF_SEL),
                    P_Fld(u1VrefSel, SHU_B0_PHY_VREF_SEL_RG_RX_ARDQ_VREF_SEL_LB_B0) |
                    P_Fld(u1VrefSel, SHU_B0_PHY_VREF_SEL_RG_RX_ARDQ_VREF_SEL_UB_B0));
        if (!isLP4_DSC)
        {
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_PHY_VREF_SEL),
                    P_Fld(u1VrefSel, SHU_B1_PHY_VREF_SEL_RG_RX_ARDQ_VREF_SEL_LB_B1) |
                    P_Fld(u1VrefSel, SHU_B1_PHY_VREF_SEL_RG_RX_ARDQ_VREF_SEL_UB_B1));
        }
        else
        {
            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_PHY_VREF_SEL),
                        P_Fld(u1VrefSel, SHU_CA_PHY_VREF_SEL_RG_RX_ARCA_VREF_SEL_LB) |
                        P_Fld(u1VrefSel, SHU_CA_PHY_VREF_SEL_RG_RX_ARCA_VREF_SEL_UB));
        }
    }


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ6), u1OnOff, B0_DQ6_RG_RX_ARDQ_O1_SEL_B0);
    if (!isLP4_DSC)
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ6), u1OnOff, B1_DQ6_RG_RX_ARDQ_O1_SEL_B1);
    else
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD6), u1OnOff, CA_CMD6_RG_RX_ARCMD_O1_SEL);



    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ3),
                        P_Fld(u1OnOff, B0_DQ3_RG_RX_ARDQ_IN_BUFF_EN_B0) |
                        P_Fld(u1OnOff, B0_DQ3_RG_RX_ARDQS0_IN_BUFF_EN_B0));
    if (!isLP4_DSC)
    {
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ3),
                        P_Fld(u1OnOff, B1_DQ3_RG_RX_ARDQ_IN_BUFF_EN_B1) |
                        P_Fld(u1OnOff, B1_DQ3_RG_RX_ARDQS0_IN_BUFF_EN_B1));
    }
    else
    {
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD3),
                            P_Fld(u1OnOff, CA_CMD3_RG_RX_ARCMD_IN_BUFF_EN) |
                            P_Fld(u1OnOff, CA_CMD3_RG_RX_ARCLK_IN_BUFF_EN));
    }


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_PHY3), u1OnOff, B0_PHY3_RG_RX_ARDQ_BUFF_EN_SEL_B0);
    if (!isLP4_DSC)
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_PHY3), u1OnOff, B1_PHY3_RG_RX_ARDQ_BUFF_EN_SEL_B1);
    else
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_CA_PHY3), u1OnOff, CA_PHY3_RG_RX_ARCA_BUFF_EN_SEL_CA);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_RX_IN_GATE_EN_CTRL),(u1OnOff << 1) | u1OnOff, MISC_RX_IN_GATE_EN_CTRL_FIX_IN_GATE_EN);

    mcDELAY_US(1);
}

static inline u8 get_ca_pi_per_ui(DRAMC_CTX_T *p)
{
        return 32;
}

static int get_capi_max(DRAMC_CTX_T *p)
{
    if (u1IsPhaseMode(p) == TRUE)
    {
        return 32;
    }

    return 64;
}
#if 0
static u8 get_autok_sweep_max_cnt(u8 lenpi, u8 respi)
{
    u8 max;

    lenpi += 1;
    max = 64 / (1 << (respi & 0x3));
    return lenpi > max? max: lenpi;
}



static int cbt_wlev_train_autok(DRAMC_CTX_T *p, ATUOK_MODE_T autok_mode,
        u8 initpi, u8 lenpi, u8 respi,
        u32 *cmp0_array,
        u32 *cmp1_array,
        u8 pin_num)
{
    u8 sweep_max_cnt, i;
    u32 cnt, ready;


    cnt = TIME_OUT_CNT * 3;

    switch (autok_mode){
    case AUTOK_CS:
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL0),
                P_Fld(0, CBT_WLEV_ATK_CTRL0_ARPICS_SW));
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL1),
                P_Fld(0, CBT_WLEV_ATK_CTRL1_UICS_SW));
        break;
    case AUTOK_CA:
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_CA_CMD0),
                P_Fld(0, SHU_R0_CA_CMD0_RG_ARPI_CLK) |
                P_Fld(0, SHU_R0_CA_CMD0_RG_ARPI_CS));
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL0),
                P_Fld(0, CBT_WLEV_ATK_CTRL0_ARPICA_SW));
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL1),
                P_Fld(0, CBT_WLEV_ATK_CTRL1_UICA_SW));
        break;
    case AUTOK_DQS:
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL0),
                P_Fld(0, CBT_WLEV_ATK_CTRL0_ARPIDQS_SW));
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL1),
                P_Fld(0, CBT_WLEV_ATK_CTRL1_UIDQS_SW));
        break;
    }

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL1),
            (get_ca_pi_per_ui(p) == 64) ? 0x1 : 0x0, CBT_WLEV_ATK_CTRL1_CBT_ATK_CA1UI64PI);

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL0),
            0x3, CBT_WLEV_ATK_CTRL0_CBT_WLEV_ATK_INTV);

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL0),
            P_Fld(lenpi, CBT_WLEV_ATK_CTRL0_CBT_WLEV_ATK_LENPI) |
            P_Fld(respi, CBT_WLEV_ATK_CTRL0_CBT_WLEV_ATK_RESPI) |
            P_Fld(initpi, CBT_WLEV_ATK_CTRL0_CBT_WLEV_ATK_INITPI));

    switch (autok_mode){
    case AUTOK_CS:
        if (p->new_cbt_mode)
        {
            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL0),
                    P_Fld(1, CBT_WLEV_ATK_CTRL0_CATRAIN_ATKEN));
        }
        else
        {
            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL0),
                    P_Fld(1, CBT_WLEV_ATK_CTRL0_CSTRAIN_ATKEN));
        }
        break;
    case AUTOK_CA:
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL0),
                P_Fld(1, CBT_WLEV_ATK_CTRL0_CATRAIN_ATKEN));
        break;
    case AUTOK_DQS:
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL0),
                P_Fld(1, CBT_WLEV_ATK_CTRL0_WLEV_ATKEN));
        break;
    }

    do {
        ready = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_STATUS),
                CBT_WLEV_STATUS_CBT_WLEV_ATK_RESPONSE);
        cnt--;
        mcDELAY_US(1);
    }
    #if FOR_DV_SIMULATION_USED
    while (ready == 0);
    #else
    while ((ready == 0) && (cnt > 0));
    #endif

    if (cnt == 0){
        mcSHOW_ERR_MSG(("[cbt_autok] Resp fail (time out) for "))
        switch (autok_mode) {
        case AUTOK_CS:
            mcSHOW_ERR_MSG(("CSTrain\n"));
            break;
        case AUTOK_CA:
            mcSHOW_ERR_MSG(("CATrain\n"));
            break;
        case AUTOK_DQS:
            mcSHOW_ERR_MSG(("DQSTrain\n"));
            break;
        }
    }

    sweep_max_cnt = get_autok_sweep_max_cnt(lenpi, respi);
    for (i = 0; i < pin_num; i++) {
        cmp0_array[i] = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_RESULT0 + i * 8));

        if (sweep_max_cnt > 32) {
            cmp1_array[i] = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_RESULT1 + i * 8));
        } else {
            cmp1_array[i] = 0xFFFFFFFF;
        }
    }

    for (i = 0; i < pin_num; i++) {
        mcSHOW_DBG_MSG4(("cmp0[%d]=0x%x, cmp1[%d]=0x%x\n",
                i, cmp0_array[i],
                i, cmp1_array[i]));
    }

    switch (autok_mode){
    case AUTOK_CS:
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL0),
                P_Fld(1, CBT_WLEV_ATK_CTRL0_ARPICS_SW));
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL1),
                P_Fld(0x3, CBT_WLEV_ATK_CTRL1_UICS_SW));
        if (p->new_cbt_mode)
        {
            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL0),
                    P_Fld(0, CBT_WLEV_ATK_CTRL0_CATRAIN_ATKEN));
        }
        else
        {
            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL0),
                    P_Fld(0, CBT_WLEV_ATK_CTRL0_CSTRAIN_ATKEN));
        }
        break;
    case AUTOK_CA:
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL0),
                P_Fld(1, CBT_WLEV_ATK_CTRL0_ARPICA_SW));
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL1),
                P_Fld(0x7F, CBT_WLEV_ATK_CTRL1_UICA_SW));
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL0),
                P_Fld(0, CBT_WLEV_ATK_CTRL0_CATRAIN_ATKEN));
        break;
    case AUTOK_DQS:
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL0),
                P_Fld(1, CBT_WLEV_ATK_CTRL0_ARPIDQS_SW));
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL1),
                P_Fld(0xF, CBT_WLEV_ATK_CTRL1_UIDQS_SW));
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_ATK_CTRL0),
                P_Fld(0, CBT_WLEV_ATK_CTRL0_WLEV_ATKEN));
        break;
    }

    return 0;
}
#endif


struct cbt_intv {
    DRAM_PLL_FREQ_SEL_T freq_sel;
    DIV_MODE_T divmode;
    u8 tcmdo1lat;
    u8 catrain_intv;
    u8 new_cbt_pat_intv;
    u8 wlev_dqspat_lat;
};

static void set_cbt_intv_rg(DRAMC_CTX_T *p, struct cbt_intv *pintv)
{
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL1),
        P_Fld(pintv->tcmdo1lat, CBT_WLEV_CTRL1_TCMDO1LAT) |
        P_Fld(pintv->catrain_intv, CBT_WLEV_CTRL1_CATRAIN_INTV));

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL5),
        P_Fld(pintv->new_cbt_pat_intv, CBT_WLEV_CTRL5_NEW_CBT_PAT_INTV));

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL0),
        P_Fld(pintv->wlev_dqspat_lat, CBT_WLEV_CTRL0_WLEV_DQSPAT_LAT));
}

static struct cbt_intv *lookup_cbt_intv(struct cbt_intv *intv, int cnt,
        DRAM_PLL_FREQ_SEL_T fsel, DIV_MODE_T dmode)
{
    struct cbt_intv *pintv = NULL;
    int i;

    for (i = 0; i < cnt; i++) {
        if (intv[i].freq_sel == fsel && intv[i].divmode == dmode) {
            pintv = &intv[i];
            break;
        }
    }

    return pintv;
}

static void set_cbt_wlev_intv_lp4(DRAMC_CTX_T *p)
{
    struct cbt_intv intv[] = {
        {
            LP4_DDR4266,
            DIV8_MODE,
            17,
            14,
            19,
            19,
        }, {
            LP4_DDR3733,
            DIV8_MODE,
            16,
            13,
            18,
            18,
        }, {
            LP4_DDR3200,
            DIV8_MODE,
            14,
            11,
            16,
            16,
        }, {
            LP4_DDR2667,
            DIV8_MODE,
            13,
            10,
            15,
            15,
        }, {
            LP4_DDR2400,
            DIV8_MODE,
            12,
            9,
            14,
            14,
        }, {
            LP4_DDR1866,
            DIV8_MODE,
            11,
            9,
            13,
            13,
        }, {
            LP4_DDR1600,
            DIV8_MODE,
            10,
            8,
            12,
            12,
        }, {
            LP4_DDR1200,
            DIV8_MODE,
            9,
            8,
            11,
            11,
        }, {
            LP4_DDR800,
            DIV8_MODE,
            8,
            8,
            10,
            10,
        }, {
            LP4_DDR1600,
            DIV4_MODE,
            16,
            13,
            16,
            16,
        }, {
            LP4_DDR1200,
            DIV4_MODE,
            14,
            13,
            14,
            14,
        }, {
            LP4_DDR800,
            DIV4_MODE,
            12,
            13,
            12,
            12,
        }, {
            LP4_DDR400,
            DIV4_MODE,
            12,
            13,
            12,
            12,
        },
    };

    struct cbt_intv *pintv;

    pintv = lookup_cbt_intv(intv, ARRAY_SIZE(intv),
            p->freq_sel, vGet_Div_Mode(p));
    if (!pintv) {
        mcSHOW_ERR_MSG(("not found entry!\n"));
        return;
    }

    set_cbt_intv_rg(p, pintv);
}

static void set_cbt_wlev_intv(DRAMC_CTX_T *p)
{
        set_cbt_wlev_intv_lp4(p);
}

#if SIMUILATION_CBT == 1

struct cbt_pinmux {
    u8 dram_dq_b0;
    u8 dram_dq_b1;
    u8 dram_dmi_b0;
    u8 dram_dmi_b1;

    u8 dram_dq7_b0;
    u8 dram_dq7_b1;
};


static struct cbt_pinmux lp4_cp[CHANNEL_NUM] = {
    {

        .dram_dq_b0 = 0,
        .dram_dq_b1 = 1,

        .dram_dmi_b0 = 0,
        .dram_dmi_b1 = 1,
    },
    #if (CHANNEL_NUM>1)
    {

        .dram_dq_b0 = 0,
        .dram_dq_b1 = 1,

        .dram_dmi_b0 = 0,
        .dram_dmi_b1 = 1,
    },
    #endif
    #if (CHANNEL_NUM>2)
    {

        .dram_dq_b0 = 0,
        .dram_dq_b1 = 1,

        .dram_dmi_b0 = 0,
        .dram_dmi_b1 = 1,
    },
    {

        .dram_dq_b0 = 0,
        .dram_dq_b1 = 1,

        .dram_dmi_b0 = 0,
        .dram_dmi_b1 = 1,
    },
    #endif
};
#if 0
static struct cbt_pinmux lp5_cp[CHANNEL_NUM] = {
    {

        .dram_dq_b0 = 1,
        .dram_dq_b1 = 0,

        .dram_dmi_b0 = 1,
        .dram_dmi_b1 = 0,

        .dram_dq7_b0 = 13,
        .dram_dq7_b1 = 5,
    },
#if (CHANNEL_NUM > 1)
    {

        .dram_dq_b0 = 1,
        .dram_dq_b1 = 0,

        .dram_dmi_b0 = 1,
        .dram_dmi_b1 = 0,

        .dram_dq7_b0 = 13,
        .dram_dq7_b1 = 5,
    },
#endif
};
#endif
static inline u8 is_byte_mode(DRAMC_CTX_T *p)
{
    return p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1? 1: 0;
}

static void vSetDramMRCBTOnOff(DRAMC_CTX_T *p, U8 u1OnOff, U8 operating_fsp)
{
    if (u1OnOff)
    {

        if (operating_fsp)
        {
            MRWriteFldMulti(p, 13, P_Fld(0, MR13_FSP_OP) |
                                   P_Fld(1, MR13_FSP_WR) |
                                   P_Fld(1, MR13_CBT),
                                   TO_MR);
        }
        else
        {
            MRWriteFldMulti(p, 13, P_Fld(1, MR13_FSP_OP) |
                                   P_Fld(0, MR13_FSP_WR) |
                                   P_Fld(1, MR13_CBT),
                                   TO_MR);
        }

        if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
        {
            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL0), P_Fld(1, CBT_WLEV_CTRL0_BYTEMODECBTEN) |
				P_Fld(1, CBT_WLEV_CTRL0_CBT_CMP_BYTEMODE));
        }
    }
    else
    {
        if (operating_fsp)
        {

            MRWriteFldMulti(p, 13, P_Fld(0, MR13_FSP_OP) |
                                   P_Fld(1, MR13_FSP_WR) |
                                   P_Fld(0, MR13_CBT),
                                   TO_MR);
        }
        else
        {
            MRWriteFldMulti(p, 13, P_Fld(1, MR13_FSP_OP) |
                                   P_Fld(0, MR13_FSP_WR) |
                                   P_Fld(0, MR13_CBT),
                                   TO_MR);
        }
    }

}

static void CBTEntryLP4(DRAMC_CTX_T *p, U8 operating_fsp, U16 operation_frequency)
{
    struct cbt_pinmux *cp = &lp4_cp[p->channel];

    #if MR_CBT_SWITCH_FREQ
    if (p->dram_fsp == FSP_1)
        DramcModeRegInit_CATerm(p, 1);
    #endif

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL),
            0, MISC_STBCAL_DQSIENCG_NORMAL_EN);

    CKEFixOnOff(p, p->rank, CKE_FIXON, TO_ONE_CHANNEL);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0), u1GetRank(p), SWCMD_CTRL0_MRSRK);


    vSetDramMRCBTOnOff(p, ENABLE, operating_fsp);


    if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE)
    {
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL0),
                1, CBT_WLEV_CTRL0_WRITE_LEVEL_EN);


        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL0),
            0x1, CBT_WLEV_CTRL0_DQSOEAOEN);

        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL0),
            (1 << cp->dram_dq_b0), CBT_WLEV_CTRL0_CBT_DQBYTE_OEAO_EN);
    }

    mcDELAY_US(1);


    CKEFixOnOff(p, p->rank, CKE_FIXOFF, TO_ONE_CHANNEL);


    (operating_fsp == FSP_1)?
            DramcMRWriteFldAlign(p, 13, 1, MR13_FSP_OP, JUST_TO_GLOBAL_VALUE):
            DramcMRWriteFldAlign(p, 13, 0, MR13_FSP_OP, JUST_TO_GLOBAL_VALUE);


    if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE)
    {

        //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PADCTRL), 0x3, PADCTRL_FIXDQIEN);


        //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ3), 1, B1_DQ3_RG_RX_ARDQ_SMT_EN_B1);
        O1PathOnOff(p, ON);
    }

    if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
    {

        //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ3), 1, B0_DQ3_RG_RX_ARDQ_SMT_EN_B0);
        O1PathOnOff(p, ON);
    }


    mcDELAY_US(1);
}

static void CBTExitLP4(DRAMC_CTX_T *p, U8 operating_fsp, U8 operation_frequency)
{
    //U8 u1MROP;

    if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE || p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
    {

        CKEFixOnOff(p, p->rank, CKE_FIXON, TO_ONE_CHANNEL);


        mcDELAY_US(1);


        vSetDramMRCBTOnOff(p, DISABLE, operating_fsp);

        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL0),
                 0, CBT_WLEV_CTRL0_WRITE_LEVEL_EN);
    }


    if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE)
    {

        //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ3), 0, B1_DQ3_RG_RX_ARDQ_SMT_EN_B1);
        O1PathOnOff(p, OFF);

        //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PADCTRL), 0, PADCTRL_FIXDQIEN);
    }

    if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
    {

        //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ3), 0, B0_DQ3_RG_RX_ARDQ_SMT_EN_B0);
        O1PathOnOff(p, OFF);


        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL0), P_Fld(0, CBT_WLEV_CTRL0_BYTEMODECBTEN) |
			P_Fld(0, CBT_WLEV_CTRL0_CBT_CMP_BYTEMODE));
    }


    mcDELAY_US(1);
}


static u8 get_mck_ck_ratio(DRAMC_CTX_T *p)
{

    u32 ratio;
    //u32 ui_max;

    ratio = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_LP5_CMD),
        SHU_LP5_CMD_LP5_CMD1TO2EN);

    mcSHOW_DBG_MSG5(("LP5 MCK:CK=%s\n", ratio == 1 ? "1:1" : "1:2"));

    return ratio;
}

static u8 get_cbtui_adjustable_maxvalue(DRAMC_CTX_T *p)
{
    u8 ratio;


		ratio = (vGet_Div_Mode(p) == DIV4_MODE) ? 3 : 7;

    return ratio;
}

static inline u32 get_ca_mck(DRAMC_CTX_T *p)
{
    u32 dly;

    dly = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA3));
    return dly & 0x0FFFFFFFU;
}

static inline void put_ca_mck(DRAMC_CTX_T *p, u32 ca_mck)
{
    u32 dly;

    dly = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA3));
    dly &= 0xF0000000U;
    ca_mck &= 0x0FFFFFFFU;
    dly |= ca_mck;

    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA3), dly);
}

static inline u32 get_ca_ui(DRAMC_CTX_T *p)
{
    u32 dly;

    dly = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7));
    return dly & 0x0FFFFFFFU;
}

static inline void put_ca_ui(DRAMC_CTX_T *p, u32 ca_ui)
{
    u32 dly;

    dly = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7));
    dly &= 0xF0000000U;
    ca_ui &= 0x0FFFFFFFU;
    dly |= ca_ui;

    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), dly);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA5), ca_ui & 0xF, SHU_SELPH_CA5_DLY_CKE);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA6), ca_ui & 0xF, SHU_SELPH_CA6_DLY_CKE1);
}

static void xlate_ca_mck_ui(DRAMC_CTX_T *p, u32 ui_delta,
        u32 mck_old, u32 ui_old, u32 *mck_new, u32 *ui_new)
{
    u8 i;
    u32 mask, max;
    u32 bit_ui, bit_mck;
    u32 ui_tmp = 0, mck_tmp = 0;

    max = get_cbtui_adjustable_maxvalue(p);
    mask = max;

    for (i = 0; i < CATRAINING_NUM_LP5; i++) {
        bit_mck = 0;
        bit_ui = ((ui_old >> (i * 4)) & mask) + ui_delta;
        if (bit_ui > max) {
            bit_mck = bit_ui / (max + 1);
            bit_ui = bit_ui % (max + 1);
        }

        mck_tmp += (bit_mck << (i * 4));
        ui_tmp += (bit_ui << (i * 4));
    }

    if (ui_new)
        *ui_new = ui_tmp;

    if (mck_new)
        *mck_new = mck_old + mck_tmp;
}

static S16 adjust_ca_ui(DRAMC_CTX_T *p, U32 ca_mck,
        U32 ca_ui, S16 pi_dly)
{
    S16 p2u;
    S16 ui, pi;
    U32 ui_new = 0, mck_new = 0;

    if (pi_dly < get_capi_max(p))
    {
        return pi_dly;
    }

    p2u = get_ca_pi_per_ui(p);

    ui = pi_dly / p2u;
    pi = pi_dly % p2u;

    xlate_ca_mck_ui(p, ui, ca_mck, ca_ui, &mck_new, &ui_new);

    put_ca_ui(p, ui_new);
    put_ca_mck(p, mck_new);
    mcSHOW_DBG_MSG5(("mck_new: 0x%x, ui_new: 0x%x, pi:%d\n",
        mck_new, ui_new, pi));

    return pi;
}

static inline u32 get_cs_mck(DRAMC_CTX_T *p)
{
    if (p->rank == RANK_1)
        return u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA1),
            SHU_SELPH_CA1_TXDLY_CS1);
    else
        return u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA1),
            SHU_SELPH_CA1_TXDLY_CS);
}

static inline void put_cs_mck(DRAMC_CTX_T *p, u32 cs_ui)
{
    if (p->rank == RANK_1)
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA1),
            cs_ui, SHU_SELPH_CA1_TXDLY_CS1);
    else
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA1),
            cs_ui, SHU_SELPH_CA1_TXDLY_CS);
}

static inline u32 get_cs_ui(DRAMC_CTX_T *p)
{
    if (p->rank == RANK_1)
        return u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA5),
            SHU_SELPH_CA5_DLY_CS1);
    else
        return u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA5),
            SHU_SELPH_CA5_DLY_CS);
}

static inline void put_cs_ui(DRAMC_CTX_T *p, u32 cs_ui)
{
    if (p->rank == RANK_1)
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA5),
            cs_ui, SHU_SELPH_CA5_DLY_CS1);
    else
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA5),
            cs_ui, SHU_SELPH_CA5_DLY_CS);
}



static S16 adjust_cs_ui(DRAMC_CTX_T *p, u32 cs_mck, u32 cs_ui, S16 pi_dly)
{
    S16 p2u;
    S16 ui = 0, pi = 0;
    u8 ratio;
    u32 ui_max;
    u32 cs_bit_mask, cs_ui_tmp, cs_mck_tmp;

    if (pi_dly < get_capi_max(p))
    {
        return pi_dly;
    }

    p2u = get_ca_pi_per_ui(p);

    ui = pi_dly / p2u;
    pi = pi_dly % p2u;

    ratio = get_mck_ck_ratio(p);
    if (ratio) {

        cs_bit_mask = 1;
    } else {

        cs_bit_mask = 3;
    }

    ui_max = get_cbtui_adjustable_maxvalue(p);
    cs_ui_tmp = (cs_ui & cs_bit_mask) + ui;
    cs_mck_tmp = 0;
    if (cs_ui_tmp > ui_max) {
        cs_mck_tmp = cs_ui_tmp / (ui_max + 1);
        cs_ui_tmp = cs_ui_tmp % (ui_max + 1);
    }

    cs_mck_tmp += cs_mck;
    put_cs_ui(p, cs_ui_tmp);
    put_cs_mck(p, cs_mck_tmp);

    mcSHOW_DBG_MSG5(("csmck:%d, csui: %d, pi:%d before\n",
            cs_mck, cs_ui, 0));
    mcSHOW_DBG_MSG5(("csmck:%d, csui: %d, pi:%d after\n",
            cs_mck_tmp, cs_ui_tmp, pi));

    return pi;
}

static u32 get_capi_step(DRAMC_CTX_T *p, int autok)
{
    u32 step;

#if FOR_DV_SIMULATION_USED
    step = 8;
#else
    switch (p->freq_sel) {
    case LP5_DDR800:
    case LP5_DDR1200:
    case LP5_DDR1600:
    case LP5_DDR3733:
        step = 8;
        break;
    default:
        if (vGet_DDR_Loop_Mode(p) == SEMI_OPEN_LOOP_MODE)
            step = 8;
        else if (vGet_DDR_Loop_Mode(p) == OPEN_LOOP_MODE)
            step = 16;
        else
            step = 1;

        break;
    }
#endif

    if (step > 8 && autok)
        step = 8;

    return step;
}

void CmdOEOnOff(DRAMC_CTX_T *p, U8 u1OnOff, CMDOE_DIS_CHANNEL CmdOeDisChannelNUM)
{
    BOOL isLP4_DSC = (p->DRAMPinmux == PINMUX_DSC)?1:0;

    if (CmdOeDisChannelNUM ==CMDOE_DIS_TO_ALL_CHANNEL)
    {
        if (!isLP4_DSC)
        {
            vIO32WriteFldMulti_All(DDRPHY_REG_CA_CMD2, P_Fld(!u1OnOff, CA_CMD2_RG_TX_ARCMD_OE_DIS_CA)
                                                    | P_Fld(u1OnOff, CA_CMD2_RG_TX_ARCA_OE_TIE_SEL_CA)
                                                    | P_Fld(0xff, CA_CMD2_RG_TX_ARCA_OE_TIE_EN_CA));
        }
        else
        {
            vIO32WriteFldMulti_All(DDRPHY_REG_B1_DQ2, P_Fld(!u1OnOff, B1_DQ2_RG_TX_ARDQ_OE_DIS_B1)
                                                    | P_Fld(u1OnOff, B1_DQ2_RG_TX_ARDQ_OE_TIE_SEL_B1)
                                                    | P_Fld(0xff, B1_DQ2_RG_TX_ARDQ_OE_TIE_EN_B1));
        }
    }
    else
    {
        if (!isLP4_DSC)
        {
            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD2), P_Fld(!u1OnOff, CA_CMD2_RG_TX_ARCMD_OE_DIS_CA)
                                                    | P_Fld(u1OnOff, CA_CMD2_RG_TX_ARCA_OE_TIE_SEL_CA)
                                                    | P_Fld(0xff, CA_CMD2_RG_TX_ARCA_OE_TIE_EN_CA));
        }
        else
        {
            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ2), P_Fld(!u1OnOff, B1_DQ2_RG_TX_ARDQ_OE_DIS_B1)
                                                    | P_Fld(u1OnOff, B1_DQ2_RG_TX_ARDQ_OE_TIE_SEL_B1)
                                                    | P_Fld(0xff, B1_DQ2_RG_TX_ARDQ_OE_TIE_EN_B1));
        }
    }


}

void CBTDelayCACLK(DRAMC_CTX_T *p, S32 iDelay)
{
    if (iDelay < 0)
    {
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_CA_CMD0),
            P_Fld(0, SHU_R0_CA_CMD0_RG_ARPI_CMD) |
            P_Fld(-iDelay, SHU_R0_CA_CMD0_RG_ARPI_CLK) |
            P_Fld(-iDelay, SHU_R0_CA_CMD0_RG_ARPI_CS));
    }
/*
    else if (iDelay >= 64)
    {
        DramcCmdUIDelaySetting(p, 2);

        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_CA_CMD0),
            P_Fld(iDelay - 64, SHU_R0_CA_CMD0_RG_ARPI_CMD) |
            P_Fld(0, SHU_R0_CA_CMD0_RG_ARPI_CLK) |
            P_Fld(0, SHU_R0_CA_CMD0_RG_ARPI_CS));
    }
*/
    else
    {
//      DramcCmdUIDelaySetting(p, 0);

        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_CA_CMD0),
            P_Fld(iDelay, SHU_R0_CA_CMD0_RG_ARPI_CMD) |
            P_Fld(0, SHU_R0_CA_CMD0_RG_ARPI_CLK) |
            P_Fld(0, SHU_R0_CA_CMD0_RG_ARPI_CS));
    }
}

#if CBT_AUTO_K_SUPPORT

#if 0
static int cbt_catrain_autok(DRAMC_CTX_T *p,
        u8 initpi, u8 steps, u8 respi,
        u32 *cmp0_array, u32 *cmp1_array,
        u8 n)
{
    u8 lenpi;
    int res;

    if (steps == 0)
        steps = 1;

    lenpi = steps - 1;

    return cbt_wlev_train_autok(p, AUTOK_CA, initpi, lenpi, respi,
            cmp0_array, cmp1_array, n);
}

static int cbt_cstrain_autok(DRAMC_CTX_T *p,
        u8 initpi, u8 steps, u8 respi,
        u32 *cmp0, u32 *cmp1)
{
    u8 lenpi;

    if (steps == 0)
        steps = 1;

    lenpi = steps - 1;

    return cbt_wlev_train_autok(p, AUTOK_CS,
            initpi, lenpi, respi, cmp0, cmp1, 1);
}


static int cbt_catrain_autok_next_window(DRAMC_CTX_T *p,
        u32 *bitmap, u8 start_pos,
        u8 initpi, u8 steps, u8 respi,
        PASS_WIN_DATA_T *pwin)
{
    u8 lenpi;
    u8 sweep_max_cnt, win_left, win_right;
    int res;

    if (steps == 0)
        steps = 1;

    lenpi = steps - 1;

    sweep_max_cnt = get_autok_sweep_max_cnt(lenpi, respi);
    res = find_zero_window(bitmap, start_pos, sweep_max_cnt - 1,
                &win_left, &win_right);

    if (!res) {
        mcSHOW_DBG_MSG4(("can't find zero window.\n"));
        return 0;
    } else {
        mcSHOW_DBG_MSG4(("find max zero window [%d, %d]\n",
            win_left, win_right));
        pwin->first_pass = initpi + win_left * (1 << respi);
        pwin->last_pass = initpi + win_right * (1 << respi);
        return 1;
    }
}
static void cbt_autok_maxwindow(DRAMC_CTX_T *p,
    u32 *bitmap, u8 uiDelay, u8 pi_step, u8 steps, u8 respi,
    S32 *iFirstPass, S32 *iLastPass)
{
    int res;
    u8 start_pos;
    PASS_WIN_DATA_T win;

    start_pos = 0;

    while (1)
    {
        res = cbt_catrain_autok_next_window(p,
                bitmap, start_pos,
                uiDelay, steps, respi, &win);

        if (!res)
        {

            mcSHOW_DBG_MSG2(("no window @pi [%d, %d]\n",
                        uiDelay + start_pos,
                        uiDelay + pi_step - 1));

            if ((*iFirstPass != PASS_RANGE_NA) &&
                    (*iLastPass == PASS_RANGE_NA))
            {

                if ((uiDelay - *iFirstPass) < 5)
                {
                    *iFirstPass = PASS_RANGE_NA;
                }
                else
                {
                    *iLastPass = uiDelay - pi_step;
                }
            }


            break;
        }
        else
        {

            mcSHOW_DBG_MSG2(("find pi pass window [%d, %d] in [%d, %d]\n",
                        win.first_pass, win.last_pass,
                        uiDelay, uiDelay + pi_step - 1));


            start_pos = win.last_pass - uiDelay + 1;

            if (*iFirstPass == PASS_RANGE_NA)
            {
                *iFirstPass = win.first_pass;
            }
            else if (*iLastPass != PASS_RANGE_NA)
            {

                if (*iLastPass + (1 << respi) >= win.first_pass)
                {
                    *iLastPass = win.last_pass;
                }
                else
                {

                    if (win.last_pass - win.first_pass >= *iLastPass - *iFirstPass)
                    {
                        *iFirstPass = win.first_pass;
                        *iLastPass = win.last_pass;
                    }
                }
                continue;
            }

            if (*iLastPass == PASS_RANGE_NA)
            {
                if ((win.last_pass - *iFirstPass) < 5)
                {
                    *iFirstPass = PASS_RANGE_NA;
                    continue;
                }

                *iLastPass = win.last_pass;
            }
        }
    }
}
#endif
#endif

static void CBTAdjustCS(DRAMC_CTX_T *p, int autok)
{
    S32 iCSFinalDelay = 0;//iFirstCSPass = 0, iLastCSPass = 0, iCSCenter
    //U32 uiDelay, u4ValueReadBack, u4CSWinSize;
    U8 backup_rank, ii;
    //u32 pi_start, pi_end, pi_step;
    u32 pi_dly;
    u32 cs_ui, cs_mck;
    //u16 u2HalfCSWin;
    //u8 idx = 0;
    //u8 step_respi = AUTOK_RESPI_1;
    //u32 capi_max;

    backup_rank = u1GetRank(p);

    cs_ui = get_cs_ui(p);
    cs_mck = get_cs_mck(p);

#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_CBT)
    if (p->femmc_Ready == 1)
    {
        CATrain_CsDelay[p->channel][p->rank] = p->pSavetimeData->u1CBTCsDelay_Save[p->channel][p->rank];
    }
#endif


    if(backup_rank == RANK_1)
    {
        iCSFinalDelay = (CATrain_CsDelay[p->channel][RANK_0] + CATrain_CsDelay[p->channel][RANK_1]) >> 1;
    }
    else
    {
        iCSFinalDelay = CATrain_CsDelay[p->channel][p->rank];
    }


    for (ii = RANK_0; ii <= backup_rank; ii++)
    {
        vSetRank(p, ii);

        pi_dly = adjust_cs_ui(p, cs_mck, cs_ui, iCSFinalDelay);

        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_CA_CMD0), pi_dly, SHU_R0_CA_CMD0_RG_ARPI_CS);

#ifdef FOR_HQA_REPORT_USED
        if (gHQALog_flag == 1)
        {
            HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "CS_Center", " ", 0, pi_dly, NULL);
        }
#endif
    }

    vSetRank(p, backup_rank);


    //mcSHOW_DBG_MSG(("CS delay=%d (%d~%d)\n", iCSFinalDelay, iFirstCSPass, iLastCSPass));
    //mcDUMP_REG_MSG(("CS delay=%d (%d~%d)\n", iCSFinalDelay, iFirstCSPass, iLastCSPass));
}

#if CA_PER_BIT_DELAY_CELL
static void CATrainingSetPerBitDelayCell(DRAMC_CTX_T *p, S16 *iCAFinalCenter, U8 ca_pin_num)
{
    U8 *uiLPDDR_CA_Mapping = NULL;
    U8 u1CA;
    S8 iCA_PerBit_DelayLine[8] = {0};

    {
        uiLPDDR_CA_Mapping = (U8 *)uiLPDDR4_CA_Mapping_POP[p->channel];
    }

    for (u1CA = 0;u1CA < ca_pin_num;u1CA++)
    {
        iCA_PerBit_DelayLine[uiLPDDR_CA_Mapping[u1CA]] = iCAFinalCenter[u1CA];
    }


    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_CA_TXDLY0),
            P_Fld(iCA_PerBit_DelayLine[0], SHU_R0_CA_TXDLY0_TX_ARCA0_DLY) |
            P_Fld(iCA_PerBit_DelayLine[1], SHU_R0_CA_TXDLY0_TX_ARCA1_DLY) |
            P_Fld(iCA_PerBit_DelayLine[2], SHU_R0_CA_TXDLY0_TX_ARCA2_DLY) |
            P_Fld(iCA_PerBit_DelayLine[3], SHU_R0_CA_TXDLY0_TX_ARCA3_DLY));

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_CA_TXDLY1),
            P_Fld(iCA_PerBit_DelayLine[4], SHU_R0_CA_TXDLY1_TX_ARCA4_DLY) |
            P_Fld(iCA_PerBit_DelayLine[5], SHU_R0_CA_TXDLY1_TX_ARCA5_DLY) |
            P_Fld(iCA_PerBit_DelayLine[6], SHU_R0_CA_TXDLY1_TX_ARCA6_DLY) |
            P_Fld(iCA_PerBit_DelayLine[7], SHU_R0_CA_TXDLY1_TX_ARCA7_DLY));
}
#endif

static void CBTSetCACLKResult(DRAMC_CTX_T *p, U32 u4MCK, U32 u4UI, U8 ca_pin_num)
{
    S8 iFinalCACLK;
    U8 backup_rank, rank_i, uiCA;
    S16 iCAFinalCenter[CATRAINING_NUM]={0};

#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_CBT)
    if (p->femmc_Ready == 1)
    {
        CATrain_CmdDelay[p->channel][p->rank] = p->pSavetimeData->s1CBTCmdDelay_Save[p->channel][p->rank];
        vSetCalibrationResult(p, DRAM_CALIBRATION_CA_TRAIN, DRAM_FAST_K);
    #if CA_PER_BIT_DELAY_CELL
        for (uiCA = 0; uiCA < ca_pin_num; uiCA++)
            iCAFinalCenter[uiCA] = p->pSavetimeData->u1CBTCA_PerBit_DelayLine_Save[p->channel][p->rank][uiCA];
    #endif
    }
#endif

    iFinalCACLK = CATrain_CmdDelay[p->channel][p->rank];

    mcSHOW_DBG_MSG(("\n[CBTSetCACLKResult] CA Dly = %d\n", iFinalCACLK));

    iFinalCACLK = adjust_ca_ui(p, u4MCK, u4UI, iFinalCACLK);

    backup_rank = u1GetRank(p);

    for (rank_i = RANK_0; rank_i <=  p->support_rank_num;rank_i++)
    {
        vSetRank(p, rank_i);

        CBTDelayCACLK(p, iFinalCACLK);

#if CA_PER_BIT_DELAY_CELL
        CATrainingSetPerBitDelayCell(p, iCAFinalCenter, ca_pin_num);
#endif
    }

    vSetRank(p, backup_rank);
}

static U8 GetCBTVrefPinMuxValue(DRAMC_CTX_T *p, U8 u1VrefRange, U8 u1VrefLevel)
{
    U8 u2VrefBit, u2Vref_org;
    U16 u2Vref_new;

    if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
        return ((u1VrefRange & 0x1) << 6) | (u1VrefLevel & 0x3f);

    u2Vref_org = ((u1VrefRange & 0x1) << 6) | (u1VrefLevel & 0x3f);

    u2Vref_new = 0;
    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_MSG4(("=== u2Vref_new: 0x%x --> 0x%x\n", u2Vref_org, u2Vref_new));

    if (lp4_cp[p->channel].dram_dq_b0)
        u2Vref_new >>= 8;

    return u2Vref_new;
}

static void CBTSetVrefLP4(DRAMC_CTX_T *p, U8 u1VrefRange, U8 u1VrefLevel, U8 operating_fsp, U8 stateFlag)
{
    U32 fld;
    U8 u4DbgValue;
    U8 u1VrefValue_pinmux;
    struct cbt_pinmux *cp = &lp4_cp[p->channel];

    if ((p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE) &&
        (stateFlag == IN_CBT))
    {
        u1VrefValue_pinmux = GetCBTVrefPinMuxValue(p, u1VrefRange, u1VrefLevel);

#if !REDUCE_LOG_FOR_PRELOADER
        mcSHOW_DBG_MSG(("\nCH_%d, RK_%d, Range=%d, VrefValue_pinmux = 0x%x\n", p->channel, p->rank, u1VrefRange, u1VrefValue_pinmux));
#endif
        u1MR12Value[p->channel][p->rank][operating_fsp] = ((u1VrefRange & 0x1) << 6) | u1VrefLevel;

        fld = (cp->dram_dq_b0) ? CBT_WLEV_CTRL4_CBT_TXDQ_B1 : CBT_WLEV_CTRL4_CBT_TXDQ_B0;

        //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), ((u1VrefRange&0x1) <<6) | (u1VrefLevel & 0x3f), WRITE_LEV_DMVREFCA);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL4),
            u1VrefValue_pinmux, fld);


        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL0), (0x1 << cp->dram_dq_b0), CBT_WLEV_CTRL0_CBT_WLEV_DQS_SEL);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL3), 0xa, CBT_WLEV_CTRL3_DQSBX_G);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL0), 1, CBT_WLEV_CTRL0_CBT_WLEV_DQS_TRIG);
        mcDELAY_US(1);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL0), 0, CBT_WLEV_CTRL0_CBT_WLEV_DQS_TRIG);

    }
    else
    {
        if (operating_fsp == FSP_1)
        {
            DramcMRWriteFldAlign(p, 13, 1, MR13_FSP_WR, TO_MR);
        }

        u4DbgValue = (((u1VrefRange & 0x1) << 6) | (u1VrefLevel & 0x3f));
        u1MR12Value[p->channel][p->rank][operating_fsp] = u4DbgValue;
        mcSHOW_DBG_MSG5(("u4DbgValue = 0x%x\n", u4DbgValue));

        DramcModeRegWriteByRank(p, p->rank, 12, u4DbgValue);
    }


    mcDELAY_US(1);
}


static void CBTEntryLP45(DRAMC_CTX_T *p, U8 u1FSP, U16 u2Freq)
{
    {
        if(p->dram_fsp == FSP_1)
        {

            CmdOEOnOff(p, DISABLE, CMDOE_DIS_TO_ONE_CHANNEL);
            cbt_switch_freq(p, CBT_LOW_FREQ);
            CmdOEOnOff(p, ENABLE, CMDOE_DIS_TO_ONE_CHANNEL);
        }
#if ENABLE_LP4Y_WA && LP4Y_BACKUP_SOLUTION
        CmdBusTrainingLP4YWA(p, DISABLE);
#endif
        CBTEntryLP4(p, u1FSP, u2Freq);
        if(p->dram_fsp == FSP_1)
        {
            cbt_switch_freq(p, CBT_HIGH_FREQ);
        }
    }
}

static void CBTExitLP45(DRAMC_CTX_T *p, U8 u1FSP, U8 u2Freq, U8 stateFlag)
{

    {
        if (stateFlag == OUT_CBT || p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
        {
            (p->dram_fsp == FSP_1)? cbt_switch_freq(p, CBT_LOW_FREQ): NULL;
            CBTExitLP4(p, u1FSP, u2Freq);
#if ENABLE_LP4Y_WA && LP4Y_BACKUP_SOLUTION
            CmdBusTrainingLP4YWA(p, ENABLE);
#endif
        }
    }
}

static void CBTSetVrefLP45(DRAMC_CTX_T *p, U8 u1VrefRange, U8 u1VrefLevel, U8 u1FSP, U16 u2Freq, U8 stateFlag)
{
    {
        if (stateFlag == IN_CBT && p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
        {

            (p->dram_fsp == FSP_1)? cbt_switch_freq(p, CBT_LOW_FREQ): NULL;
            CBTExitLP4(p, u1FSP, u2Freq);

            CBTSetVrefLP4(p, u1VrefRange, u1VrefLevel, u1FSP, stateFlag);

            CBTEntryLP4(p, u1FSP, u2Freq);
            if(p->dram_fsp == FSP_1)
            {
                cbt_switch_freq(p, CBT_HIGH_FREQ);
            }
        }
        else
        {
            CBTSetVrefLP4(p, u1VrefRange, u1VrefLevel, u1FSP, stateFlag);
        }
    }
}

static void CBTScanPI(DRAMC_CTX_T *p, S16 *s2PIStart, S16 *s2PIEnd, S16 *s2PIStep, int autok)
{
	u16 p2u;

	p2u = get_ca_pi_per_ui(p);

    if (is_discrete_lpddr4())
	*s2PIStart = -16;
	else
	*s2PIStart = 0;
	*s2PIEnd = p2u * 3 - 1;

	{

#if !CBT_MOVE_CA_INSTEAD_OF_CLK
		if (vGet_DDR_Loop_Mode(p) == SEMI_OPEN_LOOP_MODE)
		{
			*s2PIStart = -24;
		}
		else if (vGet_DDR_Loop_Mode(p) == OPEN_LOOP_MODE)
		{
			*s2PIStart = -16;
		}
		else
		{
			*s2PIStart = -MAX_CLK_PI_DELAY;
		}
		*s2PIEnd = p2u * 2 - 1;
#endif
	}

	*s2PIStep = get_capi_step(p, autok);
}

DRAM_STATUS_T CmdBusTrainingLP45(DRAMC_CTX_T *p, int autok, U8 K_Type)
{
    U8 u1FinalVref, u1FinalRange=0; //u1VrefLevel, u1VrefRange,
    //U32 u1vrefidx, u1BitIdx, ii;
    //U8 u1VRangeStart, u1VRangeEnd;
    //U8 u1VrefStart, u1VrefEnd, u1VrefStep;
    //U8 u1VrefScanStart, u1VrefScanEnd;
    //U8 u1CBTError_flag=0;
    //U32 u4CompareResult;
    //PASS_WIN_DATA_T FinalWinPerCA[CATRAINING_NUM] = {{0,0,0,0,0}};
    //U32 uiCA, uiFinishCount, uiTemp;
    //S16 iDelay, pi_dly;
    //S32 iFirstPass_tmp[CATRAINING_NUM], iLastPass_tmp[CATRAINING_NUM];
    //uiCAWinSum,
    U8 operating_fsp;
    U16 operation_frequency;
    //S32 iCA_PerBit_DelayLine[CATRAINING_NUM] = {0}, iCK_MIN = 1000
#if CA_PER_BIT_DELAY_CELL
    S16 iCAFinalCenter[CATRAINING_NUM] = {0}; //for CA_PER_BIT
#endif
    U8 u1CBTEyeScanEnable=(K_Type==NORMAL_K ? DISABLE : ENABLE);
    U8 backup_MR12Value=0;
    S32 backup_CATrain_CmdDelay=0;
    U32 backup_CATrain_CsDelay=0;
    S32 backup_CATrain_ClkDelay=0;
    U32 backup_CATrain_CmdUIDelay=0;
    U32 backup_CATrain_CmdCKEUIDelay=0;
    U32 backup_CATrain_CmdCKE1UIDelay=0;
    U32 backup_CATrain_CmdMCKDelay=0;

#if ENABLE_EYESCAN_GRAPH
    U8 EyeScan_index[CATRAINING_NUM];
#endif

    S16 pi_step; //, pi_step_bk;
    S16 pi_start, pi_end;
    u32 ca_ui; //, ca_ui_tmp
    u32 ca_mck; //Vca_mck_tmp, a_mck_default
    u8 ca_pin_num;
    u8 step_respi = AUTOK_RESPI_1;
    //u32 capi_max;

    U32 u4RegBackupAddress[] =
    {
        (DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL)),
        (DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL)),
        (DRAMC_REG_ADDR(DRAMC_REG_CKECTRL)),
        (DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ2)),
        (DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ2)),
        (DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL0)),
        (DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL1)),
        (DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL2)),
        (DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL3)),
        (DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL4)),
        (DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0)),
        (DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0)),

        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_VREF)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_VREF)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_VREF)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_PHY_VREF_SEL)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_PHY_VREF_SEL)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_PHY_VREF_SEL)),
    };

    CBTScanPI(p, &pi_start, &pi_end, &pi_step, autok);
    while (((1 << step_respi) < pi_step) && autok)
        step_respi++;

#if MRW_CHECK_ONLY
    mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
#endif

    {
        u1FinalRange = u1MR12Value[p->channel][p->rank][p->dram_fsp] >> 6;
        u1FinalVref = u1MR12Value[p->channel][p->rank][p->dram_fsp] & 0x3f;
        ca_pin_num = CATRAINING_NUM_LP4;
    }

#if ENABLE_EYESCAN_GRAPH
    if (u1CBTEyeScanEnable)
    {
        backup_MR12Value = u1MR12Value[p->channel][p->rank][p->dram_fsp];

        backup_CATrain_CmdDelay = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_CA_CMD0), SHU_R0_CA_CMD0_RG_ARPI_CMD);
        backup_CATrain_CsDelay = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_CA_CMD0), SHU_R0_CA_CMD0_RG_ARPI_CS);
        backup_CATrain_ClkDelay = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_CA_CMD0), SHU_R0_CA_CMD0_RG_ARPI_CLK);

        backup_CATrain_CmdUIDelay = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7));
        backup_CATrain_CmdCKEUIDelay = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA5), SHU_SELPH_CA5_DLY_CKE);
        backup_CATrain_CmdCKE1UIDelay = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA6), SHU_SELPH_CA6_DLY_CKE1);

        backup_CATrain_CmdMCKDelay = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA3));

        for (u1vrefidx = 0; u1vrefidx < VREF_VOLTAGE_TABLE_NUM_LP5-1; u1vrefidx++)
        {
            for (uiCA = 0; uiCA < ca_pin_num; 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;
                }
            }
        }
    }
#endif

    //DUMP_REG_MSG(("\n[dumpRG] CmdBusTraining \n"));

    vPrintCalibrationBasicInfo(p);
    mcSHOW_DBG_MSG(("[CmdBusTrainingLP45] new_cbt_mode=%d, autok=%d\n", p->new_cbt_mode, autok));
    mcSHOW_DBG_MSG2(("pi_start=%d, pi_end=%d, pi_step=%d\n", pi_start, pi_end, pi_step));


    DramcBackupRegisters(p, u4RegBackupAddress, ARRAY_SIZE(u4RegBackupAddress));


    if (u1CBTEyeScanEnable == DISABLE)
    {
        vSetCalibrationResult(p, DRAM_CALIBRATION_CA_TRAIN, DRAM_FAIL);
#if CA_PER_BIT_DELAY_CELL
        CATrainingSetPerBitDelayCell(p, iCAFinalCenter, ca_pin_num);
#endif

    }

#if CBT_MOVE_CA_INSTEAD_OF_CLK
    if (u1IsLP4Family(p->dram_type))
    {
        U8 u1CaPI = 0, u1CaUI = 0;

        u1CaUI = 1;
        u1CaPI = 0;

        DramcCmdUIDelaySetting(p, u1CaUI);

        CBTDelayCACLK(p, u1CaPI);
    }
#endif


    ca_ui = get_ca_ui(p);
    ca_mck = get_ca_mck(p);
    u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_CA_CMD0));

    vAutoRefreshSwitch(p, DISABLE);


    //vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL1),
    //      P_Fld(0x1F, CBT_WLEV_CTRL1_CATRAIN_INTV));
    set_cbt_wlev_intv(p);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_SET0),
        p->rank, TX_SET0_TXRANK);

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_SET0),
        1, TX_SET0_TXRANKFIX);

    operating_fsp = p->dram_fsp;
    operation_frequency = p->frequency;


    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL),
        P_Fld(0, DRAMC_PD_CTRL_DCMEN2) |
        P_Fld(1, DRAMC_PD_CTRL_MIOCKCTRLOFF) |
        P_Fld(0, DRAMC_PD_CTRL_PHYCLKDYNGEN) |
        P_Fld(0, DRAMC_PD_CTRL_COMBCLKCTRL) |
        P_Fld(1, DRAMC_PD_CTRL_APHYCKCG_FIXOFF) |
        P_Fld(1, DRAMC_PD_CTRL_TCKFIXON));


    CBTEntryLP45(p, operating_fsp, operation_frequency);

#if PINMUX_AUTO_TEST_PER_BIT_CA
    CheckCADelayCell(p);
#endif



#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && (BYPASS_VREF_CAL || BYPASS_CBT))
    if (p->femmc_Ready == 1)
    {
        u1FinalVref = p->pSavetimeData->u1CBTVref_Save[p->channel][p->rank];
    }
#endif

    if (u1CBTEyeScanEnable)
    {
        u1FinalVref = backup_MR12Value & 0x3f;
        u1FinalRange = (backup_MR12Value>>6) & 1;
    }

    mcSHOW_DBG_MSG(("\n[CmdBusTrainingLP45] Vref(ca) range %d: %d\n", u1FinalRange, u1FinalVref));
    //DUMP_REG_MSG(("\n[CmdBusTrainingLP45] Vref(ca) range %d: %d\n", u1FinalRange, u1FinalVref));

#ifdef FOR_HQA_TEST_USED
    gFinalCBTVrefCA[p->channel][p->rank] = u1FinalVref;
#endif


    CBTSetVrefLP45(p, u1FinalRange, u1FinalVref, operating_fsp, operation_frequency, IN_CBT);
#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_CBT)
    #if CBT_MOVE_CA_INSTEAD_OF_CLK

    DramcCmdUIDelaySetting(p, 0);
    ca_ui = get_ca_ui(p);
    #endif
#endif
    put_ca_ui(p, ca_ui);

    if (u1CBTEyeScanEnable == DISABLE)
    {
        CBTSetCACLKResult(p, ca_mck, ca_ui, ca_pin_num);
    }
    else
    {
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_CA_CMD0),
            P_Fld(backup_CATrain_CmdDelay, SHU_R0_CA_CMD0_RG_ARPI_CMD) |
            P_Fld(backup_CATrain_ClkDelay, SHU_R0_CA_CMD0_RG_ARPI_CLK) |
            P_Fld(backup_CATrain_CsDelay, SHU_R0_CA_CMD0_RG_ARPI_CS));

        vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), backup_CATrain_CmdUIDelay);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA5), backup_CATrain_CmdCKEUIDelay, SHU_SELPH_CA5_DLY_CKE);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA6), backup_CATrain_CmdCKE1UIDelay, SHU_SELPH_CA6_DLY_CKE1);

        vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA3), backup_CATrain_CmdMCKDelay);
    }

#if ENABLE_EYESCAN_GRAPH
    gEyeScan_CaliDelay[0] = CATrain_CmdDelay[p->channel][p->rank] -pi_start;
#endif



    if (u1CBTEyeScanEnable == DISABLE)
    {
        CBTAdjustCS(p, autok);
    }


    CBTExitLP45(p, operating_fsp, operation_frequency, OUT_CBT);
    CBTSetVrefLP45(p, u1FinalRange, u1FinalVref, operating_fsp, operation_frequency, OUT_CBT);

    {
        if (p->dram_fsp == FSP_1)
        {
            #if MR_CBT_SWITCH_FREQ
            DramcModeRegInit_CATerm(p, 0);
            #else
            DramcMRWriteFldAlign(p, 13, 1, MR13_FSP_OP, TO_MR);
            #endif
        }
    }

#if EYESCAN_LOG || defined(FOR_HQA_TEST_USED)
    gFinalCBTVrefDQ[p->channel][p->rank] = u1FinalVref;
#endif

    mcSHOW_DBG_MSG4(("\n[CmdBusTrainingLP45] Done\n"));


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_SET0), 0, TX_SET0_TXRANK);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_SET0), 0, TX_SET0_TXRANKFIX);


    DramcRestoreRegisters(p, u4RegBackupAddress, ARRAY_SIZE(u4RegBackupAddress));

    return DRAM_OK;
}
#endif /* SIMUILATION_CBT */


#define WRITE_LEVELING_MOVD_DQS 1

U8 u1MCK2UI_DivShift(DRAMC_CTX_T *p)
{
    {

        if (vGet_Div_Mode(p) == DIV4_MODE)
        {
            return MCK_TO_4UI_SHIFT;
        }
        else
        {
            return MCK_TO_8UI_SHIFT;
        }
    }
}

static DRAM_STATUS_T ExecuteMoveDramCDelay(DRAMC_CTX_T *p,
                                                    REG_TRANSFER_T ui_reg,
                                                    REG_TRANSFER_T mck_reg,
                                                    S8 iShiftUI)
{
    S32 s4HighLevelDelay, s4DelaySum;
    U32 u4TmpUI, u4TmpMCK;
    U8 ucDataRateDivShift = 0;
    DRAM_STATUS_T MoveResult;

    ucDataRateDivShift = u1MCK2UI_DivShift(p);

    u4TmpUI = u4IO32ReadFldAlign(DRAMC_REG_ADDR(ui_reg.u4Addr), ui_reg.u4Fld) & (~(1 << ucDataRateDivShift));
    u4TmpMCK = u4IO32ReadFldAlign(DRAMC_REG_ADDR(mck_reg.u4Addr), mck_reg.u4Fld);
    //mcSHOW_DBG_MSG(("Base:  u4TmpMCK:%d,  u4TmpUI: %d,\n", u4TmpMCK, u4TmpUI));

    s4HighLevelDelay = (u4TmpMCK << ucDataRateDivShift) + u4TmpUI;
    s4DelaySum = (s4HighLevelDelay + iShiftUI);

    if (s4DelaySum < 0)
    {
        u4TmpUI = 0;
        u4TmpMCK = 0;
        MoveResult = DRAM_FAIL;
    }
    else
    {
        u4TmpMCK = s4DelaySum >> ucDataRateDivShift;
        u4TmpUI = s4DelaySum - (u4TmpMCK << ucDataRateDivShift);
        MoveResult = DRAM_OK;
    }

    vIO32WriteFldAlign(DRAMC_REG_ADDR(ui_reg.u4Addr), u4TmpUI, ui_reg.u4Fld);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(mck_reg.u4Addr), u4TmpMCK, mck_reg.u4Fld);
    //mcSHOW_DBG_MSG(("[%d]  Final ==> u4TmpMCK:%d,  u4TmpUI: %d,\n", iShiftUI, u4TmpMCK, u4TmpUI));

    return MoveResult;
}

static void _LoopAryToDelay(DRAMC_CTX_T *p,
                                  REG_TRANSFER_T *ui_reg,
                                  REG_TRANSFER_T *mck_reg,
                                  U8 u8RG_num,
                                  S8 iShiftUI,
                                  BYTES_T eByteIdx)
{
    U8 idx = 0, step = 1;
    if (eByteIdx == BYTE_0)
    {
        idx = 0;
        step = 2;
    }
    else if (eByteIdx == BYTE_1)
    {
        idx = 1;
        step = 2;
    }

    for (; idx < u8RG_num; idx += step)
    {
        ExecuteMoveDramCDelay(p, ui_reg[idx], mck_reg[idx], iShiftUI);
    }
}

static void LP4_ShiftDQSUI(DRAMC_CTX_T *p, S8 iShiftUI, BYTES_T eByteIdx)
{

    REG_TRANSFER_T TransferUIRegs[]  = {{DRAMC_REG_SHU_SELPH_DQS1, SHU_SELPH_DQS1_DLY_DQS0},
                                        {DRAMC_REG_SHU_SELPH_DQS1, SHU_SELPH_DQS1_DLY_DQS1}};
    REG_TRANSFER_T TransferMCKRegs[] = {{DRAMC_REG_SHU_SELPH_DQS0, SHU_SELPH_DQS0_TXDLY_DQS0},
                                        {DRAMC_REG_SHU_SELPH_DQS0, SHU_SELPH_DQS0_TXDLY_DQS1}};

    _LoopAryToDelay(p, TransferUIRegs, TransferMCKRegs,
                       sizeof(TransferUIRegs) / sizeof(REG_TRANSFER_T),
                       iShiftUI, eByteIdx);
}

void LP4_ShiftDQS_OENUI(DRAMC_CTX_T *p, S8 iShiftUI, BYTES_T eByteIdx)
{

    REG_TRANSFER_T TransferUIRegs[]  = {{DRAMC_REG_SHU_SELPH_DQS1, SHU_SELPH_DQS1_DLY_OEN_DQS0},
                                        {DRAMC_REG_SHU_SELPH_DQS1, SHU_SELPH_DQS1_DLY_OEN_DQS1}};
    REG_TRANSFER_T TransferMCKRegs[] = {{DRAMC_REG_SHU_SELPH_DQS0, SHU_SELPH_DQS0_TXDLY_OEN_DQS0},
                                        {DRAMC_REG_SHU_SELPH_DQS0, SHU_SELPH_DQS0_TXDLY_OEN_DQS1}};

    _LoopAryToDelay(p, TransferUIRegs, TransferMCKRegs,
                       sizeof(TransferUIRegs) / sizeof(REG_TRANSFER_T),
                       iShiftUI, eByteIdx);
}

static void ShiftDQUI(DRAMC_CTX_T *p, S8 iShiftUI, BYTES_T eByteIdx)
{

    REG_TRANSFER_T TransferUIRegs[]  = {{DRAMC_REG_SHURK_SELPH_DQ3, SHURK_SELPH_DQ3_DLY_DQM0},
                                        {DRAMC_REG_SHURK_SELPH_DQ3, SHURK_SELPH_DQ3_DLY_DQM1},
                                        {DRAMC_REG_SHURK_SELPH_DQ2, SHURK_SELPH_DQ2_DLY_DQ0},
                                        {DRAMC_REG_SHURK_SELPH_DQ2, SHURK_SELPH_DQ2_DLY_DQ1}};
    REG_TRANSFER_T TransferMCKRegs[] = {{DRAMC_REG_SHURK_SELPH_DQ1, SHURK_SELPH_DQ1_TXDLY_DQM0},
                                        {DRAMC_REG_SHURK_SELPH_DQ1, SHURK_SELPH_DQ1_TXDLY_DQM1},
                                        {DRAMC_REG_SHURK_SELPH_DQ0, SHURK_SELPH_DQ0_TXDLY_DQ0},
                                        {DRAMC_REG_SHURK_SELPH_DQ0, SHURK_SELPH_DQ0_TXDLY_DQ1}};

    _LoopAryToDelay(p, TransferUIRegs, TransferMCKRegs,
                    sizeof(TransferUIRegs) / sizeof(REG_TRANSFER_T),
                    iShiftUI, eByteIdx);
}

static void ShiftDQUI_AllRK(DRAMC_CTX_T *p, S8 iShiftUI, BYTES_T eByteIdx)
{
    U8 backup_rank, rk_i;
    backup_rank = u1GetRank(p);


    for (rk_i = RANK_0; rk_i < p->support_rank_num; rk_i++)
    {
        vSetRank(p, rk_i);
        ShiftDQUI(p, iShiftUI, eByteIdx);
    }
    vSetRank(p, backup_rank);
}

static void ShiftDQ_OENUI(DRAMC_CTX_T *p, S8 iShiftUI, BYTES_T eByteIdx)
{
    REG_TRANSFER_T TransferUIRegs[]  = {{DRAMC_REG_SHURK_SELPH_DQ3, SHURK_SELPH_DQ3_DLY_OEN_DQM0},
                                        {DRAMC_REG_SHURK_SELPH_DQ3, SHURK_SELPH_DQ3_DLY_OEN_DQM1},
                                        {DRAMC_REG_SHURK_SELPH_DQ2, SHURK_SELPH_DQ2_DLY_OEN_DQ0},
                                        {DRAMC_REG_SHURK_SELPH_DQ2, SHURK_SELPH_DQ2_DLY_OEN_DQ1}};
    REG_TRANSFER_T TransferMCKRegs[] = {{DRAMC_REG_SHURK_SELPH_DQ1, SHURK_SELPH_DQ1_TXDLY_OEN_DQM0},
                                        {DRAMC_REG_SHURK_SELPH_DQ1, SHURK_SELPH_DQ1_TXDLY_OEN_DQM1},
                                        {DRAMC_REG_SHURK_SELPH_DQ0, SHURK_SELPH_DQ0_TXDLY_OEN_DQ0},
                                        {DRAMC_REG_SHURK_SELPH_DQ0, SHURK_SELPH_DQ0_TXDLY_OEN_DQ1}};

    _LoopAryToDelay(p, TransferUIRegs, TransferMCKRegs,
                    sizeof(TransferUIRegs) / sizeof(REG_TRANSFER_T),
                    iShiftUI, eByteIdx);
}

void ShiftDQ_OENUI_AllRK(DRAMC_CTX_T *p, S8 iShiftUI, BYTES_T eByteIdx)
{
    U8 backup_rank, rk_i;
    backup_rank = u1GetRank(p);


    for (rk_i = RANK_0; rk_i < p->support_rank_num; rk_i++)
    {
        vSetRank(p, rk_i);
        ShiftDQ_OENUI(p, iShiftUI, eByteIdx);
    }
    vSetRank(p, backup_rank);
}

//void WriteLevelingMoveDQSInsteadOfCLK(DRAMC_CTX_T *p, S8 iShiftUI)
//{
//    LP4_ShiftDQSUI(p, iShiftUI, ALL_BYTES);
//    LP4_ShiftDQUI(p, iShiftUI, ALL_BYTES);
//}

static void ShiftDQSWCK_UI(DRAMC_CTX_T *p, S8 iShiftUI, BYTES_T eByteIdx)
{
        {
            LP4_ShiftDQSUI(p, iShiftUI, eByteIdx);
            LP4_ShiftDQS_OENUI(p, iShiftUI, eByteIdx);
        }
}

U8 u1IsLP4Div4DDR800(DRAMC_CTX_T *p)
{
    if ((vGet_Div_Mode(p) == DIV4_MODE) && (p->frequency == 400))
        return TRUE;
    else
        return FALSE;
}


static void vSetDramMRWriteLevelingOnOff(DRAMC_CTX_T *p, U8 u1OnOff)
{

    if (u1OnOff)
        u1MR02Value[p->dram_fsp] |= 0x80;
    else
        u1MR02Value[p->dram_fsp] &= 0x7f;

    DramcModeRegWriteByRank(p, p->rank, 2, u1MR02Value[p->dram_fsp]);
}

U8 u1IsPhaseMode(DRAMC_CTX_T *p)
{
    if ((vGet_DDR_Loop_Mode(p) == OPEN_LOOP_MODE) || (vGet_DDR_Loop_Mode(p) == SEMI_OPEN_LOOP_MODE))
        return TRUE;
    else
        return FALSE;
}

#if 0
static DRAM_STATUS_T DramcTriggerAndWait(DRAMC_CTX_T *p, REG_TRANSFER_T TriggerReg, REG_TRANSFER_T RepondsReg)
{

    U32 u4TimeCnt = DDR_HW_AUTOK_POLLING_CNT;
    DRAM_STATUS_T u4RespFlag = 0;

    vIO32WriteFldAlign(DRAMC_REG_ADDR(TriggerReg.u4Addr), 0, TriggerReg.u4Fld);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(TriggerReg.u4Addr), 1, TriggerReg.u4Fld);
    do
    {
        u4RespFlag = u4IO32ReadFldAlign(DRAMC_REG_ADDR(RepondsReg.u4Addr), RepondsReg.u4Fld);
        u4TimeCnt --;
        mcDELAY_US(1);
    }while ((u4RespFlag == 0) && (u4TimeCnt > 0));

    if (u4TimeCnt == 0)
    {
        mcSHOW_ERR_MSG(("[DramcTriggerAndWait] Wait 0x%x respond fail (time out)\n", RepondsReg.u4Addr));
        return DRAM_FAIL;
    }

    return DRAM_OK;
}

static DRAM_STATUS_T DramcTriggerAndWait_For_RX_AutoK_WorkAround(DRAMC_CTX_T *p, REG_TRANSFER_T TriggerReg, REG_TRANSFER_T RepondsReg, U16 u16DelayStep)
{

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_RX_AUTOK_CFG0), 0, MISC_RX_AUTOK_CFG0_RX_CAL_STEP);

    vIO32WriteFldAlign(DRAMC_REG_ADDR(TriggerReg.u4Addr), 0, TriggerReg.u4Fld);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(TriggerReg.u4Addr), 1, TriggerReg.u4Fld);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(TriggerReg.u4Addr), 0, TriggerReg.u4Fld);


    DramPhyReset(p);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_RX_AUTOK_CFG0), u16DelayStep, MISC_RX_AUTOK_CFG0_RX_CAL_STEP);

    return DramcTriggerAndWait(p, TriggerReg, RepondsReg);
}
#endif
#if (SIMULATION_WRITE_LEVELING == 1)
#define DQPI_PER_UI (32)
#define STORAGED_DLY_UNIT (24)
static void WriteLevelingScanRange_PI(DRAMC_CTX_T *p, S32 *ps4DlyBegin, S32 *ps4DlyEnd, U8 *pu1PIStep, S16 *pPI_bound, WLEV_DELAY_BASED_T stDelayBase)
{
    S32 s4DlyBegin = 0, s4DlyEnd;
    U8 u1PIStep;
    S16 PI_bound;

    if (stDelayBase == PI_BASED)
    {

        s4DlyBegin = WRITE_LEVELING_MOVD_DQS * 32 - MAX_CLK_PI_DELAY - 1;
        s4DlyEnd = s4DlyBegin + 64 - 1;

        if ((vGet_DDR_Loop_Mode(p) == OPEN_LOOP_MODE))
        {
            u1PIStep = 16;
            PI_bound = 32;
        }
        else if ((vGet_DDR_Loop_Mode(p) == SEMI_OPEN_LOOP_MODE))
        {
            u1PIStep = 8;
            PI_bound = 32;
        }
        else
        {
            u1PIStep = 1;
            PI_bound = 64;
        }
    }
    else
    {

        s4DlyBegin = 0;
        s4DlyEnd = 2 * STORAGED_DLY_UNIT;

        u1PIStep = 1;
        PI_bound = 1024;
    }
    mcSHOW_DBG_MSG2(("Delay: %d->%d, Step: %d, Bound: %d\n", s4DlyBegin, s4DlyEnd, u1PIStep, PI_bound));

    *ps4DlyBegin = s4DlyBegin;
    *ps4DlyEnd = s4DlyEnd;
    *pu1PIStep = u1PIStep;
    *pPI_bound = PI_bound;

}

#if ENABLE_WDQS_MODE_2
void WriteLevelingPosCal(DRAMC_CTX_T *p, WLEV_DELAY_BASED_T stDelayBase)
{
    DRAM_RANK_T backup_rank = u1GetRank(p);
    U8 wrlevel_dqs_delay[DQS_BYTE_NUMBER] = {0};
    U8 rank_i = 0;

    if((wrlevel_dqs_final_delay[RANK_0][0] - wrlevel_dqs_final_delay[RANK_1][0])>=9 ||
        (wrlevel_dqs_final_delay[RANK_0][0] - wrlevel_dqs_final_delay[RANK_1][0])<=-9 ||
        (wrlevel_dqs_final_delay[RANK_0][1] - wrlevel_dqs_final_delay[RANK_1][1])>=9 ||
        (wrlevel_dqs_final_delay[RANK_0][1] - wrlevel_dqs_final_delay[RANK_1][1])<=-9 )
    {
        mcSHOW_ERR_MSG(("[WARNING] Larger WL R2R !!\n"));
        #if CHECK_HQA_CRITERIA
        while(1);
        #endif
    }

    wrlevel_dqs_delay[0] = (wrlevel_dqs_final_delay[RANK_0][0] + wrlevel_dqs_final_delay[RANK_1][0]) >> 1;
    wrlevel_dqs_delay[1] = (wrlevel_dqs_final_delay[RANK_0][1] + wrlevel_dqs_final_delay[RANK_1][1]) >> 1;

    wrlevel_dqs_final_delay[RANK_0][0] = wrlevel_dqs_final_delay[RANK_1][0] = wrlevel_dqs_delay[0];
    wrlevel_dqs_final_delay[RANK_0][1] = wrlevel_dqs_final_delay[RANK_1][1] = wrlevel_dqs_delay[1];

    for (rank_i = p->rank; rank_i < p->support_rank_num; rank_i++)
    {
        vSetRank(p, rank_i);


        if (stDelayBase == PI_BASED)
        {

            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_DQ0), wrlevel_dqs_delay[0], SHU_R0_B0_DQ0_ARPI_PBYTE_B0);
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_DQ0), wrlevel_dqs_delay[1], SHU_R0_B1_DQ0_ARPI_PBYTE_B1);
        }
        else
        {
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_TXDLY3), wrlevel_dqs_delay[0], SHU_R0_B0_TXDLY3_TX_ARWCK_DLY_B0);
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_TXDLY3), wrlevel_dqs_delay[1], SHU_R0_B1_TXDLY3_TX_ARWCK_DLY_B1);
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_TXDLY3), wrlevel_dqs_delay[0], SHU_R0_B0_TXDLY3_TX_ARWCKB_DLY_B0);
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_TXDLY3), wrlevel_dqs_delay[1], SHU_R0_B1_TXDLY3_TX_ARWCKB_DLY_B1);
        }
    }

    vSetRank(p, backup_rank);

    mcSHOW_DBG_MSG(("[WriteLevelingPosCal] DQS PI B0/B1 = %d/%d\n", wrlevel_dqs_delay[0], wrlevel_dqs_delay[1]));
}
#endif

#define SET_PATTERN_MANUALLY_FOR_DEBUG 1
DRAM_STATUS_T DramcWriteLeveling(DRAMC_CTX_T *p, u8 isAutoK, WLEV_DELAY_BASED_T stDelayBase)
{

    DRAM_STATUS_T KResult = DRAM_FAIL;

    //U8 *uiLPDDR_O1_Mapping = NULL;
    //U32 u4value = 0, u4dq_o1 = 0 u4value1 = 0,  u4dq_o1_tmp[DQS_BYTE_NUMBER];
    U8 byte_i, rank_i, ucDoneFlg = 0;
    //S32 iDelay, ClockDelayMax;
    //U8 ucStatus[DQS_BYTE_NUMBER], ucdq_o1[DQS_BYTE_NUMBER], ucdq_o1_shift[DQS_BYTE_NUMBER]
    //U8 ucHW_cmp_raw_data, uccmp_result[DQS_BYTE_NUMBER];
    DRAM_RANK_T backup_rank;

    //S32 wrlevel_dq_delay[DQS_BYTE_NUMBER]; // 3 is channel number
    S32 wrlevel_dqs_delay[DQS_BYTE_NUMBER]; // 3 is channel number

    //u32 bitmap31_0[DQS_BYTE_NUMBER] = {0};
    //u32 bitmap63_32[DQS_BYTE_NUMBER] = {0};
    //u8 idx = 0;
    //U16 _bitmap_stored_num = 0;

    S32 s4DlyBegin, s4DlyEnd;
    U8 u1PIStep;
    U8 u1OverBoundCnt = 0; //jj = 0
    S16 PI_bound = 64;


    vAutoRefreshSwitch(p, DISABLE);


    if (!p)
    {
        mcSHOW_ERR_MSG(("context NULL\n"));
        return DRAM_FAIL;
    }
    //DUMP_REG_MSG(("\n[dumpRG] DramcWriteLeveling \n"));
#if VENDER_JV_LOG
        vPrintCalibrationBasicInfo_ForJV(p);
#else
        vPrintCalibrationBasicInfo(p);
#endif
    mcSHOW_DBG_MSG(("[Write Leveling] autok: %d\n", isAutoK));

    fgwrlevel_done = 0;
    backup_rank = u1GetRank(p);

    //DramcRankSwap(p, p->rank);

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_SET0), p->rank, TX_SET0_TXRANK);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_SET0), 1, TX_SET0_TXRANKFIX);


    U32 u4RegBackupAddress[] =
    {
        (DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL)),
        (DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL0)),
        (DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL1)),
        (DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL3)),
        (DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL5)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_VREF)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_VREF)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_VREF)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_PHY_VREF_SEL)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_PHY_VREF_SEL)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_PHY_VREF_SEL)),
        (DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL))
    };
    DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress) / sizeof(U32));



    vSetCalibrationResult(p, DRAM_CALIBRATION_WRITE_LEVEL, DRAM_FAIL);

#if MRW_CHECK_ONLY
    mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
#endif

    if (p->isWLevInitShift[p->channel] == FALSE)
    {

#if __ETT__
		while (stDelayBase != PI_BASED);
#else
        ASSERT(stDelayBase == PI_BASED);
#endif

        p->isWLevInitShift[p->channel] = TRUE;


        ShiftDQUI_AllRK(p, -WRITE_LEVELING_MOVD_DQS, ALL_BYTES);
        ShiftDQ_OENUI_AllRK(p, -WRITE_LEVELING_MOVD_DQS, ALL_BYTES);
        ShiftDQSWCK_UI(p, -WRITE_LEVELING_MOVD_DQS, ALL_BYTES);


        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_DQ0), 0, SHU_R0_B0_DQ0_ARPI_PBYTE_B0);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_DQ0), 0, SHU_R0_B1_DQ0_ARPI_PBYTE_B1);

    }


    WriteLevelingScanRange_PI(p, &s4DlyBegin, &s4DlyEnd, &u1PIStep, &PI_bound, stDelayBase);


    if (stDelayBase == DLY_BASED)
        isAutoK = FALSE;


#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_WRITELEVELING)
    if (p->femmc_Ready == 1)
    {
        wrlevel_dqs_final_delay[p->rank][0] = p->pSavetimeData->u1WriteLeveling_bypass_Save[p->channel][p->rank][0];
        wrlevel_dqs_final_delay[p->rank][1] = p->pSavetimeData->u1WriteLeveling_bypass_Save[p->channel][p->rank][1];

        ucDoneFlg = 0xff;
        KResult = DRAM_OK;
        vSetCalibrationResult(p, DRAM_CALIBRATION_WRITE_LEVEL, DRAM_FAST_K);
    }
#endif

    if (u1OverBoundCnt > 0)
        ShiftDQSWCK_UI(p, -u1OverBoundCnt * (PI_bound / DQPI_PER_UI), ALL_BYTES);

    if (ucDoneFlg == 0xff)
    {

        fgwrlevel_done = 1;
        KResult = DRAM_OK;
    }
    else
    {
        KResult = DRAM_FAIL;
        #if PIN_CHECK_TOOL
        PINInfo_flashtool.WL_ERR_FLAG|=(0x1<<(p->channel*2+p->rank));
        #endif
    }
    vSetCalibrationResult(p, DRAM_CALIBRATION_WRITE_LEVEL, KResult);
    mcSHOW_DBG_MSG2(("pass bytecount = 0x%x (0xff: all bytes pass) \n\n", ucDoneFlg));

#if defined(FOR_HQA_TEST_USED) && defined(FOR_HQA_REPORT_USED)
    if (gHQALog_flag == 1)
    {
        for (byte_i = 0; byte_i < DQS_BYTE_NUMBER; byte_i++)
        {
            if (byte_i==0)
            {
                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT1, "", "WriteLeveling_MCK_DQS", byte_i, u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_DQS0), SHU_SELPH_DQS0_TXDLY_DQS0), NULL);
                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT1, "", "WriteLeveling_UI_DQS", byte_i, u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_DQS1), SHU_SELPH_DQS1_DLY_DQS0), NULL);
            }
            else
            {
                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT1, "", "WriteLeveling_MCK_DQS", byte_i, u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_DQS0), SHU_SELPH_DQS0_TXDLY_DQS1), NULL);
                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT1, "", "WriteLeveling_UI_DQS", byte_i, u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_DQS1), SHU_SELPH_DQS1_DLY_DQS1), NULL);
            }

            HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT1, "", "WriteLeveling_DQS", byte_i, wrlevel_dqs_final_delay[p->rank][byte_i], NULL);
        }
    }
#endif


        vSetDramMRWriteLevelingOnOff(p, DISABLE);



    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CBT_WLEV_CTRL0), 0, CBT_WLEV_CTRL0_WRITE_LEVEL_EN);


    O1PathOnOff(p, OFF);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_SET0), 0, TX_SET0_TXRANK);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_SET0), 0, TX_SET0_TXRANKFIX);


    DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress) / sizeof(U32));


    for (byte_i = 0; byte_i < DQS_BYTE_NUMBER; byte_i++)
    {

        mcSHOW_DBG_MSG(("Write leveling (Byte %d): %d", byte_i, wrlevel_dqs_final_delay[p->rank][byte_i]));
        //DUMP_REG_MSG(("Write leveling (Byte %d): %d", byte_i, wrlevel_dqs_final_delay[p->rank][byte_i]));
        if (wrlevel_dqs_final_delay[p->rank][byte_i] >= PI_bound)
        {
            ShiftDQSWCK_UI(p, (wrlevel_dqs_final_delay[p->rank][byte_i] / PI_bound) * (PI_bound / DQPI_PER_UI), byte_i);

            wrlevel_dqs_final_delay[p->rank][byte_i] %= PI_bound;
        }

        wrlevel_dqs_delay[byte_i] = wrlevel_dqs_final_delay[p->rank][byte_i];
        mcSHOW_DBG_MSG((" => %d\n", wrlevel_dqs_delay[byte_i]));
        //DUMP_REG_MSG((" => %d\n", wrlevel_dqs_delay[byte_i]));
    }

    for (rank_i = p->rank; rank_i < RANK_MAX; rank_i++)
    {
        vSetRank(p, rank_i);


        if (stDelayBase == PI_BASED)
        {

            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_DQ0), wrlevel_dqs_delay[0], SHU_R0_B0_DQ0_ARPI_PBYTE_B0);
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_DQ0), wrlevel_dqs_delay[1], SHU_R0_B1_DQ0_ARPI_PBYTE_B1);
        }
        else
        {
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_TXDLY3), wrlevel_dqs_delay[0], SHU_R0_B0_TXDLY3_TX_ARWCK_DLY_B0);
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_TXDLY3), wrlevel_dqs_delay[1], SHU_R0_B1_TXDLY3_TX_ARWCK_DLY_B1);
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_TXDLY3), wrlevel_dqs_delay[0], SHU_R0_B0_TXDLY3_TX_ARWCKB_DLY_B0);
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_TXDLY3), wrlevel_dqs_delay[1], SHU_R0_B1_TXDLY3_TX_ARWCKB_DLY_B1);
        }
    }

    vSetRank(p, backup_rank);

    mcSHOW_DBG_MSG4(("[DramcWriteLeveling] Done\n\n"));

    return KResult;
}
#endif //SIMULATION_WRITE_LEVELING

#if (fcFOR_CHIP_ID == fcA60868)
static void RunTime_SW_Cmd(DRAMC_CTX_T *p, RUNTIME_SWCMD_SEL_T runtime_SW_cmd_sel)
{
    U32 u4Response = 0;
    U32 u4TimeCnt = TIME_OUT_CNT;
    U32 u4BackupCKECTRL;


    u4BackupCKECTRL = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL));


    CKEFixOnOff(p, TO_ALL_RANK, CKE_FIXON, TO_ALL_CHANNEL);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), runtime_SW_cmd_sel, SWCMD_EN_RTSWCMD_SEL);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RTSWCMD_CNT), 0x30, RTSWCMD_CNT_RTSWCMD_CNT);
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL2),
            P_Fld(0, SWCMD_CTRL2_RTSWCMD_AGE) |
            P_Fld(p->rank, SWCMD_CTRL2_RTSWCMD_RK));

    U8 _rank_idx_CAS_OFF = 0;
    U8 _is_differential_mode = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_WCKCTRL), SHU_WCKCTRL_WCKDUAL);
    while (1)
    {

        if (runtime_SW_cmd_sel == RUNTIME_SWCMD_CAS_OFF)
        {
            if ( _is_differential_mode == 0)
                vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL2), _rank_idx_CAS_OFF, SWCMD_CTRL2_RTSWCMD_RK);
        }
        else if (runtime_SW_cmd_sel == RUNTIME_SWCMD_CAS_FS)
        {
            if (_is_differential_mode == 0)
                vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL2), 0x3, SWCMD_CTRL2_RTSWCMD_RK);
        }


        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 1, SWCMD_EN_RTSWCMDEN);

        do
        {
            u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP3), SPCMDRESP3_RTSWCMD_RESPONSE);
            u4TimeCnt --;
            mcDELAY_US(1);
        }while ((u4Response == 0) && (u4TimeCnt > 0));

        if (u4TimeCnt == 0)
        {
            mcSHOW_ERR_MSG(("[LP5 RT SW Cmd ] Resp fail (time out)\n"));
        }


        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 0, SWCMD_EN_RTSWCMDEN);


        if (runtime_SW_cmd_sel == RUNTIME_SWCMD_CAS_OFF)
        {
            if (_is_differential_mode == 0)
                if (++_rank_idx_CAS_OFF <= 1)
                    continue;
        }

        break;
    }

    vIO32Write4B_All(DRAMC_REG_CKECTRL, u4BackupCKECTRL);
}
#else
#if 0
static void RunTime_SW_Cmd(DRAMC_CTX_T *p, RUNTIME_SWCMD_SEL_T runtime_SW_cmd_sel)
{
    U32 u4Response = 0;
    U32 u4TimeCnt = TIME_OUT_CNT;


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), runtime_SW_cmd_sel, SWCMD_EN_RTSWCMD_SEL);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RTSWCMD_CNT), 0x30, RTSWCMD_CNT_RTSWCMD_CNT);
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL2),
            P_Fld(0, SWCMD_CTRL2_RTSWCMD_AGE) |
            P_Fld(p->rank, SWCMD_CTRL2_RTSWCMD_RK));


    if ((runtime_SW_cmd_sel == RUNTIME_SWCMD_CAS_FS) || (runtime_SW_cmd_sel == RUNTIME_SWCMD_CAS_OFF))
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL2), 0x3, SWCMD_CTRL2_RTSWCMD_RK);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 1, SWCMD_EN_RTSWCMDEN);

    do
    {
        u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP3), SPCMDRESP3_RTSWCMD_RESPONSE);
        u4TimeCnt --;
        mcDELAY_US(1);
    }while ((u4Response == 0) && (u4TimeCnt > 0));

    if (u4TimeCnt == 0)
    {
        mcSHOW_ERR_MSG(("[LP5 RT SW Cmd ] Resp fail (time out)\n"));
    }


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 0, SWCMD_EN_RTSWCMDEN);

}
#endif
#endif

#if (SIMULATION_DUTY_CYC_MONITOR == 1)
static U8 FetchRGSettingVal(int step_val)
{
    if (step_val <= 0)
        return (U8)(-step_val);
    else
        return ((U8)step_val | 0x08);
}

DRAM_STATUS_T DramcDutyCycleMonitor(DRAMC_CTX_T *p)
{
    U8 backup_rank;
//    U8 u8ResultDutyCycMonitor[WHOLE_STEPS_NUM] = {0};


    if (!p)
    {
        mcSHOW_ERR_MSG(("context NULL\n"));
        return DRAM_FAIL;
    }

    vAutoRefreshSwitch(p, DISABLE);
    //CKEFixOnOff(p, p->rank, CKE_FIXON, TO_ONE_CHANNEL);

    backup_rank = u1GetRank(p);

    RunTime_SW_Cmd(p, RUNTIME_SWCMD_CAS_FS);

    int i = -7;
    for (i = -7; i <= 7; i++)
    {

        U8 u8RGSettingVal = FetchRGSettingVal(i);
        mcSHOW_ERR_MSG(("Set value %d into MR30\n", u8RGSettingVal));
        MRWriteFldMulti(p, 30, P_Fld(u8RGSettingVal, MR30_DCAU) |
                               P_Fld(u8RGSettingVal, MR30_DCAL),
                               TO_MR);


        DramcMRWriteFldAlign(p, 26, 1, MR26_DCM_START_STOP, TO_MR);


        mcDELAY_US(2);


        DramcMRWriteFldAlign(p, 26, 1, MR26_DCM_FLIP, TO_MR);


        mcDELAY_US(2);


        DramcMRWriteFldAlign(p, 26, 0, MR26_DCM_FLIP, TO_MR);


        mcDELAY_US(2);


        DramcMRWriteFldAlign(p, 26, 0, MR26_DCM_START_STOP, TO_MR);


        mcDELAY_US(2);

        mcSHOW_ERR_MSG(("Wait tMRD and MRR MR26\n"));



    }


    RunTime_SW_Cmd(p, RUNTIME_SWCMD_CAS_OFF);

    vAutoRefreshSwitch(p, ENABLE);
    //CKEFixOnOff(p, p->rank, CKE_DYNAMIC, TO_ONE_CHANNEL);

    vSetRank(p, backup_rank);
}
#endif


void vResetDelayChainBeforeCalibration(DRAMC_CTX_T *p)
{
    U8 u1RankIdx, u1RankIdxBak;
    U32 u4WbrBackup = GetDramcBroadcast();

    DramcBroadcastOnOff(DRAMC_BROADCAST_OFF);
    u1RankIdxBak = u1GetRank(p);

    for(u1RankIdx=RANK_0; u1RankIdx<RANK_MAX; u1RankIdx++)
    {
        vSetRank(p, u1RankIdx);

        vIO32WriteFldMulti_All(DDRPHY_REG_SHU_R0_CA_TXDLY0,
            P_Fld(0, SHU_R0_CA_TXDLY0_TX_ARCA0_DLY) |
            P_Fld(0, SHU_R0_CA_TXDLY0_TX_ARCA1_DLY) |
            P_Fld(0, SHU_R0_CA_TXDLY0_TX_ARCA2_DLY) |
            P_Fld(0, SHU_R0_CA_TXDLY0_TX_ARCA3_DLY));

        vIO32WriteFldMulti_All(DDRPHY_REG_SHU_R0_CA_TXDLY1,
            P_Fld(0, SHU_R0_CA_TXDLY1_TX_ARCA4_DLY) |
            P_Fld(0, SHU_R0_CA_TXDLY1_TX_ARCA5_DLY) |
            P_Fld(0, SHU_R0_CA_TXDLY1_TX_ARCA6_DLY) |
            P_Fld(0, SHU_R0_CA_TXDLY1_TX_ARCA7_DLY));

        vIO32WriteFldMulti_All(DDRPHY_REG_SHU_R0_B0_TXDLY0, P_Fld(0, SHU_R0_B0_TXDLY0_TX_ARDQ0_DLY_B0)
            | P_Fld(0, SHU_R0_B0_TXDLY0_TX_ARDQ1_DLY_B0)
            | P_Fld(0, SHU_R0_B0_TXDLY0_TX_ARDQ2_DLY_B0)
            | P_Fld(0, SHU_R0_B0_TXDLY0_TX_ARDQ3_DLY_B0));
        vIO32WriteFldMulti_All(DDRPHY_REG_SHU_R0_B0_TXDLY1, P_Fld(0, SHU_R0_B0_TXDLY1_TX_ARDQ4_DLY_B0)
            | P_Fld(0, SHU_R0_B0_TXDLY1_TX_ARDQ5_DLY_B0)
            | P_Fld(0, SHU_R0_B0_TXDLY1_TX_ARDQ6_DLY_B0)
            | P_Fld(0, SHU_R0_B0_TXDLY1_TX_ARDQ7_DLY_B0));

        vIO32WriteFldMulti_All(DDRPHY_REG_SHU_R0_B1_TXDLY0, P_Fld(0, SHU_R0_B1_TXDLY0_TX_ARDQ0_DLY_B1)
            | P_Fld(0, SHU_R0_B1_TXDLY0_TX_ARDQ1_DLY_B1)
            | P_Fld(0, SHU_R0_B1_TXDLY0_TX_ARDQ2_DLY_B1)
            | P_Fld(0, SHU_R0_B1_TXDLY0_TX_ARDQ3_DLY_B1));
        vIO32WriteFldMulti_All(DDRPHY_REG_SHU_R0_B1_TXDLY1, P_Fld(0, SHU_R0_B1_TXDLY1_TX_ARDQ4_DLY_B1)
            | P_Fld(0, SHU_R0_B1_TXDLY1_TX_ARDQ5_DLY_B1)
            | P_Fld(0, SHU_R0_B1_TXDLY1_TX_ARDQ6_DLY_B1)
            | P_Fld(0, SHU_R0_B1_TXDLY1_TX_ARDQ7_DLY_B1));
        vIO32WriteFldAlign_All(DDRPHY_REG_SHU_R0_B0_TXDLY3, 0x0, SHU_R0_B0_TXDLY3_TX_ARDQM0_DLY_B0);
        vIO32WriteFldAlign_All(DDRPHY_REG_SHU_R0_B1_TXDLY3, 0x0, SHU_R0_B1_TXDLY3_TX_ARDQM0_DLY_B1);
    }

    vSetRank(p, u1RankIdxBak);
    DramcBroadcastOnOff(u4WbrBackup);
}



void DramPhyReset(DRAMC_CTX_T *p)
{

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RX_SET0), 1, RX_SET0_RDATRST);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_CTRL1), 1, MISC_CTRL1_R_DMPHYRST);


    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_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_REG_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_REG_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_REG_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_REG_MISC_CTRL1), 0, MISC_CTRL1_R_DMPHYRST);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RX_SET0), 0, RX_SET0_RDATRST);
}

#if SIMULATION_LP4_ZQ

#if ZQ_SWCMD_MODE
static DRAM_STATUS_T ZQ_SWCMD_MODE_Cal(DRAMC_CTX_T *p, U8 rank)
{
    U32 u4Response;
    U32 u4TimeCnt = TIME_OUT_CNT;
    U32 u4SWCMDEN, u4SWCMDCTRL, u4SPDCTRL, u4CKECTRL;


    u4SWCMDEN = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN));
    u4SWCMDCTRL = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0));
    u4SPDCTRL = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL));
    u4CKECTRL = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL));

    mcSHOW_DBG_MSG4(("[ZQCalibration]\n"));
    //mcFPRINTF((fp_A60501, "[ZQCalibration]\n"));


    DramCLKAlwaysOnOff(p, ON, TO_ONE_CHANNEL);
    mcDELAY_US(1);


    CKEFixOnOff(p, rank, CKE_FIXON, TO_ONE_CHANNEL);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0), rank, SWCMD_CTRL0_SWTRIG_ZQ_RK);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 1, SWCMD_EN_ZQCEN_SWTRIG);

    do
    {
        u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP3), SPCMDRESP3_ZQC_SWTRIG_RESPONSE);
        u4TimeCnt --;
        mcDELAY_US(1);

        mcSHOW_DBG_MSG4(("%d- ", u4TimeCnt));
        //mcFPRINTF((fp_A60501, "%d- ", u4TimeCnt));
    }while((u4Response==0) &&(u4TimeCnt>0));

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 0, SWCMD_EN_ZQCEN_SWTRIG);

    if(u4TimeCnt==0)
    {
        vSetCalibrationResult(p, DRAM_CALIBRATION_ZQ, DRAM_FAIL);
        mcSHOW_ERR_MSG(("ZQCAL Start fail (time out)\n"));
        //mcFPRINTF((fp_A60501, "ZQCAL Start fail (time out)\n"));
        return DRAM_FAIL;
    }


    mcDELAY_US(1);
    u4TimeCnt = TIME_OUT_CNT;


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 1, SWCMD_EN_ZQLATEN_SWTRIG);
    do
    {
        u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP3), SPCMDRESP3_ZQLAT_SWTRIG_RESPONSE);
        u4TimeCnt --;
        mcDELAY_US(1);

        mcSHOW_DBG_MSG4(("%d=\n\n", u4TimeCnt));
        //mcFPRINTF((fp_A60501, "%d= ", u4TimeCnt));
    }while((u4Response==0) &&(u4TimeCnt>0));

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 0, SWCMD_EN_ZQLATEN_SWTRIG);

    if(u4TimeCnt==0)//time out
    {
        vSetCalibrationResult(p, DRAM_CALIBRATION_ZQ, DRAM_FAIL);
        mcSHOW_ERR_MSG(("ZQCAL Latch fail (time out)\n"));
        //mcFPRINTF((fp_A60501, "ZQCAL Latch fail (time out)\n"));
        return DRAM_FAIL;
    }


    mcDELAY_US(1);


    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), u4SWCMDEN);
    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0), u4SWCMDCTRL);
    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), u4SPDCTRL);
    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL), u4CKECTRL);

    vSetCalibrationResult(p, DRAM_CALIBRATION_ZQ, DRAM_OK);
    mcSHOW_DBG_MSG4(("[DramcZQCalibration] Done\n\n"));
    //mcFPRINTF((fp_A60501, "\n[DramcZQCalibration] Done\n\n"));

    return DRAM_OK;
}
#endif
#if ZQ_RTSWCMD_MODE
static DRAM_STATUS_T ZQ_RTSWCMD_MODE_Cal(DRAMC_CTX_T *p, U8 rank)
{
    U32 u4Response;
    U32 u4TimeCnt = TIME_OUT_CNT;
    U32 u4SWCMDEN, u4SWCMDCTRL, u4MPCCTRL, u4RTSWCMD, u4SPDCTRL, u4CKECTRL;


    u4SWCMDEN = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN));
    u4SWCMDCTRL = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL2));
    u4MPCCTRL = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_MPC_CTRL));
    u4RTSWCMD = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_RTSWCMD_CNT));
    u4SPDCTRL = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL));
    u4CKECTRL = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL));

    mcSHOW_DBG_MSG4(("[ZQCalibration]\n"));
    //mcFPRINTF((fp_A60501, "[ZQCalibration]\n"));


    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 1, DRAMC_PD_CTRL_APHYCKCG_FIXOFF);
    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 1, DRAMC_PD_CTRL_TCKFIXON);
    mcDELAY_US(1);


    //CKEFixOnOff(p, rank, CKE_FIXON, TO_ONE_CHANNEL);


    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL2),
        P_Fld(rank, SWCMD_CTRL2_RTSWCMD_RK) |
        P_Fld(0x20, SWCMD_CTRL2_RTSWCMD_AGE));

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MPC_CTRL), 0x1, MPC_CTRL_RTSWCMD_HPRI_EN);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RTSWCMD_CNT), 0x2a, RTSWCMD_CNT_RTSWCMD_CNT);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 0x5, SWCMD_EN_RTSWCMD_SEL);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 1, SWCMD_EN_RTSWCMDEN);

    do
    {
        u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP3), SPCMDRESP3_RTSWCMD_RESPONSE);
        u4TimeCnt --;
        mcDELAY_US(1);

        mcSHOW_DBG_MSG4(("%d- ", u4TimeCnt));
        //mcFPRINTF((fp_A60501, "%d- ", u4TimeCnt));
    }while((u4Response==0) &&(u4TimeCnt>0));

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 0, SWCMD_EN_RTSWCMDEN);

    if(u4TimeCnt==0)
    {
        vSetCalibrationResult(p, DRAM_CALIBRATION_ZQ, DRAM_FAIL);
        mcSHOW_ERR_MSG(("ZQCAL Start fail (time out)\n"));
        //mcFPRINTF((fp_A60501, "ZQCAL Start fail (time out)\n"));
        return DRAM_FAIL;
    }


    mcDELAY_US(1);
    u4TimeCnt = TIME_OUT_CNT;


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 0x6, SWCMD_EN_RTSWCMD_SEL);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 1, SWCMD_EN_RTSWCMDEN);

    do
    {
        u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP3), SPCMDRESP3_RTSWCMD_RESPONSE);
        u4TimeCnt --;
        mcDELAY_US(1);

        mcSHOW_DBG_MSG4(("%d=", u4TimeCnt));
        //mcFPRINTF((fp_A60501, "%d= ", u4TimeCnt));
    }while((u4Response==0) &&(u4TimeCnt>0));

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 0, SWCMD_EN_RTSWCMDEN);

    if(u4TimeCnt==0)
    {
        vSetCalibrationResult(p, DRAM_CALIBRATION_ZQ, DRAM_FAIL);
        mcSHOW_ERR_MSG(("ZQCAL Latch fail (time out)\n"));
        //mcFPRINTF((fp_A60501, "ZQCAL Latch fail (time out)\n"));
        return DRAM_FAIL;
    }


    mcDELAY_US(1);


    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), u4SWCMDEN);
    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL2), u4SWCMDCTRL);
    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_MPC_CTRL), u4MPCCTRL);
    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_RTSWCMD_CNT), u4RTSWCMD);
    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), u4SPDCTRL);
    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL), u4CKECTRL);

    vSetCalibrationResult(p, DRAM_CALIBRATION_ZQ, DRAM_OK);
    mcSHOW_DBG_MSG4(("\n[DramcZQCalibration] Done\n\n"));
    //mcFPRINTF((fp_A60501, "\n[DramcZQCalibration] Done\n\n"));

    return DRAM_OK;
}
#endif
#if ZQ_SCSM_MODE
static DRAM_STATUS_T ZQ_SCSM_MODE_Cal(DRAMC_CTX_T *p, U8 rank)
{
    U32 u4Response;
    U32 u4TimeCnt = TIME_OUT_CNT;
    U32 u4SWCMDEN, u4MPCCTRL, u4SWCMDCTRL, u4SPDCTRL, u4CKECTRL;


    u4SWCMDEN = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN));
    u4SWCMDCTRL = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0));
    u4MPCCTRL = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_MPC_OPTION));
    u4SPDCTRL = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL));
    u4CKECTRL = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL));

    mcSHOW_DBG_MSG4(("[ZQCalibration]\n"));
    //mcFPRINTF((fp_A60501, "[ZQCalibration]\n"));


    DramCLKAlwaysOnOff(p, ON, TO_ONE_CHANNEL);
    mcDELAY_US(1);


    CKEFixOnOff(p, rank, CKE_FIXON, TO_ONE_CHANNEL);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0), rank, SWCMD_CTRL0_MRSRK);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MPC_OPTION), 1, MPC_OPTION_MPCRKEN);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 1, SWCMD_EN_ZQCEN);
    do
    {
        u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_ZQC_RESPONSE);
        u4TimeCnt --;
        mcDELAY_US(1);

        mcSHOW_DBG_MSG4(("%d- ", u4TimeCnt));
        //mcFPRINTF((fp_A60501, "%d- ", u4TimeCnt));
    }while((u4Response==0) &&(u4TimeCnt>0));

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 0, SWCMD_EN_ZQCEN);

    if(u4TimeCnt==0)
    {
        vSetCalibrationResult(p, DRAM_CALIBRATION_ZQ, DRAM_FAIL);
        mcSHOW_ERR_MSG(("ZQCAL Start fail (time out)\n"));
        //mcFPRINTF((fp_A60501, "ZQCAL Start fail (time out)\n"));
        return DRAM_FAIL;
    }


    mcDELAY_US(1);
    u4TimeCnt = TIME_OUT_CNT;


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 1, SWCMD_EN_ZQLATEN);
    do
    {
        u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_ZQLAT_RESPONSE);
        u4TimeCnt --;
        mcDELAY_US(1);

        mcSHOW_DBG_MSG4(("%d=", u4TimeCnt));
        //mcFPRINTF((fp_A60501, "%d= ", u4TimeCnt));
    }while((u4Response==0) &&(u4TimeCnt>0));

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 0, SWCMD_EN_ZQLATEN);

    if(u4TimeCnt==0)
    {
        vSetCalibrationResult(p, DRAM_CALIBRATION_ZQ, DRAM_FAIL);
        mcSHOW_ERR_MSG(("ZQCAL Latch fail (time out)\n"));
        //mcFPRINTF((fp_A60501, "ZQCAL Latch fail (time out)\n"));
        return DRAM_FAIL;
    }


    mcDELAY_US(1);


    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), u4SWCMDEN);
    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL2), u4SWCMDCTRL);
    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_MPC_CTRL), u4MPCCTRL);
    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), u4SPDCTRL);
    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL), u4CKECTRL);

    vSetCalibrationResult(p, DRAM_CALIBRATION_ZQ, DRAM_OK);
    mcSHOW_DBG_MSG4(("\n[DramcZQCalibration] Done\n\n"));
    //mcFPRINTF((fp_A60501, "\n[DramcZQCalibration] Done\n\n"));

    return DRAM_OK;
}
#endif

DRAM_STATUS_T DramcZQCalibration(DRAMC_CTX_T *p, U8 rank)
{
    #if ZQ_SWCMD_MODE
    return ZQ_SWCMD_MODE_Cal(p, rank);
    #elif ZQ_RTSWCMD_MODE
    return ZQ_RTSWCMD_MODE_Cal(p, rank);
    #else
    return ZQ_SCSM_MODE_Cal(p, rank);
    #endif
}
#endif

#if ENABLE_RX_INPUT_BUFF_OFF_K
static U8 RXInputBuf_DelayExchange(S8 iOfst)
{
    U8 u1Value;

    if(iOfst <0)
    {
        u1Value = 0x8 | (-iOfst);
    }
    else
    {
        u1Value = iOfst;
    }

    return u1Value;
}


DRAM_STATUS_T DramcRXInputBufferOffsetCal(DRAMC_CTX_T *p)
{
	S8 iOffset, s1begin, s1end;
	S8 s1DQFinalFlagChange[DQ_DATA_WIDTH], s1DQMFinalFlagChange[DQM_BYTE_NUM];
	U8 u1BitIdx, u1ByteIdx, u1FinishCount, u1step, u1DQFinal_rg_offset[DQ_DATA_WIDTH], u1DQMFinal_rg_offset[DQM_BYTE_NUM];
	//U8 *uiLPDDR_O1_Mapping = NULL;
	U8 ii, read_val_b0 = u1GetRank(p); //u1rank_backup
	U8 u1Offc_RgValue, u1O1_value;
	U32 u4RestltDQ, u4RestltDQ_B0, u4RestltDQ_B1, u4RestltDQM[DQM_BYTE_NUM];
	BOOL isLP4_DSC = (p->DRAMPinmux == PINMUX_DSC)?1:0;
	U32 u4RegBackupAddress[] =
	{
		(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ5)),
		(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ5)),
		(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD5)),
		(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ6)),
		(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ6)),
		(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD6)),
		(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ3)),
		(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ3)),
		(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD3)),
		(DRAMC_REG_ADDR(DDRPHY_REG_B0_PHY3)),
		(DRAMC_REG_ADDR(DDRPHY_REG_B1_PHY3)),
		(DRAMC_REG_ADDR(DDRPHY_REG_CA_PHY3)),
		(DRAMC_REG_ADDR(DDRPHY_REG_MISC_RX_IN_GATE_EN_CTRL)),
	};

	vSetCalibrationResult(p, DRAM_CALIBRATION_RX_INPUT_BUFF_OFFC, DRAM_FAIL);
	mcSHOW_DBG_MSG2(("\n[DramcRXInputBufferOffsetCal] \n"));
#if VENDER_JV_LOG
	vPrintCalibrationBasicInfo_ForJV(p);
#else
	vPrintCalibrationBasicInfo(p);
#endif

	DramcBackupRegisters(p, u4RegBackupAddress, ARRAY_SIZE(u4RegBackupAddress));


	DramcEngine2Run(p, TE_OP_READ_CHECK, TEST_AUDIO_PATTERN);

	vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_RX_IN_GATE_EN_CTRL), 0xf, MISC_RX_IN_GATE_EN_CTRL_FIX_IN_GATE_EN);

	vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_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));
	if (!isLP4_DSC)
	{
	vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_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));
	}
	else
	{
	vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD6),
					P_Fld(1, CA_CMD6_RG_RX_ARCMD_BIAS_PS) |
					P_Fld(1, CA_CMD6_RG_RX_ARCMD_RES_BIAS_EN)  |
					P_Fld(0, CA_CMD6_RG_TX_ARCMD_DDR3_SEL) |
					P_Fld(1, CA_CMD6_RG_TX_ARCMD_DDR4_SEL));
	}


	vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_VREF_EN_B0);
	if (!isLP4_DSC)
		vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_VREF_EN_B1);
	else
		vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD5), 1, CA_CMD5_RG_RX_ARCMD_VREF_EN);


	mcDELAY_US(1);


	vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_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));
	if (!isLP4_DSC)
	{
	vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_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));
	}
	else
	{
		vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD3), P_Fld(1, CA_CMD3_RG_RX_ARCMD_IN_BUFF_EN) | P_Fld(1, CA_CMD3_RG_RX_ARCLK_IN_BUFF_EN));
	}


	vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_PHY3), 1, B0_PHY3_RG_RX_ARDQ_BUFF_EN_SEL_B0);
	if (!isLP4_DSC)
	{
	vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_PHY3), 1, B1_PHY3_RG_RX_ARDQ_BUFF_EN_SEL_B1);
	}
	else
	{
		vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_CA_PHY3), 1, CA_PHY3_RG_RX_ARCA_BUFF_EN_SEL_CA);
	}

	vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ11),
            P_Fld(0x1, SHU_B0_DQ11_RG_RX_ARDQ_OFFSETC_BIAS_EN_B0) |
            P_Fld(0x1, SHU_B0_DQ11_RG_RX_ARDQ_OFFSETC_EN_B0));
	if (!isLP4_DSC)
	{
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ11),
            P_Fld(0x1, SHU_B1_DQ11_RG_RX_ARDQ_OFFSETC_BIAS_EN_B1) |
            P_Fld(0x1, SHU_B1_DQ11_RG_RX_ARDQ_OFFSETC_EN_B1));
	}
	else
	{
		vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD11),
			P_Fld(0x1, SHU_CA_CMD11_RG_RX_ARCA_OFFSETC_BIAS_EN_CA) |
			P_Fld(0x1, SHU_CA_CMD11_RG_RX_ARCA_OFFSETC_EN_CA));
	}

	vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ6), 1, B0_DQ6_RG_RX_ARDQ_O1_SEL_B0);
	if (!isLP4_DSC)
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ6), 1, B1_DQ6_RG_RX_ARDQ_O1_SEL_B1);
	else
		vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD6), 1, CA_CMD6_RG_RX_ARCMD_O1_SEL);


	u1FinishCount =0;
    s1begin = -7;
	s1end = 8;
	u1step = 1;

	memset(s1DQFinalFlagChange, 0x7f, sizeof(s1DQFinalFlagChange));
	memset(s1DQMFinalFlagChange, 0x7f, sizeof(s1DQMFinalFlagChange));


	for(iOffset = s1begin; iOffset < s1end; iOffset+=u1step)
	{
		u1Offc_RgValue = RXInputBuf_DelayExchange(iOffset);

		mcSHOW_DBG_MSG2(("iOffset= %2d, set %2d,", iOffset, u1Offc_RgValue));


		vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B0_DQ0),
            P_Fld(u1Offc_RgValue, SHU_RK_B0_DQ0_RG_RX_ARDQ0_OFFC_B0) |
            P_Fld(u1Offc_RgValue, SHU_RK_B0_DQ0_RG_RX_ARDQ1_OFFC_B0) |
            P_Fld(u1Offc_RgValue, SHU_RK_B0_DQ0_RG_RX_ARDQ2_OFFC_B0) |
            P_Fld(u1Offc_RgValue, SHU_RK_B0_DQ0_RG_RX_ARDQ3_OFFC_B0) |
            P_Fld(u1Offc_RgValue, SHU_RK_B0_DQ0_RG_RX_ARDQ4_OFFC_B0) |
            P_Fld(u1Offc_RgValue, SHU_RK_B0_DQ0_RG_RX_ARDQ5_OFFC_B0) |
            P_Fld(u1Offc_RgValue, SHU_RK_B0_DQ0_RG_RX_ARDQ6_OFFC_B0) |
            P_Fld(u1Offc_RgValue, SHU_RK_B0_DQ0_RG_RX_ARDQ7_OFFC_B0));
		if (!isLP4_DSC)
		{
		vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B1_DQ0),
            P_Fld(u1Offc_RgValue, SHU_RK_B1_DQ0_RG_RX_ARDQ0_OFFC_B1) |
            P_Fld(u1Offc_RgValue, SHU_RK_B1_DQ0_RG_RX_ARDQ1_OFFC_B1) |
            P_Fld(u1Offc_RgValue, SHU_RK_B1_DQ0_RG_RX_ARDQ2_OFFC_B1) |
            P_Fld(u1Offc_RgValue, SHU_RK_B1_DQ0_RG_RX_ARDQ3_OFFC_B1) |
            P_Fld(u1Offc_RgValue, SHU_RK_B1_DQ0_RG_RX_ARDQ4_OFFC_B1) |
            P_Fld(u1Offc_RgValue, SHU_RK_B1_DQ0_RG_RX_ARDQ5_OFFC_B1) |
            P_Fld(u1Offc_RgValue, SHU_RK_B1_DQ0_RG_RX_ARDQ6_OFFC_B1) |
            P_Fld(u1Offc_RgValue, SHU_RK_B1_DQ0_RG_RX_ARDQ7_OFFC_B1));
		}
		else
		{
			vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_CA_CMD0),
				P_Fld(u1Offc_RgValue, SHU_RK_CA_CMD0_RG_RX_ARCA0_OFFC) |
				P_Fld(u1Offc_RgValue, SHU_RK_CA_CMD0_RG_RX_ARCA1_OFFC) |
				P_Fld(u1Offc_RgValue, SHU_RK_CA_CMD0_RG_RX_ARCA2_OFFC) |
				P_Fld(u1Offc_RgValue, SHU_RK_CA_CMD0_RG_RX_ARCA3_OFFC) |
				P_Fld(u1Offc_RgValue, SHU_RK_CA_CMD0_RG_RX_ARCA4_OFFC) |
				P_Fld(u1Offc_RgValue, SHU_RK_CA_CMD0_RG_RX_ARCA5_OFFC));
			vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_CA_DQ_OFFSET),
				P_Fld(u1Offc_RgValue, SHU_RK_CA_DQ_OFFSET_RG_RX_ARDQ6_OFFSETC_C0) |
				P_Fld(u1Offc_RgValue, SHU_RK_CA_DQ_OFFSET_RG_RX_ARDQ7_OFFSETC_C0));
		}


		vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B0_DQ1), u1Offc_RgValue, SHU_RK_B0_DQ1_RG_RX_ARDQM0_OFFC_B0);
		if (!isLP4_DSC)
		{
		vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B1_DQ1), u1Offc_RgValue, SHU_RK_B1_DQ1_RG_RX_ARDQM0_OFFC_B1);
		}
		else
		{
		    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_CA_CMD1), u1Offc_RgValue, SHU_RK_CA_CMD1_RG_RX_ARCS0_OFFC);
		}


		mcDELAY_US(1);


		u4RestltDQ_B0 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_AD_RX_DQ_O1), MISC_AD_RX_DQ_O1_AD_RX_ARDQ_O1_B0);
		if (!isLP4_DSC)
		{
			u4RestltDQ_B1 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_AD_RX_DQ_O1), MISC_AD_RX_DQ_O1_AD_RX_ARDQ_O1_B1);
		}
		else
		{
			u4RestltDQ_B1 = ((u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_MISC_AD_RX_CMD_O1)))&0x3f)\
							|(u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_AD_RX_DQ_O1), MISC_AD_RX_DQ_O1_AD_RX_ARDQ6_O1_C0)<<0x6)\
							|(u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_AD_RX_DQ_O1), MISC_AD_RX_DQ_O1_AD_RX_ARDQ7_O1_C0)<<0x7);
		}
             u4RestltDQ = u4RestltDQ_B0|(u4RestltDQ_B1<<8);
             mcSHOW_DBG_MSG2((" DQ O1 = 0x%x, ", u4RestltDQ));

		for(u1BitIdx= 0; u1BitIdx < DQ_DATA_WIDTH ; u1BitIdx++)
		{
			if(s1DQFinalFlagChange[u1BitIdx] == 0x7f)
			{
				u1O1_value = (u4RestltDQ >> u1BitIdx) & 0x1;

				if(u1O1_value ==0)
				{
					s1DQFinalFlagChange[u1BitIdx] = iOffset;
					u1FinishCount ++;
#if __ETT__
					if(iOffset == s1begin)
					{
					    mcSHOW_ERR_MSG(("Error! didn't find trainsition point\n"));
					}
#endif
				}
				else if(iOffset >= (s1end - u1step))
				{
				    s1DQFinalFlagChange[u1BitIdx] = iOffset;
					u1FinishCount ++;

					mcSHOW_ERR_MSG(("Error! didn't find trainsition point\n"));
				}
			}
		}


		u4RestltDQM[0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_AD_RX_DQ_O1), MISC_AD_RX_DQ_O1_AD_RX_ARDQM0_O1_B0);
		if (!isLP4_DSC)
		{
		u4RestltDQM[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_AD_RX_DQ_O1), MISC_AD_RX_DQ_O1_AD_RX_ARDQM0_O1_B1);
		}
		else
		{
			u4RestltDQM[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_AD_RX_CMD_O1), MISC_AD_RX_CMD_O1_AD_RX_ARCS0_O1);
		}

		mcSHOW_DBG_MSG2(("DQM O1 (B1)= 0x%2x, (B0)= 0x%2x\n", u4RestltDQM[1], u4RestltDQM[0]));

		for(u1ByteIdx= 0; u1ByteIdx < DQM_BYTE_NUM; u1ByteIdx++)
		{
			if(s1DQMFinalFlagChange[u1ByteIdx]== 0x7f)
			{
				if(u4RestltDQM[u1ByteIdx]==0)
				{
					s1DQMFinalFlagChange[u1ByteIdx]= iOffset;
					u1FinishCount++;
#if __ETT__
					if(iOffset == s1begin)
					{
					    mcSHOW_ERR_MSG(("Error! didn't find trainsition point\n"));
					}
#endif
				}
				else if(iOffset == (s1end - u1step))
				{
				    s1DQMFinalFlagChange[u1ByteIdx] = iOffset;
					u1FinishCount ++;

					mcSHOW_ERR_MSG(("Error! didn't find trainsition point\n"));
				}
			}
		}

		if(u1FinishCount==(DQM_BYTE_NUM+DQ_DATA_WIDTH))
		{
		    vSetCalibrationResult(p, DRAM_CALIBRATION_RX_INPUT_BUFF_OFFC, DRAM_OK);
		    mcSHOW_DBG_MSG2(("All bits find pass window, early break!\n"));
			break;
		}
	}

	mcSHOW_DBG_MSG2(("O1 Result DQ : [00]%3d [01]%3d [02]%3d [03]%3d [04]%3d [05]%3d [06]%3d [07]%3d\n",
					s1DQFinalFlagChange[0], s1DQFinalFlagChange[1], s1DQFinalFlagChange[2], s1DQFinalFlagChange[3],
					s1DQFinalFlagChange[4], s1DQFinalFlagChange[5], s1DQFinalFlagChange[6], s1DQFinalFlagChange[7]));
	mcSHOW_DBG_MSG2(("O1 Result DQ : [08]%3d [09]%3d [10]%3d [11]%3d [12]%3d [13]%3d [14]%3d [15]%3d\n",
					s1DQFinalFlagChange[8], s1DQFinalFlagChange[9], s1DQFinalFlagChange[10], s1DQFinalFlagChange[11],
					s1DQFinalFlagChange[12], s1DQFinalFlagChange[13], s1DQFinalFlagChange[14],s1DQFinalFlagChange[15]));
	mcSHOW_DBG_MSG2(("O1 Result DQM0 %2d Result DQM1 %2d,\n", s1DQMFinalFlagChange[0], s1DQMFinalFlagChange[1]));

	for(u1BitIdx= 0; u1BitIdx <DQ_DATA_WIDTH; u1BitIdx++)
	{
	    u1DQFinal_rg_offset[u1BitIdx] = RXInputBuf_DelayExchange(s1DQFinalFlagChange[u1BitIdx]);
#ifdef FOR_HQA_REPORT_USED
            if (gHQALog_flag == 1)
            {
                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "RX_Input_Offset", " ", u1BitIdx, s1DQFinalFlagChange[u1BitIdx], NULL);
            }
#endif
	}
	u1DQMFinal_rg_offset[0]= RXInputBuf_DelayExchange(s1DQMFinalFlagChange[0]);
	u1DQMFinal_rg_offset[1]= RXInputBuf_DelayExchange(s1DQMFinalFlagChange[1]);
#ifdef FOR_HQA_REPORT_USED
    if (gHQALog_flag == 1)
    {
        HQA_LOG_Print_Prefix_String(p); mcSHOW_DBG_MSG(("RX_Input_Offset  Channel%d Rank%d DQM0 %d\n", p->channel, p->rank, s1DQMFinalFlagChange[0]));
        HQA_LOG_Print_Prefix_String(p); mcSHOW_DBG_MSG(("RX_Input_Offset  Channel%d Rank%d DQM1 %d\n", p->channel, p->rank, s1DQMFinalFlagChange[1]));
    }
#endif

    for (ii = RANK_0; ii < p->support_rank_num; ii++)
    {
        vSetRank(p, ii);

	vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B0_DQ0),
            P_Fld(u1DQFinal_rg_offset[0], SHU_RK_B0_DQ0_RG_RX_ARDQ0_OFFC_B0) |
            P_Fld(u1DQFinal_rg_offset[1], SHU_RK_B0_DQ0_RG_RX_ARDQ1_OFFC_B0) |
            P_Fld(u1DQFinal_rg_offset[2], SHU_RK_B0_DQ0_RG_RX_ARDQ2_OFFC_B0) |
            P_Fld(u1DQFinal_rg_offset[3], SHU_RK_B0_DQ0_RG_RX_ARDQ3_OFFC_B0) |
            P_Fld(u1DQFinal_rg_offset[4], SHU_RK_B0_DQ0_RG_RX_ARDQ4_OFFC_B0) |
            P_Fld(u1DQFinal_rg_offset[5], SHU_RK_B0_DQ0_RG_RX_ARDQ5_OFFC_B0) |
            P_Fld(u1DQFinal_rg_offset[6], SHU_RK_B0_DQ0_RG_RX_ARDQ6_OFFC_B0) |
            P_Fld(u1DQFinal_rg_offset[7], SHU_RK_B0_DQ0_RG_RX_ARDQ7_OFFC_B0));
		if (!isLP4_DSC)
		{
			vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B1_DQ0),
				P_Fld(u1DQFinal_rg_offset[8], SHU_RK_B1_DQ0_RG_RX_ARDQ0_OFFC_B1) |
				P_Fld(u1DQFinal_rg_offset[9], SHU_RK_B1_DQ0_RG_RX_ARDQ1_OFFC_B1) |
				P_Fld(u1DQFinal_rg_offset[10], SHU_RK_B1_DQ0_RG_RX_ARDQ2_OFFC_B1) |
				P_Fld(u1DQFinal_rg_offset[11], SHU_RK_B1_DQ0_RG_RX_ARDQ3_OFFC_B1) |
				P_Fld(u1DQFinal_rg_offset[12], SHU_RK_B1_DQ0_RG_RX_ARDQ4_OFFC_B1) |
				P_Fld(u1DQFinal_rg_offset[13], SHU_RK_B1_DQ0_RG_RX_ARDQ5_OFFC_B1) |
				P_Fld(u1DQFinal_rg_offset[14], SHU_RK_B1_DQ0_RG_RX_ARDQ6_OFFC_B1) |
				P_Fld(u1DQFinal_rg_offset[15], SHU_RK_B1_DQ0_RG_RX_ARDQ7_OFFC_B1));
		}
		else
		{
			vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_CA_CMD0),
				P_Fld(u1DQFinal_rg_offset[8], SHU_RK_CA_CMD0_RG_RX_ARCA0_OFFC) |
				P_Fld(u1DQFinal_rg_offset[9], SHU_RK_CA_CMD0_RG_RX_ARCA1_OFFC) |
				P_Fld(u1DQFinal_rg_offset[10], SHU_RK_CA_CMD0_RG_RX_ARCA2_OFFC) |
				P_Fld(u1DQFinal_rg_offset[11], SHU_RK_CA_CMD0_RG_RX_ARCA3_OFFC) |
				P_Fld(u1DQFinal_rg_offset[12], SHU_RK_CA_CMD0_RG_RX_ARCA4_OFFC) |
				P_Fld(u1DQFinal_rg_offset[13], SHU_RK_CA_CMD0_RG_RX_ARCA5_OFFC));
			vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_CA_DQ_OFFSET),
				P_Fld(u1DQFinal_rg_offset[14], SHU_RK_CA_DQ_OFFSET_RG_RX_ARDQ6_OFFSETC_C0) |
				P_Fld(u1DQFinal_rg_offset[15], SHU_RK_CA_DQ_OFFSET_RG_RX_ARDQ7_OFFSETC_C0));
		}

		vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B0_DQ1), u1DQMFinal_rg_offset[0], SHU_RK_B0_DQ1_RG_RX_ARDQM0_OFFC_B0);
		if (!isLP4_DSC)
		{
		vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B1_DQ1), u1DQMFinal_rg_offset[1], SHU_RK_B1_DQ1_RG_RX_ARDQM0_OFFC_B1);
		}
		else
		{
		    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_CA_CMD1), u1DQMFinal_rg_offset[1], SHU_RK_CA_CMD1_RG_RX_ARCS0_OFFC);
		}
    }
	vSetRank(p, read_val_b0);


	//vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_RX_IN_GATE_EN_CTRL), 0x0, MISC_RX_IN_GATE_EN_CTRL_FIX_IN_GATE_EN);
	//vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ11), 0x0, SHU_B0_DQ11_RG_RX_ARDQ_OFFSETC_EN_B0);
	//vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ11), 0x0, SHU_B1_DQ11_RG_RX_ARDQ_OFFSETC_EN_B1);

	DramcRestoreRegisters(p, u4RegBackupAddress, ARRAY_SIZE(u4RegBackupAddress));


	vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ11),
            P_Fld(0x1, SHU_B0_DQ11_RG_RX_ARDQ_OFFSETC_BIAS_EN_B0) |
            P_Fld(0x0, SHU_B0_DQ11_RG_RX_ARDQ_OFFSETC_EN_B0));
	if (!isLP4_DSC)
	{
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ11),
            P_Fld(0x1, SHU_B1_DQ11_RG_RX_ARDQ_OFFSETC_BIAS_EN_B1) |
            P_Fld(0x0, SHU_B1_DQ11_RG_RX_ARDQ_OFFSETC_EN_B1));
	}
	else
	{
		vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD11),
			P_Fld(0x1, SHU_CA_CMD11_RG_RX_ARCA_OFFSETC_BIAS_EN_CA) |
			P_Fld(0x0, SHU_CA_CMD11_RG_RX_ARCA_OFFSETC_EN_CA));
	}

	mcSHOW_DBG_MSG2(("[DramcRXInputBufferOffsetCal] ====Done====\n"));

	return DRAM_OK;
}
#endif

#if (SIMULATION_GATING == 1)
#define GATING_PATTERN_NUM_LP5      0x23
#define GATING_GOLDEND_DQSCNT_LP5   0x4646
#define RXDQS_GATING_AUTO_DBG_REG_NUM       6


#if GATING_ADJUST_TXDLY_FOR_TRACKING
U8 u1TXDLY_Cal_min =0xff, u1TXDLY_Cal_max=0;
U8 ucbest_coarse_mck_backup[RANK_MAX][DQS_BYTE_NUMBER];
U8 ucbest_coarse_ui_backup[RANK_MAX][DQS_BYTE_NUMBER];
U8 ucbest_coarse_mck_P1_backup[RANK_MAX][DQS_BYTE_NUMBER];
U8 ucbest_coarse_ui_P1_backup[RANK_MAX][DQS_BYTE_NUMBER];
#endif


struct rxdqs_gating_cal {
    U8 dqsien_dly_mck;
    U8 dqsien_dly_ui;
    U8 dqsien_dly_pi;

    U8 dqsien_dly_mck_p1;
    U8 dqsien_dly_ui_p1;

    U8 dqsien_pi_adj_step;

    U8 dqsien_pi_per_ui;
    U8 dqsien_ui_per_mck;
    U8 dqsien_freq_div;
};

struct rxdqs_gating_trans {
    U8 dqs_lead[DQS_BYTE_NUMBER];
    U8 dqs_lag[DQS_BYTE_NUMBER];
    U8 dqs_high[DQS_BYTE_NUMBER];
#if GATING_LEADLAG_LOW_LEVEL_CHECK
    U8 dqs_low[DQS_BYTE_NUMBER];
#endif
    U8 dqs_transition[DQS_BYTE_NUMBER];
    U8 dqs_transitioned[DQS_BYTE_NUMBER];
    U8 dqsien_dly_mck_leadlag[DQS_BYTE_NUMBER];
    U8 dqsien_dly_ui_leadlag[DQS_BYTE_NUMBER];
    U8 dqsien_dly_pi_leadlag[DQS_BYTE_NUMBER];
};

struct rxdqs_gating_best_win {
    U8 best_dqsien_dly_mck[DQS_BYTE_NUMBER];
    U8 best_dqsien_dly_ui[DQS_BYTE_NUMBER];
    U8 best_dqsien_dly_pi[DQS_BYTE_NUMBER];
    U8 best_dqsien_dly_mck_p1[DQS_BYTE_NUMBER];
    U8 best_dqsien_dly_ui_p1[DQS_BYTE_NUMBER];
    U8 best_dqsien_dly_pi_p1[DQS_BYTE_NUMBER];
};

struct rxdqs_gating_auto_param {
    U8 early_break;
    U8 dbg_mode;

    U8 init_mck;
    U8 init_ui;
    U8 end_mck;
    U8 end_ui;
    U8 pi_offset;

    U8 burst_len;
};

#if ENABLE_GATING_AUTOK_WA
U8 __wa__gating_swk_for_autok = 0;
U8 __wa__gating_autok_init_ui[RANK_MAX] = { 0 };
#endif

static U8 u1GetGatingStartPos(DRAMC_CTX_T *p, U8 u1AutoK)
{
    const U8 au1MR2MappingToRL[2][8] = {{6, 10, 14, 20, 24, 28, 32, 36},
                                        {6, 10, 16, 22, 26, 32, 36, 40}};
    //U8 u1CK2WCK, u1DVFSCEn;
    U8 u1MR0_LatencyMode;
    U8 u1MR2RLValue;

    u1MR2RLValue = u1MR02Value[p->dram_fsp] & 0x7;
    U8 u1RX_Path_delay_UI, u1RealRL,u1StartUI, u1ExtraMCKfor1_4mode;
    U8 u1MCK2CK_UI, u1ReadDQSINCTL, u1DQSINCTL_UI;
    U8 u4TDQSCK_UI_min;
    U8 u1GatingAheadDQS_UI;


    if(gu2MR0_Value[p->rank] == 0xffff)
    {
        u1MR0_LatencyMode = CBT_NORMAL_MODE;
    }
    else
    {
        u1MR0_LatencyMode = (gu2MR0_Value[p->rank]>>1) & 0x1;
    }

    {
        u4TDQSCK_UI_min = 1500 * DDRPhyGetRealFreq(p) *2/ 1000000;
        u1RealRL = au1MR2MappingToRL[u1MR0_LatencyMode][u1MR2RLValue];
    }


    if(vGet_Div_Mode(p) == DIV4_MODE)
    {
        u1MCK2CK_UI = 4;
        u1ExtraMCKfor1_4mode = 1;
        u1GatingAheadDQS_UI = 3;
    }
    else if (vGet_Div_Mode(p) == DIV8_MODE)
    {
        u1MCK2CK_UI = 8;
        u1ExtraMCKfor1_4mode = 0;
        u1GatingAheadDQS_UI = 5;
    }
    else
    {

        u1MCK2CK_UI = 16;
        u1ExtraMCKfor1_4mode = 0;
        u1GatingAheadDQS_UI = 8;
    }


    u1RX_Path_delay_UI = (u1RealRL<<1) + u4TDQSCK_UI_min - u1GatingAheadDQS_UI + (u1MCK2CK_UI*u1ExtraMCKfor1_4mode);

    u1ReadDQSINCTL = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_SHU_RK_DQSCTL), MISC_SHU_RK_DQSCTL_DQSINCTL);
    u1DQSINCTL_UI = u1ReadDQSINCTL * u1MCK2CK_UI;

    if(u1AutoK)
        u1RX_Path_delay_UI += 0;
    else
        u1RX_Path_delay_UI -= 3;

    if(u1RX_Path_delay_UI >= u1DQSINCTL_UI)
        u1StartUI = u1RX_Path_delay_UI - u1DQSINCTL_UI;
    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_MSG2(("[DUMPLOG] %d GatingStartPos_MR0_LatencyMode %d, u1RealRL %d , u4TDQSCK_UI_min %d, 1:4ExtraMCK %d\n", p->frequency * 2, u1MR0_LatencyMode, u1RealRL, u4TDQSCK_UI_min, u1ExtraMCKfor1_4mode));

    if(u1AutoK)
    {
        mcSHOW_DBG_MSG2(("RX_Path_delay_UI(%d) - DQSINCTL_UI(%d) = u1StartUI(%d)\n", u1RX_Path_delay_UI, u1DQSINCTL_UI, u1StartUI));
    }
    else
    {
        mcSHOW_DBG_MSG2(("RX_Path_delay_UI(%d) -3 - DQSINCTL_UI(%d) = u1StartUI(%d)\n", u1RX_Path_delay_UI, u1DQSINCTL_UI, u1StartUI));
    }

    return u1StartUI;
}

#if GATING_RODT_LATANCY_EN
static U8 get_rodt_mck2ui(DRAMC_CTX_T *p)
{
    if (vGet_Div_Mode(p) == DIV16_MODE)
        return 8;
    else if (vGet_Div_Mode(p) == DIV8_MODE)
        return 4;
    else
        return 2;
}
#endif

static u8 rxdqs_gating_bypass(DRAMC_CTX_T *p)
{
#if SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_GatingCal
        if (p->femmc_Ready == 1) {
            mcSHOW_DBG_MSG(("[FAST_K] Bypass Gating Calibration\n"));
            return 1;
        }
#endif

    return 0;
}

static void rxdqs_gating_fastk_save_restore(DRAMC_CTX_T *p,
    struct rxdqs_gating_best_win *best_win,
    struct rxdqs_gating_cal *gating_cal)
{
#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
        u8 ui_per_mck = gating_cal->dqsien_ui_per_mck;
        u8 freq_div = gating_cal->dqsien_freq_div;
        u8 ch = p->channel;
        u8 rk = p->rank;
        u8 dqs_i;

        if (p->femmc_Ready == 1) {
            for (dqs_i = 0; dqs_i < DQS_BYTE_NUMBER; dqs_i++) {
                best_win->best_dqsien_dly_mck[dqs_i] =
                    p->pSavetimeData->u1Gating_MCK_Save[ch][rk][dqs_i];
                best_win->best_dqsien_dly_ui[dqs_i] =
                    p->pSavetimeData->u1Gating_UI_Save[ch][rk][dqs_i];
                best_win->best_dqsien_dly_pi[dqs_i] =
                    p->pSavetimeData->u1Gating_PI_Save[ch][rk][dqs_i];

                /* Calculate P1 */
                best_win->best_dqsien_dly_ui_p1[dqs_i] =
                    best_win->best_dqsien_dly_mck[dqs_i] * ui_per_mck +
                    best_win->best_dqsien_dly_ui[dqs_i] + freq_div;
                best_win->best_dqsien_dly_mck_p1[dqs_i] =
                    best_win->best_dqsien_dly_ui_p1[dqs_i] / ui_per_mck;
                best_win->best_dqsien_dly_ui_p1[dqs_i] =
                    best_win->best_dqsien_dly_ui_p1[dqs_i] % ui_per_mck;

                vSetCalibrationResult(p, DRAM_CALIBRATION_GATING, DRAM_FAST_K);

                mcSHOW_DBG_MSG(("[FAST_K] CH%d RK%d best DQS%d dly(MCK, UI, PI) = (%d, %d, %d)\n",
                    ch, rk, dqs_i, best_win->best_dqsien_dly_mck[dqs_i],
                    best_win->best_dqsien_dly_ui[dqs_i],
                    best_win->best_dqsien_dly_pi[dqs_i]));
                mcSHOW_DBG_MSG(("[FAST_K] CH%d RK%d best DQS%d P1 dly(MCK, UI, PI) = (%d, %d, %d)\n",
                    ch, rk, dqs_i, best_win->best_dqsien_dly_mck_p1[dqs_i],
                    best_win->best_dqsien_dly_ui_p1[dqs_i],
                    best_win->best_dqsien_dly_pi_p1[dqs_i]));

            }
        }
#endif
}

static void rxdqs_gating_misc_process(DRAMC_CTX_T *p,
    struct rxdqs_gating_best_win *rxdqs_best_win)
{
#if GATING_ADJUST_TXDLY_FOR_TRACKING
    U8 u1TX_dly_DQSgated = 0;
#endif
    U8 dqs_i;

    for (dqs_i=0; dqs_i<DQS_BYTE_NUMBER; dqs_i++) {
#ifdef FOR_HQA_REPORT_USED
        HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT6, "DQSINCTL ", "", 0,
            u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_SHU_RK_DQSCTL), MISC_SHU_RK_DQSCTL_DQSINCTL), NULL);
        HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0,
            "Gating_Center_", "2T", dqs_i, rxdqs_best_win->best_dqsien_dly_mck[dqs_i], NULL);
        HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0,
            "Gating_Center_", "05T", dqs_i, rxdqs_best_win->best_dqsien_dly_ui[dqs_i], NULL);
        HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0,
            "Gating_Center_", "PI", dqs_i, rxdqs_best_win->best_dqsien_dly_pi[dqs_i], NULL);
#endif


        mcSHOW_DBG_MSG(("best DQS%d dly(MCK, UI, PI) = (%d, %d, %d)\n", dqs_i,
            rxdqs_best_win->best_dqsien_dly_mck[dqs_i],
            rxdqs_best_win->best_dqsien_dly_ui[dqs_i],
            rxdqs_best_win->best_dqsien_dly_pi[dqs_i]));


#if GATING_ADJUST_TXDLY_FOR_TRACKING
    u1TX_dly_DQSgated = (rxdqs_best_win->best_dqsien_dly_mck[dqs_i] << 4) +
        rxdqs_best_win->best_dqsien_dly_ui[dqs_i];

    if (vGet_Div_Mode(p) == DIV16_MODE)
        u1TX_dly_DQSgated >>= 4;
    else if (vGet_Div_Mode(p) == DIV8_MODE)
        u1TX_dly_DQSgated >>= 3;
    else
        u1TX_dly_DQSgated >>= 2;

    if (u1TX_dly_DQSgated < u1TXDLY_Cal_min)
        u1TXDLY_Cal_min = u1TX_dly_DQSgated;

    ucbest_coarse_ui_backup[p->rank][dqs_i] = rxdqs_best_win->best_dqsien_dly_ui[dqs_i];
    ucbest_coarse_mck_backup[p->rank][dqs_i] = rxdqs_best_win->best_dqsien_dly_mck[dqs_i];
#endif
    }

    mcSHOW_DBG_MSG(("\n"));


    for (dqs_i=0; dqs_i<DQS_BYTE_NUMBER; dqs_i++) {

        mcSHOW_DBG_MSG(("best DQS%d P1 dly(MCK, UI, PI) = (%d, %d, %d)\n", dqs_i,
            rxdqs_best_win->best_dqsien_dly_mck_p1[dqs_i],
            rxdqs_best_win->best_dqsien_dly_ui_p1[dqs_i],
            rxdqs_best_win->best_dqsien_dly_pi_p1[dqs_i]));


#if GATING_ADJUST_TXDLY_FOR_TRACKING

        u1TX_dly_DQSgated = (rxdqs_best_win->best_dqsien_dly_mck_p1[dqs_i] << 4) +
            rxdqs_best_win->best_dqsien_dly_ui_p1[dqs_i];

        if (vGet_Div_Mode(p) == DIV16_MODE)
            u1TX_dly_DQSgated >>= 4;
        else if (vGet_Div_Mode(p) == DIV8_MODE)
            u1TX_dly_DQSgated >>= 3;
        else
            u1TX_dly_DQSgated >>= 2;

        if(u1TX_dly_DQSgated > u1TXDLY_Cal_max)
            u1TXDLY_Cal_max = u1TX_dly_DQSgated;

        ucbest_coarse_ui_P1_backup[p->rank][dqs_i] = rxdqs_best_win->best_dqsien_dly_ui_p1[dqs_i];
        ucbest_coarse_mck_P1_backup[p->rank][dqs_i] = rxdqs_best_win->best_dqsien_dly_mck_p1[dqs_i];
#endif
    }

#if RDSEL_TRACKING_EN
    if(p->frequency >= RDSEL_TRACKING_TH)
    {


        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_INI_UIPI),
            (ucbest_coarse_mck_backup[p->rank][0] << 4) | (ucbest_coarse_ui_backup[p->rank][0]),
            SHU_R0_B0_INI_UIPI_CURR_INI_UI_B0);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_INI_UIPI), rxdqs_best_win->best_dqsien_dly_pi[0],
            SHU_R0_B0_INI_UIPI_CURR_INI_PI_B0);

        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_INI_UIPI),
            (ucbest_coarse_mck_backup[p->rank][1] << 4) | (ucbest_coarse_ui_backup[p->rank][1]),
            SHU_R0_B1_INI_UIPI_CURR_INI_UI_B1);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_INI_UIPI),
            rxdqs_best_win->best_dqsien_dly_pi[1], SHU_R0_B1_INI_UIPI_CURR_INI_PI_B1);
    }
#endif

}

#if GATING_AUTO_K_SUPPORT
static void rxdqs_gating_auto_cal_reset(DRAMC_CTX_T *p)
{

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DQSIEN_AUTOK_CFG0),
        P_Fld(0x1, MISC_DQSIEN_AUTOK_CFG0_DQSIEN_AUTOK_RK0_SW_RST) |
        P_Fld(0x1, MISC_DQSIEN_AUTOK_CFG0_DQSIEN_AUTOK_RK1_SW_RST) |
        P_Fld(0x1, MISC_DQSIEN_AUTOK_CFG0_DQSIEN_AUTOK_SW_RST));

    mcDELAY_US(1);

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DQSIEN_AUTOK_CFG0),
        P_Fld(0x0, MISC_DQSIEN_AUTOK_CFG0_DQSIEN_AUTOK_RK0_SW_RST) |
        P_Fld(0x0, MISC_DQSIEN_AUTOK_CFG0_DQSIEN_AUTOK_RK1_SW_RST) |
        P_Fld(0x0, MISC_DQSIEN_AUTOK_CFG0_DQSIEN_AUTOK_SW_RST));
}
static void rxdqs_gating_auto_cal_cfg(DRAMC_CTX_T *p,
    struct rxdqs_gating_auto_param *auto_param)
{

    rxdqs_gating_auto_cal_reset(p);



    if (p->frequency == 800) {
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL1),
            0x1, MISC_STBCAL1_STBCNT_SW_RST);
    }

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL1),
        0x1, MISC_STBCAL1_STBCNT_SHU_RST_EN);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL2),
        0x1, MISC_STBCAL2_DQSIEN_SELPH_BY_RANK_EN);

    if (p->dram_type == TYPE_LPDDR5) {
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL2),
            0x1, MISC_STBCAL2_STB_PICG_EARLY_1T_EN);
    }

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL1),
        0x1, MISC_STBCAL1_DIS_PI_TRACK_AS_NOT_RD);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ6),
        0x1, B0_DQ6_RG_RX_ARDQ_OP_BIAS_SW_EN_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ6),
        0x1, B0_DQ6_RG_RX_ARDQ_OP_BIAS_SW_EN_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL2),
        0x1, MISC_STBCAL2_STB_PICG_EARLY_1T_EN);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_SHU_STBCAL),
        0x1, MISC_SHU_STBCAL_DQSIEN_BURST_MODE);

    {
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ9),
            0x1, B0_DQ9_RG_RX_ARDQS0_DQSIENMODE_B0);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ9),
            0x1, B1_DQ9_RG_RX_ARDQS0_DQSIENMODE_B1);
    }

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ6),
        0x2, B0_DQ6_RG_RX_ARDQ_BIAS_VREF_SEL_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ6),
        0x2, B1_DQ6_RG_RX_ARDQ_BIAS_VREF_SEL_B1);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL),
        0x1, MISC_STBCAL_DQSIENMODE);


    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL2),
        P_Fld(0x1, MISC_STBCAL2_STB_IG_XRANK_CG_RST) |
        P_Fld(0x1, MISC_STBCAL2_STB_RST_BY_RANK) |
        P_Fld(0x1, MISC_STBCAL2_DQSIEN_SELPH_BY_RANK_EN));

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_PHY2),
        0x1, B0_PHY2_RG_RX_ARDQS_DQSIEN_UI_LEAD_LAG_EN_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_PHY2),
        0x1, B1_PHY2_RG_RX_ARDQS_DQSIEN_UI_LEAD_LAG_EN_B1);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DUMMY_RD),
        0x1, DUMMY_RD_DUMMY_RD_PA_OPT);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_CG_CTRL0),
        0x1, MISC_CG_CTRL0_RG_CG_PHY_OFF_DIABLE);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK_DUMMY_RD_ADR), 3, RK_DUMMY_RD_ADR_DMY_RD_LEN);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4),
        0x4, TEST2_A4_TESTAGENTRKSEL);


    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DQSIEN_AUTOK_CFG0),
        P_Fld(auto_param->init_mck, MISC_DQSIEN_AUTOK_CFG0_DQSIEN_AUTOK_INI_MCK) |
        P_Fld(auto_param->init_ui, MISC_DQSIEN_AUTOK_CFG0_DQSIEN_AUTOK_INI__UI) |
        P_Fld(auto_param->end_mck, MISC_DQSIEN_AUTOK_CFG0_DQSIEN_AUTOK_END_MCK) |
        P_Fld(auto_param->end_ui, MISC_DQSIEN_AUTOK_CFG0_DQSIEN_AUTOK_END__UI) |
        P_Fld(auto_param->pi_offset, MISC_DQSIEN_AUTOK_CFG0_DQSIEN_AUTOK_PI_OFFSET) |
        P_Fld(p->rank, MISC_DQSIEN_AUTOK_CFG0_DQSIEN_AUTOK_CUR_RANK) |
        P_Fld(auto_param->burst_len, MISC_DQSIEN_AUTOK_CFG0_DQSIEN_AUTOK_BURST_LENGTH) |
        P_Fld(0x1, MISC_DQSIEN_AUTOK_CFG0_DQSIEN_AUTOK_B0_EN) |
        P_Fld(0x1, MISC_DQSIEN_AUTOK_CFG0_DQSIEN_AUTOK_B1_EN));

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DQSIEN_AUTOK_CFG0),
        auto_param->dbg_mode, MISC_DQSIEN_AUTOK_CFG0_DQSIEN_AUTOK_DEBUG_MODE_EN);

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DQSIEN_AUTOK_CFG0),
        auto_param->early_break, MISC_DQSIEN_AUTOK_CFG0_DQSIEN_AUTOK_EARLY_BREAK_EN);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL),
        0x0, MISC_STBCAL_PICGEN);
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_MISC_SHU_STBCAL),
        P_Fld(0x0, MISC_SHU_STBCAL_STBCALEN) |
        P_Fld(0x0, MISC_SHU_STBCAL_STB_SELPHCALEN));

    mcSHOW_DBG_MSG(("[Gating] AUTO K with param:\n"));
    mcSHOW_DBG_MSG(("\tinit_mck: %d, init_ui: %d, end_mck: %d, end_ui: %d\n",
        auto_param->init_mck, auto_param->init_ui,
        auto_param->end_mck, auto_param->end_ui));
    mcSHOW_DBG_MSG(("\tpi_offset: %d, early_break: %s\n", auto_param->pi_offset,
        (auto_param->early_break)? "ENABLE" : "DISABLE"));
}

static void rxdqs_gating_auto_cal_trigger(DRAMC_CTX_T *p)
{
    mcSHOW_DBG_MSG(("[Gating] AUTO K start...\n"));
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DQSIEN_AUTOK_CFG0),
        0x1, MISC_DQSIEN_AUTOK_CFG0_DQSIEN_AUTOK_GO);
}

static void rxdqs_gating_auto_cal_stop(DRAMC_CTX_T *p)
{
    mcSHOW_DBG_MSG(("[Gating] AUTO K stop...\n"));
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DQSIEN_AUTOK_CFG0),
        0x0, MISC_DQSIEN_AUTOK_CFG0_DQSIEN_AUTOK_GO);

    rxdqs_gating_auto_cal_reset(p);
}
#endif

static void rxdqs_gating_set_final_result(DRAMC_CTX_T *p, U8 mck2ui,
    struct rxdqs_gating_best_win *best_win)
{
    //U8 reg_mck, reg_ui;
    //U8 value;
    //U8 reg_mck_rodt[DQS_BYTE_NUMBER], reg_ui_rodt[DQS_BYTE_NUMBER];
    //U8 reg_mck_rodt_p1[DQS_BYTE_NUMBER], reg_ui_rodt_p1[DQS_BYTE_NUMBER];
    //U8 dqs_i;

#if GATING_RODT_LATANCY_EN
    for (dqs_i = 0; dqs_i < DQS_BYTE_NUMBER; dqs_i++) {
        reg_mck = best_win->best_dqsien_dly_mck[dqs_i];
        reg_ui = best_win->best_dqsien_dly_ui[dqs_i];

        value = (reg_mck * mck2ui) + reg_ui;

        if (value >= 11) {
            U8 rodt_mck2ui = get_rodt_mck2ui(p);

            value -= 11;
            reg_mck_rodt[dqs_i] = value / rodt_mck2ui;
            reg_ui_rodt[dqs_i] = value % rodt_mck2ui;

            reg_mck_rodt_p1[dqs_i] = reg_mck_rodt[dqs_i];
            reg_ui_rodt_p1[dqs_i] = reg_ui_rodt[dqs_i];
        } else {

            reg_mck_rodt[dqs_i] = 0;
            reg_ui_rodt[dqs_i] = 0;
            reg_mck_rodt_p1[dqs_i] = 4;
            reg_ui_rodt_p1[dqs_i] = 4;
            mcSHOW_DBG_MSG(("[Warning] RODT cannot be -11UI for B%d\n",
                dqs_i));
        }

        mcSHOW_DBG_MSG(("DQS%d Final RODTEN: (%2d, %2d)\n",
            dqs_i, reg_mck_rodt[dqs_i], reg_ui_rodt[dqs_i]));
        mcSHOW_DBG_MSG(("DQS%d Final RODTEN_P1: (%2d, %2d)\n",
            dqs_i, reg_mck_rodt_p1[dqs_i], reg_ui_rodt_p1[dqs_i]));
    }
#endif


    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B0_DQSIEN_MCK_UI_DLY),
        P_Fld(best_win->best_dqsien_dly_mck[0],
        SHU_RK_B0_DQSIEN_MCK_UI_DLY_DQSIEN_MCK_P0_B0) |
        P_Fld(best_win->best_dqsien_dly_ui[0],
        SHU_RK_B0_DQSIEN_MCK_UI_DLY_DQSIEN_UI_P0_B0) |
        P_Fld(best_win->best_dqsien_dly_mck_p1[0],
        SHU_RK_B0_DQSIEN_MCK_UI_DLY_DQSIEN_MCK_P1_B0) |
        P_Fld(best_win->best_dqsien_dly_ui_p1[0],
        SHU_RK_B0_DQSIEN_MCK_UI_DLY_DQSIEN_UI_P1_B0));

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B1_DQSIEN_MCK_UI_DLY),
        P_Fld(best_win->best_dqsien_dly_mck[1],
        SHU_RK_B1_DQSIEN_MCK_UI_DLY_DQSIEN_MCK_P0_B1) |
        P_Fld(best_win->best_dqsien_dly_ui[1],
        SHU_RK_B1_DQSIEN_MCK_UI_DLY_DQSIEN_UI_P0_B1) |
        P_Fld(best_win->best_dqsien_dly_mck_p1[1],
        SHU_RK_B1_DQSIEN_MCK_UI_DLY_DQSIEN_MCK_P1_B1) |
        P_Fld(best_win->best_dqsien_dly_ui_p1[1],
        SHU_RK_B1_DQSIEN_MCK_UI_DLY_DQSIEN_UI_P1_B1));

#if GATING_RODT_LATANCY_EN
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B0_RODTEN_MCK_UI_DLY),
        P_Fld(reg_mck_rodt[0],
        SHU_RK_B0_RODTEN_MCK_UI_DLY_RODTEN_MCK_P0_B0) |
        P_Fld(reg_ui_rodt[0],
        SHU_RK_B0_RODTEN_MCK_UI_DLY_RODTEN_UI_P0_B0) |
        P_Fld(reg_mck_rodt_p1[0],
        SHU_RK_B0_RODTEN_MCK_UI_DLY_RODTEN_MCK_P1_B0) |
        P_Fld(reg_ui_rodt_p1[0],
        SHU_RK_B0_RODTEN_MCK_UI_DLY_RODTEN_UI_P1_B0));

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B1_RODTEN_MCK_UI_DLY),
        P_Fld(reg_mck_rodt[1],
        SHU_RK_B1_RODTEN_MCK_UI_DLY_RODTEN_MCK_P0_B1) |
        P_Fld(reg_ui_rodt[1],
        SHU_RK_B1_RODTEN_MCK_UI_DLY_RODTEN_UI_P0_B1) |
        P_Fld(reg_mck_rodt_p1[1],
        SHU_RK_B1_RODTEN_MCK_UI_DLY_RODTEN_MCK_P1_B1) |
        P_Fld(reg_ui_rodt_p1[1],
        SHU_RK_B1_RODTEN_MCK_UI_DLY_RODTEN_UI_P1_B1));
#endif

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B0_DQSIEN_PI_DLY),
        best_win->best_dqsien_dly_pi[0],
        SHU_RK_B0_DQSIEN_PI_DLY_DQSIEN_PI_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B1_DQSIEN_PI_DLY),
        best_win->best_dqsien_dly_pi[1],
        SHU_RK_B1_DQSIEN_PI_DLY_DQSIEN_PI_B1);

}

#if GATING_AUTO_K_SUPPORT

static void rxdqs_gating_auto_xlate(DRAMC_CTX_T *p,
    struct rxdqs_gating_best_win *best_win,
    struct rxdqs_gating_cal *rxdqs_cal)
{
    u8 mck, ui, pi;
    U8 mck_p1, ui_p1;
    u8 mck2ui, freq_div;
    U8 total_ui;
#if GATING_RODT_LATANCY_EN
    U8 mck_rodt, ui_rodt;
    U8 mck_rodt_p1, ui_rodt_p1;
#endif
    U16 value;
    u8 dqs_i;


    for (dqs_i = 0; dqs_i < DQS_BYTE_NUMBER; dqs_i++) {
        mck = best_win->best_dqsien_dly_mck[dqs_i];
        ui = best_win->best_dqsien_dly_ui[dqs_i];
        pi = best_win->best_dqsien_dly_pi[dqs_i];
        mck2ui = rxdqs_cal->dqsien_ui_per_mck;
        freq_div = rxdqs_cal->dqsien_freq_div;

        if (vGet_Div_Mode(p) == DIV16_MODE)
            total_ui = (mck << 4) + ui;
        else if (vGet_Div_Mode(p) == DIV8_MODE)
            total_ui = (mck << 3) + ui;
        else
            total_ui = (mck << 2) + ui;


        mck = (total_ui >> 4);
        ui = (total_ui & 0xf);

        value = mck * mck2ui + ui;
        mck_p1 = (value + freq_div) / mck2ui;
        ui_p1 = (value + freq_div) % mck2ui;

        mcSHOW_DBG_MSG(("[Gating][RG] DQS%d Final result: (%d, %d, %d)\n", dqs_i, mck, ui, pi));
        mcSHOW_DBG_MSG(("[Gating][RG] DQS%d Final result P1: (%d, %d)\n", dqs_i, mck_p1, ui_p1));

        best_win->best_dqsien_dly_mck[dqs_i] = mck;
        best_win->best_dqsien_dly_ui[dqs_i] = ui;
        best_win->best_dqsien_dly_pi[dqs_i] = pi;

        best_win->best_dqsien_dly_mck_p1[dqs_i] = mck_p1;
        best_win->best_dqsien_dly_ui_p1[dqs_i] = ui_p1;
        best_win->best_dqsien_dly_pi_p1[dqs_i] = pi;
    }
}

#define RXDQS_GATING_AUTO_CAL_STATUS_BYTE_OFFSET        0x40

static DRAM_STATUS_T rxdqs_gating_auto_cal_status(DRAMC_CTX_T *p,
    struct rxdqs_gating_auto_param *auto_param,
    struct rxdqs_gating_best_win *best_win)
{
    U8 mck_center[DQS_BYTE_NUMBER], ui_center[DQS_BYTE_NUMBER], pi_center[DQS_BYTE_NUMBER];
    U8 mck_left[DQS_BYTE_NUMBER], ui_left[DQS_BYTE_NUMBER], pi_left[DQS_BYTE_NUMBER];
    U8 mck_right[DQS_BYTE_NUMBER], ui_right[DQS_BYTE_NUMBER], pi_right[DQS_BYTE_NUMBER];
    U8 done[DQS_BYTE_NUMBER] = { 0 }, error[DQS_BYTE_NUMBER] = { 0 };
    DRAM_STATUS_T ret;
    U8 done_bytes, total_bytes;
    U8 byte_ofst;
    U8 dqs_i;
    //U8 div_mode;

    total_bytes = DQS_BYTE_NUMBER;
    done_bytes = 0;
    ret = DRAM_OK;

    while (done_bytes < total_bytes) {
        for (dqs_i = 0; dqs_i < DQS_BYTE_NUMBER; dqs_i++) {

            if (done[dqs_i])
                continue;

            byte_ofst = dqs_i * RXDQS_GATING_AUTO_CAL_STATUS_BYTE_OFFSET;

            done[dqs_i] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(
                DDRPHY_REG_DQSIEN_AUTOK_B0_RK0_STATUS0 + byte_ofst),
                DQSIEN_AUTOK_B0_RK0_STATUS0_AUTOK_DONE_B0_RK0);
            error[dqs_i] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(
                DDRPHY_REG_DQSIEN_AUTOK_B0_RK0_STATUS0 + byte_ofst),
                DQSIEN_AUTOK_B0_RK0_STATUS0_AUTOK_ERR_B0_RK0);


            if (done[dqs_i] || error[dqs_i]) {

                if (error[dqs_i] == 0) {
                    mck_center[dqs_i] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(
                        DDRPHY_REG_DQSIEN_AUTOK_B0_RK0_STATUS0 + byte_ofst),
                        DQSIEN_AUTOK_B0_RK0_STATUS0_DQSIEN_AUTOK_C_MCK_B0_RK0);
                    ui_center[dqs_i] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(
                        DDRPHY_REG_DQSIEN_AUTOK_B0_RK0_STATUS0 + byte_ofst),
                        DQSIEN_AUTOK_B0_RK0_STATUS0_DQSIEN_AUTOK_C__UI_B0_RK0);
                    pi_center[dqs_i] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(
                        DDRPHY_REG_DQSIEN_AUTOK_B0_RK0_STATUS0 + byte_ofst),
                        DQSIEN_AUTOK_B0_RK0_STATUS0_DQSIEN_AUTOK_C__PI_B0_RK0);

                    mck_left[dqs_i] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(
                        DDRPHY_REG_DQSIEN_AUTOK_B0_RK0_STATUS1 + byte_ofst),
                        DQSIEN_AUTOK_B0_RK0_STATUS1_DQSIEN_AUTOK_L_MCK_B0_RK0);
                    ui_left[dqs_i] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(
                        DDRPHY_REG_DQSIEN_AUTOK_B0_RK0_STATUS1 + byte_ofst),
                        DQSIEN_AUTOK_B0_RK0_STATUS1_DQSIEN_AUTOK_L__UI_B0_RK0);
                    pi_left[dqs_i] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(
                        DDRPHY_REG_DQSIEN_AUTOK_B0_RK0_STATUS1 + byte_ofst),
                        DQSIEN_AUTOK_B0_RK0_STATUS1_DQSIEN_AUTOK_L__PI_B0_RK0);


                    if (auto_param->early_break == DISABLE) {
                        mck_right[dqs_i] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(
                            DDRPHY_REG_DQSIEN_AUTOK_B0_RK0_STATUS1 + byte_ofst),
                            DQSIEN_AUTOK_B0_RK0_STATUS1_DQSIEN_AUTOK_R_MCK_B0_RK0);
                        ui_right[dqs_i] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(
                            DDRPHY_REG_DQSIEN_AUTOK_B0_RK0_STATUS1 + byte_ofst),
                            DQSIEN_AUTOK_B0_RK0_STATUS1_DQSIEN_AUTOK_R__UI_B0_RK0);
                        pi_right[dqs_i] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(
                            DDRPHY_REG_DQSIEN_AUTOK_B0_RK0_STATUS1 + byte_ofst),
                            DQSIEN_AUTOK_B0_RK0_STATUS1_DQSIEN_AUTOK_R__PI_B0_RK0);
                    }
                }
                else
                {

                    done[dqs_i] = 1;
                }

                if (auto_param->dbg_mode == ENABLE) {
                    U32 dbg_reg_addr;
                    U32 dbg_reg_idx;
                    U32 dbg_reg_val;

                    dbg_reg_addr = DRAMC_REG_ADDR(
                        DDRPHY_REG_DQSIEN_AUTOK_B0_RK0_DBG_STATUS0 + byte_ofst);
                    for (dbg_reg_idx = 0;
                        dbg_reg_idx < RXDQS_GATING_AUTO_DBG_REG_NUM;
                        dbg_reg_idx++, dbg_reg_addr += 4) {
                        dbg_reg_val = u4IO32Read4B(dbg_reg_addr);

                        mcSHOW_ERR_MSG(("B%d Gating AUTOK DBG Status-%d: [0x%08x]\n",
                            dqs_i, dbg_reg_idx, dbg_reg_val));
                    }
                }
            }
            else
            {
                mcSHOW_ERR_MSG(("B%d Gating AUTOK didn't be done\n", dqs_i));
            }
            done_bytes++;
        }

        mcDELAY_MS(1);
    }


    for (dqs_i = 0; dqs_i < DQS_BYTE_NUMBER; dqs_i++) {
        mcSHOW_DBG_MSG(("[Gating][%s] AUTOK of CH-%d, Rk-%d, Byte-%d:\n",
            error[dqs_i]? "Fail" : "Pass", p->channel, p->rank, dqs_i));

        if (done[dqs_i]) {
            if (error[dqs_i] == 0) {
                mcSHOW_DBG_MSG(("\tcenter(%2d, %2d, %2d)\n",
                            mck_center[dqs_i], ui_center[dqs_i], pi_center[dqs_i]));
                mcSHOW_DBG_MSG(("\tleft(%2d, %2d, %2d)\n",
                            mck_left[dqs_i], ui_left[dqs_i], pi_left[dqs_i]));

                if (auto_param->early_break == DISABLE) {
                    mcSHOW_DBG_MSG(("\tright(%2d, %2d, %2d)\n",
                                mck_right[dqs_i], ui_right[dqs_i], pi_right[dqs_i]));
                }
            }
            if (error[dqs_i]) {
                ret = DRAM_FAIL;
            } else {

                best_win->best_dqsien_dly_mck[dqs_i] = mck_center[dqs_i];
                best_win->best_dqsien_dly_ui[dqs_i] = ui_center[dqs_i];
                best_win->best_dqsien_dly_pi[dqs_i] = pi_center[dqs_i];
            }
        }
    }

    rxdqs_gating_auto_cal_stop(p);

    return ret;
}

static DRAM_STATUS_T dramc_rx_dqs_gating_auto_cal(DRAMC_CTX_T *p)
{
    struct rxdqs_gating_auto_param auto_param;
    struct rxdqs_gating_best_win rxdqs_best_win;
    struct rxdqs_gating_cal rxdqs_cal;
    DRAM_STATUS_T ret;
    U8 start_ui, end_ui;
    U8 mck2ui_hw; //mck2ui_rg, freq_div

    U32 reg_backup_address[ ] = {
        (DRAMC_REG_ADDR(DRAMC_REG_DUMMY_RD)),
        (DRAMC_REG_ADDR(DDRPHY_REG_MISC_CG_CTRL0)),
        (DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4)),
        (DRAMC_REG_ADDR(DRAMC_REG_RK_DUMMY_RD_ADR))
    };

    DramcBackupRegisters(p, reg_backup_address,
        sizeof (reg_backup_address) / sizeof (U32));

    ret = DRAM_OK;

    memset((void *)&auto_param, 0, sizeof auto_param);
    memset((void *)&rxdqs_best_win, 0, sizeof rxdqs_best_win);
    memset((void *)&rxdqs_cal, 0, sizeof rxdqs_cal);

    if (vGet_Div_Mode(p) == DIV4_MODE)
        rxdqs_cal.dqsien_freq_div = 2;
    else
        rxdqs_cal.dqsien_freq_div = 4;
    rxdqs_cal.dqsien_ui_per_mck = DQS_GW_UI_PER_MCK;

    if (!rxdqs_gating_bypass(p)) {
        if (vGet_Div_Mode(p) == DIV16_MODE)
            mck2ui_hw = 16;
        else if (vGet_Div_Mode(p) == DIV8_MODE)
            mck2ui_hw = 8;
        else
            mck2ui_hw = 4;

#if ENABLE_GATING_AUTOK_WA
        if (__wa__gating_autok_init_ui[p->rank] > 3)
            start_ui = __wa__gating_autok_init_ui[p->rank] - 3;
        else
#endif
        start_ui = u1GetGatingStartPos(p, AUTOK_ON);
        end_ui = start_ui + 32;


        auto_param.early_break = ENABLE;
        auto_param.dbg_mode = ENABLE;
        auto_param.init_mck = start_ui / mck2ui_hw;
        auto_param.init_ui = start_ui % mck2ui_hw;
        auto_param.end_mck = end_ui / mck2ui_hw;
        auto_param.end_ui = end_ui % mck2ui_hw;
        auto_param.pi_offset = 2;
        auto_param.burst_len = RXDQS_BURST_LEN_8;


#if FOR_DV_SIMULATION_USED == 1
        cal_sv_rand_args_t *psra = get_psra();

        if (psra) {
            auto_param.early_break =
                    psra->dqsien_autok_early_break_en? ENABLE: DISABLE;
            auto_param.dbg_mode =
                    psra->dqsien_autok_dbg_mode_en? ENABLE: DISABLE;
            auto_param.pi_offset =
                    psra->dqsien_autok_pi_offset? ENABLE: DISABLE;
        }
#endif

        rxdqs_gating_auto_cal_cfg(p, &auto_param);


        rxdqs_gating_auto_cal_trigger(p);

        ret = rxdqs_gating_auto_cal_status(p, &auto_param, &rxdqs_best_win);
        if (ret == DRAM_OK)
            vSetCalibrationResult(p, DRAM_CALIBRATION_GATING, DRAM_OK);

        rxdqs_gating_auto_xlate(p, &rxdqs_best_win, &rxdqs_cal);
    }

    rxdqs_gating_fastk_save_restore(p, &rxdqs_best_win, &rxdqs_cal);
    rxdqs_gating_set_final_result(p, rxdqs_cal.dqsien_ui_per_mck, &rxdqs_best_win);

    rxdqs_gating_misc_process(p, &rxdqs_best_win);
    DramcRestoreRegisters(p, reg_backup_address,
        sizeof (reg_backup_address) / sizeof (U32));

    DramPhyReset(p);

    return ret;
}
#endif

static void rxdqs_gating_sw_cal_init(DRAMC_CTX_T *p, U8 use_enhanced_rdqs)
{


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_CONF0),  0, SHU_CONF0_PBREFEN);


    if (p->frequency == 800) {
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL1),
            0x1, MISC_STBCAL1_STBCNT_SW_RST);
    }

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL1),
        0x1, MISC_STBCAL1_STBCNT_SHU_RST_EN);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL2),
        0x1, MISC_STBCAL2_DQSIEN_SELPH_BY_RANK_EN);

    if (p->dram_type == TYPE_LPDDR5) {
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL2),
            0x1, MISC_STBCAL2_STB_PICG_EARLY_1T_EN);
    }

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL1),
        0x1, MISC_STBCAL1_DIS_PI_TRACK_AS_NOT_RD);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ6),
        0x1, B0_DQ6_RG_RX_ARDQ_OP_BIAS_SW_EN_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ6),
        0x1, B0_DQ6_RG_RX_ARDQ_OP_BIAS_SW_EN_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL2),
        0x1, MISC_STBCAL2_STB_PICG_EARLY_1T_EN);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_SHU_STBCAL),
        0x1, MISC_SHU_STBCAL_DQSIEN_BURST_MODE);

    {
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ9),
            0x1, B0_DQ9_RG_RX_ARDQS0_DQSIENMODE_B0);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ9),
            0x1, B1_DQ9_RG_RX_ARDQS0_DQSIENMODE_B1);
    }

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ6),
        0x2, B0_DQ6_RG_RX_ARDQ_BIAS_VREF_SEL_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ6),
        0x2, B1_DQ6_RG_RX_ARDQ_BIAS_VREF_SEL_B1);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL),
        0x1, MISC_STBCAL_DQSIENMODE);


    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL2),
        P_Fld(0x1, MISC_STBCAL2_STB_IG_XRANK_CG_RST) |
        P_Fld(0x1, MISC_STBCAL2_STB_RST_BY_RANK) |
        P_Fld(0x1, MISC_STBCAL2_DQSIEN_SELPH_BY_RANK_EN));

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_PHY2),
        0x1, B0_PHY2_RG_RX_ARDQS_DQSIEN_UI_LEAD_LAG_EN_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_PHY2),
        0x1, B1_PHY2_RG_RX_ARDQS_DQSIEN_UI_LEAD_LAG_EN_B1);

    //DramcHWGatingOnOff(p, 0);

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL2), 1,
        MISC_STBCAL2_STBENCMPEN);

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RX_SET0), 0,
        RX_SET0_DM4TO1MODE);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL2), 1,
        MISC_STBCAL2_DQSG_CNT_EN);
    mcDELAY_US(4);

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL2), 1,
        MISC_STBCAL2_DQSG_CNT_RST);
    mcDELAY_US(1);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL2), 0,
        MISC_STBCAL2_DQSG_CNT_RST);

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_CTRL1),
        u1GetRank(p), MISC_CTRL1_R_DMSTBENCMP_RK_OPT);
    DramcEngine2Init(p, 0x55000000,
        0xaa000000 | GATING_PATTERN_NUM_LP5, TEST_AUDIO_PATTERN, 0, TE_NO_UI_SHIFT);

    if (use_enhanced_rdqs) {

    }
}

static void rxdqs_gating_set_dqsien_dly(DRAMC_CTX_T *p, U8 dly_ui,
    struct rxdqs_gating_cal *rxdqs_cal)
{
    //U32 value;
    U32 reg_mck, reg_ui;
    U32 reg_mck_p1, reg_ui_p1;
#if GATING_RODT_LATANCY_EN
    U32 reg_mck_rodt, reg_ui_rodt;
    U32 reg_mck_rodt_p1, reg_ui_rodt_p1;
#endif
    U8 mck2ui = rxdqs_cal->dqsien_ui_per_mck;

    rxdqs_cal->dqsien_dly_mck = dly_ui / rxdqs_cal->dqsien_ui_per_mck;
    rxdqs_cal->dqsien_dly_ui = dly_ui % rxdqs_cal->dqsien_ui_per_mck;
    rxdqs_cal->dqsien_dly_mck_p1 = (dly_ui + rxdqs_cal->dqsien_freq_div) / mck2ui;
    rxdqs_cal->dqsien_dly_ui_p1 = (dly_ui + rxdqs_cal->dqsien_freq_div) % mck2ui;

    reg_mck = rxdqs_cal->dqsien_dly_mck;
    reg_ui = rxdqs_cal->dqsien_dly_ui;
    reg_mck_p1 = rxdqs_cal->dqsien_dly_mck_p1;
    reg_ui_p1 = rxdqs_cal->dqsien_dly_ui_p1;

#if GATING_RODT_LATANCY_EN
    value = (reg_mck * mck2ui) + reg_ui;

    if (value >= 11) {

        U8 rodt_mck2ui = get_rodt_mck2ui(p);

        value -= 11;
        reg_mck_rodt = value / rodt_mck2ui;
        reg_ui_rodt = value % rodt_mck2ui;

        reg_mck_rodt_p1 = reg_mck_rodt;
        reg_ui_rodt_p1 = reg_ui_rodt;
    } else {

        reg_mck_rodt = 0;
        reg_ui_rodt = 0;
        reg_mck_rodt_p1 = 4;
        reg_ui_rodt_p1 = 4;
        mcSHOW_DBG_MSG(("[Warning] RODT cannot be -11UI\n"));
    }
#endif


    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B0_DQSIEN_MCK_UI_DLY),
        P_Fld(reg_mck,
        SHU_RK_B0_DQSIEN_MCK_UI_DLY_DQSIEN_MCK_P0_B0) |
        P_Fld(reg_ui,
        SHU_RK_B0_DQSIEN_MCK_UI_DLY_DQSIEN_UI_P0_B0) |
        P_Fld(reg_mck_p1,
        SHU_RK_B0_DQSIEN_MCK_UI_DLY_DQSIEN_MCK_P1_B0) |
        P_Fld(reg_ui_p1,
        SHU_RK_B0_DQSIEN_MCK_UI_DLY_DQSIEN_UI_P1_B0));

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B1_DQSIEN_MCK_UI_DLY),
        P_Fld(reg_mck,
        SHU_RK_B1_DQSIEN_MCK_UI_DLY_DQSIEN_MCK_P0_B1) |
        P_Fld(reg_ui,
        SHU_RK_B1_DQSIEN_MCK_UI_DLY_DQSIEN_UI_P0_B1) |
        P_Fld(reg_mck_p1,
        SHU_RK_B1_DQSIEN_MCK_UI_DLY_DQSIEN_MCK_P1_B1) |
        P_Fld(reg_ui_p1,
        SHU_RK_B1_DQSIEN_MCK_UI_DLY_DQSIEN_UI_P1_B1));

#if GATING_RODT_LATANCY_EN
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B0_RODTEN_MCK_UI_DLY),
        P_Fld(reg_mck_rodt,
        SHU_RK_B0_RODTEN_MCK_UI_DLY_RODTEN_MCK_P0_B0) |
        P_Fld(reg_ui_rodt,
        SHU_RK_B0_RODTEN_MCK_UI_DLY_RODTEN_UI_P0_B0) |
        P_Fld(reg_mck_rodt_p1,
        SHU_RK_B0_RODTEN_MCK_UI_DLY_RODTEN_MCK_P1_B0) |
        P_Fld(reg_ui_rodt_p1,
        SHU_RK_B0_RODTEN_MCK_UI_DLY_RODTEN_UI_P1_B0));

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B1_RODTEN_MCK_UI_DLY),
        P_Fld(reg_mck_rodt,
        SHU_RK_B1_RODTEN_MCK_UI_DLY_RODTEN_MCK_P0_B1) |
        P_Fld(reg_ui_rodt,
        SHU_RK_B1_RODTEN_MCK_UI_DLY_RODTEN_UI_P0_B1) |
        P_Fld(reg_mck_rodt_p1,
        SHU_RK_B1_RODTEN_MCK_UI_DLY_RODTEN_MCK_P1_B1) |
        P_Fld(reg_ui_rodt_p1,
        SHU_RK_B1_RODTEN_MCK_UI_DLY_RODTEN_UI_P1_B1));
#endif
}

static void rxdqs_gating_sw_cal_trigger(DRAMC_CTX_T *p,
    struct rxdqs_gating_cal *rxdqs_cal)
{
#if 0
    if (u1IsPhaseMode(p) == TRUE) {
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_DQ0),
            rxdqs_cal->dqsien_dly_pi >> 4, SHU_R0_B0_DQ0_DA_ARPI_DDR400_0D5UI_RK0_B0);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_DQ0),
            rxdqs_cal->dqsien_dly_pi >> 4, SHU_R0_B1_DQ0_DA_ARPI_DDR400_0D5UI_RK0_B1);
    } else
#endif
    {
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B0_DQSIEN_PI_DLY),
            rxdqs_cal->dqsien_dly_pi, SHU_RK_B0_DQSIEN_PI_DLY_DQSIEN_PI_B0);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B1_DQSIEN_PI_DLY),
            rxdqs_cal->dqsien_dly_pi, SHU_RK_B1_DQSIEN_PI_DLY_DQSIEN_PI_B1);
    }
    DramPhyReset(p);

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL2), 1,
        MISC_STBCAL2_DQSG_CNT_RST);
    mcDELAY_US(1);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL2), 0,
        MISC_STBCAL2_DQSG_CNT_RST);


    DramcEngine2Run(p, TE_OP_READ_CHECK, TEST_AUDIO_PATTERN);
}

static void rxdqs_gating_get_leadlag(DRAMC_CTX_T *p,
    struct rxdqs_gating_trans *rxdqs_trans,
    struct rxdqs_gating_cal *rxdqs_cal)
{
    U8 dqs_i;
    U8 debounce_thrd_PI = 16;
    BOOL isLP4_DSC = (p->DRAMPinmux == PINMUX_DSC)?1:0;

    for (dqs_i = 0; dqs_i < DQS_BYTE_NUMBER; dqs_i++) {
        if (dqs_i == 0) {
            rxdqs_trans->dqs_lead[0] = u4IO32ReadFldAlign(
                DRAMC_REG_ADDR(DDRPHY_REG_MISC_PHY_RGS_STBEN_B0),
                MISC_PHY_RGS_STBEN_B0_AD_RX_ARDQS0_STBEN_LEAD_B0);
            rxdqs_trans->dqs_lag[0] = u4IO32ReadFldAlign(
                DRAMC_REG_ADDR(DDRPHY_REG_MISC_PHY_RGS_STBEN_B0),
                MISC_PHY_RGS_STBEN_B0_AD_RX_ARDQS0_STBEN_LAG_B0);
        } else {
            if (isLP4_DSC){
                rxdqs_trans->dqs_lead[1] = u4IO32ReadFldAlign(
                    DRAMC_REG_ADDR(DDRPHY_REG_MISC_PHY_RGS_STBEN_CMD),
                    MISC_PHY_RGS_STBEN_CMD_AD_RX_ARCLK_STBEN_LEAD);
                rxdqs_trans->dqs_lag[1] = u4IO32ReadFldAlign(
                    DRAMC_REG_ADDR(DDRPHY_REG_MISC_PHY_RGS_STBEN_CMD),
                    MISC_PHY_RGS_STBEN_CMD_AD_RX_ARCLK_STBEN_LAG);
            } else {
                rxdqs_trans->dqs_lead[1] = u4IO32ReadFldAlign(
                    DRAMC_REG_ADDR(DDRPHY_REG_MISC_PHY_RGS_STBEN_B1),
                    MISC_PHY_RGS_STBEN_B1_AD_RX_ARDQS0_STBEN_LEAD_B1);
                rxdqs_trans->dqs_lag[1] = u4IO32ReadFldAlign(
                    DRAMC_REG_ADDR(DDRPHY_REG_MISC_PHY_RGS_STBEN_B1),
                    MISC_PHY_RGS_STBEN_B1_AD_RX_ARDQS0_STBEN_LAG_B1);
            }

        }

        if ((rxdqs_trans->dqs_lead[dqs_i] == 1) &&
            (rxdqs_trans->dqs_lag[dqs_i] == 1)) {
            rxdqs_trans->dqs_high[dqs_i]++;
            rxdqs_trans->dqs_transition[dqs_i] = 1;


            rxdqs_trans->dqsien_dly_mck_leadlag[dqs_i] =
                rxdqs_cal->dqsien_dly_mck;
            rxdqs_trans->dqsien_dly_ui_leadlag[dqs_i] =
                rxdqs_cal->dqsien_dly_ui;
            rxdqs_trans->dqsien_dly_pi_leadlag[dqs_i] =
                rxdqs_cal->dqsien_dly_pi;
        } else if ((rxdqs_trans->dqs_high[dqs_i] *
            rxdqs_cal->dqsien_pi_adj_step) >= debounce_thrd_PI) {

            if (((rxdqs_trans->dqs_lead[dqs_i] == 1) &&
                (rxdqs_trans->dqs_lag[dqs_i] == 0)) ||
                ((rxdqs_trans->dqs_lead[dqs_i] == 0) &&
                (rxdqs_trans->dqs_lag[dqs_i] == 1))) {
                rxdqs_trans->dqs_transition[dqs_i]++;
            }
        #if GATING_LEADLAG_LOW_LEVEL_CHECK
            else if ((rxdqs_trans->dqs_lead[dqs_i] == 0) &&
                (rxdqs_trans->dqs_lag[dqs_i] == 0)){
                if ((rxdqs_trans->dqs_low[dqs_i] *
                     rxdqs_cal->dqsien_pi_adj_step) >= debounce_thrd_PI) {

                rxdqs_trans->dqs_transitioned[dqs_i] = 1;
                    }
                rxdqs_trans->dqs_low[dqs_i]++;
            }else {
                  rxdqs_trans->dqs_high[dqs_i] = 0;
                  rxdqs_trans->dqs_low[dqs_i] = 0;
                }
        #else
        else {

            rxdqs_trans->dqs_transitioned[dqs_i] = 1;
        }
        #endif
        } else {

            rxdqs_trans->dqs_high[dqs_i] = 0;
        #if GATING_LEADLAG_LOW_LEVEL_CHECK
            rxdqs_trans->dqs_low[dqs_i] = 0;
        #endif
        }
    }
}

static U8 rxdqs_gating_sw_cal(DRAMC_CTX_T *p,
    struct rxdqs_gating_trans *rxdqs_trans,
    struct rxdqs_gating_cal *rxdqs_cal, U8 *pass_byte_count,
    struct rxdqs_gating_best_win *best_win, U8 dly_ui, U8 dly_ui_end)
{
    U8 gating_error[DQS_BYTE_NUMBER];
    U32 debug_cnt[DQS_BYTE_NUMBER];
    U32 debug_pass_cnt;
    U8 dqs_i;
    //U8 dqs_result_r, dqs_result_f;
    //U16 debug_cnt_per_byte;
    U8 passed_bytes;

    memset(debug_cnt, 0, sizeof(debug_cnt));
    passed_bytes = *pass_byte_count;

    rxdqs_gating_sw_cal_trigger(p, rxdqs_cal);

    if (p->rank == RANK_0) {
        gating_error[0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(
            DDRPHY_REG_MISC_STBERR_ALL),
            MISC_STBERR_ALL_GATING_ERROR_B0_RK0);
        gating_error[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(
            DDRPHY_REG_MISC_STBERR_ALL),
            MISC_STBERR_ALL_GATING_ERROR_B1_RK0);
    } else {
        gating_error[0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(
            DDRPHY_REG_MISC_STBERR_ALL),
            MISC_STBERR_ALL_GATING_ERROR_B0_RK1);
        gating_error[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(
            DDRPHY_REG_MISC_STBERR_ALL),
            MISC_STBERR_ALL_GATING_ERROR_B1_RK1);
    }


    debug_cnt[0] = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_CAL_DQSG_CNT_B0));
    debug_cnt[1] = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_CAL_DQSG_CNT_B1));


    rxdqs_gating_get_leadlag(p, rxdqs_trans, rxdqs_cal);

    mcSHOW_DBG_MSG2(("%2d %2d %2d | ",
        rxdqs_cal->dqsien_dly_mck, rxdqs_cal->dqsien_dly_ui,
        rxdqs_cal->dqsien_dly_pi));
    mcSHOW_DBG_MSG2(("B1->B0 | %x %x | %x %x | (%d %d) (%d %d)\n",
        debug_cnt[1], debug_cnt[0],
        gating_error[1], gating_error[0],
        rxdqs_trans->dqs_lead[1], rxdqs_trans->dqs_lag[1],
        rxdqs_trans->dqs_lead[0], rxdqs_trans->dqs_lag[0]));

        debug_pass_cnt = GATING_GOLDEND_DQSCNT_LP5;


    for (dqs_i = 0; dqs_i < DQS_BYTE_NUMBER; dqs_i++) {
        if (passed_bytes & (1 << dqs_i))
            continue;

        if ((gating_error[dqs_i] == 0) && (debug_cnt[dqs_i] == debug_pass_cnt)) {

            if (rxdqs_trans->dqs_transitioned[dqs_i] != 0) {
                U8 pass_count = rxdqs_trans->dqs_transition[dqs_i];
                U8 offset = (pass_count * rxdqs_cal->dqsien_pi_adj_step) / 2;
                U8 mck2ui, ui2pi, freq_div;
                U8 tmp;

                mck2ui = rxdqs_cal->dqsien_ui_per_mck;
                ui2pi = rxdqs_cal->dqsien_pi_per_ui;
                freq_div = rxdqs_cal->dqsien_freq_div;


                tmp = rxdqs_trans->dqsien_dly_pi_leadlag[dqs_i] + offset;
                best_win->best_dqsien_dly_pi[dqs_i] = tmp % ui2pi;
                best_win->best_dqsien_dly_pi_p1[dqs_i] =
                    best_win->best_dqsien_dly_pi[dqs_i];


                tmp /= ui2pi;
                tmp = rxdqs_trans->dqsien_dly_ui_leadlag[dqs_i] + tmp;
                best_win->best_dqsien_dly_ui[dqs_i] = tmp % mck2ui;
                best_win->best_dqsien_dly_mck[dqs_i] =
                    rxdqs_trans->dqsien_dly_mck_leadlag[dqs_i] + (tmp / mck2ui);


                best_win->best_dqsien_dly_ui_p1[dqs_i] =
                    best_win->best_dqsien_dly_mck[dqs_i] * mck2ui +
                    best_win->best_dqsien_dly_ui[dqs_i] + freq_div;
                /*mcSHOW_DBG_MSG(("Total UI for P1: %d, mck2ui %d\n",
                    best_win->best_dqsien_dly_mck_p1[dqs_i], mck2ui));*/
                best_win->best_dqsien_dly_mck_p1[dqs_i] =
                    best_win->best_dqsien_dly_ui_p1[dqs_i] / mck2ui;
                best_win->best_dqsien_dly_ui_p1[dqs_i] =
                    best_win->best_dqsien_dly_ui_p1[dqs_i] % mck2ui;

                /*mcSHOW_DBG_MSG(("best dqsien dly found for B%d: "
                    "(%2d, %2d, %2d)\n", dqs_i,
                    best_win->best_dqsien_dly_mck[dqs_i],
                    best_win->best_dqsien_dly_ui[dqs_i],
                    best_win->best_dqsien_dly_pi[dqs_i]));*/

                passed_bytes |= 1 << dqs_i;

                if ((p->data_width == DATA_WIDTH_16BIT) &&
                    (passed_bytes == 0x3)) {
                    dly_ui = dly_ui_end;
                    break;
                }
            }
        } else {

            rxdqs_trans->dqs_high[dqs_i] = 0;
            rxdqs_trans->dqs_transition[dqs_i] = 0;
            rxdqs_trans->dqs_transitioned[dqs_i] = 0;
        }
    }

    *pass_byte_count = passed_bytes;
    return dly_ui;
}

static DRAM_STATUS_T dramc_rx_dqs_gating_sw_cal(DRAMC_CTX_T *p,
    U8 use_enhance_rdqs)
{
    struct rxdqs_gating_cal rxdqs_cal;
    struct rxdqs_gating_trans rxdqs_trans;
    struct rxdqs_gating_best_win rxdqs_best_win;
    U8 dly_ui, dly_ui_start, dly_ui_end;
    U8 pi_per_ui, ui_per_mck, freq_div;
    U8 pass_byte_count;
    //U32 value;
    //U8 dqs_i;
    U8 u1GatingErrorFlag=0;

    if (p == NULL) {
        mcSHOW_ERR_MSG(("[Error] Context NULL\n"));
        return DRAM_FAIL;
    }

    memset(&rxdqs_cal, 0, sizeof(struct rxdqs_gating_cal));
    memset(&rxdqs_trans, 0, sizeof(struct rxdqs_gating_trans));
    memset(&rxdqs_best_win, 0, sizeof(struct rxdqs_gating_best_win));

    pi_per_ui = DQS_GW_PI_PER_UI;
    ui_per_mck = DQS_GW_UI_PER_MCK;
    if (vGet_Div_Mode(p) == DIV4_MODE)
        freq_div = 2;
    else
        freq_div = 4;

    if (u1IsPhaseMode(p))
        rxdqs_cal.dqsien_pi_adj_step = (0x1 << 4);
    else
        rxdqs_cal.dqsien_pi_adj_step = DQS_GW_FINE_STEP;

#if ENABLE_GATING_AUTOK_WA
    if (__wa__gating_swk_for_autok)
        rxdqs_cal.dqsien_pi_adj_step = pi_per_ui;
#endif
    rxdqs_cal.dqsien_pi_per_ui = pi_per_ui;
    rxdqs_cal.dqsien_ui_per_mck = ui_per_mck;
    rxdqs_cal.dqsien_freq_div = freq_div;

    U32 reg_backup_address[ ] = {
        (DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0)),
        (DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ6)),
        (DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ6)),
        (DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL1)),
        (DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL2)),
    };

    DramcBackupRegisters(p, reg_backup_address,
        sizeof (reg_backup_address) / sizeof (U32));

    if (!rxdqs_gating_bypass(p)) {
        rxdqs_gating_sw_cal_init(p, use_enhance_rdqs);

#if 1
        #if (LP5_DDR4266_RDBI_WORKAROUND)
        if((is_lp5_family(p)) && (p->frequency == 2133))
            dly_ui_start = 15;
        else if((is_lp5_family(p)) && (p->frequency == 2750))
            dly_ui_start = 12;
        else
            dly_ui_start = u1GetGatingStartPos(p, AUTOK_OFF);
        #else
                dly_ui_start = u1GetGatingStartPos(p, AUTOK_OFF);
        #endif

        dly_ui_end = dly_ui_start+ 32;
        pass_byte_count = 0;
#else
        {
             dly_ui_start = 9;
             if(p->freq_sel==LP4_DDR4266)
             {
                dly_ui_start = 16;
             }
             dly_ui_end = dly_ui_start + 32;
             pass_byte_count = 0;
        }
#endif


        for (dly_ui = dly_ui_start; dly_ui < dly_ui_end;
            dly_ui += DQS_GW_COARSE_STEP) {
            rxdqs_gating_set_dqsien_dly(p, dly_ui, &rxdqs_cal);

            for (rxdqs_cal.dqsien_dly_pi = 0; rxdqs_cal.dqsien_dly_pi <
                pi_per_ui; rxdqs_cal.dqsien_dly_pi +=
                rxdqs_cal.dqsien_pi_adj_step) {
                dly_ui = rxdqs_gating_sw_cal(p, &rxdqs_trans, &rxdqs_cal,
                    &pass_byte_count, &rxdqs_best_win, dly_ui, dly_ui_end);

                if (dly_ui == dly_ui_end)
                    break;
            }
        }

        DramcEngine2End(p);


        if (pass_byte_count == 0x3)
        {
            u1GatingErrorFlag=0;
            vSetCalibrationResult(p, DRAM_CALIBRATION_GATING, DRAM_OK);
        }
        else
            {
                u1GatingErrorFlag=1;
            mcSHOW_ERR_MSG(("error, no all pass taps in DQS!,pass_byte_count=%d\n", pass_byte_count));
        }
	(void)u1GatingErrorFlag;


#if (ENABLE_GATING_AUTOK_WA)
        if (!u1GatingErrorFlag && __wa__gating_swk_for_autok) {
            U8 ui[DQS_BYTE_NUMBER], ui_min = 0xff;
            U8 dqs_i;
            for (dqs_i = 0; dqs_i < DQS_BYTE_NUMBER; dqs_i++){
                ui[dqs_i] = rxdqs_best_win.best_dqsien_dly_mck[dqs_i] * ui_per_mck +
                rxdqs_best_win.best_dqsien_dly_ui[dqs_i];

                if (ui[dqs_i] < ui_min)
                    ui_min = ui[dqs_i];
            }
            __wa__gating_autok_init_ui[p->rank] = ui_min;

            DramcRestoreRegisters(p, reg_backup_address,
                sizeof (reg_backup_address) / sizeof (U32));
            return DRAM_OK;
        }
#endif
    }

    rxdqs_gating_fastk_save_restore(p, &rxdqs_best_win, &rxdqs_cal);
    rxdqs_gating_misc_process(p, &rxdqs_best_win);

    mcSHOW_DBG_MSG4(("[Gating] SW calibration Done\n"));


    rxdqs_gating_set_final_result(p, ui_per_mck, &rxdqs_best_win);

    DramcRestoreRegisters(p, reg_backup_address,
        sizeof (reg_backup_address) / sizeof (U32));

    DramPhyReset(p);

    return DRAM_OK;
}


DRAM_STATUS_T dramc_rx_dqs_gating_cal(DRAMC_CTX_T *p,
        u8 autok, U8 use_enhanced_rdqs)
{
    DRAM_STATUS_T ret;

    vPrintCalibrationBasicInfo(p);

    mcSHOW_DBG_MSG(("[DramcGating] \n"));

#if ENABLE_GATING_AUTOK_WA
     if (autok) {
         __wa__gating_swk_for_autok = 1;
         dramc_rx_dqs_gating_sw_cal(p, use_enhanced_rdqs);
         __wa__gating_swk_for_autok = 0;
     }
#endif


    vSetCalibrationResult(p, DRAM_CALIBRATION_GATING, DRAM_FAIL);


#if GATING_AUTO_K_SUPPORT
    if (autok) {
#if ENABLE_GATING_AUTOK_WA
        if (rxdqs_gating_bypass(p))
            return DRAM_OK;
#endif

        ret = dramc_rx_dqs_gating_auto_cal(p);
        if (ret == DRAM_OK) {
            return DRAM_OK;
        }

        mcSHOW_ERR_MSG(("[Error] Gating auto calibration fail!!\n"));
    }
#endif

    mcSHOW_DBG_MSG(("SW mode calibration\n"));

    return dramc_rx_dqs_gating_sw_cal(p, use_enhanced_rdqs);
}


#if GATING_ADJUST_TXDLY_FOR_TRACKING
void DramcRxdqsGatingPostProcess(DRAMC_CTX_T *p)
{
    U8 dqs_i; //u1RankRxDVS = 0
    U8 u1RankIdx, u1RankMax; //u1RankBak
    S8 s1ChangeDQSINCTL;
#if XRTRTR_NEW_CROSS_RK_MODE
    U16 u2PHSINCTL = 0;
    U32 u4Rank_Sel_MCK_P0[2], u4Rank_Sel_MCK_P1[2], u4RANKINCTL_STB;
#endif
#if RDSEL_TRACKING_EN
    //U32 u4PI_value[2] = {0};
#endif
    U32 backup_rank;
    U32 u4ReadDQSINCTL, u4RankINCTL_ROOT, u4XRTR2R, reg_TX_dly_DQSgated_min = 0;
    //U32 u4ReadRODT, u4ReadTXDLY[RANK_MAX][DQS_BYTE_NUMBER], u4ReadTXDLY_P1[RANK_MAX][DQS_BYTE_NUMBER]
    U8 mck2ui_shift;

    backup_rank = u1GetRank(p);

#ifdef XRTR2R_PERFORM_ENHANCE_DQSG_RX_DLY
    if (vGet_Div_Mode(p) == DIV8_MODE)
    {

        if (p->frequency >= 1333)
        {
            reg_TX_dly_DQSgated_min = 2;
        }
        else
        {
            reg_TX_dly_DQSgated_min = 1;
        }
    }
    else
    {
        reg_TX_dly_DQSgated_min = 1;
    }
#else

    if (p->frequency >= 1333)
    {
        reg_TX_dly_DQSgated_min = 3;
    }
    else
    {
        reg_TX_dly_DQSgated_min = 2;
    }
#endif


#if 0
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU_B0_DQ7), u1RankRxDVS, SHU_B0_DQ7_R_DMRANKRXDVS_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU_B1_DQ7), u1RankRxDVS, SHU_B1_DQ7_R_DMRANKRXDVS_B1);
#endif


    s1ChangeDQSINCTL = reg_TX_dly_DQSgated_min - u1TXDLY_Cal_min;

    //mcDUMP_REG_MSG(("\n[dumpRG] RxdqsGatingPostProcess\n"));

    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));
    /*mcDUMP_REG_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 (vGet_Div_Mode(p) == DIV16_MODE)
        mck2ui_shift = 4;
    else if (vGet_Div_Mode(p) == DIV8_MODE)
        mck2ui_shift = 3;
    else
        mck2ui_shift = 2;

    if (s1ChangeDQSINCTL != 0)
    {
        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));
            //mcDUMP_REG_MSG(("Rank: %d\n", u1RankIdx));

            for (dqs_i = 0; dqs_i < DQS_BYTE_NUMBER; dqs_i++)
            {
#if 1
                U8 total_ui, total_ui_P1;
                total_ui = (ucbest_coarse_mck_backup[u1RankIdx][dqs_i] << 4) + ucbest_coarse_ui_backup[u1RankIdx][dqs_i];
                total_ui_P1 = (ucbest_coarse_mck_P1_backup[u1RankIdx][dqs_i] << 4) + ucbest_coarse_ui_P1_backup[u1RankIdx][dqs_i];

                total_ui += (s1ChangeDQSINCTL << mck2ui_shift);
                total_ui_P1 += (s1ChangeDQSINCTL << mck2ui_shift);

                ucbest_coarse_mck_backup[u1RankIdx][dqs_i] = (total_ui >> 4);
                ucbest_coarse_ui_backup[u1RankIdx][dqs_i] = total_ui & 0xf;

                ucbest_coarse_mck_P1_backup[u1RankIdx][dqs_i] = (total_ui_P1 >> 4);
                ucbest_coarse_ui_P1_backup[u1RankIdx][dqs_i] = total_ui_P1 & 0xf;
#else
                if (vGet_Div_Mode(p) == DIV8_MODE)
                {
                    u4ReadTXDLY[u1RankIdx][dqs_i] = ucbest_coarse_mck_backup[u1RankIdx][dqs_i];
                    u4ReadTXDLY_P1[u1RankIdx][dqs_i] = ucbest_coarse_mck_P1_backup[u1RankIdx][dqs_i];

                    u4ReadTXDLY[u1RankIdx][dqs_i] += s1ChangeDQSINCTL;
                    u4ReadTXDLY_P1[u1RankIdx][dqs_i] += s1ChangeDQSINCTL;

                    ucbest_coarse_mck_backup[u1RankIdx][dqs_i] = u4ReadTXDLY[u1RankIdx][dqs_i];
                    ucbest_coarse_mck_P1_backup[u1RankIdx][dqs_i] = u4ReadTXDLY_P1[u1RankIdx][dqs_i];
                }
                else
                {
                    u4ReadTXDLY[u1RankIdx][dqs_i] = ((ucbest_coarse_mck_backup[u1RankIdx][dqs_i] << 1) + ((ucbest_coarse_ui_backup[u1RankIdx][dqs_i] >> 2) & 0x1));
                    u4ReadTXDLY_P1[u1RankIdx][dqs_i] = ((ucbest_coarse_mck_P1_backup[u1RankIdx][dqs_i] << 1) + ((ucbest_coarse_ui_P1_backup[u1RankIdx][dqs_i] >> 2) & 0x1));

                    u4ReadTXDLY[u1RankIdx][dqs_i] += s1ChangeDQSINCTL;
                    u4ReadTXDLY_P1[u1RankIdx][dqs_i] += s1ChangeDQSINCTL;

                    ucbest_coarse_mck_backup[u1RankIdx][dqs_i] = (u4ReadTXDLY[u1RankIdx][dqs_i] >> 1);
                    ucbest_coarse_ui_backup[u1RankIdx][dqs_i] = ((u4ReadTXDLY[u1RankIdx][dqs_i] & 0x1) << 2) + (ucbest_coarse_ui_backup[u1RankIdx][dqs_i] & 0x3);

                    ucbest_coarse_mck_P1_backup[u1RankIdx][dqs_i] = (u4ReadTXDLY_P1[u1RankIdx][dqs_i] >> 1);
                    ucbest_coarse_ui_P1_backup[u1RankIdx][dqs_i] = ((u4ReadTXDLY_P1[u1RankIdx][dqs_i] & 0x1) << 2) + (ucbest_coarse_ui_P1_backup[u1RankIdx][dqs_i] & 0x3);
                }
#endif
                mcSHOW_DBG_MSG(("PostProcess best DQS%d dly(2T, 0.5T) = (%d, %d)\n", dqs_i, ucbest_coarse_mck_backup[u1RankIdx][dqs_i], ucbest_coarse_ui_backup[u1RankIdx][dqs_i]));
                //mcDUMP_REG_MSG(("PostProcess best DQS%d dly(2T, 0.5T) = (%d, %d)\n", dqs_i, ucbest_coarse_mck_backup[u1RankIdx][dqs_i], ucbest_coarse_ui_backup[u1RankIdx][dqs_i]));
#ifdef FOR_HQA_REPORT_USED
                HQA_Log_Message_for_Report(p, p->channel, u1RankIdx, HQA_REPORT_FORMAT0,
                    "Gating_Center_", "2T", dqs_i, ucbest_coarse_mck_backup[u1RankIdx][dqs_i], NULL);
                HQA_Log_Message_for_Report(p, p->channel, u1RankIdx, HQA_REPORT_FORMAT0,
                    "Gating_Center_", "05T", dqs_i, ucbest_coarse_ui_backup[u1RankIdx][dqs_i], NULL);
#endif
            }
            for (dqs_i = 0; dqs_i < DQS_BYTE_NUMBER; dqs_i++)
            {
                mcSHOW_DBG_MSG(("PostProcess best DQS%d P1 dly(2T, 0.5T) = (%d, %d)\n", dqs_i, ucbest_coarse_mck_P1_backup[u1RankIdx][dqs_i], ucbest_coarse_ui_P1_backup[u1RankIdx][dqs_i]));
                //mcDUMP_REG_MSG(("PostProcess best DQS%d P1 dly(2T, 0.5T) = (%d, %d)\n", dqs_i, ucbest_coarse_mck_P1_backup[u1RankIdx][dqs_i], ucbest_coarse_ui_P1_backup[u1RankIdx][dqs_i]));
            }
        }

        for (u1RankIdx = 0; u1RankIdx < u1RankMax; u1RankIdx++)
        {
            vSetRank(p, u1RankIdx);

            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B0_DQSIEN_MCK_UI_DLY),
                P_Fld(ucbest_coarse_mck_backup[u1RankIdx][0],
                SHU_RK_B0_DQSIEN_MCK_UI_DLY_DQSIEN_MCK_P0_B0) |
                P_Fld(ucbest_coarse_ui_backup[u1RankIdx][0],
                SHU_RK_B0_DQSIEN_MCK_UI_DLY_DQSIEN_UI_P0_B0) |
                P_Fld(ucbest_coarse_mck_P1_backup[u1RankIdx][0],
                SHU_RK_B0_DQSIEN_MCK_UI_DLY_DQSIEN_MCK_P1_B0) |
                P_Fld(ucbest_coarse_ui_P1_backup[u1RankIdx][0],
                SHU_RK_B0_DQSIEN_MCK_UI_DLY_DQSIEN_UI_P1_B0));

            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B1_DQSIEN_MCK_UI_DLY),
                P_Fld(ucbest_coarse_mck_backup[u1RankIdx][1],
                SHU_RK_B1_DQSIEN_MCK_UI_DLY_DQSIEN_MCK_P0_B1) |
                P_Fld(ucbest_coarse_ui_backup[u1RankIdx][1],
                SHU_RK_B1_DQSIEN_MCK_UI_DLY_DQSIEN_UI_P0_B1) |
                P_Fld(ucbest_coarse_mck_P1_backup[u1RankIdx][1],
                SHU_RK_B1_DQSIEN_MCK_UI_DLY_DQSIEN_MCK_P1_B1) |
                P_Fld(ucbest_coarse_ui_P1_backup[u1RankIdx][1],
                SHU_RK_B1_DQSIEN_MCK_UI_DLY_DQSIEN_UI_P1_B1));
        #if RDSEL_TRACKING_EN
            if(p->frequency >= RDSEL_TRACKING_TH)
            {

                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_INI_UIPI),
                    (ucbest_coarse_mck_backup[u1RankIdx][0] << 4) | (ucbest_coarse_ui_backup[u1RankIdx][0]),
                    SHU_R0_B0_INI_UIPI_CURR_INI_UI_B0);

                vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_INI_UIPI),
                    (ucbest_coarse_mck_backup[u1RankIdx][1] << 4) | (ucbest_coarse_ui_backup[u1RankIdx][1]),
                    SHU_R0_B1_INI_UIPI_CURR_INI_UI_B1);
            }
        #endif
        }
    }
    vSetRank(p, backup_rank);

    u4ReadDQSINCTL = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_SHU_RK_DQSCTL),
        MISC_SHU_RK_DQSCTL_DQSINCTL);
    //mcDUMP_REG_MSG(("u4ReadDQSINCTL=%d\n", u4ReadDQSINCTL));
    u4ReadDQSINCTL -= s1ChangeDQSINCTL;

    #if ENABLE_READ_DBI
    if (p->DBI_R_onoff[p->dram_fsp])
    {
        u4ReadDQSINCTL++;
        #if 0
        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);
        #endif
    }
    #endif

#if XRTRTR_NEW_CROSS_RK_MODE
        for (dqs_i = 0; dqs_i < DQS_BYTE_NUMBER; dqs_i++)
        {
            if (ucbest_coarse_mck_backup[RANK_0][dqs_i] > ucbest_coarse_mck_backup[RANK_1][dqs_i])
            {
                u4Rank_Sel_MCK_P0[dqs_i] = (ucbest_coarse_mck_backup[RANK_0][dqs_i] > 0)? (ucbest_coarse_mck_backup[RANK_0][dqs_i] - 1): 0;
                u4Rank_Sel_MCK_P1[dqs_i] = (ucbest_coarse_mck_P1_backup[RANK_0][dqs_i] > 0)? (ucbest_coarse_mck_P1_backup[RANK_0][dqs_i] - 1): 0;
            }
            else
            {
                u4Rank_Sel_MCK_P0[dqs_i] = (ucbest_coarse_mck_backup[RANK_1][dqs_i] > 0)? (ucbest_coarse_mck_backup[RANK_1][dqs_i] - 1): 0;
                u4Rank_Sel_MCK_P1[dqs_i] = (ucbest_coarse_mck_P1_backup[RANK_1][dqs_i] > 0)? (ucbest_coarse_mck_P1_backup[RANK_1][dqs_i] - 1): 0;
            }
        }
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_RANK_SELPH_UI_DLY),
            P_Fld(u4Rank_Sel_MCK_P0[0], SHU_B0_RANK_SELPH_UI_DLY_RANKSEL_MCK_DLY_P0_B0) |
            P_Fld(u4Rank_Sel_MCK_P1[0], SHU_B0_RANK_SELPH_UI_DLY_RANKSEL_MCK_DLY_P1_B0));
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_RANK_SELPH_UI_DLY),
            P_Fld(u4Rank_Sel_MCK_P0[1], SHU_B1_RANK_SELPH_UI_DLY_RANKSEL_MCK_DLY_P0_B1) |
            P_Fld(u4Rank_Sel_MCK_P1[1], SHU_B1_RANK_SELPH_UI_DLY_RANKSEL_MCK_DLY_P1_B1));

        u4RANKINCTL_STB = (u4ReadDQSINCTL > 2)? (u4ReadDQSINCTL - 2): 0;
        u2PHSINCTL = (u4ReadDQSINCTL == 0)? 0: (u4ReadDQSINCTL - 1);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_SHU_RANKCTL), u4RANKINCTL_STB, MISC_SHU_RANKCTL_RANKINCTL_STB);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_MISC_RANK_SEL_STB), u2PHSINCTL, SHU_MISC_RANK_SEL_STB_RANK_SEL_PHSINCTL);
#endif

#ifdef XRTR2R_PERFORM_ENHANCE_DQSG_RX_DLY

    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

    if (u4ReadDQSINCTL >= 3)
    {
        u4RankINCTL_ROOT = u4ReadDQSINCTL - 3;
    }
    else
    {
        u4RankINCTL_ROOT = 0;
        mcSHOW_ERR_MSG(("u4RankINCTL_ROOT <3, Risk for supporting 1066/RL8\n"));
    }
#endif


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_SHU_RK_DQSCTL),
        u4ReadDQSINCTL, MISC_SHU_RK_DQSCTL_DQSINCTL);
    vSetRank(p, RANK_1);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_SHU_RK_DQSCTL),
        u4ReadDQSINCTL, MISC_SHU_RK_DQSCTL_DQSINCTL);
    vSetRank(p, backup_rank);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_SHU_RANKCTL),
        u4ReadDQSINCTL, MISC_SHU_RANKCTL_RANKINCTL_PHY);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_SHU_RANKCTL),
        u4RankINCTL_ROOT, MISC_SHU_RANKCTL_RANKINCTL);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_SHU_RANKCTL),
        u4RankINCTL_ROOT, MISC_SHU_RANKCTL_RANKINCTL_ROOT1);

#ifdef XRTR2R_PERFORM_ENHANCE_DQSG_RX_DLY
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_SHU_RANKCTL),
        u4RankINCTL_ROOT, MISC_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));
    //mcDUMP_REG_MSG(("TX_dly_DQSgated check: min %d  max %d, ChangeDQSINCTL=%d\n", u1TXDLY_Cal_min, u1TXDLY_Cal_max, s1ChangeDQSINCTL));
    //mcDUMP_REG_MSG(("DQSINCTL=%d, RANKINCTL=%d, u4XRTR2R=%d\n", u4ReadDQSINCTL, u4RankINCTL_ROOT, u4XRTR2R));
#else


    u4XRTR2R = 8 + u1TXDLY_Cal_max + 1;
    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));
    //mcDUMP_REG_MSG(("TX_dly_DQSgated check: min %d  max %d, ChangeDQSINCTL=%d\n", u1TXDLY_Cal_min, u1TXDLY_Cal_max, s1ChangeDQSINCTL));
    //mcDUMP_REG_MSG(("DQSINCTL=%d, RANKINCTL=%d, u4XRTR2R=%d\n", u4ReadDQSINCTL, u4RankINCTL_ROOT, u4XRTR2R));
#endif

#if 0

    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(u1ReadROEN, SHU_RODTENSTB_RODTENSTB_TRACK_EN));
#endif

#ifdef XRTR2W_PERFORM_ENHANCE_RODTEN

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_MISC_SHU_RODTENSTB),
        P_Fld(0x0fff, MISC_SHU_RODTENSTB_RODTENSTB_EXT) |
        P_Fld(1, MISC_SHU_RODTENSTB_RODTEN_P1_ENABLE) |
        P_Fld(1, MISC_SHU_RODTENSTB_RODTENSTB_TRACK_EN));
#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

#if RDSEL_TRACKING_EN
void RDSELRunTimeTracking_preset(DRAMC_CTX_T *p)
{
    S32 s4PosVH, s4NegVH;

    s4PosVH = divRoundClosest(400, ((1000000 / p->frequency) / 64));
    s4NegVH = 1;

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_MISC_RDSEL_TRACK), P_Fld(s4PosVH, SHU_MISC_RDSEL_TRACK_SHU_GW_THRD_POS)
                                                    | P_Fld(s4NegVH, SHU_MISC_RDSEL_TRACK_SHU_GW_THRD_NEG));
}
#endif

#if RDDQC_PINMUX_WORKAROUND
static void RDDQCPinmuxWorkaround(DRAMC_CTX_T *p)
{
    U8 *uiLPDDR_RDDQC_Mapping;
    const U8 uiLPDDR4_RDDQC_Mapping_POP[PINMUX_MAX][CHANNEL_NUM][16] =
    {
        {

            {
		0, 1, 2, 3, 7, 4, 6, 5,
		9, 8, 12, 14, 15, 10, 13, 11
            },
#if (CHANNEL_NUM>1)

            {
		0, 1, 7, 4, 3, 2, 6, 5,
		9, 8, 12, 14, 15, 10, 11, 13
            },
#endif
#if (CHANNEL_NUM>2)

            {
		0, 1, 2, 3, 7, 4, 6, 5,
		9, 8, 12, 14, 15, 10, 13, 11
            },

            {
		0, 1, 7, 4, 3, 2, 6, 5,
		9, 8, 12, 14, 15, 10, 11, 13
            },
#endif
        },
        {

            {
		0, 1, 4, 3, 2, 5, 7, 6,
		9, 8, 10, 11, 15, 13, 12, 14
            },
#if (CHANNEL_NUM>1)

            {
		0, 1, 2, 5, 3, 4, 7, 6,
		8, 9, 10, 11, 15, 14, 13, 12
            },
            #endif
            #if (CHANNEL_NUM>2)

            {
		0, 1, 2, 3, 4, 5, 6, 7,
		8, 9, 10, 11, 12, 13, 14, 15
            },

            {
		0, 1, 2, 3, 4, 5, 6, 7,
		8, 9, 10, 11, 12, 13, 14, 15
            },
#endif
        },
        {

            {
                0, 1, 6, 2, 4, 7, 3, 5,
                8, 9, 10, 12, 13, 11, 15, 14
            },
            #if (CHANNEL_NUM>1)

            {
                0, 1, 7, 4, 2, 5, 6, 3,
                9, 8, 10, 12, 11, 14, 13, 15
            },
            #endif
            #if (CHANNEL_NUM>2)

            {
                1, 0, 3, 2, 4, 7, 6, 5,
                8, 9, 10, 12, 15, 14, 11, 13
            },

            {
                0, 1, 7, 4, 2, 5, 6, 3,
                9, 8, 10, 12, 11, 14, 13, 15
            },
            #endif
        },
        {

            {
                8, 9, 14, 15, 12, 13, 11, 10,
                1, 0, 3, 2, 7, 6, 4, 5
            },
            #if (CHANNEL_NUM>1)

            {
                9, 8, 13, 12, 15, 10, 11, 14,
                0, 1, 3, 2, 4, 6, 5, 7
            },
            #endif
            #if (CHANNEL_NUM>2)

            {
                0, 1, 6, 7, 4, 5, 3, 2,
                9, 8, 11, 10, 15, 14, 12, 13
            },

            {
                1, 0, 5, 4, 7, 2, 3, 6,
                8, 9, 11, 10, 12, 14, 13, 15
            },
            #endif
        }
    };

    {
        uiLPDDR_RDDQC_Mapping = (U8 *)uiLPDDR4_RDDQC_Mapping_POP[p->DRAMPinmux][p->channel];
    }



    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_MRR_BIT_MUX1), P_Fld(uiLPDDR_RDDQC_Mapping[0], MRR_BIT_MUX1_MRR_BIT0_SEL) | P_Fld(uiLPDDR_RDDQC_Mapping[1], MRR_BIT_MUX1_MRR_BIT1_SEL) |
                                                               P_Fld(uiLPDDR_RDDQC_Mapping[2], MRR_BIT_MUX1_MRR_BIT2_SEL) | P_Fld(uiLPDDR_RDDQC_Mapping[3], MRR_BIT_MUX1_MRR_BIT3_SEL));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_MRR_BIT_MUX2), P_Fld(uiLPDDR_RDDQC_Mapping[4], MRR_BIT_MUX2_MRR_BIT4_SEL) | P_Fld(uiLPDDR_RDDQC_Mapping[5], MRR_BIT_MUX2_MRR_BIT5_SEL) |
                                                               P_Fld(uiLPDDR_RDDQC_Mapping[6], MRR_BIT_MUX2_MRR_BIT6_SEL) | P_Fld(uiLPDDR_RDDQC_Mapping[7], MRR_BIT_MUX2_MRR_BIT7_SEL));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_MRR_BIT_MUX3), P_Fld(uiLPDDR_RDDQC_Mapping[8], MRR_BIT_MUX3_MRR_BIT8_SEL) | P_Fld(uiLPDDR_RDDQC_Mapping[9], MRR_BIT_MUX3_MRR_BIT9_SEL) |
                                                               P_Fld(uiLPDDR_RDDQC_Mapping[10], MRR_BIT_MUX3_MRR_BIT10_SEL) | P_Fld(uiLPDDR_RDDQC_Mapping[11], MRR_BIT_MUX3_MRR_BIT11_SEL));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_MRR_BIT_MUX4), P_Fld(uiLPDDR_RDDQC_Mapping[12], MRR_BIT_MUX4_MRR_BIT12_SEL) | P_Fld(uiLPDDR_RDDQC_Mapping[13], MRR_BIT_MUX4_MRR_BIT13_SEL) |
                                                               P_Fld(uiLPDDR_RDDQC_Mapping[14], MRR_BIT_MUX4_MRR_BIT14_SEL) | P_Fld(uiLPDDR_RDDQC_Mapping[15], MRR_BIT_MUX4_MRR_BIT15_SEL));

}
#endif

#define RDDQCGOLDEN_LP5_MR30_BIT_CTRL_LOWER   RDDQCGOLDEN_MR15_GOLDEN
#define RDDQCGOLDEN_LP5_MR31_BIT_CTRL_UPPER   RDDQCGOLDEN_MR20_GOLDEN
#define RDDQCGOLDEN_LP5_MR32_PATTERN_A        RDDQCGOLDEN_MR32_GOLDEN
#define RDDQCGOLDEN_LP5_MR33_PATTERN_B        RDDQCGOLDEN_MR40_GOLDEN
static U32 DramcRxWinRDDQCInit(DRAMC_CTX_T *p)
{
    //int i;
    //U8 *uiLPDDR_O1_Mapping;
    //U16 temp_value = 0;
    U8 RDDQC_Bit_Ctrl_Lower = 0x55;
    U8 RDDQC_Bit_Ctrl_Upper = 0x55;
    U8 RDDQC_Pattern_A = 0x5A;
    U8 RDDQC_Pattern_B = 0x3C;

#if FOR_DV_SIMULATION_USED == 1
    cal_sv_rand_args_t *psra = get_psra();

    if (psra) {
        RDDQC_Bit_Ctrl_Lower = psra->low_byte_invert_golden & 0xFF;
        RDDQC_Bit_Ctrl_Upper = psra->upper_byte_invert_golden & 0xFF;
        RDDQC_Pattern_A = psra->mr_dq_a_golden;
        RDDQC_Pattern_B = psra->mr_dq_b_golden;


    }
#endif


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ7), 0, SHU_B0_DQ7_R_DMDQMDBI_SHU_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ7), 0, SHU_B1_DQ7_R_DMDQMDBI_SHU_B1);

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0), u1GetRank(p), SWCMD_CTRL0_MRSRK);

#if RDDQC_PINMUX_WORKAROUND

    RDDQCPinmuxWorkaround(p);
#endif


    {
        DramcModeRegWriteByRank(p, p->rank, 15, RDDQC_Bit_Ctrl_Lower);
        DramcModeRegWriteByRank(p, p->rank, 20, RDDQC_Bit_Ctrl_Upper);
        DramcModeRegWriteByRank(p, p->rank, 32, RDDQC_Pattern_A);
        DramcModeRegWriteByRank(p, p->rank, 40, RDDQC_Pattern_B);
    }


    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_RDDQCGOLDEN),
            P_Fld(RDDQC_Bit_Ctrl_Lower, RDDQCGOLDEN_LP5_MR30_BIT_CTRL_LOWER) |
            P_Fld(RDDQC_Bit_Ctrl_Upper, RDDQCGOLDEN_LP5_MR31_BIT_CTRL_UPPER) |
            P_Fld(RDDQC_Pattern_A, RDDQCGOLDEN_LP5_MR32_PATTERN_A) |
            P_Fld(RDDQC_Pattern_B, RDDQCGOLDEN_LP5_MR33_PATTERN_B));


    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ8),
            P_Fld(1, SHU_B0_DQ8_R_DMRXDLY_CG_IG_B0));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ8),
            P_Fld(1, SHU_B1_DQ8_R_DMRXDLY_CG_IG_B1));

    return 0;
}
#if PRINT_CALIBRATION_SUMMARY_FASTK_CHECK
static U32 DramcRxWinRDDQCEnd(DRAMC_CTX_T *p)
{

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0), 0, SWCMD_CTRL0_MRSRK);

    return 0;
}
#endif
static void SetRxVref(DRAMC_CTX_T *p, U8 u1Vref_B0, U8 u1Vref_B1)
{
    BOOL isLP4_DSC = (p->DRAMPinmux == PINMUX_DSC)?1:0;

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_PHY_VREF_SEL),
                            P_Fld(u1Vref_B0, SHU_B0_PHY_VREF_SEL_RG_RX_ARDQ_VREF_SEL_LB_B0) |
                            P_Fld(u1Vref_B0, SHU_B0_PHY_VREF_SEL_RG_RX_ARDQ_VREF_SEL_UB_B0));
    if (!isLP4_DSC)
    {
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_PHY_VREF_SEL),
                                P_Fld(u1Vref_B1, SHU_B1_PHY_VREF_SEL_RG_RX_ARDQ_VREF_SEL_LB_B1) |
                                P_Fld(u1Vref_B1, SHU_B1_PHY_VREF_SEL_RG_RX_ARDQ_VREF_SEL_UB_B1));
    }
    else
    {
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_PHY_VREF_SEL),
                                P_Fld(u1Vref_B1, SHU_CA_PHY_VREF_SEL_RG_RX_ARCA_VREF_SEL_LB) |
                                P_Fld(u1Vref_B1, SHU_CA_PHY_VREF_SEL_RG_RX_ARCA_VREF_SEL_UB));
    }
}
#if 0
static void SetRxDqDelay(DRAMC_CTX_T *p, U8 ii, S16 iDelay)
{
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_RXDLY0 + (ii * 4)),
            P_Fld(iDelay, SHU_R0_B0_RXDLY0_RX_ARDQ0_R_DLY_B0) |
            P_Fld(iDelay, SHU_R0_B0_RXDLY0_RX_ARDQ1_R_DLY_B0));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_RXDLY0 + (ii * 4)),
            P_Fld(iDelay, SHU_R0_B1_RXDLY0_RX_ARDQ0_R_DLY_B1) |
            P_Fld(iDelay, SHU_R0_B1_RXDLY0_RX_ARDQ1_R_DLY_B1));
}

static void SetRxDqDqsDelay(DRAMC_CTX_T *p, S16 iDelay)
{
    U8 ii; //u1ByteIdx
    //U32 u4value;

    if (iDelay <= 0)
    {
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_RXDLY5), (-iDelay), SHU_R0_B0_RXDLY5_RX_ARDQS0_R_DLY_B0);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_RXDLY5), (-iDelay), SHU_R0_B1_RXDLY5_RX_ARDQS0_R_DLY_B1);
        //DramPhyReset(p);
    }
    else
    {

        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_RXDLY4), iDelay, SHU_R0_B0_RXDLY4_RX_ARDQM0_R_DLY_B0);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_RXDLY4), iDelay, SHU_R0_B1_RXDLY4_RX_ARDQM0_R_DLY_B1);
        //DramPhyReset(p);


        for (ii = 0; ii < 4; ii++)
            SetRxDqDelay(p, ii, iDelay);

    }
}


 static U32 DramcRxWinRDDQCRun(DRAMC_CTX_T *p)
{
    U32 u4Result = 0, u4TmpResult;
    DRAM_STATUS_T u4Response = DRAM_FAIL;


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL1), 1, SWCMD_CTRL1_RDDQC_LP_ENB);


    REG_TRANSFER_T TriggerReg = {DRAMC_REG_SWCMD_EN, SWCMD_EN_RDDQCEN};
    REG_TRANSFER_T RepondsReg = {DRAMC_REG_SPCMDRESP, SPCMDRESP_RDDQC_RESPONSE};
    u4Response = DramcTriggerAndWait(p, TriggerReg, RepondsReg);


    u4TmpResult = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_RDQC_CMP));
    u4Result = (0xFFFF) & ((u4TmpResult) | (u4TmpResult >> 16));

#if (FEATURE_RDDQC_K_DMI == TRUE)

    u4TmpResult = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RDQC_DQM_CMP), RDQC_DQM_CMP_RDDQC_DQM_CMP0_ERR);
    u4TmpResult |= u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RDQC_DQM_CMP), RDQC_DQM_CMP_RDDQC_DQM_CMP1_ERR);
    u4Result |= (u4TmpResult << 16);
#endif


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 0, SWCMD_EN_RDDQCEN);

    return u4Result;
}
#endif
DRAM_STATUS_T DramcRxWindowPerbitCal(DRAMC_CTX_T *p,
                                              RX_PATTERN_OPTION_T u1UseTestEngine,
                                              U8 *u1AssignedVref,
                                              U8 isAutoK,
                                              U8 K_Type)
{
    U8 u1BitIdx, u1ByteIdx; //ii
    //U32 u1vrefidx;
    //U8 ucbit_first, ucbit_last;
    //S16 iDelay = 0, S16DelayBegin = 0, u4DelayStep=1;
    //u16DelayEnd = 0
    //U32 uiFinishCount;
    //U32 u4err_value, u4fail_bit, u4value;
    PASS_WIN_DATA_T FinalWinPerBit[DQ_DATA_WIDTH + RDDQC_ADD_DMI_NUM]; //WinPerBit[DQ_DATA_WIDTH + RDDQC_ADD_DMI_NUM]
    S32 iDQSDlyPerbyte[DQS_BYTE_NUMBER], iDQMDlyPerbyte[DQS_BYTE_NUMBER];//, iFinalDQSDly[DQS_NUMBER];
    U8 u1VrefScanEnable = FALSE;
    //U16 u2TempWinSum[DQS_BYTE_NUMBER]={0}, u2rx_window_sum[DQS_BYTE_NUMBER]={0}, u2TmpDQMSum=0;
    U16 u2FinalVref [DQS_BYTE_NUMBER]= {0xe, 0xe}; //u2VrefLevel
    U16 u2VrefBegin, u2VrefEnd, u2VrefStep;
    //U32 u4fail_bit_R, u4fail_bit_F;
    U8  u1RXEyeScanEnable=(K_Type==NORMAL_K ? DISABLE : ENABLE);
    //U16 u1min_bit_by_vref[DQS_BYTE_NUMBER], u1min_winsize_by_vref[DQS_BYTE_NUMBER];
    //U16 u1min_bit[DQS_BYTE_NUMBER], u1min_winsize[DQS_BYTE_NUMBER]={0};
    //U32 u4PassFlags = 0xFFFF;

    U16 backup_RX_FinalVref_Value[DQS_BYTE_NUMBER]={0};
    U32 backup_DQS_Dly_Value[DQS_BYTE_NUMBER]={0};
    U32 backup_DQM_Dly_Value[DQS_BYTE_NUMBER]={0};
    U32 backup_DQ_Dly_Value[DQ_DATA_WIDTH]={0};
#if ENABLE_EYESCAN_GRAPH
    U8 EyeScan_index[DQ_DATA_WIDTH + RDDQC_ADD_DMI_NUM] = {0};
    U8 u1pass_in_this_vref_flag[DQ_DATA_WIDTH + RDDQC_ADD_DMI_NUM];
#endif

    U8 backup_rank, rank_i, u1KnownVref[2]={0xff, 0xff};
    BOOL isLP4_DSC = (p->DRAMPinmux == PINMUX_DSC)?1:0;


    if (!p)
    {
        mcSHOW_ERR_MSG(("context NULL\n"));
        return DRAM_FAIL;
    }


    U32 u4RegBackupAddress[] =
    {
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ10)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ10)),
        (DRAMC_REG_ADDR(DDRPHY_REG_MISC_RX_AUTOK_CFG0)),
        (DRAMC_REG_ADDR(DDRPHY_REG_MISC_RX_AUTOK_CFG1)),
    #if RDDQC_PINMUX_WORKAROUND
        (DRAMC_REG_ADDR(DRAMC_REG_MRR_BIT_MUX1)),
        (DRAMC_REG_ADDR(DRAMC_REG_MRR_BIT_MUX2)),
        (DRAMC_REG_ADDR(DRAMC_REG_MRR_BIT_MUX3)),
        (DRAMC_REG_ADDR(DRAMC_REG_MRR_BIT_MUX4)),
    #endif
    };


    DramcBackupRegisters(p, u4RegBackupAddress, ARRAY_SIZE(u4RegBackupAddress));

#if (FEATURE_RDDQC_K_DMI == TRUE)
    if (u1UseTestEngine == PATTERN_RDDQC)
    {
        iDQMDlyPerbyte[0] = -0xFFFFFF;
        iDQMDlyPerbyte[1] = -0xFFFFFF;
    }
    else
#endif
    {
        iDQMDlyPerbyte[0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_RXDLY4), SHU_R0_B0_RXDLY4_RX_ARDQM0_R_DLY_B0);
        iDQMDlyPerbyte[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_RXDLY4), SHU_R0_B1_RXDLY4_RX_ARDQM0_R_DLY_B1);

    }


    if (u1RXEyeScanEnable)
    {
        backup_RX_FinalVref_Value[0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_PHY_VREF_SEL), SHU_B0_PHY_VREF_SEL_RG_RX_ARDQ_VREF_SEL_LB_B0);
        if (!isLP4_DSC)
            backup_RX_FinalVref_Value[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_PHY_VREF_SEL), SHU_B1_PHY_VREF_SEL_RG_RX_ARDQ_VREF_SEL_LB_B1);
        else
            backup_RX_FinalVref_Value[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_PHY_VREF_SEL), SHU_CA_PHY_VREF_SEL_RG_RX_ARCA_VREF_SEL_LB);

        backup_DQS_Dly_Value[0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_RXDLY5), SHU_R0_B0_RXDLY5_RX_ARDQS0_R_DLY_B0);
        backup_DQS_Dly_Value[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_RXDLY5), SHU_R0_B1_RXDLY5_RX_ARDQS0_R_DLY_B1);

        backup_DQM_Dly_Value[0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_RXDLY4), SHU_R0_B0_RXDLY4_RX_ARDQM0_R_DLY_B0);
        backup_DQM_Dly_Value[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_RXDLY4), SHU_R0_B1_RXDLY4_RX_ARDQM0_R_DLY_B1);

        for (u1BitIdx = 0; u1BitIdx < DQS_BIT_NUMBER; u1BitIdx += 2)
        {
            backup_DQ_Dly_Value[u1BitIdx  ] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_RXDLY0 + u1BitIdx * 2), SHU_R0_B0_RXDLY0_RX_ARDQ0_R_DLY_B0);
            backup_DQ_Dly_Value[u1BitIdx+1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_RXDLY0 + u1BitIdx * 2), SHU_R0_B0_RXDLY0_RX_ARDQ1_R_DLY_B0);
            backup_DQ_Dly_Value[u1BitIdx+8] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_RXDLY0 + u1BitIdx * 2), SHU_R0_B1_RXDLY0_RX_ARDQ0_R_DLY_B1);
            backup_DQ_Dly_Value[u1BitIdx+9] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_RXDLY0 + u1BitIdx * 2), SHU_R0_B1_RXDLY0_RX_ARDQ1_R_DLY_B1);
        }

#if ENABLE_EYESCAN_GRAPH
        if (u1UseTestEngine == PATTERN_TEST_ENGINE)
        {
            for(u1vrefidx=0; u1vrefidx<EYESCAN_RX_VREF_RANGE_END;u1vrefidx++)
            {
                for (u1BitIdx = 0; u1BitIdx < DQ_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;
                    }
                }
            }
        }
#endif
    }


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ10), 1, SHU_B0_DQ10_RG_RX_ARDQS_DLY_LAT_EN_B0);
    if (!isLP4_DSC)
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ10), 1, SHU_B1_DQ10_RG_RX_ARDQS_DLY_LAT_EN_B1);
    else
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD10), 1, SHU_CA_CMD10_RG_RX_ARCLK_DLY_LAT_EN_CA);



    vAutoRefreshSwitch(p, DISABLE);
    //CKEFixOnOff(p, p->rank, CKE_FIXON, TO_ONE_CHANNEL);

    backup_rank = u1GetRank(p);


    if (u1UseTestEngine == PATTERN_TEST_ENGINE)
    {
        if (u1RXEyeScanEnable == DISABLE)
        {
            vSetCalibrationResult(p, DRAM_CALIBRATION_RX_PERBIT, DRAM_FAIL);
        }


        if (isAutoK == TRUE)
        {
            DramcEngine2Init(p, p->test2_1, p->test2_2, TEST_XTALK_PATTERN, 0, TE_NO_UI_SHIFT);
        }
        else
        {
#if ENABLE_K_WITH_WORST_SI_UI_SHIFT
            DramcEngine2Init(p, p->test2_1, p->test2_2, p->test_pattern | 0x80, 0, TE_UI_SHIFT);
#else
            DramcEngine2Init(p, p->test2_1, p->test2_2, p->test_pattern, 0, TE_NO_UI_SHIFT);
#endif
        }
    }
    else
    {
        if (u1RXEyeScanEnable == DISABLE)
        {
            vSetCalibrationResult(p, DRAM_CALIBRATION_RX_RDDQC, DRAM_FAIL);
        }
        DramcRxWinRDDQCInit(p);
    }


    u2VrefBegin = 0;
    u2VrefEnd = 0;
    u2VrefStep = 1;

    if (u1UseTestEngine == PATTERN_TEST_ENGINE)
    {
    #if (FOR_DV_SIMULATION_USED==0 && SW_CHANGE_FOR_SIMULATION==0)
        if ((p->rank==RANK_0) || (p->frequency >= RX_VREF_DUAL_RANK_K_FREQ) || (u1RXEyeScanEnable==1))
            u1VrefScanEnable =1;
    #else
            u1VrefScanEnable =0;
    #endif
    }

#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
    if (p->femmc_Ready == 1 && ((p->Bypass_RDDQC && u1UseTestEngine == PATTERN_RDDQC) || (p->Bypass_RXWINDOW && u1UseTestEngine == PATTERN_TEST_ENGINE)))
    {
        mcSHOW_DBG_MSG(("[FAST_K] Bypass RX Calibration\n"));
    }
    else
#endif
    {

        //mcDUMP_REG_MSG(("\n[dumpRG] %s\n",u1UseTestEngine==PATTERN_RDDQC?"RDDQC":"DramcRxWindowPerbitCal"));
#if VENDER_JV_LOG
#if 0
        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_MSG(("[RxWindowPerbitCal] UseTestEngine: %s, RX Vref Scan: %d, Autok:%d\n", u1UseTestEngine==PATTERN_RDDQC?"RDDQC":"DramcRxWindowPerbitCal", u1VrefScanEnable, isAutoK));

    if (u1VrefScanEnable)
    {
        if ((Get_Vref_Calibration_OnOff(p) == VREF_CALI_OFF) && (u1RXEyeScanEnable == 0))
        {
            u2VrefBegin = 0;
            u2VrefEnd = 0;
            u1KnownVref[0] = gFinalRXVrefDQForSpeedUp[p->channel][p->rank][p->odt_onoff][0];
            u1KnownVref[1] = gFinalRXVrefDQForSpeedUp[p->channel][p->rank][p->odt_onoff][1];

            if (u1UseTestEngine == PATTERN_TEST_ENGINE && ((u1KnownVref[0] == 0) || (u1KnownVref[1] == 0)))
            {
//                mcSHOW_ERR_MSG(("\nWrong frequency K order= %d\n"));
                #if __ETT__
                while (1);
                #endif
            }
        }
        else if (u1AssignedVref != NULL)
        {
            u2VrefBegin = 0;
            u2VrefEnd = 0;
            u1KnownVref[0] = u1AssignedVref[0];
            u1KnownVref[1] = u1AssignedVref[1];
        }
        else
        {
            #if (SW_CHANGE_FOR_SIMULATION || FOR_DV_SIMULATION_USED)
            u2VrefBegin = RX_VREF_RANGE_BEGIN;
            #else
            if (u1RXEyeScanEnable == 0)
            {
                if (p->odt_onoff)
                {
                    u2VrefBegin = RX_VREF_RANGE_BEGIN_ODT_ON;
                }
                else
                {
                    u2VrefBegin = RX_VREF_RANGE_BEGIN_ODT_OFF;
                }
                u2VrefEnd = RX_VREF_RANGE_END-1;

                //mcSHOW_DBG_MSG(("\nSet Vref Range= %d -> %d\n",u2VrefBegin,u2VrefEnd));
            }
            else
            {
                u2VrefBegin = 0;
		(void)u2VrefBegin;
                u2VrefEnd = EYESCAN_RX_VREF_RANGE_END-1;
		(void)u2VrefEnd;
                //mcSHOW_DBG_MSG(("\nSet Eyescan Vref Range= %d -> %d\n",u2VrefBegin,u2VrefEnd));
            }
        #endif
        }

        if (u1RXEyeScanEnable == 0)
        {
            u2VrefStep = RX_VREF_RANGE_STEP;
        }
        else
        {
            u2VrefStep = EYESCAN_GRAPH_RX_VREF_STEP;
        }

        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_VREF_EN_B0);
        if (!isLP4_DSC)
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_VREF_EN_B1);
        else
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD5), 1, CA_CMD5_RG_RX_ARCMD_VREF_EN);
    }
    else
    {
        u2VrefBegin = 0;
        u2VrefEnd = 0;
        u2VrefStep = 1;
    }
    (void)u2VrefStep;


#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
    if (p->femmc_Ready == 1 && ((p->Bypass_RDDQC && u1UseTestEngine == PATTERN_RDDQC) || (p->Bypass_RXWINDOW && u1UseTestEngine == PATTERN_TEST_ENGINE)))
    {

        for (u1ByteIdx = 0; u1ByteIdx < DQS_BYTE_NUMBER; u1ByteIdx++)
        {
            if (u1VrefScanEnable)
            {

            #if ( SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_VREF_CAL)
                u2FinalVref[u1ByteIdx] = p->pSavetimeData->u1RxWinPerbitVref_Save[p->channel][p->rank][u1ByteIdx];
            #endif
            }

            iDQSDlyPerbyte[u1ByteIdx] = p->pSavetimeData->u1RxWinPerbit_DQS[p->channel][p->rank][u1ByteIdx];
            iDQMDlyPerbyte[u1ByteIdx] = p->pSavetimeData->u1RxWinPerbit_DQM[p->channel][p->rank][u1ByteIdx];
        }


        for (u1BitIdx = 0; u1BitIdx < 16; u1BitIdx++)
        {
            FinalWinPerBit[u1BitIdx].best_dqdly = p->pSavetimeData->u1RxWinPerbit_DQ[p->channel][p->rank][u1BitIdx];
        }

        if (u1RXEyeScanEnable == DISABLE)
        {
            if (u1UseTestEngine == PATTERN_TEST_ENGINE)
                vSetCalibrationResult(p, DRAM_CALIBRATION_RX_PERBIT, DRAM_FAST_K);
            else
                vSetCalibrationResult(p, DRAM_CALIBRATION_RX_RDDQC, DRAM_FAST_K);
        }
    }
#endif
    if (u1RXEyeScanEnable)
    {
        u2FinalVref[0] = backup_RX_FinalVref_Value[0];
        u2FinalVref[1] = backup_RX_FinalVref_Value[1];

        iDQSDlyPerbyte[0] = backup_DQS_Dly_Value[0];
        iDQSDlyPerbyte[1] = backup_DQS_Dly_Value[1];

        iDQMDlyPerbyte[0] = backup_DQM_Dly_Value[0];
        iDQMDlyPerbyte[1] = backup_DQM_Dly_Value[1];

        for (u1BitIdx = 0; u1BitIdx < DQS_BIT_NUMBER; u1BitIdx += 2)
        {
            FinalWinPerBit[u1BitIdx    ].best_dqdly = backup_DQ_Dly_Value[u1BitIdx  ];
            FinalWinPerBit[u1BitIdx + 1].best_dqdly = backup_DQ_Dly_Value[u1BitIdx+1];
            FinalWinPerBit[u1BitIdx + 8].best_dqdly = backup_DQ_Dly_Value[u1BitIdx+8];
            FinalWinPerBit[u1BitIdx + 9].best_dqdly = backup_DQ_Dly_Value[u1BitIdx+9];
        }
    }

    if (u1VrefScanEnable == TRUE)
    {

        for (rank_i = p->rank; rank_i < p->support_rank_num; rank_i++)
        {
            vSetRank(p, rank_i);

            SetRxVref(p, u2FinalVref[0], u2FinalVref[1]);

            for (u1ByteIdx = 0; u1ByteIdx < DQS_BYTE_NUMBER; u1ByteIdx++)
            {
                mcSHOW_DBG_MSG(("\nFinal RX Vref Byte %d = %d to rank%d", u1ByteIdx, u2FinalVref[u1ByteIdx], rank_i));
                //mcDUMP_REG_MSG(("\nFinal RX Vref Byte %d = %d to rank%d", u1ByteIdx, u2FinalVref[u1ByteIdx], rank_i));

                gFinalRXVrefDQ[p->channel][rank_i][u1ByteIdx] = (U8) u2FinalVref[u1ByteIdx];
                gFinalRXVrefDQForSpeedUp[p->channel][rank_i][p->odt_onoff][u1ByteIdx] = (U8) u2FinalVref[u1ByteIdx];
            }
        }
        vSetRank(p, backup_rank);
    }
    mcSHOW_DBG_MSG(("\n"));

#if DUMP_TA2_WINDOW_SIZE_RX_TX

    if (u1UseTestEngine == PATTERN_TEST_ENGINE)
    {
        U32 u4B0Tatal =0;
        U32 u4B1Tatal =0;
        mcSHOW_DBG_MSG(("RX window per bit CH[%d] Rank[%d] window size\n", p->channel, p->rank));
        for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
        {
            mcSHOW_DBG_MSG(("DQ[%d] size = %d\n", u1BitIdx, gFinalRXPerbitWin[p->channel][p->rank][u1BitIdx]));
            if(u1BitIdx < 8)
            {
                u4B0Tatal += gFinalRXPerbitWin[p->channel][p->rank][u1BitIdx];
            }
            else
            {
                u4B1Tatal += gFinalRXPerbitWin[p->channel][p->rank][u1BitIdx];
            }
        }
        mcSHOW_DBG_MSG(("total rx window size B0: %d B1: %d\n", u4B0Tatal, u4B1Tatal));
    }
#endif


    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_RXDLY5),
            P_Fld((U32)iDQSDlyPerbyte[0], SHU_R0_B0_RXDLY5_RX_ARDQS0_R_DLY_B0));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_RXDLY4),
            P_Fld((U32)iDQMDlyPerbyte[0], SHU_R0_B0_RXDLY4_RX_ARDQM0_R_DLY_B0));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_RXDLY5),
            P_Fld((U32)iDQSDlyPerbyte[1], SHU_R0_B1_RXDLY5_RX_ARDQS0_R_DLY_B1));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_RXDLY4),
            P_Fld((U32)iDQMDlyPerbyte[1], SHU_R0_B1_RXDLY4_RX_ARDQM0_R_DLY_B1));


    for (u1BitIdx = 0; u1BitIdx < DQS_BIT_NUMBER; u1BitIdx += 2)
    {
         vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_RXDLY0 + u1BitIdx * 2),
                                        P_Fld(((U32)FinalWinPerBit[u1BitIdx].best_dqdly), SHU_R0_B0_RXDLY0_RX_ARDQ0_R_DLY_B0) |
                                        P_Fld(((U32)FinalWinPerBit[u1BitIdx + 1].best_dqdly), SHU_R0_B0_RXDLY0_RX_ARDQ1_R_DLY_B0));

         vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_RXDLY0 + u1BitIdx * 2),
                                        P_Fld((U32)FinalWinPerBit[u1BitIdx + 8].best_dqdly, SHU_R0_B1_RXDLY0_RX_ARDQ0_R_DLY_B1) |
                                        P_Fld((U32)FinalWinPerBit[u1BitIdx + 9].best_dqdly, SHU_R0_B1_RXDLY0_RX_ARDQ1_R_DLY_B1));

        //mcSHOW_DBG_MSG(("u1BitId %d  Addr 0x%2x = %2d %2d %2d %2d \n", u1BitIdx, DDRPHY_RXDQ1+u1BitIdx*2,
        //                FinalWinPerBit[u1BitIdx].best_dqdly, FinalWinPerBit[u1BitIdx+1].best_dqdly,  FinalWinPerBit[u1BitIdx+8].best_dqdly, FinalWinPerBit[u1BitIdx+9].best_dqdly));
    }

    DramPhyReset(p);

#if RDDQC_PINMUX_WORKAROUND
    DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress) / sizeof(U32));
#endif

    vSetRank(p, backup_rank);
    //vPrintCalibrationBasicInfo(p);

#ifdef ETT_PRINT_FORMAT
    mcSHOW_DBG_MSG(("\nDQS Delay:\nDQS0 = %d, DQS1 = %d\n"
                    "DQM Delay:\nDQM0 = %d, DQM1 = %d\n",
                        iDQSDlyPerbyte[0], iDQSDlyPerbyte[1],
                        iDQMDlyPerbyte[0], iDQMDlyPerbyte[1]));
    /*mcDUMP_REG_MSG(("\nDQS Delay:\nDQS0 = %d, DQS1 = %d\n"
                    "DQM Delay:\nDQM0 = %d, DQM1 = %d\n",
                        iDQSDlyPerbyte[0], iDQSDlyPerbyte[1],
                        iDQMDlyPerbyte[0], iDQMDlyPerbyte[1]));*/
#else
    mcSHOW_DBG_MSG(("\nDQS Delay:\nDQS0 = %2d, DQS1 = %2d\n"
                    "DQM Delay:\nDQM0 = %2d, DQM1 = %2d\n",
                        iDQSDlyPerbyte[0], iDQSDlyPerbyte[1],
                        iDQMDlyPerbyte[0], iDQMDlyPerbyte[1]));
    /*mcDUMP_REG_MSG(("\nDQS Delay:\nDQS0 = %2d, DQS1 = %2d\n"
                    "DQM Delay:\nDQM0 = %2d, DQM1 = %2d\n",
                        iDQSDlyPerbyte[0], iDQSDlyPerbyte[1],
                        iDQMDlyPerbyte[0], iDQMDlyPerbyte[1]));*/
#endif
    mcSHOW_DBG_MSG(("DQ Delay:\n"));
    //mcDUMP_REG_MSG(("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));
        //mcDUMP_REG_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));
        //mcDUMP_REG_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
    }
    mcSHOW_DBG_MSG(("\n"));
    mcSHOW_DBG_MSG4(("[DramcRxWindowPerbitCal] Done\n"));

    #if LP5_DDR4266_RDBI_WORKAROUND
    if((is_lp5_family(p)) && (p->frequency >= 2133))
    {
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ7), 1, SHU_B0_DQ7_R_DMDQMDBI_SHU_B0);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ7), 1, SHU_B1_DQ7_R_DMDQMDBI_SHU_B1);
    }
    #endif

return DRAM_OK;

}

#if SIMULATION_RX_DVS
static U8 DramcRxDVSCal(DRAMC_CTX_T *p, U8 u1byte)
{
    U8 u1rising_lead, u1falling_lead, u1rising_lag, u1falling_lag, u1lead_lag;

    if (u1byte == 0)
    {
        u1rising_lead = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_FT_STATUS0), MISC_FT_STATUS0_AD_RX_ARDQ_DVS_R_LEAD_B0);
        u1falling_lead = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_FT_STATUS1), MISC_FT_STATUS1_AD_RX_ARDQ_DVS_F_LEAD_B0);
        u1rising_lag = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_FT_STATUS0), MISC_FT_STATUS0_AD_RX_ARDQ_DVS_R_LAG_B0);
        u1falling_lag = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_FT_STATUS1), MISC_FT_STATUS1_AD_RX_ARDQ_DVS_F_LAG_B0);
    }
    else
    {
        u1rising_lead = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_FT_STATUS0), MISC_FT_STATUS0_AD_RX_ARDQ_DVS_R_LAG_B1);
        u1falling_lead = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_FT_STATUS1), MISC_FT_STATUS1_AD_RX_ARDQ_DVS_F_LEAD_B1);
        u1rising_lag = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_FT_STATUS0), MISC_FT_STATUS0_AD_RX_ARDQ_DVS_R_LAG_B1);
        u1falling_lag = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_FT_STATUS1), MISC_FT_STATUS1_AD_RX_ARDQ_DVS_F_LAG_B1);
    }

    mcSHOW_DBG_MSG2(("Byte%d | LEAD(%d %d) | LAG(%d %d)\n", u1byte, u1rising_lead, u1falling_lead, u1rising_lag, u1falling_lag));

    u1lead_lag = (u1rising_lead | u1falling_lead | u1rising_lag | u1falling_lag);

    return u1lead_lag;
}

DRAM_STATUS_T DramcRxDVSWindowCal(DRAMC_CTX_T *p)
{
    U8 ii, u1ByteIdx;
    S16 iDelay = 0, S16DelayBegin = 0;
    U16 u16DelayEnd = 0, u16DelayStep = 1;
    U32 u4err_value;

    U8 u1lead_lag, u1DVS_first_flag[DQS_BYTE_NUMBER]={0}, u1DVS_first_pass[DQS_BYTE_NUMBER]={0}, u1DVS_pass_window[DQS_BYTE_NUMBER]={0}, u1finish_flag[DQS_BYTE_NUMBER]={0};
    U32 u4RegBackupAddress[] =
    {
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ11)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ11)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_RXDLY0)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_RXDLY0)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_RXDLY5)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_RXDLY5)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_RXDLY4)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_RXDLY4)),
    };


    if (!p)
    {
        mcSHOW_ERR_MSG(("context NULL\n"));
        return DRAM_FAIL;
    }

    mcSHOW_DBG_MSG(("[RX DVS calibration]\n"));


    vAutoRefreshSwitch(p, DISABLE);
    //CKEFixOnOff(p, p->rank, CKE_FIXON, TO_ONE_CHANNEL);

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ11), 1, SHU_B0_DQ11_RG_RX_ARDQ_DVS_EN_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ11), 1, SHU_B1_DQ11_RG_RX_ARDQ_DVS_EN_B1);


#if ENABLE_K_WITH_WORST_SI_UI_SHIFT
    DramcEngine2Init(p, p->test2_1, p->test2_2, p->test_pattern | 0x80, 0, TE_UI_SHIFT);
#else
    DramcEngine2Init(p, p->test2_1, p->test2_2, TEST_XTALK_PATTERN, 0, TE_NO_UI_SHIFT);
#endif

    {
        u16DelayStep = 4;
    }

    S16DelayBegin = -80;
    u16DelayEnd = 100;

    mcSHOW_DBG_MSG2(("\nRX Delay %d -> %d, step: %d\n", S16DelayBegin, u16DelayEnd, u16DelayStep));

    {

        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_RXDLY4),
                P_Fld(0, SHU_R0_B0_RXDLY4_RX_ARDQM0_R_DLY_B0) |
                P_Fld(0, SHU_R0_B0_RXDLY4_RX_ARDQM0_F_DLY_B0));
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_RXDLY4),
                P_Fld(0, SHU_R0_B1_RXDLY4_RX_ARDQM0_R_DLY_B1) |
                P_Fld(0, SHU_R0_B1_RXDLY4_RX_ARDQM0_F_DLY_B1));


        for (ii = 0; ii < 4; ii++)
            SetRxDqDelay(p, ii, 0);
        {

            for (iDelay = S16DelayBegin; iDelay <= u16DelayEnd; iDelay += u16DelayStep)
            {
                SetRxDqDqsDelay(p, iDelay);

                u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, p->test_pattern);

                mcSHOW_DBG_MSG2(("iDelay= %4d, err_value: 0x%x", iDelay, u4err_value));

                for(u1ByteIdx=0; u1ByteIdx<DQS_BYTE_NUMBER; u1ByteIdx++)
                {
                    u1lead_lag = DramcRxDVSCal(p, u1ByteIdx);

                    if ((u1lead_lag == 0) && (u1DVS_first_flag[u1ByteIdx] == 0) && (((u4err_value >> (u1ByteIdx<<3)) & 0xff) == 0))
                    {
                        u1DVS_first_pass[u1ByteIdx] = iDelay;
                        u1DVS_first_flag[u1ByteIdx] = 1;

                        mcSHOW_DBG_MSG2(("Byte%d find first pass delay\n"))
                    }
                    else if (((u1lead_lag == 1) || (((u4err_value >> (u1ByteIdx<<3)) & 0xff) != 0)) && (u1DVS_first_flag[u1ByteIdx] == 1) && (u1finish_flag[u1ByteIdx] == 0))
                    {
                        u1DVS_pass_window[u1ByteIdx] = iDelay - u1DVS_first_pass[u1ByteIdx] - u16DelayStep;

                        if (u1DVS_pass_window[u1ByteIdx] < 7)
                        {
                            u1DVS_pass_window[u1ByteIdx] = 0;
                            u1DVS_first_flag[u1ByteIdx] = 0;
                            mcSHOW_DBG_MSG2(("Byte%d find fake window\n"))
                        }
                        else
                        {
                             u1finish_flag[u1ByteIdx] = 1;
                             mcSHOW_DBG_MSG2(("Byte%d find pass window\n"))
                        }
                    }
                }

                if ((u1finish_flag[0]==1) && (u1finish_flag[1]==1))
                {
                    mcSHOW_DBG_MSG2(("Two byte DVS window find, early break!\n"));
                    break;
                }
            }
        }
    }

    DramcEngine2End(p);

    for (u1ByteIdx = 0; u1ByteIdx < DQS_BYTE_NUMBER; u1ByteIdx++)
    {
        u1DVS_increase[p->rank][u1ByteIdx] = (u1DVS_pass_window[u1ByteIdx] > 8)? ((u1DVS_pass_window[u1ByteIdx] - 8) >> 3): 0;
        mcSHOW_DBG_MSG(("\nByte %d final DVS window size(M) %d, DVS increase %d\n", u1ByteIdx, u1DVS_pass_window[u1ByteIdx], u1DVS_increase[p->rank][u1ByteIdx]));
    }

    DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress) / sizeof(U32));

    vAutoRefreshSwitch(p, ENABLE);

    DramPhyReset(p);

    vPrintCalibrationBasicInfo(p);

    mcSHOW_DBG_MSG(("\n\n"));
    mcSHOW_DBG_MSG4(("[DramcRxDVSWindowCal] Done\n"));

return DRAM_OK;
}

void DramcDramcRxDVSCalPostProcess(DRAMC_CTX_T *p)
{
    U8 rank_i, u1ByteIdx, u1DVS_increase_final, u1DVS_dly_final[DQS_BYTE_NUMBER]={0};
    U8 backup_rank = p->rank;

    for (u1ByteIdx = 0; u1ByteIdx < DQS_BYTE_NUMBER; u1ByteIdx++)
    {
        if (p->support_rank_num == RANK_DUAL)
            u1DVS_increase_final = (u1DVS_increase[RANK_0][u1ByteIdx] < u1DVS_increase[RANK_1][u1ByteIdx])? u1DVS_increase[RANK_0][u1ByteIdx] : u1DVS_increase[RANK_1][u1ByteIdx];
        else
            u1DVS_increase_final = u1DVS_increase[p->rank][u1ByteIdx];

        if (u1ByteIdx == 0)
        {
            u1DVS_dly_final[u1ByteIdx] = u1DVS_increase_final + (u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ11), SHU_B0_DQ11_RG_RX_ARDQ_DVS_DLY_B0));
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ11), u1DVS_dly_final[u1ByteIdx], SHU_B0_DQ11_RG_RX_ARDQ_DVS_DLY_B0);
        }
        else
        {
            u1DVS_dly_final[u1ByteIdx] = u1DVS_increase_final + (u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ11), SHU_B1_DQ11_RG_RX_ARDQ_DVS_DLY_B1));
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ11), u1DVS_dly_final[u1ByteIdx], SHU_B1_DQ11_RG_RX_ARDQ_DVS_DLY_B1);
        }
        mcSHOW_DBG_MSG(("Byte%d final DVS delay: %d\n", u1ByteIdx, u1DVS_dly_final[u1ByteIdx]));
    }

    for(rank_i=RANK_0; rank_i< p->support_rank_num; rank_i++)
    {
        vSetRank(p, rank_i);
        DramcRxWindowPerbitCal(p, PATTERN_TEST_ENGINE, DVS_CAL_KEEP_VREF, AUTOK_OFF, NORMAL_K);
    }

    if ((DramcRxDVSCal(p, 0) == 1) || (DramcRxDVSCal(p, 1) == 1))
    {
        mcSHOW_ERR_MSG(("Final DVS delay is out of RX window\n"));
        for (u1ByteIdx = 0; u1ByteIdx < DQS_BYTE_NUMBER; u1ByteIdx++)
        {
            if (u1DVS_dly_final[u1ByteIdx] > 0)
            {
                u1DVS_dly_final[u1ByteIdx] -= 1;
                if (u1ByteIdx == 0)
                {
                    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ11), u1DVS_dly_final[u1ByteIdx], SHU_B0_DQ11_RG_RX_ARDQ_DVS_DLY_B0);
                }
                else
                {
                    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ11), u1DVS_dly_final[u1ByteIdx], SHU_B1_DQ11_RG_RX_ARDQ_DVS_DLY_B1);
                }
            }
            for(rank_i=RANK_0; rank_i< p->support_rank_num; rank_i++)
            {
                vSetRank(p, rank_i);
                DramcRxWindowPerbitCal(p, PATTERN_TEST_ENGINE, DVS_CAL_KEEP_VREF, AUTOK_OFF, NORMAL_K);
            }
        }
    }

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ11), 1, SHU_B0_DQ11_RG_RX_ARDQ_DVS_EN_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ11), 1, SHU_B1_DQ11_RG_RX_ARDQ_DVS_EN_B1);

    vSetRank(p, backup_rank);
}
#endif

#if SIMULATION_DATLAT
static void dle_factor_handler(DRAMC_CTX_T *p, U8 curr_val)
{
    U8 u1DATLAT_DSEL = 0;
    U8 u1DLECG_OptionEXT1 = 0;
    U8 u1DLECG_OptionEXT2 = 0;
    U8 u1DLECG_OptionEXT3 = 0;


    if (u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_MISC_RX_PIPE_CTRL), SHU_MISC_RX_PIPE_CTRL_RX_PIPE_BYPASS_EN))
    {
        u1DATLAT_DSEL = curr_val;
    }
    else
    {
        if (curr_val < 1)
            u1DATLAT_DSEL = curr_val;
        else
            u1DATLAT_DSEL = curr_val - 1;
    }

//    mcSHOW_DBG_MSG(("DATLAT: %d, u1DATLAT_DSEL: %d\n", curr_val, u1DATLAT_DSEL));

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_MISC_SHU_RDAT),
            P_Fld(curr_val, MISC_SHU_RDAT_DATLAT) |
            P_Fld(u1DATLAT_DSEL, MISC_SHU_RDAT_DATLAT_DSEL) |
            P_Fld(u1DATLAT_DSEL, MISC_SHU_RDAT_DATLAT_DSEL_PHY));


    u1DLECG_OptionEXT1 = (curr_val >= 8)? (1): (0);
    u1DLECG_OptionEXT2 = (curr_val >= 14)? (1): (0);
    u1DLECG_OptionEXT3 = (curr_val >= 19)? (1): (0);
//    mcSHOW_DBG_MSG(("u1DLECG_OptionEXT1: %d, 2 for %d, 3 for %d\n", u1DLECG_OptionEXT1, u1DLECG_OptionEXT2, u1DLECG_OptionEXT3));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU_RX_CG_SET0),
            P_Fld(u1DLECG_OptionEXT1, SHU_RX_CG_SET0_READ_START_EXTEND1) |
            P_Fld(u1DLECG_OptionEXT1, SHU_RX_CG_SET0_DLE_LAST_EXTEND1) |
            P_Fld((u1DLECG_OptionEXT2), SHU_RX_CG_SET0_READ_START_EXTEND2) |
            P_Fld((u1DLECG_OptionEXT2), SHU_RX_CG_SET0_DLE_LAST_EXTEND2) |
            P_Fld((u1DLECG_OptionEXT3), SHU_RX_CG_SET0_READ_START_EXTEND3) |
            P_Fld((u1DLECG_OptionEXT3), SHU_RX_CG_SET0_DLE_LAST_EXTEND3));

    DramPhyReset(p);

}

static U8 aru1RxDatlatResult[RANK_MAX];
DRAM_STATUS_T DramcRxdatlatCal(DRAMC_CTX_T *p)
{
    //U8 ii, ucStartCalVal = 0;
    //U32 u4err_value = 0xffffffff;
    U8 ucbest_step; //ucpipe_num = 0;


    if (!p)
    {
        mcSHOW_ERR_MSG(("context NULL\n"));
        return DRAM_FAIL;
    }

    //mcDUMP_REG_MSG(("\n[dumpRG] DramcRxdatlatCal\n"));
    #if VENDER_JV_LOG
    vPrintCalibrationBasicInfo_ForJV(p);
    #else
    vPrintCalibrationBasicInfo(p);
    #endif
    mcSHOW_DBG_MSG(("[RxdatlatCal]\n"));


    u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_MISC_SHU_RDAT));


    vSetCalibrationResult(p, DRAM_CALIBRATION_DATLAT, DRAM_FAIL);


    ucbest_step = (U8) u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_SHU_RDAT), MISC_SHU_RDAT_DATLAT);
    mcSHOW_DBG_MSG2(("DATLAT Default: 0x%x\n", ucbest_step));
    //mcDUMP_REG_MSG(("DATLAT Default: 0x%x\n", ucbest_step));


    DramcEngine2Init(p, p->test2_1, p->test2_2, p->test_pattern | 0x80, 0, TE_UI_SHIFT);

#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_DATLAT)
    if (p->femmc_Ready == 1)
    {
        ucbest_step = p->pSavetimeData->u1RxDatlat_Save[p->channel][p->rank];
    }
#endif

    aru1RxDatlatResult[p->rank] = ucbest_step;

    mcSHOW_DBG_MSG(("best_step = %d\n\n", ucbest_step));
    //mcDUMP_REG_MSG(("best_step=%d\n\n", ucbest_step));

#if __A60868_TO_BE_PORTING__
#if __ETT__
    U8 _init_Datlat_value = vDramcACTimingGetDatLat(p);
    if ((_init_Datlat_value > (ucbest_step + 1)) || (_init_Datlat_value < (ucbest_step - 1)))
    {
        mcSHOW_DBG_MSG(("[WARNING!!] Datlat initial value(%d) = best_step(%d) %c %d, out of range!\n\n",
                           _init_Datlat_value,
                           ucbest_step,
                           (ucbest_step > _init_Datlat_value)? '-': '+',
                           abs(ucbest_step - _init_Datlat_value)));
        while (1);
    }
#endif
#endif
#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_DATLAT)
    if (p->femmc_Ready == 1)
    {
        dle_factor_handler(p, ucbest_step);
        vSetCalibrationResult(p, DRAM_CALIBRATION_DATLAT, DRAM_FAST_K);
    }
#endif

    mcSHOW_DBG_MSG4(("[DramcRxdatlatCal] Done\n"));
    return DRAM_OK;

}

DRAM_STATUS_T DramcDualRankRxdatlatCal(DRAMC_CTX_T *p)
{
    U8 u1FinalDatlat, u1Datlat0, u1Datlat1;

    u1Datlat0 = aru1RxDatlatResult[0];
    u1Datlat1 = aru1RxDatlatResult[1];

    if (p->support_rank_num == RANK_DUAL)
    {
        if (u1Datlat0 > u1Datlat1)
        {
            u1FinalDatlat = u1Datlat0;
        }
        else
        {
            u1FinalDatlat = u1Datlat1;
        }
    }
    else
    {
        u1FinalDatlat = u1Datlat0;
    }

#if ENABLE_READ_DBI
    if (p->DBI_R_onoff[p->dram_fsp])
    {
      u1FinalDatlat++;
    }
#endif

    dle_factor_handler(p, u1FinalDatlat);

#if RDSEL_TRACKING_EN
    if(p->frequency >= RDSEL_TRACKING_TH)
    {
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_MISC_RDSEL_TRACK), u1FinalDatlat, SHU_MISC_RDSEL_TRACK_DMDATLAT_I);
    }
#endif

    mcSHOW_DBG_MSG(("[DualRankRxdatlatCal] RK0: %d, RK1: %d, Final_Datlat %d\n", u1Datlat0, u1Datlat1, u1FinalDatlat));
    //mcDUMP_REG_MSG(("[DualRankRxdatlatCal] RK0: %d, RK1: %d, Final_Datlat %d\n", u1Datlat0, u1Datlat1, u1FinalDatlat));


#if defined(FOR_HQA_TEST_USED) && defined(FOR_HQA_REPORT_USED)
    {   U8 backup_rank, rank_index;

        backup_rank = u1GetRank(p);
        for(rank_index = RANK_0; rank_index < p->support_rank_num; rank_index++)
        {
            vSetRank(p, rank_index);
            HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "DATLAT", "", 0, u1FinalDatlat, NULL);
        }
        vSetRank(p, backup_rank);
    }
#endif

    return DRAM_OK;

}
#endif

#if SIMULATION_TX_PERBIT

#if (SW_CHANGE_FOR_SIMULATION || FOR_DV_SIMULATION_USED)
#define TX_VREF_RANGE_BEGIN       0
#define TX_VREF_RANGE_END           2
#define TX_VREF_RANGE_STEP         2
#else
#define TX_VREF_RANGE_BEGIN       16
#define TX_VREF_RANGE_END           50
#define TX_VREF_RANGE_STEP         2
#endif

#define TX_DQ_UI_TO_PI_TAP         64
#define TX_PHASE_DQ_UI_TO_PI_TAP         32
#define LP4_TX_VREF_DATA_NUM 50
#define LP4_TX_VREF_PASS_CONDITION 0
#define TX_PASS_WIN_CRITERIA    7
#define LP4_TX_VREF_BOUNDARY_NOT_READY 0xff

typedef struct _PASS_WIN_DATA_BY_VREF_T
{
    U16 u2VrefUsed;
    U16 u2WinSum_byVref;
    U8 u1WorseBitWinSize_byVref;
    U8 u1WorseBitIdx_byVref;
} PASS_WIN_DATA_BY_VREF_T;

#if 0
static U16 WDQSMode2AcTxOEShift(DRAMC_CTX_T *p)
{
    U16 u2TxDQOEShift = 0;

    switch (p->frequency)
    {
        case 1866:
            u2TxDQOEShift = 19;
            break;
        case 1600:
        case 1200:
        case 800:
        case 600:
            u2TxDQOEShift = 15;
            break;
        case 933:
            u2TxDQOEShift = 11;
            break;
        case 400:
            u2TxDQOEShift = 16;
            break;
        default:
            mcSHOW_ERR_MSG(("[WDQSMode2AcTxOEShift] frequency err!\n"));
            #if __ETT__
            while (1);
            #endif
    }

    return u2TxDQOEShift;
}
#endif
void TxWinTransferDelayToUIPI(DRAMC_CTX_T *p, U16 uiDelay, U8 u1AdjustPIToCenter, U8* pu1UILarge_DQ, U8* pu1UISmall_DQ, U8* pu1PI, U8* pu1UILarge_DQOE, U8* pu1UISmall_DQOE)
{
    U8 u1Small_ui_to_large, u1PI = 0, u164PIto1UI, u1TxDQOEShift = 0;
    U16 u2TmpValue, u2DQOE_shift;
    DDR800_MODE_T eDdr800Mode = vGet_DDR_Loop_Mode(p);
    U8 u1PiTap = (u1IsPhaseMode(p) == TRUE) ? TX_PHASE_DQ_UI_TO_PI_TAP : TX_DQ_UI_TO_PI_TAP;

    u1Small_ui_to_large = u1MCK2UI_DivShift(p);

    #if ENABLE_WDQS_MODE_2
    u1TxDQOEShift = WDQSMode2AcTxOEShift(p);
    #else
    u1TxDQOEShift = TX_DQ_OE_SHIFT_LP4;
    #endif

    if(pu1PI != NULL)
    {
        u1PI = uiDelay & (u1PiTap-1);
        *pu1PI =u1PI;
    }

    if (u1IsLP4Div4DDR800(p) || u1IsPhaseMode(p))
        u164PIto1UI = 0;
    else
        u164PIto1UI = 1;

    u2TmpValue = (uiDelay /u1PiTap)<<u164PIto1UI;

    if (u1AdjustPIToCenter && (pu1PI != NULL) && (eDdr800Mode == CLOSE_LOOP_MODE))
    {
        if (u1PI < 10)
        {
            u1PI += (u1PiTap) >> 1;
            u2TmpValue --;
        }
        else if (u1PI > u1PiTap - 10)
        {
            u1PI -= (u1PiTap) >> 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

    {
        u2TmpValue -= u1TxDQOEShift;
    }

    if(((u1MR03Value[p->dram_fsp]&0x80)>>7)==1)
    {
        if (vGet_Div_Mode(p) == DIV4_MODE)
            u2DQOE_shift = 4;
        else
            u2DQOE_shift = 8;

        u2TmpValue += u2DQOE_shift;
    }

    *pu1UISmall_DQOE = u2TmpValue - ((u2TmpValue >> u1Small_ui_to_large) << u1Small_ui_to_large);
    *pu1UILarge_DQOE = (u2TmpValue >> u1Small_ui_to_large);
}

#if 0
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
    #if PIN_CHECK_TOOL
            PINInfo_flashtool.DQ_TX_WIN_SIZE[p->channel][p->rank][u1BitIdx] = WinPerBitData[u1BitIdx].win_size;
            PINInfo_flashtool.DQ_TX_WIN_SIZE[p->channel][p->rank][u1BitIdx+8] = WinPerBitData[u1BitIdx+8].win_size;
    #endif
        mcSHOW_DBG_MSG(("\n"));
    }
    mcSHOW_DBG_MSG(("\n"));
#if DUMP_TA2_WINDOW_SIZE_RX_TX
    {
        U32 u4B0Tatal=0;
        U32 u4B1Tatal=0;
        for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
        {
            if(u1BitIdx < 8)
            {
                u4B0Tatal += WinPerBitData[u1BitIdx].win_size;
            }
            else
            {
                u4B1Tatal += WinPerBitData[u1BitIdx].win_size;
            }
        }
        mcSHOW_DBG_MSG(("\ntotal tx window size B0: %d B1: %d\n", u4B0Tatal, u4B1Tatal));
    }
#endif
}
#endif

static void TXPerbitCalibrationInit(DRAMC_CTX_T *p, U8 calType)
{

    if (calType != TX_DQ_DQS_MOVE_DQM_ONLY)
    {
    #if 1
    #if PINMUX_AUTO_TEST_PER_BIT_TX
        if(gTX_check_per_bit_flag == 1)
        {

        }
        else
    #endif
        {
            vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_TXDLY0), 0);
            vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_TXDLY1), 0);
            vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_TXDLY0), 0);
            vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_TXDLY1), 0);
        }
    #else
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU_R0_B0_DQ0), P_Fld(0x0, SHU_R0_B0_DQ0_RK0_TX_ARDQ7_DLY_B0)
            | P_Fld(0x0, SHU_R0_B0_DQ0_RK0_TX_ARDQ6_DLY_B0)
            | P_Fld(0x0, SHU_R0_B0_DQ0_RK0_TX_ARDQ5_DLY_B0)
            | P_Fld(0x0, SHU_R0_B0_DQ0_RK0_TX_ARDQ4_DLY_B0)
            | P_Fld(0x0, SHU_R0_B0_DQ0_RK0_TX_ARDQ3_DLY_B0)
            | P_Fld(0x0, SHU_R0_B0_DQ0_RK0_TX_ARDQ2_DLY_B0)
            | P_Fld(0x0, SHU_R0_B0_DQ0_RK0_TX_ARDQ1_DLY_B0)
            | P_Fld(0x0, SHU_R0_B0_DQ0_RK0_TX_ARDQ0_DLY_B0));
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU_R0_B1_DQ0), P_Fld(0x0, SHU_R0_B1_DQ0_RK0_TX_ARDQ7_DLY_B1)
            | P_Fld(0x0, SHU_R0_B1_DQ0_RK0_TX_ARDQ6_DLY_B1)
            | P_Fld(0x0, SHU_R0_B1_DQ0_RK0_TX_ARDQ5_DLY_B1)
            | P_Fld(0x0, SHU_R0_B1_DQ0_RK0_TX_ARDQ4_DLY_B1)
            | P_Fld(0x0, SHU_R0_B1_DQ0_RK0_TX_ARDQ3_DLY_B1)
            | P_Fld(0x0, SHU_R0_B1_DQ0_RK0_TX_ARDQ2_DLY_B1)
            | P_Fld(0x0, SHU_R0_B1_DQ0_RK0_TX_ARDQ1_DLY_B1)
            | P_Fld(0x0, SHU_R0_B1_DQ0_RK0_TX_ARDQ0_DLY_B1));
    #endif
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_TXDLY3), 0x0, SHU_R0_B0_TXDLY3_TX_ARDQM0_DLY_B0);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_TXDLY3), 0x0, SHU_R0_B1_TXDLY3_TX_ARDQM0_DLY_B1);
    }



}

#define TX_TDQS2DQ_PRE_CAL 0
#if TX_TDQS2DQ_PRE_CAL

U16 u2DQS2DQ_Pre_Cal[CHANNEL_NUM][RANK_MAX][2] = {0};
#endif

static void TXScanRange_PI(DRAMC_CTX_T *p, DRAM_TX_PER_BIT_CALIBRATION_TYTE_T calType, U16 *pu2Begin, U16 *pu2End)
{
    U8 u1MCK2UI, u1UI2PI, u1ByteIdx;
    U32 u4RegValue_TXDLY, u4RegValue_dly;
    U8 ucdq_ui_large_bak[DQS_BYTE_NUMBER], ucdq_ui_small_bak[DQS_BYTE_NUMBER];
    U16 u2TempVirtualDelay, u2SmallestVirtualDelay = 0xffff;
    U16 u2DQDelayBegin = 0, u2DQDelayEnd = 0;

    {
        u4RegValue_TXDLY = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_DQS0));
        u4RegValue_dly = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_DQS1));
    }

    u1MCK2UI = u1MCK2UI_DivShift(p);

    if (vGet_DDR_Loop_Mode(p) == DDR800_CLOSE_LOOP)
        u1UI2PI = 6;
    else
        u1UI2PI = 5;



    for (u1ByteIdx = 0; u1ByteIdx < DQS_BYTE_NUMBER; u1ByteIdx++)
    {
        ucdq_ui_large_bak[u1ByteIdx] = (u4RegValue_TXDLY >> (u1ByteIdx << 2)) & 0x7;
        ucdq_ui_small_bak[u1ByteIdx] = (u4RegValue_dly >> (u1ByteIdx << 2)) & 0x7;

        u2TempVirtualDelay = (((ucdq_ui_large_bak[u1ByteIdx] << u1MCK2UI) + ucdq_ui_small_bak[u1ByteIdx]) << u1UI2PI) + wrlevel_dqs_final_delay[p->rank][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[p->rank][u1ByteIdx]));
    }

    u2DQDelayBegin = u2SmallestVirtualDelay;

    #if TX_TDQS2DQ_PRE_CAL
    if (u1IsLP4Div4DDR800(p) == FALSE)
    {
        if (u2DQS2DQ_Pre_Cal[p->channel][p->rank][vGet_Div_Mode(p)] > 0)
        {
            U16 u2TmpShift;
            mcSHOW_DBG_MSG(("TX_TDQS2DQ_PRE_CAL : change DQ begin %d -->", u2DQDelayBegin));

            u2TmpShift = (u2DQS2DQ_Pre_Cal[p->channel][p->rank][vGet_Div_Mode(p)]* p->frequency) / 1000;
            if (u2TmpShift >= 15)
                u2TmpShift -= 15;
            else
                u2TmpShift = 0;

            u2DQDelayBegin += u2TmpShift;
            mcSHOW_DBG_MSG(("%d (+%d)\n", u2DQDelayBegin, u2TmpShift));
        }
    }
    #endif

    #if TX_K_DQM_WITH_WDBI
    if (calType == TX_DQ_DQS_MOVE_DQM_ONLY)
    {

        u2DQDelayBegin -= (1 << (u1MCK2UI + 5));
    }
    #endif

    u2DQDelayEnd = u2DQDelayBegin + ((1 << u1MCK2UI) << u1UI2PI);

    *pu2Begin = u2DQDelayBegin;
    *pu2End = u2DQDelayEnd;

    #if 0
    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 = 0, u2VrefEnd = 0;

    if (u1VrefScanEnable)
    {
    #if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_VREF_CAL)
        if (p->femmc_Ready == 1)
        {

            u2VrefBegin = p->pSavetimeData->u1TxWindowPerbitVref_Save[p->channel][p->rank];
            u2VrefEnd = u2VrefBegin + 1;
        }
    #endif
    }
    else
    {
        u2VrefBegin = 0;
        u2VrefEnd = 0;
    }

    *pu2Range = (!p->odt_onoff);
    *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, u1WorseBitIdx = 0, u1WinSizeOfWorseBit = 0;
    //U8 u1VrefPassBegin = LP4_TX_VREF_BOUNDARY_NOT_READY, u1VrefPassEnd = LP4_TX_VREF_BOUNDARY_NOT_READY, u1TempPassNum = 0, u1MaxVerfPassNum = 0;
    //U8 u1VrefPassBegin_Final = LP4_TX_VREF_BOUNDARY_NOT_READY, u1VrefPassEnd_Final = LP4_TX_VREF_BOUNDARY_NOT_READY;
    U16 u2MaxWinSum = 0;
    U16 u2FinalVref = 0;

    for (u1VrefIdx = 0; u1VrefIdx < u1VrefNum; u1VrefIdx++)
    {
        mcSHOW_DBG_MSG2(("TX Vref=%d, minBit %d, minWin=%d, winSum=%d\n",
            pVrefInfo[u1VrefIdx].u2VrefUsed,
            pVrefInfo[u1VrefIdx].u1WorseBitIdx_byVref,
            pVrefInfo[u1VrefIdx].u1WorseBitWinSize_byVref,
            pVrefInfo[u1VrefIdx].u2WinSum_byVref));

        #if LP4_TX_VREF_PASS_CONDITION
        if ((pVrefInfo[u1VrefIdx].u1WorseBitWinSize_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)
    {

        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
    {

        for (u1VrefIdx = 0; u1VrefIdx < u1VrefNum; u1VrefIdx++)
        {
            if ((pVrefInfo[u1VrefIdx].u1WorseBitWinSize_byVref > u1WinSizeOfWorseBit) ||
                ((pVrefInfo[u1VrefIdx].u1WorseBitWinSize_byVref == u1WinSizeOfWorseBit) && (pVrefInfo[u1VrefIdx].u2WinSum_byVref > u2MaxWinSum)))
            {
                u1WinSizeOfWorseBit = pVrefInfo[u1VrefIdx].u1WorseBitWinSize_byVref;
                u1WorseBitIdx = pVrefInfo[u1VrefIdx].u1WorseBitIdx_byVref;
                u2MaxWinSum = pVrefInfo[u1VrefIdx].u2WinSum_byVref;
                u2FinalVref = pVrefInfo[u1VrefIdx].u2VrefUsed;
            }
        }

        mcSHOW_DBG_MSG(("[TxChooseVref] Worse bit %d, Min win %d, Win sum %d, Final Vref %d\n", u1WorseBitIdx, u1WinSizeOfWorseBit, u2MaxWinSum, u2FinalVref));
        //mcDUMP_REG_MSG(("[TxChooseVref] Worse bit %d, Min win %d, Win sum %d, Final Vref %d\n", u1WorseBitIdx, u1WinSizeOfWorseBit, u2MaxWinSum, u2FinalVref));
    }

    return u2FinalVref;
}


static void DramcTXSetVref(DRAMC_CTX_T *p, U8 u1VrefRange, U8 u1VrefValue)
{
    U8 u1TempOPValue;

        u1TempOPValue = ((u1VrefValue & 0x3f) | (u1VrefRange << 6));

    u1MR14Value[p->channel][p->rank][p->dram_fsp] = u1TempOPValue;


    DramcModeRegWriteByRank(p, p->rank, 14, u1TempOPValue);

    #if CALIBRATION_SPEED_UP_DEBUG
    mcSHOW_DBG_MSG2(("Yulia TX Vref : CH%d Rank%d, TX Range %d Vref %d\n\n", p->channel, p->rank, u1VrefRange, (u1VrefValue & 0x3f)));
    #endif
}


static void TXSetFinalVref(DRAMC_CTX_T *p, U16 u2FinalRange, U16 u2FinalVref)
{
    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));
#endif

    #if CALIBRATION_SPEED_UP_DEBUG
    mcSHOW_DBG_MSG2(("Yulia TX Vref Final: CH%d Rank%d, TX Range %d Vref %d\n\n", p->channel, p->rank, u2FinalRange, u2FinalVref));
    #endif
}


#if ENABLE_TX_TRACKING
#if !BYPASS_CALIBRATION
static
#endif
void TXUpdateTXTracking(DRAMC_CTX_T *p, DRAM_TX_PER_BIT_CALIBRATION_TYTE_T calType, U8 ucdq_pi[], U8 ucdqm_pi[])
{
     if (calType == TX_DQ_DQS_MOVE_DQ_ONLY || calType == TX_DQ_DQS_MOVE_DQM_ONLY)
     {

         if (calType == TX_DQ_DQS_MOVE_DQ_ONLY)
         {
            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK_PI),
                            P_Fld(ucdq_pi[0], SHURK_PI_RK0_ARPI_DQ_B0) | P_Fld(ucdq_pi[1], SHURK_PI_RK0_ARPI_DQ_B1));


            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK_DQS2DQ_CAL1),
                                                    P_Fld(ucdq_pi[1], SHURK_DQS2DQ_CAL1_BOOT_ORIG_UI_RK0_DQ1) |
                                                    P_Fld(ucdq_pi[0], SHURK_DQS2DQ_CAL1_BOOT_ORIG_UI_RK0_DQ0));

             vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK_DQS2DQ_CAL2),
                                                     P_Fld(ucdq_pi[1], SHURK_DQS2DQ_CAL2_BOOT_TARG_UI_RK0_DQ1) |
                                                     P_Fld(ucdq_pi[0], SHURK_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_SHURK_PI),
                            P_Fld(ucdqm_pi[0], SHURK_PI_RK0_ARPI_DQM_B0) | P_Fld(ucdqm_pi[1], SHURK_PI_RK0_ARPI_DQM_B1));


             vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK_DQS2DQ_CAL5),
                                                 P_Fld(ucdqm_pi[1], SHURK_DQS2DQ_CAL5_BOOT_TARG_UI_RK0_DQM1) |
                                                 P_Fld(ucdqm_pi[0], SHURK_DQS2DQ_CAL5_BOOT_TARG_UI_RK0_DQM0));
         }
     }


#if 0
     vIO32WriteFldMulti(DRAMC_REG_SHURK0_PI + (CHANNEL_A << POS_BANK_NUM), \
                              P_Fld(ucdq_final_pi[0], SHURK0_PI_RK0_ARPI_DQ_B0) | P_Fld(ucdq_final_pi[1], SHURK0_PI_RK0_ARPI_DQ_B1));

     vIO32WriteFldMulti(DRAMC_REG_SHURK0_PI + SHIFT_TO_CHB_ADDR, \
                              P_Fld(ucdq_final_pi[2], SHURK0_PI_RK0_ARPI_DQ_B0) | P_Fld(ucdq_final_pi[3], SHURK0_PI_RK0_ARPI_DQ_B1));
#endif

}
#endif

#if !BYPASS_CALIBRATION
static
#endif
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_SHURK_SELPH_DQ0), \
                                     P_Fld(ucdq_ui_large[0], SHURK_SELPH_DQ0_TXDLY_DQ0) |
                                     P_Fld(ucdq_ui_large[1], SHURK_SELPH_DQ0_TXDLY_DQ1) |
                                     P_Fld(ucdq_oen_ui_large[0], SHURK_SELPH_DQ0_TXDLY_OEN_DQ0) |
                                     P_Fld(ucdq_oen_ui_large[1], SHURK_SELPH_DQ0_TXDLY_OEN_DQ1));


        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ2), \
                                     P_Fld(ucdq_ui_small[0], SHURK_SELPH_DQ2_DLY_DQ0) |
                                     P_Fld(ucdq_ui_small[1], SHURK_SELPH_DQ2_DLY_DQ1) |
                                     P_Fld(ucdq_oen_ui_small[0], SHURK_SELPH_DQ2_DLY_OEN_DQ0) |
                                     P_Fld(ucdq_oen_ui_small[1], SHURK_SELPH_DQ2_DLY_OEN_DQ1));
    }


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_DQ0), ucdql_pi[0], SHU_R0_B0_DQ0_SW_ARPI_DQ_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_DQ0), ucdql_pi[1], SHU_R0_B1_DQ0_SW_ARPI_DQ_B1);
}

#if !BYPASS_CALIBRATION
static
#endif
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_SHURK_SELPH_DQ1),
                                     P_Fld(ucdqm_ui_large[0], SHURK_SELPH_DQ1_TXDLY_DQM0) |
                                     P_Fld(ucdqm_ui_large[1], SHURK_SELPH_DQ1_TXDLY_DQM1) |
                                     P_Fld(ucdqm_oen_ui_large[0], SHURK_SELPH_DQ1_TXDLY_OEN_DQM0) |
                                     P_Fld(ucdqm_oen_ui_large[1], SHURK_SELPH_DQ1_TXDLY_OEN_DQM1));


        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ3),
                                     P_Fld(ucdqm_ui_small[0], SHURK_SELPH_DQ3_DLY_DQM0) |
                                     P_Fld(ucdqm_ui_small[1], SHURK_SELPH_DQ3_DLY_DQM1) |
                                     P_Fld(ucdqm_oen_ui_small[0], SHURK_SELPH_DQ3_DLY_OEN_DQM0) |
                                     P_Fld(ucdqm_oen_ui_small[1], SHURK_SELPH_DQ3_DLY_OEN_DQM1));
    }

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_DQ0), ucdqm_pi[0], SHU_R0_B0_DQ0_SW_ARPI_DQM_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_DQ0), ucdqm_pi[1], SHU_R0_B1_DQ0_SW_ARPI_DQM_B1);
}

#if TX_AUTO_K_SUPPORT
static void Tx_Auto_K_Init(DRAMC_CTX_T *p, DRAM_TX_PER_BIT_CALIBRATION_TYTE_T calType, U8 ucdq_pi, U8 u1PI_Len)
{
    u8 pi_thrd = 0xa;
    //u8 early_break = 0x0;

#if FOR_DV_SIMULATION_USED == 1
    cal_sv_rand_args_t *psra = get_psra();

    if (psra) {
        pi_thrd = psra->tx_atk_pass_pi_thrd & 0xFF;
        early_break = psra->tx_atk_early_break & 0xFF;
    }
#endif

#if ENABLE_PA_IMPRO_FOR_TX_AUTOK
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DCM_SUB_CTRL), 0x1, DCM_SUB_CTRL_SUBCLK_CTRL_TX_AUTOK);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_CG_SET0), 0x1, TX_CG_SET0_TX_ATK_CLKRUN);
#endif

    if (calType == TX_DQ_DQS_MOVE_DQ_DQM)
    {
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_SET1),
                                     P_Fld(0x1, TX_ATK_SET1_TX_ATK_DQ_PI_EN) |
                                     P_Fld(0x1, TX_ATK_SET1_TX_ATK_DQM_PI_EN));
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_SET0),
                                     P_Fld(ucdq_pi, TX_ATK_SET0_TX_ATK_DQ_B0_PI_INIT) |
                                     P_Fld(ucdq_pi, TX_ATK_SET0_TX_ATK_DQ_B1_PI_INIT) |
                                     P_Fld(ucdq_pi, TX_ATK_SET0_TX_ATK_DQM_B0_PI_INIT) |
                                     P_Fld(ucdq_pi, TX_ATK_SET0_TX_ATK_DQM_B1_PI_INIT));
    }
    else if (calType == TX_DQ_DQS_MOVE_DQM_ONLY)
    {
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_SET1), 0x1, TX_ATK_SET1_TX_ATK_DQM_PI_EN);
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_SET0),
                                     P_Fld(ucdq_pi, TX_ATK_SET0_TX_ATK_DQM_B0_PI_INIT) |
                                     P_Fld(ucdq_pi, TX_ATK_SET0_TX_ATK_DQM_B1_PI_INIT));
    }
    else
    {
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_SET1), 0x1, TX_ATK_SET1_TX_ATK_DQ_PI_EN);
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_SET0),
                                     P_Fld(ucdq_pi, TX_ATK_SET0_TX_ATK_DQ_B0_PI_INIT) |
                                     P_Fld(ucdq_pi, TX_ATK_SET0_TX_ATK_DQ_B1_PI_INIT));
    }

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_CTRL1), 0, MISC_CTRL1_R_DMARPIDQ_SW);
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_SET1),
            P_Fld(u1PI_Len, TX_ATK_SET1_TX_ATK_PI_LEN) |
            P_Fld(pi_thrd, TX_ATK_SET1_TX_ATK_PASS_PI_THRD));
#if (fcFOR_CHIP_ID == fcIPM)
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_SET1), early_break, TX_ATK_SET1_TX_ATK_EARLY_BREAK);
#endif

    {
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU_TX_SET0),
                P_Fld(0x3, SHU_TX_SET0_TXOEN_AUTOSET_OFFSET) |
                P_Fld(0x1, SHU_TX_SET0_TXOEN_AUTOSET_EN));
    }

#if TX_AUTO_K_DEBUG_ENABLE
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_SET1), 0x1, TX_ATK_SET1_TX_ATK_DBG_EN);
#endif
}

static void Tx_Auto_K_complete_check(DRAMC_CTX_T *p)
{
    U32 u4loop_count = 0;

    while ((u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_RESULT8), TX_ATK_RESULT8_TX_ATK_DONE) != 0x1))
    {
        mcDELAY_US(1);
        u4loop_count++;
        //mcSHOW_DBG_MSG(("Wait! TX auto K is not done!\n"));
        if (u4loop_count > 100000)
        {
            mcSHOW_ERR_MSG(("Error! TX auto K is not done!\n"));
            break;
        }
    }

    if ((u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_RESULT8), TX_ATK_RESULT8_TX_ATK_FIND_PW) == 0x1))
    {
        vSetCalibrationResult(p, DRAM_CALIBRATION_TX_PERBIT, DRAM_OK);
        mcSHOW_DBG_MSG(("Tx auto K, all bit find passs window\n"));
    }
    else
    {
        mcSHOW_ERR_MSG(("Error! TX auto K is fail!\n"));
    }
}

static void Tx_Auto_K_Clear(DRAMC_CTX_T *p)
{
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_SET1), 0x0, TX_ATK_SET1_TX_ATK_TRIG);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_TX_SET0), 0x0, SHU_TX_SET0_TXOEN_AUTOSET_EN);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_CTRL1), 0x1, MISC_CTRL1_R_DMARPIDQ_SW);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_SET1), 0x0, TX_ATK_SET1_TX_ATK_DBG_EN);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_SET1), 0x1, TX_ATK_SET1_TX_ATK_CLR);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_SET1), 0x0, TX_ATK_SET1_TX_ATK_CLR);
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_SET1),
                                 P_Fld(0x0, TX_ATK_SET1_TX_ATK_PI_LEN) |
                                 P_Fld(0x0, TX_ATK_SET1_TX_ATK_DQ_PI_EN) |
                                 P_Fld(0x0, TX_ATK_SET1_TX_ATK_DQM_PI_EN));
#if ENABLE_PA_IMPRO_FOR_TX_AUTOK
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_CG_SET0), 0x0, TX_CG_SET0_TX_ATK_CLKRUN);
#endif
}

#if TX_AUTO_K_WORKAROUND
static void Tx_Auto_K_DQM_Workaround(DRAMC_CTX_T *p)
{
    //U32 u4DQM_MCK, u4DQM_UI, u4DQM_PI_B0, u4DQM_PI_B1;

    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ1), u4DQM_MCK_RK1_backup);
    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ3), u4DQM_UI_RK1_backup);
    vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_DQ0), u4DQM_PI_RK1_backup[0]);
    vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_DQ0), u4DQM_PI_RK1_backup[1]);
}
static void Tx_Auto_K_DQ_Workaround(DRAMC_CTX_T *p)
{
    //U32 u4DQ_MCK, u4DQ_UI, u4DQ_PI_B0, u4DQ_PI_B1;

    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ0), u4DQ_MCK_RK1_backup);
    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ2), u4DQ_UI_RK1_backup);
    vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_DQ0), u4DQ_PI_RK1_backup[0]);
    vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_DQ0), u4DQ_PI_RK1_backup[1]);
}
#endif

#if TX_AUTO_K_DEBUG_ENABLE
static void Tx_Auto_K_Debug_Message(DRAMC_CTX_T *p, U8 u1PI_Len)
{
    U8 u1bit_num = 0, u1BitIdx;
    U16 u2Length = 0, u2Length_max = 0;
    U32 u4status;
    U32 u4status_bit[4][DQ_DATA_WIDTH];

    if (u1PI_Len == 0)
        u2Length_max = 48;
    else
        u2Length_max = 32 * (1 + u1PI_Len);

    for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
    {
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_SET1), u1BitIdx, TX_ATK_SET1_TX_ATK_DBG_BIT_SEL);

        u4status_bit[0][u1BitIdx] = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_DBG_BIT_STATUS1));
        u4status_bit[1][u1BitIdx] = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_DBG_BIT_STATUS2));
        u4status_bit[2][u1BitIdx] = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_DBG_BIT_STATUS3));
        u4status_bit[3][u1BitIdx] = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_DBG_BIT_STATUS4));
    }

    mcSHOW_DBG_MSG2(("Debug TX DQ PASS/FAIL status:\n"));

    for (u2Length = 0; u2Length < u2Length_max; u2Length++)
    {
        mcSHOW_DBG_MSG2(("Delay=%3d ", u2Length));

        for (u1bit_num = 0; u1bit_num < p->data_width; u1bit_num++)
        {
            u4status = ((u4status_bit[u2Length / 32][u1bit_num] >> (u2Length % 32)) & 0x1);

            if (u4status == 0)
            {
                mcSHOW_DBG_MSG2(("x"));
            }
            else
            {
                mcSHOW_DBG_MSG2(("o"));
            }

            if (u1bit_num == (p->data_width - 1))
            {
                mcSHOW_DBG_MSG2((" \n"));
            }
        }
    }

    //mcSHOW_DBG_MSG(("Debug DQ PASS(1)/FAIL(0) bit: %d, STATUS1: 0x%x, STATUS2: 0x%x, STATUS3: 0x%x, STATUS4: 0x%x,\n",u1BitIdx,u4status_bit[0][u1BitIdx],u4status_bit[1][u1BitIdx],u4status_bit[2][u1BitIdx],u4status_bit[3][u1BitIdx]));
}
#endif
#endif

#if TX_K_DQM_WITH_WDBI
void vSwitchWriteDBISettings(DRAMC_CTX_T *p, U8 u1OnOff)
{
    S8 u1TXShiftMCK;

    u1TXShiftMCK = (u1OnOff)? -1: 1;
    DramcWriteShiftMCKForWriteDBI(p, u1TXShiftMCK);

    SetDramModeRegForWriteDBIOnOff(p, p->dram_fsp, u1OnOff);
    DramcWriteDBIOnOff(p, u1OnOff);

    #if (TX_AUTO_K_SUPPORT && TX_AUTO_K_WORKAROUND)
    if (p->rank == RANK_1)
    {
        u4DQ_MCK_RK1_backup = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ0));
        u4DQ_UI_RK1_backup = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ2));
        u4DQ_PI_RK1_backup[0] = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_DQ0));
        u4DQ_PI_RK1_backup[1] = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_DQ0));
    }
    #endif
}
#endif

DRAM_STATUS_T DramcTxWindowPerbitCal(DRAMC_CTX_T *p, DRAM_TX_PER_BIT_CALIBRATION_TYTE_T calType, U8 u1VrefScanEnable, u8 isAutoK)
{
    U8 u1BitTemp, u1BitIdx, u1ByteIdx, u1RankIdx, backup_rank;
    U32 uiFinishCount;
    PASS_WIN_DATA_T WinPerBit[DQ_DATA_WIDTH], VrefWinPerBit[DQ_DATA_WIDTH], FinalWinPerBit[DQ_DATA_WIDTH];

    U16 uiDelay, u2DQDelayBegin, u2DQDelayEnd, u2DQDelayStep = 1;

    U8 ucdq_pi, ucdq_ui_small, ucdq_ui_large, ucdq_oen_ui_small, ucdq_oen_ui_large;
    U8 ucdq_ui_small_reg_value, u1UpdateRegUI;

    U8 ucdq_reg_pi[DQS_BYTE_NUMBER], ucdq_reg_ui_large[DQS_BYTE_NUMBER], ucdq_reg_ui_small[DQS_BYTE_NUMBER];
    U8 ucdq_reg_oen_ui_large[DQS_BYTE_NUMBER], ucdq_reg_oen_ui_small[DQS_BYTE_NUMBER];

    U8 ucdq_reg_dqm_pi[DQS_BYTE_NUMBER] = {0}, ucdq_reg_dqm_ui_large[DQS_BYTE_NUMBER] = {0}, ucdq_reg_dqm_ui_small[DQS_BYTE_NUMBER] = {0};
    U8 ucdq_reg_dqm_oen_ui_large[DQS_BYTE_NUMBER] = {0}, ucdq_reg_dqm_oen_ui_small[DQS_BYTE_NUMBER] = {0};

    #if 1
    U16 u2DQM_Delay;
    U16 u2Center_min[DQS_BYTE_NUMBER] = {0}, u2Center_max[DQS_BYTE_NUMBER] = {0};
    #endif
    U8 u1EnableDelayCell = 0;
    U16 u2DelayCellOfst[DQ_DATA_WIDTH] = {0};
    U32 u4err_value, u4fail_bit;
    U16 u2FinalRange = 0, u2FinalVref;
    U16 u2VrefLevel, u2VrefBegin = 0, u2VrefEnd = 0, u2VrefStep;
    U16 u2TempWinSum, u2MaxWindowSum = 0;//, u2tx_window_sum[LP4_TX_VREF_DATA_NUM]={0};
    //U32 u4TempRegValue;
    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 TX_AUTO_K_SUPPORT
    U8 u1PI_Len, u1dq_shift;
    U32 PwMaxInitReg[4] = {DRAMC_REG_TX_ATK_RESULT0, DRAMC_REG_TX_ATK_RESULT1, DRAMC_REG_TX_ATK_RESULT2, DRAMC_REG_TX_ATK_RESULT3};
    U32 PwMaxLenReg[4] = {DRAMC_REG_TX_ATK_RESULT4, DRAMC_REG_TX_ATK_RESULT5, DRAMC_REG_TX_ATK_RESULT6, DRAMC_REG_TX_ATK_RESULT7};
    U32 u4Length = 0;
    #if TX_AUTO_K_WORKAROUND
    U8 u1backup_Rank = 0;
    #endif
    #if TX_AUTO_K_WORKAROUND
    U32 u4RegBackupAddress[] =
    {
        (DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ0)),
        (DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ2)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_DQ0)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_DQ0)),
        (DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ1)),
        (DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ3)),
    };
    #endif
    #endif
#if 0
    if(0)//(p->channel==CHANNEL_D)
    {
        ucdq_reg_ui_large[0] = ucdq_reg_ui_large[1] = 2;
        ucdq_reg_ui_small[0] = ucdq_reg_ui_small[1] = 1;
        ucdq_reg_oen_ui_large[0] = ucdq_reg_oen_ui_large[1] = 1;
        ucdq_reg_oen_ui_small[0] = ucdq_reg_oen_ui_small[1] = 6;
        ucdq_reg_pi[0] = ucdq_reg_pi[1] = 20;


        ucdq_reg_dqm_ui_large[0] = ucdq_reg_dqm_ui_large[1] = 2;
        ucdq_reg_dqm_ui_small[0] = ucdq_reg_dqm_ui_small[1] = 1;
        ucdq_reg_dqm_oen_ui_large[0] = ucdq_reg_dqm_oen_ui_large[1] = 1;
        ucdq_reg_dqm_oen_ui_small[0] = ucdq_reg_dqm_oen_ui_small[1] = 6;
        ucdq_reg_dqm_pi[0] = ucdq_reg_dqm_pi[1] = 20;

        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);
        return;
    }
#endif
    //mcDUMP_REG_MSG(("\n[dumpRG] DramcTxWindowPerbitCal\n"));
#if VENDER_JV_LOG
    if (calType == TX_DQ_DQS_MOVE_DQ_ONLY)
        vPrintCalibrationBasicInfo_ForJV(p);
#else
        vPrintCalibrationBasicInfo(p);
#endif
    mcSHOW_DBG_MSG(("[TxWindowPerbitCal] caltype:%d Autok:%d\n", calType, isAutoK));

    backup_rank = u1GetRank(p);

    TXPerbitCalibrationInit(p, calType);
    TXScanRange_PI(p, calType, &u2DQDelayBegin, &u2DQDelayEnd);
    TXScanRange_Vref(p, u1VrefScanEnable, &u2FinalRange, &u2VrefBegin, &u2VrefEnd, &u2VrefStep);


    vSetCalibrationResult(p, DRAM_CALIBRATION_TX_PERBIT, DRAM_FAIL);

    if (isAutoK)
    {
    #if TX_AUTO_K_SUPPORT
    //CKEFixOnOff(p, p->rank, CKE_FIXON, TO_ONE_CHANNEL);


    u1UpdateRegUI = 1;
    uiDelay = u2DQDelayBegin;
    u1PI_Len = 3;
    TxWinTransferDelayToUIPI(p, uiDelay, 0, &ucdq_ui_large, &ucdq_ui_small, &ucdq_pi, &ucdq_oen_ui_large, &ucdq_oen_ui_small);

    for (u1ByteIdx = 0; u1ByteIdx < DQS_BYTE_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 TX_AUTO_K_WORKAROUND
    if (p->rank == 1)
    {
        u1backup_Rank = 1;
        p->rank = 0;
        DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress) / sizeof(U32));
    }
    #endif

    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);
        mcSHOW_DBG_MSG2(("TX Auto-K set begin delay DQ MCK: %d, UI: %d, PI: %d\n", ucdq_reg_ui_large[0], ucdq_reg_ui_small[0], ucdq_reg_pi[0]));

        #if TX_AUTO_K_WORKAROUND
        if ((calType == TX_DQ_DQS_MOVE_DQ_ONLY) && (u1backup_Rank == 1))
            Tx_Auto_K_DQM_Workaround(p);
        #endif
    }
    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);

        mcSHOW_DBG_MSG2(("TX Auto-K set begin delay DQM MCK: %d, UI: %d, PI: %d\n", ucdq_reg_dqm_ui_large[0], ucdq_reg_dqm_ui_small[0], ucdq_reg_dqm_pi[0]));

        #if TX_AUTO_K_WORKAROUND
        if ((calType == TX_DQ_DQS_MOVE_DQM_ONLY) && (u1backup_Rank == 1))
            Tx_Auto_K_DQ_Workaround(p);
        #endif
    }

    #if TX_AUTO_K_WORKAROUND
    if (u1backup_Rank == 1)
        p->rank = 1;
    #endif


    #endif
    }
    else
    {
    if (vGet_DDR_Loop_Mode(p) == SEMI_OPEN_LOOP_MODE)
        u2DQDelayStep = (1 << 3);
    else if (vGet_DDR_Loop_Mode(p) == OPEN_LOOP_MODE)
        u2DQDelayStep = (1 << 4);
    else if (calType == TX_DQ_DQS_MOVE_DQ_DQM)
        u2DQDelayStep = 2;
    else
        u2DQDelayStep = 1;

    #if (FOR_DV_SIMULATION_USED == 1)
        u2DQDelayStep = (vGet_DDR_Loop_Mode(p) == OPEN_LOOP_MODE) ? 16 : 8;
    #endif
    }

#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));
#endif

    #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
    if (p->femmc_Ready == 1 && (p->Bypass_TXWINDOW))
    {
        for (u1ByteIdx = 0; u1ByteIdx < DQS_BYTE_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_FAST_K);
    }
    else
    #endif
    {
#if ENABLE_K_WITH_WORST_SI_UI_SHIFT
        DramcEngine2Init(p, p->test2_1, p->test2_2, p->test_pattern | 0x80, 0, TE_UI_SHIFT);
#else
        DramcEngine2Init(p, p->test2_1, p->test2_2, TEST_XTALK_PATTERN, 0, TE_NO_UI_SHIFT);
#endif

        for (u2VrefLevel = u2VrefBegin; u2VrefLevel <= u2VrefEnd; u2VrefLevel += u2VrefStep)
        {

            if (u1VrefScanEnable)
            {
                #if (!REDUCE_LOG_FOR_PRELOADER)
                mcSHOW_DBG_MSG2(("\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\tLP4 TX VrefRange %d, VrefLevel=%d\n", u2FinalRange, u2VrefLevel));
                }
                #endif

                DramcTXSetVref(p, u2FinalRange, u2VrefLevel);
            }
            else
            {
                mcSHOW_DBG_MSG(("\n\tTX Vref Scan disable\n"));
            }


            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;
            }

            if (isAutoK)
            {
            #if TX_AUTO_K_SUPPORT
            Tx_Auto_K_Init(p, calType, ucdq_pi, u1PI_Len);
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_SET1), 0x1, TX_ATK_SET1_TX_ATK_TRIG);
            #endif
            }
            else
            {

            for (uiDelay = u2DQDelayBegin; uiDelay < u2DQDelayEnd; uiDelay += u2DQDelayStep)
            {
                TxWinTransferDelayToUIPI(p, uiDelay, 0, &ucdq_ui_large, &ucdq_ui_small, &ucdq_pi, &ucdq_oen_ui_large, &ucdq_oen_ui_small);


                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_BYTE_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);
                }

                u4err_value = 0;
#if ENABLE_K_WITH_WORST_SI_UI_SHIFT

                u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, p->test_pattern);
#else

                DramcEngine2SetPat(p, TEST_AUDIO_PATTERN, 0, 0, TE_NO_UI_SHIFT);
                u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, TEST_AUDIO_PATTERN);
                DramcEngine2SetPat(p, TEST_XTALK_PATTERN, 0, 1, TE_NO_UI_SHIFT);
                u4err_value |= DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, TEST_XTALK_PATTERN);
#endif


                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_MSG3(("%d |%d %d %d|[0]", uiDelay, ucdq_ui_large, ucdq_ui_small, ucdq_pi));
                    }
                    #else
                    mcSHOW_DBG_MSG3(("Delay=%3d |%2d %2d %3d| 0x%8x [0]", uiDelay, ucdq_ui_large, ucdq_ui_small, ucdq_pi, u4err_value));
                    #endif
                }


                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_MSG3((" "));
                            }

                            if (u4fail_bit == 0)
                            {
                                 mcSHOW_DBG_MSG3(("o"));
                            }
                            else
                            {
                                mcSHOW_DBG_MSG3(("x"));
                            }
                        }
                    }

                    if (WinPerBit[u1BitIdx].first_pass == PASS_RANGE_NA)
                    {
                        if (u4fail_bit == 0)
                        {
                            WinPerBit[u1BitIdx].first_pass = uiDelay;

                            #if TX_TDQS2DQ_PRE_CAL
                            if ((u1IsLP4Div4DDR800(p) == FALSE) && (calType == TX_DQ_DQS_MOVE_DQ_ONLY) && (u1VrefScanEnable == FALSE))
                            {
                                if (u2DQS2DQ_Pre_Cal[p->channel][p->rank][vGet_Div_Mode(p)] == 0)
                                {
                                    u2DQS2DQ_Pre_Cal[p->channel][p->rank][vGet_Div_Mode(p)] = ((uiDelay - u2DQDelayBegin)* 1000) / 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)
                        {
                            WinPerBit[u1BitIdx].last_pass = uiDelay - u2DQDelayStep;
                        }
                        else if (uiDelay >= (u2DQDelayEnd - u2DQDelayStep))
                        {
                            WinPerBit[u1BitIdx].last_pass = uiDelay;
                            mcSHOW_ERR_MSG(("\nTx last pass not found!!\n"));
                            #if __ETT__
                                while(1);
                            #endif
                        }

                        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)));
                                }


                                if (((WinPerBit[u1BitIdx].last_pass - WinPerBit[u1BitIdx].first_pass) > TX_PASS_WIN_CRITERIA)
                                    ||((u2DQDelayStep>=16) && (WinPerBit[u1BitIdx].first_pass!=PASS_RANGE_NA)))
                                    uiFinishCount |= (1 << u1BitIdx);


                                VrefWinPerBit[u1BitIdx].first_pass = WinPerBit[u1BitIdx].first_pass;
                                VrefWinPerBit[u1BitIdx].last_pass = WinPerBit[u1BitIdx].last_pass;
                            }


                            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_MSG3((" [MSB]\n"));
                    }
                }


                if (uiFinishCount == 0xffff)
                {
                    vSetCalibrationResult(p, DRAM_CALIBRATION_TX_PERBIT, DRAM_OK);
                    #if !REDUCE_LOG_FOR_PRELOADER
                    #ifdef ETT_PRINT_FORMAT
                    mcSHOW_DBG_MSG3(("TX calibration finding left boundary early break. PI DQ delay=0x%B\n", uiDelay));
                    #else
                    mcSHOW_DBG_MSG3(("TX calibration finding left boundary early break. PI DQ delay=0x%2x\n", uiDelay));
                    #endif
                    #endif
                    break;
                }
            }
            }

            if (isAutoK)
            {
            #if TX_AUTO_K_SUPPORT
                Tx_Auto_K_complete_check(p);
                #if TX_AUTO_K_DEBUG_ENABLE
                Tx_Auto_K_Debug_Message(p, u1PI_Len);
                #endif
            #endif
            }

            u1min_winsize = 0xff;
            u1min_bit = 0xff;
            for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
            {
                if (isAutoK)
                {
                #if TX_AUTO_K_SUPPORT
                u1dq_shift = ((u1BitIdx % 4) * 8);
                VrefWinPerBit[u1BitIdx].first_pass = u2DQDelayBegin - ucdq_pi + ((u4IO32Read4B(DRAMC_REG_ADDR(PwMaxInitReg[u1BitIdx / 4])) & (0xff << u1dq_shift)) >> u1dq_shift);
                VrefWinPerBit[u1BitIdx].last_pass = ((u4IO32Read4B(DRAMC_REG_ADDR(PwMaxLenReg[u1BitIdx / 4])) & (0xff << u1dq_shift)) >> u1dq_shift) + VrefWinPerBit[u1BitIdx].first_pass;
                VrefWinPerBit[u1BitIdx].win_size = ((u4IO32Read4B(DRAMC_REG_ADDR(PwMaxLenReg[u1BitIdx / 4])) & (0xff << u1dq_shift)) >> u1dq_shift);

                if (u1PI_Len == 0)
                    u4Length = 48;
                else
                    u4Length = 32 * (1 + u1PI_Len);

                if ((VrefWinPerBit[u1BitIdx].first_pass == (int)(u2DQDelayBegin - ucdq_pi)) || (VrefWinPerBit[u1BitIdx].last_pass == (int)(u2DQDelayBegin + u4Length)))
                {
                    mcSHOW_ERR_MSG(("Error! Probably miss pass window!\n"));
                }

                mcSHOW_DBG_MSG(("TX DQ bit %d, first pass: %d, last pass: %d\n", u1BitIdx, VrefWinPerBit[u1BitIdx].first_pass, VrefWinPerBit[u1BitIdx].last_pass));
                #else
                //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 + u2DQDelayStep;
                #endif
                }
                else
                {
                    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 + u2DQDelayStep;
                }

                if (VrefWinPerBit[u1BitIdx].win_size < u1min_winsize)
                {
                    u1min_bit = u1BitIdx;
                    u1min_winsize = VrefWinPerBit[u1BitIdx].win_size;
                }

                u2TempWinSum += VrefWinPerBit[u1BitIdx].win_size;

                #if VENDER_JV_LOG
                if (calType == TX_DQ_DQS_MOVE_DQ_ONLY)
                {
                    mcSHOW_DBG_MSG5(("TX Bit%d, %d%%\n", u1BitIdx, (VrefWinPerBit[u1BitIdx].win_size * 100 + 31) / 32));
                }
                #endif



                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
            }


            #if (__ETT__ || PIN_CHECK_TOOL)
            if (u1VrefScanEnable == 0)
            {
                //mcSHOW_DBG_MSG(("\n\tCH=%d, VrefRange= %d, VrefLevel = %d\n", p->channel, u2FinalRange, u2VrefLevel));
                TxPrintWidnowInfo(p, VrefWinPerBit);
            }
            #endif

            if (u1VrefScanEnable == 1)
            {
                if (u2TempWinSum > u2MaxWindowSum)
                    u2MaxWindowSum = u2TempWinSum;

                VrefInfo[u1VrefIdx].u2VrefUsed = u2VrefLevel;
                VrefInfo[u1VrefIdx].u1WorseBitWinSize_byVref = u1min_winsize;
                VrefInfo[u1VrefIdx].u1WorseBitIdx_byVref = u1min_bit;
                VrefInfo[u1VrefIdx].u2WinSum_byVref = u2TempWinSum;
                u1VrefIdx ++;
            }

            #if TX_AUTO_K_SUPPORT
            if (isAutoK)
                Tx_Auto_K_Clear(p);
            #endif

            #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)) && (u1min_winsize > TX_PASS_WIN_CRITERIA))
            #endif
            {
                mcSHOW_DBG_MSG(("\nTX Vref early break, caculate TX vref\n"));
                break;
            }

            #if TX_AUTO_K_SUPPORT
            Tx_Auto_K_Clear(p);
            #endif
        }

        DramcEngine2End(p);

        #if (TX_AUTO_K_SUPPORT && TX_AUTO_K_WORKAROUND)
        if ((isAutoK) && (p->rank == RANK_1))
        {
            vSetRank(p, RANK_0);
            DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress) / sizeof(U32));
            vSetRank(p, backup_rank);
        }
        #endif

        if (u1VrefScanEnable == 0)
        {

            for (u1ByteIdx = 0; u1ByteIdx < DQS_BYTE_NUMBER; u1ByteIdx++)
            {
                #if 1
                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 ((calType == TX_DQ_DQS_MOVE_DQ_ONLY) && (u1VrefScanEnable == 0))
                    {
                        gFinalTXPerbitWin[p->channel][p->rank][u1BitTemp] = FinalWinPerBit[u1BitTemp].win_size;
                    }
                    #endif
                }
            }
        }
    }


    if (u1VrefScanEnable)
    {
        #if SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_VREF_CAL
        if (p->femmc_Ready == 1 && (p->Bypass_TXWINDOW))
        {
            u2FinalVref = p->pSavetimeData->u1TxWindowPerbitVref_Save[p->channel][p->rank];
        }
        else
        #endif
        {
            u2FinalVref = TxChooseVref(p, VrefInfo, u1VrefIdx);
        }

        TXSetFinalVref(p, u2FinalRange, u2FinalVref);
        return DRAM_OK;
    }

#ifdef FOR_HQA_TEST_USED

    if (calType == TX_DQ_DQS_MOVE_DQ_ONLY)
    {
        gFinalTXPerbitWin_min_max[p->channel][p->rank] = u1min_winsize;
        if(u1min_winsize<16)
        {
            mcSHOW_ERR_MSG(("[WARNING] Smaller TX win !!\n"));
            #if CHECK_HQA_CRITERIA
            while(1);
            #endif
        }
    }
#endif


    if ((calType == TX_DQ_DQS_MOVE_DQ_ONLY) && (p->frequency >= 1333) && (p->u2DelayCellTimex100 != 0))
    {
        u1EnableDelayCell = 1;
        mcSHOW_DBG_MSG(("[TX_PER_BIT_DELAY_CELL] DelayCellTimex100 =%d/100 ps\n", p->u2DelayCellTimex100));
        //mcDUMP_REG_MSG(("[TX_PER_BIT_DELAY_CELL] DelayCellTimex100 =%d/100 ps\n", p->u2DelayCellTimex100));
    }


    for (u1ByteIdx = 0; u1ByteIdx < DQS_BYTE_NUMBER; u1ByteIdx++)
    {
        mcSHOW_DBG_MSG((" == TX Byte %d ==\n", u1ByteIdx));
        //mcDUMP_REG_MSG((" == TX Byte %d ==\n", u1ByteIdx));
        u2DQM_Delay = ((u2Center_min[u1ByteIdx] + u2Center_max[u1ByteIdx]) >> 1);

        if (u1EnableDelayCell == 0)
        {
            uiDelay = u2DQM_Delay;
        }
        else
        {
            uiDelay = u2Center_min[u1ByteIdx];


            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)
                {
                    u2DelayCellOfst[u1BitTemp] = (u1PIDiff * 100000000 / (DDRPhyGetRealFreq(p)<< 6)) / p->u2DelayCellTimex100;
                    mcSHOW_DBG_MSG(("u2DelayCellOfst[%d]=%d cells (%d PI)\n", u1BitTemp, u2DelayCellOfst[u1BitTemp], u1PIDiff));
                    //mcDUMP_REG_MSG(("u2DelayCellOfst[%d]=%d cells (%d PI)\n", u1BitTemp, u2DelayCellOfst[u1BitTemp], u1PIDiff));


                    if(u2DelayCellOfst[u1BitTemp]>255)
                    {
                        mcSHOW_DBG_MSG(("[WARNING] TX DQ%d delay cell %d >255, adjust to 255 cell\n", u1BitIdx, u2DelayCellOfst[u1BitTemp]));
                        u2DelayCellOfst[u1BitTemp] =255;
                    }
                }
                else
                {
                    mcSHOW_ERR_MSG(("Error: Cell time (p->u2DelayCellTimex100) is 0 \n"));
                    break;
                }
            }

        }

        TxWinTransferDelayToUIPI(p, 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, u2DQM_Delay, 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]));
            /*mcDUMP_REG_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]));*/
        }

        //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)\n",
                    u2DQM_Delay, 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]));
            /*mcDUMP_REG_MSG(("Update DQM dly =%d (%d ,%d, %d)  DQM OEN =(%d ,%d)\n",
                    u2DQM_Delay, 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)
        {
            HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT1, "TX_Window_Center_", "BYTE", u1ByteIdx, uiDelay, NULL);

            for (u1BitIdx = u1ByteIdx*8; u1BitIdx < u1ByteIdx*8+8; 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 TX_K_DQM_WITH_WDBI
        if ((p->DBI_W_onoff[p->dram_fsp]!=DBI_ON))
        {
            if (calType == TX_DQ_DQS_MOVE_DQ_ONLY && u1VrefScanEnable == FALSE)
            {
                HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0, "TX_Window_Center_", "DQM", u1ByteIdx, u2DQM_Delay, NULL);
            }
        }
        else
        {
            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, u2DQM_Delay, NULL);
        }
        }
#else
        if (calType == TX_DQ_DQS_MOVE_DQ_ONLY && u1VrefScanEnable == FALSE)
        {
            HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0, "TX_Window_Center_", "DQM", u1ByteIdx, u2DQM_Delay, NULL);
        }
#endif


#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

    }


#if REG_ACCESS_PORTING_DGB
    RegLogEnable = 1;
#endif


        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 (u1EnableDelayCell)
             {
                vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_TXDLY0),
                           P_Fld(u2DelayCellOfst[3], SHU_R0_B0_TXDLY0_TX_ARDQ3_DLY_B0)
                         | P_Fld(u2DelayCellOfst[2], SHU_R0_B0_TXDLY0_TX_ARDQ2_DLY_B0)
                         | P_Fld(u2DelayCellOfst[1], SHU_R0_B0_TXDLY0_TX_ARDQ1_DLY_B0)
                         | P_Fld(u2DelayCellOfst[0], SHU_R0_B0_TXDLY0_TX_ARDQ0_DLY_B0));
                 vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_TXDLY1),
                           P_Fld(u2DelayCellOfst[7], SHU_R0_B0_TXDLY1_TX_ARDQ7_DLY_B0)
                         | P_Fld(u2DelayCellOfst[6], SHU_R0_B0_TXDLY1_TX_ARDQ6_DLY_B0)
                         | P_Fld(u2DelayCellOfst[5], SHU_R0_B0_TXDLY1_TX_ARDQ5_DLY_B0)
                         | P_Fld(u2DelayCellOfst[4], SHU_R0_B0_TXDLY1_TX_ARDQ4_DLY_B0));
                 vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_TXDLY0),
                           P_Fld(u2DelayCellOfst[11], SHU_R0_B1_TXDLY0_TX_ARDQ3_DLY_B1)
                         | P_Fld(u2DelayCellOfst[10], SHU_R0_B1_TXDLY0_TX_ARDQ2_DLY_B1)
                         | P_Fld(u2DelayCellOfst[9], SHU_R0_B1_TXDLY0_TX_ARDQ1_DLY_B1)
                         | P_Fld(u2DelayCellOfst[8], SHU_R0_B1_TXDLY0_TX_ARDQ0_DLY_B1));
                 vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_TXDLY1),
                           P_Fld(u2DelayCellOfst[15], SHU_R0_B1_TXDLY1_TX_ARDQ7_DLY_B1)
                         | P_Fld(u2DelayCellOfst[14], SHU_R0_B1_TXDLY1_TX_ARDQ6_DLY_B1)
                         | P_Fld(u2DelayCellOfst[13], SHU_R0_B1_TXDLY1_TX_ARDQ5_DLY_B1)
                         | P_Fld(u2DelayCellOfst[12], SHU_R0_B1_TXDLY1_TX_ARDQ4_DLY_B1));
             }
            #if ENABLE_TX_TRACKING
            TXUpdateTXTracking(p, calType, ucdq_reg_pi, ucdq_reg_dqm_pi);
            #endif
        }

        vSetRank(p, backup_rank);

        if (isAutoK)
        {
        #if TX_AUTO_K_SUPPORT
            #if TX_AUTO_K_WORKAROUND
            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TX_ATK_SET0),
                                 P_Fld(ucdq_reg_pi[0], TX_ATK_SET0_TX_ATK_DQ_B0_PI_INIT) |
                                 P_Fld(ucdq_reg_pi[1], TX_ATK_SET0_TX_ATK_DQ_B1_PI_INIT) |
                                 P_Fld(ucdq_reg_dqm_pi[0], TX_ATK_SET0_TX_ATK_DQM_B0_PI_INIT) |
                                 P_Fld(ucdq_reg_dqm_pi[1], TX_ATK_SET0_TX_ATK_DQM_B1_PI_INIT));
            #endif
        #endif
        }

#if REG_ACCESS_PORTING_DGB
    RegLogEnable = 0;
#endif

#if (TX_AUTO_K_SUPPORT && TX_AUTO_K_WORKAROUND)
    if ((isAutoK) && (p->rank == RANK_1) && (calType == TX_DQ_DQS_MOVE_DQ_DQM))
    {
        u4DQM_MCK_RK1_backup = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ1));
        u4DQM_UI_RK1_backup = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ3));
        u4DQM_PI_RK1_backup[0] = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_DQ0));
        u4DQM_PI_RK1_backup[1] = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_DQ0));
        u4DQ_MCK_RK1_backup = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ0));
        u4DQ_UI_RK1_backup = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ2));
        u4DQ_PI_RK1_backup[0] = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_DQ0));
        u4DQ_PI_RK1_backup[1] = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_DQ0));
    }
#endif

    mcSHOW_DBG_MSG4(("[TxWindowPerbitCal] Done\n\n"));

    #if 0
    vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_PADCTL4), 1, PADCTL4_CKEFIXON);
    #endif

    return DRAM_OK;
}

#endif

#if ENABLE_EYESCAN_GRAPH
void Dramc_K_TX_EyeScan_Log(DRAMC_CTX_T *p)
{
    U8 ucindex, u1BitIdx, u1ByteIdx;
    U8 ii, backup_rank, u1PrintWinData, 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
    U16 u2Center_min[DQS_BYTE_NUMBER],u2Center_max[DQS_BYTE_NUMBER];
    #endif

    U16 TXPerbitWin_min_max = 0;
    U32 min_bit, min_winsize;

    U16 u2FinalVref=0xd;
    U16 u2FinalRange=0;

    U8 EyeScan_index[DQ_DATA_WIDTH];

    U16 backup_u1MR14Value;
    U8 u1pass_in_this_vref_flag[DQ_DATA_WIDTH];

    U8 u1MCK2UI, u1UI2PI;

    U32 u4RegBackupAddress[] =
    {
        (DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ0)),
        (DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ2)),
        (DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ1)),
        (DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ3)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_DQ0)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_DQ0)),
    };

    //if (gTX_EYE_Scan_only_higheset_freq_flag==1 && p->frequency != u2DFSGetHighestFreq(p)) return;


    DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));

    backup_u1MR14Value = u1MR14Value[p->channel][p->rank][p->dram_fsp];

    if (gFinalTXVrefDQ[p->channel][p->rank] ==0)
        gFinalTXVrefDQ[p->channel][p->rank] = u1MR14Value[p->channel][p->rank][p->dram_fsp];


    for(u1vrefidx=0; u1vrefidx<=VREF_VOLTAGE_TABLE_NUM_LP5-1;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;
        }
    }


    u1MCK2UI = u1MCK2UI_DivShift(p);

    //if (vGet_DDR800_Mode(p) == DDR800_CLOSE_LOOP)
    //    u1UI2PI = 6;
    //else
        u1UI2PI = 5;


    for(u1ByteIdx=0; u1ByteIdx < DQS_BYTE_NUMBER; u1ByteIdx++)
    {
        if (u1ByteIdx == 0)
        {
            tx_pi_delay[u1ByteIdx] = (u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ0), SHURK_SELPH_DQ0_TXDLY_DQ0)<<(u1MCK2UI+u1UI2PI)) +
                          (u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ2), SHURK_SELPH_DQ2_DLY_DQ0)<<u1UI2PI) +
                          u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_DQ0), SHU_R0_B0_DQ0_SW_ARPI_DQ_B0);

            tx_dqm_pi_delay[u1ByteIdx] = (u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ1), SHURK_SELPH_DQ1_TXDLY_DQM0)<<(u1MCK2UI+u1UI2PI)) +
                              (u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ3), SHURK_SELPH_DQ3_DLY_DQM0)<<u1UI2PI) +
                              u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_DQ0), SHU_R0_B0_DQ0_SW_ARPI_DQM_B0);
        }
        else
        {
            tx_pi_delay[u1ByteIdx] = (u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ0), SHURK_SELPH_DQ0_TXDLY_DQ1)<<(u1MCK2UI+u1UI2PI)) +
                          (u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ2), SHURK_SELPH_DQ2_DLY_DQ1)<<u1UI2PI) +
                          u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_DQ0), SHU_R0_B1_DQ0_SW_ARPI_DQ_B1);

            tx_dqm_pi_delay[u1ByteIdx] = (u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ1), SHURK_SELPH_DQ1_TXDLY_DQM1)<<(u1MCK2UI+u1UI2PI)) +
                              (u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ3), SHURK_SELPH_DQ3_DLY_DQM1)<<u1UI2PI) +
                              u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_DQ0), SHU_R0_B1_DQ0_SW_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 = (p->dram_type==TYPE_LPDDR5?VREF_VOLTAGE_TABLE_NUM_LP5:VREF_VOLTAGE_TABLE_NUM_LP4)-1;
    u2VrefStep = EYESCAN_GRAPH_CATX_VREF_STEP;
    mcSHOW_DBG_MSG3(("\nTX Vref %d -> %d, step: %d\n", u2VrefBegin, u2VrefEnd, u2VrefStep));

#if ENABLE_K_WITH_WORST_SI_UI_SHIFT
    DramcEngine2Init(p, p->test2_1, p->test2_2, p->test_pattern | 0x80, 0, TE_UI_SHIFT);
#else
    DramcEngine2Init(p, p->test2_1, p->test2_2, TEST_XTALK_PATTERN, 0, TE_NO_UI_SHIFT);
#endif


    for(u2VrefLevel = u2VrefBegin; u2VrefLevel <= u2VrefEnd; u2VrefLevel += u2VrefStep)
    {

        DramcTXSetVref(p, u2VrefRange, u2VrefLevel);
        mcSHOW_DBG_MSG3(("\n\n Set TX VrefRange %d, VrefLevel=%d\n", u2VrefRange, u2VrefLevel));


        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+=(u1IsPhaseMode(p)==TRUE ? 8 : 1))
        {
            TxWinTransferDelayToUIPI(p, 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_SHURK_SELPH_DQ0), \
                                             P_Fld(ucdq_ui_large, SHURK_SELPH_DQ0_TXDLY_DQ0) | \
                                             P_Fld(ucdq_oen_ui_large, SHURK_SELPH_DQ0_TXDLY_OEN_DQ0));
            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ2), \
                                             P_Fld(ucdq_ui_small, SHURK_SELPH_DQ2_DLY_DQ0) | \
                                             P_Fld(ucdq_oen_ui_small, SHURK_SELPH_DQ2_DLY_OEN_DQ0));
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_DQ0), ucdq_pi, SHU_R0_B0_DQ0_SW_ARPI_DQ_B0);

            TxWinTransferDelayToUIPI(p, 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_SHURK_SELPH_DQ0), \
                                             P_Fld(ucdq_ui_large, SHURK_SELPH_DQ0_TXDLY_DQ1) | \
                                             P_Fld(ucdq_oen_ui_large, SHURK_SELPH_DQ0_TXDLY_OEN_DQ1));
            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ2), \
                                             P_Fld(ucdq_ui_small, SHURK_SELPH_DQ2_DLY_DQ1) | \
                                             P_Fld(ucdq_oen_ui_small, SHURK_SELPH_DQ2_DLY_OEN_DQ1));
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_DQ0), ucdq_pi, SHU_R0_B1_DQ0_SW_ARPI_DQ_B1);

            TxWinTransferDelayToUIPI(p, 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_SHURK_SELPH_DQ1), \
                                            P_Fld(ucdq_ui_large, SHURK_SELPH_DQ1_TXDLY_DQM0) | \
                                            P_Fld(ucdq_oen_ui_large, SHURK_SELPH_DQ1_TXDLY_OEN_DQM0));
           vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ3), \
                                            P_Fld(ucdq_ui_small, SHURK_SELPH_DQ3_DLY_DQM0) | \
                                            P_Fld(ucdq_oen_ui_small, SHURK_SELPH_DQ3_DLY_OEN_DQM0));
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B0_DQ0), ucdq_pi,  SHU_R0_B0_DQ0_SW_ARPI_DQM_B0);

            TxWinTransferDelayToUIPI(p, 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_SHURK_SELPH_DQ1), \
                                             P_Fld(ucdq_ui_large, SHURK_SELPH_DQ1_TXDLY_DQM1) | \
                                             P_Fld(ucdq_oen_ui_large, SHURK_SELPH_DQ1_TXDLY_OEN_DQM1));
            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ3), \
                                             P_Fld(ucdq_ui_small, SHURK_SELPH_DQ3_DLY_DQM1) | \
                                             P_Fld(ucdq_oen_ui_small, SHURK_SELPH_DQ3_DLY_OEN_DQM1));
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_R0_B1_DQ0), ucdq_pi, SHU_R0_B1_DQ0_SW_ARPI_DQM_B1);

            u4err_value=0;
#if ENABLE_K_WITH_WORST_SI_UI_SHIFT
            //DramcEngine2SetPat(p, p->test_pattern, 0, 0, TE_UI_SHIFT);
            u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, p->test_pattern);
#else

            DramcEngine2SetPat(p, TEST_AUDIO_PATTERN, 0, 0, TE_NO_UI_SHIFT);
            u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, TEST_AUDIO_PATTERN);
            DramcEngine2SetPat(p, TEST_XTALK_PATTERN, 0, 1, TE_NO_UI_SHIFT);
            u4err_value |= DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, TEST_XTALK_PATTERN);
#endif

            for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
            {
                u4fail_bit = u4err_value&((U32)1<<u1BitIdx);

                if (u4fail_bit == 0)
                {
                    gEyeScan_TotalPassCount[u1BitIdx]+=EYESCAN_GRAPH_CATX_VREF_STEP;
                }

                if(WinPerBit[u1BitIdx].first_pass== PASS_RANGE_NA)
                {
                    if(u4fail_bit==0)
                    {
                        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)
                    {
                        WinPerBit[u1BitIdx].last_pass  = (uiDelay-1);
                    }
                    else if (uiDelay>=63)
                    {
                        WinPerBit[u1BitIdx].last_pass  = 63;
                    }

                    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((WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass) >7)
                                uiFinishCount |= (1<<u1BitIdx);


                            VrefWinPerBit[u1BitIdx].first_pass = WinPerBit[u1BitIdx].first_pass;
                            VrefWinPerBit[u1BitIdx].last_pass = WinPerBit[u1BitIdx].last_pass;
                        }


                            if (EyeScan_index[u1BitIdx] < EYESCAN_BROKEN_NUM)
                            {
#if VENDER_JV_LOG || defined(RELEASE)
                                gEyeScan_Min[(u2VrefLevel+u2VrefRange*30)/EYESCAN_GRAPH_CATX_VREF_STEP][u1BitIdx][EyeScan_index[u1BitIdx]] = WinPerBit[u1BitIdx].first_pass;
                                gEyeScan_Max[(u2VrefLevel+u2VrefRange*30)/EYESCAN_GRAPH_CATX_VREF_STEP][u1BitIdx][EyeScan_index[u1BitIdx]] = WinPerBit[u1BitIdx].last_pass;
#else

                                gEyeScan_Min[(u2VrefLevel+u2VrefRange*30)/EYESCAN_GRAPH_CATX_VREF_STEP][u1BitIdx][EyeScan_index[u1BitIdx]] = (S8) WinPerBit[u1BitIdx].first_pass;
                                gEyeScan_Max[(u2VrefLevel+u2VrefRange*30)/EYESCAN_GRAPH_CATX_VREF_STEP][u1BitIdx][EyeScan_index[u1BitIdx]] = (S8) WinPerBit[u1BitIdx].last_pass;
                                mcSHOW_DBG_MSG3(("VrefRange %d, VrefLevel=%d, u1BitIdx=%d, index=%d (%d, %d)==\n",u2VrefRange,u2VrefLevel, u1BitIdx, EyeScan_index[u1BitIdx], gEyeScan_Min[u2VrefLevel/EYESCAN_GRAPH_CATX_VREF_STEP][u1BitIdx][EyeScan_index[u1BitIdx]], gEyeScan_Max[u2VrefLevel/EYESCAN_GRAPH_CATX_VREF_STEP][u1BitIdx][EyeScan_index[u1BitIdx]]));
                                gEyeScan_MinMax_store_delay[u1BitIdx/8] =  tx_pi_delay[u1BitIdx/8]-32;
#endif
                                EyeScan_index[u1BitIdx]=EyeScan_index[u1BitIdx]+1;
                            }



                        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;

            gEyeScan_WinSize[(u2VrefLevel+u2VrefRange*30)/EYESCAN_GRAPH_CATX_VREF_STEP][u1BitIdx] = VrefWinPerBit[u1BitIdx].win_size;

#ifdef FOR_HQA_TEST_USED
            if((((backup_u1MR14Value>>6)&1) == u2VrefRange) && ((backup_u1MR14Value&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;


            for (u1ByteIdx=0; u1ByteIdx<DQS_BYTE_NUMBER; u1ByteIdx++)
            {
        #if 1
                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 && p->dram_type!=TYPE_LPDDR5)
        {
            u2VrefRange = 1;
            u2VrefLevel = 20;
        }

        for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
        {
            if (u1pass_in_this_vref_flag[u1BitIdx]) gEyeScan_ContinueVrefHeight[u1BitIdx]+=EYESCAN_GRAPH_CATX_VREF_STEP;
        }
    }

    DramcEngine2End(p);


    for (u1ByteIdx=0; u1ByteIdx<DQS_BYTE_NUMBER; u1ByteIdx++)
    {
        uiDelay = ((u2Center_min[u1ByteIdx] + u2Center_max[u1ByteIdx])>>1);

#if VENDER_JV_LOG || defined(RELEASE)
        gEyeScan_CaliDelay[u1ByteIdx] = uiDelay;
#else
        gEyeScan_CaliDelay[u1ByteIdx] = uiDelay + tx_pi_delay[u1ByteIdx]-32;
#endif
    }



    DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));


    {
       u2VrefRange = backup_u1MR14Value>>6;
       u2VrefLevel = backup_u1MR14Value & 0x3f;
    }
    DramcTXSetVref(p, u2VrefRange, u2VrefLevel);
    u1MR14Value[p->channel][p->rank][p->dram_fsp] = backup_u1MR14Value;

}
#endif

#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] = {0xff, 0xff}, 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_BYTE_NUMBER], ucdq_ui_small_bak[DQS_BYTE_NUMBER];
    U8 ucdq_oen_ui_large[2] = {0}, ucdq_oen_ui_small[2] = {0};
    //U8 ucdq_current_ui_large, ucdq_current_ui_small;
    //U8 ucdq_ui_large_reg_value=0xff, ucdq_ui_small_reg_value=0xff;
    //U8 ucdq_final_dqm_oen_ui_large[DQS_BYTE_NUMBER] = {0}, ucdq_final_dqm_oen_ui_small[DQS_BYTE_NUMBER] = {0};
    //DRAM_STATUS_T KResult;

    //mcDUMP_REG_MSG(("\n[dumpRG] DramcTXOECalibration\n"));
#if VENDER_JV_LOG
    vPrintCalibrationBasicInfo_ForJV(p);
#else
    vPrintCalibrationBasicInfo(p);
#endif

#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


    vSetCalibrationResult(p, DRAM_CALIBRATION_TX_OE, DRAM_FAIL);

#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION)
    if (p->femmc_Ready == 1)
    {
        for (u1ByteIdx = 0; u1ByteIdx < DQS_BYTE_NUMBER; 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];
        }
     vSetCalibrationResult(p, DRAM_CALIBRATION_TX_OE, DRAM_FAST_K);
    }
#endif

    for (u1ByteIdx = 0; u1ByteIdx < DQS_BYTE_NUMBER; 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]));
        //mcDUMP_REG_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_SHURK_SELPH_DQ0), \
                                    P_Fld(ucdq_oen_ui_large[0], SHURK_SELPH_DQ0_TXDLY_OEN_DQ0) | \
                                    P_Fld(ucdq_oen_ui_large[1], SHURK_SELPH_DQ0_TXDLY_OEN_DQ1));

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ1), \
                                    P_Fld(ucdq_oen_ui_large[0], SHURK_SELPH_DQ1_TXDLY_OEN_DQM0) | \
                                    P_Fld(ucdq_oen_ui_large[1], SHURK_SELPH_DQ1_TXDLY_OEN_DQM1));

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ2), \
                                    P_Fld(ucdq_oen_ui_small[0], SHURK_SELPH_DQ2_DLY_OEN_DQ0) | \
                                    P_Fld(ucdq_oen_ui_small[1], SHURK_SELPH_DQ2_DLY_OEN_DQ1) );

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK_SELPH_DQ3), \
                                     P_Fld(ucdq_oen_ui_small[0], SHURK_SELPH_DQ3_DLY_OEN_DQM0) | \
                                     P_Fld(ucdq_oen_ui_small[1], SHURK_SELPH_DQ3_DLY_OEN_DQM1));

}
#endif

#define fld_val(_reg, _fld) \
	((_reg & Fld2Msk32(_fld)) >> Fld_shft(_fld))
static void OECKCKE_Control(DRAMC_CTX_T *p, U32 option)
{

	static U32 u4CA_CMD2_backup = 0;
	static U32 u4SHU_CA_CMD13_backup = 0;
    static U32 u4CS_CTRL_backup = 0;
    static U32 u4CKE_CTRL_backup = 0;
	static U32 u4backup_done = 0;
	BOOL isLP4_DSC = (p->DRAMPinmux == PINMUX_DSC)?1:0;

	if (option == DISABLE) {
		if (u4backup_done == 1) {
			mcSHOW_ERR_MSG(("[%s] Backup OE again without restored??\n", __func__));
		#if __ETT__
			while (1);
		#else
			ASSERT(0);
		#endif
		}
		if (!isLP4_DSC)
		{
		    u4CA_CMD2_backup = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD2));
		    u4SHU_CA_CMD13_backup = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD13));
            u4CS_CTRL_backup = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_CA_TX_ARCS_CTRL));
		}
		else
		{
		    u4CA_CMD2_backup = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ2));
		    u4SHU_CA_CMD13_backup = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ13));
            u4CKE_CTRL_backup = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_B1_TX_CKE_CTRL));
		}
		u4backup_done = 1;


		if (!isLP4_DSC)
		{

		    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD2), P_Fld( 0, CA_CMD2_RG_TX_ARCS_OE_TIE_SEL_CA) \
															  | P_Fld( 1, CA_CMD2_RG_TX_ARCS_OE_TIE_EN_CA) \
															  | P_Fld( 0, CA_CMD2_RG_TX_ARCA_OE_TIE_SEL_CA) \
															  | P_Fld( 0xff, CA_CMD2_RG_TX_ARCA_OE_TIE_EN_CA));

            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_CA_TX_ARCS_CTRL), P_Fld( 0, CA_TX_ARCS_CTRL_RG_TX_ARCS_OE_TIE_SEL_C0));
		}
		else
		{

            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_B1_TX_CKE_CTRL), P_Fld( 0, B1_TX_CKE_CTRL_RG_TX_ARCKE_OE_TIE_SEL_B1) \
                                    | P_Fld( 1, B1_TX_CKE_CTRL_RG_TX_ARCKE_OE_TIE_EN_B1));

		    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ2), P_Fld( 0, B1_DQ2_RG_TX_ARDQM_OE_TIE_SEL_B1) \
															  | P_Fld( 1, B1_DQ2_RG_TX_ARDQM_OE_TIE_EN_B1) \
															  | P_Fld( 0, B1_DQ2_RG_TX_ARDQ_OE_TIE_SEL_B1) \
															  | P_Fld( 0xff, B1_DQ2_RG_TX_ARDQ_OE_TIE_EN_B1));
		}

		mcDELAY_US(1);
		if (!isLP4_DSC)
		{

			vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD2), P_Fld( 0, CA_CMD2_RG_TX_ARCLK_OE_TIE_SEL_CA) \
																  | P_Fld( 1, CA_CMD2_RG_TX_ARCLK_OE_TIE_EN_CA));


			vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD13), P_Fld( 0, SHU_CA_CMD13_RG_TX_ARCLKB_OE_TIE_SEL_CA) \
																  | P_Fld( 1, SHU_CA_CMD13_RG_TX_ARCLKB_OE_TIE_EN_CA));
		}
		else
		{

			vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ2), P_Fld( 0, B1_DQ2_RG_TX_ARDQS_OE_TIE_SEL_B1) \
																  | P_Fld( 1, B1_DQ2_RG_TX_ARDQS_OE_TIE_EN_B1));


			vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ13), P_Fld( 0, SHU_B1_DQ13_RG_TX_ARDQSB_OE_TIE_SEL_B1) \
																  | P_Fld( 1, SHU_B1_DQ13_RG_TX_ARDQSB_OE_TIE_EN_B1));
		}
	} else {
		U32 u4CKOE_TieSel, u4CKOE_TieEn;
		U32 u4CKBOE_TieSel, u4CKBOE_TieEn;
		U32 u4CSOE_TieSel, u4CSOE_TieEn;
		U32 u4CAOE_TieSel, u4CAOE_TieEn;
		U32 u4CKEOE_TieSel, u4CKEOE_TieEN;

		if (u4backup_done == 0) {
			mcSHOW_ERR_MSG(("[%s] Restore OE while not backup??\n", __func__));
		#if __ETT__
			while (1);
		#else
			ASSERT(0);
		#endif
		}

		u4CKOE_TieSel = fld_val(u4CA_CMD2_backup, CA_CMD2_RG_TX_ARCLK_OE_TIE_SEL_CA);
		u4CKOE_TieEn = fld_val(u4CA_CMD2_backup, CA_CMD2_RG_TX_ARCLK_OE_TIE_EN_CA);
		u4CKBOE_TieSel = fld_val(u4SHU_CA_CMD13_backup, SHU_CA_CMD13_RG_TX_ARCLKB_OE_TIE_SEL_CA);
		u4CKBOE_TieEn = fld_val(u4SHU_CA_CMD13_backup, SHU_CA_CMD13_RG_TX_ARCLKB_OE_TIE_EN_CA);
		u4CAOE_TieSel = fld_val(u4CA_CMD2_backup, CA_CMD2_RG_TX_ARCA_OE_TIE_SEL_CA);
		u4CAOE_TieEn = fld_val(u4CA_CMD2_backup, CA_CMD2_RG_TX_ARCA_OE_TIE_EN_CA);
        if(!isLP4_DSC)
        {
            u4CSOE_TieSel = fld_val(u4CS_CTRL_backup, CA_TX_ARCS_CTRL_RG_TX_ARCS_OE_TIE_SEL_C0);
            u4CSOE_TieEn = fld_val(u4CA_CMD2_backup, CA_CMD2_RG_TX_ARCA_OE_TIE_EN_CA);
            u4CKEOE_TieSel = fld_val(u4CA_CMD2_backup, CA_CMD2_RG_TX_ARCS_OE_TIE_SEL_CA);

            u4CKEOE_TieEN = u4CSOE_TieEn;
        }
        else
        {
            u4CSOE_TieSel = fld_val(u4CA_CMD2_backup, B1_DQ2_RG_TX_ARDQM_OE_TIE_SEL_B1);
            u4CSOE_TieEn = fld_val(u4CA_CMD2_backup, B1_DQ2_RG_TX_ARDQM_OE_TIE_EN_B1);
            u4CKEOE_TieSel = fld_val(u4CKE_CTRL_backup, B1_TX_CKE_CTRL_RG_TX_ARCKE_OE_TIE_SEL_B1);
            u4CKEOE_TieEN = fld_val(u4CKE_CTRL_backup, B1_TX_CKE_CTRL_RG_TX_ARCKE_OE_TIE_EN_B1);
        }

		if (!isLP4_DSC)
		{

			vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD2), P_Fld( u4CKOE_TieSel, CA_CMD2_RG_TX_ARCLK_OE_TIE_SEL_CA) \
																  | P_Fld( u4CKOE_TieEn, CA_CMD2_RG_TX_ARCLK_OE_TIE_EN_CA));


			vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD13), P_Fld( u4CKBOE_TieSel, SHU_CA_CMD13_RG_TX_ARCLKB_OE_TIE_SEL_CA ) \
																  | P_Fld( u4CKBOE_TieEn, SHU_CA_CMD13_RG_TX_ARCLKB_OE_TIE_EN_CA));
		}
		else
		{

			vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ2), P_Fld( u4CKOE_TieSel, B1_DQ2_RG_TX_ARDQS_OE_TIE_SEL_B1) \
																  | P_Fld( u4CKOE_TieEn, B1_DQ2_RG_TX_ARDQS_OE_TIE_EN_B1));


			vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ13), P_Fld( u4CKBOE_TieSel, SHU_B1_DQ13_RG_TX_ARDQSB_OE_TIE_SEL_B1 ) \
																  | P_Fld( u4CKBOE_TieEn, SHU_B1_DQ13_RG_TX_ARDQSB_OE_TIE_EN_B1));
		}

		mcDELAY_US(1);

		if (!isLP4_DSC)
		{

            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_CA_TX_ARCS_CTRL), P_Fld( u4CSOE_TieSel, CA_TX_ARCS_CTRL_RG_TX_ARCS_OE_TIE_SEL_C0));

            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD2), P_Fld( u4CKEOE_TieSel, CA_CMD2_RG_TX_ARCS_OE_TIE_SEL_CA) \
																  | P_Fld( u4CSOE_TieEn, CA_CMD2_RG_TX_ARCS_OE_TIE_EN_CA) \
																  | P_Fld( u4CAOE_TieSel, CA_CMD2_RG_TX_ARCA_OE_TIE_SEL_CA) \
																  | P_Fld( u4CAOE_TieEn, CA_CMD2_RG_TX_ARCA_OE_TIE_EN_CA));
		}
		else
		{

			vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ2), P_Fld( u4CSOE_TieSel, B1_DQ2_RG_TX_ARDQM_OE_TIE_SEL_B1) \
																  | P_Fld( u4CSOE_TieEn, B1_DQ2_RG_TX_ARDQM_OE_TIE_EN_B1) \
																  | P_Fld( u4CAOE_TieSel, B1_DQ2_RG_TX_ARDQ_OE_TIE_SEL_B1) \
																  | P_Fld( u4CAOE_TieEn, B1_DQ2_RG_TX_ARDQ_OE_TIE_EN_B1));

            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_B1_TX_CKE_CTRL), P_Fld( u4CKEOE_TieSel, B1_TX_CKE_CTRL_RG_TX_ARCKE_OE_TIE_SEL_B1) \
                              | P_Fld( u4CKEOE_TieEN, B1_TX_CKE_CTRL_RG_TX_ARCKE_OE_TIE_EN_B1));
		}

		u4backup_done = 0;
	}
}

static void OEDisable(DRAMC_CTX_T *p)
{
    BOOL isLP4_DSC = (p->DRAMPinmux == PINMUX_DSC)?1:0;


    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ2), P_Fld( 0 , B0_DQ2_RG_TX_ARDQS_OE_TIE_SEL_B0 ) \
                                                          | P_Fld( 1       , B0_DQ2_RG_TX_ARDQS_OE_TIE_EN_B0  ) \
                                                          | P_Fld( 0 , B0_DQ2_RG_TX_ARWCK_OE_TIE_SEL_B0 ) \
                                                          | P_Fld( 1       , B0_DQ2_RG_TX_ARWCK_OE_TIE_EN_B0  ) \
                                                          | P_Fld( 0 , B0_DQ2_RG_TX_ARWCKB_OE_TIE_SEL_B0 ) \
                                                          | P_Fld( 1       , B0_DQ2_RG_TX_ARWCKB_OE_TIE_EN_B0  ) \
                                                          | P_Fld( 0 , B0_DQ2_RG_TX_ARDQM_OE_TIE_SEL_B0 ) \
                                                          | P_Fld( 1       , B0_DQ2_RG_TX_ARDQM_OE_TIE_EN_B0  ) \
                                                          | P_Fld( 0 , B0_DQ2_RG_TX_ARDQ_OE_TIE_SEL_B0 ) \
                                                          | P_Fld( 0xff       , B0_DQ2_RG_TX_ARDQ_OE_TIE_EN_B0  ) );
    if (!isLP4_DSC)
    {
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ2), P_Fld( 0 , B1_DQ2_RG_TX_ARDQS_OE_TIE_SEL_B1 ) \
                                                              | P_Fld( 1       , B1_DQ2_RG_TX_ARDQS_OE_TIE_EN_B1  ) \
                                                              | P_Fld( 0 , B1_DQ2_RG_TX_ARWCK_OE_TIE_SEL_B1 ) \
                                                              | P_Fld( 1       , B1_DQ2_RG_TX_ARWCK_OE_TIE_EN_B1  ) \
                                                              | P_Fld( 0 , B1_DQ2_RG_TX_ARWCKB_OE_TIE_SEL_B1 ) \
                                                              | P_Fld( 1       , B1_DQ2_RG_TX_ARWCKB_OE_TIE_EN_B1  ) \
                                                              | P_Fld( 0 , B1_DQ2_RG_TX_ARDQM_OE_TIE_SEL_B1 ) \
                                                              | P_Fld( 1       , B1_DQ2_RG_TX_ARDQM_OE_TIE_EN_B1  ) \
                                                              | P_Fld( 0 , B1_DQ2_RG_TX_ARDQ_OE_TIE_SEL_B1 ) \
                                                              | P_Fld( 0xff , B1_DQ2_RG_TX_ARDQ_OE_TIE_EN_B1) );
    }
    else
    {
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD2), P_Fld( 0 , CA_CMD2_RG_TX_ARCLK_OE_TIE_SEL_CA ) \
                                                              | P_Fld( 1       , CA_CMD2_RG_TX_ARCLK_OE_TIE_EN_CA  ) \
                                                              | P_Fld( 0 , CA_CMD2_RG_TX_ARCS_OE_TIE_SEL_CA ) \
                                                              | P_Fld( 1       , CA_CMD2_RG_TX_ARCS_OE_TIE_EN_CA  ) \
                                                              | P_Fld( 0 , CA_CMD2_RG_TX_ARCA_OE_TIE_SEL_CA ) \
                                                              | P_Fld( 0xff , CA_CMD2_RG_TX_ARCA_OE_TIE_EN_CA) );
    }

    OECKCKE_Control(p, DISABLE);

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ13) , P_Fld( 0 , SHU_B0_DQ13_RG_TX_ARDQSB_OE_TIE_SEL_B0  ) \
                                                          | P_Fld( 1       , SHU_B0_DQ13_RG_TX_ARDQSB_OE_TIE_EN_B0   ));
    if (!isLP4_DSC)
    {
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ13) , P_Fld( 0 , SHU_B1_DQ13_RG_TX_ARDQSB_OE_TIE_SEL_B1  ) \
                                                              | P_Fld( 1       , SHU_B1_DQ13_RG_TX_ARDQSB_OE_TIE_EN_B1   ));
    }
    else
    {
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD13) , P_Fld( 0 , SHU_CA_CMD13_RG_TX_ARCLKB_OE_TIE_SEL_CA  ) \
                                                              | P_Fld( 1       , SHU_CA_CMD13_RG_TX_ARCLKB_OE_TIE_EN_CA   ));
    }


}

#ifdef FOR_HQA_TEST_USED

VCORE_DELAYCELL_T gVcoreDelayCellTable[49]={    {500000, 512},
                                                {506250, 496},
                                                {512500, 482},
                                                {518750, 469},
                                                {525000, 457},
                                                {531250, 445},
                                                {537500, 434},
                                                {543750, 423},
                                                {550000, 412},
                                                {556250, 402},
                                                {562500, 393},
                                                {568750, 384},
                                                {575000, 377},
                                                {581250, 369},
                                                {587500, 362},
                                                {593750, 355},
                                                {600000, 348},
                                                {606250, 341},
                                                {612500, 335},
                                                {618750, 328},
                                                {625000, 322},
                                                {631250, 317},
                                                {637500, 312},
                                                {643750, 307},
                                                {650000, 302},
                                                {656250, 297},
                                                {662500, 292},
                                                {668750, 288},
                                                {675000, 284},
                                                {681250, 280},
                                                {687500, 276},
                                                {693750, 272},
                                                {700000, 269},
                                                {706250, 265},
                                                {712500, 262},
                                                {718750, 258},
                                                {725000, 255},
                                                {731250, 252},
                                                {737500, 249},
                                                {743750, 246},
                                                {750000, 243},
                                                {756250, 241},
                                                {762500, 238},
                                                {768750, 236},
                                                {775000, 233},
                                                {781250, 231},
                                                {787500, 229},
                                                {793750, 227},
                                                {800000, 225},
                                                //{825000, 718},
                                                //{831250, 717},
                                                //{837500, 715},
                                                //{843750, 713},
                                                //{850000, 708},
                                                //{856250, 705},
                                                //{862500, 702},
                                                //{868750, 700},
                                                //{875000, 698}
                                                };

static U16 GetVcoreDelayCellTimeFromTable(DRAMC_CTX_T *p)
{
    U32 i;
    U32 get_vcore = 0;
    U16 delay_cell_ps = 0;
    U8 u1delay_cell_cnt = 0;
    VCORE_DELAYCELL_T *pVcoreDelayCellTable;

#if (defined(DRAM_HQA) || __ETT__) && (FOR_DV_SIMULATION_USED == 0)
    get_vcore = dramc_get_vcore_voltage();
#endif

    pVcoreDelayCellTable = (VCORE_DELAYCELL_T *)gVcoreDelayCellTable;
    u1delay_cell_cnt = sizeof(gVcoreDelayCellTable)/sizeof(gVcoreDelayCellTable[0]);

    for(i=0; i<u1delay_cell_cnt; i++)
    {
        if (get_vcore <= pVcoreDelayCellTable[i].u2Vcore)
        {
            delay_cell_ps = pVcoreDelayCellTable[i].u2DelayCell;
            break;
        }
    }

    mcSHOW_DBG_MSG(("[GetVcoreDelayCellTimeFromTable(%d)] VCore=%d(x100), DelayCell=%d(x100)\n", u1delay_cell_cnt, get_vcore, delay_cell_ps));

    return delay_cell_ps;
}
#endif


#if ENABLE_8PHASE_CALIBRATION || defined(ENABLE_MIOCK_JMETER)
static void DramcJmeterInit(DRAMC_CTX_T *p, U8 u1IsJmtrK)
{
    OEDisable(p);

    //DramcHWGatingOnOff(p, 0);
    if(u1IsJmtrK != TRUE)
    {
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_MISC_SHU_STBCAL), P_Fld(0x0, MISC_SHU_STBCAL_STBCALEN)
                                                           | P_Fld(0x0, MISC_SHU_STBCAL_STB_SELPHCALEN));
    }

#if 0
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_DLL_ARPI0), 0, B0_DLL_ARPI0_RG_ARPI_RESETB_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_DLL_ARPI0), 0, B1_DLL_ARPI0_RG_ARPI_RESETB_B1);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_CA_DLL_ARPI0), 0, CA_DLL_ARPI0_RG_ARPI_RESETB_CA);
    mcDELAY_US(1);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_DLL_ARPI0), 1, B0_DLL_ARPI0_RG_ARPI_RESETB_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_DLL_ARPI0), 1, B1_DLL_ARPI0_RG_ARPI_RESETB_B1);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_CA_DLL_ARPI0), 1, CA_DLL_ARPI0_RG_ARPI_RESETB_CA);

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ6), 0, SHU_B0_DQ6_RG_ARPI_OFFSET_DQSIEN_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ6), 0, SHU_B1_DQ6_RG_ARPI_OFFSET_DQSIEN_B1);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD6), 0, SHU_CA_CMD6_RG_ARPI_OFFSET_DQSIEN_CA);
#endif


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ11), 0, SHU_B0_DQ11_RG_RX_ARDQ_RANK_SEL_SER_EN_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ11), 0, SHU_B1_DQ11_RG_RX_ARDQ_RANK_SEL_SER_EN_B1);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD11), 0, SHU_CA_CMD11_RG_RX_ARCA_RANK_SEL_SER_EN_CA);


    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_DLL1), P_Fld(0x0, SHU_CA_DLL1_RG_ARDLL_PHDET_EN_CA)
                                        | P_Fld(0x0, SHU_CA_DLL1_RG_ARDLL_PHDET_OUT_SEL_CA));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DLL1), P_Fld(0x0, SHU_B0_DLL1_RG_ARDLL_PHDET_EN_B0)
                                        | P_Fld(0x0, SHU_B0_DLL1_RG_ARDLL_PHDET_OUT_SEL_B0));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DLL1), P_Fld(0x0, SHU_B1_DLL1_RG_ARDLL_PHDET_EN_B1)
                                        | P_Fld(0x0, SHU_B1_DLL1_RG_ARDLL_PHDET_OUT_SEL_B1));


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_CTRL1), 0, MISC_CTRL1_R_DMDQSIENCG_EN);

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DLL_ARPI2), 0, SHU_B0_DLL_ARPI2_RG_ARPI_CG_DQSIEN_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DLL_ARPI2), 0, SHU_B1_DLL_ARPI2_RG_ARPI_CG_DQSIEN_B1);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DUTYSCAN1), 1, MISC_DUTYSCAN1_RX_EYE_SCAN_CG_EN);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_CTRL4), 0, MISC_CTRL4_R_OPT2_CG_DQSIEN);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL), 0, MISC_STBCAL_DQSIENCG_NORMAL_EN);

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ6), 1, B0_DQ6_RG_RX_ARDQ_EYE_DLY_DQS_BYPASS_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ6), 1, B1_DQ6_RG_RX_ARDQ_EYE_DLY_DQS_BYPASS_B1);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DUTYSCAN1), 1, MISC_DUTYSCAN1_RX_EYE_SCAN_EN);
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DUTYSCAN1), P_Fld(0x1, MISC_DUTYSCAN1_EYESCAN_DQS_SYNC_EN)
                                        | P_Fld(0x1, MISC_DUTYSCAN1_EYESCAN_NEW_DQ_SYNC_EN)
                                        | P_Fld(0x1, MISC_DUTYSCAN1_EYESCAN_DQ_SYNC_EN));
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_EYE_EN_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_EYE_EN_B1);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_VREF_EN_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_VREF_EN_B1);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ3), 1, B0_DQ3_RG_RX_ARDQ_SMT_EN_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ3), 1, B1_DQ3_RG_RX_ARDQ_SMT_EN_B1);

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_PHY2), 1, B0_PHY2_RG_RX_ARDQS_JM_EN_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_PHY2), 1, B1_PHY2_RG_RX_ARDQS_JM_EN_B1);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_JMETER), 1, MISC_JMETER_JMTR_EN);



    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_PHY2), 1, B0_PHY2_RG_RX_ARDQS_JM_SEL_B0);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_PHY2), 1, B1_PHY2_RG_RX_ARDQS_JM_SEL_B1);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DUTYSCAN1), 1, MISC_DUTYSCAN1_RX_MIOCK_JIT_EN);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DUTYSCAN1), 0, MISC_DUTYSCAN1_RX_EYE_SCAN_EN);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DUTYSCAN1), 0, MISC_DUTYSCAN1_DQSERRCNT_DIS);

#if MIOCK_JMETER_CNT_WA

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DUTYSCAN1), 0, MISC_DUTYSCAN1_EYESCAN_DQS_OPT);
#endif

}

static void DramcJmeterCalib(DRAMC_CTX_T *p, JMETER_T *pJmtrInfo, U16 u2JmDlyStep, U8 u1IsJmtrK)
{
    U16 u2Jm_dly_start = 0, u2Jm_dly_end = 512, u2Jm_dly_step = u2JmDlyStep;
    U16 ucdqs_dly, fgcurrent_value, fginitial_value;
    U16 ucsearch_state = 0xffff;
    U32 u4sample_cnt, u4ones_cnt[DQS_BYTE_NUMBER];
    U8 check;

    check = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DUTYSCAN1), MISC_DUTYSCAN1_EYESCAN_DQS_OPT);
    (void)check;

    for (ucdqs_dly = u2Jm_dly_start; ucdqs_dly < u2Jm_dly_end; ucdqs_dly += u2Jm_dly_step)
    {

        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B0_PHY2), ucdqs_dly, B0_PHY2_RG_RX_ARDQS_JM_DLY_B0);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_B1_PHY2), ucdqs_dly, B1_PHY2_RG_RX_ARDQS_JM_DLY_B1);



        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DUTYSCAN1), 1, MISC_DUTYSCAN1_REG_SW_RST);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DUTYSCAN1), 0, MISC_DUTYSCAN1_REG_SW_RST);


        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DUTYSCAN1), 1, MISC_DUTYSCAN1_RX_EYE_SCAN_EN);


        mcDELAY_US(10);


        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DUTYSCAN1), 0, MISC_DUTYSCAN1_RX_EYE_SCAN_EN);


        u4sample_cnt = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DUTY_TOGGLE_CNT), MISC_DUTY_TOGGLE_CNT_TOGGLE_CNT);
        u4ones_cnt[0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DUTY_DQS0_ERR_CNT), MISC_DUTY_DQS0_ERR_CNT_DQS0_ERR_CNT);
        //u4ones_cnt[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DUTY_DQS1_ERR_CNT), MISC_DUTY_DQS1_ERR_CNT_DQS1_ERR_CNT);
        //u4ones_cnt[2] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DUTY_DQS2_ERR_CNT), MISC_DUTY_DQS2_ERR_CNT_DQS2_ERR_CNT);
        //u4ones_cnt[3] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DUTY_DQS3_ERR_CNT), MISC_DUTY_DQS3_ERR_CNT_DQS3_ERR_CNT);
#ifndef DDR_INIT_TIME_PROFILING
        if (u1IsJmtrK == TRUE){
            mcSHOW_DBG_MSG2(("%d : %d, %d\n", ucdqs_dly, u4sample_cnt, u4ones_cnt[0]));
        }
#endif


        if (u4ones_cnt[0] < (u4sample_cnt / 2))
        {
            fgcurrent_value = 0;
        }
        else
        {
            fgcurrent_value = 1;
        }


        if (ucsearch_state == 0xffff)
        {

            fginitial_value = fgcurrent_value;
            ucsearch_state = 0;
        }
        else
        {

            if (fgcurrent_value != fginitial_value)
            {

                fginitial_value = fgcurrent_value;
                pJmtrInfo->JmtrInfo[ucsearch_state].u1JmDelay = ucdqs_dly;
                pJmtrInfo->JmtrInfo[ucsearch_state].u1TransLevel = fgcurrent_value;

                ucsearch_state++;
                pJmtrInfo->u1TransCnt = ucsearch_state;
                if (ucsearch_state == CYCLE_1T)
                    break;
            }
        }
    }
}
#endif


#ifdef ENABLE_MIOCK_JMETER

U16 GetVcoreDelayCellTime(DRAMC_CTX_T *p)
{

#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
    if(p->femmc_Ready==1)
    {
        mcSHOW_DBG_MSG(("[FAST_K] Freq=%d, DelayCellTimex100=%d\n", p->frequency, p->pSavetimeData->u2DelayCellTimex100));
        return p->pSavetimeData->u2DelayCellTimex100;
    }
#endif

    return 0;
}

void Get_RX_DelayCell(DRAMC_CTX_T *p)
{
#if defined(FOR_HQA_REPORT_USED) && (FOR_DV_SIMULATION_USED==0) && (SW_CHANGE_FOR_SIMULATION==0)

    #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
        if(p->femmc_Ready == 1)
        {
            return;
        }
    #endif

        if (gHQALOG_RX_delay_cell_ps_075V == 0)
        {
#if __ETT__
            mcSHOW_DBG_MSG(("RX delay cell calibration (%d):\n", hqa_vmddr_class));
            switch (hqa_vmddr_class)
    {
                case 1:
                    dramc_set_vcore_voltage(_SEL_PREFIX(VMDDR, HV, LP4));
                    break;
                case 2:
                    dramc_set_vcore_voltage(_SEL_PREFIX(VMDDR, NV, LP4));
                    break;
                case 3:
                    dramc_set_vcore_voltage(_SEL_PREFIX(VMDDR, LV, LP4));
                    break;
    }
#else

            dramc_set_vcore_voltage(SEL_PREFIX_VMDDR);
#endif

            gHQALOG_RX_delay_cell_ps_075V = GetVcoreDelayCellTime(p);


            vSetVcoreByFreq(p);
    }
#endif
}
#endif


DRAM_STATUS_T Dramc8PhaseCal(DRAMC_CTX_T *p)
{
#if ENABLE_8PHASE_CALIBRATION
    U8 u18Ph_dly_loop_break = 0;
    U8 u1DqsienPI = 0;
    U8 u18Phase_SM = DQS_8PH_DEGREE_0, u18Ph_dly_final = 0xff;
    U8 u18Ph_dly = 0, u18Ph_start = 0, u18Ph_end = 0;

    U16 u2R0 = 0xffff, u2R180 = 0xffff, u2R = 0xffff;
    U16 u2P = 0xffff, ucdqs_dly = 0;
    S16 s2Err_code = 0x7fff, s2Err_code_min = 0x7fff;

    U8 backup_rank, u1RankIdx, u18PhDlyBackup = 0;
    U8 u1loop_cnt = 0, u1early_break_cnt = 5;


    JMETER_T JmtrInfo;
    U8 u1JmtrPrintCnt = 0;

    U32 u4backup_broadcast= GetDramcBroadcast();
    DRAM_STATUS_T eDRAMStatus = DRAM_OK;

#ifdef DUMP_INIT_RG_LOG_TO_DE
    return DRAM_OK;
#endif

    u1DqsienPI = 0x0;


    if (!p)
    {
        mcSHOW_ERR_MSG(("context NULL\n"));
        return DRAM_FAIL;
    }

    if (p->frequency < 1866)
    {
        //mcSHOW_ERR_MSG(("skip 8-Phase Calib Freq is %d < 1866 !!!\n", p->frequency));
        return DRAM_OK;
    }

    //mcDUMP_REG_MSG(("\n[dumpRG] Dramc8PhaseCal\n"));
#if VENDER_JV_LOG
    vPrintCalibrationBasicInfo_ForJV(p);
#else
    vPrintCalibrationBasicInfo(p);
#endif

    mcSHOW_DBG_MSG(("[Dramc8PhaseCal]\n"));

    U32 u4RegBackupAddress[] =
    {
        (DRAMC_REG_ADDR(DDRPHY_REG_MISC_DUTYSCAN1)),
        (DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ6)),
        (DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ6)),
        (DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ5)),
        (DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ5)),
        (DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ3)),
        (DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ3)),
        (DRAMC_REG_ADDR(DDRPHY_REG_MISC_CTRL1)),
        (DRAMC_REG_ADDR(DDRPHY_REG_MISC_CTRL4)),
        (DRAMC_REG_ADDR(DDRPHY_REG_B0_PHY2)),
        (DRAMC_REG_ADDR(DDRPHY_REG_B1_PHY2)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DLL_ARPI2)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DLL_ARPI2)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ11)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ11)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD11)),
        (DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B0_DQSIEN_PI_DLY)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B0_DQSIEN_PI_DLY + DDRPHY_AO_RANK_OFFSET)),
        (DRAMC_REG_ADDR(DDRPHY_REG_MISC_JMETER)),
        //(DRAMC_REG_ADDR(DDRPHY_REG_MISC_STBCAL2)),
        //(DRAMC_REG_ADDR(DDRPHY_REG_MISC_DVFSCTL2)),
        (DRAMC_REG_ADDR(DDRPHY_REG_MISC_SHU_STBCAL)),
#if 0
        (DRAMC_REG_ADDR(DDRPHY_REG_B0_DLL_ARPI0)),
        (DRAMC_REG_ADDR(DDRPHY_REG_B1_DLL_ARPI0)),
        (DRAMC_REG_ADDR(DDRPHY_REG_CA_DLL_ARPI0)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ6)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ6)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD6)),
#endif
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_DLL1)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DLL1)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DLL1)),
        (DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ2)),
        (DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ2)),
        (DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD2)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ13)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ13)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD13)),

    };

    backup_rank = u1GetRank(p);
    memset(&JmtrInfo, 0, sizeof(JmtrInfo));
    DramcBroadcastOnOff(DRAMC_BROADCAST_OFF);


    DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress) / sizeof(U32));

    DramcJmeterInit(p, FALSE);

    u18PhDlyBackup = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ1), SHU_B0_DQ1_RG_ARPI_MIDPI_8PH_DLY_B0);

    for (u18Phase_SM = DQS_8PH_DEGREE_0; u18Phase_SM < DQS_8PH_DEGREE_MAX; u18Phase_SM++)
    {
        switch (u18Phase_SM)
        {
            case DQS_8PH_DEGREE_0:
                u1DqsienPI = 16;
                u18Ph_start = 0;
                u18Ph_end = 1;
                break;
            case DQS_8PH_DEGREE_180:
                u1DqsienPI = 48;
                u18Ph_start = 0;
                u18Ph_end = 1;
                break;
            case DQS_8PH_DEGREE_45:
                u1DqsienPI = 24;
                u18Ph_start = 0;
                u18Ph_end = 32;
                break;
            default:
                mcSHOW_ERR_MSG(("u18Phase_SM err!\n"));
                #if __ETT__
                while (1);
                #endif
        }

        mcSHOW_DBG_MSG2(("\n[Dramc8PhaseCal] 8-Phase SM_%d, 8PH_dly (%d~%d), DQSIEN PI = %d, 8PH_Dly = %d\n", u18Phase_SM, u18Ph_start, u18Ph_end, u1DqsienPI, u18PhDlyBackup));


        for (u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
        {
            vSetRank(p, u1RankIdx);

            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_RK_B0_DQSIEN_PI_DLY), u1DqsienPI, SHU_RK_B0_DQSIEN_PI_DLY_DQSIEN_PI_B0);
        }
        vSetRank(p, backup_rank);

        for (u18Ph_dly = u18Ph_start; u18Ph_dly < u18Ph_end; u18Ph_dly++)
        {
            mcSHOW_DBG_MSG2(("8PH dly = %d\n", u18Ph_dly));

            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ1), u18Ph_dly, SHU_B0_DQ1_RG_ARPI_MIDPI_8PH_DLY_B0);
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ1), u18Ph_dly, SHU_B1_DQ1_RG_ARPI_MIDPI_8PH_DLY_B1);
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD1), u18Ph_dly, SHU_CA_CMD1_RG_ARPI_MIDPI_8PH_DLY_CA);

            DramcJmeterCalib(p, &JmtrInfo, 1, FALSE);

            for (u1JmtrPrintCnt = 0; u1JmtrPrintCnt < JmtrInfo.u1TransCnt; u1JmtrPrintCnt++)
            {
                if (JmtrInfo.JmtrInfo[u1JmtrPrintCnt].u1TransLevel == 1)
                {
                    ucdqs_dly = JmtrInfo.JmtrInfo[u1JmtrPrintCnt].u1JmDelay;

                    if (u18Phase_SM == DQS_8PH_DEGREE_0)
                    {
                        u2R0 = ucdqs_dly;
                        mcSHOW_DBG_MSG2(("R0 (H) = %d\n", u2R0));
                        break;
                    }
                    else if (u18Phase_SM == DQS_8PH_DEGREE_180)
                    {
                        u2R180 = ucdqs_dly;
                        if (u2R180 > u2R0)
                        {
                            u2R = u2R0 + ((u2R180 - u2R0) >> 2);
                            mcSHOW_DBG_MSG2(("R = %d, R180 (H) = %d\n", u2R, u2R180));
                            break;
                        }
                    }
                    else if (u18Phase_SM == DQS_8PH_DEGREE_45)
                    {
                        u2P = ucdqs_dly;
                        if (u2P > u2R0)
                        {

                            if (u2R > u2P)
                                s2Err_code = u2R - u2P;
                            else
                                s2Err_code = u2P - u2R;

                            if (s2Err_code == 0)
                            {
                                s2Err_code_min = s2Err_code;
                                u18Ph_dly_final = u18Ph_dly;
                                u18Ph_dly_loop_break = 1;
                            }
                            else if (s2Err_code < s2Err_code_min)
                            {
                                s2Err_code_min = s2Err_code;
                                u18Ph_dly_final = u18Ph_dly;
                                u1loop_cnt = 0;
                            }
                            else if (s2Err_code >= s2Err_code_min)
                            {

                                u1loop_cnt++;
                                if (u1loop_cnt > u1early_break_cnt)
                                    u18Ph_dly_loop_break = 1;
                            }

                            mcSHOW_DBG_MSG2(("diff (P-R) = %d, min = %d, early break count = %d, R45 (H) = %d\n", s2Err_code, s2Err_code_min, u1loop_cnt, u2P));

                            break;
                        }
                    }
                    else
                    {
                        mcSHOW_ERR_MSG(("u18Phase_SM err!\n"));
                        #if __ETT__
                        while (1);
                        #endif
                    }
                }
            }


            if (JmtrInfo.u1TransCnt == u1JmtrPrintCnt)
            {
                u18Ph_dly_final = u18PhDlyBackup;
                eDRAMStatus = DRAM_FAIL;
                mcSHOW_ERR_MSG(("\n[Dramc8PhaseCal] 8-Phase SM_%d is fail (to Default) !!!\n", u18Phase_SM));
                goto exit;
            } else if (u18Ph_dly_loop_break == 1)
                break;
        }
    }

exit:
    mcSHOW_DBG_MSG(("\n[Dramc8PhaseCal] u18Ph_dly_final = %d\n\n", u18Ph_dly_final));
    //mcDUMP_REG_MSG(("\n[Dramc8PhaseCal] u18Ph_dly_final = %d\n\n", u18Ph_dly_final));

    vIO32WriteFldAlign_All(DDRPHY_REG_SHU_B0_DQ1, u18Ph_dly_final, SHU_B0_DQ1_RG_ARPI_MIDPI_8PH_DLY_B0);
    vIO32WriteFldAlign_All(DDRPHY_REG_SHU_B1_DQ1, u18Ph_dly_final, SHU_B1_DQ1_RG_ARPI_MIDPI_8PH_DLY_B1);
    vIO32WriteFldAlign_All(DDRPHY_REG_SHU_CA_CMD1, u18Ph_dly_final, SHU_CA_CMD1_RG_ARPI_MIDPI_8PH_DLY_CA);


    OECKCKE_Control(p, ENABLE);
    DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress) / sizeof(U32));

    DramcBroadcastOnOff(u4backup_broadcast);

    return eDRAMStatus;
#endif
}

#if SIMULATION_SW_IMPED

#if 0
static U32 SwImpedanceAdjust(U32 u4ImpVal, S8 s1StepCnt)
{
    S32 S4ImpedanceTemp = (S32)u4ImpVal;


    S4ImpedanceTemp += s1StepCnt;

    if ((S4ImpedanceTemp > 15) && (S4ImpedanceTemp < 29))
    {
        S4ImpedanceTemp = S4ImpedanceTemp - 16 + 29;
    }

    if (S4ImpedanceTemp > 31)
    {
        S4ImpedanceTemp = 31;
    }
    else if (S4ImpedanceTemp < 0)
    {
        S4ImpedanceTemp = 0;
    }

    return (U32)S4ImpedanceTemp;
}
#endif

#define IMPCAL_STAGE_DRVP     0
#define IMPCAL_STAGE_DRVN     1
#define IMPCAL_STAGE_ODTP     2
#define IMPCAL_STAGE_ODTN     3
#define IMPCAL_STAGE_TRACKING 4


#define IMP_TRACK_LP4X_LOWFREQ_VREF_SEL  0x37
#define IMP_TRACK_LP4X_HIGHFREQ_VREF_SEL  0x3a

#define IMP_TRACK_LP5_LOWFREQ_VREF_SEL  0x38
#define IMP_TRACK_LP5_HIGHFREQ_VREF_SEL  0x3a

static const U8 ImpLP4VrefSel[IMP_VREF_MAX][IMP_DRV_MAX] = {

    {0x37, 0x33, 0x00, 0x37},
    {0x3a, 0x33, 0x00, 0x3a},
    {0x2a, 0x2a, 0x00, 0x3a}
};

static const U8 ImpLP5VrefSel[IMP_VREF_MAX][IMP_DRV_MAX] = {

    {0x38, 0x33, 0x00, 0x38},
    {0x3a, 0x33, 0x00, 0x3a},
    {0x2a, 0x2a, 0x00, 0x3a}
};


static void vImpCalVrefSel(DRAMC_CTX_T *p, DRAMC_IMP_T efreq_region, U8 u1ImpCalStage)
{
    U8 u1RegTmpValue = 0;
    U32 u4DrvFld = 0;

    if (p->dram_type == TYPE_LPDDR4X)
    {
        if (u1ImpCalStage == IMPCAL_STAGE_TRACKING)
            u1RegTmpValue = (efreq_region == IMP_LOW_FREQ) ? IMP_TRACK_LP4X_LOWFREQ_VREF_SEL : IMP_TRACK_LP4X_HIGHFREQ_VREF_SEL;
        else
            u1RegTmpValue = ImpLP4VrefSel[efreq_region][u1ImpCalStage];
    }
    else if (p->dram_type == TYPE_LPDDR5)
    {
        if (u1ImpCalStage == IMPCAL_STAGE_TRACKING)
            u1RegTmpValue = (efreq_region == IMP_LOW_FREQ) ? IMP_TRACK_LP5_LOWFREQ_VREF_SEL : IMP_TRACK_LP5_HIGHFREQ_VREF_SEL;
        else
            u1RegTmpValue = ImpLP5VrefSel[efreq_region][u1ImpCalStage];
    }
    else
    {
        mcSHOW_ERR_MSG(("[vImpCalVrefSel] Warnning: Need confirm DRAM type for IMP_VREF_SEL !!!\n"));
        #if __ETT__
        while(1);
        #endif
    }

    switch (u1ImpCalStage)
    {
        case IMPCAL_STAGE_DRVP:
            u4DrvFld = SHU_CA_CMD12_RG_RIMP_VREF_SEL_DRVP;
            break;
        case IMPCAL_STAGE_DRVN:
            u4DrvFld = SHU_CA_CMD12_RG_RIMP_VREF_SEL_DRVN;
            break;
        case IMPCAL_STAGE_ODTN:
            u4DrvFld = SHU_CA_CMD12_RG_RIMP_VREF_SEL_ODTN;
            break;
        case IMPCAL_STAGE_TRACKING:
            break;
        default:
            mcSHOW_ERR_MSG(("[vImpCalVrefSel] Warnning: Need confirm u1ImpCalStage for SW IMP Calibration !!!\n"));
            break;
    }


    mcSHOW_DBG_MSG3(("[vImpCalVrefSel] IMP_VREF_SEL 0x%x, IMPCAL stage:%u, freq_region:%u\n",
                      u1RegTmpValue, u1ImpCalStage, efreq_region));


    if (u1ImpCalStage == IMPCAL_STAGE_TRACKING) {

        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD12), u1RegTmpValue, SHU_CA_CMD12_RG_RIMP_VREF_SEL_DRVP);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD12), u1RegTmpValue, SHU_CA_CMD12_RG_RIMP_VREF_SEL_ODTN);
    } else {
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD12), u1RegTmpValue, u4DrvFld);
    }

    return;
}

void DramcSwImpedanceSaveRegister(DRAMC_CTX_T *p, U8 ca_freq_option, U8 dq_freq_option, U8 save_to_where)
{
    U32 backup_broadcast;
    //U8 u1Hysteresis;

    backup_broadcast = GetDramcBroadcast();

    DramcBroadcastOnOff(DRAMC_BROADCAST_ON);


    vImpCalVrefSel(p, dq_freq_option, IMPCAL_STAGE_TRACKING);


    vIO32WriteFldMulti((DDRPHY_REG_SHU_MISC_DRVING1 + save_to_where * SHU_GRP_DDRPHY_OFFSET), P_Fld(gDramcImpedanceResult[dq_freq_option][DRVP], SHU_MISC_DRVING1_DQDRVP2) | P_Fld(gDramcImpedanceResult[dq_freq_option][DRVN], SHU_MISC_DRVING1_DQDRVN2));
    vIO32WriteFldMulti((DDRPHY_REG_SHU_MISC_DRVING2 + save_to_where * SHU_GRP_DDRPHY_OFFSET), P_Fld(gDramcImpedanceResult[dq_freq_option][DRVP], SHU_MISC_DRVING2_DQDRVP1) | P_Fld(gDramcImpedanceResult[dq_freq_option][DRVN], SHU_MISC_DRVING2_DQDRVN1));
    vIO32WriteFldMulti((DDRPHY_REG_SHU_MISC_DRVING3 + save_to_where * SHU_GRP_DDRPHY_OFFSET), P_Fld(gDramcImpedanceResult[dq_freq_option][ODTP], SHU_MISC_DRVING3_DQODTP2) | P_Fld(gDramcImpedanceResult[dq_freq_option][ODTN], SHU_MISC_DRVING3_DQODTN2));
    vIO32WriteFldMulti((DDRPHY_REG_SHU_MISC_DRVING4 + save_to_where * SHU_GRP_DDRPHY_OFFSET), P_Fld(gDramcImpedanceResult[dq_freq_option][ODTP], SHU_MISC_DRVING4_DQODTP1) | P_Fld(gDramcImpedanceResult[dq_freq_option][ODTN], SHU_MISC_DRVING4_DQODTN1));


    #if SUPPORT_HYNIX_RX_DQS_WEAK_PULL
    if (p->vendor_id == VENDOR_HYNIX)
    {  U32 temp_value[4];
        int i;
        for(i=0; i<4; i++)
        {
            temp_value[i] = SwImpedanceAdjust(gDramcImpedanceResult[dq_freq_option][i], 2);
        }
         vIO32WriteFldMulti((DDRPHY_REG_SHU_MISC_DRVING1 + save_to_where * SHU_GRP_DDRPHY_OFFSET), P_Fld(temp_value[0], SHU_MISC_DRVING1_DQSDRVP2) | P_Fld(temp_value[1], SHU_MISC_DRVING1_DQSDRVN2));
         vIO32WriteFldMulti((DDRPHY_REG_SHU_MISC_DRVING1 + save_to_where * SHU_GRP_DDRPHY_OFFSET), P_Fld(temp_value[0], SHU_MISC_DRVING1_DQSDRVP1) | P_Fld(temp_value[1], SHU_MISC_DRVING1_DQSDRVN1));
         vIO32WriteFldMulti((DDRPHY_REG_SHU_MISC_DRVING3 + save_to_where * SHU_GRP_DDRPHY_OFFSET), P_Fld(temp_value[2], SHU_MISC_DRVING3_DQSODTP2) | P_Fld(temp_value[3], SHU_MISC_DRVING3_DQSODTN2));
         vIO32WriteFldMulti((DDRPHY_REG_SHU_MISC_DRVING3 + save_to_where * SHU_GRP_DDRPHY_OFFSET), P_Fld(temp_value[2], SHU_MISC_DRVING3_DQSODTP) | P_Fld(temp_value[3], SHU_MISC_DRVING3_DQSODTN));
    }
    else
    #endif
    {
        vIO32WriteFldMulti((DDRPHY_REG_SHU_MISC_DRVING1 + save_to_where * SHU_GRP_DDRPHY_OFFSET), P_Fld(gDramcImpedanceResult[dq_freq_option][DRVP], SHU_MISC_DRVING1_DQSDRVP2) | P_Fld(gDramcImpedanceResult[dq_freq_option][DRVN], SHU_MISC_DRVING1_DQSDRVN2));
        vIO32WriteFldMulti((DDRPHY_REG_SHU_MISC_DRVING1 + save_to_where * SHU_GRP_DDRPHY_OFFSET), P_Fld(gDramcImpedanceResult[dq_freq_option][DRVP], SHU_MISC_DRVING1_DQSDRVP1) | P_Fld(gDramcImpedanceResult[dq_freq_option][DRVN], SHU_MISC_DRVING1_DQSDRVN1));
        vIO32WriteFldMulti((DDRPHY_REG_SHU_MISC_DRVING3 + save_to_where * SHU_GRP_DDRPHY_OFFSET), P_Fld(gDramcImpedanceResult[dq_freq_option][ODTP], SHU_MISC_DRVING3_DQSODTP2) | P_Fld(gDramcImpedanceResult[dq_freq_option][ODTN], SHU_MISC_DRVING3_DQSODTN2));
        vIO32WriteFldMulti((DDRPHY_REG_SHU_MISC_DRVING3 + save_to_where * SHU_GRP_DDRPHY_OFFSET), P_Fld(gDramcImpedanceResult[dq_freq_option][ODTP], SHU_MISC_DRVING3_DQSODTP) | P_Fld(gDramcImpedanceResult[dq_freq_option][ODTN], SHU_MISC_DRVING3_DQSODTN));
    }


    vIO32WriteFldMulti((DDRPHY_REG_SHU_MISC_DRVING2 + save_to_where * SHU_GRP_DDRPHY_OFFSET), P_Fld(gDramcImpedanceResult[ca_freq_option][DRVP], SHU_MISC_DRVING2_CMDDRVP2) | P_Fld(gDramcImpedanceResult[ca_freq_option][DRVN], SHU_MISC_DRVING2_CMDDRVN2));
    vIO32WriteFldMulti((DDRPHY_REG_SHU_MISC_DRVING2 + save_to_where * SHU_GRP_DDRPHY_OFFSET), P_Fld(gDramcImpedanceResult[ca_freq_option][DRVP], SHU_MISC_DRVING2_CMDDRVP1) | P_Fld(gDramcImpedanceResult[ca_freq_option][DRVN], SHU_MISC_DRVING2_CMDDRVN1));
    vIO32WriteFldMulti((DDRPHY_REG_SHU_MISC_DRVING4 + save_to_where * SHU_GRP_DDRPHY_OFFSET), P_Fld(gDramcImpedanceResult[ca_freq_option][ODTP], SHU_MISC_DRVING4_CMDODTP2) | P_Fld(gDramcImpedanceResult[ca_freq_option][ODTN], SHU_MISC_DRVING4_CMDODTN2));
    vIO32WriteFldMulti((DDRPHY_REG_SHU_MISC_DRVING4 + save_to_where * SHU_GRP_DDRPHY_OFFSET), P_Fld(gDramcImpedanceResult[ca_freq_option][ODTP], SHU_MISC_DRVING4_CMDODTP1) | P_Fld(gDramcImpedanceResult[ca_freq_option][ODTN], SHU_MISC_DRVING4_CMDODTN1));


    #if (fcFOR_CHIP_ID == fcA60868)
    vIO32WriteFldAlign((DDRPHY_REG_MISC_SHU_DRVING8 + save_to_where * SHU_GRP_DDRPHY_OFFSET), 0xA, MISC_SHU_DRVING8_CS_DRVP);
    vIO32WriteFldAlign((DDRPHY_REG_MISC_SHU_DRVING8 + save_to_where * SHU_GRP_DDRPHY_OFFSET), 0xA, MISC_SHU_DRVING8_CS_DRVN);
    #elif (fcFOR_CHIP_ID == fc8195)

    vIO32WriteFldAlign((DDRPHY_REG_MISC_SHU_DRVING8 + save_to_where * SHU_GRP_DDRPHY_OFFSET), 0xF, MISC_SHU_DRVING8_CS_DRVP);
    vIO32WriteFldAlign((DDRPHY_REG_MISC_SHU_DRVING8 + save_to_where * SHU_GRP_DDRPHY_OFFSET), 0x14, MISC_SHU_DRVING8_CS_DRVN);
    #endif

    DramcBroadcastOnOff(backup_broadcast);
}

#if IMPEDANCE_HW_CALIBRATION
static void Dramc_Hw_ImpedanceCal(DRAMC_CTX_T *p, DRAMC_IMP_T freq_region)
{
    U8 u1DrvType = 0;
    U32 u4DRVP_Result = 0xff, u4ODTN_Result = 0xff, u4DRVN_Result = 0xff;

    vAutoRefreshSwitch(p, ENABLE);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_CONF0), 0, SHU_CONF0_PBREFEN);

    for (u1DrvType = DRVP; u1DrvType < IMP_DRV_MAX; u1DrvType++)
    {
        if (u1DrvType == ODTP)
            continue;


        vImpCalVrefSel(p, freq_region, u1DrvType);
    }

    ImpedanceTracking_DisImpHw_Setting(p, DISABLE);

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_MISC_IMPCAL1), P_Fld(4, SHU_MISC_IMPCAL1_IMPCALCNT) | P_Fld(1, SHU_MISC_IMPCAL1_IMPCAL_CHKCYCLE));
    DramcImpedanceTrackingEnable(p);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_IMPCAL), 0, MISC_IMPCAL_IMPCAL_ECO_OPT);

    mcDELAY_US(16);

    u4DRVN_Result = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_IMPCAL_STATUS3), MISC_IMPCAL_STATUS3_DRVNDQ_SAVE_1);
    u4DRVP_Result = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_IMPCAL_STATUS3), MISC_IMPCAL_STATUS3_DRVPDQ_SAVE_1);
    u4ODTN_Result = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_IMPCAL_STATUS3), MISC_IMPCAL_STATUS3_ODTNDQ_SAVE_1);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_MISC_IMPCAL1), u4DRVP_Result, SHU_MISC_IMPCAL1_IMPDRVP);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_MISC_IMPCAL1), u4DRVN_Result, SHU_MISC_IMPCAL1_IMPDRVN);

    mcSHOW_DBG_MSG(("[HwImpedanceCal] DRVP=%d, DRVN=%d, ODTN=%d\n", u4DRVP_Result, u4DRVN_Result, u4ODTN_Result));

    gDramcImpedanceResult[freq_region][DRVP] = u4DRVP_Result;
    gDramcImpedanceResult[freq_region][DRVN] = u4DRVN_Result;
    gDramcImpedanceResult[freq_region][ODTP] = 0;
    gDramcImpedanceResult[freq_region][ODTN] = u4ODTN_Result;

    //vAutoRefreshSwitch(p, DISABLE);

}

#else
static U32 DramcSwImpCalResult(DRAMC_CTX_T *p, const char *drvType, U32 u4Fld)
{
    U32 u4ImpxDrv = 0, u4ImpCalResult = 0;
    U32 u4CheckImpChange = (u4Fld == SHU_MISC_IMPCAL1_IMPDRVP)? 1: 0;

    for (u4ImpxDrv = 0; u4ImpxDrv < 32; u4ImpxDrv++)
    {
#if 0
        if (u4ImpxDrv == 16)
            u4ImpxDrv = 29;
#endif

        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_MISC_IMPCAL1), u4ImpxDrv, u4Fld);
        mcDELAY_US(1);
        u4ImpCalResult = u4IO32ReadFldAlign((DDRPHY_REG_MISC_PHY_RGS_CMD), MISC_PHY_RGS_CMD_RGS_RIMPCALOUT);
        mcSHOW_DBG_MSG2(("OCD %s=%d ,CALOUT=%d\n", drvType, u4ImpxDrv, u4ImpCalResult));

        if (u4ImpCalResult == u4CheckImpChange)
        {
            mcSHOW_DBG_MSG2(("\nOCD %s calibration OK! %s=%d\n\n", drvType, drvType, u4ImpxDrv));
            break;
        }
    }

    if (u4ImpxDrv == 32)
    {
        u4ImpxDrv = 31;
        mcSHOW_DBG_MSG2(("\nOCD %s calibration FAIL! %s=%d\n\n", drvType, drvType, u4ImpxDrv));
    }

    return u4ImpxDrv;
}

static void Dramc_Sw_ImpedanceCal(DRAMC_CTX_T *p, DRAMC_IMP_T freq_region)
{
    U8 u1DrvType = 0, u1CALI_ENP = 0, u1CALI_ENN = 0;
    U32 u4DRVP_Result = 0xff, u4ODTN_Result = 0xff, u4DRVN_Result = 0xff;
    U32 u4SwImpCalResult = 0, u4DrvFld = 0;
    const char *drvStr = "NULL";

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_IMPCAL), 1, MISC_IMPCAL_IMPCAL_CALI_EN);
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_MISC_IMPCAL1), P_Fld(0, SHU_MISC_IMPCAL1_IMPDRVN) | P_Fld(0, SHU_MISC_IMPCAL1_IMPDRVP));


    for (u1DrvType = DRVP; u1DrvType < IMP_DRV_MAX; u1DrvType++)
    {
        if (u1DrvType == ODTP)
            continue;


        vImpCalVrefSel(p, freq_region, u1DrvType);

        switch (u1DrvType)
        {
            case DRVP:
                drvStr = "DRVP";
                u1CALI_ENP = 0x1;
                u1CALI_ENN = 0x0;
                u4DrvFld = SHU_MISC_IMPCAL1_IMPDRVP;
                u4DRVP_Result = 0;
                break;
            case DRVN:
            case ODTN:
                drvStr = (u1DrvType == DRVN)? "DRVN" : "ODTN";
                u1CALI_ENP = 0x0;
                u1CALI_ENN = (u1DrvType == DRVN)? 0x0: 0x1;
                u4DrvFld = SHU_MISC_IMPCAL1_IMPDRVN;
                break;
            default:
                mcSHOW_ERR_MSG(("[DramcSwImpedanceCal] Warnning: Need confirm u1DrvType for SW IMP Calibration !!!\n"));
                break;
        }


        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_IMPCAL), u1CALI_ENP, MISC_IMPCAL_IMPCAL_CALI_ENP);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_IMPCAL), u1CALI_ENN, MISC_IMPCAL_IMPCAL_CALI_ENN);

        mcSHOW_DBG_MSG2(("\n\n\tK %s\n", drvStr));


        vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_MISC_IMPCAL1), u4DRVP_Result, SHU_MISC_IMPCAL1_IMPDRVP);


        u4SwImpCalResult = DramcSwImpCalResult(p, drvStr, u4DrvFld);

        switch (u1DrvType)
        {
            case DRVP:
                u4DRVP_Result = u4SwImpCalResult;
                break;
            case DRVN:
                u4DRVN_Result = u4SwImpCalResult;
                break;
            case ODTN:
                u4ODTN_Result = u4SwImpCalResult;
                break;
            default:
                mcSHOW_ERR_MSG(("[DramcSwImpedanceCal] Warnning: Need confirm u4SwImpCalResult for SW IMP Calibration !!!\n"));
                break;
        }
    }

    mcSHOW_DBG_MSG(("[SwImpedanceCal] DRVP=%d, DRVN=%d, ODTN=%d\n", u4DRVP_Result, u4DRVN_Result, u4ODTN_Result));

    gDramcImpedanceResult[freq_region][DRVP] = u4DRVP_Result;
    gDramcImpedanceResult[freq_region][DRVN] = u4DRVN_Result;
    gDramcImpedanceResult[freq_region][ODTP] = 0;
    gDramcImpedanceResult[freq_region][ODTN] = u4ODTN_Result;

}
#endif

DRAM_STATUS_T DramcImpedanceCal(DRAMC_CTX_T *p, U8 u1Para, DRAMC_IMP_T freq_region)
{
    //U32 u4BaklReg_DDRPHY_MISC_IMP_CTRL0, u4BaklReg_DDRPHY_MISC_IMP_CTRL1;
    //U32 u4BaklReg_DRAMC_REG_IMPCAL;
    U8 backup_channel;
    U32 backup_broadcast;
    U8 u1Drv05 = 0, u1DDR4 = 0;

    U32 u4RegBackupAddress[] =
    {
        (DDRPHY_REG_MISC_IMPCAL),
        #if IMPEDANCE_HW_CALIBRATION
        (DDRPHY_REG_MISC_IMPCAL + SHIFT_TO_CHB_ADDR),
        (DRAMC_REG_ADDR(DRAMC_REG_DDRCOMMON0)),
        (DRAMC_REG_DRAMC_PD_CTRL),
        (DRAMC_REG_DRAMC_PD_CTRL+ SHIFT_TO_CHB_ADDR),
        #if (CHANNEL_NUM > 2)
        (DDRPHY_REG_MISC_IMPCAL + SHIFT_TO_CHC_ADDR),
        (DDRPHY_REG_MISC_IMPCAL + SHIFT_TO_CHD_ADDR),
        #endif
        (DDRPHY_REG_MISC_CTRL0),
        (DDRPHY_REG_MISC_CTRL0 + SHIFT_TO_CHB_ADDR),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_MISC_DRVING1)),
        (DRAMC_REG_ADDR(DDRPHY_REG_SHU_MISC_DRVING2)),
        (DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0)),
        #endif
    };

    backup_broadcast = GetDramcBroadcast();
    DramcBroadcastOnOff(DRAMC_BROADCAST_OFF);


    vSetCalibrationResult(p, DRAM_CALIBRATION_SW_IMPEDANCE, DRAM_FAIL);

#if VENDER_JV_LOG
    vPrintCalibrationBasicInfo_ForJV(p);
#else
    vPrintCalibrationBasicInfo(p);
#endif

    mcSHOW_DBG_MSG(("[DramcImpedenceCal]\n"));


    vIO32WriteFldMulti_All(DDRPHY_REG_MISC_LP_CTRL, P_Fld(0x0, MISC_LP_CTRL_RG_ARDMSUS_10) | \
                        P_Fld(0x0, MISC_LP_CTRL_RG_ARDMSUS_10_LP_SEL) | \
                        P_Fld(0x0, MISC_LP_CTRL_RG_RIMP_DMSUS_10) | \
                        P_Fld(0x0, MISC_LP_CTRL_RG_RIMP_DMSUS_10_LP_SEL));

    vIO32WriteFldAlign_All(DDRPHY_REG_MISC_IMPCAL, 0, MISC_IMPCAL_IMPCAL_HW);
    backup_channel = p->channel;
    vSetPHY2ChannelMapping(p, CHANNEL_A);


    //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(DDRPHY_REG_MISC_IMPCAL));
    DramcBackupRegisters(p, u4RegBackupAddress, ARRAY_SIZE(u4RegBackupAddress));

#if IMPEDANCE_HW_CALIBRATION
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DDRCOMMON0), 1, DDRCOMMON0_LPDDR4EN);
    vIO32WriteFldMulti_All(DRAMC_REG_DRAMC_PD_CTRL, P_Fld(1, DRAMC_PD_CTRL_PHYCLKDYNGEN)\
                                                   | P_Fld(1, DRAMC_PD_CTRL_DCMEN));
#endif


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_MISC_IMP_CTRL1), 0, MISC_IMP_CTRL1_RG_RIMP_PRE_EN);
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_MISC_IMPCAL), P_Fld(0, MISC_IMPCAL_IMPCAL_CALI_ENN) | P_Fld(1, MISC_IMPCAL_IMPCAL_IMPPDP) | \
                                      P_Fld(1, MISC_IMPCAL_IMPCAL_IMPPDN));

        u1DDR4 = 1;

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_MISC_IMP_CTRL1), P_Fld(1, MISC_IMP_CTRL1_RG_IMP_EN) | \
                        P_Fld(0, MISC_IMP_CTRL1_RG_RIMP_DDR3_SEL) | \
                        P_Fld(1, MISC_IMP_CTRL1_RG_RIMP_VREF_EN) | \
                        P_Fld(u1DDR4, MISC_IMP_CTRL1_RG_RIMP_DDR4_SEL));
    mcDELAY_US(1);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD12), u1Drv05, SHU_CA_CMD12_RG_RIMP_DRV05);

    #if IMPEDANCE_HW_CALIBRATION
        Dramc_Hw_ImpedanceCal(p, freq_region);
    #else
        Dramc_Sw_ImpedanceCal(p, freq_region);
    #endif

    DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress) / sizeof(U32));
    //vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_REG_MISC_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);



    #if 0
    if (u1Para)
    {
        u4ODTN_Result = ImpedanceAdjustment_Hynix(u4ODTN_Result, u1Para);
    }
    #endif

#if RUNTIME_SHMOO_RELEATED_FUNCTION && SUPPORT_SAVE_TIME_FOR_CALIBRATION
    {
        U8 u1drv;
        {
            for (u1drv = 0; u1drv < 4; u1drv++)
            {
                {
                    gDramcImpedanceResult[freq_region][u1drv] = p->pSavetimeData->u1SwImpedanceResule[freq_region][u1drv];
                    vSetCalibrationResult(p, DRAM_CALIBRATION_SW_IMPEDANCE, DRAM_FAST_K);
                }
            }
        }
    }
#endif

    mcSHOW_DBG_MSG(("freq_region=%d, Reg: DRVP=%d, DRVN=%d, ODTN=%d\n", freq_region, gDramcImpedanceResult[freq_region][DRVP],
                                         gDramcImpedanceResult[freq_region][DRVN], gDramcImpedanceResult[freq_region][ODTN]));

#if APPLY_SIGNAL_WAVEFORM_SETTINGS_ADJUST
    if ((p->dram_type == TYPE_LPDDR4) && (freq_region == 0))
    {
        gDramcImpedanceResult[freq_region][DRVP] = SwImpedanceAdjust(gDramcImpedanceResult[freq_region][DRVP], gDramcSwImpedanceAdjust[freq_region][DRVP]);
        gDramcImpedanceResult[freq_region][DRVN] = SwImpedanceAdjust(gDramcImpedanceResult[freq_region][DRVN], gDramcSwImpedanceAdjust[freq_region][ODTN]);
    }
    else
    {
        gDramcImpedanceResult[freq_region][DRVP] = SwImpedanceAdjust(gDramcImpedanceResult[freq_region][DRVP], gDramcSwImpedanceAdjust[freq_region][DRVP]);
        gDramcImpedanceResult[freq_region][ODTN] = SwImpedanceAdjust(gDramcImpedanceResult[freq_region][ODTN], gDramcSwImpedanceAdjust[freq_region][ODTN]);
    }

    mcSHOW_DBG_MSG(("freq_region=%d, Reg: DRVP=%d, DRVN=%d, ODTN=%d (After Adjust)\n", freq_region, gDramcImpedanceResult[freq_region][DRVP],
                                         gDramcImpedanceResult[freq_region][DRVN], gDramcImpedanceResult[freq_region][ODTN]));
#endif

#if 0

    if (gDramcSwImpedanceResult[freq_region][DRVP] >= 31 && (freq_region == 0) ) {
        mcSHOW_DBG_MSG(("SLT_BIN2\n"));
        while (1);
    }
#else

    if (freq_region==0)
    {
        if (!(gDramcImpedanceResult[freq_region][DRVP] >= 1 && gDramcImpedanceResult[freq_region][DRVP] <= 0x16) ||
            !(gDramcImpedanceResult[freq_region][DRVN] >= 10 && gDramcImpedanceResult[freq_region][DRVN] <= 23) ||
            !(gDramcImpedanceResult[freq_region][ODTN] >= 3 && gDramcImpedanceResult[freq_region][ODTN] <= 0x13)) {
            #if defined(SLT)
            mcSHOW_ERR_MSG(("[DramcInit] SLT_BIN2\n"));
            while (1);
            #else
                mcSHOW_ERR_MSG(("[Warning] freq_region = %d, Unexpected value for impedance calibration\n", freq_region));
                #if __ETT__
                    while (1);
                #endif
            #endif
        }else{
            vSetCalibrationResult(p, DRAM_CALIBRATION_SW_IMPEDANCE, DRAM_OK);
        }
    }
    else
    {

        if (!(gDramcImpedanceResult[freq_region][DRVP] >= 1 && gDramcImpedanceResult[freq_region][DRVP] <= 24) ||
            !(gDramcImpedanceResult[freq_region][DRVN] >= 10 && gDramcImpedanceResult[freq_region][DRVN] <= 30) ||
            !(gDramcImpedanceResult[freq_region][ODTN] >= 3 && gDramcImpedanceResult[freq_region][ODTN] <= 12)) {
            #if defined(SLT)
            mcSHOW_ERR_MSG(("[DramcInit] SLT_BIN2\n"));
            while (1);
            #else
                mcSHOW_ERR_MSG(("[Warning] freq_region = %d, Unexpected value for impedance calibration\n", freq_region));
                #if __ETT__
                    while (1);
                #endif
            #endif
        }else{
            vSetCalibrationResult(p, DRAM_CALIBRATION_SW_IMPEDANCE, DRAM_OK);
        }
    }
#endif

#if PIN_CHECK_TOOL
    if((gDramcImpedanceResult[freq_region][ODTN] ==0)||(gDramcImpedanceResult[freq_region][ODTN] >=31))
    {
        mcSHOW_DBG_MSG(("[WARNING] freq_region = %d, ODTN = %d ==> unexpect value\n", freq_region, gDramcImpedanceResult[freq_region][ODTN]));
        PINInfo_flashtool.IMP_ERR_FLAG |= (0x1<<(freq_region+ODTN));
    }
    else if((gDramcImpedanceResult[freq_region][DRVP] ==0)||(gDramcImpedanceResult[freq_region][DRVP] >=31))
    {
        mcSHOW_DBG_MSG(("[WARNING] freq_region = %d, DRVP = %d ==> unexpect value\n", freq_region, gDramcImpedanceResult[freq_region][DRVP]));
        PINInfo_flashtool.IMP_ERR_FLAG |= (0x1<<(freq_region+DRVP));
    }
    else if((gDramcImpedanceResult[freq_region][DRVN] ==0)||(gDramcImpedanceResult[freq_region][DRVN] >=31))
    {
        mcSHOW_DBG_MSG(("[WARNING] freq_region = %d, DRVN = %d ==> unexpect value\n", freq_region, gDramcImpedanceResult[freq_region][DRVN]));
        PINInfo_flashtool.IMP_ERR_FLAG |= (0x1<<(freq_region+DRVN));
    }
#endif

    mcSHOW_DBG_MSG4(("[DramcImpedanceCal] Done\n\n"));

    vSetPHY2ChannelMapping(p, backup_channel);
    DramcBroadcastOnOff(backup_broadcast);

    return DRAM_OK;
}
#endif

#if ENABLE_WRITE_DBI || TX_K_DQM_WITH_WDBI
void DramcWriteShiftMCKForWriteDBI(DRAMC_CTX_T *p, S8 iShiftMCK)
{
    U8 ucDataRateDivShift = 0;
    S8 s1UIMove = 0;

    ucDataRateDivShift = u1MCK2UI_DivShift(p);
    s1UIMove = iShiftMCK * (S8)(1 << ucDataRateDivShift);
    ShiftDQUI(p, s1UIMove, ALL_BYTES);
}
#endif

#if ENABLE_DUTY_SCAN_V2

#define DutyPrintAllLog         0

#define DUTY_OFFSET_START -28
#define DUTY_OFFSET_END 28
#define DUTY_OFFSET_STEP 4

#define CLOCK_PI_START 0
#define CLOCK_PI_END 63

#if FOR_DV_SIMULATION_USED
#define CLOCK_PI_STEP 8
#else
#define CLOCK_PI_STEP 2
#endif

#define ClockDutyFailLowerBound 4500
#define ClockDutyFailUpperBound 5500
#define ClockDutyMiddleBound    5000


static U8 DramcDutyDelayRGSettingConvert(DRAMC_CTX_T *p, S8 scDutyDelay,
    U8 *tDly)
{
    U8 tDelay;

    if (scDutyDelay < 0)
    {
        tDelay = -scDutyDelay;
    }
    else if (scDutyDelay > 0)
    {
        tDelay = scDutyDelay + (1 << 5);
    }
    else
    {
        tDelay = 0;
    }

    *tDly = tDelay;
    return tDelay;
}

static void DramcClockDutySetClkDelayCell(DRAMC_CTX_T *p, S8 *scDutyDelay)
{
    U8 u1ShuffleIdx = 0;
    U32 save_offset;
    U8 tDelay;

    DramcDutyDelayRGSettingConvert(p, scDutyDelay[0], &tDelay);

#if DUTY_SCAN_V2_ONLY_K_HIGHEST_FREQ
    for(u1ShuffleIdx = 0; u1ShuffleIdx<DRAM_DFS_SRAM_MAX; u1ShuffleIdx++)
#endif
    {
        save_offset = u1ShuffleIdx * SHU_GRP_DDRPHY_OFFSET;
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_TXDUTY + save_offset),
            P_Fld(tDelay, SHU_CA_TXDUTY_DA_TX_ARCLK_DUTY_DLY));
    }
}

static void DQSDutyScan_SetDqsDelayCell(DRAMC_CTX_T *p, S8 *scDutyDelay)
{
    U8 u1ShuffleIdx = 0, u1DQSIdx;
    U32 save_offset;
    U8 tDelay[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++)
    {
        DramcDutyDelayRGSettingConvert(p, scDutyDelay[u1DQSIdx], &(tDelay[u1DQSIdx]));
    }

#if DUTY_SCAN_V2_ONLY_K_HIGHEST_FREQ
    for(u1ShuffleIdx = 0; u1ShuffleIdx<DRAM_DFS_SRAM_MAX; u1ShuffleIdx++)
#endif
    {
        {
            for(u1DQSIdx = 0; u1DQSIdx<2; u1DQSIdx++)
            {
                save_offset = u1ShuffleIdx * SHU_GRP_DDRPHY_OFFSET + u1DQSIdx*DDRPHY_AO_B0_B1_OFFSET;
                vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_TXDUTY) + save_offset,
                    P_Fld(tDelay[u1DQSIdx], SHU_B0_TXDUTY_DA_TX_ARDQS_DUTY_DLY_B0));
            }
        }
    }
}

#if APPLY_DQDQM_DUTY_CALIBRATION
static void DQDQMDutyScan_SetDQDQMDelayCell(DRAMC_CTX_T *p, U8 u1ChannelIdx, S8 *scDutyDelay, U8 k_type)
{
    U8 u1ShuffleIdx = 0, u1DQSIdx;
    U32 save_offset;
    U8 tDelay[2];

    for(u1DQSIdx=0; u1DQSIdx<2; u1DQSIdx++)
    {
        DramcDutyDelayRGSettingConvert(p, scDutyDelay[u1DQSIdx], &(tDelay[u1DQSIdx]));
    }

#if DUTY_SCAN_V2_ONLY_K_HIGHEST_FREQ
    for(u1ShuffleIdx = 0; u1ShuffleIdx<DRAM_DFS_SRAM_MAX; u1ShuffleIdx++)
#endif
    {
        for(u1DQSIdx = 0; u1DQSIdx<2; u1DQSIdx++)
        {
            save_offset = u1ShuffleIdx * SHU_GRP_DDRPHY_OFFSET + u1DQSIdx*DDRPHY_AO_B0_B1_OFFSET;

            if (k_type == DutyScan_Calibration_K_DQ)
            {
                vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_TXDUTY) + save_offset,
                    P_Fld(tDelay[u1DQSIdx], SHU_B0_TXDUTY_DA_TX_ARDQ_DUTY_DLY_B0));
            }

            if (k_type == DutyScan_Calibration_K_DQM)
            {
                vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_TXDUTY) + save_offset,
                    P_Fld(tDelay[u1DQSIdx], SHU_B0_TXDUTY_DA_TX_ARDQM_DUTY_DLY_B0));
            }
        }
    }
}

#if 0
void DQDQMDutyScan_CopyDQRG2DQMRG(DRAMC_CTX_T *p)
{
    U8 u1ShuffleIdx = 0, u1DQSIdx, u1RankIdx = 0;
    U32 save_offset;
    U8 ucDQDQMDelay;
    U8 ucRev_DQDQM_Bit0, ucRev_DQDQM_Bit1;

#if DUTY_SCAN_V2_ONLY_K_HIGHEST_FREQ
    for(u1ShuffleIdx = 0; u1ShuffleIdx<DRAM_DFS_SRAM_MAX; u1ShuffleIdx++)
#endif
    {
            for(u1DQSIdx = 0; u1DQSIdx<2; u1DQSIdx++)
            {
            save_offset = u1ShuffleIdx * SHU_GRP_DDRPHY_OFFSET + u1DQSIdx*DDRPHY_AO_B0_B1_OFFSET_0X80;

            ucDQDQMDelay = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU_B0_DQ3) + save_offset, SHU_B0_DQ3_RG_ARDQ_DUTYREV_B0_DQ_DLY);
            ucRev_DQDQM_Bit0 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU_B0_DQ3) + save_offset, SHU_B0_DQ3_RG_TX_ARDQS0_PU_PRE_B0_BIT0);
            ucRev_DQDQM_Bit1 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU_B0_DQ3) + save_offset, SHU_B0_DQ3_RG_TX_ARDQS0_PU_PRE_B0_BIT0);

            vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU_B0_DQ3) + save_offset, P_Fld(ucDQDQMDelay, SHU_B0_DQ3_RG_ARDQ_DUTYREV_B0_DQM_DLY)
                                                                    | P_Fld(ucRev_DQDQM_Bit0, SHU_B0_DQ3_RG_TX_ARDQS0_PU_B0_BIT0)
                                                                    | P_Fld(ucRev_DQDQM_Bit1, SHU_B0_DQ3_RG_TX_ARDQS0_PU_B0_BIT1));
            }
        }
    }
#endif
#endif

S8 gcFinal_K_CLK_delay_cell[DQS_BYTE_NUMBER];
S8 gcFinal_K_DQS_delay_cell[DQS_BYTE_NUMBER];
S8 gcFinal_K_WCK_delay_cell[DQS_BYTE_NUMBER];
#if APPLY_DQDQM_DUTY_CALIBRATION
S8 gcFinal_K_DQ_delay_cell[DQS_BYTE_NUMBER];
S8 gcFinal_K_DQM_delay_cell[DQS_BYTE_NUMBER];
#endif
typedef struct _TEST_DUTY_AVG_LOG_PARAMETER_T
{
    U32 ucmost_approach_50_percent;
    S8  scFinal_clk_delay_cell;
    U32 ucFinal_period_duty_averige;
    U32 ucFinal_period_duty_max;
    U32 ucFinal_period_duty_min;
    U32 ucFinal_duty_max_clk_dly;
    U32 ucFinal_duty_min_clk_dly;
} TEST_DUTY_AVG_LOG_PARAMETER_T;

void DramcNewDutyCalibration(DRAMC_CTX_T *p)
{
    U8 u1backup_rank;
    BOOL isLP4_DSC = (p->DRAMPinmux == PINMUX_DSC)?1:0;
    U32 backup_DDRPHY_REG_B0_DQ2=0, backup_DDRPHY_REG_B1_DQ2=0, backup_DDRPHY_REG_CA_CMD2=0;
    U32 backup_DDRPHY_REG_SHU_B0_DQ13=0, backup_DDRPHY_REG_SHU_B1_DQ13=0, backup_DDRPHY_REG_SHU_CA_CMD13=0;

#if(DQS_DUTY_SLT_CONDITION_TEST)
        U16 u2TestCnt, u2FailCnt=0, u2TestCntTotal =20;
        U8 u1ByteIdx, u1PI_FB;
        U32 u4Variance;
#endif


    u1backup_rank = u1GetRank(p);
    vSetRank(p, RANK_0);


    backup_DDRPHY_REG_B0_DQ2 = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ2));
    if (!isLP4_DSC)
        backup_DDRPHY_REG_B1_DQ2 = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ2));
    else
        backup_DDRPHY_REG_CA_CMD2 = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD2));
    backup_DDRPHY_REG_SHU_B0_DQ13 = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ13));
    if (!isLP4_DSC)
        backup_DDRPHY_REG_SHU_B1_DQ13 = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ13));
    else
        backup_DDRPHY_REG_SHU_CA_CMD13 = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD13));


    vSetCalibrationResult(p, DRAM_CALIBRATION_DUTY_SCAN, DRAM_FAIL);

#if !FT_DSIM_USED
#if DUTY_SCAN_V2_ONLY_K_HIGHEST_FREQ
    if (p->frequency == u2DFSGetHighestFreq(p))
#else

#endif
#endif
    {
        U8 u1ChannelIdx;
        U8 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, u1ChannelIdx);

                DramcClockDutySetClkDelayCell(p, p->pSavetimeData->s1ClockDuty_clk_delay_cell[p->channel]);
                DQSDutyScan_SetDqsDelayCell(p, p->pSavetimeData->s1DQSDuty_clk_delay_cell[p->channel]);
                #if APPLY_DQDQM_DUTY_CALIBRATION
                DQDQMDutyScan_SetDQDQMDelayCell(p, p->channel, p->pSavetimeData->s1DQMDuty_clk_delay_cell[p->channel], DutyScan_Calibration_K_DQM);
                DQDQMDutyScan_SetDQDQMDelayCell(p, p->channel, p->pSavetimeData->s1DQDuty_clk_delay_cell[p->channel], DutyScan_Calibration_K_DQ);
                #endif
            }
            vSetPHY2ChannelMapping(p, u1backup_channel);

            vSetCalibrationResult(p, DRAM_CALIBRATION_DUTY_SCAN, DRAM_FAST_K);
            return;
        }
        #endif
    }

    OECKCKE_Control(p, ENABLE);

    vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_REG_B0_DQ2), backup_DDRPHY_REG_B0_DQ2);
    if (!isLP4_DSC)
        vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_REG_B1_DQ2), backup_DDRPHY_REG_B1_DQ2);
    else
        vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_REG_CA_CMD2), backup_DDRPHY_REG_CA_CMD2);
    vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B0_DQ13), backup_DDRPHY_REG_SHU_B0_DQ13);
    if (!isLP4_DSC)
        vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_B1_DQ13), backup_DDRPHY_REG_SHU_B1_DQ13);
    else
        vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_REG_SHU_CA_CMD13), backup_DDRPHY_REG_SHU_CA_CMD13);


    vSetRank(p, u1backup_rank);
}
#endif
