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

//-----------------------------------------------------------------------------
// Include files
//-----------------------------------------------------------------------------
#include "dramc_common.h"
#include "dramc_int_global.h" //for gu1BroadcastIsLP4
#include "dramc_dv_init.h"
#include "x_hal_io.h"
#if (FOR_DV_SIMULATION_USED == 0)
#include "dramc_top.h"
#endif
#include "emi.h"
//#include "dramc_register.h"
#if __ETT__
#include <barriers.h>
#endif
#if DRAM_AUXADC_CONFIG
#include <mtk_auxadc_sw.h>
#endif
//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------

#if (fcFOR_CHIP_ID == fcA60868)
U8 u1EnterRuntime;
#endif

U8 u1IsLP4Family(DRAM_DRAM_TYPE_T dram_type)
{
    if (dram_type == TYPE_LPDDR5)
        return FALSE;
    else
        return TRUE;
}

u8 is_lp5_family(DRAMC_CTX_T *p)
{
    return p->dram_type == TYPE_LPDDR5? TRUE: FALSE;
}

u8 is_heff_mode(DRAMC_CTX_T *p)
{
    u8 res = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_COMMON0),
            SHU_COMMON0_LP5HEFF_MODE);
    mcSHOW_DBG_MSG5(("HEFF Mode: %d\n", res));
    return res? TRUE: FALSE;
}

#if FOR_DV_SIMULATION_USED
U8 u1BroadcastOnOff = 0;
#endif
U32 GetDramcBroadcast(void)
{
#if (fcFOR_CHIP_ID == fcA60868)
    return 0;
#endif

#if (FOR_DV_SIMULATION_USED == 0)
    return *((volatile unsigned int *)(DRAMC_WBR));
#else
    return u1BroadcastOnOff;
#endif
}

void DramcBroadcastOnOff(U32 bOnOff)
{
#if (FOR_DV_SIMULATION_USED==0 && SW_CHANGE_FOR_SIMULATION==0)

    #if (fcFOR_CHIP_ID == fcA60868)
        return;
    #endif

    #if __Petrus_TO_BE_PORTING__
        U8 u1BroadcastStatus = 0;

        u1BroadcastStatus = (*((volatile unsigned int *)(INFRA_RSVD3)) >> 8) & 0x3;
        if (u1BroadcastStatus & 0x1)
        {
            if (bOnOff == DRAMC_BROADCAST_ON)
                *((volatile unsigned int *)(DRAMC_WBR_SET)) = DRAMC_BROADCAST_SET;
            else
                *((volatile unsigned int *)(DRAMC_WBR_CLR)) = DRAMC_BROADCAST_CLR;
        }
        else
    #endif
		if (bOnOff == DRAMC_BROADCAST_ON) {
			if (channel_num_auxadc > 2)
                *((volatile unsigned int *)(DRAMC_WBR)) = DRAMC_BROADCAST_ON_4CH;
			else
				*((volatile unsigned int *)(DRAMC_WBR)) = DRAMC_BROADCAST_ON_2CH;
			}
		else {
            *((volatile unsigned int *)(DRAMC_WBR)) = bOnOff;
			}
        dsb();
#endif

#if (FOR_DV_SIMULATION_USED == 1)
        if (gu1BroadcastIsLP4 == TRUE)
        {
            #if (fcFOR_CHIP_ID == fcA60868)
            bOnOff = 0;
            #endif
            if (bOnOff)
            {
                broadcast_on();
                mcSHOW_DBG_MSG2(("Broadcast ON\n"));
                u1BroadcastOnOff = bOnOff;
            }
            else
            {
                broadcast_off();
                mcSHOW_DBG_MSG2(("Broadcast OFF\n"));
                u1BroadcastOnOff = bOnOff;
            }
        }
#endif

#ifdef DUMP_INIT_RG_LOG_TO_DE
        if(gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag)
        {
            U8 u1BroadcastStatus = 0;
            U32 addr, val;

            addr = DRAMC_WBR;
            val = bOnOff;
            // *((volatile unsigned int *)(DRAMC_WBR)) = bOnOff;

            mcSHOW_DUMP_INIT_RG_MSG(("*((UINT32P)(0x%x)) = 0x%x;\n",addr, val));
    //        mcDELAY_MS(1);
#if (FOR_DV_SIMULATION_USED==0)
            GPT_Delay_ms(1);
#endif
        }
#endif
    }



#if __ETT__
const U32 u4Cannot_Use_Dramc_WBR_Reg[]=
{
    DDRPHY_REG_CA_DLL_ARPI5,
    DDRPHY_REG_B0_DLL_ARPI5,
    DDRPHY_REG_B1_DLL_ARPI5,

    DDRPHY_REG_SHU_CA_DLL0,
    DDRPHY_REG_SHU_CA_DLL1,

    DDRPHY_REG_CA_LP_CTRL0,

    DDRPHY_REG_MISC_DVFSCTL2,
    DDRPHY_REG_MISC_SHU_OPT,

    DDRPHY_REG_MISC_DVFSCTL,
    DDRPHY_REG_MISC_DVFSCTL3,

    DDRPHY_REG_MISC_CKMUX_SEL,
    DRAMC_REG_DVFS_CTRL0
};
#define CANNOT_USE_WBR_SIZE ((sizeof(u4Cannot_Use_Dramc_WBR_Reg)) / (sizeof(U32)))
void CheckDramcWBR(U32 u4address)
{

    U32 i, channel_and_value;
    if (GetDramcBroadcast()==DRAMC_BROADCAST_ON)
    {
        #if (CHANNEL_NUM > 2)
			if (channel_num_auxadc > 2) {
            channel_and_value = 0x3;
				}
        #else
            channel_and_value = 0x1;
        #endif
        if ((((u4address - Channel_A_DRAMC_NAO_BASE_VIRTUAL) >> POS_BANK_NUM) & channel_and_value) != CHANNEL_A)
        {
            mcSHOW_ERR_MSG(("Error! virtual address 0x%x is not CHA and cannot use Dramc WBR\n", u4address));
            while (1);
        }
            for (i = 0; i < CANNOT_USE_WBR_SIZE; i++)
            {
                if (u4Cannot_Use_Dramc_WBR_Reg[i] == u4address)
                {
                    mcSHOW_ERR_MSG(("Error! virtual address 0x%x cannot use Dramc WBR\n", u4address));
                    while (1);
                }
             }
     }
}
#endif

void vSetPHY2ChannelMapping(DRAMC_CTX_T *p, U8 u1Channel)
{
    p->channel = (DRAM_CHANNEL_T)u1Channel;
}

U8 vGetPHY2ChannelMapping(DRAMC_CTX_T *p)
{
    return p->channel;
}
#if 0
static U8 GetChannelInfoToConf(DRAMC_CTX_T *p)
{
    U8 u1ch_num = CHANNEL_NUM;
#if ((fcFOR_CHIP_ID == fc8195) && (FOR_DV_SIMULATION_USED == 0 && SW_CHANGE_FOR_SIMULATION == 0))
    EMI_SETTINGS *emi_set;
    U32 u4value = 0;

    emi_set = &g_default_emi_setting;

    u4value = (emi_set->EMI_CONA_VAL >> 8) & 0x3;

    if (u4value == 0)
        u1ch_num = CHANNEL_SINGLE;
    else if (u4value == 1)
        u1ch_num = CHANNEL_DUAL;
#if (CHANNEL_NUM > 2)
	    else if (u4value == 2)
			if (channel_num_auxadc > 2) {
		        u1ch_num = CHANNEL_FOURTH;
				}
#endif
    mcSHOW_DBG_MSG2(("Channel num: %d, CONA[0x%x]\n", u1ch_num, emi_set->EMI_CONA_VAL));
#endif
    return u1ch_num;
}
#endif
void vSetChannelNumber(DRAMC_CTX_T *p)
{
#if DRAM_AUXADC_CONFIG
    p->support_channel_num = channel_num_auxadc;//GetChannelInfoToConf(p);
#else
    p->support_channel_num = CHANNEL_FOURTH;
#endif
}

void vSetRank(DRAMC_CTX_T *p, U8 ucRank)
{
    p->rank = (DRAM_RANK_T)ucRank;
}

U8 u1GetRank(DRAMC_CTX_T *p)
{
    return p->rank;
}

void vSetRankNumber(DRAMC_CTX_T *p)
{
#if(FOR_DV_SIMULATION_USED==0 && SW_CHANGE_FOR_SIMULATION==0)
    if (u4IO32ReadFldAlign(DRAMC_REG_SA_RESERVE, SA_RESERVE_SINGLE_RANK) == 1)
    {
        p->support_rank_num =RANK_SINGLE;
    }
    else
#endif
    {
        p->support_rank_num = RANK_DUAL;
    }
}

void vSetFSPNumber(DRAMC_CTX_T *p)
{
        p->support_fsp_num = 2;
}

static void setFreqGroup(DRAMC_CTX_T *p)
{


    {
        if (p->frequency <= 200)
        {
            p->freqGroup = 200;
        }
        else if (p->frequency <= 400)
        {
            p->freqGroup = 400;
        }
        else if (p->frequency <= 600)
        {
            p->freqGroup = 600;
        }
        else if (p->frequency <= 800)
        {
            p->freqGroup = 800;
        }
        else if (p->frequency <= 933)
        {
            p->freqGroup = 933;
        }
        else if (p->frequency <= 1200)
        {
            p->freqGroup = 1200;
        }
        else if (p->frequency <= 1333)
        {
            p->freqGroup = 1333;
        }
        else if (p->frequency <= 1600)
        {
            p->freqGroup = 1600;
        }
        else if (p->frequency <= 1866)
        {
            p->freqGroup = 1866;
        }
        else
        {
            p->freqGroup = 2133;
        }
    }

    mcSHOW_DBG_MSG4(("[setFreqGroup] p-> frequency %u, freqGroup: %u\n", p->frequency, p->freqGroup));
    return;
}


#define CKGEN_FMETER 0x0
#define ABIST_FMETER 0x1

U16 gddrphyfmeter_value[DRAM_DFS_SRAM_MAX] = {0};

U16 DDRPhyGetRealFreq(DRAMC_CTX_T *p)
{
    U8 u1SRAMShuLevel = vGet_Current_SRAMIdx(p);


    if(gddrphyfmeter_value[u1SRAMShuLevel])
    {
        return gddrphyfmeter_value[u1SRAMShuLevel];
    }else{
        mcSHOW_ERR_MSG(("gddrphyfmeter_value[%d] = 0, return p->frequency\n", u1SRAMShuLevel));
        return p->frequency;
    }
}

#if __ETT__  || defined(SLT)
void GetPhyPllFrequency(DRAMC_CTX_T *p)
{

    U8 u1ShuLevel = u4IO32ReadFldAlign(DDRPHY_REG_DVFS_STATUS, DVFS_STATUS_OTHER_SHU_GP);
    U32 u4PLL5_ADDR = DDRPHY_REG_SHU_PHYPLL1 + SHU_GRP_DDRPHY_OFFSET * u1ShuLevel;
    U32 u4PLL8_ADDR = DDRPHY_REG_SHU_PHYPLL2 + SHU_GRP_DDRPHY_OFFSET * u1ShuLevel;
    U32 u4B0_DQ = DDRPHY_REG_SHU_B0_DQ1 + SHU_GRP_DDRPHY_OFFSET * u1ShuLevel;
    U32 u4PLL3_ADDR = DDRPHY_REG_SHU_PHYPLL3 + SHU_GRP_DDRPHY_OFFSET * u1ShuLevel;

    U32 u4B0_DQ6 = DDRPHY_REG_SHU_B0_DQ6 + SHU_GRP_DDRPHY_OFFSET * u1ShuLevel;

    U32 u4SDM_PCW = u4IO32ReadFldAlign(u4PLL5_ADDR, SHU_PHYPLL1_RG_RPHYPLL_SDM_PCW);
    U32 u4PREDIV = u4IO32ReadFldAlign(u4PLL8_ADDR, SHU_PHYPLL2_RG_RPHYPLL_PREDIV);
    U32 u4POSDIV = u4IO32ReadFldAlign(u4PLL8_ADDR, SHU_PHYPLL2_RG_RPHYPLL_POSDIV);
    U32 u4CKDIV4 = u4IO32ReadFldAlign(u4B0_DQ, SHU_B0_DQ1_RG_ARPI_MIDPI_CKDIV4_EN_B0);
    U8 u1FBKSEL = u4IO32ReadFldAlign(u4PLL3_ADDR, SHU_PHYPLL3_RG_RPHYPLL_FBKSEL);

    U8 u1SopenDQ = u4IO32ReadFldAlign(u4B0_DQ6, SHU_B0_DQ6_RG_ARPI_SOPEN_EN_B0);
    U8 u1OpenDQ = u4IO32ReadFldAlign(u4B0_DQ6, SHU_B0_DQ6_RG_ARPI_OPEN_EN_B0);

    U32 u4VCOFreq = (((52>>u4PREDIV)*(u4SDM_PCW>>8))>>u4POSDIV) << u1FBKSEL;
    U32 u4DataRate = u4VCOFreq>>u4CKDIV4;
    if ((u1SopenDQ == ENABLE)||(u1OpenDQ == ENABLE))
        u4DataRate >>= 2;

    //mcSHOW_DBG_MSG(("PCW=0x%X, u4PREDIV=%d, u4POSDIV=%d, CKDIV4=%d, DataRate=%d\n", u4SDM_PCW, u4PREDIV, u4POSDIV, u4CKDIV4, u4DataRate));
    mcSHOW_DBG_MSG2(("[F] DataRate=%d at SHU%d\n", u4DataRate, u1ShuLevel));
}
#endif

DRAM_PLL_FREQ_SEL_T vGet_PLL_FreqSel(DRAMC_CTX_T *p)
{
    return p->pDFSTable->freq_sel;
}

