blob: 63384cf4f8d18305381c6cb0d231dd578eb6ae47 [file] [log] [blame]
/* 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; //disable broadcast in A60868
#endif
#if __Petrus_TO_BE_PORTING__
U8 u1BroadcastStatus = 0;
// INFRA_RSVD3[9:8] = protect_set_clr_mask
u1BroadcastStatus = (*((volatile unsigned int *)(INFRA_RSVD3)) >> 8) & 0x3;
if (u1BroadcastStatus & 0x1) // Enable new infra access by Preloader
{
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 //for channel number = 1 or 2
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;//CONA 8,9th 0:1ch, 1:2ch, 2:4ch
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)
{
/* Below listed conditions represent freqs that exist in ACTimingTable
* -> Should cover freqGroup settings for all real freq values
*/
{
if (p->frequency <= 200) // DDR400
{
p->freqGroup = 200;
}
else if (p->frequency <= 400) // DDR800
{
p->freqGroup = 400;
}
else if (p->frequency <= 600) // DDR1200
{
p->freqGroup = 600;
}
else if (p->frequency <= 800) // DDR1600
{
p->freqGroup = 800;
}
else if (p->frequency <= 933) //DDR1866
{
p->freqGroup = 933;
}
else if (p->frequency <= 1200) //DDR2400, DDR2280
{
p->freqGroup = 1200;
}
else if (p->frequency <= 1333) // DDR2667
{
p->freqGroup = 1333;
}
else if (p->frequency <= 1600) // DDR3200
{
p->freqGroup = 1600;
}
else if (p->frequency <= 1866) // DDR3733
{
p->freqGroup = 1866;
}
else // DDR4266
{
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);
/* The result may be used as divisor, so need to avoid 0 returned */
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(DRAMC_REG_SHUSTATUS, SHUSTATUS_SHUFFLE_LEVEL);
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;
//Darren-U32 u4PLL4 = DDRPHY_SHU_PLL4 + SHU_GRP_DDRPHY_OFFSET * u1ShuLevel; // for DDR4266
U32 u4B0_DQ6 = DDRPHY_REG_SHU_B0_DQ6 + SHU_GRP_DDRPHY_OFFSET * u1ShuLevel;
/* VCOFreq = FREQ_XTAL x ((RG_RCLRPLL_SDM_PCW) / 2^(RG_*_RCLRPLL_PREDIV)) / 2^(RG_*_RCLRPLL_POSDIV) */
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);
//Darren-U16 u2CKMUL2 = u4IO32ReadFldAlign(u4PLL4, SHU_PLL4_RG_RPHYPLL_RESERVED);
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)) // for 1:4 mode DDR800 (3.2G/DIV4) and DDR400 (1.6G/DIV4)
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; //@ tg add for simulation speed up
#else
return p->pDFSTable->vref_calibartion_enable;
#endif
}
/* vGet_Dram_CBT_Mode
* Due to current HW design (both ranks share the same set of ACTiming regs), mixed
* mode LP4 now uses byte mode ACTiming settings. This means most calibration steps
* should use byte mode code flow.
* Note: The below items must have per-rank settings (Don't use this function)
* 1. CBT training 2. TX tracking
*/
DRAM_CBT_MODE_T vGet_Dram_CBT_Mode(DRAMC_CTX_T *p)
{
if (p->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 /*DDRPhyFMeter()*/,
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); /* Set p->freqGroup to support freqs not in ACTimingTable */
///TODO: add DBI_onoff by condition
//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) //need check unterm highest freq is saved at SRAM_SHU4??
//CBT
if (get_type == EYESCAN_TYPE_CBT)
if (ENABLE_EYESCAN_CBT==1) return ENABLE; //TO DO :Temp Force open EYESCAN
//RX
if (get_type == EYESCAN_TYPE_RX)
if (ENABLE_EYESCAN_RX==1) return ENABLE; //TO DO :Temp Force open EYESCAN
//TX
if (get_type == EYESCAN_TYPE_TX)
if (ENABLE_EYESCAN_TX==1) return ENABLE; //TO DO :Temp Force open EYESCAN
#else
//CBT
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; //K All freq
if (p->frequency == u2DFSGetHighestFreq(p)) return ENABLE; // K highest freq
if (gEye_Scan_unterm_highest_flag==ENABLE && vGet_Current_SRAMIdx(p)==SRAM_SHU2) return ENABLE; // K unterm highest freq
}
//RX
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; //K All freq
if (p->frequency == u2DFSGetHighestFreq(p)) return ENABLE; // K highest freq
if (gEye_Scan_unterm_highest_flag==ENABLE && vGet_Current_SRAMIdx(p)==SRAM_SHU2) return ENABLE; // K unterm highest freq
}
//TX
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; //K All freq
if (p->frequency == u2DFSGetHighestFreq(p)) return ENABLE; // K highest freq
if (gEye_Scan_unterm_highest_flag==ENABLE && vGet_Current_SRAMIdx(p)==SRAM_SHU2) return ENABLE; // K unterm highest freq
}
#endif
#endif
return DISABLE;
}
void DramcWriteDBIOnOff(DRAMC_CTX_T *p, U8 onoff)
{
// DRAMC Write-DBI On/Off
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)
{
// DRAMC Read-DBI On/Off
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));
//DRAM MR3[6] read-DBI On/Off
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
//DRAM MR3[7] write-DBI On/Off
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);
//restore broadcast on/off
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) //if CKE is dynamic, set both CKE fix On and Off as 0
{ //After CKE FIX on/off, CKE should be returned to dynamic (control by HW)
u1CKEOn = u1CKEOff = 0;
}
else //if CKE fix on is set as 1, CKE fix off should also be set as 0; vice versa
{
u1CKEOn = option;
u1CKEOff = (1 - option);
}
if (WriteChannelNUM == TO_ALL_CHANNEL) //write register 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)
{
//enable autorefresh
vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0), 0, REFCTRL0_REFDIS); //REFDIS=0, enable auto refresh
}
else // DISABLE
{
//disable autorefresh
vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0), 1, REFCTRL0_REFDIS); //REFDIS=1, disable auto refresh
//because HW will actually disable autorefresh after refresh_queue empty, so we need to wait quene empty.
mcDELAY_US(u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MISC_STATUSA), MISC_STATUSA_REFRESH_QUEUE_CNT) * 4); //wait refresh_queue_cnt * 3.9us
}
}
//-------------------------------------------------------------------------
/** vCKERankCtrl
* Control CKE toggle mode (toggle both ranks 1. at the same time (CKE_RANK_DEPENDENT) 2. individually (CKE_RANK_INDEPENDENT))
* Note: Sets CKE toggle mode for all channels
* @param p Pointer of context created by DramcCtxCreate.
* @param CKECtrlMode Indicates
*/
//-------------------------------------------------------------------------
void vCKERankCtrl(DRAMC_CTX_T *p, CKE_CTRL_MODE_T CKECtrlMode)
{
/* Struct indicating all register fields mentioned in "multi rank CKE control" */
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_Rank dependent/independent mode register setting values */
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
};
//Select CKE control mode
CKE_Mode = (CKECtrlMode == CKE_RANK_INDEPENDENT)? CKE_Rank_Independent: CKE_Rank_Dependent;
//Apply CKE control mode register settings
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 // max loop
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)//UI shift function
{
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)
{
//LPDDR2_3_ADRDECEN_TARKMODE =0, always rank0
/* ADRDECEN_TARKMODE: rank input selection
* 1'b1 select CTO_AGENT1_RANK, 1'b0 rank by address decode
*/
vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3), 1, TEST2_A3_ADRDECEN_TARKMODE);
// DUMMY_TESTAGENTRKSEL =0, select rank according to CATRAIN_TESTAGENTRK
/* TESTAGENTRKSEL: Test agent access rank mode selection
* 2'b00: rank selection by TESTAGENTRK, 2'b01: rank selection by CTO_AGENT_1_BK_ADR[0]
* 2'b10: rank selection by CTO_AGENT1_COL_ADR[3], 2'b11: rank selection by CTO_AGENT1_COL_ADR[4]
*/
vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4), 0, TEST2_A4_TESTAGENTRKSEL);
//CATRAIN_TESTAGENTRK = u1RankSel
/* TESTAGENTRK: Specify test agent rank
* 2'b00 rank 0, 2'b01 rank 1, 2'b10 rank 2
*/
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) //u1LoopCnt is related to rank
{
if ((u1TestPat == TEST_XTALK_PATTERN) || (u1TestPat == TEST_SSOXTALK_PATTERN)) //xtalk or SSO+XTALK
{
//TEST_REQ_LEN1=1 is new feature, hope to make dq bus continously.
//but DV simulation will got problem of compare err
//so go back to use old way
//TEST_REQ_LEN1=0, R_DMRWOFOEN=1
if (u1Len1Flag != 0)
{
vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4),
P_Fld(1, TEST2_A4_TEST_REQ_LEN1)); //test agent 2 with cmd length = 0, LEN1 of 256bits data
DramcSetRWOFOEN(p, 0); //@IPM will fix for LEN1=1 issue
}
else
{
vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4),
P_Fld(0, TEST2_A4_TEST_REQ_LEN1)); //test agent 2 with cmd length = 0
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)); //dont use audio pattern
if (u1TestPat == TEST_SSOXTALK_PATTERN)
{
//set addr 0x48[16] to 1, TESTXTALKPAT = 1
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)); //use XTALK pattern, dont use audio pattern
//R_DMTESTSSOPAT=0, R_DMTESTSSOXTALKPAT=0
vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4),
P_Fld(1, TEST2_A4_TESTSSOPAT) |
P_Fld(0, TEST2_A4_TESTSSOXTALKPAT)); //dont use sso, sso+xtalk pattern
}
else //select XTALK pattern
{
//set addr 0x48[16] to 1, TESTXTALKPAT = 1
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)); //use XTALK pattern, dont use audio pattern
//R_DMTESTSSOPAT=0, R_DMTESTSSOXTALKPAT=0
vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4),
P_Fld(0, TEST2_A4_TESTSSOPAT) |
P_Fld(0, TEST2_A4_TESTSSOXTALKPAT)); //dont use sso, sso+xtalk pattern
}
}
else if (u1TestPat == TEST_AUDIO_PATTERN) //AUDIO
{
vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4),
P_Fld(0, TEST2_A4_TEST_REQ_LEN1)); //test agent 2 with cmd length = 0
// set AUDINIT=0x11 AUDINC=0x0d AUDBITINV=1 AUDMODE=1(1:read only(address fix), 0: write/read address change)
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));
// set addr 0x044 [7] to 1 ,select audio pattern
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) //TEST2_OFF > 'h56
{
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);//Set to min value to save time;
}
else //ISI
{
vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4),
P_Fld(0, TEST2_A4_TEST_REQ_LEN1)); //test agent 2 with cmd length = 0
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); //Enalbe/Disable UI shift
}
#define CMP_CPT_POLLING_PERIOD 1 // timeout for TE2: (CMP_CPT_POLLING_PERIOD X MAX_CMP_CPT_WAIT_LOOP)
#define MAX_CMP_CPT_WAIT_LOOP 100000 // max loop
static void DramcEngine2CheckComplete(DRAMC_CTX_T *p, U8 u1status)
{
U32 u4loop_count = 0;
U32 u4Ta2_loop_count = 0;
U32 u4ShiftUiFlag = 0;//Use TEST_WORST_SI_PATTERN_UI_SHIFT
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)
{
/*TINFO="fcWAVEFORM_MEASURE_A %d: time out\n", u4loop_count*/
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)//Use TEST_WORST_SI_PATTERN_UI_SHIFT
{
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; //RK0
U32 u4ShiftUiFlag = 0;
u4loopcount = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3), TEST2_A3_TESTCNT);
if (u4loopcount == 1)
u1status = 3; //RK0/1
u4ShiftUiFlag = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A3), TEST2_A3_TEST2_PAT_SHIFT);
if (wr == TE_OP_WRITE_READ_CHECK)
{
if(!u4ShiftUiFlag)//Could not use while UI shift is open
{
// read data compare ready check
DramcEngine2CheckComplete(p, u1status);
// disable write
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);
// enable read
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));
}
}
// 5
// read data compare ready check
DramcEngine2CheckComplete(p, u1status);
// delay 10ns after ready check from DE suggestion (1ms here)
//mcDELAY_US(1);
u4result = (u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_TESTRPT)) >> 4) & u1status; //CMP_ERR_RK0/1
return u4result;
}
//-------------------------------------------------------------------------
/** DramcEngine2
* start the self test engine 2 inside dramc to test dram w/r.
* @param p Pointer of context created by DramcCtxCreate.
* @param wr (DRAM_TE_OP_T): TE operation
* @param test2_1 (U32): 28bits,base address[27:0].
* @param test2_2 (U32): 28bits,offset address[27:0]. (unit is 16-byte, i.e: 0x100 is 0x1000).
* @param loopforever (S16): 0 read\write one time ,then exit
* >0 enable eingie2, after "loopforever" second ,write log and exit
* -1 loop forever to read\write, every "period" seconds ,check result ,only when we find error,write log and exit
* -2 loop forever to read\write, every "period" seconds ,write log ,only when we find error,write log and exit
* -3 just enable loop forever ,then exit
* @param period (U8): it is valid only when loopforever <0; period should greater than 0
* @param u1LoopCnt (U8): test loop number of test agent2 loop number =2^(u1LoopCnt) ,0 one time
* @retval status (U32): return the value of DM_CMP_ERR ,0 is ok ,others mean error
*/
//-------------------------------------------------------------------------
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;
// error handling
if (!p)
{
mcSHOW_ERR_MSG(("context is NULL\n"));
return DRAM_FAIL;
}
// check loop number validness
// if ((u1LoopCnt > 15) || (u1LoopCnt < 0)) // U8 >=0 always.
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)); //must close dummy read when do test agent
//fixme-zj vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TESTCHIP_DMA1), 0, TESTCHIP_DMA1_DMA_LP4MATAB_OPT);
// disable self test engine1 and self test engine2
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));
// 1.set pattern ,base address ,offset address
// 2.select ISI pattern or audio pattern or xtalk pattern
// 3.set loop number
// 4.enable read or write
// 5.loop to check DM_CMP_CPT
// 6.return CMP_ERR
// currently only implement ucengine_status = 1, others are left for future extension
// 1
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));
{
// LP4 TA2 base: 0x10000. It's only TBA constrain, but not HW.
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);
// 2 & 3
// (TESTXTALKPAT, TESTAUDPAT) = 00 (ISI), 01 (AUD), 10 (XTALK), 11 (UNKNOWN)
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;
// 4
if (wr == TE_OP_READ_CHECK)
{
if ((u1TestPat == 1) || (u1TestPat == 2))
{
//if audio pattern, enable read only (disable write after read), AUDMODE=0x48[15]=0
vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A4), 0, TEST2_A4_TESTAUDMODE);
}
// enable read, 0x008[31:29]
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)
{
// enable write
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);
// delay 10ns after ready check from DE suggestion (1ms here)
mcDELAY_US(1);
// 6
// return CMP_ERR, 0 is ok ,others are fail,diable test2w or test2r
// get result
// or all result
u4result = (u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_CMP_ERR)));
// disable read
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)); //test agent 2 with cmd length = 0
DramcSetRWOFOEN(p, 1);
vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_DUMMY_RD), uiReg0D0h);
}
#if 0
// Full set of usage test engine 2, including of DramcEngine2Init->DramcEngine2Run->DramcEngine2End
// if you don't care the performance, and just for convinent, you may use this API (TestEngineCompare)
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///TODO:Darren confirm
//#define SUB_EMI_APB_BASE 0x1021D000
// 0x10219000 for CH0/1
// 0x1021D000 for CH2/3
#endif
U8 u1MaType = 0x2; // for DV sim
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; // 0x1021D000 for CH2/3
u1EmiChIdx = u1ChannelIdx-2;
}
}
#endif
u4matype = u4IO32Read4B(EMI_APB_BASE + u4EmiOffset);
u4matypeR0 = ((u4matype >> (4 + u1EmiChIdx * 16)) & 0x3) + 1; //refer to init_ta2_single_channel()
u4matypeR1 = ((u4matype >> (6 + u1EmiChIdx * 16)) & 0x3) + 1; //refer to init_ta2_single_channel()
if(p->support_rank_num==RANK_SINGLE)
{
u4matype = u4matypeR0;
}
else
{
u4matype = (u4matypeR0 > u4matypeR1) ? u4matypeR1 : u4matypeR0; //get min value
}
//vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MATYPE), u4matype, MATYPE_MATYPE);
}
vSetPHY2ChannelMapping(p, eOriChannel);
u1MaType = u4matype;
return;
}
/* ----------------------------------------------------------------------
* LP4 RG Address
* bit: 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 9 8 7 6 5 4 3 2 1 0
* 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
* ---------------------------------------------------------------
* RG: - - R R R R R R R R R R R R R R R R R R|B B B|C C C C C C - - -
* 2_BASE 1 1 1 1 1 1 1 1 9 8 7 6 5 4 3 2 1 0|A A A|9 8 7 6 5 4
* 7 6 5 4 3 2 1 0 |2 1 0|
* AXI ---------------------------------------------------------------
* Addr: R R R R R R R R R R R R R R R R|B B B|C C C|C|C C C C C C C -
* 1 1 1 1 1 1 9 8 7 6 5 4 3 2 1 0|A A A|9 8 7|H|6 5 4 3 2 1 0
* 5 4 3 2 1 0 |2 1 0| | |
* ----------------------------------------------------------------------
*/
#define TA2_RANK0_ADDRESS (0x40200000)
#define AXI_CHAN_BIT_WIDTH 1 //2: 4_channel 1: 2_channel
#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 // @ tg add to fix simulation compile error
#else
#define TRANSFER_DRAM_ADDR_BY_EMI_API 1 //1: by emi API 0: by above table
#endif
void TA2_Test_Run_Time_HW_Presetting(DRAMC_CTX_T * p, U32 len, TA2_RKSEL_TYPE_T rksel_mode)/* Should call after TA2_Test_Run_Time_Pat_Setting() */
{
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); //Make sure row. bank. column are correct
u4BaseR0 = ((dram_addr.row << 12) | (dram_addr.bk << 9) | (dram_addr.col >> 1)) >> 3;// >>1: RG C4 @3th bit >>3: RG start with bit 3
}
#else
// >>AXI_CHAN_BIT_WIDTH: drop bit8; >>OFFSET_OF_RG_BASE_AND_AXI: align with RG row; >>3: RG start with bit 3
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);//5:0x20 bytes(256 bits) address coverage per pattern(128 bits data + 128 bits bubble); offset should bigger than 0xFF
}
else
{
u4BaseR0 = u4Addr >> 4;
if (rksel_mode == TA2_RKSEL_XRT)
{
u4Offset = len >> 4;//16B per pattern
}
else
{
u4Offset = (len >> 4) >> 1;//16B per pattern //len should be >>2 or test engine will time out
}
}
u4BaseR1 = u4BaseR0;
u4matypeR0 = ((u4IO32Read4B(EMI_APB_BASE) >> 4) & 0x3) + 1;
u4matypeR1 = ((u4IO32Read4B(EMI_APB_BASE) >> 6) & 0x3) + 1;
if (u4matypeR0 != u4matypeR1)//R0 R1 mix mode
{
(u4matypeR0 > u4matypeR1)? (u4BaseR0 >>= 1): (u4BaseR1 >>= 1);//set the correct start address, refer to mapping table
u4Offset >>= 1;//set min value
}
u4Offset = (u4Offset == 0) ? 1 : u4Offset; //halt if u4Offset = 0
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;//3; //6: for emilpbk_dq_dvs_leadlag_toggle_ringcnt
}
#endif
if (TA2_RKSEL_XRT == rksel_mode)
{
// In order to enhance XRT R2R/W2W probability, use TEST2_4_TESTAGENTRKSEL=3, PERFCTL0_RWOFOEN=0 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);//fill based on RG table for Rank 0
}
vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A2), u4Offset, TEST2_A2_TEST2_OFF);//128 bits data length per offest
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; //Worst SI pattern + loop mode + LEN1
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; //3: 2 ranks; 1: 1 rank
U32 u4loop_count = 0;
DRAM_CHANNEL_T eOriChannel = p->channel;
for (u1ChannelIdx = 0; u1ChannelIdx < p->support_channel_num; u1ChannelIdx++)
{
vSetPHY2ChannelMapping(p, u1ChannelIdx);
//Step 1: set LOOP_NV_END=0
vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A0), 0, TEST2_A0_LOOP_NV_END);
//Step 2: check TA2 status
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;
}
}
//Step 3: set TEST2W/TEST2R=0 and RG_TA2_LOOP_EN=0
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; //CMP_ERR_RK0/1
//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)); //loop counter
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) //RK0 or RK1 test fail
{
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; //RK0/1
vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TEST2_A0), 0, TEST2_A0_LOOP_NV_END);//cancel NV_END
DramcEngine2CheckComplete(p, u1status);//Wait for complete
//mcSHOW_DBG_MSG(("TESTRPT_TESTSTAT:%x\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TESTRPT), TESTRPT_TESTSTAT)));//check TESTRPT_TESTSTAT
u4ErrorValue = (u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_TESTRPT)) >> 4) & 0x3; //CMP_ERR_RK0/1
}
else
u4ErrorValue = DramcEngine2Compare(p, TE_OP_WRITE_READ_CHECK);
if (u4ErrorValue & 0x3) //RK0 or RK1 test fail
{
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); //TEST2_2_TEST2_OFF = 0x400
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 trigger W
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) /* All MR */
{
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) /* MR only in FSP0/FSP1 */
{
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 /* MR in FSP0/FSP1/FSP2 */
{
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);
// MRR command will be fired when MRREN 0->1
vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 1, SWCMD_EN_MRREN);
// wait MRR command fired.
while (u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_MRR_RESPONSE) == 0)
{
mcDELAY_US(1);
}
// Since LP3 does not support CG condition, LP3 can not use MRR_STATUS_MRR_SW_REG to do sw mrr.
// After fix HW CG condition, LP3 will use MRR_STATUS_MRR_SW_REG to do sw mrr.
U32 u4MRRReg;
if (u1IsLP4Family(p->dram_type))
u4MRRReg = MRR_STATUS_MRR_SW_REG;
else
u4MRRReg = MRR_STATUS_MRR_REG;
// Read out mode register value
u4MRValue = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRR_STATUS), u4MRRReg);
*u2pValue = (U16)u4MRValue;
// Set MRREN =0 for next time MRR.
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;
/* Since, TMRRI design changed (2 kinds of modes depending on value of R_DMRK_SCINPUT_OPT)
* DE: Jouling, Berson
* To specify SW_MRR rank -> new mode(scinput_opt == 0): MRSRK
* old mode(scinput_opt == 1): MRRRK
* Note: MPCRK is not used by SW to control rank anymore
*/
//Backup & set rank
u1RankBak = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0), SWCMD_CTRL0_MRSRK); //backup rank
vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0), u1Rank, SWCMD_CTRL0_MRSRK); //set rank
//Mode reg read
DramcModeRegRead(p, u1MRIdx, &u2Value);
*u2pValue = u2Value;
//Restore rank
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)//time out
{
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;
// backup rank
u4RabnkBackup = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0), SWCMD_CTRL0_MRSRK);
//backup register of CKE fix on/off
u4register_024 = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL));
// set rank
vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_CTRL0), u1Rank, SWCMD_CTRL0_MRSRK);
//CKE must be fix on when doing MRW
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);
// MRW command will be fired when MRWEN 0->1
vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 1, SWCMD_EN_MRWEN);
// wait MRW command fired.
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);
}
// Set MRWEN =0 for next time MRW.
vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SWCMD_EN), 0, SWCMD_EN_MRWEN);
// restore CKEFIXON value
vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL), u4register_024);
// restore rank
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)
// RTMRW & RTSWCMD-MRW can not be used in runtime
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);//reserve 100ns period for clock mute and latch the rising edge sync condition for BCLK
vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_REG_MISC_CG_CTRL0), 0, MISC_CG_CTRL0_W_CHG_MEM);
#if (fcFOR_CHIP_ID == fcLafite)
// 26M
vIO32WriteFldMulti_All(DDRPHY_CKMUX_SEL, P_Fld(0x1, CKMUX_SEL_R_PHYCTRLMUX) //move CKMUX_SEL_R_PHYCTRLMUX to here (it was originally between MISC_CG_CTRL0_CLK_MEM_SEL and MISC_CTRL0_R_DMRDSEL_DIV2_OPT)
| P_Fld(0x1, CKMUX_SEL_R_PHYCTRLDCM)); // PHYCTRLDCM 1: follow DDRPHY_conf DCM settings, 0: follow infra DCM settings
vIO32WriteFldMulti_All(DDRPHY_MISC_CG_CTRL0, P_Fld(0, MISC_CG_CTRL0_W_CHG_MEM)
| P_Fld(0, MISC_CG_CTRL0_CLK_MEM_SEL));//[5:4] mem_ck mux: 2'b00: 26MHz, [0]: change memory clock
vIO32WriteFldAlign_All(DDRPHY_MISC_CG_CTRL0, 1, MISC_CG_CTRL0_W_CHG_MEM);//change clock freq
mcDELAY_US(1);
vIO32WriteFldAlign_All(DDRPHY_MISC_CG_CTRL0, 0, MISC_CG_CTRL0_W_CHG_MEM);//disable memory clock change
// dramc conf reset
//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
//DDRPHY Reset
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);//Since there is only 1 PLL, only control CHA
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);//Since there is only 1 PLL, only control CHA
//Disable SPM control
vIO32WriteFldMulti(SPM_POWERON_CONFIG_EN, P_Fld(0xB16, POWERON_CONFIG_EN_PROJECT_CODE) | P_Fld(0, POWERON_CONFIG_EN_BCLK_CG_EN));
//For FMeter after dcm enable
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;
/* === Verify the tied bits (tied high) === */
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;
}
}
/* === Verify the tied bits (tied low) === */
for (i = 0; i < size; i++)
{
if (MEM32_BASE[i] != 0xffffffff)
{
return -2;
}
else
MEM32_BASE[i] = 0x00;
}
/* === Verify pattern 1 (0x00~0xff) === */
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;
}
}
/* === Verify pattern 2 (0x00~0xff) === */
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;
}
/* === Verify pattern 3 (0x00~0xffff) === */
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;
}
}
/* === Verify pattern 4 (0x00~0xffffffff) === */
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;
}
}
/* === Pattern 5: Filling memory range with 0x44332211 === */
for (i = 0; i < size; i++)
MEM32_BASE[i] = 0x44332211;
/* === Read Check then Fill Memory with a5a5a5a5 Pattern === */
for (i = 0; i < size; i++)
{
if (MEM32_BASE[i] != 0x44332211)
{
return -7;
}
else
{
MEM32_BASE[i] = 0xa5a5a5a5;
}
}
/* === Read Check then Fill Memory with 00 Byte Pattern at offset 0h === */
for (i = 0; i < size; i++)
{
if (MEM32_BASE[i] != 0xa5a5a5a5)
{
return -8;
}
else
{
MEM8_BASE[i * 4] = 0x00;
}
}
/* === Read Check then Fill Memory with 00 Byte Pattern at offset 2h === */
for (i = 0; i < size; i++)
{
if (MEM32_BASE[i] != 0xa5a5a500)
{
return -9;
}
else
{
MEM8_BASE[i * 4 + 2] = 0x00;
}
}
/* === Read Check then Fill Memory with 00 Byte Pattern at offset 1h === */
for (i = 0; i < size; i++)
{
if (MEM32_BASE[i] != 0xa500a500)
{
return -10;
}
else
{
MEM8_BASE[i * 4 + 1] = 0x00;
}
}
/* === Read Check then Fill Memory with 00 Byte Pattern at offset 3h === */
for (i = 0; i < size; i++)
{
if (MEM32_BASE[i] != 0xa5000000)
{
return -11;
}
else
{
MEM8_BASE[i * 4 + 3] = 0x00;
}
}
/* === Read Check then Fill Memory with ffff Word Pattern at offset 1h == */
for (i = 0; i < size; i++)
{
if (MEM32_BASE[i] != 0x00000000)
{
return -12;
}
else
{
MEM16_BASE[i * 2 + 1] = 0xffff;
}
}
/* === Read Check then Fill Memory with ffff Word Pattern at offset 0h == */
for (i = 0; i < size; i++)
{
if (MEM32_BASE[i] != 0xffff0000)
{
return -13;
}
else
{
MEM16_BASE[i * 2] = 0xffff;
}
}
/*=== Read Check === */
for (i = 0; i < size; i++)
{
if (MEM32_BASE[i] != 0xffffffff)
{
return -14;
}
}
/************************************************
* Additional verification
************************************************/
/* === stage 1 => write 0 === */
for (i = 0; i < size; i++)
{
MEM_BASE[i] = PATTERN1;
}
/* === stage 2 => read 0, write 0xF === */
for (i = 0; i < size; i++)
{
value = MEM_BASE[i];
if (value != PATTERN1)
{
return -15;
}
MEM_BASE[i] = PATTERN2;
}
/* === stage 3 => read 0xF, write 0 === */
for (i = 0; i < size; i++)
{
value = MEM_BASE[i];
if (value != PATTERN2)
{
return -16;
}
MEM_BASE[i] = PATTERN1;
}
/* === stage 4 => read 0, write 0xF === */
for (i = 0; i < size; i++)
{
value = MEM_BASE[i];
if (value != PATTERN1)
{
return -17;
}
MEM_BASE[i] = PATTERN2;
}
/* === stage 5 => read 0xF, write 0 === */
for (i = 0; i < size; i++)
{
value = MEM_BASE[i];
if (value != PATTERN2)
{
return -18;
}
MEM_BASE[i] = PATTERN1;
}
/* === stage 6 => read 0 === */
for (i = 0; i < size; i++)
{
value = MEM_BASE[i];
if (value != PATTERN1)
{
return -19;
}
}
#if 1
/* === 1/2/4-byte combination test === */
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
/* === Verify pattern 1 (0x00~0xff) === */
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++;
}
/* === Verify pattern 2 (0x00~0xffff) === */
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++;
}
/* === Verify pattern 3 (0x00~0xffffffff) === */
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);
/* temporary patch for overflow */
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
// disable self test engine1 and self test engine2
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));
// 1.set pattern ,base address ,offset address
// 2.select ISI pattern or audio pattern or xtalk pattern
// 3.set loop number
// 4.enable read or write
// 5.loop to check DM_CMP_CPT
// 6.return CMP_ERR
// currently only implement ucengine_status = 1, others are left for future extension
// 1
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)
//DV sim memory 0~0x100 has values, can't used
//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); //LPDDR4 Setting
vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK_TEST2_A1), 0x0, RK_TEST2_A1_TEST2_BASE); //Eddie Change to 0 for LP5
#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);//Eddie
return;
}
#endif