void vSet_PLL_FreqSel(DRAMC_CTX_T *p, DRAM_PLL_FREQ_SEL_T sel)
{
    p->pDFSTable->freq_sel = sel;
}

DDR800_MODE_T vGet_DDR_Loop_Mode(DRAMC_CTX_T *p)
{
    return p->pDFSTable->ddr_loop_mode;
}

void vSet_Div_Mode(DRAMC_CTX_T *p, DIV_MODE_T eMode)
{
    p->pDFSTable->divmode = eMode;
}

DIV_MODE_T vGet_Div_Mode(DRAMC_CTX_T *p)
{
    return p->pDFSTable->divmode;
}

void vSet_Current_SRAMIdx(DRAMC_CTX_T *p, DRAM_DFS_SRAM_SHU_T u1SRAMIdx)
{
    p->pDFSTable->SRAMIdx = u1SRAMIdx;
}

DRAM_DFS_SRAM_SHU_T vGet_Current_SRAMIdx(DRAMC_CTX_T *p)
{
    return p->pDFSTable->SRAMIdx;
}

#if 0
void vSet_Duty_Calibration_Mode(DRAMC_CTX_T *p, U8 kMode)
{
    p->pDFSTable->duty_calibration_mode = kMode;
}
#endif

DUTY_CALIBRATION_T Get_Duty_Calibration_Mode(DRAMC_CTX_T *p)
{
    return p->pDFSTable->duty_calibration_mode;
}

VREF_CALIBRATION_ENABLE_T Get_Vref_Calibration_OnOff(DRAMC_CTX_T *p)
{
#if FOR_DV_SIMULATION_USED
    return VREF_CALI_OFF;
#else
    return p->pDFSTable->vref_calibartion_enable;
#endif
}


DRAM_CBT_MODE_T vGet_Dram_CBT_Mode(DRAMC_CTX_T *p)
{
    if (p->support_rank_num == RANK_DUAL)
    {
        if(p->dram_cbt_mode[RANK_0] == CBT_NORMAL_MODE && p->dram_cbt_mode[RANK_1] == CBT_NORMAL_MODE)
            return CBT_NORMAL_MODE;
    }
    else // Single rank
    {
        if(p->dram_cbt_mode[RANK_0] == CBT_NORMAL_MODE)
            return CBT_NORMAL_MODE;
    }

    return CBT_BYTE_MODE1;
}


void vPrintCalibrationBasicInfo(DRAMC_CTX_T *p)
{
#if __ETT__
    mcSHOW_DBG_MSG(("===============================================================================\n"));
    mcSHOW_DBG_MSG(("Dram Type= %d, Freq= %u, FreqGroup= %u, CH_%d, rank %d\n"
                    "fsp= %d, odt_onoff= %d, Byte mode= %d, DivMode= %d\n",
                        p->dram_type, DDRPhyGetRealFreq(p), p->freqGroup, p->channel, p->rank,
                        p->dram_fsp, p->odt_onoff, p->dram_cbt_mode[p->rank], vGet_Div_Mode(p)));
    mcSHOW_DBG_MSG(("===============================================================================\n"));

#else
    mcSHOW_DBG_MSG(("===============================================================================\n"
                    "Dram Type= %d, Freq= %u, CH_%d, rank %d\n"
                    "fsp= %d, odt_onoff= %d, Byte mode= %d, DivMode= %d\n"
                    "===============================================================================\n",
                        p->dram_type,
                        p->frequency,
                        p->channel,
                        p->rank,
                        p->dram_fsp,
                        p->odt_onoff,
                        p->dram_cbt_mode[p->rank],
                        vGet_Div_Mode(p)));
#endif
}

#if 0
void vPrintCalibrationBasicInfo_ForJV(DRAMC_CTX_T *p)
{
    mcSHOW_DBG_MSG5(("\n\nDram type:"));

    switch (p->dram_type)
    {
        case TYPE_LPDDR4:
            mcSHOW_DBG_MSG5(("LPDDR4\t"));
            break;

        case TYPE_LPDDR4X:
            mcSHOW_DBG_MSG5(("LPDDR4X\t"));
            break;

        case TYPE_LPDDR4P:
            mcSHOW_DBG_MSG5(("LPDDR4P\t"));
            break;
    }

    mcSHOW_DBG_MSG5(("Freq: %d, FreqGroup %u, channel %d, rank %d\n"
                     "dram_fsp= %d, odt_onoff= %d, Byte mode= %d, DivMode= %d\n\n",
                                        p->frequency, p->freqGroup, p->channel, p->rank,
                                        p->dram_fsp, p->odt_onoff, p->dram_cbt_mode[p->rank], vGet_Div_Mode(p)));

    return;
}
#endif

U16 GetFreqBySel(DRAMC_CTX_T *p, DRAM_PLL_FREQ_SEL_T sel)
{
    U16 u2freq=0;

    switch(sel)
    {
        case LP4_DDR4266:
            u2freq=2133;
            break;
        case LP4_DDR3733:
            u2freq=1866;
            break;
        case LP4_DDR3200:
            u2freq=1600;
            break;
        case LP4_DDR2667:
            u2freq=1333;
            break;
        case LP4_DDR2400:
            u2freq=1200;
            break;
        case LP4_DDR1866:
            u2freq=933;
            break;
        case LP4_DDR1600:
            u2freq=800;
            break;
        case LP4_DDR1200:
            u2freq=600;
            break;
        case LP4_DDR800:
            u2freq=400;
            break;
        case LP4_DDR400:
            u2freq=200;
            break;

        case LP5_DDR6400:
            u2freq=3200;
            break;
        case LP5_DDR6000:
            u2freq=3000;
            break;
        case LP5_DDR5500:
            u2freq=2750;
            break;
        case LP5_DDR4800:
            u2freq=2400;
            break;
        case LP5_DDR4266:
            u2freq=2133;
            break;
        case LP5_DDR3733:
            u2freq=1866;
            break;
        case LP5_DDR3200:
            u2freq=1600;
            break;
        case LP5_DDR2400:
            u2freq=1200;
            break;
        case LP5_DDR1600:
            u2freq=800;
            break;
        case LP5_DDR1200:
            u2freq=600;
            break;
        case LP5_DDR800:
            u2freq=400;
            break;

        default:
            mcSHOW_ERR_MSG(("[GetFreqBySel] freq sel is incorrect !!!\n"));
            break;
    }

    return u2freq;
}

DRAM_PLL_FREQ_SEL_T GetSelByFreq(DRAMC_CTX_T *p, U16 u2freq)
{
    DRAM_PLL_FREQ_SEL_T sel=0;

    switch(u2freq)
    {
        case 2133:
            sel=LP4_DDR4266;
            break;
        case 1866:
            sel=LP4_DDR3733;
            break;
        case 1600:
            sel=LP4_DDR3200;
            break;
        case 1333:
            sel=LP4_DDR2667;
            break;
        case 1200:
            sel=LP4_DDR2400;
            break;
        case 933:
            sel=LP4_DDR1866;
            break;
        case 800:
            sel=LP4_DDR1600;
            break;
        case 600:
            sel=LP4_DDR1200;
            break;
        case 400:
            sel=LP4_DDR800;
            break;
        case 200:
            sel=LP4_DDR400;
            break;
        default:
            mcSHOW_ERR_MSG(("[GetSelByFreq] sel is incorrect !!!\n"));
            break;
    }

    return sel;
}

void DDRPhyFreqSel(DRAMC_CTX_T *p, DRAM_PLL_FREQ_SEL_T sel)
{
    p->freq_sel = sel;
    p->frequency = GetFreqBySel(p, sel);

    {
        p->dram_fsp = (p->frequency < LP4_MRFSP_TERM_FREQ)? FSP_0: FSP_1;
        p->odt_onoff = (p->frequency < LP4_MRFSP_TERM_FREQ)? ODT_OFF: ODT_ON;
    }

    if (p->dram_type == TYPE_LPDDR4P)
        p->odt_onoff = ODT_OFF;

    setFreqGroup(p);

    //p->DBI_onoff = p->odt_onoff;
}


U16 u2DFSGetHighestFreq(DRAMC_CTX_T * p)
{
    U8 u1ShuffleIdx = 0;
    U16 u2Freq=0;
    static U16 u2FreqMax=0;

    if ((u2FreqMax == 0) || (gUpdateHighestFreq == TRUE))
    {
        gUpdateHighestFreq = FALSE;
        u2FreqMax = 0;
        for (u1ShuffleIdx = 0; u1ShuffleIdx < DRAM_DFS_SRAM_MAX; u1ShuffleIdx++)
        {
            u2Freq = GetFreqBySel(p, gFreqTbl[u1ShuffleIdx].freq_sel);
            if(u2FreqMax < u2Freq)
                u2FreqMax = u2Freq;
        }
    }

    return u2FreqMax;
}

U8 GetEyeScanEnable(DRAMC_CTX_T * p, U8 get_type)
{
#if ENABLE_EYESCAN_GRAPH
#if (fcFOR_CHIP_ID == fcA60868)

    if (get_type == EYESCAN_TYPE_CBT)
        if (ENABLE_EYESCAN_CBT==1) return ENABLE;


    if (get_type == EYESCAN_TYPE_RX)
        if (ENABLE_EYESCAN_RX==1) return ENABLE;


    if (get_type == EYESCAN_TYPE_TX)
        if (ENABLE_EYESCAN_TX==1) return ENABLE;

#else

    if (get_type == EYESCAN_TYPE_CBT)
    {
        if (gCBT_EYE_Scan_flag==DISABLE) return DISABLE;
        if (gCBT_EYE_Scan_only_higheset_freq_flag == DISABLE) return ENABLE;
        if (p->frequency == u2DFSGetHighestFreq(p)) return ENABLE;
        if (gEye_Scan_unterm_highest_flag==ENABLE && vGet_Current_SRAMIdx(p)==SRAM_SHU2) return ENABLE;
    }


    if (get_type == EYESCAN_TYPE_RX)
    {
        if (gRX_EYE_Scan_flag==DISABLE) return DISABLE;
        if (gRX_EYE_Scan_only_higheset_freq_flag == DISABLE) return ENABLE;
        if (p->frequency == u2DFSGetHighestFreq(p)) return ENABLE;
        if (gEye_Scan_unterm_highest_flag==ENABLE && vGet_Current_SRAMIdx(p)==SRAM_SHU2) return ENABLE;
    }


    if (get_type == EYESCAN_TYPE_TX)
    {
        if (gTX_EYE_Scan_flag==DISABLE) return DISABLE;
        if (gTX_EYE_Scan_only_higheset_freq_flag == DISABLE) return ENABLE;
        if (p->frequency == u2DFSGetHighestFreq(p)) return ENABLE;
        if (gEye_Scan_unterm_highest_flag==ENABLE && vGet_Current_SRAMIdx(p)==SRAM_SHU2) return ENABLE;
    }

#endif
#endif

    return DISABLE;
}

void DramcWriteDBIOnOff(DRAMC_CTX_T *p, U8 onoff)
{

    vIO32WriteFldAlign_All(DRAMC_REG_SHU_TX_SET0, onoff, SHU_TX_SET0_DBIWR);
    mcSHOW_DBG_MSG2(("DramC Write-DBI %s\n", ((onoff == DBI_ON) ? "on" : "off")));
}

void DramcReadDBIOnOff(DRAMC_CTX_T *p, U8 onoff)
{

    vIO32WriteFldAlign_All(DDRPHY_REG_SHU_B0_DQ7, onoff, SHU_B0_DQ7_R_DMDQMDBI_SHU_B0);
    vIO32WriteFldAlign_All(DDRPHY_REG_SHU_B1_DQ7, onoff, SHU_B1_DQ7_R_DMDQMDBI_SHU_B1);
    mcSHOW_DBG_MSG2(("DramC Read-DBI %s\n", ((onoff == DBI_ON) ? "on" : "off")));
}
#if ENABLE_READ_DBI
void SetDramModeRegForReadDBIOnOff(DRAMC_CTX_T *p, U8 u1fsp, U8 onoff)
{
#if MRW_CHECK_ONLY
    mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
#endif
    //mcSHOW_DBG_MSG(("--Fsp%d --\n", p->dram_fsp));


    u1MR03Value[u1fsp] = ((u1MR03Value[u1fsp] & 0xbf) | (onoff << 6));
    DramcModeRegWriteByRank(p, p->rank, 3, u1MR03Value[u1fsp]);
}
#endif

#if ENABLE_WRITE_DBI
void SetDramModeRegForWriteDBIOnOff(DRAMC_CTX_T *p, U8 u1fsp, U8 onoff)
{
#if MRW_CHECK_ONLY
    mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
#endif

    u1MR03Value[u1fsp] = ((u1MR03Value[u1fsp] & 0x7F) | (onoff << 7));
    DramcModeRegWriteByRank(p, p->rank, 3, u1MR03Value[u1fsp]);
}
#endif

#if 0
static void AutoRefreshCKEOff(DRAMC_CTX_T *p)
{
    U32 u4backup_broadcast= GetDramcBroadcast();

    DramcBroadcastOnOff(DRAMC_BROADCAST_OFF);

    mcSHOW_DBG_MSG(("AutoRefreshCKEOff AutoREF OFF\n"));
    vIO32WriteFldAlign_All(DRAMC_REG_REFCTRL0, 0x1, REFCTRL0_REFDIS);
    mcDELAY_US(3);
    mcSHOW_DBG_MSG(("DDRPhyPLLSetting-CKEOFF\n"));

    CKEFixOnOff(p, TO_ALL_RANK, CKE_FIXOFF, TO_ALL_CHANNEL);

    mcDELAY_US(1);


    DramcBroadcastOnOff(u4backup_broadcast);
}
#endif
void DramCLKAlwaysOnOff(DRAMC_CTX_T *p, U8 option, CHANNEL_RANK_SEL_T WriteChannelNUM)
{
    if (WriteChannelNUM == TO_ALL_CHANNEL) {
        vIO32WriteFldMulti_All(DRAMC_REG_DRAMC_PD_CTRL,
                P_Fld(option, DRAMC_PD_CTRL_APHYCKCG_FIXOFF) |
                P_Fld(option, DRAMC_PD_CTRL_TCKFIXON));
    } else {
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL),
                P_Fld(option, DRAMC_PD_CTRL_APHYCKCG_FIXOFF) |
                P_Fld(option, DRAMC_PD_CTRL_TCKFIXON));
    }
}

void CKEFixOnOff(DRAMC_CTX_T *p, U8 u1RankIdx, CKE_FIX_OPTION option, CHANNEL_RANK_SEL_T WriteChannelNUM)
{
    U8 u1CKEOn, u1CKEOff;

    if (option == CKE_DYNAMIC)
    {
        u1CKEOn = u1CKEOff = 0;
    }
    else
    {
        u1CKEOn = option;
        u1CKEOff = (1 - option);
    }

    if (WriteChannelNUM == TO_ALL_CHANNEL)
    {
        if((u1RankIdx == RANK_0)||(u1RankIdx == TO_ALL_RANK))
        {
            vIO32WriteFldMulti_All(DRAMC_REG_CKECTRL, P_Fld(u1CKEOff, CKECTRL_CKEFIXOFF)
                                                    | P_Fld(u1CKEOn, CKECTRL_CKEFIXON));
        }

        if(u1RankIdx == RANK_1||((u1RankIdx == TO_ALL_RANK) && (p->support_rank_num == RANK_DUAL)))
        {
            vIO32WriteFldMulti_All(DRAMC_REG_CKECTRL, P_Fld(u1CKEOff, CKECTRL_CKE1FIXOFF)
                                                    | P_Fld(u1CKEOn, CKECTRL_CKE1FIXON));
        }
    }
    else
    {
        if((u1RankIdx == RANK_0) || (u1RankIdx == TO_ALL_RANK))
        {
            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL), P_Fld(u1CKEOff, CKECTRL_CKEFIXOFF)
                                                                | P_Fld(u1CKEOn, CKECTRL_CKEFIXON));
        }

        if((u1RankIdx == RANK_1) ||((u1RankIdx == TO_ALL_RANK) && (p->support_rank_num == RANK_DUAL)))
        {
            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL), P_Fld(u1CKEOff, CKECTRL_CKE1FIXOFF)
                                                                | P_Fld(u1CKEOn, CKECTRL_CKE1FIXON));
        }
    }
}


void vAutoRefreshSwitch(DRAMC_CTX_T *p, U8 option)
{
    if (option == ENABLE)
    {

        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0), 0, REFCTRL0_REFDIS);
    }
    else
    {

        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0), 1, REFCTRL0_REFDIS);


        mcDELAY_US(u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MISC_STATUSA), MISC_STATUSA_REFRESH_QUEUE_CNT) * 4);
    }
}


void vCKERankCtrl(DRAMC_CTX_T *p, CKE_CTRL_MODE_T CKECtrlMode)
{

    typedef struct
    {
        U8 u1CKE2Rank: Fld_wid(RKCFG_CKE2RANK);
        U8 u1CKE2Rank_Opt :Fld_wid(CKECTRL_CKE2RANK_OPT);
        U8 u1CKE2Rank_Opt2 :Fld_wid(CKECTRL_CKE2RANK_OPT2);
        U8 u1CKE2Rank_Opt3: Fld_wid(CKECTRL_CKE2RANK_OPT3);
        U8 u1CKE2Rank_Opt5: Fld_wid(CKECTRL_CKE2RANK_OPT5);
        U8 u1CKE2Rank_Opt6: Fld_wid(CKECTRL_CKE2RANK_OPT6);
        U8 u1CKE2Rank_Opt7: Fld_wid(CKECTRL_CKE2RANK_OPT7);
        U8 u1CKE2Rank_Opt8: Fld_wid(CKECTRL_CKE2RANK_OPT8);
        U8 u1CKETimer_Sel: Fld_wid(CKECTRL_CKETIMER_SEL);
        U8 u1FASTWake: Fld_wid(SHU_DCM_CTRL0_FASTWAKE);
        U8 u1FASTWake2: Fld_wid(SHU_DCM_CTRL0_FASTWAKE2);
        U8 u1FastWake_Sel: Fld_wid(CKECTRL_FASTWAKE_SEL);
        U8 u1CKEWake_Sel: Fld_wid(CKECTRL_CKEWAKE_SEL);
        U8 u1ClkWiTrfc: Fld_wid(ACTIMING_CTRL_CLKWITRFC);
    } CKE_CTRL_T;


    CKE_CTRL_T CKE_Mode, CKE_Rank_Independent = { .u1CKE2Rank = 0, .u1CKE2Rank_Opt3 = 0, .u1CKE2Rank_Opt2 = 1,
                                                  .u1CKE2Rank_Opt5 = 0, .u1CKE2Rank_Opt6 = 0, .u1CKE2Rank_Opt7 = 1, .u1CKE2Rank_Opt8 = 0,
                                                  .u1CKETimer_Sel = 0, .u1FASTWake = 1, .u1FASTWake2 = 1, .u1FastWake_Sel = 1, .u1CKEWake_Sel = 0, .u1ClkWiTrfc = 0
                                                },
                         CKE_Rank_Dependent = { .u1CKE2Rank = 1, .u1CKE2Rank_Opt3 = 0,
                                                .u1CKE2Rank_Opt5 = 0, .u1CKE2Rank_Opt6 = 0, .u1CKE2Rank_Opt7 = 0, .u1CKE2Rank_Opt8 = 0, .u1CKETimer_Sel = 1,
                                                .u1FASTWake = 1, .u1FASTWake2 = 0, .u1FastWake_Sel = 0, .u1CKEWake_Sel = 0, .u1ClkWiTrfc = 0
                                              };

    CKE_Mode = (CKECtrlMode == CKE_RANK_INDEPENDENT)? CKE_Rank_Independent: CKE_Rank_Dependent;


    vIO32WriteFldAlign_All(DRAMC_REG_RKCFG, CKE_Mode.u1CKE2Rank, RKCFG_CKE2RANK);
    vIO32WriteFldMulti_All(DRAMC_REG_CKECTRL, P_Fld(CKE_Mode.u1CKE2Rank_Opt3, CKECTRL_CKE2RANK_OPT3)
                    | P_Fld(CKE_Mode.u1CKE2Rank_Opt, CKECTRL_CKE2RANK_OPT)
                    | P_Fld(CKE_Mode.u1CKE2Rank_Opt2, CKECTRL_CKE2RANK_OPT2)
                    | P_Fld(CKE_Mode.u1CKE2Rank_Opt5, CKECTRL_CKE2RANK_OPT5)
                    | P_Fld(CKE_Mode.u1CKE2Rank_Opt6, CKECTRL_CKE2RANK_OPT6)
                    | P_Fld(CKE_Mode.u1CKE2Rank_Opt7, CKECTRL_CKE2RANK_OPT7)
                    | P_Fld(CKE_Mode.u1CKE2Rank_Opt8, CKECTRL_CKE2RANK_OPT8)
                    | P_Fld(CKE_Mode.u1CKETimer_Sel, CKECTRL_CKETIMER_SEL)
                    | P_Fld(CKE_Mode.u1FastWake_Sel, CKECTRL_FASTWAKE_SEL)
                    | P_Fld(CKE_Mode.u1CKEWake_Sel, CKECTRL_CKEWAKE_SEL));

    vIO32WriteFldMulti_All(DRAMC_REG_SHU_DCM_CTRL0, P_Fld(CKE_Mode.u1FASTWake, SHU_DCM_CTRL0_FASTWAKE) | P_Fld(CKE_Mode.u1FASTWake2, SHU_DCM_CTRL0_FASTWAKE2));

    vIO32WriteFldAlign_All(DRAMC_REG_ACTIMING_CTRL, CKE_Mode.u1ClkWiTrfc, ACTIMING_CTRL_CLKWITRFC);
}


#define MAX_CMP_CPT_WAIT_LOOP 100000
static void DramcSetRWOFOEN(DRAMC_CTX_T *p, U8 u1onoff)
{
    U32 u4loop_count = 0;

    {
        while(u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MISC_STATUSA), MISC_STATUSA_REQQ_EMPTY) != 1)
        {
            mcDELAY_US(1);
            u4loop_count ++;

            if(u4loop_count > MAX_CMP_CPT_WAIT_LOOP)
            {
                mcSHOW_ERR_MSG(("RWOFOEN timout! queue is not empty\n"));
            #if __ETT__
                while(1);
            #else
                break;
            #endif
            }
        }
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SCHEDULER_COM), u1onoff, SCHEDULER_COM_RWOFOEN);
    }
}


//static void DramcEngine2CleanWorstSiPattern(DRAMC_CTX_T *p)
//{
//    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3),
//            P_Fld(0, TEST2_A3_AUTO_GEN_PAT) |
//            P_Fld(0, TEST2_A3_HFIDPAT) |
//            P_Fld(0, TEST2_A3_TEST_AID_EN));
//}


static void DramcEngine2SetUiShift(DRAMC_CTX_T *p, U8 option)
{
    if(option == ENABLE)
    {
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A0),
                P_Fld(1, TEST2_A0_TA2_LOOP_EN) |
                P_Fld(3, TEST2_A0_LOOP_CNT_INDEX));
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3),
                P_Fld(1, TEST2_A3_TEST2_PAT_SHIFT) |
                P_Fld(0, TEST2_A3_PAT_SHIFT_SW_EN));
    }
    else
    {
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A0),
                P_Fld(0, TEST2_A0_TA2_LOOP_EN) |
                P_Fld(0, TEST2_A0_LOOP_CNT_INDEX));
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3),
                P_Fld(0, TEST2_A3_TEST2_PAT_SHIFT));
    }
}


void DramcSetRankEngine2(DRAMC_CTX_T *p, U8 u1RankSel)
{

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3), 1, TEST2_A3_ADRDECEN_TARKMODE);


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


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4), u1RankSel, TEST2_A4_TESTAGENTRK);
}


void DramcEngine2SetPat(DRAMC_CTX_T *p, U8 u1TestPat, U8 u1LoopCnt, U8 u1Len1Flag, U8 u1EnableUiShift)
{

    if ((u1TestPat == TEST_XTALK_PATTERN) || (u1TestPat == TEST_SSOXTALK_PATTERN))
    {

        if (u1Len1Flag != 0)
        {
            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4),
                    P_Fld(1, TEST2_A4_TEST_REQ_LEN1));
            DramcSetRWOFOEN(p, 0);

        }
        else
        {
            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4),
                    P_Fld(0, TEST2_A4_TEST_REQ_LEN1));
            DramcSetRWOFOEN(p, 1);
        }

        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3),
                P_Fld(0, TEST2_A3_AUTO_GEN_PAT) |
                P_Fld(0, TEST2_A3_HFIDPAT) |
                P_Fld(0, TEST2_A3_TEST_AID_EN) |
                P_Fld(0, TEST2_A3_TESTAUDPAT) |
                P_Fld(u1LoopCnt, TEST2_A3_TESTCNT));

        if (u1TestPat == TEST_SSOXTALK_PATTERN)
        {

            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4),
                    P_Fld(1, TEST2_A4_TESTXTALKPAT) |
                    P_Fld(0, TEST2_A4_TESTAUDMODE) |
                    P_Fld(0, TEST2_A4_TESTAUDBITINV));


            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4),
                    P_Fld(1, TEST2_A4_TESTSSOPAT) |
                    P_Fld(0, TEST2_A4_TESTSSOXTALKPAT));
        }
        else
        {

            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4),
                    P_Fld(1, TEST2_A4_TESTXTALKPAT) |
                    P_Fld(0, TEST2_A4_TESTAUDMODE) |
                    P_Fld(0, TEST2_A4_TESTAUDBITINV));


            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4),
                    P_Fld(0, TEST2_A4_TESTSSOPAT) |
                    P_Fld(0, TEST2_A4_TESTSSOXTALKPAT));
        }
    }
    else if (u1TestPat == TEST_AUDIO_PATTERN)
    {
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4),
                P_Fld(0, TEST2_A4_TEST_REQ_LEN1));

        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4),
                P_Fld(0x00000011, TEST2_A4_TESTAUDINIT) |
                P_Fld(0x0000000d, TEST2_A4_TESTAUDINC) |
                P_Fld(0, TEST2_A4_TESTXTALKPAT) |
                P_Fld(0, TEST2_A4_TESTAUDMODE) |
                P_Fld(1, TEST2_A4_TESTAUDBITINV));


        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3),
                P_Fld(0, TEST2_A3_AUTO_GEN_PAT) |
                P_Fld(0, TEST2_A3_HFIDPAT) |
                P_Fld(0, TEST2_A3_TEST_AID_EN) |
                P_Fld(1, TEST2_A3_TESTAUDPAT) |
                P_Fld(u1LoopCnt, TEST2_A3_TESTCNT));
    }
    else if (u1TestPat == TEST_WORST_SI_PATTERN)
    {
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4),
                P_Fld(u1Len1Flag, TEST2_A4_TEST_REQ_LEN1)|
                P_Fld(0, TEST2_A4_TESTAUDINIT) |
                P_Fld(0, TEST2_A4_TESTAUDINC) |
                P_Fld(0, TEST2_A4_TESTXTALKPAT) |
                P_Fld(0, TEST2_A4_TESTSSOPAT)
                );
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3),
                P_Fld(0, TEST2_A3_TESTAUDPAT) |
                P_Fld(1, TEST2_A3_AUTO_GEN_PAT) |
                P_Fld(1, TEST2_A3_HFIDPAT) |
                P_Fld(1, TEST2_A3_TEST_AID_EN) |
                P_Fld(u1LoopCnt, TEST2_A3_TESTCNT)
                );
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A2), 0x56, TEST2_A2_TEST2_OFF);
    }
    else
    {
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4),
                P_Fld(0, TEST2_A4_TEST_REQ_LEN1));

        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3),
                P_Fld(0, TEST2_A3_AUTO_GEN_PAT) |
                P_Fld(0, TEST2_A3_HFIDPAT) |
                P_Fld(0, TEST2_A3_TEST_AID_EN) |
                P_Fld(0, TEST2_A3_TESTAUDPAT) |
                P_Fld(u1LoopCnt, TEST2_A3_TESTCNT));
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4), 0, TEST2_A4_TESTXTALKPAT);
    }

    DramcEngine2SetUiShift(p, u1EnableUiShift);
}

#define CMP_CPT_POLLING_PERIOD 1
#define MAX_CMP_CPT_WAIT_LOOP 100000
static void DramcEngine2CheckComplete(DRAMC_CTX_T *p, U8 u1status)
{
    U32 u4loop_count = 0;
    U32 u4Ta2_loop_count = 0;
    U32 u4ShiftUiFlag = 0;

    while ((u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_TESTRPT)) & u1status) != u1status)
    {
        mcDELAY_US(CMP_CPT_POLLING_PERIOD);
        u4loop_count++;
        if ((u4loop_count > 3) && (u4loop_count <= MAX_CMP_CPT_WAIT_LOOP))
        {
            //mcSHOW_ERR_MSG(("TESTRPT_DM_CMP_CPT: %d\n", u4loop_count));
        }
        else if (u4loop_count > MAX_CMP_CPT_WAIT_LOOP)
        {

            mcSHOW_ERR_MSG(("fcWAVEFORM_MEASURE_A %d :time out, [22:20]=0x%x\n", u4loop_count, u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TESTRPT), TESTRPT_TESTSTAT)));

            //mcFPRINTF((fp_A60501, "fcWAVEFORM_MEASURE_A %d: time out\n", u4loop_count));

            break;
        }
    }

    u4loop_count = 0;
    u4ShiftUiFlag = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3), TEST2_A3_TEST2_PAT_SHIFT);
    if(u4ShiftUiFlag)
    {
        while ((u4Ta2_loop_count = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_TEST_LOOP_CNT))) != 8)
        {
            u4loop_count++;
            if(u4loop_count > MAX_CMP_CPT_WAIT_LOOP)
            {
                mcSHOW_ERR_MSG(("over MAX_CMP_CPT_WAIT_LOOP[%d] TEST_LOOP_CNT[%d]\n", u4loop_count, u4Ta2_loop_count));
                break;
            }
        }
    }
}

static U32 DramcEngine2Compare(DRAMC_CTX_T *p, DRAM_TE_OP_T wr)
{
    U32 u4result = 0xffffffff;
    U32 u4loopcount;
    U8  u1status = 1;
    U32 u4ShiftUiFlag = 0;

    u4loopcount = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3), TEST2_A3_TESTCNT);
    if (u4loopcount == 1)
        u1status = 3;

    u4ShiftUiFlag = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3), TEST2_A3_TEST2_PAT_SHIFT);

    if (wr == TE_OP_WRITE_READ_CHECK)
    {
        if(!u4ShiftUiFlag)
        {

            DramcEngine2CheckComplete(p, u1status);


            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3),
                    P_Fld(0, TEST2_A3_TEST2W) |
                    P_Fld(0, TEST2_A3_TEST2R) |
                    P_Fld(0, TEST2_A3_TEST1));

            mcDELAY_US(1);


            vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3),
                    P_Fld(0, TEST2_A3_TEST2W) |
                    P_Fld(1, TEST2_A3_TEST2R) |
                    P_Fld(0, TEST2_A3_TEST1));
        }
    }


    DramcEngine2CheckComplete(p, u1status);

    //mcDELAY_US(1);

    u4result = (u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_TESTRPT)) >> 4) & u1status;

    return u4result;
}


static U32 uiReg0D0h;
DRAM_STATUS_T DramcEngine2Init(DRAMC_CTX_T *p, U32 test2_1, U32 test2_2, U8 u1TestPat, U8 u1LoopCnt, U8 u1EnableUiShift)
{
    U8 u1Len1Flag;


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


//    if ((u1LoopCnt > 15) || (u1LoopCnt < 0))
    if (u1LoopCnt > 15)
    {
        mcSHOW_ERR_MSG(("wrong param: u1LoopCnt > 15\n"));
        return DRAM_FAIL;
    }

    u1Len1Flag = (u1TestPat & 0x80) >> 7;
    u1TestPat = u1TestPat & 0x7f;

    DramcSetRankEngine2(p, p->rank);

    uiReg0D0h = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_DUMMY_RD));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_DUMMY_RD),
            P_Fld(0, DUMMY_RD_DQSG_DMYRD_EN) |
            P_Fld(0, DUMMY_RD_DQSG_DMYWR_EN) |
            P_Fld(0, DUMMY_RD_DUMMY_RD_EN) |
            P_Fld(0, DUMMY_RD_SREF_DMYRD_EN) |
            P_Fld(0, DUMMY_RD_DMY_RD_DBG) |
            P_Fld(0, DUMMY_RD_DMY_WR_DBG));


    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3),
            P_Fld(0, TEST2_A3_TEST2W) |
            P_Fld(0, TEST2_A3_TEST2R) |
            P_Fld(0, TEST2_A3_TEST1));


    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A0),
            P_Fld(test2_1 >> 24, TEST2_A0_TEST2_PAT0) |
            P_Fld(test2_2 >> 24, TEST2_A0_TEST2_PAT1));

    {

        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK_TEST2_A1),
                (test2_1 + 0x10000) & 0x00ffffff, RK_TEST2_A1_TEST2_BASE);
    }

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A2),
            test2_2 & 0x00ffffff, TEST2_A2_TEST2_OFF);


    DramcEngine2SetPat(p, u1TestPat, u1LoopCnt, u1Len1Flag, u1EnableUiShift);

    return DRAM_OK;
}


U32 DramcEngine2Run(DRAMC_CTX_T *p, DRAM_TE_OP_T wr, U8 u1TestPat)
{
    U32 u4result = 0xffffffff;


    if (wr == TE_OP_READ_CHECK)
    {
        if ((u1TestPat == 1) || (u1TestPat == 2))
        {

            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4), 0, TEST2_A4_TESTAUDMODE);
        }


        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3),
                P_Fld(0, TEST2_A3_TEST2W) |
                P_Fld(1, TEST2_A3_TEST2R) |
                P_Fld(0, TEST2_A3_TEST1));
    }
    else if (wr == TE_OP_WRITE_READ_CHECK)
    {

        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3),
                P_Fld(1, TEST2_A3_TEST2W) |
                P_Fld(0, TEST2_A3_TEST2R) |
                P_Fld(0, TEST2_A3_TEST1));
    }
    DramcEngine2Compare(p, wr);


    mcDELAY_US(1);


    u4result = (u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_CMP_ERR)));


    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3),
            P_Fld(0, TEST2_A3_TEST2W) |
            P_Fld(0, TEST2_A3_TEST2R) |
            P_Fld(0, TEST2_A3_TEST1));

    return u4result;
}

void DramcEngine2End(DRAMC_CTX_T *p)
{
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4),
            P_Fld(0, TEST2_A4_TEST_REQ_LEN1));
    DramcSetRWOFOEN(p, 1);
    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_DUMMY_RD), uiReg0D0h);
}
#if 0

static U32 TestEngineCompare(DRAMC_CTX_T *p)
{
    U8 jj;
    U32 u4err_value;

    if (p->test_pattern <= TEST_XTALK_PATTERN)
    {
        DramcEngine2Init(p, p->test2_1, p->test2_2, p->test_pattern, 0, TE_NO_UI_SHIFT);
        u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, p->test_pattern);
        DramcEngine2End(p);
    }
    else if (p->test_pattern == TEST_MIX_PATTERN)
    {
        DramcEngine2Init(p, p->test2_1, p->test2_2, TEST_AUDIO_PATTERN, 0, TE_NO_UI_SHIFT);
        u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, TEST_AUDIO_PATTERN);
        DramcEngine2End(p);

        DramcEngine2Init(p, p->test2_1, p->test2_2, TEST_XTALK_PATTERN, 0, TE_NO_UI_SHIFT);
        u4err_value |= DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, TEST_XTALK_PATTERN);
        DramcEngine2End(p);
    }
    else
    {
        mcSHOW_ERR_MSG(("Test pattern error! Using default xtalk pattern\n"));
        DramcEngine2Init(p, p->test2_1, p->test2_2, TEST_XTALK_PATTERN, 0, TE_NO_UI_SHIFT);
        u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, TEST_XTALK_PATTERN);
        DramcEngine2End(p);
    }
    return u4err_value;
}
#endif
#if (fcFOR_CHIP_ID == fcA60868)
    #define EMI_APB_BASE    0x10219000
#elif (fcFOR_CHIP_ID == fc8195)
    #define EMI_APB_BASE    0x10219000
    //#define SUB_EMI_APB_BASE    0x1021D000

#endif

U8 u1MaType = 0x2;
void TA2_Test_Run_Time_HW_Set_Column_Num(DRAMC_CTX_T * p)
{
    U8 u1ChannelIdx = 0;
    U8 u1EmiChIdx = 0;
    U32 u4matypeR0 = 0, u4matypeR1 = 0;
    U32 u4matype = 0;
    U32 u4EmiOffset = 0;
    DRAM_CHANNEL_T eOriChannel = p->channel;

    for (u1ChannelIdx = 0; u1ChannelIdx < p->support_channel_num; u1ChannelIdx++)
    {
        vSetPHY2ChannelMapping(p, u1ChannelIdx);

        u4EmiOffset = 0;
        u1EmiChIdx = u1ChannelIdx;
#if (CHANNEL_NUM > 2)
	if (channel_num_auxadc > 2) {
        if (u1ChannelIdx >= CHANNEL_C)
        {
            u4EmiOffset = 0x4000;
            u1EmiChIdx = u1ChannelIdx-2;
        }
		}
#endif

        u4matype = u4IO32Read4B(EMI_APB_BASE + u4EmiOffset);
        u4matypeR0 = ((u4matype >> (4 + u1EmiChIdx * 16)) & 0x3) + 1;
        u4matypeR1 = ((u4matype >> (6 + u1EmiChIdx * 16)) & 0x3) + 1;

        if(p->support_rank_num==RANK_SINGLE)
        {
            u4matype = u4matypeR0;
        }
        else
        {
            u4matype = (u4matypeR0 > u4matypeR1) ? u4matypeR1 : u4matypeR0;
        }
        //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MATYPE), u4matype, MATYPE_MATYPE);
    }
    vSetPHY2ChannelMapping(p, eOriChannel);
    u1MaType = u4matype;

    return;
}


#define TA2_RANK0_ADDRESS   (0x40200000)
#define AXI_CHAN_BIT_WIDTH 1
#define OFFSET_OF_RG_BASE_AND_AXI 2
#define LEN1_INTRINSIC_OFFSET 2
#if FOR_DV_SIMULATION_USED
#define TRANSFER_DRAM_ADDR_BY_EMI_API 0
#else
#define TRANSFER_DRAM_ADDR_BY_EMI_API 1
#endif
void TA2_Test_Run_Time_HW_Presetting(DRAMC_CTX_T * p, U32 len, TA2_RKSEL_TYPE_T rksel_mode)
{
    DRAM_CHANNEL_T eOriChannel = p->channel;
    DRAM_RANK_T eOriRank = p->rank;
    U32 u4BaseR0, u4BaseR1, u4Offset, u4Addr;
    U32 u4matypeR0, u4matypeR1, u4LEN1;
    U8 u1ChannelIdx, uiRWOFOEN, u1RkIdx;

    u4Addr = TA2_RANK0_ADDRESS & 0x1fffffff;
    if (u1IsLP4Family(p->dram_type))
    {
#if TRANSFER_DRAM_ADDR_BY_EMI_API
        {
            dram_addr_t dram_addr;
            unsigned long long ull_axi_addr = TA2_RANK0_ADDRESS;

            memset(&dram_addr, 0, sizeof(dram_addr));
            phy_addr_to_dram_addr(&dram_addr, ull_axi_addr);
            u4BaseR0 = ((dram_addr.row << 12) | (dram_addr.bk << 9) | (dram_addr.col >> 1)) >> 3;
        }
#else

        u4BaseR0 = (((u4Addr & ~0x1ff) >> AXI_CHAN_BIT_WIDTH) | (u4Addr & 0xff)) >> (OFFSET_OF_RG_BASE_AND_AXI + 3);
#endif
        //mcSHOW_DBG_MSG(("===u4BaseR0 = 0x%x\n", u4BaseR0));

        u4Offset = len >> (AXI_CHAN_BIT_WIDTH + 5);
    }
    else
    {
        u4BaseR0 = u4Addr >> 4;
        if (rksel_mode == TA2_RKSEL_XRT)
        {
            u4Offset = len >> 4;
        }
        else
        {
            u4Offset = (len >> 4) >> 1;
        }
    }
    u4BaseR1 = u4BaseR0;

    u4matypeR0 = ((u4IO32Read4B(EMI_APB_BASE) >> 4) & 0x3) + 1;
    u4matypeR1 = ((u4IO32Read4B(EMI_APB_BASE) >> 6) & 0x3) + 1;
    if (u4matypeR0 != u4matypeR1)
    {
        (u4matypeR0 > u4matypeR1)? (u4BaseR0 >>= 1): (u4BaseR1 >>= 1);
        u4Offset >>= 1;
    }

    u4Offset = (u4Offset == 0) ? 1 : u4Offset;

    u4LEN1 = u4IO32ReadFldAlign(DRAMC_REG_TEST2_A4, TEST2_A4_TEST_REQ_LEN1);
    if(u4LEN1)
    {
        u4Offset = u4Offset - LEN1_INTRINSIC_OFFSET;
    }

#if ENABLE_EMI_LPBK_TEST && EMI_USE_TA2
    if (gEmiLpbkTest)
    {
        u4matypeR0 = 2;
        u4matypeR1 = 2;
        u4Offset = 3;
        //u4Offset = 6;
    }
#endif

    if (TA2_RKSEL_XRT == rksel_mode)
    {

        uiRWOFOEN = 0;
        mcSHOW_DBG_MSG2(("=== TA2 XRT R2R/W2W\n"));
    }
    else
    {
        uiRWOFOEN = 1;
#if !ENABLE_EMI_LPBK_TEST
        mcSHOW_DBG_MSG2(("=== TA2 HW\n"));
#endif
    }
#if !ENABLE_EMI_LPBK_TEST
    mcSHOW_DBG_MSG2(("=== OFFSET:0x%x\n", u4Offset));
#endif
    for (u1ChannelIdx = 0; u1ChannelIdx < p->support_channel_num; u1ChannelIdx++)
    {
        p->channel = (DRAM_CHANNEL_T)u1ChannelIdx;

        for(u1RkIdx = 0; u1RkIdx < p->support_rank_num; u1RkIdx++)
        {
            p->rank = (DRAM_RANK_T)u1RkIdx;
            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK_TEST2_A1), u4BaseR0, RK_TEST2_A1_TEST2_BASE);
        }
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A2), u4Offset, TEST2_A2_TEST2_OFF);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4), rksel_mode, TEST2_A4_TESTAGENTRKSEL);
        DramcSetRWOFOEN(p, uiRWOFOEN);
    }
    p->channel = eOriChannel;
    p->rank = eOriRank;
    //TA2_Test_Run_Time_HW_Set_Column_Num(p);

    return;
}
#if ETT_MINI_STRESS_USE_TA2_LOOP_MODE
#define TA2_PAT TEST_WORST_SI_PATTERN
#else
#define TA2_PAT TEST_XTALK_PATTERN
#endif

void TA2_Test_Run_Time_Pat_Setting(DRAMC_CTX_T *p, U8 PatSwitch)
{
    static U8 u1Pat = TA2_PAT;
    U8 u1ChannelIdx = 0;
    DRAM_CHANNEL_T eOriChannel = p->channel;

#if !ENABLE_EMI_LPBK_TEST
    mcSHOW_DBG_MSG2(("TA2 PAT: %d\n", u1Pat));
#endif
    for (u1ChannelIdx = CHANNEL_A; u1ChannelIdx < p->support_channel_num; u1ChannelIdx++)
    {
        p->channel = (DRAM_CHANNEL_T)u1ChannelIdx;
        DramcEngine2SetPat(p, u1Pat, p->support_rank_num - 1, 0, TE_NO_UI_SHIFT);
    }
    p->channel = eOriChannel;

    #if !ETT_MINI_STRESS_USE_TA2_LOOP_MODE
    {
        U32 u4Value = 0;
        u4Value = (u1Pat == TEST_WORST_SI_PATTERN) ? 1 : 0;
        vIO32WriteFldAlign_All(DRAMC_REG_TEST2_A0, u4Value, TEST2_A0_TA2_LOOP_EN);
        vIO32WriteFldAlign_All(DRAMC_REG_TEST2_A0, u4Value, TEST2_A0_LOOP_NV_END);
        vIO32WriteFldAlign_All(DRAMC_REG_TEST2_A0, u4Value, TEST2_A0_ERR_BREAK_EN);
        vIO32WriteFldAlign_All(DRAMC_REG_TEST2_A4, u4Value, TEST2_A4_TEST_REQ_LEN1);
    }
    #endif

    if (PatSwitch)
        u1Pat = (u1Pat + 1) % 4;

    return;
}
#if 0
static void TA2_Test_Run_Time_HW_Read(DRAMC_CTX_T * p, U8 u1Enable)
{
    DRAM_CHANNEL_T eOriChannel = p->channel;
    U8 u1ChannelIdx;

    mcSHOW_DBG_MSG2(("\nTA2 Trigger Read\n"));
    for (u1ChannelIdx = 0; u1ChannelIdx < p->support_channel_num; u1ChannelIdx++)
    {
        p->channel = (DRAM_CHANNEL_T)u1ChannelIdx;
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3), u1Enable, TEST2_A3_TEST2R);
    }
    p->channel = eOriChannel;
    return;
}
#endif
void TA2_Test_Run_Time_HW_Write(DRAMC_CTX_T * p, U8 u1Enable)
{
    DRAM_CHANNEL_T eOriChannel = p->channel;
    U8 u1ChannelIdx;

#if !ENABLE_EMI_LPBK_TEST
    mcSHOW_DBG_MSG2(("\nTA2 Trigger Write\n"));
#endif
    for (u1ChannelIdx = 0; u1ChannelIdx < p->support_channel_num; u1ChannelIdx++)
    {
        p->channel = (DRAM_CHANNEL_T)u1ChannelIdx;
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3), u1Enable, TEST2_A3_TEST2W);
    }
    p->channel = eOriChannel;
    return;
}

#if defined(RELEASE) && defined(DEVIATION)
#undef mcSHOW_JV_LOG_MSG
#define mcSHOW_JV_LOG_MSG(_x_)	opt_print _x_
#endif
static void TA2_Show_Cnt(DRAMC_CTX_T * p, U32 u4ErrorValue)
{
    static U32 err_count = 0;
    static U32 pass_count = 0;
    U8 u1RankIdx = 0;

    for (u1RankIdx = 0; u1RankIdx < p->support_rank_num; u1RankIdx++)
    {
        if (u4ErrorValue & (1 << u1RankIdx))
        {
            err_count++;
            mcSHOW_DBG_MSG2(("HW channel(%d) Rank(%d), TA2 failed, pass_cnt:%d, err_cnt:%d, err_bit:0x%x\n", p->channel, u1RankIdx, pass_count, err_count, u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_CMP_ERR))));
        }
        else
        {
            pass_count++;
            mcSHOW_DBG_MSG2(("HW channel(%d) Rank(%d), TA2 pass, pass_cnt:%d, err_cnt:%d\n", p->channel, u1RankIdx, pass_count, err_count));
        }
    }
}


#if ETT_MINI_STRESS_USE_TA2_LOOP_MODE
#if 0
static void TA2_Test_Run_Time_Stop_Loop_Mode(DRAMC_CTX_T * p)
{
    U8 u1ChannelIdx = 0;
    U8 u1status = (p->support_rank_num == 2) ? 3 : 1;
    U32 u4loop_count = 0;
    DRAM_CHANNEL_T eOriChannel = p->channel;

    for (u1ChannelIdx = 0; u1ChannelIdx < p->support_channel_num; u1ChannelIdx++)
    {
        vSetPHY2ChannelMapping(p, u1ChannelIdx);


        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A0), 0, TEST2_A0_LOOP_NV_END);


        while (((u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_TESTRPT)) & u1status) != u1status) || (u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TESTRPT), TESTRPT_TESTSTAT)))
        {
            mcDELAY_US(CMP_CPT_POLLING_PERIOD);
            u4loop_count++;
            if ((u4loop_count > 3) && (u4loop_count <= MAX_CMP_CPT_WAIT_LOOP))
            {
                //mcSHOW_ERR_MSG(("TESTRPT_DM_CMP_CPT: %d\n", u4loop_count));
            }
            else if (u4loop_count > MAX_CMP_CPT_WAIT_LOOP)
            {
                mcSHOW_ERR_MSG(("fcWAVEFORM_MEASURE_A %d :time out, [22:20]=0x%x\n", u4loop_count, u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TESTRPT), TESTRPT_TESTSTAT)));
                break;
            }
        }


        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3), P_Fld(0, TEST2_A3_TEST2W) | P_Fld(0, TEST2_A3_TEST2R) | P_Fld(0, TEST2_A3_TEST1));
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A0), 0, TEST2_A0_TA2_LOOP_EN);
    }
    vSetPHY2ChannelMapping(p, eOriChannel);
}

static void TA2_Test_Run_Time_Start_Loop_Mode(DRAMC_CTX_T *p)
{
    vIO32WriteFldAlign_All(DRAMC_REG_TEST2_A0, 1, TEST2_A0_TA2_LOOP_EN);
    vIO32WriteFldAlign_All(DRAMC_REG_TEST2_A0, 1, TEST2_A0_LOOP_NV_END);
    vIO32WriteFldAlign_All(DRAMC_REG_TEST2_A0, 1, TEST2_A0_ERR_BREAK_EN);
    vIO32WriteFldAlign_All(DRAMC_REG_TEST2_A4, 1, TEST2_A4_TEST_REQ_LEN1);
}

static U32 TA2_Test_Run_Time_Err_Status(DRAMC_CTX_T *p)
{
    static U32 err_count = 0;
    static U32 pass_count = 0;
    U32 u4Value = 0xffffffff;
    U32 u4ErrorValue = 0;
    U32 u4AllErrorValue = 0;
    U8 u1ChannelIdx = 0;
    DRAM_CHANNEL_T bkchannel = p->channel;

    for(u1ChannelIdx=CHANNEL_A; u1ChannelIdx<(p->support_channel_num); u1ChannelIdx++)
    {
        vSetPHY2ChannelMapping(p, u1ChannelIdx);
        u4ErrorValue = (u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_TESTRPT)) >> 4) & 0x3;
        //mcSHOW_DBG_MSG(("CMP_ERR_RK0/1:0x%x ", u4ErrorValue));
        TA2_Show_Cnt(p, u4ErrorValue);
        u4AllErrorValue |= u4ErrorValue;

        u4Value = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_TEST_LOOP_CNT));
        mcSHOW_DBG_MSG2(("CH[%d] LOOP_CNT:0x%x \n", u1ChannelIdx, u4Value));
    }
    vSetPHY2ChannelMapping(p, bkchannel);
    return u4AllErrorValue;
}
#endif
U32 TA2_Test_Run_Time_HW_Status(DRAMC_CTX_T * p)
{
    U8 u1ChannelIdx = 0;
    U32 u4ErrorValue = 0;
    U32 bit_error = 0;
    DRAM_CHANNEL_T eOriChannel = p->channel;

    for (u1ChannelIdx = 0; u1ChannelIdx < p->support_channel_num; u1ChannelIdx++)
    {
        vSetPHY2ChannelMapping(p, u1ChannelIdx);
        u4ErrorValue = DramcEngine2Compare(p, TE_OP_WRITE_READ_CHECK);

        if (u4ErrorValue & 0x3)
        {
            mcSHOW_DBG_MSG2(("=== HW channel(%d) u4ErrorValue: 0x%x, bit error: 0x%x\n", u1ChannelIdx, u4ErrorValue, u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_CMP_ERR))));
#if defined(SLT)
            mcSHOW_ERR_MSG(("[dramc] DRAM_FATAL_ERR_FLAG = 0x00000001, line: %d\n",__LINE__));
            while (1);
#endif
        }
        TA2_Show_Cnt(p, u4ErrorValue);

        bit_error |= u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_CMP_ERR));
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3), P_Fld(0, TEST2_A3_TEST2W) | P_Fld(0, TEST2_A3_TEST2R) | P_Fld(0, TEST2_A3_TEST1));
    }
    vSetPHY2ChannelMapping(p, eOriChannel);

    return bit_error;
}
#else
U32 TA2_Test_Run_Time_HW_Status(DRAMC_CTX_T * p)
{
    U8 u1ChannelIdx = 0;
    U32 u4ErrorValue = 0;
    U32 u4Ta2LoopEn = 0;
    U32 u4loopcount = 0;
    U8 u1status = 0;
    U32 bit_error = 0;
    static U32 err_count = 0;
    static U32 pass_count = 0;
    DRAM_CHANNEL_T eOriChannel = p->channel;

    for (u1ChannelIdx = 0; u1ChannelIdx < p->support_channel_num; u1ChannelIdx++)
    {
        vSetPHY2ChannelMapping(p, u1ChannelIdx);
        u4Ta2LoopEn = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A0), TEST2_A0_TA2_LOOP_EN);
        //mcSHOW_DBG_MSG(("### u4Ta2LoopEn:%d ### \n", u4Ta2LoopEn));

        if(u4Ta2LoopEn)
        {
            u4loopcount = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3), TEST2_A3_TESTCNT);
            if (u4loopcount == 1)
                u1status = 3;

            vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A0), 0, TEST2_A0_LOOP_NV_END);
            DramcEngine2CheckComplete(p, u1status);
            //mcSHOW_DBG_MSG(("TESTRPT_TESTSTAT:%x\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TESTRPT), TESTRPT_TESTSTAT)));
            u4ErrorValue = (u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_TESTRPT)) >> 4) & 0x3;
        }
        else
            u4ErrorValue = DramcEngine2Compare(p, TE_OP_WRITE_READ_CHECK);

        if (u4ErrorValue & 0x3)
        {
            mcSHOW_DBG_MSG2(("=== HW channel(%d) u4ErrorValue: 0x%x, bit error: 0x%x\n", u1ChannelIdx, u4ErrorValue, u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_CMP_ERR))));
#if defined(SLT)
            mcSHOW_ERR_MSG(("[dramc] DRAM_FATAL_ERR_FLAG = 0x00000001, line: %d\n",__LINE__));
            while (1);
#endif
        }
        TA2_Show_Cnt(p, u4ErrorValue);

        bit_error |= u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_CMP_ERR));
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3), P_Fld(0, TEST2_A3_TEST2W) | P_Fld(0, TEST2_A3_TEST2R) | P_Fld(0, TEST2_A3_TEST1));
    }
    vSetPHY2ChannelMapping(p, eOriChannel);

    return bit_error;
}
#endif
#if defined(RELEASE) && defined(DEVIATION)
#undef mcSHOW_JV_LOG_MSG
#define mcSHOW_JV_LOG_MSG(_x_)
#endif


void TA2_Test_Run_Time_HW(DRAMC_CTX_T * p)
{
    DRAM_CHANNEL_T channel_bak = p->channel;
    DRAM_RANK_T rank_bak = p->rank;

    TA2_Test_Run_Time_HW_Presetting(p, 0x10000, TA2_RKSEL_HW);
    TA2_Test_Run_Time_Pat_Setting(p, TA2_PAT_SWITCH_OFF);
    TA2_Test_Run_Time_HW_Write(p, ENABLE);
    //mcDELAY_MS(1);
    TA2_Test_Run_Time_HW_Status(p);

    p->channel = channel_bak;
    p->rank = rank_bak;
    return;
}

void Temp_TA2_Test_After_K(DRAMC_CTX_T * p)
{
    DRAM_CHANNEL_T channel_bak = p->channel;
    DRAM_RANK_T rank_bak = p->rank;

    do {
        TA2_Test_Run_Time_Pat_Setting(p, TA2_PAT_SWITCH_ON);
        TA2_Test_Run_Time_HW_Presetting(p, 0x200000, TA2_RKSEL_HW);
        TA2_Test_Run_Time_HW_Write(p, ENABLE);
        TA2_Test_Run_Time_HW_Status(p);
       }while(1);

    p->channel = channel_bak;
    p->rank = rank_bak;
    return;
}

static U8 *DramcFetchGlobalMR(DRAMC_CTX_T *p, U8 mr_idx)
{
    U8 *pMRGlobalValue = NULL;

    switch (mr_idx)
    {
        case 13: pMRGlobalValue = &u1MR13Value[p->rank]; break;
        case 26: pMRGlobalValue = &u1MR26Value[p->rank]; break;
        case 30: pMRGlobalValue = &u1MR30Value[p->rank]; break;
        default:
            mcSHOW_ERR_MSG(("%s NULL\n", __func__));
            #if __ETT__
            while(1);
            #endif
            break;
    }

    return pMRGlobalValue;
}

#if MRW_BACKUP
U8 DramcMRWriteBackup(DRAMC_CTX_T *p, U8 u1MRIdx, U8 u1Rank)
{
    U8 u1Value=0xff;
    U8 u1Fsp;
    U8 u1MRBackup_ERR_Flag=0, u1backupRK=p->rank;
    U16 u2Offset=0x0;
    REG_TRANSFER_T TransferReg;

    u1Fsp = FSP_0;

    {
        switch (u1MRIdx)
        {
            case 1:
            case 2:
            case 3:
            case 11:
            case 12:
            case 14:
            case 22:
                u1Fsp = gFSPWR_Flag[u1Rank];
                break;
        }
    }

    if (u1Fsp == FSP_0)
    {
        switch (u1MRIdx)
        {
            case 1:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_00_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_00_RK0_FSP0_MRWBK_RK0_FSP0_MR1;
                break;
            case 2:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_00_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_00_RK0_FSP0_MRWBK_RK0_FSP0_MR2;
                break;
            case 3:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_00_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_00_RK0_FSP0_MRWBK_RK0_FSP0_MR3;
                break;
            case 4:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_00_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_00_RK0_FSP0_MRWBK_RK0_FSP0_MR4;
                break;
            case 9:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_01_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_01_RK0_FSP0_MRWBK_RK0_FSP0_MR9;
                break;
            case 10:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_01_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_01_RK0_FSP0_MRWBK_RK0_FSP0_MR10;
                break;
            case 11:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_01_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_01_RK0_FSP0_MRWBK_RK0_FSP0_MR11;
                break;
            case 12:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_01_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_01_RK0_FSP0_MRWBK_RK0_FSP0_MR12;
                break;
            case 13:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_02_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_02_RK0_FSP0_MRWBK_RK0_FSP0_MR13;
                break;
            case 14:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_02_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_02_RK0_FSP0_MRWBK_RK0_FSP0_MR14;
                break;
            case 15:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_02_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_02_RK0_FSP0_MRWBK_RK0_FSP0_MR15;
                break;
            case 16:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_02_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_02_RK0_FSP0_MRWBK_RK0_FSP0_MR16;
                break;
            case 17:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_03_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_03_RK0_FSP0_MRWBK_RK0_FSP0_MR17;
                break;
            case 18:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_03_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_03_RK0_FSP0_MRWBK_RK0_FSP0_MR18;
                break;
            case 19:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_03_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_03_RK0_FSP0_MRWBK_RK0_FSP0_MR19;
                break;
            case 20:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_03_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_03_RK0_FSP0_MRWBK_RK0_FSP0_MR20;
                break;
            case 21:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_04_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_04_RK0_FSP0_MRWBK_RK0_FSP0_MR21;
                break;
            case 22:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_04_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_04_RK0_FSP0_MRWBK_RK0_FSP0_MR22;
                break;
            case 23:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_04_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_04_RK0_FSP0_MRWBK_RK0_FSP0_MR23;
                break;
            case 24:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_04_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_04_RK0_FSP0_MRWBK_RK0_FSP0_MR24;
                break;
            case 25:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_05_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_05_RK0_FSP0_MRWBK_RK0_FSP0_MR25;
                break;
            case 26:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_05_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_05_RK0_FSP0_MRWBK_RK0_FSP0_MR26;
                break;
            case 27:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_05_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_05_RK0_FSP0_MRWBK_RK0_FSP0_MR27;
                break;
            case 28:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_05_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_05_RK0_FSP0_MRWBK_RK0_FSP0_MR28;
                break;
            case 30:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_06_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_06_RK0_FSP0_MRWBK_RK0_FSP0_MR30;
                break;
            case 31:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_06_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_06_RK0_FSP0_MRWBK_RK0_FSP0_MR31;
                break;
            case 32:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_06_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_06_RK0_FSP0_MRWBK_RK0_FSP0_MR32;
                break;
            case 33:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_06_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_06_RK0_FSP0_MRWBK_RK0_FSP0_MR33;
                break;
            case 34:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_07_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_07_RK0_FSP0_MRWBK_RK0_FSP0_MR34;
                break;
            case 37:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_07_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_07_RK0_FSP0_MRWBK_RK0_FSP0_MR37;
                break;
            case 39:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_07_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_07_RK0_FSP0_MRWBK_RK0_FSP0_MR39;
                break;
            case 40:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_07_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_07_RK0_FSP0_MRWBK_RK0_FSP0_MR40;
                break;
            case 41:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_08_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_08_RK0_FSP0_MRWBK_RK0_FSP0_MR41;
                break;
            case 42:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_08_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_08_RK0_FSP0_MRWBK_RK0_FSP0_MR42;
                break;
            case 46:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_08_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_08_RK0_FSP0_MRWBK_RK0_FSP0_MR46;
                break;
            case 48:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_08_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_08_RK0_FSP0_MRWBK_RK0_FSP0_MR48;
                break;
            case 51:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_09_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_09_RK0_FSP0_MRWBK_RK0_FSP0_MR51;
                break;
            case 63:
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_09_RK0_FSP0;
                TransferReg.u4Fld = MR_BACKUP_09_RK0_FSP0_MRWBK_RK0_FSP0_MR63;
                break;
        }
    }
    else if (u1MRIdx == 21 || u1MRIdx == 22)
    {
        if (u1MRIdx == 21)
        {
            TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_04_RK0_FSP1;
            TransferReg.u4Fld = MR_BACKUP_04_RK0_FSP1_MRWBK_RK0_FSP1_MR21;
        }
        else
        {
            TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_03_RK0_FSP1;
            TransferReg.u4Fld = MR_BACKUP_03_RK0_FSP1_MRWBK_RK0_FSP1_MR22;
        }
    }
    else
    {
        if (u1MRIdx <= 20)
        {
            if (u1MRIdx <= 10)
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_00_RK0_FSP1;
            else if (u1MRIdx <= 15)
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_01_RK0_FSP1;
            else
                TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_03_RK0_FSP1;

            TransferReg.u4Addr += ((u1Fsp - FSP_1) * 0x30);

            if (u1MRIdx == 1 || u1MRIdx == 11 || u1MRIdx == 17)
                TransferReg.u4Fld = MR_BACKUP_00_RK0_FSP1_MRWBK_RK0_FSP1_MR1;
            else if (u1MRIdx == 2 || u1MRIdx == 12 || u1MRIdx == 18)
                TransferReg.u4Fld = MR_BACKUP_00_RK0_FSP1_MRWBK_RK0_FSP1_MR2;
            else if (u1MRIdx == 3 || u1MRIdx == 14 || u1MRIdx == 19)
                TransferReg.u4Fld = MR_BACKUP_00_RK0_FSP1_MRWBK_RK0_FSP1_MR3;
            else
                TransferReg.u4Fld = MR_BACKUP_00_RK0_FSP1_MRWBK_RK0_FSP1_MR10;
        }
        else if (u1Fsp == FSP_2 && u1MRIdx == 24)
        {
            TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_03_RK0_FSP2;
            TransferReg.u4Fld = MR_BACKUP_03_RK0_FSP2_MRWBK_RK0_FSP2_MR24;
        }
        else if (u1Fsp == FSP_1 && u1MRIdx == 41)
        {
            TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_03_RK0_FSP1;
            TransferReg.u4Fld = MR_BACKUP_03_RK0_FSP1_MRWBK_RK0_FSP1_MR41;
        }
        else
        {
            TransferReg.u4Addr = DRAMC_REG_MR_BACKUP_03_RK0_FSP1 + ((u1Fsp - FSP_1) * 0x30);
            if ((u1Fsp == FSP_1 && u1MRIdx == 24) || (u1Fsp == FSP_2 && u1MRIdx == 30))
            {
                TransferReg.u4Fld = MR_BACKUP_03_RK0_FSP1_MRWBK_RK0_FSP1_MR24;
            }
            else
            {
                TransferReg.u4Fld = MR_BACKUP_03_RK0_FSP1_MRWBK_RK0_FSP1_MR30;
            }
        }
    }

    vSetRank(p, u1Rank);

    if (u1MRBackup_ERR_Flag==0)
    {
        u1Value=u4IO32ReadFldAlign(DRAMC_REG_ADDR(TransferReg.u4Addr), TransferReg.u4Fld);
        mcSHOW_MRW_MSG(("  [MRW Backup] Rank%d FSP%d MR%d=0x%x\n",u1Rank, gFSPWR_Flag[u1Rank], u1MRIdx, u1Value));
    }
    vSetRank(p, u1backupRK);

    return u1Value;

}
#endif

void DramcMRWriteFldMsk(DRAMC_CTX_T *p, U8 mr_idx, U8 listVal8, U8 msk8, U8 UpdateMode)
{
    U8 *pMRGlobalValue = DramcFetchGlobalMR(p, mr_idx);

    // ASSERT (pMRGlobalValue != NULL)

    *pMRGlobalValue = ((*pMRGlobalValue & ~msk8) | listVal8);

    if (UpdateMode == TO_MR)
        DramcModeRegWriteByRank(p, p->rank, mr_idx, *pMRGlobalValue);
}

void DramcMRWriteFldAlign(DRAMC_CTX_T *p, U8 mr_idx, U8 value, U32 mr_fld, U8 UpdateMode)
{
    U8 *pMRGlobalValue = DramcFetchGlobalMR(p, mr_idx);

    // ASSERT (pMRGlobalValue != NULL)

    *pMRGlobalValue &= ~(Fld2Msk32(mr_fld));
    *pMRGlobalValue |= (value << Fld_shft(mr_fld));

    if (UpdateMode == TO_MR)
        DramcModeRegWriteByRank(p, p->rank, mr_idx, *pMRGlobalValue);
}

void DramcModeRegRead(DRAMC_CTX_T *p, U8 u1MRIdx, U16 *u2pValue)
{
    U32 u4MRValue;
#ifdef DUMP_INIT_RG_LOG_TO_DE
    gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag=0;
#endif
    //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0), p->rank, SWCMD_CTRL0_MRRRK);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0), u1MRIdx, SWCMD_CTRL0_MRSMA);


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


    while (u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_MRR_RESPONSE) == 0)
    {
        mcDELAY_US(1);
    }


    U32 u4MRRReg;
    if (u1IsLP4Family(p->dram_type))
        u4MRRReg = MRR_STATUS_MRR_SW_REG;
    else
        u4MRRReg = MRR_STATUS_MRR_REG;


    u4MRValue = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRR_STATUS), u4MRRReg);
    *u2pValue = (U16)u4MRValue;


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

#ifdef DUMP_INIT_RG_LOG_TO_DE
    gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag=1;
#endif

    mcSHOW_DBG_MSG4(("Read MR%d =0x%x\n", u1MRIdx, u4MRValue));
}


void DramcModeRegReadByRank(DRAMC_CTX_T *p, U8 u1Rank, U8 u1MRIdx, U16 *u2pValue)
{
    U16 u2Value = 0;
    U8 u1RankBak;


    u1RankBak = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0), SWCMD_CTRL0_MRSRK);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0), u1Rank, SWCMD_CTRL0_MRSRK);


    DramcModeRegRead(p, u1MRIdx, &u2Value);
    *u2pValue = u2Value;


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

}

void DramcModeRegWriteByRank_RTMRW(DRAMC_CTX_T *p, U8 *u1Rank, U8 *u1MRIdx, U8 *u1Value, U8 u1Len)
{
    U32 u4Response, u4TimeCnt, ii;
    U8 u1MRRK[6] = {0}, u1MRMA[6] = {0}, u1MROP[6] = {0};

    if (u1Len > 6 || u1Len == 0)
        return;

    for (ii = 0;ii < u1Len;ii++)
    {
        u1MRRK[ii] = u1Rank[ii];
        u1MRMA[ii] = u1MRIdx[ii];
        u1MROP[ii] = u1Value[ii];
    }

    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_RTMRW_CTRL0),
            P_Fld(3, RTMRW_CTRL0_RTMRW_LAT) |
            P_Fld(0x20, RTMRW_CTRL0_RTMRW_AGE) |
            P_Fld(u1Len - 1, RTMRW_CTRL0_RTMRW_LEN) |
            P_Fld(u1MRRK[0], RTMRW_CTRL0_RTMRW0_RK) |
            P_Fld(u1MRRK[1], RTMRW_CTRL0_RTMRW1_RK) |
            P_Fld(u1MRRK[2], RTMRW_CTRL0_RTMRW2_RK) |
            P_Fld(u1MRRK[3], RTMRW_CTRL0_RTMRW3_RK) |
            P_Fld(u1MRRK[4], RTMRW_CTRL0_RTMRW4_RK) |
            P_Fld(u1MRRK[5], RTMRW_CTRL0_RTMRW5_RK));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_RTMRW_CTRL1),
            P_Fld(u1MRMA[0], RTMRW_CTRL1_RTMRW0_MA) |
            P_Fld(u1MRMA[1], RTMRW_CTRL1_RTMRW1_MA) |
            P_Fld(u1MRMA[2], RTMRW_CTRL1_RTMRW2_MA) |
            P_Fld(u1MRMA[3], RTMRW_CTRL1_RTMRW3_MA));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_RTMRW_CTRL2),
            P_Fld(u1MROP[0], RTMRW_CTRL2_RTMRW0_OP) |
            P_Fld(u1MROP[1], RTMRW_CTRL2_RTMRW1_OP) |
            P_Fld(u1MROP[2], RTMRW_CTRL2_RTMRW2_OP) |
            P_Fld(u1MROP[3], RTMRW_CTRL2_RTMRW3_OP));
    vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_RTMRW_CTRL3),
            P_Fld(u1MRMA[4], RTMRW_CTRL3_RTMRW4_MA) |
            P_Fld(u1MRMA[5], RTMRW_CTRL3_RTMRW5_MA) |
            P_Fld(u1MROP[4], RTMRW_CTRL3_RTMRW4_OP) |
            P_Fld(u1MROP[5], RTMRW_CTRL3_RTMRW5_OP));
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MPC_CTRL),
            1, MPC_CTRL_RTMRW_HPRI_EN);
    mcDELAY_US(5);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN),
            1, SWCMD_EN_RTMRWEN);

    u4TimeCnt = TIME_OUT_CNT;

    do {
        u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP),
                SPCMDRESP_RTMRW_RESPONSE);
        u4TimeCnt--;
        mcDELAY_US(5);
    } while ((u4Response == 0) && (u4TimeCnt > 0));

    if (u4TimeCnt == 0)
    {
        mcSHOW_ERR_MSG(("[LP5 RT MRW ] Resp fail (time out) Rank=%d, MR%d=0x%x\n", u1Rank[0], u1MRIdx[0], u1Value[0]));
    }

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN),
            0, SWCMD_EN_RTMRWEN);
}

static void DramcModeRegWriteByRank_SCSM(DRAMC_CTX_T *p, U8 u1Rank, U8 u1MRIdx, U8 u1Value)
{
    U32 counter = 0;
    U32 u4RabnkBackup;
    U32 u4register_024;


    u4RabnkBackup = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0), SWCMD_CTRL0_MRSRK);


    u4register_024 = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL));


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


    CKEFixOnOff(p, u1Rank, CKE_FIXON, TO_ONE_CHANNEL);

    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0), u1MRIdx, SWCMD_CTRL0_MRSMA);
    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0), u1Value, SWCMD_CTRL0_MRSOP);


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


    while (u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_MRW_RESPONSE) == 0)
    {
        counter++;
        mcSHOW_DBG_MSG2(("wait MRW command Rank%d MR%d =0x%x fired (%d)\n", u1Rank, u1MRIdx, u1Value, counter));
        mcDELAY_US(1);
    }


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


    vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL), u4register_024);


    vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0), u4RabnkBackup, SWCMD_CTRL0_MRSRK);
}

void DramcModeRegWriteByRank(DRAMC_CTX_T *p, U8 u1Rank, U8 u1MRIdx, U8 u1Value)
{
    mcSHOW_DBG_MSG2(("MRW RK%d MR#%d = 0x%x\n", u1Rank,u1MRIdx, u1Value));

    #if (fcFOR_CHIP_ID == fcA60868)


        if (u1EnterRuntime)
        {
            DramcModeRegWriteByRank_SCSM(p, u1Rank, u1MRIdx, u1Value);
        }
    else
#endif
        {
            {
                DramcModeRegWriteByRank_SCSM(p, u1Rank, u1MRIdx, u1Value);
            }
        }

    #if MRW_CHECK_ONLY
    u1PrintModeRegWrite = 1;
    U8 u1Backup_Rank;
    U8 u1RankIdx, u1RankNum, u1RankStart;
    U8 u1FSPMRIdx;

    u1Backup_Rank=p->rank;

    if (u1Rank==3)
    {
        u1RankNum = 2;
        u1RankStart = 0;
    }
    else
    {
        u1RankNum = 1;
        u1RankStart = u1Rank;
    }

        u1FSPMRIdx=13;

    for (u1RankIdx=u1RankStart;u1RankIdx<u1RankStart+u1RankNum;u1RankIdx++)
    {
        vSetRank(p, u1RankIdx);
        if (u1MRIdx==u1FSPMRIdx)
        {
            u2MRRecord[p->channel][u1RankIdx][FSP_0][u1FSPMRIdx] =u1Value;
            u2MRRecord[p->channel][u1RankIdx][FSP_1][u1FSPMRIdx] =u1Value;
        }
        else
            u2MRRecord[p->channel][u1RankIdx][gFSPWR_Flag[u1RankIdx]][u1MRIdx] = u1Value;

        if(u1PrintModeRegWrite)
        {
            #if VENDER_JV_LOG
            mcSHOW_JV_LOG_MSG(("Write Rank%d MR%d =0x%x\n", u1RankIdx, u1MRIdx, u1Value));
            #endif
            #if MRW_CHECK_ONLY
            mcSHOW_MRW_MSG(("MRW CH%d Rank%d FSP%d MR%d =0x%x\n", p->channel, u1RankIdx, gFSPWR_Flag[u1RankIdx], u1MRIdx, u1Value));
            #endif
            mcSHOW_DBG_MSG2(("Write Rank%d MR%d =0x%x\n", u1RankIdx, u1MRIdx, u1Value));
            //mcDUMP_REG_MSG(("Write Rank%d MR%d =0x%x\n", u1RankIdx, u1MRIdx, u1Value));
        }
        #if MRW_BACKUP
        U8 MR_backup;

        MR_backup=DramcMRWriteBackup(p, u1MRIdx, u1RankIdx);
        if (MR_backup!=0xff)
            mcSHOW_MRW_MSG(("  [MRW Check] Rank%d FSP%d Backup_MR%d= 0x%x MR%d= 0x%x ==>%s\n", u1RankIdx, gFSPWR_Flag[u1RankIdx], u1MRIdx, MR_backup, u1MRIdx, u1Value, (u1Value==MR_backup?"PASS":"FAIL")));
        #endif

            {
                if (u1MRIdx==u1FSPMRIdx)
                    gFSPWR_Flag[u1RankIdx] = (u1Value>> 6) & 0x1;
            }
    }
    vSetRank(p, u1Backup_Rank);
    #endif
}

#if __ETT__
static U8 u1gpRegBackup;
#endif
U32 u4gpRegBackupVlaue[100];
void DramcBackupRegisters(DRAMC_CTX_T *p, U32 *backup_addr, U32 backup_num)
{
    U32 u4RegIdx;

#if __ETT__
    if (backup_num > 100 || u1gpRegBackup)
    {
        mcSHOW_ERR_MSG(("[DramcBackupRegisters] backup number over 64!!!\n"));
        while (1);
    }

    u1gpRegBackup++;
#endif

    for (u4RegIdx = 0; u4RegIdx < backup_num; u4RegIdx++)
    {
        u4gpRegBackupVlaue[u4RegIdx] = u4IO32Read4B(backup_addr[u4RegIdx]);
        //mcSHOW_DBG_MSG(("Backup Reg(0x%X) = 0x%X\n", backup_addr[u4RegIdx], u4gpRegBackupVlaue[u4RegIdx]));
    }
}

void DramcRestoreRegisters(DRAMC_CTX_T *p, U32 *restore_addr, U32 restore_num)
{
    U32 u4RegIdx;

#if __ETT__
    if (u1gpRegBackup == 0)
    {
        mcSHOW_ERR_MSG(("[DramcRestoreRegisters] Need to call backup first\n"));
    }

    u1gpRegBackup--;
#endif

    for (u4RegIdx = 0; u4RegIdx < restore_num; u4RegIdx++)
    {
        vIO32Write4B(restore_addr[u4RegIdx], u4gpRegBackupVlaue[u4RegIdx]);
        //mcSHOW_DBG_MSG(("Restore Reg(0x%X) = 0x%X\n", restore_addr[u4RegIdx], u4gpRegBackupVlaue[u4RegIdx]));
    }
}


U8 u1GetMR4RefreshRate(DRAMC_CTX_T *p, DRAM_CHANNEL_T channel)
{
    U8 u1RefreshRate; //u1Dummy

    //vSetPHY2ChannelMapping(p, channel);

    //DramcModeRegRead(p, 4, &u1Dummy);
    //mcSHOW_DBG_MSG(("[u2GetRefreshRate] MR4 0x%x,  u1RefreshRate= 0x%x\n", u1Dummy, u1RefreshRate));
    u1RefreshRate = (U8)u4IO32ReadFldAlign((DRAMC_REG_MISC_STATUSA) + (channel << POS_BANK_NUM), MISC_STATUSA_REFRESH_RATE);
    //mcSHOW_DBG_MSG(("[u2GetRefreshRate] channel = %d, u1RefreshRate= 0x%x\n", channel, u1RefreshRate));

    return u1RefreshRate;
}

#if 0
//#if defined(DDR_INIT_TIME_PROFILING) || (__ETT__ && SUPPORT_SAVE_TIME_FOR_CALIBRATION)
void DramcConfInfraReset(DRAMC_CTX_T *p)
{
#if (FOR_DV_SIMULATION_USED == 0 && SW_CHANGE_FOR_SIMULATION == 0)
        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_ADDR(DDRPHY_REG_MISC_CG_CTRL0), P_Fld(0, MISC_CG_CTRL0_CLK_MEM_SEL)
                                                                | P_Fld(1, MISC_CG_CTRL0_W_CHG_MEM));
        mcDELAY_XNS(100);
        vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_REG_MISC_CG_CTRL0), 0, MISC_CG_CTRL0_W_CHG_MEM);

#if (fcFOR_CHIP_ID == fcLafite)

        vIO32WriteFldMulti_All(DDRPHY_CKMUX_SEL, P_Fld(0x1, CKMUX_SEL_R_PHYCTRLMUX)
                                    | P_Fld(0x1, CKMUX_SEL_R_PHYCTRLDCM));
        vIO32WriteFldMulti_All(DDRPHY_MISC_CG_CTRL0, P_Fld(0, MISC_CG_CTRL0_W_CHG_MEM)
                    | P_Fld(0, MISC_CG_CTRL0_CLK_MEM_SEL));
        vIO32WriteFldAlign_All(DDRPHY_MISC_CG_CTRL0, 1, MISC_CG_CTRL0_W_CHG_MEM);
        mcDELAY_US(1);
        vIO32WriteFldAlign_All(DDRPHY_MISC_CG_CTRL0, 0, MISC_CG_CTRL0_W_CHG_MEM);


        //mcSHOW_TIME_MSG(("Before infra reset, 0x10001148:%x\n", *(volatile unsigned *)(0x10001148)));
        *(volatile unsigned *)(0x10001140) = (0x1 << 15);
        //mcSHOW_TIME_MSG(("After infra reset, 0x10001148:%x\n",  *(volatile unsigned *)(0x10001148)));
        __asm__ __volatile__ ("dsb" : : : "memory");
        mcDELAY_US(200);
        //mcSHOW_TIME_MSG(("Before infra clear, 0x10001148:%x\n",  *(volatile unsigned *)(0x10001148)));
        *(volatile unsigned *)(0x10001144) = (0x1 << 15);
        //mcSHOW_TIME_MSG(("After infra clear, 0x10001148:%x\n",  *(volatile unsigned *)(0x10001148)));

        #if 0
        mcDELAY_US(200);
        *(volatile unsigned *)(0x10007018) = 0x88000040;
        mcDELAY_US(200);
        *(volatile unsigned *)(0x10007018) = 0x88000000;
        mcDELAY_US(200);
        #endif


        vIO32WriteFldAlign_All(DDRPHY_B0_DQ3, 0x0, B0_DQ3_RG_ARDQ_RESETB_B0);
        vIO32WriteFldAlign_All(DDRPHY_B0_DLL_ARPI0, 0x0, B0_DLL_ARPI0_RG_ARPI_RESETB_B0);
        vIO32WriteFldAlign_All(DDRPHY_B1_DQ3, 0x0, B1_DQ3_RG_ARDQ_RESETB_B1);
        vIO32WriteFldAlign_All(DDRPHY_B1_DLL_ARPI0, 0x0, B1_DLL_ARPI0_RG_ARPI_RESETB_B1);
        vIO32WriteFldAlign_All(DDRPHY_CA_CMD3, 0x0, CA_CMD3_RG_ARCMD_RESETB);
        vIO32WriteFldAlign_All(DDRPHY_CA_DLL_ARPI0, 0x0, CA_DLL_ARPI0_RG_ARPI_RESETB_CA);
        vIO32WriteFldAlign(DDRPHY_PLL4, 0x0, PLL4_RG_RPHYPLL_RESETB);
        mcDELAY_US(200);
        vIO32WriteFldAlign_All(DDRPHY_B0_DQ3, 0x1, B0_DQ3_RG_ARDQ_RESETB_B0);
        vIO32WriteFldAlign_All(DDRPHY_B0_DLL_ARPI0, 0x1, B0_DLL_ARPI0_RG_ARPI_RESETB_B0);
        vIO32WriteFldAlign_All(DDRPHY_B1_DQ3, 0x1, B1_DQ3_RG_ARDQ_RESETB_B1);
        vIO32WriteFldAlign_All(DDRPHY_B1_DLL_ARPI0, 0x1, B1_DLL_ARPI0_RG_ARPI_RESETB_B1);
        vIO32WriteFldAlign_All(DDRPHY_CA_CMD3, 0x1, CA_CMD3_RG_ARCMD_RESETB);
        vIO32WriteFldAlign_All(DDRPHY_CA_DLL_ARPI0, 0x1, CA_DLL_ARPI0_RG_ARPI_RESETB_CA);
        vIO32WriteFldAlign(DDRPHY_PLL4, 0x1, PLL4_RG_RPHYPLL_RESETB);


        vIO32WriteFldMulti(SPM_POWERON_CONFIG_EN, P_Fld(0xB16, POWERON_CONFIG_EN_PROJECT_CODE) | P_Fld(0, POWERON_CONFIG_EN_BCLK_CG_EN));


        vIO32WriteFldAlign_All(DDRPHY_MISC_CG_CTRL2, 0x0, MISC_CG_CTRL2_RG_MEM_DCM_DCM_EN);
        vIO32WriteFldAlign_All(DDRPHY_MISC_CG_CTRL2, 0x1, MISC_CG_CTRL2_RG_MEM_DCM_FORCE_ON);
#endif
#endif
}
#endif

#if 0
#define PATTERN1 0x5A5A5A5A
#define PATTERN2 0xA5A5A5A5
int dramc_complex_mem_test (unsigned int start, unsigned int len)
{
    unsigned char *MEM8_BASE = (unsigned char *) start;
    unsigned short *MEM16_BASE = (unsigned short *) start;
    unsigned int *MEM32_BASE = (unsigned int *) start;
    unsigned int *MEM_BASE = (unsigned int *) start;
    unsigned char pattern8;
    unsigned short pattern16;
    unsigned int i, j, size, pattern32;
    unsigned int value;

    size = len >> 2;


    for (i = 0; i < size; i++)
    {
        MEM32_BASE[i] = 0;
    }

    for (i = 0; i < size; i++)
    {
        if (MEM32_BASE[i] != 0)
        {
            return -1;
        }
        else
        {
            MEM32_BASE[i] = 0xffffffff;
        }
    }


    for (i = 0; i < size; i++)
    {
        if (MEM32_BASE[i] != 0xffffffff)
        {
            return -2;
        }
        else
            MEM32_BASE[i] = 0x00;
    }


    pattern8 = 0x00;
    for (i = 0; i < len; i++)
        MEM8_BASE[i] = pattern8++;
    pattern8 = 0x00;
    for (i = 0; i < len; i++)
    {
        if (MEM8_BASE[i] != pattern8++)
        {
            return -3;
        }
    }


    pattern8 = 0x00;
    for (i = j = 0; i < len; i += 2, j++)
    {
        if (MEM8_BASE[i] == pattern8)
            MEM16_BASE[j] = pattern8;
        if (MEM16_BASE[j] != pattern8)
        {
            return -4;
        }
        pattern8 += 2;
    }


    pattern16 = 0x00;
    for (i = 0; i < (len >> 1); i++)
        MEM16_BASE[i] = pattern16++;
    pattern16 = 0x00;
    for (i = 0; i < (len >> 1); i++)
    {
        if (MEM16_BASE[i] != pattern16++)
        {
            return -5;
        }
    }


    pattern32 = 0x00;
    for (i = 0; i < (len >> 2); i++)
        MEM32_BASE[i] = pattern32++;
    pattern32 = 0x00;
    for (i = 0; i < (len >> 2); i++)
    {
        if (MEM32_BASE[i] != pattern32++)
        {
            return -6;
        }
    }


    for (i = 0; i < size; i++)
        MEM32_BASE[i] = 0x44332211;


    for (i = 0; i < size; i++)
    {
        if (MEM32_BASE[i] != 0x44332211)
        {
            return -7;
        }
        else
        {
            MEM32_BASE[i] = 0xa5a5a5a5;
        }
    }


    for (i = 0; i < size; i++)
    {
        if (MEM32_BASE[i] != 0xa5a5a5a5)
        {
            return -8;
        }
        else
        {
            MEM8_BASE[i * 4] = 0x00;
        }
    }


    for (i = 0; i < size; i++)
    {
        if (MEM32_BASE[i] != 0xa5a5a500)
        {
            return -9;
        }
        else
        {
            MEM8_BASE[i * 4 + 2] = 0x00;
        }
    }


    for (i = 0; i < size; i++)
    {
        if (MEM32_BASE[i] != 0xa500a500)
        {
            return -10;
        }
        else
        {
            MEM8_BASE[i * 4 + 1] = 0x00;
        }
    }


    for (i = 0; i < size; i++)
    {
        if (MEM32_BASE[i] != 0xa5000000)
        {
            return -11;
        }
        else
        {
            MEM8_BASE[i * 4 + 3] = 0x00;
        }
    }


    for (i = 0; i < size; i++)
    {
        if (MEM32_BASE[i] != 0x00000000)
        {
            return -12;
        }
        else
        {
            MEM16_BASE[i * 2 + 1] = 0xffff;
        }
    }


    for (i = 0; i < size; i++)
    {
        if (MEM32_BASE[i] != 0xffff0000)
        {
            return -13;
        }
        else
        {
            MEM16_BASE[i * 2] = 0xffff;
        }
    }


    for (i = 0; i < size; i++)
    {
        if (MEM32_BASE[i] != 0xffffffff)
        {
            return -14;
        }
    }



    for (i = 0; i < size; i++)
    {
        MEM_BASE[i] = PATTERN1;
    }


    for (i = 0; i < size; i++)
    {
        value = MEM_BASE[i];

        if (value != PATTERN1)
        {
            return -15;
        }
        MEM_BASE[i] = PATTERN2;
    }


    for (i = 0; i < size; i++)
    {
        value = MEM_BASE[i];
        if (value != PATTERN2)
        {
            return -16;
        }
        MEM_BASE[i] = PATTERN1;
    }



    for (i = 0; i < size; i++)
    {
        value = MEM_BASE[i];
        if (value != PATTERN1)
        {
            return -17;
        }
        MEM_BASE[i] = PATTERN2;
    }


    for (i = 0; i < size; i++)
    {
        value = MEM_BASE[i];
        if (value != PATTERN2)
        {
            return -18;
        }
        MEM_BASE[i] = PATTERN1;
    }


    for (i = 0; i < size; i++)
    {
        value = MEM_BASE[i];
        if (value != PATTERN1)
        {
            return -19;
        }
    }

#if 1

    i = (unsigned int) MEM_BASE;

    while (i < (unsigned int) MEM_BASE + (size << 2))
    {
        *((unsigned char *) i) = 0x78;
        i += 1;
        *((unsigned char *) i) = 0x56;
        i += 1;
        *((unsigned short *) i) = 0x1234;
        i += 2;
        *((unsigned int *) i) = 0x12345678;
        i += 4;
        *((unsigned short *) i) = 0x5678;
        i += 2;
        *((unsigned char *) i) = 0x34;
        i += 1;
        *((unsigned char *) i) = 0x12;
        i += 1;
        *((unsigned int *) i) = 0x12345678;
        i += 4;
        *((unsigned char *) i) = 0x78;
        i += 1;
        *((unsigned char *) i) = 0x56;
        i += 1;
        *((unsigned short *) i) = 0x1234;
        i += 2;
        *((unsigned int *) i) = 0x12345678;
        i += 4;
        *((unsigned short *) i) = 0x5678;
        i += 2;
        *((unsigned char *) i) = 0x34;
        i += 1;
        *((unsigned char *) i) = 0x12;
        i += 1;
        *((unsigned int *) i) = 0x12345678;
        i += 4;
    }
    for (i = 0; i < size; i++)
    {
        value = MEM_BASE[i];
        if (value != 0x12345678)
        {
            return -20;
        }
    }
#endif


    pattern8 = 0x00;
    MEM8_BASE[0] = pattern8;
    for (i = 0; i < size * 4; i++)
    {
        unsigned char waddr8, raddr8;
        waddr8 = i + 1;
        raddr8 = i;
        if (i < size * 4 - 1)
            MEM8_BASE[waddr8] = pattern8 + 1;
        if (MEM8_BASE[raddr8] != pattern8)
        {
            return -21;
        }
        pattern8++;
    }


    pattern16 = 0x00;
    MEM16_BASE[0] = pattern16;
    for (i = 0; i < size * 2; i++)
    {
        if (i < size * 2 - 1)
            MEM16_BASE[i + 1] = pattern16 + 1;
        if (MEM16_BASE[i] != pattern16)
        {
            return -22;
        }
        pattern16++;
    }


    pattern32 = 0x00;
    MEM32_BASE[0] = pattern32;
    for (i = 0; i < size; i++)
    {
        if (i < size - 1)
            MEM32_BASE[i + 1] = pattern32 + 1;
        if (MEM32_BASE[i] != pattern32)
        {
            return -23;
        }
        pattern32++;
    }
    return 0;
}
#endif

#if defined(DDR_INIT_TIME_PROFILING) || ENABLE_APB_MASK_WRITE
static PROFILING_TIME_T prof_tick0;

void TimeProfileGetTick(PROFILING_TIME_T *ptime)
{
#if __ETT__
    ptime->u4TickLow = GPT_GetTickCount(&ptime->u4TickHigh);
#else
    ptime->u4TickHigh = 0;
    ptime->u4TickLow = get_timer(0);
#endif
}

U32 TimeProfileDiffUS(PROFILING_TIME_T *base)
{
    U32 u4Diff;

#if __ETT__
    const U32 u4TsMax = 0xFFFFFFFFUL;
    const U32 u4NsPerTick = 76;
    const U32 u4OV = u4TsMax / u4NsPerTick;
    U32 u4Acc;
    PROFILING_TIME_T end;

    u4Acc = 0;
    TimeProfileGetTick(&end);


        u4Diff = end.u4TickLow - base->u4TickLow;
    if (end.u4TickLow > base->u4TickLow)
    {
        u4Diff = end.u4TickLow - base->u4TickLow;
    }
    else
    {
        u4Diff = u4TsMax - base->u4TickLow + end.u4TickLow;
        mcSHOW_TIME_MSG(("%s(): overflow detected\n", __func__));
    }

    while (u4Diff >= u4OV)
    {
        u4Acc++;
        u4Diff -= u4OV;
    }

    u4Diff = u4Diff * u4NsPerTick / 1000;
    u4Diff += u4Acc * (u4TsMax / 1000);
#else
    u4Diff = get_timer(base->u4TickLow) * 1000;
#endif

    return u4Diff;
}

void TimeProfileBegin(void)
{
    TimeProfileGetTick(&prof_tick0);
}

U32 TimeProfileEnd(void)
{
    return TimeProfileDiffUS(&prof_tick0);
}
#endif

#if QT_GUI_Tool
void TA2_Test_Run_Time_SW_Presetting(DRAMC_CTX_T *p, U32 test2_1, U32 test2_2, U8 u1TestPat, U8 u1LoopCnt)
{
        u1TestPat = u1TestPat & 0x7f;

        DramcSetRankEngine2(p, p->rank);

        uiReg0D0h=u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_DUMMY_RD));
        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_DUMMY_RD), P_Fld(0, DUMMY_RD_DQSG_DMYRD_EN) | P_Fld(0, DUMMY_RD_DQSG_DMYWR_EN) | P_Fld(0, DUMMY_RD_DUMMY_RD_EN) | P_Fld(0, DUMMY_RD_SREF_DMYRD_EN) | P_Fld(0, DUMMY_RD_DMY_RD_DBG) | P_Fld(0, DUMMY_RD_DMY_WR_DBG));  //must close dummy read when do test agent

        //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TESTCHIP_DMA1), 0, TESTCHIP_DMA1_DMA_LP4MATAB_OPT);//Eddie

        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3), P_Fld(0, TEST2_A3_TEST2W) | P_Fld(0, TEST2_A3_TEST2R) | P_Fld(0, TEST2_A3_TEST1));


        vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A0), P_Fld(test2_1>>24,TEST2_A0_TEST2_PAT0)|P_Fld(test2_2>>24,TEST2_A0_TEST2_PAT1));

    #if (FOR_DV_SIMULATION_USED==1 || SW_CHANGE_FOR_SIMULATION==1)

        //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A1), (test2_1+0x100) & 0x00ffffff, TEST2_A1_TEST2_BASE);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK_TEST2_A1),  0x10000, RK_TEST2_A1_TEST2_BASE);
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK_TEST2_A1),  0x0, RK_TEST2_A1_TEST2_BASE);
    #else
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK_TEST2_A1), 0, RK_TEST2_A1_TEST2_BASE);
    #endif
        vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A2), 0x2, TEST2_A2_TEST2_OFF);

    return;
}
#endif
