[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/bsp/dramk_2731/dramc_pi_calibration_api.c b/src/bsp/dramk_2731/dramc_pi_calibration_api.c
new file mode 100755
index 0000000..a6df28f
--- /dev/null
+++ b/src/bsp/dramk_2731/dramc_pi_calibration_api.c
@@ -0,0 +1,17629 @@
+/*----------------------------------------------------------------------------*
+ * Copyright Statement: *
+ * *
+ * This software/firmware and related documentation ("MediaTek Software") *
+ * are protected under international and related jurisdictions'copyright laws *
+ * as unpublished works. The information contained herein is confidential and *
+ * proprietary to MediaTek Inc. Without the prior written permission of *
+ * MediaTek Inc., any reproduction, modification, use or disclosure of *
+ * MediaTek Software, and information contained herein, in whole or in part, *
+ * shall be strictly prohibited. *
+ * MediaTek Inc. Copyright (C) 2010. All rights reserved. *
+ * *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND *
+ * AGREES TO THE FOLLOWING: *
+ * *
+ * 1)Any and all intellectual property rights (including without *
+ * limitation, patent, copyright, and trade secrets) in and to this *
+ * Software/firmware and related documentation ("MediaTek Software") shall *
+ * remain the exclusive property of MediaTek Inc. Any and all intellectual *
+ * property rights (including without limitation, patent, copyright, and *
+ * trade secrets) in and to any modifications and derivatives to MediaTek *
+ * Software, whoever made, shall also remain the exclusive property of *
+ * MediaTek Inc. Nothing herein shall be construed as any transfer of any *
+ * title to any intellectual property right in MediaTek Software to Receiver. *
+ * *
+ * 2)This MediaTek Software Receiver received from MediaTek Inc. and/or its *
+ * representatives is provided to Receiver on an "AS IS" basis only. *
+ * MediaTek Inc. expressly disclaims all warranties, expressed or implied, *
+ * including but not limited to any implied warranties of merchantability, *
+ * non-infringement and fitness for a particular purpose and any warranties *
+ * arising out of course of performance, course of dealing or usage of trade. *
+ * MediaTek Inc. does not provide any warranty whatsoever with respect to the *
+ * software of any third party which may be used by, incorporated in, or *
+ * supplied with the MediaTek Software, and Receiver agrees to look only to *
+ * such third parties for any warranty claim relating thereto. Receiver *
+ * expressly acknowledges that it is Receiver's sole responsibility to obtain *
+ * from any third party all proper licenses contained in or delivered with *
+ * MediaTek Software. MediaTek is not responsible for any MediaTek Software *
+ * releases made to Receiver's specifications or to conform to a particular *
+ * standard or open forum. *
+ * *
+ * 3)Receiver further acknowledge that Receiver may, either presently *
+ * and/or in the future, instruct MediaTek Inc. to assist it in the *
+ * development and the implementation, in accordance with Receiver's designs, *
+ * of certain softwares relating to Receiver's product(s) (the "Services"). *
+ * Except as may be otherwise agreed to in writing, no warranties of any *
+ * kind, whether express or implied, are given by MediaTek Inc. with respect *
+ * to the Services provided, and the Services are provided on an "AS IS" *
+ * basis. Receiver further acknowledges that the Services may contain errors *
+ * that testing is important and it is solely responsible for fully testing *
+ * the Services and/or derivatives thereof before they are used, sublicensed *
+ * or distributed. Should there be any third party action brought against *
+ * MediaTek Inc. arising out of or relating to the Services, Receiver agree *
+ * to fully indemnify and hold MediaTek Inc. harmless. If the parties *
+ * mutually agree to enter into or continue a business relationship or other *
+ * arrangement, the terms and conditions set forth herein shall remain *
+ * effective and, unless explicitly stated otherwise, shall prevail in the *
+ * event of a conflict in the terms in any agreements entered into between *
+ * the parties. *
+ * *
+ * 4)Receiver's sole and exclusive remedy and MediaTek Inc.'s entire and *
+ * cumulative liability with respect to MediaTek Software released hereunder *
+ * will be, at MediaTek Inc.'s sole discretion, to replace or revise the *
+ * MediaTek Software at issue. *
+ * *
+ * 5)The transaction contemplated hereunder shall be construed in *
+ * accordance with the laws of Singapore, excluding its conflict of laws *
+ * principles. Any disputes, controversies or claims arising thereof and *
+ * related thereto shall be settled via arbitration in Singapore, under the *
+ * then current rules of the International Chamber of Commerce (ICC). The *
+ * arbitration shall be conducted in English. The awards of the arbitration *
+ * shall be final and binding upon both parties and shall be entered and *
+ * enforceable in any court of competent jurisdiction. *
+ *---------------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------------
+ *
+ * $Author: jc.wu $
+ * $Date: 2012/6/5 $
+ * $RCSfile: pi_calibration_api.c,v $
+ * $Revision: #5 $
+ *
+ *---------------------------------------------------------------------------*/
+
+/** @file pi_calibration_api.c
+ * Basic DRAMC calibration API implementation
+ */
+
+//-----------------------------------------------------------------------------
+// Include files
+//-----------------------------------------------------------------------------
+//#include "..\Common\pd_common.h"
+#include "dramc_common.h"
+#include "x_hal_io.h"
+#include "dramc_pi_api.h"
+//#include "DramC_reg.h"
+//#include "System_reg.h"
+
+#if 1//REG_ACCESS_PORTING_DGB
+U8 RegLogEnable=0;
+#endif
+
+#if REG_SHUFFLE_REG_CHECK
+U8 ShuffleRegCheck =0;
+#endif
+
+#define CATRAINING_NUM_LP3 10
+#define CATRAINING_NUM_LP4 6
+#define CATRAINING_NUM 10
+#define LP3_DIE_NUM_MAX 2
+
+#define MAX_CA_PI_DELAY 95 //63+32
+#define MAX_CS_PI_DELAY 63
+#define MAX_CLK_PI_DELAY 31
+
+#define PASS_RANGE_NA 0x7fff
+#define CATRAINING_PASS_RANGE_NA 0x7f
+
+
+#if (SW_CHANGE_FOR_SIMULATION ||FOR_DV_SIMULATION_USED)
+#define RX_VREF_RANGE_BEGIN 0
+#define RX_VREF_RANGE_END 2
+#define RX_VREF_RANGE_STEP 2
+#else
+#define RX_VREF_RANGE_BEGIN_ODT_OFF 16
+#define RX_VREF_RANGE_BEGIN_ODT_ON 6
+#define RX_VREF_RANGE_END 31 //bit5 useless (Justin) //field is 6 bit, but can only use 0~31
+#define RX_VREF_RANGE_STEP 1
+#endif
+
+//-----------------------------------------------------------------------------
+// Global variables
+//-----------------------------------------------------------------------------
+static U8 fgwrlevel_done = 0;
+
+#if defined(RELEASE)
+U8 gEye_Scan_color_flag = 0;
+U8 gCBT_EYE_Scan_flag = 0;
+U8 gCBT_EYE_Scan_only_higheset_freq_flag = 1;
+U8 gRX_EYE_Scan_flag = 0;
+U8 gRX_EYE_Scan_only_higheset_freq_flag = 1;
+U8 gTX_EYE_Scan_flag = 1;
+U8 gTX_EYE_Scan_only_higheset_freq_flag = 1;
+#else
+U8 gEye_Scan_color_flag = 1;
+U8 gCBT_EYE_Scan_flag = 0;
+U8 gCBT_EYE_Scan_only_higheset_freq_flag = 1;
+U8 gRX_EYE_Scan_flag = 0;
+U8 gRX_EYE_Scan_only_higheset_freq_flag = 1;
+U8 gTX_EYE_Scan_flag = 0;
+U8 gTX_EYE_Scan_only_higheset_freq_flag = 1;
+#endif
+
+#ifdef FOR_HQA_REPORT_USED
+U8 gHQALog_flag = 0;
+#endif
+
+U8 *u1ChannelSet;
+const U8 u1LP4Channel[] =
+{
+ CHANNEL_B
+}; //0:CHA, 1:CHB, 2:CHC, 3:CHD
+#if ENABLE_LP3_SW
+const U8 u1LP3Channel[] =
+{
+ CHANNEL_A
+}; //0:CHA, 1:CHB, 2:CHC, 3:CHD
+#endif
+
+U16 gu2MR0_Value[RANK_MAX] = {0xffff, 0xffff};
+U8 u1MR01Value[FSP_MAX];
+U8 u1MR02Value[FSP_MAX];
+U8 u1MR03Value[FSP_MAX];
+U8 u1MR13Value;
+
+U8 u1MR12Value[CHANNEL_NUM][RANK_MAX][FSP_MAX];
+U8 u1MR14Value[CHANNEL_NUM][RANK_MAX][FSP_MAX];
+
+#if MRW_CHECK_ONLY
+U16 u2MRRecord[CHANNEL_NUM][RANK_MAX][FSP_MAX][MR_NUM];
+#endif
+
+U8 gCBT_VREF_RANGE_SEL;
+U8 gCBT_VREF_RANGE_BEGIN;
+U8 gCBT_VREF_RANGE_END;
+U8 gCBT_VREF_RANGE_STEP;
+
+U8 gu1LP3DieNum[2]; // 2 rank may have different die number
+
+//U8 gu1MR23Done = FALSE; /* Not used starting from Vinson (all freqs use MR23=0x3F) */
+U8 gu1MR23[CHANNEL_NUM][RANK_MAX];
+/* DQSOSCTHRD_INC & _DEC are 12 bits (Starting from Vinson) */
+U16 gu2DQSOSCTHRD_INC[CHANNEL_NUM][RANK_MAX];
+U16 gu2DQSOSCTHRD_DEC[CHANNEL_NUM][RANK_MAX];
+U16 gu2MR18[CHANNEL_NUM][RANK_MAX]; /* Stores MRR MR18 (DQS ocillator count - MSB) */
+U16 gu2MR19[CHANNEL_NUM][RANK_MAX]; /* Stores MRR MR19 (DQS ocillator count - LSB) */
+U16 gu2DQSOSC[CHANNEL_NUM][RANK_MAX]; /* Stores tDQSOSC results */
+U16 gu2DQSOscCnt[CHANNEL_NUM][RANK_MAX][2];
+
+#define CBT_WORKAROUND_O1_SWAP 0 // set default clk and ca value
+
+static S32 CATrain_CmdDelay[CHANNEL_NUM][RANK_MAX];
+static U32 CATrain_CsDelay[CHANNEL_NUM][RANK_MAX];
+static S32 CATrain_ClkDelay[CHANNEL_NUM][RANK_MAX];
+static S32 wrlevel_dqs_final_delay[DQS_NUMBER]; // 3 is channel number
+static U16 u2rx_window_sum;
+static U8 ucg_num_dlycell_perT = 49; //from 60807
+U16 u2gdelay_cell_ps;
+U8 ucg_num_dlycell_perT_all[DRAM_DFS_SHUFFLE_MAX][CHANNEL_NUM];///TODO: to be removed by Francis
+U16 u2gdelay_cell_ps_all[DRAM_DFS_SHUFFLE_MAX][CHANNEL_NUM];///TODO: to be removed by Francis
+U32 u4gVcore[DRAM_DFS_SHUFFLE_MAX];
+
+U32 gDramcSwImpedanceResule[2][4]={{0,0,0,0},{0,0,0,0}};//ODT_ON/OFF x DRVP/DRVN/ODTP/ODTN
+#if APPLY_SIGNAL_WAVEFORM_SETTINGS_ADJUST
+S8 gDramcSwImpedanceAdjust[2][4]={{0,0,0,0},{0,0,0,0}};//ODT_ON/OFF x DRVP/DRVN/ODTP/ODTN
+S8 gDramcDqOdtRZQAdjust=-1;
+S8 gDramcMR03PDDSAdjust[FSP_MAX]={-1,-1};
+S8 gDramcMR22SoCODTAdjust[FSP_MAX]={-1,-1};
+#endif
+S8 iFirstCAPass[RANK_MAX][LP3_DIE_NUM_MAX][CATRAINING_NUM], iLastCAPass[RANK_MAX][LP3_DIE_NUM_MAX][CATRAINING_NUM]; // 2 die.
+
+S16 gu2RX_DQS_Duty_Offset[DQS_NUMBER][2];
+
+#ifdef FOR_HQA_TEST_USED
+U16 gFinalCBTVrefCA[CHANNEL_NUM][RANK_MAX];
+U16 gFinalCBTCA[CHANNEL_NUM][RANK_MAX][10];
+U16 gFinalRXPerbitWin[CHANNEL_NUM][RANK_MAX][DQ_DATA_WIDTH];
+U16 gFinalTXPerbitWin[CHANNEL_NUM][RANK_MAX][DQ_DATA_WIDTH];
+U16 gFinalTXPerbitWin_min_max[CHANNEL_NUM][RANK_MAX];
+U16 gFinalTXPerbitWin_min_margin[CHANNEL_NUM][RANK_MAX];
+U16 gFinalTXPerbitWin_min_margin_bit[CHANNEL_NUM][RANK_MAX];
+S8 gFinalClkDuty[CHANNEL_NUM];
+U32 gFinalClkDutyMinMax[CHANNEL_NUM][2];
+S8 gFinalDQSDuty[CHANNEL_NUM][DQS_NUMBER];
+U32 gFinalDQSDutyMinMax[CHANNEL_NUM][DQS_NUMBER][2];
+#endif
+U8 gFinalCBTVrefDQ[CHANNEL_NUM][RANK_MAX];
+U8 gFinalRXVrefDQ[CHANNEL_NUM][RANK_MAX];
+U8 gFinalTXVrefDQ[CHANNEL_NUM][RANK_MAX];
+
+#if EYESCAN_LOG
+#define VREF_TOTAL_NUM_WITH_RANGE 51+30 //range0 0~50 + range1 21~50
+#define EYESCAN_BROKEN_NUM 3
+#define EYESCAN_DATA_INVALID 0x7fff
+S16 gEyeScan_Min[VREF_TOTAL_NUM_WITH_RANGE][DQ_DATA_WIDTH_LP4][EYESCAN_BROKEN_NUM];
+S16 gEyeScan_Max[VREF_TOTAL_NUM_WITH_RANGE][DQ_DATA_WIDTH_LP4][EYESCAN_BROKEN_NUM];
+U16 gEyeScan_CaliDelay[DQS_NUMBER];
+U8 gEyeScan_WinSize[VREF_TOTAL_NUM_WITH_RANGE][DQ_DATA_WIDTH_LP4];
+S8 gEyeScan_DelayCellPI[DQ_DATA_WIDTH_LP4];
+U8 gEyeScan_ContinueVrefHeight[DQ_DATA_WIDTH_LP4];
+U16 gEyeScan_TotalPassCount[DQ_DATA_WIDTH_LP4];
+#endif
+
+#ifdef DEVIATION
+U8 gSetSpecificedVref_Enable[3]={0};
+U8 gSetSpecificedVref_Type=0;
+U8 gSetSpecificedVref_All_ChRk[3]={0};
+U8 gSetSpecificedVref_Channel[3]={0};
+U8 gSetSpecificedVref_Rank[3]={0};
+S8 gSetSpecificedVref_Vref_Offset[3]={0};
+#endif
+
+extern const U8 uiLPDDR4_MRR_Mapping_POP[CHANNEL_NUM][16];
+#if ENABLE_LP3_SW
+extern const U8 uiLPDDR3_O1_Mapping_POP[32];
+extern const U8 uiLPDDR3_O1_Mapping_POP_DLP3[32];
+#endif
+extern const U8 uiLPDDR4_O1_Mapping_POP[CHANNEL_NUM][16];
+
+extern DRAM_DFS_FREQUENCY_TABLE_T gFreqTbl[];
+extern DRAM_DFS_FREQUENCY_TABLE_T gFreqTbl_LP3[];
+
+extern const U16 gRXVref_Voltage_Table_LP4[RX_VREF_RANGE_END+1];
+extern const U16 gVref_Voltage_Table_LP4X[VREF_RANGE_MAX][VREF_VOLTAGE_TABLE_NUM];
+extern const U16 gVref_Voltage_Table_LP4[VREF_RANGE_MAX][VREF_VOLTAGE_TABLE_NUM];
+
+
+static void dle_factor_handler(DRAMC_CTX_T *p, U8 curr_val, U8 pip_num);
+U8 GetCmdBusTrainingVrefPinMuxRevertValue(DRAMC_CTX_T *p, U8 u1VrefLevel);
+U8 get_shuffleIndex_by_Freq(DRAMC_CTX_T *p); //Retrieve LP4's shuffle index from gFreqTbl
+
+void vInitGlobalVariablesByCondition(DRAM_DRAM_TYPE_T dram_type)
+{
+ U8 u1CHIdx, u1RankIdx, u1FSPIdx;
+#if MRW_CHECK_ONLY
+ U8 u1MRIdx;
+#endif
+ U8 u1Vref_Unterm;
+
+ u1MR01Value[FSP_0] = 0x26;
+ u1MR01Value[FSP_1] = 0x56;
+
+ if(dram_type==TYPE_LPDDR4)
+ u1Vref_Unterm = 0x4d; //LP4
+ else
+ u1Vref_Unterm = 0x5d; //LP4X
+
+ memset(u1MR12Value, u1Vref_Unterm, sizeof(u1MR12Value));
+
+ for(u1FSPIdx=0; u1FSPIdx<FSP_MAX; u1FSPIdx++)
+ {
+ u1MR02Value[u1FSPIdx]=0x1a;
+ u1MR03Value[u1FSPIdx]=0x31;
+ }
+
+ for(u1CHIdx=0; u1CHIdx<CHANNEL_NUM; u1CHIdx++)
+ for(u1RankIdx=0; u1RankIdx< RANK_MAX; u1RankIdx++)
+ for(u1FSPIdx=0; u1FSPIdx<FSP_MAX; u1FSPIdx++)
+ {
+ // MR14 default value, LP4 default 0x4d, LP4X 0x5d
+ u1MR14Value[u1CHIdx][u1RankIdx][u1FSPIdx] = (u1FSPIdx==FSP_0) ? u1Vref_Unterm : 0x10;
+ #if MRW_CHECK_ONLY
+ for(u1MRIdx=0; u1MRIdx<MR_NUM; u1MRIdx++)
+ u2MRRecord[u1CHIdx][u1RankIdx][u1FSPIdx][u1MRIdx] =0xffff;
+ #endif
+ }
+
+ memset(gu1MR23, 0x3F, sizeof(gu1MR23)); /* MR23 should be 0x3F for all freqs (Starting from Vinson) */
+ memset(gu2DQSOSCTHRD_INC, 0x6, sizeof(gu2DQSOSCTHRD_INC));
+ memset(gu2DQSOSCTHRD_DEC, 0x4, sizeof(gu2DQSOSCTHRD_DEC));
+ memset(gu2RX_DQS_Duty_Offset, 0, sizeof(gu2RX_DQS_Duty_Offset));
+
+
+}
+
+void vSetChannelNumber(DRAMC_CTX_T *p)
+{
+ if(u1IsLP4Family(p->dram_type))
+ {
+ u1ChannelSet = (U8 *)u1LP4Channel;
+ #if (!FOR_DV_SIMULATION_USED)
+ p->support_channel_num = sizeof(u1LP4Channel)/sizeof(U8); // 2 channel
+ #else
+ p->support_channel_num = CHANNEL_SINGLE;
+ #endif
+ }
+#if ENABLE_LP3_SW
+ else //LP3
+ {
+ u1ChannelSet = (U8 *)u1LP3Channel;
+ p->support_channel_num = sizeof(u1LP3Channel)/sizeof(U8);
+ }
+#endif /* ENABLE_LP3_SW */
+}
+
+void vSetRankNumber(DRAMC_CTX_T *p)
+{
+ if (u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RSTMASK), RSTMASK_RSV_DRAM_SUPPORT_RANK_NUM) == 0)
+ {
+ p->support_rank_num =RANK_DUAL;
+ }
+ else
+ {
+ p->support_rank_num =RANK_SINGLE;
+ }
+}
+
+void vSetPHY2ChannelMapping(DRAMC_CTX_T *p, U8 u1Channel)
+{
+ p->channel =u1Channel;
+}
+
+
+U8 vGetPHY2ChannelMapping(DRAMC_CTX_T *p)
+{
+ return p->channel;
+}
+
+void vSetRank(DRAMC_CTX_T *p, U8 ucRank)
+{
+ p->rank = ucRank;
+}
+
+U8 u1GetRank(DRAMC_CTX_T *p)
+{
+ return p->rank;
+}
+
+/* vGet_Dram_CBT_Mode
+ * Due to current HW design (both ranks share the same set of ACTiming regs), mixed
+ * mode LP4 now uses byte mode ACTiming settings. This means most calibration steps
+ * should use byte mode code flow.
+ * Note: The below items must have per-rank settings (Don't use this function)
+ * 1. CBT training 2. TX tracking
+ */
+DRAM_CBT_MODE_T vGet_Dram_CBT_Mode(DRAMC_CTX_T *p)
+{
+ if(p->dram_cbt_mode[RANK_0] == CBT_NORMAL_MODE && p->dram_cbt_mode[RANK_1] == CBT_NORMAL_MODE)
+ {
+ return CBT_NORMAL_MODE;
+ }
+ else // For Mixed mode & Byte mode LP4
+ {
+ return CBT_BYTE_MODE1;
+ }
+}
+
+#if PRINT_CALIBRATION_SUMMARY
+void vSetCalibrationResult(DRAMC_CTX_T *p, U8 ucCalType, U8 ucResult)
+{
+ p->aru4CalExecuteFlag[p->channel][p->rank] |= (1<<ucCalType); // ececution done
+ if (ucResult == DRAM_OK) // Calibration OK
+ {
+ p->aru4CalResultFlag[p->channel][p->rank] &= (~(1<<ucCalType));
+ }
+ else //Calibration fail
+ {
+ p->aru4CalResultFlag[p->channel][p->rank] |= (1<<ucCalType);
+ }
+}
+
+#if 0 //no use now, disable for saving code size.
+void vGetCalibrationResult_All(DRAMC_CTX_T *p, U8 u1Channel, U8 u1Rank, U8 u1FreqType, U32 *u4CalExecute, U32 *u4CalResult)
+{
+ *u4CalExecute = p->aru4CalExecuteFlag[u1Channel][u1Rank];
+ *u4CalResult = p->aru4CalResultFlag[u1Channel][u1Rank];
+}
+
+void vGetCalibrationResult(DRAMC_CTX_T *p, U8 ucCalType, U8 *ucCalExecute, U8 *ucCalResult)
+{
+ U32 ucCalResult_All, ucCalExecute_All;
+
+ ucCalExecute_All = p->aru4CalExecuteFlag[p->channel][p->rank];
+ ucCalResult_All = p->aru4CalResultFlag[p->channel][p->rank];
+
+ *ucCalExecute = (U8)((ucCalExecute_All >>ucCalType) & 0x1);
+ *ucCalResult = (U8)((ucCalResult_All >>ucCalType) & 0x1);
+}
+#endif
+
+const char *szCalibStatusName[DRAM_CALIBRATION_MAX]=
+{
+ "ZQ Calibration",
+ "SW Impedance",
+ "CA Training",
+ "Write leveling",
+ "RX DQS gating",
+ "RX DATLAT",
+ "RX DQ/DQS(RDDQC)",
+ "RX DQ/DQS(Engine)",
+ "TX DQ/DQS",
+};
+
+void vPrintCalibrationResult(DRAMC_CTX_T *p)
+{
+ U8 ucCHIdx, ucRankIdx, ucCalIdx;
+ U32 ucCalResult_All, ucCalExecute_All;
+ U8 ucCalResult, ucCalExecute;
+ U8 u1CalibrationFail;
+
+ mcSHOW_DBG_MSG(("\n\n[Calibration Summary] Freqency %d\n", p->frequency));
+
+ //for(ucFreqIdx=0; ucFreqIdx<DRAM_DFS_SHUFFLE_MAX; ucFreqIdx++)
+ {
+ //mcSHOW_DBG_MSG(("==Freqency = %d==\n", get_Freq_by_shuffleIndex(p,ucFreqIdx)));
+ for(ucCHIdx=0; ucCHIdx<p->support_channel_num; ucCHIdx++)
+ {
+ for(ucRankIdx=0; ucRankIdx<p->support_rank_num; ucRankIdx++)
+ {
+ u1CalibrationFail =0;
+ ucCalExecute_All = p->aru4CalExecuteFlag[u1ChannelSet[ucCHIdx]][ucRankIdx];
+ ucCalResult_All = p->aru4CalResultFlag[u1ChannelSet[ucCHIdx]][ucRankIdx];
+ mcSHOW_DBG_MSG(("CH %d, Rank %d\n", u1ChannelSet[ucCHIdx], ucRankIdx));
+ //mcSHOW_DBG_MSG(("[vPrintCalibrationResult] Channel = %d, Rank= %d, Freq.= %d, (ucCalExecute_All 0x%x, ucCalResult_All 0x%x)\n", ucCHIdx, ucRankIdx, ucFreqIdx, ucCalExecute_All, ucCalResult_All));
+
+ for(ucCalIdx =0; ucCalIdx<DRAM_CALIBRATION_MAX; ucCalIdx++)
+ {
+ ucCalExecute = (U8)((ucCalExecute_All >>ucCalIdx) & 0x1);
+ ucCalResult = (U8)((ucCalResult_All >>ucCalIdx) & 0x1);
+
+ if(ucCalExecute==1 && ucCalResult ==1) // excuted and fail
+ {
+ u1CalibrationFail =1;
+ mcSHOW_DBG_MSG(("%s: %s\n", szCalibStatusName[ucCalIdx], ((ucCalResult == 0) ? "OK" : "Fail")));
+ }
+ }
+
+ if(u1CalibrationFail ==0)
+ {
+ mcSHOW_DBG_MSG(("All Pass.\n"));
+ }
+ mcSHOW_DBG_MSG(("\n"));
+ }
+ }
+ }
+
+ memset(p->aru4CalResultFlag, 0, sizeof(p->aru4CalResultFlag));
+ memset(p->aru4CalExecuteFlag, 0, sizeof(p->aru4CalExecuteFlag));
+}
+#endif
+
+void vPrintCalibrationBasicInfo(DRAMC_CTX_T *p)
+{
+#if __ETT__
+ mcSHOW_DBG_MSG(("===============================================================================\n"
+ "Dram Type= %d, Freq= %u, FreqGroup= %u, CH_%d, rank %d\n"
+ "fsp= %d, odt_onoff= %d, Byte mode= %d\n"
+ "===============================================================================\n",
+ p->dram_type, DDRPhyFMeter(), p->freqGroup, p->channel, p->rank,
+ p->dram_fsp, p->odt_onoff, p->dram_cbt_mode[p->rank]));
+#else
+ mcSHOW_DBG_MSG(("===============================================================================\n"
+ "Dram Type= %d, Freq= %u, CH_%d, rank %d\n"
+ "fsp= %d, odt_onoff= %d, Byte mode= %d\n"
+ "===============================================================================\n",
+ p->dram_type, DDRPhyFMeter(), p->channel, p->rank,
+ p->dram_fsp, p->odt_onoff, p->dram_cbt_mode[p->rank]));
+#endif
+}
+
+#if VENDER_JV_LOG
+void vPrintCalibrationBasicInfo_ForJV(DRAMC_CTX_T *p)
+{
+ mcSHOW_DBG_MSG5(("\n\nDram type:"));
+
+ switch(p->dram_type)
+ {
+#if ENABLE_LP3_SW
+ case TYPE_LPDDR3:
+ mcSHOW_DBG_MSG5(("LPDDR3\t"));
+ break;
+#endif /* ENABLE_LP3_SW */
+ case TYPE_LPDDR4:
+ mcSHOW_DBG_MSG5(("LPDDR4\t"));
+ break;
+
+ case TYPE_LPDDR4X:
+ mcSHOW_DBG_MSG5(("LPDDR4X\t"));
+ break;
+
+ case TYPE_LPDDR4P:
+ mcSHOW_DBG_MSG5(("LPDDR4P\t"));
+ break;
+ }
+
+ mcSHOW_DBG_MSG5(("Freq: %d, FreqGroup %u, channel %d, rank %d\n"
+ "dram_fsp= %d, odt_onoff= %d, Byte mode= %d\n\n",
+ p->frequency, p->freqGroup, p->channel, p->rank,
+ p->dram_fsp, p->odt_onoff, p->dram_cbt_mode[p->rank]));
+
+ return;
+}
+#endif
+
+#ifdef DEVIATION
+void DeviationAddVrefOffset(U8 k_type, U16 *u2FinalRange, U16 *u2FinalVref, S8 Vref_Offset)
+{
+ S16 temp_vref_value;
+
+ if (k_type==1)
+ {
+ temp_vref_value = *u2FinalVref + Vref_Offset;
+ if (temp_vref_value < 0)
+ {
+ *u2FinalVref = 0;
+ }
+ else if (temp_vref_value < RX_VREF_RANGE_END)
+ {
+ *u2FinalVref = temp_vref_value;
+ }
+ else
+ {
+ *u2FinalVref = RX_VREF_RANGE_END;
+ }
+ }
+ else
+ {
+ temp_vref_value = (*u2FinalRange*30) + *u2FinalVref + Vref_Offset;
+ if (temp_vref_value < 0)
+ {
+ *u2FinalRange = 0;
+ *u2FinalVref = 0;
+ }
+ else if (temp_vref_value <=50)
+ {
+ *u2FinalRange = 0;
+ *u2FinalVref = temp_vref_value;
+ }
+ else if (temp_vref_value < 81)
+ {
+ *u2FinalRange = 1;
+ *u2FinalVref = temp_vref_value - 30;
+ }
+ else
+ {
+ *u2FinalRange = 1;
+ *u2FinalVref = 50;
+ }
+ }
+}
+#endif
+
+#if (__ETT__ || ENABLE_LP3_SW)
+//for LP3 read register in different byte
+U32 u4IO32ReadFldAlign_Phy_Byte2(DRAMC_CTX_T *p, U8 ucByteIdx, U32 reg32, U32 fld)
+{
+ U32 offset=0;
+ U32 except_offset=0;
+
+#if (fcFOR_CHIP_ID == fcLaurel)
+ if(reg32<Channel_A_PHY_AO_BASE_VIRTUAL)
+ {
+ mcSHOW_DBG_MSG(("\n[ReadFldAlign_Phy_Byte] wrong addr 0x%x\n", reg32));
+ #if (FOR_DV_SIMULATION_USED==0 && SW_CHANGE_FOR_SIMULATION==0)
+ ASSERT(0);
+ #endif
+ }
+
+ reg32 &= 0xffff;
+
+ if (reg32 >= (DDRPHY_SHU1_R0_B0_DQ0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_SHU1_R0_B1_DQ0-DDRPHY_AO_BASE_ADDR))
+ {
+ offset = 0x50;
+ ///TODO: BE CAREFUL. CLK (PHY) -> DQS (DRAM)
+ if (reg32 >= (DDRPHY_SHU1_R0_B0_DQ0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_SHU1_R0_B0_DQ6-DDRPHY_AO_BASE_ADDR))
+ {
+ except_offset = 0x0;
+ }
+ else
+ {
+ except_offset = 0x8;
+ }
+ }
+ else if (reg32 >= (DDRPHY_R0_B0_RXDVS0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_R0_B1_RXDVS0-DDRPHY_AO_BASE_ADDR))
+ {
+ offset = 0x80;
+ except_offset = 0;
+ }
+ else if (reg32 >= (DDRPHY_SHU1_B0_DQ0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_SHU1_B1_DQ0-DDRPHY_AO_BASE_ADDR))
+ {
+ offset = 0x80;
+ except_offset = 0;
+ }
+ else if (reg32 >= (DDRPHY_B0_DLL_ARPI0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_B1_DLL_ARPI0-DDRPHY_AO_BASE_ADDR))
+ {
+ offset = 0x80;
+ except_offset = 0;
+ }
+ else
+ {
+ offset = 0x0;
+ except_offset = 0;
+ }
+
+ switch(ucByteIdx)
+ {
+ case 0:
+ return u4IO32ReadFldAlign(reg32+Channel_B_PHY_AO_BASE_VIRTUAL+offset, fld); //CHB_B1
+ break;
+ case 1:
+ if(reg32==(DDRPHY_SHU1_R0_B0_DQ7&0xffff) && fld==SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0)
+ {
+ fld=SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS;
+ }
+ return u4IO32ReadFldAlign(reg32+Channel_B_PHY_AO_BASE_VIRTUAL+(offset<<1)+except_offset, fld); //CHB_CA
+ break;
+ case 2:
+ return u4IO32ReadFldAlign(reg32+Channel_A_PHY_AO_BASE_VIRTUAL+offset, fld); //CHA_B1
+ break;
+ case 3:
+ return u4IO32ReadFldAlign(reg32+Channel_B_PHY_AO_BASE_VIRTUAL, fld); //CHB_B0
+ break;
+ default:
+ mcSHOW_DBG_MSG(("\n[ReadFldAlign_Phy_Byte] wrong index of ucByteIdx !!!\n"));
+ break;
+ }
+#endif
+
+ #if (FOR_DV_SIMULATION_USED==0 && SW_CHANGE_FOR_SIMULATION==0)
+ ASSERT(0);
+ #endif
+}
+#endif
+
+#if ENABLE_LP3_SW
+//for LP3 write register in different byte
+void vIO32WriteFldAlign_Phy_Byte2(DRAMC_CTX_T *p, U8 ucByteIdx, U32 reg32, U32 val32, U32 fld)
+{
+#if (fcFOR_PINMUX == fcLaurel)
+ U32 offset=0;
+ U32 except_offset=0;
+
+ if(reg32 < Channel_A_PHY_AO_BASE_VIRTUAL)
+ {
+ mcSHOW_DBG_MSG(("\n[WriteFldAlign_Phy_Byte] wrong addr 0x%x\n", reg32));
+ return;
+ }
+ reg32 &= 0xffff;
+ if (reg32 >= (DDRPHY_SHU1_R0_B0_DQ0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_SHU1_R0_B1_DQ0-DDRPHY_AO_BASE_ADDR))
+ {
+ offset = 0x50;
+ ///TODO: BE CAREFUL. CLK (PHY) -> DQS (DRAM)
+ if (reg32 >= (DDRPHY_SHU1_R0_B0_DQ0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_SHU1_R0_B0_DQ6-DDRPHY_AO_BASE_ADDR))
+ {
+ except_offset = 0x0;
+ }
+ else
+ {
+ except_offset = 0x8;
+ }
+ }
+ else if (reg32 >= (DDRPHY_R0_B0_RXDVS0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_R0_B1_RXDVS0-DDRPHY_AO_BASE_ADDR))
+ {
+ offset = 0x80;
+ except_offset = 0x0;
+ }
+ else if (reg32 >= (DDRPHY_SHU1_B0_DQ0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_SHU1_B1_DQ0-DDRPHY_AO_BASE_ADDR))
+ {
+ offset = 0x80;
+ except_offset = 0;
+ }
+ else if (reg32 >= (DDRPHY_B0_DLL_ARPI0-DDRPHY_AO_BASE_ADDR) && reg32 < (DDRPHY_B1_DLL_ARPI0-DDRPHY_AO_BASE_ADDR))
+ {
+ offset = 0x80;
+ except_offset = 0;
+ }
+ else
+ {
+ offset = 0x0;
+ except_offset = 0;
+ }
+
+ switch(ucByteIdx)
+ {
+ case 0:
+ vIO32WriteFldAlign(reg32+Channel_B_PHY_AO_BASE_VIRTUAL+offset, val32, fld); //CHB_B1
+ break;
+ case 1:
+ if(reg32==(DDRPHY_SHU1_R0_B0_DQ7&0xffff) && fld==SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0)
+ {
+ fld=SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS;
+ }
+ vIO32WriteFldAlign(reg32+Channel_B_PHY_AO_BASE_VIRTUAL+(offset<<1)+except_offset, val32, fld); //CHB_CA
+ break;
+ case 2:
+ vIO32WriteFldAlign(reg32+Channel_A_PHY_AO_BASE_VIRTUAL+offset, val32, fld); //CHA_B1
+ break;
+ case 3:
+ vIO32WriteFldAlign(reg32+Channel_B_PHY_AO_BASE_VIRTUAL, val32, fld); //CHB_B0
+ break;
+ default:
+ mcSHOW_DBG_MSG(("\n[WriteFldAlign_Phy_Byte] wrong index of ucByteIdx !!!\n"));
+#if (FOR_DV_SIMULATION_USED==0 && SW_CHANGE_FOR_SIMULATION==0)
+ ASSERT(0);
+#endif
+ break;
+ }
+#endif
+}
+#endif /* ENABLE_LP3_SW */
+
+// for LP3 to control all PHY of single channel
+void vIO32WriteFldAlign_Phy_All2(DRAMC_CTX_T *p, U32 reg32, U32 val32, U32 fld)
+{
+ U8 ucCHIdx;
+
+ if(reg32<Channel_A_PHY_AO_BASE_VIRTUAL)
+ {
+ mcSHOW_DBG_MSG(("\n[WriteFldAlign_Phy_All] wrong addr 0x%x\n", reg32));
+ return;
+ }
+
+ reg32 &= 0xffff;
+
+ for(ucCHIdx=0; ucCHIdx<CHANNEL_NUM; ucCHIdx++)
+ {
+ vIO32WriteFldAlign(reg32+Channel_A_PHY_AO_BASE_VIRTUAL+0x10000*ucCHIdx, val32, fld);
+ }
+}
+
+void vApplyConfigAfterCalibration(DRAMC_CTX_T *p)
+{
+ U8 shu_index;
+/*================================
+ PHY RX Settings
+==================================*/
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldAlign_All(DDRPHY_MISC_CG_CTRL4, 0x11400000, MISC_CG_CTRL4_R_PHY_MCK_CG_CTRL);
+ vIO32WriteFldAlign_All(DRAMC_REG_REFCTRL1, 0x0, REFCTRL1_SREF_CG_OPT);
+ vIO32WriteFldAlign_All(DRAMC_REG_SHUCTRL, 0x0, SHUCTRL_DVFS_CG_OPT);
+
+ /* Burst mode settings are removed from here due to
+ * 1. Set in UpdateInitialSettings_LP4
+ * 2. DQS Gating ensures new burst mode is switched when to done
+ * (or doesn't switch gatingMode at all, depending on "LP4_GATING_OLD_BURST_MODE")
+ */
+
+ vIO32WriteFldAlign_All(DDRPHY_CA_CMD6, 0x0, CA_CMD6_RG_RX_ARCMD_RES_BIAS_EN);
+#if 0
+ vIO32WriteFldAlign_All(DDRPHY_B0_DQ6, 0x0, B0_DQ6_RG_TX_ARDQ_OE_EXT_DIS_B0);
+ vIO32WriteFldAlign_All(DDRPHY_B1_DQ6, 0x0, B1_DQ6_RG_TX_ARDQ_OE_EXT_DIS_B1);
+ vIO32WriteFldAlign_All(DDRPHY_CA_CMD6, 0x0, CA_CMD6_RG_TX_ARCMD_OE_EXT_DIS);
+#endif
+
+#if ENABLE_WRITE_DBI
+ EnableDRAMModeRegWriteDBIAfterCalibration(p);
+#endif
+
+#if ENABLE_READ_DBI
+ EnableDRAMModeRegReadDBIAfterCalibration(p);
+#endif
+
+ // Set VRCG{MR13[3]} to 0 both to DRAM and DVFS
+ SetMr13VrcgToNormalOperation(p);
+
+ }
+#if ENABLE_LP3_SW
+ else
+ { //pulse mode
+ vIO32WriteFldAlign_All(DDRPHY_B0_DQ9, 0x0, B0_DQ9_RG_RX_ARDQS0_DQSIENMODE_B0);
+ vIO32WriteFldAlign_All(DDRPHY_B1_DQ9, 0x0, B1_DQ9_RG_RX_ARDQS0_DQSIENMODE_B1);
+ vIO32WriteFldAlign_All(DDRPHY_CA_CMD10, 0x0, CA_CMD10_RG_RX_ARCLK_DQSIENMODE);
+
+ vIO32WriteFldAlign_All(DDRPHY_B0_DQ6, 0x0, B0_DQ6_RG_RX_ARDQ_BIAS_VREF_SEL_B0);
+ vIO32WriteFldAlign_All(DDRPHY_B1_DQ6, 0x0, B1_DQ6_RG_RX_ARDQ_BIAS_VREF_SEL_B1);
+ vIO32WriteFldAlign_All(DDRPHY_CA_CMD6, 0x0, CA_CMD6_RG_RX_ARCMD_BIAS_VREF_SEL);
+
+#if 0
+ vIO32WriteFldAlign_All(DDRPHY_B0_DQ6, 0x1, B0_DQ6_RG_TX_ARDQ_OE_EXT_DIS_B0);
+ vIO32WriteFldAlign_All(DDRPHY_B1_DQ6, 0x1, B1_DQ6_RG_TX_ARDQ_OE_EXT_DIS_B1);
+ vIO32WriteFldAlign_All(DDRPHY_CA_CMD6, 0x1, CA_CMD6_RG_TX_ARCMD_OE_EXT_DIS);
+#endif
+
+ }
+#endif /* ENABLE_LP3_SW */
+
+ //DA mode
+ vIO32WriteFldAlign_All(DDRPHY_B0_DQ6, 0x0, B0_DQ6_RG_RX_ARDQ_BIAS_PS_B0);
+ vIO32WriteFldAlign_All(DDRPHY_B1_DQ6, 0x0, B1_DQ6_RG_RX_ARDQ_BIAS_PS_B1);
+ vIO32WriteFldAlign_All(DDRPHY_CA_CMD6, 0x0, CA_CMD6_RG_RX_ARCMD_BIAS_PS);
+
+ vIO32WriteFldAlign_All(DDRPHY_B0_DQ6, 0x1, B0_DQ6_RG_RX_ARDQ_RPRE_TOG_EN_B0);
+ vIO32WriteFldAlign_All(DDRPHY_B1_DQ6, 0x1, B1_DQ6_RG_RX_ARDQ_RPRE_TOG_EN_B1);
+ vIO32WriteFldAlign_All(DDRPHY_CA_CMD6, 0x1, CA_CMD6_RG_RX_ARCMD_RPRE_TOG_EN);
+
+
+/*================================
+ IMPCAL Settings
+==================================*/
+ vIO32WriteFldMulti_All(DRAMC_REG_IMPCAL, P_Fld(0, IMPCAL_IMPCAL_IMPPDP) | P_Fld(0, IMPCAL_IMPCAL_IMPPDN)); //RG_RIMP_BIAS_EN and RG_RIMP_VREF_EN move to IMPPDP and IMPPDN
+ vIO32WriteFldAlign_All(DDRPHY_MISC_IMP_CTRL0, 0, MISC_IMP_CTRL0_RG_IMP_EN);
+
+/*================================
+ MR1
+==================================*/
+
+ //MR1 op[7]=0 already be setted at end of gating calibration, no need to set here again
+/*
+ u1MR01Value[p->dram_fsp] &= 0x7f;
+ DramcModeRegWrite(p, 1, u1MR01Value[p->dram_fsp]);
+*/
+ //Prevent M_CK OFF because of hardware auto-sync
+ vIO32WriteFldAlign_All(DDRPHY_MISC_CG_CTRL0, 0, Fld(4,0));
+
+ //DFS- fix Gating Tracking settings
+ vIO32WriteFldAlign_All(DDRPHY_MISC_CTRL0, 0, MISC_CTRL0_R_STBENCMP_DIV4CK_EN);
+ vIO32WriteFldAlign_All(DDRPHY_MISC_CTRL1, 0, MISC_CTRL1_R_DMSTBENCMP_RK_OPT);
+
+ ///TODO: Disable MR4 MR18/MR19, TxHWTracking, Dummy RD - for DFS workaround
+ vIO32WriteFldAlign_All(DRAMC_REG_SPCMDCTRL, 0x1, SPCMDCTRL_REFRDIS); //MR4 Disable
+ vIO32WriteFldAlign_All(DRAMC_REG_DQSOSCR, 0x1, DQSOSCR_DQSOSCRDIS); //MR18, MR19 Disable
+ for(shu_index = DRAM_DFS_SHUFFLE_1; shu_index < DRAM_DFS_SHUFFLE_MAX; shu_index++)
+ vIO32WriteFldAlign_All(DRAMC_REG_SHU_SCINTV + SHU_GRP_DRAMC_OFFSET*shu_index, 0x1, SHU_SCINTV_DQSOSCENDIS);
+ //vIO32WriteFldAlign_All(DRAMC_REG_SHU_SCINTV, 0x1, SHU_SCINTV_DQSOSCENDIS);
+ //vIO32WriteFldAlign_All(DRAMC_REG_SHU2_SCINTV, 0x1, SHU2_SCINTV_DQSOSCENDIS);
+ //vIO32WriteFldAlign_All(DRAMC_REG_SHU3_SCINTV, 0x1, SHU3_SCINTV_DQSOSCENDIS);
+ vIO32WriteFldMulti_All(DRAMC_REG_DUMMY_RD, P_Fld(0x0, DUMMY_RD_DUMMY_RD_EN)
+ | P_Fld(0x1, DUMMY_RD_SREF_DMYRD_EN)
+ | P_Fld(0x0, DUMMY_RD_DQSG_DMYRD_EN)
+ | P_Fld(0x0, DUMMY_RD_DMY_RD_DBG));
+#if APPLY_LP4_POWER_INIT_SEQUENCE
+ //CKE dynamic
+#if ENABLE_TMRRI_NEW_MODE
+ CKEFixOnOff(p, CKE_WRITE_TO_ALL_RANK, CKE_DYNAMIC, CKE_WRITE_TO_ALL_CHANNEL);
+#else
+ CKEFixOnOff(p, RANK_0, CKE_DYNAMIC, CKE_WRITE_TO_ALL_CHANNEL);
+#endif
+
+ //// Enable HW MIOCK control to make CLK dynamic
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 0, DRAMC_PD_CTRL_MIOCKCTRLOFF);
+#endif
+
+ //close eyescan to save power
+ vIO32WriteFldMulti_All(DRAMC_REG_EYESCAN, P_Fld(0x0, EYESCAN_EYESCAN_DQS_SYNC_EN)
+ | P_Fld(0x0, EYESCAN_EYESCAN_NEW_DQ_SYNC_EN)
+ | P_Fld(0x0, EYESCAN_EYESCAN_DQ_SYNC_EN));
+
+ /* TESTAGENT2 */
+ vIO32WriteFldAlign_All(DRAMC_REG_TEST2_4, 4, TEST2_4_TESTAGENTRKSEL); // Rank selection is controlled by Test Agent
+}
+
+#if defined(LOOPBACK_TEST) || (EMI_LPBK_DRAM_USED==0)
+void DramcLoopbackTest_settings(DRAMC_CTX_T *p, U8 u1Type)
+{
+
+ //close DCM, or DQ no clock
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 0, MISC_CTRL1_R_DMDQSIENCG_EN);
+
+ if (u1Type==1) //external loop back
+ {
+ //IOBIAS settings
+ vIO32WriteFldAlign_All(DDRPHY_B0_DQ6, 1, B0_DQ6_RG_RX_ARDQ_BIAS_PS_B0);
+ vIO32WriteFldAlign_All(DDRPHY_B1_DQ6, 1, B1_DQ6_RG_RX_ARDQ_BIAS_PS_B1);
+ vIO32WriteFldAlign_All(DDRPHY_CA_CMD6, 1, CA_CMD6_RG_RX_ARCMD_BIAS_PS);
+
+ //after initial, must set 0 of PHY registers
+ vIO32WriteFldMulti_All(DDRPHY_B0_DQ3, P_Fld(0, B0_DQ3_RG_RX_ARDQS0_SWAP_EN_B0) | P_Fld(0, B0_DQ3_RG_RX_ARDQ_OFFC_EN_B0) | P_Fld(0, B0_DQ3_RG_RX_ARDQ_SMT_EN_B0));
+ vIO32WriteFldMulti_All(DDRPHY_B1_DQ3, P_Fld(0, B1_DQ3_RG_RX_ARDQS0_SWAP_EN_B1) | P_Fld(0, B1_DQ3_RG_RX_ARDQ_OFFC_EN_B1) | P_Fld(0, B1_DQ3_RG_RX_ARDQ_SMT_EN_B1));
+ vIO32WriteFldMulti_All(DDRPHY_CA_CMD3, P_Fld(0, CA_CMD3_RG_RX_ARCLK_SWAP_EN) | P_Fld(0, CA_CMD3_RG_RX_ARCMD_OFFC_EN) | P_Fld(0, CA_CMD3_RG_RX_ARCMD_SMT_EN));
+
+ //after initial, must set 1 of PHY registers
+ vIO32WriteFldMulti_All(DDRPHY_B0_DQ3, P_Fld(1, B0_DQ3_RG_RX_ARDQ_STBENCMP_EN_B0) | P_Fld(1, B0_DQ3_RG_RX_ARDQ_IN_BUFF_EN_B0) | P_Fld(1, B0_DQ3_RG_RX_ARDQS0_IN_BUFF_EN_B0) | P_Fld(1, B0_DQ3_RG_ARDQ_RESETB_B0));
+ vIO32WriteFldAlign_All(DDRPHY_B0_DQ9, 1, B0_DQ9_RG_RX_ARDQ_STBEN_RESETB_B0);
+ vIO32WriteFldAlign_All(DDRPHY_B0_DQ5, 1, B0_DQ5_RG_RX_ARDQ_VREF_EN_B0);
+ vIO32WriteFldMulti_All(DDRPHY_B0_DQ6, P_Fld(1, B0_DQ6_RG_RX_ARDQ_BIAS_EN_B0) | P_Fld(1, B0_DQ6_RG_RX_ARDQ_RES_BIAS_EN_B0));
+
+ vIO32WriteFldMulti_All(DDRPHY_B1_DQ3, P_Fld(1, B1_DQ3_RG_RX_ARDQ_STBENCMP_EN_B1) | P_Fld(1, B1_DQ3_RG_RX_ARDQ_IN_BUFF_EN_B1) | P_Fld(1, B1_DQ3_RG_RX_ARDQS0_IN_BUFF_EN_B1) | P_Fld(1, B1_DQ3_RG_ARDQ_RESETB_B1));
+ vIO32WriteFldAlign_All(DDRPHY_B1_DQ9, 1, B1_DQ9_RG_RX_ARDQ_STBEN_RESETB_B1);
+ vIO32WriteFldAlign_All(DDRPHY_B1_DQ5, 1, B1_DQ5_RG_RX_ARDQ_VREF_EN_B1);
+ vIO32WriteFldMulti_All(DDRPHY_B1_DQ6, P_Fld(1, B1_DQ6_RG_RX_ARDQ_BIAS_EN_B1) | P_Fld(1, B1_DQ6_RG_RX_ARDQ_RES_BIAS_EN_B1));
+
+ vIO32WriteFldMulti_All(DDRPHY_CA_CMD3, P_Fld(1, CA_CMD3_RG_RX_ARCMD_STBENCMP_EN) | P_Fld(1, CA_CMD3_RG_RX_ARCMD_IN_BUFF_EN) | P_Fld(1, CA_CMD3_RG_RX_ARCLK_IN_BUFF_EN) | P_Fld(1, CA_CMD3_RG_ARCMD_RESETB));
+ vIO32WriteFldAlign_All(DDRPHY_CA_CMD10, 1, CA_CMD10_RG_RX_ARCMD_STBEN_RESETB);
+ vIO32WriteFldAlign_All(DDRPHY_CA_CMD5, 1, CA_CMD5_RG_RX_ARCMD_VREF_EN);
+ vIO32WriteFldMulti_All(DDRPHY_CA_CMD6, P_Fld(1, CA_CMD6_RG_RX_ARCMD_BIAS_EN) | P_Fld(1, CA_CMD6_RG_RX_ARCMD_RES_BIAS_EN));
+ }
+}
+#endif
+
+
+void vResetDelayChainBeforeCalibration(DRAMC_CTX_T *p)
+{
+ U8 u1RankIdx, u1RankIdxBak;
+
+ u1RankIdxBak = u1GetRank(p);
+
+ for(u1RankIdx=RANK_0; u1RankIdx<RANK_MAX; u1RankIdx++)
+ {
+ vSetRank(p, u1RankIdx);
+ vIO32WriteFldMulti_All(DDRPHY_SHU1_R0_CA_CMD0, P_Fld(0x0, SHU1_R0_CA_CMD0_RK0_TX_ARCA5_DLY)
+ | P_Fld(0x0, SHU1_R0_CA_CMD0_RK0_TX_ARCA4_DLY)
+ | P_Fld(0x0, SHU1_R0_CA_CMD0_RK0_TX_ARCA3_DLY)
+ | P_Fld(0x0, SHU1_R0_CA_CMD0_RK0_TX_ARCA2_DLY)
+ | P_Fld(0x0, SHU1_R0_CA_CMD0_RK0_TX_ARCA1_DLY)
+ | P_Fld(0x0, SHU1_R0_CA_CMD0_RK0_TX_ARCA0_DLY));
+ vIO32WriteFldMulti_All(DDRPHY_SHU1_R0_B0_DQ0, P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ7_DLY_B0)
+ | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ6_DLY_B0)
+ | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ5_DLY_B0)
+ | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ4_DLY_B0)
+ | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ3_DLY_B0)
+ | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ2_DLY_B0)
+ | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ1_DLY_B0)
+ | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ0_DLY_B0));
+ vIO32WriteFldMulti_All(DDRPHY_SHU1_R0_B1_DQ0, P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ7_DLY_B1)
+ | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ6_DLY_B1)
+ | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ5_DLY_B1)
+ | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ4_DLY_B1)
+ | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ3_DLY_B1)
+ | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ2_DLY_B1)
+ | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ1_DLY_B1)
+ | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ0_DLY_B1));
+ vIO32WriteFldAlign_All(DDRPHY_SHU1_R0_B0_DQ1, 0x0, SHU1_R0_B0_DQ1_RK0_TX_ARDQM0_DLY_B0);
+ vIO32WriteFldAlign_All(DDRPHY_SHU1_R0_B1_DQ1, 0x0, SHU1_R0_B1_DQ1_RK0_TX_ARDQM0_DLY_B1);
+ }
+
+ vSetRank(p, u1RankIdxBak);
+}
+
+
+void vApplyConfigBeforeCalibration(DRAMC_CTX_T *p)
+{
+ U8 shu_index;
+ U8 u1RankIdx, u1RankIdxBak;
+ u1RankIdxBak = u1GetRank(p);
+
+#if 0//ENABLE_LP3_SW
+ if(p->dram_type == TYPE_LPDDR3)
+ {
+ vIO32WriteFldAlign(DDRPHY_SHU1_B1_DLL0, 0x6, SHU1_B1_DLL0_RG_ARDLL_GAIN_B1);
+ vIO32WriteFldAlign(DDRPHY_SHU1_CA_DLL0+(SHIFT_TO_CHB_ADDR), 0x6, SHU1_CA_DLL0_RG_ARDLL_GAIN_CA);
+ vIO32WriteFldAlign(DDRPHY_SHU1_B0_DLL0+(SHIFT_TO_CHB_ADDR), 0x6, SHU1_B0_DLL0_RG_ARDLL_GAIN_B0);
+ vIO32WriteFldAlign(DDRPHY_SHU1_B1_DLL0+(SHIFT_TO_CHB_ADDR), 0x6, SHU1_B1_DLL0_RG_ARDLL_GAIN_B1);
+ }
+#endif
+
+ //Clk free run
+#if (SW_CHANGE_FOR_SIMULATION==0)
+ EnableDramcPhyDCM(p, 0);
+#endif
+
+ //Set LP3/LP4 Rank0/1 CA/TX delay chain to 0
+#if (FOR_DV_SIMULATION_USED==0)
+ //CA0~9 per bit delay line -> CHA_CA0 CHA_CA3 CHA_B0_DQ6 CHA_B0_DQ7 CHA_B0_DQ2 CHA_B0_DQ5 CHA_B0_DQ4 CHA_B0_DQ1 CHA_B0_DQ0 CHA_B0_DQ3
+ vResetDelayChainBeforeCalibration(p);
+#endif
+
+ //MR4 refresh cnt set to 0x1ff (2ms update)
+ vIO32WriteFldAlign_All(DRAMC_REG_SHU_CONF3, 0x1ff, SHU_CONF3_REFRCNT);
+
+ //The counter for Read MR4 cannot be reset after SREF if DRAMC no power down.
+ vIO32WriteFldAlign_All(DRAMC_REG_SPCMDCTRL, 1, SPCMDCTRL_SRFMR4_CNTKEEP_B);
+
+ //---- ZQ CS init --------
+ vIO32WriteFldAlign_All(DRAMC_REG_SHU_SCINTV, 0x1B, SHU_SCINTV_TZQLAT); //ZQ Calibration Time, unit: 38.46ns, tZQCAL min is 1 us. need to set larger than 0x1b
+ for(shu_index = DRAM_DFS_SHUFFLE_1; shu_index < DRAM_DFS_SHUFFLE_MAX; shu_index++)
+ vIO32WriteFldAlign_All(DRAMC_REG_SHU_CONF3 + SHU_GRP_DRAMC_OFFSET*shu_index, 0x1ff, SHU_CONF3_ZQCSCNT); //Every refresh number to issue ZQCS commands, only for DDR3/LPDDR2/LPDDR3/LPDDR4
+ //vIO32WriteFldAlign_All(DRAMC_REG_SHU_CONF3, 0x1ff, SHU_CONF3_ZQCSCNT); //Every refresh number to issue ZQCS commands, only for DDR3/LPDDR2/LPDDR3/LPDDR4
+ //vIO32WriteFldAlign_All(DRAMC_REG_SHU2_CONF3, 0x1ff, SHU_CONF3_ZQCSCNT); //Every refresh number to issue ZQCS commands, only for DDR3/LPDDR2/LPDDR3/LPDDR4
+ //vIO32WriteFldAlign_All(DRAMC_REG_SHU3_CONF3, 0x1ff, SHU_CONF3_ZQCSCNT); //Every refresh number to issue ZQCS commands, only for DDR3/LPDDR2/LPDDR3/LPDDR4
+ vIO32WriteFldAlign_All(DRAMC_REG_DRAMCTRL, 0, DRAMCTRL_ZQCALL); // HW send ZQ command for both rank, disable it due to some dram only have 1 ZQ pin for two rank.
+
+ //Dual channel ZQCS interlace, 0: disable, 1: enable
+ if(p->support_channel_num==CHANNEL_SINGLE)
+ {
+ //single channel, ZQCSDUAL=0, ZQCSMASK=0
+ vIO32WriteFldMulti(DRAMC_REG_ZQCS, P_Fld(0, ZQCS_ZQCSDUAL)| P_Fld(0x0, ZQCS_ZQCSMASK));
+ }
+ else if(p->support_channel_num==CHANNEL_DUAL)
+ {
+ // HW ZQ command is channel interleaving since 2 channel share the same ZQ pin.
+ #ifdef ZQCS_ENABLE_LP4
+ // dual channel, ZQCSDUAL =1, and CHA ZQCSMASK=0, CHB ZQCSMASK=1
+ vIO32WriteFldMulti_All(DRAMC_REG_ZQCS, P_Fld(1, ZQCS_ZQCSDUAL) | \
+ P_Fld(0, ZQCS_ZQCSMASK_OPT) | \
+ P_Fld(0, ZQCS_ZQMASK_CGAR) | \
+ P_Fld(0, ZQCS_ZQCS_MASK_SEL_CGAR));
+
+ // DRAMC CHA(CHN0):ZQCSMASK=1, DRAMC CHB(CHN1):ZQCSMASK=0.
+ // ZQCSMASK setting: (Ch A, Ch B) = (1,0) or (0,1)
+ // if CHA.ZQCSMASK=1, and then set CHA.ZQCALDISB=1 first, else set CHB.ZQCALDISB=1 first
+ vIO32WriteFldAlign(DRAMC_REG_ZQCS + (CHANNEL_A<< POS_BANK_NUM), 1, ZQCS_ZQCSMASK);
+ vIO32WriteFldAlign(DRAMC_REG_ZQCS + SHIFT_TO_CHB_ADDR, 0, ZQCS_ZQCSMASK);
+
+ // DRAMC CHA(CHN0):ZQCS_ZQCS_MASK_SEL=0, DRAMC CHB(CHN1):ZQCS_ZQCS_MASK_SEL=0.
+ vIO32WriteFldAlign_All(DRAMC_REG_ZQCS, 0, ZQCS_ZQCS_MASK_SEL);
+ #endif
+ }
+
+ // Disable LP3 HW ZQ
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), 0, SPCMDCTRL_ZQCSDISB); //LP3 ZQCSDISB=0
+ // Disable LP4 HW ZQ
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), 0, SPCMDCTRL_ZQCALDISB); //LP4 ZQCALDISB=0
+ // ---- End of ZQ CS init -----
+
+ #if ENABLE_TX_TRACKING
+ vIO32WriteFldAlign_All(DRAMC_REG_DQSOSCR, p->dram_cbt_mode[RANK_0],DQSOSCR_RK0_BYTE_MODE);
+ vIO32WriteFldAlign_All(DRAMC_REG_DQSOSCR, p->dram_cbt_mode[RANK_1],DQSOSCR_RK1_BYTE_MODE);
+ #endif
+ //Disable write-DBI of DRAMC (Avoids pre-defined data pattern being modified)
+ DramcWriteDBIOnOff(p, DBI_OFF);
+ //Disable read-DBI of DRAMC (Avoids pre-defined data pattern being modified)
+ DramcReadDBIOnOff(p, DBI_OFF);
+ //disable MR4 read, REFRDIS=1
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), 1, SPCMDCTRL_REFRDIS);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 0x1, DQSOSCR_DQSOSCRDIS); //MR18, MR19 Disable
+ for(shu_index = DRAM_DFS_SHUFFLE_1; shu_index < DRAM_DFS_SHUFFLE_MAX; shu_index++)
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV) + SHU_GRP_DRAMC_OFFSET*shu_index, 0x1, SHU_SCINTV_DQSOSCENDIS);
+ //vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV), 0x1, SHU_SCINTV_DQSOSCENDIS);
+ //vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_SHU2_SCINTV), 0x1, SHU2_SCINTV_DQSOSCENDIS);
+ //vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_SHU3_SCINTV), 0x1, SHU3_SCINTV_DQSOSCENDIS);
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DRAMC_REG_DUMMY_RD), P_Fld(0x0, DUMMY_RD_DUMMY_RD_EN)
+ | P_Fld(0x0, DUMMY_RD_SREF_DMYRD_EN)
+ | P_Fld(0x0, DUMMY_RD_DQSG_DMYRD_EN)
+ | P_Fld(0x0, DUMMY_RD_DMY_RD_DBG));
+
+ // Disable HW gating tracking first, 0x1c0[31], need to disable both UI and PI tracking or the gating delay reg won't be valid.
+ DramcHWGatingOnOff(p, 0);
+
+ // Disable gating debug
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_STBCAL2), 0, STBCAL2_STB_GERRSTOP);
+
+ for(u1RankIdx=RANK_0; u1RankIdx<RANK_MAX; u1RankIdx++)
+ {
+ vSetRank(p, u1RankIdx);
+
+ // Disable RX delay tracking
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2), 0x0, R0_B0_RXDVS2_R_RK0_RX_DLY_RIS_TRACK_GATE_ENA_B0);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2), 0x0, R0_B1_RXDVS2_R_RK0_RX_DLY_RIS_TRACK_GATE_ENA_B1);
+
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2), 0x0, R0_B0_RXDVS2_R_RK0_RX_DLY_FAL_TRACK_GATE_ENA_B0);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2), 0x0, R0_B1_RXDVS2_R_RK0_RX_DLY_FAL_TRACK_GATE_ENA_B1);
+
+ //RX delay mux, delay vlaue from reg.
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2), 0x0, R0_B0_RXDVS2_R_RK0_DVS_MODE_B0);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2), 0x0, R0_B1_RXDVS2_R_RK0_DVS_MODE_B1);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_CA_RXDVS2), 0x0, R0_CA_RXDVS2_R_RK0_DVS_MODE_CA);
+ }
+ vSetRank(p, u1RankIdxBak);
+
+ // ARPI_DQ SW mode mux, TX DQ use 1: PHY Reg 0: DRAMC Reg
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 1, MISC_CTRL1_R_DMARPIDQ_SW);
+
+ // Set to all-bank refresh
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0), 0, REFCTRL0_PBREFEN);
+
+ // set MRSRK to 0, MPCRKEN always set 1 (Derping)
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_MRS), 0, MRS_MRSRK);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_MPC_OPTION), 1, MPC_OPTION_MPCRKEN);
+
+ //RG mode
+ vIO32WriteFldAlign_All(DDRPHY_B0_DQ6, 0x1, B0_DQ6_RG_RX_ARDQ_BIAS_PS_B0);
+ vIO32WriteFldAlign_All(DDRPHY_B1_DQ6, 0x1, B1_DQ6_RG_RX_ARDQ_BIAS_PS_B1);
+ vIO32WriteFldAlign_All(DDRPHY_CA_CMD6, 0x1, CA_CMD6_RG_RX_ARCMD_BIAS_PS);
+
+#if ENABLE_RX_TRACKING_LP4
+ if(u1IsLP4Family(p->dram_type))
+ {
+ DramcRxInputDelayTrackingInit_byFreq(p);
+ }
+#endif
+
+#ifdef LOOPBACK_TEST
+#ifdef LPBK_INTERNAL_EN
+ DramcLoopbackTest_settings(p, 0); //0: internal loopback test 1: external loopback test
+#else
+ DramcLoopbackTest_settings(p, 1); //0: internal loopback test 1: external loopback test
+#endif
+#endif
+
+#if EMI_LPBK_DRAM_USED==0
+ DramcLoopbackTest_settings(p, 0);
+#endif
+
+#if ENABLE_TMRRI_NEW_MODE
+ SetCKE2RankIndependent(p);
+#endif
+
+#ifdef DUMMY_READ_FOR_TRACKING
+ if (u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldAlign_All(DRAMC_REG_DUMMY_RD, 1, DUMMY_RD_DMY_RD_RX_TRACK);
+ }
+#endif
+
+ vIO32WriteFldAlign_All(DRAMC_REG_DRSCTRL, 1, DRSCTRL_DRSDIS);
+
+#ifdef IMPEDANCE_TRACKING_ENABLE
+ if(u1IsLP4Family(p->dram_type))
+ {
+ // set correct setting to control IMPCAL HW Tracking in shuffle RG
+ // if p->freq >= 1333, enable IMP HW tracking(SHU1_DRVING1_DIS_IMPCAL_HW=0), else SHU1_DRVING1_DIS_IMPCAL_HW = 1
+ U8 u1DisImpHw;
+
+ u1DisImpHw = (p->frequency >= 1200)?0:1;
+ vIO32WriteFldAlign_All(DRAMC_REG_SHU1_DRVING1, u1DisImpHw, SHU1_DRVING1_DIS_IMPCAL_HW);
+ }
+ else
+ {
+ vIO32WriteFldAlign_All(DRAMC_REG_SHU1_DRVING1, 1, SHU1_DRVING1_DIS_IMPCAL_HW);
+ }
+#else
+ vIO32WriteFldAlign_All(DRAMC_REG_SHU1_DRVING1, 1, SHU1_DRVING1_DIS_IMPCAL_HW);
+ vIO32WriteFldAlign_All(DRAMC_REG_SHU1_DRVING1, 1, SHU1_DRVING1_DIS_IMP_ODTN_TRACK);
+#endif
+}
+
+
+//Reset PHY to prevent glitch when change DQS gating delay or RX DQS input delay
+// [Lynx] Everest : cannot reset single channel. All DramC and All Phy have to reset together.
+void DramPhyReset(DRAMC_CTX_T *p)
+{
+ // Everest change reset order : reset DQS before DQ, move PHY reset to final.
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DDRCONF0), 1, DDRCONF0_RDATRST);// read data counter reset
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 1, MISC_CTRL1_R_DMPHYRST);
+
+ //RG_ARCMD_RESETB & RG_ARDQ_RESETB_B0/1 only reset once at init, Justin Chan.
+ ///TODO: need to confirm RG_ARCMD_RESETB & RG_ARDQ_RESETB_B0/1 is reset at mem.c
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ9), P_Fld(0, B0_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B0) |P_Fld(0, B0_DQ9_RG_RX_ARDQ_STBEN_RESETB_B0));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ9), P_Fld(0, B1_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B1) |P_Fld(0, B1_DQ9_RG_RX_ARDQ_STBEN_RESETB_B1));
+ #ifdef LOOPBACK_TEST
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_CA_CMD10), P_Fld(0, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB) | P_Fld(0, CA_CMD10_RG_RX_ARCMD_STBEN_RESETB));
+ #endif
+
+#if EMI_LPBK_USE_LP3_PINMUX
+vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD10), P_Fld(0, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB) | P_Fld(0, CA_CMD10_RG_RX_ARCMD_STBEN_RESETB));
+vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD10), P_Fld(0, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB) | P_Fld(0, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB));
+#endif
+ mcDELAY_US(1);//delay 10ns
+ #ifdef LOOPBACK_TEST
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_CA_CMD10), P_Fld(1, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB) | P_Fld(1, CA_CMD10_RG_RX_ARCMD_STBEN_RESETB));
+ #endif
+
+#if EMI_LPBK_USE_LP3_PINMUX
+vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD10), P_Fld(1, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB) | P_Fld(1, CA_CMD10_RG_RX_ARCMD_STBEN_RESETB));
+vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD10), P_Fld(1, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB) | P_Fld(1, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB));
+#endif
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ9), P_Fld(1, B1_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B1) | P_Fld(1, B1_DQ9_RG_RX_ARDQ_STBEN_RESETB_B1));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ9), P_Fld(1, B0_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B0) |P_Fld(1, B0_DQ9_RG_RX_ARDQ_STBEN_RESETB_B0));
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 0, MISC_CTRL1_R_DMPHYRST);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DDRCONF0), 0, DDRCONF0_RDATRST);// read data counter reset
+ }
+#if ENABLE_LP3_SW
+ else //LPDDR3
+ {
+ // Everest change : must reset all dramC and PHY together.
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DDRCONF0), 1, DDRCONF0_RDATRST);// read data counter reset
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 1, MISC_CTRL1_R_DMPHYRST);
+
+ //RG_ARCMD_RESETB & RG_ARDQ_RESETB_B0/1 only reset once at init, Justin Chan.
+ ///TODO: need to confirm RG_ARCMD_RESETB & RG_ARDQ_RESETB_B0/1 is reset at mem.c
+ //only in LP3 due to DQ pinmux to CA
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD10), P_Fld(0, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB) |P_Fld(0, CA_CMD10_RG_RX_ARCMD_STBEN_RESETB));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ9), P_Fld(0, B0_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B0) |P_Fld(0, B0_DQ9_RG_RX_ARDQ_STBEN_RESETB_B0));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ9), P_Fld(0, B1_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B1) |P_Fld(0, B1_DQ9_RG_RX_ARDQ_STBEN_RESETB_B1));
+ mcDELAY_US(1);//delay 10ns
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ9), P_Fld(1, B1_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B1) |P_Fld(1, B1_DQ9_RG_RX_ARDQ_STBEN_RESETB_B1));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ9), P_Fld(1, B0_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B0) |P_Fld(1, B0_DQ9_RG_RX_ARDQ_STBEN_RESETB_B0));
+ //only in LP3 due to DQ pinmux to CA
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD10), P_Fld(1, CA_CMD10_RG_RX_ARCLK_STBEN_RESETB) | P_Fld(1, CA_CMD10_RG_RX_ARCMD_STBEN_RESETB));
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 0, MISC_CTRL1_R_DMPHYRST);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DDRCONF0), 0, DDRCONF0_RDATRST);// read data counter reset
+ }
+#endif
+
+}
+
+
+void DramEyeStbenReset(DRAMC_CTX_T *p)
+{
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_GDDR3CTL1), 1, GDDR3CTL1_RDATRST);// read data counter reset
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 0, B0_DQ5_RG_RX_ARDQ_EYE_STBEN_RESETB_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 0, B1_DQ5_RG_RX_ARDQ_EYE_STBEN_RESETB_B1);
+
+ mcDELAY_US(1);//delay 10ns
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_EYE_STBEN_RESETB_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_EYE_STBEN_RESETB_B1);
+ }
+#if ENABLE_LP3_SW
+ else //LPDDR3
+ {
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 0, B0_DQ5_RG_RX_ARDQ_EYE_STBEN_RESETB_B0);
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 0, B1_DQ5_RG_RX_ARDQ_EYE_STBEN_RESETB_B1);
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 0, CA_CMD5_RG_RX_ARCMD_EYE_STBEN_RESETB); //only in LP3 due to DQ pinmux to CA
+
+ mcDELAY_US(1);//delay 10ns
+
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_EYE_STBEN_RESETB_B0);
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_EYE_STBEN_RESETB_B1);
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 1, CA_CMD5_RG_RX_ARCMD_EYE_STBEN_RESETB);//only in LP3 due to DQ pinmux to CA
+ }
+#endif
+}
+
+#if 0
+DRAM_STATUS_T DramcRankSwap(DRAMC_CTX_T *p, U8 u1Rank)
+{
+ U8 u1Multi;
+
+#if 0
+ if (p->support_rank_num > 1)
+ u1Multi = 1;
+ else
+ u1Multi = 0;
+#else
+ //RANK_DUAL or RANK_SINGLE, all set RKMODE to 1
+ u1Multi = 1;
+#endif
+
+ mcSHOW_DBG_MSG(("[RankSwap] Rank num %d, (Multi %d), Rank %d\n", p->support_rank_num, u1Multi, u1Rank));
+ //mcFPRINTF((fp_A60501, "[DramcRankSwap] Rank number %d, (u1Multi %d), Rank %d\n", p->support_rank_num, u1Multi, u1Rank));
+
+ //Set to non-zero for multi-rank
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), u1Multi, RKCFG_RKMODE);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), u1Rank, RKCFG_RKSWAP);
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), u1Rank, RKCFG_TXRANK); //use other rank's setting //TXRANK should be set before TXRANKFIX
+
+ if (u1Rank == 0)
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANKFIX);
+ }
+ else
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 1, RKCFG_TXRANKFIX);
+ }
+
+ return DRAM_OK;
+}
+#endif
+
+DRAM_STATUS_T DramcStartDQSOSC(DRAMC_CTX_T *p)
+{
+ U32 u4Response;
+ U32 u4TimeCnt;
+
+ u4TimeCnt = TIME_OUT_CNT;
+ mcSHOW_DBG_MSG(("[DQSOSC]\n"));
+
+ //R_DMDQSOSCENEN, 0x1E4[10]=1 for DQSOSC Start
+ //Wait dqsoscen_response=1 (dramc_conf_nao, 0x3b8[29])
+ //R_DMDQSOSCENEN, 0x1E4[10]=0
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_DQSOSCENEN);
+ do
+ {
+ u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_DQSOSCEN_RESPONSE);
+ u4TimeCnt --;
+ mcDELAY_US(1);
+ }while((u4Response==0) &&(u4TimeCnt>0));
+
+ if(u4TimeCnt==0)//time out
+ {
+ mcSHOW_DBG_MSG(("Start fail (time out)\n"));
+ //mcFPRINTF((fp_A60501, "[DramcStartDQSOSC] Start fail (time out)\n"));
+ return DRAM_FAIL;
+ }
+ else
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_DQSOSCENEN);
+ }
+
+ return DRAM_OK;
+}
+
+
+DRAM_STATUS_T DramcDQSOSCAuto(DRAMC_CTX_T *p)
+{
+ U8 u1MR23 = gu1MR23[p->channel][p->rank], shu_index;
+ U16 u2MR18, u2MR19;
+ U16 u2DQSCnt;
+ U16 u2DQSOsc[2];
+ U32 u4RegBak[3];
+
+#if MRW_CHECK_ONLY
+ mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
+#endif
+
+ u4RegBak[0] = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_MRS));
+ u4RegBak[1] = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL));
+ u4RegBak[2] = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL));
+
+ //!!R_DMMRSRK(R_DMMPCRKEN=1) specify rank0 or rank1
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_DQSOSC2RK);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRS), u1GetRank(p), MRS_MRSRK);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MPC_OPTION), 1, MPC_OPTION_MPCRKEN);
+
+ //LPDDR4-3200, PI resolution = tCK/64 =9.76ps
+ //Only if MR23>=16, then error < PI resolution.
+ //Set MR23 == 0x3f, stop after 63*16 clock
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRS), u1GetRank(p), MRS_MRSRK);
+ DramcModeRegWrite(p, 23, u1MR23);
+
+ //SW mode
+ for(shu_index = DRAM_DFS_SHUFFLE_1; shu_index < DRAM_DFS_SHUFFLE_MAX; shu_index++)
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV) + SHU_GRP_DRAMC_OFFSET*shu_index, 1, SHU_SCINTV_DQSOSCENDIS);
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV), 1, SHU_SCINTV_DQSOSCENDIS);
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU2_SCINTV), 1, SHU2_SCINTV_DQSOSCENDIS);
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU3_SCINTV), 1, SHU3_SCINTV_DQSOSCENDIS);
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 1, DRAMC_PD_CTRL_MIOCKCTRLOFF); //MIOCKCTRLOFF=1
+
+ CKEFixOnOff(p, p->rank, CKE_FIXON, CKE_WRITE_TO_ONE_CHANNEL);
+
+ DramcStartDQSOSC(p);
+ mcDELAY_US(1);
+#if ENABLE_TMRRI_NEW_MODE
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRS), u1GetRank(p), MRS_MRSRK);
+#else
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRS), u1GetRank(p), MRS_MRRRK);
+#endif
+ DramcModeRegRead(p, 18, &u2MR18);
+ DramcModeRegRead(p, 19, &u2MR19);
+
+
+#if (SW_CHANGE_FOR_SIMULATION==0)
+ //B0
+ u2DQSCnt = (u2MR18 & 0x00FF) | ((u2MR19 & 0x00FF) <<8);
+ if(u2DQSCnt !=0)
+ u2DQSOsc[0] = u1MR23*16*1000000/(2 * u2DQSCnt * p->frequency); //tDQSOSC = 16*MR23*tCK/2*count
+ else
+ u2DQSOsc[0] = 0;
+
+ //B1
+ u2DQSCnt = (u2MR18 >> 8) | ((u2MR19 & 0xFF00));
+ if(u2DQSCnt !=0)
+ u2DQSOsc[1] = u1MR23*16*1000000/(2 * u2DQSCnt * p->frequency); //tDQSOSC = 16*MR23*tCK/2*count
+ else
+ u2DQSOsc[1] = 0;
+ mcSHOW_DBG_MSG(("[DQSOSCAuto] RK%d, (LSB)MR18= 0x%x, (MSB)MR19= 0x%x, tDQSOscB0 = %d ps tDQSOscB1 = %d ps\n", u1GetRank(p), u2MR18, u2MR19, u2DQSOsc[0], u2DQSOsc[1]));
+#endif
+
+ gu2MR18[p->channel][p->rank] = u2MR18;
+ gu2MR19[p->channel][p->rank] = u2MR19;
+ gu2DQSOSC[p->channel][p->rank] = u2DQSOsc[0];
+
+ if(u2DQSOsc[1]!=0 && u2DQSOsc[1]<u2DQSOsc[0])
+ gu2DQSOSC[p->channel][p->rank] = u2DQSOsc[1];
+
+ vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_MRS), u4RegBak[0]);
+ vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), u4RegBak[1]);
+ vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL), u4RegBak[2]);
+
+ /* Starting from Vinson, MR23 should be 0x3F for all case ("HW tracking modify" DVT)
+ * -> Value is already set in during gu1MR23 array init
+ * The below code snippet is used for KIBO/Alaska/Whitney E2 projects
+ * (Adjusts MR23 according to freq, since back then _INC _DEC bit's weren't sufficient)
+ */
+#if 0
+ if(gu1MR23Done==FALSE)
+ {
+ DRAM_CHANNEL_T chIdx = CHANNEL_A;
+ DRAM_RANK_T rankIdx = RANK_0;
+ if(gu2DQSOSC[p->channel][p->rank]>500)
+ {
+ u1MR23 = 0x30;
+ }
+ else if(gu2DQSOSC[p->channel][p->rank]>350)
+ {
+ u1MR23 = 0x20;
+ }
+ else
+ {
+ u1MR23 = 0x10;
+ }
+ for(chIdx=CHANNEL_A; chIdx<p->support_channel_num; chIdx++)
+ {
+ for(rankIdx=RANK_0; rankIdx<RANK_MAX; rankIdx++)
+ {
+ gu1MR23[chIdx][rankIdx] = u1MR23;
+ }
+ }
+ mcSHOW_DBG_MSG(("Update MR23=%d\n", u1MR23));
+ gu1MR23Done = TRUE;
+ }
+#endif
+
+ return DRAM_OK;
+}
+
+#if 1
+/* Using gu2DQSOSC results calculated from DramcDQSOSCAuto
+ * -> calculate DQSOSCTHRD_INC, DQSOSCTHRD_DEC
+ * _INC, _DEC formulas are extracted from "Verification plan of Vinson LPDDR4 HW TX Tracking" doc
+ */
+DRAM_STATUS_T DramcDQSOSCMR23(DRAMC_CTX_T *p)
+{
+#if (SW_CHANGE_FOR_SIMULATION==0)
+#if 1
+ /* Preloader doesn't support floating point numbers -> Manually expand/simpify _INC, _DEC formula */
+ U8 u1MR23 = gu1MR23[p->channel][p->rank];
+ U16 u2DQSOSC = gu2DQSOSC[p->channel][p->rank];
+ U32 u4tCK = 1000000 / p->frequency;
+
+ if(u2DQSOSC !=0)
+ {
+ gu2DQSOSCTHRD_INC[p->channel][p->rank] = (3 * u1MR23 * u4tCK * u4tCK) / (u2DQSOSC * u2DQSOSC * 20);
+ gu2DQSOSCTHRD_DEC[p->channel][p->rank] = (u1MR23 * u4tCK * u4tCK) / (u2DQSOSC * u2DQSOSC * 10);
+ }
+#else
+ /* Formulas implemented directly as mentioned (using floating point numbers) */
+ #define DQSOSC_ALPHA 0.2
+ /*
+ * actualAlpha, tickTime, goldenMR23 formulas are extracted from
+ * "Vinson HW TX Tracking Modify" DVT document's excel file
+ */
+ float actualAlpha = DQSOSC_ALPHA/((1600/(float)p->frequency)*(1600/(float)p->frequency)); //DDR3200's alpha = 0.2, use it as base
+ float tickTime = (1/(float)p->frequency)*1000000;
+ float goldenMR23 = (2*4/DQSOSC_ALPHA)*(((float)u2DQSOSC/tickTime)*((float)u2DQSOSC/tickTime));
+
+ /* (Floating point + 0.5) and truncated into unsigned integer -> roundup floating point number */
+ gu2DQSOSCTHRD_INC[p->channel][p->rank] = (5*1.2*((float)u4MR23/goldenMR23)+0.5);
+ gu2DQSOSCTHRD_DEC[p->channel][p->rank] = (5*0.8*((float)u4MR23/goldenMR23)+0.5);
+#endif
+ mcSHOW_DBG_MSG(("CH%d_RK%d: MR19=0x%X, MR18=0x%X, DQSOSC=%d, MR23=%u, INC=%u, DEC=%u\n", p->channel, p->rank,
+ gu2MR19[p->channel][p->rank], gu2MR18[p->channel][p->rank], gu2DQSOSC[p->channel][p->rank],
+ u1MR23, gu2DQSOSCTHRD_INC[p->channel][p->rank], gu2DQSOSCTHRD_DEC[p->channel][p->rank]));
+#endif
+ return DRAM_OK;
+}
+#else
+/* Used for previous projects (before Vinson) */
+DRAM_STATUS_T DramcDQSOSCMR23(DRAMC_CTX_T *p)
+{
+#if (SW_CHANGE_FOR_SIMULATION==0)
+ U16 u2DQSOSC = gu2DQSOSC[p->channel][p->rank];
+ U32 u4tCK = 1000000/p->frequency;
+ U32 u4RunTime = (32*4*5*(u2DQSOSC*u2DQSOSC)/(u4tCK*u4tCK))+1;
+ //U32 u4MR23 = (u4RunTime/16)+1;
+ U32 u4MR23 = gu1MR23[p->channel][p->rank];
+
+ gu2DQSOSCTHRD_INC[p->channel][p->rank] = (6*u4MR23*16)/(u4RunTime);
+ gu2DQSOSCTHRD_DEC[p->channel][p->rank] = (4*u4MR23*16)/(u4RunTime);
+ mcSHOW_DBG_MSG(("CH%d_RK%d: MR19=%X, MR18=%X, DQSOSC=%d, Runtime=%d, MR23=%d, INC=%d, DEC=%d\n",
+ p->channel, p->rank, gu2MR19[p->channel][p->rank], gu2MR18[p->channel][p->rank], gu2DQSOSC[p->channel][p->rank],
+ u4RunTime,u4MR23, gu2DQSOSCTHRD_INC[p->channel][p->rank], gu2DQSOSCTHRD_DEC[p->channel][p->rank]));
+#endif
+ return DRAM_OK;
+}
+#endif
+
+/* Sets DQSOSC_BASE for specified rank/byte */
+DRAM_STATUS_T DramcDQSOSCSetMR18MR19(DRAMC_CTX_T *p)
+{
+ U16 u2DQSOscCnt[2];
+ DramcDQSOSCAuto(p);
+
+ //B0
+ gu2DQSOscCnt[p->channel][p->rank][0] = u2DQSOscCnt[0] = (gu2MR18[p->channel][p->rank] & 0x00FF) | ((gu2MR19[p->channel][p->rank] & 0x00FF) <<8);
+ //B1
+ gu2DQSOscCnt[p->channel][p->rank][1] = u2DQSOscCnt[1] = (gu2MR18[p->channel][p->rank] >> 8) | ((gu2MR19[p->channel][p->rank] & 0xFF00));
+
+ if((p->dram_cbt_mode[p->rank]==CBT_NORMAL_MODE) && (gu2DQSOscCnt[p->channel][p->rank][1]==0))
+ {
+ gu2DQSOscCnt[p->channel][p->rank][1] = u2DQSOscCnt[1] = u2DQSOscCnt[0];
+ }
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_DQSOSC), P_Fld(u2DQSOscCnt[0], SHU1RK0_DQSOSC_DQSOSC_BASE_RK0)| P_Fld(u2DQSOscCnt[1], SHU1RK0_DQSOSC_DQSOSC_BASE_RK0_B1));
+
+ mcSHOW_DBG_MSG(("CH%d RK%d: MR19=%X, MR18=%X\n", p->channel, p->rank, gu2MR19[p->channel][p->rank], gu2MR18[p->channel][p->rank]));
+ return DRAM_OK;
+}
+
+DRAM_STATUS_T DramcDQSOSCShuSettings(DRAMC_CTX_T *p)
+{
+ U16 u2PRDCNT = 0x3FF;
+ U16 u2DQSOSCENCNT = 0x1FF;
+ U16 u2Thrd_inc, u2Thrd_dec;
+ U8 u1FILT_PITHRD = 0;
+ U8 u1W2R_SEL = 0;
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV), 0x0, SHU_SCINTV_DQS2DQ_SHU_PITHRD);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK0_DQSOSC), 0x0, RK0_DQSOSC_R_DMDQS2DQ_FILT_OPT);
+ if(p->frequency<=400)
+ {
+ u1FILT_PITHRD = 0x4;
+ u1W2R_SEL = 0x5;
+ }
+ else if(p->frequency<=600)
+ {
+ u1FILT_PITHRD = 0x6;
+ u1W2R_SEL = 0x5;
+ }
+ else if(p->frequency<=800)
+ {
+ u1FILT_PITHRD = 0x7;
+ u1W2R_SEL = 0x5;
+ }
+ else if(p->frequency<=1200)
+ {
+ u1FILT_PITHRD = 0xb;
+ u1W2R_SEL = 0x2;
+ }
+ else if(p->frequency<=1333)
+ {
+ u1FILT_PITHRD = 0xc;
+ u1W2R_SEL = 0x2;
+ }
+ else if(p->frequency<=1600)
+ {
+ u1FILT_PITHRD = 0xE;
+ u1W2R_SEL = 0x2;
+ }
+ else if(p->frequency<=1866)
+ {
+ u1FILT_PITHRD = 0x12;
+ u1W2R_SEL = 0x2;
+ }
+ else //4266
+ {
+ u1FILT_PITHRD = 0x15;
+ u1W2R_SEL = 0x2;
+ }
+
+ u2PRDCNT = (gu1MR23[p->channel][RANK_0]/4)+3;
+ if (p->support_rank_num==RANK_DUAL)
+ {
+ if(gu1MR23[p->channel][RANK_0]>gu1MR23[p->channel][RANK_1])
+ u2PRDCNT = (gu1MR23[p->channel][RANK_0]/4)+3;
+ else
+ u2PRDCNT = (gu1MR23[p->channel][RANK_1]/4)+3;
+ }
+
+ //Don't power down dram during DQS interval timer run time, (MR23[7:0] /4) + (tOSCO/MCK unit/16)
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1_DQSOSC_PRD), u2PRDCNT, SHU1_DQSOSC_PRD_DQSOSC_PRDCNT);
+
+ //set tOSCO constraint to read MR18/MR19, should be > 40ns/MCK
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_DQSOSCR), ((p->frequency-1)/100)+1, SHU_DQSOSCR_DQSOSCRCNT);//unit: MCK to meet spec. tOSCO
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV), u1FILT_PITHRD, SHU_SCINTV_DQS2DQ_FILT_PITHRD);
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU1_WODT), P_Fld(u1W2R_SEL, SHU1_WODT_TXUPD_W2R_SEL) | P_Fld(0x0, SHU1_WODT_TXUPD_SEL));
+
+ /* Starting from Vinson, DQSOSCTHRD_INC & _DEC is split into RK0 and RK1 */
+ //Rank 0
+ u2Thrd_inc = gu2DQSOSCTHRD_INC[p->channel][RANK_0];
+ u2Thrd_dec = gu2DQSOSCTHRD_DEC[p->channel][RANK_0];
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_DQSOSCTHRD), u2Thrd_inc, SHU_DQSOSCTHRD_DQSOSCTHRD_INC_RK0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_DQSOSCTHRD), u2Thrd_dec, SHU_DQSOSCTHRD_DQSOSCTHRD_DEC_RK0);
+
+ //Rank 1
+ u2Thrd_inc = gu2DQSOSCTHRD_INC[p->channel][RANK_1];
+ u2Thrd_dec = gu2DQSOSCTHRD_DEC[p->channel][RANK_1];
+ /* DQSOSCTHRD_INC_RK1 is split into 2 register fields (starting from Vinson) */
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_DQSOSCTHRD), (u2Thrd_inc & 0x0FF), SHU_DQSOSCTHRD_DQSOSCTHRD_INC_RK1_7TO0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1_DQSOSC_PRD), ((u2Thrd_inc & 0xF00) >> 8), SHU1_DQSOSC_PRD_DQSOSCTHRD_INC_RK1_11TO8);
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1_DQSOSC_PRD), u2Thrd_dec, SHU1_DQSOSC_PRD_DQSOSCTHRD_DEC_RK1);
+
+ //set interval to do MPC(start DQSOSC) command, and dramc send DQSOSC start to rank0/1/2 at the same time
+ //TX tracking period unit: 3.9us
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_DQSOSCR2), u2DQSOSCENCNT, SHU_DQSOSCR2_DQSOSCENCNT);
+
+ return DRAM_OK;
+}
+
+void DramcHwDQSOSCSetFreqRatio(DRAMC_CTX_T *p)
+{
+#if 0
+ //for SHUFFLE_1
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_RK2_DQSOSC), P_Fld((U16)(gFreqTbl[1].frequency*8/gFreqTbl[0].frequency), RK2_DQSOSC_FREQ_RATIO_TX_0)
+ | P_Fld((U16)(gFreqTbl[2].frequency*8/gFreqTbl[0].frequency), RK2_DQSOSC_FREQ_RATIO_TX_1));
+ //for SHUFFLE_2
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_RK2_DQSOSC), P_Fld((U16)(gFreqTbl[0].frequency*8/gFreqTbl[1].frequency), RK2_DQSOSC_FREQ_RATIO_TX_3)
+ | P_Fld((U16)(gFreqTbl[2].frequency*8/gFreqTbl[1].frequency), RK2_DQSOSC_FREQ_RATIO_TX_4));
+ //for SHUFFLE_3
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_RK2_DUMMY_RD_BK), P_Fld((U16)(gFreqTbl[0].frequency*8/gFreqTbl[2].frequency), RK2_DUMMY_RD_BK_FREQ_RATIO_TX_6)
+ | P_Fld((U16)(gFreqTbl[1].frequency*8/gFreqTbl[2].frequency), RK2_DUMMY_RD_BK_FREQ_RATIO_TX_7));
+
+ //for SHUFFLE_4
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_PRE_TDQSCK1), P_Fld(1, PRE_TDQSCK1_SHU_PRELOAD_TX_HW)
+ | P_Fld(0, PRE_TDQSCK1_SHU_PRELOAD_TX_START)
+ | P_Fld(0, PRE_TDQSCK1_SW_UP_TX_NOW_CASE));
+
+#endif
+ mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_0=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DQSOSC), RK2_DQSOSC_FREQ_RATIO_TX_0)));
+ mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_1=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DQSOSC), RK2_DQSOSC_FREQ_RATIO_TX_1)));
+ mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_2=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DQSOSC), RK2_DQSOSC_FREQ_RATIO_TX_2)));
+ mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_3=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DQSOSC), RK2_DQSOSC_FREQ_RATIO_TX_3)));
+ mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_4=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DQSOSC), RK2_DQSOSC_FREQ_RATIO_TX_4)));
+ mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_5=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DQSOSC), RK2_DQSOSC_FREQ_RATIO_TX_5)));
+ mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_6=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DUMMY_RD_BK), RK2_DUMMY_RD_BK_FREQ_RATIO_TX_6)));
+ mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_7=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DUMMY_RD_BK), RK2_DUMMY_RD_BK_FREQ_RATIO_TX_7)));
+ mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_8=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DUMMY_RD_BK), RK2_DUMMY_RD_BK_FREQ_RATIO_TX_8)));
+ mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_9=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK2_DQSOSC), RK2_DQSOSC_FREQ_RATIO_TX_0)));
+ mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_9=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PRE_TDQSCK1), PRE_TDQSCK1_FREQ_RATIO_TX_9)));
+ mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_10=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PRE_TDQSCK1), PRE_TDQSCK1_FREQ_RATIO_TX_10)));
+ mcSHOW_DBG_MSG3(("TX_FREQ_RATIO_11=%d\n", u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PRE_TDQSCK1), PRE_TDQSCK1_FREQ_RATIO_TX_11)));
+}
+
+void DramcHwDQSOSC(DRAMC_CTX_T *p)
+{
+ U8 shu_index;
+ DRAM_RANK_T rank_bak = u1GetRank(p);
+ DRAM_CHANNEL_T ch_bak = p->channel;
+
+ DramcHwDQSOSCSetFreqRatio(p);
+
+ //DQSOSC MPC command violation
+#if ENABLE_TMRRI_NEW_MODE
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MPC_OPTION), 1, MPC_OPTION_MPC_BLOCKALE_OPT);
+#else
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MPC_OPTION), 0, MPC_OPTION_MPC_BLOCKALE_OPT);
+#endif
+
+ //DQS2DQ UI/PI setting controlled by HW
+ #if ENABLE_SW_TX_TRACKING
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 1, MISC_CTRL1_R_DMARPIDQ_SW);
+ #else
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 0, MISC_CTRL1_R_DMARPIDQ_SW);
+ #endif
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 1, DQSOSCR_ARUIDQ_SW);
+
+ //Set dqsosc oscillator run time by MRW
+ //write RK0 MR23
+ #if 0
+ U8 u1MR23 = 0x3F;
+ vSetRank(p, RANK_0);
+ vSetPHY2ChannelMapping(p, CHANNEL_A);
+ DramcModeRegWrite(p, 23, u1MR23);
+ vSetPHY2ChannelMapping(p, CHANNEL_B);
+ DramcModeRegWrite(p, 23, u1MR23);
+ //write RK1 MR23
+ vSetRank(p, RANK_1);
+ vSetPHY2ChannelMapping(p, CHANNEL_A);
+ DramcModeRegWrite(p, 23, u1MR23);
+ vSetPHY2ChannelMapping(p, CHANNEL_B);
+ DramcModeRegWrite(p, 23, u1MR23);
+ #endif
+
+ //Enable HW read MR18/MR19 for each rank
+ #if ENABLE_SW_TX_TRACKING
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 1, DQSOSCR_DQSOSCRDIS);
+ #else
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 0, DQSOSCR_DQSOSCRDIS);
+ #endif
+
+ vSetRank(p, RANK_0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK0_DQSOSC), 1, RK0_DQSOSC_DQSOSCR_RK0EN);
+ if (p->support_rank_num == RANK_DUAL)
+ {
+ vSetRank(p, RANK_1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RK1_DQSOSC), 1, RK1_DQSOSC_DQSOSCR_RK1EN);
+ }
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRSCTRL), 1, DRSCTRL_DRSCLR_RK0_EN); //Set as 1 to fix issue of single rank, dual rank can also be enable
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 1, DQSOSCR_DQSOSC_CALEN);
+
+ //enable DQSOSC HW mode
+ #if ENABLE_SW_TX_TRACKING
+ for(shu_index = DRAM_DFS_SHUFFLE_1; shu_index < DRAM_DFS_SHUFFLE_MAX; shu_index++)
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV) + SHU_GRP_DRAMC_OFFSET*shu_index, 1, SHU_SCINTV_DQSOSCENDIS);
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV), 1, SHU_SCINTV_DQSOSCENDIS);
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU2_SCINTV), 1, SHU2_SCINTV_DQSOSCENDIS);
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU3_SCINTV), 1, SHU3_SCINTV_DQSOSCENDIS);
+ #else
+ for(shu_index = DRAM_DFS_SHUFFLE_1; shu_index < DRAM_DFS_SHUFFLE_MAX; shu_index++)
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV) + SHU_GRP_DRAMC_OFFSET*shu_index, 0, SHU_SCINTV_DQSOSCENDIS);
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV), 0, SHU_SCINTV_DQSOSCENDIS);
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU2_SCINTV), 0, SHU2_SCINTV_DQSOSCENDIS);
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU3_SCINTV), 0, SHU3_SCINTV_DQSOSCENDIS);
+ #endif
+
+ vSetRank(p, rank_bak);
+ vSetPHY2ChannelMapping(p, ch_bak);
+}
+
+#if ENABLE_SW_TX_TRACKING & __ETT__
+void DramcSWTxTracking(DRAMC_CTX_T *p)
+{
+ U8 u1MR4OnOff = 1;
+ U8 rankIdx = RANK_0;
+ U8 u1ShuLevel = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHUSTATUS), SHUSTATUS_SHUFFLE_LEVEL);
+ U16 u2DramcOffset = SHU_GRP_DRAMC_OFFSET * u1ShuLevel;
+ U16 u2MR1819_Base[CHANNEL_NUM][RANK_MAX][2];
+ U16 u2MR1819_Runtime[CHANNEL_NUM][RANK_MAX][2];
+ U16 u2DQSOSC_INC[RANK_MAX] = {6}, u2DQSOSC_DEC[RANK_MAX] = {4};
+ U8 u1AdjPI[RANK_MAX][2];
+ U8 u1OriginalPI_DQ[DRAM_DFS_SHUFFLE_MAX][RANK_MAX][2];
+ U8 u1UpdatedPI_DQ[DRAM_DFS_SHUFFLE_MAX][RANK_MAX][2];
+ U8 u1OriginalPI_DQM[DRAM_DFS_SHUFFLE_MAX][RANK_MAX][2];
+ U8 u1UpdatedPI_DQM[DRAM_DFS_SHUFFLE_MAX][RANK_MAX][2];
+ U8 u1FreqRatioTX[DRAM_DFS_SHUFFLE_MAX];
+ U8 shuIdx=0;
+
+ for(shuIdx=0; shuIdx<DRAM_DFS_SHUFFLE_MAX; shuIdx++)
+ {
+ u1FreqRatioTX[shuIdx] = (gFreqTbl[shuIdx].frequency*8/gFreqTbl[u1ShuLevel].frequency);
+ mcSHOW_DBG_MSG(("[SWTxTracking] ShuLevel=%d, Ratio[%d]=%d", u1ShuLevel, shuIdx, u1FreqRatioTX[shuIdx]));
+ }
+
+ vSetRank(p, RANK_0);
+
+ /* Starting from Vinson, DQSOSCTHRD_INC & _DEC is split into RK0 and RK1 */
+ //Rank 0
+ u2DQSOSC_INC[RANK_0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_DQSOSCTHRD) + u2DramcOffset, SHU_DQSOSCTHRD_DQSOSCTHRD_INC_RK0);
+ u2DQSOSC_DEC[RANK_0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_DQSOSCTHRD) + u2DramcOffset, SHU_DQSOSCTHRD_DQSOSCTHRD_DEC_RK0);
+
+
+ /* DQSOSCTHRD_INC_RK1 is split into 2 register fields (starting from Vinson) */
+ //Rank 1
+ u2DQSOSC_INC[RANK_1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1_DQSOSC_PRD) + u2DramcOffset, SHU1_DQSOSC_PRD_DQSOSCTHRD_INC_RK1_11TO8);
+ u2DQSOSC_INC[RANK_1] = u2DQSOSC_INC[RANK_1] << 8; /* Shift [3:0] to correct position [11:8] */
+ u2DQSOSC_INC[RANK_1] = u2DQSOSC_INC[RANK_1] | u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_DQSOSCTHRD) + u2DramcOffset, SHU_DQSOSCTHRD_DQSOSCTHRD_INC_RK1_7TO0);
+
+ u2DQSOSC_DEC[RANK_1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1_DQSOSC_PRD) + u2DramcOffset, SHU1_DQSOSC_PRD_DQSOSCTHRD_DEC_RK1);
+
+ for(shuIdx=0; shuIdx<DRAM_DFS_SHUFFLE_MAX; shuIdx++)
+ {
+ u1OriginalPI_DQ[shuIdx][RANK_0][0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_PI)+(SHU_GRP_DRAMC_OFFSET * shuIdx), SHU1RK0_PI_RK0_ARPI_DQ_B0);
+ u1OriginalPI_DQ[shuIdx][RANK_0][1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_PI)+(SHU_GRP_DRAMC_OFFSET * shuIdx), SHU1RK0_PI_RK0_ARPI_DQ_B1);
+ u1OriginalPI_DQ[shuIdx][RANK_1][0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK1_PI)+(SHU_GRP_DRAMC_OFFSET * shuIdx), SHU1RK1_PI_RK1_ARPI_DQ_B0);
+ u1OriginalPI_DQ[shuIdx][RANK_1][1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK1_PI)+(SHU_GRP_DRAMC_OFFSET * shuIdx), SHU1RK1_PI_RK1_ARPI_DQ_B1);
+
+ u1OriginalPI_DQM[shuIdx][RANK_0][0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_PI)+(SHU_GRP_DRAMC_OFFSET * shuIdx), SHU1RK0_PI_RK0_ARPI_DQM_B0);
+ u1OriginalPI_DQM[shuIdx][RANK_0][1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_PI)+(SHU_GRP_DRAMC_OFFSET * shuIdx), SHU1RK0_PI_RK0_ARPI_DQM_B1);
+ u1OriginalPI_DQM[shuIdx][RANK_1][0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK1_PI)+(SHU_GRP_DRAMC_OFFSET * shuIdx), SHU1RK1_PI_RK1_ARPI_DQM_B0);
+ u1OriginalPI_DQM[shuIdx][RANK_1][1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK1_PI)+(SHU_GRP_DRAMC_OFFSET * shuIdx), SHU1RK1_PI_RK1_ARPI_DQM_B1);
+ }
+
+ u2MR1819_Base[p->channel][RANK_0][0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_DQSOSC)+u2DramcOffset, SHU1RK0_DQSOSC_DQSOSC_BASE_RK0);
+ u2MR1819_Base[p->channel][RANK_0][1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_DQSOSC)+u2DramcOffset, SHU1RK0_DQSOSC_DQSOSC_BASE_RK0_B1);
+ u2MR1819_Base[p->channel][RANK_1][0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK1_DQSOSC)+u2DramcOffset, SHU1RK1_DQSOSC_DQSOSC_BASE_RK1);
+ u2MR1819_Base[p->channel][RANK_1][1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK1_DQSOSC)+u2DramcOffset, SHU1RK1_DQSOSC_DQSOSC_BASE_RK1_B1);
+
+ u1MR4OnOff = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), SPCMDCTRL_REFRDIS);
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), 1, SPCMDCTRL_REFRDIS);
+ for(rankIdx=RANK_0; rankIdx<p->support_rank_num; rankIdx++)
+ {
+ U8 byteIdx=0;
+
+ vSetRank(p, rankIdx);
+ DramcDQSOSCAuto(p);
+ u2MR1819_Runtime[p->channel][p->rank][0] = (gu2MR18[p->channel][p->rank] & 0x00FF) | ((gu2MR19[p->channel][p->rank] & 0x00FF) <<8);
+ if(p->dram_cbt_mode[p->rank]==CBT_BYTE_MODE1)
+ {
+ u2MR1819_Runtime[p->channel][p->rank][1] = (gu2MR18[p->channel][p->rank] >> 8) | ((gu2MR19[p->channel][p->rank] & 0xFF00));
+ }
+ else
+ {
+ u2MR1819_Runtime[p->channel][p->rank][1] = u2MR1819_Runtime[p->channel][p->rank][0];
+ }
+ //INC : MR1819>base. PI-
+ //DEC : MR1819<base. PI+
+ for(byteIdx=0; byteIdx<2; byteIdx++)
+ {
+ U16 deltaMR1819=0;
+
+ if(u2MR1819_Runtime[p->channel][p->rank][byteIdx] >= u2MR1819_Base[p->channel][p->rank][byteIdx])
+ {
+ deltaMR1819 = u2MR1819_Runtime[p->channel][p->rank][byteIdx] - u2MR1819_Base[p->channel][p->rank][byteIdx];
+ u1AdjPI[rankIdx][byteIdx] = deltaMR1819/u2DQSOSC_INC[rankIdx];
+ for(shuIdx=0; shuIdx<DRAM_DFS_SHUFFLE_MAX; shuIdx++)
+ {
+ u1UpdatedPI_DQ[shuIdx][rankIdx][byteIdx] = u1OriginalPI_DQ[shuIdx][rankIdx][byteIdx] - (u1AdjPI[rankIdx][byteIdx]*u1FreqRatioTX[shuIdx]/u1FreqRatioTX[u1ShuLevel]);
+ u1UpdatedPI_DQM[shuIdx][rankIdx][byteIdx] = u1OriginalPI_DQM[shuIdx][rankIdx][byteIdx] - (u1AdjPI[rankIdx][byteIdx]*u1FreqRatioTX[shuIdx]/u1FreqRatioTX[u1ShuLevel]);
+ mcSHOW_DBG_MSG(("SHU%u CH%d RK%d B%d, Base=%X Runtime=%X delta=%d INC=%d PI=0x%B Adj=%d newPI=0x%B\n", shuIdx, p->channel, u1GetRank(p), byteIdx
+ , u2MR1819_Base[p->channel][p->rank][byteIdx], u2MR1819_Runtime[p->channel][p->rank][byteIdx], deltaMR1819, u2DQSOSC_INC[rankIdx]
+ , u1OriginalPI_DQ[shuIdx][rankIdx][byteIdx], (u1AdjPI[rankIdx][byteIdx]*u1FreqRatioTX[shuIdx]/u1FreqRatioTX[u1ShuLevel]), u1UpdatedPI_DQ[shuIdx][rankIdx][byteIdx]));
+ }
+ }
+ else
+ {
+ deltaMR1819 = u2MR1819_Base[p->channel][p->rank][byteIdx] - u2MR1819_Runtime[p->channel][p->rank][byteIdx];
+ u1AdjPI[rankIdx][byteIdx] = deltaMR1819/u2DQSOSC_DEC[rankIdx];
+ for(shuIdx=0; shuIdx<DRAM_DFS_SHUFFLE_MAX; shuIdx++)
+ {
+ u1UpdatedPI_DQ[shuIdx][rankIdx][byteIdx] = u1OriginalPI_DQ[shuIdx][rankIdx][byteIdx] + (u1AdjPI[rankIdx][byteIdx]*u1FreqRatioTX[shuIdx]/u1FreqRatioTX[u1ShuLevel]);
+ u1UpdatedPI_DQM[shuIdx][rankIdx][byteIdx] = u1OriginalPI_DQM[shuIdx][rankIdx][byteIdx] + (u1AdjPI[rankIdx][byteIdx]*u1FreqRatioTX[shuIdx]/u1FreqRatioTX[u1ShuLevel]);
+ mcSHOW_DBG_MSG(("SHU%u CH%d RK%d B%d, Base=%X Runtime=%X delta=%d DEC=%d PI=0x%B Adj=%d newPI=0x%B\n", shuIdx, p->channel,u1GetRank(p), byteIdx
+ , u2MR1819_Base[p->channel][p->rank][byteIdx], u2MR1819_Runtime[p->channel][p->rank][byteIdx], deltaMR1819, u2DQSOSC_DEC[rankIdx]
+ , u1OriginalPI_DQ[shuIdx][rankIdx][byteIdx], (u1AdjPI[rankIdx][byteIdx]*u1FreqRatioTX[shuIdx]/u1FreqRatioTX[u1ShuLevel]), u1UpdatedPI_DQ[shuIdx][rankIdx][byteIdx]));
+ }
+ }
+ }
+ }
+
+ vSetRank(p, RANK_0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 1, DQSOSCR_TXUPDMODE);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 1, DQSOSCR_MANUTXUPD);
+
+ for(shuIdx=0; shuIdx<DRAM_DFS_SHUFFLE_MAX; shuIdx++)
+ {
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7)+(SHU_GRP_DDRPHY_OFFSET * shuIdx), P_Fld(u1UpdatedPI_DQ[shuIdx][RANK_0][0], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0)
+ | P_Fld(u1UpdatedPI_DQM[shuIdx][RANK_0][0], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0));
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7)+(SHU_GRP_DDRPHY_OFFSET * shuIdx), P_Fld(u1UpdatedPI_DQ[shuIdx][RANK_0][1], SHU1_R0_B1_DQ7_RK0_ARPI_DQ_B1)
+ | P_Fld(u1UpdatedPI_DQM[shuIdx][RANK_0][1], SHU1_R0_B1_DQ7_RK0_ARPI_DQM_B1));
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R1_B0_DQ7)+(SHU_GRP_DDRPHY_OFFSET * shuIdx), P_Fld(u1UpdatedPI_DQ[shuIdx][RANK_1][0], SHU1_R1_B0_DQ7_RK1_ARPI_DQ_B0)
+ | P_Fld(u1UpdatedPI_DQM[shuIdx][RANK_1][0], SHU1_R1_B0_DQ7_RK1_ARPI_DQM_B0));
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R1_B1_DQ7)+(SHU_GRP_DDRPHY_OFFSET * shuIdx), P_Fld(u1UpdatedPI_DQ[shuIdx][RANK_1][1], SHU1_R1_B1_DQ7_RK1_ARPI_DQ_B1)
+ | P_Fld(u1UpdatedPI_DQM[shuIdx][RANK_1][1], SHU1_R1_B1_DQ7_RK1_ARPI_DQM_B1));
+ }
+
+ while(u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MISC_STATUSA),MISC_STATUSA_MANUTXUPD_DONE)!=1)
+ {
+ mcDELAY_US(1);
+ }
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 0, DQSOSCR_TXUPDMODE);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 0, DQSOSCR_MANUTXUPD);
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), u1MR4OnOff, SPCMDCTRL_REFRDIS);
+}
+#endif
+
+#if ENABLE_RX_TRACKING_LP4
+void DramcRxInputDelayTrackingInit_Common(DRAMC_CTX_T *p)
+{
+ U8 ii, backup_rank;
+
+ backup_rank = u1GetRank(p);
+
+ //Enable RX_FIFO macro DIV4 clock CG
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_MISC_CG_CTRL1), 0xffffffff, MISC_CG_CTRL1_R_DVS_DIV4_CG_CTRL);
+
+ //DVS mode to RG mode
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2),0x0, R0_B0_RXDVS2_R_RK0_DVS_MODE_B0);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2),0x0, R0_B1_RXDVS2_R_RK0_DVS_MODE_B1);
+
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R1_B0_RXDVS2),0x0, R1_B0_RXDVS2_R_RK1_DVS_MODE_B0);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R1_B1_RXDVS2),0x0, R1_B1_RXDVS2_R_RK1_DVS_MODE_B1);
+
+ //Tracking lead/lag counter >> Rx DLY adjustment fixed to 1
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B0_RXDVS0),0x0, B0_RXDVS0_R_DMRXDVS_CNTCMP_OPT_B0);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B1_RXDVS0),0x0, B1_RXDVS0_R_DMRXDVS_CNTCMP_OPT_B1);
+
+ //DQIEN pre-state option to block update for RX ASVA 1-2
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B0_RXDVS0),0x1, B0_RXDVS0_R_DMRXDVS_DQIENPRE_OPT_B0);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B1_RXDVS0),0x1, B1_RXDVS0_R_DMRXDVS_DQIENPRE_OPT_B1);
+
+ //Turn off F_DLY individual calibration option (CTO_AGENT_RDAT cannot separate DR/DF error)
+ //tracking rising and update rising/falling together
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2),0x0, R0_B0_RXDVS2_R_RK0_DVS_FDLY_MODE_B0);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2),0x0, R0_B1_RXDVS2_R_RK0_DVS_FDLY_MODE_B1);
+
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R1_B0_RXDVS2),0x0, R1_B0_RXDVS2_R_RK1_DVS_FDLY_MODE_B0);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R1_B1_RXDVS2),0x0, R1_B1_RXDVS2_R_RK1_DVS_FDLY_MODE_B1);
+
+ for(ii=RANK_0; ii<RANK_MAX; ii++)
+ {
+ vSetRank(p, ii);
+
+ //DQ/DQM/DQS DLY MAX/MIN value under Tracking mode
+ /* Byte 0 */
+#if (fcFOR_CHIP_ID == fcLaurel)
+ /* DQS, DQ, DQM (DQ, DQM are tied together now) -> controlled using DQM MAX_MIN */
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS7), P_Fld(0x0, R0_B0_RXDVS7_RG_RK0_ARDQ_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS7_RG_RK0_ARDQ_MAX_DLY_B0)
+ | P_Fld(0x0, R0_B0_RXDVS7_RG_RK0_ARDQS0_MIN_DLY_B0) | P_Fld(0x7f, R0_B0_RXDVS7_RG_RK0_ARDQS0_MAX_DLY_B0));
+#else
+ /* Previous design DQ, DQM MAX/MIN are controlled using different register fields */
+ /* DQM, DQS */
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS7), P_Fld(0x0, R0_B0_RXDVS7_RG_RK0_ARDQ_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS7_RG_RK0_ARDQ_MAX_DLY_B0)
+ | P_Fld(0x0, R0_B0_RXDVS7_RG_RK0_ARDQS0_MIN_DLY_B0) | P_Fld(0x7f, R0_B0_RXDVS7_RG_RK0_ARDQS0_MAX_DLY_B0));
+ /* DQ */
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS3), P_Fld(0x0, R0_B0_RXDVS3_RG_RK0_ARDQ0_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS3_RG_RK0_ARDQ0_MAX_DLY_B0));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS3), P_Fld(0x0, R0_B0_RXDVS3_RG_RK0_ARDQ1_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS3_RG_RK0_ARDQ1_MAX_DLY_B0));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS4), P_Fld(0x0, R0_B0_RXDVS4_RG_RK0_ARDQ2_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS4_RG_RK0_ARDQ2_MAX_DLY_B0));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS4), P_Fld(0x0, R0_B0_RXDVS4_RG_RK0_ARDQ3_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS4_RG_RK0_ARDQ3_MAX_DLY_B0));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS5), P_Fld(0x0, R0_B0_RXDVS5_RG_RK0_ARDQ4_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS5_RG_RK0_ARDQ4_MAX_DLY_B0));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS5), P_Fld(0x0, R0_B0_RXDVS5_RG_RK0_ARDQ5_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS5_RG_RK0_ARDQ5_MAX_DLY_B0));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS6), P_Fld(0x0, R0_B0_RXDVS6_RG_RK0_ARDQ6_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS6_RG_RK0_ARDQ6_MAX_DLY_B0));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS6), P_Fld(0x0, R0_B0_RXDVS6_RG_RK0_ARDQ7_MIN_DLY_B0) | P_Fld(0x3f, R0_B0_RXDVS6_RG_RK0_ARDQ7_MAX_DLY_B0));
+#endif
+
+ /* Byte 1 */
+#if (fcFOR_CHIP_ID == fcLaurel)
+ /* DQS, DQ, DQM (DQ, DQM are tied together now) -> controlled using DQM MAX_MIN */
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS7), P_Fld(0x0, R0_B1_RXDVS7_RG_RK0_ARDQ_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS7_RG_RK0_ARDQ_MAX_DLY_B1)
+ | P_Fld(0x0, R0_B1_RXDVS7_RG_RK0_ARDQS0_MIN_DLY_B1) | P_Fld(0x7f, R0_B1_RXDVS7_RG_RK0_ARDQS0_MAX_DLY_B1));
+#else
+ /* Previous design DQ, DQM MAX/MIN are controlled using different register fields */
+ /* DQM, DQS */
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS7), P_Fld(0x0, R0_B1_RXDVS7_RG_RK0_ARDQ_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS7_RG_RK0_ARDQ_MAX_DLY_B1)
+ | P_Fld(0x0, R0_B1_RXDVS7_RG_RK0_ARDQS0_MIN_DLY_B1) | P_Fld(0x7f, R0_B1_RXDVS7_RG_RK0_ARDQS0_MAX_DLY_B1));
+ /* DQ */
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS3), P_Fld(0x0, R0_B1_RXDVS3_RG_RK0_ARDQ0_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS3_RG_RK0_ARDQ0_MAX_DLY_B1));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS3), P_Fld(0x0, R0_B1_RXDVS3_RG_RK0_ARDQ1_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS3_RG_RK0_ARDQ1_MAX_DLY_B1));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS4), P_Fld(0x0, R0_B1_RXDVS4_RG_RK0_ARDQ2_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS4_RG_RK0_ARDQ2_MAX_DLY_B1));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS4), P_Fld(0x0, R0_B1_RXDVS4_RG_RK0_ARDQ3_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS4_RG_RK0_ARDQ3_MAX_DLY_B1));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS5), P_Fld(0x0, R0_B1_RXDVS5_RG_RK0_ARDQ4_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS5_RG_RK0_ARDQ4_MAX_DLY_B1));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS5), P_Fld(0x0, R0_B1_RXDVS5_RG_RK0_ARDQ5_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS5_RG_RK0_ARDQ5_MAX_DLY_B1));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS6), P_Fld(0x0, R0_B1_RXDVS6_RG_RK0_ARDQ6_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS6_RG_RK0_ARDQ6_MAX_DLY_B1));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS6), P_Fld(0x0, R0_B1_RXDVS6_RG_RK0_ARDQ7_MIN_DLY_B1) | P_Fld(0x3f, R0_B1_RXDVS6_RG_RK0_ARDQ7_MAX_DLY_B1));
+#endif
+
+ //Threshold for LEAD/LAG filter
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS1), P_Fld(0x2, R0_B0_RXDVS1_R_RK0_B0_DVS_TH_LEAD) | P_Fld(0x2, R0_B0_RXDVS1_R_RK0_B0_DVS_TH_LAG));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS1), P_Fld(0x2, R0_B1_RXDVS1_R_RK0_B1_DVS_TH_LEAD) | P_Fld(0x2, R0_B1_RXDVS1_R_RK0_B1_DVS_TH_LAG));
+
+ //DQ/DQS Rx DLY adjustment for tracking mode
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2), P_Fld(0x0, R0_B0_RXDVS2_R_RK0_RX_DLY_RIS_DQ_SCALE_B0) | P_Fld(0x0, R0_B0_RXDVS2_R_RK0_RX_DLY_RIS_DQS_SCALE_B0));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2), P_Fld(0x0, R0_B1_RXDVS2_R_RK0_RX_DLY_RIS_DQ_SCALE_B1) | P_Fld(0x0, R0_B1_RXDVS2_R_RK0_RX_DLY_RIS_DQS_SCALE_B1));
+
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2), P_Fld(0x0, R0_B0_RXDVS2_R_RK0_RX_DLY_FAL_DQ_SCALE_B0) | P_Fld(0x0, R0_B0_RXDVS2_R_RK0_RX_DLY_FAL_DQS_SCALE_B0));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2), P_Fld(0x0, R0_B1_RXDVS2_R_RK0_RX_DLY_FAL_DQ_SCALE_B1) | P_Fld(0x0, R0_B1_RXDVS2_R_RK0_RX_DLY_FAL_DQS_SCALE_B1));
+ }
+
+ vSetRank(p, backup_rank);
+}
+#endif
+
+void DramcRxInputDelayTrackingInit_byFreq(DRAMC_CTX_T *p)
+{
+ U8 u1DVS_Delay;
+ //Monitor window size setting
+ //DDRPHY.SHU*_B*_DQ5.RG_RX_ARDQS0_DVS_DLY_B* (suggested value from A-PHY owner)
+//WHITNEY_TO_BE_PORTING
+#if (fcFOR_CHIP_ID == fcLaurel)
+ // Speed Voltage DVS_DLY
+ //======================================
+ //SHU1 3200 0.8V 3
+ //SHU2 2667 0.8V-0.7V 4
+ //SHU3 1600 0.7V-0.65V 5
+ if(p->freqGroup == 2132)
+ {
+ u1DVS_Delay =2;
+ }
+ else
+ if(p->freqGroup == 1866)
+ {
+ u1DVS_Delay =3;
+ }
+ else
+ if(p->freqGroup == 1600)
+ {
+ u1DVS_Delay =3;
+ }
+ else if(p->freqGroup == 1333 || p->freqGroup == 1200)
+ {
+ u1DVS_Delay =4;
+ }
+ else// if(p->freqGroup == 800)
+ {
+ u1DVS_Delay =5;
+ }
+#endif
+
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ5), u1DVS_Delay, SHU1_B0_DQ5_RG_RX_ARDQS0_DVS_DLY_B0);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ5), u1DVS_Delay, SHU1_B1_DQ5_RG_RX_ARDQS0_DVS_DLY_B1);
+
+ /* Bianco HW design issue: run-time PBYTE flag will lose it's function and become per-bit -> set to 0 */
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ7), P_Fld(0x0, SHU1_B0_DQ7_R_DMRXDVS_PBYTE_FLAG_OPT_B0)
+ | P_Fld(0x0, SHU1_B0_DQ7_R_DMRXDVS_PBYTE_DQM_EN_B0));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ7), P_Fld(0x0, SHU1_B1_DQ7_R_DMRXDVS_PBYTE_FLAG_OPT_B1)
+ | P_Fld(0x0, SHU1_B1_DQ7_R_DMRXDVS_PBYTE_DQM_EN_B1));
+}
+
+#if ENABLE_RX_TRACKING_LP4
+void DramcRxInputDelayTrackingHW(DRAMC_CTX_T *p)
+{
+ DRAM_CHANNEL_T channel_bak = p->channel;
+ //UINT8 updateDone=0;
+ //U16 u2DVS_TH=0x0;
+ //U16 u2MinDly=0x14;
+ //U16 u2MaxDly=0x30;
+ U8 ii, backup_rank;
+
+ vSetPHY2ChannelMapping(p, CHANNEL_A);
+ backup_rank = u1GetRank(p);
+
+ //Rx DLY tracking setting (Static)
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_B0_RXDVS0),
+ P_Fld(1, B0_RXDVS0_R_RX_DLY_TRACK_SPM_CTRL_B0) |
+ P_Fld(0, B0_RXDVS0_R_RX_RANKINCTL_B0)|
+ P_Fld(1, B0_RXDVS0_R_RX_RANKINSEL_B0));
+
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_B1_RXDVS0),
+ P_Fld(1, B1_RXDVS0_R_RX_DLY_TRACK_SPM_CTRL_B1) |
+ P_Fld(0, B1_RXDVS0_R_RX_RANKINCTL_B1)|
+ P_Fld(1, B1_RXDVS0_R_RX_RANKINSEL_B1));
+
+#if (fcFOR_CHIP_ID == fcLaurel)
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ9), P_Fld(0x1, B0_DQ9_R_DMRXDVS_RDSEL_LAT_B0 | P_Fld(0, B0_DQ9_R_DMRXDVS_VALID_LAT_B0)));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ9), P_Fld(0x1, B1_DQ9_R_DMRXDVS_RDSEL_LAT_B1) | P_Fld(0, B1_DQ9_R_DMRXDVS_VALID_LAT_B1));
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD10), P_Fld(0,CA_CMD10_R_DMRXDVS_RDSEL_LAT_CA) | P_Fld(0, CA_CMD10_R_DMRXDVS_VALID_LAT_CA));
+
+ /* DMRXTRACK_DQM_B* (rxdly_track SM DQM enable) -> need to be set to 1 if R_DBI is on
+ * They are shuffle regs -> move setting to DramcSetting_Olympus_LP4_ByteMode()
+ */
+
+ //Enable A-PHY DVS LEAD/LAG
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 0x1, B0_DQ5_RG_RX_ARDQS0_DVS_EN_B0);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 0x1, B1_DQ5_RG_RX_ARDQS0_DVS_EN_B1);
+#else
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_MISC_RXDVS2), P_Fld(0x1, MISC_RXDVS2_R_RXDVS_RDSEL_TOG_LAT)
+ | P_Fld(0x2, MISC_RXDVS2_R_RXDVS_RDSEL_BUS_LAT));
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 0x0, MISC_CTRL1_R_DMDQMDBI);
+
+ //Enable A-PHY DVS LEAD/LAG
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 0x1, B0_DQ5_RG_RX_ARDQS0_DVS_EN_B0);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 0x1, B1_DQ5_RG_RX_ARDQS0_DVS_EN_B1);
+#endif
+
+ //Rx DLY tracking function CG enable
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B0_RXDVS0), 0x1, B0_RXDVS0_R_RX_DLY_TRACK_CG_EN_B0);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B1_RXDVS0), 0x1, B1_RXDVS0_R_RX_DLY_TRACK_CG_EN_B1);
+
+ //Rx DLY tracking lead/lag counter enable
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B0_RXDVS0), 0x1, B0_RXDVS0_R_RX_DLY_TRACK_ENA_B0);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B1_RXDVS0), 0x1, B1_RXDVS0_R_RX_DLY_TRACK_ENA_B1);
+
+ for(ii=RANK_0; ii<RANK_MAX; ii++)
+ {
+ vSetRank(p, ii);
+
+ //Rx DLY tracking update enable (HW mode)
+ #if 0
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2), 0x2, R0_B0_RXDVS2_R_RK0_DVS_MODE_B0);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2), 0x2, R0_B1_RXDVS2_R_RK0_DVS_MODE_B1);
+
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2), 0x1, R0_B0_RXDVS2_R_RK0_RX_DLY_RIS_TRACK_GATE_ENA_B0);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2), 0x1, R0_B1_RXDVS2_R_RK0_RX_DLY_RIS_TRACK_GATE_ENA_B1);
+
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2), 0x1, R0_B0_RXDVS2_R_RK0_RX_DLY_FAL_TRACK_GATE_ENA_B0);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2), 0x1, R0_B1_RXDVS2_R_RK0_RX_DLY_FAL_TRACK_GATE_ENA_B1);
+ #else
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B0_RXDVS2),
+ P_Fld(2, R0_B0_RXDVS2_R_RK0_DVS_MODE_B0) |
+ P_Fld(1, R0_B0_RXDVS2_R_RK0_RX_DLY_RIS_TRACK_GATE_ENA_B0)|
+ P_Fld(1, R0_B0_RXDVS2_R_RK0_RX_DLY_FAL_TRACK_GATE_ENA_B0));
+
+ vIO32WriteFldMulti_All(DRAMC_REG_ADDR(DDRPHY_R0_B1_RXDVS2),
+ P_Fld(2, R0_B1_RXDVS2_R_RK0_DVS_MODE_B1) |
+ P_Fld(1, R0_B1_RXDVS2_R_RK0_RX_DLY_RIS_TRACK_GATE_ENA_B1)|
+ P_Fld(1, R0_B1_RXDVS2_R_RK0_RX_DLY_FAL_TRACK_GATE_ENA_B1));
+ #endif
+ }
+
+ vSetRank(p, backup_rank);
+
+#if 0
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B0_RXDVS0),0x1, B0_RXDVS0_R_RX_DLY_RK_OPT_B0);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B1_RXDVS0),0x1, B1_RXDVS0_R_RX_DLY_RK_OPT_B1);
+
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 1, MISC_CTRL1_R_HWSAVE_MODE_ENA);
+#endif
+
+ vSetPHY2ChannelMapping(p, channel_bak);
+}
+#endif
+
+
+#if SIMULATION_LP4_ZQ
+//-------------------------------------------------------------------------
+/** DramcZQCalibration
+ * start Dram ZQ calibration.
+ * @param p Pointer of context created by DramcCtxCreate.
+ * @retval status (DRAM_STATUS_T): DRAM_OK or DRAM_FAIL
+ */
+//-------------------------------------------------------------------------
+DRAM_STATUS_T DramcZQCalibration(DRAMC_CTX_T *p)
+{
+ U32 u4Response;
+ U32 u4TimeCnt = TIME_OUT_CNT;
+ U32 u4RegBackupAddress[] = {DRAMC_REG_ADDR(DRAMC_REG_MRS), DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), DRAMC_REG_ADDR(DRAMC_REG_CKECTRL)};
+
+ // Backup rank, CKE fix on/off, HW MIOCK control settings
+ DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+ mcSHOW_DBG_MSG3(("[ZQCalibration]\n"));
+ mcFPRINTF((fp_A60501, "[ZQCalibration]\n"));
+
+ // Disable HW MIOCK control to make CLK always on
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 1, DRAMC_PD_CTRL_MIOCKCTRLOFF);
+ mcDELAY_US(1);
+
+ //if CKE2RANK=1, only need to set CKEFIXON, it will apply to both rank.
+ CKEFixOnOff(p, p->rank, CKE_FIXON, CKE_WRITE_TO_ONE_CHANNEL);
+
+ //Use rank swap or MRSRK to select rank
+ //DramcRankSwap(p, p->rank);
+ //!!R_DMMRSRK(R_DMMPCRKEN=1) specify rank0 or rank1
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRS), u1GetRank(p), MRS_MRSRK);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MPC_OPTION), 1, MPC_OPTION_MPCRKEN);
+
+ //ZQCAL Start
+ //R_DMZQCEN, 0x1E4[4]=1 for ZQCal Start
+ //Wait zqc_response=1 (dramc_conf_nao, 0x3b8[4])
+ //R_DMZQCEN, 0x1E4[4]=0
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_ZQCEN);
+ do
+ {
+ u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_ZQC_RESPONSE);
+ u4TimeCnt --;
+ mcDELAY_US(1); // Wait tZQCAL(min) 1us or wait next polling
+
+ mcSHOW_DBG_MSG3(("%d- ", u4TimeCnt));
+ mcFPRINTF((fp_A60501, "%d- ", u4TimeCnt));
+ }while((u4Response==0) &&(u4TimeCnt>0));
+
+ if(u4TimeCnt==0)//time out
+ {
+ vSetCalibrationResult(p, DRAM_CALIBRATION_ZQ, DRAM_FAIL);
+ mcSHOW_DBG_MSG(("ZQCAL Start fail (time out)\n"));
+ mcFPRINTF((fp_A60501, "ZQCAL Start fail (time out)\n"));
+ return DRAM_FAIL;
+ }
+ else
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_ZQCEN);
+ }
+
+ // [JC] delay tZQCAL
+ mcDELAY_US(1);
+ u4TimeCnt = TIME_OUT_CNT;
+
+ //ZQCAL Latch
+ //R_DMZQLATEN, 0x1E4[6]=1 for ZQCal latch
+ //Wait zqlat_response=1 (dramc_conf_nao, 0x3b8[28])
+ //R_DMZQLATEN, 0x1E4[6]=0
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_ZQLATEN);
+ do
+ {
+ u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_ZQLAT_RESPONSE);
+ u4TimeCnt --;
+ mcDELAY_US(1);// Wait tZQLAT 30ns or wait next polling
+
+ mcSHOW_DBG_MSG3(("%d=", u4TimeCnt));
+ mcFPRINTF((fp_A60501, "%d= ", u4TimeCnt));
+ }while((u4Response==0) &&(u4TimeCnt>0));
+
+ if(u4TimeCnt==0)//time out
+ {
+ vSetCalibrationResult(p, DRAM_CALIBRATION_ZQ, DRAM_FAIL);
+ mcSHOW_DBG_MSG(("ZQCAL Latch fail (time out)\n"));
+ mcFPRINTF((fp_A60501, "ZQCAL Latch fail (time out)\n"));
+ return DRAM_FAIL;
+ }
+ else
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_ZQLATEN);
+ }
+
+ // [JC] delay tZQLAT
+ mcDELAY_US(1);
+
+ // Restore rank, CKE fix on, HW MIOCK control settings
+ DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+ vSetCalibrationResult(p, DRAM_CALIBRATION_ZQ, DRAM_OK);
+ mcSHOW_DBG_MSG3(("\n[DramcZQCalibration] Done\n\n"));
+ mcFPRINTF((fp_A60501, "\n[DramcZQCalibration] Done\n\n"));
+
+ return DRAM_OK;
+}
+#endif
+
+#if SIMULATION_RX_INPUT_BUF
+//-------------------------------------------------------------------------
+/** DramcSwImpedanceCal
+ * start TX OCD impedance calibration.
+ * @param p Pointer of context created by DramcCtxCreate.
+ * @param apply (U8): 0 don't apply the register we set 1 apply the register we set ,default don't apply.
+ * @retval status (DRAM_STATUS_T): DRAM_OK or DRAM_FAIL
+ */
+//-------------------------------------------------------------------------
+static U8 RXInputBuf_DelayExchange(S8 iOfst)
+{
+ U8 u1Value;
+
+ if(iOfst <0)
+ {
+ u1Value = 0x8 | (-iOfst);
+ }
+ else
+ {
+ u1Value = iOfst;
+ }
+
+ return u1Value;
+}
+
+// cannot be simulated in DV or DSim, it's analog feature.
+DRAM_STATUS_T DramcRXInputBufferOffsetCal(DRAMC_CTX_T *p)
+{
+ U16 u2RXVrefDefault;
+ U32 u4RegBackupAddress[] =
+ {
+ (DRAMC_REG_ADDR(DDRPHY_B0_DQ5)),
+ (DRAMC_REG_ADDR(DDRPHY_B1_DQ5)),
+ (DRAMC_REG_ADDR(DDRPHY_B0_DQ6)),
+ (DRAMC_REG_ADDR(DDRPHY_B1_DQ6)),
+ (DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ5)),
+ (DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ5)),
+ (DRAMC_REG_ADDR(DDRPHY_B0_DQ3)),
+ (DRAMC_REG_ADDR(DDRPHY_B1_DQ3)),
+ (DRAMC_REG_ADDR(DRAMC_REG_PADCTRL)),
+ };
+ S8 iOffset, iDQFlagChange[16], iDQMFlagChange[2];
+ U32 u4Value, u4RestltDQ[2], u4RestltDQM[2];
+ U8 u1BitIdx, u1ByteIdx, u1FinishCount, u1DQFinalFlagChange[16], u1DQMFinalFlagChange[2];
+
+ mcSHOW_DBG_MSG(("\n[RXInputBufferOffsetCal]\n"));
+ mcFPRINTF((fp_A60501, "\n[RXInputBufferOffsetCal] \n"));
+
+ if(!u1IsLP4Family(p->dram_type))
+ {
+ //RX offset calibration(LP4 only)
+ mcSHOW_ERR_MSG(("LP3 no need\n"));
+ return DRAM_FAIL;
+ }
+
+ //Back up dramC register
+ DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PADCTRL), 0xf, PADCTRL_FIXDQIEN);
+
+ //Enable BIAS (RG_RX_*RDQ*_RES_BIAS_EN_B), RG_RX_*_BIAS_PS* = 2'b01(RG mode)
+ //Select VREF, for LPDDR4 set RG_RX_*DQ_DDR4_SEL_* =1, RG_RX_*DQ_DDR3_SEL_* =0
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ6),
+ P_Fld(1, B0_DQ6_RG_RX_ARDQ_BIAS_PS_B0) |
+ P_Fld(1, B0_DQ6_RG_RX_ARDQ_RES_BIAS_EN_B0) |
+ P_Fld(0, B0_DQ6_RG_RX_ARDQ_DDR3_SEL_B0) |
+ P_Fld(1, B0_DQ6_RG_RX_ARDQ_DDR4_SEL_B0));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ6),
+ P_Fld(1, B1_DQ6_RG_RX_ARDQ_BIAS_PS_B1) |
+ P_Fld(1, B1_DQ6_RG_RX_ARDQ_RES_BIAS_EN_B1) |
+ P_Fld(0, B1_DQ6_RG_TX_ARDQ_DDR3_SEL_B1) |
+ P_Fld(1, B1_DQ6_RG_TX_ARDQ_DDR4_SEL_B1));
+
+ //Enable VREF, (RG_RX_*DQ_VREF_EN_* =1)
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_VREF_EN_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_VREF_EN_B1);
+
+ //Set Vref voltage: LP4 with termination SEL[4:0] = 01110 (0xe) (refer to Vref default table)
+ //Only need to set Vref with term, only K rx input offset at highest freq.
+ //Need to set according to ODT on/off.
+ u2RXVrefDefault = vGetRXVrefDefault(p);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ5), u2RXVrefDefault, SHU1_B0_DQ5_RG_RX_ARDQ_VREF_SEL_B0); // LP4 and LP4x with term: 0xe
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ5), u2RXVrefDefault, SHU1_B1_DQ5_RG_RX_ARDQ_VREF_SEL_B1); // LP4 and LP4x with term: 0xe
+
+ // Wait 1us.
+ mcDELAY_US(1);
+
+ //Enable RX input buffer (RG_RX_*DQ_IN_BUFF_EN_* =1, DA_RX_*DQ_IN_GATE_EN_* =1)
+ //Enable RX input buffer offset calibration (RG_RX_*DQ_OFFC_EN_*=1)
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PADCTRL), 0xf, PADCTRL_FIXDQIEN); // same as DA_RX_*DQ_IN_GATE_EN_*=1, Keep DQ input always ON. ==> Note: Do not enable again.
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ3), P_Fld(1, B0_DQ3_RG_RX_ARDQ_IN_BUFF_EN_B0) | P_Fld(1, B0_DQ3_RG_RX_ARDQ_OFFC_EN_B0));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ3), P_Fld(1, B1_DQ3_RG_RX_ARDQ_IN_BUFF_EN_B1) | P_Fld(1, B1_DQ3_RG_RX_ARDQ_OFFC_EN_B1));
+
+ // SW parameter initialization
+ u1FinishCount =0;
+ iDQMFlagChange[0] = 0x7f;
+ iDQMFlagChange[1] = 0x7f;
+
+ for(u1BitIdx=0; u1BitIdx< 16; u1BitIdx++)
+ {
+ iDQFlagChange[u1BitIdx] = 0x7f; //initial as invalid
+ }
+
+ //Sweep RX offset calibration code (RG_RX_*DQ*_OFFC<3:0>), the MSB is sign bit, sweep the code from -7(1111) to +7(0111)
+ for(iOffset=-7; iOffset<7; iOffset++)
+ {
+ u4Value = RXInputBuf_DelayExchange(iOffset);
+
+ #ifdef ETT_PRINT_FORMAT
+ mcSHOW_DBG_MSG(("iOffset= %d, u4Value=%d,", iOffset, u4Value));
+ #else
+ mcSHOW_DBG_MSG(("iOffset= %2d, u4Value=%2d,", iOffset, u4Value));
+ #endif
+ mcFPRINTF((fp_A60501, "iOffset= %2d, u4Value=%2d,", iOffset, u4Value));
+
+ //Delay of DQM0.
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ1), u4Value, B0_DQ1_RG_RX_ARDQM0_OFFC_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ1), u4Value, B1_DQ1_RG_RX_ARDQM0_OFFC_B1);
+
+ //Delay of DQ0~DQ7.
+ u4Value = u4Value |(u4Value<<4) |(u4Value<<8) |(u4Value<<12) |(u4Value<<16) |(u4Value<<20) |(u4Value<<24) |(u4Value<<28);
+ vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_B0_DQ0), u4Value);
+ vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_B1_DQ0), u4Value);
+
+ //For each code sweep, wait 0.1us to check the flag.
+ mcDELAY_US(1);
+
+ //Check offset flag of DQ (RGS_*DQ*_OFFSET_FLAG_*), the value will be from 1(-7) to 0(+7). Record the value when the flag becomes "0".
+ //Flag bit0 is for DQ0, Flag bit15 for DQ15
+ u4RestltDQ[0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_PHY_RGS_DQ), MISC_PHY_RGS_DQ_RGS_ARDQ_OFFSET_FLAG_B0);
+ u4RestltDQ[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_PHY_RGS_DQ), MISC_PHY_RGS_DQ_RGS_ARDQ_OFFSET_FLAG_B1);
+ u4RestltDQ[0] |= (u4RestltDQ[1] <<8);
+
+ mcSHOW_DBG_MSG(("RestltDQ (B1)0x%x (B0)0x%x, ", u4RestltDQ[1], u4RestltDQ[0]));
+ mcFPRINTF((fp_A60501, "RestltDQ (B1)0x%x (B0)0x%x, ", u4RestltDQ[1], u4RestltDQ[0]));
+
+ for(u1BitIdx= 0; u1BitIdx <16; u1BitIdx++)
+ {
+ if(iDQFlagChange[u1BitIdx] == 0x7f) //invalid
+ {
+ u4Value = (u4RestltDQ[0] >> u1BitIdx) & 0x1;
+
+ if(u4Value ==0) // 1 -> 0
+ {
+ iDQFlagChange[u1BitIdx] = iOffset;
+ u1FinishCount ++;
+ }
+ }
+ }
+
+ //Check offset flag of DQM (RGS_*DQ*_OFFSET_FLAG_*), the value will be from 1(-7) to 0(+7). Record the value when the flag becomes "0".
+ u4RestltDQM[0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_PHY_RGS_DQ), MISC_PHY_RGS_DQ_RGS_ARDQM0_OFFSET_FLAG_B0);
+ u4RestltDQM[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_PHY_RGS_DQ), MISC_PHY_RGS_DQ_RGS_ARDQM0_OFFSET_FLAG_B1);
+
+ mcSHOW_DBG_MSG(("RestltDQM (B1)= 0x%x, (B0)= 0x%x\n", u4RestltDQM[1], u4RestltDQM[0]));
+ mcFPRINTF((fp_A60501, "RestltDQM (B1)= 0x%x, (B0)= 0x%x\n", u4RestltDQM[1], u4RestltDQM[0]));
+
+ for(u1ByteIdx= 0; u1ByteIdx <2; u1ByteIdx++)
+ {
+ if(iDQMFlagChange[u1ByteIdx]== 0x7f) //invalid
+ {
+ if(u4RestltDQM[u1ByteIdx]==0)// 1 -> 0
+ {
+ iDQMFlagChange[u1ByteIdx]= iOffset;
+ u1FinishCount++;
+ }
+ }
+ }
+
+ if(u1FinishCount==18) // (DQ8 bits, DQM 1bit, total 9 bits.) x2 bytes
+ {
+ break; //all bits done, early break
+ }
+ }
+
+ mcSHOW_DBG_MSG(("\nResult DQ\n"
+ "\t0\t1\t2\t3\t4\t5\t6\t7\n"
+ "Byte 0\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n"
+ "Byte 1\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n"
+ "Result DQM [0] %d, [1] %d\n",
+ iDQFlagChange[0], iDQFlagChange[1], iDQFlagChange[2], iDQFlagChange[3],
+ iDQFlagChange[4], iDQFlagChange[5], iDQFlagChange[6], iDQFlagChange[7],
+ iDQFlagChange[8], iDQFlagChange[9], iDQFlagChange[10], iDQFlagChange[11],
+ iDQFlagChange[12], iDQFlagChange[13], iDQFlagChange[14],iDQFlagChange[15],
+ iDQMFlagChange[0], iDQMFlagChange[1]));
+
+ mcFPRINTF((fp_A60501,"Result DQ [0]%d [1]%d [2]%d [3]%d [4]%d [5]%d [6]%d [7]%d\n", \
+ iDQFlagChange[0], iDQFlagChange[1], iDQFlagChange[2], iDQFlagChange[3], \
+ iDQFlagChange[4], iDQFlagChange[5], iDQFlagChange[6],iDQFlagChange[7]));
+
+ mcFPRINTF((fp_A60501, "Result DQ Byte 1 [0]%d [1]%d [2]%d [3]%d [4]%d [5]%d [6]%d [7]%d\n", \
+ iDQFlagChange[8], iDQFlagChange[9], iDQFlagChange[10], iDQFlagChange[11], \
+ iDQFlagChange[12], iDQFlagChange[13], iDQFlagChange[14],iDQFlagChange[15]));
+
+ mcFPRINTF((fp_A60501, "Result DQM[0] %d, Result DQM[1] %d,\n", iDQMFlagChange[0], iDQMFlagChange[1]));
+
+ //Restore setting registers
+ DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+ // Change the offset value according to register format
+ for(u1BitIdx= 0; u1BitIdx <16; u1BitIdx++)
+ {
+ u1DQFinalFlagChange[u1BitIdx] = RXInputBuf_DelayExchange(iDQFlagChange[u1BitIdx]);
+ }
+ u1DQMFinalFlagChange[0]= RXInputBuf_DelayExchange(iDQMFlagChange[0]);
+ u1DQMFinalFlagChange[1]= RXInputBuf_DelayExchange(iDQMFlagChange[1]);
+
+ //Apply the code recorded.
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ1), u1DQMFinalFlagChange[0], B0_DQ1_RG_RX_ARDQM0_OFFC_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ1), u1DQMFinalFlagChange[1], B1_DQ1_RG_RX_ARDQM0_OFFC_B1);
+
+ u4Value = u1DQFinalFlagChange[0] |(u1DQFinalFlagChange[1]<<4) |(u1DQFinalFlagChange[2]<<8) |(u1DQFinalFlagChange[3]<<12) | \
+ (u1DQFinalFlagChange[4]<<16) |(u1DQFinalFlagChange[5]<<20) |(u1DQFinalFlagChange[6]<<24) |(u1DQFinalFlagChange[7]<<28);
+ vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_B0_DQ0), u4Value);
+
+ u4Value = u1DQFinalFlagChange[8] |(u1DQFinalFlagChange[9]<<4) |(u1DQFinalFlagChange[10]<<8) |(u1DQFinalFlagChange[11]<<12) | \
+ (u1DQFinalFlagChange[12]<<16) |(u1DQFinalFlagChange[13]<<20) |(u1DQFinalFlagChange[14]<<24) |(u1DQFinalFlagChange[15]<<28);
+ vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_B1_DQ0), u4Value);
+
+ // Disable RX input buffer offset calibration (RG_RX_*DQ_OFFC_EN_*=0)
+ //U32 u4AddrOfst = 0x50;
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_TXDQ3+u4AddrOfst), 0, TXDQ3_RG_RX_ARDQ_OFFC_EN_B0);
+
+ #if 0
+ mcSHOW_DBG_MSG(("Register DQ [0]%d [1]%d [2]%d [3]%d [4]%d [5]%d [6]%d [7]%d\n", \
+ u1DQFinalFlagChange[0], u1DQFinalFlagChange[1], u1DQFinalFlagChange[2], u1DQFinalFlagChange[3], \
+ u1DQFinalFlagChange[4], u1DQFinalFlagChange[5], u1DQFinalFlagChange[6],u1DQFinalFlagChange[7]));
+ mcFPRINTF((fp_A60501,"Register DQ [0]%d [1]%d [2]%d [3]%d [4]%d [5]%d [6]%d [7]%d\n", \
+ u1DQFinalFlagChange[0], u1DQFinalFlagChange[1], u1DQFinalFlagChange[2], u1DQFinalFlagChange[3], \
+ u1DQFinalFlagChange[4], u1DQFinalFlagChange[5], u1DQFinalFlagChange[6],u1DQFinalFlagChange[7]));
+ mcSHOW_DBG_MSG(("Register DQM %d\n", u1DQMFinalFlagChange));
+ mcFPRINTF((fp_A60501, "Register DQM %d\n", u1DQMFinalFlagChange));
+ #endif
+ mcSHOW_DBG_MSG3(("[DramcRXInputBufferOffsetCal] Done\n"));
+ mcFPRINTF((fp_A60501, "[DramcRXInputBufferOffsetCal] Done\n"));
+
+ return DRAM_OK;
+}
+#endif
+
+//-------------------------------------------------------------------------
+/** DramcSwImpedanceCal
+ * start TX OCD impedance calibration.
+ * @param p Pointer of context created by DramcCtxCreate.
+ * @param apply (U8): 0 don't apply the register we set 1 apply the register we set ,default don't apply.
+ * @retval status (DRAM_STATUS_T): DRAM_OK or DRAM_FAIL
+ */
+//-------------------------------------------------------------------------
+#define HYNIX_IMPX_ADJUST 0
+#if HYNIX_IMPX_ADJUST
+U32 ImpedanceAdjustment_Hynix(U32 u4OriValue, U8 u1Div)
+{
+ U32 u4RODT;
+ U32 u4AdjustValue;
+
+ if(u1Div >0)
+ {
+ u4RODT = 240/u1Div;
+ u4AdjustValue = 60 *(u4OriValue+2)/u4RODT -2;
+ }
+ else
+ {
+ u4RODT =0;
+ u4AdjustValue = u4OriValue;
+ }
+
+ mcSHOW_DBG_MSG(("ODTN Change by Tool, 240 div %d =%d, After adjustment ODTN=%d\n\n", u1Div, u4RODT, u4AdjustValue));
+
+ return u4AdjustValue;
+}
+#endif
+
+/* Impedance have a total of 19 steps, but the HW value mapping to hardware is 0~15, 29~31
+* This function adjusts passed value u1ImpVal by adjust step count "u1AdjStepCnt"
+* After adjustment, if value is 1. Too large (val > 31) -> set to max 31
+* 2. Too small (val < 0) -> set to min 0
+* 3. Value is between 15 & 29, adjust accordingly ( 15 < value < 29 )
+* returns: Impedance value after adjustment
+*/
+static U32 SwImpedanceAdjust(U32 u4ImpVal, S8 s1StepCnt)
+{
+ S32 S4ImpedanceTemp = (S32)u4ImpVal;
+
+ // Perform impedance value adjustment
+ S4ImpedanceTemp += s1StepCnt;
+ /* After adjustment, if value is 1. Too large (val > 31) -> set to max 31
+ * 2. Too small (val < 0) -> set to min 0
+ * 3. Value is between 15 & 29, adjust accordingly ( 15 < value < 29 )
+ */
+ if ((S4ImpedanceTemp > 15) && (S4ImpedanceTemp < 29)) //Value is between 15 & 29 ( 15 < value < 29)
+ {
+ S4ImpedanceTemp = S4ImpedanceTemp - 16 + 29;
+ }
+
+ if (S4ImpedanceTemp > 31) //Value after adjustment too large -> set to max 31
+ {
+ S4ImpedanceTemp = 31;
+ }
+ else if (S4ImpedanceTemp < 0) //Value after adjustment too small -> set to min 0
+ {
+ S4ImpedanceTemp = 0;
+ }
+
+ return (U32)S4ImpedanceTemp;
+}
+
+#if SIMULATION_SW_IMPED
+void DramcSwImpedanceSaveRegister(DRAMC_CTX_T *p, U8 ca_term_option, U8 dq_term_option, U8 save_to_where)
+{
+ U8 backup_broadcast;
+
+ backup_broadcast = GetDramcBroadcast();
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ DramcBroadcastOnOff(DRAMC_BROADCAST_ON);
+ //DQ
+ vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING1 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVP], SHU1_DRVING1_DQDRVP2) | P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVN], SHU1_DRVING1_DQDRVN2));
+ vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING2 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVP], SHU1_DRVING2_DQDRVP1) | P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVN], SHU1_DRVING2_DQDRVN1) | P_Fld((!dq_term_option), SHU1_DRVING2_DIS_IMPCAL_ODT_EN));
+ vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING3 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][ODTP], SHU1_DRVING3_DQODTP2) | P_Fld(gDramcSwImpedanceResule[dq_term_option][ODTN], SHU1_DRVING3_DQODTN2));
+ vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING4 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][ODTP], SHU1_DRVING4_DQODTP1) | P_Fld(gDramcSwImpedanceResule[dq_term_option][ODTN], SHU1_DRVING4_DQODTN1));
+
+ //DQS
+ vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING1 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVP], SHU1_DRVING1_DQSDRVP2) | P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVN], SHU1_DRVING1_DQSDRVN2));
+ vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING1 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVP], SHU1_DRVING1_DQSDRVP1) | P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVN], SHU1_DRVING1_DQSDRVN1));
+ vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING3 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][ODTP], SHU1_DRVING3_DQSODTP2) | P_Fld(gDramcSwImpedanceResule[dq_term_option][ODTN], SHU1_DRVING3_DQSODTN2));
+ vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING3 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][ODTP], SHU1_DRVING3_DQSODTP) | P_Fld(gDramcSwImpedanceResule[dq_term_option][ODTN], SHU1_DRVING3_DQSODTN));
+
+ //CMD & CLK
+ vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING2 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[ca_term_option][DRVP], SHU1_DRVING2_CMDDRVP2) | P_Fld(gDramcSwImpedanceResule[ca_term_option][DRVN], SHU1_DRVING2_CMDDRVN2));
+ vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING2 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[ca_term_option][DRVP], SHU1_DRVING2_CMDDRVP1) | P_Fld(gDramcSwImpedanceResule[ca_term_option][DRVN], SHU1_DRVING2_CMDDRVN1));
+ vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING4 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[ca_term_option][ODTP], SHU1_DRVING4_CMDODTP2) | P_Fld(gDramcSwImpedanceResule[ca_term_option][ODTN], SHU1_DRVING4_CMDODTN2));
+ vIO32WriteFldMulti((DRAMC_REG_SHU1_DRVING4 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[ca_term_option][ODTP], SHU1_DRVING4_CMDODTP1) | P_Fld(gDramcSwImpedanceResule[ca_term_option][ODTN], SHU1_DRVING4_CMDODTN1));
+
+ //RG_TX_*RCKE_DRVP/RG_TX_*RCKE_DRVN doesn't set, so set 0xA first
+ vIO32WriteFldAlign((DDRPHY_SHU1_CA_CMD11 + save_to_where * SHU_GRP_DDRPHY_OFFSET), gDramcSwImpedanceResule[ca_term_option][DRVP], SHU1_CA_CMD11_RG_TX_ARCKE_DRVP);
+ vIO32WriteFldAlign((DDRPHY_SHU1_CA_CMD11 + save_to_where * SHU_GRP_DDRPHY_OFFSET), gDramcSwImpedanceResule[ca_term_option][DRVN], SHU1_CA_CMD11_RG_TX_ARCKE_DRVN);
+
+ //CKE
+ // CKE is full swing.
+ // LP4/LP4X set DRVP/DRVN as LP3's default value
+ // DRVP=8
+ // DRVN=9
+ //DRVP[4:0] = RG_TX_ARCMD_PU_PRE<1:0>, RG_TX_ARCLK_DRVN_PRE<2:0>
+ vIO32WriteFldAlign((DDRPHY_SHU1_CA_CMD3 + save_to_where * SHU_GRP_DDRPHY_OFFSET), (8>>3)&0x3, SHU1_CA_CMD3_RG_TX_ARCMD_PU_PRE);
+ vIO32WriteFldAlign((DDRPHY_SHU1_CA_CMD0 + save_to_where * SHU_GRP_DDRPHY_OFFSET), 8&0x7, SHU1_CA_CMD0_RG_TX_ARCLK_DRVN_PRE);
+ //DRVN[4:0] = RG_ARCMD_REV<12:8>
+ #if (fcFOR_CHIP_ID == fcLaurel)
+ DramcBroadcastOnOff(DRAMC_BROADCAST_OFF);
+ vIO32WriteFldAlign_All((DDRPHY_SHU1_CA_DLL1 + save_to_where * SHU_GRP_DDRPHY_OFFSET), 9, RG_ARCMD_REV_BIT_1208_TX_CKE_DRVN);
+ DramcBroadcastOnOff(DRAMC_BROADCAST_ON);
+ #endif
+
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ //DQ
+ vIO32WriteFldMulti_All((DRAMC_REG_SHU1_DRVING1 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVP], SHU1_DRVING1_DQDRVP2) | P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVN], SHU1_DRVING1_DQDRVN2));
+ vIO32WriteFldMulti_All((DRAMC_REG_SHU1_DRVING2 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVP], SHU1_DRVING2_DQDRVP1) | P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVN], SHU1_DRVING2_DQDRVN1) | P_Fld((!dq_term_option), SHU1_DRVING2_DIS_IMPCAL_ODT_EN));
+
+ //DQS
+ vIO32WriteFldMulti_All((DRAMC_REG_SHU1_DRVING1 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVP], SHU1_DRVING1_DQSDRVP2) | P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVN], SHU1_DRVING1_DQSDRVN2));
+ vIO32WriteFldMulti_All((DRAMC_REG_SHU1_DRVING1 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVP], SHU1_DRVING1_DQSDRVP1) | P_Fld(gDramcSwImpedanceResule[dq_term_option][DRVN], SHU1_DRVING1_DQSDRVN1));
+
+ //CMD & CLK
+ vIO32WriteFldMulti_All((DRAMC_REG_SHU1_DRVING2 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[ca_term_option][DRVP], SHU1_DRVING2_CMDDRVP2) | P_Fld(gDramcSwImpedanceResule[ca_term_option][DRVN], SHU1_DRVING2_CMDDRVN2));
+ vIO32WriteFldMulti_All((DRAMC_REG_SHU1_DRVING2 + save_to_where * SHU_GRP_DRAMC_OFFSET), P_Fld(gDramcSwImpedanceResule[ca_term_option][DRVP], SHU1_DRVING2_CMDDRVP1) | P_Fld(gDramcSwImpedanceResule[ca_term_option][DRVN], SHU1_DRVING2_CMDDRVN1));
+
+
+ //CKE
+ // CKE is full swing.
+ // LP3 CKE DRVP/DRVN is same above
+ //DRVP[4:0] = RG_TX_ARCMD_PU_PRE<1:0>, RG_TX_ARCLK_DRVN_PRE<2:0>
+ vIO32WriteFldAlign_All((DDRPHY_SHU1_CA_CMD3 + save_to_where * SHU_GRP_DDRPHY_OFFSET), (gDramcSwImpedanceResule[dq_term_option][DRVP]>>3)&0x3, SHU1_CA_CMD3_RG_TX_ARCMD_PU_PRE);
+ vIO32WriteFldAlign_All((DDRPHY_SHU1_CA_CMD0 + save_to_where * SHU_GRP_DDRPHY_OFFSET), gDramcSwImpedanceResule[dq_term_option][DRVP]&0x7, SHU1_CA_CMD0_RG_TX_ARCLK_DRVN_PRE);
+ //DRVN[4:0] = RG_ARCMD_REV<12:8>
+ #if (fcFOR_CHIP_ID == fcLaurel)
+ vIO32WriteFldAlign_All((DDRPHY_SHU1_CA_DLL1 + save_to_where * SHU_GRP_DDRPHY_OFFSET), gDramcSwImpedanceResule[dq_term_option][DRVN], RG_ARCMD_REV_BIT_1208_TX_CKE_DRVN);
+ #endif
+ }
+#endif /* ENABLE_LP3_SW */
+ DramcBroadcastOnOff(backup_broadcast);
+}
+
+//-------------------------------------------------------------------------
+/** vImpCalVrefSel
+ * Set IMP_VREF_SEL for DRVP, DRVN, Run-time/Tracking
+ * (Refer to "IMPCAL Settings" document register "RG_RIMP_VREF_SEL" settings)
+ * @param p Pointer of context created by DramcCtxCreate.
+ * @param term_option (U8): pass term_option (odt_on/off) for LP4X
+ * @param u1ImpCalStage (U8): During DRVP, DRVN, run-time/tracking stages
+ * some vref_sel values are different
+ */
+//-------------------------------------------------------------------------
+/* Definitions to make IMPCAL_VREF_SEL function more readable */
+#define IMPCAL_STAGE_DRVP 1
+#define IMPCAL_STAGE_DRVN 2
+#define IMPCAL_STAGE_TRACKING 3
+
+/* LP3 IMP_VREF_SEL ============================== */
+#define IMP_LP3_VREF_SEL 0x2b
+
+/* LP4 IMP_VREF_SEL ============================== */
+#define IMP_LP4_VREF_SEL 0x1b
+
+/* LP4X IMP_VREF_SEL ============================== */
+#define IMP_LP4X_TERM_VREF_SEL 0x1b
+
+/* LP4X IMP_VREF_SEL w/o term ==== */
+#if (ENABLE_DQ3200_UNTERM == 1)
+ #define IMP_DRVP_LP4X_UNTERM_VREF_SEL 0x3a
+ #define IMP_DRVN_LP4X_UNTERM_VREF_SEL 0x2a
+ #define IMP_TRACK_LP4X_UNTERM_VREF_SEL 0x3a
+#else
+ #define IMP_DRVP_LP4X_UNTERM_VREF_SEL 0x1a
+ #define IMP_DRVN_LP4X_UNTERM_VREF_SEL 0x16
+ #define IMP_TRACK_LP4X_UNTERM_VREF_SEL 0x1a
+#endif
+
+/* LP4P IMP_VREF_SEL ============================== */
+#define IMP_DRVP_LP4P_VREF_SEL 0x13
+#define IMP_DRVN_LP4P_VREF_SEL 0xf
+#define IMP_TRACK_LP4P_VREF_SEL 0x13
+
+/* Refer to "IMPCAL Settings" document register "RG_RIMP_VREF_SEL" settings */
+static void vImpCalVrefSel(DRAMC_CTX_T *p, U8 term_option, U8 u1ImpCalStage)
+{
+ U8 u1RegTmpValue = 0;
+
+ if (p->dram_type == TYPE_LPDDR4)
+ {
+ u1RegTmpValue = IMP_LP4_VREF_SEL;
+ }
+ else if (p->dram_type == TYPE_LPDDR4X)
+ {
+ if (term_option == 1) // w/i term
+ {
+ u1RegTmpValue = IMP_LP4X_TERM_VREF_SEL;
+ }
+ else // w/o term
+ {
+ if (u1ImpCalStage == IMPCAL_STAGE_DRVP) // OCDP
+ {
+ u1RegTmpValue = IMP_DRVP_LP4X_UNTERM_VREF_SEL;
+ }
+ else if (u1ImpCalStage == IMPCAL_STAGE_DRVN) // ODTN
+ {
+ u1RegTmpValue = IMP_DRVN_LP4X_UNTERM_VREF_SEL;
+ }
+ else // IMPCAL_STAGE_TRACKING (Tracking)
+ {
+ u1RegTmpValue = IMP_TRACK_LP4X_UNTERM_VREF_SEL;
+ }
+ }
+ }
+ else if (p->dram_type == TYPE_LPDDR4P)
+ {
+ if (u1ImpCalStage == IMPCAL_STAGE_DRVP) // OCDP
+ {
+ u1RegTmpValue = IMP_DRVP_LP4P_VREF_SEL;
+ }
+ else if (u1ImpCalStage == IMPCAL_STAGE_DRVN) // OCDN
+ {
+ u1RegTmpValue = IMP_DRVN_LP4P_VREF_SEL;
+ }
+ else // IMPCAL_STAGE_TRACKING (Tracking)
+ {
+ u1RegTmpValue = IMP_TRACK_LP4P_VREF_SEL;
+ }
+ }
+ else // TYPE_LPDDR3
+ {
+ u1RegTmpValue = IMP_LP3_VREF_SEL;
+ }
+
+ // dbg msg after vref_sel selection
+ mcSHOW_DBG_MSG3(("[vImpCalVrefSel] IMP_VREF_SEL 0x%x, IMPCAL stage:%u, term_option:%u\n",
+ u1RegTmpValue, u1ImpCalStage, term_option));
+
+ /* Set IMP_VREF_SEL register field's value */
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD11), u1RegTmpValue, SHU1_CA_CMD11_RG_RIMP_VREF_SEL); /*fra : fix single channel b */
+
+ return;
+}
+
+DRAM_STATUS_T DramcSwImpedanceCal(DRAMC_CTX_T *p, U8 u1Para, U8 term_option)
+{
+ U32 u4ImpxDrv, u4ImpCalResult;
+ U32 u4DRVP_Result =0xff,u4ODTN_Result =0xff, u4DRVN_Result =0xff;
+ U32 u4BaklReg_DRAMC_REG_IMPCAL;
+ U8 u1RegTmpValue;
+ U8 backup_channel;
+ U8 backup_broadcast;
+
+ backup_broadcast = GetDramcBroadcast();
+
+ DramcBroadcastOnOff(DRAMC_BROADCAST_OFF);
+
+ // Darren
+ vIO32WriteFldMulti_All(DDRPHY_MISC_SPM_CTRL1, P_Fld(0x0, MISC_SPM_CTRL1_RG_ARDMSUS_10) | P_Fld(0x0, MISC_SPM_CTRL1_RG_ARDMSUS_10_B0)
+ | P_Fld(0x0, MISC_SPM_CTRL1_RG_ARDMSUS_10_B1) | P_Fld(0x0, MISC_SPM_CTRL1_RG_ARDMSUS_10_CA));
+
+ vIO32WriteFldAlign_All(DDRPHY_MISC_SPM_CTRL2, 0x0, MISC_SPM_CTRL2_PHY_SPM_CTL2);
+ vIO32WriteFldAlign_All(DDRPHY_MISC_SPM_CTRL0, 0x0, MISC_SPM_CTRL0_PHY_SPM_CTL0);
+
+ //Disable IMP HW Tracking
+ //Hw Imp tracking disable for all channels Because SwImpCal will be K again when resume from DDR reserved mode
+ vIO32WriteFldAlign_All(DRAMC_REG_IMPCAL, 0, IMPCAL_IMPCAL_HW);
+
+ backup_channel = p->channel;
+
+#if (fcFOR_PINMUX == fcLaurel)
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vSetPHY2ChannelMapping(p, CHANNEL_B);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL0), 0x1, MISC_CTRL0_IMPCAL_CHAB_EN);//switch to CHB
+ }
+ else //LP3
+ {
+ vSetPHY2ChannelMapping(p, CHANNEL_A);
+ }
+#endif
+
+ //Register backup
+ //u4BaklReg_DDRPHY_MISC_IMP_CTRL0 = u4IO32Read4B((DDRPHY_MISC_IMP_CTRL0));
+ //u4BaklReg_DDRPHY_MISC_IMP_CTRL1 = u4IO32Read4B((DDRPHY_MISC_IMP_CTRL1));
+ u4BaklReg_DRAMC_REG_IMPCAL = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL));
+
+ /* Set IMP_VREF_SEL value for DRVP */
+ vImpCalVrefSel(p, term_option, IMPCAL_STAGE_DRVP);
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ //RG_IMPCAL_VREF_SEL (now set in vImpCalVrefSel())
+ //RG_IMPCAL_LP3_EN=0, RG_IMPCAL_LP4_EN=1
+#if 0
+ vIO32WriteFldMulti( (DDRPHY_MISC_IMP_CTRL1), P_Fld(1, MISC_IMP_CTRL1_RG_RIMP_BIAS_EN) | \
+ P_Fld(0, MISC_IMP_CTRL1_RG_RIMP_PRE_EN) | P_Fld(1, MISC_IMP_CTRL1_RG_RIMP_VREF_EN));
+#else
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1), P_Fld(0, MISC_IMP_CTRL1_RG_RIMP_PRE_EN));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), P_Fld(0, IMPCAL_IMPCAL_CALI_ENN) | P_Fld(1, IMPCAL_IMPCAL_IMPPDP) | \
+ P_Fld(1, IMPCAL_IMPCAL_IMPPDN)); //RG_RIMP_BIAS_EN and RG_RIMP_VREF_EN move to IMPPDP and IMPPDN
+#endif
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0), P_Fld(1, MISC_IMP_CTRL0_RG_IMP_EN) | \
+ P_Fld(0, MISC_IMP_CTRL0_RG_RIMP_DDR3_SEL) | P_Fld(1, MISC_IMP_CTRL0_RG_RIMP_DDR4_SEL));
+ }
+#if ENABLE_LP3_SW
+ else //LPDDR3
+ {
+ //RG_IMPCAL_VREF_SEL (now set in vImpCalVrefSel())
+ //RG_IMPCAL_LP3_EN=0, RG_IMPCAL_LP4_EN=1
+ //RG_IMPCAL_ODT_EN=0
+#if 0
+ vIO32WriteFldMulti((DDRPHY_MISC_IMP_CTRL1), P_Fld(0, MISC_IMP_CTRL1_RG_RIMP_ODT_EN)| P_Fld(1, MISC_IMP_CTRL1_RG_RIMP_BIAS_EN) | \
+ P_Fld(0, MISC_IMP_CTRL1_RG_RIMP_PRE_EN) | P_Fld(1, MISC_IMP_CTRL1_RG_RIMP_VREF_EN));
+#else
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1), P_Fld(0, MISC_IMP_CTRL1_RG_RIMP_PRE_EN));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), P_Fld(0, IMPCAL_IMPCAL_CALI_ENN) | P_Fld(1, IMPCAL_IMPCAL_IMPPDP) | \
+ P_Fld(1, IMPCAL_IMPCAL_IMPPDN)); //RG_RIMP_BIAS_EN and RG_RIMP_VREF_EN move to IMPPDP and IMPPDN, ODT_EN move to CALI_ENN
+#endif
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0), P_Fld(1, MISC_IMP_CTRL0_RG_IMP_EN) | \
+ P_Fld(1, MISC_IMP_CTRL0_RG_RIMP_DDR3_SEL) | P_Fld(0, MISC_IMP_CTRL0_RG_RIMP_DDR4_SEL));
+
+ #ifdef ETT_PRINT_FORMAT
+ mcSHOW_DBG_MSG2(("0x%X=0x%X\n", DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1), u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1))));
+ mcSHOW_DBG_MSG2(("0x%X=0x%X\n", DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0), u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0))));
+ #else
+ mcSHOW_DBG_MSG2(("0x%8x=0x%8x\n", DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1), u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1))));
+ mcSHOW_DBG_MSG2(("0x%8x=0x%8x\n", DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0), u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0))));
+ #endif
+ }
+#endif
+ mcDELAY_US(1);
+
+ // K pull up
+ mcSHOW_DBG_MSG2(("\n\tK DRVP\n"));
+ mcFPRINTF((fp_A60501, "\n\tK DRVP\n"));
+ //PUCMP_EN=1
+ //ODT_EN=0
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), 1, IMPCAL_IMPCAL_CALI_EN);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), 1, IMPCAL_IMPCAL_CALI_ENP); //PUCMP_EN move to CALI_ENP
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), 0, IMPCAL_IMPCAL_CALI_ENN); //ODT_EN move to CALI_ENN
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU_IMPCAL1), P_Fld(0, SHU_IMPCAL1_IMPDRVN)|P_Fld(0, SHU_IMPCAL1_IMPDRVP));
+
+ //DRVP=0
+ //DRV05=1
+#if (fcFOR_CHIP_ID == fcLaurel)
+ if(p->dram_type == TYPE_LPDDR4)
+ {
+ u1RegTmpValue = 1;//LP4P_EN=0, DRV05=1
+ }
+ else //TYPE_LPDDR4X || TYPE_LPDDR4P
+ {
+ u1RegTmpValue = 0;//LP4P_EN=1, DRV05=1
+ }
+#endif
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD11), u1RegTmpValue, SHU1_CA_CMD11_RG_RIMP_REV); /* fra : fix single channel b */
+
+ //OCDP Flow
+ //If RGS_TX_OCD_IMPCALOUTX=0
+ //RG_IMPX_DRVP++;
+ //Else save and keep RG_IMPX_DRVP value, and assign to DRVP
+ for(u4ImpxDrv=0; u4ImpxDrv<32; u4ImpxDrv++)
+ {
+ if(u4ImpxDrv==16) //0~15, 29~31
+ u4ImpxDrv = 29;
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_IMPCAL1), u4ImpxDrv, SHU_IMPCAL1_IMPDRVP);
+ mcDELAY_US(1);
+ u4ImpCalResult = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_PHY_RGS_CMD), MISC_PHY_RGS_CMD_RGS_RIMPCALOUT);
+ mcSHOW_DBG_MSG2(("1. OCD DRVP=%d CALOUT=%d\n", u4ImpxDrv, u4ImpCalResult));
+ mcFPRINTF((fp_A60501, "1. OCD DRVP=%d CALOUT=%d\n", u4ImpxDrv, u4ImpCalResult));
+
+ if((u4ImpCalResult ==1) && (u4DRVP_Result == 0xff))//first found
+ {
+ u4DRVP_Result = u4ImpxDrv;
+ mcSHOW_DBG_MSG2(("\n1. OCD DRVP calibration OK! DRVP=%d\n\n", u4DRVP_Result));
+ mcFPRINTF((fp_A60501, "\n1. OCD DRVP calibration OK! DRVP=%d\n\n", u4DRVP_Result));
+ break;
+ }
+ }
+
+ //LP4: ODTN calibration, LP3: DRVN calibration
+ mcSHOW_DBG_MSG2(("\n\n\tK ODTN\n"));
+ mcFPRINTF((fp_A60501, "\n\tK ODTN\n"));
+
+
+ /* Set IMP_VREF_SEL value for DRVN */
+ vImpCalVrefSel(p, term_option, IMPCAL_STAGE_DRVN);
+
+ //PUCMP_EN=0
+ //LPDDR4 : ODT_EN=1
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), 0, IMPCAL_IMPCAL_CALI_ENP); //PUCMP_EN move to CALI_ENP
+
+ if(p->dram_type == TYPE_LPDDR4 || p->dram_type == TYPE_LPDDR4X)
+ {
+ if (term_option == 1)
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), 1, IMPCAL_IMPCAL_CALI_ENN); //ODT_EN move to CALI_ENN
+ }
+ }
+
+ //DRVP=DRVP_FINAL
+ //DRVN=0
+ //DRV05=1
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU_IMPCAL1), P_Fld(u4DRVP_Result, SHU_IMPCAL1_IMPDRVP) | P_Fld(0, SHU_IMPCAL1_IMPDRVN));
+
+#if (fcFOR_CHIP_ID == fcLaurel)
+ if(p->dram_type == TYPE_LPDDR4)
+ {
+ u1RegTmpValue = 1;//LP4P_EN=0, DRV05=1
+ }
+ else //TYPE_LPDDR4X || TYPE_LPDDR4P
+ {
+ u1RegTmpValue = 3;//LP4P_EN=1, DRV05=3
+ }
+#endif
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD11), u1RegTmpValue, SHU1_CA_CMD11_RG_RIMP_REV); /*Fra : A, B write same value to avoid dram init A broadcast to B when single CHB */
+
+
+
+ //If RGS_TX_OCD_IMPCALOUTX=1
+ //RG_IMPX_DRVN++;
+ //Else save RG_IMPX_DRVN value and assign to DRVN
+ for(u4ImpxDrv=0; u4ImpxDrv<32 ; u4ImpxDrv++)
+ {
+ if(u4ImpxDrv==16) //0~15, 29~31
+ u4ImpxDrv = 29;
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_IMPCAL1), u4ImpxDrv, SHU_IMPCAL1_IMPDRVN);
+ mcDELAY_US(1);
+ u4ImpCalResult = u4IO32ReadFldAlign((DDRPHY_MISC_PHY_RGS_CMD), MISC_PHY_RGS_CMD_RGS_RIMPCALOUT);
+ mcSHOW_DBG_MSG2(("3. OCD ODTN=%d ,CALOUT=%d\n", u4ImpxDrv, u4ImpCalResult));
+ mcFPRINTF((fp_A60501, "3. OCD ODTN=%d ,CALOUT=%d\n", u4ImpxDrv, u4ImpCalResult));
+
+ if((u4ImpCalResult ==0) &&(u4ODTN_Result == 0xff))//first found
+ {
+ u4ODTN_Result = u4ImpxDrv;
+ mcSHOW_DBG_MSG2(("\n3. OCD ODTN calibration OK! ODTN=%d\n\n", u4ODTN_Result));
+ mcFPRINTF((fp_A60501, "\n3. OCD ODTN calibration OK! ODTN=%d\n\n", u4ODTN_Result));
+ break;
+ }
+ }
+
+ //Register Restore
+ vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), u4BaklReg_DRAMC_REG_IMPCAL);
+ //vIO32Write4B((DDRPHY_MISC_IMP_CTRL0), u4BaklReg_DDRPHY_MISC_IMP_CTRL0);
+ //vIO32Write4B((DDRPHY_MISC_IMP_CTRL1), u4BaklReg_DDRPHY_MISC_IMP_CTRL1);
+
+
+/*** default value if K fail
+ LP3: DRVP=8, DRVN=9
+ LP4: DRVP=6, DRVN=9, ODTN=14
+ LP4X(UT): DRVP=12, DRVN=9
+ LP4X(T): DRVP=5, DRVN=9, ODTN=14
+ LP4P: DRVP=8, DRVN=10
+***/
+ if(u1IsLP4Family(p->dram_type))
+ {
+#if (fcFOR_CHIP_ID == fcLaurel)
+ u4DRVN_Result = 9; //fixed value from DE YingMin Liao
+#endif
+
+ if(u4DRVP_Result==0xff)
+ {
+ mcFPRINTF((fp_A60501, "\n[CHIP_SCAN]1. OCD DRVP calibration FAIL! \n\n"));
+#if (fcFOR_CHIP_ID == fcLaurel)
+ u4DRVP_Result = 31;
+#endif
+ }
+ if(u4ODTN_Result==0xff || u4DRVP_Result==0xff)
+ {
+ mcFPRINTF((fp_A60501, "\n[CHIP_SCAN]3. OCD ODTN calibration FAIL! \n\n"));
+#if (fcFOR_CHIP_ID == fcLaurel)
+ u4ODTN_Result = 31;
+#endif
+ }
+
+ mcSHOW_DBG_MSG(("[SwImpedanceCal] DRVP=%d, DRVN=%d, ODTN=%d\n", u4DRVP_Result, u4DRVN_Result, u4ODTN_Result));
+ mcFPRINTF((fp_A60501, "[SwImpedanceCal] DRVP=%d, DRVN=%d, ODTN=%d\n", u4DRVP_Result, u4DRVN_Result, u4ODTN_Result));
+
+ #if 0//HYNIX_IMPX_ADJUST
+ if(u1Para)
+ {
+ u4ODTN_Result= ImpedanceAdjustment_Hynix(u4ODTN_Result, u1Para);
+ }
+ #endif
+
+ if((p->dram_type == TYPE_LPDDR4X || p->dram_type == TYPE_LPDDR4P) && (term_option ==0))
+ {
+ gDramcSwImpedanceResule[term_option][DRVP] = u4DRVP_Result;
+ gDramcSwImpedanceResule[term_option][DRVN] = u4ODTN_Result; //Justin : LP4X unterm DRVN is ODTN * 2
+ gDramcSwImpedanceResule[term_option][ODTP] = 0;
+ gDramcSwImpedanceResule[term_option][ODTN] = 15; //Justin : LP4X unterm, ODTN is useless
+ }
+ else
+ {
+ gDramcSwImpedanceResule[term_option][DRVP] = (u4DRVP_Result<=3) ? (u4DRVP_Result * 3) : u4DRVP_Result;
+ gDramcSwImpedanceResule[term_option][DRVN] = (u4DRVN_Result<=3) ? (u4DRVN_Result * 3) : u4DRVN_Result;
+ gDramcSwImpedanceResule[term_option][ODTP] = 0;
+ gDramcSwImpedanceResule[term_option][ODTN] = (u4ODTN_Result<=3) ? (u4ODTN_Result * 3) : u4ODTN_Result;
+ }
+ }
+#if ENABLE_LP3_SW
+ else //LPDDR3
+ {
+ u4DRVN_Result = u4ODTN_Result;
+ if(u4DRVN_Result==0xff || u4DRVP_Result==0xff)
+ {
+ u4DRVP_Result = 8;
+ u4DRVN_Result = 9;
+ }
+
+ gDramcSwImpedanceResule[term_option][DRVP] = (u4DRVP_Result<=3) ? (u4DRVP_Result * 3) : u4DRVP_Result;
+ gDramcSwImpedanceResule[term_option][DRVN] = (u4DRVN_Result<=3) ? (u4DRVN_Result * 3) : u4DRVN_Result;
+ gDramcSwImpedanceResule[term_option][ODTP] = 0;
+ gDramcSwImpedanceResule[term_option][ODTN] = (u4ODTN_Result<=3) ? (u4ODTN_Result * 3) : u4ODTN_Result;
+ }
+#endif
+
+ /* Set IMP_VREF_SEL value for TRACKING/RUN-TIME */
+ vImpCalVrefSel(p, term_option, IMPCAL_STAGE_TRACKING);
+
+#if RUNTIME_SHMOO_RELEATED_FUNCTION && SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ {
+ U8 u1drv;
+ {
+ for (u1drv=0; u1drv<4; u1drv++)
+ {
+ if(p->femmc_Ready==0)
+ p->pSavetimeData->u1SwImpedanceResule[term_option][u1drv] = gDramcSwImpedanceResule[term_option][u1drv];
+ else
+ gDramcSwImpedanceResule[term_option][u1drv] = p->pSavetimeData->u1SwImpedanceResule[term_option][u1drv];
+ }
+ }
+ }
+#endif
+ mcSHOW_DBG_MSG(("term_option=%d, Reg: DRVP=%d, DRVN=%d, ODTN=%d\n", term_option, gDramcSwImpedanceResule[term_option][DRVP],
+ gDramcSwImpedanceResule[term_option][DRVN], gDramcSwImpedanceResule[term_option][ODTN]));
+
+#if APPLY_SIGNAL_WAVEFORM_SETTINGS_ADJUST
+ if((p->dram_type == TYPE_LPDDR4X || p->dram_type == TYPE_LPDDR4P) && (term_option ==0))
+ {
+ gDramcSwImpedanceResule[term_option][DRVP] = SwImpedanceAdjust(gDramcSwImpedanceResule[term_option][DRVP], gDramcSwImpedanceAdjust[term_option][DRVP]);
+ gDramcSwImpedanceResule[term_option][DRVN] = SwImpedanceAdjust(gDramcSwImpedanceResule[term_option][DRVN], gDramcSwImpedanceAdjust[term_option][ODTN]);
+ }
+ else
+ {
+ gDramcSwImpedanceResule[term_option][DRVP] = SwImpedanceAdjust(gDramcSwImpedanceResule[term_option][DRVP], gDramcSwImpedanceAdjust[term_option][DRVP]);
+ gDramcSwImpedanceResule[term_option][ODTN] = SwImpedanceAdjust(gDramcSwImpedanceResule[term_option][ODTN], gDramcSwImpedanceAdjust[term_option][ODTN]);
+ }
+
+ mcSHOW_DBG_MSG(("term_option=%d, Reg: DRVP=%d, DRVN=%d, ODTN=%d (After Adjust)\n", term_option, gDramcSwImpedanceResule[term_option][DRVP],
+ gDramcSwImpedanceResule[term_option][DRVN], gDramcSwImpedanceResule[term_option][ODTN]));
+#endif
+
+#if SIMULATION_SW_IMPED && ENABLE_LP3_SW
+ //LP3 updates impedance parameters to shuffle "SaveRegister" here, un-term only
+ if(p->dram_type == TYPE_LPDDR3)
+ DramcSwImpedanceSaveRegister(p, term_option, term_option, DRAM_DFS_SHUFFLE_1);
+#endif
+
+
+#if defined(SLT)
+ if (gDramcSwImpedanceResule[term_option][DRVP] >= 31 && (term_option ==1) ) {
+ mcSHOW_DBG_MSG(("SLT_BIN2\n"));
+ while(1);
+ }
+#endif
+
+
+ vSetCalibrationResult(p, DRAM_CALIBRATION_SW_IMPEDANCE, DRAM_OK);
+ mcSHOW_DBG_MSG3(("[DramcSwImpedanceCal] Done\n\n"));
+ mcFPRINTF((fp_A60501, "[DramcSwImpedanceCal] Done\n\n"));
+
+ vSetPHY2ChannelMapping(p, backup_channel);
+ DramcBroadcastOnOff(backup_broadcast);
+
+ return DRAM_OK;
+}
+#endif //SIMULATION_SW_IMPED
+
+void DramcUpdateImpedanceTerm2UnTerm(DRAMC_CTX_T *p)
+{
+ gDramcSwImpedanceResule[ODT_OFF][ODTP] = gDramcSwImpedanceResule[ODT_ON][ODTP];
+ gDramcSwImpedanceResule[ODT_OFF][ODTN] = gDramcSwImpedanceResule[ODT_ON][ODTN];
+}
+
+#ifdef ENABLE_HW_IMPCAL
+DRAM_STATUS_T DramcHwImpedanceCal(DRAMC_CTX_T *p, U8 u1Para, U8 term_option)
+{
+ U32 u4ImpxDrv, u4ImpCalResult;
+ U32 u4DRVP_Result =0xff,u4ODTN_Result =0xff, u4DRVN_Result =0xff;
+ U32 u4BaklReg_DDRPHY_MISC_IMP_CTRL0, u4BaklReg_DDRPHY_MISC_IMP_CTRL1, u4BaklReg_DRAMC_REG_IMPCAL;
+ U32 u4BaklReg_DRAMC_REG_REFCTRL0;
+ U8 u1ByteIdx, u1RegTmpValue;
+ U8 backup_channel;
+ U8 backup_broadcast;
+
+ backup_broadcast = GetDramcBroadcast();
+
+ DramcBroadcastOnOff(DRAMC_BROADCAST_OFF);
+
+ // Darren
+ vIO32WriteFldMulti_All(DDRPHY_MISC_SPM_CTRL1, P_Fld(0x0, MISC_SPM_CTRL1_RG_ARDMSUS_10) | P_Fld(0x0, MISC_SPM_CTRL1_RG_ARDMSUS_10_B0)
+ | P_Fld(0x0, MISC_SPM_CTRL1_RG_ARDMSUS_10_B1) | P_Fld(0x0, MISC_SPM_CTRL1_RG_ARDMSUS_10_CA));
+
+ vIO32WriteFldAlign_All(DDRPHY_MISC_SPM_CTRL2, 0x0, MISC_SPM_CTRL2_PHY_SPM_CTL2);
+ vIO32WriteFldAlign_All(DDRPHY_MISC_SPM_CTRL0, 0x0, MISC_SPM_CTRL0_PHY_SPM_CTL0);
+
+ //Disable IMP HW Tracking
+ vIO32WriteFldAlign_All(DRAMC_REG_IMPCAL, 0, IMPCAL_IMPCAL_HW);
+
+ backup_channel = p->channel;
+ vSetPHY2ChannelMapping(p, CHANNEL_A);
+
+ //Register backup
+ //u4BaklReg_DDRPHY_MISC_IMP_CTRL0 = u4IO32Read4B((DDRPHY_MISC_IMP_CTRL0));
+ //u4BaklReg_DDRPHY_MISC_IMP_CTRL1 = u4IO32Read4B((DDRPHY_MISC_IMP_CTRL1));
+ u4BaklReg_DRAMC_REG_IMPCAL = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL));
+ u4BaklReg_DRAMC_REG_REFCTRL0 = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0));
+
+ //enable autorefresh
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0), 0, REFCTRL0_REFDIS); //REFDIS=0, enable autorefresh
+
+ //Basic setup
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA2), 0x7, SHU_SELPH_CA2_TXDLY_CMD);
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1), 0, MISC_IMP_CTRL1_RG_RIMP_PRE_EN);
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), P_Fld(0, IMPCAL_IMPCAL_IMPPDP) |
+ P_Fld(0, IMPCAL_IMPCAL_IMPPDN) |
+ P_Fld(0, IMPCAL_IMPCAL_CALI_ENP) |
+ P_Fld(0, IMPCAL_IMPCAL_CALI_ENN) |
+ P_Fld(0, IMPCAL_IMPCAL_CALI_EN) |
+ //P_Fld(0, IMPCAL_IMPCAL_DRVUPOPT) | // for Cannon project
+ P_Fld(1, IMPCAL_IMPCAL_NEW_OLD_SL) | //Impedance tracking form, 0: old, 1:new.
+ P_Fld(1, IMPCAL_IMPCAL_SWVALUE_EN)); //Impedance tracking DRVP, DRVN initial value from SW setting
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU_IMPCAL1), P_Fld(0, SHU_IMPCAL1_IMPDRVP) | //Set SW calibration value & HW initial calibration value for OCDP
+ P_Fld(3, SHU_IMPCAL1_IMPCALCNT) | //hw impcal interval (unit: the number of refresh)
+ P_Fld(7, SHU_IMPCAL1_IMPCAL_CHKCYCLE)); //hw impcal calibration to check CMPOOUT
+
+ /* Set IMP_VREF_SEL value for DRVP */
+ vImpCalVrefSel(p, term_option, IMPCAL_STAGE_DRVP);
+
+#if (fcFOR_CHIP_ID == fcLaurel)
+ if(p->dram_type == TYPE_LPDDR4)
+ {
+ u1RegTmpValue = 1;//LP4P_EN=0, DRV05=1
+ }
+ else //TYPE_LPDDR4X || TYPE_LPDDR4P
+ {
+ u1RegTmpValue = 0;//LP4P_EN=1, DRV05=1
+ }
+#endif
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD11), u1RegTmpValue, SHU1_CA_CMD11_RG_RIMP_REV);
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0), P_Fld(0, MISC_IMP_CTRL0_RG_IMP_EN) | \
+ P_Fld(0, MISC_IMP_CTRL0_RG_RIMP_DDR3_SEL) | \
+ P_Fld(1, MISC_IMP_CTRL0_RG_RIMP_DDR4_SEL));
+ }
+#if ENABLE_LP3_SW
+ else //LPDDR3
+ {
+ //enable auto refresh process for LP3
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0), 1, REFCTRL0_REFDIS);
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 1, DRAMC_PD_CTRL_DCMREF_OPT);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL), 1, CKECTRL_CKEFIXON);
+ //mcDELAY_US(1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CKECTRL), 0, CKECTRL_CKEFIXON);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0), 1, REFCTRL0_REFFRERUN);
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_ACTIM3), 0x70, SHU_ACTIM3_REFCNT);
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0), 0, REFCTRL0_REFDIS);
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_IMPCAL1), 0x1F, SHU_IMPCAL1_IMPDRVN);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1_DRVING2), 1, SHU1_DRVING2_DIS_IMPCAL_ODT_EN);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU1_DRVING1), 0x1, SHU1_DRVING1_DIS_IMP_ODTN_TRACK);
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0), P_Fld(0, MISC_IMP_CTRL0_RG_IMP_EN) | \
+ P_Fld(1, MISC_IMP_CTRL0_RG_RIMP_DDR3_SEL) | \
+ P_Fld(0, MISC_IMP_CTRL0_RG_RIMP_DDR4_SEL));
+
+ #ifdef ETT_PRINT_FORMAT
+ mcSHOW_DBG_MSG2(("0x%X=0x%X\n", DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1), u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1))));
+ mcSHOW_DBG_MSG2(("0x%X=0x%X\n", DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0), u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0))));
+ #else
+ mcSHOW_DBG_MSG2(("0x%8x=0x%8x\n", DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1), u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL1))));
+ mcSHOW_DBG_MSG2(("0x%8x=0x%8x\n", DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0), u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_IMP_CTRL0))));
+ #endif
+ }
+#endif
+
+ //Enable HW Imp tracking for calibration (SW impcal switch, 0: SW. 1:HW.)
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), 1, IMPCAL_IMPCAL_HW);
+#if ENABLE_LP3_SW
+ if(p->dram_type == TYPE_LPDDR3)
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), 1, IMPCAL_IMPCAL_EN); //lp3 needed
+ }
+#endif
+
+ {
+ U8 DQ_DRVP,DQ_ODTN;
+ int u1Dly_cnt = 0;
+
+ while (2000>(u1Dly_cnt++))
+ {
+ if(u1IsLP4Family(p->dram_type))
+ {
+ DQ_DRVP = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL_STATUS2), IMPCAL_STATUS2_DRVPDQ_SAVE1);
+ DQ_ODTN = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL_STATUS2), IMPCAL_STATUS2_DRVNDQ_SAVE1);
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ DQ_DRVP = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CMDDRV_STATUS), CMDDRV_STATUS_DRVPDQ_1);
+ DQ_ODTN = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CMDDRV_STATUS), CMDDRV_STATUS_DRVNDQ_1);
+ }
+#endif
+ if (DQ_DRVP!=0 && DQ_ODTN!=0)
+ {
+ u4DRVP_Result = DQ_DRVP;
+ u4ODTN_Result = DQ_ODTN;
+ break;
+ }
+ mcDELAY_US(1);
+ }
+ }
+
+ //Register Restore
+ vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_IMPCAL), u4BaklReg_DRAMC_REG_IMPCAL);
+ vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0), u4BaklReg_DRAMC_REG_REFCTRL0);
+
+
+/*** default value if K fail
+ LP3: DRVP=8, DRVN=9
+ LP4: DRVP=6, DRVN=9, ODTN=14
+ LP4X(UT): DRVP=12, DRVN=9
+ LP4X(T): DRVP=5, DRVN=9, ODTN=14
+ LP4P: DRVP=8, DRVN=10
+***/
+ if(u1IsLP4Family(p->dram_type))
+ {
+#if (fcFOR_CHIP_ID == fcLaurel)
+ u4DRVN_Result = 9; //fixed value from DE YingMin Liao
+#endif
+
+ if(u4DRVP_Result==0xff)
+ {
+ mcFPRINTF((fp_A60501, "\n[CHIP_SCAN]1. OCD DRVP calibration FAIL! \n\n"));
+#if (fcFOR_CHIP_ID == fcLaurel)
+ u4DRVP_Result = 31;
+#endif
+ }
+ if(u4ODTN_Result==0xff || u4DRVP_Result==0xff)
+ {
+ mcFPRINTF((fp_A60501, "\n[CHIP_SCAN]3. OCD ODTN calibration FAIL! \n\n"));
+#if (fcFOR_CHIP_ID == fcLaurel)
+ u4ODTN_Result = 31;
+#endif
+ }
+
+ mcSHOW_DBG_MSG(("[HwImpedanceCal] DRVP=%d, DRVN=%d, ODTN=%d\n", u4DRVP_Result, u4DRVN_Result, u4ODTN_Result));
+ mcFPRINTF((fp_A60501, "[HwImpedanceCal] DRVP=%d, DRVN=%d, ODTN=%d\n", u4DRVP_Result, u4DRVN_Result, u4ODTN_Result));
+
+ #if 0//HYNIX_IMPX_ADJUST
+ if(u1Para)
+ {
+ u4ODTN_Result= ImpedanceAdjustment_Hynix(u4ODTN_Result, u1Para);
+ }
+ #endif
+
+ if((p->dram_type == TYPE_LPDDR4X || p->dram_type == TYPE_LPDDR4P) && (term_option ==0))
+ {
+ gDramcSwImpedanceResule[term_option][DRVP] = u4DRVP_Result;
+ gDramcSwImpedanceResule[term_option][DRVN] = u4ODTN_Result; //Justin : LP4X unterm DRVN is ODTN * 2
+ gDramcSwImpedanceResule[term_option][ODTP] = 0;
+ gDramcSwImpedanceResule[term_option][ODTN] = 15; //Justin : LP4X unterm, ODTN is useless
+ }
+ else
+ {
+ gDramcSwImpedanceResule[term_option][DRVP] = (u4DRVP_Result<=3) ? (u4DRVP_Result * 3) : u4DRVP_Result;
+ gDramcSwImpedanceResule[term_option][DRVN] = (u4DRVN_Result<=3) ? (u4DRVN_Result * 3) : u4DRVN_Result;
+ gDramcSwImpedanceResule[term_option][ODTP] = 0;
+ gDramcSwImpedanceResule[term_option][ODTN] = (u4ODTN_Result<=3) ? (u4ODTN_Result * 3) : u4ODTN_Result;
+ }
+ }
+#if ENABLE_LP3_SW
+ else //LPDDR3
+ {
+ u4DRVN_Result = u4ODTN_Result;
+ if(u4DRVN_Result==0xff || u4DRVP_Result==0xff)
+ {
+ u4DRVP_Result = 8;
+ u4DRVN_Result = 9;
+ }
+
+ gDramcSwImpedanceResule[term_option][DRVP] = (u4DRVP_Result<=3) ? (u4DRVP_Result * 3) : u4DRVP_Result;
+ gDramcSwImpedanceResule[term_option][DRVN] = (u4DRVN_Result<=3) ? (u4DRVN_Result * 3) : u4DRVN_Result;
+ gDramcSwImpedanceResule[term_option][ODTP] = 0;
+ gDramcSwImpedanceResule[term_option][ODTN] = (u4ODTN_Result<=3) ? (u4ODTN_Result * 3) : u4ODTN_Result;
+ }
+#endif
+
+ /* Set IMP_VREF_SEL value for TRACKING/RUN-TIME */
+ vImpCalVrefSel(p, term_option, IMPCAL_STAGE_TRACKING);
+
+#if RUNTIME_SHMOO_RELEATED_FUNCTION && SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ {
+ U8 u1drv;
+ {
+ for (u1drv=0; u1drv<4; u1drv++)
+ {
+ if(p->femmc_Ready==0)
+ p->pSavetimeData->u1SwImpedanceResule[term_option][u1drv] = gDramcSwImpedanceResule[term_option][u1drv];
+ else
+ gDramcSwImpedanceResule[term_option][u1drv] = p->pSavetimeData->u1SwImpedanceResule[term_option][u1drv];
+ }
+ }
+ }
+#endif
+ mcSHOW_DBG_MSG(("term_option=%d, Reg: DRVP=%d, DRVN=%d, ODTN=%d\n", term_option, gDramcSwImpedanceResule[term_option][0],
+ gDramcSwImpedanceResule[term_option][1], gDramcSwImpedanceResule[term_option][ODTN]));
+
+#if APPLY_SIGNAL_WAVEFORM_SETTINGS_ADJUST
+ if((p->dram_type == TYPE_LPDDR4X || p->dram_type == TYPE_LPDDR4P) && (term_option ==0))
+ {
+ gDramcSwImpedanceResule[term_option][DRVP] = SwImpedanceAdjust(gDramcSwImpedanceResule[term_option][DRVP], gDramcSwImpedanceAdjust[term_option][DRVP]);
+ gDramcSwImpedanceResule[term_option][DRVN] = SwImpedanceAdjust(gDramcSwImpedanceResule[term_option][DRVN], gDramcSwImpedanceAdjust[term_option][ODTN]);
+ }
+ else
+ {
+ gDramcSwImpedanceResule[term_option][DRVP] = SwImpedanceAdjust(gDramcSwImpedanceResule[term_option][DRVP], gDramcSwImpedanceAdjust[term_option][DRVP]);
+ gDramcSwImpedanceResule[term_option][ODTN] = SwImpedanceAdjust(gDramcSwImpedanceResule[term_option][ODTN], gDramcSwImpedanceAdjust[term_option][ODTN]);
+ }
+
+ mcSHOW_DBG_MSG(("term_option=%d, Reg: DRVP=%d, DRVN=%d, ODTN=%d (After Adjust)\n", term_option, gDramcSwImpedanceResule[term_option][DRVP],
+ gDramcSwImpedanceResule[term_option][DRVN], gDramcSwImpedanceResule[term_option][ODTN]));
+#endif
+
+#if SIMULATION_SW_IMPED && ENABLE_LP3_SW
+ //LP3 updates impedance parameters to shuffle "SaveRegister" here, un-term only
+ if(p->dram_type == TYPE_LPDDR3)
+ DramcSwImpedanceSaveRegister(p, term_option, term_option, DRAM_DFS_SHUFFLE_1);
+#endif
+
+
+#if defined(SLT)
+ if (gDramcSwImpedanceResule[term_option][DRVP] >= 31 && (term_option ==1) ) {
+ mcSHOW_DBG_MSG(("SLT_BIN2\n"));
+ while(1);
+ }
+#endif
+
+ vSetCalibrationResult(p, DRAM_CALIBRATION_SW_IMPEDANCE, DRAM_OK);
+ mcSHOW_DBG_MSG3(("[DramcSwImpedanceCal] Done\n\n"));
+ mcFPRINTF((fp_A60501, "[DramcSwImpedanceCal] Done\n\n"));
+
+ vSetPHY2ChannelMapping(p, backup_channel);
+ DramcBroadcastOnOff(backup_broadcast);
+
+ return DRAM_OK;
+}
+#endif
+
+#if 0
+void Dram_Reset(DRAMC_CTX_T *p)
+{
+ // This function is implemented based on DE's bring up flow for DRAMC
+ #if !SW_CHANGE_FOR_SIMULATION
+ if(p->dram_type == TYPE_LPDDR3)
+ DramcModeRegInit_LP3(p);
+ else
+ DramcModeRegInit_LP4(p);
+ #endif
+
+ ///TODO: update MR2(WL& RL) from AC timing table
+}
+#endif
+
+
+void O1PathOnOff(DRAMC_CTX_T *p, U8 u1OnOff)
+{
+ U8 u1FixDQIEN = 0;
+
+ if (u1IsLP4Family(p->dram_type))
+ {
+ u1FixDQIEN = (u1OnOff == ENABLE) ? 3 : 0;
+ vIO32WriteFldAlign_All(DRAMC_REG_PADCTRL, u1FixDQIEN, PADCTRL_FIXDQIEN);
+
+ vIO32WriteFldAlign_All(DDRPHY_B0_DQ5, u1OnOff, B0_DQ5_RG_RX_ARDQ_EYE_VREF_EN_B0);
+ vIO32WriteFldAlign_All(DDRPHY_B1_DQ5, u1OnOff, B1_DQ5_RG_RX_ARDQ_EYE_VREF_EN_B1);
+ vIO32WriteFldAlign_All(DDRPHY_B0_DQ3, u1OnOff, B0_DQ3_RG_RX_ARDQ_SMT_EN_B0);
+ vIO32WriteFldAlign_All(DDRPHY_B1_DQ3, u1OnOff, B1_DQ3_RG_RX_ARDQ_SMT_EN_B1);
+ }
+ #if ENABLE_LP3_SW
+ else
+ {
+ u1FixDQIEN = (u1OnOff == ENABLE) ? 15 : 0;
+ vIO32WriteFldAlign_All(DRAMC_REG_PADCTRL, u1FixDQIEN, PADCTRL_FIXDQIEN);
+
+ vIO32WriteFldAlign(DDRPHY_B1_DQ5, u1OnOff, B1_DQ5_RG_RX_ARDQ_EYE_VREF_EN_B1); //CHA B1
+ vIO32WriteFldAlign(DDRPHY_B0_DQ5 + SHIFT_TO_CHB_ADDR, u1OnOff, B0_DQ5_RG_RX_ARDQ_EYE_VREF_EN_B0); //CHB B0
+ vIO32WriteFldAlign(DDRPHY_CA_CMD5 + SHIFT_TO_CHB_ADDR, u1OnOff, CA_CMD5_RG_RX_ARCMD_EYE_VREF_EN); //CHB CA
+ vIO32WriteFldAlign(DDRPHY_B1_DQ5 + SHIFT_TO_CHB_ADDR, u1OnOff, B1_DQ5_RG_RX_ARDQ_EYE_VREF_EN_B1); //CHB B1
+
+ vIO32WriteFldAlign(DDRPHY_B1_DQ3, u1OnOff, B1_DQ3_RG_RX_ARDQ_SMT_EN_B1); //CHA B1
+ vIO32WriteFldAlign(DDRPHY_B0_DQ3 + SHIFT_TO_CHB_ADDR, u1OnOff, B0_DQ3_RG_RX_ARDQ_SMT_EN_B0); //CHB B0
+ vIO32WriteFldAlign(DDRPHY_CA_CMD3 + SHIFT_TO_CHB_ADDR, u1OnOff, CA_CMD3_RG_RX_ARCMD_SMT_EN); //CHB CA
+ vIO32WriteFldAlign(DDRPHY_B1_DQ3 + SHIFT_TO_CHB_ADDR, u1OnOff, B1_DQ3_RG_RX_ARDQ_SMT_EN_B1); //CHB B1
+ }
+ #endif
+ mcDELAY_US(1);
+}
+
+void CATrainingPosCal(DRAMC_CTX_T *p, U8* pu1LP3DieNum, S8* ps1CAMacroDelay, S8 *ps1CACenterDiff)
+{
+ U8 u1RankIdx, u1DieIdx, u1CAIdx, u1MacroIdx, u1MacroNum;
+ S8 s1Intersect_min_byMacro[2], s1Intersect_max_byMacro[2];
+ S8 s1Intersect_min_byBit[CATRAINING_NUM], s1Intersect_max_byBit[CATRAINING_NUM], s1CACenter_min[2];//, s1CACenter[CATRAINING_NUM];
+ S8 s1TempFirstPass, s1TempLastPass;
+ U8 u1PerBitDelayCellEnable =0, u1CABitNum=0;
+ S8 s1CACenter[CATRAINING_NUM];
+
+ if (!u1IsLP4Family(p->dram_type))
+ {
+#if LP3_CA_PER_BIT
+ u1PerBitDelayCellEnable =1;
+#endif
+ u1CABitNum = 10;
+ }
+
+ if (u1IsLP4Family(p->dram_type))
+ {
+#if CA_PER_BIT_DELAY_CELL
+ u1PerBitDelayCellEnable =1;
+#endif
+ u1CABitNum =6;
+ }
+
+ mcSHOW_DBG_MSG(("\n[CATrainingPosCal] consider %d rank data\n", p->rank +1));
+
+ for(u1MacroIdx =0; u1MacroIdx <2; u1MacroIdx++)
+ {
+ s1Intersect_min_byMacro[u1MacroIdx] = -127; // 127
+ s1Intersect_max_byMacro[u1MacroIdx] = 127; //-127
+ s1CACenter_min[u1MacroIdx] = 0x7f;
+ }
+
+ for(u1CAIdx=0; u1CAIdx < u1CABitNum; u1CAIdx++)
+ {
+ s1Intersect_min_byBit[u1CAIdx] = -127; // 127
+ s1Intersect_max_byBit[u1CAIdx] = 127; //-127
+
+ if (u1IsLP4Family(p->dram_type))
+ {
+ u1MacroIdx=0;
+ }
+ else //LP3
+ {
+ if(u1CAIdx==0 || u1CAIdx==1)
+ {
+ u1MacroIdx=0;
+ }
+ else
+ u1MacroIdx=1;
+ }
+
+ for(u1RankIdx=RANK_0; u1RankIdx<(p->rank+1); u1RankIdx++)
+ {
+ for(u1DieIdx=0; u1DieIdx< pu1LP3DieNum[u1RankIdx]; u1DieIdx++)
+ {
+ s1TempFirstPass = iFirstCAPass[u1RankIdx][u1DieIdx][u1CAIdx];
+ s1TempLastPass = iLastCAPass[u1RankIdx][u1DieIdx][u1CAIdx];
+ //mcSHOW_DBG_MSG(("RK%d, Die%d ,CA%d,iFirstCAPass = %d, iLastCAPass=%d \n",u1RankIdx, u1DieIdx, u1CAIdx, s1TempFirstPass, s1TempLastPass));
+
+ // Intersection by Macro
+ if(s1TempFirstPass > s1Intersect_min_byMacro[u1MacroIdx])
+ s1Intersect_min_byMacro[u1MacroIdx] = s1TempFirstPass;
+
+ if(s1TempLastPass < s1Intersect_max_byMacro[u1MacroIdx])
+ s1Intersect_max_byMacro[u1MacroIdx] = s1TempLastPass;
+
+ // intersection by CA bit
+ if(s1TempFirstPass > s1Intersect_min_byBit[u1CAIdx])
+ s1Intersect_min_byBit[u1CAIdx] = s1TempFirstPass;
+
+ if(s1TempLastPass < s1Intersect_max_byBit[u1CAIdx])
+ s1Intersect_max_byBit[u1CAIdx] = s1TempLastPass;
+ }
+ }
+
+ s1CACenter[u1CAIdx] = (s1Intersect_min_byBit[u1CAIdx] +s1Intersect_max_byBit[u1CAIdx])/2;
+
+ if(s1CACenter[u1CAIdx] < s1CACenter_min[u1MacroIdx])
+ s1CACenter_min[u1MacroIdx] = s1CACenter[u1CAIdx];
+ }
+
+ // If CA perbit, choose min CA PI of all bits.
+ // If CA perbyte, choose middle position of intersenction range of all bits.
+ if(u1IsLP4Family(p->dram_type))
+ {
+ u1MacroNum=1;
+ }
+ else //LP3
+ {
+ u1MacroNum=2;
+ }
+
+ // CA perbit enable
+ if(u1PerBitDelayCellEnable && (p->u2DelayCellTimex100 !=0))
+ {
+ for(u1MacroIdx =0; u1MacroIdx<u1MacroNum; u1MacroIdx++)
+ {
+ #if LP3_CATRAING_SHIFT_CLK_PI
+ if(u1IsLP4Family(p->dram_type))
+ #endif
+ {
+ if(s1CACenter_min[u1MacroIdx] <0) //don't move clk
+ {
+ //mcSHOW_DBG_MSG(("warning : Macro%d minimum CA PI delay is %d(<0) and changed to 0\n", u1MacroIdx, s1CACenter_min[u1MacroIdx]));
+ s1CACenter_min[u1MacroIdx] =0;
+ }
+ }
+
+ ps1CAMacroDelay[u1MacroIdx] = s1CACenter_min[u1MacroIdx];
+ }
+
+ mcSHOW_DBG_MSG(("u2DelayCellTimex100 = %d/100 ps\n", p->u2DelayCellTimex100));
+
+ for(u1CAIdx=0; u1CAIdx < u1CABitNum; u1CAIdx++)
+ {
+ if(u1IsLP4Family(p->dram_type))
+ {
+ u1MacroIdx=0;
+ }
+ else //LP3
+ {
+ if(u1CAIdx==0 || u1CAIdx==1)
+ {
+ u1MacroIdx=0;
+ }
+ else
+ u1MacroIdx=1;
+ }
+
+
+ #if LP3_CATRAING_SHIFT_CLK_PI
+ if(u1IsLP4Family(p->dram_type) && s1CACenter[u1CAIdx] <0) //don't move clk
+ #else
+ if(s1CACenter[u1CAIdx] <0) //don't move clk
+ #endif
+ {
+ s1CACenter[u1CAIdx] =0;
+ ps1CACenterDiff[u1CAIdx]=0;
+ }
+ else
+ {
+ ps1CACenterDiff[u1CAIdx] = s1CACenter[u1CAIdx] - s1CACenter_min[u1MacroIdx];
+ }
+
+ mcSHOW_DBG_MSG(("CA%d delay=%d (%d~%d),", u1CAIdx, s1CACenter[u1CAIdx], s1Intersect_min_byBit[u1CAIdx], s1Intersect_max_byBit[u1CAIdx]));
+ mcSHOW_DBG_MSG(("Diff = %d PI ", ps1CACenterDiff[u1CAIdx]));
+ ps1CACenterDiff[u1CAIdx] = (ps1CACenterDiff[u1CAIdx]*100000000/(p->frequency<<6))/p->u2DelayCellTimex100;
+ mcSHOW_DBG_MSG(("(%d cell)", ps1CACenterDiff[u1CAIdx]));
+
+ if(ps1CACenterDiff[u1CAIdx]>15)
+ {
+ mcSHOW_DBG_MSG(("[WARNING] CA%d delay cell %d >15, adjust to 15 cell", u1CAIdx, ps1CACenterDiff[u1CAIdx]));
+ ps1CACenterDiff[u1CAIdx] =15;
+ }
+
+ mcSHOW_DBG_MSG(("\n"));
+ }
+
+ for(u1MacroIdx =0; u1MacroIdx < u1MacroNum; u1MacroIdx++)
+ {
+ mcSHOW_DBG_MSG(("\nCA PerBit enable=%d, Macro%d, CA PI delay=%d\n", u1PerBitDelayCellEnable, u1MacroIdx, ps1CAMacroDelay[u1MacroIdx]));
+ }
+ }
+ else //CA perbyte
+ {
+ for(u1MacroIdx =0; u1MacroIdx < u1MacroNum; u1MacroIdx++)
+ {
+ ps1CAMacroDelay[u1MacroIdx] = (s1Intersect_min_byMacro[u1MacroIdx] +s1Intersect_max_byMacro[u1MacroIdx])/2;
+
+ if(ps1CAMacroDelay[u1MacroIdx] <0)//don't move clk
+ {
+ //mcSHOW_DBG_MSG(("warning : CA PI delay is %d(<0) and changed to 0\n", ps1CAMacroDelay[u1MacroIdx]));
+ ps1CAMacroDelay[u1MacroIdx] =0;
+ }
+ mcSHOW_DBG_MSG(("CA PerBit enable=%d, Macro%d, CA PI delay=%d (%d~%d)\n", u1PerBitDelayCellEnable, u1MacroIdx, ps1CAMacroDelay[u1MacroIdx], s1Intersect_min_byMacro[u1MacroIdx], s1Intersect_max_byMacro[u1MacroIdx]));
+ }
+ }
+}
+
+#if PINMUX_AUTO_TEST_PER_BIT_CA
+void CheckCADelayCell(DRAMC_CTX_T *p)
+{
+ DRAM_CHANNEL_T channel_bak = p->channel;
+ DRAM_RANK_T rank_bak = p->rank;
+
+ vSetPHY2ChannelMapping(p, CHANNEL_A);
+ vSetRank(p, RANK_0);
+ mcSHOW_DBG_MSG(("CA_delay_cell CHA R0[%X] CHB R0[%X] CHA R1[%X] CHB R1[%X]\n",
+ u4IO32Read4B(DDRPHY_SHU1_R0_CA_CMD0),
+ u4IO32Read4B(DDRPHY_SHU1_R0_CA_CMD0 + SHIFT_TO_CHB_ADDR),
+ u4IO32Read4B(DDRPHY_SHU1_R0_CA_CMD0 + 0x100),
+ u4IO32Read4B(DDRPHY_SHU1_R0_CA_CMD0 + SHIFT_TO_CHB_ADDR + 0x100)));
+ vSetPHY2ChannelMapping(p, channel_bak);
+ vSetRank(p, rank_bak);
+
+ return;
+}
+
+U16 gFinalCAPerbitFirstPass[CHANNEL_NUM][RANK_MAX][CATRAINING_NUM_LP4];
+void CheckCAPinMux(DRAMC_CTX_T *p)
+{
+ U8 u1CAIndex[CATRAINING_NUM_LP4] = {0};
+ U8 u1CAdelay[CATRAINING_NUM_LP4] = {0};
+ int i = 0;
+ int j = 0;
+ U8 u1Min = 0xff;
+ U8 u1MinIdx = 0;
+
+ for(i = 0; i<CATRAINING_NUM_LP4; i++)
+ {
+ memset(u1CAdelay, 0, sizeof(u1CAdelay));
+ u1CAdelay[i] = 0xf;
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), p->rank, RKCFG_TXRANK);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 1, RKCFG_TXRANKFIX);
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD0), P_Fld(u1CAdelay[5], SHU1_R0_CA_CMD0_RK0_TX_ARCA5_DLY)
+ | P_Fld(u1CAdelay[4], SHU1_R0_CA_CMD0_RK0_TX_ARCA4_DLY)
+ | P_Fld(u1CAdelay[3], SHU1_R0_CA_CMD0_RK0_TX_ARCA3_DLY)
+ | P_Fld(u1CAdelay[2], SHU1_R0_CA_CMD0_RK0_TX_ARCA2_DLY)
+ | P_Fld(u1CAdelay[1], SHU1_R0_CA_CMD0_RK0_TX_ARCA1_DLY)
+ | P_Fld(u1CAdelay[0], SHU1_R0_CA_CMD0_RK0_TX_ARCA0_DLY));
+ CmdBusTrainingLP4(p);
+
+ u1Min = 0xff;
+ for(j = 0; j<CATRAINING_NUM_LP4; j++)
+ {
+ if(gFinalCAPerbitFirstPass[p->channel][p->rank][j] <= u1Min)
+ {
+ u1Min = gFinalCAPerbitFirstPass[p->channel][p->rank][j];
+ u1MinIdx = j;
+ }
+ }
+ u1CAIndex[i] = u1MinIdx;
+ }
+ for(i = 0; i<CATRAINING_NUM_LP4; i++)
+ {
+ mcSHOW_DBG_MSG(("CH[%d] Rank[%d] APHY_CA[%d]-->DRAM(->MRR->DRAMC)[%d]\n", p->channel, p->rank, i, u1CAIndex[i]));
+ if(u1CAIndex[i] != uiLPDDR4_CA_Mapping_POP[p->channel][i])
+ {
+ mcSHOW_DBG_MSG(("!Not mapping with CA mapping table\n"));
+ while(1);
+ }
+ }
+ memset(u1CAdelay, 0, sizeof(u1CAdelay));
+ vIO32WriteFldMulti_All(DDRPHY_SHU1_R0_CA_CMD0, P_Fld(u1CAdelay[5], SHU1_R0_CA_CMD0_RK0_TX_ARCA5_DLY)
+ | P_Fld(u1CAdelay[4], SHU1_R0_CA_CMD0_RK0_TX_ARCA4_DLY)
+ | P_Fld(u1CAdelay[3], SHU1_R0_CA_CMD0_RK0_TX_ARCA3_DLY)
+ | P_Fld(u1CAdelay[2], SHU1_R0_CA_CMD0_RK0_TX_ARCA2_DLY)
+ | P_Fld(u1CAdelay[1], SHU1_R0_CA_CMD0_RK0_TX_ARCA1_DLY)
+ | P_Fld(u1CAdelay[0], SHU1_R0_CA_CMD0_RK0_TX_ARCA0_DLY));
+ return;
+}
+
+#if ENABLE_LP3_SW
+DRAM_STATUS_T CATrainingLP3(DRAMC_CTX_T *p);
+int gFinalCAPerbitFirstPass_LP3[RANK_MAX][CATRAINING_NUM_LP3];
+void CheckCAPinMux_LP3(DRAMC_CTX_T *p)
+{
+ U8 u1CAIndex[CATRAINING_NUM_LP3] = {0};
+ U8 u1CAdelay[CATRAINING_NUM_LP3] = {0};
+ int i = 0;
+ int j = 0;
+ int iMin = 0xff;
+ U8 u1MinIdx = 0;
+ int iOriFirstPass[CATRAINING_NUM_LP3] = {0};
+
+ CATrainingLP3(p);
+ for(j = 0; j < CATRAINING_NUM_LP3; j++)
+ {
+ iOriFirstPass[j] = gFinalCAPerbitFirstPass_LP3[p->rank][j];
+ mcSHOW_DBG_MSG(("### Ori first pass %d = [%d]\n", j, iOriFirstPass[j]));
+ }
+
+ for(i = 0; i < CATRAINING_NUM_LP3; i++)
+ {
+ memset(u1CAdelay, 0, sizeof(u1CAdelay));
+ u1CAdelay[i] = 0xf;
+ mcSHOW_DBG_MSG(("### Set delay cell of CA[%d]\n", i));
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD0), P_Fld(u1CAdelay[0], SHU1_R0_CA_CMD0_RK0_TX_ARCA1_DLY) |
+ P_Fld(u1CAdelay[1], SHU1_R0_CA_CMD0_RK0_TX_ARCA3_DLY));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ0), P_Fld(u1CAdelay[2], SHU1_R0_B0_DQ0_RK0_TX_ARDQ5_DLY_B0) |
+ P_Fld(u1CAdelay[3], SHU1_R0_B0_DQ0_RK0_TX_ARDQ7_DLY_B0) |
+ P_Fld(u1CAdelay[4], SHU1_R0_B0_DQ0_RK0_TX_ARDQ2_DLY_B0) |
+ P_Fld(u1CAdelay[5], SHU1_R0_B0_DQ0_RK0_TX_ARDQ0_DLY_B0) |
+ P_Fld(u1CAdelay[6], SHU1_R0_B0_DQ0_RK0_TX_ARDQ4_DLY_B0) |
+ P_Fld(u1CAdelay[7], SHU1_R0_B0_DQ0_RK0_TX_ARDQ6_DLY_B0) |
+ P_Fld(u1CAdelay[8], SHU1_R0_B0_DQ0_RK0_TX_ARDQ1_DLY_B0) |
+ P_Fld(u1CAdelay[9], SHU1_R0_B0_DQ0_RK0_TX_ARDQ3_DLY_B0));
+
+ CATrainingLP3(p);
+
+ iMin = 0xff;
+ for(j = 0; j < CATRAINING_NUM_LP3; j++)
+ {
+ //mcSHOW_DBG_MSG(("###CA[%d] ori=[%d] first_pass=[%d]\n", j, iOriFirstPass[j], gFinalCAPerbitFirstPass[p->rank][j]));
+ if((gFinalCAPerbitFirstPass_LP3[p->rank][j] - iOriFirstPass[j]) <= iMin)
+ {
+ iMin = gFinalCAPerbitFirstPass_LP3[p->rank][j] - iOriFirstPass[j];
+ u1MinIdx = j;
+ mcSHOW_DBG_MSG(( "[%d]enter %d %d \n", j, (gFinalCAPerbitFirstPass_LP3[p->rank][j] - iOriFirstPass[j]), iMin));
+ }
+ }
+ u1CAIndex[i] = u1MinIdx;
+ //mcSHOW_DBG_MSG(("### u1CAIndex = %d\n", u1CAIndex[i]));
+ }
+
+ for(i = 0; i < CATRAINING_NUM_LP3; i++)
+ {
+ mcSHOW_DBG_MSG(("CH[%d] Rank[%d] APHY_CA[%d]-->DRAM(->O1)[%d]\n", p->channel, p->rank, i, u1CAIndex[i]));
+ if(u1CAIndex[i] != i)
+ {
+ mcSHOW_DBG_MSG(("!Not mapping with CA mapping table\n"));
+ while(1);
+ }
+ }
+
+ memset(u1CAdelay, 0, sizeof(u1CAdelay));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD0), P_Fld(u1CAdelay[0], SHU1_R0_CA_CMD0_RK0_TX_ARCA1_DLY) |
+ P_Fld(u1CAdelay[1], SHU1_R0_CA_CMD0_RK0_TX_ARCA3_DLY));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ0), P_Fld(u1CAdelay[2], SHU1_R0_B0_DQ0_RK0_TX_ARDQ5_DLY_B0) |
+ P_Fld(u1CAdelay[3], SHU1_R0_B0_DQ0_RK0_TX_ARDQ7_DLY_B0) |
+ P_Fld(u1CAdelay[4], SHU1_R0_B0_DQ0_RK0_TX_ARDQ2_DLY_B0) |
+ P_Fld(u1CAdelay[5], SHU1_R0_B0_DQ0_RK0_TX_ARDQ0_DLY_B0) |
+ P_Fld(u1CAdelay[6], SHU1_R0_B0_DQ0_RK0_TX_ARDQ4_DLY_B0) |
+ P_Fld(u1CAdelay[7], SHU1_R0_B0_DQ0_RK0_TX_ARDQ6_DLY_B0) |
+ P_Fld(u1CAdelay[8], SHU1_R0_B0_DQ0_RK0_TX_ARDQ1_DLY_B0) |
+ P_Fld(u1CAdelay[9], SHU1_R0_B0_DQ0_RK0_TX_ARDQ3_DLY_B0));
+ return;
+}
+#endif
+#endif
+
+#if PINMUX_AUTO_TEST_PER_BIT_RX
+U8 gRX_check_per_bit_flag = 0;
+U8 gRX_Check_per_bit_idx = 0;
+U16 gFinalRXPerbitWinSiz[CHANNEL_NUM][DQ_DATA_WIDTH];
+void CheckRXDelayCell(DRAMC_CTX_T *p)
+{
+ int ii;
+ for (ii = 0; ii < 4; ii++)
+ {
+ mcSHOW_DBG_MSG2(("#### B0[%x] B1[%x]", u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2 + ii*4)), u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2 + ii*4))));
+ }
+}
+
+
+void SetRxPerBitDelayCellForPinMuxCheck(DRAMC_CTX_T *p, U8 U1bitIdx)
+{
+ U32 u4delay = 0x3f;
+ switch(U1bitIdx)
+ {
+ case 0:
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2),
+ P_Fld(u4delay, SHU1_R0_B0_DQ2_RK0_RX_ARDQ0_R_DLY_B0) |
+ P_Fld(u4delay, SHU1_R0_B0_DQ2_RK0_RX_ARDQ0_F_DLY_B0));//bit0
+ break;
+ case 1:
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2),
+ P_Fld(u4delay, SHU1_R0_B0_DQ2_RK0_RX_ARDQ1_R_DLY_B0) |
+ P_Fld(u4delay, SHU1_R0_B0_DQ2_RK0_RX_ARDQ1_F_DLY_B0));//bit1
+ break;
+ case 2:
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ3),
+ P_Fld(u4delay, SHU1_R0_B0_DQ3_RK0_RX_ARDQ2_R_DLY_B0) |
+ P_Fld(u4delay, SHU1_R0_B0_DQ3_RK0_RX_ARDQ2_F_DLY_B0)); //bit2
+ break;
+ case 3:
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ3),
+ P_Fld(u4delay, SHU1_R0_B0_DQ3_RK0_RX_ARDQ3_R_DLY_B0) |
+ P_Fld(u4delay, SHU1_R0_B0_DQ3_RK0_RX_ARDQ3_F_DLY_B0)); //bit3
+ break;
+ case 4:
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ4),
+ P_Fld(0x3f, SHU1_R0_B0_DQ4_RK0_RX_ARDQ4_R_DLY_B0) |
+ P_Fld(0x3f, SHU1_R0_B0_DQ4_RK0_RX_ARDQ4_F_DLY_B0)); //bit4
+ break;
+ case 5:
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ4),
+ P_Fld(u4delay, SHU1_R0_B0_DQ4_RK0_RX_ARDQ5_R_DLY_B0) |
+ P_Fld(u4delay, SHU1_R0_B0_DQ4_RK0_RX_ARDQ5_F_DLY_B0)); //bit5
+ break;
+ case 6:
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ5),
+ P_Fld(u4delay, SHU1_R0_B0_DQ5_RK0_RX_ARDQ6_R_DLY_B0) |
+ P_Fld(u4delay, SHU1_R0_B0_DQ5_RK0_RX_ARDQ6_F_DLY_B0)); //bit6
+ break;
+ case 7:
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ5),
+ P_Fld(u4delay, SHU1_R0_B0_DQ5_RK0_RX_ARDQ7_R_DLY_B0) |
+ P_Fld(u4delay, SHU1_R0_B0_DQ5_RK0_RX_ARDQ7_F_DLY_B0)); //bit7
+ break;
+ case 8:
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2),
+ P_Fld(u4delay, SHU1_R0_B1_DQ2_RK0_RX_ARDQ0_R_DLY_B1) |
+ P_Fld(u4delay, SHU1_R0_B1_DQ2_RK0_RX_ARDQ0_F_DLY_B1)); //bit8
+ break;
+ case 9:
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2),
+ P_Fld(u4delay, SHU1_R0_B1_DQ2_RK0_RX_ARDQ1_R_DLY_B1) |
+ P_Fld(u4delay, SHU1_R0_B1_DQ2_RK0_RX_ARDQ1_F_DLY_B1)); //bit9
+ break;
+ case 10:
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ3),
+ P_Fld(u4delay, SHU1_R0_B1_DQ3_RK0_RX_ARDQ2_R_DLY_B1) |
+ P_Fld(u4delay, SHU1_R0_B1_DQ3_RK0_RX_ARDQ2_F_DLY_B1)); //bit10
+ break;
+ case 11:
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ3),
+ P_Fld(u4delay, SHU1_R0_B1_DQ3_RK0_RX_ARDQ3_R_DLY_B1) |
+ P_Fld(u4delay, SHU1_R0_B1_DQ3_RK0_RX_ARDQ3_F_DLY_B1)); //bit 11
+ break;
+ case 12:
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ4),
+ P_Fld(u4delay, SHU1_R0_B1_DQ4_RK0_RX_ARDQ4_R_DLY_B1) |
+ P_Fld(u4delay, SHU1_R0_B1_DQ4_RK0_RX_ARDQ4_F_DLY_B1)); //bit 12
+ break;
+ case 13:
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ4),
+ P_Fld(u4delay, SHU1_R0_B1_DQ4_RK0_RX_ARDQ5_R_DLY_B1) |
+ P_Fld(u4delay, SHU1_R0_B1_DQ4_RK0_RX_ARDQ5_F_DLY_B1)); //bit 13
+ break;
+ case 14:
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ5),
+ P_Fld(u4delay, SHU1_R0_B1_DQ5_RK0_RX_ARDQ6_R_DLY_B1) |
+ P_Fld(u4delay, SHU1_R0_B1_DQ5_RK0_RX_ARDQ6_F_DLY_B1)); //bit 14
+ break;
+ case 15:
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ5),
+ P_Fld(u4delay, SHU1_R0_B1_DQ5_RK0_RX_ARDQ7_R_DLY_B1) |
+ P_Fld(u4delay, SHU1_R0_B1_DQ5_RK0_RX_ARDQ7_F_DLY_B1)); //bit 15
+ break;
+ default:
+ mcSHOW_DBG_MSG(("Not assign correct index\n"));
+ }
+}
+
+void CheckRxPinMux(DRAMC_CTX_T *p)//By view of DRAM in LP4
+{
+ U8 u1RxIndex[DQ_DATA_WIDTH_LP4] = {0};
+ int i = 0;
+ int j = 0;
+ gRX_check_per_bit_flag = 1;
+
+ U16 u2Min = 0xffff;
+ U8 u1MinIdx = 0;
+
+ for (i=0; i < DQ_DATA_WIDTH_LP4; i+=1)
+ {
+ gRX_Check_per_bit_idx = i;
+
+ DramcRxWindowPerbitCal(p, 0);//RDDQC
+
+ u2Min = 0xffff;
+ for(j = 0; j < DQ_DATA_WIDTH_LP4; j++)
+ {
+ if(gFinalRXPerbitWinSiz[p->channel][j] <= u2Min)
+ {
+ u2Min = gFinalRXPerbitWinSiz[p->channel][j];
+ u1MinIdx = j;
+ }
+ }
+ u1RxIndex[i] = u1MinIdx;
+ }
+
+ for(i = 0; i < DQ_DATA_WIDTH_LP4; i++)
+ {
+ mcSHOW_DBG_MSG(("CH[%d] Rank[%d] APHY_RX[%d]-->DRAMC(-->RDDQC-->O1)[%d]\n", p->channel, p->rank, i, u1RxIndex[i]));
+ if(u1RxIndex[i] != i)
+ {
+ mcSHOW_DBG_MSG(("!RX APHY DRAMC DQ is not mapping directly\n"));
+ while(1);
+ }
+ }
+ gRX_check_per_bit_flag = 0;
+ return;
+}
+#endif
+
+#if PINMUX_AUTO_TEST_PER_BIT_RX_LP3
+U8 gRX_check_per_bit_flag = 0;
+U8 gRX_Check_per_bit_idx = 0;
+U16 gFinalRXPerbitWinSiz[CHANNEL_NUM][DQ_DATA_WIDTH];
+void Set_RX_DQ_DelayLine_Phy_Byte(DRAMC_CTX_T *p, U8 u1ByteIdx, U8 value[8]);
+void SetRxPerBitDelayCellForPinMuxCheckLp3(DRAMC_CTX_T *p, U8 U1bitIdx, S16 iDelay)
+{
+ DRAM_CHANNEL_T backup_channel;
+ backup_channel = p->channel;
+ S8 dl_value[8] = {0};
+ U8 u1ByteIdx = U1bitIdx / 8;
+ U8 u1BitIdxInByte = U1bitIdx % 8;
+ int i = 0;
+
+ mcSHOW_DBG_MSG(("get gRX_Check_per_bit_idx: %d ==> ByteIdx: %d, BitIdx: %d\n", U1bitIdx, u1ByteIdx, u1BitIdxInByte));
+
+ for(i=0; i < 8; i++)
+ {
+ dl_value[i] = (i != u1BitIdxInByte) ? iDelay : 0x3f;//Set delay cell of specific bit to max, others keep original value
+ }
+
+ Set_RX_DQ_DelayLine_Phy_Byte(p, u1ByteIdx, dl_value);//View of DRAMC
+
+ p->channel = backup_channel;
+ return;
+}
+
+void CheckRxPinMux(DRAMC_CTX_T *p)//By view of DRAMC in LP3
+{
+ U8 u1RxIndex[DQ_DATA_WIDTH] = {0};
+ int i = 0;
+ int j = 0;
+ gRX_check_per_bit_flag = 1;
+ U16 u2Min = 0xffff;
+ U8 u1MinIdx = 0;
+
+ for (i=0; i < DQ_DATA_WIDTH; i+=1)
+ {
+ gRX_Check_per_bit_idx = i;
+
+ mcSHOW_DBG_MSG(("Set DQ[%d] delay cell to max\n", i));
+ DramcRxWindowPerbitCal(p, 1);//LP3 only for TA2
+
+ u2Min = 0xffff;
+ for(j = 0; j < DQ_DATA_WIDTH; j++)
+ {
+ if(u2Min >= gFinalRXPerbitWinSiz[p->channel][j])
+ {
+ u2Min = gFinalRXPerbitWinSiz[p->channel][j];
+ u1MinIdx = j;
+ }
+ }
+ u1RxIndex[i] = u1MinIdx;
+ }
+
+ mcSHOW_DBG_MSG(("CH[%d] Rank[%d]\n", p->channel, p->rank));
+ bool is_wrong = false;
+ for(i = 0; i < DQ_DATA_WIDTH; i++)
+ {
+ mcSHOW_DBG_MSG(("APHY_RX[%d] by DRAMC order-->DRAMC(-->TA2)[%d] TA2_answer[%d]\n", i, u1RxIndex[i], i));
+ if(u1RxIndex[i] != i)
+ {
+ if((u1GetRank(p) == RANK_0) && ((i == 9) || (i == 12)))//check pinmux table, DRAMC DQ9 = MCP DQ10; DRAMC DQ12 = MCP DQ12
+ {
+ mcSHOW_DBG_MSG(("!Rank0 BRCKE0 of APHY will effect DQ10 && DQ12 of MCP\n"));
+ }
+ else
+ {
+ mcSHOW_DBG_MSG(("!RX APHY DRAMC DQ is not mapping directly\n"));
+ is_wrong = true;
+ //Since BRCKE0 of APHY will effect DQ10 && DQ12 of MCP
+ }
+ }
+
+ }
+ if (is_wrong == true)
+ {
+ while(1);
+ }
+
+ gRX_check_per_bit_flag = 0;
+ return;
+}
+#endif // PINMUX_AUTO_TEST_PER_BIT_RX_LP3
+
+#if PINMUX_AUTO_TEST_PER_BIT_TX
+U8 gTX_check_per_bit_flag = 0;
+U16 gFinalTXPerbitFirstPass[CHANNEL_NUM][DQ_DATA_WIDTH];
+void CheckTxPinMux(DRAMC_CTX_T *p)
+{
+ U8 u1Txdelay[16] = {0};
+ U8 u1TxIndex[16] = {0};
+ int i = 0;
+ int j = 0;
+ gTX_check_per_bit_flag = 1;
+ U16 u2Min = 0xffff;
+ U8 u1MinIdx = 0;
+
+ for(i = 0; i < DQ_DATA_WIDTH_LP4; i++)
+ {
+ memset(u1Txdelay, 0, sizeof(u1Txdelay));
+ u1Txdelay[i] = 0xf;
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ0), P_Fld(u1Txdelay[7], SHU1_R0_B0_DQ0_RK0_TX_ARDQ7_DLY_B0)
+ | P_Fld(u1Txdelay[6], SHU1_R0_B0_DQ0_RK0_TX_ARDQ6_DLY_B0)
+ | P_Fld(u1Txdelay[5], SHU1_R0_B0_DQ0_RK0_TX_ARDQ5_DLY_B0)
+ | P_Fld(u1Txdelay[4], SHU1_R0_B0_DQ0_RK0_TX_ARDQ4_DLY_B0)
+ | P_Fld(u1Txdelay[3], SHU1_R0_B0_DQ0_RK0_TX_ARDQ3_DLY_B0)
+ | P_Fld(u1Txdelay[2], SHU1_R0_B0_DQ0_RK0_TX_ARDQ2_DLY_B0)
+ | P_Fld(u1Txdelay[1], SHU1_R0_B0_DQ0_RK0_TX_ARDQ1_DLY_B0)
+ | P_Fld(u1Txdelay[0], SHU1_R0_B0_DQ0_RK0_TX_ARDQ0_DLY_B0));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ0), P_Fld(u1Txdelay[15], SHU1_R0_B1_DQ0_RK0_TX_ARDQ7_DLY_B1)
+ | P_Fld(u1Txdelay[14], SHU1_R0_B1_DQ0_RK0_TX_ARDQ6_DLY_B1)
+ | P_Fld(u1Txdelay[13], SHU1_R0_B1_DQ0_RK0_TX_ARDQ5_DLY_B1)
+ | P_Fld(u1Txdelay[12], SHU1_R0_B1_DQ0_RK0_TX_ARDQ4_DLY_B1)
+ | P_Fld(u1Txdelay[11], SHU1_R0_B1_DQ0_RK0_TX_ARDQ3_DLY_B1)
+ | P_Fld(u1Txdelay[10], SHU1_R0_B1_DQ0_RK0_TX_ARDQ2_DLY_B1)
+ | P_Fld(u1Txdelay[9], SHU1_R0_B1_DQ0_RK0_TX_ARDQ1_DLY_B1)
+ | P_Fld(u1Txdelay[8], SHU1_R0_B1_DQ0_RK0_TX_ARDQ0_DLY_B1));
+ DramcTxWindowPerbitCal(p, TX_DQ_DQS_MOVE_DQ_ONLY, FALSE);
+ mcSHOW_DBG_MSG(("set 1 ranks set:0xf\n"));
+
+ u2Min = 0xffff;
+ for(j = 0; j < DQ_DATA_WIDTH_LP4; j++)
+ {
+ if(gFinalTXPerbitFirstPass[p->channel][j] <= u2Min)
+ {
+ u2Min = gFinalTXPerbitFirstPass[p->channel][j];
+ u1MinIdx = j;
+ }
+ }
+ u1TxIndex[i] = u1MinIdx;
+ }
+
+ for(i = 0; i < DQ_DATA_WIDTH_LP4; i++)
+ {
+ mcSHOW_DBG_MSG(("CH[%d] Rank[%d] APHY_TX[%d]-->DRAMC(->TA2->)[%d]\n", p->channel, p->rank, i, u1TxIndex[i]));
+ if(u1TxIndex[i] != i)
+ {
+ mcSHOW_DBG_MSG(("!TX APHY DRAMC DQ is not mapping directly\n"));
+ while(1);
+ }
+ }
+ gTX_check_per_bit_flag = 0;
+ return;
+}
+#endif
+
+void CATrainingSetPerBitDelayCell(DRAMC_CTX_T *p, S8 *ps1CACenterDiff)
+{
+ // Need to porting for each project according to LP3 pinmux table
+ #if (fcFOR_CHIP_ID == fcLaurel)
+ #if LP3_CA_PER_BIT
+ if(!u1IsLP4Family(p->dram_type))
+ {
+ //DRAM CA0/1 delay cell
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD0), P_Fld(ps1CACenterDiff[0], SHU1_R0_CA_CMD0_RK0_TX_ARCA1_DLY)|
+ P_Fld(ps1CACenterDiff[1], SHU1_R0_CA_CMD0_RK0_TX_ARCA3_DLY));
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ0), P_Fld(ps1CACenterDiff[2], SHU1_R0_B0_DQ0_RK0_TX_ARDQ5_DLY_B0)|
+ P_Fld(ps1CACenterDiff[3], SHU1_R0_B0_DQ0_RK0_TX_ARDQ7_DLY_B0)|
+ P_Fld(ps1CACenterDiff[4], SHU1_R0_B0_DQ0_RK0_TX_ARDQ2_DLY_B0)|
+ P_Fld(ps1CACenterDiff[5], SHU1_R0_B0_DQ0_RK0_TX_ARDQ0_DLY_B0)|
+ P_Fld(ps1CACenterDiff[6], SHU1_R0_B0_DQ0_RK0_TX_ARDQ4_DLY_B0)|
+ P_Fld(ps1CACenterDiff[7], SHU1_R0_B0_DQ0_RK0_TX_ARDQ6_DLY_B0)|
+ P_Fld(ps1CACenterDiff[8], SHU1_R0_B0_DQ0_RK0_TX_ARDQ1_DLY_B0)|
+ P_Fld(ps1CACenterDiff[9], SHU1_R0_B0_DQ0_RK0_TX_ARDQ3_DLY_B0));
+ }
+ #endif// end of LP3_CA_PER_BIT
+
+ #if CA_PER_BIT_DELAY_CELL
+ U8 uiCA;
+ U8 *uiLPDDR_CA_Mapping = (U8 *)uiLPDDR4_CA_Mapping_POP[p->channel];
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ for (uiCA=0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+ {
+ //mcSHOW_DBG_MSG(("CA%d dly line = %d cells \n", uiLPDDR_CA_Mapping[uiCA], ps1CACenterDiff[uiCA]));
+ #if EYESCAN_LOG
+ gEyeScan_DelayCellPI[uiCA] = (S8) ps1CACenterDiff[uiCA];
+ #endif
+ }
+
+ // Set CA perbit delay line calibration results
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD0), P_Fld(ps1CACenterDiff[uiLPDDR_CA_Mapping[0]], SHU1_R0_CA_CMD0_RK0_TX_ARCA0_DLY) | \
+ P_Fld(ps1CACenterDiff[uiLPDDR_CA_Mapping[1]], SHU1_R0_CA_CMD0_RK0_TX_ARCA1_DLY) | \
+ P_Fld(ps1CACenterDiff[uiLPDDR_CA_Mapping[2]], SHU1_R0_CA_CMD0_RK0_TX_ARCA2_DLY) | \
+ P_Fld(ps1CACenterDiff[uiLPDDR_CA_Mapping[3]], SHU1_R0_CA_CMD0_RK0_TX_ARCA3_DLY) | \
+ P_Fld(ps1CACenterDiff[uiLPDDR_CA_Mapping[4]], SHU1_R0_CA_CMD0_RK0_TX_ARCA4_DLY) | \
+ P_Fld(ps1CACenterDiff[uiLPDDR_CA_Mapping[5]], SHU1_R0_CA_CMD0_RK0_TX_ARCA5_DLY) );
+ }
+ #endif
+ #endif
+}
+
+#if ENABLE_LP3_SW
+#if SIMULATION_LP3_CA_TRAINING
+//-------------------------------------------------------------------------
+/** DramcCATraining
+ * start the calibrate the skew between Clk pin and CAx pins.
+ * @param p Pointer of context created by DramcCtxCreate.
+ * @retval status (DRAM_STATUS_T): DRAM_OK or DRAM_FAIL
+ */
+//-------------------------------------------------------------------------
+#define MAX_CLKO_DELAY 31
+
+static DRAM_STATUS_T CATrainingEntry(DRAMC_CTX_T *p, U32 uiMR41, U32 u4GoldenPattern)
+{
+ //CA_TRAINING_BEGIN:
+
+ // CS extent enable (need DRAM to support)
+ // for testing
+#if CA_TRAINING_K_RANK1_ENABLE
+ if(p->rank == RANK_1)
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRS), p->rank, MRS_MRSRK);
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), P_Fld(0, RKCFG_CS0FORCE)|P_Fld(0, RKCFG_CS2RANK)); //cannot enable before any MRW command
+ }
+#endif
+
+#if (FOR_DV_SIMULATION_USED==0)
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 1, CATRAINING1_CATRAINCSEXT);
+#endif
+
+ // CKE high, CKE must be driven HIGH prior to issuance of the MRW41 and MRW48 command
+ CKEFixOnOff(p, p->rank, CKE_FIXON, CKE_WRITE_TO_ONE_CHANNEL);
+
+ // Hold the CA bus stable for at least one cycle.
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 1, CATRAINING1_CATRAINMRS);
+
+ mcDELAY_US(1);
+
+ // Enter MR 41/MR48
+ // Set MA & OP.
+ if (uiMR41)
+ {
+ DramcModeRegWrite(p, 41, 0xa4); //MR41=0xa4 CA Training Mode enable
+ }
+ else
+ {
+ DramcModeRegWrite(p, 48, 0xc0); //MR48=0xc0 CA Training Mode enable
+ }
+
+ // Disable CA bus stable.
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 0, CATRAINING1_CATRAINMRS);
+
+ // Wait tCACKEL(10 tck) before CKE low
+ mcDELAY_US(1);
+
+ // CKE low
+ CKEFixOnOff(p, p->rank, CKE_FIXOFF, CKE_WRITE_TO_ONE_CHANNEL);
+
+ // Set CA0~CA3, CA5~CA8 rising/falling golden value.
+ vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING2), u4GoldenPattern);
+
+#if CA_TRAINING_K_RANK1_ENABLE
+ if(p->rank == RANK_1)
+ {
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), P_Fld(1, RKCFG_CS0FORCE)| P_Fld(1, RKCFG_CS2RANK)); //enable to force CS switch to rank1
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 1, RKCFG_TXRANK); //TXRANKFIX should be write after TXRANK or the rank will be fix at rank 1
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 1, RKCFG_TXRANKFIX); //enable to switch to rank1
+ }
+#endif
+
+
+ // Wait tCAENT(10 tck) before pattern output
+ mcDELAY_US(1);
+
+ return DRAM_OK;
+}
+
+
+static S32 CheckCATrainingTransition(U32 uiCA, U32 capattern, U32 uiRisingEdge, U32 uiFallingEdge)
+{
+ S32 iPass=0;
+ U32 iii;
+
+ if (capattern == 0x55555555)
+ {
+ if ((uiRisingEdge!=0) && (uiFallingEdge==0))
+ {
+ iPass = 1;
+ }
+ else
+ {
+ iPass = 0;
+ }
+ }
+ else if (capattern == 0xaaaaaaaa)
+ {
+ if ((uiRisingEdge==0) && (uiFallingEdge!=0))
+ {
+ iPass = 1;
+ }
+ else
+ {
+ iPass = 0;
+ }
+ }
+ else if (capattern == 0x99999999)
+ {
+ iii = uiCA;
+ if (iii>=5) iii-=5;
+
+ if ((iii & 1) == 0)
+ {
+ if ((uiRisingEdge!=0) && (uiFallingEdge==0))
+ {
+ iPass = 1;
+ }
+ else
+ {
+ iPass = 0;
+ }
+ }
+ else
+ {
+ if ((uiRisingEdge==0) && (uiFallingEdge!=0))
+ {
+ iPass = 1;
+ }
+ else
+ {
+ iPass = 0;
+ }
+ }
+ }
+ else if (capattern == 0x66666666)
+ {
+ iii = uiCA;
+ if (iii>=5) iii-=5;
+
+ if ((iii & 1) == 0)
+ {
+ if ((uiRisingEdge==0) && (uiFallingEdge!=0))
+ {
+ iPass = 1;
+ }
+ else
+ {
+ iPass = 0;
+ }
+ }
+ else
+ {
+ if ((uiRisingEdge!=0) && (uiFallingEdge==0))
+ {
+ iPass = 1;
+ }
+ else
+ {
+ iPass = 0;
+ }
+ }
+ }
+
+ return iPass;
+}
+
+
+static void CATrainingExit(DRAMC_CTX_T *p)
+{
+#if CA_TRAINING_K_RANK1_ENABLE
+ if(p->rank == RANK_1) //disable setting of CS and TX rank sel switch to rank1 before leaving CA training
+ {
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), P_Fld(0, RKCFG_CS0FORCE)| P_Fld(0, RKCFG_CS2RANK));
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANK); //TXRANKFIX should be write after TXRANK or the rank will be fix at rank 1
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANKFIX); //enable to switch to rank1
+ }
+#endif
+
+ CKEFixOnOff(p, p->rank, CKE_FIXON, CKE_WRITE_TO_ONE_CHANNEL);
+ mcDELAY_US(1);
+
+ // CS extent enable
+ // for testing
+#if (FOR_DV_SIMULATION_USED==0)
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 1, CATRAINING1_CATRAINCSEXT);
+#endif
+
+ // Hold the CA bus stable for at least one cycle.
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 1, CATRAINING1_CATRAINMRS);
+
+ mcDELAY_US(1);
+
+ // MR42 to leave CA training.
+ DramcModeRegWrite(p, 42, 0xa8); //MR42=0xa8 CA Training Mode disable
+
+ // Disable the hold the CA bus stable for at least one cycle.
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 0, CATRAINING1_CATRAINMRS);
+
+ // CS extent disable
+ // for testing
+#if (FOR_DV_SIMULATION_USED==0)
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 0, CATRAINING1_CATRAINCSEXT);
+#endif
+}
+
+void CATrainingDelayCompare(DRAMC_CTX_T *p, U32 uiMR41, U32 u4GoldenPattern, U8 u1LP3DieNum, U32 delayinecompare_flag)
+{
+ U8 *uiLPDDR_O1_Mapping = NULL, u1DieIdx;
+// U32 u4O1Data[DQS_NUMBER];
+ U8 u1Offset;
+ U32 uiTemp, uiCA, uiRisingEdge, uiFallingEdge, uiFinishCount;
+ S32 iPass, iDelay, iDelay_Start, iDelay_End;
+
+ S32 iCenter[LP3_DIE_NUM_MAX][CATRAINING_NUM] = {0};
+
+ #if (fcFOR_CHIP_ID == fcLaurel)
+ if(p->bDLP3)
+ {
+ uiLPDDR_O1_Mapping = (U8 *)uiLPDDR3_O1_Mapping_POP_DLP3;
+ }
+ else
+ #endif
+ {
+ uiLPDDR_O1_Mapping = (U8 *)uiLPDDR3_O1_Mapping_POP;
+ }
+
+ // Calculate the middle range & max middle.
+ mcSHOW_DBG_MSG(("\n[CA Training]\n"));
+ vPrintCalibrationBasicInfo(p);
+
+ mcFPRINTF((fp_A60501, "\n1. CA training window before adjustment.\n"));
+ mcFPRINTF((fp_A60501, "x=Pass window CA(max~min) Clk(min~max) center. \n"));
+ if(uiMR41)
+ {
+ mcSHOW_DBG_MSG(("y=CA0~CA3, CA5~8\n\n"));
+ mcFPRINTF((fp_A60501, "y=CA0~CA3, CA5~8\n\n"));
+ }
+ else//MR48
+ {
+ mcSHOW_DBG_MSG(("y=CA4 CA9\n\n"));
+ mcFPRINTF((fp_A60501, "y=CA4 CA9\n\n"));
+ }
+
+ uiFinishCount = 0;
+
+ for (u1DieIdx=0; u1DieIdx<LP3_DIE_NUM_MAX; u1DieIdx++)
+ {
+ for (uiCA=0; uiCA<CATRAINING_NUM; uiCA++)
+ {
+ if(uiMR41 && ((uiCA==4) || (uiCA==9))) // MR41 is for CA0~3, CA5~8
+ {
+ continue;
+ }
+ else if((uiMR41==0) && ((uiCA!=4) && (uiCA!=9)))// MR48 is for CA4, CA9
+ {
+ continue;
+ }
+
+ iLastCAPass[p->rank][u1DieIdx][uiCA] = CATRAINING_PASS_RANGE_NA;
+ iFirstCAPass[p->rank][u1DieIdx][uiCA] = CATRAINING_PASS_RANGE_NA;
+ }
+ }
+
+ if (delayinecompare_flag == 0)
+ {
+#if (fcFOR_PINMUX == fcLaurel)
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), 0, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD); //CA0~1 CA_PI_Delay
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), 0, SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0); //CA2~9 CA_PI_Delay
+#endif
+ }
+
+ if (delayinecompare_flag == 0)
+ {
+ iDelay_Start = -(MAX_CLK_PI_DELAY/2);
+ /* [Justin May 19, 2017 7:13 PM]SW modification is required if the final CMD/CS PI code=32~63
+ HW bug: LP3 CA/CS delay cannot >31 PI. if larger than 31PI, use UI instead.
+ The problem will be fixed in Cannon and can change iDelay_End back to 63 */
+ iDelay_End = MAX_CA_PI_DELAY;
+ }
+ else
+ {
+ iDelay_Start = 0;
+ iDelay_End = MAX_CLK_PI_DELAY;
+ }
+
+ // Delay clock output delay to do CA training in order to get the pass window.
+ for (iDelay= iDelay_Start; iDelay <= iDelay_End; iDelay++)
+ {
+ if (delayinecompare_flag == 0)
+ {
+ if(iDelay <=0)
+ { //Set CLK delay
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), -iDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK); //clock_PI_Delay
+ }
+ else
+ { // Set CA output delay
+#if (fcFOR_PINMUX == fcLaurel)
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), iDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD); //CA0~1 CA_PI_Delay
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), iDelay, SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0); //CA2~9 CA_PI_Delay
+#endif
+ }
+ }
+ else
+ {
+ // set CLK PI value
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), iDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK); //clock_PI_Delay
+ }
+
+ // CA training pattern output enable
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 1, CATRAINING1_CATRAINEN);
+ // delay 2 DRAM clock cycle
+ mcDELAY_US(1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 0, CATRAINING1_CATRAINEN);
+
+
+ // Wait tADR(20ns) before CA sampled values available in DQ.
+ mcDELAY_US(1);
+
+ // Get DQ value.
+ uiTemp = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_DQO1));
+
+ #ifdef ETT_PRINT_FORMAT
+ mcSHOW_DBG_MSG3(("%d, DQ_O1 0x%x| ", iDelay, uiTemp));
+ #else
+ mcSHOW_DBG_MSG3(("delay %3d, DQ_O1 0x%8x| Pass ", iDelay, uiTemp));
+ #endif
+ mcFPRINTF((fp_A60501, "delay %3d, DQ_O1 0x%8x| Pass ", iDelay, uiTemp));
+
+ // Compare with golden value.
+ for (u1DieIdx=0; u1DieIdx<u1LP3DieNum; u1DieIdx++)
+ {
+ if(u1LP3DieNum>1)
+ {
+ mcSHOW_DBG_MSG3(("|D%d ",u1DieIdx));
+ }
+
+ for (uiCA=0; uiCA<CATRAINING_NUM; uiCA++)
+ {
+ if(uiMR41 && ((uiCA==4) || (uiCA==9))) // MR41 is for CA0~3, CA5~8
+ {
+ continue;
+ }
+ else if((uiMR41==0) && ((uiCA!=4) && (uiCA!=9)))// MR48 is for CA4, CA8
+ {
+ continue;
+ }
+
+ u1Offset = 16 * u1DieIdx;
+ //if ( (iFirstCAPass[p->rank][u1DieIdx][uiCA]==CATRAINING_PASS_RANGE_NA) || (iLastCAPass[p->rank][u1DieIdx][uiCA]==CATRAINING_PASS_RANGE_NA)) //marked fo debug
+ {
+ if (uiCA<4) //CA0~3
+ {
+ uiRisingEdge = uiTemp & ((0x01 << uiLPDDR_O1_Mapping[(uiCA << 1) + u1Offset]));
+ uiFallingEdge = uiTemp & ((0x01 << uiLPDDR_O1_Mapping[(uiCA << 1) + 1 + u1Offset]));
+ }
+ else if((uiCA==4) || (uiCA==9))
+ {
+ uiRisingEdge = uiTemp & ((0x01 << uiLPDDR_O1_Mapping[(uiCA == 4) ? 0 + u1Offset: 8 + u1Offset]));
+ uiFallingEdge = uiTemp & ((0x01 << uiLPDDR_O1_Mapping[(uiCA == 4) ? 1 + u1Offset : 9 + u1Offset]));
+ }
+ else//CA5~8
+ {
+ uiRisingEdge = uiTemp & ((0x01 << uiLPDDR_O1_Mapping[((uiCA - 1) << 1) + u1Offset]));
+ uiFallingEdge = uiTemp & ((0x01 << uiLPDDR_O1_Mapping[((uiCA - 1) << 1) + 1 + u1Offset]));
+ }
+
+ iPass = CheckCATrainingTransition(uiCA, u4GoldenPattern, uiRisingEdge, uiFallingEdge);
+ mcSHOW_DBG_MSG3(("%d ", iPass));
+ mcFPRINTF((fp_A60501, "%d ", iPass));
+
+ if (iFirstCAPass[p->rank][u1DieIdx][uiCA]==CATRAINING_PASS_RANGE_NA)
+ {
+ if (iPass == 1)
+ {
+ iFirstCAPass[p->rank][u1DieIdx][uiCA] = iDelay;
+ }
+ }
+ else
+ {
+ if (iLastCAPass[p->rank][u1DieIdx][uiCA]==CATRAINING_PASS_RANGE_NA)
+ {
+ if (iPass == 0)
+ {
+ if((iDelay-iFirstCAPass[p->rank][u1DieIdx][uiCA]) < 8) // prevent glitch
+ {
+ iFirstCAPass[p->rank][u1DieIdx][uiCA]=CATRAINING_PASS_RANGE_NA;
+ continue;
+ }
+
+ uiFinishCount++;
+ iLastCAPass[p->rank][u1DieIdx][uiCA] = iDelay-1;
+
+ iCenter[u1DieIdx][uiCA] = (iLastCAPass[p->rank][u1DieIdx][uiCA] + iFirstCAPass[p->rank][u1DieIdx][uiCA]) >>1;
+ }
+ else
+ {
+ if (iDelay==MAX_CA_PI_DELAY)
+ {
+ uiFinishCount++;
+ iLastCAPass[p->rank][u1DieIdx][uiCA] = iDelay;
+
+ iCenter[u1DieIdx][uiCA] = (iLastCAPass[p->rank][u1DieIdx][uiCA] + iFirstCAPass[p->rank][u1DieIdx][uiCA]) >>1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Wait tCACD(22clk) before output CA pattern to DDR again..
+ mcDELAY_US(1);
+
+ mcSHOW_DBG_MSG3(("\n"));
+ mcFPRINTF((fp_A60501, "\n"));
+
+ if((uiMR41 && (uiFinishCount==(8*u1LP3DieNum))) || ((uiMR41==0) && (uiFinishCount==(2*u1LP3DieNum))))
+ {
+ mcSHOW_DBG_MSG(("Early break, MR41=%d FinishCount=%d\n", uiMR41, uiFinishCount));
+ mcFPRINTF((fp_A60501, "Early break, uiMR41=%d\n", uiMR41));
+ break;
+ }
+ }
+
+
+ vSetCalibrationResult(p, DRAM_CALIBRATION_CA_TRAIN, DRAM_OK); // set default result OK, udpate status when per bit fail
+
+ if (delayinecompare_flag == 1)
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), 0, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK);
+ }
+
+ for(u1DieIdx=0; u1DieIdx<u1LP3DieNum; u1DieIdx++)
+ {
+ for (uiCA=0; uiCA<CATRAINING_NUM; uiCA++)
+ {
+ if(uiMR41 && ((uiCA==4) || (uiCA==9))) // MR41 is for CA0~3, CA5~8
+ {
+ continue;
+ }
+ else if((uiMR41==0) && ((uiCA!=4) && (uiCA!=9)))// MR48 is for CA4, CA9
+ {
+ continue;
+ }
+
+ #ifdef FOR_HQA_TEST_USED
+ gFinalCBTCA[p->channel][p->rank][uiCA] = (iLastCAPass[p->rank][u1DieIdx][uiCA] - iFirstCAPass[p->rank][u1DieIdx][uiCA])+(iLastCAPass[p->rank][u1DieIdx][uiCA]==iFirstCAPass[p->rank][u1DieIdx][uiCA]?0:1);
+ #endif
+ #if PINMUX_AUTO_TEST_PER_BIT_CA
+ gFinalCAPerbitFirstPass_LP3[p->rank][uiCA] = iFirstCAPass[p->rank][0][uiCA];//only use die0
+ #endif
+
+ if(u1LP3DieNum ==1)
+ {
+ #ifdef ETT_PRINT_FORMAT
+ mcSHOW_DBG_MSG(("CA%d (%d~%d) %d,\n", uiCA, iFirstCAPass[p->rank][u1DieIdx][uiCA], iLastCAPass[p->rank][u1DieIdx][uiCA], iCenter[u1DieIdx][uiCA]));
+ #else
+ mcSHOW_DBG_MSG(("CA%3d Pass(%3d~%3d) Center %3d,\n", uiCA, iFirstCAPass[p->rank][u1DieIdx][uiCA], iLastCAPass[p->rank][u1DieIdx][uiCA], iCenter[u1DieIdx][uiCA]));
+ #endif
+ mcFPRINTF((fp_A60501, "CA%4d Pass(%3d~%3d) Center %3d,\n", uiCA, iFirstCAPass[p->rank][u1DieIdx][uiCA], iLastCAPass[p->rank][u1DieIdx][uiCA], iCenter[u1DieIdx][uiCA]));
+ }
+
+ if(iLastCAPass[p->rank][u1DieIdx][uiCA]==CATRAINING_PASS_RANGE_NA) // no CA window found
+ {
+ vSetCalibrationResult(p, DRAM_CALIBRATION_CA_TRAIN, DRAM_FAIL);
+ }
+ }
+ }
+
+
+ if(u1LP3DieNum>1)
+ {
+ for (uiCA=0; uiCA<CATRAINING_NUM; uiCA++)
+ {
+ if(uiMR41 && ((uiCA==4) || (uiCA==9))) // MR41 is for CA0~3, CA5~8
+ {
+ continue;
+ }
+ else if((uiMR41==0) && ((uiCA!=4) && (uiCA!=9)))// MR48 is for CA4, CA9
+ {
+ continue;
+ }
+
+ mcSHOW_DBG_MSG(("CA%d |D0 (%d~%d) %d |D1 (%d~%d) %d\n", uiCA, iFirstCAPass[p->rank][0][uiCA], iLastCAPass[p->rank][0][uiCA], iCenter[0][uiCA], \
+ iFirstCAPass[p->rank][1][uiCA], iLastCAPass[p->rank][1][uiCA], iCenter[1][uiCA]));
+ }
+ }
+
+ // CS extent disable
+ // for testing
+#if (FOR_DV_SIMULATION_USED==0)
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 0, CATRAINING1_CATRAINCSEXT);
+#endif
+
+ // Wait tCACKEN (10ck)
+ mcDELAY_US(1);
+
+ if((uiMR41 && (uiFinishCount<8)) || ((uiMR41==0) && (uiFinishCount<2)))
+ {
+ mcSHOW_DBG_MSG(("Error: some bits have abnormal window, uiMR41=%d, FinishCount=%d\n", uiMR41, uiFinishCount));
+ mcFPRINTF((fp_A60501, "Error: some bits have abnormal window, uiMR41=%d, FinishCount=%d\n", uiMR41, uiFinishCount));
+ }
+}
+
+DRAM_STATUS_T CATrainingLP3(DRAMC_CTX_T *p)
+{
+ U32 uiMR41;
+ U32 u4RegBackupAddress[] =
+ {
+ (DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL)),
+ (DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0)),
+ (DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL)),
+ (DRAMC_REG_ADDR(DRAMC_REG_CKECTRL)),
+ (DRAMC_REG_ADDR(DRAMC_REG_MRS)),
+ };
+ S8 iFinalCACLK[2];
+ S8 s1CACenterDiff[CATRAINING_NUM]={0}; //for LP3_CA_PER_BIT
+ U32 module_i;
+ U8 backup_rank, rank_i;
+
+#if LP3_CATRAING_SHIFT_CLK_PI
+ U8 u1CLK_Shift_PI = 0;
+#endif
+
+ // 01010101b -> 10101010b : Golden value = 1001100110011001b=0x9999
+ // 11111111b -> 00000000b : Golden value = 0101010101010101b=0x5555
+ U32 u4GoldenPattern =0x55555555;
+ //U32 u4GoldenPattern =0xA6AAA6AA;
+
+ backup_rank = u1GetRank(p);
+
+ mcSHOW_DBG_MSG(("\n[CATrainingLP3]\n"));
+ mcFPRINTF((fp_A60501, "\n[CATrainingLP3]\n"));
+ #if MRW_CHECK_ONLY
+ mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
+ #endif
+
+ if(p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+ gu1LP3DieNum[p->rank] =2;
+ else
+ gu1LP3DieNum[p->rank] =1;
+
+ // Fix ODT off. A60501 disable ODT in the init code. So no need to do the following code.
+ //uiReg54h=u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WODT), WODT_WODTFIXOFF);
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WODT), 1, WODT_WODTFIXOFF);// According to Derping, should set to 1 to disable ODT.
+
+ // Let MIO_CK always ON.
+ DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+ vAutoRefreshSwitch(p, DISABLE); //When doing CA training, should make sure that auto refresh is disable
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 1, DRAMC_PD_CTRL_MIOCKCTRLOFF); //MIOCKCTRLOFF=1
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 0, DRAMC_PD_CTRL_PHYCLKDYNGEN); // set R_DMPHYCLKDYNGEN=0
+
+
+#ifdef CA_LAG_CK
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), SHU_SELPH_CA7_DLY_RA2) - 1, SHU_SELPH_CA7_DLY_RA2);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), SHU_SELPH_CA7_DLY_RA3) - 1, SHU_SELPH_CA7_DLY_RA3);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), SHU_SELPH_CA7_DLY_RA4) - 1, SHU_SELPH_CA7_DLY_RA4);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), SHU_SELPH_CA7_DLY_RA5) - 1, SHU_SELPH_CA7_DLY_RA5);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), SHU_SELPH_CA7_DLY_RA6) - 1, SHU_SELPH_CA7_DLY_RA6);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA7), SHU_SELPH_CA7_DLY_RA7) - 1, SHU_SELPH_CA7_DLY_RA7);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA8), u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA8), SHU_SELPH_CA8_DLY_RA8) - 1, SHU_SELPH_CA8_DLY_RA8);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA8), u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_CA8), SHU_SELPH_CA8_DLY_RA9) - 1, SHU_SELPH_CA8_DLY_RA9);
+#endif
+
+#if LP3_CA_PER_BIT
+ CATrainingSetPerBitDelayCell(p, s1CACenterDiff); //reset delay to 0
+#endif
+
+
+ // Step 1.1 : let IO to O1 path valid
+ O1PathOnOff(p, 1);
+
+ // ----- MR41, CA0~3, CA5~8 -------
+ uiMR41 = 1;
+ CATrainingEntry(p, uiMR41, u4GoldenPattern); //MR41
+ CATrainingDelayCompare(p, uiMR41, u4GoldenPattern, gu1LP3DieNum[p->rank], 0);
+
+ // ----- MR48, CA4 and 9 -------
+ uiMR41 = 0;
+ CATrainingEntry(p, uiMR41, u4GoldenPattern); //MR48
+ CATrainingDelayCompare(p, uiMR41, u4GoldenPattern, gu1LP3DieNum[p->rank], 0);
+
+ CATrainingPosCal(p, gu1LP3DieNum, iFinalCACLK, s1CACenterDiff);
+
+#if LP3_CATRAING_SHIFT_CLK_PI
+ if((iFinalCACLK[0] <-LP3_CATRAING_SHIFT_CLK_PI) || (iFinalCACLK[1] <-LP3_CATRAING_SHIFT_CLK_PI))
+ {
+ u1CLK_Shift_PI = LP3_CATRAING_SHIFT_CLK_PI <<1; // if delay <-8, CLK += 16
+ }
+ else if((iFinalCACLK[0] <0) || (iFinalCACLK[1] <0))
+ {
+ u1CLK_Shift_PI = LP3_CATRAING_SHIFT_CLK_PI ; // if delay <0, CLK += 8
+ }
+ else
+ u1CLK_Shift_PI = 0;
+
+
+ if(u1CLK_Shift_PI >0)
+ {
+ mcSHOW_ERR_MSG(("\n\n[WARNING] CA Center < 0, CLK shif +%d PI\n", u1CLK_Shift_PI));
+ mcSHOW_ERR_MSG(("Origin CA min0 = %d, CA min1 = %d\n\n", iFinalCACLK[0], iFinalCACLK[1]));
+
+ iFinalCACLK[0] += u1CLK_Shift_PI;
+ iFinalCACLK[1] += u1CLK_Shift_PI;
+
+ mcSHOW_ERR_MSG(("Updated min0 = %d, CA min1 = %d\n\n", iFinalCACLK[0], iFinalCACLK[1]));
+ }
+#endif
+
+ for(module_i=0; module_i<2; module_i++)
+ {
+ if(iFinalCACLK[module_i] <0) //don't move clk
+ {
+ mcSHOW_DBG_MSG(("warning : Macro%d minimum CA PI delay is %d(<0) and changed to 0\n", module_i, iFinalCACLK[module_i]));
+ iFinalCACLK[module_i] =0;
+ }
+ }
+
+
+ #ifdef ETT_PRINT_FORMAT
+ mcSHOW_DBG_MSG(("\nGoldenPattern 0x%X\n", u4GoldenPattern));
+ #else
+ mcSHOW_DBG_MSG(("\nGoldenPattern 0x%x\n", u4GoldenPattern));
+ #endif
+
+ #if REG_SHUFFLE_REG_CHECK
+ ShuffleRegCheck =1;
+ #endif
+
+ /* p->rank = RANK_0, save to Reg Rank0 and Rank1, p->rank = RANK_1, save to Reg Rank1 */
+ for(rank_i=RANK_0; rank_i<backup_rank+1; rank_i++)
+ {
+ // no need to enter self refresh before setting CLK under CA training mode
+ #if LP3_CATRAING_SHIFT_CLK_PI
+ CATrain_ClkDelay[p->channel][rank_i] = u1CLK_Shift_PI;
+ CATrain_CsDelay[p->channel][rank_i] = u1CLK_Shift_PI;
+ #else
+ CATrain_ClkDelay[p->channel][rank_i] = 0;
+ CATrain_CsDelay[p->channel][rank_i] = 0;
+ #endif
+
+ vSetRank(p, rank_i);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), iFinalCACLK[0], SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), iFinalCACLK[1], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), CATrain_ClkDelay[p->channel][rank_i] , SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), CATrain_CsDelay[p->channel][rank_i] , SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS);
+
+ for(module_i=0; module_i<2; module_i++)
+ {
+ mcSHOW_DBG_MSG(("Rank%d, Macro%d Clk dly: %d, CA dly: %d, CS dly: %d\n", rank_i, module_i, CATrain_ClkDelay[p->channel][rank_i], iFinalCACLK[module_i], CATrain_CsDelay[p->channel][rank_i]));
+ mcFPRINTF((fp_A60501, "Rank%d, Macro%d Clk dly: %d, CA dly: %d, CS dly: %d\n\n", rank_i, module_i, CATrain_ClkDelay[p->channel][rank_i], iFinalCACLK[module_i], CATrain_CsDelay[p->channel][rank_i]));
+ }
+
+ #if LP3_CA_PER_BIT
+ CATrainingSetPerBitDelayCell(p, s1CACenterDiff);
+ #endif
+ }
+ vSetRank(p, backup_rank);
+
+ #if REG_SHUFFLE_REG_CHECK
+ ShuffleRegCheck =0;
+ #endif
+
+ CATrainingExit(p);
+
+ // Disable fix DQ input enable. Disable IO to O1 path
+ O1PathOnOff(p, 0);
+
+ // NO need to disable CKE high and back to dynamic when calibration
+ //CKEFixOnOff(p, CKE_DYNAMIC, CKE_WRITE_TO_ONE_CHANNEL);
+
+ // Restore the registers' values.
+ DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+ mcSHOW_DBG_MSG(("\n\n"));
+
+ return DRAM_OK;
+}
+#endif
+#endif //SIMULATION_LP3_CA_TRAINING
+
+
+#if SIMUILATION_LP4_CBT
+//-------------------------------------------------------------------------
+/** CmdBusTrainingLP4
+ * start the calibrate the skew between (1) Clk pin and CAx pins. (2) Clk and CS pin (3)Vref(ca) driving
+ * @param p Pointer of context created by DramcCtxCreate.
+ * @retval status (DRAM_STATUS_T): DRAM_OK or DRAM_FAIL
+ */
+//-------------------------------------------------------------------------
+static void insertionSort(S32 a[], S32 array_size)
+{
+ S32 i, j, index;
+ for (i = 1; i < array_size; ++i)
+ {
+ index = a[i];
+ for (j = i; j > 0 && a[j-1] > index; j--)
+ a[j] = a[j-1];
+
+ a[j] = index;
+ }
+}
+
+void CBT_Switch_Freq(DRAMC_CTX_T *p, U8 freq)
+{
+#if DUAL_FREQ_K
+#if (fcFOR_CHIP_ID == fcLaurel)
+ if(freq==CBT_LOW_FREQ)
+ {
+ CBT_DramcDFSDirectJump(p, (DRAM_DFS_SHUFFLE_MAX-1));
+ }
+ else
+ {
+ CBT_DramcDFSDirectJump(p, DRAM_DFS_SHUFFLE_1);
+ }
+#else
+ #error Need check of the DRAM_DFS_SHUFFLE_X for your chip !!!
+#endif
+ //DDRPhyFreqMeter();
+#endif
+}
+
+static void vSetDramMRCBTOnOff(DRAMC_CTX_T *p, U8 u1OnOff, U8 operating_fsp)
+{
+ if(u1OnOff)
+ {
+ u1MR13Value |= 0x1; //MR13 OP[0]=1, enable CBT
+
+ // op[7] = !(p->dram_fsp), dram will switch to another FSP_OP automatically
+ if(operating_fsp)
+ u1MR13Value &= 0x7f; // OP[7] =0;
+ else
+ u1MR13Value |= 0x80; // OP[7] =1;
+
+ if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 1, WRITE_LEV_BYTEMODECBTEN); //BYTEMODECBTEN=1
+ }
+ }
+ else
+ {
+ u1MR13Value &= 0xfe; //MR13 OP[0]=0, disable CBT
+
+ if(operating_fsp)
+ u1MR13Value |= 0x80; // OP[7] =1;
+ else
+ u1MR13Value &= 0x7f; // OP[7] =0;
+ }
+ DramcModeRegWriteByRank(p, p->rank, 13, u1MR13Value);
+}
+
+void CBTEntry(DRAMC_CTX_T *p, U8 operating_fsp, U16 operation_frequency)
+{
+ //Write (DRAMC_AO_BASE+ 0xE<<2) [25] = 1b0 // disable dramc DCMEN
+ //Write (DRAMC_AO_BASE+ 0xE<<2) [30] = 1b0 // set R_DMPHYCLKDYNGEN=0
+ //Write (DRAMC_AO_BASE+ 0x80<<2) [29] = 1b0 // set R_DMDQSIENCG_NORMAL_EN=0
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), P_Fld(0, DRAMC_PD_CTRL_PHYCLKDYNGEN)| P_Fld(0, DRAMC_PD_CTRL_DCMEN));
+
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_STBCAL), 0, STBCAL_DQSIENCG_NORMAL_EN);
+
+ //Step 0.0 CKE go high (Release R_DMCKEFIXOFF, R_DMCKEFIXON=1)
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 1, DRAMC_PD_CTRL_MIOCKCTRLOFF); //MIOCKCTRLOFF=1
+
+ CKEFixOnOff(p, p->rank, CKE_FIXON, CKE_WRITE_TO_ONE_CHANNEL);
+
+ //Step 0: MRW MR13 OP[0]=1 to enable CBT
+ vSetDramMRCBTOnOff(p, ENABLE, operating_fsp);
+
+ //Step 0.1: before CKE low, Let DQS=0 by R_DMwrite_level_en=1, spec: DQS_t has to retain a low level during tDQSCKE period
+ if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE)
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 1, WRITE_LEV_WRITE_LEVEL_EN);
+ }
+
+ mcDELAY_US(1);
+
+ //Step 1.0: let CKE go low
+ CKEFixOnOff(p, p->rank, CKE_FIXOFF, CKE_WRITE_TO_ONE_CHANNEL);
+
+
+ // Step 1.1 : let IO to O1 path valid
+ if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE)
+ {
+ // Let R_DMFIXDQIEN1=1 (byte1), 0xd8[13] ==> Note: Do not enable again.
+ //Currently set in O1PathOnOff
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PADCTRL), 0x3, PADCTRL_FIXDQIEN);
+
+ // Let DDRPHY RG_RX_ARDQ_SMT_EN_B1=1 (byte1)
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ3), 1, B1_DQ3_RG_RX_ARDQ_SMT_EN_B1);
+ O1PathOnOff(p, 1);
+ }
+
+ if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+ {
+ // let IO to O1 path valid by DDRPHY RG_RX_ARDQ_SMT_EN_B0=1
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ3), 1, B0_DQ3_RG_RX_ARDQ_SMT_EN_B0);
+ O1PathOnOff(p, 1);
+ }
+}
+
+void CBTExit(DRAMC_CTX_T *p, U8 operating_fsp, U8 operation_frequency)
+{
+ if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE || p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+ {
+ //Step 1: CKE go high (Release R_DMCKEFIXOFF, R_DMCKEFIXON=1)
+ CKEFixOnOff(p, p->rank, CKE_FIXON, CKE_WRITE_TO_ONE_CHANNEL);
+
+ //Step 2:wait tCATX, wait tFC
+ mcDELAY_US(1);
+
+ //Step 3: MRW to command bus training exit (MR13 OP[0]=0 to disable CBT)
+ vSetDramMRCBTOnOff(p, DISABLE, operating_fsp);
+ }
+
+ //Step 4:
+ //Disable O1 path output
+ if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE)
+ {
+ //Let DDRPHY RG_RX_ARDQ_SMT_EN_B1=0
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ3), 0, B1_DQ3_RG_RX_ARDQ_SMT_EN_B1);
+ O1PathOnOff(p, 0);
+
+ //Let FIXDQIEN1=0 ==> Note: Do not enable again.
+ //Moved into O1PathOnOff
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PADCTRL), 0, PADCTRL_FIXDQIEN);
+ }
+
+ if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+ {
+ //Let DDRPHY RG_RX_ARDQ_SMT_EN_B0=0
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ3), 0, B0_DQ3_RG_RX_ARDQ_SMT_EN_B0);
+ O1PathOnOff(p, 0);
+
+ //Disable Byte mode CBT enable bit
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 0, WRITE_LEV_BYTEMODECBTEN); //BYTEMODECBTEN=0
+ }
+}
+
+static void CBTSetFSP(DRAMC_CTX_T *p, U8 operating_fsp, U8 final_set_flag)
+{
+ if(operating_fsp==FSP_0)
+ {
+ u1MR13Value &= ~(1<<6); //OP[6], fsp_wr=0
+ u1MR13Value &= 0x7f; // OP[7] =0;
+ }
+ else
+ {
+#if (DUAL_FREQ_K)
+ if (final_set_flag==0)
+ {
+ u1MR13Value |= (1<<6); //OP[6], fsp_wr=1
+ u1MR13Value &= 0x7f; // OP[7] =0;
+ }
+ else
+ {
+ u1MR13Value |= (1<<6); //OP[6], fsp_wr=1
+ u1MR13Value |= 0x80; // OP[7] =1;
+ }
+#else
+ u1MR13Value |= (1<<6); //OP[6], fsp_wr=1
+ u1MR13Value |= 0x80; // OP[7] =1;
+#endif
+ }
+
+ DramcModeRegWriteByRank(p, p->rank, 13, u1MR13Value);
+}
+
+static void CBTSetVref(DRAMC_CTX_T *p, U32 u2VrefLevel, U8 operating_fsp, U8 final_set_flag)
+{
+ U32 u4DbgValue;
+ U8 u1VrefValue_pinmux;
+
+ u1VrefValue_pinmux = (GetCmdBusTrainingVrefPinMuxRevertValue(p, u2VrefLevel) & 0x3f);
+
+#if !REDUCE_LOG_FOR_PRELOADER
+ mcSHOW_DBG_MSG(("\nCH_%d, RK_%d, Range=%d, VrefValue_pinmux = 0x%x\n",p->channel, p->rank, gCBT_VREF_RANGE_SEL, u1VrefValue_pinmux));
+#endif
+ mcFPRINTF((fp_A60501, "\nCBTSetVref = 0x%x\n", u2VrefLevel));
+
+
+ if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE && final_set_flag==0)
+ {
+ u1MR12Value[p->channel][p->rank][operating_fsp] = ((gCBT_VREF_RANGE_SEL&0x1) <<6) | u1VrefValue_pinmux;
+
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), ((gCBT_VREF_RANGE_SEL&0x1) <<6) | (u2VrefLevel & 0x3f), WRITE_LEV_DMVREFCA); //MR12, bit[25:20]=OP[5:0] bit 26=OP[6]
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), u2VrefLevel, WRITE_LEV_DMVREFCA); //MR12, bit[25:20]=OP[5:0] bit 26=OP[6]
+
+ //DQS_SEL=1, DQS_B1_G=1, Toggle R_DMDQS_WLEV (1 to 0)
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 1 , WRITE_LEV_DQS_SEL);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 0xa , WRITE_LEV_DQSBX_G);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 1 , WRITE_LEV_DQS_WLEV);
+ mcDELAY_US(1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 0, WRITE_LEV_DQS_WLEV);
+
+ }
+ else
+ {
+ u4DbgValue = (((gCBT_VREF_RANGE_SEL&0x1) <<6) | (u2VrefLevel & 0x3f));
+ u1MR12Value[p->channel][p->rank][operating_fsp] = u4DbgValue;
+ mcSHOW_DBG_MSG3(("u4DbgValue = 0x%x\n", u4DbgValue));
+
+ DramcModeRegWriteByRank(p, p->rank, 12, u4DbgValue);
+ }
+
+ //wait tVREF_LONG
+ mcDELAY_US(1);
+}
+
+static U32 CBTDelayCACLKCompare(DRAMC_CTX_T *p, S32 iDelay)
+{
+ U32 u4Result=0, u4Result0=0, u4Ready;
+ U32 u4TimeCnt;
+
+ u4TimeCnt = TIME_OUT_CNT;
+ if(iDelay < 0)
+ { //Set CLK delay
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), P_Fld(0, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD) |
+ P_Fld(-iDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK) |
+ P_Fld(-iDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS));
+ }
+ else if(iDelay>=64)
+ { //Set CA output delay + 2UI
+ DramcCmdUIDelaySetting(p, 2);
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), P_Fld(iDelay-64, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD) |
+ P_Fld(CLK_SHIFT_PI_DELAY, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK) |
+ P_Fld(0, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS));
+ }
+ else
+ { //Set CA output delay
+ DramcCmdUIDelaySetting(p, 0);
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), P_Fld(iDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD) |
+ P_Fld(CLK_SHIFT_PI_DELAY, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK) |
+ P_Fld(0, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS));
+ }
+
+ //Let R_DMTESTCATRAIN=1 to enable HW CAPAT Generator
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 1, CATRAINING1_TESTCATRAIN);
+
+ //Check CA training compare ready (dramc_conf_nao 0x3fc , CATRAIN_CMP_CPT)
+ do
+ {
+ u4Ready = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TCMDO1LAT), TCMDO1LAT_CATRAIN_CMP_CPT);
+ u4TimeCnt --;
+ mcDELAY_US(1);
+ }while((u4Ready==0) &&(u4TimeCnt>0));
+
+ if(u4TimeCnt==0)//time out
+ {
+ mcSHOW_DBG_MSG(("[CBTDelayCACLKCompare] Resp fail (time out)\n"));
+ mcFPRINTF((fp_A60501, "[CBTDelayCACLKCompare] Resp fail (time out)\n"));
+ //return DRAM_FAIL;
+ }
+
+ //Get CA training compare result (dramc_conf_nao 0x3fc , CATRAIN_CMP_ERR)
+ if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE)
+ {
+ u4Result = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TCMDO1LAT), TCMDO1LAT_CATRAIN_CMP_ERR);
+ }
+ else
+ {
+ u4Result0 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TCMDO1LAT), TCMDO1LAT_CATRAIN_CMP_ERR0);
+// mcSHOW_DBG_MSG(("[Francis] TCMDO1LAT_CATRAIN_CMP_ERR0=0x%x\n", u4Result0));
+ u4Result = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TCMDO1LAT), TCMDO1LAT_CATRAIN_CMP_ERR);
+// mcSHOW_DBG_MSG(("[Francis] TCMDO1LAT_CATRAIN_CMP_ERR=0x%x\n", u4Result));
+ }
+
+ //Let R_DMTESTCATRAIN=0 to disable HW CAPAT Generator
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_CATRAINING1), 0, CATRAINING1_TESTCATRAIN);
+
+ return (u4Result|u4Result0); // return pattern compre result
+}
+
+
+static U32 CBTDelayCSCompare(DRAMC_CTX_T *p, U32 uiDelay)
+{
+ U8 *uiLPDDR_O1_Mapping = NULL;
+ U32 u4Result, u4Ready;
+ U32 u4TimeCnt;
+ U32 u4dq_o1;
+ U32 u4byte_index;
+
+ u4TimeCnt = TIME_OUT_CNT;
+
+ if (u1IsLP4Family(p->dram_type))
+ {
+ uiLPDDR_O1_Mapping = (U8 *)uiLPDDR4_O1_Mapping_POP[p->channel];
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ #if (fcFOR_CHIP_ID == fcLaurel)
+ if(p->bDLP3)
+ {
+ uiLPDDR_O1_Mapping = (U8 *)uiLPDDR3_O1_Mapping_POP_DLP3;
+ }
+ else
+ #endif
+ {
+ uiLPDDR_O1_Mapping = (U8 *)uiLPDDR3_O1_Mapping_POP;
+ }
+ }
+#endif /* ENABLE_LP3_SW */
+
+ //Set CS output delay
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), uiDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS);
+ //Step 5: toggle CS/CA for CS training by R_DMTCMDEN (wait dramc_nao tcmd_response=1, disable R_DMTCMDEN), 0x1e4[5]
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_TCMDEN);
+ do
+ {
+ u4Ready = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_TCMD_RESPONSE);
+ u4TimeCnt --;
+ mcDELAY_US(1);
+ }while((u4Ready==0) &&(u4TimeCnt>0));
+
+
+ if(u4TimeCnt==0)//time out
+ {
+ mcSHOW_DBG_MSG(("[CBTDelayCSCompare] Resp fail (time out)\n"));
+ mcFPRINTF((fp_A60501, "[CBTDelayCSCompare] Resp fail (time out)\n"));
+ //return DRAM_FAIL;
+ }
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_TCMDEN);
+
+ //Step 6: check CS training result on DQ[13:8] by O1, DDRPHYCFG 0xF80
+ //Expected CA value is h2a (CA pulse width is 6UI, CS pulse is 1UI)
+ u4dq_o1 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_DQO1), MISC_DQO1_DQO1_RO);
+ u4Result = 0;
+ for(u4byte_index=8; u4byte_index<=13; u4byte_index++)
+ {
+ u4Result |= (((u4dq_o1 & (1<<uiLPDDR_O1_Mapping[u4byte_index])) >> (uiLPDDR_O1_Mapping[u4byte_index])) << (u4byte_index-8));
+ }
+ mcSHOW_DBG_MSG3(("CS Dly = %d, Result=0x%x\n", uiDelay, u4Result));
+ return u4Result; // return pattern compre result
+}
+
+#if 0 //for CBT CS test
+static U32 CBTDelayCSCompare2(DRAMC_CTX_T *p)
+{
+ U32 u4err_value, uiDelay;
+
+ for (uiDelay=0; uiDelay<=MAX_CS_PI_DELAY; uiDelay++)
+ {
+ // Set CS output delay
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_ARPI_CMD), uiDelay, ARPI_CMD_DA_ARPI_CS);
+ u4err_value= TestEngineCompare(p);
+ mcSHOW_DBG_MSG(("CBTDelayCSCompare2= %3d, u4err_value=0x%2x\n", uiDelay, u4err_value));
+ }
+
+ return DRAM_OK; // return pattern compre result
+}
+#endif
+
+#if 0
+void DramcCmdBusTrainingPostProcess(DRAMC_CTX_T *p)
+{
+ S32 iCSFinalClkDelay, iCSFinalCmdDelay, iCSFinalCSDelay;
+ U8 backup_rank, irank;
+
+ // CBT Rank0/1 must set Clk/CA/CS the same from Wei-Jen
+
+ mcSHOW_DBG_MSG(("[DramcCmdBusTrainingPostProcess] p->frequency=%d\n", p->frequency));
+
+ backup_rank = u1GetRank(p);
+
+ iCSFinalClkDelay= (CATrain_ClkDelay[p->channel][RANK_0] + CATrain_ClkDelay[p->channel][RANK_1])/2;
+ CATrain_ClkDelay[p->channel][RANK_0] = iCSFinalClkDelay;
+ CATrain_ClkDelay[p->channel][RANK_1] = iCSFinalClkDelay;
+
+ iCSFinalCmdDelay= (CATrain_CmdDelay[p->channel][RANK_0] + CATrain_CmdDelay[p->channel][RANK_1])/2;
+ CATrain_CmdDelay[p->channel][RANK_0] = iCSFinalCmdDelay;
+ CATrain_CmdDelay[p->channel][RANK_1] = iCSFinalCmdDelay;
+
+ iCSFinalCSDelay= (CATrain_CsDelay[p->channel][RANK_0] + CATrain_CsDelay[p->channel][RANK_1])/2;
+ CATrain_CsDelay[p->channel][RANK_0] = iCSFinalCSDelay;
+ CATrain_CsDelay[p->channel][RANK_1] = iCSFinalCSDelay;
+
+ for(irank=RANK_0; irank<=RANK_1; irank++)
+ {
+ vSetRank(p, irank);
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), P_Fld(iCSFinalClkDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK) |
+ P_Fld(iCSFinalCmdDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD) |
+ P_Fld(iCSFinalCSDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS));
+ }
+
+ mcSHOW_DBG_MSG(("Clk Dly = %d\nCmd Dly = %d\nCS Dly = %d\n", iCSFinalClkDelay, iCSFinalCmdDelay, iCSFinalCSDelay));
+
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==0)
+ {
+ p->pSavetimeData->u1CBTClkDelay_Save[p->channel][RANK_0]= iCSFinalClkDelay;
+ p->pSavetimeData->u1CBTClkDelay_Save[p->channel][RANK_1]= iCSFinalClkDelay;
+
+ p->pSavetimeData->u1CBTCmdDelay_Save[p->channel][RANK_0]= iCSFinalCmdDelay;
+ p->pSavetimeData->u1CBTCmdDelay_Save[p->channel][RANK_1]= iCSFinalCmdDelay;
+
+ p->pSavetimeData->u1CBTCsDelay_Save[p->channel][RANK_0]= iCSFinalCSDelay;
+ p->pSavetimeData->u1CBTCsDelay_Save[p->channel][RANK_1]= iCSFinalCSDelay;
+ }
+#endif
+
+ vSetRank(p, backup_rank);
+}
+#endif
+
+static void CBTAdjustCS(DRAMC_CTX_T *p)
+{
+ S32 iFirstCSPass, iLastCSPass, iCSFinalDelay;//iCSCenter
+ U32 uiDelay, u4ValueReadBack, u4CSWinSize;
+ U8 backup_rank, rank_i;
+
+ backup_rank = u1GetRank(p);
+
+#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_CBT)
+ if(p->femmc_Ready==1)
+ {
+ iCSFinalDelay=p->pSavetimeData->u1CBTCsDelay_Save[p->channel][p->rank];
+ }
+ else
+#endif
+ {
+ iFirstCSPass = -1;
+ iLastCSPass = -1;
+
+ for (uiDelay=0; uiDelay<=MAX_CS_PI_DELAY; uiDelay++)
+ {
+ u4ValueReadBack = CBTDelayCSCompare(p, uiDelay);
+
+ if(iFirstCSPass == -1)
+ {
+ if(u4ValueReadBack== 0x2a) // compare pass
+ {
+ iFirstCSPass = uiDelay;
+ }
+ }
+ else if(iLastCSPass == -1)
+ {
+ if(u4ValueReadBack != 0x2a) // compare fail
+ {
+ iLastCSPass = uiDelay-1;
+ }
+ else if (uiDelay ==MAX_CS_PI_DELAY)
+ {
+ iLastCSPass = uiDelay;
+ }
+ }
+
+ // Wait time before output CS pattern to DDR again.. (Review this if need to save time)
+ mcDELAY_US(1);
+ }
+
+ u4CSWinSize = iLastCSPass - iFirstCSPass + (iLastCSPass==iFirstCSPass?0:1);
+
+ if(u4CSWinSize > ((MAX_CS_PI_DELAY+1)>>1)) // if winSize >32, CS delay= winSize -32.
+ {
+ iCSFinalDelay = u4CSWinSize -((MAX_CS_PI_DELAY+1)>>1);
+ }
+ else ///TODO: need to delay CLK? A60817 and A60501 cannot move CLK PI due to multi_phase problem.
+ {
+ iCSFinalDelay =0;
+ }
+
+ CATrain_CsDelay[p->channel][p->rank] = iCSFinalDelay;
+ mcSHOW_DBG_MSG(("\nCS Dly= %d (%d-%d-32)\n", iCSFinalDelay, iLastCSPass, iFirstCSPass));
+ mcFPRINTF((fp_A60501, "\nCS Dly= %d (%d-%d-32)\n", iCSFinalDelay, iLastCSPass, iFirstCSPass));
+
+ // if dual rank, use average position of both rank
+ if(backup_rank == RANK_1)
+ {
+ iCSFinalDelay = (CATrain_CsDelay[p->channel][RANK_0] + CATrain_CsDelay[p->channel][RANK_1])/2;
+ }
+ }
+ //Set CS output delay after training
+ /* p->rank = RANK_0, save to Reg Rank0 and Rank1, p->rank = RANK_1, save to Reg Rank1 */
+ for(rank_i=RANK_0; rank_i<backup_rank+1; rank_i++)
+ {
+ vSetRank(p, rank_i);
+
+ #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==0)
+ {
+ p->pSavetimeData->u1CBTCsDelay_Save[p->channel][p->rank]= iCSFinalDelay;
+ }
+ #endif
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), iCSFinalDelay, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS);
+ CATrain_CsDelay[p->channel][rank_i]= iCSFinalDelay;
+ //mcSHOW_DBG_MSG(("\n[CBTAdjustCS] RK%d ,CS Dly: %d\n",rank_i, iCSFinalDelay));
+ }
+ vSetRank(p, backup_rank);
+}
+
+static void CBTSetCACLKResult(DRAMC_CTX_T *p, S8 s1FinalCACLK, S8 *ps1CACenterDiff)
+{
+ U8 backup_rank, rank_i;
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ U8 uiCA;
+#endif
+
+ backup_rank = u1GetRank(p);
+
+ /* p->rank = RANK_0, save to Reg Rank0 and Rank1, p->rank = RANK_1, save to Reg Rank1 */
+ for(rank_i=RANK_0; rank_i<backup_rank+1; rank_i++)
+ {
+ vSetRank(p, rank_i);
+
+ #if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_CBT)
+ if(p->femmc_Ready==1)
+ {
+ CATrain_ClkDelay[p->channel][p->rank]=p->pSavetimeData->u1CBTClkDelay_Save[p->channel][p->rank];
+ CATrain_CmdDelay[p->channel][p->rank]=p->pSavetimeData->u1CBTCmdDelay_Save[p->channel][p->rank];
+
+ #if CA_PER_BIT_DELAY_CELL
+ for (uiCA = 0; uiCA < CATRAINING_NUM_LP4; uiCA++)
+ {
+ ps1CACenterDiff[uiCA] = p->pSavetimeData->u1CBTCA_PerBit_DelayLine_Save[p->channel][p->rank][uiCA];
+ }
+ #endif
+
+ vSetCalibrationResult(p, DRAM_CALIBRATION_CA_TRAIN, DRAM_OK); // set default result OK, udpate status when per bit fail
+ }
+ else
+ #endif
+ {
+ CATrain_ClkDelay[p->channel][p->rank] = CLK_SHIFT_PI_DELAY;
+
+ if(s1FinalCACLK<0)
+ {
+ CATrain_CmdDelay[p->channel][p->rank] = 0;
+ }
+ else
+ {
+ if(s1FinalCACLK>=64)
+ CATrain_CmdDelay[p->channel][p->rank] = s1FinalCACLK-64;
+ else
+ CATrain_CmdDelay[p->channel][p->rank] = s1FinalCACLK;
+ }
+ }
+
+ //mcSHOW_DBG_MSG(("[CBTSetCACLKResult]Rank%d, Clk dly= %d, CA dly= %d\n", rank_i, CATrain_ClkDelay[p->channel][p->rank], CATrain_CmdDelay[p->channel][p->rank]));
+ //mcFPRINTF((fp_A60501, "[CBTSetCACLKResult]Rank%d, Clk dly= %d, CA dly= %d\n", rank_i, CATrain_ClkDelay[p->channel][p->rank], CATrain_CmdDelay[p->channel][p->rank]));
+ if(s1FinalCACLK<64)
+ {
+ DramcCmdUIDelaySetting(p, 0);
+ }
+ else
+ {
+ DramcCmdUIDelaySetting(p, 2);
+ }
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), P_Fld(CATrain_CmdDelay[p->channel][p->rank], SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD) |
+ P_Fld(CATrain_ClkDelay[p->channel][p->rank], SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK));
+
+ #if CA_PER_BIT_DELAY_CELL
+ CATrainingSetPerBitDelayCell(p, ps1CACenterDiff);
+ #endif
+
+
+ #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==0)
+ {
+ p->pSavetimeData->u1CBTClkDelay_Save[p->channel][p->rank]= CATrain_ClkDelay[p->channel][p->rank];
+ p->pSavetimeData->u1CBTCmdDelay_Save[p->channel][p->rank]= CATrain_CmdDelay[p->channel][p->rank];
+
+ #if CA_PER_BIT_DELAY_CELL
+ for (uiCA = 0; uiCA < CATRAINING_NUM_LP4; uiCA++)
+ {
+ p->pSavetimeData->u1CBTCA_PerBit_DelayLine_Save[p->channel][p->rank][uiCA] = ps1CACenterDiff[uiCA];
+ }
+
+#endif
+ }
+ #endif
+ }
+
+ vSetRank(p, backup_rank);
+
+#if EYESCAN_LOG
+ gEyeScan_CaliDelay[0] = CATrain_CmdDelay[p->channel][p->rank] + (CBT_MOVE_CA_INSTEAD_OF_CLK==0?MAX_CLK_PI_DELAY:0);
+#endif
+}
+
+
+U8 GetCmdBusTrainingVrefPinMuxValue(DRAMC_CTX_T *p, U8 u1VrefLevel)
+{
+ U8 u2VrefBit, u2Vref_new, u2Vref_org;
+
+ if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1) return ((gCBT_VREF_RANGE_SEL&0x1) <<6) | (u1VrefLevel & 0x3f);
+
+
+ u2Vref_new = 0;
+ u2Vref_org = ((gCBT_VREF_RANGE_SEL&0x1) <<6) | (u1VrefLevel & 0x3f);
+ for (u2VrefBit = 0; u2VrefBit < 8; u2VrefBit++)
+ {
+// mcSHOW_DBG_MSG(("=== u2VrefBit: %d, %d\n",u2VrefBit,uiLPDDR4_O1_Mapping_POP[p->channel][u2VrefBit]));
+ if (u2Vref_org & (1 << u2VrefBit))
+ {
+ u2Vref_new |= (1 << uiLPDDR4_O1_Mapping_POP[p->channel][u2VrefBit]);
+// mcSHOW_DBG_MSG(("=== u2VrefBit: %d, %d, u2Vref_org: %x, u2Vref_new: 0x%x\n",u2VrefBit,uiLPDDR4_O1_Mapping_POP[p->channel][u2VrefBit],u2Vref_org,u2Vref_new));
+ }
+ }
+
+ mcSHOW_DBG_MSG3(("=== u2Vref_new: 0x%x --> 0x%x\n",u2Vref_org,u2Vref_new));
+
+ return u2Vref_new;
+}
+
+U8 GetCmdBusTrainingVrefPinMuxRevertValue(DRAMC_CTX_T *p, U8 u1VrefLevel)
+{
+ U8 u2VrefBit, u2Vref_new, u2Vref_org;
+
+ if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1) return u1VrefLevel;
+
+ u2Vref_new = 0;
+ u2Vref_org = u1VrefLevel;
+ for (u2VrefBit = 0; u2VrefBit < 8; u2VrefBit++)
+ {
+ u2Vref_new |= ((u2Vref_org>>uiLPDDR4_O1_Mapping_POP[p->channel][u2VrefBit])&1) << u2VrefBit;
+ }
+
+ mcSHOW_DBG_MSG3(("=== Revert u2Vref_new: 0x%x --> 0x%x\n",u2Vref_org,u2Vref_new));
+
+ return u2Vref_new;
+}
+
+
+DRAM_STATUS_T CmdBusTrainingLP4(DRAMC_CTX_T *p)
+{
+ U16 u1VrefLevel, uiFinalVref;
+ U32 u4CompareResult;
+ PASS_WIN_DATA_T FinalWinPerCA[CATRAINING_NUM_LP4];
+ U32 uiCA, uiFinishCount, uiTemp;
+ S16 iDelay;
+#if CBT_SPEED_UP_CALIBRATION
+ U8 all_first_pass_flag=0, already_speed_up_flag=0;
+#endif
+
+ S32 iFirstPass_temp[CATRAINING_NUM_LP4], iLastPass_temp[CATRAINING_NUM_LP4];
+ U32 uiCAWinSum, uiCAWinSumMax;
+ //S32 iCACenter[CATRAINING_NUM_LP4] = {0}, iCACenterSum = 0, iCAFinalCenter[CATRAINING_NUM_LP4] = {0};
+ U8 operating_fsp;
+ U16 operation_frequency;
+ U8 irange, irange_start, irange_end;
+ U16 uiFinalRange=0;
+ U8 u1CBTEyeScanEnable;
+
+ S8 iFinalCACLK;
+ S8 s1CACenterDiff[CATRAINING_NUM]={0}; //for CA_PER_BIT
+
+#if EYESCAN_LOG
+ U8 EyeScan_index[CATRAINING_NUM_LP4];
+#endif
+ U32 u4RegBackupAddress[] =
+ {
+ (DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL)),
+ (DRAMC_REG_ADDR(DRAMC_REG_STBCAL)),
+ (DRAMC_REG_ADDR(DRAMC_REG_CKECTRL)),
+ (DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV)),
+ (DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0)),
+ (DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL)),
+ };
+
+#if MRW_CHECK_ONLY
+ mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
+#endif
+
+ u1CBTEyeScanEnable = (gCBT_EYE_Scan_flag==1 && ((gCBT_EYE_Scan_only_higheset_freq_flag==1 && p->frequency == u2DFSGetHighestFreq(p)) || gCBT_EYE_Scan_only_higheset_freq_flag==0));
+
+#if EYESCAN_LOG
+ U32 u1vrefidx, ii;
+
+ if (u1IsLP4Family(p->dram_type))
+ {
+ for(u1vrefidx=0; u1vrefidx<VREF_TOTAL_NUM_WITH_RANGE;u1vrefidx++)
+ {
+ for (uiCA = 0; uiCA < CATRAINING_NUM_LP4; uiCA++)
+ {
+ for(ii=0; ii<EYESCAN_BROKEN_NUM; ii++)
+ {
+ gEyeScan_Min[u1vrefidx][uiCA][ii] = EYESCAN_DATA_INVALID;
+ gEyeScan_Max[u1vrefidx][uiCA][ii] = EYESCAN_DATA_INVALID;
+ }
+
+ FinalWinPerCA[uiCA].first_pass = EYESCAN_DATA_INVALID;
+ FinalWinPerCA[uiCA].last_pass = EYESCAN_DATA_INVALID;
+ FinalWinPerCA[uiCA].win_center = 0;
+ FinalWinPerCA[uiCA].win_size = 0;
+ }
+ }
+ }
+#endif
+
+ //Back up dramC register
+ DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+ vAutoRefreshSwitch(p, DISABLE); //When doing CA training, should make sure that auto refresh is disable
+
+ //tx_rank_sel is selected by SW //Lewis@20180509: tx_rank_sel is selected by SW in CBT if TMRRI design has changed.
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), p->rank, RKCFG_TXRANK);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 1, RKCFG_TXRANKFIX); //TXRANKFIX should be write after TXRANK
+
+ //SW variable initialization
+ uiCAWinSumMax=0;
+ uiFinalVref=u1MR12Value[p->channel][p->rank][p->dram_fsp] & 0x3f;
+ iFinalCACLK=0;
+ operating_fsp = p->dram_fsp;
+ operation_frequency = p->frequency;
+ #if CA_PER_BIT_DELAY_CELL
+ CATrainingSetPerBitDelayCell(p, s1CACenterDiff);
+ #endif
+
+
+ if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE)
+ {
+ //switch to low freq
+ if (operating_fsp == FSP_1)
+ {
+ CBT_Switch_Freq(p, CBT_LOW_FREQ);
+ }
+ //Step 1: Enter Command Bus Training Mode
+ CBTEntry(p, operating_fsp, operation_frequency);
+ //Step 2: wait tCAENT
+ mcDELAY_US(1);
+ //switch to high freq
+ if (operating_fsp == FSP_1)
+ {
+ CBT_Switch_Freq(p, CBT_HIGH_FREQ);
+ }
+ }
+
+#if PINMUX_AUTO_TEST_PER_BIT_CA
+#if ENABLE_LPDDR4
+ CheckCADelayCell(p);
+#endif
+#endif
+
+#if VENDER_JV_LOG
+ vPrintCalibrationBasicInfo_ForJV(p);
+#else
+ vPrintCalibrationBasicInfo(p);
+#endif
+
+ //Step 3: set CBT range, verify range and setp
+#if (SW_CHANGE_FOR_SIMULATION ||FOR_DV_SIMULATION_USED)
+ gCBT_VREF_RANGE_SEL = 0; //MR12,OP[6]
+ irange_start=irange_end=0;
+ gCBT_VREF_RANGE_BEGIN = 0;
+ gCBT_VREF_RANGE_END = 2; // binary 110010
+ gCBT_VREF_RANGE_STEP = 2;
+#else
+ gCBT_VREF_RANGE_SEL = 1; //MR12,OP[6]
+ irange_start=irange_end=1;
+ gCBT_VREF_RANGE_STEP = 2;
+
+ if (p->enable_cbt_scan_vref == DISABLE_VREF_SCAN)
+ {
+ gCBT_VREF_RANGE_BEGIN = (u1MR12Value[p->channel][p->rank][p->dram_fsp] & 0x3f);
+ gCBT_VREF_RANGE_END = gCBT_VREF_RANGE_BEGIN;
+ }
+ else
+ {
+ if (p->dram_type == TYPE_LPDDR4)
+ {
+ //range 1
+ gCBT_VREF_RANGE_BEGIN = 13 - 5; // 300/1100(VDDQ) = 27.2%
+ gCBT_VREF_RANGE_END = 13 + 5;
+ }
+ else
+ {
+ //range 1
+ gCBT_VREF_RANGE_BEGIN = 27 - 5; // 290/600(VDDQ)=48.3%
+ gCBT_VREF_RANGE_END = 27 + 5;
+ }
+ }
+#endif
+
+ if (u1CBTEyeScanEnable)
+ {
+ irange_start = 0;
+ irange_end = 1;
+ }
+
+ for(irange=irange_start; irange<=irange_end; irange++)
+ {
+ if (u1CBTEyeScanEnable)
+ {
+ gCBT_VREF_RANGE_SEL = irange;
+ gCBT_VREF_RANGE_BEGIN = 0;
+ gCBT_VREF_RANGE_END = 50;
+ gCBT_VREF_RANGE_STEP = 1;
+
+ if (gCBT_VREF_RANGE_SEL == 1)
+ {
+ gCBT_VREF_RANGE_BEGIN = 21;
+ }
+ }
+
+#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_VREF_CAL)
+ if(p->femmc_Ready==1)
+ {
+ mcSHOW_DBG_MSG(("\n[FAST_K] BYPASS_VREF_CAL CBT\n"));
+ }
+ else
+#endif
+ {
+ for(u1VrefLevel = gCBT_VREF_RANGE_BEGIN; u1VrefLevel<=gCBT_VREF_RANGE_END; u1VrefLevel+=gCBT_VREF_RANGE_STEP)
+ {
+#if EYESCAN_LOG
+ for (uiCA = 0; uiCA < CATRAINING_NUM_LP4; uiCA++)
+ {
+ gEyeScan_DelayCellPI[uiCA] = 0;
+ EyeScan_index[uiCA] = 0;
+ }
+#endif
+
+ //VREFCA = you want
+ {
+ if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+ {
+#if (FOR_DV_SIMULATION_USED==0)
+ //switch to low freq
+ if (operating_fsp == FSP_1)
+ {
+ CBT_Switch_Freq(p, CBT_LOW_FREQ);
+ }
+#endif
+ CBTSetFSP(p, operating_fsp, 0);
+ }
+ CBTSetVref(p, GetCmdBusTrainingVrefPinMuxValue(p, u1VrefLevel), operating_fsp, 0);
+ }
+
+#if VENDER_JV_LOG
+ mcSHOW_DBG_MSG5(("\n\tLP4 CBT VrefRange %d, VrefLevel=%d\n", gCBT_VREF_RANGE_SEL, u1VrefLevel));
+#endif
+ if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+ {
+ //Step 1: Enter Command Bus Training Mode
+ CBTEntry(p, operating_fsp, operation_frequency);
+ //Step 2: wait tCAENT
+ mcDELAY_US(1);
+
+#if (FOR_DV_SIMULATION_USED==0)
+ //switch to high freq
+ if (operating_fsp == FSP_1)
+ {
+ CBT_Switch_Freq(p, CBT_HIGH_FREQ);
+ }
+#endif
+ }
+ // Delay CA output delay to do CA training in order to get the pass window.
+ // moving CA relative to CK and repeating until CA is centered on the latching edge of CK
+ // Note !!!!!!!!!!!!!!!!!!!!!!!
+ // Assume : Leave clk as the init value and adjust CA delay only can find out each CA window including of the left boundary.
+ // If NOT, we may need to off-line adjust 0x404 SELPH2_TXDLY_CMD
+ // SW variable initialization
+ uiFinishCount = 0;
+ uiCAWinSum = 0;
+#if CBT_SPEED_UP_CALIBRATION
+ already_speed_up_flag = 0;
+#endif
+ for (uiCA=0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+ {
+ iLastPass_temp[uiCA] = PASS_RANGE_NA;
+ iFirstPass_temp[uiCA] = PASS_RANGE_NA;
+ }
+
+#if CBT_MOVE_CA_INSTEAD_OF_CLK
+ for (iDelay=0; iDelay<=MAX_CA_PI_DELAY; iDelay++)
+#else
+ for (iDelay= (-MAX_CLK_PI_DELAY); iDelay<=MAX_CA_PI_DELAY; iDelay++)
+#endif
+ {
+ u4CompareResult= CBTDelayCACLKCompare(p, iDelay);
+
+ //Wait tCACD(22clk) before output CA pattern to DDR again..
+ mcDELAY_US(1);
+
+ mcSHOW_DBG_MSG3(("CBTDelayCACLK Delay= %d, CompareResult 0x%x\n", iDelay, u4CompareResult));
+ mcFPRINTF((fp_A60501, "CBTDelayCACLK Delay = %d, CompareResult 0x%x\n", iDelay, u4CompareResult));
+
+ for (uiCA=0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+ {
+ if((iFirstPass_temp[uiCA] != PASS_RANGE_NA) && (iLastPass_temp[uiCA] != PASS_RANGE_NA))
+ {
+ continue;
+ }
+
+ uiTemp = (u4CompareResult >>uiCA) & 0x1; //Get Each bit of CA result
+
+ if(iFirstPass_temp[uiCA] == PASS_RANGE_NA)
+ {
+ if(uiTemp==0) //compare correct: pass
+ {
+ iFirstPass_temp[uiCA] = iDelay;
+ }
+ }
+ else if(iLastPass_temp[uiCA] == PASS_RANGE_NA)
+ {
+ if(uiTemp==1) //compare error : fail
+ {
+ #if CBT_SPEED_UP_CALIBRATION
+ if (already_speed_up_flag==1)
+ {
+ // fra : if test fail after first step of speed up, then show warning message
+ mcSHOW_ERR_MSG(("[CBT] CA=%d, fail after speed up! iDelay=%d !!\n", uiCA, iDelay));
+ #if __ETT__
+ while(1);
+ #endif
+ }
+ #endif
+
+ if ((iDelay-iFirstPass_temp[uiCA]) < 5) //prevent glitch
+ {
+ iFirstPass_temp[uiCA] = PASS_RANGE_NA;
+ continue;
+ }
+
+ iLastPass_temp[uiCA] = (iDelay-1);
+ }
+ else if (iDelay==MAX_CA_PI_DELAY)
+ {
+ iLastPass_temp[uiCA] = iDelay;
+ }
+
+ if(iLastPass_temp[uiCA] !=PASS_RANGE_NA)
+ {
+ uiFinishCount++;
+ uiCAWinSum += (iLastPass_temp[uiCA] -iFirstPass_temp[uiCA]); //Sum of CA Windows for vref selection
+ //iCACenter[uiCA] = (iLastPass_temp[uiCA] +iFirstPass_temp[uiCA])>>1; //window center of each CA bit
+ //iCACenterSum += iCACenter[uiCA];
+#if !REDUCE_LOG_FOR_PRELOADER
+ mcSHOW_DBG_MSG(("\n[CA %d] Center %d (%d~%d)\n", uiCA, iCACenter[uiCA] , iFirstPass_temp[uiCA], iLastPass_temp[uiCA]));
+#endif
+#if EYESCAN_LOG
+ if (EyeScan_index[uiCA] < EYESCAN_BROKEN_NUM)
+ {
+ gEyeScan_Min[u1VrefLevel+irange*30][uiCA][EyeScan_index[uiCA]] = iFirstPass_temp[uiCA]+(CBT_MOVE_CA_INSTEAD_OF_CLK==0?MAX_CLK_PI_DELAY:0);
+ gEyeScan_Max[u1VrefLevel+irange*30][uiCA][EyeScan_index[uiCA]] = iLastPass_temp[uiCA]+(CBT_MOVE_CA_INSTEAD_OF_CLK==0?MAX_CLK_PI_DELAY:0);
+ mcSHOW_DBG_MSG3(("u2VrefLevel=%d, u2VrefRange=%d, %d, uiCA=%d, index=%d (%d, %d)==\n",u1VrefLevel, irange, u1VrefLevel+irange*30, uiCA, EyeScan_index[uiCA], gEyeScan_Min[u1VrefLevel+irange*30][uiCA][EyeScan_index[uiCA]], gEyeScan_Max[u1VrefLevel+irange*30][uiCA][EyeScan_index[uiCA]]));
+ EyeScan_index[uiCA]=EyeScan_index[uiCA]+1;
+ }
+#endif
+ }
+ }
+ }
+
+
+#if CBT_SPEED_UP_CALIBRATION
+ if (!u1CBTEyeScanEnable)
+ {
+ if (already_speed_up_flag==0)
+ {
+ all_first_pass_flag=0;
+ for (uiCA = 0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+ {
+ if (iFirstPass_temp[uiCA] != PASS_RANGE_NA && (iDelay-iFirstPass_temp[uiCA]) >= 5) //prevent glitch
+ {
+ all_first_pass_flag|=1<<uiCA;
+ }
+ }
+
+ if (all_first_pass_flag==0x3f)
+ {
+ // fra : speed up 30 steps to save K time
+ iDelay+=30;
+ already_speed_up_flag = 1;
+ }
+ }
+ else
+ {
+ already_speed_up_flag=2; //the check fail of first step after already speed up done.
+ }
+ }
+#endif
+
+ if(uiFinishCount == CATRAINING_NUM_LP4)
+ break;
+ }
+#if VENDER_JV_LOG
+ for (uiCA=0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+ {
+ mcSHOW_DBG_MSG5(("CBT Bit%d, CA window %d ps\n", uiCA, (iLastPass_temp[uiCA]-iFirstPass_temp[uiCA]+1)*1000000/p->frequency/64));
+ }
+#endif
+
+ //set CK/CS pi delay to 0 and set CA pi delay to center
+ #if CBT_MOVE_CA_INSTEAD_OF_CLK
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), P_Fld(0x20, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD) | P_Fld(CLK_SHIFT_PI_DELAY, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK) | P_Fld(0, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS));
+ #else
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), P_Fld(0, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD) | P_Fld(CLK_SHIFT_PI_DELAY, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK) | P_Fld(0, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS));
+ #endif
+
+#if !REDUCE_LOG_FOR_PRELOADER
+ mcSHOW_DBG_MSG(("\n[CmdBusTrainingLP4] CAWinSum: %d\n", uiCAWinSum));
+#endif
+ if(uiCAWinSum > uiCAWinSumMax)
+ {
+ uiCAWinSumMax =uiCAWinSum;
+ uiFinalVref = u1VrefLevel;
+ if (u1CBTEyeScanEnable) uiFinalRange = gCBT_VREF_RANGE_SEL;
+
+ for (uiCA=0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+ {
+ FinalWinPerCA[uiCA].first_pass = iFirstPass_temp[uiCA];
+ FinalWinPerCA[uiCA].last_pass = iLastPass_temp[uiCA];
+ }
+ }
+
+#if EYESCAN_LOG
+ for (uiCA=0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+ {
+ gEyeScan_WinSize[u1VrefLevel+irange*30][uiCA] = (iLastPass_temp[uiCA] - iFirstPass_temp[uiCA])+(iLastPass_temp[uiCA]==iFirstPass_temp[uiCA]?0:1);
+ }
+#endif
+ if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+ {
+#if (FOR_DV_SIMULATION_USED==0)
+ //switch to low freq
+ if (operating_fsp == FSP_1)
+ {
+ CBT_Switch_Freq(p, CBT_LOW_FREQ);
+ }
+#endif
+ //Step 1: Enter Command Bus Training Mode
+ CBTExit(p, operating_fsp, operation_frequency);
+ //Step 2: wait tCAENT
+ mcDELAY_US(1);
+ }
+
+ if (gCBT_EYE_Scan_flag == 0)
+ {
+ if(uiCAWinSum < (uiCAWinSumMax*95/100))
+ {
+ mcSHOW_DBG_MSG(("\nCBT Vref found, early break!\n"));
+ break;//max vref found, early break;
+ }
+ }
+ }
+ }
+ }
+
+ if (u1CBTEyeScanEnable)
+ gCBT_VREF_RANGE_SEL = uiFinalRange;
+
+#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_VREF_CAL)
+ if(p->femmc_Ready==0)
+#endif
+ {
+ for (uiCA=0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+ {
+ FinalWinPerCA[uiCA].win_center = (FinalWinPerCA[uiCA].first_pass + FinalWinPerCA[uiCA].last_pass)/2;
+ FinalWinPerCA[uiCA].win_size = (FinalWinPerCA[uiCA].last_pass - FinalWinPerCA[uiCA].first_pass)+(FinalWinPerCA[uiCA].last_pass==FinalWinPerCA[uiCA].first_pass?0:1);
+
+ #if 1//CA_PER_BIT_DELAY_CELL
+ iFirstCAPass[p->rank][0][uiCA] = FinalWinPerCA[uiCA].first_pass;
+ iLastCAPass[p->rank][0][uiCA] = FinalWinPerCA[uiCA].last_pass;
+ #endif
+
+ #ifdef FOR_HQA_TEST_USED
+ gFinalCBTCA[p->channel][p->rank][uiCA] = FinalWinPerCA[uiCA].win_size;
+ #endif
+
+ #if PINMUX_AUTO_TEST_PER_BIT_CA
+ gFinalCAPerbitFirstPass[p->channel][p->rank][uiCA] = FinalWinPerCA[uiCA].first_pass;
+ #endif
+
+ mcSHOW_DBG_MSG(("[CA %d] Center %d (%d~%d) winsize %d\n", uiCA, FinalWinPerCA[uiCA].win_center , FinalWinPerCA[uiCA].first_pass, FinalWinPerCA[uiCA].last_pass, FinalWinPerCA[uiCA].win_size));
+ }
+
+#ifdef FOR_HQA_REPORT_USED
+ if (gHQALog_flag==1)
+ {
+ mcSHOW_DBG_MSG(("\n"));
+ for (uiCA=0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+ {
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_2, "CA_Center", uiCA, FinalWinPerCA[uiCA].win_center, NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_2, "CA_Window", uiCA, FinalWinPerCA[uiCA].win_size, NULL);
+ }
+ }
+#endif
+
+ #if 1//CA_PER_BIT_DELAY_CELL
+ // LP4 has already consider two dies. No more position calculation of 2 dies.
+ gu1LP3DieNum[p->rank] =1;
+ CATrainingPosCal(p, gu1LP3DieNum, &iFinalCACLK, s1CACenterDiff);
+ #else
+ #if SW_CHANGE_FOR_SIMULATION
+ iFinalCACLK =(int)((float) iCACenterSum/(float)CATRAINING_NUM_LP4);
+ #else
+ iFinalCACLK = iCACenterSum/CATRAINING_NUM_LP4;
+ #endif
+ #endif
+ }
+
+#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_VREF_CAL)
+ if(p->femmc_Ready==1 )
+ {
+ uiFinalVref = p->pSavetimeData->u1CBTVref_Save[p->channel][p->rank];
+ }
+#endif
+
+#ifdef DEVIATION
+ if (p->frequency == u2DFSGetHighestFreq(p) && gSetSpecificedVref_Enable[0]==ENABLE && ((p->channel==gSetSpecificedVref_Channel[0] && p->rank==gSetSpecificedVref_Rank[0]) || gSetSpecificedVref_All_ChRk[0]==ENABLE))
+ {
+ uiFinalRange = gCBT_VREF_RANGE_SEL;
+ DeviationAddVrefOffset(0, &uiFinalRange, &uiFinalVref, gSetSpecificedVref_Vref_Offset[0]);
+ gCBT_VREF_RANGE_SEL = (U8) uiFinalRange;
+ }
+#endif
+
+ //Set Vref after trainging
+ if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+ {
+#if (FOR_DV_SIMULATION_USED==0)
+ //switch to low freq
+ if (operating_fsp == FSP_1)
+ {
+ CBT_Switch_Freq(p, CBT_LOW_FREQ);
+ }
+#endif
+ CBTSetFSP(p, operating_fsp, 1);
+ CBTSetVref(p, GetCmdBusTrainingVrefPinMuxValue(p,uiFinalVref), operating_fsp, 1);
+ }
+ else
+ {
+ CBTSetVref(p, GetCmdBusTrainingVrefPinMuxValue(p,uiFinalVref), operating_fsp, 0); //Francis, normol mode go DQ pin set vref, don't set final_set_flag here
+ }
+
+ mcSHOW_DBG_MSG(("\nVref(ca) range %d: %d\n", gCBT_VREF_RANGE_SEL, uiFinalVref));
+ mcFPRINTF((fp_A60501, "\nVref(ca) is Range %d: %d\n", gCBT_VREF_RANGE_SEL, uiFinalVref));
+#if VENDER_JV_LOG
+ mcSHOW_DBG_MSG5(("\nVref(ca) range %d: %d\n", gCBT_VREF_RANGE_SEL, uiFinalVref));
+#endif
+
+#ifdef FOR_HQA_TEST_USED
+ gFinalCBTVrefCA[p->channel][p->rank] = uiFinalVref & 0x3f;
+#endif
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==0)
+ {
+ p->pSavetimeData->u1CBTVref_Save[p->channel][p->rank]= uiFinalVref;
+ }
+#endif
+
+ if (p->dram_cbt_mode[p->rank] == CBT_BYTE_MODE1)
+ {
+ //Step 1: Enter Command Bus Training Mode
+ CBTEntry(p, operating_fsp, operation_frequency);
+ //Step 2: wait tCAENT
+ mcDELAY_US(1);
+
+#if (FOR_DV_SIMULATION_USED==0)
+ //switch to high freq
+ if (operating_fsp == FSP_1)
+ {
+ CBT_Switch_Freq(p, CBT_HIGH_FREQ);
+ }
+#endif
+ }
+
+ //Set CLK and CA delay in CBT mode to prevent dram abnormal.
+ CBTSetCACLKResult(p, iFinalCACLK, s1CACenterDiff);
+
+ //wait tVREF_LONG
+ mcDELAY_US(1);
+
+ //------------- CS and CLK ----------
+ CBTAdjustCS(p);
+
+//------- Going to exit Command bus training(CBT) mode.-------------
+#if (FOR_DV_SIMULATION_USED==0)
+ //switch to low freq
+ if (operating_fsp == FSP_1)
+ {
+ CBT_Switch_Freq(p, CBT_LOW_FREQ);
+ }
+#endif
+
+#if EYESCAN_LOG || defined(FOR_HQA_TEST_USED)
+ gFinalCBTVrefDQ[p->channel][p->rank] = uiFinalVref;
+#endif
+
+ CBTExit(p, operating_fsp, operation_frequency);
+
+ if (p->dram_cbt_mode[p->rank] == CBT_NORMAL_MODE)
+ {
+ CBTSetFSP(p, operating_fsp, 1);
+ CBTSetVref(p, uiFinalVref, operating_fsp, 1); //francis, normal mode go MR12 set vref again, set final_set_flag to force to MR12 flow
+ }
+
+#if (FOR_DV_SIMULATION_USED==0)
+ //switch to high freq
+ if (operating_fsp == FSP_1)
+ {
+ CBT_Switch_Freq(p, CBT_HIGH_FREQ);
+ }
+#endif
+
+ if((p->rank+1) == p->support_rank_num) // both rank calibration done.
+ {
+ mcSHOW_DBG_MSG(("\n[CmdBusTrainingLP4] Final result for both ranks\nClk dly= %d PI\nCA dly= %d PI\nCS dly= %d PI\n\n", CATrain_ClkDelay[p->channel][p->rank], CATrain_CmdDelay[p->channel][p->rank], CATrain_CsDelay[p->channel][p->rank]));
+ mcFPRINTF((fp_A60501, "\n[CmdBusTrainingLP4] Final result for both ranks\nClk dly= %d PI\nCA dly= %d PI\nCS dly=%d PI\n\n", CATrain_ClkDelay[p->channel][p->rank], CATrain_CmdDelay[p->channel][p->rank], CATrain_CsDelay[p->channel][p->rank]));
+ }
+ mcSHOW_DBG_MSG3(("\n[CmdBusTrainingLP4] Done\n"));
+ mcFPRINTF((fp_A60501, "\n[CmdBusTrainingLP4] Done\n"));
+
+ //tx_rank_sel is selected by HW //Lewis@20180509: tx_rank_sel is selected by SW in CBT if TMRRI design has changed.
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANK);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANKFIX); //TXRANKFIX should be write after TXRANK
+
+ //Restore setting registers
+ DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+ return DRAM_OK;
+}
+#endif //SIMUILATION_LP4_CBT
+
+//-------------------------------------------------------------------------
+/** DramcWriteLeveling
+ * start Write Leveling Calibration.
+ * @param p Pointer of context created by DramcCtxCreate.
+ * @param apply (U8): 0 don't apply the register we set 1 apply the register we set ,default don't apply.
+ * @retval status (DRAM_STATUS_T): DRAM_OK or DRAM_FAIL
+ */
+//-------------------------------------------------------------------------
+#define WRITE_LEVELING_MOVD_DQS 1//UI
+
+
+// NOT suitable for Gating delay
+static DRAM_STATUS_T ExecuteMoveDramCDelay(DRAMC_CTX_T *p, REG_TRANSFER_T regs[], S8 iShiftUI)
+{
+ S32 s4HighLevelDelay, s4DelaySum;
+ U32 u4Tmp0p5T, u4Tmp2T;
+ U8 ucDataRateDivShift = 0;
+ DRAM_STATUS_T MoveResult;
+
+ if (u1IsLP4Family(p->dram_type))
+ {
+ ucDataRateDivShift = 3;
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ ucDataRateDivShift = 2;
+ }
+#endif /* ENABLE_LP3_SW */
+
+ u4Tmp0p5T = u4IO32ReadFldAlign(DRAMC_REG_ADDR(regs[0].u4Addr), regs[0].u4Fld) & (~(1<<ucDataRateDivShift));
+ u4Tmp2T = u4IO32ReadFldAlign(DRAMC_REG_ADDR(regs[1].u4Addr), regs[1].u4Fld);
+ //mcSHOW_DBG_MSG(("\n[MoveDramC_Orz] u4Tmp2T:%d, u4Tmp0p5T: %d,\n", u4Tmp2T, u4Tmp0p5T));
+ //mcFPRINTF((fp_A60501, "\n[MoveDramC_Orz] u4Tmp2T:%d, u4Tmp0p5T: %d,\n", u4Tmp2T, u4Tmp0p5T));
+
+ s4HighLevelDelay = (u4Tmp2T <<ucDataRateDivShift) + u4Tmp0p5T;
+ s4DelaySum = (s4HighLevelDelay + iShiftUI);
+ //mcSHOW_DBG_MSG(("\n[MoveDramC_Orz] s4HighLevelDealy(%d) + iShiftUI(%d) = %d\n", s4HighLevelDelay, iShiftUI, s4DelaySum));
+
+ if(s4DelaySum < 0)
+ {
+ u4Tmp0p5T =0;
+ u4Tmp2T=0;
+ MoveResult = DRAM_FAIL;
+ //mcSHOW_ERR_MSG(("\n[MoveDramC_Orz] s4HighLevelDealy(%d) + iShiftUI(%d) is small than 0!!\n", s4HighLevelDelay, iShiftUI));
+ }
+ else
+ {
+ u4Tmp2T = s4DelaySum >> ucDataRateDivShift;
+ u4Tmp0p5T = s4DelaySum - (u4Tmp2T <<ucDataRateDivShift);
+ MoveResult = DRAM_OK;
+ }
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(regs[0].u4Addr), u4Tmp0p5T, regs[0].u4Fld);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(regs[1].u4Addr), u4Tmp2T, regs[1].u4Fld);
+ //mcSHOW_DBG_MSG(("\n[MoveDramC_Orz] Final ==> u4Tmp2T:%d, u4Tmp0p5T: %d,\n", u4Tmp2T, u4Tmp0p5T));
+ //mcFPRINTF((fp_A60501, "\n[MoveDramC_Orz] Final ==> u4Tmp2T:%d, u4Tmp0p5T: %d,\n", u4Tmp2T, u4Tmp0p5T));
+
+ return MoveResult;
+}
+
+void MoveDramC_TX_DQS(DRAMC_CTX_T *p, U8 u1ByteIdx, S8 iShiftUI)
+{
+ REG_TRANSFER_T TransferReg[2];
+
+ //mcSHOW_DBG_MSG(("\n[MoveDramC_TX_DQS] Byte %d, iShiftUI %d\n", u1ByteIdx, iShiftUI));
+
+ switch(u1ByteIdx)
+ {
+ case 0:
+ // DQS0
+ TransferReg[0].u4Addr = DRAMC_REG_SHU_SELPH_DQS1;
+ TransferReg[0].u4Fld =SHU_SELPH_DQS1_DLY_DQS0;
+ TransferReg[1].u4Addr = DRAMC_REG_SHU_SELPH_DQS0;
+ TransferReg[1].u4Fld =SHU_SELPH_DQS0_TXDLY_DQS0;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ break;
+
+ case 1:
+ // DQS1
+ TransferReg[0].u4Addr = DRAMC_REG_SHU_SELPH_DQS1;
+ TransferReg[0].u4Fld =SHU_SELPH_DQS1_DLY_DQS1;
+ TransferReg[1].u4Addr = DRAMC_REG_SHU_SELPH_DQS0;
+ TransferReg[1].u4Fld =SHU_SELPH_DQS0_TXDLY_DQS1;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ break;
+
+ case 2:
+ // DQS2
+ TransferReg[0].u4Addr = DRAMC_REG_SHU_SELPH_DQS1;
+ TransferReg[0].u4Fld =SHU_SELPH_DQS1_DLY_DQS2;
+ TransferReg[1].u4Addr = DRAMC_REG_SHU_SELPH_DQS0;
+ TransferReg[1].u4Fld =SHU_SELPH_DQS0_TXDLY_DQS2;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ break;
+
+ case 3:
+ // DQS3
+ TransferReg[0].u4Addr = DRAMC_REG_SHU_SELPH_DQS1;
+ TransferReg[0].u4Fld =SHU_SELPH_DQS1_DLY_DQS3;
+ TransferReg[1].u4Addr = DRAMC_REG_SHU_SELPH_DQS0;
+ TransferReg[1].u4Fld =SHU_SELPH_DQS0_TXDLY_DQS3;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void MoveDramC_TX_DQS_OEN(DRAMC_CTX_T *p, U8 u1ByteIdx, S8 iShiftUI)
+{
+ REG_TRANSFER_T TransferReg[2];
+
+ //mcSHOW_DBG_MSG(("\n[MoveDramC_TX_DQS_OEN] Byte %d, iShiftUI %d\n", u1ByteIdx, iShiftUI));
+
+ switch(u1ByteIdx)
+ {
+ case 0:
+ // DQS_OEN_0
+ TransferReg[0].u4Addr = DRAMC_REG_SHU_SELPH_DQS1;
+ TransferReg[0].u4Fld =SHU_SELPH_DQS1_DLY_OEN_DQS0;
+ TransferReg[1].u4Addr = DRAMC_REG_SHU_SELPH_DQS0;
+ TransferReg[1].u4Fld =SHU_SELPH_DQS0_TXDLY_OEN_DQS0;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ break;
+
+ case 1:
+ // DQS_OEN_1
+ TransferReg[0].u4Addr = DRAMC_REG_SHU_SELPH_DQS1;
+ TransferReg[0].u4Fld =SHU_SELPH_DQS1_DLY_OEN_DQS1;
+ TransferReg[1].u4Addr = DRAMC_REG_SHU_SELPH_DQS0;
+ TransferReg[1].u4Fld =SHU_SELPH_DQS0_TXDLY_OEN_DQS1;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ break;
+
+ case 2:
+ // DQS_OEN_2
+ TransferReg[0].u4Addr = DRAMC_REG_SHU_SELPH_DQS1;
+ TransferReg[0].u4Fld =SHU_SELPH_DQS1_DLY_OEN_DQS2;
+ TransferReg[1].u4Addr = DRAMC_REG_SHU_SELPH_DQS0;
+ TransferReg[1].u4Fld =SHU_SELPH_DQS0_TXDLY_OEN_DQS2;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ break;
+
+ case 3:
+ // DQS_OEN_3
+ TransferReg[0].u4Addr = DRAMC_REG_SHU_SELPH_DQS1;
+ TransferReg[0].u4Fld =SHU_SELPH_DQS1_DLY_OEN_DQS3;
+ TransferReg[1].u4Addr = DRAMC_REG_SHU_SELPH_DQS0;
+ TransferReg[1].u4Fld =SHU_SELPH_DQS0_TXDLY_OEN_DQS3;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+void MoveDramC_TX_DQ(DRAMC_CTX_T *p, U8 u1ByteIdx, S8 iShiftUI)
+{
+ REG_TRANSFER_T TransferReg[2];
+
+ //mcSHOW_DBG_MSG(("\n[MoveDramC_TX_DQ] Byte %d, iShiftUI %d\n", u1ByteIdx, iShiftUI));
+
+ switch(u1ByteIdx)
+ {
+ case 0:
+ // DQM0
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_DQM0;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_DQM0;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+
+ // DQ0
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_DQ0;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_DQ0;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ break;
+
+ case 1:
+ // DQM1
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_DQM1;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_DQM1;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ // DQ1
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_DQ1;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_DQ1;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ break;
+
+ case 2:
+ // DQM2
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_DQM2;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_DQM2;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ // DQ2
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_DQ2;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_DQ2;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ break;
+
+ case 3:
+ // DQM3
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_DQM3;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_DQM3;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ // DQ3
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_DQ3;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_DQ3;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ break;
+ }
+}
+
+void MoveDramC_TX_DQ_OEN(DRAMC_CTX_T *p, U8 u1ByteIdx, S8 iShiftUI)
+{
+ REG_TRANSFER_T TransferReg[2];
+
+ //mcSHOW_DBG_MSG(("\n[MoveDramC_TX_DQ_OEN] Byte %d, iShiftUI %d\n", u1ByteIdx, iShiftUI));
+
+ switch(u1ByteIdx)
+ {
+ case 0:
+ // DQM_OEN_0
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_OEN_DQM0;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_OEN_DQM0;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ // DQ_OEN_0
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_OEN_DQ0;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_OEN_DQ0;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ break;
+
+ case 1:
+ // DQM_OEN_1
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_OEN_DQM1;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_OEN_DQM1;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ // DQ_OEN_1
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_OEN_DQ1;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_OEN_DQ1;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ break;
+
+ case 2:
+ // DQM_OEN_2
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_OEN_DQM2;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_OEN_DQM2;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ // DQ_OEN_2
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_OEN_DQ2;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_OEN_DQ2;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ break;
+
+ case 3:
+ // DQM_OEN_3
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_OEN_DQM3;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_OEN_DQM3;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ // DQ_OEN_3
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_OEN_DQ3;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_OEN_DQ3;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ break;
+ }
+}
+
+#if ENABLE_LP3_SW
+//for LPDDR3 DQ delay line used
+void Set_RX_DQ_DelayLine_Phy_Byte(DRAMC_CTX_T *p, U8 u1ByteIdx, U8 value[8])
+{
+ DRAM_CHANNEL_T backup_channel;
+ backup_channel = p->channel;
+
+#if (fcFOR_PINMUX == fcLaurel)
+
+ switch(u1ByteIdx)
+ {
+ case 0:
+ p->channel = CHANNEL_B;
+ //DQ0 -> BRDQ0_B1 //DQ3 -> BRDQ1_B1
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2),
+ P_Fld(value[0], SHU1_R0_B1_DQ2_RK0_RX_ARDQ0_F_DLY_B1) |
+ P_Fld(value[0], SHU1_R0_B1_DQ2_RK0_RX_ARDQ0_R_DLY_B1) |
+ P_Fld(value[3], SHU1_R0_B1_DQ2_RK0_RX_ARDQ1_F_DLY_B1) |
+ P_Fld(value[3], SHU1_R0_B1_DQ2_RK0_RX_ARDQ1_R_DLY_B1) );
+ //DQ7 -> BRDQ2_B1 //DQ1 -> BRDQ3_B1
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ3),
+ P_Fld(value[7], SHU1_R0_B1_DQ3_RK0_RX_ARDQ2_F_DLY_B1) |
+ P_Fld(value[7], SHU1_R0_B1_DQ3_RK0_RX_ARDQ2_R_DLY_B1) |
+ P_Fld(value[1], SHU1_R0_B1_DQ3_RK0_RX_ARDQ3_F_DLY_B1) |
+ P_Fld(value[1], SHU1_R0_B1_DQ3_RK0_RX_ARDQ3_R_DLY_B1) );
+ //DQ2 -> BRDQ4_B1 //DQ6 -> BRDQ5_B1
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ4),
+ P_Fld(value[2], SHU1_R0_B1_DQ4_RK0_RX_ARDQ4_F_DLY_B1) |
+ P_Fld(value[2], SHU1_R0_B1_DQ4_RK0_RX_ARDQ4_R_DLY_B1) |
+ P_Fld(value[6], SHU1_R0_B1_DQ4_RK0_RX_ARDQ5_F_DLY_B1) |
+ P_Fld(value[6], SHU1_R0_B1_DQ4_RK0_RX_ARDQ5_R_DLY_B1));
+ //DQ5 -> BRDQ6_B1 //DQ4 -> BRDQ7_B1
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ5),
+ P_Fld(value[5], SHU1_R0_B1_DQ5_RK0_RX_ARDQ6_F_DLY_B1) |
+ P_Fld(value[5], SHU1_R0_B1_DQ5_RK0_RX_ARDQ6_R_DLY_B1) |
+ P_Fld(value[4], SHU1_R0_B1_DQ5_RK0_RX_ARDQ7_F_DLY_B1) |
+ P_Fld(value[4], SHU1_R0_B1_DQ5_RK0_RX_ARDQ7_R_DLY_B1));
+ break;
+ case 1:
+ p->channel = CHANNEL_B;
+ //DQ5 -> BRCA0 //DQ1 -> BRCA1
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD2),
+ P_Fld(value[5], SHU1_R0_CA_CMD2_RG_RK0_RX_ARCA0_F_DLY) |
+ P_Fld(value[5], SHU1_R0_CA_CMD2_RG_RK0_RX_ARCA0_R_DLY) |
+ P_Fld(value[1], SHU1_R0_CA_CMD2_RG_RK0_RX_ARCA1_F_DLY) |
+ P_Fld(value[1], SHU1_R0_CA_CMD2_RG_RK0_RX_ARCA1_R_DLY));
+ //DQ4 -> BRCA2 //DQ6 -> BRCA3
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD3),
+ P_Fld(value[4], SHU1_R0_CA_CMD3_RG_RK0_RX_ARCA2_F_DLY) |
+ P_Fld(value[4], SHU1_R0_CA_CMD3_RG_RK0_RX_ARCA2_R_DLY) |
+ P_Fld(value[6], SHU1_R0_CA_CMD3_RG_RK0_RX_ARCA3_F_DLY) |
+ P_Fld(value[6], SHU1_R0_CA_CMD3_RG_RK0_RX_ARCA3_R_DLY));
+ //DQ2 -> BRCA4 //DQ7 -> BRCS5
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD4),
+ P_Fld(value[2], SHU1_R0_CA_CMD4_RG_RK0_RX_ARCA4_F_DLY) |
+ P_Fld(value[2], SHU1_R0_CA_CMD4_RG_RK0_RX_ARCA4_R_DLY) |
+ P_Fld(value[7], SHU1_R0_CA_CMD4_RG_RK0_RX_ARCA5_F_DLY) |
+ P_Fld(value[7], SHU1_R0_CA_CMD4_RG_RK0_RX_ARCA5_R_DLY));
+ //DQ3 -> BRCKE0 //DQ0 -> BRCKE1
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD5),
+ P_Fld(value[3], SHU1_R0_CA_CMD5_RG_RK0_RX_ARCKE0_F_DLY) |
+ P_Fld(value[3], SHU1_R0_CA_CMD5_RG_RK0_RX_ARCKE0_R_DLY) |
+ P_Fld(value[0], SHU1_R0_CA_CMD5_RG_RK0_RX_ARCKE1_F_DLY) |
+ P_Fld(value[0], SHU1_R0_CA_CMD5_RG_RK0_RX_ARCKE1_R_DLY));
+
+ break;
+ case 2:
+ p->channel = CHANNEL_A;
+ //DQ1 -> ARDQ0_B1 //DQ0 -> ARDQ1_B1
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2),
+ P_Fld(value[1], SHU1_R0_B1_DQ2_RK0_RX_ARDQ0_F_DLY_B1) |
+ P_Fld(value[1], SHU1_R0_B1_DQ2_RK0_RX_ARDQ0_R_DLY_B1) |
+ P_Fld(value[0], SHU1_R0_B1_DQ2_RK0_RX_ARDQ1_F_DLY_B1) |
+ P_Fld(value[0], SHU1_R0_B1_DQ2_RK0_RX_ARDQ1_R_DLY_B1));
+ //DQ4 -> ARDQ2_B1 //DQ5 -> ARDQ3_B1
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ3),
+ P_Fld(value[4], SHU1_R0_B1_DQ3_RK0_RX_ARDQ2_F_DLY_B1) |
+ P_Fld(value[4], SHU1_R0_B1_DQ3_RK0_RX_ARDQ2_R_DLY_B1) |
+ P_Fld(value[5], SHU1_R0_B1_DQ3_RK0_RX_ARDQ3_F_DLY_B1) |
+ P_Fld(value[5], SHU1_R0_B1_DQ3_RK0_RX_ARDQ3_R_DLY_B1));
+ //DQ2 -> ARDQ4_B1 //DQ6 -> ARDQ5_B1
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ4),
+ P_Fld(value[2], SHU1_R0_B1_DQ4_RK0_RX_ARDQ4_F_DLY_B1) |
+ P_Fld(value[2], SHU1_R0_B1_DQ4_RK0_RX_ARDQ4_R_DLY_B1) |
+ P_Fld(value[6], SHU1_R0_B1_DQ4_RK0_RX_ARDQ5_F_DLY_B1) |
+ P_Fld(value[6], SHU1_R0_B1_DQ4_RK0_RX_ARDQ5_R_DLY_B1));
+ //DQ3 -> ARDQ6_B1 //DQ7 -> ARDQ7_B1
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ5),
+ P_Fld(value[3], SHU1_R0_B1_DQ5_RK0_RX_ARDQ6_F_DLY_B1) |
+ P_Fld(value[3], SHU1_R0_B1_DQ5_RK0_RX_ARDQ6_R_DLY_B1) |
+ P_Fld(value[7], SHU1_R0_B1_DQ5_RK0_RX_ARDQ7_F_DLY_B1) |
+ P_Fld(value[7], SHU1_R0_B1_DQ5_RK0_RX_ARDQ7_R_DLY_B1));
+ break;
+ case 3:
+ p->channel = CHANNEL_B;
+ //DQ5 -> BRDQ0_B0 //DQ0 -> BRDQ1_B0
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2),
+ P_Fld(value[5], SHU1_R0_B0_DQ2_RK0_RX_ARDQ0_F_DLY_B0) |
+ P_Fld(value[5], SHU1_R0_B0_DQ2_RK0_RX_ARDQ0_R_DLY_B0) |
+ P_Fld(value[0], SHU1_R0_B0_DQ2_RK0_RX_ARDQ1_F_DLY_B0) |
+ P_Fld(value[0], SHU1_R0_B0_DQ2_RK0_RX_ARDQ1_R_DLY_B0));
+ //DQ6 -> BRDQ2_B0 //DQ4 -> BRDQ3_B0
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ3),
+ P_Fld(value[6], SHU1_R0_B0_DQ3_RK0_RX_ARDQ2_F_DLY_B0) |
+ P_Fld(value[6], SHU1_R0_B0_DQ3_RK0_RX_ARDQ2_R_DLY_B0) |
+ P_Fld(value[4], SHU1_R0_B0_DQ3_RK0_RX_ARDQ3_F_DLY_B0) |
+ P_Fld(value[4], SHU1_R0_B0_DQ3_RK0_RX_ARDQ3_R_DLY_B0));
+ //DQ3 -> BRDQ4_B0 //DQ7 -> BRDQ5_B0
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ4),
+ P_Fld(value[3], SHU1_R0_B0_DQ4_RK0_RX_ARDQ4_F_DLY_B0) |
+ P_Fld(value[3], SHU1_R0_B0_DQ4_RK0_RX_ARDQ4_R_DLY_B0) |
+ P_Fld(value[7], SHU1_R0_B0_DQ4_RK0_RX_ARDQ5_F_DLY_B0) |
+ P_Fld(value[7], SHU1_R0_B0_DQ4_RK0_RX_ARDQ5_R_DLY_B0));
+ //DQ2 -> BRDQ6_B0 //DQ1 -> BRDQ7_B0
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ5),
+ P_Fld(value[2], SHU1_R0_B0_DQ5_RK0_RX_ARDQ6_F_DLY_B0) |
+ P_Fld(value[2], SHU1_R0_B0_DQ5_RK0_RX_ARDQ6_R_DLY_B0) |
+ P_Fld(value[1], SHU1_R0_B0_DQ5_RK0_RX_ARDQ7_F_DLY_B0) |
+ P_Fld(value[1], SHU1_R0_B0_DQ5_RK0_RX_ARDQ7_R_DLY_B0));
+ break;
+
+ }
+#endif
+ p->channel = backup_channel;
+}
+
+//for LPDDR3 DQM delay line used
+void Set_RX_DQM_DelayLine_Phy_Byte(DRAMC_CTX_T *p, U8 u1ByteIdx, S8 value)
+{
+ DRAM_CHANNEL_T backup_channel;
+ backup_channel = p->channel;
+
+#if (fcFOR_PINMUX == fcLaurel)
+ switch(u1ByteIdx)
+ {
+ case 0:
+ p->channel = CHANNEL_B;
+ //DQM0 -> BRDQM0_B1
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ6), P_Fld(value, SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_F_DLY_B1) | P_Fld(value, SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_R_DLY_B1));
+ break;
+ case 1:
+ p->channel = CHANNEL_B;
+ //DQM1 -> BRCS0
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD6), P_Fld(value, SHU1_R0_CA_CMD6_RG_RK0_RX_ARCS0_F_DLY) | P_Fld(value, SHU1_R0_CA_CMD6_RG_RK0_RX_ARCS0_R_DLY));
+ break;
+ case 2:
+ p->channel = CHANNEL_A;
+ //DQM2 -> ARDQM0_B1
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ6), P_Fld(value, SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_F_DLY_B1) | P_Fld(value, SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_R_DLY_B1));
+ break;
+ case 3:
+ p->channel = CHANNEL_B;
+ //DQM3 -> BRDQM0_B0
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6), P_Fld(value, SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_F_DLY_B0) | P_Fld(value, SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_R_DLY_B0));
+ break;
+
+ }
+#endif
+
+ p->channel = backup_channel;
+}
+#endif
+
+#if SIMULATION_WRITE_LEVELING
+#if WRITE_LEVELING_MOVE_DQS_INSTEAD_OF_CLK
+void WriteLevelingMoveDQSInsteadOfCLK(DRAMC_CTX_T *p)
+{
+ U8 u1ByteIdx;
+ U8 backup_rank, ii;
+
+ backup_rank = u1GetRank(p);
+
+ for(u1ByteIdx =0 ; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+ {
+ MoveDramC_TX_DQS(p, u1ByteIdx, -WRITE_LEVELING_MOVD_DQS);
+ MoveDramC_TX_DQS_OEN(p, u1ByteIdx, -WRITE_LEVELING_MOVD_DQS);
+
+ for(ii=RANK_0; ii<RANK_MAX; ii++)
+ {
+ vSetRank(p, ii);
+ MoveDramC_TX_DQ(p, u1ByteIdx, -WRITE_LEVELING_MOVD_DQS);
+ MoveDramC_TX_DQ_OEN(p, u1ByteIdx, -WRITE_LEVELING_MOVD_DQS);
+ }
+ vSetRank(p, backup_rank);
+ }
+}
+#endif
+
+
+//static void vSetDramMRWriteLevelingOnOff(DRAMC_CTX_T *p, U8 u1OnOff)
+void vSetDramMRWriteLevelingOnOff(DRAMC_CTX_T *p, U8 u1OnOff)
+{
+ // MR2 OP[7] to enable/disable write leveling
+ if(u1OnOff)
+ u1MR02Value[p->dram_fsp] |= 0x80; // OP[7] WR LEV =1
+ else
+ u1MR02Value[p->dram_fsp] &= 0x7f; // OP[7] WR LEV =0
+
+ DramcModeRegWriteByRank(p, p->rank, 2, u1MR02Value[p->dram_fsp]);
+}
+
+#define DQS_DUTY_MEASURE_WITH_WRITE_LEVELING 0
+DRAM_STATUS_T DramcWriteLeveling(DRAMC_CTX_T *p)
+{
+// Note that below procedure is based on "ODT off"
+ DRAM_STATUS_T KResult= DRAM_FAIL;
+
+ U32 u4value=0, u4dq_o1=0;
+ U8 byte_i, ucsample_count;
+ S32 ii;
+ U8 ucsample_status[DQS_NUMBER], ucdq_o1_perbyte[DQS_NUMBER], ucdq_o1_index[DQS_NUMBER];
+ DRAM_RANK_T backup_rank;
+
+ S32 wrlevel_dq_delay[DQS_NUMBER]; // 3 is channel number
+#if ENABLE_LP3_SW
+ S32 wrlevel_dqs_delay[DQS_NUMBER]; // 3 is channel number
+#endif
+
+ #if WRITE_LEVELING_MOVE_DQS_INSTEAD_OF_CLK
+ S32 i4PIBegin, i4PIEnd;
+ U8 u1PIStep;
+ #endif
+
+ #if DQS_DUTY_MEASURE_WITH_WRITE_LEVELING
+ U16 u2TriggerCnt;
+ #endif
+
+ // error handling
+ if (!p)
+ {
+ mcSHOW_ERR_MSG(("context NULL\n"));
+ return DRAM_FAIL;
+ }
+
+ U32 u4RegBackupAddress[] =
+ {
+ (DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0)),
+ (DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL)),
+ (DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL)),
+ (DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV)),
+ (DRAMC_REG_ADDR(DRAMC_REG_CKECTRL)),
+ };
+
+#if MRW_CHECK_ONLY
+ mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
+#endif
+
+ vPrintCalibrationBasicInfo(p);
+
+ fgwrlevel_done = 0;
+ backup_rank = u1GetRank(p);
+
+ #if CBT_WORKAROUND_O1_SWAP
+ if(u1IsLP4Family(p->dram_type))
+ {
+ CATrain_CmdDelay[p->channel][p->rank] = 0;//u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_ARPI_CMD), ARPI_CMD_DA_ARPI_CMD);
+ CATrain_CsDelay[p->channel][p->rank] = 0;//u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_ARPI_CMD), ARPI_CMD_DA_ARPI_CS);
+ CATrain_ClkDelay[p->channel][p->rank] = 0;//u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_ARPI_CMD), ARPI_CMD_DA_ARPI_CK);
+ }
+ #endif
+
+ //DramcRankSwap(p, p->rank);
+ //tx_rank_sel is selected by SW //Lewis@20180604: tx_rank_sel is selected by SW in WL if TMRRI design has changed.
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), p->rank, RKCFG_TXRANK);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 1, RKCFG_TXRANKFIX); //TXRANKFIX should be write after TXRANK
+
+ // DQ mapping
+ ///!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ /// Note : uiLPDDR_O1_Mapping_POP, need to take care mapping in real chip, but not in test chip.
+ /// Everest : there is bit swap inside single byte. PHY & DRAM is 1-1 byte mapping, no swap.
+ for (byte_i=0; byte_i<(p->data_width/DQS_BIT_NUMBER); byte_i++)
+ {
+ ucdq_o1_index[byte_i] = byte_i*8;
+ }
+
+#ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+ U8 u1GUMP_INIT_RG_LOG_TO_DE_bak = gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag;
+ gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag=0;
+#endif
+
+#if REG_ACCESS_PORTING_DGB
+ RegLogEnable =1;
+ mcSHOW_DBG_MSG(("\n[REG_ACCESS_PORTING_FUNC] DramcWriteLeveling\n"));
+ mcFPRINTF((fp_A60501, "\n[REG_ACCESS_PORTING_FUNC] DramcWriteLeveling\n"));
+#endif
+
+ // backup mode settings
+ DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+ vAutoRefreshSwitch(p, DISABLE); //When doing CA training, should make sure that auto refresh is disable
+
+ #if WRITE_LEVELING_MOVE_DQS_INSTEAD_OF_CLK
+ if(p->arfgWriteLevelingInitShif[p->channel][p->rank] ==FALSE)
+ {
+ WriteLevelingMoveDQSInsteadOfCLK(p);
+ //p->arfgWriteLevelingInitShif[p->channel][p->rank] =TRUE;
+ p->arfgWriteLevelingInitShif[p->channel][RANK_0] =TRUE;
+ p->arfgWriteLevelingInitShif[p->channel][RANK_1] =TRUE;
+ #if TX_PERBIT_INIT_FLOW_CONTROL
+ // both 2 rank use one write leveling result, TX need to udpate.
+ p->fgTXPerbifInit[p->channel][RANK_0]= FALSE;
+ p->fgTXPerbifInit[p->channel][RANK_1]= FALSE;
+ #endif
+
+ mcSHOW_DBG_MSG3(("WriteLevelingMoveDQSInsteadOfCLK\n"));
+ mcFPRINTF((fp_A60501, "WriteLevelingMoveDQSInsteadOfCLK\n"));
+ }
+ #endif
+
+#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_WRITELEVELING)
+ if(p->femmc_Ready==1)
+ {
+ wrlevel_dqs_final_delay[0] =p->pSavetimeData->u1WriteLeveling_bypass_Save[p->channel][p->rank][0];
+ wrlevel_dqs_final_delay[1] =p->pSavetimeData->u1WriteLeveling_bypass_Save[p->channel][p->rank][1];
+
+ ucsample_count = 0xff;
+ KResult = DRAM_OK;
+ vSetCalibrationResult(p, DRAM_CALIBRATION_WRITE_LEVEL, DRAM_OK);
+ }
+ else
+#endif
+ {
+ //write leveling mode initialization
+ //REFCNT_FR_CLK = 0 (0x1dc[23:16]), ADVREFEN = 0 (0x44[30]), (CONF2_REFCNT =0)
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 1, DRAMC_PD_CTRL_MIOCKCTRLOFF); //MIOCKCTRLOFF=1
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 0, DRAMC_PD_CTRL_PHYCLKDYNGEN); //PHYCLKDYNGEN=0
+
+ //Make CKE fixed at 1 (Don't enter power down, Put this before issuing MRS): CKEFIXON = 1
+ CKEFixOnOff(p, p->rank, CKE_FIXON, CKE_WRITE_TO_ONE_CHANNEL);
+
+ //PHY RX Setting for Write Leveling
+ //Let IO toO1 path valid, Enable SMT_EN
+ O1PathOnOff(p, 1);
+
+ // enable DDR write leveling mode: issue MR2[7] to enable write leveling (refer to DEFAULT MR2 value)
+ vSetDramMRWriteLevelingOnOff(p, ENABLE);
+
+ //wait tWLDQSEN (25 nCK / 25ns) after enabling write leveling mode (DDR3 / LPDDDR3)
+ mcDELAY_US(1);
+
+ //Set {R_DQS_B3_G R_DQS_B2_G R_DQS_B1_G R_DQS_B0_G}=1010: 0x13c[4:1] (this depends on sel_ph setting)
+ //Enable Write leveling: 0x13c[0]
+ //vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEVELING), P_Fld(0xa, WRITE_LEVELING_DQSBX_G)|P_Fld(1, WRITE_LEVELING_WRITE_LEVEL_EN));
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 0xa, WRITE_LEV_DQSBX_G);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 1, WRITE_LEV_WRITE_LEVEL_EN);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 1, WRITE_LEV_CBTMASKDQSOE);
+
+ // select DQS
+#if ENABLE_LP3_SW
+ if(p->dram_type == TYPE_LPDDR3)
+ {
+ u4value = 0xf;//select byte 0.1.2.3
+ }
+ else //LPDDR4
+#endif /* ENABLE_LP3_SW */
+ {
+ u4value = 0x3;//select byte 0.1
+ }
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), u4value, WRITE_LEV_DQS_SEL);
+
+ // wait tWLMRD (40 nCL / 40 ns) before DQS pulse (DDR3 / LPDDR3)
+ mcDELAY_US(1);
+
+ //Proceed write leveling...
+ //Initilize sw parameters
+ for (ii=0; ii < (S32)(p->data_width/DQS_BIT_NUMBER); ii++)
+ {
+ ucsample_status[ii] = 0;
+ wrlevel_dqs_final_delay[ii] = 0;
+ }
+
+ //used for WL done status
+ // each bit of sample_cnt represents one-byte WL status
+ // 1: done or N/A. 0: NOK
+ if ((p->data_width == DATA_WIDTH_16BIT))
+ {
+ ucsample_count = 0xfc;
+ }
+ else
+ {
+ ucsample_count = 0xf0;
+ }
+
+ mcSHOW_DBG_MSG(("[Write Leveling]\n"));
+ mcSHOW_DBG_MSG(("delay byte0 byte1 byte2 byte3\n\n"));
+
+ mcFPRINTF((fp_A60501, "\n\tdramc_write_leveling_swcal\n"));
+ mcFPRINTF((fp_A60501, "delay byte0 byte1 byte2 byte3\n\n"));
+
+ // Set DQS output delay to 0
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), 0, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0); //rank0, byte0, DQS delay
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), 0, SHU1_R0_B1_DQ7_RK0_ARPI_PBYTE_B1); //rank0, byte1, DQS delay
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), 0, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+ vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), 0, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+ vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), 0, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+ vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), 0, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+ }
+#endif
+ #if WRITE_LEVELING_MOVE_DQS_INSTEAD_OF_CLK
+ i4PIBegin = WRITE_LEVELING_MOVD_DQS*32 -MAX_CLK_PI_DELAY-1;
+ #endif
+
+ #if (fcFOR_CHIP_ID == fcLaurel)
+ i4PIBegin += 10; // for save time
+ #endif
+
+ i4PIEnd = 63; // SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0: 6 bits
+
+ #if DQS_DUTY_MEASURE_WITH_WRITE_LEVELING
+ if(p->channel==CHANNEL_A && p->frequency == u2DFSGetHighestFreq(p))
+ u1PIStep =2;
+ else
+ #endif
+ u1PIStep =1;
+
+ #if WRITE_LEVELING_MOVE_DQS_INSTEAD_OF_CLK
+ for (ii=i4PIBegin; ii<i4PIEnd; ii+=u1PIStep)
+ #else
+ for (ii=(-MAX_CLK_PI_DELAY); ii<=MAX_TX_DQSDLY_TAPS; ii++)
+ #endif
+ {
+ #if DQS_DUTY_MEASURE_WITH_WRITE_LEVELING
+ if(u1PIStep==2)
+ mcDELAY_MS(10000);
+ #endif
+
+ if (ii <= 0)
+ {
+ // Adjust Clk output delay.
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), -ii, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK);
+ }
+ else
+ {
+ // Adjust DQS output delay.
+ // PI (TX DQ/DQS adjust at the same time)
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ii, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0); //rank0, byte0, DQS delay
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), ii, SHU1_R0_B1_DQ7_RK0_ARPI_PBYTE_B1); //rank0, byte1, DQS delay
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ii, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+ vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ii, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+ vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ii, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+ vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ii, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+ }
+#endif
+ }
+
+ //Trigger DQS pulse, R_DQS_WLEV: 0x13c[8] from 1 to 0
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 1, WRITE_LEV_DQS_WLEV);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 0, WRITE_LEV_DQS_WLEV);
+
+ #if DQS_DUTY_MEASURE_WITH_WRITE_LEVELING
+ if(u1PIStep==2)
+ {
+ for(u2TriggerCnt=0; u2TriggerCnt<10000; u2TriggerCnt++)
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 1, WRITE_LEV_DQS_WLEV);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_WRITE_LEV), 0, WRITE_LEV_DQS_WLEV);
+ }
+ }
+ #endif
+
+ //wait tWLO (7.5ns / 20ns) before output (DDR3 / LPDDR3)
+ mcDELAY_US(1);
+
+ //Read DQ_O1 from register
+ if(u1IsLP4Family(p->dram_type))
+ {
+ u4dq_o1 = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_DQO1));
+ }
+#if ENABLE_LP3_SW
+ else //LPRRR3
+ {
+ // Get DQ value.
+ u4dq_o1 = u4IO32Read4B(DRAMC_REG_ADDR(DDRPHY_MISC_DQO1));
+ //mcSHOW_DBG_MSG2(("DQ_O1: 0x%x\n", u4dq_o1));
+ }
+#endif
+ #ifdef ETT_PRINT_FORMAT
+ mcSHOW_DBG_MSG2(("%d ", ii));
+ #else
+ mcSHOW_DBG_MSG2(("%2d ", ii));
+ #endif
+ mcFPRINTF((fp_A60501, "%2d ", ii));
+
+ //mcSHOW_DBG_MSG(("0x%x ", u4dq_o1));
+ //mcFPRINTF((fp_A60501, "0x%x ", u4dq_o1));
+
+ for (byte_i = 0; byte_i < (p->data_width/DQS_BIT_NUMBER); byte_i++)
+ {
+ ucdq_o1_perbyte[byte_i] = (U8)((u4dq_o1>>ucdq_o1_index[byte_i]) & 0xff); // ==> TOBEREVIEW
+
+ mcSHOW_DBG_MSG2(("%x ", ucdq_o1_perbyte[byte_i]));
+ mcFPRINTF((fp_A60501, "%x ", ucdq_o1_perbyte[byte_i]));
+
+ if ((ucsample_status[byte_i]==0) && (ucdq_o1_perbyte[byte_i]==0))
+ {
+ ucsample_status[byte_i] = 1;
+ }
+ else if ((ucsample_status[byte_i]>=1) && (ucdq_o1_perbyte[byte_i] ==0))
+ {
+ ucsample_status[byte_i] = 1;
+ }
+ else if ((ucsample_status[byte_i]>=1) && (ucdq_o1_perbyte[byte_i] !=0))
+ {
+ ucsample_status[byte_i]++;
+ }
+ //mcSHOW_DBG_MSG(("(%x) ", ucsample_status[byte_i]));
+
+ if((ucsample_count &(0x01 << byte_i))==0)// result not found of byte yet
+ {
+ #if WRITE_LEVELING_MOVE_DQS_INSTEAD_OF_CLK
+ if((ucsample_status[byte_i] ==8) || ((ii==i4PIEnd-1) && (ucsample_status[byte_i] >1)))
+ #else
+ if((ucsample_status[byte_i] ==8) || ((ii==MAX_TX_DQSDLY_TAPS)&& (ucsample_status[byte_i] >1)))
+ #endif
+ {
+ wrlevel_dqs_final_delay[byte_i] = ii -ucsample_status[byte_i] +2;
+ ucsample_count |= (0x01 << byte_i);
+ //mcSHOW_DBG_MSG(("(record %d) ", wrlevel_dqs_final_delay[byte_i]));
+ }
+ }
+ }
+ mcSHOW_DBG_MSG2(("\n"));
+ mcFPRINTF((fp_A60501, "\n"));
+
+ #if !DQS_DUTY_MEASURE_WITH_WRITE_LEVELING
+ if (ucsample_count == 0xff)
+ break; // all byte found, early break.
+ #endif
+ }
+ }
+
+ if (ucsample_count == 0xff)
+ {
+ // all bytes are done
+ fgwrlevel_done= 1;
+ KResult = DRAM_OK;
+ }
+ else
+ {
+ KResult = DRAM_FAIL;
+ }
+
+ vSetCalibrationResult(p, DRAM_CALIBRATION_WRITE_LEVEL, KResult);
+
+ mcSHOW_DBG_MSG2(("pass bytecount = 0x%x (0xff: all bytes pass) \n\n", ucsample_count));
+ mcFPRINTF((fp_A60501, "pass bytecount = 0x%x (0xff: all bytes pass)\n\n", ucsample_count));
+#if 0
+ U32 u4value1=0
+ S32 ClockDelayMax = MAX_TX_DQSDLY_TAPS;
+
+ for (byte_i = 0; byte_i < (p->data_width/DQS_BIT_NUMBER); byte_i++)
+ {
+ if (ClockDelayMax > wrlevel_dqs_final_delay[byte_i])
+ {
+ ClockDelayMax = wrlevel_dqs_final_delay[byte_i];
+ }
+ }
+
+ if (ClockDelayMax > 0)
+ {
+ ClockDelayMax = 0;
+ }
+ else
+ {
+ ClockDelayMax = -ClockDelayMax;
+ }
+
+ vPrintCalibrationBasicInfo(p);
+
+ mcSHOW_DBG_MSG(("WL Clk dly = %d, CA clk dly = %d\n", ClockDelayMax, CATrain_ClkDelay[p->channel][p->rank]));
+ mcFPRINTF((fp_A60501, "WL Clk dly = %d, CA clk dly = %d\n", ClockDelayMax, CATrain_ClkDelay[p->channel][p->rank]));
+
+ // Adjust Clk & CA if needed
+ if (CATrain_ClkDelay[p->channel][p->rank] < ClockDelayMax)
+ {
+ S32 Diff = ClockDelayMax - CATrain_ClkDelay[p->channel][p->rank];
+ mcSHOW_DBG_MSG(("CA adjust %d taps\n", Diff));
+ // Write shift value into CA output delay.
+ if(u1IsLP4Family(p->dram_type))
+ {
+ u4value = CATrain_CmdDelay[p->channel][p->rank];
+ u4value += Diff;
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), u4value, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD);
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+#if (fcFOR_PINMUX == fcLaurel)
+ for(ii=p->rank; ii<RANK_MAX; ii++)
+ {
+ vSetRank(p,ii);
+ u4value = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD);
+ u4value += Diff;
+ //default value in init() is 0x10 , vIO32Write4B(mcSET_DDRPHY_REG_ADDR_CHC(0x0458), 0x00100000); // Partickl
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), u4value, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CMD);
+
+ u4value1 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+ u4value1 += Diff;
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), u4value1, SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+ }
+ vSetRank(p, backup_rank);
+#endif
+ }
+#endif
+ mcSHOW_DBG_MSG(("Update CA PI Dly Macro0 = %d, Macro1 = %d\n", u4value, u4value1));
+ mcFPRINTF((fp_A60501, "Update CA PI Dly Macro0 = %d, Macro1 = %d\n", u4value, u4value1));
+
+ // Write shift value into CS output delay.
+ if(u1IsLP4Family(p->dram_type))
+ {
+ //u4value = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_ARPI_CMD), ARPI_CMD_DA_ARPI_CS);
+ u4value = CATrain_CsDelay[p->channel][p->rank];
+ u4value += Diff;
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), u4value, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS);
+ mcSHOW_DBG_MSG(("Update CS Dly = %d\n", u4value));
+ mcFPRINTF((fp_A60501, "Update CS Dly = %d\n", u4value));
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+#if (fcFOR_PINMUX == fcLaurel)
+ for(ii=p->rank; ii<RANK_MAX; ii++)
+ {
+ vSetRank(p,ii);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), ClockDelayMax, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS);
+ mcSHOW_DBG_MSG(("Update CS Dly = %d\n", ClockDelayMax));
+ mcFPRINTF((fp_A60501, "Update CS Dly = %d\n", ClockDelayMax));
+ }
+ vSetRank(p, backup_rank);
+#endif
+ }
+#endif
+ }
+ else
+ {
+ mcSHOW_DBG_MSG(("No need to update CA/CS dly (CLK dly smaller than CA training)\n"));
+ ClockDelayMax = CATrain_ClkDelay[p->channel][p->rank];
+ }
+
+ //DramcEnterSelfRefresh(p, 1); //enter self refresh mode when changing CLK
+ // Write max center value into Clk output delay.
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), ClockDelayMax, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK);
+ //DramcEnterSelfRefresh(p, 0);
+
+ mcFPRINTF((fp_A60501, "Final Clk output dly = %d\n", ClockDelayMax));
+ mcSHOW_DBG_MSG(("Final Clk output dly = %d\n", ClockDelayMax));
+ //mcSHOW_DBG_MSG(("After adjustment...\n"));
+#endif
+ for (byte_i = 0; byte_i < (p->data_width/DQS_BIT_NUMBER); byte_i++)
+ {
+ #if 0
+ wrlevel_dqs_final_delay[byte_i] += (ClockDelayMax);
+ #endif
+ mcSHOW_DBG_MSG(("DQS%d dly: %d\n", byte_i, wrlevel_dqs_final_delay[byte_i]));
+ mcFPRINTF((fp_A60501, "DQS%d dly: %d\n", byte_i, wrlevel_dqs_final_delay[byte_i]));
+
+#ifdef FOR_HQA_TEST_USED
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT1, "WriteLeveling_DQS", byte_i, wrlevel_dqs_final_delay[byte_i], NULL);
+#endif
+ }
+
+ #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==0)
+ {
+ p->pSavetimeData->u1WriteLeveling_bypass_Save[p->channel][p->rank][0]=wrlevel_dqs_final_delay[0];
+ p->pSavetimeData->u1WriteLeveling_bypass_Save[p->channel][p->rank][1]=wrlevel_dqs_final_delay[1];
+ }
+ #endif
+ // write leveling done, mode settings recovery if necessary
+ // recover mode registers : issue MR2[7] to disable write leveling (refer to DEFAULT MR2 value)
+ vSetDramMRWriteLevelingOnOff(p, DISABLE);
+
+ // restore registers.
+ DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+ //Disable DQ_O1, SELO1ASO=0 for power saving
+ O1PathOnOff(p, 0);
+ if(u1IsLP4Family(p->dram_type))
+ {
+ #if REG_SHUFFLE_REG_CHECK
+ ShuffleRegCheck =1;
+ #endif
+
+ // set to best values for DQS
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dqs_final_delay[0], SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), wrlevel_dqs_final_delay[1], SHU1_R0_B1_DQ7_RK0_ARPI_PBYTE_B1);
+
+ for(byte_i = 0; byte_i < (p->data_width/DQS_BIT_NUMBER); byte_i++)
+ {
+ wrlevel_dq_delay[byte_i] = wrlevel_dqs_final_delay[byte_i] + 0x10;
+ if(wrlevel_dq_delay[byte_i] >= 0x40) //ARPI_DQ_B* is 6 bits, max 0x40
+ {
+ wrlevel_dq_delay[byte_i] -= 0x40;
+ MoveDramC_TX_DQ(p, byte_i, 2);
+ MoveDramC_TX_DQ_OEN(p, byte_i, 2);
+ }
+ }
+
+ #ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+ gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag = u1GUMP_INIT_RG_LOG_TO_DE_bak;
+ #endif
+
+ // set to best values for DQM, DQ
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7),
+ P_Fld(wrlevel_dq_delay[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0) |
+ P_Fld(wrlevel_dq_delay[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0));
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7),
+ P_Fld(wrlevel_dq_delay[1], SHU1_R0_B1_DQ7_RK0_ARPI_DQM_B1) |
+ P_Fld(wrlevel_dq_delay[1], SHU1_R0_B1_DQ7_RK0_ARPI_DQ_B1));
+
+ #if REG_SHUFFLE_REG_CHECK
+ ShuffleRegCheck =0;
+ #endif
+ }
+#if ENABLE_LP3_SW
+ else //LPDDR3
+ {
+ #if REG_SHUFFLE_REG_CHECK
+ ShuffleRegCheck =1;
+ #endif
+
+ for(byte_i=0; byte_i<(p->data_width/DQS_BIT_NUMBER); byte_i++)
+ {
+ if(wrlevel_dqs_final_delay[byte_i] >= 0x40) //ARPI_PBYTE_B* is 6 bits, max 0x40
+ {
+ wrlevel_dqs_final_delay[byte_i] -= 0x40;
+ MoveDramC_TX_DQS(p, byte_i, 2);
+ MoveDramC_TX_DQS_OEN(p, byte_i, 2);
+ }
+ wrlevel_dqs_delay[byte_i] = wrlevel_dqs_final_delay[byte_i];
+ }
+
+#ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+ gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag = u1GUMP_INIT_RG_LOG_TO_DE_bak;
+#endif
+
+#if 1
+ /* p->rank = RANK_0, save to Reg Rank0 and Rank1, p->rank = RANK_1, save to Reg Rank1 */
+ for(ii=p->rank; ii<RANK_MAX; ii++)
+ {
+ vSetRank(p,ii);
+
+ // set to best values for DQS
+ vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dqs_delay[0], SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+ vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dqs_delay[1], SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+ vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dqs_delay[2], SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+ vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dqs_delay[3], SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+ }
+ vSetRank(p,backup_rank);
+#else
+ // set to best values for DQS
+ vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dqs_delay[0], SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+ vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dqs_delay[1], SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+ vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dqs_delay[2], SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+ vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dqs_delay[3], SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+#endif
+
+
+ #if 1//EVEREST_CHANGE_OF_PHY_PBYTE
+ //Evereest new change, ARPI_DQ_RK0_ARPI_PBYTE_B* only move DQS, not including of DQM&DQ anymore.
+ //Add move DQ, DQ= DQS+0x10, after cali. take care diff. UI. with DQS
+ for(byte_i=0; byte_i<(p->data_width/DQS_BIT_NUMBER); byte_i++)
+ {
+ wrlevel_dq_delay[byte_i] = wrlevel_dqs_final_delay[byte_i] + 0x10;
+ if(wrlevel_dq_delay[byte_i] >= 0x40) //ARPI_DQ_B* is 6 bits, max 0x40
+ {
+ wrlevel_dq_delay[byte_i] -= 0x40;
+ MoveDramC_TX_DQ(p, byte_i, 2);
+ MoveDramC_TX_DQ_OEN(p, byte_i, 2);
+ }
+ }
+
+#if 1
+ /* p->rank = RANK_0, save to Reg Rank0 and Rank1, p->rank = RANK_1, save to Reg Rank1 */
+ for(ii=p->rank; ii<RANK_MAX; ii++)
+ {
+ vSetRank(p,ii);
+
+ // set to best values for DQ/DQM/DQ_OEN/DQM_OEN
+ vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+ vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[1], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+ vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[2], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+ vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[3], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+
+ vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+ vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[1], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+ vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[2], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+ vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[3], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+ }
+ vSetRank(p,backup_rank);
+#else
+ // set to best values for DQ/DQM/DQ_OEN/DQM_OEN
+ vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+ vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[1], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+ vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[2], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+ vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[3], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+
+
+ vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+#if (FOR_DV_SIMULATION_USED!=0)
+ vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[1], SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS);
+ vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[2], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+
+#else
+ vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[1], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+ vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[2], SHU1_R0_CA_CMD9_RG_RK0_ARPI_CS);
+#endif
+ vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), wrlevel_dq_delay[3], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+#endif
+
+ #endif
+
+ #if REG_SHUFFLE_REG_CHECK
+ ShuffleRegCheck =0;
+ #endif
+ }
+#endif
+ //DramcRankSwap(p, RANK_0);
+ //tx_rank_sel is selected by HW
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANK);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANKFIX); //TXRANKFIX should be write after TXRANK
+
+#if REG_ACCESS_PORTING_DGB
+ RegLogEnable =0;
+#endif
+ mcSHOW_DBG_MSG3(("[DramcWriteLeveling] Done\n\n"));
+ mcFPRINTF((fp_A60501, "[DramcWriteLeveling] Done\n\n"));
+
+ return KResult;
+}
+#endif //SIMULATION_WRITE_LEVELING
+
+
+#if SIMULATION_GATING
+//LP3 RODT is not enable, don't need to set the RODT settings.
+//LP4 RODT range is very large(5ns), no need to adjust with gating position
+//0x860 SHU_ODTCTRL 32 ODT CONTROL REGISTER
+// 31 31 RODTE RW PUBLIC 1'b1
+// 30 30 RODTE2 RW PUBLIC 1'b1
+// 7 4 RODT RW PUBLIC 4'bx= DQSINCTL or -1
+#if ENABLE_RODT_TRACKING
+#define GATING_RODT_LATANCY_EN 0 //disable when RODT tracking enable
+#else
+#define GATING_RODT_LATANCY_EN 1 //Need to enable when RODT enable
+#endif
+
+#define GATING_PATTERN_NUM_LP4 0x23
+#define GATING_GOLDEND_DQSCNT_LP4 0x4646
+
+#define GATING_PATTERN_NUM_LP3 0x46
+#define GATING_GOLDEND_DQSCNT_LP3 0x2323
+
+#define GATING_TXDLY_CHNAGE 1 //Gating txdly chcange & RANKINCTL setting
+
+#if SW_CHANGE_FOR_SIMULATION
+#define ucRX_DLY_DQSIENSTB_LOOP 32
+#define ucRX_DQS_CTL_LOOP 8
+#endif
+
+#if GATING_ADJUST_TXDLY_FOR_TRACKING
+U8 u1TXDLY_Cal_min =0xff, u1TXDLY_Cal_max=0;
+U8 ucbest_coarse_tune2T_backup[RANK_MAX][DQS_NUMBER];
+U8 ucbest_coarse_tune0p5T_backup[RANK_MAX][DQS_NUMBER];
+U8 ucbest_coarse_tune2T_P1_backup[RANK_MAX][DQS_NUMBER];
+U8 ucbest_coarse_tune0p5T_P1_backup[RANK_MAX][DQS_NUMBER];
+#endif
+
+// Use gating old burst mode to find gating window boundary
+// Set the begining of window as new burst mode gating window center.
+#define LP4_GATING_OLD_BURST_MODE 1
+#define LP4_GATING_LEAD_LAG_FLAG_JUDGE LP4_GATING_OLD_BURST_MODE
+
+/* Current function is for LP4 only
+ * u1Mode decides old or new length modes (7UI, 8UI) should be used
+ * 0: OLD 8UI mode (not extend 2T RD preamble)
+ * 1: NEW 7UI mode (extend 2T RD preamble) (DQS_GW_7UI defined)
+ * NEW 8UI mode (extend 2T RD preamble) (DQS_GW_7UI not defined)
+ */
+void DramcGatingMode(DRAMC_CTX_T *p, U8 u1Mode)
+{
+ // mode 0: old burst mode
+ // mode 1: 7UI or 8UI gating window length mode (depends on if DQS_GW_7UI is defined)
+#if (fcFOR_CHIP_ID == fcLaurel)
+ /* There are currently 2 ways to set GatingMode (sets different registers)
+ * 1. Alaska
+ * 2. Bianco, Whitney, Kibo+(Olympus)
+ */
+ U8 u1VrefSel = 0, u1BurstE2 = 0;
+
+ //mcSHOW_DBG_MSG3(("[GatingMode] "));
+ if (u1Mode == 0) /* old mode */
+ {
+ u1VrefSel = 0;
+ u1BurstE2 = 0;
+ //mcSHOW_DBG_MSG3(("old 8UI\n"));
+ }
+ else /* 7UI or 8UI gating window length mode */
+ {
+#ifdef DQS_GW_7UI
+ u1VrefSel = 2;
+ u1BurstE2 = 1;
+ //mcSHOW_DBG_MSG3(("new 7UI\n"));
+#else
+ u1VrefSel = 1;
+ u1BurstE2 = 0;
+ //mcSHOW_DBG_MSG3(("new 8UI\n"));
+#endif
+ }
+
+ /* BIAS_VREF_SEL is used as switch for old, new burst modes */
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ6), u1VrefSel, B0_DQ6_RG_RX_ARDQ_BIAS_VREF_SEL_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ6), u1VrefSel, B1_DQ6_RG_RX_ARDQ_BIAS_VREF_SEL_B1);
+#endif /* fcFOR_CHIP_ID */
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ9), 1, B0_DQ9_RG_RX_ARDQS0_DQSIENMODE_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ9), 1, B1_DQ9_RG_RX_ARDQS0_DQSIENMODE_B1);
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_STBCAL1), u1BurstE2, STBCAL1_DQSIEN_7UI_EN);
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_STBCAL), 1, STBCAL_DQSIENMODE_SELPH);
+
+ /* Perform reset (makes sure PHY's behavior works as the above setting) */
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ9), P_Fld(0, B0_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B0) |P_Fld(0, B0_DQ9_RG_RX_ARDQ_STBEN_RESETB_B0));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ9), P_Fld(0, B1_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B1) |P_Fld(0, B1_DQ9_RG_RX_ARDQ_STBEN_RESETB_B1));
+ mcDELAY_US(1);//delay 10ns
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ9), P_Fld(1, B1_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B1) |P_Fld(1, B1_DQ9_RG_RX_ARDQ_STBEN_RESETB_B1));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ9), P_Fld(1, B0_DQ9_RG_RX_ARDQS0_STBEN_RESETB_B0) |P_Fld(1, B0_DQ9_RG_RX_ARDQ_STBEN_RESETB_B0));
+ //DramPhyReset(p);
+#if __ETT__
+ if (u1IsLP4Family(p->dram_type) == FALSE)
+ { // GatingMode() is designed for LP4 only (only resets current channel PHY)
+ mcSHOW_ERR_MSG(("GatingMode err!(LP4 only)\n"));
+ }
+#endif
+}
+
+U8 u1GetGatingStartPos(DRAMC_CTX_T *p)
+{
+ const U8 au1MR2MappingToRL[2][8] = {{6, 10, 14, 20, 24, 28, 32, 36}, /*normal mode*/
+ {6, 10, 16, 22, 26, 32, 36, 40}}; /*byte mode*/
+
+ U8 u1MR0_LatencyMode;
+ U8 u1MR2RLValue = u1MR02Value[p->dram_fsp] & 0x7; /*MR2 Op[2:0]*/
+ U8 u1RX_Path_delay_UI, u1RealRL,u1StartUI, u1ExtraMCKfor1_4mode;
+ U8 u1MCK2CK_UI, u1ReadDQSINCTL, u1DQSINCTL_UI;
+ U8 u4TDQSCK_UI_min = 1500 * p->frequency *2/ 1000000;
+ /* 1500ps = ? UI */
+
+ if(gu2MR0_Value[p->rank] == 0xffff) /*MR0 is not ready*/
+ {
+ u1MR0_LatencyMode = CBT_NORMAL_MODE;
+ }
+ else
+ {
+ u1MR0_LatencyMode = (gu2MR0_Value[p->rank]>>1) & 0x1; /*MR0 OP[1], 0:normal mode, 1:byte mode*/
+ }
+
+ u1RealRL = au1MR2MappingToRL[u1MR0_LatencyMode][u1MR2RLValue];
+
+ if(0) /*(vGet_Div_Mode(p) == DIV4_MODE)*/
+ {
+ u1MCK2CK_UI = 4;
+ u1ExtraMCKfor1_4mode = 1;
+ }
+ else
+ {
+ u1MCK2CK_UI = 8;
+ u1ExtraMCKfor1_4mode = 0;
+ }
+
+ /* RX_Path_delay_UI = RL*2 + tDQSCK_UI<1500~3500ps> - PHY_interanl<skip 30ps> - GatingAheadDQS<2UI> + if(1:4 mod)+1MCK */
+ u1RX_Path_delay_UI = (u1RealRL<<1) + u4TDQSCK_UI_min - 2 + (u1MCK2CK_UI*u1ExtraMCKfor1_4mode);
+
+ u1ReadDQSINCTL = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_DQSCTL), SHURK0_DQSCTL_DQSINCTL);
+ u1DQSINCTL_UI = u1ReadDQSINCTL * u1MCK2CK_UI;
+
+ if((u1RX_Path_delay_UI-3) >= u1DQSINCTL_UI)
+ u1StartUI = (u1RX_Path_delay_UI -3) - u1DQSINCTL_UI; /* gating start calibration position = gating min position(1500ns) -3UI */
+ else
+ {
+ u1StartUI =0;
+ mcSHOW_ERR_MSG(("GatingStartPos err! Need to fine-tune default DQSINCTL value.\n(RX_Path_delay_UI %d) < DQSINCTL_UI %d)\n", u1RX_Path_delay_UI, u1DQSINCTL_UI));
+ #if __ETT__
+ while(1);
+ #endif
+ }
+
+ mcSHOW_DBG_MSG(("[GatingStartPos] MR0_LatencyMode %d, u1RealRL %d , u4TDQSCK_UI_min %d, 1:4ExtraMCK %d\n", u1MR0_LatencyMode, u1RealRL, u4TDQSCK_UI_min, u1ExtraMCKfor1_4mode));
+ mcSHOW_DBG_MSG(("RX_Path_delay_UI(%d) -3 - DQSINCTL_UI(%d) = u1StartUI(%d)\n", u1RX_Path_delay_UI, u1DQSINCTL_UI, u1StartUI));
+
+ return u1StartUI;
+}
+
+
+DRAM_STATUS_T DramcRxdqsGatingCal(DRAMC_CTX_T *p)
+{
+ #if !SW_CHANGE_FOR_SIMULATION
+ U8 ucRX_DLY_DQSIENSTB_LOOP,ucRX_DQS_CTL_LOOP;
+ #endif
+ U32 u4value, u4all_result_R=0, u4all_result_F=0, u4err_value;
+ U8 ucpass_begin[DQS_NUMBER] = {0}, ucpass_count[DQS_NUMBER] = {0}, ucCurrentPass;
+ U8 ucmin_coarse_tune2T[DQS_NUMBER] = {0}, ucmin_coarse_tune0p5T[DQS_NUMBER] = {0}, ucmin_fine_tune[DQS_NUMBER] = {0};
+ U8 ucpass_count_1[DQS_NUMBER] = {0}, ucmin_coarse_tune2T_1[DQS_NUMBER] = {0}, ucmin_coarse_tune0p5T_1[DQS_NUMBER] = {0}, ucmin_fine_tune_1[DQS_NUMBER] = {0};
+ U8 dqs_i=0, ucdly_coarse_large, ucdly_coarse_0p5T, ucdly_fine_xT, ucDQS_GW_FINE_STEP;
+ U8 ucdqs_result_R, ucdqs_result_F, uctmp_offset, uctmp_value;
+ U8 ucbest_fine_tune[DQS_NUMBER] = {0}, ucbest_coarse_tune0p5T[DQS_NUMBER] = {0}, ucbest_coarse_tune2T[DQS_NUMBER] = {0};
+ U8 ucbest_fine_tune_P1[DQS_NUMBER] = {0}, ucbest_coarse_tune0p5T_P1[DQS_NUMBER] = {0}, ucbest_coarse_tune2T_P1[DQS_NUMBER] = {0};
+
+ U8 ucFreqDiv;
+ U8 ucdly_coarse_large_P1, ucdly_coarse_0p5T_P1;
+
+ #if GATING_ADJUST_TXDLY_FOR_TRACKING
+ U8 u1TX_dly_DQSgated = 0;
+ #endif
+
+ #if GATING_RODT_LATANCY_EN
+ U8 ucdly_coarse_large_RODT, ucdly_coarse_0p5T_RODT;
+ U8 ucdly_coarse_large_RODT_P1 = 0, ucdly_coarse_0p5T_RODT_P1 = 0;
+ U8 ucbest_coarse_large_RODT[DQS_NUMBER] = {0}, ucbest_coarse_0p5T_RODT[DQS_NUMBER] = {0};
+ U8 ucbest_coarse_large_RODT_P1[DQS_NUMBER] = {0}, ucbest_coarse_0p5T_RODT_P1[DQS_NUMBER] = {0};
+ #endif
+ U8 ucCoarseTune=0, ucCoarseStart=8, ucCoarseEnd=8;
+#if ENABLE_LP3_SW
+ U32 LP3_DataPerByte[DQS_NUMBER] = {0};
+#endif
+ U32 u4DebugCnt[DQS_NUMBER] = {0};
+ U16 u2DebugCntPerByte;
+
+ #if LP4_GATING_LEAD_LAG_FLAG_JUDGE
+ U8 u1DQS_lead[DQS_NUMBER] = {0}, u1DQS_lag[DQS_NUMBER] = {0}, u1DQS_high[DQS_NUMBER] = {0}, u1DQS_transition[DQS_NUMBER] = {0}, u1DQSGatingFound[DQS_NUMBER] = {0};
+ U8 ucdly_coarse_large_leadLag[DQS_NUMBER] = {0}, ucdly_coarse_0p5T_leadLag[DQS_NUMBER] = {0}, ucdly_fine_tune_leadLag[DQS_NUMBER] = {0};
+ #endif
+
+ U8 u1PassByteCount=0;
+
+ #if 0///SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ U8 ucpass_offset=0;
+ U8 ucpass_count_0_temp=0;
+ U8 ucpass_count_1_temp=0;
+ U8 ucCoarseTune_offset=0;
+ U8 minpasscount=0;
+ #endif
+
+ // error handling
+ if (!p)
+ {
+ mcSHOW_ERR_MSG(("context NULL\n"));
+ return DRAM_FAIL;
+ }
+
+ U32 u4RegBackupAddress[] =
+ {
+ (DRAMC_REG_ADDR(DRAMC_REG_STBCAL)),
+ (DRAMC_REG_ADDR(DRAMC_REG_STBCAL1)),
+ (DRAMC_REG_ADDR(DRAMC_REG_DDRCONF0)),
+ (DRAMC_REG_ADDR(DRAMC_REG_SPCMD)),
+ (DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0)),
+ #if LP4_GATING_OLD_BURST_MODE
+ (DRAMC_REG_ADDR(DDRPHY_B0_DQ6)),
+ (DRAMC_REG_ADDR(DDRPHY_B1_DQ6)),
+ #else
+ (DRAMC_REG_ADDR(DDRPHY_B0_DQ7)),
+ (DRAMC_REG_ADDR(DDRPHY_B1_DQ7)),
+ #endif
+ };
+
+
+ //Register backup
+ DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+ //Justin: DQ_REV_B*[5] =1, select RX gating mode to prevent 0.5T fake gating window behind real window.
+ if(u1IsLP4Family(p->dram_type))
+ {
+ #if MRW_CHECK_ONLY
+ mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
+ #endif
+ /* LP4: Disable(set to 0) "RX DQS ISI pulse CG function" during gating window calibration (must set to 1 when done) */
+ RxDQSIsiPulseCG(p, DISABLE);
+
+ #if LP4_GATING_OLD_BURST_MODE
+ #if !LP4_GATING_LEAD_LAG_FLAG_JUDGE
+ DramcGatingMode(p, 0);
+ #endif
+ u1MR01Value[p->dram_fsp] |= 0x80;
+ DramcModeRegWriteByRank(p, p->rank, 1, u1MR01Value[p->dram_fsp]);
+ #else
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ7), P_Fld( 1, B0_DQ7_RG_TX_ARDQS_PULL_UP_B0) | P_Fld( 1, B0_DQ7_RG_TX_ARDQSB_PULL_DN_B0));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ7), P_Fld( 1, B1_DQ7_RG_TX_ARDQS0_PULL_UP_B1) | P_Fld( 1, B1_DQ7_RG_TX_ARDQS0B_PULL_DN_B1));
+ #endif
+ }
+ #if 0 // LP3: Since it is always set to 1 (should be set during initial register settings, comment out here to save code size
+ else
+ {
+ /* LP3: Always enable(set to 1) "RX DQS ISI pulse CG function" */
+ RxDQSIsiPulseCG(p, ENABLE);
+ }
+ #endif
+
+ //Disable perbank refresh, use all bank refresh, currently DUT problem
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0), 0, REFCTRL0_PBREFEN);
+
+ // Disable HW gating first, 0x1c0[31], need to disable both UI and PI tracking or the gating delay reg won't be valid.
+ DramcHWGatingOnOff(p, 0);
+
+ //If DQS ring counter is different as our expectation, error flag is asserted and the status is in ddrphycfg 0xFC0 ~ 0xFCC
+ //Enable this function by R_DMSTBENCMPEN=1 (0x348[18])
+ //Set R_DMSTBCNT_LATCH_EN=1, 0x348[11]
+ //Set R_DM4TO1MODE=0, 0x54[11]
+ //Clear error flag by ddrphycfg 0x5c0[1] R_DMPHYRST
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_STBCAL1), 1, STBCAL1_STBENCMPEN);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_STBCAL1), 1, STBCAL1_STBCNT_LATCH_EN);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DDRCONF0), 0, DDRCONF0_DM4TO1MODE);
+
+ //enable &reset DQS counter
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_DQSGCNTEN);
+ mcDELAY_US(4);//wait 1 auto refresh after DQS Counter enable
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_DQSGCNTRST);
+ mcDELAY_US(1);//delay 2T
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_DQSGCNTRST);
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), u1GetRank(p), MISC_CTRL1_R_DMSTBENCMP_RK_OPT);
+ DramcEngine2Init(p, 0x55000000, 0xaa000000 |GATING_PATTERN_NUM_LP4, TEST_AUDIO_PATTERN, 0);
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ vIO32WriteFldAlign_All(DDRPHY_MISC_CTRL1, u1GetRank(p), MISC_CTRL1_R_DMSTBENCMP_RK_OPT);
+ DramcEngine2Init(p, 0x55000000, 0xaa000000 |GATING_PATTERN_NUM_LP3, TEST_AUDIO_PATTERN, 0);
+ }
+#endif
+
+ #if 0 // Array initialization are now performed during declaration
+ //Initialize variables
+ for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+ {
+ ucpass_begin[dqs_i] = 0;
+ ucpass_count[dqs_i] = 0;
+ #if LP4_GATING_LEAD_LAG_FLAG_JUDGE
+ u1DQS_lead[dqs_i] = 0;
+ u1DQS_lag[dqs_i] = 0;
+ u1DQS_high[dqs_i] = 0;
+ u1DQS_transition[dqs_i] =0;
+
+ ucdly_coarse_large_leadLag[dqs_i] = 0;
+ ucdly_coarse_0p5T_leadLag[dqs_i] = 0;
+ ucdly_fine_tune_leadLag[dqs_i] = 0;
+ #endif
+ }
+ #endif
+ #if !SW_CHANGE_FOR_SIMULATION
+ ucRX_DLY_DQSIENSTB_LOOP= 32;// PI fine tune 0->31
+ ucRX_DQS_CTL_LOOP = 8; // Since Everest, no matter LP3 or LP4. ucRX_DQS_CTL_LOOP is 8.
+ #endif
+
+ #ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+ U8 u1GUMP_INIT_RG_LOG_TO_DE_bak = gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag;
+ gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag=0;
+ #endif
+
+ mcSHOW_DBG_MSG2(("[Gating]\n"));
+ vPrintCalibrationBasicInfo(p);
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ ucFreqDiv= 4;
+ ucDQS_GW_FINE_STEP = DQS_GW_FINE_STEP;
+
+ /* ucCoarseStart
+ * 1. Depends on current freq's DQSINCTL setting
+ * 2. Preserves ~4UI before actual DQS delay value
+ */
+
+ ucCoarseStart = u1GetGatingStartPos(p);
+
+#if SPECIAL_WORKAROUND_FOR_LP4
+ //for Biwin/LongSys DRAM special workaround
+ if (p->dram_type == TYPE_LPDDR4)
+ {
+ ucCoarseStart -= 8;
+ ucCoarseEnd = ucCoarseStart + 28; // for Hynix LP4
+ }
+ else
+#endif
+ ucCoarseEnd = ucCoarseStart + 12;
+
+ if (Get_MDL_Used_Flag()==GET_MDL_USED)
+ ucCoarseEnd+=8; // extend gating calibration range if wrong byte/normal setting
+ }
+#if ENABLE_LP3_SW
+ else //LPDDR3
+ {
+ ucFreqDiv= 2;
+ ucDQS_GW_FINE_STEP = DQS_GW_FINE_STEP;
+
+ if(p->frequency >= 933) //1600
+ ucCoarseStart = 8;
+ else if(p->frequency >= 800) //1600
+ ucCoarseStart = 8;
+ else if(p->frequency >= 600) //1333, 1200
+ ucCoarseStart = 8;
+ else //if(p->frequency >= 533) //933
+ ucCoarseStart = 6;
+
+ #if 0//FOR_DV_SIMULATION_USED
+ if(ucCoarseStart >=5)
+ ucCoarseStart -=5;
+ else
+ ucCoarseStart=0;
+ #endif
+
+ ucCoarseEnd = ucCoarseStart+12;
+ }
+#endif
+
+ #if GATING_RODT_LATANCY_EN //LP3 RODT is not enable, don't need to set the RODT settings.
+ // Fix build warning, initialize variables.
+ ucdly_coarse_large_RODT = 0;
+ ucdly_coarse_0p5T_RODT = 0;
+
+ if (u1IsLP4Family(p->dram_type))
+ {
+ ucdly_coarse_large_RODT_P1 = 4;
+ ucdly_coarse_0p5T_RODT_P1 = 4;
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ ucdly_coarse_large_RODT_P1 = 2;
+ ucdly_coarse_0p5T_RODT_P1 = 2;
+ }
+#endif /* ENABLE_LP3_SW */
+
+ // 1. DQSG latency =
+ // (1) R_DMR*DQSINCTL[3:0] (MCK) +
+ // (2) selph_TX_DLY[2:0] (MCK) +
+ // (3) selph_dly[2:0] (UI)
+
+ // 2. RODT latency =
+ // (1) R_DMTRODT[3:0] (MCK) +
+ // (2) selph_TX_DLY[2:0] (MCK) +
+ // (3) selph_dly[2:0] (UI)
+
+ #if 0
+ if(u1IsLP4Family(p->dram_type))
+ {
+ //R_DMTRODT[3:0] (MCK) = R_DMR*DQSINCTL[3:0] (MCK)
+ //if(p->rank == RANK_0)
+ {
+ u4value = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_DQSCTL), SHURK0_DQSCTL_DQSINCTL);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_ODTCTRL), u4value, SHU_ODTCTRL_RODT);
+ }
+ #if 0 //R1DQSINCTL and R2DQSINCTL is useless on A-PHY. Only need to set RODT once.
+ else //rank1
+ {
+ u4value = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSCTL2), DQSCTL2_R1DQSINCTL);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DDR2CTL), u4value & 0x7, DDR2CTL_RODT);//R_DMTRODT[2:0]
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DDR2CTL), (u4value >>3), DDR2CTL_RODT3);//R_DMTRODT[3]
+ }
+ #endif
+ }
+ #endif
+ #endif
+
+#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_GatingCal)
+ if(p->femmc_Ready==1)
+ {
+ mcSHOW_DBG_MSG2(("[bypass Gating]\n"));
+ }
+ else
+#endif
+ {
+ for (ucCoarseTune = ucCoarseStart; ucCoarseTune < ucCoarseEnd; ucCoarseTune += DQS_GW_COARSE_STEP)
+ {
+ ucdly_coarse_large = ucCoarseTune / ucRX_DQS_CTL_LOOP;
+ ucdly_coarse_0p5T = ucCoarseTune % ucRX_DQS_CTL_LOOP;
+
+ ucdly_coarse_large_P1 = (ucCoarseTune + ucFreqDiv) / ucRX_DQS_CTL_LOOP;
+ ucdly_coarse_0p5T_P1 =(ucCoarseTune + ucFreqDiv) % ucRX_DQS_CTL_LOOP;
+
+ #if GATING_RODT_LATANCY_EN //LP3 RODT is not enable, don't need to set the RODT settings.
+ if(u1IsLP4Family(p->dram_type))
+ {
+ u4value = (ucdly_coarse_large <<3)+ucdly_coarse_0p5T;
+
+ if(u4value>=11)
+ {
+ u4value -=11;
+ ucdly_coarse_large_RODT = u4value>>3;
+ ucdly_coarse_0p5T_RODT = u4value -(ucdly_coarse_large_RODT<<3);
+
+ u4value = (ucdly_coarse_large <<3)+ucdly_coarse_0p5T -11;
+ ucdly_coarse_large_RODT_P1 = u4value>>3;
+ ucdly_coarse_0p5T_RODT_P1 = u4value -(ucdly_coarse_large_RODT_P1<<3);
+ }
+ else
+ {
+ ucdly_coarse_large_RODT = 0;
+ ucdly_coarse_0p5T_RODT = 0;
+
+ ucdly_coarse_large_RODT_P1 = 4;
+ ucdly_coarse_0p5T_RODT_P1 = 4;
+
+ mcSHOW_ERR_MSG(("[RxdqsGatingCal] Error: ucdly_coarse_large_RODT[%d] is already 0. RODT cannot be -11 UI\n", dqs_i));
+ mcFPRINTF((fp_A60501, "[RxdqsGatingCal] Error: ucdly_coarse_large_RODT[%d] is already 0. RODT cannot be -11 UI\n", dqs_i));
+ }
+ }
+ #endif
+
+ //DramPhyCGReset(p, 1);// need to reset when UI update or PI change >=2
+
+ // 4T or 2T coarse tune
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQSG0), \
+ P_Fld((U32) ucdly_coarse_large, SHURK0_SELPH_DQSG0_TX_DLY_DQS0_GATED)| \
+ P_Fld((U32) ucdly_coarse_large, SHURK0_SELPH_DQSG0_TX_DLY_DQS1_GATED)| \
+ P_Fld((U32) ucdly_coarse_large, SHURK0_SELPH_DQSG0_TX_DLY_DQS2_GATED)| \
+ P_Fld((U32) ucdly_coarse_large, SHURK0_SELPH_DQSG0_TX_DLY_DQS3_GATED)| \
+ P_Fld((U32) ucdly_coarse_large_P1, SHURK0_SELPH_DQSG0_TX_DLY_DQS0_GATED_P1)| \
+ P_Fld((U32) ucdly_coarse_large_P1, SHURK0_SELPH_DQSG0_TX_DLY_DQS1_GATED_P1)| \
+ P_Fld((U32) ucdly_coarse_large_P1, SHURK0_SELPH_DQSG0_TX_DLY_DQS2_GATED_P1)| \
+ P_Fld((U32) ucdly_coarse_large_P1, SHURK0_SELPH_DQSG0_TX_DLY_DQS3_GATED_P1));
+
+ // 0.5T coarse tune
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQSG1), \
+ P_Fld((U32) ucdly_coarse_0p5T, SHURK0_SELPH_DQSG1_REG_DLY_DQS0_GATED)| \
+ P_Fld((U32) ucdly_coarse_0p5T, SHURK0_SELPH_DQSG1_REG_DLY_DQS1_GATED)| \
+ P_Fld((U32) ucdly_coarse_0p5T, SHURK0_SELPH_DQSG1_REG_DLY_DQS2_GATED)| \
+ P_Fld((U32) ucdly_coarse_0p5T, SHURK0_SELPH_DQSG1_REG_DLY_DQS3_GATED)| \
+ P_Fld((U32) ucdly_coarse_0p5T_P1, SHURK0_SELPH_DQSG1_REG_DLY_DQS0_GATED_P1)| \
+ P_Fld((U32) ucdly_coarse_0p5T_P1, SHURK0_SELPH_DQSG1_REG_DLY_DQS1_GATED_P1)| \
+ P_Fld((U32) ucdly_coarse_0p5T_P1, SHURK0_SELPH_DQSG1_REG_DLY_DQS2_GATED_P1)| \
+ P_Fld((U32) ucdly_coarse_0p5T_P1, SHURK0_SELPH_DQSG1_REG_DLY_DQS3_GATED_P1));
+
+ #if GATING_RODT_LATANCY_EN //LP3 RODT is not enable, don't need to set the RODT settings.
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_ODTEN0), \
+ P_Fld((U32) ucdly_coarse_large_RODT, SHURK0_SELPH_ODTEN0_TXDLY_B0_RODTEN)| \
+ P_Fld((U32) ucdly_coarse_large_RODT, SHURK0_SELPH_ODTEN0_TXDLY_B1_RODTEN)| \
+ P_Fld((U32) ucdly_coarse_large_RODT, SHURK0_SELPH_ODTEN0_TXDLY_B2_RODTEN)| \
+ P_Fld((U32) ucdly_coarse_large_RODT, SHURK0_SELPH_ODTEN0_TXDLY_B3_RODTEN)| \
+ P_Fld((U32) ucdly_coarse_large_RODT_P1, SHURK0_SELPH_ODTEN0_TXDLY_B0_RODTEN_P1)| \
+ P_Fld((U32) ucdly_coarse_large_RODT_P1, SHURK0_SELPH_ODTEN0_TXDLY_B1_RODTEN_P1)| \
+ P_Fld((U32) ucdly_coarse_large_RODT_P1, SHURK0_SELPH_ODTEN0_TXDLY_B2_RODTEN_P1)| \
+ P_Fld((U32) ucdly_coarse_large_RODT_P1, SHURK0_SELPH_ODTEN0_TXDLY_B3_RODTEN_P1));
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_ODTEN1), \
+ P_Fld((U32) ucdly_coarse_0p5T_RODT, SHURK0_SELPH_ODTEN1_DLY_B0_RODTEN)| \
+ P_Fld((U32) ucdly_coarse_0p5T_RODT, SHURK0_SELPH_ODTEN1_DLY_B1_RODTEN)| \
+ P_Fld((U32) ucdly_coarse_0p5T_RODT, SHURK0_SELPH_ODTEN1_DLY_B2_RODTEN)| \
+ P_Fld((U32) ucdly_coarse_0p5T_RODT, SHURK0_SELPH_ODTEN1_DLY_B3_RODTEN)| \
+ P_Fld((U32) ucdly_coarse_0p5T_RODT_P1, SHURK0_SELPH_ODTEN1_DLY_B0_RODTEN_P1)| \
+ P_Fld((U32) ucdly_coarse_0p5T_RODT_P1, SHURK0_SELPH_ODTEN1_DLY_B1_RODTEN_P1)| \
+ P_Fld((U32) ucdly_coarse_0p5T_RODT_P1, SHURK0_SELPH_ODTEN1_DLY_B2_RODTEN_P1)| \
+ P_Fld((U32) ucdly_coarse_0p5T_RODT_P1, SHURK0_SELPH_ODTEN1_DLY_B3_RODTEN_P1));
+
+ //mcSHOW_DBG_MSG2(("RODT delay(2T, 0.5T) = (%d, %d)\n", ucdly_coarse_large_RODT, ucdly_coarse_0p5T_RODT));
+ //mcFPRINTF((fp_A60501,"RODT delay(2T, 0.5T) = (%d, %d)\n", ucdly_coarse_large_RODT, ucdly_coarse_0p5T_RODT));
+ }
+ #endif
+
+ for (ucdly_fine_xT=DQS_GW_FINE_START; ucdly_fine_xT<DQS_GW_FINE_END; ucdly_fine_xT+=ucDQS_GW_FINE_STEP)
+ {
+ #if LP4_GATING_LEAD_LAG_FLAG_JUDGE
+ if(u1IsLP4Family(p->dram_type))
+ {
+ DramcGatingMode(p, 0);
+ }
+ #endif
+
+ //ok we set a coarse/fine tune value already
+ u4value = ucdly_fine_xT | (ucdly_fine_xT<<8) | (ucdly_fine_xT<<16) | (ucdly_fine_xT<<24);
+ vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_DQSIEN), u4value);
+
+ //reset phy, reset read data counter
+ DramPhyReset(p);
+
+ //reset DQS counter
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_DQSGCNTRST);
+ mcDELAY_US(1);//delay 2T
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_DQSGCNTRST);
+
+ // enable TE2, audio pattern
+ DramcEngine2Run(p, TE_OP_READ_CHECK, TEST_AUDIO_PATTERN);
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ u4all_result_R = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_STBERR_RK0_R), MISC_STBERR_RK0_R_STBERR_RK0_R);
+ u4all_result_F = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_STBERR_RK0_F), MISC_STBERR_RK0_F_STBERR_RK0_F);
+ }
+ #if ENABLE_LP3_SW
+ else //LPDDR3
+ {
+ LP3_DataPerByte[0] = u4IO32ReadFldAlign(DDRPHY_MISC_STBERR_RK0_R, MISC_STBERR_RK0_R_STBERR_RK0_R); // CHA for B0 and B1
+ LP3_DataPerByte[1] = u4IO32ReadFldAlign(DDRPHY_MISC_STBERR_RK0_R+SHIFT_TO_CHB_ADDR, MISC_STBERR_RK0_R_STBERR_RK0_R);// CHB for B2 and B3
+ u4all_result_R = LP3_DataPerByte[0] | (LP3_DataPerByte[1] <<16);
+
+ LP3_DataPerByte[0] = u4IO32ReadFldAlign(DDRPHY_MISC_STBERR_RK0_F, MISC_STBERR_RK0_F_STBERR_RK0_F); // CHA for B0 and B1
+ LP3_DataPerByte[1] = u4IO32ReadFldAlign(DDRPHY_MISC_STBERR_RK0_F+SHIFT_TO_CHB_ADDR, MISC_STBERR_RK0_F_STBERR_RK0_F);// CHB for B2 and B3
+ u4all_result_F = LP3_DataPerByte[0] | (LP3_DataPerByte[1] <<16);
+ }
+ #endif
+
+ //read DQS counter
+ u4DebugCnt[0] = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_DQSGNWCNT0));
+ u4DebugCnt[1] = (u4DebugCnt[0] >> 16) & 0xffff;
+ u4DebugCnt[0] &= 0xffff;
+#if ENABLE_LP3_SW
+ if(p->dram_type == TYPE_LPDDR3)
+ {
+ u4DebugCnt[2] = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_DQSGNWCNT1));
+ u4DebugCnt[3] = (u4DebugCnt[2] >> 16) & 0xffff;
+ u4DebugCnt[2] &= 0xffff;
+ }
+#endif /* ENABLE_LP3_SW */
+ u4err_value =0;
+
+ #if LP4_GATING_LEAD_LAG_FLAG_JUDGE
+ if(u1IsLP4Family(p->dram_type))
+ {
+ DramcGatingMode(p, 1);
+ DramcEngine2Run(p, TE_OP_READ_CHECK, TEST_AUDIO_PATTERN);// trigger read to make lead/lag flag update.
+
+ for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+ {
+ if(u1DQSGatingFound[dqs_i]==1)
+ {
+ continue;
+ }
+
+ if(dqs_i==0)
+ {
+ u1DQS_lead[0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_PHY_RGS_STBEN_B0), MISC_PHY_RGS_STBEN_B0_AD_RX_ARDQS0_STBEN_LEAD_B0);
+ u1DQS_lag[0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_PHY_RGS_STBEN_B0), MISC_PHY_RGS_STBEN_B0_AD_RX_ARDQS0_STBEN_LAG_B0);
+ }
+ else //dqs1
+ {
+ u1DQS_lead[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_PHY_RGS_STBEN_B1), MISC_PHY_RGS_STBEN_B1_AD_RX_ARDQS0_STBEN_LEAD_B1);
+ u1DQS_lag[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_PHY_RGS_STBEN_B1), MISC_PHY_RGS_STBEN_B1_AD_RX_ARDQS0_STBEN_LAG_B1);
+ }
+
+ if((u1DQS_lead[dqs_i]==1) && (u1DQS_lag[dqs_i]==1))
+ {
+ u1DQS_high[dqs_i] ++;
+ //mcSHOW_DBG_MSG2(("[Byte %d] Lead/lag falling high (%d)\n", dqs_i,u1DQS_high[dqs_i]));
+ }
+
+ if(u1DQS_high[dqs_i] *ucDQS_GW_FINE_STEP >16)//>16 PI prevent glitch
+ {
+ if((u1DQS_lead[dqs_i]==1) && (u1DQS_lag[dqs_i]==1))
+ {
+ ucdly_coarse_large_leadLag[dqs_i] = ucdly_coarse_large;
+ ucdly_coarse_0p5T_leadLag[dqs_i] = ucdly_coarse_0p5T;
+ ucdly_fine_tune_leadLag[dqs_i] = ucdly_fine_xT;
+ u1DQS_transition[dqs_i] =1;
+ }
+ else if(((u1DQS_lead[dqs_i]==1) && (u1DQS_lag[dqs_i]==0)) ||((u1DQS_lead[dqs_i]==0) && (u1DQS_lag[dqs_i]==1)))
+ {
+ if(u1DQS_transition[dqs_i] ==1)
+ {
+ mcSHOW_DBG_MSG(("[Byte %d] Lead/lag falling Transition (%d, %d, %d)\n", dqs_i,ucdly_coarse_large_leadLag[dqs_i], ucdly_coarse_0p5T_leadLag[dqs_i], ucdly_fine_tune_leadLag[dqs_i]));
+ }
+ u1DQS_transition[dqs_i] ++;
+ }
+ else if((u1DQS_lead[dqs_i]==0) && (u1DQS_lag[dqs_i]==0))
+ {
+ mcSHOW_DBG_MSG(("[Byte %d] Lead/lag Transition tap number (%d)\n", dqs_i, u1DQS_transition[dqs_i]));
+ u1DQS_high[dqs_i] =0;
+ }
+ }
+ }
+ }
+ #endif
+
+ /*TINFO="%2d %2d %2d |(B3->B0) 0x%4x, 0x%4x, 0x%4x, 0x%4x | %2x %2x %2x %2x %2x %2x %2x %2x | 0x%8x\n", ucdly_coarse_large, ucdly_coarse_0p5T, ucdly_fine_xT, \
+ u4DebugCnt[3], u4DebugCnt[2], u4DebugCnt[1], u4DebugCnt[0], \
+ (u4all_result_F>>24)&0xff, (u4all_result_R>>24)&0xff, \
+ (u4all_result_F>>16)&0xff, (u4all_result_R>>16)&0xff, \
+ (u4all_result_F>>8)&0xff, (u4all_result_R>>8)&0xff, \
+ (u4all_result_F)&0xff, (u4all_result_R)&0xff, u4err_value*/
+
+ #ifdef ETT_PRINT_FORMAT
+ #if 0
+ mcSHOW_DBG_MSG(("%d %d %d |(B3->B0) 0x%H, 0x%H, 0x%H, 0x%H | %B %B %B %B %B %B %B %B | B0(%d, %d) B1(%d, %d) |0x%X\n",
+ ucdly_coarse_large, ucdly_coarse_0p5T, ucdly_fine_xT, \
+ u4DebugCnt[3], u4DebugCnt[2], u4DebugCnt[1], u4DebugCnt[0], \
+ (u4all_result_F>>24)&0xff, (u4all_result_R>>24)&0xff, \
+ (u4all_result_F>>16)&0xff, (u4all_result_R>>16)&0xff, \
+ (u4all_result_F>>8)&0xff, (u4all_result_R>>8)&0xff, \
+ (u4all_result_F)&0xff, (u4all_result_R)&0xff,
+ #if LP4_GATING_LEAD_LAG_FLAG_JUDGE
+ u1DQS_lead[0], u1DQS_lag[0], u1DQS_lead[1], u1DQS_lag[1],
+ #else
+ 0,0,0,0,
+ #endif
+ u4err_value));
+ #else
+ mcSHOW_DBG_MSG(("%d %d %d |", ucdly_coarse_large, ucdly_coarse_0p5T, ucdly_fine_xT ));
+
+ for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+ {
+ mcSHOW_DBG_MSG(("%X ", u4DebugCnt[dqs_i]));
+ }
+ mcSHOW_DBG_MSG((" |"));
+ for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+ {
+ mcSHOW_DBG_MSG(("(%X %X)", (u4all_result_F>>(DQS_BIT_NUMBER*dqs_i)) & 0xff, (u4all_result_R>>(DQS_BIT_NUMBER*dqs_i)) & 0xff));
+ }
+
+ #if LP4_GATING_LEAD_LAG_FLAG_JUDGE
+ mcSHOW_DBG_MSG((" |"));
+ for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+ {
+ mcSHOW_DBG_MSG(("(%d %d)", u1DQS_lead[dqs_i], u1DQS_lag[dqs_i]));
+ }
+ #endif
+
+ mcSHOW_DBG_MSG2(("| %X", u4err_value));
+ mcSHOW_DBG_MSG(("\n"));
+ #endif
+
+ #else
+ mcSHOW_DBG_MSG(("%2d %2d %2d |(B3->B0) 0x%4x, 0x%4x, 0x%4x, 0x%4x | %2x %2x %2x %2x %2x %2x %2x %2x | 0x%8x\n", ucdly_coarse_large, ucdly_coarse_0p5T, ucdly_fine_xT, \
+ u4DebugCnt[3], u4DebugCnt[2], u4DebugCnt[1], u4DebugCnt[0], \
+ (u4all_result_F>>24)&0xff, (u4all_result_R>>24)&0xff, \
+ (u4all_result_F>>16)&0xff, (u4all_result_R>>16)&0xff, \
+ (u4all_result_F>>8)&0xff, (u4all_result_R>>8)&0xff, \
+ (u4all_result_F)&0xff, (u4all_result_R)&0xff, u4err_value));
+
+ #endif
+
+ mcFPRINTF((fp_A60501,"%2d %2d %2d |(B3->B0) 0x%4x, 0x%4x, 0x%4x, 0x%4x | (B3->B0) %2x %2x %2x %2x %2x %2x %2x %2x | 0x%8x\n", ucdly_coarse_large, ucdly_coarse_0p5T, ucdly_fine_xT, \
+ u4DebugCnt[3], u4DebugCnt[2], u4DebugCnt[1], u4DebugCnt[0], \
+ (u4all_result_F>>24)&0xff, (u4all_result_R>>24)&0xff, \
+ (u4all_result_F>>16)&0xff, (u4all_result_R>>16)&0xff, \
+ (u4all_result_F>>8)&0xff, (u4all_result_R>>8)&0xff, \
+ (u4all_result_F)&0xff, (u4all_result_R)&0xff, u4err_value));
+
+ //find gating window pass range per DQS separately
+ for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+ {
+ if(u1PassByteCount & (1<<dqs_i))
+ {
+ // real window found, break to prevent finding fake window.
+ continue;
+ }
+ //get dqs error result
+ ucdqs_result_R = (U8)((u4all_result_R>>(8*dqs_i))&0xff);
+ ucdqs_result_F = (U8)((u4all_result_F>>(8*dqs_i))&0xff);
+ u2DebugCntPerByte =(U16) u4DebugCnt[dqs_i];
+
+ // check if current tap is pass
+ ucCurrentPass =0;
+ if(u1IsLP4Family(p->dram_type))
+ {
+ if((ucdqs_result_R==0) && (ucdqs_result_F==0) && (u2DebugCntPerByte==GATING_GOLDEND_DQSCNT_LP4))
+ ucCurrentPass =1;
+ }
+ #if ENABLE_LP3_SW
+ else //LPDDR3
+ {
+ if((ucdqs_result_R==0) && (ucdqs_result_F==0) && (u2DebugCntPerByte==GATING_GOLDEND_DQSCNT_LP3))
+ {
+ ucCurrentPass =1;
+ ucDQS_GW_FINE_STEP = 1;
+ }
+ }
+ #endif
+
+ //if current tap is pass
+ if (ucCurrentPass)
+ {
+ if (ucpass_begin[dqs_i]==0)
+ {
+ //no pass tap before , so it is the begining of pass range
+ ucpass_begin[dqs_i] = 1;
+ ucpass_count_1[dqs_i] = 0;
+ ucmin_coarse_tune2T_1[dqs_i] = ucdly_coarse_large;
+ ucmin_coarse_tune0p5T_1[dqs_i] = ucdly_coarse_0p5T;
+ ucmin_fine_tune_1[dqs_i] = ucdly_fine_xT;
+
+ /*TINFO="[Byte %d]First pass (%d, %d, %d)\n", dqs_i,ucdly_coarse_large, ucdly_coarse_0p5T, ucdly_fine_xT*/
+ mcSHOW_DBG_MSG2(("[Byte %d]First pass (%d, %d, %d)\n", dqs_i, ucdly_coarse_large, ucdly_coarse_0p5T, ucdly_fine_xT));
+ }
+
+ if (ucpass_begin[dqs_i]==1)
+ {
+ //incr pass tap number
+ ucpass_count_1[dqs_i]++;
+ }
+
+#if LP4_GATING_LEAD_LAG_FLAG_JUDGE
+ // Francis add to prevent lead/lag transition miss judgement
+ if (u1IsLP4Family(p->dram_type) && (ucpass_begin[dqs_i] == 1) && (ucpass_count_1[dqs_i]*ucDQS_GW_FINE_STEP > 32))
+ {
+ u1DQSGatingFound[dqs_i] =1;
+ }
+
+ if (u1IsLP4Family(p->dram_type) && (ucpass_count_1[0]*ucDQS_GW_FINE_STEP > 32) && (ucpass_count_1[1]*ucDQS_GW_FINE_STEP > 32))
+ {
+ // if all bytes gating windows > 1UI, then early break;
+ mcSHOW_DBG_MSG2(("All bytes gating window > 1UI, Early break!\n"));
+ mcFPRINTF((fp_A60501, "All bytes gating window > 1UI, Early break!\n"));
+ ucdly_fine_xT = DQS_GW_FINE_END;//break loop
+ ucCoarseTune = ucCoarseEnd; //break loop
+
+ }
+#endif
+ }
+ else // current tap is fail
+ {
+ if (ucpass_begin[dqs_i]==1)
+ {
+ //at the end of pass range
+ ucpass_begin[dqs_i] = 0;
+
+ //save the max range settings, to avoid glitch
+ if (ucpass_count_1[dqs_i] > ucpass_count[dqs_i])
+ {
+ ucmin_coarse_tune2T[dqs_i] = ucmin_coarse_tune2T_1[dqs_i];
+ ucmin_coarse_tune0p5T[dqs_i] = ucmin_coarse_tune0p5T_1[dqs_i];
+ ucmin_fine_tune[dqs_i] = ucmin_fine_tune_1[dqs_i];
+ ucpass_count[dqs_i] = ucpass_count_1[dqs_i];
+
+#if ENABLE_LP3_SW
+ //LP3 CHB_CA didn't has lead/lag RG, use SW workaround
+ if (!u1IsLP4Family(p->dram_type))
+ {
+ if (ucpass_count_1[dqs_i] >= 70) // if didn't check fail region and pass UI more than 2UI, then workaround back to 2UI
+ {
+ ucpass_count_1[dqs_i] = 64; // 2UI
+ ucpass_count[dqs_i] = ucpass_count_1[dqs_i];
+ }
+ }
+#endif
+
+ /*TINFO="[Byte %d]Bigger pass win(%d, %d, %d) Pass tap=%d\n", \
+ dqs_i, ucmin_coarse_tune2T_1[dqs_i], ucmin_coarse_tune0p5T_1[dqs_i], ucmin_fine_tune_1[dqs_i], ucpass_count_1[dqs_i]*/
+ mcSHOW_DBG_MSG(("[Byte %d]Bigger pass win(%d, %d, %d) Pass tap=%d\n", \
+ dqs_i, ucmin_coarse_tune2T_1[dqs_i], ucmin_coarse_tune0p5T_1[dqs_i], ucmin_fine_tune_1[dqs_i], ucpass_count_1[dqs_i]));
+
+ // LP4 pass window around 6 UI(burst mode), set 1~3 UI is pass
+ // LP3 pass window around 2 UI(pause mode), set 1~3 UI is pass
+ if((ucpass_count_1[dqs_i]*ucDQS_GW_FINE_STEP > 32) && (ucpass_count_1[dqs_i]*ucDQS_GW_FINE_STEP < 96))
+ {
+ u1PassByteCount |= (1<<dqs_i);
+ }
+
+ if(((u1IsLP4Family(p->dram_type)) && (u1PassByteCount==0x3)) || ((p->dram_type==TYPE_LPDDR3) && (u1PassByteCount==0xf)))
+ {
+ mcSHOW_DBG_MSG2(("All bytes gating window pass Done, Early break!\n"));
+ mcFPRINTF((fp_A60501, "All bytes gating window pass Done, Early break!\n"));
+ ucdly_fine_xT = DQS_GW_FINE_END;//break loop
+ ucCoarseTune = ucCoarseEnd; //break loop
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ DramcEngine2End(p);
+
+#if !SW_CHANGE_FOR_SIMULATION
+ vSetCalibrationResult(p, DRAM_CALIBRATION_GATING, DRAM_OK);
+#endif
+
+ //check if there is no pass taps for each DQS
+ for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+ {
+ if (ucpass_count[dqs_i]==0)
+ {
+#if LP4_GATING_LEAD_LAG_FLAG_JUDGE==0
+ /*TINFO="error, no pass taps in DQS_%d !!!\n", dqs_i*/
+ mcSHOW_ERR_MSG(("error, no pass taps in DQS_%d!\n", dqs_i));
+ mcFPRINTF((fp_A60501, "error, no pass taps in DQS_%d!\n", dqs_i));
+ #if !SW_CHANGE_FOR_SIMULATION
+ vSetCalibrationResult(p, DRAM_CALIBRATION_GATING, DRAM_FAIL);
+ #endif
+#endif
+ }
+ }
+
+ #if LP4_GATING_OLD_BURST_MODE
+ if(u1IsLP4Family(p->dram_type))
+ {
+ //Set the gating window begin as gating position
+ //ucpass_count[0]=0;
+ //ucpass_count[1]=0;
+
+ //Set the gating window end-2UI as gating position
+ ucpass_count[0] <<=1;
+ ucpass_count[1] <<=1;
+ }
+ #else
+ if(u1IsLP4Family(p->dram_type))
+ {
+ // LP4 burst mode, may find 6 UI. The 2 UI of the begining may not work.
+ //if gating window > 5UI, skip the first 2 UI.
+ if((ucpass_count_1[0]*ucDQS_GW_FINE_STEP > 160) &&(ucpass_count_1[1]*ucDQS_GW_FINE_STEP > 160))
+ {
+ mcSHOW_DBG_MSG2(("If gating window > 4.5UI, skip the first 2 UI! \n"));
+ mcFPRINTF((fp_A60501, "If gating window > 4.5UI, skip the first 2 UI!\n"));
+
+ for (dqs_i=0; dqs_i<2; dqs_i++)
+ {
+ ucmin_coarse_tune0p5T[dqs_i] +=2;
+
+ if(ucmin_coarse_tune0p5T[dqs_i] > ucRX_DQS_CTL_LOOP)
+ {
+ ucmin_coarse_tune0p5T[dqs_i] -= ucRX_DQS_CTL_LOOP;
+ ucmin_coarse_tune2T[dqs_i] +=1;
+ }
+ mcSHOW_DBG_MSG2(("Change Byte%d Window begin to (%d, %d)\n", dqs_i, ucmin_coarse_tune2T[dqs_i], ucmin_coarse_tune0p5T[dqs_i]));
+ mcFPRINTF((fp_A60501, "Change Byte%d Window begin to (%d, %d)\n", dqs_i ucmin_coarse_tune2T[dqs_i], ucmin_coarse_tune0p5T[dqs_i]));
+ }
+ }
+ }
+ #endif
+}
+ //find center of each byte
+ for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+ {
+#if SW_CHANGE_FOR_SIMULATION // simulation cannot support %
+ // -- PI for Phase0 & Phase1 --
+ uctmp_offset = ucpass_count[dqs_i]*ucDQS_GW_FINE_STEP/2;
+ uctmp_value = ucmin_fine_tune[dqs_i]+uctmp_offset;
+ ucbest_fine_tune[dqs_i] = uctmp_value - (uctmp_value/ucRX_DLY_DQSIENSTB_LOOP) * ucRX_DLY_DQSIENSTB_LOOP;
+ ucbest_fine_tune_P1[dqs_i] = ucbest_fine_tune[dqs_i];
+
+ // coarse tune 0.5T for Phase 0
+ uctmp_offset = uctmp_value / ucRX_DLY_DQSIENSTB_LOOP;
+ uctmp_value = ucmin_coarse_tune0p5T[dqs_i]+uctmp_offset;
+ ucbest_coarse_tune0p5T[dqs_i] = uctmp_value - (uctmp_value/ucRX_DQS_CTL_LOOP) * ucRX_DQS_CTL_LOOP;
+
+ // coarse tune 2T for Phase 0
+ uctmp_offset = uctmp_value/ucRX_DQS_CTL_LOOP;
+ ucbest_coarse_tune2T[dqs_i] = ucmin_coarse_tune2T[dqs_i]+uctmp_offset;
+
+ // coarse tune 0.5T for Phase 1
+ uctmp_value = ucbest_coarse_tune0p5T[dqs_i]+ ucFreqDiv;
+ ucbest_coarse_tune0p5T_P1[dqs_i] = uctmp_value - (uctmp_value/ ucRX_DQS_CTL_LOOP) *ucRX_DQS_CTL_LOOP;
+
+ // coarse tune 2T for Phase 1
+ uctmp_offset = uctmp_value/ucRX_DQS_CTL_LOOP;
+ ucbest_coarse_tune2T_P1[dqs_i] = ucbest_coarse_tune2T[dqs_i]+uctmp_offset;
+#else
+
+ #if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_GatingCal)
+ if(p->femmc_Ready==1)
+ {
+ ucmin_coarse_tune2T[dqs_i]=p->pSavetimeData->u1Gating2T_Save[p->channel][p->rank][dqs_i];
+ ucmin_coarse_tune0p5T[dqs_i]=p->pSavetimeData->u1Gating05T_Save[p->channel][p->rank][dqs_i];
+ ucmin_fine_tune[dqs_i]=p->pSavetimeData->u1Gatingfine_tune_Save[p->channel][p->rank][dqs_i];
+ ucpass_count[dqs_i]=p->pSavetimeData->u1Gatingucpass_count_Save[p->channel][p->rank][dqs_i];
+ vSetCalibrationResult(p, DRAM_CALIBRATION_GATING, DRAM_OK);
+ }
+ else
+#endif
+ {
+
+ #if LP4_GATING_LEAD_LAG_FLAG_JUDGE
+ if(u1IsLP4Family(p->dram_type))
+ {
+ ucpass_count[dqs_i] = u1DQS_transition[dqs_i];
+ ucmin_fine_tune[dqs_i] = ucdly_fine_tune_leadLag[dqs_i];
+ ucmin_coarse_tune0p5T[dqs_i] = ucdly_coarse_0p5T_leadLag[dqs_i];
+ ucmin_coarse_tune2T[dqs_i] = ucdly_coarse_large_leadLag[dqs_i];
+ }
+ #endif
+ }
+
+ #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==0)
+ {
+ p->pSavetimeData->u1Gating2T_Save[p->channel][p->rank][dqs_i]=ucmin_coarse_tune2T[dqs_i];
+ p->pSavetimeData->u1Gating05T_Save[p->channel][p->rank][dqs_i]=ucmin_coarse_tune0p5T[dqs_i];
+ p->pSavetimeData->u1Gatingfine_tune_Save[p->channel][p->rank][dqs_i]=ucmin_fine_tune[dqs_i];
+ p->pSavetimeData->u1Gatingucpass_count_Save[p->channel][p->rank][dqs_i]=ucpass_count[dqs_i];
+ // mcSHOW_DBG_MSG(("save Gating\n"));
+ }
+ #endif
+ // -- PI for Phase0 & Phase1 --
+ #if (LP4_GATING_END_MINUS2UI==1 && LP4_GATING_OLD_BURST_MODE==0)
+ mcSHOW_DBG_MSG(("ucpass_count[dqs_i]*ucDQS_GW_FINE_STEP=%d\n", (ucpass_count[dqs_i]*ucDQS_GW_FINE_STEP)));
+ if((ucpass_count[dqs_i]*ucDQS_GW_FINE_STEP)<128)//window size < 4UI : select center
+ {
+ uctmp_offset = ucpass_count[dqs_i]*ucDQS_GW_FINE_STEP/2;
+ }
+ else // select window_end-2UI
+ {
+ uctmp_offset = (ucpass_count[dqs_i]*ucDQS_GW_FINE_STEP) - 64;
+ }
+ #else
+ uctmp_offset = ucpass_count[dqs_i]*ucDQS_GW_FINE_STEP/2;
+ #endif
+
+ uctmp_value = ucmin_fine_tune[dqs_i]+uctmp_offset;
+ ucbest_fine_tune[dqs_i] = uctmp_value% ucRX_DLY_DQSIENSTB_LOOP;
+ ucbest_fine_tune_P1[dqs_i] = ucbest_fine_tune[dqs_i];
+
+ // coarse tune 0.5T for Phase 0
+ uctmp_offset = uctmp_value / ucRX_DLY_DQSIENSTB_LOOP;
+ uctmp_value = ucmin_coarse_tune0p5T[dqs_i]+uctmp_offset;
+ ucbest_coarse_tune0p5T[dqs_i] = uctmp_value% ucRX_DQS_CTL_LOOP;
+
+ // coarse tune 2T for Phase 0
+ uctmp_offset = uctmp_value/ucRX_DQS_CTL_LOOP;
+ ucbest_coarse_tune2T[dqs_i] = ucmin_coarse_tune2T[dqs_i]+uctmp_offset;
+
+ // coarse tune 0.5T for Phase 1
+ uctmp_value = ucbest_coarse_tune0p5T[dqs_i]+ ucFreqDiv;
+ ucbest_coarse_tune0p5T_P1[dqs_i] = uctmp_value% ucRX_DQS_CTL_LOOP;
+
+ // coarse tune 2T for Phase 1
+ uctmp_offset = uctmp_value/ucRX_DQS_CTL_LOOP;
+ ucbest_coarse_tune2T_P1[dqs_i] = ucbest_coarse_tune2T[dqs_i]+uctmp_offset;
+#endif
+ }
+
+ mcSHOW_DBG_MSG3(("\n\tdqs input gating window, final dly value\n\n"));
+
+ //mcSHOW_DBG_MSG(("test2_1: 0x%x, test2_2: 0x%x, test pattern: %d\n", p->test2_1,p->test2_2, p->test_pattern));
+ //mcSHOW_DBG_MSG3(("\tdqs input gating window, best dly value\n\n"));
+
+
+ mcFPRINTF((fp_A60501, "\n\tdqs input gating window, final dly value\n\n"));
+ //mcFPRINTF((fp_A60501, "test2_1: 0x%x, test2_2: 0x%x, test pattern: %d\n", p->test2_1,p->test2_2, p->test_pattern));
+ mcFPRINTF((fp_A60501, "\tdqs input gating window, best dly value\n\n"));
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ for (dqs_i=2; dqs_i<4; dqs_i++) // LP4, DQ byte 2 and byte 3 are useless, set gating result as 0.
+ {
+ ucbest_coarse_tune2T[dqs_i] = ucbest_coarse_tune0p5T[dqs_i] = ucbest_fine_tune[dqs_i]= 0;
+ ucbest_coarse_tune2T_P1[dqs_i] = ucbest_coarse_tune0p5T_P1[dqs_i] = ucbest_fine_tune_P1[dqs_i]= 0;
+
+ #if GATING_ADJUST_TXDLY_FOR_TRACKING
+ ucbest_coarse_tune2T_backup[p->rank][dqs_i] = ucbest_coarse_tune0p5T_backup[p->rank][dqs_i] = 0;
+ ucbest_coarse_tune2T_P1_backup[p->rank][dqs_i] = ucbest_coarse_tune0p5T_P1_backup[p->rank][dqs_i] = 0;
+ #endif
+ }
+ }
+
+ for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+ {
+ #ifdef FOR_HQA_REPORT_USED
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0, "Gating_Center_2T", dqs_i, ucbest_coarse_tune2T[dqs_i], NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0, "Gating_Center_05T", dqs_i, ucbest_coarse_tune0p5T[dqs_i], NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0, "Gating_Center_PI", dqs_i, ucbest_fine_tune[dqs_i], NULL);
+ #endif
+
+ /*TINFO="best DQS%d delay(2T, 0.5T, PI) = (%d, %d, %d)\n", dqs_i, ucbest_coarse_tune2T[dqs_i], ucbest_coarse_tune0p5T[dqs_i], ucbest_fine_tune[dqs_i]*/
+ mcSHOW_DBG_MSG(("\nbest DQS%d dly(2T, 0.5T, PI) = (%d, %d, %d)\n", dqs_i, ucbest_coarse_tune2T[dqs_i], ucbest_coarse_tune0p5T[dqs_i], ucbest_fine_tune[dqs_i]));
+ mcFPRINTF((fp_A60501,"best DQS%d dly(2T, 0.5T, PI) = (%d, %d, %d)\n", dqs_i, ucbest_coarse_tune2T[dqs_i], ucbest_coarse_tune0p5T[dqs_i], ucbest_fine_tune[dqs_i]));
+ #if GATING_ADJUST_TXDLY_FOR_TRACKING
+ // find min gating TXDLY (should be in P0)
+ if (u1IsLP4Family(p->dram_type))
+ {
+ u1TX_dly_DQSgated =ucbest_coarse_tune2T[dqs_i];
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ u1TX_dly_DQSgated = ((ucbest_coarse_tune2T[dqs_i] <<1)|((ucbest_coarse_tune0p5T[dqs_i] >>2)&0x1));
+ }
+#endif /* ENABLE_LP3_SW */
+
+ if(u1TX_dly_DQSgated < u1TXDLY_Cal_min)
+ u1TXDLY_Cal_min = u1TX_dly_DQSgated;
+
+ ucbest_coarse_tune0p5T_backup[p->rank][dqs_i] = ucbest_coarse_tune0p5T[dqs_i];
+ ucbest_coarse_tune2T_backup[p->rank][dqs_i] = ucbest_coarse_tune2T[dqs_i];
+ #endif
+ }
+
+ mcSHOW_DBG_MSG(("\n\n"));
+ mcFPRINTF((fp_A60501,"\n\n"));
+
+ for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+ {
+ /*TINFO="best DQS%d P1 delay(2T, 0.5T, PI) = (%d, %d, %d)\n", dqs_i, ucbest_coarse_tune2T_P1[dqs_i], ucbest_coarse_tune0p5T_P1[dqs_i], ucbest_fine_tune[dqs_i]*/
+ mcSHOW_DBG_MSG(("\nbest DQS%d P1 dly(2T, 0.5T, PI) = (%d, %d, %d)\n", dqs_i, ucbest_coarse_tune2T_P1[dqs_i], ucbest_coarse_tune0p5T_P1[dqs_i], ucbest_fine_tune[dqs_i]));
+ mcFPRINTF((fp_A60501,"best DQS%d P1 dly(2T, 0.5T, PI) = (%d, %d, %d)\n", dqs_i, ucbest_coarse_tune2T_P1[dqs_i], ucbest_coarse_tune0p5T_P1[dqs_i], ucbest_fine_tune[dqs_i]));
+
+ #if GATING_ADJUST_TXDLY_FOR_TRACKING
+ // find max gating TXDLY (should be in P1)
+
+ if (u1IsLP4Family(p->dram_type))
+ {
+ u1TX_dly_DQSgated = ucbest_coarse_tune2T_P1[dqs_i];
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ u1TX_dly_DQSgated = ((ucbest_coarse_tune2T_P1[dqs_i] <<1)|((ucbest_coarse_tune0p5T_P1[dqs_i] >>2)&0x1));
+ }
+#endif /* ENABLE_LP3_SW */
+
+ if(u1TX_dly_DQSgated > u1TXDLY_Cal_max)
+ u1TXDLY_Cal_max = u1TX_dly_DQSgated;
+
+ ucbest_coarse_tune0p5T_P1_backup[p->rank][dqs_i] = ucbest_coarse_tune0p5T_P1[dqs_i];
+ ucbest_coarse_tune2T_P1_backup[p->rank][dqs_i] = ucbest_coarse_tune2T_P1[dqs_i];
+ #endif
+ }
+
+ mcSHOW_DBG_MSG(("\n\n"));
+ mcFPRINTF((fp_A60501,"\n\n"));
+
+ //Restore registers
+ DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+#ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+ gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag = u1GUMP_INIT_RG_LOG_TO_DE_bak;
+#endif
+
+ #if LP4_GATING_OLD_BURST_MODE
+ if(u1IsLP4Family(p->dram_type))
+ {
+ #if !LP4_GATING_LEAD_LAG_FLAG_JUDGE
+ DramcGatingMode(p, 1);
+ #endif
+ //MR1 OP[7]=0;
+ u1MR01Value[p->dram_fsp] &= 0x7f;
+ DramcModeRegWriteByRank(p, p->rank, 1, u1MR01Value[p->dram_fsp]);
+ }
+ #endif
+
+ /* LP3/4: Set ARDQ_RPRE_TOG_EN must be 1 after gating window calibration */
+ RxDQSIsiPulseCG(p, ENABLE);
+
+ #if REG_SHUFFLE_REG_CHECK
+ ShuffleRegCheck =1;
+ #endif
+
+ // 4T or 2T coarse tune
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQSG0), \
+ P_Fld((U32) ucbest_coarse_tune2T[0], SHURK0_SELPH_DQSG0_TX_DLY_DQS0_GATED)| \
+ P_Fld((U32) ucbest_coarse_tune2T[1], SHURK0_SELPH_DQSG0_TX_DLY_DQS1_GATED)| \
+ P_Fld((U32) ucbest_coarse_tune2T[2], SHURK0_SELPH_DQSG0_TX_DLY_DQS2_GATED)| \
+ P_Fld((U32) ucbest_coarse_tune2T[3], SHURK0_SELPH_DQSG0_TX_DLY_DQS3_GATED)| \
+ P_Fld((U32) ucbest_coarse_tune2T_P1[0], SHURK0_SELPH_DQSG0_TX_DLY_DQS0_GATED_P1)| \
+ P_Fld((U32) ucbest_coarse_tune2T_P1[1], SHURK0_SELPH_DQSG0_TX_DLY_DQS1_GATED_P1)| \
+ P_Fld((U32) ucbest_coarse_tune2T_P1[2], SHURK0_SELPH_DQSG0_TX_DLY_DQS2_GATED_P1)| \
+ P_Fld((U32) ucbest_coarse_tune2T_P1[3], SHURK0_SELPH_DQSG0_TX_DLY_DQS3_GATED_P1));
+
+ // 0.5T coarse tune
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQSG1), \
+ P_Fld((U32) ucbest_coarse_tune0p5T[0], SHURK0_SELPH_DQSG1_REG_DLY_DQS0_GATED)| \
+ P_Fld((U32) ucbest_coarse_tune0p5T[1], SHURK0_SELPH_DQSG1_REG_DLY_DQS1_GATED)| \
+ P_Fld((U32) ucbest_coarse_tune0p5T[2], SHURK0_SELPH_DQSG1_REG_DLY_DQS2_GATED)| \
+ P_Fld((U32) ucbest_coarse_tune0p5T[3], SHURK0_SELPH_DQSG1_REG_DLY_DQS3_GATED)| \
+ P_Fld((U32) ucbest_coarse_tune0p5T_P1[0], SHURK0_SELPH_DQSG1_REG_DLY_DQS0_GATED_P1)| \
+ P_Fld((U32) ucbest_coarse_tune0p5T_P1[1], SHURK0_SELPH_DQSG1_REG_DLY_DQS1_GATED_P1)| \
+ P_Fld((U32) ucbest_coarse_tune0p5T_P1[2], SHURK0_SELPH_DQSG1_REG_DLY_DQS2_GATED_P1)| \
+ P_Fld((U32) ucbest_coarse_tune0p5T_P1[3], SHURK0_SELPH_DQSG1_REG_DLY_DQS3_GATED_P1));
+
+
+ #if GATING_RODT_LATANCY_EN //LP3 RODT is not enable, don't need to set the RODT settings.
+ // RODT = Gating - 11UI,
+ if(u1IsLP4Family(p->dram_type))
+ {
+ for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+ {
+ uctmp_value = (ucbest_coarse_tune2T[dqs_i] <<3)+ucbest_coarse_tune0p5T[dqs_i];
+
+ if(uctmp_value>=11)
+ {
+ //P0
+ uctmp_value -=11;
+ ucbest_coarse_large_RODT[dqs_i] = uctmp_value >>3;
+ ucbest_coarse_0p5T_RODT[dqs_i] = uctmp_value - (ucbest_coarse_large_RODT[dqs_i] <<3);
+
+ //P1
+ uctmp_value = (ucbest_coarse_tune2T_P1[dqs_i] <<3)+ucbest_coarse_tune0p5T_P1[dqs_i] -11;
+ ucbest_coarse_large_RODT_P1[dqs_i] = uctmp_value >>3;
+ ucbest_coarse_0p5T_RODT_P1[dqs_i] = uctmp_value - (ucbest_coarse_large_RODT_P1[dqs_i] <<3);
+
+ mcSHOW_DBG_MSG2(("\nbest RODT dly(2T, 0.5T) = (%d, %d)\n", ucbest_coarse_large_RODT[dqs_i], ucbest_coarse_0p5T_RODT[dqs_i]));
+ mcFPRINTF((fp_A60501,"best RODT dly(2T, 0.5T) = (%d, %d)\n", ucbest_coarse_large_RODT[dqs_i], ucbest_coarse_0p5T_RODT[dqs_i]));
+ }
+ else //if(ucbest_coarse_tune2T[0] ==0) //shouble not happen, just only protect this happen
+ {
+ //P0
+ ucbest_coarse_large_RODT[dqs_i] =0;
+ ucbest_coarse_0p5T_RODT[dqs_i] = 0;
+ //P1
+ ucbest_coarse_large_RODT_P1[dqs_i] =4;
+ ucbest_coarse_0p5T_RODT_P1[dqs_i] = 4;
+
+ mcSHOW_ERR_MSG(("[RxdqsGatingCal] Error: ucbest_coarse_tune2T[%d] is already 0. RODT cannot be -1 UI\n", dqs_i));
+ mcFPRINTF((fp_A60501, "[RxdqsGatingCal] Error: ucbest_coarse_tune2T[%d] is already 0. RODT cannot be -1 UI\n", dqs_i));
+ }
+ }
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_ODTEN0), \
+ P_Fld((U32) ucbest_coarse_large_RODT[0], SHURK0_SELPH_ODTEN0_TXDLY_B0_RODTEN)| \
+ P_Fld((U32) ucbest_coarse_large_RODT[1], SHURK0_SELPH_ODTEN0_TXDLY_B1_RODTEN)| \
+ P_Fld((U32) ucbest_coarse_large_RODT[2], SHURK0_SELPH_ODTEN0_TXDLY_B2_RODTEN)| \
+ P_Fld((U32) ucbest_coarse_large_RODT[3], SHURK0_SELPH_ODTEN0_TXDLY_B3_RODTEN)| \
+ P_Fld((U32) ucbest_coarse_large_RODT_P1[0], SHURK0_SELPH_ODTEN0_TXDLY_B0_RODTEN_P1)| \
+ P_Fld((U32) ucbest_coarse_large_RODT_P1[1], SHURK0_SELPH_ODTEN0_TXDLY_B1_RODTEN_P1)| \
+ P_Fld((U32) ucbest_coarse_large_RODT_P1[2], SHURK0_SELPH_ODTEN0_TXDLY_B2_RODTEN_P1)| \
+ P_Fld((U32) ucbest_coarse_large_RODT_P1[3], SHURK0_SELPH_ODTEN0_TXDLY_B3_RODTEN_P1));
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_ODTEN1), \
+ P_Fld((U32) ucbest_coarse_0p5T_RODT[0], SHURK0_SELPH_ODTEN1_DLY_B0_RODTEN)| \
+ P_Fld((U32) ucbest_coarse_0p5T_RODT[1], SHURK0_SELPH_ODTEN1_DLY_B1_RODTEN)| \
+ P_Fld((U32) ucbest_coarse_0p5T_RODT[2], SHURK0_SELPH_ODTEN1_DLY_B2_RODTEN)| \
+ P_Fld((U32) ucbest_coarse_0p5T_RODT[3], SHURK0_SELPH_ODTEN1_DLY_B3_RODTEN)| \
+ P_Fld((U32) ucbest_coarse_0p5T_RODT_P1[0], SHURK0_SELPH_ODTEN1_DLY_B0_RODTEN_P1)| \
+ P_Fld((U32) ucbest_coarse_0p5T_RODT_P1[1], SHURK0_SELPH_ODTEN1_DLY_B1_RODTEN_P1)| \
+ P_Fld((U32) ucbest_coarse_0p5T_RODT_P1[2], SHURK0_SELPH_ODTEN1_DLY_B2_RODTEN_P1)| \
+ P_Fld((U32) ucbest_coarse_0p5T_RODT_P1[3], SHURK0_SELPH_ODTEN1_DLY_B3_RODTEN_P1));
+ }
+ #endif
+
+ // Set Fine Tune Value to registers
+ u4value = ucbest_fine_tune[0] | (ucbest_fine_tune[1]<<8) | (ucbest_fine_tune[2]<<16) | (ucbest_fine_tune[3]<<24);
+ vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_DQSIEN), u4value);
+
+ #if REG_SHUFFLE_REG_CHECK
+ ShuffleRegCheck =0;
+ #endif
+
+ //mcDELAY_US(1);//delay 2T
+ //DramPhyCGReset(p, 0);
+ DramPhyReset(p); //reset phy, reset read data counter
+
+ /*TINFO="[DramcRxdqsGatingCal] Done\n"*/
+ mcSHOW_DBG_MSG3(("[DramcRxdqsGatingCal] Done\n\n"));
+ mcFPRINTF((fp_A60501, "[DramcRxdqsGatingCal] Done\n\n"));
+
+ return DRAM_OK;
+ // log example
+ /*
+ 0 1 12 |(B3->B0) 0x 0, 0x1211, 0x1212, 0x1211 | (B3->B0) 11 11 11 11 11 11 11 11 | 0xffffffff
+ 0 1 16 |(B3->B0) 0x 0, 0x1211, 0x1212, 0x1211 | (B3->B0) 11 11 11 11 11 11 11 11 | 0xffffffff
+ 0 1 20 |(B3->B0) 0x 0, 0x1211, 0x1212, 0x1211 | (B3->B0) 11 11 11 11 11 11 11 11 | 0xffffffff
+ 0 1 24 |(B3->B0) 0x 0, 0x1211, 0x1212, 0x1211 | (B3->B0) 11 11 11 11 11 11 11 11 | 0xffffffff
+ 0 1 28 |(B3->B0) 0x 0, 0x1211, 0x1212, 0x1211 | (B3->B0) 11 11 11 11 11 11 11 11 | 0xffffffff
+ 0 2 0 |(B3->B0) 0x 0, 0x1d1c, 0x1212, 0x1211 | (B3->B0) 11 11 11 11 11 11 11 11 | 0xffffffff
+ 0 2 4 |(B3->B0) 0x 0, 0x2324, 0x1212, 0x1413 | (B3->B0) 11 11 0 0 11 11 11 11 | 0xffffffff
+ 0 2 8 |(B3->B0) 0x 0, 0x2323, 0x1212, 0x2222 | (B3->B0) 0 0 0 0 11 11 11 11 | 0xff00ffff
+ 0 2 12 |(B3->B0) 0x 0, 0x2323, 0x1211, 0x2323 | (B3->B0) 0 0 0 0 11 11 0 0 | 0x ffff
+ 0 2 16 |(B3->B0) 0x 0, 0x2323, 0x 504, 0x2324 | (B3->B0) 0 0 0 0 11 11 0 0 | 0x ff00
+ 0 2 20 |(B3->B0) 0x 0, 0x2323, 0x 303, 0x2323 | (B3->B0) 0 0 0 0 1 1 0 0 | 0x ff00
+ 0 2 24 |(B3->B0) 0x 0, 0x2323, 0x2324, 0x2323 | (B3->B0) 0 0 0 0 0 0 0 0 | 0x 0
+ 0 2 28 |(B3->B0) 0x 0, 0x2323, 0x2323, 0x2323 | (B3->B0) 0 0 0 0 0 0 0 0 | 0x 0
+ 0 3 0 |(B3->B0) 0x 0, 0x2323, 0x2323, 0x2323 | (B3->B0) 0 0 0 0 0 0 0 0 | 0x 0
+ 0 3 4 |(B3->B0) 0x 0, 0x2323, 0x2323, 0x2323 | (B3->B0) 0 0 0 0 0 0 0 0 | 0x 0
+ 0 3 8 |(B3->B0) 0x 0, 0x2323, 0x2323, 0x2323 | (B3->B0) 0 0 0 0 0 0 0 0 | 0x 0
+ 0 3 12 |(B3->B0) 0x 0, 0x2323, 0x2323, 0x2323 | (B3->B0) 0 0 0 0 0 0 0 0 | 0x 0
+ 0 3 16 |(B3->B0) 0x 0, 0x2323, 0x2323, 0x2323 | (B3->B0) 0 0 0 0 0 0 0 0 | 0x 0
+ 0 3 20 |(B3->B0) 0x 0, 0x2323, 0x2323, 0x2323 | (B3->B0) 0 0 0 0 0 0 0 0 | 0x 0
+ 0 3 24 |(B3->B0) 0x 0, 0x2323, 0x2323, 0x2323 | (B3->B0) 0 0 0 0 0 0 0 0 | 0x 0
+ 0 3 28 |(B3->B0) 0x 0, 0x2323, 0x2323, 0x2323 | (B3->B0) 0 0 0 0 0 0 0 0 | 0x 0
+ 1 0 0 |(B3->B0) 0x 0, 0x2120, 0x2323, 0x2323 | (B3->B0) 11 11 11 11 0 0 0 0 | 0xffff0000
+ 1 0 4 |(B3->B0) 0x 0, 0x2323, 0x2323, 0x1212 | (B3->B0) 11 11 0 0 0 0 11 11 | 0xffff00ff
+ 1 0 8 |(B3->B0) 0x 0, 0x2324, 0x2323, 0x2323 | (B3->B0) 0 0 0 0 0 0 0 0 | 0xffff00ff
+ 1 0 12 |(B3->B0) 0x 0, 0x2323, 0x2323, 0x2323 | (B3->B0) 0 0 0 0 0 0 0 0 | 0xffff00ff
+ 1 0 16 |(B3->B0) 0x 0, 0x2323, 0x1f1f, 0x2323 | (B3->B0) 0 0 0 0 11 11 0 0 | 0xffffffff
+ 1 0 20 |(B3->B0) 0x 0, 0x2323, 0x2324, 0x2323 | (B3->B0) 0 0 0 0 0 0 0 0 | 0xffffffff
+ 1 0 24 |(B3->B0) 0x 0, 0x2323, 0x2323, 0x2323 | (B3->B0) 0 0 0 0 0 0 0 0 | 0xffffffff
+ 1 0 28 |(B3->B0) 0x 0, 0x2322, 0x2324, 0x2323 | (B3->B0) 11 11 11 11 0 0 0 0 | 0x ffff
+ 1 1 0 |(B3->B0) 0x 0, 0x2322, 0x2324, 0x2323 | (B3->B0) 11 11 11 11 0 0 0 0 | 0xffffffff
+ 1 1 4 |(B3->B0) 0x 0, 0x2323, 0x2324, 0x2322 | (B3->B0) 11 11 11 11 0 0 11 11 | 0xffffff00
+ 1 1 8 |(B3->B0) 0x 0, 0x2323, 0x2324, 0x2322 | (B3->B0) 11 11 11 11 11 11 11 11 | 0xffffffff
+ 1 1 12 |(B3->B0) 0x 0, 0x2323, 0x2323, 0x2323 | (B3->B0) 11 11 11 11 11 11 11 11 | 0xffffffff
+ 1 1 16 |(B3->B0) 0x 0, 0x2323, 0x2322, 0x2323 | (B3->B0) 11 11 11 11 11 11 11 11 | 0xffffffff
+ 1 1 20 |(B3->B0) 0x 0, 0x2323, 0x2323, 0x2323 | (B3->B0) 11 11 11 11 11 11 11 11 | 0xffffffff
+ 1 1 24 |(B3->B0) 0x 0, 0x2323, 0x2323, 0x2323 | (B3->B0) 11 11 11 11 11 11 11 11 | 0xffffffff
+ 1 1 28 |(B3->B0) 0x 0, 0x2323, 0x2323, 0x2323 | (B3->B0) 11 11 11 11 11 11 11 11 | 0xffffffff
+ 1 2 0 |(B3->B0) 0x 0, 0x1a1b, 0x2323, 0x2323 | (B3->B0) 11 11 11 11 11 11 11 11 | 0xffffffff
+ 1 2 4 |(B3->B0) 0x 0, 0x1a1b, 0x2323, 0x1e1f | (B3->B0) 0 0 11 11 11 11 0 0 | 0xffffffff
+
+ ===============================================================================
+ dqs input gating widnow, final delay value
+ channel=2(2:cha, 3:chb)
+ ===============================================================================
+ test2_1: 0x55000000, test2_2: 0xaa000400, test pattern: 5
+ dqs input gating widnow, best delay value
+ ===============================================================================
+ best DQS0 delay(2T, 0.5T, PI) = (0, 3, 12)
+ best DQS1 delay(2T, 0.5T, PI) = (0, 3, 22)
+ best DQS2 delay(2T, 0.5T, PI) = (0, 3, 4)
+ best DQS3 delay(2T, 0.5T, PI) = (0, 3, 4)
+ ===============================================================================
+ best DQS0 P1 delay(2T, 0.5T, PI) = (1, 1, 12)
+ best DQS1 P1 delay(2T, 0.5T, PI) = (1, 1, 22)
+ best DQS2 P1 delay(2T, 0.5T, PI) = (1, 1, 4)
+ best DQS3 P1 delay(2T, 0.5T, PI) = (1, 1, 4)
+ ===============================================================================
+ [DramcRxdqsGatingCal] ====Done====
+
+*/
+}
+
+#if GATING_ADJUST_TXDLY_FOR_TRACKING
+void DramcRxdqsGatingPostProcess(DRAMC_CTX_T *p)
+{
+ U8 dqs_i;
+#if ENABLE_LP3_SW
+ U8 u1RankRxDVS=0;
+#endif
+ U8 u1RankIdx, u1RankMax;
+ S8 s1ChangeDQSINCTL;
+ U32 backup_rank;
+ U32 u4ReadDQSINCTL, u4ReadTXDLY[RANK_MAX][DQS_NUMBER], u4ReadTXDLY_P1[RANK_MAX][DQS_NUMBER], u4RankINCTL_ROOT, u4XRTR2R, reg_TX_dly_DQSgated_min = 0;
+
+ backup_rank = u1GetRank(p);
+
+#ifdef XRTR2R_PERFORM_ENHANCE_DQSG_RX_DLY
+ if (u1IsLP4Family(p->dram_type))
+ {
+ // wei-jen: DQSgated_min should be 2 when freq >= 1333, 1 when freq < 1333
+ if (p->frequency >= 1333)
+ {
+ reg_TX_dly_DQSgated_min = 2;
+ }
+ else
+ {
+ reg_TX_dly_DQSgated_min = 1;
+ }
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ // 1866,1600,1333,1200 : reg_TX_dly_DQSgated (min) =2
+ reg_TX_dly_DQSgated_min = 2;
+ }
+#endif /* ENABLE_LP3_SW */
+#else
+ if (u1IsLP4Family(p->dram_type))
+ {
+ // wei-jen: DQSgated_min should be 3 when freq >= 1333, 2 when freq < 1333
+ if (p->frequency >= 1333)
+ {
+ reg_TX_dly_DQSgated_min = 3;
+ }
+ else
+ {
+ reg_TX_dly_DQSgated_min = 2;
+ }
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ // 800 : reg_TX_dly_DQSgated (min) =2
+ // 1066 : reg_TX_dly_DQSgated (min) =2
+ // 1270 : reg_TX_dly_DQSgated (min) =2
+ // 1600 : reg_TX_dly_DQSgated (min) =3
+ // 1866 : reg_TX_dly_DQSgated (min) =3
+ if(p->frequency < 700)
+ {
+ reg_TX_dly_DQSgated_min = 2;
+ }
+ else
+ {
+ reg_TX_dly_DQSgated_min = 3;
+ }
+ }
+#endif /* ENABLE_LP3_SW */
+#endif
+#if ENABLE_LP3_SW
+ // === Begin of DVS setting =====
+ //RANKRXDVS = reg_TX_dly_DQSgated (min) -1 = Roundup(tDQSCKdiff/MCK)
+ if (!u1IsLP4Family(p->dram_type))
+ {
+ if(reg_TX_dly_DQSgated_min>1)
+ {
+ u1RankRxDVS = reg_TX_dly_DQSgated_min -1;
+ }
+ else
+ {
+ u1RankRxDVS=0;
+ mcSHOW_ERR_MSG(("[RxdqsGatingPostProcess] u1RankRxDVS <1, Please check!\n"));
+ }
+ }
+#endif
+//Sylvia MP setting is switched to new mode, so RANKRXDVS can be set as 0 (review by HJ Huang)
+#if 0
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ7), u1RankRxDVS, SHU1_B0_DQ7_R_DMRANKRXDVS_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ7), u1RankRxDVS, SHU1_B1_DQ7_R_DMRANKRXDVS_B1);
+ }
+#endif
+#if ENABLE_LP3_SW
+ for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+ {
+ vIO32WriteFldAlign_Phy_Byte(dqs_i, DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ7), u1RankRxDVS, SHU1_B0_DQ7_R_DMRANKRXDVS_B0);
+ }
+#endif /* ENABLE_LP3_SW */
+ // === End of DVS setting =====
+
+ s1ChangeDQSINCTL = reg_TX_dly_DQSgated_min- u1TXDLY_Cal_min;
+
+ mcSHOW_DBG_MSG(("[RxdqsGatingPostProcess] freq %d\n"
+ "ChangeDQSINCTL %d, reg_TX_dly_DQSgated_min %d, u1TXDLY_Cal_min %d\n",
+ p->frequency,
+ s1ChangeDQSINCTL, reg_TX_dly_DQSgated_min, u1TXDLY_Cal_min));
+
+ if(s1ChangeDQSINCTL!=0) // need to change DQSINCTL and TXDLY of each byte
+ {
+ u1TXDLY_Cal_min += s1ChangeDQSINCTL;
+ u1TXDLY_Cal_max += s1ChangeDQSINCTL;
+
+ if (p->support_rank_num==RANK_DUAL)
+ u1RankMax = RANK_MAX;
+ else
+ u1RankMax =RANK_1;
+
+ for(u1RankIdx=0; u1RankIdx<u1RankMax; u1RankIdx++)
+ {
+ mcSHOW_DBG_MSG2(("Rank: %d\n", u1RankIdx));
+
+ for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+ {
+ if(u1IsLP4Family(p->dram_type))
+ {
+ u4ReadTXDLY[u1RankIdx][dqs_i]= ucbest_coarse_tune2T_backup[u1RankIdx][dqs_i];
+ u4ReadTXDLY_P1[u1RankIdx][dqs_i]= ucbest_coarse_tune2T_P1_backup[u1RankIdx][dqs_i];
+
+ u4ReadTXDLY[u1RankIdx][dqs_i] += s1ChangeDQSINCTL;
+ u4ReadTXDLY_P1[u1RankIdx][dqs_i] += s1ChangeDQSINCTL;
+
+ ucbest_coarse_tune2T_backup[u1RankIdx][dqs_i] = u4ReadTXDLY[u1RankIdx][dqs_i];
+ ucbest_coarse_tune2T_P1_backup[u1RankIdx][dqs_i] = u4ReadTXDLY_P1[u1RankIdx][dqs_i];
+ }
+ else
+ {
+ u4ReadTXDLY[u1RankIdx][dqs_i]= ((ucbest_coarse_tune2T_backup[u1RankIdx][dqs_i]<<1) + ((ucbest_coarse_tune0p5T_backup[u1RankIdx][dqs_i]>>2) & 0x1));
+ u4ReadTXDLY_P1[u1RankIdx][dqs_i]= ((ucbest_coarse_tune2T_P1_backup[u1RankIdx][dqs_i]<<1) + ((ucbest_coarse_tune0p5T_P1_backup[u1RankIdx][dqs_i]>>2) & 0x1));
+
+ u4ReadTXDLY[u1RankIdx][dqs_i] += s1ChangeDQSINCTL;
+ u4ReadTXDLY_P1[u1RankIdx][dqs_i] += s1ChangeDQSINCTL;
+
+ ucbest_coarse_tune2T_backup[u1RankIdx][dqs_i] = (u4ReadTXDLY[u1RankIdx][dqs_i] >>1);
+ ucbest_coarse_tune0p5T_backup[u1RankIdx][dqs_i] = ((u4ReadTXDLY[u1RankIdx][dqs_i] & 0x1) <<2)+(ucbest_coarse_tune0p5T_backup[u1RankIdx][dqs_i] & 0x3);
+
+ ucbest_coarse_tune2T_P1_backup[u1RankIdx][dqs_i] = (u4ReadTXDLY_P1[u1RankIdx][dqs_i] >>1);
+ ucbest_coarse_tune0p5T_P1_backup[u1RankIdx][dqs_i] = ((u4ReadTXDLY_P1[u1RankIdx][dqs_i] & 0x1)<<2) +(ucbest_coarse_tune0p5T_P1_backup[u1RankIdx][dqs_i] & 0x3);
+ }
+ mcSHOW_DBG_MSG(("best DQS%d dly(2T, 0.5T) = (%d, %d)\n", dqs_i, ucbest_coarse_tune2T_backup[u1RankIdx][dqs_i], ucbest_coarse_tune0p5T_backup[u1RankIdx][dqs_i]));
+ }
+
+ for (dqs_i=0; dqs_i<(p->data_width/DQS_BIT_NUMBER); dqs_i++)
+ {
+ mcSHOW_DBG_MSG(("best DQS%d P1 dly(2T, 0.5T) = (%d, %d)\n", dqs_i, ucbest_coarse_tune2T_P1_backup[u1RankIdx][dqs_i], ucbest_coarse_tune0p5T_P1_backup[u1RankIdx][dqs_i]));
+ }
+ }
+
+ for(u1RankIdx=0; u1RankIdx<u1RankMax; u1RankIdx++)
+ {
+ vSetRank(p, u1RankIdx);
+ // 4T or 2T coarse tune
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQSG0), \
+ P_Fld((U32) ucbest_coarse_tune2T_backup[u1RankIdx][0], SHURK0_SELPH_DQSG0_TX_DLY_DQS0_GATED)| \
+ P_Fld((U32) ucbest_coarse_tune2T_backup[u1RankIdx][1], SHURK0_SELPH_DQSG0_TX_DLY_DQS1_GATED)| \
+ P_Fld((U32) ucbest_coarse_tune2T_backup[u1RankIdx][2], SHURK0_SELPH_DQSG0_TX_DLY_DQS2_GATED)| \
+ P_Fld((U32) ucbest_coarse_tune2T_backup[u1RankIdx][3], SHURK0_SELPH_DQSG0_TX_DLY_DQS3_GATED)| \
+ P_Fld((U32) ucbest_coarse_tune2T_P1_backup[u1RankIdx][0], SHURK0_SELPH_DQSG0_TX_DLY_DQS0_GATED_P1)| \
+ P_Fld((U32) ucbest_coarse_tune2T_P1_backup[u1RankIdx][1], SHURK0_SELPH_DQSG0_TX_DLY_DQS1_GATED_P1)| \
+ P_Fld((U32) ucbest_coarse_tune2T_P1_backup[u1RankIdx][2], SHURK0_SELPH_DQSG0_TX_DLY_DQS2_GATED_P1)| \
+ P_Fld((U32) ucbest_coarse_tune2T_P1_backup[u1RankIdx][3], SHURK0_SELPH_DQSG0_TX_DLY_DQS3_GATED_P1));
+
+ // 0.5T coarse tune
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQSG1), \
+ P_Fld((U32) ucbest_coarse_tune0p5T_backup[u1RankIdx][0], SHURK0_SELPH_DQSG1_REG_DLY_DQS0_GATED)| \
+ P_Fld((U32) ucbest_coarse_tune0p5T_backup[u1RankIdx][1], SHURK0_SELPH_DQSG1_REG_DLY_DQS1_GATED)| \
+ P_Fld((U32) ucbest_coarse_tune0p5T_backup[u1RankIdx][2], SHURK0_SELPH_DQSG1_REG_DLY_DQS2_GATED)| \
+ P_Fld((U32) ucbest_coarse_tune0p5T_backup[u1RankIdx][3], SHURK0_SELPH_DQSG1_REG_DLY_DQS3_GATED)| \
+ P_Fld((U32) ucbest_coarse_tune0p5T_P1_backup[u1RankIdx][0], SHURK0_SELPH_DQSG1_REG_DLY_DQS0_GATED_P1)| \
+ P_Fld((U32) ucbest_coarse_tune0p5T_P1_backup[u1RankIdx][1], SHURK0_SELPH_DQSG1_REG_DLY_DQS1_GATED_P1)| \
+ P_Fld((U32) ucbest_coarse_tune0p5T_P1_backup[u1RankIdx][2], SHURK0_SELPH_DQSG1_REG_DLY_DQS2_GATED_P1)| \
+ P_Fld((U32) ucbest_coarse_tune0p5T_P1_backup[u1RankIdx][3], SHURK0_SELPH_DQSG1_REG_DLY_DQS3_GATED_P1));
+ }
+ }
+ vSetRank(p, backup_rank);
+
+ u4ReadDQSINCTL = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_DQSCTL), SHURK0_DQSCTL_DQSINCTL);
+ u4ReadDQSINCTL -= s1ChangeDQSINCTL;
+
+ #if ENABLE_READ_DBI
+ U32 u4ReadRODT;
+ if(p->DBI_R_onoff[p->dram_fsp])
+ {
+ u4ReadDQSINCTL++;
+ u4ReadRODT = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_ODTCTRL), SHU_ODTCTRL_RODT);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_ODTCTRL), u4ReadRODT+1, SHU_ODTCTRL_RODT); //update RODT value when READ_DBI is on
+ }
+ #endif
+
+#ifdef XRTR2R_PERFORM_ENHANCE_DQSG_RX_DLY
+ // Wei-Jen: RANKINCTL_RXDLY = RANKINCTL = RankINCTL_ROOT = u4ReadDQSINCTL-2, if XRTR2R_PERFORM_ENHANCE_DQSG_RX_DLY enable
+ // Wei-Jen: New algorithm : u4ReadDQSINCTL-2 >= 0
+ if(u4ReadDQSINCTL>=2)
+ {
+ u4RankINCTL_ROOT = u4ReadDQSINCTL-2;
+ }
+ else
+ {
+ u4RankINCTL_ROOT=0;
+ mcSHOW_ERR_MSG(("u4RankINCTL_ROOT <2, Please check\n"));
+#if (__ETT__)
+ while(1);
+#endif
+ }
+#else
+ //Modify for corner IC failed at HQA test XTLV
+ if(u4ReadDQSINCTL>=3)
+ {
+ u4RankINCTL_ROOT = u4ReadDQSINCTL-3;
+ }
+ else
+ {
+ u4RankINCTL_ROOT=0;
+ mcSHOW_ERR_MSG(("u4RankINCTL_ROOT <3, Risk for supporting 1066/RL8\n"));
+ }
+#endif
+
+ //DQSINCTL
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_DQSCTL), u4ReadDQSINCTL, SHURK0_DQSCTL_DQSINCTL); //Rank0 DQSINCTL
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK1_DQSCTL), u4ReadDQSINCTL, SHURK1_DQSCTL_R1DQSINCTL); //Rank1 DQSINCTL
+
+ //No need to update RODT. If we update RODT, also need to update SELPH_ODTEN0_TXDLY
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_ODTCTRL), u4ReadDQSINCTL, SHU_ODTCTRL_RODT); //RODT = DQSINCTL
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_RANKCTL), u4ReadDQSINCTL, SHU_RANKCTL_RANKINCTL_PHY); //RANKINCTL_PHY = DQSINCTL
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_RANKCTL), u4RankINCTL_ROOT, SHU_RANKCTL_RANKINCTL); //RANKINCTL= DQSINCTL -3
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_RANKCTL), u4RankINCTL_ROOT, SHU_RANKCTL_RANKINCTL_ROOT1); //RANKINCTL_ROOT1= DQSINCTL -3
+#ifdef XRTR2R_PERFORM_ENHANCE_DQSG_RX_DLY
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_RANKCTL), u4RankINCTL_ROOT, SHU_RANKCTL_RANKINCTL_RXDLY);
+
+ u4XRTR2R= u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_ACTIM_XRT), SHU_ACTIM_XRT_XRTR2R);
+
+ mcSHOW_DBG_MSG2(("TX_dly_DQSgated check: min %d max %d, ChangeDQSINCTL=%d\n", u1TXDLY_Cal_min, u1TXDLY_Cal_max, s1ChangeDQSINCTL));
+ mcSHOW_DBG_MSG2(("DQSINCTL=%d, RANKINCTL=%d, u4XRTR2R=%d\n", u4ReadDQSINCTL, u4RankINCTL_ROOT, u4XRTR2R));
+
+#else
+ //XRTR2R=A-phy forbidden margin(6T) + reg_TX_dly_DQSgated (max) +Roundup(tDQSCKdiff/MCK+0.25MCK)+1(05T sel_ph margin)-1(forbidden margin overlap part)
+ //Roundup(tDQSCKdiff/MCK+1UI) =1~2 all LP3 and LP4 timing
+ //u4XRTR2R= 8 + u1TXDLY_Cal_max; // 6+ u1TXDLY_Cal_max +2
+
+ //Modify for corner IC failed at HQA test XTLV @ 3200MHz
+ u4XRTR2R= 8 + u1TXDLY_Cal_max + 1; // 6+ u1TXDLY_Cal_max +2
+ if (u4XRTR2R > 12)
+ {
+ u4XRTR2R= 12;
+ mcSHOW_ERR_MSG(("XRTR2R > 12, Max value is 12\n"));
+ }
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_ACTIM_XRT), u4XRTR2R, SHU_ACTIM_XRT_XRTR2R);
+
+ mcSHOW_DBG_MSG2(("TX_dly_DQSgated check: min %d max %d, ChangeDQSINCTL=%d\n", u1TXDLY_Cal_min, u1TXDLY_Cal_max, s1ChangeDQSINCTL));
+ mcSHOW_DBG_MSG2(("DQSINCTL=%d, RANKINCTL=%d, u4XRTR2R=%d\n", u4ReadDQSINCTL, u4RankINCTL_ROOT, u4XRTR2R));
+
+#endif
+
+#if 0//ENABLE_RODT_TRACKING
+ //Because Kibo+,WE2,Bianco,Vinson...or behind project support WDQS, they need to apply the correct new setting
+ //The following 2 items are indepentent
+ //1. if TX_WDQS on(by vendor_id) or p->odt_onoff = 1, ROEN/RODTE/RODTE2 = 1
+ //2. if ENABLE_RODT_TRACKING on, apply new setting and RODTEN_MCK_MODESEL = ROEN
+ // LP4 support only
+ if (u1IsLP4Family(p->dram_type))
+ {
+ U8 u1ReadROEN;
+ u1ReadROEN = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_ODTCTRL), SHU_ODTCTRL_ROEN);
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU_RODTENSTB), P_Fld(0xff, SHU_RODTENSTB_RODTENSTB_EXT)|\
+ P_Fld(9, SHU_RODTENSTB_RODTENSTB_OFFSET)|\
+ P_Fld(u1ReadROEN, SHU_RODTENSTB_RODTEN_MCK_MODESEL));
+ }
+#endif
+#ifdef XRTR2W_PERFORM_ENHANCE_RODTEN
+ // LP4 support only
+ if (u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU_RODTENSTB), P_Fld(0x0fff, SHU_RODTENSTB_RODTENSTB_EXT)|\
+ P_Fld(1, SHU_RODTENSTB_RODTEN_P1_ENABLE)|\
+ P_Fld(1, SHU_RODTENSTB_RODTEN_MCK_MODESEL));
+ }
+#endif
+
+
+ vSetRank(p, backup_rank);
+
+
+}
+#endif
+
+
+#if GATING_ADJUST_TXDLY_FOR_TRACKING
+void DramcRxdqsGatingPreProcess(DRAMC_CTX_T *p)
+{
+ u1TXDLY_Cal_min =0xff;
+ u1TXDLY_Cal_max=0;
+}
+#endif
+#endif //SIMULATION_GATING
+
+//-------------------------------------------------------------------------
+/** DramcRxWindowPerbitCal (v2 version)
+ * start the rx dqs perbit sw calibration.
+ * @param p Pointer of context created by DramcCtxCreate.
+ * @retval status (DRAM_STATUS_T): DRAM_OK or DRAM_FAIL
+ */
+//-------------------------------------------------------------------------
+// default RX vref is 0xe=14
+static void DramcRxWinRDDQCInit(DRAMC_CTX_T *p)
+{
+ U8 *uiLPDDR_MRR_Mapping;
+ U16 temp_value=0;
+ U8 MR_GOLDEN_MR15_GOLDEN_value=0, MR_GOLDEN_MR20_GOLDEN_value=0;
+ int i;
+
+ //U8 u1ReadDBIbak[2];
+ //U32 u4MRS_reg_bak;
+
+ // Disable Read DBI
+ //u1ReadDBIbak[0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ7), SHU1_B0_DQ7_R_DMDQMDBI_SHU_B0);
+ //u1ReadDBIbak[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ7), SHU1_B1_DQ7_R_DMDQMDBI_SHU_B1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ7), 0, SHU1_B0_DQ7_R_DMDQMDBI_SHU_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ7), 0, SHU1_B1_DQ7_R_DMDQMDBI_SHU_B1);
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), 1, SPCMDCTRL_RDDQCDIS); Moved to "DramcRxWinRDDQCRun()"
+
+ //u4MRS_reg_bak = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_MRS));
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRS), u1GetRank(p), MRS_MRSRK);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MPC_OPTION), 1, MPC_OPTION_MPCRKEN);
+ uiLPDDR_MRR_Mapping = (U8 *)uiLPDDR4_MRR_Mapping_POP[p->channel];
+
+ for(i=0; i<16; i++)
+ {
+ temp_value |= ((0x5555 >> i) & 0x1) << uiLPDDR_MRR_Mapping[i];
+ }
+ MR_GOLDEN_MR15_GOLDEN_value = (U8) temp_value & 0xff;
+ MR_GOLDEN_MR20_GOLDEN_value = (U8) (temp_value>>8) & 0xff;
+ //Set golden pattern from Shih-hsiu's suggestion. 2016/3/25 04:43pm, RE: [Olympus] RX per bit calibration.
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_MR_GOLDEN), P_Fld(MR_GOLDEN_MR15_GOLDEN_value, MR_GOLDEN_MR15_GOLDEN) | P_Fld(MR_GOLDEN_MR20_GOLDEN_value, MR_GOLDEN_MR20_GOLDEN));
+
+ //MPC_RDDQC_SET_MRS
+ //Write MR32 DQ calibration pattern A //skip it if you want default 5Ah
+ //Write MR40 DQ calibration pattern B //skip it if you want default 3Ch
+ //Write MR15 low byte inverter for DQ calibration (byte 0) //skip it if you want default 55h
+ //Write MR20 uper byte inverter for DQ calibration (byte 1) //skip it if you want default aah
+ //DramcModeRegWrite(p, 32, 0x86);
+ //DramcModeRegWrite(p, 40, 0xC9);
+ //DramcModeRegWrite(p, 32, 0xaa);
+ //DramcModeRegWrite(p, 32, 0xbb);
+}
+
+/* Issue "RD DQ Calibration"
+ * 1. RDDQCEN = 1 for RDDQC
+ * 2. RDDQCDIS = 1 to stop RDDQC burst
+ * 3. Wait rddqc_response = 1
+ * 4. Read compare result
+ * 5. RDDQCEN = 0
+ * 6. RDDQCDIS = 0 (Stops RDDQC request)
+ */
+static U32 DramcRxWinRDDQCRun(DRAMC_CTX_T *p)
+{
+ U32 u4Result, u4Response;
+ U32 u4TimeCnt= TIME_OUT_CNT;
+
+ //Issue RD DQ calibration
+ //R_DMRDDQCEN, 0x1E4[7]=1 for RDDQC, R_DMRDDQCDIS, 0x1EC[26]=1 to stop RDDQC burst
+ //Wait rddqc_response=1, (dramc_conf_nao, 0x3b8[31])
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), 1, SPCMDCTRL_RDDQCDIS);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_RDDQCEN);
+ do
+ {
+ u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_RDDQC_RESPONSE);
+ u4TimeCnt --;
+ mcDELAY_US(1);
+ }while((u4Response ==0) &&(u4TimeCnt>0));
+
+ if(u4TimeCnt==0)//time out
+ {
+ mcSHOW_DBG_MSG(("[RxWinRDDQC] Resp fail (time out)\n"));
+ mcFPRINTF((fp_A60501, "[RxWinRDDQC] Resp fail (time out)\n"));
+ //return DRAM_FAIL;
+ }
+
+ //Then read RDDQC compare result (dramc_conf_nao, 0x36c)
+ u4Result = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_RDQC_CMP));
+ //R_DMRDDQCEN, 0x1E4[7]=0
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_RDDQCEN);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), 0, SPCMDCTRL_RDDQCDIS);
+
+ return u4Result;
+}
+
+static void DramcRxWinRDDQCEnd(DRAMC_CTX_T *p)
+{
+ //Recover Read DBI
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ7), p->DBI_R_onoff, SHU1_B0_DQ7_R_DMDQMDBI_SHU_B0);
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ7), p->DBI_R_onoff, SHU1_B1_DQ7_R_DMDQMDBI_SHU_B1);
+
+ // Recover MPC Rank
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRS), 0, MRS_MRSRK);
+}
+
+#ifdef MPC_SW_FIFO
+void DramcMPC_FIFO(DRAMC_CTX_T *p)
+{
+ U32 u4Result3,u4Result2,u4Result1,u4Result0;
+ U32 u4Result, u4Response;
+ U32 u4TimeCnt= TIME_OUT_CNT;
+ U32 u4RegBackupAddress[] =
+ {
+ (DRAMC_REG_ADDR(DRAMC_REG_LBWDAT3)),
+ (DRAMC_REG_ADDR(DRAMC_REG_LBWDAT2)),
+ (DRAMC_REG_ADDR(DRAMC_REG_LBWDAT1)),
+ (DRAMC_REG_ADDR(DRAMC_REG_LBWDAT0)),
+ (DRAMC_REG_ADDR(DRAMC_REG_REFCTRL0)),
+ (DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL)),
+ (DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV)),
+ (DRAMC_REG_ADDR(DRAMC_REG_PERFCTL0)),
+ };
+
+
+ mcSHOW_DBG_MSG(("[DramcMPC_FIFO]\n"));
+ //Register backup
+ DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+ //WRFIFO and RDFIFO's golden data
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_LBWDAT3), 0xAAAAAAAA, LBWDAT3_LBWDATA3);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_LBWDAT2), 0x55555555, LBWDAT2_LBWDATA2);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_LBWDAT1), 0xAAAAAAAA, LBWDAT1_LBWDATA1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_LBWDAT0), 0x55555555, LBWDAT0_LBWDATA0);
+
+ u4Result3 = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_LBWDAT3));
+ mcSHOW_DBG_MSG(("DRAMC_REG_LBWDAT3: 0x%x\n", u4Result3));
+ mcFPRINTF((fp_A60501, "DRAMC_REG_LBWDAT3: 0x%x\n", u4Result3));
+ u4Result2 = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_LBWDAT2));
+ mcSHOW_DBG_MSG(("DRAMC_REG_LBWDAT2: 0x%x\n", u4Result2));
+ mcFPRINTF((fp_A60501, "DRAMC_REG_LBWDAT2: 0x%x\n", u4Result2));
+ u4Result1 = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_LBWDAT1));
+ mcSHOW_DBG_MSG(("DRAMC_REG_LBWDAT1: 0x%x\n", u4Result1));
+ mcFPRINTF((fp_A60501, "DRAMC_REG_LBWDAT1: 0x%x\n", u4Result1));
+ u4Result0 = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_LBWDAT0));
+ mcSHOW_DBG_MSG(("DRAMC_REG_LBWDAT0: 0x%x\n", u4Result0));
+ mcFPRINTF((fp_A60501, "DRAMC_REG_LBWDAT0: 0x%x\n", u4Result0));
+
+
+ //Other command is not valid during "WRFIFO and RDFIFO" period.
+ //Disable auto refresh: set R_DMREFDIS=1
+ vAutoRefreshSwitch(p, DISABLE);
+ //Disable MR4: set R_DMREFRDIS=1
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), 1, SPCMDCTRL_REFRDIS);
+ //Disable ZQCAL/ZQLAT command: set R_DMZQCALDISB=0
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDCTRL), 0, SPCMDCTRL_ZQCALDISB);
+
+
+ //When R_DMWRFIFOEN=1, MPC WRFIFO can send single request or 5 requests by R_DMRDDQC_INTV[1:0] (0x8C8[12:11])
+ //Set R_DMRDDQC_INTV=2'b00 and Set R_DMWRFIO_MODE2 = 1'b0 for single MPC WRFIFO (single mode)
+ //Set R_DMRDDQC_INTV=2'b01 and Set R_DMWRFIO_MODE2 = 1'b1 for five MPC WRFIFO (burst mode)
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_SCINTV), 0, SHU_SCINTV_RDDQC_INTV);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PERFCTL0), 0, PERFCTL0_WRFIO_MODE2);
+
+
+ //Issue MPC RD FIFO
+ //R_DMWRFIFOEN, 0x0C[31]=1 for WR FIFO
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PERFCTL0), 1, PERFCTL0_WRFIFOEN);
+
+ //Wait wrfifo_response=1 (dramc_conf_nao, 0x88[31])
+ do
+ {
+ u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_WRFIFO_RESPONSE);
+ u4TimeCnt --;
+ mcDELAY_US(1);
+ }while((u4Response ==0) &&(u4TimeCnt>0));
+
+ if(u4TimeCnt==0)//time out
+ {
+ mcSHOW_DBG_MSG(("[DramcMPC_FIFO] Resp fail (time out)\n"));
+ mcFPRINTF((fp_A60501, "[DramcMPC_FIFO] Resp fail (time out)\n"));
+ //return DRAM_FAIL;
+ }
+
+ //R_DMWRFIFOEN, 0x0C[31]=0
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PERFCTL0), 0, PERFCTL0_WRFIFOEN);
+
+
+
+ //Issue MPC RD FIFO
+ //R_DMRDFIFOEN, 0x0C[30]=1 for RD FIFO
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PERFCTL0), 1, PERFCTL0_RDFIFOEN);
+
+ //Wait wrfifo_response=1 (dramc_conf_nao, 0x88[31])
+ do
+ {
+ u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_RDFIFO_RESPONSE);
+ u4TimeCnt --;
+ mcDELAY_US(1);
+ }while((u4Response ==0) &&(u4TimeCnt>0));
+
+ if(u4TimeCnt==0)//time out
+ {
+ mcSHOW_DBG_MSG(("[DramcMPC_FIFO] Resp fail (time out)\n"));
+ mcFPRINTF((fp_A60501, "[DramcMPC_FIFO] Resp fail (time out)\n"));
+ //return DRAM_FAIL;
+ }
+
+ //Then read RDFIFO compare result (dramc_conf_nao, 0x124)
+ //Must do WRFIO first, then do RDFIFO, then compare it.
+ u4Result = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_CMP_ERR));
+ mcSHOW_DBG_MSG(("[DramcMPC_FIFO] Read RDFIFO compare result: 0x%x\n", u4Result));
+
+ //R_DMRDFIFOEN, 0x0C[30]=0
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PERFCTL0), 0, PERFCTL0_RDFIFOEN);
+
+ //Restore registers
+ DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+}
+#endif
+
+#ifdef ENABLE_POST_PACKAGE_REPAIR
+U8 global_sk_ppr_channel[SK_CHANNEL_BITS] = {0, 1}; //CHB //base on SK hynix_Repair_Guide_20180411.pdf
+U8 global_sk_ppr_rank[SK_RANK_BITS] = {0, 1}; //R1 of fail IC
+U8 global_sk_ppr_bank[SK_BANK_BITS] = {0, 0, 0, 0, 1, 0, 0, 0}; //Bank 4
+U8 global_sk_ppr_byte[SK_BYTE_BITS] = {0};
+U8 global_sk_ppr_row[SK_ROW_BITS] = {0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1}; //0x7154
+U8 global_sk_vendor_id = VENDOR_HYNIX;
+
+#ifdef POST_PACKAGE_REPAIR_LP4
+U8 TrasformToFailAddr(U8 *pArray ,U8 u1Size)
+{
+ U8 ucIdx = 0;
+ U8 ucFailAddr = 0xff;
+
+ for(ucIdx=0; ucIdx<u1Size; ucIdx++)//could only allow one channel/rank/bank wrong
+ {
+ if(pArray[ucIdx] == 1)
+ {
+ ucFailAddr = ucIdx;
+ break;
+ }
+ }
+
+ return ucFailAddr;
+}
+
+
+void DramcPostPackageRepair(DRAMC_CTX_T *p)
+{
+ U32 u4Response=0;
+ U32 u4TimeCnt= TIME_OUT_CNT;
+ U16 u2Value=0;
+ U16 u2FailRow = 0;
+ U8 ucFailChannel = 0xff;
+ U8 ucFailRK = 0xff;
+ U8 ucFailBK = 0xff;
+ U8 ucIdx = 0;
+
+ ucFailChannel = TrasformToFailAddr(global_sk_ppr_channel, SK_CHANNEL_BITS);
+ ucFailRK = TrasformToFailAddr(global_sk_ppr_rank, SK_RANK_BITS);
+ ucFailBK = TrasformToFailAddr(global_sk_ppr_bank, SK_BANK_BITS);
+ if((ucFailChannel == 0xff) || (ucFailRK == 0xff) || (ucFailBK == 0xff))
+ {
+ mcSHOW_ERR_MSG(("PPR Not assign channel/rank/bank!!\n"));
+ return;
+ }
+
+ for(ucIdx=0; ucIdx<SK_ROW_BITS; ucIdx++)//could only allow one bank wrong
+ {
+ u2FailRow += (global_sk_ppr_row[ucIdx] << ucIdx);
+ }
+
+ vSetPHY2ChannelMapping(p, ucFailChannel);//Based on usage; fail IC 1-18, LP4 need to assign channel && rank
+ vSetRank(p, ucFailRK);//Based on usage; fail IC 1-18, LP4 need to assign channel && rank
+
+ mcSHOW_DBG_MSG(("ucFailBK=0x%x, u2FailRow=0x%x\n", ucFailBK, u2FailRow));
+ mcSHOW_DBG_MSG(("[DramcPostPackageRepair]\n"
+ "\n\tFreq=%d, CH=%d, Rank=%d\n", p->frequency, p->channel, p->rank));
+ mcFPRINTF((fp_A60501, "[DramcPostPackageRepair]"
+ "\n\tFreq=%d, CH=%d, Rank=%d\n", p->frequency, p->channel, p->rank));
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MRS), u1GetRank(p), MRS_MRSRK);
+
+ //1.DRAMC DCM freerun,
+ //R_DMDCMEN2(dramc conf AO 0x38[1])=0
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 0, DRAMC_PD_CTRL_DCMEN2);
+
+ //2.PHY DCM freerun,
+ //R_DMPHYCLKDYNGEN(dramc conf AO 0x38[30])=0
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 0, DRAMC_PD_CTRL_PHYCLKDYNGEN);
+
+ //3.Dram clock freerun,
+ //R_DMMIOCKCTRLOFF(dramc conf AO 0x38[26])=1
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 1, DRAMC_PD_CTRL_MIOCKCTRLOFF);
+
+#if MRW_CHECK_ONLY
+ mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
+#endif
+
+ //MR25 contains one bit of readout per bank indicating that at least one resource is available for Post Package Repair programming.
+ DramcModeRegRead(p, 25, &u2Value);
+ mcSHOW_DBG_MSG(("Before PostPackageRepair, MR25 = 0x%x\n", u2Value & 0xFF));
+ mcFPRINTF((fp_A60501, "Before PostPackageRepair, MR25 = 0x%x\n", u2Value & 0xFF));
+
+ //4.Fix CKE0 and CKE1 be high,
+ //R_DMCKEFIXON(dramc conf AO 0x24[6], CKECTRL.CKEFIXON)=1
+ //R_DMCKE1FIXON(dramc conf AO 0x24[4], CKECTRL.CKE1FIXON)=1
+ CKEFixOnOff(p, CKE_WRITE_TO_ALL_RANK, CKE_FIXON, CKE_WRITE_TO_ALL_CHANNEL);
+
+ //Step 0: disable refresh for PPR
+ //Let R_DMREFDIS=1
+ vAutoRefreshSwitch(p, DISABLE);
+
+ //Step 1: before enter PPR mode, all banks must be precharged
+ //Set R_DMPREAEN=1
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_PREAEN);
+ mcDELAY_US(1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_PREAEN);
+
+ //wait dramc_conf_nao.prea_response=1
+ u4TimeCnt= TIME_OUT_CNT;
+ u4Response = 0;
+ do
+ {
+ u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_PREA_RESPONSE);
+ u4TimeCnt --;
+ mcDELAY_US(1);
+ }while((u4Response ==0) &&(u4TimeCnt>0));
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_PREAEN);
+
+ if(u4TimeCnt==0)//time out
+ {
+ mcSHOW_DBG_MSG(("dramc_conf_nao.prea_response fail (time out)\n"));
+ mcFPRINTF((fp_A60501, "dramc_conf_nao.prea_response fail (time out)\n"));
+ //return DRAM_FAIL;
+ }
+
+ //Step 2: enter PPR mode
+ if(global_sk_vendor_id == VENDOR_HYNIX) //Skhynix Manufacturer ID
+ {
+ //Skhynix DRAM PPR Enable Sequence
+ //Assumption: MR3 OP<2> - LOW
+ //Skhynix 2z 6Gb/4Gb LPDDR4x PPR Guard key
+ //PPR Guard Key, MR9 with following OP codes : B8 - E8 - 98 - BF - EF - 9F - B9 - E9 - 99 - 84 - A2 - 81
+ //Skhynix 2z 8Gb LPDDR4x PPR Guard key
+ //PPR Guard Key, MR9 with following OP codes : CD - AD -FD -C9 -A9 -F9 -C7 -A7 -F7
+ DramcModeRegWrite(p, 9, 0xB8);
+ DramcModeRegWrite(p, 9, 0xE8);
+ DramcModeRegWrite(p, 9, 0x98);
+ DramcModeRegWrite(p, 9, 0xBF);
+ DramcModeRegWrite(p, 9, 0xEF);
+ DramcModeRegWrite(p, 9, 0x9F);
+ DramcModeRegWrite(p, 9, 0xB9);
+ DramcModeRegWrite(p, 9, 0xE9);
+ DramcModeRegWrite(p, 9, 0x99);
+ DramcModeRegWrite(p, 9, 0x84);
+ DramcModeRegWrite(p, 9, 0xA2);
+ DramcModeRegWrite(p, 9, 0x81);
+ }
+
+ //Set MR4[4]=1: PPR entry
+ DramcModeRegWrite(p, 4, 0x10);
+
+ //Step 3: wait tMRD
+ //mcDELAY_US(1000);
+ mcDELAY_MS(1000);
+
+ //Step 4: issue ACT command with fail row address
+ //Set R_DMACTEN_ROW, R_DMACTEN_BK, then set R_DMACTEN,
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_MPC_OPTION), 1, MPC_OPTION_MPCRKEN);
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PPR_CTRL), u2FailRow, PPR_CTRL_ACTEN_ROW);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_PPR_CTRL), ucFailBK, PPR_CTRL_ACTEN_BK);
+ mcSHOW_DBG_MSG(("PPR, Fail Row = 0x%x, Fail Bank = 0x%x\n", u2FailRow, ucFailBK));
+ mcFPRINTF((fp_A60501, "PPR, Fail Row = 0x%x, Fail Bank = 0x%x\n", u2FailRow, ucFailBK));
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_ACTEN);
+ mcDELAY_US(1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_ACTEN);
+
+ //wait dramc_conf_nao.act_response=1
+ u4TimeCnt= TIME_OUT_CNT;
+ u4Response=0;
+ do
+ {
+ u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_ACT_RESPONSE);
+ u4TimeCnt --;
+ mcDELAY_US(1);
+ }while((u4Response ==0) &&(u4TimeCnt>0));
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_ACTEN);
+
+ if(u4TimeCnt==0)//time out
+ {
+ mcSHOW_DBG_MSG(("dramc_conf_nao.act_response fail (time out)\n"));
+ mcFPRINTF((fp_A60501, "dramc_conf_nao.act_response fail (time out)\n"));
+ //return DRAM_FAIL;
+ }
+
+ //Step 5: wait tPGM to allow DRAM repair internally
+ mcDELAY_MS(3000);
+
+ //Step 6: issue PRE
+ //Set R_DMPREAEN=1
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 0, SPCMD_PREAEN);
+ mcDELAY_US(1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMD), 1, SPCMD_PREAEN);
+
+ //wait dramc_conf_nao.prea_response=1
+ u4TimeCnt= TIME_OUT_CNT;
+ u4Response=0;
+ do
+ {
+ u4Response = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SPCMDRESP), SPCMDRESP_PREA_RESPONSE);
+ u4TimeCnt --;
+ mcDELAY_US(1);
+ }while((u4Response ==0) &&(u4TimeCnt>0));
+
+ if(u4TimeCnt==0)//time out
+ {
+ mcSHOW_DBG_MSG(("dramc_conf_nao.prea_response fail (time out)\n"));
+ mcFPRINTF((fp_A60501, "dramc_conf_nao.prea_response fail (time out)\n"));
+ //return DRAM_FAIL;
+ }
+
+ //Step 7: wait tPGM_Exit
+ //mcDELAY_US(1000);
+ mcDELAY_MS(1000);
+
+ //Step 8: exit PPR
+ //Set MR4[4]=0: PPR exit
+ DramcModeRegWrite(p, 4, 0x0);
+
+ //Step 9: wait tPGMPST, them dram is ready for any valid command
+ //mcDELAY_US(1000);
+ mcDELAY_MS(1000);
+
+ //MR25 contains one bit of readout per bank indicating that at least one resource is available for Post Package Repair programming.
+ DramcModeRegRead(p, 25, &u2Value);
+ mcSHOW_DBG_MSG(("After PostPackageRepair, MR25 = 0x%x\n", u2Value & 0xFF));
+ mcFPRINTF((fp_A60501, "After PostPackageRepair, MR25 = 0x%x\n", u2Value & 0xFF));
+}
+#endif
+
+#ifdef SKH_POST_PACKAGE_REPAIR_LP3
+static void DramcModeRegWriteByRankUsDelay(DRAMC_CTX_T *p, U8 u1MRIdx, U8 u1Value, U8 u1Delay)
+{
+ DramcModeRegWriteByRank(p, p->rank, u1MRIdx, u1Value);
+ mcDELAY_US(u1Delay);
+ mcSHOW_DBG_MSG(("SKPPR R<%d> MR<%d> Value<%x> delay<%d>\n", p->rank, u1MRIdx, u1Value, u1Delay));
+
+ return;
+}
+
+
+void SkRepairSequenceOp0(DRAMC_CTX_T *p)
+{
+ DRAM_RANK_T eOriRank = u1GetRank(p);
+ U8 u1Mr9_Op = 0;
+ int i = 0;
+ U8 u1RankIdx = 0;
+ U8 u1DQ = ((global_sk_ppr_byte[0] == 1) || (global_sk_ppr_byte[2] == 1)) ? 0 : 1;
+ U8 u1BK[3] = {0};
+
+ for(i = 0; i<=SK_BANK_BITS; i++)
+ {
+ if(global_sk_ppr_bank[i] == 1)
+ {
+ u1BK[0] = i & 1;
+ u1BK[1] = (i >> 1) & 1;
+ u1BK[2] = (i >> 2) & 1;
+ break;
+ }
+ }
+ mcSHOW_DBG_MSG(("SKPPR BK0<%d> BK1<%d> BK2<%d>\n", u1BK[0], u1BK[1], u1BK[2]));
+
+ for(u1RankIdx=0; u1RankIdx<(U8)p->support_rank_num; u1RankIdx++)
+ {
+ if(global_sk_ppr_rank[u1RankIdx] == 1)
+ {
+ vSetRank(p, u1RankIdx);
+
+ //Iput Entry Code
+ DramcModeRegWriteByRankUsDelay(p, 9, 0xB0, 3);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0xE0, 3);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x90, 3);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0xC8, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x90, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x8B, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0xE0, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0xD8, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x88, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x93, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0xE0, 25);
+
+ //Input Fail Addr.
+ u1Mr9_Op = ((u1DQ << 1) |
+ (u1BK[0] << 2) |
+ (1 << 3) |
+ (global_sk_ppr_row[12] << 4) |
+ (global_sk_ppr_row[8] << 5) |
+ (global_sk_ppr_row[4] << 6) |
+ (1 << 7));
+ DramcModeRegWriteByRankUsDelay(p, 9, u1Mr9_Op, 25);
+
+ u1Mr9_Op = ((u1BK[2] << 1) |
+ (global_sk_ppr_row[14] << 2) |
+ (global_sk_ppr_row[11] << 4) |
+ (global_sk_ppr_row[7] << 5) |
+ (global_sk_ppr_row[3] << 6));
+ DramcModeRegWriteByRankUsDelay(p, 9, u1Mr9_Op, 25);
+
+ u1Mr9_Op = ((u1BK[1] << 1) |
+ (1 << 2) |
+ (1 << 3) |
+ (global_sk_ppr_row[10] << 4) |
+ (global_sk_ppr_row[6] << 5) |
+ (global_sk_ppr_row[2] << 6));
+ DramcModeRegWriteByRankUsDelay(p, 9, u1Mr9_Op, 25);
+
+ u1Mr9_Op = ((1 << 2) |
+ (global_sk_ppr_row[9] << 4) |
+ (global_sk_ppr_row[5] << 5) |
+ (global_sk_ppr_row[1] << 6) |
+ (1 << 7));
+ DramcModeRegWriteByRankUsDelay(p, 9, u1Mr9_Op, 25);
+
+ //Input additional TM
+ DramcModeRegWriteByRankUsDelay(p, 9, 0xD4, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x84, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0xE3, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0xE0, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0xB4, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x8C, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x87, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0xE0, 25);
+
+ //Execute SKH Repair
+ mcSHOW_DBG_MSG(("36 loop Start\n"));
+ for(i=0; i<36; i++) //36 LOOP
+ {
+ DramcModeRegWriteByRankUsDelay(p, 9, 0xC4, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x9C, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x93, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0xE0, 25);
+ }
+ mcSHOW_DBG_MSG(("36 loop Stop\n"));
+
+ //Exit SKH repair mode
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x00, 25);
+ }
+ }
+
+ vSetRank(p, (U8)eOriRank);
+ return;
+}
+
+
+void SkRepairSequenceOp1(DRAMC_CTX_T *p)
+{
+ DRAM_RANK_T eOriRank = u1GetRank(p);
+ U8 u1Mr9_Op = 0;
+ int i = 0;
+ U8 u1RankIdx = 0;
+ U8 u1DQ = ((global_sk_ppr_byte[0] == 1) || (global_sk_ppr_byte[2] == 1)) ? 0 : 1;
+ U8 u1BK[3] = {0};
+
+ for(i = 0; i<=SK_BANK_BITS; i++)
+ {
+ if((global_sk_ppr_bank[0] == 1) || (global_sk_ppr_bank[1] == 1))
+ {
+ u1BK[2] = 0;
+ u1BK[1] = 0;
+ }
+ else if((global_sk_ppr_bank[2] == 1) || (global_sk_ppr_bank[3] == 1))
+ {
+ u1BK[2] = 0;
+ u1BK[1] = 1;
+ }
+ else if((global_sk_ppr_bank[4] == 1) || (global_sk_ppr_bank[5] == 1))
+ {
+ u1BK[2] = 1;
+ u1BK[1] = 0;
+ }
+ else if((global_sk_ppr_bank[6] == 1) || (global_sk_ppr_bank[7] == 1))
+ {
+ u1BK[2] = 1;
+ u1BK[1] = 1;
+ }
+ }
+ mcSHOW_DBG_MSG(("SKPPR BK0<%d> BK1<%d> BK2<%d>\n", u1BK[0], u1BK[1], u1BK[2]));
+
+ for(u1RankIdx=0; u1RankIdx<(U8)p->support_rank_num; u1RankIdx++)
+ {
+ if(global_sk_ppr_rank[u1RankIdx] == 1)
+ {
+ vSetRank(p, u1RankIdx);
+
+ //Iput Entry Code
+ DramcModeRegWriteByRankUsDelay(p, 9, 0xB0, 3);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0xE0, 3);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x90, 3);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0xA8, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x8E, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x83, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0xA8, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x84, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x86, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x83, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0xA8, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x90, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x9E, 25);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x83, 25);
+
+ //Input Fail Addr.
+ u1Mr9_Op = ((global_sk_ppr_row[12] << 1) |
+ (global_sk_ppr_row[11] << 3) |
+ (global_sk_ppr_row[10] << 5) |
+ (u1DQ << 6) |
+ (global_sk_ppr_row[9] << 7));
+ DramcModeRegWriteByRankUsDelay(p, 9, u1Mr9_Op, 25);
+
+ u1Mr9_Op = ((global_sk_ppr_row[8] << 1) |
+ (global_sk_ppr_row[7] << 3) |
+ (u1BK[2] << 4) |
+ (global_sk_ppr_row[6] << 5) |
+ (u1BK[1] << 6)|
+ (global_sk_ppr_row[5] << 7));
+ DramcModeRegWriteByRankUsDelay(p, 9, u1Mr9_Op, 25);
+
+ u1Mr9_Op = ((global_sk_ppr_row[14]) |
+ (global_sk_ppr_row[4] << 1) |
+ (global_sk_ppr_row[13] << 2) |
+ (global_sk_ppr_row[3] << 3) |
+ (global_sk_ppr_row[2] << 5) |
+ (global_sk_ppr_row[1] << 7));
+ DramcModeRegWriteByRankUsDelay(p, 9, u1Mr9_Op, 25);
+
+ u1Mr9_Op = 0xD2;
+ DramcModeRegWriteByRankUsDelay(p, 9, u1Mr9_Op, 25);
+
+ //Execute SKH Repair
+ for(i=0; i<36; i++) //36 LOOP
+ {
+ DramcModeRegWriteByRankUsDelay(p, 9, 0xAC, 10);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x88, 10);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x86, 10);
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x83, 10);
+ }
+ //Exit SKH repair mode
+ DramcModeRegWriteByRankUsDelay(p, 9, 0x00, 10);
+ }
+ }
+
+ vSetRank(p, (U8)eOriRank);
+ return;
+}
+
+
+static U32 u4SKPostPackageRepairBackupAddress[] =
+{
+ (DRAMC_REG_DRAMC_PD_CTRL),
+ (DRAMC_REG_REFCTRL0),
+ (DRAMC_REG_SPCMDCTRL),
+ (DRAMC_REG_SHU_SCINTV),
+ (DRAMC_REG_SHU2_SCINTV),
+ (DRAMC_REG_SHU3_SCINTV)
+};
+
+
+void SkPostPackageRepairLP3(DRAMC_CTX_T *p) //Backup restore
+{
+ //DRAM_CHANNEL_T eOriChannel = vGetPHY2ChannelMapping(p);
+ //DRAM_RANK_T eOriRank = u1GetRank(p);
+ U16 u2Mr7Op = 0;
+
+ mcSHOW_DBG_MSG(("SKPPR\n"
+ "\nFreq=%d, CH=%d, Rank=%d\n", p->frequency, p->channel, p->rank));
+
+ //Backup regs
+ DramcBackupRegisters(p, u4SKPostPackageRepairBackupAddress, sizeof(u4SKPostPackageRepairBackupAddress)/sizeof(U32));
+
+ //DRAMC DCM freerun,
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 0, DRAMC_PD_CTRL_DCMEN2);
+
+ //PHY DCM freerun,
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 0, DRAMC_PD_CTRL_PHYCLKDYNGEN);
+
+ //Dram clock freerun,
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_DRAMC_PD_CTRL), 1, DRAMC_PD_CTRL_MIOCKCTRLOFF);
+
+ //Fix CKE0 and CKE1 be high,
+ CKEFixOnOff(p, CKE_WRITE_TO_ALL_RANK, CKE_FIXON, CKE_WRITE_TO_ALL_CHANNEL);
+
+ //All banks must be precharged
+ //Enter_Precharge_All(p);
+ //vIO32WriteFldAlign(DRAMC_REG_SPCMD, 0, SPCMD_PREAEN);
+
+ //Disable MR4, refresh, ZQ_Cal, TX
+ vIO32WriteFldAlign(DRAMC_REG_REFCTRL0, 1, REFCTRL0_REFDIS);
+ vIO32WriteFldAlign(DRAMC_REG_SPCMDCTRL, 1, SPCMDCTRL_REFRDIS);
+ vIO32WriteFldAlign(DRAMC_REG_SPCMDCTRL, 0, SPCMDCTRL_ZQCSDISB);
+ vIO32WriteFldAlign(DRAMC_REG_SHU_SCINTV, 1, SHU_SCINTV_DQSOSCENDIS);
+ vIO32WriteFldAlign(DRAMC_REG_SHU2_SCINTV, 1, SHU2_SCINTV_DQSOSCENDIS);
+ vIO32WriteFldAlign(DRAMC_REG_SHU3_SCINTV, 1, SHU3_SCINTV_DQSOSCENDIS);
+
+ DramcModeRegReadByRank(p, RANK_0, 7, &u2Mr7Op);//CHA R0
+ u2Mr7Op &= 0xff;
+ mcSHOW_DBG_MSG(("Before SKPPR, MR7 = 0x%x\n", u2Mr7Op));//0: 1st 8G 1: 2rd 8G
+
+ if(u2Mr7Op == 0)
+ {
+ SkRepairSequenceOp0(p);
+ }
+ else
+ {
+ SkRepairSequenceOp1(p);
+ }
+ //Restore regs
+ DramcRestoreRegisters(p, u4SKPostPackageRepairBackupAddress, sizeof(u4SKPostPackageRepairBackupAddress)/sizeof(U32));
+ return;
+}
+#endif //SKH_POST_PACKAGE_REPAIR_LP3
+
+
+extern DRAMC_CTX_T DramCtx_LPDDR4;
+extern DRAMC_CTX_T DramCtx_LPDDR3;
+void PostPackageRepair(void)
+{
+ BOOL bLp4 = u1IsLP4Family(mt_get_dram_type_from_hw_trap());
+ DRAMC_CTX_T *p = (bLp4) ? (&DramCtx_LPDDR4) : (&DramCtx_LPDDR3);
+ DRAM_CHANNEL_T eOriChannel = vGetPHY2ChannelMapping(p);
+ DRAM_RANK_T eOriRank = u1GetRank(p);
+
+ if(bLp4)//Based on VDRAM to decide the DRAM type
+ {
+#ifdef POST_PACKAGE_REPAIR_LP4
+ DramcPostPackageRepair(p);
+#endif
+ }
+ else
+ { // LPDDR3
+#ifdef SKH_POST_PACKAGE_REPAIR_LP3
+ p->support_rank_num = RANK_DUAL;//Based on usage
+ SkPostPackageRepairLP3(p);
+#endif
+ }
+
+ vSetRank(p, eOriRank);
+ vSetPHY2ChannelMapping(p, eOriChannel);
+ return;
+}
+#endif //ENABLE_POST_PACKAGE_REPAIR
+
+
+static void SetRxDqDqsDelay(DRAMC_CTX_T *p, S16 iDelay)
+{
+ U8 ii;
+ U32 u4value;
+#if ENABLE_LP3_SW
+ U8 dl_value[8];
+ U8 u1ByteIdx;
+#endif
+
+ if (iDelay <=0)
+ {
+ if(u1IsLP4Family(p->dram_type))
+ {
+ // Set DQS delay
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6), \
+ P_Fld((-iDelay+gu2RX_DQS_Duty_Offset[0][0]),SHU1_R0_B0_DQ6_RK0_RX_ARDQS0_R_DLY_B0) |P_Fld((-iDelay+gu2RX_DQS_Duty_Offset[0][1]),SHU1_R0_B0_DQ6_RK0_RX_ARDQS0_F_DLY_B0));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ6), \
+ P_Fld((-iDelay+gu2RX_DQS_Duty_Offset[1][0]),SHU1_R0_B1_DQ6_RK0_RX_ARDQS0_R_DLY_B1) |P_Fld((-iDelay+gu2RX_DQS_Duty_Offset[1][1]),SHU1_R0_B1_DQ6_RK0_RX_ARDQS0_F_DLY_B1));
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+ {
+ vIO32WriteFldAlign_Phy_Byte(u1ByteIdx, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6), -iDelay, SHU1_R0_B0_DQ6_RK0_RX_ARDQS0_R_DLY_B0);
+ vIO32WriteFldAlign_Phy_Byte(u1ByteIdx, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6), -iDelay, SHU1_R0_B0_DQ6_RK0_RX_ARDQS0_F_DLY_B0);
+ }
+ }
+#endif
+
+ DramPhyReset(p);
+ }
+ else
+ {
+ // Adjust DQM output delay.
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6), \
+ P_Fld(iDelay,SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_R_DLY_B0) |P_Fld(iDelay,SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_F_DLY_B0));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ6), \
+ P_Fld(iDelay,SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_R_DLY_B1) |P_Fld(iDelay,SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_F_DLY_B1));
+ }
+ #if ENABLE_LP3_SW
+ else
+ {
+ for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+ {
+ Set_RX_DQM_DelayLine_Phy_Byte(p, u1ByteIdx, iDelay);
+ }
+ }
+ #endif
+
+ DramPhyReset(p);
+
+ // Adjust DQ output delay.
+ if(u1IsLP4Family(p->dram_type))
+ {
+ u4value = ((U32) iDelay) | (((U32)iDelay)<<8) | (((U32)iDelay)<<16) | (((U32)iDelay)<<24);
+ for (ii=0; ii<4; ii++)
+ {
+ vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2+ ii*4), u4value);//DQ0~DQ7
+ vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2+ ii*4), u4value);//DQ8~DQ15
+ }
+
+ #if PINMUX_AUTO_TEST_PER_BIT_RX
+ if(gRX_check_per_bit_flag)
+ {
+ SetRxPerBitDelayCellForPinMuxCheck(p, gRX_Check_per_bit_idx);
+ //CheckRXDelayCell(p);
+ }
+ #endif
+
+ }
+ #if ENABLE_LP3_SW
+ else//LPDDR3
+ {
+ //every 2bit dq have the same delay register address
+ for (u1ByteIdx=0; u1ByteIdx<DQS_NUMBER; u1ByteIdx++)
+ {
+ dl_value[0] = iDelay;
+ dl_value[1] = iDelay;
+ dl_value[2] = iDelay;
+ dl_value[3] = iDelay;
+ dl_value[4] = iDelay;
+ dl_value[5] = iDelay;
+ dl_value[6] = iDelay;
+ dl_value[7] = iDelay;
+
+ Set_RX_DQ_DelayLine_Phy_Byte(p, u1ByteIdx, dl_value);
+ }
+ #if PINMUX_AUTO_TEST_PER_BIT_RX_LP3
+ if(gRX_check_per_bit_flag)
+ {
+ SetRxPerBitDelayCellForPinMuxCheckLp3(p, gRX_Check_per_bit_idx, iDelay);
+ //CheckRXDelayCell(p);
+ }
+ #endif
+ }
+ #endif
+ }
+}
+
+
+#if SIMULATION_RX_PERBIT
+
+#define RX_DELAY_PRE_CAL 1
+#if RX_DELAY_PRE_CAL
+S16 s2RxDelayPreCal=PASS_RANGE_NA;
+#endif
+DRAM_STATUS_T DramcRxWindowPerbitCal(DRAMC_CTX_T *p, U8 u1UseTestEngine)
+{
+ U8 ii, u1BitIdx, u1ByteIdx;
+ U8 ucbit_first, ucbit_last;
+ S16 iDelay=0, u4DelayBegin=0, u4DelayEnd, u4DelayStep=1;
+ S16 iDutyOffset=0, u4DutyOffsetBegin, u4DutyOffsetEnd, u4DutyOffsetStep=4;
+ U32 uiFinishCount;
+ U32 u4err_value, u4fail_bit;
+ PASS_WIN_DATA_T WinPerBit[DQ_DATA_WIDTH], FinalWinPerBit[DQ_DATA_WIDTH];
+ S32 iDQSDlyPerbyte[DQS_NUMBER], iDQMDlyPerbyte[DQS_NUMBER];//, iFinalDQSDly[DQS_NUMBER];
+ U8 u1VrefScanEnable;
+ U16 u2VrefLevel, u2TempWinSum, u2TmpDQMSum, u2FinalVref=0xe;
+ U16 u2VrefBegin, u2VrefEnd, u2VrefStep;
+ U32 u4AddrOfst = 0x50;
+ U8 u1RXEyeScanEnable;
+#if ENABLE_LP3_SW
+ U8 dl_value[8]={0,0,0,0,0,0,0,0};
+#endif
+ U8 backup_rank;
+
+#if 0//PPORT_SAVE_TIME_FOR_CALIBRATION
+ S16 u1minfirst_pass=0xff,u1minlast_pass=0xff,u4Delayoffset;
+ U8 u1AllBitPassCount;
+#endif
+
+#if EYESCAN_LOG
+ U8 EyeScan_index[DQ_DATA_WIDTH_LP4];
+ U8 u1pass_in_this_vref_flag[DQ_DATA_WIDTH_LP4];
+#endif
+
+
+#if REG_ACCESS_PORTING_DGB
+ RegLogEnable =1;
+ mcSHOW_DBG_MSG(("\n[REG_ACCESS_PORTING_FUNC] DramcRxWindowPerbitCal\n"));
+ mcFPRINTF((fp_A60501, "\n[REG_ACCESS_PORTING_FUNC] DramcRxWindowPerbitCal\n"));
+#endif
+
+ // error handling
+ if (!p)
+ {
+ mcSHOW_ERR_MSG(("context NULL\n"));
+ return DRAM_FAIL;
+ }
+
+#ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+ U8 u1GUMP_INIT_RG_LOG_TO_DE_bak = gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag;
+ gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag=0;
+#endif
+
+ backup_rank = u1GetRank(p);
+
+ u1RXEyeScanEnable = (gRX_EYE_Scan_flag==1 && ((gRX_EYE_Scan_only_higheset_freq_flag==1 && p->frequency == u2DFSGetHighestFreq(p)) || gRX_EYE_Scan_only_higheset_freq_flag==0));
+
+#if EYESCAN_LOG
+ U32 u1vrefidx;
+
+ if (u1IsLP4Family(p->dram_type))
+ {
+ for(u1vrefidx=0; u1vrefidx<RX_VREF_RANGE_END+1;u1vrefidx++)
+ {
+ for (u1BitIdx = 0; u1BitIdx < DQ_DATA_WIDTH_LP4; u1BitIdx++)
+ {
+ for(ii=0; ii<EYESCAN_BROKEN_NUM; ii++)
+ {
+ gEyeScan_Min[u1vrefidx][u1BitIdx][ii] = EYESCAN_DATA_INVALID;
+ gEyeScan_Max[u1vrefidx][u1BitIdx][ii] = EYESCAN_DATA_INVALID;
+
+ gEyeScan_ContinueVrefHeight[u1BitIdx] = 0;
+ gEyeScan_TotalPassCount[u1BitIdx] = 0;
+ }
+ }
+ }
+ }
+#endif
+
+
+ //defult set result fail. When window found, update the result as oK
+ if(u1UseTestEngine)
+ {
+ vSetCalibrationResult(p, DRAM_CALIBRATION_RX_PERBIT, DRAM_FAIL);
+ DramcEngine2Init(p, p->test2_1, p->test2_2, p->test_pattern, 0);
+ }
+ else
+ {
+ vSetCalibrationResult(p, DRAM_CALIBRATION_RX_RDDQC, DRAM_FAIL);
+ DramcRxWinRDDQCInit(p);
+ }
+
+
+ // for loop, different Vref,
+ u2rx_window_sum = 0;
+
+ if(u1IsLP4Family(p->dram_type) && (u1UseTestEngine==1) && (p->enable_rx_scan_vref==ENABLE) && (p->rank==RANK_0)) //only apply RX Vref Scan for Rank 0 (Rank 0 and 1 use the same Vref reg)
+ u1VrefScanEnable =1;
+ else
+ u1VrefScanEnable =0;
+
+ if (gRX_EYE_Scan_flag==1 && u1VrefScanEnable==0)
+ {
+ if(u1IsLP4Family(p->dram_type) && (u1UseTestEngine==1) && (p->enable_rx_scan_vref==ENABLE) && (p->rank==RANK_1)) //also need to K rank1 for debug
+ u1VrefScanEnable =1;
+ }
+
+
+ #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==1 && (p->Bypass_RDDQC || p->Bypass_RXWINDOW))
+ {
+ mcSHOW_DBG_MSG(("[FAST_K] Bypass RX Calibration\n"));
+ }
+ else
+ #endif
+ {
+#if VENDER_JV_LOG
+#if 0 //BU don't want customer knows our RX's ability
+ if(u1UseTestEngine ==1)
+ vPrintCalibrationBasicInfo_ForJV(p);
+#endif
+#else
+ vPrintCalibrationBasicInfo(p);
+#endif
+ mcSHOW_DBG_MSG2(("Start DQ dly to find pass range UseTestEngine =%d\n", u1UseTestEngine));
+ mcSHOW_DBG_MSG2(("x-axis: bit #, y-axis: DQ dly (%d~%d)\n", (-MAX_RX_DQSDLY_TAPS), MAX_RX_DQDLY_TAPS));
+ mcFPRINTF((fp_A60501, "Start RX DQ/DQS calibration UseTestEngine =%d\n", u1UseTestEngine));
+ mcFPRINTF((fp_A60501, "x-axis is bit #; y-axis is DQ delay\n"));
+ }
+
+ mcSHOW_DBG_MSG(("RX Vref Scan = %d\n", u1VrefScanEnable));
+ mcFPRINTF((fp_A60501, "RX Vref Scan= %d\n", u1VrefScanEnable));
+
+ if(u1VrefScanEnable)
+ {
+ #if (SW_CHANGE_FOR_SIMULATION ||FOR_DV_SIMULATION_USED)
+ u2VrefBegin =RX_VREF_RANGE_BEGIN;
+ #else
+ if (gRX_EYE_Scan_flag==0)
+ {
+ if(p->odt_onoff)
+ {
+ u2VrefBegin = RX_VREF_RANGE_BEGIN_ODT_ON;
+ }
+ else
+ {
+ u2VrefBegin = RX_VREF_RANGE_BEGIN_ODT_OFF;
+ }
+ }
+ else
+ u2VrefBegin = 0;//Lewis@20160817: Enlarge RX Vref range for eye scan
+ #endif
+
+ u2VrefEnd =RX_VREF_RANGE_END;
+ u2VrefStep=RX_VREF_RANGE_STEP;
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_VREF_EN_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_VREF_EN_B1);
+ }
+ else //LPDDR3 or diable RX Vref
+ {
+ u2VrefBegin = 0;
+ u2VrefEnd = 0; // SEL[4:0] = 01110
+ u2VrefStep =1; //don't care, just make for loop break;
+ }
+
+ #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==1 && (p->Bypass_RDDQC || p->Bypass_RXWINDOW))
+ {
+ if(u1VrefScanEnable)
+ {
+ // load RX Vref from eMMC
+ #if ( SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_VREF_CAL)
+ //u2VrefBegin = p->pSavetimeData->u1RxWinPerbitVref_Save[p->channel];
+ //u2VrefEnd=u2VrefBegin+1;
+ u2FinalVref = p->pSavetimeData->u1RxWinPerbitVref_Save[p->channel];
+ #endif
+ }
+
+ // load RX DQS and DQM delay from eMMC
+ for (u1ByteIdx=0; u1ByteIdx<DQS_NUMBER_LP4; u1ByteIdx++)
+ {
+ iDQSDlyPerbyte[u1ByteIdx]= p->pSavetimeData->u1RxWinPerbit_DQS[p->channel][p->rank][u1ByteIdx];
+ iDQMDlyPerbyte[u1ByteIdx]= p->pSavetimeData->u1RxWinPerbit_DQM[p->channel][p->rank][u1ByteIdx];
+ }
+
+ // load RX DQ delay from eMMC
+ for (u1BitIdx=0; u1BitIdx<16; u1BitIdx++)
+ {
+ FinalWinPerBit[u1BitIdx].best_dqdly= p->pSavetimeData->u1RxWinPerbit_DQ[p->channel][p->rank][u1BitIdx];
+ }
+
+ if(u1UseTestEngine)
+ vSetCalibrationResult(p, DRAM_CALIBRATION_RX_PERBIT, DRAM_OK);
+ else
+ vSetCalibrationResult(p, DRAM_CALIBRATION_RX_RDDQC, DRAM_OK);
+ }
+ else
+ #endif
+ {
+ if(u1IsLP4Family(p->dram_type))
+ {
+ #if RX_DELAY_PRE_CAL
+ if(u1UseTestEngine==0)
+ #endif
+ {
+ if(p->frequency >=1600)
+ {
+ u4DelayBegin= -26;
+ }
+ else if(p->frequency >= 1140)
+ {
+ u4DelayBegin= -30;
+ }
+ else if(p->frequency >=800)
+ {
+ u4DelayBegin= -48;
+ }
+ else
+ {
+ u4DelayBegin= -MAX_RX_DQSDLY_TAPS;
+ }
+
+ s2RxDelayPreCal =PASS_RANGE_NA;
+ }
+ #if RX_DELAY_PRE_CAL
+ else
+ {
+ u4DelayBegin = s2RxDelayPreCal -10; // for test engine
+ }
+ #endif
+
+ //mcSHOW_DBG_MSG(("RX_DELAY_PRE_CAL: RX delay begin = %d\n", u4DelayBegin));
+
+ u4DelayEnd = MAX_RX_DQDLY_TAPS;
+
+ if(p->frequency <850)
+ u4DelayStep =2; //1600
+ else
+ u4DelayStep =1;//2667, 3200
+
+ if(u1UseTestEngine==0) //if RDDQD, roughly calibration
+ u4DelayStep <<= 1;
+ }
+ #if ENABLE_LP3_SW
+ else
+ {
+ if(p->frequency >=933)
+ {
+ u4DelayBegin= -48;
+ }
+ else if(p->frequency >=600)
+ {
+ u4DelayBegin= -70;
+ }
+ else if(p->frequency >=450)
+ {
+ u4DelayBegin= -110;
+ }
+ else
+ {
+ u4DelayBegin= -MAX_RX_DQSDLY_TAPS;
+ }
+ u4DelayEnd = MAX_RX_DQDLY_TAPS;
+
+ if(p->frequency <600)
+ u4DelayStep =2; //1066
+ else
+ u4DelayStep =1;//1600, 1270
+ }
+ #endif
+
+ u4DutyOffsetBegin = 0;
+ u4DutyOffsetEnd = 0;
+ u4DutyOffsetStep = 1;
+
+ #if !REDUCE_LOG_FOR_PRELOADER
+ mcSHOW_DBG_MSG(("\nRX DQS R/F Scan, iDutyOffset= %d\n", iDutyOffset));
+ mcFPRINTF((fp_A60501, "\nRX DQS R/F Scan, iDutyOffset= %d\n", iDutyOffset));
+ #endif
+
+ for(u2VrefLevel = u2VrefBegin; u2VrefLevel <= u2VrefEnd; u2VrefLevel += u2VrefStep)
+ {
+ if(u1VrefScanEnable ==1)
+ {
+ #if !REDUCE_LOG_FOR_PRELOADER
+ mcSHOW_DBG_MSG(("\n\tRX VrefLevel=%d\n", u2VrefLevel));
+ mcFPRINTF((fp_A60501, "\n\tRX VrefLevel=%d\n", u2VrefLevel));
+ #endif
+#if 0
+ #if VENDER_JV_LOG
+ if(u1UseTestEngine ==1)
+ mcSHOW_DBG_MSG5(("\n\tRX VrefLevel=%d\n", u2VrefLevel));
+ #endif
+#endif
+
+ //Set RX Vref Here
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ5), u2VrefLevel, SHU1_B0_DQ5_RG_RX_ARDQ_VREF_SEL_B0); // LP4 and LP4x with term: 0xe
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ5), u2VrefLevel, SHU1_B1_DQ5_RG_RX_ARDQ_VREF_SEL_B1); // LP4 and LP4x with term: 0xe
+ }
+
+ // 1.delay DQ ,find the pass widnow (left boundary).
+ // 2.delay DQS find the pass window (right boundary).
+ // 3.Find the best DQ / DQS to satify the middle value of the overall pass window per bit
+ // 4.Set DQS delay to the max per byte, delay DQ to de-skew
+
+ for (iDutyOffset=u4DutyOffsetBegin; iDutyOffset<=u4DutyOffsetEnd; iDutyOffset+=u4DutyOffsetStep)
+ {
+ // initialize parameters
+ u2TempWinSum =0;
+ uiFinishCount =0;
+
+ for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+ {
+ WinPerBit[u1BitIdx].first_pass = (S16)PASS_RANGE_NA;
+ WinPerBit[u1BitIdx].last_pass = (S16)PASS_RANGE_NA;
+ FinalWinPerBit[u1BitIdx].first_pass = (S16)PASS_RANGE_NA;
+ FinalWinPerBit[u1BitIdx].last_pass = (S16)PASS_RANGE_NA;
+
+ #if EYESCAN_LOG
+ if (u1IsLP4Family(p->dram_type))
+ {
+ gEyeScan_CaliDelay[u1BitIdx/8] = 0;
+ gEyeScan_DelayCellPI[u1BitIdx] = 0;
+ EyeScan_index[u1BitIdx] = 0;
+ u1pass_in_this_vref_flag[u1BitIdx] = 0;
+ }
+ #endif
+ }
+
+ // Adjust DQM output delay to 0
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6), \
+ P_Fld(0, SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_R_DLY_B0) |P_Fld(0, SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_F_DLY_B0));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ6), \
+ P_Fld(0,SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_R_DLY_B1) |P_Fld(0, SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_F_DLY_B1));
+ }
+ #if ENABLE_LP3_SW
+ else
+ {
+ for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+ {
+ Set_RX_DQM_DelayLine_Phy_Byte(p, u1ByteIdx, 0);
+ }
+ }
+ #endif
+
+ // Adjust DQ output delay to 0
+ //every 2bit dq have the same delay register address
+ if(u1IsLP4Family(p->dram_type))
+ {
+ for (ii=0; ii<4; ii++)
+ {
+ vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2+ ii*4), 0);//DQ0~DQ7
+ vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2+ ii*4), 0);//DQ8~DQ15
+ }
+ }
+ #if ENABLE_LP3_SW
+ else//LPDDR3
+ {
+ for (u1ByteIdx=0; u1ByteIdx<DQS_NUMBER; u1ByteIdx++)
+ {
+ Set_RX_DQ_DelayLine_Phy_Byte(p, u1ByteIdx, dl_value);
+ }
+ }
+ #endif
+
+ for (iDelay=u4DelayBegin; iDelay<=u4DelayEnd; iDelay+= u4DelayStep)
+ {
+ SetRxDqDqsDelay(p, iDelay);
+
+ if(u1UseTestEngine)
+ {
+ u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, p->test_pattern);
+ }
+ else
+ {
+ u4err_value = DramcRxWinRDDQCRun(p);
+ }
+
+ if((u1VrefScanEnable==0) || u1RXEyeScanEnable)
+ {
+ #ifdef ETT_PRINT_FORMAT
+ if(u4err_value !=0)
+ {
+ mcSHOW_DBG_MSG2(("%d, [0]", iDelay));
+ }
+ #else
+ mcSHOW_DBG_MSG2(("iDelay= %4d, [0]", iDelay));
+ #endif
+ mcFPRINTF((fp_A60501, "iDelay= %4d, [0]", iDelay));
+ //mcSHOW_DBG_MSG2(("u4err_value %x, u1MRRValue %x\n", u4err_value, u1MRRValue));
+ //mcFPRINTF((fp_A60501, "u4err_value!! %x", u4err_value));
+ }
+
+ // check fail bit ,0 ok ,others fail
+ for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+ {
+ u4fail_bit = u4err_value&((U32)1<<u1BitIdx);
+
+ if(WinPerBit[u1BitIdx].first_pass== PASS_RANGE_NA)
+ {
+ if(u4fail_bit==0) //compare correct: pass
+ {
+ WinPerBit[u1BitIdx].first_pass = iDelay;
+
+ #if RX_DELAY_PRE_CAL
+ if(u1UseTestEngine==0 && (s2RxDelayPreCal ==PASS_RANGE_NA))
+ {
+ s2RxDelayPreCal = iDelay;
+ }
+
+ if(u1UseTestEngine==1 && iDelay==u4DelayBegin)
+ {
+ mcSHOW_ERR_MSG(("RX_DELAY_PRE_CAL: Warning, possible miss RX window boundary\n"));
+ #if __ETT__
+ while(1);
+ #endif
+ }
+
+ #endif
+
+ #if EYESCAN_LOG
+ if (u1IsLP4Family(p->dram_type))
+ {
+ u1pass_in_this_vref_flag[u1BitIdx]=1;
+ }
+ #endif
+ }
+ }
+ else if(WinPerBit[u1BitIdx].last_pass == PASS_RANGE_NA)
+ {
+ //mcSHOW_DBG_MSG(("fb%d \n", u4fail_bit));
+
+ if(u4fail_bit !=0) //compare error : fail
+ {
+ WinPerBit[u1BitIdx].last_pass = (iDelay-1);
+ }
+ else if (iDelay==u4DelayEnd)
+ {
+ WinPerBit[u1BitIdx].last_pass = iDelay;
+ }
+
+ if(WinPerBit[u1BitIdx].last_pass !=PASS_RANGE_NA)
+ {
+ if((WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass) >= (FinalWinPerBit[u1BitIdx].last_pass -FinalWinPerBit[u1BitIdx].first_pass))
+ {
+ #if 0 //for debug
+ if(FinalWinPerBit[u1BitIdx].last_pass != PASS_RANGE_NA)
+ {
+ mcSHOW_DBG_MSG2(("Bit[%d] Bigger window update %d > %d\n", u1BitIdx, \
+ (WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass), (FinalWinPerBit[u1BitIdx].last_pass -FinalWinPerBit[u1BitIdx].first_pass)));
+ mcFPRINTF((fp_A60501,"Bit[%d] Bigger window update %d > %d\n", u1BitIdx, \
+ (WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass), (FinalWinPerBit[u1BitIdx].last_pass -FinalWinPerBit[u1BitIdx].first_pass)));
+ }
+ #endif
+
+ //if window size bigger than 7, consider as real pass window. If not, don't update finish counte and won't do early break;
+ if((WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass) >7)
+ uiFinishCount |= (1<<u1BitIdx);
+
+ //update bigger window size
+ FinalWinPerBit[u1BitIdx].first_pass = WinPerBit[u1BitIdx].first_pass;
+ FinalWinPerBit[u1BitIdx].last_pass = WinPerBit[u1BitIdx].last_pass;
+ }
+
+ #if EYESCAN_LOG
+ if(u1UseTestEngine && u1IsLP4Family(p->dram_type))
+ {
+ if (EyeScan_index[u1BitIdx] < EYESCAN_BROKEN_NUM)
+ {
+ gEyeScan_Min[u2VrefLevel][u1BitIdx][EyeScan_index[u1BitIdx]] = WinPerBit[u1BitIdx].first_pass;
+ gEyeScan_Max[u2VrefLevel][u1BitIdx][EyeScan_index[u1BitIdx]] = WinPerBit[u1BitIdx].last_pass;
+ mcSHOW_DBG_MSG3(("u2VrefLevel=%d, u1BitIdx=%d, index=%d (%d, %d)==\n",u2VrefLevel, u1BitIdx, EyeScan_index[u1BitIdx], gEyeScan_Min[u2VrefLevel][u1BitIdx][EyeScan_index[u1BitIdx]], gEyeScan_Max[u2VrefLevel][u1BitIdx][EyeScan_index[u1BitIdx]]));
+ EyeScan_index[u1BitIdx]=EyeScan_index[u1BitIdx]+1;
+ }
+ }
+ #endif
+
+ //reset tmp window
+ WinPerBit[u1BitIdx].first_pass = PASS_RANGE_NA;
+ WinPerBit[u1BitIdx].last_pass = PASS_RANGE_NA;
+ }
+ }
+
+ if((u1VrefScanEnable==0) || u1RXEyeScanEnable)
+ {
+ #ifdef ETT_PRINT_FORMAT
+ if(u4err_value !=0)
+ #endif
+ {
+ if(u1BitIdx%DQS_BIT_NUMBER ==0)
+ {
+ mcSHOW_DBG_MSG2((" "));
+ mcFPRINTF((fp_A60501, " "));
+ }
+
+ if (u4fail_bit == 0)
+ {
+ mcSHOW_DBG_MSG2(("o"));
+ mcFPRINTF((fp_A60501, "o"));
+ #if EYESCAN_LOG
+ if (u1IsLP4Family(p->dram_type))
+ {
+ gEyeScan_TotalPassCount[u1BitIdx]+=u4DelayStep;
+ }
+ #endif
+ }
+ else
+ {
+ mcSHOW_DBG_MSG2(("x"));
+ mcFPRINTF((fp_A60501, "x"));
+ }
+ }
+#if EYESCAN_LOG
+ #ifdef ETT_PRINT_FORMAT
+ else
+ #endif
+ {
+ if (u1IsLP4Family(p->dram_type))
+ {
+ gEyeScan_TotalPassCount[u1BitIdx]+=u4DelayStep;
+ }
+ }
+#endif
+ }
+ }
+
+ if((u1VrefScanEnable==0) || u1RXEyeScanEnable)
+ {
+ #ifdef ETT_PRINT_FORMAT
+ if(u4err_value !=0)
+ #endif
+ {
+ mcSHOW_DBG_MSG2((" [MSB]\n"));
+ mcFPRINTF((fp_A60501, " [MSB]\n"));
+ }
+ }
+
+ //if all bits widnow found and all bits turns to fail again, early break;
+ if((u1IsLP4Family(p->dram_type) &&(uiFinishCount == 0xffff)) || \
+ ((p->dram_type == TYPE_LPDDR3) &&(uiFinishCount == 0xffffffff)))
+ {
+ if(u1UseTestEngine)
+ vSetCalibrationResult(p, DRAM_CALIBRATION_RX_PERBIT, DRAM_OK);
+ else
+ vSetCalibrationResult(p, DRAM_CALIBRATION_RX_RDDQC, DRAM_OK);
+
+ if((u1VrefScanEnable==0) || u1RXEyeScanEnable)
+ {
+ if((u1IsLP4Family(p->dram_type) &&((u4err_value&0xffff) == 0xffff)) ||
+ ((p->dram_type == TYPE_LPDDR3) &&(u4err_value == 0xffffffff)))
+ {
+ #if !REDUCE_LOG_FOR_PRELOADER
+ mcSHOW_DBG_MSG(("\nRX all bits window found, early break!\n"));
+ #endif
+ break; //early break
+ }
+ }
+ }
+ }
+
+ for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+ {
+ FinalWinPerBit[u1BitIdx].win_size = FinalWinPerBit[u1BitIdx].last_pass - FinalWinPerBit[u1BitIdx].first_pass + (FinalWinPerBit[u1BitIdx].last_pass==FinalWinPerBit[u1BitIdx].first_pass?0:1);
+
+ #if (PINMUX_AUTO_TEST_PER_BIT_RX | PINMUX_AUTO_TEST_PER_BIT_RX_LP3)
+ gFinalRXPerbitWinSiz[p->channel][u1BitIdx] = FinalWinPerBit[u1BitIdx].win_size;
+ #endif
+
+ u2TempWinSum += FinalWinPerBit[u1BitIdx].win_size; //Sum of CA Windows for vref selection
+
+#if 0 //BU don't want customer knows our RX's ability
+ #if VENDER_JV_LOG
+ if(u1UseTestEngine ==1)
+ {
+ U8 shuffleIdx;
+ shuffleIdx = get_shuffleIndex_by_Freq(p);
+ mcSHOW_DBG_MSG5(("RX Bit%d, %d%%\n", u1BitIdx, ((FinalWinPerBit[u1BitIdx].win_size*u2gdelay_cell_ps_all[shuffleIdx][0]*p->frequency*2)+(1000000-1))/1000000));
+ }
+ #endif
+#endif
+#if EYESCAN_LOG
+ if (u1IsLP4Family(p->dram_type))
+ {
+ gEyeScan_WinSize[u2VrefLevel][u1BitIdx] = FinalWinPerBit[u1BitIdx].win_size;
+ }
+#endif
+ }
+
+ #if 1//!REDUCE_LOG_FOR_PRELOADER
+ mcSHOW_DBG_MSG2(("RX Vref %d, Window Sum %d\n", u2VrefLevel, u2TempWinSum));
+ mcFPRINTF((fp_A60501, "RX Vref %d, Window Sum %d\n", u2VrefLevel, u2TempWinSum));
+ #endif
+
+ #if 0
+ if((u1IsLP4Family(p->dram_type) &&(u2TempWinSum <250)) || \
+ ((p->dram_type == TYPE_LPDDR3) &&(u2TempWinSum <1100)))
+ {
+ mcSHOW_DBG_MSG2(("\n\n[NOTICE] CH %d, TestEngine %d, RX_sum %d\n", p->channel, u1UseTestEngine, u2TempWinSum));
+ mcFPRINTF((fp_A60501, "\n\n[NOTICE] CH %d, TestEngine %d, RX_sum %d\n", p->channel, u1UseTestEngine, u2TempWinSum));
+ }
+ #endif
+
+ if(u2TempWinSum >u2rx_window_sum)
+ {
+ mcSHOW_DBG_MSG3(("\nBetter RX Vref found %d, Window Sum %d > %d\n", u2VrefLevel, u2TempWinSum, u2rx_window_sum));
+ mcFPRINTF((fp_A60501, "\nBetter RX Vref found %d, Window Sum %d > %d\n", u2VrefLevel, u2TempWinSum, u2rx_window_sum));
+
+ u2rx_window_sum =u2TempWinSum;
+ u2FinalVref = u2VrefLevel;
+
+ for (u1BitIdx=0; u1BitIdx<p->data_width; u1BitIdx++)
+ {
+ FinalWinPerBit[u1BitIdx].win_center = (FinalWinPerBit[u1BitIdx].last_pass + FinalWinPerBit[u1BitIdx].first_pass)>>1; // window center of each DQ bit
+
+ if((u1VrefScanEnable==0) || u1RXEyeScanEnable)
+ {
+ #ifdef ETT_PRINT_FORMAT
+ mcSHOW_DBG_MSG(("iDelay=%d, Bit %d, Center %d (%d ~ %d) %d\n", iDelay, u1BitIdx, FinalWinPerBit[u1BitIdx].win_center, FinalWinPerBit[u1BitIdx].first_pass, FinalWinPerBit[u1BitIdx].last_pass, FinalWinPerBit[u1BitIdx].win_size));
+ #else
+ mcSHOW_DBG_MSG(("iDelay=%d, Bit %2d, Center %3d (%4d ~ %4d) %d\n", iDelay, u1BitIdx, FinalWinPerBit[u1BitIdx].win_center, FinalWinPerBit[u1BitIdx].first_pass, FinalWinPerBit[u1BitIdx].last_pass, FinalWinPerBit[u1BitIdx].win_size));
+ #endif
+ mcFPRINTF((fp_A60501, "iDelay=%d, Bit %2d, Center %3d (%4d ~ %4d)\n", iDelay, u1BitIdx, FinalWinPerBit[u1BitIdx].win_center, FinalWinPerBit[u1BitIdx].first_pass, FinalWinPerBit[u1BitIdx].last_pass, FinalWinPerBit[u1BitIdx].win_size));
+ }
+
+#ifdef FOR_HQA_TEST_USED
+ if(u1UseTestEngine ==1)
+ {
+ gFinalRXPerbitWin[p->channel][p->rank][u1BitIdx] = FinalWinPerBit[u1BitIdx].win_size;
+ }
+#endif
+ }
+ }
+ }
+
+#if EYESCAN_LOG
+ if (u1IsLP4Family(p->dram_type))
+ {
+ for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+ {
+ if (u1pass_in_this_vref_flag[u1BitIdx]) gEyeScan_ContinueVrefHeight[u1BitIdx]++; //count pass number of continue vref
+ }
+ }
+#endif
+
+ if((u2TempWinSum < (u2rx_window_sum*95/100)) && gRX_EYE_Scan_flag == 0)
+ {
+ mcSHOW_DBG_MSG(("\nRX Vref found, early break!\n"));
+ u2VrefLevel = u2VrefEnd;
+ break;//max vref found, early break;
+ }
+ }
+
+ if(u1UseTestEngine)
+ {
+ DramcEngine2End(p);
+ }
+ else
+ {
+ DramcRxWinRDDQCEnd(p);
+ }
+
+ // 3
+ //As per byte, check max DQS delay in 8-bit. Except for the bit of max DQS delay, delay DQ to fulfill setup time = hold time
+ for (u1ByteIdx = 0; u1ByteIdx < (p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+ {
+ u2TmpDQMSum =0;
+
+ ucbit_first =DQS_BIT_NUMBER*u1ByteIdx;
+ ucbit_last = DQS_BIT_NUMBER*u1ByteIdx+DQS_BIT_NUMBER-1;
+ iDQSDlyPerbyte[u1ByteIdx] = MAX_RX_DQSDLY_TAPS;
+
+ for (u1BitIdx = ucbit_first; u1BitIdx <= ucbit_last; u1BitIdx++)
+ {
+ // find out max Center value
+ if(FinalWinPerBit[u1BitIdx].win_center < iDQSDlyPerbyte[u1ByteIdx])
+ {
+ iDQSDlyPerbyte[u1ByteIdx] = FinalWinPerBit[u1BitIdx].win_center;
+ }
+
+ //mcSHOW_DBG_MSG(("bit#%2d : center=(%2d)\n", u1BitIdx, FinalWinPerBit[u1BitIdx].win_center));
+ //mcFPRINTF((fp_A60501, "bit#%2d : center=(%2d)\n", u1BitIdx, FinalWinPerBit[u1BitIdx].win_center));
+ }
+
+ //mcSHOW_DBG_MSG(("----seperate line----\n"));
+ //mcFPRINTF((fp_A60501, "----seperate line----\n"));
+
+ if (iDQSDlyPerbyte[u1ByteIdx] > 0) // Delay DQS=0, Delay DQ only
+ {
+ iDQSDlyPerbyte[u1ByteIdx] = 0;
+ }
+ else //Need to delay DQS
+ {
+ iDQSDlyPerbyte[u1ByteIdx] = -iDQSDlyPerbyte[u1ByteIdx] ;
+ }
+
+ // we delay DQ or DQS to let DQS sample the middle of rx pass window for all the 8 bits,
+ for (u1BitIdx = ucbit_first; u1BitIdx <= ucbit_last; u1BitIdx++)
+ {
+ FinalWinPerBit[u1BitIdx].best_dqdly = iDQSDlyPerbyte[u1ByteIdx] + FinalWinPerBit[u1BitIdx].win_center;
+ u2TmpDQMSum += FinalWinPerBit[u1BitIdx].best_dqdly;
+#if EYESCAN_LOG
+ if (u1IsLP4Family(p->dram_type))
+ {
+ gEyeScan_DelayCellPI[u1BitIdx] = FinalWinPerBit[u1BitIdx].best_dqdly;
+ }
+#endif
+ }
+
+ // calculate DQM as average of 8 DQ delay
+ iDQMDlyPerbyte[u1ByteIdx] = u2TmpDQMSum/DQS_BIT_NUMBER;
+
+#ifdef FOR_HQA_REPORT_USED
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0, "RX_Window_Center_DQS", u1ByteIdx, iDQSDlyPerbyte[u1ByteIdx], NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0, "RX_Window_Center_DQM", u1ByteIdx, iDQMDlyPerbyte[u1ByteIdx], NULL);
+ for (u1BitIdx = ucbit_first; u1BitIdx <= ucbit_last; u1BitIdx++)
+ {
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT1, "RX_Window_Center_DQ", u1BitIdx, FinalWinPerBit[u1BitIdx].win_center, NULL);
+ }
+#endif
+ }
+ }
+
+#ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+ gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag = u1GUMP_INIT_RG_LOG_TO_DE_bak;
+#endif
+
+ //Set RX Final Vref Here
+ if(u1VrefScanEnable==1)
+ {
+#ifdef DEVIATION
+ if (p->frequency == u2DFSGetHighestFreq(p) && gSetSpecificedVref_Enable[1]==ENABLE && ((p->channel==gSetSpecificedVref_Channel[1]) || gSetSpecificedVref_All_ChRk[1]==ENABLE))
+ {
+ DeviationAddVrefOffset(1, NULL, &u2FinalVref, gSetSpecificedVref_Vref_Offset[1]);
+ }
+#endif
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ5), u2FinalVref, SHU1_B0_DQ5_RG_RX_ARDQ_VREF_SEL_B0); // LP4 and LP4x with term: 0xe
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ5), u2FinalVref, SHU1_B1_DQ5_RG_RX_ARDQ_VREF_SEL_B1); // LP4 and LP4x with term: 0xe
+
+ mcSHOW_DBG_MSG(("\nFinal RX Vref %d, apply to both rank0 and 1\n", u2FinalVref));
+ mcFPRINTF((fp_A60501, "\nFinal RX Vref %d, apply to both rank0 and 1\n", u2FinalVref));
+#if 0 //BU don't want customer knows our RX's ability
+#if VENDER_JV_LOG
+ mcSHOW_DBG_MSG5(("\nFinal RX Vref %d, apply to both rank0 and 1\n", u2FinalVref));
+#endif
+#endif
+
+ #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==0)
+ {
+ p->pSavetimeData->u1RxWinPerbitVref_Save[p->channel]=u2FinalVref;
+ }
+ #endif
+
+ // When only calibrate RX Vref for Rank 0, apply the same value for Rank 1.
+ gFinalRXVrefDQ[p->channel][p->rank] = (U8) u2FinalVref;
+ }
+
+ #if REG_SHUFFLE_REG_CHECK
+ ShuffleRegCheck =1;
+ #endif
+
+ gu2RX_DQS_Duty_Offset[0][0]=gu2RX_DQS_Duty_Offset[0][1]=gu2RX_DQS_Duty_Offset[1][0]=gu2RX_DQS_Duty_Offset[1][1] = 0;
+
+ // set dqs delay, (dqm delay)
+ for (u1ByteIdx = 0; u1ByteIdx < (p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+ {
+ // Set DQS & DQM delay
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6+ u4AddrOfst*u1ByteIdx), \
+ P_Fld(((U32)iDQSDlyPerbyte[u1ByteIdx]+gu2RX_DQS_Duty_Offset[u1ByteIdx][0]),SHU1_R0_B0_DQ6_RK0_RX_ARDQS0_R_DLY_B0) |P_Fld(((U32)iDQSDlyPerbyte[u1ByteIdx]+gu2RX_DQS_Duty_Offset[u1ByteIdx][1]),SHU1_R0_B0_DQ6_RK0_RX_ARDQS0_F_DLY_B0) |
+ P_Fld(((U32)iDQMDlyPerbyte[u1ByteIdx]),SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_R_DLY_B0) |P_Fld(((U32)iDQMDlyPerbyte[u1ByteIdx]),SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_F_DLY_B0));
+
+ #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==0)
+ {
+ p->pSavetimeData->u1RxWinPerbit_DQS[p->channel][p->rank][u1ByteIdx]=(U32)iDQSDlyPerbyte[u1ByteIdx];
+ p->pSavetimeData->u1RxWinPerbit_DQM[p->channel][p->rank][u1ByteIdx]=(U32)iDQMDlyPerbyte[u1ByteIdx];
+ }
+ #endif
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ /* p->rank = RANK_0, save to Reg Rank0 and Rank1, p->rank = RANK_1, save to Reg Rank1 */
+ for(ii=p->rank; ii<RANK_MAX; ii++)
+ {
+ vSetRank(p,ii);
+ vIO32WriteFldAlign_Phy_Byte(u1ByteIdx, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6), (U32)iDQSDlyPerbyte[u1ByteIdx], SHU1_R0_B0_DQ6_RK0_RX_ARDQS0_R_DLY_B0);
+ vIO32WriteFldAlign_Phy_Byte(u1ByteIdx, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6), (U32)iDQSDlyPerbyte[u1ByteIdx], SHU1_R0_B0_DQ6_RK0_RX_ARDQS0_F_DLY_B0);
+ Set_RX_DQM_DelayLine_Phy_Byte(p, u1ByteIdx,(U32)iDQMDlyPerbyte[u1ByteIdx]);
+ }
+ vSetRank(p, backup_rank);
+ }
+#endif
+ }
+
+ #if REG_SHUFFLE_REG_CHECK
+ ShuffleRegCheck =0;
+ #endif
+
+ #if REG_SHUFFLE_REG_CHECK
+ ShuffleRegCheck =1;
+ #endif
+
+ // set dq delay
+ if(u1IsLP4Family(p->dram_type))
+ {
+ for (u1BitIdx=0; u1BitIdx<DQS_BIT_NUMBER; u1BitIdx+=2)
+ {
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2+u1BitIdx*2), \
+ P_Fld(((U32)FinalWinPerBit[u1BitIdx].best_dqdly),SHU1_R0_B0_DQ2_RK0_RX_ARDQ0_R_DLY_B0) |\
+ P_Fld(((U32)FinalWinPerBit[u1BitIdx].best_dqdly),SHU1_R0_B0_DQ2_RK0_RX_ARDQ0_F_DLY_B0)| \
+ P_Fld(((U32)FinalWinPerBit[u1BitIdx+1].best_dqdly),SHU1_R0_B0_DQ2_RK0_RX_ARDQ1_R_DLY_B0) |\
+ P_Fld(((U32)FinalWinPerBit[u1BitIdx+1].best_dqdly),SHU1_R0_B0_DQ2_RK0_RX_ARDQ1_F_DLY_B0));
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2+u1BitIdx*2), \
+ P_Fld(((U32)FinalWinPerBit[u1BitIdx+8].best_dqdly),SHU1_R0_B1_DQ2_RK0_RX_ARDQ0_R_DLY_B1) | \
+ P_Fld((U32)FinalWinPerBit[u1BitIdx+8].best_dqdly,SHU1_R0_B1_DQ2_RK0_RX_ARDQ0_F_DLY_B1)| \
+ P_Fld(((U32)FinalWinPerBit[u1BitIdx+9].best_dqdly),SHU1_R0_B1_DQ2_RK0_RX_ARDQ1_R_DLY_B1) |\
+ P_Fld((U32)FinalWinPerBit[u1BitIdx+9].best_dqdly,SHU1_R0_B1_DQ2_RK0_RX_ARDQ1_F_DLY_B1));
+
+ /*mcSHOW_DBG_MSG(("u1BitId %d Addr 0x%2x = %2d %2d %2d %2d \n", u1BitIdx, DRAMC_REG_ADDR(DDRPHY_RXDQ1+u1BitIdx*2), \
+ * FinalWinPerBit[u1BitIdx].best_dqdly, FinalWinPerBit[u1BitIdx+1].best_dqdly, FinalWinPerBit[u1BitIdx+8].best_dqdly, FinalWinPerBit[u1BitIdx+9].best_dqdly));
+ */
+ }
+
+ #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==0)
+ {
+ for (u1BitIdx=0; u1BitIdx<16; u1BitIdx++)
+ {
+ p->pSavetimeData->u1RxWinPerbit_DQ[p->channel][p->rank][u1BitIdx]=(U32)FinalWinPerBit[u1BitIdx].best_dqdly;
+
+ }
+ }
+ #endif
+ }
+#if ENABLE_LP3_SW
+ else //LPDDR3
+ {
+ /* p->rank = RANK_0, save to Reg Rank0 and Rank1, p->rank = RANK_1, save to Reg Rank1 */
+ for(ii=p->rank; ii<RANK_MAX; ii++)
+ {
+ vSetRank(p,ii);
+
+ //every 2bit dq have the same delay register address
+ for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+ {
+ u1BitIdx = u1ByteIdx *DQS_BIT_NUMBER;
+
+ dl_value[0] = FinalWinPerBit[u1BitIdx].best_dqdly;
+ dl_value[1] = FinalWinPerBit[u1BitIdx+1].best_dqdly;
+ dl_value[2] = FinalWinPerBit[u1BitIdx+2].best_dqdly;
+ dl_value[3] = FinalWinPerBit[u1BitIdx+3].best_dqdly;
+ dl_value[4] = FinalWinPerBit[u1BitIdx+4].best_dqdly;
+ dl_value[5] = FinalWinPerBit[u1BitIdx+5].best_dqdly;
+ dl_value[6] = FinalWinPerBit[u1BitIdx+6].best_dqdly;
+ dl_value[7] = FinalWinPerBit[u1BitIdx+7].best_dqdly;
+ Set_RX_DQ_DelayLine_Phy_Byte(p, u1ByteIdx, dl_value);
+ }
+ }
+ vSetRank(p, backup_rank);
+ }
+#endif
+
+ DramPhyReset(p);
+
+ vPrintCalibrationBasicInfo(p);
+
+#ifdef ETT_PRINT_FORMAT
+ if(u1IsLP4Family(p->dram_type))
+ {
+ mcSHOW_DBG_MSG(("DQS Delay:\nDQS0 = %d, DQS1 = %d\n"
+ "DQM Delay:\nDQM0 = %d, DQM1 = %d\n",
+ iDQSDlyPerbyte[0], iDQSDlyPerbyte[1],
+ iDQMDlyPerbyte[0], iDQMDlyPerbyte[1]));
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ mcSHOW_DBG_MSG(("DQS Delay:\nDQS0 = %d, DQS1 = %d, DQS2 = %d, DQS3 = %d\n"
+ "DQM Delay:\nDQM0 = %d, DQM1 = %d, DQM2 = %d, DQM3 = %d\n",
+ iDQSDlyPerbyte[0], iDQSDlyPerbyte[1], iDQSDlyPerbyte[2], iDQSDlyPerbyte[3],
+ iDQMDlyPerbyte[0], iDQMDlyPerbyte[1], iDQMDlyPerbyte[2], iDQMDlyPerbyte[3]));
+ }
+#endif /* ENABLE_LP3_SW */
+#else
+ if(u1IsLP4Family(p->dram_type))
+ {
+ mcSHOW_DBG_MSG(("DQS Delay:\nDQS0 = %2d, DQS1 = %2d\n"
+ "DQM Delay:\nDQM0 = %2d, DQM1 = %2d\n",
+ iDQSDlyPerbyte[0], iDQSDlyPerbyte[1],
+ iDQMDlyPerbyte[0], iDQMDlyPerbyte[1]));
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ mcSHOW_DBG_MSG(("DQS Delay:\nDQS0 = %2d, DQS1 = %2d, DQS2 = %2d, DQS3 = %2d\n"
+ "DQM Delay:\nDQM0 = %2d, DQM1 = %2d, DQM2 = %2d, DQM3 = %2d\n",
+ iDQSDlyPerbyte[0], iDQSDlyPerbyte[1], iDQSDlyPerbyte[2], iDQSDlyPerbyte[3],
+ iDQMDlyPerbyte[0], iDQMDlyPerbyte[1], iDQMDlyPerbyte[2], iDQMDlyPerbyte[3]));
+ }
+#endif /* ENABLE_LP3_SW */
+#endif
+ mcSHOW_DBG_MSG(("DQ Delay:\n"));
+
+ mcFPRINTF((fp_A60501, "\tdramc_rxdqs_perbit_swcal\n"));
+ mcFPRINTF((fp_A60501, "\tchannel=%d(1:cha) \n", p->channel));
+ mcFPRINTF((fp_A60501, "\tbus width=%d\n\n", p->data_width));
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ mcFPRINTF((fp_A60501, "DQS Delay:\n DQS0 = %2d DQS1 = %2d\n", iDQSDlyPerbyte[0], iDQSDlyPerbyte[1]));
+ mcFPRINTF((fp_A60501, "DQM Delay:\n DQM0 = %2d DQM1 = %2d\n", iDQMDlyPerbyte[0], iDQMDlyPerbyte[1]));
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ mcFPRINTF((fp_A60501, "DQS Delay:\n DQS0 = %2d DQS1 = %2d DQS2 = %2d DQS3 = %2d\n", iDQSDlyPerbyte[0], iDQSDlyPerbyte[1], iDQSDlyPerbyte[2], iDQSDlyPerbyte[3]));
+ mcFPRINTF((fp_A60501, "DQM Delay:\n DQM0 = %2d DQM1 = %2d DQM2 = %2d DQM3 = %2d\n", iDQMDlyPerbyte[0], iDQMDlyPerbyte[1], iDQMDlyPerbyte[2], iDQMDlyPerbyte[3]));
+ }
+#endif /* ENABLE_LP3_SW */
+ mcFPRINTF((fp_A60501, "DQ Delay:\n"));
+
+ for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx=u1BitIdx+4)
+ {
+ #ifdef ETT_PRINT_FORMAT
+ mcSHOW_DBG_MSG(("DQ%d =%d, DQ%d =%d, DQ%d =%d, DQ%d =%d\n", u1BitIdx, FinalWinPerBit[u1BitIdx].best_dqdly, u1BitIdx+1, FinalWinPerBit[u1BitIdx+1].best_dqdly, u1BitIdx+2, FinalWinPerBit[u1BitIdx+2].best_dqdly, u1BitIdx+3, FinalWinPerBit[u1BitIdx+3].best_dqdly));
+ #else
+ mcSHOW_DBG_MSG(("DQ%2d =%2d, DQ%2d =%2d, DQ%2d =%2d, DQ%2d =%2d\n", u1BitIdx, FinalWinPerBit[u1BitIdx].best_dqdly, u1BitIdx+1, FinalWinPerBit[u1BitIdx+1].best_dqdly, u1BitIdx+2, FinalWinPerBit[u1BitIdx+2].best_dqdly, u1BitIdx+3, FinalWinPerBit[u1BitIdx+3].best_dqdly));
+ #endif
+ mcFPRINTF((fp_A60501, "DQ%2d =%2d, DQ%2d =%2d, DQ%2d =%2d, DQ%2d=%2d\n", u1BitIdx, FinalWinPerBit[u1BitIdx].best_dqdly, u1BitIdx+1, FinalWinPerBit[u1BitIdx+1].best_dqdly, u1BitIdx+2, FinalWinPerBit[u1BitIdx+2].best_dqdly, u1BitIdx+3, FinalWinPerBit[u1BitIdx+3].best_dqdly));
+ }
+ mcSHOW_DBG_MSG(("\n\n"));
+ mcFPRINTF((fp_A60501, "\n\n"));
+
+ // BU request RX & TX window size log.
+#if 0//def RELEASE // for parsing tool
+ if(u1UseTestEngine==1)
+ {
+ mcSHOW_DBG_MSG4(("RX CH%d R%d ,Freq %d\n", p->channel, p->rank, p->frequency));
+ for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+ {
+ mcSHOW_DBG_MSG4(("%d: %d\n", u1BitIdx, gFinalRXPerbitWin[p->channel][p->rank][u1BitIdx]));
+ }
+ }
+#endif
+
+ #if REG_SHUFFLE_REG_CHECK
+ ShuffleRegCheck =0;
+ #endif
+ mcSHOW_DBG_MSG3(("[DramcRxWindowPerbitCal] Done\n"));
+ mcFPRINTF((fp_A60501, "[DramcRxWindowPerbitCal] Done\n"));
+
+#if REG_ACCESS_PORTING_DGB
+ RegLogEnable =0;
+#endif
+
+return DRAM_OK;
+
+ // Log example ==> Neec to update
+ /*
+------------------------------------------------------
+Start calculate dq time and dqs time /
+Find max DQS delay per byte / Adjust DQ delay to align DQS...
+------------------------------------------------------
+bit# 0 : dq time=11 dqs time= 8
+bit# 1 : dq time=11 dqs time= 8
+bit# 2 : dq time=11 dqs time= 6
+bit# 3 : dq time=10 dqs time= 8
+bit# 4 : dq time=11 dqs time= 8
+bit# 5 : dq time=10 dqs time= 8
+bit# 6 : dq time=11 dqs time= 8
+bit# 7 : dq time= 9 dqs time= 6
+----seperate line----
+bit# 8 : dq time=12 dqs time= 7
+bit# 9 : dq time=10 dqs time= 8
+bit#10 : dq time=11 dqs time= 8
+bit#11 : dq time=10 dqs time= 8
+bit#12 : dq time=11 dqs time= 8
+bit#13 : dq time=11 dqs time= 8
+bit#14 : dq time=11 dqs time= 8
+bit#15 : dq time=12 dqs time= 8
+----seperate line----
+bit#16 : dq time=11 dqs time= 7
+bit#17 : dq time=10 dqs time= 8
+bit#18 : dq time=11 dqs time= 7
+bit#19 : dq time=11 dqs time= 6
+bit#20 : dq time=10 dqs time= 9
+bit#21 : dq time=11 dqs time=10
+bit#22 : dq time=11 dqs time=10
+bit#23 : dq time= 9 dqs time= 9
+----seperate line----
+bit#24 : dq time=12 dqs time= 6
+bit#25 : dq time=13 dqs time= 6
+bit#26 : dq time=13 dqs time= 7
+bit#27 : dq time=11 dqs time= 7
+bit#28 : dq time=12 dqs time= 8
+bit#29 : dq time=10 dqs time= 8
+bit#30 : dq time=13 dqs time= 7
+bit#31 : dq time=11 dqs time= 8
+----seperate line----
+==================================================
+ dramc_rxdqs_perbit_swcal_v2
+ channel=2(2:cha, 3:chb) apply = 1
+==================================================
+DQS Delay :
+ DQS0 = 0 DQS1 = 0 DQS2 = 0 DQS3 = 0
+DQ Delay :
+DQ 0 = 1 DQ 1 = 1 DQ 2 = 2 DQ 3 = 1
+DQ 4 = 1 DQ 5 = 1 DQ 6 = 1 DQ 7 = 1
+DQ 8 = 2 DQ 9 = 1 DQ10 = 1 DQ11 = 1
+DQ12 = 1 DQ13 = 1 DQ14 = 1 DQ15 = 2
+DQ16 = 2 DQ17 = 1 DQ18 = 2 DQ19 = 2
+DQ20 = 0 DQ21 = 0 DQ22 = 0 DQ23 = 0
+DQ24 = 3 DQ25 = 3 DQ26 = 3 DQ27 = 2
+DQ28 = 2 DQ29 = 1 DQ30 = 3 DQ31 = 1
+_______________________________________________________________
+ */
+}
+#endif //SIMULATION_RX_PERBIT
+
+#if SIMULATION_DATLAT
+static void dle_factor_handler(DRAMC_CTX_T *p, U8 curr_val, U8 pip_num)
+{
+ U8 u1DATLAT_DSEL=0;
+ U8 u1DLECG_OptionEXT1 = 0;
+ U8 u1DLECG_OptionEXT2 = 0;
+ U8 u1DLECG_OptionEXT3 = 0;
+
+#if REG_ACCESS_PORTING_DGB
+ RegLogEnable =1;
+ mcSHOW_DBG_MSG(("\n[REG_ACCESS_PORTING_FUNC] dle_factor_handler\n"));
+ mcFPRINTF((fp_A60501, "\n[REG_ACCESS_PORTING_FUNC] dle_factor_handler\n"));
+#endif
+
+ #if REG_SHUFFLE_REG_CHECK
+ ShuffleRegCheck =1;
+ #endif
+
+ if(curr_val<2)
+ curr_val =2;
+
+#if RX_PIPE_BYPASS_EN
+ /* if rx pipe bypass en, then datlat will less 1 pipe. So DSEL minus 1, not minus 2 */
+ u1DATLAT_DSEL = curr_val - 1;
+#else
+ u1DATLAT_DSEL = curr_val - 2;
+#endif
+
+ // Datlat_dsel = datlat -1, only 1 TX pipe
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU_CONF1),
+ P_Fld(curr_val, SHU_CONF1_DATLAT) |
+ P_Fld(u1DATLAT_DSEL, SHU_CONF1_DATLAT_DSEL) |
+ P_Fld(u1DATLAT_DSEL, SHU_CONF1_DATLAT_DSEL_PHY));
+
+ //(>=8 & <14) set EXT1 =1, EXT2=0, EXT3=0
+ //(>= 14 & <19) set EXT1=1, EXT2=1, EXT3=0
+ //(>=19) set EXT1=1, EXT2=1, EXT3=1
+ u1DLECG_OptionEXT1 = (curr_val >= 8)? (1): (0);
+ u1DLECG_OptionEXT2 = (curr_val >= 14)? (1): (0);
+ u1DLECG_OptionEXT3 = (curr_val >= 19)? (1): (0);
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU_PIPE), P_Fld(u1DLECG_OptionEXT1, SHU_PIPE_READ_START_EXTEND1)
+ | P_Fld(u1DLECG_OptionEXT1, SHU_PIPE_DLE_LAST_EXTEND1)
+ | P_Fld((u1DLECG_OptionEXT2), SHU_PIPE_READ_START_EXTEND2)
+ | P_Fld((u1DLECG_OptionEXT2), SHU_PIPE_DLE_LAST_EXTEND2)
+ | P_Fld((u1DLECG_OptionEXT3), SHU_PIPE_READ_START_EXTEND3)
+ | P_Fld((u1DLECG_OptionEXT3), SHU_PIPE_DLE_LAST_EXTEND3));
+
+ #if REG_SHUFFLE_REG_CHECK
+ ShuffleRegCheck =0;
+ #endif
+
+ DramPhyReset(p);
+
+#if REG_ACCESS_PORTING_DGB
+ RegLogEnable =0;
+#endif
+}
+
+//-------------------------------------------------------------------------
+/** Dramc_ta2_rx_scan
+ */
+//-------------------------------------------------------------------------
+static U32 Dramc_ta2_rx_scan(DRAMC_CTX_T *p, U8 u1UseTestEngine)
+{
+ U32 ii, u4err_value;
+ S16 iDelay;
+#if ENABLE_LP3_SW
+ U8 u1ByteIdx;
+ U8 dl_value[8]={0,0,0,0,0,0,0,0};
+#endif
+
+ // reg backup
+#if 0
+ U32 u4RegBak_DDRPHY_RXDQ_RK0[DQS_NUMBER][5]; // rank 0
+ for (ii=0; ii<5; ii++)
+ {
+ if(u1IsLP4Family(p->dram_type))
+ {
+ u4RegBak_DDRPHY_RXDQ_RK0[0][ii] =(u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2+ii*4), PHY_FLD_FULL)); // rank 0, byte 0
+ u4RegBak_DDRPHY_RXDQ_RK0[1][ii] =(u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2+ii*4), PHY_FLD_FULL)); // rank 0, byte 1
+ }
+#if ENABLE_LP3_SW
+ else //LPDDR3 , only record rank 0, will not modify rank1
+ {
+#if 0 //LP3 no need to backup DQ delay line reg
+ for(u1ByteIdx=0; u1ByteIdx<4; u1ByteIdx++)
+ {
+ u4RegBak_DDRPHY_RXDQ_RK0[u1ByteIdx][ii] =u4IO32ReadFldAlign_Phy_Byte(u1ByteIdx, DRAMC_REG_ADDR(DDRPHY_SHU2_R0_B0_DQ2+ii*4), PHY_FLD_FULL);
+ }
+#endif
+ }
+#endif
+ }
+#endif
+
+ // Adjust DQM output delay to 0
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ6), \
+ P_Fld(0,SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_R_DLY_B0) |P_Fld(0, SHU1_R0_B0_DQ6_RK0_RX_ARDQM0_F_DLY_B0));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ6), \
+ P_Fld(0,SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_R_DLY_B1) |P_Fld(0, SHU1_R0_B1_DQ6_RK0_RX_ARDQM0_F_DLY_B1));
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ for(u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+ {
+ Set_RX_DQM_DelayLine_Phy_Byte(p, u1ByteIdx, 0);
+ }
+ }
+#endif
+
+ // Adjust DQ output delay to 0
+ //every 2bit dq have the same delay register address
+ if(u1IsLP4Family(p->dram_type))
+ {
+ for (ii=0; ii<4; ii++)
+ {
+ vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2+ii*4), 0); //DQ0~DQ7
+ vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2+ii*4), 0);//DQ8~DQ15
+ }
+ }
+#if ENABLE_LP3_SW
+ else //LPDDR3
+ {
+ for (u1ByteIdx=0; u1ByteIdx<DQS_NUMBER; u1ByteIdx++)
+ {
+ Set_RX_DQ_DelayLine_Phy_Byte(p, u1ByteIdx, dl_value);
+ }
+ }
+#endif
+
+ if(u1UseTestEngine)
+ DramcEngine2Init(p, p->test2_1, p->test2_2, p->test_pattern, 0);
+
+ // quick rx dqs search
+ //mcSHOW_DBG_MSG(("quick rx dqs search\n"));
+ //mcFPRINTF((fp_A60817, "quick rx dqs search\n", iDelay));
+ for (iDelay=-32; iDelay<=32; iDelay+=4)
+ {
+ //mcSHOW_DBG_MSG(("%2d, ", iDelay));
+ //mcFPRINTF((fp_A60817,"%2d, ", iDelay));
+ SetRxDqDqsDelay(p, iDelay);
+
+ if(u1UseTestEngine)
+ {
+ u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, p->test_pattern);
+ }
+ else
+ {
+ //sagy: no definition of DramcRxWinRDDQC, u4err_value = DramcRxWinRDDQC(p);
+ }
+
+ if(u4err_value ==0)// rx dqs found.
+ break;
+ }
+
+ if(u1UseTestEngine)
+ DramcEngine2End(p);
+
+ #ifdef ETT_PRINT_FORMAT
+ mcSHOW_DBG_MSG(("RX DQS dly = %d, ", iDelay));
+ #else
+ mcSHOW_DBG_MSG(("RX DQS dly = %2d, ", iDelay));
+ #endif
+ mcFPRINTF((fp_A60501, "RX DQS dly = %2d, ", iDelay));
+
+#if 0
+ // restore registers
+ for (ii=0; ii<5; ii++)
+ {
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ2+ ii*4), u4RegBak_DDRPHY_RXDQ_RK0[0][ii] , PHY_FLD_FULL);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ2+ ii*4), u4RegBak_DDRPHY_RXDQ_RK0[1][ii] , PHY_FLD_FULL);
+ }
+#if ENABLE_LP3_SW
+ else //LPDDR3
+ {
+#if 0 //LP3 no need to restore backup DQ delay line reg
+ for(u1ByteIdx=0; u1ByteIdx<4; u1ByteIdx++)
+ {
+ vIO32WriteFldAlign_Phy_Byte(u1ByteIdx, DRAMC_REG_ADDR(DDRPHY_SHU2_R0_B0_DQ2+ ii*4), u4RegBak_DDRPHY_RXDQ_RK0[u1ByteIdx][ii] , PHY_FLD_FULL);
+ }
+#endif
+ }
+#endif
+ }
+#endif
+
+ return u4err_value;
+}
+
+
+static U8 aru1RxDatlatResult[CHANNEL_NUM][RANK_MAX];
+
+U8 DramcRxdatlatScan(DRAMC_CTX_T *p, DRAM_DATLAT_CALIBRATION_TYTE_T use_rxtx_scan)
+{
+ U8 ii;
+ U32 u4prv_register_080;
+ U32 u4err_value= 0xffffffff;
+ U8 ucfirst, ucbegin, ucsum, ucbest_step, ucpipe_num =0;
+ U16 u2DatlatBegin;
+
+ // error handling
+ if (!p)
+ {
+ mcSHOW_ERR_MSG(("context NULL\n"));
+ return DRAM_FAIL;
+ }
+#if REG_ACCESS_PORTING_DGB
+ RegLogEnable =1;
+ mcSHOW_DBG_MSG(("\n[REG_ACCESS_PORTING_FUNC] DramcRxdatlatCal\n"));
+ mcFPRINTF((fp_A60501, "\n[REG_ACCESS_PORTING_FUNC] DramcRxdatlatCal\n"));
+#endif
+
+ mcSHOW_DBG_MSG(("\n[DATLAT]\n"
+ "Freq=%d, CH%d RK%d, use_rxtx_scan=%d\n\n",
+ p->frequency, p->channel, p->rank, use_rxtx_scan));
+
+ mcFPRINTF((fp_A60501, "\n\tDATLAT calibration\n"));
+ mcFPRINTF((fp_A60501, "\tch=%d(1:cha), rank=%d, use_rxtx_scan=%d\n\n",
+ p->channel, p->rank, use_rxtx_scan));
+
+ // [11:10] DQIENQKEND 01 -> 00 for DATLAT calibration issue, DQS input enable will refer to DATLAT
+ // if need to enable this (for power saving), do it after all calibration done
+ //u4prv_register_0d8 = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_MCKDLY));
+ //vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_PADCTRL), P_Fld(0, PADCTRL_DQIENQKEND) | P_Fld(0, PADCTRL_DQIENLATEBEGIN));
+
+ // pre-save
+ // 0x07c[6:4] DATLAT bit2-bit0
+ u4prv_register_080 = u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_CONF1));
+
+ // init best_step to default
+ ucbest_step = (U8) u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHU_CONF1), SHU_CONF1_DATLAT);
+ mcSHOW_DBG_MSG(("DATLAT Default: 0x%x\n", ucbest_step));
+ mcFPRINTF((fp_A60501, "DATLAT Default: 0x%x\n", ucbest_step));
+
+#ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+ U8 u1GUMP_INIT_RG_LOG_TO_DE_bak = gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag;
+ gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag=0;
+#endif
+
+ // 1.set DATLAT 0-15 (0-21 for MT6595)
+ // 2.enable engine1 or engine2
+ // 3.check result ,3~4 taps pass
+ // 4.set DATLAT 2nd value for optimal
+
+ // Initialize
+ ucfirst = 0xff;
+ ucbegin = 0;
+ ucsum = 0;
+
+ DramcEngine2Init(p, p->test2_1, p->test2_2, p->test_pattern, 0);
+#if (FOR_DV_SIMULATION_USED==0)
+ u2DatlatBegin=7;
+#else
+ u2DatlatBegin=0;
+#endif
+
+ #if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_DATLAT)
+ if(p->femmc_Ready==1)
+ {
+ ucbest_step = p->pSavetimeData->u1RxDatlat_Save[p->channel][p->rank];
+ }
+ else
+ #endif
+ {
+ for (ii = u2DatlatBegin; ii < DATLAT_TAP_NUMBER; ii++)
+ {
+ // 1
+ dle_factor_handler(p, ii, ucpipe_num);
+
+ // 2
+ if(use_rxtx_scan == fcDATLAT_USE_DEFAULT)
+ {
+ u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, p->test_pattern);
+ }
+#if ENABLE_LP3_SW
+ else //if(use_rxtx_scan == fcDATLAT_USE_RX_SCAN)//LPDDR3, LP4 Should not enter if datlat calibration is after RDDQC
+ {
+ u4err_value = Dramc_ta2_rx_scan(p, 1);
+ }
+#endif
+
+ // 3
+ if (u4err_value == 0)
+ {
+ if (ucbegin == 0)
+ {
+ // first tap which is pass
+ ucfirst = ii;
+ ucbegin = 1;
+ }
+ if (ucbegin == 1)
+ {
+ ucsum++;
+
+ if(ucsum >4)
+ break; //early break.
+ }
+ }
+ else
+ {
+ if (ucbegin == 1)
+ {
+ // pass range end
+ ucbegin = 0xff;
+ }
+ }
+
+ #ifdef ETT_PRINT_FORMAT
+ mcSHOW_DBG_MSG(("%d, 0x%X, sum=%d\n", ii, u4err_value, ucsum));
+ #else
+ mcSHOW_DBG_MSG(("TAP=%2d, err_value=0x%8x, sum=%d\n", ii, u4err_value, ucsum));
+ #endif
+ mcFPRINTF((fp_A60501, "TAP=%2d, err_value=0x%8x, begin=%d, first=%3d, sum=%d\n", ii, u4err_value, ucbegin, ucfirst, ucsum));
+ }
+
+ DramcEngine2End(p);
+
+ // 4
+ if (ucsum == 0)
+ {
+ mcSHOW_ERR_MSG(("no DATLAT taps pass, DATLAT calibration fail!\n"));
+ }
+ else if (ucsum <= 3)
+ {
+ ucbest_step = ucfirst + (ucsum>>1);
+ }
+ else // window is larger htan 3
+ {
+ ucbest_step = ucfirst + 2;
+ }
+ }
+ aru1RxDatlatResult[p->channel][p->rank] = ucbest_step;
+
+ #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==0)
+ {
+ p->pSavetimeData->u1RxDatlat_Save[p->channel][p->rank] = ucbest_step;
+ }
+ #endif
+
+ mcSHOW_DBG_MSG(("best_step=%d\n\n", ucbest_step));
+ mcFPRINTF((fp_A60501, "best_step=%d\n", ucbest_step));
+
+
+#ifdef FOR_HQA_TEST_USED
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "DATLAT", 0, ucbest_step, NULL);
+#endif
+
+#ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+ gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag = u1GUMP_INIT_RG_LOG_TO_DE_bak;
+#endif
+
+ #if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_DATLAT)
+ if(p->femmc_Ready==1)
+ {
+ dle_factor_handler(p, ucbest_step, ucpipe_num);
+ vSetCalibrationResult(p, DRAM_CALIBRATION_DATLAT, DRAM_OK);
+ }
+ else
+ #endif
+ {
+ if(ucsum <4)
+ {
+ mcSHOW_DBG_MSG2(("[NOTICE] CH%d, DatlatSum %d\n", p->channel, ucsum));
+ mcFPRINTF((fp_A60501, "[NOTICE] CH%d, DatlatSum %d\n", p->channel, ucsum));
+ }
+
+ if (ucsum == 0)
+ {
+ mcSHOW_ERR_MSG(("DATLAT calibration fail, write back to default values!\n"));
+ vIO32Write4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_CONF1), u4prv_register_080);
+ vSetCalibrationResult(p, DRAM_CALIBRATION_DATLAT, DRAM_FAIL);
+ }
+ else
+ {
+ dle_factor_handler(p, ucbest_step, ucpipe_num);
+ vSetCalibrationResult(p, DRAM_CALIBRATION_DATLAT, DRAM_OK);
+ }
+ }
+ // [11:10] DQIENQKEND 01 -> 00 for DATLAT calibration issue, DQS input enable will refer to DATLAT
+ // if need to enable this (for power saving), do it after all calibration done
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_PADCTRL), P_Fld(1, PADCTRL_DQIENQKEND) | P_Fld(1, PADCTRL_DQIENLATEBEGIN));
+
+ mcSHOW_DBG_MSG3(("[DramcRxdatlatCal] Done\n"));
+ mcFPRINTF((fp_A60501, "[DramcRxdatlatCal] Done\n"));
+
+#if REG_ACCESS_PORTING_DGB
+ RegLogEnable =0;
+#endif
+
+ return ucsum;
+}
+
+void DramcRxdatlatCal(DRAMC_CTX_T *p)
+{
+ U8 u1DatlatWindowSum;
+
+ u1DatlatWindowSum = DramcRxdatlatScan(p, fcDATLAT_USE_DEFAULT);
+
+ if((p->dram_type == TYPE_LPDDR3) &&(u1DatlatWindowSum <5))
+ {
+ mcSHOW_DBG_MSG(("\nDatlatWindowSum %d too small(<5), Start RX + Datlat scan\n", u1DatlatWindowSum));
+ DramcRxdatlatScan(p, fcDATLAT_USE_RX_SCAN);
+ }
+}
+
+DRAM_STATUS_T DramcDualRankRxdatlatCal(DRAMC_CTX_T *p)
+{
+ U8 u1FinalDatlat, u1Datlat0, u1Datlat1;
+
+ u1Datlat0 = aru1RxDatlatResult[p->channel][0];
+ u1Datlat1 = aru1RxDatlatResult[p->channel][1];
+
+ if(u1Datlat0> u1Datlat1)
+ {
+ u1FinalDatlat= u1Datlat0;
+ }
+ else
+ {
+ u1FinalDatlat= u1Datlat1;
+ }
+
+ #if ENABLE_READ_DBI
+ if(p->DBI_R_onoff[p->dram_fsp])
+ {
+ u1FinalDatlat++;
+ }
+ #endif
+
+ dle_factor_handler(p, u1FinalDatlat, 3);
+ mcSHOW_DBG_MSG(("[DualRankRxdatlatCal] RK0: %d, RK1: %d, Final_Datlat %d\n", u1Datlat0, u1Datlat1, u1FinalDatlat));
+ mcFPRINTF((fp_A60501, "[DualRankRxdatlatCal] RK0: %d, RK1: %d, Final_Datlat %d\n", u1Datlat0, u1Datlat1, u1FinalDatlat));
+
+ return DRAM_OK;
+
+}
+#endif //SIMULATION_DATLAT
+
+#if SIMULATION_TX_PERBIT
+
+#if TX_OE_CALIBATION
+#define TX_OE_PATTERN_USE_TA2 1
+#define TX_OE_SCAN_FULL_RANGE 0
+
+void DramcTxOECalibration(DRAMC_CTX_T *p)
+{
+ U8 u1ByteIdx, ucBegin[2]={0}, ucEnd[2]={0xff, 0xff}, ucbest_step[2];
+ //U8 ucbegin=0xff, , ucfirst, ucsum, ucbest_step;
+ U32 u4RegValue_TXDLY, u4RegValue_dly, u4err_value;
+ U16 u2Delay, u2TempVirtualDelay, u2SmallestVirtualDelay=0xffff;
+ U16 u2DQOEN_DelayBegin, u2DQEN_DelayEnd;
+ U8 ucdq_ui_large_bak[DQS_NUMBER], ucdq_ui_small_bak[DQS_NUMBER];
+ U8 ucdq_oen_ui_large[2], ucdq_oen_ui_small[2];
+ U8 ucdq_current_ui_large, ucdq_current_ui_small;
+ //U8 ucdq_ui_large_reg_value=0xff, ucdq_ui_small_reg_value=0xff;
+
+ if(!u1IsLP4Family(p->dram_type))
+ return; //only apply in LP4
+
+ #if TX_OE_PATTERN_USE_TA2
+ mcSHOW_DBG_MSG(("\n[DramC_TX_OE_Calibration] TA2\n"));
+ #else
+ mcSHOW_DBG_MSG(("\n[DramC_TX_OE_Calibration] DMA\n"));
+ #endif
+
+ #ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+ U8 u1GUMP_INIT_RG_LOG_TO_DE_bak = gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag;
+ gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag=0;
+ #endif
+
+
+#if (SUPPORT_SAVE_TIME_FOR_CALIBRATION)
+ if(p->femmc_Ready==1)
+ {
+ for(u1ByteIdx=0; u1ByteIdx<DQS_NUMBER_LP4; u1ByteIdx++)
+ {
+ ucdq_oen_ui_large[u1ByteIdx]= p->pSavetimeData->u1TX_OE_DQ_MCK[p->channel][p->rank][u1ByteIdx];
+ ucdq_oen_ui_small[u1ByteIdx]= p->pSavetimeData->u1TX_OE_DQ_UI[p->channel][p->rank][u1ByteIdx];
+ }
+ }
+ else
+#endif
+ {
+ u4RegValue_TXDLY= u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0));
+ u4RegValue_dly= u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2));
+
+ // find smallest DQ byte delay
+ for(u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+ {
+ ucdq_ui_large_bak[u1ByteIdx] = (u4RegValue_TXDLY >> (u1ByteIdx*4)) &0x7;
+ ucdq_ui_small_bak[u1ByteIdx] = (u4RegValue_dly >> (u1ByteIdx*4)) &0x7;
+
+ u2TempVirtualDelay = (ucdq_ui_large_bak[u1ByteIdx] <<3) + ucdq_ui_small_bak[u1ByteIdx];
+ if(u2TempVirtualDelay < u2SmallestVirtualDelay)
+ {
+ u2SmallestVirtualDelay = u2TempVirtualDelay;
+ }
+
+ mcSHOW_DBG_MSG(("Original DQ_B%d (%d %d) =%d, OEN = %d\n", u1ByteIdx, ucdq_ui_large_bak[u1ByteIdx], ucdq_ui_small_bak[u1ByteIdx], u2TempVirtualDelay, u2TempVirtualDelay-TX_DQ_OE_SHIFT_LP4));
+ }
+
+ #if TX_OE_PATTERN_USE_TA2
+ DramcEngine2Init(p, p->test2_1, p->test2_2, TEST_AUDIO_PATTERN, 0);
+ #else
+ DramcDmaEngine((DRAMC_CTX_T *)p, 0x50000000, 0x60000000, 0xff00, 8, DMA_PREPARE_DATA_ONLY, p->support_channel_num);
+ #endif
+
+ #if TX_OE_SCAN_FULL_RANGE
+ // -17~+8 UI
+ if(u2SmallestVirtualDelay >= 17)
+ u2DQOEN_DelayBegin = u2SmallestVirtualDelay -17;
+ else
+ u2DQOEN_DelayBegin =0;
+
+ u2DQEN_DelayEnd = u2DQOEN_DelayBegin +25;
+
+ #else // reduce range to speed up
+ if(u2SmallestVirtualDelay >= 7)
+ u2DQOEN_DelayBegin = u2SmallestVirtualDelay -7;
+ else
+ u2DQOEN_DelayBegin =0;
+
+ u2DQEN_DelayEnd = u2DQOEN_DelayBegin +10;
+ #endif
+
+ for (u2Delay = u2DQOEN_DelayBegin; u2Delay <= u2DQEN_DelayEnd; u2Delay++)
+ {
+ ucdq_current_ui_large= (u2Delay >>3);
+ ucdq_current_ui_small = u2Delay & 0x7;
+ //mcSHOW_DBG_MSG(("\nucdq_oen_ui %d %d ", ucdq_oen_ui_large, ucdq_oen_ui_small));
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), \
+ P_Fld(ucdq_current_ui_large, SHURK0_SELPH_DQ0_TXDLY_OEN_DQ0) | \
+ P_Fld(ucdq_current_ui_large, SHURK0_SELPH_DQ0_TXDLY_OEN_DQ1) );
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), \
+ P_Fld(ucdq_current_ui_large, SHURK0_SELPH_DQ1_TXDLY_OEN_DQM0) | \
+ P_Fld(ucdq_current_ui_large, SHURK0_SELPH_DQ1_TXDLY_OEN_DQM1));
+
+ // DLY_DQ[2:0]
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2), \
+ P_Fld(ucdq_current_ui_small, SHURK0_SELPH_DQ2_DLY_OEN_DQ0) | \
+ P_Fld(ucdq_current_ui_small, SHURK0_SELPH_DQ2_DLY_OEN_DQ1) );
+
+ // DLY_DQM[2:0]
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3), \
+ P_Fld(ucdq_current_ui_small, SHURK0_SELPH_DQ3_DLY_OEN_DQM0) | \
+ P_Fld(ucdq_current_ui_small, SHURK0_SELPH_DQ3_DLY_OEN_DQM1));
+
+ #if TX_OE_PATTERN_USE_TA2
+ u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, TEST_AUDIO_PATTERN);
+ #else
+ u4err_value= DramcDmaEngine((DRAMC_CTX_T *)p, 0x50000000, 0x60000000, 0xff00, 8, DMA_CHECK_DATA_ACCESS_AND_COMPARE, p->support_channel_num);
+ #endif
+
+ // 3
+ for(u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+ {
+ if (((u4err_value >> (u1ByteIdx<<3)) & 0xff) == 0)
+ {
+ if(ucBegin[u1ByteIdx]==0)
+ ucBegin[u1ByteIdx]=1;
+
+ ucEnd[u1ByteIdx] = u2Delay;
+ }
+ }
+
+#ifdef ETT_PRINT_FORMAT
+ mcSHOW_DBG_MSG(("%d, 0x%X, End_B0=%d End_B1=%d\n", u2Delay, u4err_value, ucEnd[0], ucEnd[1]));
+#else
+ mcSHOW_DBG_MSG(("TAP=%2d, err_value=0x%8x, End_B0=%d End_B1=%d\n", u2Delay, u4err_value, ucEnd[0], ucEnd[1]));
+#endif
+ mcFPRINTF((fp_A60501, "TAP=%2d, err_value=0x%8x, End_B0=%d End_B1=%d\n", u2Delay, u4err_value, ucEnd[0], ucEnd[1]));
+
+ if(((u4err_value & 0xffff) !=0) && ucBegin[0]==1 && ucBegin[1]==1)
+ break; // early break;
+ }
+
+ #if TX_OE_PATTERN_USE_TA2
+ DramcEngine2End(p);
+ #endif
+
+ // 4
+ for(u1ByteIdx=0; u1ByteIdx<DQS_NUMBER_LP4; u1ByteIdx++)
+ {
+ if (ucEnd[u1ByteIdx] == 0xff)
+ {
+ ucbest_step[u1ByteIdx] = u2SmallestVirtualDelay - TX_DQ_OE_SHIFT_LP4; //bakcup original delay, will be uesed if Pass window not found.
+ mcSHOW_ERR_MSG(("Byte %d no TX OE taps pass, calibration fail!\n", u1ByteIdx));
+ }
+ else // window is larger htan 3
+ {
+ ucbest_step[u1ByteIdx] = ucEnd[u1ByteIdx] - 3;
+ }
+ mcSHOW_DBG_MSG(("Byte%d end_step=%d best_step=%d\n", u1ByteIdx, ucEnd[u1ByteIdx], ucbest_step[u1ByteIdx]));
+ mcFPRINTF((fp_A60501, "Byte%d first_step=%d best_step=%d\n", u1ByteIdx, ucEnd[u1ByteIdx], ucbest_step[u1ByteIdx]));
+
+ ucdq_oen_ui_large[u1ByteIdx]= (ucbest_step[u1ByteIdx] >>3);
+ ucdq_oen_ui_small[u1ByteIdx] = ucbest_step[u1ByteIdx] & 0x7;
+ }
+ }
+
+ #ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+ gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag = u1GUMP_INIT_RG_LOG_TO_DE_bak;
+ #endif
+
+ for(u1ByteIdx=0; u1ByteIdx<DQS_NUMBER_LP4; u1ByteIdx++)
+ {
+ mcSHOW_DBG_MSG(("Byte%d TX OE(2T, 0.5T) = (%d, %d)\n", u1ByteIdx, ucdq_oen_ui_large[u1ByteIdx], ucdq_oen_ui_small[u1ByteIdx]));
+ }
+ mcSHOW_DBG_MSG(("\n\n"));
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), \
+ P_Fld(ucdq_oen_ui_large[0], SHURK0_SELPH_DQ0_TXDLY_OEN_DQ0) | \
+ P_Fld(ucdq_oen_ui_large[1], SHURK0_SELPH_DQ0_TXDLY_OEN_DQ1));
+
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), \
+ P_Fld(ucdq_oen_ui_large[0], SHURK0_SELPH_DQ1_TXDLY_OEN_DQM0) | \
+ P_Fld(ucdq_oen_ui_large[1], SHURK0_SELPH_DQ1_TXDLY_OEN_DQM1));
+ // DLY_DQ[2:0]
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2), \
+ P_Fld(ucdq_oen_ui_small[0], SHURK0_SELPH_DQ2_DLY_OEN_DQ0) | \
+ P_Fld(ucdq_oen_ui_small[1], SHURK0_SELPH_DQ2_DLY_OEN_DQ1) );
+ // DLY_DQM[2:0]
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3), \
+ P_Fld(ucdq_oen_ui_small[0], SHURK0_SELPH_DQ3_DLY_OEN_DQM0) | \
+ P_Fld(ucdq_oen_ui_small[1], SHURK0_SELPH_DQ3_DLY_OEN_DQM1));
+
+ #if (SUPPORT_SAVE_TIME_FOR_CALIBRATION)
+ if(p->femmc_Ready==0)
+ {
+ for(u1ByteIdx=0; u1ByteIdx<DQS_NUMBER_LP4; u1ByteIdx++)
+ {
+ p->pSavetimeData->u1TX_OE_DQ_MCK[p->channel][p->rank][u1ByteIdx] = ucdq_oen_ui_large[u1ByteIdx];
+ p->pSavetimeData->u1TX_OE_DQ_UI[p->channel][p->rank][u1ByteIdx] = ucdq_oen_ui_small[u1ByteIdx];
+ }
+ }
+ #endif
+
+}
+#endif
+
+
+
+//=============================================================
+///// DramC TX perbi calibration ----------Begin--------------
+//=============================================================
+//-------------------------------------------------------------------------
+/** DramcTxWindowPerbitCal (v2)
+ * TX DQS per bit SW calibration.
+ * @param p Pointer of context created by DramcCtxCreate.
+ * @param apply (U8): 0 don't apply the register we set 1 apply the register we set ,default don't apply.
+ * @retval status (DRAM_STATUS_T): DRAM_OK or DRAM_FAIL
+ */
+//-------------------------------------------------------------------------
+#if (SW_CHANGE_FOR_SIMULATION ||FOR_DV_SIMULATION_USED)
+#define TX_VREF_RANGE_BEGIN 0
+#define TX_VREF_RANGE_END 2 // binary 110010
+#define TX_VREF_RANGE_STEP 2
+#else
+#define TX_VREF_RANGE_BEGIN 16
+#define TX_VREF_RANGE_END 50 // binary 110010
+#define TX_VREF_RANGE_STEP 2
+#endif
+
+#define TX_DQ_UI_TO_PI_TAP 64 // 1 PI = tCK/64, total 128 PI, 1UI = 32 PI
+#define LP4_TX_VREF_DATA_NUM 50
+#define LP4_TX_VREF_PASS_CONDITION 0
+#define LP4_TX_VREF_BOUNDARY_NOT_READY 0xff
+
+typedef struct _PASS_WIN_DATA_BY_VREF_T
+{
+ U16 u2VrefUsed;
+ U16 u2WinSum_byVref;
+ U16 u2MinWinSize_byVref;
+} PASS_WIN_DATA_BY_VREF_T;
+
+U16 u2TX_DQ_PreCal_LP4[DQS_NUMBER]; // LP4 only
+
+
+void TxWinTransferDelayToUIPI(DRAMC_CTX_T *p, DRAM_TX_PER_BIT_CALIBRATION_TYTE_T calType, U16 uiDelay, U8 u1AdjustPIToCenter, U8* pu1UILarge_DQ, U8* pu1UISmall_DQ, U8* pu1PI, U8* pu1UILarge_DQOE, U8* pu1UISmall_DQOE)
+{
+ U8 u1Small_ui_to_large, u1PI, u164PIto1UI;
+ U16 u2TmpValue;
+
+#if (fcFOR_PINMUX == fcLaurel) //LP2 is full rate
+ //in LP4, 8 small UI = 1 large UI
+ //in LP3, 4 small UI = 1 large UI
+ if(u1IsLP4Family(p->dram_type))
+ {
+ u1Small_ui_to_large = 3;
+ u164PIto1UI = 1;
+ }
+ else //LPDDR3
+ {
+ u1Small_ui_to_large = 2;
+ u164PIto1UI = 0;
+ }
+#endif
+
+ if(pu1PI != NULL)
+ {
+ #if 0
+ u1PI = uiDelay% TX_DQ_UI_TO_PI_TAP;
+ #else
+ u1PI = uiDelay & (TX_DQ_UI_TO_PI_TAP-1);
+ #endif
+
+ *pu1PI =u1PI;
+ }
+
+ u2TmpValue = (uiDelay /TX_DQ_UI_TO_PI_TAP)<<u164PIto1UI;
+
+ if(u1AdjustPIToCenter && (pu1PI!=NULL))
+ {
+ if(u1PI<10)
+ {
+ u1PI += (TX_DQ_UI_TO_PI_TAP)>>1;
+ u2TmpValue --;
+ }
+ else if(u1PI>TX_DQ_UI_TO_PI_TAP-10)
+ {
+ u1PI -= (TX_DQ_UI_TO_PI_TAP)>>1;
+ u2TmpValue ++;
+ }
+
+ *pu1PI =u1PI;
+ }
+
+ #if 0
+ *pu1UISmall_DQ = u2TmpValue % u1Small_ui_to_large;
+ *pu1UILarge_DQ = u2TmpValue / u1Small_ui_to_large;
+ #else
+ *pu1UISmall_DQ = u2TmpValue - ((u2TmpValue >> u1Small_ui_to_large) <<u1Small_ui_to_large);
+ *pu1UILarge_DQ = (u2TmpValue >> u1Small_ui_to_large);
+ #endif
+
+ // calculate DQ OE according to DQ UI
+ if(u1IsLP4Family(p->dram_type))
+ {
+ u2TmpValue -= TX_DQ_OE_SHIFT_LP4;
+
+ if(((u1MR03Value[p->dram_fsp]&0x80)>>7)==1) //if WDBI is on, OE_DLY don't need to shift 1 MCK with DLY
+ {
+ u2TmpValue += 8;
+ }
+
+ }
+ else
+ {
+ u2TmpValue -= TX_DQ_OE_SHIFT_LP3;
+ }
+
+ *pu1UISmall_DQOE = u2TmpValue - ((u2TmpValue >> u1Small_ui_to_large) <<u1Small_ui_to_large);
+ *pu1UILarge_DQOE = (u2TmpValue >> u1Small_ui_to_large);
+}
+
+static void TxPrintWidnowInfo(DRAMC_CTX_T *p, PASS_WIN_DATA_T WinPerBitData[])
+{
+ U8 u1BitIdx;
+
+ for (u1BitIdx = 0; u1BitIdx < DQS_BIT_NUMBER; u1BitIdx++)
+ {
+ #ifdef ETT_PRINT_FORMAT
+ mcSHOW_DBG_MSG(("TX Bit%d (%d~%d) %d %d, Bit%d (%d~%d) %d %d,", \
+ u1BitIdx, WinPerBitData[u1BitIdx].first_pass, WinPerBitData[u1BitIdx].last_pass, WinPerBitData[u1BitIdx].win_size, WinPerBitData[u1BitIdx].win_center, \
+ u1BitIdx+8, WinPerBitData[u1BitIdx+8].first_pass, WinPerBitData[u1BitIdx+8].last_pass, WinPerBitData[u1BitIdx+8].win_size, WinPerBitData[u1BitIdx+8].win_center));
+ #else
+ mcSHOW_DBG_MSG(("TX Bit%2d (%2d~%2d) %2d %2d, Bit%2d (%2d~%2d) %2d %2d,", \
+ u1BitIdx, WinPerBitData[u1BitIdx].first_pass, WinPerBitData[u1BitIdx].last_pass, WinPerBitData[u1BitIdx].win_size, WinPerBitData[u1BitIdx].win_center, \
+ u1BitIdx+8, WinPerBitData[u1BitIdx+8].first_pass, WinPerBitData[u1BitIdx+8].last_pass, WinPerBitData[u1BitIdx+8].win_size, WinPerBitData[u1BitIdx+8].win_center));
+ #endif
+ mcFPRINTF((fp_A60501,"TX Bit%2d (%2d~%2d) %2d %2d, Bit%2d (%2d~%2d) %2d %2d,", \
+ u1BitIdx, WinPerBitData[u1BitIdx].first_pass, WinPerBitData[u1BitIdx].last_pass, WinPerBitData[u1BitIdx].win_size, WinPerBitData[u1BitIdx].win_center, \
+ u1BitIdx+8, WinPerBitData[u1BitIdx+8].first_pass, WinPerBitData[u1BitIdx+8].last_pass, WinPerBitData[u1BitIdx+8].win_size, WinPerBitData[u1BitIdx+8].win_center));
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ mcSHOW_DBG_MSG(("\n"));
+ mcFPRINTF((fp_A60501,"\n"));
+ }
+ #if ENABLE_LP3_SW
+ else //LPDDR3
+ {
+ #ifdef ETT_PRINT_FORMAT
+ mcSHOW_DBG_MSG((" %d (%d~%d) %d %d, %d (%d~%d) %d %d\n", \
+ u1BitIdx+16, WinPerBitData[u1BitIdx+16].first_pass, WinPerBitData[u1BitIdx+16].last_pass, WinPerBitData[u1BitIdx+16].win_size, WinPerBitData[u1BitIdx+16].win_center, \
+ u1BitIdx+24, WinPerBitData[u1BitIdx+24].first_pass, WinPerBitData[u1BitIdx+24].last_pass, WinPerBitData[u1BitIdx+24].win_size, WinPerBitData[u1BitIdx+24].win_center ));
+ #else
+ mcSHOW_DBG_MSG((" %2d (%2d~%2d) %2d %2d, %2d (%2d~%2d) %2d %2d\n", \
+ u1BitIdx+16, WinPerBitData[u1BitIdx+16].first_pass, WinPerBitData[u1BitIdx+16].last_pass, WinPerBitData[u1BitIdx+16].win_size, WinPerBitData[u1BitIdx+16].win_center, \
+ u1BitIdx+24, WinPerBitData[u1BitIdx+24].first_pass, WinPerBitData[u1BitIdx+24].last_pass, WinPerBitData[u1BitIdx+24].win_size, WinPerBitData[u1BitIdx+24].win_center ));
+ #endif
+
+ mcFPRINTF((fp_A60501," %2d (%2d~%2d) %2d %2d, %2d (%2d~%2d) %2d %2d\n", \
+ u1BitIdx+16, WinPerBitData[u1BitIdx+16].first_pass, WinPerBitData[u1BitIdx+16].last_pass, WinPerBitData[u1BitIdx+16].win_size, WinPerBitData[u1BitIdx+16].win_center, \
+ u1BitIdx+24, WinPerBitData[u1BitIdx+24].first_pass, WinPerBitData[u1BitIdx+24].last_pass, WinPerBitData[u1BitIdx+24].win_size, WinPerBitData[u1BitIdx+24].win_center ));
+ }
+ #endif//ENABLE_LP3_SW
+ }
+ mcSHOW_DBG_MSG(("\n"));
+ mcFPRINTF((fp_A60501,"\n"));
+}
+
+
+static void TXPerbitCalibrationInit(DRAMC_CTX_T *p, U8 calType)
+{
+ //Set TX delay chain to 0
+ if(u1IsLP4Family(p->dram_type) && (calType !=TX_DQ_DQS_MOVE_DQM_ONLY))
+ {
+ #if 1
+ #if PINMUX_AUTO_TEST_PER_BIT_TX
+ if(gTX_check_per_bit_flag == 1)
+ {
+ //not reset delay cell
+ }
+ else
+ #endif
+ {
+ vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ0), 0);
+ vIO32Write4B(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ0), 0);
+ }
+ #else
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ0), P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ7_DLY_B0)
+ | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ6_DLY_B0)
+ | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ5_DLY_B0)
+ | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ4_DLY_B0)
+ | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ3_DLY_B0)
+ | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ2_DLY_B0)
+ | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ1_DLY_B0)
+ | P_Fld(0x0, SHU1_R0_B0_DQ0_RK0_TX_ARDQ0_DLY_B0));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ0), P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ7_DLY_B1)
+ | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ6_DLY_B1)
+ | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ5_DLY_B1)
+ | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ4_DLY_B1)
+ | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ3_DLY_B1)
+ | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ2_DLY_B1)
+ | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ1_DLY_B1)
+ | P_Fld(0x0, SHU1_R0_B1_DQ0_RK0_TX_ARDQ0_DLY_B1));
+ #endif
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ1), 0x0, SHU1_R0_B0_DQ1_RK0_TX_ARDQM0_DLY_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ1), 0x0, SHU1_R0_B1_DQ1_RK0_TX_ARDQM0_DLY_B1);
+ }
+
+
+ //Use HW TX tracking value
+ //R_DMARPIDQ_SW :drphy_conf (0x170[7])(default set 1)
+ // 0: DQS2DQ PI setting controlled by HW
+ //R_DMARUIDQ_SW : Dramc_conf(0x156[15])(default set 1)
+ // 0: DQS2DQ UI setting controlled by HW
+ ///TODO: need backup original setting?
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 1, MISC_CTRL1_R_DMARPIDQ_SW);
+ //vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQSOSCR), 1, DQSOSCR_ARUIDQ_SW);
+
+}
+
+#define TX_TDQS2DQ_PRE_CAL 1
+#if TX_TDQS2DQ_PRE_CAL
+U16 u2DQS2DQ_Pre_Cal[CHANNEL_NUM][RANK_MAX]={0};
+#endif
+
+static void TXScanRange_PI(DRAMC_CTX_T *p, DRAM_TX_PER_BIT_CALIBRATION_TYTE_T calType, U16 *pu2Begin, U16 *pu2End)
+{
+ U8 u1MCK2UI, u1ByteIdx, u1UI2PI;
+ U32 u4RegValue_TXDLY, u4RegValue_dly;
+ U8 ucdq_ui_large_bak[DQS_NUMBER], ucdq_ui_small_bak[DQS_NUMBER];
+ U16 u2TempVirtualDelay, u2SmallestVirtualDelay=0xffff;
+ U16 u2DQDelayBegin=0, u2DQDelayEnd=0, u2TX_DQ_PreCal_LP4_Samll;
+
+ u4RegValue_TXDLY= u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_DQS0));
+ u4RegValue_dly= u4IO32Read4B(DRAMC_REG_ADDR(DRAMC_REG_SHU_SELPH_DQS1));
+
+#if (fcFOR_PINMUX == fcLaurel) //LP2 is full rate
+ if(u1IsLP4Family(p->dram_type))
+ {
+ u1MCK2UI= 3;
+ u1UI2PI = 5;
+ }
+ else
+ {
+ u1MCK2UI =2;
+ u1UI2PI = 6;
+ }
+#endif
+
+ // find smallest DQS delay
+ for(u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+ {
+ ucdq_ui_large_bak[u1ByteIdx] = (u4RegValue_TXDLY >> (u1ByteIdx<<2)) &0x7;// MCK
+ ucdq_ui_small_bak[u1ByteIdx] = (u4RegValue_dly >> (u1ByteIdx<<2)) &0x7;// UI
+ //wrlevel_dqs_final_delay[u1ByteIdx] ==> PI
+
+ //LP4 : Virtual Delay = 256 * MCK + 32*UI + PI;
+ //LP3 : Virtual Delay = 128 * MCK + 32*UI + PI;
+ u2TempVirtualDelay = (((ucdq_ui_large_bak[u1ByteIdx] <<u1MCK2UI) + ucdq_ui_small_bak[u1ByteIdx])<<u1UI2PI) + wrlevel_dqs_final_delay[u1ByteIdx];
+ if(u2TempVirtualDelay < u2SmallestVirtualDelay)
+ {
+ u2SmallestVirtualDelay = u2TempVirtualDelay;
+ }
+
+ /*mcSHOW_DBG_MSG2(("Original DQS_B%d VirtualDelay %d = (%d %d %d)\n", u1ByteIdx, u2TempVirtualDelay,\
+ * ucdq_ui_large_bak[u1ByteIdx], ucdq_ui_small_bak[u1ByteIdx], wrlevel_dqs_final_delay[u1ByteIdx]));
+ */
+ }
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ // (1)LP4 will calibration DQM at the first time, K full range, and then rember the TX position.
+ // (2)The sencod time will calibrate DQ+Vref, reference TX postion of (1)
+ if(calType==TX_DQ_DQS_MOVE_DQ_DQM)
+ {
+ u2DQDelayBegin = u2SmallestVirtualDelay;
+
+ #if TX_TDQS2DQ_PRE_CAL
+ if(p->frequency == LP4_LOWEST_FREQ)
+ {
+ // Save first freqency DQS2DQ, but skip MDL_UESED. Therefore, clean this value.
+ u2DQS2DQ_Pre_Cal[p->channel][p->rank]=0;
+ }
+ else if(u2DQS2DQ_Pre_Cal[p->channel][p->rank]> 0)
+ {
+ mcSHOW_DBG_MSG(("TX_TDQS2DQ_PRE_CAL : change DQ begin %d -->", u2DQDelayBegin));
+ u2DQDelayBegin += (u2DQS2DQ_Pre_Cal[p->channel][p->rank]* p->frequency /1000);
+ mcSHOW_DBG_MSG(("%d\n", u2DQDelayBegin));
+ }
+ #endif
+ u2DQDelayEnd = u2DQDelayBegin + 256;
+ }
+ else //if(calType==TX_DQ_DQS_MOVE_DQ_ONLY)
+ {
+ if(u2TX_DQ_PreCal_LP4[0] < u2TX_DQ_PreCal_LP4[1])
+ u2TX_DQ_PreCal_LP4_Samll = u2TX_DQ_PreCal_LP4[0];
+ else
+ u2TX_DQ_PreCal_LP4_Samll = u2TX_DQ_PreCal_LP4[1];
+
+ if(u2TX_DQ_PreCal_LP4_Samll >24)
+ u2DQDelayBegin = u2TX_DQ_PreCal_LP4_Samll-24;
+ else
+ u2DQDelayBegin =0;
+
+ #if TX_K_DQM_WITH_WDBI
+ if(calType==TX_DQ_DQS_MOVE_DQM_ONLY)
+ {
+ // DBI on, calibration range -1MCK
+ u2DQDelayBegin -=(1<<(u1MCK2UI+5));
+ }
+ #endif
+ u2DQDelayEnd = u2DQDelayBegin + 64;
+ }
+
+ }
+ else
+ {
+ u2DQDelayBegin = (u2SmallestVirtualDelay > 16)? (u2SmallestVirtualDelay - 16) : 0;
+ u2DQDelayEnd = u2SmallestVirtualDelay + 96;
+ }
+
+ *pu2Begin = u2DQDelayBegin;
+ *pu2End = u2DQDelayEnd;
+
+ #if 0//TX_TDQS2DQ_PRE_CAL
+ mcSHOW_DBG_MSG(("TXScanRange_PI %d~%d\n", u2DQDelayBegin,u2DQDelayEnd));
+ #endif
+}
+
+
+static void TXScanRange_Vref(DRAMC_CTX_T *p, U8 u1VrefScanEnable, U16* pu2Range, U16 *pu2Begin, U16 *pu2End, U16 *pu2Setp)
+{
+ U16 u2VrefBegin, u2VrefEnd;
+ U16 u2VrefRange=!p->odt_onoff;
+
+ if(u1VrefScanEnable==ENABLE_VREF_SCAN)
+ {
+ #if (SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_VREF_CAL)
+ if(p->femmc_Ready==1)
+ {
+ // if fast K, use TX Vref that saved.
+ u2VrefBegin = p->pSavetimeData->u1TxWindowPerbitVref_Save[p->channel][p->rank];
+ u2VrefEnd = u2VrefBegin+1;
+ }
+ else
+ #endif
+ {
+ if (p->odt_onoff == ODT_OFF)
+ {
+ if (p->dram_type == TYPE_LPDDR4)
+ {
+ //range 1
+ u2VrefBegin = 13 - 5; // 300/1100(VDDQ) = 27.2%
+ u2VrefEnd = 13 + 5;
+ }
+ else
+ {
+ //range 1
+ u2VrefBegin = 27 - 5; // 290/600(VDDQ)=48.3%
+ u2VrefEnd = 27 + 5;
+ }
+ }
+ else
+ {
+ if (p->dram_type == TYPE_LPDDR4)
+ {
+ // range 0
+ u2VrefBegin = 12;
+ }
+ else
+ {
+ // range 0
+ u2VrefBegin = TX_VREF_RANGE_BEGIN;
+ }
+ u2VrefEnd = TX_VREF_RANGE_END;
+ }
+ }
+ }
+ else //LPDDR3, the for loop will only excute u2VrefLevel=TX_VREF_RANGE_END/2.
+ {
+ u2VrefBegin = 0;
+ u2VrefEnd = 0;
+ }
+
+ *pu2Range = u2VrefRange;
+ *pu2Begin = u2VrefBegin;
+ *pu2End = u2VrefEnd;
+ *pu2Setp = TX_VREF_RANGE_STEP;
+
+}
+
+static U16 TxChooseVref(DRAMC_CTX_T *p, PASS_WIN_DATA_BY_VREF_T pVrefInfo[], U8 u1VrefNum)
+{
+ U8 u1VrefIdx;
+ U16 u2MaxMinSize=0, u2MaxWinSum=0;
+ U16 u2FinalVref=0;
+
+#if LP4_TX_VREF_PASS_CONDITION
+ U8 u1TempPassNum=0;
+ U8 u1VrefPassBegin=LP4_TX_VREF_BOUNDARY_NOT_READY;
+ U8 u1VrefPassEnd=LP4_TX_VREF_BOUNDARY_NOT_READY;
+ U8 u1MaxVerfPassNum=0;
+ U8 u1VrefPassBegin_Final=LP4_TX_VREF_BOUNDARY_NOT_READY;
+ U8 u1VrefPassEnd_Final=LP4_TX_VREF_BOUNDARY_NOT_READY;
+#endif
+
+ for(u1VrefIdx=0; u1VrefIdx < u1VrefNum; u1VrefIdx++)
+ {
+ mcSHOW_DBG_MSG(("Vref=%d, minWin=%d, winSum=%d\n",
+ pVrefInfo[u1VrefIdx].u2VrefUsed,
+ pVrefInfo[u1VrefIdx].u2MinWinSize_byVref,
+ pVrefInfo[u1VrefIdx].u2WinSum_byVref));
+
+ #if LP4_TX_VREF_PASS_CONDITION
+ if((pVrefInfo[u1VrefIdx].u2MinWinSize_byVref > LP4_TX_VREF_PASS_CONDITION))
+ {
+ if(u1VrefPassBegin ==LP4_TX_VREF_BOUNDARY_NOT_READY)
+ {
+ u1VrefPassBegin = pVrefInfo[u1VrefIdx].u2VrefUsed;
+ u1TempPassNum =1;
+ }
+ else
+ u1TempPassNum ++;
+
+ if(u1VrefIdx==u1VrefNum-1)
+ {
+ u1VrefPassEnd = pVrefInfo[u1VrefIdx].u2VrefUsed;
+ if(u1TempPassNum > u1MaxVerfPassNum)
+ {
+ u1VrefPassBegin_Final= u1VrefPassBegin;
+ u1VrefPassEnd_Final = u1VrefPassEnd;
+ u1MaxVerfPassNum= u1TempPassNum;
+ }
+ }
+ }
+ else
+ {
+ if((u1VrefPassBegin != LP4_TX_VREF_BOUNDARY_NOT_READY) && (u1VrefPassEnd==LP4_TX_VREF_BOUNDARY_NOT_READY))
+ {
+ u1VrefPassEnd = pVrefInfo[u1VrefIdx].u2VrefUsed-TX_VREF_RANGE_STEP;
+ if(u1TempPassNum > u1MaxVerfPassNum)
+ {
+ u1VrefPassBegin_Final= u1VrefPassBegin;
+ u1VrefPassEnd_Final = u1VrefPassEnd;
+ u1MaxVerfPassNum= u1TempPassNum;
+ }
+ u1VrefPassBegin=0xff;
+ u1VrefPassEnd=0xff;
+ u1TempPassNum =0;
+ }
+ }
+ #endif
+ }
+
+ #if LP4_TX_VREF_PASS_CONDITION
+ //if((u1VrefPassBegin_Final !=LP4_TX_VREF_BOUNDARY_NOT_READY) && (u1VrefPassEnd_Final!=LP4_TX_VREF_BOUNDARY_NOT_READY))
+ if(u1MaxVerfPassNum>0)
+ {
+ // vref pass window found
+ u2FinalVref = (u1VrefPassBegin_Final + u1VrefPassEnd_Final) >>1;
+ mcSHOW_DBG_MSG(("[TxChooseVref] Window > %d, Vref (%d~%d), Final Vref %d\n",LP4_TX_VREF_PASS_CONDITION, u1VrefPassBegin_Final, u1VrefPassEnd_Final, u2FinalVref));
+ }
+ else
+ #endif
+ {
+ // not vref found
+ for(u1VrefIdx=0; u1VrefIdx < u1VrefNum; u1VrefIdx++)
+ {
+ if((pVrefInfo[u1VrefIdx].u2MinWinSize_byVref > u2MaxMinSize) ||
+ ((pVrefInfo[u1VrefIdx].u2MinWinSize_byVref == u2MaxMinSize) && (pVrefInfo[u1VrefIdx].u2WinSum_byVref > u2MaxWinSum)))
+ {
+ u2MaxMinSize = pVrefInfo[u1VrefIdx].u2MinWinSize_byVref;
+ u2MaxWinSum = pVrefInfo[u1VrefIdx].u2WinSum_byVref;
+ u2FinalVref = pVrefInfo[u1VrefIdx].u2VrefUsed;
+ }
+ }
+
+ mcSHOW_DBG_MSG(("[TxChooseVref] Min win %d, Win sum %d, Final Vref %d\n", u2MaxMinSize, u2MaxWinSum, u2FinalVref));
+ }
+
+ return u2FinalVref;
+}
+
+
+void DramcTXSetVref(DRAMC_CTX_T *p, U8 u1VrefRange, U8 u1VrefValue)
+{
+ U8 u1TempOPValue = ((u1VrefValue & 0x3f) | (u1VrefRange<<6));
+
+ u1MR14Value[p->channel][p->rank][p->dram_fsp] = u1TempOPValue;
+ DramcModeRegWriteByRank(p, p->rank, 14, u1TempOPValue);
+}
+
+
+static void TXSetFinalVref(DRAMC_CTX_T *p, U16 u2FinalRange, U16 u2FinalVref)
+{
+ // SET tx Vref (DQ) = u2FinalVref, LP3 no need to set this.
+ if(!u1IsLP4Family(p->dram_type))
+ return;
+
+ DramcTXSetVref(p, u2FinalRange, u2FinalVref);
+
+#ifdef FOR_HQA_TEST_USED
+ gFinalTXVrefDQ[p->channel][p->rank] = (U8) u2FinalVref;
+#endif
+
+#if VENDER_JV_LOG
+ mcSHOW_DBG_MSG5(("\nFinal TX Range %d Vref %d\n\n", u2FinalRange, u2FinalVref));
+#else
+ mcSHOW_DBG_MSG(("\nFinal TX Range %d Vref %d\n\n", u2FinalRange, u2FinalVref));
+ mcFPRINTF((fp_A60501, "\nFinal TX Range %d Vref %d\n\n", u2FinalRange, u2FinalVref));
+#endif
+}
+
+
+#if ENABLE_TX_TRACKING
+static void TXUpdateTXTracking(DRAMC_CTX_T *p, DRAM_TX_PER_BIT_CALIBRATION_TYTE_T calType, U8 ucdq_pi[], U8 ucdqm_pi[])
+{
+ if(u1IsLP4Family(p->dram_type) && (calType == TX_DQ_DQS_MOVE_DQ_ONLY ||calType ==TX_DQ_DQS_MOVE_DQM_ONLY))
+ {
+ //make a copy to dramc reg for TX DQ tracking used
+ if(calType ==TX_DQ_DQS_MOVE_DQ_ONLY)
+ {
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_PI),
+ P_Fld(ucdq_pi[0], SHU1RK0_PI_RK0_ARPI_DQ_B0) | P_Fld(ucdq_pi[1], SHU1RK0_PI_RK0_ARPI_DQ_B1));
+
+ // Source DQ
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_DQS2DQ_CAL1),
+ P_Fld(ucdq_pi[1], SHU1RK0_DQS2DQ_CAL1_BOOT_ORIG_UI_RK0_DQ1) |
+ P_Fld(ucdq_pi[0], SHU1RK0_DQS2DQ_CAL1_BOOT_ORIG_UI_RK0_DQ0));
+ // Target DQ
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_DQS2DQ_CAL2),
+ P_Fld(ucdq_pi[1], SHU1RK0_DQS2DQ_CAL2_BOOT_TARG_UI_RK0_DQ1) |
+ P_Fld(ucdq_pi[0], SHU1RK0_DQS2DQ_CAL2_BOOT_TARG_UI_RK0_DQ0));
+ }
+
+ //if(calType ==TX_DQ_DQS_MOVE_DQM_ONLY || (calType ==TX_DQ_DQS_MOVE_DQ_ONLY))
+ {
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_PI),
+ P_Fld(ucdqm_pi[0], SHU1RK0_PI_RK0_ARPI_DQM_B0) | P_Fld(ucdqm_pi[1], SHU1RK0_PI_RK0_ARPI_DQM_B1));
+
+ // Target DQM
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHU1RK0_DQS2DQ_CAL5),
+ P_Fld(ucdqm_pi[1], SHU1RK0_DQS2DQ_CAL5_BOOT_TARG_UI_RK0_DQM1) |
+ P_Fld(ucdqm_pi[0], SHU1RK0_DQS2DQ_CAL5_BOOT_TARG_UI_RK0_DQM0));
+ }
+ }
+
+
+#if 0// for LP3 , TX tracking will be disable, don't need to set DQ delay in DramC.
+ ///TODO: check LP3 byte mapping of dramC
+ vIO32WriteFldMulti(DRAMC_REG_SHU1RK0_PI+(CHANNEL_A<< POS_BANK_NUM), \
+ P_Fld(ucdq_final_pi[0], SHU1RK0_PI_RK0_ARPI_DQ_B0) | P_Fld(ucdq_final_pi[1], SHU1RK0_PI_RK0_ARPI_DQ_B1));
+
+ vIO32WriteFldMulti(DRAMC_REG_SHU1RK0_PI+SHIFT_TO_CHB_ADDR, \
+ P_Fld(ucdq_final_pi[2], SHU1RK0_PI_RK0_ARPI_DQ_B0) | P_Fld(ucdq_final_pi[3], SHU1RK0_PI_RK0_ARPI_DQ_B1));
+#endif
+
+}
+#endif //End ENABLE_TX_TRACKING
+
+
+static void TXSetDelayReg_DQ(DRAMC_CTX_T *p, U8 u1UpdateRegUI, U8 ucdq_ui_large[], U8 ucdq_oen_ui_large[], U8 ucdq_ui_small[], U8 ucdq_oen_ui_small[], U8 ucdql_pi[])
+{
+ if(u1UpdateRegUI)
+ {
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), \
+ P_Fld(ucdq_ui_large[0], SHURK0_SELPH_DQ0_TXDLY_DQ0) |
+ P_Fld(ucdq_ui_large[1], SHURK0_SELPH_DQ0_TXDLY_DQ1) |
+ P_Fld(ucdq_ui_large[2], SHURK0_SELPH_DQ0_TXDLY_DQ2) |
+ P_Fld(ucdq_ui_large[3], SHURK0_SELPH_DQ0_TXDLY_DQ3) |
+ P_Fld(ucdq_oen_ui_large[0], SHURK0_SELPH_DQ0_TXDLY_OEN_DQ0) |
+ P_Fld(ucdq_oen_ui_large[1], SHURK0_SELPH_DQ0_TXDLY_OEN_DQ1) |
+ P_Fld(ucdq_oen_ui_large[2], SHURK0_SELPH_DQ0_TXDLY_OEN_DQ2) |
+ P_Fld(ucdq_oen_ui_large[3], SHURK0_SELPH_DQ0_TXDLY_OEN_DQ3));
+
+ // DLY_DQ[2:0]
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2), \
+ P_Fld(ucdq_ui_small[0], SHURK0_SELPH_DQ2_DLY_DQ0) |
+ P_Fld(ucdq_ui_small[1], SHURK0_SELPH_DQ2_DLY_DQ1) |
+ P_Fld(ucdq_ui_small[2], SHURK0_SELPH_DQ2_DLY_DQ2) |
+ P_Fld(ucdq_ui_small[3], SHURK0_SELPH_DQ2_DLY_DQ3) |
+ P_Fld(ucdq_oen_ui_small[0], SHURK0_SELPH_DQ2_DLY_OEN_DQ0) |
+ P_Fld(ucdq_oen_ui_small[1], SHURK0_SELPH_DQ2_DLY_OEN_DQ1) |
+ P_Fld(ucdq_oen_ui_small[2], SHURK0_SELPH_DQ2_DLY_OEN_DQ2) |
+ P_Fld(ucdq_oen_ui_small[3], SHURK0_SELPH_DQ2_DLY_OEN_DQ3));
+ }
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdql_pi[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), ucdql_pi[1], SHU1_R0_B1_DQ7_RK0_ARPI_DQ_B1);
+ }
+ #if ENABLE_LP3_SW
+ else
+ {
+ vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdql_pi[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+ vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdql_pi[1], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+ vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdql_pi[2], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+ vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdql_pi[3], SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+ }
+ #endif
+}
+
+
+static void TXSetDelayReg_DQM(DRAMC_CTX_T *p, U8 u1UpdateRegUI, U8 ucdqm_ui_large[], U8 ucdqm_oen_ui_large[], U8 ucdqm_ui_small[], U8 ucdqm_oen_ui_small[], U8 ucdqm_pi[])
+{
+ if(u1UpdateRegUI)
+ {
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1),
+ P_Fld(ucdqm_ui_large[0], SHURK0_SELPH_DQ1_TXDLY_DQM0) |
+ P_Fld(ucdqm_ui_large[1], SHURK0_SELPH_DQ1_TXDLY_DQM1) |
+ P_Fld(ucdqm_ui_large[2], SHURK0_SELPH_DQ1_TXDLY_DQM2) |
+ P_Fld(ucdqm_ui_large[3], SHURK0_SELPH_DQ1_TXDLY_DQM3) |
+ P_Fld(ucdqm_oen_ui_large[0], SHURK0_SELPH_DQ1_TXDLY_OEN_DQM0) |
+ P_Fld(ucdqm_oen_ui_large[1], SHURK0_SELPH_DQ1_TXDLY_OEN_DQM1) |
+ P_Fld(ucdqm_oen_ui_large[2], SHURK0_SELPH_DQ1_TXDLY_OEN_DQM2) |
+ P_Fld(ucdqm_oen_ui_large[3], SHURK0_SELPH_DQ1_TXDLY_OEN_DQM3));
+
+ // DLY_DQM[2:0]
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3),
+ P_Fld(ucdqm_ui_small[0], SHURK0_SELPH_DQ3_DLY_DQM0) |
+ P_Fld(ucdqm_ui_small[1], SHURK0_SELPH_DQ3_DLY_DQM1) |
+ P_Fld(ucdqm_ui_small[2], SHURK0_SELPH_DQ3_DLY_DQM2) |
+ P_Fld(ucdqm_ui_small[3], SHURK0_SELPH_DQ3_DLY_DQM3) |
+ P_Fld(ucdqm_oen_ui_small[0], SHURK0_SELPH_DQ3_DLY_OEN_DQM0) |
+ P_Fld(ucdqm_oen_ui_small[1], SHURK0_SELPH_DQ3_DLY_OEN_DQM1) |
+ P_Fld(ucdqm_oen_ui_small[2], SHURK0_SELPH_DQ3_DLY_OEN_DQM2) |
+ P_Fld(ucdqm_oen_ui_small[3], SHURK0_SELPH_DQ3_DLY_OEN_DQM3));
+ }
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdqm_pi[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), ucdqm_pi[1], SHU1_R0_B1_DQ7_RK0_ARPI_DQM_B1);
+ }
+ #if ENABLE_LP3_SW
+ else
+ {
+ vIO32WriteFldAlign_Phy_Byte(0, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdqm_pi[0], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+ vIO32WriteFldAlign_Phy_Byte(1, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdqm_pi[1], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+ vIO32WriteFldAlign_Phy_Byte(2, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdqm_pi[2], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+ vIO32WriteFldAlign_Phy_Byte(3, DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdqm_pi[3], SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+ }
+ #endif
+}
+
+DRAM_STATUS_T DramcTxWindowPerbitCal(DRAMC_CTX_T *p, DRAM_TX_PER_BIT_CALIBRATION_TYTE_T calType, U8 u1VrefScanEnable)
+{
+ U8 u1BitTemp, u1BitIdx, u1ByteIdx, u1RankIdx, backup_rank;
+ U32 uiFinishCount;
+ PASS_WIN_DATA_T WinPerBit[DQ_DATA_WIDTH] = {{0,0,0,0,0}};
+ PASS_WIN_DATA_T VrefWinPerBit[DQ_DATA_WIDTH] = {{0,0,0,0,0}};
+ PASS_WIN_DATA_T FinalWinPerBit[DQ_DATA_WIDTH] = {{0,0,0,0,0}};
+
+ U16 uiDelay, u2DQDelayBegin, u2DQDelayEnd;
+
+ U8 ucdq_pi, ucdq_ui_small, ucdq_ui_large,ucdq_oen_ui_small, ucdq_oen_ui_large;
+ U8 ucdq_ui_small_reg_value, u1UpdateRegUI; // for UI and TXDLY change check, if different , set reg.
+
+ U8 ucdq_reg_pi[DQS_NUMBER], ucdq_reg_ui_large[DQS_NUMBER], ucdq_reg_ui_small[DQS_NUMBER];
+ U8 ucdq_reg_oen_ui_large[DQS_NUMBER], ucdq_reg_oen_ui_small[DQS_NUMBER];
+
+ U8 ucdq_reg_dqm_pi[DQS_NUMBER] = {0}, ucdq_reg_dqm_ui_large[DQS_NUMBER] = {0}, ucdq_reg_dqm_ui_small[DQS_NUMBER] = {0};
+ U8 ucdq_reg_dqm_oen_ui_large[DQS_NUMBER] = {0}, ucdq_reg_dqm_oen_ui_small[DQS_NUMBER] = {0};
+
+ #if 1//TX_DQM_CALC_MAX_MIN_CENTER
+ U16 u2Center_min[DQS_NUMBER],u2Center_max[DQS_NUMBER];
+ #endif
+ U8 u1EnableDelayCell=0, u1DelayCellOfst[DQ_DATA_WIDTH]={0};
+ U32 u4err_value, u4fail_bit;
+ U16 u2FinalRange=0, u2FinalVref=0xd;
+ U16 u2VrefLevel, u2VrefBegin, u2VrefEnd, u2VrefStep;
+ U16 u2TempWinSum, u2MaxWindowSum=0;//, u2tx_window_sum[LP4_TX_VREF_DATA_NUM]={0};
+ U8 u1min_bit, u1min_winsize=0;
+ U8 u1VrefIdx =0;
+ U8 u1PIDiff;
+ PASS_WIN_DATA_BY_VREF_T VrefInfo[LP4_TX_VREF_DATA_NUM];
+
+ if (!p)
+ {
+ mcSHOW_ERR_MSG(("context NULL\n"));
+ return DRAM_FAIL;
+ }
+
+#if VENDER_JV_LOG
+ if((calType ==TX_DQ_DQS_MOVE_DQ_ONLY && u1IsLP4Family(p->dram_type)) || (calType ==TX_DQ_DQS_MOVE_DQ_DQM && !u1IsLP4Family(p->dram_type)))
+ vPrintCalibrationBasicInfo_ForJV(p);
+#else
+ vPrintCalibrationBasicInfo(p);
+#endif
+
+ backup_rank = u1GetRank(p);
+
+ TXPerbitCalibrationInit(p, calType);
+ TXScanRange_PI(p, calType, &u2DQDelayBegin, &u2DQDelayEnd);
+ TXScanRange_Vref(p, u1VrefScanEnable, &u2FinalRange, &u2VrefBegin, &u2VrefEnd, &u2VrefStep);
+
+#ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+ U8 u1GUMP_INIT_RG_LOG_TO_DE_bak = gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag;
+ gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag=0;
+#endif
+
+ vSetCalibrationResult(p, DRAM_CALIBRATION_TX_PERBIT, DRAM_FAIL);
+
+#if 0
+ mcSHOW_DBG_MSG(("[TxWindowPerbitCal] calType=%d, VrefScanEnable %d (Range %d, VrefBegin %d, u2VrefEnd %d)\n"
+ "\nBegin, DQ Scan Range %d~%d\n",
+ calType, u1VrefScanEnable, u2FinalRange, u2VrefBegin, u2VrefEnd, u2DQDelayBegin, u2DQDelayEnd));
+
+ mcFPRINTF((fp_A60501, "[TxWindowPerbitCal] calType=%d, VrefScanEnable %d\n"
+ "\nBegin, DQ Scan Range %d~%d\n",
+ calType, u1VrefScanEnable, u2DQDelayBegin, u2DQDelayEnd));
+#endif
+
+ #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==1 && (p->Bypass_TXWINDOW))
+ {
+ for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+ {
+ u2Center_min[u1ByteIdx]=p->pSavetimeData->u1TxCenter_min_Save[p->channel][p->rank][u1ByteIdx];
+ u2Center_max[u1ByteIdx]=p->pSavetimeData->u1TxCenter_max_Save[p->channel][p->rank][u1ByteIdx];
+
+ for (u1BitIdx=0; u1BitIdx<DQS_BIT_NUMBER; u1BitIdx++)
+ {
+ u1BitTemp = u1ByteIdx*DQS_BIT_NUMBER+u1BitIdx;
+ FinalWinPerBit[u1BitTemp].win_center= p->pSavetimeData->u1Txwin_center_Save[p->channel][p->rank][u1BitTemp];
+ }
+ }
+
+ vSetCalibrationResult(p, DRAM_CALIBRATION_TX_PERBIT, DRAM_OK);
+ }
+ else
+ #endif
+ {
+ DramcEngine2Init(p, p->test2_1, p->test2_2, p->test_pattern, 0);
+
+ for(u2VrefLevel = u2VrefBegin; u2VrefLevel <= u2VrefEnd; u2VrefLevel += u2VrefStep)
+ {
+ // SET tx Vref (DQ) here, LP3 no need to set this.
+ if(u1VrefScanEnable)
+ {
+ #if 0//(!REDUCE_LOG_FOR_PRELOADER)
+ mcSHOW_DBG_MSG(("\n\n\tLP4 TX VrefRange %d, VrefLevel=%d\n", u2FinalRange, u2VrefLevel));
+ mcFPRINTF((fp_A60501, "\n\n\tLP4 TX VrefRange %d,VrefLevel=%d\n", u2FinalRange, u2VrefLevel));
+ #endif
+
+ #if VENDER_JV_LOG
+ if(calType ==TX_DQ_DQS_MOVE_DQ_ONLY)
+ {
+ mcSHOW_DBG_MSG5(("\n\n\tLP4 TX VrefRange %d, VrefLevel=%d\n", u2FinalRange, u2VrefLevel));
+ }
+ #endif
+
+ DramcTXSetVref(p, u2FinalRange, u2VrefLevel);
+ }
+ else
+ {
+ mcSHOW_DBG_MSG(("\n\n\tTX Vref Scan disable\n"));
+ mcFPRINTF((fp_A60501, "\n\n\tTX Vref Scan disable\n"));
+ }
+
+ // initialize parameters
+ uiFinishCount = 0;
+ u2TempWinSum =0;
+ ucdq_ui_small_reg_value = 0xff;
+
+ for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+ {
+ WinPerBit[u1BitIdx].first_pass = (S16)PASS_RANGE_NA;
+ WinPerBit[u1BitIdx].last_pass = (S16)PASS_RANGE_NA;
+ VrefWinPerBit[u1BitIdx].first_pass = (S16)PASS_RANGE_NA;
+ VrefWinPerBit[u1BitIdx].last_pass = (S16)PASS_RANGE_NA;
+ }
+
+ //Move DQ delay , 1 PI = tCK/64, total 128 PI, 1UI = 32 PI
+ //For data rate 3200, max tDQS2DQ is 2.56UI (82 PI)
+ //For data rate 4266, max tDQS2DQ is 3.41UI (109 PI)
+ for (uiDelay = u2DQDelayBegin; uiDelay <u2DQDelayEnd; uiDelay++)
+ {
+ TxWinTransferDelayToUIPI(p, calType, uiDelay, 0, &ucdq_ui_large, &ucdq_ui_small, &ucdq_pi, &ucdq_oen_ui_large, &ucdq_oen_ui_small);
+
+ // Check if TX UI changed, if not change , don't need to set reg again
+ if(ucdq_ui_small_reg_value != ucdq_ui_small)
+ {
+ u1UpdateRegUI=1;
+ ucdq_ui_small_reg_value = ucdq_ui_small;
+ }
+ else
+ u1UpdateRegUI=0;
+
+ for(u1ByteIdx=0; u1ByteIdx < DQS_NUMBER; u1ByteIdx++)
+ {
+ if(u1UpdateRegUI)
+ {
+ ucdq_reg_ui_large[u1ByteIdx] = ucdq_ui_large;
+ ucdq_reg_ui_small[u1ByteIdx] = ucdq_ui_small;
+ ucdq_reg_oen_ui_large[u1ByteIdx] = ucdq_oen_ui_large;
+ ucdq_reg_oen_ui_small[u1ByteIdx] = ucdq_oen_ui_small;
+
+ ucdq_reg_dqm_ui_large[u1ByteIdx] = ucdq_ui_large;
+ ucdq_reg_dqm_ui_small[u1ByteIdx] = ucdq_ui_small;
+ ucdq_reg_dqm_oen_ui_large[u1ByteIdx] = ucdq_oen_ui_large;
+ ucdq_reg_dqm_oen_ui_small[u1ByteIdx] = ucdq_oen_ui_small;
+ }
+
+ ucdq_reg_pi[u1ByteIdx] = ucdq_pi;
+ ucdq_reg_dqm_pi[u1ByteIdx] = ucdq_pi;
+ }
+
+ if(calType ==TX_DQ_DQS_MOVE_DQ_ONLY || calType== TX_DQ_DQS_MOVE_DQ_DQM)
+ {
+ TXSetDelayReg_DQ(p, u1UpdateRegUI, ucdq_reg_ui_large, ucdq_reg_oen_ui_large, ucdq_reg_ui_small, ucdq_reg_oen_ui_small, ucdq_reg_pi);
+ }
+
+ if(calType ==TX_DQ_DQS_MOVE_DQM_ONLY || calType== TX_DQ_DQS_MOVE_DQ_DQM)
+ {
+ TXSetDelayReg_DQM(p, u1UpdateRegUI, ucdq_reg_dqm_ui_large, ucdq_reg_dqm_oen_ui_large, ucdq_reg_dqm_ui_small, ucdq_reg_dqm_oen_ui_small, ucdq_reg_dqm_pi);
+ }
+
+ // audio +xtalk pattern
+ //u4err_value=0;
+ DramcEngine2SetPat(p,TEST_AUDIO_PATTERN, 0,0);
+ u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, TEST_AUDIO_PATTERN);
+ DramcEngine2SetPat(p,TEST_XTALK_PATTERN, 0,0);
+ u4err_value |= DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, TEST_XTALK_PATTERN);
+
+ if(u1VrefScanEnable==0 && (calType != TX_DQ_DQS_MOVE_DQM_ONLY))
+ {
+ //mcSHOW_DBG_MSG(("Delay=%3d |%2d %2d %3d| %2d %2d| 0x%8x [0]",uiDelay, ucdq_ui_large,ucdq_ui_small, ucdq_pi, ucdq_oen_ui_large,ucdq_oen_ui_small, u4err_value));
+ #ifdef ETT_PRINT_FORMAT
+ if(u4err_value !=0)
+ {
+ mcSHOW_DBG_MSG2(("%d |%d %d %d|[0]", uiDelay, ucdq_ui_large, ucdq_ui_small, ucdq_pi));
+ }
+ #else
+ mcSHOW_DBG_MSG2(("Delay=%3d |%2d %2d %3d| 0x%8x [0]", uiDelay, ucdq_ui_large, ucdq_ui_small, ucdq_pi, u4err_value));
+ #endif
+ mcFPRINTF((fp_A60501, "Delay=%3d | %2d %2d %3d| 0x%8x [0]", uiDelay, ucdq_ui_large,ucdq_ui_small, ucdq_pi, u4err_value));
+ }
+
+ // check fail bit ,0 ok ,others fail
+ for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+ {
+ u4fail_bit = u4err_value&((U32)1<<u1BitIdx);
+
+ if(u1VrefScanEnable==0 && (calType != TX_DQ_DQS_MOVE_DQM_ONLY))
+ {
+ if(u4err_value != 0)
+ {
+ if(u1BitIdx%DQS_BIT_NUMBER ==0)
+ {
+ mcSHOW_DBG_MSG2((" "));
+ mcFPRINTF((fp_A60501, " "));
+ }
+
+ if (u4fail_bit == 0)
+ {
+ mcSHOW_DBG_MSG2(("o"));
+ mcFPRINTF((fp_A60501, "o"));
+ }
+ else
+ {
+ mcSHOW_DBG_MSG2(("x"));
+ mcFPRINTF((fp_A60501, "x"));
+ }
+ }
+ }
+
+ if(WinPerBit[u1BitIdx].first_pass== PASS_RANGE_NA)
+ {
+ if(u4fail_bit==0) //compare correct: pass
+ {
+ WinPerBit[u1BitIdx].first_pass = uiDelay;
+
+ #if TX_TDQS2DQ_PRE_CAL
+ if((p->frequency == LP4_LOWEST_FREQ) && (u2DQS2DQ_Pre_Cal[p->channel][p->rank]==0))
+ {
+ u2DQS2DQ_Pre_Cal[p->channel][p->rank] = (uiDelay - u2DQDelayBegin) *850 / p->frequency;
+ }
+
+ if(uiDelay==u2DQDelayBegin)
+ {
+ mcSHOW_ERR_MSG(("TX_TDQS2DQ_PRE_CAL: Warning, possible miss TX window boundary\n"));
+ #if __ETT__
+ while(1);
+ #endif
+ }
+ #endif
+ }
+ }
+ else if(WinPerBit[u1BitIdx].last_pass == PASS_RANGE_NA)
+ {
+ if(u4fail_bit !=0) //compare error : fail
+ {
+ WinPerBit[u1BitIdx].last_pass = (uiDelay-1);
+ }
+ else if (uiDelay==u2DQDelayEnd)
+ {
+ WinPerBit[u1BitIdx].last_pass = uiDelay;
+ }
+
+ if(WinPerBit[u1BitIdx].last_pass !=PASS_RANGE_NA)
+ {
+ if((WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass) >= (VrefWinPerBit[u1BitIdx].last_pass -VrefWinPerBit[u1BitIdx].first_pass))
+ {
+ if((VrefWinPerBit[u1BitIdx].last_pass != PASS_RANGE_NA) && (VrefWinPerBit[u1BitIdx].last_pass -VrefWinPerBit[u1BitIdx].first_pass)>0)
+ {
+ mcSHOW_DBG_MSG2(("Bit[%d] Bigger window update %d > %d, window broken?\n", u1BitIdx, \
+ (WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass), (VrefWinPerBit[u1BitIdx].last_pass -VrefWinPerBit[u1BitIdx].first_pass)));
+ mcFPRINTF((fp_A60501,"Bit[%d] Bigger window update %d > %d\n", u1BitIdx, \
+ (WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass), (VrefWinPerBit[u1BitIdx].last_pass -VrefWinPerBit[u1BitIdx].first_pass)));
+
+ }
+
+ //if window size bigger than 7, consider as real pass window. If not, don't update finish counte and won't do early break;
+ if((WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass) >7)
+ uiFinishCount |= (1<<u1BitIdx);
+
+ //update bigger window size
+ VrefWinPerBit[u1BitIdx].first_pass = WinPerBit[u1BitIdx].first_pass;
+ VrefWinPerBit[u1BitIdx].last_pass = WinPerBit[u1BitIdx].last_pass;
+ }
+
+ //reset tmp window
+ WinPerBit[u1BitIdx].first_pass = PASS_RANGE_NA;
+ WinPerBit[u1BitIdx].last_pass = PASS_RANGE_NA;
+ }
+ }
+ }
+
+ if(u1VrefScanEnable==0 && (calType != TX_DQ_DQS_MOVE_DQM_ONLY))
+ {
+ if(u4err_value != 0)
+ {
+ mcSHOW_DBG_MSG2((" [MSB]\n"));
+ mcFPRINTF((fp_A60501, " [MSB]\n"));
+ }
+ }
+
+ //if all bits widnow found and all bits turns to fail again, early break;
+ if((u1IsLP4Family(p->dram_type) &&(uiFinishCount == 0xffff)) || \
+ ((p->dram_type == TYPE_LPDDR3) &&(uiFinishCount == 0xffffffff)))
+ {
+ vSetCalibrationResult(p, DRAM_CALIBRATION_TX_PERBIT, DRAM_OK);
+
+ #if !REDUCE_LOG_FOR_PRELOADER
+ #ifdef ETT_PRINT_FORMAT
+ mcSHOW_DBG_MSG2(("TX calibration finding left boundary early break. PI DQ delay=0x%B\n", uiDelay));
+ #else
+ mcSHOW_DBG_MSG2(("TX calibration finding left boundary early break. PI DQ delay=0x%2x\n", uiDelay));
+ #endif
+ #endif
+ break; //early break
+ }
+ }
+
+
+ // (1) calculate per bit window size
+ // (2) find out min win of all DQ bits
+ // (3) calculate perbit window center
+ u1min_winsize = 0xff;
+ u1min_bit = 0xff;
+ for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+ {
+ //if(VrefWinPerBit[u1BitIdx].last_pass == VrefWinPerBit[u1BitIdx].first_pass)
+ if(VrefWinPerBit[u1BitIdx].first_pass == PASS_RANGE_NA)
+ VrefWinPerBit[u1BitIdx].win_size = 0;
+ else
+ VrefWinPerBit[u1BitIdx].win_size= VrefWinPerBit[u1BitIdx].last_pass- VrefWinPerBit[u1BitIdx].first_pass +1;
+
+ if (VrefWinPerBit[u1BitIdx].win_size < u1min_winsize)
+ {
+ u1min_bit = u1BitIdx;
+ u1min_winsize = VrefWinPerBit[u1BitIdx].win_size;
+ }
+
+ u2TempWinSum += VrefWinPerBit[u1BitIdx].win_size; //Sum of CA Windows for vref selection
+
+ #if VENDER_JV_LOG
+ if((calType ==TX_DQ_DQS_MOVE_DQ_ONLY && u1IsLP4Family(p->dram_type)) || (calType ==TX_DQ_DQS_MOVE_DQ_DQM && !u1IsLP4Family(p->dram_type)))
+ {
+ mcSHOW_DBG_MSG5(("TX Bit%d, %d%%\n", u1BitIdx, (VrefWinPerBit[u1BitIdx].win_size*100+31)/32));
+ }
+ #endif
+
+
+ // calculate per bit window position and print
+ VrefWinPerBit[u1BitIdx].win_center= (VrefWinPerBit[u1BitIdx].first_pass + VrefWinPerBit[u1BitIdx].last_pass) >> 1;
+
+ #if PINMUX_AUTO_TEST_PER_BIT_TX
+ gFinalTXPerbitFirstPass[p->channel][u1BitIdx] = VrefWinPerBit[u1BitIdx].first_pass;
+ #endif
+ }
+
+ mcSHOW_DBG_MSG3(("Min Bit=%d, winsize=%d\n",u1min_bit, u1min_winsize));
+ #if __ETT__
+ if(u1VrefScanEnable==0)
+ {
+ //mcSHOW_DBG_MSG(("\n\tCH=%d, VrefRange= %d, VrefLevel = %d\n", p->channel, u2FinalRange, u2VrefLevel));
+ //mcFPRINTF((fp_A60501,"\n\tchannel=%d(2:cha, 3:chb) u2VrefLevel = %d\n", p->channel, u2VrefLevel));
+ TxPrintWidnowInfo(p, VrefWinPerBit);
+ }
+ #endif
+
+ if(u1VrefScanEnable==1)
+ {
+ if(u2TempWinSum > u2MaxWindowSum)
+ u2MaxWindowSum= u2TempWinSum;
+
+ VrefInfo[u1VrefIdx].u2VrefUsed = u2VrefLevel;
+ VrefInfo[u1VrefIdx].u2MinWinSize_byVref= u1min_winsize;
+ VrefInfo[u1VrefIdx].u2WinSum_byVref = u2TempWinSum;
+ u1VrefIdx ++;
+ }
+
+ #if LP4_TX_VREF_PASS_CONDITION
+ if(u1VrefScanEnable && (u2TempWinSum < (u2MaxWindowSum*95/100)) &&(u1min_winsize < LP4_TX_VREF_PASS_CONDITION))
+ #else
+ if(u1VrefScanEnable && (u2TempWinSum < (u2MaxWindowSum*95/100)))
+ #endif
+ {
+ mcSHOW_DBG_MSG(("\nTX Vref early break, caculate TX vref\n"));
+ break;
+ }
+ }
+
+ DramcEngine2End(p);
+
+ if(u1VrefScanEnable==0)// ..if time domain (not vref scan) , calculate window center of all bits.
+ {
+ // Calculate the center of DQ pass window
+ // Record center sum of each byte
+ for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+ {
+ #if 1//TX_DQM_CALC_MAX_MIN_CENTER
+ u2Center_min[u1ByteIdx] = 0xffff;
+ u2Center_max[u1ByteIdx] = 0;
+ #endif
+
+ for (u1BitIdx=0; u1BitIdx<DQS_BIT_NUMBER; u1BitIdx++)
+ {
+ u1BitTemp = u1ByteIdx * DQS_BIT_NUMBER + u1BitIdx;
+ memcpy(FinalWinPerBit, VrefWinPerBit, sizeof(PASS_WIN_DATA_T)*DQ_DATA_WIDTH);
+
+ if(FinalWinPerBit[u1BitTemp].win_center < u2Center_min[u1ByteIdx])
+ u2Center_min[u1ByteIdx] = FinalWinPerBit[u1BitTemp].win_center;
+
+ if(FinalWinPerBit[u1BitTemp].win_center > u2Center_max[u1ByteIdx])
+ u2Center_max[u1ByteIdx] = FinalWinPerBit[u1BitTemp].win_center;
+
+ #ifdef FOR_HQA_TEST_USED
+ if((u1IsLP4Family(p->dram_type) && calType == TX_DQ_DQS_MOVE_DQ_ONLY && (u1VrefScanEnable==0))
+ || (!u1IsLP4Family(p->dram_type) && (calType == TX_DQ_DQS_MOVE_DQ_DQM)))
+ {
+ gFinalTXPerbitWin[p->channel][p->rank][u1BitTemp] = FinalWinPerBit[u1BitTemp].win_size;
+ }
+ #endif
+ }
+ }
+
+ #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==0)//save firtst run pass value
+ {
+ for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+ {
+ if(calType == TX_DQ_DQS_MOVE_DQ_ONLY) // && u1VrefScanEnable==0
+ {
+ p->pSavetimeData->u1TxCenter_min_Save[p->channel][p->rank][u1ByteIdx]=u2Center_min[u1ByteIdx];
+ p->pSavetimeData->u1TxCenter_max_Save[p->channel][p->rank][u1ByteIdx]=u2Center_max[u1ByteIdx];
+
+ for (u1BitIdx=0; u1BitIdx<DQS_BIT_NUMBER; u1BitIdx++)
+ {
+ u1BitTemp = u1ByteIdx*DQS_BIT_NUMBER+u1BitIdx;
+ p->pSavetimeData->u1Txwin_center_Save[p->channel][p->rank][u1BitTemp]=FinalWinPerBit[u1BitTemp].win_center;
+ }
+ }
+ }
+ }
+ #endif
+ }
+ }
+
+ // SET tx Vref (DQ) = u2FinalVref, LP3 no need to set this.
+ if(u1IsLP4Family(p->dram_type) && (u1VrefScanEnable!=DISABLE_VREF_SCAN))
+ {
+ #if SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_VREF_CAL
+ if(p->femmc_Ready==1 && (p->Bypass_TXWINDOW) && u1VrefScanEnable!=SET_VREF_AND_DISABLE_VREF_SCAN)
+ {
+ u2FinalVref = p->pSavetimeData->u1TxWindowPerbitVref_Save[p->channel][p->rank];
+ }
+ else
+ #endif
+ {
+ if (u1VrefScanEnable==ENABLE_VREF_SCAN)
+ {
+ u2FinalVref = TxChooseVref(p, VrefInfo, u1VrefIdx);
+
+#ifdef DEVIATION
+ if (p->frequency == u2DFSGetHighestFreq(p) && gSetSpecificedVref_Enable[2]==ENABLE && ((p->channel==gSetSpecificedVref_Channel[2] && p->rank==gSetSpecificedVref_Rank[2]) || gSetSpecificedVref_All_ChRk[2]==ENABLE))
+ {
+ DeviationAddVrefOffset(2, &u2FinalRange, &u2FinalVref, gSetSpecificedVref_Vref_Offset[2]);
+ }
+#endif
+ }
+
+ #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==0)////save firtst run Vref value
+ {
+ p->pSavetimeData->u1TxWindowPerbitVref_Save[p->channel][p->rank]=u2FinalVref;
+ }
+ #endif
+ }
+ #ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+ gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag = u1GUMP_INIT_RG_LOG_TO_DE_bak;
+ #endif
+
+ TXSetFinalVref(p, u2FinalRange, u2FinalVref);
+ return DRAM_OK;
+ }
+
+
+#ifdef FOR_HQA_TEST_USED
+ // LP4 DQ time domain || LP3 DQ_DQM time domain
+ if((u1IsLP4Family(p->dram_type) && (calType == TX_DQ_DQS_MOVE_DQ_ONLY)) ||
+ (!u1IsLP4Family(p->dram_type) && (calType == TX_DQ_DQS_MOVE_DQ_DQM)))
+ {
+ gFinalTXPerbitWin_min_max[p->channel][p->rank] = u1min_winsize;
+ }
+#endif
+
+ // LP3 only use "TX_DQ_DQS_MOVE_DQ_DQM" scan
+ // first freq 800(LP4-1600) doesn't support jitter meter(data < 1T), therefore, don't use delay cell
+ if((calType == TX_DQ_DQS_MOVE_DQ_ONLY) && (p->frequency >= gu4TermFreq) && (p->u2DelayCellTimex100!=0))
+ {
+ u1EnableDelayCell =1;
+ mcSHOW_DBG_MSG(("[TX_PER_BIT_DELAY_CELL] DelayCellTimex100 =%d/100 ps\n", p->u2DelayCellTimex100));
+ }
+
+ //Calculate the center of DQ pass window
+ //average the center delay
+ for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+ {
+ mcSHOW_DBG_MSG((" == TX Byte %d ==\n", u1ByteIdx));
+ if(u1EnableDelayCell==0)
+ {
+ uiDelay = ((u2Center_min[u1ByteIdx] + u2Center_max[u1ByteIdx])>>1); //(max +min)/2
+ u2TX_DQ_PreCal_LP4[u1ByteIdx] = uiDelay; //LP4 only, for tDQS2DQ
+ }
+ else // if(calType == TX_DQ_DQS_MOVE_DQ_ONLY)
+ {
+ uiDelay = u2Center_min[u1ByteIdx]; // for DQ PI delay , will adjust with delay cell
+ u2TX_DQ_PreCal_LP4[u1ByteIdx] = ((u2Center_min[u1ByteIdx] + u2Center_max[u1ByteIdx])>>1); // for DQM PI delay
+
+ #if 0//SUPPORT_SAVE_TIME_FOR_CALIBRATION//BYPASS_TX_PER_BIT_DELAY_CELL
+ if(p->femmc_Ready==1 && (p->Bypass_TXWINDOW))
+ {
+ for (u1BitIdx = 0; u1BitIdx < DQS_BIT_NUMBER; u1BitIdx++)
+ {
+ u1BitTemp = u1ByteIdx*DQS_BIT_NUMBER+u1BitIdx;
+ u1DelayCellOfst[u1BitTemp] = p->pSavetimeData->u1TX_PerBit_DelayLine_Save[p->channel][p->rank][u1BitTemp];
+ }
+ }
+ else
+ #endif
+ {
+ // calculate delay cell perbit
+ for (u1BitIdx = 0; u1BitIdx < DQS_BIT_NUMBER; u1BitIdx++)
+ {
+ u1BitTemp = u1ByteIdx*DQS_BIT_NUMBER+u1BitIdx;
+ u1PIDiff = FinalWinPerBit[u1BitTemp].win_center - u2Center_min[u1ByteIdx];
+ if(p->u2DelayCellTimex100 !=0)
+ {
+ u1DelayCellOfst[u1BitTemp] = (u1PIDiff*100000000/(p->frequency<<6))/p->u2DelayCellTimex100;
+ #if 0//SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ p->pSavetimeData->u1TX_PerBit_DelayLine_Save[p->channel][p->rank][u1BitTemp] = u1DelayCellOfst[u1BitTemp];
+ #endif
+ mcSHOW_DBG_MSG(("u1DelayCellOfst[%d]=%d cells (%d PI)\n", u1BitTemp, u1DelayCellOfst[u1BitTemp], u1PIDiff));
+ }
+ else
+ {
+ mcSHOW_ERR_MSG(("Error: Cell time (p->u2DelayCellTimex100) is 0 \n"));
+ break;
+ }
+ }
+ }
+ }
+
+ TxWinTransferDelayToUIPI(p, calType, uiDelay, 1, &ucdq_reg_ui_large[u1ByteIdx], &ucdq_reg_ui_small[u1ByteIdx], &ucdq_reg_pi[u1ByteIdx],\
+ &ucdq_reg_oen_ui_large[u1ByteIdx], &ucdq_reg_oen_ui_small[u1ByteIdx]);
+
+ TxWinTransferDelayToUIPI(p, calType, u2TX_DQ_PreCal_LP4[u1ByteIdx], 1, &ucdq_reg_dqm_ui_large[u1ByteIdx], &ucdq_reg_dqm_ui_small[u1ByteIdx], &ucdq_reg_dqm_pi[u1ByteIdx],\
+ &ucdq_reg_dqm_oen_ui_large[u1ByteIdx], &ucdq_reg_dqm_oen_ui_small[u1ByteIdx]);
+
+ if(calType ==TX_DQ_DQS_MOVE_DQ_ONLY || calType== TX_DQ_DQS_MOVE_DQ_DQM)
+ {
+ mcSHOW_DBG_MSG(("Update DQ dly =%d (%d ,%d, %d) DQ OEN =(%d ,%d)\n",
+ uiDelay, ucdq_reg_ui_large[u1ByteIdx], ucdq_reg_ui_small[u1ByteIdx], ucdq_reg_pi[u1ByteIdx],\
+ ucdq_reg_oen_ui_large[u1ByteIdx], ucdq_reg_oen_ui_small[u1ByteIdx]));
+
+ mcFPRINTF((fp_A60501,"Byte%d, PI DQ dly %d\n", u1ByteIdx, uiDelay));
+ mcFPRINTF((fp_A60501,"Final DQ PI dly(LargeUI, SmallUI, PI) =(%d ,%d, %d)\n", ucdq_reg_ui_large[u1ByteIdx], ucdq_reg_ui_small[u1ByteIdx], ucdq_reg_pi[u1ByteIdx]));
+ mcFPRINTF((fp_A60501,"OEN DQ PI dly(LargeUI, SmallUI, PI) =(%d ,%d, %d)\n\n", ucdq_reg_oen_ui_large[u1ByteIdx], ucdq_reg_oen_ui_small[u1ByteIdx], ucdq_reg_pi[u1ByteIdx]));
+ }
+
+ //if(calType ==TX_DQ_DQS_MOVE_DQM_ONLY || calType== TX_DQ_DQS_MOVE_DQ_DQM)
+ {
+ mcSHOW_DBG_MSG(("Update DQM dly =%d (%d ,%d, %d) DQM OEN =(%d ,%d)",
+ u2TX_DQ_PreCal_LP4[u1ByteIdx], ucdq_reg_dqm_ui_large[u1ByteIdx], ucdq_reg_dqm_ui_small[u1ByteIdx], ucdq_reg_dqm_pi[u1ByteIdx], \
+ ucdq_reg_dqm_oen_ui_large[u1ByteIdx], ucdq_reg_dqm_oen_ui_small[u1ByteIdx]));
+ }
+ mcSHOW_DBG_MSG(("\n"));
+
+#ifdef FOR_HQA_REPORT_USED
+ if(calType == TX_DQ_DQS_MOVE_DQ_ONLY)
+ {
+ for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+ {
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT1, "TX_Window_Center_DQ", u1BitIdx, FinalWinPerBit[u1BitIdx].win_center, NULL);
+ }
+ }
+
+ if(calType == TX_DQ_DQS_MOVE_DQM_ONLY)
+ {
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0, "TX_Window_Center_DQM", u1ByteIdx, u2TX_DQ_PreCal_LP4[u1ByteIdx], NULL);
+ }
+#if 0
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT1, "TX_Window_Center_LargeUI", u1ByteIdx, ucdq_reg_ui_large[u1ByteIdx], NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0, "TX_Window_Center_SmallUI", u1ByteIdx, ucdq_reg_ui_small[u1ByteIdx], NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0, "TX_Window_Center_PI", u1ByteIdx, ucdq_reg_pi[u1ByteIdx], NULL);
+#endif
+#endif
+
+ }
+
+#ifdef DUMP_INIT_AND_K_RG_LOG_TO_DE
+ gDUMP_INIT_RG_LOG_TO_DE_RG_log_flag = u1GUMP_INIT_RG_LOG_TO_DE_bak;
+#endif
+
+#if REG_ACCESS_PORTING_DGB
+ RegLogEnable =1;
+#endif
+
+ /* p->rank = RANK_0, save to Reg Rank0 and Rank1, p->rank = RANK_1, save to Reg Rank1 */
+ for(u1RankIdx=p->rank; u1RankIdx<RANK_MAX; u1RankIdx++)
+ {
+ vSetRank(p,u1RankIdx);
+
+ if(calType ==TX_DQ_DQS_MOVE_DQ_ONLY || calType== TX_DQ_DQS_MOVE_DQ_DQM)
+ {
+ TXSetDelayReg_DQ(p, TRUE, ucdq_reg_ui_large, ucdq_reg_oen_ui_large, ucdq_reg_ui_small, ucdq_reg_oen_ui_small, ucdq_reg_pi);
+ }
+
+ TXSetDelayReg_DQM(p, TRUE, ucdq_reg_dqm_ui_large, ucdq_reg_dqm_oen_ui_large, ucdq_reg_dqm_ui_small, ucdq_reg_dqm_oen_ui_small, ucdq_reg_dqm_pi);
+
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ if(u1EnableDelayCell)
+ {
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ0),
+ P_Fld(u1DelayCellOfst[7] , SHU1_R0_B0_DQ0_RK0_TX_ARDQ7_DLY_B0)
+ | P_Fld(u1DelayCellOfst[6] , SHU1_R0_B0_DQ0_RK0_TX_ARDQ6_DLY_B0)
+ | P_Fld(u1DelayCellOfst[5] , SHU1_R0_B0_DQ0_RK0_TX_ARDQ5_DLY_B0)
+ | P_Fld(u1DelayCellOfst[4] , SHU1_R0_B0_DQ0_RK0_TX_ARDQ4_DLY_B0)
+ | P_Fld(u1DelayCellOfst[3] , SHU1_R0_B0_DQ0_RK0_TX_ARDQ3_DLY_B0)
+ | P_Fld(u1DelayCellOfst[2] , SHU1_R0_B0_DQ0_RK0_TX_ARDQ2_DLY_B0)
+ | P_Fld(u1DelayCellOfst[1] , SHU1_R0_B0_DQ0_RK0_TX_ARDQ1_DLY_B0)
+ | P_Fld(u1DelayCellOfst[0] , SHU1_R0_B0_DQ0_RK0_TX_ARDQ0_DLY_B0));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ0),
+ P_Fld(u1DelayCellOfst[15] , SHU1_R0_B1_DQ0_RK0_TX_ARDQ7_DLY_B1)
+ | P_Fld(u1DelayCellOfst[14] , SHU1_R0_B1_DQ0_RK0_TX_ARDQ6_DLY_B1)
+ | P_Fld(u1DelayCellOfst[13] , SHU1_R0_B1_DQ0_RK0_TX_ARDQ5_DLY_B1)
+ | P_Fld(u1DelayCellOfst[12] , SHU1_R0_B1_DQ0_RK0_TX_ARDQ4_DLY_B1)
+ | P_Fld(u1DelayCellOfst[11] , SHU1_R0_B1_DQ0_RK0_TX_ARDQ3_DLY_B1)
+ | P_Fld(u1DelayCellOfst[10] , SHU1_R0_B1_DQ0_RK0_TX_ARDQ2_DLY_B1)
+ | P_Fld(u1DelayCellOfst[9] , SHU1_R0_B1_DQ0_RK0_TX_ARDQ1_DLY_B1)
+ | P_Fld(u1DelayCellOfst[8] , SHU1_R0_B1_DQ0_RK0_TX_ARDQ0_DLY_B1));
+ }
+ }
+
+ #if ENABLE_TX_TRACKING
+ TXUpdateTXTracking(p, calType, ucdq_reg_pi, ucdq_reg_dqm_pi);
+ #endif
+ }
+
+ vSetRank(p, backup_rank);
+
+#if REG_ACCESS_PORTING_DGB
+ RegLogEnable =0;
+#endif
+
+ mcSHOW_DBG_MSG3(("[TxWindowPerbitCal] Done\n\n"));
+ mcFPRINTF((fp_A60501, "[TxWindowPerbitCal] Done\n\n"));
+
+ #if 0
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DRAMC_REG_PADCTL4), 1, PADCTL4_CKEFIXON); // test only
+ #endif
+
+ return DRAM_OK;
+}
+#endif //SIMULATION_TX_PERBIT
+
+#if EYESCAN_LOG
+void Dramc_K_TX_EyeScan_Log(DRAMC_CTX_T *p)
+{
+ U8 ucindex, u1BitIdx, u1ByteIdx;
+ U8 ii, u1vrefidx;
+ PASS_WIN_DATA_T WinPerBit[DQ_DATA_WIDTH], VrefWinPerBit[DQ_DATA_WIDTH], FinalWinPerBit[DQ_DATA_WIDTH];
+ U16 tx_pi_delay[4], tx_dqm_pi_delay[4];
+ U16 u2DQDelayBegin, uiDelay;
+ U16 u2VrefLevel, u2VrefBegin, u2VrefEnd, u2VrefStep, u2VrefRange;
+ U8 ucdq_pi, ucdq_ui_small, ucdq_ui_large,ucdq_oen_ui_small, ucdq_oen_ui_large;
+ U32 uiFinishCount;
+ U16 u2TempWinSum, u2tx_window_sum=0;
+ U32 u4err_value, u4fail_bit;
+ #if 1//TX_DQM_CALC_MAX_MIN_CENTER
+ U16 u2Center_min[DQS_NUMBER],u2Center_max[DQS_NUMBER];
+ #endif
+
+ U16 TXPerbitWin_min_max = 0;
+ U32 min_bit, min_winsize;
+
+ U16 u2FinalVref=0xd;
+ U16 u2FinalRange=0;
+
+ U8 EyeScan_index[DQ_DATA_WIDTH];
+
+ U8 backup_u1MR14Value;
+ U8 u1pass_in_this_vref_flag[DQ_DATA_WIDTH];
+
+ U32 u4RegBackupAddress[] =
+ {
+ (DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0)),
+ (DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2)),
+ (DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1)),
+ (DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3)),
+ (DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7)),
+ (DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7)),
+ };
+
+ if(gTX_EYE_Scan_flag==0) return;
+
+ if (gTX_EYE_Scan_only_higheset_freq_flag==1 && p->frequency != u2DFSGetHighestFreq(p)) return;
+
+
+ //backup register value
+ DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+ backup_u1MR14Value = u1MR14Value[p->channel][p->rank][p->dram_fsp];
+
+ //set initial values
+ for(u1vrefidx=0; u1vrefidx<VREF_TOTAL_NUM_WITH_RANGE;u1vrefidx++)
+ {
+ for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+ {
+ for(ii=0; ii<EYESCAN_BROKEN_NUM; ii++)
+ {
+ gEyeScan_Min[u1vrefidx][u1BitIdx][ii] = EYESCAN_DATA_INVALID;
+ gEyeScan_Max[u1vrefidx][u1BitIdx][ii] = EYESCAN_DATA_INVALID;
+ }
+ gEyeScan_ContinueVrefHeight[u1BitIdx] = 0;
+ gEyeScan_TotalPassCount[u1BitIdx] = 0;
+ }
+ }
+
+ for(u1ByteIdx=0; u1ByteIdx < p->data_width/DQS_BIT_NUMBER; u1ByteIdx++)
+ {
+ if (u1ByteIdx == 0)
+ {
+ tx_pi_delay[u1ByteIdx] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), SHURK0_SELPH_DQ0_TXDLY_DQ0) * 256 +
+ u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2), SHURK0_SELPH_DQ2_DLY_DQ0) * 32 +
+ u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+
+ tx_dqm_pi_delay[u1ByteIdx] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), SHURK0_SELPH_DQ1_TXDLY_DQM0) * 256 +
+ u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3), SHURK0_SELPH_DQ3_DLY_DQM0) * 32 +
+ u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+ }
+ else
+ {
+ tx_pi_delay[u1ByteIdx] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), SHURK0_SELPH_DQ0_TXDLY_DQ1) * 256 +
+ u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2), SHURK0_SELPH_DQ2_DLY_DQ1) * 32 +
+ u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), SHU1_R0_B1_DQ7_RK0_ARPI_DQ_B1);
+
+ tx_dqm_pi_delay[u1ByteIdx] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), SHURK0_SELPH_DQ1_TXDLY_DQM1) * 256 +
+ u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3), SHURK0_SELPH_DQ3_DLY_DQM1) * 32 +
+ u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), SHU1_R0_B1_DQ7_RK0_ARPI_DQM_B1);
+ }
+ }
+
+ if (tx_pi_delay[0] < tx_pi_delay[1])
+ {
+ u2DQDelayBegin = tx_pi_delay[0]-32;
+ }
+ else
+ {
+ u2DQDelayBegin = tx_pi_delay[1]-32;
+ }
+
+ u2VrefRange = 0;
+ u2VrefBegin = 0;
+ u2VrefEnd = 50;
+ u2VrefStep = 1;
+
+ DramcEngine2Init(p, p->test2_1, p->test2_2, p->test_pattern, 0);
+
+ for(u2VrefLevel = u2VrefBegin; u2VrefLevel <= u2VrefEnd; u2VrefLevel += u2VrefStep)
+ {
+ //set vref
+//fra u1MR14Value[p->channel][p->rank][p->dram_fsp] = (u2VrefLevel | (u2VrefRange<<6));
+ DramcModeRegWriteByRank(p, p->rank, 14, u2VrefLevel | (u2VrefRange<<6));
+
+ // initialize parameters
+ uiFinishCount = 0;
+ u2TempWinSum =0;
+
+ for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+ {
+ WinPerBit[u1BitIdx].first_pass = (S16)PASS_RANGE_NA;
+ WinPerBit[u1BitIdx].last_pass = (S16)PASS_RANGE_NA;
+ VrefWinPerBit[u1BitIdx].first_pass = (S16)PASS_RANGE_NA;
+ VrefWinPerBit[u1BitIdx].last_pass = (S16)PASS_RANGE_NA;
+
+ gEyeScan_DelayCellPI[u1BitIdx] = 0;
+
+ EyeScan_index[u1BitIdx] = 0;
+ u1pass_in_this_vref_flag[u1BitIdx] = 0;
+ }
+
+ for (uiDelay=0; uiDelay<64; uiDelay++)
+ {
+ TxWinTransferDelayToUIPI(p, TX_DQ_DQS_MOVE_DQ_DQM, tx_pi_delay[0]+uiDelay-32, 0, &ucdq_ui_large, &ucdq_ui_small, &ucdq_pi, &ucdq_oen_ui_large, &ucdq_oen_ui_small);
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), \
+ P_Fld(ucdq_ui_large, SHURK0_SELPH_DQ0_TXDLY_DQ0) | \
+ P_Fld(ucdq_oen_ui_large, SHURK0_SELPH_DQ0_TXDLY_OEN_DQ0));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2), \
+ P_Fld(ucdq_ui_small, SHURK0_SELPH_DQ2_DLY_DQ0) | \
+ P_Fld(ucdq_oen_ui_small, SHURK0_SELPH_DQ2_DLY_OEN_DQ0));
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdq_pi, SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+
+ TxWinTransferDelayToUIPI(p, TX_DQ_DQS_MOVE_DQ_DQM, tx_pi_delay[1]+uiDelay-32, 0, &ucdq_ui_large, &ucdq_ui_small, &ucdq_pi, &ucdq_oen_ui_large, &ucdq_oen_ui_small);
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), \
+ P_Fld(ucdq_ui_large, SHURK0_SELPH_DQ0_TXDLY_DQ1) | \
+ P_Fld(ucdq_oen_ui_large, SHURK0_SELPH_DQ0_TXDLY_OEN_DQ1));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ2), \
+ P_Fld(ucdq_ui_small, SHURK0_SELPH_DQ2_DLY_DQ1) | \
+ P_Fld(ucdq_oen_ui_small, SHURK0_SELPH_DQ2_DLY_OEN_DQ1));
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), ucdq_pi, SHU1_R0_B1_DQ7_RK0_ARPI_DQ_B1);
+
+ TxWinTransferDelayToUIPI(p, TX_DQ_DQS_MOVE_DQ_DQM, tx_dqm_pi_delay[0]+uiDelay-32, 0, &ucdq_ui_large, &ucdq_ui_small, &ucdq_pi, &ucdq_oen_ui_large, &ucdq_oen_ui_small);
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), \
+ P_Fld(ucdq_ui_large, SHURK0_SELPH_DQ1_TXDLY_DQM0) | \
+ P_Fld(ucdq_oen_ui_large, SHURK0_SELPH_DQ1_TXDLY_OEN_DQM0));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3), \
+ P_Fld(ucdq_ui_small, SHURK0_SELPH_DQ3_DLY_DQM0) | \
+ P_Fld(ucdq_oen_ui_small, SHURK0_SELPH_DQ3_DLY_OEN_DQM0));
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), ucdq_pi, SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+
+ TxWinTransferDelayToUIPI(p, TX_DQ_DQS_MOVE_DQ_DQM, tx_dqm_pi_delay[1]+uiDelay-32, 0, &ucdq_ui_large, &ucdq_ui_small, &ucdq_pi, &ucdq_oen_ui_large, &ucdq_oen_ui_small);
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), \
+ P_Fld(ucdq_ui_large, SHURK0_SELPH_DQ1_TXDLY_DQM1) | \
+ P_Fld(ucdq_oen_ui_large, SHURK0_SELPH_DQ1_TXDLY_OEN_DQM1));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ3), \
+ P_Fld(ucdq_ui_small, SHURK0_SELPH_DQ3_DLY_DQM1) | \
+ P_Fld(ucdq_oen_ui_small, SHURK0_SELPH_DQ3_DLY_OEN_DQM1));
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), ucdq_pi, SHU1_R0_B1_DQ7_RK0_ARPI_DQM_B1);
+
+
+ // audio +xtalk pattern
+ u4err_value=0;
+ DramcEngine2SetPat(p,TEST_AUDIO_PATTERN, 0,0);
+ u4err_value = DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, TEST_AUDIO_PATTERN);
+ DramcEngine2SetPat(p,TEST_XTALK_PATTERN, 0,0);
+ u4err_value |= DramcEngine2Run(p, TE_OP_WRITE_READ_CHECK, TEST_XTALK_PATTERN);
+
+ // check fail bit ,0 ok ,others fail
+ for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+ {
+ u4fail_bit = u4err_value&((U32)1<<u1BitIdx);
+
+ if (u4fail_bit == 0)
+ {
+ gEyeScan_TotalPassCount[u1BitIdx]++;
+ }
+
+ if(WinPerBit[u1BitIdx].first_pass== PASS_RANGE_NA)
+ {
+ if(u4fail_bit==0) //compare correct: pass
+ {
+ WinPerBit[u1BitIdx].first_pass = uiDelay;
+ u1pass_in_this_vref_flag[u1BitIdx] = 1;
+ }
+ }
+ else if(WinPerBit[u1BitIdx].last_pass == PASS_RANGE_NA)
+ {
+ if(u4fail_bit !=0) //compare error : fail
+ {
+ WinPerBit[u1BitIdx].last_pass = (uiDelay-1);
+ }
+ else if (uiDelay==64)
+ {
+ WinPerBit[u1BitIdx].last_pass = uiDelay;
+ }
+
+ if(WinPerBit[u1BitIdx].last_pass !=PASS_RANGE_NA)
+ {
+ if((WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass) >= (VrefWinPerBit[u1BitIdx].last_pass -VrefWinPerBit[u1BitIdx].first_pass))
+ {
+ //if window size bigger than 7, consider as real pass window. If not, don't update finish counte and won't do early break;
+ if((WinPerBit[u1BitIdx].last_pass -WinPerBit[u1BitIdx].first_pass) >7)
+ uiFinishCount |= (1<<u1BitIdx);
+
+ //update bigger window size
+ VrefWinPerBit[u1BitIdx].first_pass = WinPerBit[u1BitIdx].first_pass;
+ VrefWinPerBit[u1BitIdx].last_pass = WinPerBit[u1BitIdx].last_pass;
+ }
+
+#if EYESCAN_LOG
+ if (EyeScan_index[u1BitIdx] < EYESCAN_BROKEN_NUM)
+ {
+#if VENDER_JV_LOG || defined(RELEASE)
+ gEyeScan_Min[u2VrefLevel+u2VrefRange*30][u1BitIdx][EyeScan_index[u1BitIdx]] = WinPerBit[u1BitIdx].first_pass;
+ gEyeScan_Max[u2VrefLevel+u2VrefRange*30][u1BitIdx][EyeScan_index[u1BitIdx]] = WinPerBit[u1BitIdx].last_pass;
+#else
+ gEyeScan_Min[u2VrefLevel+u2VrefRange*30][u1BitIdx][EyeScan_index[u1BitIdx]] = WinPerBit[u1BitIdx].first_pass + tx_pi_delay[u1BitIdx/8]-32;
+ gEyeScan_Max[u2VrefLevel+u2VrefRange*30][u1BitIdx][EyeScan_index[u1BitIdx]] = WinPerBit[u1BitIdx].last_pass + tx_pi_delay[u1BitIdx/8]-32;
+#endif
+ EyeScan_index[u1BitIdx]=EyeScan_index[u1BitIdx]+1;
+ }
+#endif
+
+ //reset tmp window
+ WinPerBit[u1BitIdx].first_pass = PASS_RANGE_NA;
+ WinPerBit[u1BitIdx].last_pass = PASS_RANGE_NA;
+ }
+ }
+ }
+ }
+
+ min_winsize = 0xffff;
+ min_bit = 0xff;
+ for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+ {
+ VrefWinPerBit[u1BitIdx].win_size = VrefWinPerBit[u1BitIdx].last_pass- VrefWinPerBit[u1BitIdx].first_pass +(VrefWinPerBit[u1BitIdx].last_pass==VrefWinPerBit[u1BitIdx].first_pass?0:1);
+
+ if (VrefWinPerBit[u1BitIdx].win_size < min_winsize)
+ {
+ min_bit = u1BitIdx;
+ min_winsize = VrefWinPerBit[u1BitIdx].win_size;
+ }
+
+ u2TempWinSum += VrefWinPerBit[u1BitIdx].win_size; //Sum of CA Windows for vref selection
+
+#if EYESCAN_LOG
+ gEyeScan_WinSize[u2VrefLevel+u2VrefRange*30][u1BitIdx] = VrefWinPerBit[u1BitIdx].win_size;
+#endif
+
+#ifdef FOR_HQA_TEST_USED
+ if((((u1MR14Value[p->channel][p->rank][p->dram_fsp]>>6)&1) == u2VrefRange) && ((u1MR14Value[p->channel][p->rank][p->dram_fsp]&0x3f)==u2VrefLevel))
+ {
+ gFinalTXPerbitWin[p->channel][p->rank][u1BitIdx] = VrefWinPerBit[u1BitIdx].win_size;
+ }
+#endif
+ }
+
+ if ((min_winsize > TXPerbitWin_min_max) || ((min_winsize == TXPerbitWin_min_max) && (u2TempWinSum >u2tx_window_sum)))
+ {
+ TXPerbitWin_min_max = min_winsize;
+ u2tx_window_sum =u2TempWinSum;
+ u2FinalRange = u2VrefRange;
+ u2FinalVref = u2VrefLevel;
+
+ //Calculate the center of DQ pass window
+ // Record center sum of each byte
+ for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+ {
+ #if 1//TX_DQM_CALC_MAX_MIN_CENTER
+ u2Center_min[u1ByteIdx] = 0xffff;
+ u2Center_max[u1ByteIdx] = 0;
+ #endif
+
+ for (u1BitIdx=0; u1BitIdx<DQS_BIT_NUMBER; u1BitIdx++)
+ {
+ ucindex = u1ByteIdx * DQS_BIT_NUMBER + u1BitIdx;
+ FinalWinPerBit[ucindex].first_pass = VrefWinPerBit[ucindex].first_pass;
+ FinalWinPerBit[ucindex].last_pass = VrefWinPerBit[ucindex].last_pass;
+ FinalWinPerBit[ucindex].win_size = VrefWinPerBit[ucindex].win_size;
+ FinalWinPerBit[ucindex].win_center = (FinalWinPerBit[ucindex].first_pass + FinalWinPerBit[ucindex].last_pass) >> 1;
+
+ if(FinalWinPerBit[ucindex].win_center < u2Center_min[u1ByteIdx])
+ u2Center_min[u1ByteIdx] = FinalWinPerBit[ucindex].win_center;
+
+ if(FinalWinPerBit[ucindex].win_center > u2Center_max[u1ByteIdx])
+ u2Center_max[u1ByteIdx] = FinalWinPerBit[ucindex].win_center;
+ }
+ }
+ }
+
+
+ if(u2VrefRange==0 && u2VrefLevel ==50)
+ {
+ u2VrefRange = 1;
+ u2VrefLevel = 20;
+ }
+
+ for (u1BitIdx = 0; u1BitIdx < p->data_width; u1BitIdx++)
+ {
+ if (u1pass_in_this_vref_flag[u1BitIdx]) gEyeScan_ContinueVrefHeight[u1BitIdx]++; //count pass number of continue vref
+ }
+ }
+
+ DramcEngine2End(p);
+
+ //Calculate the center of DQ pass window
+ //average the center delay
+ for (u1ByteIdx=0; u1ByteIdx<(p->data_width/DQS_BIT_NUMBER); u1ByteIdx++)
+ {
+ uiDelay = ((u2Center_min[u1ByteIdx] + u2Center_max[u1ByteIdx])>>1); //(max +min)/2
+
+#if EYESCAN_LOG
+#if VENDER_JV_LOG || defined(RELEASE)
+ gEyeScan_CaliDelay[u1ByteIdx] = uiDelay;
+#else
+ gEyeScan_CaliDelay[u1ByteIdx] = uiDelay + tx_pi_delay[u1ByteIdx]-32;
+#endif
+#endif
+ }
+
+
+ //restore to orignal value
+ DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+
+ DramcModeRegWriteByRank(p, p->rank, 14, backup_u1MR14Value);
+ u1MR14Value[p->channel][p->rank][p->dram_fsp] = backup_u1MR14Value;
+
+}
+#endif
+
+
+#ifdef FOR_HQA_TEST_USED
+void HQA_measure_message_reset_all_data(DRAMC_CTX_T *p)
+{
+ U32 u1BitIdx, u1RankIdx, u1ChannelIdx;
+
+ for(u1ChannelIdx=CHANNEL_A; u1ChannelIdx<CHANNEL_NUM; u1ChannelIdx++)
+ {
+ for(u1RankIdx=RANK_0; u1RankIdx<RANK_MAX; u1RankIdx++)
+ {
+ for (u1BitIdx=0; u1BitIdx<p->data_width; u1BitIdx++)
+ {
+ gFinalRXPerbitWin[u1ChannelIdx][u1RankIdx][u1BitIdx] =0;
+ gFinalTXPerbitWin[u1ChannelIdx][u1RankIdx][u1BitIdx] =0;
+ }
+ }
+ }
+}
+#endif
+
+#ifdef FOR_HQA_REPORT_USED
+void print_EyeScanVcent_for_HQA_report_used(DRAMC_CTX_T *p, U8 print_type, U8 u1ChannelIdx, U8 u1RankIdx, U8 *EyeScanVcent, U8 EyeScanVcentUpperBound, U8 EyeScanVcentUpperBound_bit, U8 EyeScanVcentLowerBound, U8 EyeScanVcentLowerBound_bit)
+{
+ U32 uiCA, u1BitIdx;
+ U16 *pCBTVref_Voltage_Table[VREF_VOLTAGE_TABLE_NUM];
+ U16 *pTXVref_Voltage_Table[VREF_VOLTAGE_TABLE_NUM];
+ U8 CBTVrefRange;
+ U8 TXVrefRange;
+ U32 vddq;
+ U8 local_channel_num=2;
+ U8 shuffleIdx;
+ U8 u1CBTEyeScanEnable, u1RXEyeScanEnable, u1TXEyeScanEnable;
+
+ mcSHOW_DBG_MSG(("\n"));
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ local_channel_num = p->support_channel_num;
+ }
+ else
+ {
+ //LP3
+ local_channel_num = 1;
+ }
+
+ u1CBTEyeScanEnable = (gCBT_EYE_Scan_flag==1 && ((gCBT_EYE_Scan_only_higheset_freq_flag==1 && p->frequency == u2DFSGetHighestFreq(p)) || gCBT_EYE_Scan_only_higheset_freq_flag==0));
+ u1RXEyeScanEnable = (gRX_EYE_Scan_flag==1 && ((gRX_EYE_Scan_only_higheset_freq_flag==1 && p->frequency == u2DFSGetHighestFreq(p)) || gRX_EYE_Scan_only_higheset_freq_flag==0));
+ u1TXEyeScanEnable = (gTX_EYE_Scan_flag==1 && ((gTX_EYE_Scan_only_higheset_freq_flag==1 && p->frequency == u2DFSGetHighestFreq(p)) || gTX_EYE_Scan_only_higheset_freq_flag==0));
+
+ shuffleIdx = get_shuffleIndex_by_Freq(p);
+
+ if (gHQALog_flag==1 && print_type==0)
+ {
+ if (u1CBTEyeScanEnable)
+ {
+ if (p->dram_type == TYPE_LPDDR4)
+ {
+ pCBTVref_Voltage_Table[VREF_RANGE_0] = (U16 *)gVref_Voltage_Table_LP4[VREF_RANGE_0];
+ pCBTVref_Voltage_Table[VREF_RANGE_1] = (U16 *)gVref_Voltage_Table_LP4[VREF_RANGE_1];
+ }
+ if (p->dram_type == TYPE_LPDDR4X)
+ {
+ pCBTVref_Voltage_Table[VREF_RANGE_0] = (U16 *)gVref_Voltage_Table_LP4X[VREF_RANGE_0];
+ pCBTVref_Voltage_Table[VREF_RANGE_1] = (U16 *)gVref_Voltage_Table_LP4X[VREF_RANGE_1];
+ }
+
+ CBTVrefRange = (u1MR12Value[p->channel][p->rank][p->dram_fsp]>>6)&1;
+ vddq=vGetVoltage(p, 2)/1000; //mv
+
+ mcSHOW_DBG_MSG(("\n\n\n[HQA] information for measurement, "));
+ mcSHOW_DBG_MSG(("\tDram Data rate = %d\n",p->frequency*2));
+
+ mcSHOW_DBG_MSG(("CBT Eye Scan Vcent Voltage\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "CBT_Final_Vref Vcent", 0, pCBTVref_Voltage_Table[EyeScanVcent[0]][EyeScanVcent[1]]*vddq/100, NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "CBT_VdlVWHigh_Upper Vcent", 0, pCBTVref_Voltage_Table[EyeScanVcent[2]][EyeScanVcent[3]]*vddq/100, NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "CBT_VdlVWHigh_Lower Vcent", 0, pCBTVref_Voltage_Table[EyeScanVcent[4]][EyeScanVcent[5]]*vddq/100, NULL);
+
+ mcSHOW_DBG_MSG(("\n"));
+
+ mcSHOW_DBG_MSG(("CBT Eye Scan Vcent_UpperBound window\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "CBT_Vcent_UpperBound_Window", 0, EyeScanVcentUpperBound, NULL);
+ mcSHOW_DBG_MSG(("CBT Eye Scan Vcent_UpperBound_Window worse bit\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "CBT_Vcent_UpperBound_Window_bit", 0, EyeScanVcentUpperBound_bit, NULL);
+ mcSHOW_DBG_MSG(("CBT Eye Scan Vcent_UpperBound Min Window(%%)\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "CBT_Vcent_UpperBound_Window(%)", 0, (EyeScanVcentUpperBound * 100 + (u1IsLP4Family(p->dram_type)==1?63:31)) / (u1IsLP4Family(p->dram_type)==1?64:32), NULL);
+ mcSHOW_DBG_MSG(("CBT Eye Scan Vcent_UpperBound Min Window PASS/FAIL\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT4, "CBT_Vcent_UpperBound_Window_PF", 0, 0, (EyeScanVcentUpperBound * 100 + (u1IsLP4Family(p->dram_type)==1?63:31)) / (u1IsLP4Family(p->dram_type)==1?64:32) >= 25 ? "PASS" : "FAIL");
+
+ mcSHOW_DBG_MSG(("\n"));
+
+
+ mcSHOW_DBG_MSG(("CBT Eye Scan Vcent_LowerBound window\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "CBT_Vcent_LowerBound_Window", 0, EyeScanVcentLowerBound, NULL);
+ mcSHOW_DBG_MSG(("CBT Eye Scan Vcent_LowerBound_Window worse bit\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "CBT_Vcent_LowerBound_Window_bit", 0, EyeScanVcentLowerBound_bit, NULL);
+ mcSHOW_DBG_MSG(("CBT Eye Scan Vcent_UpperBound Min Window(%%)\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "CBT_Vcent_LowerBound_Window(%)", 0, (EyeScanVcentLowerBound * 100 + (u1IsLP4Family(p->dram_type)==1?63:31)) / (u1IsLP4Family(p->dram_type)==1?64:32), NULL);
+ mcSHOW_DBG_MSG(("CBT Eye Scan Vcent_LowerBound Min Window PASS/FAIL\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT4, "CBT_Vcent_LowerBound_Window_PF", 0, 0, (EyeScanVcentLowerBound * 100 + (u1IsLP4Family(p->dram_type)==1?63:31)) / (u1IsLP4Family(p->dram_type)==1?64:32) >= 25 ? "PASS" : "FAIL");
+
+ mcSHOW_DBG_MSG(("\n"));
+ mcSHOW_DBG_MSG(("CA Eye Scan per_bit window(%%)\n"));
+ for (uiCA=0; uiCA<CATRAINING_NUM_LP4; uiCA++)
+ {
+#if EYESCAN_LOG
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_2, "CA_Perbit_Window(%)", uiCA, ((gEyeScan_WinSize[EyeScanVcent[0]*30+EyeScanVcent[1]][uiCA]) * 100 + 31) / 32, NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_2, "CA_Perbit_BestWindow(%)", uiCA, ((gEyeScan_WinSize[EyeScanVcent[10+uiCA*2]*30+EyeScanVcent[10+uiCA*2+1]][uiCA]) * 100 + 31) / 32, NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_2, "CA_Perbit_Window_Upperbond(%)", uiCA, ((gEyeScan_WinSize[EyeScanVcent[2]*30+EyeScanVcent[3]][uiCA]) * 100 + 31) / 32, NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_2, "CA_Perbit_Window_Lowerbond(%) ", uiCA, ((gEyeScan_WinSize[EyeScanVcent[4]*30+EyeScanVcent[5]][uiCA]) * 100 + 31) / 32, NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_2, "CA_Perbit_Eye_Height", uiCA, (gEyeScan_ContinueVrefHeight[uiCA]-1)*6*vddq/1000, NULL);
+// HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_2, "CA_Perbit_Eye_Area", uiCA, gEyeScan_TotalPassCount[uiCA]*1000*3*vddq/(32*DDRPhyFMeter()), NULL); //total count*1/32UI*(1/freq*10^6 ps)*(0.6%vddq)
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_2, "CA_Perbit_Eye_Area", uiCA, (gEyeScan_TotalPassCount[uiCA]*10*3*vddq/(32*DDRPhyFMeter()))*100, NULL); //total count*1/32UI*(1/freq*10^6 ps)*(0.6%vddq)
+#endif
+ }
+ }
+ }
+
+ if (gHQALog_flag==1 && print_type==1)
+ {
+ if (u1RXEyeScanEnable)
+ {
+ mcSHOW_DBG_MSG(("\n\n\n[HQA] information for measurement, "));
+ mcSHOW_DBG_MSG(("\tDram Data rate = %d\n",p->frequency*2));
+
+ mcSHOW_DBG_MSG(("RX Eye Scan Vcent Voltage\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "RX_Final_Vref Vcent", 0, gRXVref_Voltage_Table_LP4[EyeScanVcent[0]], NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "RX_VdlVWHigh_Upper Vcent", 0, gRXVref_Voltage_Table_LP4[EyeScanVcent[1]], NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "RX_VdlVWHigh_Lower Vcent", 0, gRXVref_Voltage_Table_LP4[EyeScanVcent[2]], NULL);
+
+ mcSHOW_DBG_MSG(("\n"));
+
+ mcSHOW_DBG_MSG(("RX Eye Scan Vcent_UpperBound window\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "RX_Vcent_UpperBound_Window", 0, EyeScanVcentUpperBound, NULL);
+ mcSHOW_DBG_MSG(("RX Eye Scan Vcent_UpperBound_Window worse bit\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "RX_Vcent_UpperBound_Window_bit", 0, EyeScanVcentUpperBound_bit, NULL);
+ mcSHOW_DBG_MSG(("RX Eye Scan Vcent_UpperBound Min Window(%%)\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "RX_Vcent_UpperBound_Window(%)", 0, ((EyeScanVcentUpperBound * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000, NULL);
+ mcSHOW_DBG_MSG(("RX Eye Scan Vcent_UpperBound Min Window PASS/FAIL\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT4, "RX_Vcent_UpperBound_Window_PF", 0, 0, ((EyeScanVcentUpperBound * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000 >= 20 ? "PASS" : "FAIL");
+
+ mcSHOW_DBG_MSG(("\n"));
+
+
+ mcSHOW_DBG_MSG(("RX Eye Scan Vcent_LowerBound window\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "RX_Vcent_LowerBound_Window", 0, EyeScanVcentLowerBound, NULL);
+ mcSHOW_DBG_MSG(("RX Eye Scan Vcent_LowerBound_Window worse bit\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "RX_Vcent_LowerBound_Window_bit", 0, EyeScanVcentLowerBound_bit, NULL);
+ mcSHOW_DBG_MSG(("RX Eye Scan Vcent_UpperBound Min Window(%%)\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "RX_Vcent_LowerBound_Window(%)", 0, ((EyeScanVcentLowerBound * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000, NULL);
+ mcSHOW_DBG_MSG(("RX Eye Scan Vcent_LowerBound Min Window PASS/FAIL\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT4, "RX_Vcent_LowerBound_Window_PF", 0, 0, ((EyeScanVcentLowerBound * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000 >= 20 ? "PASS" : "FAIL");
+
+
+ mcSHOW_DBG_MSG(("\n"));
+ mcSHOW_DBG_MSG(("RX Eye Scan per_bit window(%%)\n"));
+ for (u1BitIdx=0; u1BitIdx<p->data_width; u1BitIdx++)
+ {
+#if EYESCAN_LOG
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "RX_Perbit_Window(%)", u1BitIdx, ((gEyeScan_WinSize[EyeScanVcent[0]][u1BitIdx] * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000, NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "RX_Perbit_BestWindow(%)", u1BitIdx, ((gEyeScan_WinSize[EyeScanVcent[10+u1BitIdx]][u1BitIdx] * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000, NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "RX_Perbit_Window_Upperbond(%)", u1BitIdx, ((gEyeScan_WinSize[EyeScanVcent[1]][u1BitIdx] * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000, NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "RX_Perbit_Window_Lowerbond(%) ", u1BitIdx, ((gEyeScan_WinSize[EyeScanVcent[2]][u1BitIdx] * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000, NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "RX_Perbit_Eye_Height", u1BitIdx, (gEyeScan_ContinueVrefHeight[u1BitIdx]-1)*1330/100, NULL); //RX vref height 1225 ~ 1440, use 1330mv
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "RX_Perbit_Eye_Area", u1BitIdx, gEyeScan_TotalPassCount[u1BitIdx]*u2gdelay_cell_ps_all[get_shuffleIndex_by_Freq(p)][u1ChannelSet[0]]*133/1000, NULL); //total count*jitter metter delay cell*(1/freq*10^6 ps)*(1330mv)
+#endif
+ }
+ }
+ }
+
+ if (gHQALog_flag==1 && print_type==2)
+ {
+ if (u1TXEyeScanEnable)
+ {
+ if (p->dram_type == TYPE_LPDDR4)
+ {
+ pTXVref_Voltage_Table[VREF_RANGE_0] = (U16 *)gVref_Voltage_Table_LP4[VREF_RANGE_0];
+ pTXVref_Voltage_Table[VREF_RANGE_1] = (U16 *)gVref_Voltage_Table_LP4[VREF_RANGE_1];
+ }
+ if (p->dram_type == TYPE_LPDDR4X)
+ {
+ pTXVref_Voltage_Table[VREF_RANGE_0] = (U16 *)gVref_Voltage_Table_LP4X[VREF_RANGE_0];
+ pTXVref_Voltage_Table[VREF_RANGE_1] = (U16 *)gVref_Voltage_Table_LP4X[VREF_RANGE_1];
+ }
+
+ TXVrefRange = (u1MR14Value[p->channel][p->rank][p->dram_fsp]>>6)&1;
+ vddq=vGetVoltage(p, 2)/1000; //mv
+
+ mcSHOW_DBG_MSG(("\n\n\n[HQA] information for measurement, "));
+ mcSHOW_DBG_MSG(("\tDram Data rate = %d\n",p->frequency*2));
+
+ mcSHOW_DBG_MSG(("TX Eye Scan Vcent Voltage\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "TX_Final_Vref Vcent", 0, pTXVref_Voltage_Table[EyeScanVcent[0]][EyeScanVcent[1]]*vddq/100, NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "TX_VdlVWHigh_Upper Vcent", 0, pTXVref_Voltage_Table[EyeScanVcent[2]][EyeScanVcent[3]]*vddq/100, NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "TX_VdlVWHigh_Lower Vcent", 0, pTXVref_Voltage_Table[EyeScanVcent[4]][EyeScanVcent[5]]*vddq/100, NULL);
+
+ mcSHOW_DBG_MSG(("\n"));
+
+ mcSHOW_DBG_MSG(("TX Eye Scan Vcent_UpperBound window\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "TX_Vcent_UpperBound_Window", 0, EyeScanVcentUpperBound, NULL);
+ mcSHOW_DBG_MSG(("TX Eye Scan Vcent_UpperBound_Window worse bit\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "TX_Vcent_UpperBound_Window_bit", 0, EyeScanVcentUpperBound_bit, NULL);
+ mcSHOW_DBG_MSG(("TX Eye Scan Vcent_UpperBound Min Window(%%)\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "TX_Vcent_UpperBound_Window(%)", 0, (EyeScanVcentUpperBound * 100 + 31) / 32, NULL);
+ mcSHOW_DBG_MSG(("TX Eye Scan Vcent_UpperBound Min Window PASS/FAIL\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT4, "TX_Vcent_UpperBound_Window_PF", 0, 0, (EyeScanVcentUpperBound * 100 + 31) / 32 >= 20 ? "PASS" : "FAIL");
+
+ mcSHOW_DBG_MSG(("\n"));
+
+ mcSHOW_DBG_MSG(("TX Eye Scan Vcent_LowerBound window\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "TX_Vcent_LowerBound_Window", 0, EyeScanVcentLowerBound, NULL);
+ mcSHOW_DBG_MSG(("TX Eye Scan Vcent_LowerBound_Window worse bit\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "TX_Vcent_LowerBound_Window_bit", 0, EyeScanVcentLowerBound_bit, NULL);
+ mcSHOW_DBG_MSG(("TX Eye Scan Vcent_UpperBound Min Window(%%)\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT2, "TX_Vcent_LowerBound_Window(%)", 0, (EyeScanVcentLowerBound * 100 + 31) / 32, NULL);
+ mcSHOW_DBG_MSG(("TX Eye Scan Vcent_LowerBound Min Window PASS/FAIL\n"));
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT4, "TX_Vcent_LowerBound_Window_PF", 0, 0, (EyeScanVcentLowerBound * 100 + 31) / 32 >= 20 ? "PASS" : "FAIL");
+
+ mcSHOW_DBG_MSG(("\n"));
+ mcSHOW_DBG_MSG(("TX Eye Scan per_bit window(%%)\n"));
+ for (u1BitIdx=0; u1BitIdx<p->data_width; u1BitIdx++)
+ {
+#if EYESCAN_LOG
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "TX_Perbit_Window(%)", u1BitIdx, ((gEyeScan_WinSize[EyeScanVcent[0]*30+EyeScanVcent[1]][u1BitIdx]) * 100 + 31) / 32, NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "TX_Perbit_BestWindow(%)", u1BitIdx, ((gEyeScan_WinSize[EyeScanVcent[10+u1BitIdx*2]*30+EyeScanVcent[10+u1BitIdx*2+1]][u1BitIdx]) * 100 + 31) / 32, NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "TX_Perbit_Window_Upperbond(%)", u1BitIdx, ((gEyeScan_WinSize[EyeScanVcent[2]*30+EyeScanVcent[3]][u1BitIdx]) * 100 + 31) / 32, NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "TX_Perbit_Window_Lowerbond(%) ", u1BitIdx, ((gEyeScan_WinSize[EyeScanVcent[4]*30+EyeScanVcent[5]][u1BitIdx]) * 100 + 31) / 32, NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "TX_Perbit_Eye_Height", u1BitIdx, (gEyeScan_ContinueVrefHeight[u1BitIdx]-1)*6*vddq/1000, NULL);
+// HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "TX_Perbit_Eye_Area", u1BitIdx, gEyeScan_TotalPassCount[u1BitIdx]*1000*3*vddq/(32*DDRPhyFMeter()), NULL); //total count*1/32UI*(1/freq*10^6 ps)*(0.6%vddq)
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT0_1, "TX_Perbit_Eye_Area", u1BitIdx, (gEyeScan_TotalPassCount[u1BitIdx]*10*3*vddq/(32*DDRPhyFMeter()))*100, NULL); //total count*1/32UI*(1/freq*10^6 ps)*(0.6%vddq)
+#endif
+ }
+ }
+ }
+
+ mcSHOW_DBG_MSG(("\n"));
+}
+#endif
+
+
+#ifdef FOR_HQA_REPORT_USED
+void HQA_Log_Message_for_Report(DRAMC_CTX_T *p, U8 u1ChannelIdx, U8 u1RankIdx, U32 who_am_I, U8 *main_str, U8 byte_bit_idx, S32 value1, U8 *ans_str)
+{
+ // HQA_REPORT_FORMAT0 : [HQALOG] 3200 Gating_Center_2T Channel0 Rank0 Byte0 3
+ // HQA_REPORT_FORMAT0_1:[HQALOG] 3200 Gating_Center_2T Channel0 Rank0 Bit0 3
+ // HQA_REPORT_FORMAT0_2:[HQALOG] 3200 Gating_Center_2T Channel0 Rank0 CA0 3
+ // HQA_REPORT_FORMAT1 : [HQALOG] 3200 WriteLeveling_DQS0 Channel0 Rank0 35
+ // HQA_REPORT_FORMAT2 : [HQALOG] 3200 TX_Final_Vref Vcent Channel0 Rank0 16860
+ // HQA_REPORT_FORMAT3 : [HQALOG] 3200 DUTY CLK_MAX Channel0 5171
+ // HQA_REPORT_FORMAT4 : [HQALOG] 3200 TX_Vcent_LowerBound_Window_PF Channel0 Rank0 PASS
+ // HQA_REPORT_FORMAT5 : [HQALOG] 3200 AAAAAAAAAAAA BBBBB
+ // HQA_REPORT_FORMAT6 : [HQALOG] 3200 AAAAAAAAAAAA 0
+
+ if (gHQALog_flag==1)
+ {
+ mcSHOW_DBG_MSG(("[HQALOG] %d %s", p->frequency*2, main_str ));
+ switch (who_am_I)
+ {
+ case HQA_REPORT_FORMAT1:
+ mcSHOW_DBG_MSG(("%d", byte_bit_idx));
+ break;
+ }
+
+ if (who_am_I == HQA_REPORT_FORMAT3)
+ {
+ mcSHOW_DBG_MSG((" Channel%d ", u1ChannelIdx));
+ }
+ else if (who_am_I != HQA_REPORT_FORMAT5 && who_am_I != HQA_REPORT_FORMAT6)
+ {
+ mcSHOW_DBG_MSG((" Channel%d Rank%d ", u1ChannelIdx, u1RankIdx));
+ }
+
+ switch (who_am_I)
+ {
+ case HQA_REPORT_FORMAT0:
+ mcSHOW_DBG_MSG(("Byte%d %d\n", byte_bit_idx, value1));
+ break;
+ case HQA_REPORT_FORMAT0_1:
+ mcSHOW_DBG_MSG(("Bit%x %d\n", byte_bit_idx, value1));
+ break;
+ case HQA_REPORT_FORMAT0_2:
+ mcSHOW_DBG_MSG(("CA%x %d\n", byte_bit_idx, value1));
+ break;
+ case HQA_REPORT_FORMAT1:
+ case HQA_REPORT_FORMAT2:
+ case HQA_REPORT_FORMAT3:
+ case HQA_REPORT_FORMAT6:
+ mcSHOW_DBG_MSG(("%d\n", value1));
+ break;
+ case HQA_REPORT_FORMAT4:
+ case HQA_REPORT_FORMAT5:
+ mcSHOW_DBG_MSG((" %s\n", ans_str));
+ break;
+ }
+ }
+}
+
+#endif
+
+
+#ifdef FOR_HQA_TEST_USED
+#ifdef RELEASE
+#undef mcSHOW_DBG_MSG
+#define mcSHOW_DBG_MSG(_x_) opt_print _x_
+#endif
+void print_HQA_measure_message(DRAMC_CTX_T *p)
+{
+ U32 uiCA, u1BitIdx, u1RankIdx;
+ U32 min_ca_value[CHANNEL_NUM][RANK_MAX], min_ca_bit[CHANNEL_NUM][RANK_MAX];
+ U32 min_rx_value[CHANNEL_NUM][RANK_MAX], min_tx_value[CHANNEL_NUM][RANK_MAX];
+ U32 min_RX_DQ_bit[CHANNEL_NUM][RANK_MAX], min_TX_DQ_bit[CHANNEL_NUM][RANK_MAX];
+ U8 shuffleIdx, local_channel_num=2, shuffle_index;
+ U8 print_imp_option[2]={FALSE, FALSE};
+ U8 u1ChannelIdx, u1Channel;
+ int i;
+
+ mcSHOW_DBG_MSG(("\n\n\n[HQA] information for measurement, "));
+ mcSHOW_DBG_MSG(("\tDram Data rate = %d\n",p->frequency*2));
+ vPrintCalibrationBasicInfo(p);
+ mcSHOW_DBG_MSG(("[HQALOG] %d Frequency = %u\n", p->frequency*2, DDRPhyFMeter()));
+
+ shuffleIdx = get_shuffleIndex_by_Freq(p);
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ local_channel_num = p->support_channel_num;
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ //LP3
+ local_channel_num = 1;
+ }
+#endif
+
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+
+ for(u1RankIdx=RANK_0; u1RankIdx<p->support_rank_num; u1RankIdx++)
+ {
+ min_ca_value[u1ChannelIdx][u1RankIdx] = 0xffff;
+ min_rx_value[u1ChannelIdx][u1RankIdx] = 0xffff;
+ min_tx_value[u1ChannelIdx][u1RankIdx] = 0xffff;
+ min_RX_DQ_bit[u1ChannelIdx][u1RankIdx] = 0xffff;
+ min_TX_DQ_bit[u1ChannelIdx][u1RankIdx] = 0xffff;
+
+ for (uiCA=0; uiCA<((u1IsLP4Family(p->dram_type)==1) ? CATRAINING_NUM_LP4 : CATRAINING_NUM_LP3); uiCA++)
+ {
+ if (gFinalCBTCA[u1ChannelIdx][u1RankIdx][uiCA] < min_ca_value[u1ChannelIdx][u1RankIdx])
+ {
+ min_ca_value[u1ChannelIdx][u1RankIdx] = gFinalCBTCA[u1ChannelIdx][u1RankIdx][uiCA];
+ min_ca_bit[u1ChannelIdx][u1RankIdx] = uiCA;
+ }
+ }
+
+ for (u1BitIdx=0; u1BitIdx<p->data_width; u1BitIdx++)
+ {
+ if (gFinalRXPerbitWin[u1ChannelIdx][u1RankIdx][u1BitIdx] < min_rx_value[u1ChannelIdx][u1RankIdx])
+ {
+ min_rx_value[u1ChannelIdx][u1RankIdx] = gFinalRXPerbitWin[u1ChannelIdx][u1RankIdx][u1BitIdx];
+ min_RX_DQ_bit[u1ChannelIdx][u1RankIdx] = u1BitIdx;
+ }
+ if (gFinalTXPerbitWin[u1ChannelIdx][u1RankIdx][u1BitIdx] < min_tx_value[u1ChannelIdx][u1RankIdx])
+ {
+ min_tx_value[u1ChannelIdx][u1RankIdx] = gFinalTXPerbitWin[u1ChannelIdx][u1RankIdx][u1BitIdx];
+ min_TX_DQ_bit[u1ChannelIdx][u1RankIdx] = u1BitIdx;
+ }
+ }
+ }
+ }
+
+
+ if (p->support_rank_num==RANK_DUAL)
+ {
+ //Preloader LP3 RX/TX only K Rank0, so Rank1 use Rank0's value
+ if(!u1IsLP4Family(p->dram_type))
+ {
+#ifndef LP3_DUAL_RANK_RX_K
+ min_rx_value[0][1] = min_rx_value[0][0];
+ min_RX_DQ_bit[0][1] = min_RX_DQ_bit[0][0];
+#endif
+
+#ifndef LP3_DUAL_RANK_TX_K
+ min_tx_value[0][1] = min_tx_value[0][0];
+ gFinalTXPerbitWin_min_max[0][1] = gFinalTXPerbitWin_min_max[0][0];
+ min_TX_DQ_bit[0][1] = min_TX_DQ_bit[0][0];
+#endif
+
+ #if 0//(TX_PER_BIT_DELAY_CELL==0)
+ gFinalTXPerbitWin_min_margin[0][1] = gFinalTXPerbitWin_min_margin[0][0];
+ gFinalTXPerbitWin_min_margin_bit[0][1] = gFinalTXPerbitWin_min_margin_bit[0][0];
+ #endif
+ }
+ }
+
+
+#if defined(DRAM_HQA)
+ mcSHOW_DBG_MSG(("[Read Voltage]\n"));
+ mcSHOW_DBG_MSG(("[HQALOG] %d Vcore_HQA = %d\n", p->frequency*2, vGetVoltage(p, 0)));
+
+ if (u1IsLP4Family(p->dram_type)) {
+ /* LPDDR4 */
+ mcSHOW_DBG_MSG(("[HQALOG] %d Vdram_HQA = %d\n", p->frequency*2, vGetVoltage(p, 1)));
+ mcSHOW_DBG_MSG(("[HQALOG] %d Vddq_HQA = %d\n", p->frequency*2, vGetVoltage(p, 2)));
+ mcSHOW_DBG_MSG(("[HQALOG] %d Vdd1_HQA = %d\n", p->frequency*2, vGetVoltage(p, 3)));
+ } else {
+ /* LPDDR3 */
+ mcSHOW_DBG_MSG(("[HQALOG] %d Vdram_HQA = %d\n", p->frequency*2, vGetVoltage(p, 1)));
+ mcSHOW_DBG_MSG(("[HQALOG] %d Vdd1_HQA = %d\n", p->frequency*2, vGetVoltage(p, 3)));
+ }
+ mcSHOW_DBG_MSG(("\n"));
+#endif
+
+ /*
+ [Impedance Calibration]
+
+ term_option=0
+ [HQALOG] Impedance term_option=0 DRVP 11
+ [HQALOG] Impedance term_option=0 DRVN 7
+
+ term_option=1
+ [HQALOG] Impedance term_option=1 DRVP 13
+ [HQALOG] Impedance term_option=1 ODTN 15
+ */
+ if (p->dram_type == TYPE_LPDDR4)
+ {
+ print_imp_option[1] = TRUE;
+ }
+ else if (p->dram_type == TYPE_LPDDR4X)
+ {
+ print_imp_option[0] = TRUE;
+ print_imp_option[1] = TRUE;
+ }
+ else
+ {
+ //TYPE_LPDDR4P, TYPE_LPDDR3
+ print_imp_option[0] = TRUE;
+ }
+
+#ifdef FOR_HQA_REPORT_USED
+if (gHQALog_flag==1)
+{
+ mcSHOW_DBG_MSG(("[Impedance Calibration]\n"));
+ for(i=0; i<2; i++)
+ {
+ mcSHOW_DBG_MSG(("term_option=%d\n", i));
+ if (print_imp_option[i]==FALSE || (print_imp_option[i]==TRUE && p->odt_onoff==ODT_OFF && i==1) || (print_imp_option[i]==TRUE && p->odt_onoff==ODT_ON && i==0))
+ {
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT5, i==0 ? "Impedance term_option=0 DRVP" : "Impedance term_option=1 DRVP", 0, 0, "NA");
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT5, i==0 ? "Impedance term_option=0 DRVN" : "Impedance term_option=1 ODTN", 0, 0, "NA");
+ }
+ else
+ {
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT6, i==0 ? "Impedance term_option=0 DRVP" : "Impedance term_option=1 DRVP", 0, gDramcSwImpedanceResule[i][DRVP], NULL);
+ HQA_Log_Message_for_Report(p, p->channel, p->rank, HQA_REPORT_FORMAT6, i==0 ? "Impedance term_option=0 DRVN" : "Impedance term_option=1 ODTN", 0, i==0 ? gDramcSwImpedanceResule[i][DRVN] : gDramcSwImpedanceResule[i][ODTN], NULL);
+ }
+ }
+ mcSHOW_DBG_MSG(("\n"));
+}
+#endif
+
+
+
+
+if(u1IsLP4Family(p->dram_type))
+{
+ mcSHOW_DBG_MSG(("\n[Cmd Bus Training window]\n"));
+ if(u1IsLP4Family(p->dram_type))
+ {
+ mcSHOW_DBG_MSG(("VrefCA Range : %d\n", gCBT_VREF_RANGE_SEL));
+ /*
+ VrefCA
+ [HQALOG] 1600 VrefCA Channel0 Rank0 32
+ [HQALOG] 1600 VrefCA Channel0 Rank1 24
+ [HQALOG] 1600 VrefCA Channel1 Rank0 26
+ [HQALOG] 1600 VrefCA Channel1 Rank1 30
+ */
+ mcSHOW_DBG_MSG(("VrefCA\n"));
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+
+ for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+ {
+ mcSHOW_DBG_MSG(("[HQALOG] %d VrefCA Channel%d "
+ "Rank%d %d\n",
+ p->frequency*2,
+ u1ChannelIdx,
+ u1RankIdx,
+ gFinalCBTVrefCA[u1ChannelIdx][u1RankIdx]));
+ }
+ }
+ }
+
+#if 0//(SUPPORT_SAVE_TIME_FOR_CALIBRATION && BYPASS_CBT)
+ if(p->femmc_Ready==1 )
+ {
+ mcSHOW_DBG_MSG(("\n[Cmd Bus Training window bypass calibration]\n"));
+ }
+ else
+#endif
+ {
+ /*
+ CA_Window
+ [HQALOG] 1600 CA_Window Channel0 Rank0 61(bit 2)
+ [HQALOG] 1600 CA_Window Channel0 Rank1 62(bit 1)
+ [HQALOG] 1600 CA_Window Channel1 Rank0 60(bit 5)
+ [HQALOG] 1600 CA_Window Channel1 Rank1 60(bit 5)
+ */
+ mcSHOW_DBG_MSG(("CA_Window\n"));
+#ifdef FOR_HQA_REPORT_USED
+if (gHQALog_flag==1)
+{
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+
+ for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+ {
+ HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT2, "CA_Window", 0, min_ca_value[u1ChannelIdx][u1RankIdx], NULL);
+ HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT2, "CA_Window_bit", 0, min_ca_bit[u1ChannelIdx][u1RankIdx], NULL);
+ }
+ }
+ mcSHOW_DBG_MSG(("\n"));
+}
+else
+#endif
+{
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+
+ for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+ {
+ mcSHOW_DBG_MSG(("[HQALOG] %d CA_Window Channel%d "
+ "Rank%d %d (bit %d)\n",
+ p->frequency*2,
+ u1ChannelIdx,
+ u1RankIdx,
+ min_ca_value[u1ChannelIdx][u1RankIdx], min_ca_bit[u1ChannelIdx][u1RankIdx]));
+ }
+ }
+}
+
+ /*
+ CA Min Window(%)
+ [HQALOG] 1600 CA_Window(%) Channel0 Rank0 96%(PASS)
+ [HQALOG] 1600 CA_Window(%) Channel0 Rank1 97%(PASS)
+ [HQALOG] 1600 CA_Window(%) Channel1 Rank0 94%(PASS)
+ [HQALOG] 1600 CA_Window(%) Channel1 Rank1 94%(PASS)
+ */
+ mcSHOW_DBG_MSG(("CA Min Window(%%)\n"));
+#ifdef FOR_HQA_REPORT_USED
+if (gHQALog_flag==1)
+{
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+
+ for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+ {
+ HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT2, "CA_Window(%)", 0, ((min_ca_value[u1ChannelIdx][u1RankIdx] * 100 + (u1IsLP4Family(p->dram_type)==1?63:31)) / (u1IsLP4Family(p->dram_type)==1?64:32)), NULL);
+ HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT4, "CA_Window_PF", 0, 0, ((((min_ca_value[u1ChannelIdx][u1RankIdx] * 100 + (u1IsLP4Family(p->dram_type)==1?63:31)) / (u1IsLP4Family(p->dram_type)==1?64:32)) >= 30) ? "PASS" : "FAIL"));
+ }
+ }
+ mcSHOW_DBG_MSG(("\n"));
+}
+else
+#endif
+{
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+
+ for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+ {
+ mcSHOW_DBG_MSG(("[HQALOG] %d CA_Window(%%) Channel%d "
+ "Rank%d %d%% (%s)\n",
+ p->frequency*2,
+ u1ChannelIdx,
+ u1RankIdx,
+ ((min_ca_value[u1ChannelIdx][u1RankIdx] * 100 + (u1IsLP4Family(p->dram_type)==1?63:31)) / (u1IsLP4Family(p->dram_type)==1?64:32)),
+ ((((min_ca_value[u1ChannelIdx][u1RankIdx] * 100 + (u1IsLP4Family(p->dram_type)==1?63:31)) / (u1IsLP4Family(p->dram_type)==1?64:32)) >= 30) ? "PASS" : "FAIL")));
+ }
+ }
+}
+ }
+ mcSHOW_DBG_MSG(("\n"));
+}
+
+
+ /*
+ [RX minimum per bit window]
+ Delay cell measurement (/100ps)
+ [HQALOG] 3200 delaycell 892
+ */
+ mcSHOW_DBG_MSG(("\n[RX minimum per bit window]\n"));
+ mcSHOW_DBG_MSG(("Delaycell measurement(/100ps)\n"));
+#if !defined(RELEASE) && (VENDER_JV_LOG==0)
+ mcSHOW_DBG_MSG(("[HQALOG] %d delaycell %d\n",
+ p->frequency*2,
+ u2gdelay_cell_ps_all[shuffleIdx][u1ChannelSet[0]]));
+#endif
+ /*
+ VrefDQ
+ [HQALOG] 1600 VrefRX Channel0 24
+ [HQALOG] 1600 VrefRX Channel1 24
+ */
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ if (p->enable_rx_scan_vref == ENABLE)
+ {
+ mcSHOW_DBG_MSG(("VrefRX\n"));
+ if (gRX_EYE_Scan_flag==1)
+ {
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+
+ for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+ {
+ mcSHOW_DBG_MSG(("[HQALOG] %d VrefRX Channel%d Rank%d %d\n",
+ p->frequency*2,
+ u1ChannelIdx,
+ u1RankIdx,
+ gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx]));
+ }
+ }
+ }
+ else
+ {
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+
+ mcSHOW_DBG_MSG(("[HQALOG] %d VrefRX Channel%d %d\n",
+ p->frequency*2,
+ u1ChannelIdx,
+ gFinalRXVrefDQ[u1ChannelIdx][RANK_0]));
+ }
+ }
+ }
+ else
+ {
+ mcSHOW_DBG_MSG(("RX DQ Vref Scan : Disable\n"));
+ }
+ }
+
+#if 0//(SUPPORT_SAVE_TIME_FOR_CALIBRATION )
+ if(p->femmc_Ready==1 && ( p->Bypass_RXWINDOW))
+ {
+ mcSHOW_DBG_MSG(("\n[RX minimum per bit window bypass calibration]\n"));
+ }
+ else
+#endif
+ {
+ /*
+ RX_Window
+ [HQALOG] 1600 RX_Window Channel0 Rank0 52(bit 2)
+ [HQALOG] 1600 RX_Window Channel0 Rank1 52(bit 2)
+ [HQALOG] 1600 RX_Window Channel1 Rank0 60(bit 12)
+ [HQALOG] 1600 RX_Window Channel1 Rank1 62(bit 9)
+ */
+ mcSHOW_DBG_MSG(("RX_Window\n"));
+#ifdef FOR_HQA_REPORT_USED
+if (gHQALog_flag==1)
+{
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+
+ for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+ {
+ HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT2, "RX_Window", 0, min_rx_value[u1ChannelIdx][u1RankIdx], NULL);
+ HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT2, "RX_Window_bit", 0, min_RX_DQ_bit[u1ChannelIdx][u1RankIdx], NULL);
+ }
+ }
+}
+else
+#endif
+{
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+
+ for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+ {
+ mcSHOW_DBG_MSG(("[HQALOG] %d RX_Window Channel%d "
+ "Rank%d %d (bit %d)\n",
+ p->frequency*2,
+ u1ChannelIdx,
+ u1RankIdx,
+ min_rx_value[u1ChannelIdx][u1RankIdx], min_RX_DQ_bit[u1ChannelIdx][u1RankIdx]));
+ }
+ }
+}
+
+ /*
+ RX Min Window(%)
+ [HQALOG] 1600 RX_Window(%) Channel0 Rank0 43316/100ps(70%)(PASS)
+ [HQALOG] 1600 RX_Window(%) Channel0 Rank1 43316/100ps(70%)(PASS)
+ [HQALOG] 1600 RX_Window(%) Channel1 Rank0 49980/100ps(80%)(PASS)
+ [HQALOG] 1600 RX_Window(%) Channel1 Rank1 51646/100ps(83%)(PASS)
+ */
+ mcSHOW_DBG_MSG(("RX Window(%%)\n"));
+#ifdef FOR_HQA_REPORT_USED
+if (gHQALog_flag==1)
+{
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+
+ for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+ {
+ HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT2, "RX_Window(%)", 0, ((min_rx_value[u1ChannelIdx][u1RankIdx] * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000, NULL);
+ HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT4, "RX_Window_PF", 0, 0, (min_rx_value[u1ChannelIdx][u1RankIdx] * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) / 1000000 >= 40 ? "PASS" : "FAIL");
+ }
+ }
+}
+else
+#endif
+{
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+
+ for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+ {
+ mcSHOW_DBG_MSG(("[HQALOG] %d RX_Window(%%) Channel%d "
+ "Rank%d "
+ "%d/100ps (%d%%) (%s)\n",
+ p->frequency*2,
+ u1ChannelIdx,
+ u1RankIdx,
+ min_rx_value[u1ChannelIdx][u1RankIdx] * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx],
+ ((min_rx_value[u1ChannelIdx][u1RankIdx] * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000,
+ ((min_rx_value[u1ChannelIdx][u1RankIdx] * u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx] * p->frequency * 2) + (1000000 - 1)) / 1000000 >= 40 ? "PASS" : "FAIL"));
+ }
+ }
+}
+
+ mcSHOW_DBG_MSG(("\n"));
+ }
+
+
+
+
+
+
+ /* [TX minimum per bit window]
+ VrefDQ Range : 1
+ VrefDQ
+ [HQALOG] 1600 VrefTX Channel0 Rank0 30
+ [HQALOG] 1600 VrefTX Channel0 Rank1 25
+ [HQALOG] 1600 VrefTX Channel1 Rank0 24
+ [HQALOG] 1600 VrefTX Channel1 Rank1 23
+ */
+ mcSHOW_DBG_MSG(("\n[TX minimum per bit window]\n"));
+ if(u1IsLP4Family(p->dram_type))
+ {
+ if (p->enable_tx_scan_vref == ENABLE_VREF_SCAN)
+ {
+ mcSHOW_DBG_MSG(("VrefDQ Range : %d\n",(u1MR14Value[p->channel][p->rank][p->dram_fsp]>>6)&1));
+ mcSHOW_DBG_MSG(("VrefDQ\n"));
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+
+ for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+ {
+ mcSHOW_DBG_MSG(("[HQALOG] %d VrefDQ Channel%d "
+ "Rank%d %d\n",
+ p->frequency*2,
+ u1ChannelIdx,
+ u1RankIdx,
+ gFinalTXVrefDQ[u1ChannelIdx][u1RankIdx]));
+ }
+ }
+ }
+ else
+ {
+ mcSHOW_DBG_MSG(("TX DQ Vref Scan : Disable\n"));
+ }
+ }
+#if 0//(SUPPORT_SAVE_TIME_FOR_CALIBRATION )
+ if(p->femmc_Ready==1 && (p->Bypass_TXWINDOW))
+ {
+ mcSHOW_DBG_MSG(("\n[TX minimum per bit window bypass calibration]\n"));
+ }
+ else
+#endif
+ {
+ /*
+ TX_Window
+ [HQALOG] 1600 TX_Window Channel0 Rank0 25(bit 2)
+ [HQALOG] 1600 TX_Window Channel0 Rank1 25(bit 2)
+ [HQALOG] 1600 TX_Window Channel1 Rank0 22(bit 9)
+ [HQALOG] 1600 TX_Window Channel1 Rank1 23(bit 9)
+ */
+ mcSHOW_DBG_MSG(("TX_Window\n"));
+#ifdef FOR_HQA_REPORT_USED
+if (gHQALog_flag==1)
+{
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+
+ for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+ {
+ HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT2, "TX_Window", 0, gFinalTXPerbitWin_min_max[u1ChannelIdx][u1RankIdx], NULL);
+ HQA_Log_Message_for_Report(p,u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT2, "TX_Window_bit", 0, min_TX_DQ_bit[u1ChannelIdx][u1RankIdx], NULL);
+ }
+ }
+}
+else
+#endif
+{
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+
+ for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+ {
+ mcSHOW_DBG_MSG(("[HQALOG] %d TX_Window Channel%d "
+ "Rank%d %d (bit %d)\n",
+ p->frequency*2,
+ u1ChannelIdx,
+ u1RankIdx,
+ gFinalTXPerbitWin_min_max[u1ChannelIdx][u1RankIdx], min_TX_DQ_bit[u1ChannelIdx][u1RankIdx]));
+ }
+ }
+}
+#if 0//(TX_PER_BIT_DELAY_CELL==0)
+ mcSHOW_DBG_MSG(("min DQ margin\n"));
+ for(u1ChannelIdx=CHANNEL_A; u1ChannelIdx<local_channel_num; u1ChannelIdx++)
+ {
+ for(u1RankIdx = RANK_0; u1RankIdx < 2; u1RankIdx++)
+ {
+ mcSHOW_DBG_MSG(("[HQALOG] %d min_DQ_margin Channel%d "
+ "Rank%d %d (bit %d)\n",
+ p->frequency*2,
+ u1ChannelIdx,
+ u1RankIdx,
+ gFinalTXPerbitWin_min_margin[u1ChannelIdx][u1RankIdx], gFinalTXPerbitWin_min_margin_bit[u1ChannelIdx][u1RankIdx]));
+ }
+ }
+#endif
+
+
+ /*
+ TX Min Window(%)
+ [HQALOG] 1600 TX_Window(%) Channel0 Rank0 79%(PASS)
+ [HQALOG] 1600 TX_Window(%) Channel0 Rank1 79%(PASS)
+ [HQALOG] 1600 TX_Window(%) Channel1 Rank0 69%(PASS)
+ [HQALOG] 1600 TX_Window(%) Channel1 Rank1 72%(PASS)
+ */
+ mcSHOW_DBG_MSG(("TX Min Window(%%)\n"));
+#ifdef FOR_HQA_REPORT_USED
+if (gHQALog_flag==1)
+{
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+
+ for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+ {
+ HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT2, "TX_Window(%)", 0, (min_tx_value[u1ChannelIdx][u1RankIdx] * 100 + 31) / (u1IsLP4Family(p->dram_type)==1?32:64), NULL);
+ HQA_Log_Message_for_Report(p, u1ChannelIdx, u1RankIdx, HQA_REPORT_FORMAT4, "TX_Window_PF", 0, 0, (min_tx_value[u1ChannelIdx][u1RankIdx] * 100 + 31) / (u1IsLP4Family(p->dram_type)==1?32:64) >= 45 ? "PASS" : "FAIL");
+ }
+ }
+}
+else
+#endif
+{
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+
+ for(u1RankIdx = RANK_0; u1RankIdx < p->support_rank_num; u1RankIdx++)
+ {
+ mcSHOW_DBG_MSG(("[HQALOG] %d TX_Window(%%) Channel%d "
+ "Rank%d %d%% (%s)\n",
+ p->frequency*2,
+ u1ChannelIdx,
+ u1RankIdx,
+ (min_tx_value[u1ChannelIdx][u1RankIdx] * 100 + 31) / (u1IsLP4Family(p->dram_type)==1?32:64),
+ (min_tx_value[u1ChannelIdx][u1RankIdx] * 100 + 31) / (u1IsLP4Family(p->dram_type)==1?32:64) >= 45 ? "PASS" : "FAIL"));
+ }
+ }
+}
+
+ mcSHOW_DBG_MSG(("\n"));
+ }
+
+
+
+ /*
+ [Duty Calibration]
+ CLK Duty Final Delay Cell
+ [HQALOG] DUTY CLK_Final_Delay Channel0 0
+ [HQALOG] DUTY CLK_Final_Delay Channel1 -2
+ */
+#if !defined(RELEASE) && (VENDER_JV_LOG==0)
+ if (u1IsLP4Family(p->dram_type))
+ {
+ mcSHOW_DBG_MSG(("[duty Calibration]\n"));
+ mcSHOW_DBG_MSG(("CLK Duty Final Delay Cell\n"));
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+ mcSHOW_DBG_MSG(("[HQALOG] %d DUTY CLK_Final_Delay Channel%d %d\n", p->frequency*2, u1ChannelIdx, gFinalClkDuty[u1ChannelIdx]));
+ }
+
+ /*
+ CLK Duty MAX
+ [HQALOG] DUTY CLK_MAX Channel0 4765%(X100)
+ [HQALOG] DUTY CLK_MAX Channel1 5212%(X100)
+ */
+ mcSHOW_DBG_MSG(("CLK Duty MAX\n"));
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+#ifdef FOR_HQA_REPORT_USED
+ if (gHQALog_flag==1)
+ {
+ HQA_Log_Message_for_Report(p, u1ChannelIdx, 0, HQA_REPORT_FORMAT3, "DUTY CLK_MAX", 0, gFinalClkDutyMinMax[u1ChannelIdx][1], NULL);
+ }
+ else
+#endif
+ {
+ mcSHOW_DBG_MSG(("[HQALOG] %d DUTY CLK_MAX Channel%d %d%%(X100)\n", p->frequency*2, u1ChannelIdx, gFinalClkDutyMinMax[u1ChannelIdx][1]));
+ }
+ }
+
+ /*
+ CLK Duty MIN
+ [HQALOG] DUTY CLK_MIN Channel0 4565%(X100)
+ [HQALOG] DUTY CLK_MIN Channel1 5012%(X100)
+ */
+ mcSHOW_DBG_MSG(("CLK Duty MIN\n"));
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+#ifdef FOR_HQA_REPORT_USED
+ if (gHQALog_flag==1)
+ {
+ HQA_Log_Message_for_Report(p, u1ChannelIdx, 0, HQA_REPORT_FORMAT3, "DUTY CLK_MIN", 0, gFinalClkDutyMinMax[u1ChannelIdx][0], NULL);
+ HQA_Log_Message_for_Report(p, u1ChannelIdx, 0, HQA_REPORT_FORMAT3, "DUTY CLK_MAX-MIN", 0, gFinalClkDutyMinMax[u1ChannelIdx][1]-gFinalClkDutyMinMax[u1ChannelIdx][0], NULL);
+ }
+ else
+#endif
+ {
+ mcSHOW_DBG_MSG(("[HQALOG] %d DUTY CLK_MIN Channel%d %d%%(X100)\n", p->frequency*2, u1ChannelIdx, gFinalClkDutyMinMax[u1ChannelIdx][0]));
+ }
+ }
+
+ mcSHOW_DBG_MSG(("\n"));
+ }
+
+
+
+
+ /*
+ DQS Duty Final Delay Cell
+ [HQALOG] DUTY DQS_Final_Delay Channel0 DQS0 0
+ [HQALOG] DUTY DQS_Final_Delay Channel0 DQS1 1
+ [HQALOG] DUTY DQS_Final_Delay Channel1 DQS0 -2
+ [HQALOG] DUTY DQS_Final_Delay Channel1 DQS1 -1
+ */
+ if (u1IsLP4Family(p->dram_type))
+ {
+ mcSHOW_DBG_MSG(("DQS Duty Final Delay Cell\n"));
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+
+ if (p->frequency == u2DFSGetHighestFreq(p))
+ {
+ mcSHOW_DBG_MSG(("[HQALOG] %d DUTY DQS_Final_Delay Channel%d DQS0 %d\n", p->frequency*2, u1ChannelIdx, gFinalDQSDuty[u1ChannelIdx][0]));
+ mcSHOW_DBG_MSG(("[HQALOG] %d DUTY DQS_Final_Delay Channel%d DQS1 %d\n", p->frequency*2, u1ChannelIdx, gFinalDQSDuty[u1ChannelIdx][1]));
+ }
+ }
+
+ /*
+ DQS Duty MAX
+ [HQALOG] DUTY DQS_MAX Channel0 DQS0 4765%(X100)
+ [HQALOG] DUTY DQS_MAX Channel0 DQS1 5212%(X100)
+ [HQALOG] DUTY DQS_MAX Channel1 DQS0 4765%(X100)
+ [HQALOG] DUTY DQS_MAX Channel1 DQS1 5212%(X100)
+ */
+ mcSHOW_DBG_MSG(("DQS Duty MAX\n"));
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+#ifdef FOR_HQA_REPORT_USED
+ if (gHQALog_flag==1)
+ {
+ HQA_Log_Message_for_Report(p, u1ChannelIdx, 0, HQA_REPORT_FORMAT0, "DUTY DQS_MAX", 0, gFinalDQSDutyMinMax[u1ChannelIdx][0][1], NULL);
+ HQA_Log_Message_for_Report(p,u1ChannelIdx, 0, HQA_REPORT_FORMAT0, "DUTY DQS_MAX", 1, gFinalDQSDutyMinMax[u1ChannelIdx][1][1], NULL);
+ }
+ else
+#endif
+ {
+ mcSHOW_DBG_MSG(("[HQALOG] %d DUTY DQS_MAX Channel%d DQS0 %d%%(X100)\n", p->frequency*2, u1ChannelIdx, gFinalDQSDutyMinMax[u1ChannelIdx][0][1]));
+ mcSHOW_DBG_MSG(("[HQALOG] %d DUTY DQS_MAX Channel%d DQS1 %d%%(X100)\n", p->frequency*2, u1ChannelIdx, gFinalDQSDutyMinMax[u1ChannelIdx][1][1]));
+ }
+ }
+
+ /*
+ DQS Duty MIN
+ [HQALOG] DUTY DQS_MIN Channel0 DQS0 4765%(X100)
+ [HQALOG] DUTY DQS_MIN Channel0 DQS1 5212%(X100)
+ [HQALOG] DUTY DQS_MIN Channel1 DQS0 4765%(X100)
+ [HQALOG] DUTY DQS_MIN Channel1 DQS1 5212%(X100)
+ */
+ mcSHOW_DBG_MSG(("DQS Duty MIN\n"));
+ for(u1Channel=CHANNEL_A; u1Channel<local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+#ifdef FOR_HQA_REPORT_USED
+ if (gHQALog_flag==1)
+ {
+ HQA_Log_Message_for_Report(p, u1ChannelIdx, 0, HQA_REPORT_FORMAT0, "DUTY DQS_MIN", 0, gFinalDQSDutyMinMax[u1ChannelIdx][0][0], NULL);
+ HQA_Log_Message_for_Report(p, u1ChannelIdx, 0, HQA_REPORT_FORMAT0, "DUTY DQS_MIN", 1, gFinalDQSDutyMinMax[u1ChannelIdx][1][0], NULL);
+ HQA_Log_Message_for_Report(p, u1ChannelIdx, 0, HQA_REPORT_FORMAT0, "DUTY DQS_MAX-MIN", 0, gFinalDQSDutyMinMax[u1ChannelIdx][0][1]-gFinalDQSDutyMinMax[u1ChannelIdx][0][0], NULL);
+ HQA_Log_Message_for_Report(p, u1ChannelIdx, 0, HQA_REPORT_FORMAT0, "DUTY DQS_MAX-MIN", 1, gFinalDQSDutyMinMax[u1ChannelIdx][1][1]-gFinalDQSDutyMinMax[u1ChannelIdx][1][0], NULL);
+ }
+ else
+#endif
+ {
+ mcSHOW_DBG_MSG(("[HQALOG] %d DUTY DQS_MIN Channel%d DQS0 %d%%(X100)\n", p->frequency*2, u1ChannelIdx, gFinalDQSDutyMinMax[u1ChannelIdx][0][0]));
+ mcSHOW_DBG_MSG(("[HQALOG] %d DUTY DQS_MIN Channel%d DQS1 %d%%(X100)\n", p->frequency*2, u1ChannelIdx, gFinalDQSDutyMinMax[u1ChannelIdx][1][0]));
+ }
+ }
+
+ mcSHOW_DBG_MSG(("\n"));
+ }
+#endif
+
+
+
+
+
+
+
+
+
+
+
+ #if defined(ENABLE_MIOCK_JMETER) && !defined(RELEASE)
+ //if(p->frequency == u2DFSGetHighestFreq(p))
+ {
+ if(u1IsLP4Family(p->dram_type)) //LP4 Series
+ {
+ mcSHOW_DBG_MSG(("\n[DramcMiockJmeter]\n"
+ "Channel\tVCORE\t\t1 delay cell\n"));
+
+ for(shuffle_index=DRAM_DFS_SHUFFLE_1; shuffle_index<DRAM_DFS_SHUFFLE_MAX; shuffle_index++)
+ {
+ mcSHOW_DBG_MSG(("\nSHUFFLE %d\n", shuffle_index+1));
+
+ for (u1Channel = 0; u1Channel < local_channel_num; u1Channel++)
+ {
+ u1ChannelIdx = u1ChannelSet[u1Channel];
+ mcSHOW_DBG_MSG(("CH%d\t%d\t\t%d/100 ps\n", u1ChannelIdx, u4gVcore[shuffle_index], u2gdelay_cell_ps_all[shuffle_index][u1ChannelIdx]));
+ }
+ }
+ }
+ }
+ #endif
+
+ mcSHOW_DBG_MSG(("\n\n\n"));
+
+
+
+#if VENDER_JV_LOG
+ mcSHOW_DBG_MSG5(("\n\n\n[Summary] information for measurement\n"));
+ //mcSHOW_DBG_MSG5(("\tDram Data rate = %d\n",p->frequency*2));
+ vPrintCalibrationBasicInfo_ForJV(p);
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ mcSHOW_DBG_MSG5(("[Cmd Bus Training window]\n"));
+ mcSHOW_DBG_MSG5(("VrefCA Range : %d\n", gCBT_VREF_RANGE_SEL));
+#if CHANNEL_NUM==4
+ mcSHOW_DBG_MSG5(("CHA_VrefCA_Rank0 CHB_VrefCA_Rank0 CHC_VrefCA_Rank0 CHD_VrefCA_Rank0\n"));
+ mcSHOW_DBG_MSG5(("%d %d %d %d\n", gFinalCBTVrefCA[0][0], gFinalCBTVrefCA[1][0], gFinalCBTVrefCA[2][0], gFinalCBTVrefCA[3][0]));
+#else
+ mcSHOW_DBG_MSG5(("CHA_VrefCA_Rank0 CHB_VrefCA_Rank0\n"));
+ mcSHOW_DBG_MSG5(("%d %d\n", gFinalCBTVrefCA[0][0], gFinalCBTVrefCA[1][0]));
+#endif
+ mcSHOW_DBG_MSG5(("CHA_CA_window_Rank0 CHB_CA_winow_Rank0\n"));
+ mcSHOW_DBG_MSG5(("%d%%(bit %d) %d%%(bit %d) \n\n",(min_ca_value[0][0]*100+63)/64, min_ca_bit[0][0],
+ (min_ca_value[1][0]*100+63)/64, min_ca_bit[1][0]));
+ }
+#if 0
+ else
+ {
+ mcSHOW_DBG_MSG5(("[CA Training window]\n"));
+ mcSHOW_DBG_MSG5(("CHA_CA_win_Rank0\n"));
+ mcSHOW_DBG_MSG5(("%d%%(bit %d)\n\n",(min_ca_value[0][0]*100+63)/64, min_ca_bit[0][0]));
+ }
+#endif
+
+ mcSHOW_DBG_MSG5(("[RX minimum per bit window]\n"));
+ if (p->enable_rx_scan_vref == ENABLE)
+ {
+#if CHANNEL_NUM==4
+ mcSHOW_DBG_MSG5(("CHA_VrefDQ CHB_VrefDQ CHC_VrefDQ CHD_VrefDQ\n"));
+ mcSHOW_DBG_MSG5(("%d %d %d %d \n", gFinalRXVrefDQ[CHANNEL_A][RANK_0], gFinalRXVrefDQ[CHANNEL_B][RANK_0], gFinalRXVrefDQ[CHANNEL_C][RANK_0], gFinalRXVrefDQ[CHANNEL_D][RANK_0]));
+#else
+ mcSHOW_DBG_MSG5(("CHA_VrefDQ CHB_VrefDQ\n"));
+ mcSHOW_DBG_MSG5(("%d %d \n", gFinalRXVrefDQ[CHANNEL_A][RANK_0], gFinalRXVrefDQ[CHANNEL_B][RANK_0]));
+#endif
+ }
+ else
+ {
+ mcSHOW_DBG_MSG5(("RX DQ Vref Scan : Disable\n"));
+
+ }
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+#if CHANNEL_NUM==4
+ mcSHOW_DBG_MSG5(("CHA_Rank0 CHA_Rank1 CHB_Rank0 CHB_Rank1 CHC_Rank0 CHC_Rank1 CHD_Rank0 CHD_Rank1\n"));
+ mcSHOW_DBG_MSG5(("%d%%(bit %d) %d%%(bit %d) %d%%(bit %d) %d%%(bit %d) %d%%(bit %d) %d%%(bit %d) %d%%(bit %d) %d%%(bit %d)\n\n",
+ ((min_rx_value[0][0]*u2gdelay_cell_ps_all[shuffleIdx][0]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[0][0],
+ ((min_rx_value[0][1]*u2gdelay_cell_ps_all[shuffleIdx][0]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[0][1],
+ ((min_rx_value[1][0]*u2gdelay_cell_ps_all[shuffleIdx][1]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[1][0],
+ ((min_rx_value[1][1]*u2gdelay_cell_ps_all[shuffleIdx][1]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[1][1],
+ ((min_rx_value[2][0]*u2gdelay_cell_ps_all[shuffleIdx][2]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[2][0],
+ ((min_rx_value[2][1]*u2gdelay_cell_ps_all[shuffleIdx][2]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[2][1],
+ ((min_rx_value[3][0]*u2gdelay_cell_ps_all[shuffleIdx][3]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[3][0],
+ ((min_rx_value[3][1]*u2gdelay_cell_ps_all[shuffleIdx][3]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[3][1]));
+#else
+ mcSHOW_DBG_MSG5(("CHA_Rank0 CHA_Rank1 CHB_Rank0 CHB_Rank1\n"));
+ mcSHOW_DBG_MSG5(("%d%%(bit %d) %d%%(bit %d) %d%%(bit %d) %d%%(bit %d)\n\n",
+ ((min_rx_value[0][0]*u2gdelay_cell_ps_all[shuffleIdx][0]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[0][0],
+ ((min_rx_value[0][1]*u2gdelay_cell_ps_all[shuffleIdx][0]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[0][1],
+ ((min_rx_value[1][0]*u2gdelay_cell_ps_all[shuffleIdx][1]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[1][0],
+ ((min_rx_value[1][1]*u2gdelay_cell_ps_all[shuffleIdx][1]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[1][1]));
+#endif
+ }
+ else
+ {
+ mcSHOW_DBG_MSG5(("CHA_Rank0 CHA_Rank1\n"));
+ mcSHOW_DBG_MSG5(("%d%%(bit %d) %d%%(bit %d)\n\n",
+ ((min_rx_value[0][0]*u2gdelay_cell_ps_all[shuffleIdx][0]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[0][0],
+ ((min_rx_value[0][1]*u2gdelay_cell_ps_all[shuffleIdx][0]*p->frequency*2)+(1000000-1))/1000000, min_RX_DQ_bit[0][1]));
+ }
+
+
+ mcSHOW_DBG_MSG5(("[TX minimum per bit window]\n"));
+ if (p->enable_tx_scan_vref == ENABLE_VREF_SCAN)
+ {
+ mcSHOW_DBG_MSG5(("VrefDQ Range : %d\n",(u1MR14Value[p->channel][p->rank][p->dram_fsp]>>6)&1));
+#if CHANNEL_NUM==4
+ mcSHOW_DBG_MSG5(("CHA_VrefDQ_Rank0 CHA_VrefDQ_Rank1 CHB_VrefDQ_Rank0 CHB_VrefDQ_Rank1 CHC_VrefDQ_Rank0 CHC_VrefDQ_Rank1 CHD_VrefDQ_Rank0 CHD_VrefDQ_Rank1\n"));
+ mcSHOW_DBG_MSG5(("%d %d %d %d %d %d %d %d\n"
+ , gFinalTXVrefDQ[0][0], gFinalTXVrefDQ[0][1], gFinalTXVrefDQ[1][0], gFinalTXVrefDQ[1][1]
+ , gFinalTXVrefDQ[2][0], gFinalTXVrefDQ[2][1], gFinalTXVrefDQ[3][0], gFinalTXVrefDQ[3][1]
+ ));
+#else
+ mcSHOW_DBG_MSG5(("CHA_VrefDQ_Rank0 CHA_VrefDQ_Rank1 CHB_VrefDQ_Rank0 CHB_VrefDQ_Rank1\n"));
+ mcSHOW_DBG_MSG5(("%d %d %d %d\n", gFinalTXVrefDQ[0][0], gFinalTXVrefDQ[0][1], gFinalTXVrefDQ[1][0], gFinalTXVrefDQ[1][1]));
+#endif
+ }
+ else
+ {
+ mcSHOW_DBG_MSG5(("TX DQ Vref Scan : Disable\n"));
+ }
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+#if CHANNEL_NUM==4
+ mcSHOW_DBG_MSG5(("CHA_Rank0 CHA_Rank1 CHB_Rank0 CHB_Rank1 CHC_Rank0 CHC_Rank1 CHD_Rank0 CHD_Rank1\n"));
+ mcSHOW_DBG_MSG5(("%d%% %d%% %d%% %d%% %d%% %d%% %d%% %d%%\n",
+ (min_tx_value[0][0]*100+31)/32,
+ (min_tx_value[0][1]*100+31)/32,
+ (min_tx_value[1][0]*100+31)/32,
+ (min_tx_value[1][1]*100+31)/32,
+ (min_tx_value[2][0]*100+31)/32,
+ (min_tx_value[2][1]*100+31)/32,
+ (min_tx_value[3][0]*100+31)/32,
+ (min_tx_value[3][1]*100+31)/32
+ ));
+#else
+ mcSHOW_DBG_MSG5(("CHA_Rank0 CHA_Rank1 CHB_Rank0 CHB_Rank1\n"));
+ mcSHOW_DBG_MSG5(("%d%% %d%% %d%% %d%%\n",
+ (min_tx_value[0][0]*100+31)/32,
+ (min_tx_value[0][1]*100+31)/32,
+ (min_tx_value[1][0]*100+31)/32,
+ (min_tx_value[1][1]*100+31)/32));
+#endif
+ }
+ else
+ {
+ mcSHOW_DBG_MSG5(("CHA_Rank0 CHA_Rank1\n"));
+ mcSHOW_DBG_MSG5(("%d%% %d%%\n",
+ (min_tx_value[0][0]*100+31)/32,
+ (min_tx_value[0][1]*100+31)/32));
+ }
+#endif
+
+
+ // reset all data
+ HQA_measure_message_reset_all_data(p);
+}
+#ifdef RELEASE
+#undef mcSHOW_DBG_MSG
+#define mcSHOW_DBG_MSG(_x_)
+#endif
+#endif
+
+
+#if EYESCAN_LOG
+#ifdef RELEASE
+#undef mcSHOW_DBG_MSG
+#define mcSHOW_DBG_MSG(_x_) opt_print _x_
+#endif
+
+#if FOR_DV_SIMULATION_USED
+const U16 gRXVref_Voltage_Table_LP4[RX_VREF_RANGE_END+1]={0};
+#else
+const U16 gRXVref_Voltage_Table_LP4[RX_VREF_RANGE_END+1]={
+ 1363,
+ 2590,
+ 3815,
+ 5040,
+ 6264,
+ 7489,
+ 8714,
+ 9938,
+ 11160,
+ 12390,
+ 13610,
+ 14840,
+ 16060,
+ 17290,
+ 18510,
+ 19740,
+ 20670,
+ 22100,
+ 23530,
+ 24970,
+ 26400,
+ 27830,
+ 29260,
+ 30700,
+ 32130,
+ 33560,
+ 34990,
+ 36430,
+ 37860,
+ 39290,
+ 40720,
+ 42160
+};
+#endif
+const U16 gVref_Voltage_Table_LP4X[VREF_RANGE_MAX][VREF_VOLTAGE_TABLE_NUM]={
+ {1500,1560,1620,1680,1740,1800,1860,1920,1980,2040,2100,2160,2220,2280,2340,2400,2460,2510,2570,2630,2690,2750,2810,2870,2930,2990,3050,3110,3170,3230,3290,3350,3410,3470,3530,3590,3650,3710,3770,3830,3890,3950,4010,4070,4130,4190,4250,4310,4370,4430,4490},
+ {3290,3350,3410,3470,3530,3590,3650,3710,3770,3830,3890,3950,4010,4070,4130,4190,4250,4310,4370,4430,4490,4550,4610,4670,4730,4790,4850,4910,4970,5030,5090,5150,5210,5270,5330,5390,5450,5510,5570,5630,5690,5750,5810,5870,5930,5990,6050,6110,6170,6230,6290}
+};
+const U16 gVref_Voltage_Table_LP4[VREF_RANGE_MAX][VREF_VOLTAGE_TABLE_NUM]={
+ {1000,1040,1080,1120,1160,1200,1240,1280,1320,1360,1400,1440,1480,1520,1560,1600,1640,1680,1720,1760,1800,1840,1880,1920,1960,2000,2040,2080,2120,2160,2200,2240,2280,2320,2360,2400,2440,2480,2520,2560,2600,2640,2680,2720,2760,2800,2840,2880,2920,2960,3000},
+ {2200,2240,2280,2320,2360,2400,2440,2480,2520,2560,2600,2640,2680,2720,2760,2800,2840,2880,2920,2960,3000,3040,3080,3120,3160,3200,3240,3280,3320,3360,3400,3440,3480,3520,3560,3600,3640,3680,3720,3760,3880,3840,3880,3920,3960,4000,4040,4080,4120,4160,4200}
+};
+#define EyeScan_Pic_draw_line_Mirror 1
+#define EysScan_Pic_draw_1UI_line 1
+void EyeScan_Pic_draw_line(DRAMC_CTX_T *p, U8 draw_type, U8 u1VrefRange, U8 u1VrefIdx, U8 u1BitIdx, S16 u2DQDelayBegin, S16 u2DQDelayEnd, U8 u1FinalVrefRange, U16 Final_Vref_val, U8 VdlVWHigh_Upper_Vcent_Range, U32 VdlVWHigh_Upper_Vcent, U8 VdlVWHigh_Lower_Vcent_Range, U32 VdlVWHigh_Lower_Vcent, U16 FinalDQCaliDelay, S8 EyeScan_DelayCellPI_value, U16 delay_cell_ps, U16 Max_EyeScan_Min_val)
+{
+ int i;
+ int local_VrefIdx, local_Upper_Vcent, local_Lower_Vcent, local_Final_VrefIdx;
+ S8 EyeScan_Index;
+ S16 EyeScan_Min_val, EyeScan_Max_val, Final_EyeScan_Min_val=EYESCAN_DATA_INVALID, Final_EyeScan_Max_val=EYESCAN_DATA_INVALID, Final_EyeScan_winsize=1;
+ U16 *pVref_Voltage_Table[VREF_VOLTAGE_TABLE_NUM];
+ U32 PI_of_1_UI;
+
+ if (draw_type == 1)
+ {
+ pVref_Voltage_Table[VREF_RANGE_0]= (U16 *)gRXVref_Voltage_Table_LP4;
+ if(p->u2DelayCellTimex100!=0)
+ {
+ PI_of_1_UI = (50000000/(p->frequency*p->u2DelayCellTimex100));
+
+ FinalDQCaliDelay = (U16)EyeScan_DelayCellPI_value;
+ EyeScan_DelayCellPI_value = 0;
+ }
+ else
+ {
+ PI_of_1_UI = 0;
+ mcSHOW_ERR_MSG(("DelayCell is 0\n"));
+ }
+ }
+ else
+ {
+ if (p->dram_type == TYPE_LPDDR4)
+ {
+ pVref_Voltage_Table[VREF_RANGE_0] = (U16 *)gVref_Voltage_Table_LP4[VREF_RANGE_0];
+ pVref_Voltage_Table[VREF_RANGE_1] = (U16 *)gVref_Voltage_Table_LP4[VREF_RANGE_1];
+ }
+ if (p->dram_type == TYPE_LPDDR4X)
+ {
+ pVref_Voltage_Table[VREF_RANGE_0] = (U16 *)gVref_Voltage_Table_LP4X[VREF_RANGE_0];
+ pVref_Voltage_Table[VREF_RANGE_1] = (U16 *)gVref_Voltage_Table_LP4X[VREF_RANGE_1];
+ }
+
+ PI_of_1_UI = 32;
+ }
+
+ if (u1VrefRange==1 && u1VrefIdx <=20)
+ {
+ u1VrefRange=0;
+ u1VrefIdx += 30;
+ }
+ if (u1FinalVrefRange==1 && Final_Vref_val <=20)
+ {
+ u1FinalVrefRange=0;
+ Final_Vref_val += 30;
+ }
+ if (u1VrefRange != u1FinalVrefRange)
+ {
+ Final_Vref_val = 0xff;
+ }
+
+ local_Upper_Vcent = VdlVWHigh_Upper_Vcent_Range*VREF_VOLTAGE_TABLE_NUM+VdlVWHigh_Upper_Vcent;
+ local_Lower_Vcent = VdlVWHigh_Lower_Vcent_Range*VREF_VOLTAGE_TABLE_NUM+VdlVWHigh_Lower_Vcent;
+ local_VrefIdx = u1VrefRange*VREF_VOLTAGE_TABLE_NUM+u1VrefIdx;
+ local_Final_VrefIdx = u1FinalVrefRange*VREF_VOLTAGE_TABLE_NUM+Final_Vref_val;
+
+ if (VdlVWHigh_Upper_Vcent_Range==VREF_RANGE_1 && VdlVWHigh_Upper_Vcent<=20) local_Upper_Vcent = VdlVWHigh_Upper_Vcent_Range*VREF_VOLTAGE_TABLE_NUM+VdlVWHigh_Upper_Vcent-20;
+ if (VdlVWHigh_Lower_Vcent_Range==VREF_RANGE_1 && VdlVWHigh_Lower_Vcent<=20) local_Lower_Vcent = VdlVWHigh_Lower_Vcent_Range*VREF_VOLTAGE_TABLE_NUM+VdlVWHigh_Lower_Vcent-20;
+
+ mcSHOW_EYESCAN_MSG(("Vref-"));
+
+ if (draw_type == 1 && u1VrefIdx <= 7)
+ {
+ mcSHOW_EYESCAN_MSG((" "));
+ }
+
+ mcSHOW_EYESCAN_MSG(("%d.%d%d",pVref_Voltage_Table[u1VrefRange][u1VrefIdx]/100, ((pVref_Voltage_Table[u1VrefRange][u1VrefIdx]%100)/10), pVref_Voltage_Table[u1VrefRange][u1VrefIdx]%10));
+
+ if (draw_type == 1)
+ {
+ mcSHOW_EYESCAN_MSG(("m|"));
+ }
+ else
+ {
+ mcSHOW_EYESCAN_MSG(("%%|"));
+ }
+
+
+
+
+#if VENDER_JV_LOG || defined(RELEASE)
+#if EyeScan_Pic_draw_line_Mirror
+ EyeScan_DelayCellPI_value = 0-EyeScan_DelayCellPI_value;
+#endif
+#endif
+
+#if EyeScan_Pic_draw_line_Mirror
+ EyeScan_Index=EYESCAN_BROKEN_NUM-1;
+ EyeScan_Min_val = gEyeScan_Min[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+ EyeScan_Max_val = gEyeScan_Max[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+
+ while(EyeScan_Min_val==EYESCAN_DATA_INVALID && EyeScan_Index>0)
+ {
+ EyeScan_Index--;
+ EyeScan_Min_val = gEyeScan_Min[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+ EyeScan_Max_val = gEyeScan_Max[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+ }
+#else
+ EyeScan_Index=0;
+ EyeScan_Min_val = gEyeScan_Min[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+ EyeScan_Max_val = gEyeScan_Max[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+#endif
+
+ if ((EyeScan_Max_val - EyeScan_Min_val + 1) > Final_EyeScan_winsize)
+ {
+#if EyeScan_Pic_draw_line_Mirror
+ Final_EyeScan_Max_val = EyeScan_Max_val;
+ Final_EyeScan_Min_val = EyeScan_Min_val;
+#else
+ Final_EyeScan_Max_val = EyeScan_Max_val;
+ Final_EyeScan_Min_val = EyeScan_Min_val;
+#endif
+ Final_EyeScan_winsize = (EyeScan_Max_val - EyeScan_Min_val + 1);
+ }
+
+#if VENDER_JV_LOG || defined(RELEASE)
+#if EyeScan_Pic_draw_line_Mirror
+ for(i=(Max_EyeScan_Min_val+PI_of_1_UI+EyeScan_DelayCellPI_value)*delay_cell_ps/100; i>(Max_EyeScan_Min_val+EyeScan_DelayCellPI_value)*delay_cell_ps/100; i-=10)
+#else
+ for(i=(Max_EyeScan_Min_val+EyeScan_DelayCellPI_value)*delay_cell_ps/100; i<(Max_EyeScan_Min_val+PI_of_1_UI+EyeScan_DelayCellPI_value)*delay_cell_ps/100; i+=10)
+#endif
+#else
+#if EyeScan_Pic_draw_line_Mirror
+ for(i=u2DQDelayEnd; i>=u2DQDelayBegin; i--)
+#else
+ for(i=u2DQDelayBegin; i<=u2DQDelayEnd; i++)
+#endif
+#endif
+ {
+
+#if VENDER_JV_LOG || defined(RELEASE)
+#if EyeScan_Pic_draw_line_Mirror
+ if (i<=((EyeScan_Min_val+EyeScan_DelayCellPI_value)*delay_cell_ps/100) && EyeScan_Index!= 0)
+ {
+ EyeScan_Index--;
+ EyeScan_Min_val = gEyeScan_Min[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+ EyeScan_Max_val = gEyeScan_Max[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+
+ if ((EyeScan_Max_val - EyeScan_Min_val + 1) > Final_EyeScan_winsize)
+ {
+ Final_EyeScan_Max_val = EyeScan_Max_val;
+ Final_EyeScan_Min_val = EyeScan_Min_val;
+ Final_EyeScan_winsize = (EyeScan_Max_val - EyeScan_Min_val + 1);
+ }
+
+ }
+#endif
+#else
+#if EyeScan_Pic_draw_line_Mirror
+ if (i==(EyeScan_Min_val) && EyeScan_Index!= 0)
+ {
+ EyeScan_Index--;
+ EyeScan_Min_val = gEyeScan_Min[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+ EyeScan_Max_val = gEyeScan_Max[u1VrefIdx+u1VrefRange*30][u1BitIdx][EyeScan_Index];
+
+ if ((EyeScan_Max_val - EyeScan_Min_val + 1) > Final_EyeScan_winsize)
+ {
+ Final_EyeScan_Max_val = EyeScan_Max_val;
+ Final_EyeScan_Min_val = EyeScan_Min_val;
+ Final_EyeScan_winsize = (EyeScan_Max_val - EyeScan_Min_val + 1);
+ }
+
+ }
+#endif
+#endif
+
+#if VENDER_JV_LOG || defined(RELEASE)
+ if (i>=((EyeScan_Min_val+EyeScan_DelayCellPI_value)*delay_cell_ps/100) && i<=((EyeScan_Max_val+EyeScan_DelayCellPI_value)*delay_cell_ps/100))
+#else
+ if (i>=(EyeScan_Min_val) && i<=(EyeScan_Max_val))
+#endif
+ {
+#if !VENDER_JV_LOG && !defined(RELEASE)
+ if (i==FinalDQCaliDelay+EyeScan_DelayCellPI_value) //Final DQ delay
+ {
+ if (gEye_Scan_color_flag)
+ {
+ mcSHOW_EYESCAN_MSG(("\033[0;105mH\033[m"));
+ }
+ else
+ {
+ mcSHOW_EYESCAN_MSG(("H"));
+ }
+ }
+ else
+ if (local_VrefIdx==local_Final_VrefIdx) //Final Vref
+ {
+ if (gEye_Scan_color_flag)
+ {
+ mcSHOW_EYESCAN_MSG(("\033[0;105mV\033[m"));
+ }
+ else
+ {
+ mcSHOW_EYESCAN_MSG(("V"));
+ }
+ }
+ else //spec in margin
+ if (local_VrefIdx<=local_Upper_Vcent && local_VrefIdx>=local_Lower_Vcent && i>=(FinalDQCaliDelay+EyeScan_DelayCellPI_value-3) && i<=(FinalDQCaliDelay+EyeScan_DelayCellPI_value+3))
+ {
+ if (gEye_Scan_color_flag)
+ {
+ mcSHOW_EYESCAN_MSG(("\033[0;103mQ\033[m"));
+ }
+ else
+ {
+ mcSHOW_EYESCAN_MSG(("Q"));
+ }
+ }
+ else //pass margin
+#endif
+ {
+#if VENDER_JV_LOG || defined(RELEASE)
+ if (gEye_Scan_color_flag)
+ {
+ mcSHOW_EYESCAN_MSG(("\033[0;102mO\033[m"));
+ }
+ else
+ {
+ mcSHOW_EYESCAN_MSG(("O"));
+ }
+#else
+ if (gEye_Scan_color_flag)
+ {
+ mcSHOW_EYESCAN_MSG(("\033[0;102mO\033[m"));
+ }
+ else
+ {
+ mcSHOW_EYESCAN_MSG(("O"));
+ }
+#endif
+ }
+ }
+ else
+ {
+#if !VENDER_JV_LOG && !defined(RELEASE)
+#if EysScan_Pic_draw_1UI_line
+ if (i==(int)(Max_EyeScan_Min_val) || i==(int)(Max_EyeScan_Min_val+PI_of_1_UI))
+ {
+ if (gEye_Scan_color_flag)
+ {
+ mcSHOW_EYESCAN_MSG(("\033[0;107m.\033[m"));
+ }
+ else
+ {
+ mcSHOW_EYESCAN_MSG(("."));
+ }
+ }
+ else
+#endif
+#endif
+ {
+ //not valid
+#if VENDER_JV_LOG || defined(RELEASE)
+ if (gEye_Scan_color_flag)
+ {
+ mcSHOW_EYESCAN_MSG(("\033[0;100m.\033[m"));
+ }
+ else
+ {
+ mcSHOW_EYESCAN_MSG(("."));
+ }
+#else
+ if (gEye_Scan_color_flag)
+ {
+ mcSHOW_EYESCAN_MSG(("\033[0;100m.\033[m"));
+ }
+ else
+ {
+ mcSHOW_EYESCAN_MSG(("."));
+ }
+#endif
+ }
+ }
+ }
+
+
+#if EyeScan_Pic_draw_line_Mirror
+ if (Final_EyeScan_Min_val!=EYESCAN_DATA_INVALID && Final_EyeScan_Max_val!=EYESCAN_DATA_INVALID)
+ {
+#if !VENDER_JV_LOG && !defined(RELEASE)
+ if (Final_EyeScan_Max_val>(FinalDQCaliDelay+EyeScan_DelayCellPI_value) && (FinalDQCaliDelay+EyeScan_DelayCellPI_value)>Final_EyeScan_Min_val)
+ {
+ mcSHOW_EYESCAN_MSG((" -%d ",(Final_EyeScan_Max_val-(FinalDQCaliDelay+EyeScan_DelayCellPI_value))));
+ mcSHOW_EYESCAN_MSG(("%d ", ((FinalDQCaliDelay+EyeScan_DelayCellPI_value)-Final_EyeScan_Min_val)));
+ }
+ else if (Final_EyeScan_Max_val>(FinalDQCaliDelay+EyeScan_DelayCellPI_value) && Final_EyeScan_Min_val>(FinalDQCaliDelay+EyeScan_DelayCellPI_value))
+ {
+ mcSHOW_EYESCAN_MSG((" -%d ",(Final_EyeScan_Max_val-Final_EyeScan_Min_val)));
+ mcSHOW_EYESCAN_MSG((" --- "));
+ }
+ else if ((FinalDQCaliDelay+EyeScan_DelayCellPI_value)>Final_EyeScan_Max_val && (FinalDQCaliDelay+EyeScan_DelayCellPI_value)>Final_EyeScan_Min_val)
+ {
+ mcSHOW_EYESCAN_MSG((" --- "));
+ mcSHOW_EYESCAN_MSG(("%d ", (Final_EyeScan_Max_val-Final_EyeScan_Min_val)));
+ }
+ else
+ {
+ mcSHOW_EYESCAN_MSG((" --- "));
+ mcSHOW_EYESCAN_MSG((" --- "));
+ }
+#endif
+ //window
+#if VENDER_JV_LOG || defined(RELEASE)
+ mcSHOW_EYESCAN_MSG(("%dps", Final_EyeScan_winsize*delay_cell_ps/100));
+#else
+ mcSHOW_EYESCAN_MSG(("%d", Final_EyeScan_winsize));
+#endif
+ }
+#else
+ if (Final_EyeScan_Max_val != Final_EyeScan_Min_val && Final_EyeScan_Max_val!=EYESCAN_DATA_INVALID)
+ {
+#if !VENDER_JV_LOG && !defined(RELEASE)
+ if (Final_EyeScan_Max_val>(FinalDQCaliDelay+EyeScan_DelayCellPI_value) && (FinalDQCaliDelay+EyeScan_DelayCellPI_value)>Final_EyeScan_Min_val)
+ {
+ mcSHOW_EYESCAN_MSG((" -%d ", ((FinalDQCaliDelay+EyeScan_DelayCellPI_value)-Final_EyeScan_Min_val)));
+ mcSHOW_EYESCAN_MSG(("%d ",(Final_EyeScan_Max_val-(FinalDQCaliDelay+EyeScan_DelayCellPI_value))));
+ }
+ else if (Final_EyeScan_Max_val>(FinalDQCaliDelay+EyeScan_DelayCellPI_value) && Final_EyeScan_Min_val>(FinalDQCaliDelay+EyeScan_DelayCellPI_value))
+ {
+ mcSHOW_EYESCAN_MSG((" --- "));
+ mcSHOW_EYESCAN_MSG(("%d ",(Final_EyeScan_Max_val-Final_EyeScan_Min_val)));
+ }
+ else if ((FinalDQCaliDelay+EyeScan_DelayCellPI_value)>Final_EyeScan_Max_val && (FinalDQCaliDelay+EyeScan_DelayCellPI_value)>Final_EyeScan_Min_val)
+ {
+ mcSHOW_EYESCAN_MSG((" -%d ", (Final_EyeScan_Max_val-Final_EyeScan_Min_val)));
+ mcSHOW_EYESCAN_MSG((" --- "));
+ }
+ else
+ {
+ mcSHOW_EYESCAN_MSG((" --- "));
+ mcSHOW_EYESCAN_MSG((" --- "));
+ }
+#endif
+ //window
+#if VENDER_JV_LOG || defined(RELEASE)
+ mcSHOW_EYESCAN_MSG(("%dps", Final_EyeScan_winsize*delay_cell_ps/100));
+#else
+ mcSHOW_EYESCAN_MSG(("%d", Final_EyeScan_winsize));
+#endif
+ }
+#endif
+
+ mcSHOW_EYESCAN_MSG(("\n"));
+
+
+}
+
+void print_EYESCAN_LOG_message(DRAMC_CTX_T *p, U8 print_type)
+{
+ U32 u1ChannelIdx=p->channel, u1RankIdx=p->rank;
+ S8 u1VrefIdx;
+ U8 u1VrefRange;
+ U8 u1BitIdx, u1CA;
+ U32 VdlVWTotal, Vcent_DQ;
+ U32 VdlVWHigh_Upper_Vcent=VREF_VOLTAGE_TABLE_NUM-1, VdlVWHigh_Lower_Vcent=0, VdlVWBest_Vcent=0;
+ U32 VdlVWHigh_Upper_Vcent_Range=1, VdlVWHigh_Lower_Vcent_Range=0, VdlVWBest_Vcent_Range=1;;
+ U8 Upper_Vcent_pass_flag=0, Lower_Vcent_pass_flag=0;
+ S32 i, vrefrange_i;
+ U8 local_channel_num=2;
+ U8 shuffleIdx;
+ U8 TXVrefRange, CBTVrefRange;
+ U32 vddq;
+ U8 Min_Value_1UI_Line;
+ S8 EyeScan_Index;
+ U16 *pVref_Voltage_Table[VREF_VOLTAGE_TABLE_NUM];
+ S8 EyeScan_DelayCellPI_value;
+ U8 EyeScanVcent[10+DQ_DATA_WIDTH_LP4*2], max_winsize;
+ U8 minCBTEyeScanVcentUpperBound=0xff, minCBTEyeScanVcentUpperBound_bit=0;
+ U8 minCBTEyeScanVcentLowerBound=0xff, minCBTEyeScanVcentLowerBound_bit=0;
+ U8 minRXEyeScanVcentUpperBound=0xff, minRXEyeScanVcentUpperBound_bit=0;
+ U8 minRXEyeScanVcentLowerBound=0xff, minRXEyeScanVcentLowerBound_bit=0;
+ U8 minTXEyeScanVcentUpperBound=0xff, minTXEyeScanVcentUpperBound_bit=0;
+ U8 minTXEyeScanVcentLowerBound=0xff, minTXEyeScanVcentLowerBound_bit=0;
+ U16 one_pi_ps=100000000/(p->frequency*2*32);
+ U8 u1CBTEyeScanEnable, u1RXEyeScanEnable, u1TXEyeScanEnable;
+
+ U16 u2DQDelayBegin, u2DQDelayEnd;
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ local_channel_num = p->support_channel_num;
+ }
+ else
+ {
+ //LP3
+ local_channel_num = 1;
+ }
+
+ if (p->dram_type == TYPE_LPDDR4)
+ {
+ pVref_Voltage_Table[VREF_RANGE_0] = (U16 *)gVref_Voltage_Table_LP4[VREF_RANGE_0];
+ pVref_Voltage_Table[VREF_RANGE_1] = (U16 *)gVref_Voltage_Table_LP4[VREF_RANGE_1];
+ }
+ if (p->dram_type == TYPE_LPDDR4X)
+ {
+ pVref_Voltage_Table[VREF_RANGE_0] = (U16 *)gVref_Voltage_Table_LP4X[VREF_RANGE_0];
+ pVref_Voltage_Table[VREF_RANGE_1] = (U16 *)gVref_Voltage_Table_LP4X[VREF_RANGE_1];
+ }
+
+ u1CBTEyeScanEnable = (gCBT_EYE_Scan_flag==1 && ((gCBT_EYE_Scan_only_higheset_freq_flag==1 && p->frequency == u2DFSGetHighestFreq(p)) || gCBT_EYE_Scan_only_higheset_freq_flag==0));
+ u1RXEyeScanEnable = (gRX_EYE_Scan_flag==1 && ((gRX_EYE_Scan_only_higheset_freq_flag==1 && p->frequency == u2DFSGetHighestFreq(p)) || gRX_EYE_Scan_only_higheset_freq_flag==0));
+ u1TXEyeScanEnable = (gTX_EYE_Scan_flag==1 && ((gTX_EYE_Scan_only_higheset_freq_flag==1 && p->frequency == u2DFSGetHighestFreq(p)) || gTX_EYE_Scan_only_higheset_freq_flag==0));
+
+
+
+
+/**************************************************************************************
+ CBT EYESCAN log
+***************************************************************************************/
+ if (p->frequency <=934) VdlVWTotal = 17500; //VcIVW 175mv
+ else if (p->frequency <= 1600) VdlVWTotal = 15500; //VcIVW 155mv
+ else VdlVWTotal = 14500; //VcIVW 145mv
+
+ CBTVrefRange = (u1MR12Value[p->channel][p->rank][p->dram_fsp]>>6)&1;
+
+#if !VENDER_JV_LOG && !defined(RELEASE)
+ if (print_type==0)
+ if (u1CBTEyeScanEnable)
+ {
+ mcSHOW_DBG_MSG(("[EYESCAN_LOG] CBT Window\n"));
+ vddq=vGetVoltage(p, 2)/1000; //mv
+ mcSHOW_DBG_MSG(("[EYESCAN_LOG] VDDQ=%dmV\n",vddq));
+// for(u1ChannelIdx=CHANNEL_A; u1ChannelIdx<local_channel_num; u1ChannelIdx++)
+ {
+// for(u1RankIdx = RANK_0; u1RankIdx < 2; u1RankIdx++)
+ {
+ mcSHOW_DBG_MSG(("[EYESCAN_LOG] CBT Channel%d Range %d Final_Vref Vcent=%d(%dmV(X100))\n",
+ u1ChannelIdx,
+ CBTVrefRange,
+ gFinalCBTVrefDQ[u1ChannelIdx][u1RankIdx],
+ pVref_Voltage_Table[CBTVrefRange][gFinalCBTVrefDQ[u1ChannelIdx][u1RankIdx]]*vddq/100));
+
+ Vcent_DQ = pVref_Voltage_Table[CBTVrefRange][gFinalCBTVrefDQ[u1ChannelIdx][u1RankIdx]]*vddq/100;
+
+ //find VdlVWHigh first
+ VdlVWHigh_Upper_Vcent_Range = 1;
+ VdlVWHigh_Upper_Vcent = VREF_VOLTAGE_TABLE_NUM-1;
+ vrefrange_i = CBTVrefRange;
+ for(i=(gFinalCBTVrefDQ[u1ChannelIdx][u1RankIdx]); i<VREF_VOLTAGE_TABLE_NUM; i++)
+ {
+ if (((pVref_Voltage_Table[vrefrange_i][i]*vddq/100 - Vcent_DQ)) >= VdlVWTotal/2)
+ {
+ /* find VdlVWHigh upper bound */
+ VdlVWHigh_Upper_Vcent = i;
+ VdlVWHigh_Upper_Vcent_Range = vrefrange_i;
+ break;
+ }
+ if (i==(VREF_VOLTAGE_TABLE_NUM-1) && vrefrange_i==0)
+ {
+ vrefrange_i=1;
+ i=20;
+ }
+ }
+ mcSHOW_DBG_MSG(("[EYESCAN_LOG] CBT VdlVWHigh_Upper Range=%d Vcent=%d(%dmV(X100))\n",
+ VdlVWHigh_Upper_Vcent_Range,
+ VdlVWHigh_Upper_Vcent,
+ pVref_Voltage_Table[VdlVWHigh_Upper_Vcent_Range][VdlVWHigh_Upper_Vcent]*vddq/100));
+
+ //find VldVWLow first
+ VdlVWHigh_Lower_Vcent_Range = 0;
+ VdlVWHigh_Lower_Vcent = 0;
+ vrefrange_i = CBTVrefRange;
+ for(i=(gFinalCBTVrefDQ[u1ChannelIdx][u1RankIdx]); i>=0; i--)
+ {
+ if (((Vcent_DQ - pVref_Voltage_Table[vrefrange_i][i]*vddq/100)) >= VdlVWTotal/2)
+ {
+ /* find VdlVWHigh lower bound */
+ VdlVWHigh_Lower_Vcent = i;
+ VdlVWHigh_Lower_Vcent_Range = vrefrange_i;
+ break;
+ }
+ if (i<=21 && vrefrange_i==1)
+ {
+ vrefrange_i=0;
+ i=VREF_VOLTAGE_TABLE_NUM-(21-i);
+ }
+ }
+ mcSHOW_DBG_MSG(("[EYESCAN_LOG] CBT VdlVWHigh_Lower Range=%d Vcent=%d(%dmV(X100))\n",
+ VdlVWHigh_Lower_Vcent_Range,
+ VdlVWHigh_Lower_Vcent,
+ pVref_Voltage_Table[VdlVWHigh_Lower_Vcent_Range][VdlVWHigh_Lower_Vcent]*vddq/100));
+
+#ifdef FOR_HQA_TEST_USED
+ EyeScanVcent[0] = CBTVrefRange;
+ EyeScanVcent[1] = gFinalCBTVrefDQ[u1ChannelIdx][u1RankIdx];
+ EyeScanVcent[2] = VdlVWHigh_Upper_Vcent_Range;
+ EyeScanVcent[3] = VdlVWHigh_Upper_Vcent;
+ EyeScanVcent[4] = VdlVWHigh_Lower_Vcent_Range;
+ EyeScanVcent[5] = VdlVWHigh_Lower_Vcent;
+#endif
+
+ shuffleIdx = get_shuffleIndex_by_Freq(p);
+
+ // mcSHOW_DBG_MSG(("[EYESCAN_LOG] delay cell %d/100ps\n", u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx]));
+
+ for (u1CA=0; u1CA<CATRAINING_NUM_LP4; u1CA++)
+ {
+
+ // compare Upper/Lower Vcent pass criterion is pass or fail?
+ for(u1VrefIdx=gFinalCBTVrefDQ[u1ChannelIdx][u1RankIdx]+CBTVrefRange*30; u1VrefIdx<=(S8)(VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30); u1VrefIdx++)
+ {
+ Upper_Vcent_pass_flag = 0;
+ for (EyeScan_Index=0; EyeScan_Index<EYESCAN_BROKEN_NUM; EyeScan_Index++)
+ {
+ if ((((gEyeScan_CaliDelay[0]+gEyeScan_DelayCellPI[u1CA]) - gEyeScan_Min[u1VrefIdx][u1CA][EyeScan_Index]) >=4 ) && ((gEyeScan_Max[u1VrefIdx][u1CA][EyeScan_Index] - (gEyeScan_CaliDelay[0]+gEyeScan_DelayCellPI[u1CA])) >=4 ))
+ {
+ Upper_Vcent_pass_flag = 1;
+ }
+ }
+ if (Upper_Vcent_pass_flag == 0) break; // fail!!
+ }
+ for(u1VrefIdx=VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30; u1VrefIdx<=(S8)(gFinalCBTVrefDQ[u1ChannelIdx][u1RankIdx]+CBTVrefRange*30); u1VrefIdx++)
+ {
+ Lower_Vcent_pass_flag = 0;
+ for (EyeScan_Index=0; EyeScan_Index<EYESCAN_BROKEN_NUM; EyeScan_Index++)
+ {
+ if ((((gEyeScan_CaliDelay[0]+gEyeScan_DelayCellPI[u1CA]) - gEyeScan_Min[u1VrefIdx][u1CA][EyeScan_Index]) >=4 ) && ((gEyeScan_Max[u1VrefIdx][u1CA][EyeScan_Index] - (gEyeScan_CaliDelay[0]+gEyeScan_DelayCellPI[u1CA])) >=4 ))
+ {
+ Lower_Vcent_pass_flag = 1;
+ }
+ }
+ if (Lower_Vcent_pass_flag == 0) break; //fail!!
+ }
+
+ mcSHOW_DBG_MSG(("[EYESCAN_LOG] %d Channel%d Rank%d CA%d\tHigher VdlTW=%dPI(%d/100ps)(%s)\tLower VdlTW=%dpi(%d/100ps)(%s)\n",
+ p->frequency*2,
+ u1ChannelIdx,
+ u1RankIdx,
+ u1CA,
+ gEyeScan_WinSize[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1CA],
+ gEyeScan_WinSize[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1CA]*one_pi_ps,
+ Upper_Vcent_pass_flag==1 ? "PASS" : "FAIL",
+ gEyeScan_WinSize[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1CA],
+ gEyeScan_WinSize[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1CA]*one_pi_ps,
+ Lower_Vcent_pass_flag==1 ? "PASS" : "FAIL"
+ ));
+
+#ifdef FOR_HQA_TEST_USED
+ //find VdlVWBest Vref Range and Vref
+ VdlVWBest_Vcent_Range = 1;
+ VdlVWBest_Vcent = VREF_VOLTAGE_TABLE_NUM-1;
+ vrefrange_i = 1;
+ max_winsize = 0;
+ for(i=VREF_VOLTAGE_TABLE_NUM-1; i>=0; i--)
+ {
+ if (gEyeScan_WinSize[i+vrefrange_i*30][u1CA] > max_winsize)
+ {
+ max_winsize = gEyeScan_WinSize[i+vrefrange_i*30][u1CA];
+ VdlVWBest_Vcent_Range = vrefrange_i;
+ VdlVWBest_Vcent = i;
+ }
+ if (i==21 && vrefrange_i==1)
+ {
+ vrefrange_i=0;
+ i=VREF_VOLTAGE_TABLE_NUM;
+ }
+ }
+
+ EyeScanVcent[10+u1CA*2] = VdlVWBest_Vcent_Range;
+ EyeScanVcent[10+u1CA*2+1] = VdlVWBest_Vcent;
+#endif
+
+ if (gEyeScan_WinSize[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1CA] < minCBTEyeScanVcentUpperBound)
+ {
+ minCBTEyeScanVcentUpperBound = gEyeScan_WinSize[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1CA];
+ minCBTEyeScanVcentUpperBound_bit = u1CA;
+ }
+ if (gEyeScan_WinSize[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1CA] < minCBTEyeScanVcentLowerBound)
+ {
+ minCBTEyeScanVcentLowerBound = gEyeScan_WinSize[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1CA];
+ minCBTEyeScanVcentLowerBound_bit = u1CA;
+ }
+ }
+#ifdef FOR_HQA_TEST_USED
+#ifdef FOR_HQA_REPORT_USED
+ print_EyeScanVcent_for_HQA_report_used(p, print_type, u1ChannelIdx, u1RankIdx, EyeScanVcent, minCBTEyeScanVcentUpperBound, minCBTEyeScanVcentUpperBound_bit, minCBTEyeScanVcentLowerBound, minCBTEyeScanVcentLowerBound_bit);
+#endif
+#endif
+ }
+ }
+ }
+#endif
+
+
+
+
+
+ if (print_type==0)
+ if (u1CBTEyeScanEnable)
+ {
+ mcSHOW_DBG_MSG(("\n\n"));
+
+ for (u1CA=0; u1CA<CATRAINING_NUM_LP4; u1CA++)
+ {
+ EyeScan_Index = 0;
+
+#if EyeScan_Pic_draw_line_Mirror
+ EyeScan_DelayCellPI_value = 0-gEyeScan_DelayCellPI[u1CA];
+#else
+ EyeScan_DelayCellPI_value = gEyeScan_DelayCellPI[u1CA];
+#endif
+ Min_Value_1UI_Line = gEyeScan_CaliDelay[0]-16-EyeScan_DelayCellPI_value;
+
+
+ mcSHOW_EYESCAN_MSG(("[EYESCAN_LOG] CBT EYESCAN Channel%d, Rank%d, CA%d ===\n",p->channel, p->rank, u1CA));
+
+#if VENDER_JV_LOG || defined(RELEASE)
+ for(i=0; i<8+one_pi_ps*32/1000; i++) mcSHOW_EYESCAN_MSG((" "));
+ mcSHOW_EYESCAN_MSG(("window\n"));
+#else
+ for(i=0; i<8+one_pi_ps*32/1000; i++) mcSHOW_EYESCAN_MSG((" "));
+ mcSHOW_EYESCAN_MSG(("first last window\n"));
+#endif
+
+ u1VrefRange=1;
+ for (u1VrefIdx=VREF_VOLTAGE_TABLE_NUM-1; u1VrefIdx>=0; u1VrefIdx--)
+ {
+
+ EyeScan_Pic_draw_line(p, 0, u1VrefRange, u1VrefIdx, u1CA, 0, 64, CBTVrefRange, gFinalCBTVrefDQ[u1ChannelIdx][u1RankIdx], VdlVWHigh_Upper_Vcent_Range, VdlVWHigh_Upper_Vcent, VdlVWHigh_Lower_Vcent_Range, VdlVWHigh_Lower_Vcent, gEyeScan_CaliDelay[0], gEyeScan_DelayCellPI[u1CA], one_pi_ps, Min_Value_1UI_Line);
+
+ if (u1VrefRange==VREF_RANGE_1 && u1VrefIdx==21)
+ {
+ u1VrefRange=VREF_RANGE_0;
+ u1VrefIdx=VREF_VOLTAGE_TABLE_NUM;
+ }
+ }
+ mcSHOW_EYESCAN_MSG(("\n\n"));
+
+ }
+ }
+
+
+
+
+
+/**************************************************************************************
+ RX EYESCAN log
+***************************************************************************************/
+ if (p->frequency <=1600) VdlVWTotal = 10000; //14000; //140mv
+ else VdlVWTotal = 10000; //12000; //120mv
+
+#if !VENDER_JV_LOG && !defined(RELEASE)
+ if (print_type==1)
+ if (u1RXEyeScanEnable)
+ {
+ mcSHOW_DBG_MSG(("[EYESCAN_LOG] RX Window\n"));
+ {
+ mcSHOW_DBG_MSG(("[EYESCAN_LOG] RX Final_Vref Vcent Channel%d %d(%dmV(X100))\n",
+ u1ChannelIdx,
+ gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx],
+ gRXVref_Voltage_Table_LP4[gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx]]));
+
+ Vcent_DQ = gRXVref_Voltage_Table_LP4[gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx]];
+
+ //find VdlVWHigh first
+ VdlVWHigh_Upper_Vcent_Range = 0;
+ VdlVWHigh_Upper_Vcent = RX_VREF_RANGE_END;
+ for(i=gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx]; i<=RX_VREF_RANGE_END; i++)
+ {
+ if (gRXVref_Voltage_Table_LP4[i] - Vcent_DQ >= VdlVWTotal/2)
+ {
+ /* find VdlVWHigh upper bound */
+ VdlVWHigh_Upper_Vcent = i;
+ break;
+ }
+ }
+ mcSHOW_DBG_MSG(("[EYESCAN_LOG] RX VdlVWHigh_Upper Vcent=%d(%dmV(X100))\n", VdlVWHigh_Upper_Vcent, gRXVref_Voltage_Table_LP4[VdlVWHigh_Upper_Vcent]));
+
+ //find VldVWLow first
+ VdlVWHigh_Lower_Vcent_Range = 0;
+ VdlVWHigh_Lower_Vcent = 0;
+ for(i=gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx]; i>=0; i--)
+ {
+ if (Vcent_DQ - gRXVref_Voltage_Table_LP4[i] >= VdlVWTotal/2)
+ {
+ /* find VdlVWHigh lower bound */
+ VdlVWHigh_Lower_Vcent = i;
+ break;
+ }
+ }
+ mcSHOW_DBG_MSG(("[EYESCAN_LOG] RX VdlVWHigh_Lower Vcent=%d(%dmV(X100))\n", VdlVWHigh_Lower_Vcent, gRXVref_Voltage_Table_LP4[VdlVWHigh_Lower_Vcent]));
+
+#ifdef FOR_HQA_TEST_USED
+ EyeScanVcent[0] = gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx];
+ EyeScanVcent[1] = VdlVWHigh_Upper_Vcent;
+ EyeScanVcent[2] = VdlVWHigh_Lower_Vcent;
+#endif
+
+ shuffleIdx = get_shuffleIndex_by_Freq(p);
+
+ mcSHOW_DBG_MSG(("[EYESCAN_LOG] delay cell %d/100ps\n", u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx]));
+
+ for (u1BitIdx=0; u1BitIdx<p->data_width; u1BitIdx++)
+ {
+ mcSHOW_DBG_MSG(("[EYESCAN_LOG] %d Channel%d Bit%d(DRAM DQ%d)\tHigher VdlTW=%d/100ps\tLower VdlTW=%d/100ps\n",
+ p->frequency*2,
+ u1ChannelIdx,
+ u1BitIdx,
+ uiLPDDR4_O1_Mapping_POP[p->channel][u1BitIdx],
+ gEyeScan_WinSize[VdlVWHigh_Upper_Vcent][u1BitIdx]*u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx],
+ gEyeScan_WinSize[VdlVWHigh_Lower_Vcent][u1BitIdx]*u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx]
+ ));
+
+#ifdef FOR_HQA_TEST_USED
+ //find VdlVWBest Vref Range and Vref
+ VdlVWBest_Vcent = VREF_VOLTAGE_TABLE_NUM-1;
+ max_winsize = 0;
+ for(i=RX_VREF_RANGE_END; i>=0; i--)
+ {
+ if (gEyeScan_WinSize[i][u1BitIdx] > max_winsize)
+ {
+ max_winsize = gEyeScan_WinSize[i][u1BitIdx];
+ VdlVWBest_Vcent = i;
+ }
+ }
+
+ EyeScanVcent[10+u1BitIdx] = VdlVWBest_Vcent;
+#endif
+
+ if (gEyeScan_WinSize[VdlVWHigh_Upper_Vcent][u1BitIdx] < minRXEyeScanVcentUpperBound)
+ {
+ minRXEyeScanVcentUpperBound = gEyeScan_WinSize[VdlVWHigh_Upper_Vcent][u1BitIdx];
+ minRXEyeScanVcentUpperBound_bit = u1BitIdx;
+ }
+ if (gEyeScan_WinSize[VdlVWHigh_Lower_Vcent][u1BitIdx] < minRXEyeScanVcentLowerBound)
+ {
+ minRXEyeScanVcentLowerBound = gEyeScan_WinSize[VdlVWHigh_Lower_Vcent][u1BitIdx];
+ minRXEyeScanVcentLowerBound_bit = u1BitIdx;
+ }
+ }
+
+#ifdef FOR_HQA_TEST_USED
+#ifdef FOR_HQA_REPORT_USED
+ print_EyeScanVcent_for_HQA_report_used(p, print_type, u1ChannelIdx, u1RankIdx, EyeScanVcent, minRXEyeScanVcentUpperBound, minRXEyeScanVcentUpperBound_bit, minRXEyeScanVcentLowerBound, minRXEyeScanVcentLowerBound_bit);
+#endif
+#endif
+ }
+ }
+#endif
+
+
+
+ if (print_type==1)
+ if (u1RXEyeScanEnable)
+ {
+ int drawend, drawbegin;
+
+ mcSHOW_DBG_MSG(("\n\n"));
+
+ for (u1BitIdx=0; u1BitIdx<p->data_width; u1BitIdx++)
+ {
+ EyeScan_Index = 0;
+
+ Min_Value_1UI_Line = gEyeScan_DelayCellPI[u1BitIdx]-16;
+
+ mcSHOW_EYESCAN_MSG(("[EYESCAN_LOG] RX EYESCAN Channel%d, Rank%d, DQ%d ===\n",p->channel, p->rank, u1BitIdx));
+
+#if VENDER_JV_LOG || defined(RELEASE)
+ for(i=0; i<8+one_pi_ps*32/1000; i++) mcSHOW_EYESCAN_MSG((" "));
+ mcSHOW_EYESCAN_MSG(("window\n"));
+#else
+ for(i=0; i<8+one_pi_ps*32/1000; i++) mcSHOW_EYESCAN_MSG((" "));
+ mcSHOW_EYESCAN_MSG(("first last window\n"));
+#endif
+
+ drawbegin = -32 ;//gEyeScan_Min[gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx]][u1BitIdx][EyeScan_Index]-5;
+ drawend = 64;
+
+ u1VrefRange=0;
+ for (u1VrefIdx=RX_VREF_RANGE_END; u1VrefIdx>=0; u1VrefIdx--)
+ {
+//fra EyeScan_Pic_draw_line(p, 1, u1VrefRange, u1VrefIdx, u1BitIdx, p->odt_onoff==ODT_ON ? 0 : -32, 64, u1VrefRange, gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx], VdlVWHigh_Upper_Vcent_Range, VdlVWHigh_Upper_Vcent, VdlVWHigh_Lower_Vcent_Range, VdlVWHigh_Lower_Vcent, gEyeScan_CaliDelay[u1BitIdx/8], gEyeScan_DelayCellPI[u1BitIdx], one_pi_ps, Min_Value_1UI_Line);
+ EyeScan_Pic_draw_line(p, 1, u1VrefRange, u1VrefIdx, u1BitIdx, drawbegin, drawend, u1VrefRange, gFinalRXVrefDQ[u1ChannelIdx][u1RankIdx], VdlVWHigh_Upper_Vcent_Range, VdlVWHigh_Upper_Vcent, VdlVWHigh_Lower_Vcent_Range, VdlVWHigh_Lower_Vcent, gEyeScan_CaliDelay[u1BitIdx/8], gEyeScan_DelayCellPI[u1BitIdx], one_pi_ps, Min_Value_1UI_Line);
+ }
+ mcSHOW_EYESCAN_MSG(("\n\n"));
+
+ }
+//fra while(1);
+ }
+
+
+
+
+
+/**************************************************************************************
+ TX EYESCAN log
+***************************************************************************************/
+ TXVrefRange = (u1MR14Value[p->channel][p->rank][p->dram_fsp]>>6)&1;
+
+#if !VENDER_JV_LOG && !defined(RELEASE)
+ if (print_type==2)
+ if (u1TXEyeScanEnable)
+ { U8 cal_length;
+ U16 finalTXVref;
+
+ if (print_type==2)
+ {
+ mcSHOW_DBG_MSG(("[EYESCAN_LOG] TX DQ Window\n"));
+ cal_length = p->data_width;
+ finalTXVref = gFinalTXVrefDQ[u1ChannelIdx][u1RankIdx];
+ }
+
+ vddq=vGetVoltage(p, 2)/1000; //mv
+ mcSHOW_DBG_MSG(("[EYESCAN_LOG] VDDQ=%dmV\n",vddq));
+// for(u1ChannelIdx=CHANNEL_A; u1ChannelIdx<local_channel_num; u1ChannelIdx++)
+ {
+// for(u1RankIdx = RANK_0; u1RankIdx < 2; u1RankIdx++)
+ {
+ if (print_type==2)
+ {
+ mcSHOW_DBG_MSG(("[EYESCAN_LOG] TX Channel%d Range %d Final_Vref Vcent=%d(%dmV(X100))\n",
+ u1ChannelIdx,
+ TXVrefRange,
+ gFinalTXVrefDQ[u1ChannelIdx][u1RankIdx],
+ pVref_Voltage_Table[TXVrefRange][gFinalTXVrefDQ[u1ChannelIdx][u1RankIdx]]*vddq/100));
+
+ Vcent_DQ = pVref_Voltage_Table[TXVrefRange][gFinalTXVrefDQ[u1ChannelIdx][u1RankIdx]]*vddq/100;
+ }
+
+ //find VdlVWHigh first
+ VdlVWHigh_Upper_Vcent_Range = 1;
+ VdlVWHigh_Upper_Vcent = VREF_VOLTAGE_TABLE_NUM-1;
+ vrefrange_i = TXVrefRange;
+ for(i=(finalTXVref); i<VREF_VOLTAGE_TABLE_NUM; i++)
+ {
+ if (((pVref_Voltage_Table[vrefrange_i][i]*vddq/100 - Vcent_DQ)) >= VdlVWTotal/2)
+ {
+ /* find VdlVWHigh upper bound */
+ VdlVWHigh_Upper_Vcent = i;
+ VdlVWHigh_Upper_Vcent_Range = vrefrange_i;
+ break;
+ }
+ if (i==(VREF_VOLTAGE_TABLE_NUM-1) && vrefrange_i==0)
+ {
+ vrefrange_i=1;
+ i=20;
+ }
+ }
+ mcSHOW_DBG_MSG(("[EYESCAN_LOG] TX VdlVWHigh_Upper Range=%d Vcent=%d(%dmV(X100))\n",
+ VdlVWHigh_Upper_Vcent_Range,
+ VdlVWHigh_Upper_Vcent,
+ pVref_Voltage_Table[VdlVWHigh_Upper_Vcent_Range][VdlVWHigh_Upper_Vcent]*vddq/100));
+
+ //find VldVWLow first
+ VdlVWHigh_Lower_Vcent_Range = 0;
+ VdlVWHigh_Lower_Vcent = 0;
+ vrefrange_i = TXVrefRange;
+ for(i=(finalTXVref); i>=0; i--)
+ {
+ if (((Vcent_DQ - pVref_Voltage_Table[vrefrange_i][i]*vddq/100)) >= VdlVWTotal/2)
+ {
+ /* find VdlVWHigh lower bound */
+ VdlVWHigh_Lower_Vcent = i;
+ VdlVWHigh_Lower_Vcent_Range = vrefrange_i;
+ break;
+ }
+ if (i<=21 && vrefrange_i==1)
+ {
+ vrefrange_i=0;
+ i=VREF_VOLTAGE_TABLE_NUM-(21-i);
+ }
+ }
+ mcSHOW_DBG_MSG(("[EYESCAN_LOG] TX VdlVWHigh_Lower Range=%d Vcent=%d(%dmV(X100))\n",
+ VdlVWHigh_Lower_Vcent_Range,
+ VdlVWHigh_Lower_Vcent,
+ pVref_Voltage_Table[VdlVWHigh_Lower_Vcent_Range][VdlVWHigh_Lower_Vcent]*vddq/100));
+
+#ifdef FOR_HQA_TEST_USED
+ EyeScanVcent[0] = TXVrefRange;
+ EyeScanVcent[1] = gFinalTXVrefDQ[u1ChannelIdx][u1RankIdx];
+ EyeScanVcent[2] = VdlVWHigh_Upper_Vcent_Range;
+ EyeScanVcent[3] = VdlVWHigh_Upper_Vcent;
+ EyeScanVcent[4] = VdlVWHigh_Lower_Vcent_Range;
+ EyeScanVcent[5] = VdlVWHigh_Lower_Vcent;
+#endif
+
+ shuffleIdx = get_shuffleIndex_by_Freq(p);
+
+ // mcSHOW_DBG_MSG(("[EYESCAN_LOG] delay cell %d/100ps\n", u2gdelay_cell_ps_all[shuffleIdx][u1ChannelIdx]));
+
+ for (u1BitIdx=0; u1BitIdx<cal_length; u1BitIdx++)
+ {
+
+ // compare Upper/Lower Vcent pass criterion is pass or fail?
+#if 1
+ for(u1VrefIdx=finalTXVref+TXVrefRange*30; u1VrefIdx<=(S8)(VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30); u1VrefIdx++)
+ {
+ Upper_Vcent_pass_flag = 0;
+ for (EyeScan_Index=0; EyeScan_Index<EYESCAN_BROKEN_NUM; EyeScan_Index++)
+ {
+ if (print_type==2)
+ if ((((gEyeScan_CaliDelay[u1BitIdx/8]+gEyeScan_DelayCellPI[u1BitIdx]) - gEyeScan_Min[u1VrefIdx][u1BitIdx][EyeScan_Index]) >=4 ) && ((gEyeScan_Max[u1VrefIdx][u1BitIdx][EyeScan_Index] - (gEyeScan_CaliDelay[u1BitIdx/8]+gEyeScan_DelayCellPI[u1BitIdx])) >=4 ))
+ {
+ Upper_Vcent_pass_flag = 1;
+ }
+ }
+ if (Upper_Vcent_pass_flag == 0) break; // fail!!
+ }
+ for(u1VrefIdx=VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30; u1VrefIdx<=(S8)(finalTXVref+TXVrefRange*30); u1VrefIdx++)
+ {
+ Lower_Vcent_pass_flag = 0;
+ for (EyeScan_Index=0; EyeScan_Index<EYESCAN_BROKEN_NUM; EyeScan_Index++)
+ {
+ if (print_type==2)
+ if ((((gEyeScan_CaliDelay[u1BitIdx/8]+gEyeScan_DelayCellPI[u1BitIdx]) - gEyeScan_Min[u1VrefIdx][u1BitIdx][EyeScan_Index]) >=4 ) && ((gEyeScan_Max[u1VrefIdx][u1BitIdx][EyeScan_Index] - (gEyeScan_CaliDelay[u1BitIdx/8]+gEyeScan_DelayCellPI[u1BitIdx])) >=4 ))
+ {
+ Lower_Vcent_pass_flag = 1;
+ }
+ }
+ if (Lower_Vcent_pass_flag == 0) break; //fail!!
+ }
+
+#else
+ Upper_Vcent_pass_flag = 0;
+ Lower_Vcent_pass_flag = 0;
+ for (EyeScan_Index=0; EyeScan_Index<EYESCAN_BROKEN_NUM; EyeScan_Index++)
+ {
+ if ((EyeScan_Min[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1BitIdx][EyeScan_Index] <= (EyeScan_CaliDelay[u1BitIdx/8]-4+EyeScan_DelayCellPI[u1BitIdx])) && ((EyeScan_CaliDelay[u1BitIdx/8]+4+EyeScan_DelayCellPI[u1BitIdx]) <= EyeScan_Max[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1BitIdx][EyeScan_Index]))
+ {
+ Upper_Vcent_pass_flag = 1;
+ }
+
+ if ((EyeScan_Min[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1BitIdx][EyeScan_Index] <= (EyeScan_CaliDelay[u1BitIdx/8]-4+EyeScan_DelayCellPI[u1BitIdx])) && ((EyeScan_CaliDelay[u1BitIdx/8]+4+EyeScan_DelayCellPI[u1BitIdx]) <= EyeScan_Max[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1BitIdx][EyeScan_Index]))
+ {
+ Lower_Vcent_pass_flag = 1;
+ }
+ }
+#endif
+
+#ifdef FOR_HQA_TEST_USED
+ //find VdlVWBest Vref Range and Vref
+ VdlVWBest_Vcent_Range = 1;
+ VdlVWBest_Vcent = VREF_VOLTAGE_TABLE_NUM-1;
+ vrefrange_i = 1;
+ max_winsize = 0;
+ for(i=VREF_VOLTAGE_TABLE_NUM-1; i>=0; i--)
+ {
+ if (gEyeScan_WinSize[i+vrefrange_i*30][u1BitIdx] > max_winsize)
+ {
+ max_winsize = gEyeScan_WinSize[i+vrefrange_i*30][u1BitIdx];
+ VdlVWBest_Vcent_Range = vrefrange_i;
+ VdlVWBest_Vcent = i;
+ }
+ if (i==21 && vrefrange_i==1)
+ {
+ vrefrange_i=0;
+ i=VREF_VOLTAGE_TABLE_NUM;
+ }
+ }
+
+ EyeScanVcent[10+u1BitIdx*2] = VdlVWBest_Vcent_Range;
+ EyeScanVcent[10+u1BitIdx*2+1] = VdlVWBest_Vcent;
+#endif
+
+ if (print_type==2)
+ {
+ mcSHOW_DBG_MSG(("[EYESCAN_LOG] %d Channel%d Rank%d Bit%d(DRAM DQ%d)\tHigher VdlTW=%dPI(%d/100ps)(%s)\tLower VdlTW=%dpi(%d/100ps)(%s)\n",
+ p->frequency*2,
+ u1ChannelIdx,
+ u1RankIdx,
+ u1BitIdx,
+ uiLPDDR4_O1_Mapping_POP[p->channel][u1BitIdx],
+ gEyeScan_WinSize[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1BitIdx],
+ gEyeScan_WinSize[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1BitIdx]*one_pi_ps,
+ Upper_Vcent_pass_flag==1 ? "PASS" : "FAIL",
+ gEyeScan_WinSize[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1BitIdx],
+ gEyeScan_WinSize[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1BitIdx]*one_pi_ps,
+ Lower_Vcent_pass_flag==1 ? "PASS" : "FAIL"
+ ));
+
+ if (gEyeScan_WinSize[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1BitIdx] < minTXEyeScanVcentUpperBound)
+ {
+ minTXEyeScanVcentUpperBound = gEyeScan_WinSize[VdlVWHigh_Upper_Vcent+VdlVWHigh_Upper_Vcent_Range*30][u1BitIdx];
+ minTXEyeScanVcentUpperBound_bit = u1BitIdx;
+ }
+ if (gEyeScan_WinSize[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1BitIdx] < minTXEyeScanVcentLowerBound)
+ {
+ minTXEyeScanVcentLowerBound = gEyeScan_WinSize[VdlVWHigh_Lower_Vcent+VdlVWHigh_Lower_Vcent_Range*30][u1BitIdx];
+ minTXEyeScanVcentLowerBound_bit = u1BitIdx;
+ }
+ }
+ }
+#ifdef FOR_HQA_TEST_USED
+#ifdef FOR_HQA_REPORT_USED
+ print_EyeScanVcent_for_HQA_report_used(p, print_type, u1ChannelIdx, u1RankIdx, EyeScanVcent, minTXEyeScanVcentUpperBound, minTXEyeScanVcentUpperBound_bit, minTXEyeScanVcentLowerBound, minTXEyeScanVcentLowerBound_bit);
+#endif
+#endif
+ }
+ }
+ }
+#endif
+
+
+ if (print_type==2)
+ if (u1TXEyeScanEnable)
+ { U8 cal_length;
+
+ mcSHOW_DBG_MSG(("\n\n"));
+
+ if (print_type==2) cal_length = p->data_width;
+
+ if(gEyeScan_CaliDelay[0] <gEyeScan_CaliDelay[1])
+ u2DQDelayBegin = gEyeScan_CaliDelay[0]-24;
+ else
+ u2DQDelayBegin = gEyeScan_CaliDelay[1]-24;
+
+
+ u2DQDelayEnd = u2DQDelayBegin + 64;
+
+
+ for (u1BitIdx=0; u1BitIdx<cal_length; u1BitIdx++)
+ {
+ EyeScan_Index = 0;
+
+#if EyeScan_Pic_draw_line_Mirror
+ EyeScan_DelayCellPI_value = 0-gEyeScan_DelayCellPI[u1BitIdx];
+#else
+ EyeScan_DelayCellPI_value = gEyeScan_DelayCellPI[u1BitIdx];
+#endif
+ if (print_type==2) Min_Value_1UI_Line = gEyeScan_CaliDelay[u1BitIdx/8]-16-EyeScan_DelayCellPI_value;
+
+ if (print_type==2)
+ {
+ mcSHOW_EYESCAN_MSG(("[EYESCAN_LOG] TX DQ EYESCAN Channel%d, Rank%d, Bit%d(DRAM DQ%d) ===\n",p->channel, p->rank, u1BitIdx, uiLPDDR4_O1_Mapping_POP[p->channel][u1BitIdx]));
+ }
+
+#if VENDER_JV_LOG
+ for(i=0; i<8+one_pi_ps*32/1000; i++)
+ {
+ mcSHOW_DBG_MSG5((" "));
+ }
+ mcSHOW_EYESCAN_MSG(("window\n"));
+#else
+ for(i=0; i<15+u2DQDelayEnd-u2DQDelayBegin+2; i++) mcSHOW_DBG_MSG((" "));
+ mcSHOW_EYESCAN_MSG(("first last window\n"));
+#endif
+
+ u1VrefRange=VREF_RANGE_1;
+ for (u1VrefIdx=VREF_VOLTAGE_TABLE_NUM-1; u1VrefIdx>=0; u1VrefIdx--)
+ {
+ if (print_type == 2)
+ EyeScan_Pic_draw_line(p, print_type, u1VrefRange, u1VrefIdx, u1BitIdx, u2DQDelayBegin, u2DQDelayEnd, TXVrefRange, gFinalTXVrefDQ[u1ChannelIdx][u1RankIdx], VdlVWHigh_Upper_Vcent_Range, VdlVWHigh_Upper_Vcent, VdlVWHigh_Lower_Vcent_Range, VdlVWHigh_Lower_Vcent, gEyeScan_CaliDelay[u1BitIdx/8], gEyeScan_DelayCellPI[u1BitIdx], one_pi_ps, Min_Value_1UI_Line);
+
+ if (u1VrefRange==VREF_RANGE_1 && u1VrefIdx==21)
+ {
+ u1VrefRange=VREF_RANGE_0;
+ u1VrefIdx=VREF_VOLTAGE_TABLE_NUM;
+ }
+ }
+ mcSHOW_EYESCAN_MSG(("\n\n"));
+
+ }
+ }
+}
+#ifdef RELEASE
+#undef mcSHOW_DBG_MSG
+#define mcSHOW_DBG_MSG(_x_)
+#endif
+#endif
+
+
+
+
+
+
+
+
+//-------------------------------------------------------------------------
+/** DramcMiockJmeter
+ * start MIOCK jitter meter.
+ * @param p Pointer of context created by DramcCtxCreate.
+ * @param block_no (U8): block 0 or 1.
+ * @retval status (DRAM_STATUS_T): DRAM_OK or DRAM_FAIL
+ */
+//-------------------------------------------------------------------------
+
+#ifdef ENABLE_MIOCK_JMETER
+DRAM_STATUS_T DramcMiockJmeter(DRAMC_CTX_T *p)
+{
+ U8 ucsearch_state, ucdqs_dly, fgcurrent_value, fginitial_value, ucstart_period=0, ucmiddle_period=0, ucend_period=0;
+ U32 u4sample_cnt, u4ones_cnt[DQS_NUMBER];
+ U16 u2real_freq, u2real_period;
+
+ U8 u1ShuLevel;
+ U32 u4PLL5_ADDR;
+ U32 u4PLL8_ADDR;
+ U32 u4CA_CMD6;
+ U32 u4SDM_PCW;
+ U32 u4PREDIV;
+ U32 u4POSDIV;
+ U32 u4CKDIV4;
+ U32 u4VCOFreq;
+ U32 u4DataRate;
+ U8 u1RxGatingPI=0, u1RxGatingPI_start=12, u1RxGatingPI_end=63;
+
+ // error handling
+ if (!p)
+ {
+ mcSHOW_ERR_MSG(("context NULL\n"));
+ return DRAM_FAIL;
+ }
+
+#if (fcFOR_CHIP_ID == fcLaurel)
+ if(u1IsLP4Family(p->dram_type))
+ {
+ u1RxGatingPI_start = 0; //0x10;
+ u1RxGatingPI_end = 63; //u1RxGatingPI_start + 1;
+ }
+ else
+ {
+ u1RxGatingPI_start = 10;
+ u1RxGatingPI_end = 63;
+ }
+#endif
+
+ u2gdelay_cell_ps=0;
+
+ U32 u4RegBackupAddress[] =
+ {
+ (DRAMC_REG_ADDR(DRAMC_REG_EYESCAN)),
+ (DRAMC_REG_ADDR(DRAMC_REG_STBCAL1)),
+ (DRAMC_REG_ADDR(DDRPHY_B0_DQ6)),
+ (DRAMC_REG_ADDR(DDRPHY_B1_DQ6)),
+ (DRAMC_REG_ADDR(DDRPHY_B0_DQ5)),
+ (DRAMC_REG_ADDR(DDRPHY_B1_DQ5)),
+ (DRAMC_REG_ADDR(DDRPHY_B0_DQ3)),
+ (DRAMC_REG_ADDR(DDRPHY_B1_DQ3)),
+ (DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ7)),
+ (DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ7)),
+ (DRAMC_REG_ADDR(DDRPHY_B0_DQ4)),
+ (DRAMC_REG_ADDR(DDRPHY_B1_DQ4)),
+ (DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1)),
+ (DRAMC_REG_ADDR(DRAMC_REG_SHURK0_DQSIEN)),
+ ((DDRPHY_CA_DLL_ARPI2)),
+ ((DDRPHY_B0_DLL_ARPI2)),
+ ((DDRPHY_B1_DLL_ARPI2)),
+ ((DDRPHY_CA_DLL_ARPI2)+SHIFT_TO_CHB_ADDR),
+ ((DDRPHY_B0_DLL_ARPI2)+SHIFT_TO_CHB_ADDR),
+ ((DDRPHY_B1_DLL_ARPI2)+SHIFT_TO_CHB_ADDR),
+ };
+
+#if ENABLE_LP3_SW
+ U32 u4RegBackupAddress_LP3[] =
+ {
+ (DRAMC_REG_ADDR(DRAMC_REG_EYESCAN)),
+ (DRAMC_REG_ADDR(DRAMC_REG_STBCAL1)),
+ (DRAMC_REG_ADDR(DRAMC_REG_SHURK0_DQSIEN)),
+
+ (DRAMC_REG_ADDR(DDRPHY_B0_DQ6)),
+ (DRAMC_REG_ADDR(DDRPHY_B1_DQ6)),
+ (DRAMC_REG_ADDR(DDRPHY_B0_DQ5)),
+ (DRAMC_REG_ADDR(DDRPHY_B1_DQ5)),
+ (DRAMC_REG_ADDR(DDRPHY_B0_DQ3)),
+ (DRAMC_REG_ADDR(DDRPHY_B1_DQ3)),
+ (DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ7)),
+ (DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ7)),
+ (DRAMC_REG_ADDR(DDRPHY_B0_DQ4)),
+ (DRAMC_REG_ADDR(DDRPHY_B1_DQ4)),
+ (DRAMC_REG_ADDR(DDRPHY_CA_CMD4)),
+ (DRAMC_REG_ADDR(DDRPHY_CA_CMD6)),
+ (DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1)),
+
+
+ (DRAMC_REG_ADDR(DDRPHY_B0_DQ6)+SHIFT_TO_CHB_ADDR),
+ (DRAMC_REG_ADDR(DDRPHY_B1_DQ6)+SHIFT_TO_CHB_ADDR),
+ (DRAMC_REG_ADDR(DDRPHY_B0_DQ5)+SHIFT_TO_CHB_ADDR),
+ (DRAMC_REG_ADDR(DDRPHY_B1_DQ5)+SHIFT_TO_CHB_ADDR),
+ (DRAMC_REG_ADDR(DDRPHY_B0_DQ3)+SHIFT_TO_CHB_ADDR),
+ (DRAMC_REG_ADDR(DDRPHY_B1_DQ3)+SHIFT_TO_CHB_ADDR),
+ (DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ7)+SHIFT_TO_CHB_ADDR),
+ (DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ7)+SHIFT_TO_CHB_ADDR),
+ (DRAMC_REG_ADDR(DDRPHY_B0_DQ4)+SHIFT_TO_CHB_ADDR),
+ (DRAMC_REG_ADDR(DDRPHY_B1_DQ4)+SHIFT_TO_CHB_ADDR),
+ (DRAMC_REG_ADDR(DDRPHY_CA_CMD4)+SHIFT_TO_CHB_ADDR),
+ (DRAMC_REG_ADDR(DDRPHY_CA_CMD6)+SHIFT_TO_CHB_ADDR),
+ (DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1)+SHIFT_TO_CHB_ADDR),
+
+ ((DDRPHY_CA_DLL_ARPI2)),
+ ((DDRPHY_B0_DLL_ARPI2)),
+ ((DDRPHY_B1_DLL_ARPI2)),
+ ((DDRPHY_CA_DLL_ARPI2)+SHIFT_TO_CHB_ADDR),
+ ((DDRPHY_B0_DLL_ARPI2)+SHIFT_TO_CHB_ADDR),
+ ((DDRPHY_B1_DLL_ARPI2)+SHIFT_TO_CHB_ADDR),
+ };
+#endif
+
+ //backup register value
+ if(u1IsLP4Family(p->dram_type))
+ {
+ DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ DramcBackupRegisters(p, u4RegBackupAddress_LP3, sizeof(u4RegBackupAddress_LP3)/sizeof(U32));
+ }
+#endif
+
+ //DLL off to fix middle transion from high to low or low to high at high vcore
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_CA_DLL_ARPI2), 0x0, CA_DLL_ARPI2_RG_ARDLL_PHDET_EN_CA);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B0_DLL_ARPI2), 0x0, B0_DLL_ARPI2_RG_ARDLL_PHDET_EN_B0);
+ vIO32WriteFldAlign_All(DRAMC_REG_ADDR(DDRPHY_B1_DLL_ARPI2), 0x0, B1_DLL_ARPI2_RG_ARDLL_PHDET_EN_B1);
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ //MCK4X CG
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 0, MISC_CTRL1_R_DMDQSIENCG_EN);
+
+ // Bypass DQS glitch-free mode
+ // RG_RX_*RDQ_EYE_DLY_DQS_BYPASS_B**
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ6), 1, B0_DQ6_RG_RX_ARDQ_EYE_DLY_DQS_BYPASS_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ6), 1, B1_DQ6_RG_RX_ARDQ_EYE_DLY_DQS_BYPASS_B1);
+
+ //Enable DQ eye scan
+ //RG_??_RX_EYE_SCAN_EN
+ //RG_??_RX_VREF_EN
+ //RG_??_RX_SMT_EN
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), 1, EYESCAN_RG_RX_EYE_SCAN_EN);
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), P_Fld(0x1, EYESCAN_EYESCAN_DQS_SYNC_EN)
+ | P_Fld(0x1, EYESCAN_EYESCAN_NEW_DQ_SYNC_EN)
+ | P_Fld(0x1, EYESCAN_EYESCAN_DQ_SYNC_EN));
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_EYE_EN_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_EYE_EN_B1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_VREF_EN_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_VREF_EN_B1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ3), 1, B0_DQ3_RG_RX_ARDQ_SMT_EN_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ3), 1, B1_DQ3_RG_RX_ARDQ_SMT_EN_B1);
+
+ //JM_SEL
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ6), 1, B0_DQ6_RG_RX_ARDQ_JM_SEL_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ6), 1, B1_DQ6_RG_RX_ARDQ_JM_SEL_B1);
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ //MCK4X CG
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_MISC_CTRL1), 0, MISC_CTRL1_R_DMDQSIENCG_EN);
+
+ // Bypass DQS glitch-free mode
+ // RG_RX_*RDQ_EYE_DLY_DQS_BYPASS_B**
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ6), 1, B0_DQ6_RG_RX_ARDQ_EYE_DLY_DQS_BYPASS_B0);
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ6), 1, B1_DQ6_RG_RX_ARDQ_EYE_DLY_DQS_BYPASS_B1);
+
+ //Enable DQ eye scan
+ //RG_??_RX_EYE_SCAN_EN
+ //RG_??_RX_VREF_EN
+ //RG_??_RX_SMT_EN
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), 1, EYESCAN_RG_RX_EYE_SCAN_EN);
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), P_Fld(0x1, EYESCAN_EYESCAN_DQS_SYNC_EN)
+ | P_Fld(0x1, EYESCAN_EYESCAN_NEW_DQ_SYNC_EN)
+ | P_Fld(0x1, EYESCAN_EYESCAN_DQ_SYNC_EN));
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_EYE_EN_B0);
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_EYE_EN_B1);
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), 1, B0_DQ5_RG_RX_ARDQ_VREF_EN_B0);
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), 1, B1_DQ5_RG_RX_ARDQ_VREF_EN_B1);
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ3), 1, B0_DQ3_RG_RX_ARDQ_SMT_EN_B0);
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ3), 1, B1_DQ3_RG_RX_ARDQ_SMT_EN_B1);
+
+ //JM_SEL
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ6), 1, B0_DQ6_RG_RX_ARDQ_JM_SEL_B0);
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ6), 1, B1_DQ6_RG_RX_ARDQ_JM_SEL_B1);
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD6), 1, CA_CMD6_RG_RX_ARCMD_JM_SEL);
+ }
+#endif
+
+
+ //Enable MIOCK jitter meter mode ( RG_RX_MIOCK_JIT_EN=1)
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), 1, EYESCAN_RG_RX_MIOCK_JIT_EN);
+
+ //Disable DQ eye scan (b'1), for counter clear
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), 0, EYESCAN_RG_RX_EYE_SCAN_EN);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_STBCAL1), 0, STBCAL1_DQSERRCNT_DIS);
+
+ //Using test engine to switch back to RK0, or the gating PI cannont be adjust successfully.
+ DramcEngine2Run(p, TE_OP_READ_CHECK, p->test_pattern);
+
+ for (u1RxGatingPI=u1RxGatingPI_start; u1RxGatingPI<u1RxGatingPI_end; u1RxGatingPI+=4)
+ {
+ mcSHOW_DBG_MSG(("\n[DramcMiockJmeter] u1RxGatingPI = %d\n", u1RxGatingPI));
+
+ ucsearch_state = 0;
+
+ //to see 1T(H,L) or 1T(L,H) from delaycell=0 to 127
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_DQSIEN), P_Fld(u1RxGatingPI, SHURK0_DQSIEN_R0DQS0IEN) | P_Fld(u1RxGatingPI, SHURK0_DQSIEN_R0DQS1IEN)
+ | P_Fld(u1RxGatingPI, SHURK0_DQSIEN_R0DQS2IEN) | P_Fld(u1RxGatingPI, SHURK0_DQSIEN_R0DQS3IEN));
+
+ for (ucdqs_dly=0; ucdqs_dly<128; ucdqs_dly++)
+ {
+
+ //Set DQS delay (RG_??_RX_DQS_EYE_DLY)
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ4), ucdqs_dly, B0_DQ4_RG_RX_ARDQS_EYE_R_DLY_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ4), ucdqs_dly, B0_DQ4_RG_RX_ARDQS_EYE_F_DLY_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ4), ucdqs_dly, B1_DQ4_RG_RX_ARDQS_EYE_R_DLY_B1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ4), ucdqs_dly, B1_DQ4_RG_RX_ARDQS_EYE_F_DLY_B1);
+ }
+#if ENABLE_LP3_SW
+ else //LPDDR3
+ {
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ4), ucdqs_dly, B0_DQ4_RG_RX_ARDQS_EYE_R_DLY_B0);
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B0_DQ4), ucdqs_dly, B0_DQ4_RG_RX_ARDQS_EYE_F_DLY_B0);
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ4), ucdqs_dly, B1_DQ4_RG_RX_ARDQS_EYE_R_DLY_B1);
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_B1_DQ4), ucdqs_dly, B1_DQ4_RG_RX_ARDQS_EYE_F_DLY_B1);
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD4), ucdqs_dly, CA_CMD4_RG_RX_ARCLK_EYE_R_DLY);
+ vIO32WriteFldAlign_Phy_All(DRAMC_REG_ADDR(DDRPHY_CA_CMD4), ucdqs_dly, CA_CMD4_RG_RX_ARCLK_EYE_F_DLY);
+ }
+#endif
+ DramPhyReset(p);
+
+ //Reset eye scan counters (reg_sw_rst): 1 to 0
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), 1, EYESCAN_REG_SW_RST);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), 0, EYESCAN_REG_SW_RST);
+
+ //Enable DQ eye scan (b'1)
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), 1, EYESCAN_RG_RX_EYE_SCAN_EN);
+
+ //2ns/sample, here we delay 1ms about 500 samples
+ mcDELAY_US(10);
+
+ //Disable DQ eye scan (b'1), for counter latch
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_EYESCAN), 0, EYESCAN_RG_RX_EYE_SCAN_EN);
+
+ //Read the counter values from registers (toggle_cnt*, dqs_err_cnt*);
+ u4sample_cnt = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_TOGGLE_CNT), TOGGLE_CNT_TOGGLE_CNT);
+ u4ones_cnt[0] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQS0_ERR_CNT), DQS0_ERR_CNT_DQS0_ERR_CNT);
+ u4ones_cnt[1] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQS1_ERR_CNT), DQS1_ERR_CNT_DQS1_ERR_CNT);
+ u4ones_cnt[2] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQS2_ERR_CNT), DQS2_ERR_CNT_DQS2_ERR_CNT);
+ u4ones_cnt[3] = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_DQS3_ERR_CNT), DQS3_ERR_CNT_DQS3_ERR_CNT);
+ #ifdef ETT_PRINT_FORMAT
+ mcSHOW_DBG_MSG(("%d : %d, %d, %d, %d, %d\n", ucdqs_dly, u4sample_cnt, u4ones_cnt[0],u4ones_cnt[1],u4ones_cnt[2],u4ones_cnt[3]));
+ #else
+ mcSHOW_DBG_MSG(("%3d : %8d, %8d, %8d, %8d, %8d\n", ucdqs_dly, u4sample_cnt, u4ones_cnt[0],u4ones_cnt[2],u4ones_cnt[3]));
+ #endif
+
+ /*
+ //Disable DQ eye scan (RG_RX_EYE_SCAN_EN=0, RG_RX_*RDQ_VREF_EN_B*=0, RG_RX_*RDQ_EYE_VREF_EN_B*=0, RG_RX_*RDQ_SMT_EN_B*=0)
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_STBCAL_F), 0, STBCAL_F_RG_EX_EYE_SCAN_EN);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_EYE2), 0, EYE2_RG_RX_ARDQ_VREF_EN_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_EYEB1_2), 0, EYEB1_2_RG_RX_ARDQ_VREF_EN_B1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_EYE2), 0, EYE2_RG_RX_ARDQ_EYE_VREF_EN_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_EYEB1_2), 0, EYEB1_2_RG_RX_ARDQ_EYE_VREF_EN_B1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_TXDQ3), 0, TXDQ3_RG_RX_ARDQ_SMT_EN_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_RXDQ13),0, RXDQ13_RG_RX_ARDQ_SMT_EN_B1);
+ */
+
+ //change to boolean value
+ if (u4ones_cnt[0] < (u4sample_cnt/2))
+ {
+ fgcurrent_value = 0;
+ }
+ else
+ {
+ fgcurrent_value = 1;
+ }
+
+ #if 1//more than 1T data
+ {
+ if (ucsearch_state==0)
+ {
+ //record initial value at the beginning
+ fginitial_value = fgcurrent_value;
+ ucsearch_state = 1;
+ }
+ else if (ucsearch_state==1)
+ {
+ // check if change value
+ if (fgcurrent_value != fginitial_value)
+ {
+ // start of the period
+ fginitial_value = fgcurrent_value;
+ ucstart_period = ucdqs_dly;
+ ucsearch_state = 2;
+ }
+ }
+ else if (ucsearch_state==2)
+ {
+ // check if change value
+ if (fgcurrent_value != fginitial_value)
+ {
+ fginitial_value = fgcurrent_value;
+ ucmiddle_period = ucdqs_dly;
+ ucsearch_state = 3;
+ }
+ }
+ else if (ucsearch_state==3)
+ {
+ // check if change value
+ if (fgcurrent_value != fginitial_value)
+ {
+ // end of the period, break the loop
+ ucend_period = ucdqs_dly;
+ ucsearch_state = 4;
+ break;
+ }
+ }
+ else
+ {
+ //nothing
+ }
+ }
+ #else //only 0.5T data
+ {
+ if (ucsearch_state==0)
+ {
+ //record initial value at the beginning
+ fginitial_value = fgcurrent_value;
+ ucsearch_state = 1;
+ }
+ else if (ucsearch_state==1)
+ {
+ // check if change value
+ if (fgcurrent_value != fginitial_value)
+ {
+ // start of the period
+ fginitial_value = fgcurrent_value;
+ ucstart_period = ucdqs_dly;
+ ucsearch_state = 2;
+ }
+ }
+ else if (ucsearch_state==2)
+ {
+ // check if change value
+ if (fgcurrent_value != fginitial_value)
+ {
+ // end of the period, break the loop
+ ucend_period = ucdqs_dly;
+ ucsearch_state = 4;
+ break;
+ }
+ }
+ }
+ #endif
+ }
+
+ if((ucsearch_state==4) || (ucsearch_state==3))
+ break;
+ }
+
+ //restore to orignal value
+ if(u1IsLP4Family(p->dram_type))
+ {
+ DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ DramcRestoreRegisters(p, u4RegBackupAddress_LP3, sizeof(u4RegBackupAddress_LP3)/sizeof(U32));
+ }
+#endif
+
+ if(ucsearch_state!=4)
+ {
+ if (ucsearch_state!=3)
+ {
+ mcSHOW_DBG_MSG(("\n\tMIOCK jitter meter - ch=%d\n", p->channel));
+ mcSHOW_DBG_MSG(("\tLess than 0.5T data. Cannot calculate delay cell time\n\n"));
+
+ ucg_num_dlycell_perT = 0; //for LP3/4 lookup table used
+
+ return DRAM_FAIL;
+ }
+ else
+ {
+ //Calculate 1 delay cell = ? ps
+ // 1T = ? delay cell
+ ucg_num_dlycell_perT = (ucmiddle_period - ucstart_period)*2;
+ // 1T = ? ps
+ }
+ }
+ else
+ {
+ //Calculate 1 delay cell = ? ps
+ // 1T = ? delay cell
+ ucg_num_dlycell_perT = (ucend_period - ucstart_period);
+ // 1T = ? ps
+ }
+
+ u1ShuLevel = u4IO32ReadFldAlign(DRAMC_REG_SHUSTATUS, SHUSTATUS_SHUFFLE_LEVEL);
+ u4PLL5_ADDR = DDRPHY_SHU1_PLL5 + SHU_GRP_DDRPHY_OFFSET * u1ShuLevel;
+ u4PLL8_ADDR = DDRPHY_SHU1_PLL8 + SHU_GRP_DDRPHY_OFFSET * u1ShuLevel;
+ u4CA_CMD6 = DDRPHY_SHU1_CA_CMD6 + SHU_GRP_DDRPHY_OFFSET * u1ShuLevel;
+ u4SDM_PCW = u4IO32ReadFldAlign(u4PLL5_ADDR, SHU1_PLL5_RG_RPHYPLL_SDM_PCW);
+ u4PREDIV = u4IO32ReadFldAlign(u4PLL8_ADDR, SHU1_PLL8_RG_RPHYPLL_PREDIV);
+ u4POSDIV = u4IO32ReadFldAlign(u4PLL8_ADDR, SHU1_PLL8_RG_RPHYPLL_POSDIV);
+ u4CKDIV4 = u4IO32ReadFldAlign(u4CA_CMD6, SHU1_CA_CMD6_RG_ARPI_MIDPI_CKDIV4_EN_CA);
+ u4VCOFreq = ((52>>u4PREDIV)*(u4SDM_PCW>>8))>>u4POSDIV;
+ u4DataRate = u4VCOFreq>>u4CKDIV4;
+ u2real_freq = u4DataRate>>1;
+
+ u2real_period = (U16) (1000000/u2real_freq);
+ //calculate delay cell time
+
+ u2gdelay_cell_ps = u2real_period*100 / ucg_num_dlycell_perT;
+
+ if (ucsearch_state==4)
+ {
+ mcSHOW_DBG_MSG(("\n\tMIOCK jitter meter\tch=%d\n\n"
+ "1T = (%d-%d) = %d dly cells\n"
+ "Clock freq = %d MHz, period = %d ps, 1 dly cell = %d/100 ps\n",
+ p->channel,
+ ucend_period, ucstart_period, ucg_num_dlycell_perT,
+ u2real_freq, u2real_period, u2gdelay_cell_ps));
+ }
+ else
+ {
+ mcSHOW_DBG_MSG(("\n\tMIOCK jitter meter\tch=%d\n\n"
+ "1T = (%d-%d)*2 = %d dly cells\n"
+ "Clock freq = %d MHz, period = %d ps, 1 dly cell = %d/100 ps\n",
+ p->channel,
+ ucmiddle_period, ucstart_period, ucg_num_dlycell_perT,
+ u2real_freq, u2real_period, u2gdelay_cell_ps));
+ }
+
+ return DRAM_OK;
+
+// log example
+/* dly: sample_cnt DQS0_cnt DQS1_cnt
+ 0 : 10962054, 0, 0
+ 1 : 10958229, 0, 0
+ 2 : 10961109, 0, 0
+ 3 : 10946916, 0, 0
+ 4 : 10955421, 0, 0
+ 5 : 10967274, 0, 0
+ 6 : 10893582, 0, 0
+ 7 : 10974762, 0, 0
+ 8 : 10990278, 0, 0
+ 9 : 10972026, 0, 0
+ 10 : 7421004, 0, 0
+ 11 : 10943883, 0, 0
+ 12 : 10984275, 0, 0
+ 13 : 10955268, 0, 0
+ 14 : 10960326, 0, 0
+ 15 : 10952451, 0, 0
+ 16 : 10956906, 0, 0
+ 17 : 10960803, 0, 0
+ 18 : 10944108, 0, 0
+ 19 : 10959939, 0, 0
+ 20 : 10959246, 0, 0
+ 21 : 11002212, 0, 0
+ 22 : 10919700, 0, 0
+ 23 : 10977489, 0, 0
+ 24 : 11009853, 0, 0
+ 25 : 10991133, 0, 0
+ 26 : 10990431, 0, 0
+ 27 : 10970703, 11161, 0
+ 28 : 10970775, 257118, 0
+ 29 : 10934442, 9450467, 0
+ 30 : 10970622, 10968475, 0
+ 31 : 10968831, 10968831, 0
+ 32 : 10956123, 10956123, 0
+ 33 : 10950273, 10950273, 0
+ 34 : 10975770, 10975770, 0
+ 35 : 10983024, 10983024, 0
+ 36 : 10981701, 10981701, 0
+ 37 : 10936782, 10936782, 0
+ 38 : 10889523, 10889523, 0
+ 39 : 10985913, 10985913, 55562
+ 40 : 10970235, 10970235, 272294
+ 41 : 10996056, 10996056, 9322868
+ 42 : 10972350, 10972350, 10969738
+ 43 : 10963917, 10963917, 10963917
+ 44 : 10967895, 10967895, 10967895
+ 45 : 10961739, 10961739, 10961739
+ 46 : 10937097, 10937097, 10937097
+ 47 : 10937952, 10937952, 10937952
+ 48 : 10926018, 10926018, 10926018
+ 49 : 10943793, 10943793, 10943793
+ 50 : 10954638, 10954638, 10954638
+ 51 : 10968048, 10968048, 10968048
+ 52 : 10944036, 10944036, 10944036
+ 53 : 11012112, 11012112, 11012112
+ 54 : 10969137, 10969137, 10969137
+ 55 : 10968516, 10968516, 10968516
+ 56 : 10952532, 10952532, 10952532
+ 57 : 10985832, 10985832, 10985832
+ 58 : 11002527, 11002527, 11002527
+ 59 : 10950660, 10873571, 10950660
+ 60 : 10949022, 10781797, 10949022
+ 61 : 10974366, 10700617, 10974366
+ 62 : 10972422, 1331974, 10972422
+ 63 : 10926567, 0, 10926567
+ 64 : 10961658, 0, 10961658
+ 65 : 10978893, 0, 10978893
+ 66 : 10962828, 0, 10962828
+ 67 : 10957599, 0, 10957599
+ 68 : 10969227, 0, 10969227
+ 69 : 10960722, 0, 10960722
+ 70 : 10970937, 0, 10963180
+ 71 : 10962054, 0, 10711639
+ 72 : 10954719, 0, 10612707
+ 73 : 10958778, 0, 479589
+ 74 : 10973898, 0, 0
+ 75 : 11004156, 0, 0
+ 76 : 10944261, 0, 0
+ 77 : 10955340, 0, 0
+ 78 : 10998153, 0, 0
+ 79 : 10998774, 0, 0
+ 80 : 10953234, 0, 0
+ 81 : 10960020, 0, 0
+ 82 : 10923831, 0, 0
+ 83 : 10951362, 0, 0
+ 84 : 10965249, 0, 0
+ 85 : 10949103, 0, 0
+ 86 : 10948707, 0, 0
+ 87 : 10941147, 0, 0
+ 88 : 10966572, 0, 0
+ 89 : 10971333, 0, 0
+ 90 : 10943721, 0, 0
+ 91 : 10949337, 0, 0
+ 92 : 10965942, 0, 0
+ 93 : 10970397, 0, 0
+ 94 : 10956429, 0, 0
+ 95 : 10939896, 0, 0
+ 96 : 10967112, 0, 0
+ 97 : 10951911, 0, 0
+ 98 : 10953702, 0, 0
+ 99 : 10971090, 0, 0
+ 100 : 10939590, 0, 0
+ 101 : 10993392, 0, 0
+ 102 : 10975932, 0, 0
+ 103 : 10949499, 40748, 0
+ 104 : 10962522, 258638, 0
+ 105 : 10951524, 275292, 0
+ 106 : 10982475, 417642, 0
+ 107 : 10966887, 10564347, 0
+ ===============================================================================
+ MIOCK jitter meter - channel=0
+ ===============================================================================
+ 1T = (107-29) = 78 delay cells
+ Clock frequency = 936 MHz, Clock period = 1068 ps, 1 delay cell = 13 ps
+*/
+}
+#endif
+
+
+
+
+#if ENABLE_DUTY_SCAN_V2
+
+#define DutyPrintAllLog 0
+#define DutyPrintCalibrationLog 1
+
+#define DUTY_OFFSET_START -8
+#define DUTY_OFFSET_END 8
+
+#define CLOCK_PI_START 0
+#define CLOCK_PI_END 63
+#define CLOCK_PI_STEP 2
+
+#define ClockDutyFailLowerBound 4500 // 45%
+#define ClockDutyFailUpperBound 5500 // 55%
+#define ClockDutyMiddleBound 5000 // 50%
+
+void DramcClockDutySetClkDelayCell(DRAMC_CTX_T *p, U8 u1RankIdx, S8 scDutyDelay, U8 use_rev_bit)
+{
+ U8 u1ShuffleIdx = 0;
+ U32 save_offset;
+ U8 ucDelay, ucDelayB;
+ U8 ucRev_Bit0=0, ucRev_Bit1=0;
+
+// mcSHOW_DBG_MSG(("CH%d, Final CLK duty delay cell = %d\n", p->channel, scDutyDelay));
+
+ if (scDutyDelay<0)
+ {
+ ucDelay = -scDutyDelay;
+ ucDelayB = 0;
+
+ if (use_rev_bit)
+ {
+ ucRev_Bit0 = 1;
+ ucRev_Bit1 = 0;
+ }
+ }
+ else if (scDutyDelay>0)
+ {
+ ucDelay = 0;
+ ucDelayB= scDutyDelay;
+
+ if (use_rev_bit)
+ {
+ ucRev_Bit0 = 0;
+ ucRev_Bit1 = 1;
+ }
+ }
+ else
+ {
+ ucDelay = 0;
+ ucDelayB= 0;
+
+ if (use_rev_bit)
+ {
+ ucRev_Bit0 = 0;
+ ucRev_Bit1 = 0;
+ }
+ }
+
+#if DUTY_SCAN_V2_ONLY_K_HIGHEST_FREQ
+ for(u1ShuffleIdx = 0; u1ShuffleIdx<DRAM_DFS_SHUFFLE_MAX; u1ShuffleIdx++)
+#endif
+ {
+ save_offset = u1ShuffleIdx * SHU_GRP_DDRPHY_OFFSET + u1RankIdx*0x100;
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD1) + save_offset, P_Fld(ucDelay, SHU1_R0_CA_CMD1_RK0_TX_ARCLK_DLY) | P_Fld(ucDelay, SHU1_R0_CA_CMD1_RK0_TX_ARCLKB_DLY));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD0) + save_offset, P_Fld(ucDelayB, SHU1_R0_CA_CMD0_RK0_TX_ARCLK_DLYB) | P_Fld(ucDelayB, SHU1_R0_CA_CMD0_RK0_TX_ARCLKB_DLYB));
+
+// Lau_rel like Mer_lot, no need to set this to big scale mode, just use small scale mode
+ save_offset = u1ShuffleIdx * SHU_GRP_DDRPHY_OFFSET;
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD3), P_Fld(ucRev_Bit0, SHU1_CA_CMD3_RG_TX_ARCMD_PU_BIT0) | P_Fld(ucRev_Bit1, SHU1_CA_CMD3_RG_TX_ARCMD_PU_BIT1));
+ }
+}
+
+void DQSDutyScan_SetDqsDelayCell(DRAMC_CTX_T *p, S8 *scDutyDelay, U8 use_rev_bit)
+{
+ U8 u1ShuffleIdx = 0, u1DQSIdx, u1RankIdx = 0;
+ U32 save_offset;
+ U8 u1Delay[2], u1DelayB[2];
+ U8 ucRev_Bit0[2]={0,0}, ucRev_Bit1[2]={0,0};
+
+// mcSHOW_DBG_MSG(("CH%d, Final DQS0 duty delay cell = %d\n", p->channel, scDutyDelay[0]));
+// mcSHOW_DBG_MSG(("CH%d, Final DQS1 duty delay cell = %d\n", p->channel, scDutyDelay[1]));
+
+ for(u1DQSIdx=0; u1DQSIdx<2; u1DQSIdx++)
+ {
+ if(scDutyDelay[u1DQSIdx] <0)
+ {
+ u1Delay[u1DQSIdx] = -(scDutyDelay[u1DQSIdx]);
+ u1DelayB[u1DQSIdx] =0;
+
+ if (use_rev_bit)
+ {
+ ucRev_Bit0[u1DQSIdx] = 1;
+ ucRev_Bit1[u1DQSIdx] = 0;
+ }
+ }
+ else if(scDutyDelay[u1DQSIdx] >0)
+ {
+ u1Delay[u1DQSIdx] = 0;
+ u1DelayB[u1DQSIdx] = scDutyDelay[u1DQSIdx];
+
+ if (use_rev_bit)
+ {
+ ucRev_Bit0[u1DQSIdx] = 0;
+ ucRev_Bit1[u1DQSIdx] = 1;
+ }
+ }
+ else
+ {
+ u1Delay[u1DQSIdx] = 0;
+ u1DelayB[u1DQSIdx] =0;
+
+ if (use_rev_bit)
+ {
+ ucRev_Bit0[u1DQSIdx] = 0;
+ ucRev_Bit1[u1DQSIdx] = 0;
+ }
+ }
+ }
+
+#if DUTY_SCAN_V2_ONLY_K_HIGHEST_FREQ
+ for(u1ShuffleIdx = 0; u1ShuffleIdx<DRAM_DFS_SHUFFLE_MAX; u1ShuffleIdx++)
+#endif
+ {
+ for(u1RankIdx = 0; u1RankIdx<RANK_MAX; u1RankIdx++)
+ {
+ for(u1DQSIdx = 0; u1DQSIdx<2; u1DQSIdx++)
+ {
+ save_offset = u1ShuffleIdx * SHU_GRP_DDRPHY_OFFSET + u1RankIdx*0x100 + u1DQSIdx*0x50;
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ1) + save_offset, P_Fld(u1Delay[u1DQSIdx], SHU1_R0_B0_DQ1_RK0_TX_ARDQS0_DLY_B0) | P_Fld(u1Delay[u1DQSIdx], SHU1_R0_B0_DQ1_RK0_TX_ARDQS0B_DLY_B0));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ1) + save_offset, P_Fld(u1DelayB[u1DQSIdx], SHU1_R0_B0_DQ1_RK0_TX_ARDQS0_DLYB_B0) | P_Fld(u1DelayB[u1DQSIdx], SHU1_R0_B0_DQ1_RK0_TX_ARDQS0B_DLYB_B0));
+
+// Lau_rel like Mer_lot, no need to set this to big scale mode, just use small scale mode
+ save_offset = u1ShuffleIdx * SHU_GRP_DDRPHY_OFFSET + u1DQSIdx*0x80;
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DLL1) + save_offset, P_Fld(ucRev_Bit0[u1DQSIdx], RG_ARDQ_REV_BIT_00_DQS_MCK4X_DLY_EN) | P_Fld(ucRev_Bit1[u1DQSIdx], RG_ARDQ_REV_BIT_01_DQS_MCK4XB_DLY_EN));
+ }
+ }
+ }
+}
+
+
+void DQDQMDutyScan_SetDQDQMDelayCell(DRAMC_CTX_T *p, S8 *scDutyDelay, U8 use_rev_bit, U8 k_type)
+{
+ U8 u1ShuffleIdx = 0, u1DQSIdx;
+ U32 save_offset;
+ U8 u1Delay[2];
+ U8 ucRev_Bit0[2], ucRev_Bit1[2];
+
+// mcSHOW_DBG_MSG(("CH%d, Final DQS0 duty delay cell = %d\n", p->channel, scDutyDelay[0]));
+// mcSHOW_DBG_MSG(("CH%d, Final DQS1 duty delay cell = %d\n", p->channel, scDutyDelay[1]));
+
+ for(u1DQSIdx=0; u1DQSIdx<2; u1DQSIdx++)
+ {
+ if(scDutyDelay[u1DQSIdx] <0)
+ {
+ u1Delay[u1DQSIdx] = (-(scDutyDelay[u1DQSIdx])) | (1<<3); //sign bit
+
+ if (use_rev_bit)
+ {
+ ucRev_Bit0[u1DQSIdx] = 0;
+ ucRev_Bit1[u1DQSIdx] = 1;
+ }
+ }
+ else if(scDutyDelay[u1DQSIdx] >0)
+ {
+ u1Delay[u1DQSIdx] = scDutyDelay[u1DQSIdx];
+
+ if (use_rev_bit)
+ {
+ ucRev_Bit0[u1DQSIdx] = 1;
+ ucRev_Bit1[u1DQSIdx] = 0;
+ }
+ }
+ else
+ {
+ u1Delay[u1DQSIdx] = 0;
+
+ if (use_rev_bit)
+ {
+ ucRev_Bit0[u1DQSIdx] = 0;
+ ucRev_Bit1[u1DQSIdx] = 0;
+ }
+ }
+ }
+
+#if DUTY_SCAN_V2_ONLY_K_HIGHEST_FREQ
+ for(u1ShuffleIdx = 0; u1ShuffleIdx<DRAM_DFS_SHUFFLE_MAX; u1ShuffleIdx++)
+#endif
+ {
+ for(u1DQSIdx = 0; u1DQSIdx<2; u1DQSIdx++)
+ {
+ save_offset = u1ShuffleIdx * SHU_GRP_DDRPHY_OFFSET + u1DQSIdx*DDRPHY_AO_B0_B1_OFFSET_0X80;
+
+ if (k_type == DutyScan_Calibration_K_DQM)
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ10) + save_offset, u1Delay[u1DQSIdx], B0_DQ10_RG_ARDQ_DUTYREV_B0_DQM_DUTY_DELAY);
+
+// Lau_rel like Mer_lot, no need to set this to big scale mode, just use small scale mode
+// vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ3) + save_offset, P_Fld(ucRev_Bit0[u1DQSIdx], SHU1_B0_DQ3_RG_TX_ARDQS0_PU_B0_BIT0)
+// | P_Fld(ucRev_Bit1[u1DQSIdx], SHU1_B0_DQ3_RG_TX_ARDQS0_PU_B0_BIT1));
+ }
+
+ if ((k_type == DutyScan_Calibration_K_DQ) || (k_type == DutyScan_Calibration_K_DQM)) //DQM is special case
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ10) + save_offset, u1Delay[u1DQSIdx], B0_DQ10_RG_ARDQ_DUTYREV_B0_DQ_DUTY_DELAY);
+
+// Lau_rel like Mer_lot, no need to set this to big scale mode, just use small scale mode
+// vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ3) + save_offset, P_Fld(ucRev_Bit0[u1DQSIdx], SHU1_B0_DQ3_RG_TX_ARDQS0_PU_PRE_B0_BIT0)
+// | P_Fld(ucRev_Bit1[u1DQSIdx], SHU1_B0_DQ3_RG_TX_ARDQS0_PU_PRE_B0_BIT1));
+ }
+ }
+ }
+}
+
+
+// offset is not related to DQ/DQM/DQS
+// we have a circuit to measure duty, But this circuit is not very accurate
+// so we need to K offset of this circuit first
+// After we got this offset, then we can use it to measure duty
+// this offset can measure DQ/DQS/DQM, and every byte has this circuit, too.
+// B0/B1/CA all have one circuit.
+// CA's circuit can measure CLK duty
+// B0/B1's can measure DQ/DQM/DQS duty
+S8 DutyScan_Offset_Convert(U8 val)
+{
+ U8 calibration_sequence[15]={0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7};
+
+ return ((S8)(calibration_sequence[val]>8 ? 0-(calibration_sequence[val]&0x7) : calibration_sequence[val]));
+
+}
+void DutyScan_Offset_Calibration(DRAMC_CTX_T *p)
+{
+ U8 calibration_sequence[15]={0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7};
+ U8 i, read_val_b0, read_val_b1, read_val_ca;
+ U8 cal_i_b0=0xff, cal_i_b1=0xff, cal_i_ca=0xff;
+
+#if VENDER_JV_LOG
+ vPrintCalibrationBasicInfo_ForJV(p);
+#else
+ vPrintCalibrationBasicInfo(p);
+#endif
+
+#if DutyPrintCalibrationLog
+ mcSHOW_DBG_MSG(("[Duty_Offset_Calibration]\n\n"));
+#endif
+
+ //B0
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ6), P_Fld(1, B0_DQ6_RG_RX_ARDQ_LPBK_EN_B0) | P_Fld(0, B0_DQ6_RG_RX_ARDQ_DDR4_SEL_B0) | P_Fld(1, B0_DQ6_RG_RX_ARDQ_DDR3_SEL_B0));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DLL1), P_Fld(1, RG_ARDQ_REV_BIT_20_DATA_SWAP_EN) | P_Fld(2, RG_ARDQ_REV_BIT_2221_DATA_SWAP));
+// vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ3), P_Fld(1, SHU1_B0_DQ3_DQ_REV_B0_BIT_06) | P_Fld(0, SHU1_B0_DQ3_DQ_REV_B0_BIT_05) | P_Fld(1, SHU1_B0_DQ3_DQ_REV_B0_BIT_04));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ5), P_Fld(0, SHU1_B0_DQ5_RG_RX_ARDQ_VREF_BYPASS_B0) | P_Fld(0xB, SHU1_B0_DQ5_RG_RX_ARDQ_VREF_SEL_B0));
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ0), 1, SHU1_B0_DQ0_RG_TX_ARDQS0_DRVP_PRE_B0_BIT1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ0), 0, B0_DQ0_RG_RX_ARDQ2_OFFC_B0);
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ5), P_Fld(1, B0_DQ5_RG_RX_ARDQ_VREF_EN_B0) | P_Fld(0x1, B0_DQ5_RG_RX_ARDQ_EYE_VREF_EN_B0));
+ mcDELAY_US(1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ0), 1, SHU1_B0_DQ0_RG_TX_ARDQS0_DRVP_PRE_B0_BIT2);
+
+ //B1
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ6), P_Fld(1, B1_DQ6_RG_RX_ARDQ_LPBK_EN_B1) | P_Fld(0, B1_DQ6_RG_RX_ARDQ_DDR4_SEL_B1) | P_Fld(1, B1_DQ6_RG_RX_ARDQ_DDR3_SEL_B1));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DLL1), P_Fld(1, RG_ARDQ_REV_BIT_20_DATA_SWAP_EN) | P_Fld(2, RG_ARDQ_REV_BIT_2221_DATA_SWAP));
+// vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ3), P_Fld(1, SHU1_B1_DQ3_DQ_REV_B1_BIT_06) | P_Fld(0, SHU1_B1_DQ3_DQ_REV_B1_BIT_05) | P_Fld(1, SHU1_B1_DQ3_DQ_REV_B1_BIT_04));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ5), P_Fld(0, SHU1_B1_DQ5_RG_RX_ARDQ_VREF_BYPASS_B1) | P_Fld(0xB, SHU1_B1_DQ5_RG_RX_ARDQ_VREF_SEL_B1));
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ0), 1, SHU1_B1_DQ0_RG_TX_ARDQS0_DRVP_PRE_B1_BIT1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ0), 0, B1_DQ0_RG_RX_ARDQ2_OFFC_B1);
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ5), P_Fld(1, B1_DQ5_RG_RX_ARDQ_VREF_EN_B1) | P_Fld(0x1, B1_DQ5_RG_RX_ARDQ_EYE_VREF_EN_B1));
+ mcDELAY_US(1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ0), 1, SHU1_B1_DQ0_RG_TX_ARDQS0_DRVP_PRE_B1_BIT2);
+
+ //CA
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_CA_CMD6), P_Fld(1, CA_CMD6_RG_RX_ARCMD_LPBK_EN) | P_Fld(0, CA_CMD6_RG_RX_ARCMD_DDR4_SEL) | P_Fld(1, CA_CMD6_RG_RX_ARCMD_DDR3_SEL));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_DLL1), P_Fld(1, RG_ARCMD_REV_BIT_20_DATA_SWAP_EN) | P_Fld(2, RG_ARCMD_REV_BIT_2221_DATA_SWAP));
+// vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD3), P_Fld(1, SHU1_CA_CMD3_ARCMD_REV_BIT_06) | P_Fld(0, SHU1_CA_CMD3_ARCMD_REV_BIT_05) | P_Fld(1, SHU1_CA_CMD3_ARCMD_REV_BIT_04));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD5), P_Fld(0, SHU1_CA_CMD5_RG_RX_ARCMD_VREF_BYPASS) | P_Fld(0xB, SHU1_CA_CMD5_RG_RX_ARCMD_VREF_SEL));
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD0), 1, SHU1_CA_CMD0_RG_TX_ARCLK_DRVP_PRE_BIT1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_CA_CMD0), 0, CA_CMD0_RG_RX_ARCA2_OFFC);
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_CA_CMD5), P_Fld(1, CA_CMD5_RG_RX_ARCMD_VREF_EN) | P_Fld(0x1, CA_CMD5_RG_RX_ARCMD_EYE_VREF_EN));
+ mcDELAY_US(1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD0), 1, SHU1_CA_CMD0_RG_TX_ARCLK_DRVP_PRE_BIT2);
+
+ mcDELAY_US(1);
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ0), 1, SHU1_B0_DQ0_RG_TX_ARDQS0_DRVP_PRE_B0_BIT0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ0), 1, SHU1_B1_DQ0_RG_TX_ARDQS0_DRVP_PRE_B1_BIT0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD0), 1, SHU1_CA_CMD0_RG_TX_ARCLK_DRVP_PRE_BIT0);
+
+#if DutyPrintCalibrationLog
+ mcSHOW_DBG_MSG(("\tB0\tB1\tCA\n"));
+ mcSHOW_DBG_MSG(("===========================\n"));
+#endif
+
+ for(i=0; i<15; i++)
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ0), calibration_sequence[i], B0_DQ0_RG_RX_ARDQ2_OFFC_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ0), calibration_sequence[i], B1_DQ0_RG_RX_ARDQ2_OFFC_B1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_CA_CMD0), calibration_sequence[i], CA_CMD0_RG_RX_ARCA2_OFFC);
+
+ mcDELAY_US(1);
+
+ read_val_b0 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_AD_RX_DQ_O1), MISC_AD_RX_DQ_O1_AD_RX_ARDQ_O1_B0_BIT2);
+ read_val_b1 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_AD_RX_DQ_O1), MISC_AD_RX_DQ_O1_AD_RX_ARDQ_O1_B1_BIT2);
+ read_val_ca = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_AD_RX_CMD_O1), MISC_AD_RX_CMD_O1_AD_RX_ARCA2_O1);
+
+#if DutyPrintCalibrationLog
+ mcSHOW_DBG_MSG(("%d\t%d\t%d\t%d\n", DutyScan_Offset_Convert(i), read_val_b0, read_val_b1, read_val_ca));
+#endif
+
+ if (read_val_b0 == 0 && cal_i_b0==0xff)
+ {
+ cal_i_b0 = i;
+ }
+
+ if (read_val_b1 == 0 && cal_i_b1==0xff)
+ {
+ cal_i_b1 = i;
+ }
+
+ if (read_val_ca == 0 && cal_i_ca==0xff)
+ {
+ cal_i_ca = i;
+ }
+ }
+
+ if (cal_i_b0==0 || cal_i_b1==0 || cal_i_ca==0)
+ {
+#if DutyPrintCalibrationLog
+ mcSHOW_ERR_MSG(("offset calibration i=-7 and AD_RX_*RDQ_O1_B*<2>/AD_RX_*RCA2_O1 ==0 !!\n"));
+#endif
+#if __ETT__
+ while(1);
+#endif
+ }
+ else
+ if ((read_val_b0==1 && cal_i_b0==0xff) || (read_val_b1==1 && cal_i_b1==0xff) || (read_val_ca==1 && cal_i_ca==0xff))
+ {
+#if DutyPrintCalibrationLog
+ mcSHOW_ERR_MSG(("offset calibration i=7 and AD_RX_*RDQ_O1_B*<2>/AD_RX_*RCA2_O1 ==1 !!\n"));
+#endif
+#if __ETT__
+ while(1);
+#endif
+
+ }
+ else
+ {
+#if DutyPrintCalibrationLog
+ mcSHOW_DBG_MSG(("===========================\n"));
+ mcSHOW_DBG_MSG(("\tB0:%d\tB1:%d\tCA:%d\n",DutyScan_Offset_Convert(cal_i_b0),DutyScan_Offset_Convert(cal_i_b1),DutyScan_Offset_Convert(cal_i_ca)));
+#endif
+ }
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ0), 0, SHU1_B0_DQ0_RG_TX_ARDQS0_DRVP_PRE_B0_BIT0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ0), 0, SHU1_B1_DQ0_RG_TX_ARDQS0_DRVP_PRE_B1_BIT0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD0), 0, SHU1_CA_CMD0_RG_TX_ARCLK_DRVP_PRE_BIT0);
+
+ if (cal_i_b0!=0xff) vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ0), calibration_sequence[cal_i_b0], B0_DQ0_RG_RX_ARDQ2_OFFC_B0);
+ if (cal_i_b1!=0xff) vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ0), calibration_sequence[cal_i_b1], B1_DQ0_RG_RX_ARDQ2_OFFC_B1);
+ if (cal_i_ca!=0xff) vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_CA_CMD0), calibration_sequence[cal_i_ca], CA_CMD0_RG_RX_ARCA2_OFFC);
+
+ return;
+}
+
+#if defined(YH_SWEEP_IC)
+typedef struct _YH_SWEEP_IC_T
+{
+ U32 maxduty;
+ U32 minduty;
+ U32 dutydiff;
+ U32 avgduty;
+} YH_SWEEP_IC_T;
+
+YH_SWEEP_IC_T gYH_Sweep_IC_test_result[4][CHANNEL_NUM][DQS_NUMBER];
+
+#define YH_SWEEP_IC_PASS_CRITERIO 1 // 0: FT 1: SLT
+void YH_Sweep_IC_Print_Result(DRAMC_CTX_T *p)
+{
+ U8 u1ChannelIdx, u1ByteIdx, k_type;
+ U8 u1ByteIdxNum;
+
+ // SLT:
+ // CHB CLK duty max-min j5.3%: FAIL0
+ // NDQS duty max-min j5.8%: FAIL1
+ // NDQDQM maxduty j54.5% or min_duty<45.5% or max-min j5.8%: FAIL2
+
+ mcSHOW_ERR_MSG(("\n\n YH Sweep IC Print Result =========\n"));
+
+ for(k_type=0; k_type<4; k_type++)
+ {
+
+ if (k_type == DutyScan_Calibration_K_CLK) u1ByteIdxNum = 1;
+ else u1ByteIdxNum = 2;
+
+ for(u1ChannelIdx=0; u1ChannelIdx<CHANNEL_NUM; u1ChannelIdx++)
+ for(u1ByteIdx=0; u1ByteIdx<u1ByteIdxNum; u1ByteIdx++)
+ {
+ if (k_type == DutyScan_Calibration_K_CLK && u1ChannelIdx == CHANNEL_B)
+ {
+ mcSHOW_ERR_MSG(("CH%d CLK max-min Duty %d%% : ",u1ChannelIdx, gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].dutydiff));
+#if YH_SWEEP_IC_PASS_CRITERIO
+ if (gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].dutydiff > 530)
+#else
+ if (gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].dutydiff > 450)
+#endif
+ {
+ mcSHOW_ERR_MSG(("FAIL0\n"));
+ }
+ else
+ {
+ mcSHOW_ERR_MSG(("PASS\n"));
+ }
+ }
+ if (k_type == DutyScan_Calibration_K_DQS)
+ {
+ mcSHOW_ERR_MSG(("CH%d DQS Byte %d max-min Duty %d%% : ",u1ChannelIdx, u1ByteIdx, gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].dutydiff));
+#if YH_SWEEP_IC_PASS_CRITERIO
+ if (gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].dutydiff > 580)
+#else
+ if (gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].dutydiff > 500)
+#endif
+ {
+ mcSHOW_ERR_MSG(("FAIL1\n"));
+ }
+ else
+ {
+ mcSHOW_ERR_MSG(("PASS\n"));
+ }
+ }
+ if (k_type == DutyScan_Calibration_K_DQ || k_type == DutyScan_Calibration_K_DQM)
+ {
+ mcSHOW_ERR_MSG(("CH%d %s Byte %d max Duty %d%%, min Duty %d%% : ",u1ChannelIdx, k_type == DutyScan_Calibration_K_DQ ? "DQ" : "DQM", u1ByteIdx, gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].maxduty, gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].minduty));
+#if YH_SWEEP_IC_PASS_CRITERIO
+ if (gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].minduty < 4550 || gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].maxduty > 5450 || gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].dutydiff > 580)
+#else
+ if (gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].minduty < 4600 || gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].maxduty > 5400 || gYH_Sweep_IC_test_result[k_type][u1ChannelIdx][u1ByteIdx].dutydiff > 500)
+#endif
+ {
+ mcSHOW_ERR_MSG(("FAIL2\n"));
+ }
+ else
+ {
+ mcSHOW_ERR_MSG(("PASS\n"));
+ }
+ }
+ }
+ }
+}
+#endif
+
+S8 gcFinal_K_CLK_delay_cell[CHANNEL_NUM][DQS_NUMBER];
+S8 gcFinal_K_DQS_delay_cell[CHANNEL_NUM][DQS_NUMBER];
+#if APPLY_DQDQM_DUTY_CALIBRATION
+S8 gcFinal_K_DQ_delay_cell[CHANNEL_NUM][DQS_NUMBER];
+S8 gcFinal_K_DQM_delay_cell[CHANNEL_NUM][DQS_NUMBER];
+#endif
+DRAM_STATUS_T DutyScan_Calibration_Flow(DRAMC_CTX_T *p, U8 k_type, U8 use_rev_bit)
+{
+ S8 scinner_duty_ofst, scFinal_clk_delay_cell[DQS_NUMBER]={0,0};
+ S8 scinner_duty_ofst_start = 0, scinner_duty_ofst_end = 0;
+ S32 s4PICnt, s4PIBegin, s4PIEnd, s4PICnt_mod64;
+ S8 i, swap_idx, ucdqs_i, ucdqs_i_count=2;
+ U8 ucDelay, ucDelayB;
+ U8 ucRev_Bit0=0, ucRev_Bit1=0;
+ U8 ucDelayDQDQM, ucRev_Bit0_DQDQM=0, ucRev_Bit1_DQDQM=0;
+ U32 u4DutyDiff, u4DutyDiff_Limit=900;
+
+ U8 vref_sel_value[2], cal_out_value;
+ S32 duty_value[2];
+ S32 final_duty;
+
+ U32 ucperiod_duty_max=0, ucperiod_duty_min=0xffffffff, ucperiod_duty_max_clk_dly=0, ucperiod_duty_min_clk_dly=0;
+ U32 ucperiod_duty_averige=0, ucFinal_period_duty_averige[DQS_NUMBER]={0,0}, ucmost_approach_50_percent=0xffffffff;
+ U32 ucFinal_period_duty_max[DQS_NUMBER] = {0,0}, ucFinal_period_duty_min[DQS_NUMBER] = {0,0};
+ U32 ucFinal_duty_max_clk_dly[DQS_NUMBER]={0},ucFinal_duty_min_clk_dly[DQS_NUMBER]={0};
+ U8 early_break_count=0;
+ U8 str_clk_duty[]="CLK", str_dqs_duty[]="DQS", str_dq_duty[]="DQ", str_dqm_duty[]="DQM";
+ U8 *str_who_am_I=str_clk_duty;
+
+ mcSHOW_ERR_MSG(("\n[DutyScan_Calibration_Flow] %s Calibration\n", use_rev_bit==0 ? "First" : "Second"));
+ mcSHOW_ERR_MSG(("\n[DutyScan_Calibration_Flow] k_type=%d, use_rev_bit=%d\n", k_type, use_rev_bit));
+ /*TINFO="\n[DutyScan_Calibration_Flow] k_type=%d\n", k_type */
+
+
+ if (k_type == DutyScan_Calibration_K_CLK)
+ {
+#if 0
+ // DQS duty test 3
+ //mcSHOW_ERR_MSG(("\n[*PHDET_EN*=0]\n"));
+ mcSHOW_ERR_MSG(("\n[*PI*RESETB*=0 *PHDET_EN*=0 *PI_RESETB*=1]\n"));
+ /*TINFO="\n[*PI*RESETB*=0 *PHDET_EN*=0 *PI_RESETB*=1]\n" */
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_CA_DLL_ARPI0), 0x0, CA_DLL_ARPI0_RG_ARPI_RESETB_CA);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_CA_DLL_ARPI2), 0x0, CA_DLL_ARPI2_RG_ARDLL_PHDET_EN_CA);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_CA_DLL_ARPI0), 0x1, CA_DLL_ARPI0_RG_ARPI_RESETB_CA);
+#else
+#if DutyPrintCalibrationLog
+ mcSHOW_ERR_MSG(("\n[ *PHDET_EN*=0 \n"));
+#endif
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_CA_DLL_ARPI2), 0x0, CA_DLL_ARPI2_RG_ARDLL_PHDET_EN_CA);
+#endif
+ }
+ else
+ {
+ // DQS duty test 3
+ //mcSHOW_ERR_MSG(("\n[*PHDET_EN*=0]\n"));
+#if DutyPrintCalibrationLog
+ mcSHOW_ERR_MSG(("[*PI*RESETB*=0 *PHDET_EN*=0 *PI_RESETB*=1]\n"));
+#endif
+ /*TINFO="[*PI*RESETB*=0 *PHDET_EN*=0 *PI_RESETB*=1]\n" */
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DLL_ARPI0), 0x0, B0_DLL_ARPI0_RG_ARPI_RESETB_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DLL_ARPI0), 0x0, B1_DLL_ARPI0_RG_ARPI_RESETB_B1);
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DLL_ARPI2), 0x0, B0_DLL_ARPI2_RG_ARDLL_PHDET_EN_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DLL_ARPI2), 0x0, B1_DLL_ARPI2_RG_ARDLL_PHDET_EN_B1);
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DLL_ARPI0), 0x1, B0_DLL_ARPI0_RG_ARPI_RESETB_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DLL_ARPI0), 0x1, B1_DLL_ARPI0_RG_ARPI_RESETB_B1);
+ }
+
+ //CLK Source Select (DQ/DQM/DQS/CLK)
+ if (k_type == DutyScan_Calibration_K_DQ) // K DQ
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ8), 0, B0_DQ8_RG_TX_ARDQ_CAP_DET_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DLL1), 0, RG_ARDQ_REV_BIT_06_MCK4X_SEL_DQ1);
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ8), 0, B1_DQ8_RG_TX_ARDQ_CAP_DET_B1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DLL1), 0, RG_ARDQ_REV_BIT_06_MCK4X_SEL_DQ1);
+
+ ucdqs_i_count = 2;
+ str_who_am_I = (U8*)str_dq_duty;
+
+#if APPLY_DQDQM_DUTY_CALIBRATION
+ scinner_duty_ofst_start = -7;
+ scinner_duty_ofst_end = 7;
+#else
+ scinner_duty_ofst_start = 0;
+ scinner_duty_ofst_end = 0;
+#endif
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ p->pSavetimeData->u1dq_use_rev_bit = use_rev_bit;
+#endif
+ }
+ else if (k_type == DutyScan_Calibration_K_DQM) // K DQM
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ8), 0, B0_DQ8_RG_TX_ARDQ_CAP_DET_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DLL1), 1, RG_ARDQ_REV_BIT_06_MCK4X_SEL_DQ1);
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ8), 0, B1_DQ8_RG_TX_ARDQ_CAP_DET_B1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DLL1), 1, RG_ARDQ_REV_BIT_06_MCK4X_SEL_DQ1);
+
+ ucdqs_i_count = 2;
+ str_who_am_I = (U8*)str_dqm_duty;
+
+#if APPLY_DQDQM_DUTY_CALIBRATION
+ scinner_duty_ofst_start = -7;
+ scinner_duty_ofst_end = 7;
+#else
+ scinner_duty_ofst_start = 0;
+ scinner_duty_ofst_end = 0;
+#endif
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ p->pSavetimeData->u1dqm_use_rev_bit = use_rev_bit;
+#endif
+ }
+ else if (k_type == DutyScan_Calibration_K_DQS) // K DQS
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ8), 1, B0_DQ8_RG_TX_ARDQ_CAP_DET_B0);
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ8), 1, B1_DQ8_RG_TX_ARDQ_CAP_DET_B1);
+
+ ucdqs_i_count = 2;
+ str_who_am_I = (U8*)str_dqs_duty;
+
+ scinner_duty_ofst_start = DUTY_OFFSET_START;
+ scinner_duty_ofst_end = DUTY_OFFSET_END;
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ p->pSavetimeData->u1dqs_use_rev_bit = use_rev_bit;
+#endif
+ }
+ else if (k_type == DutyScan_Calibration_K_CLK) // K CLK
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_CA_CMD9), 1, CA_CMD9_RG_TX_ARCMD_CAP_DET);
+
+ ucdqs_i_count = 1;
+ str_who_am_I = (U8*)str_clk_duty;
+
+ scinner_duty_ofst_start = DUTY_OFFSET_START;
+ scinner_duty_ofst_end = DUTY_OFFSET_END;
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ p->pSavetimeData->u1clk_use_rev_bit = use_rev_bit;
+#endif
+ }
+
+#if defined(YH_SWEEP_IC) || FT_DSIM_USED
+ scinner_duty_ofst_start=0;
+ scinner_duty_ofst_end=0;
+#endif
+
+#if (fcFOR_CHIP_ID == fcLaurel)
+ if (k_type == DutyScan_Calibration_K_CLK)
+ {
+ u4DutyDiff_Limit = 530;
+ }
+ else
+ {
+ u4DutyDiff_Limit = 580;
+ }
+#endif
+
+#if (fcFOR_CHIP_ID == fcLaurel)
+#if !defined(YH_SWEEP_IC)
+ if (k_type == DutyScan_Calibration_K_CLK && p->channel == CHANNEL_A)
+ {
+ s4PIBegin = 0;
+ s4PIEnd = 0;
+ }
+ else
+#endif
+#endif
+ {
+ s4PIBegin = CLOCK_PI_START;
+ s4PIEnd = CLOCK_PI_END;
+ }
+
+ for(ucdqs_i=0; ucdqs_i<ucdqs_i_count; ucdqs_i++)
+ {
+#if DutyPrintCalibrationLog
+ if (k_type == DutyScan_Calibration_K_CLK)
+ {
+ mcSHOW_ERR_MSG(("\n[CLK Duty scan]\n"));
+ /*TINFO="\n[CLK Duty scan]\n"*/
+ }
+ else
+ {
+ mcSHOW_ERR_MSG(("\n[%s B%d Duty scan]\n", str_who_am_I, ucdqs_i));
+ /*TINFO="\n[%s B%d Duty scan]\n", str_who_am_I, ucdqs_i */
+ }
+#endif
+
+ ucmost_approach_50_percent=0xffffffff;
+ early_break_count=0;
+
+ for(scinner_duty_ofst=scinner_duty_ofst_start; scinner_duty_ofst<=scinner_duty_ofst_end; scinner_duty_ofst++)
+ {
+ ucperiod_duty_max = 0;
+ ucperiod_duty_min = 100000;
+
+ if (scinner_duty_ofst<0)
+ {
+ ucDelay = -scinner_duty_ofst;
+ ucDelayB = 0;
+
+ if (use_rev_bit)
+ {
+ ucRev_Bit0 = 1;
+ ucRev_Bit1 = 0;
+ }
+
+ ucDelayDQDQM = (-scinner_duty_ofst) | (1<<3); //sign bit
+ ucRev_Bit0_DQDQM = 0;
+ ucRev_Bit1_DQDQM = 1;
+ }
+ else if (scinner_duty_ofst>0)
+ {
+ ucDelay = 0;
+ ucDelayB= scinner_duty_ofst;
+
+ if (use_rev_bit)
+ {
+ ucRev_Bit0 = 0;
+ ucRev_Bit1 = 1;
+ }
+
+ ucDelayDQDQM = scinner_duty_ofst;
+ ucRev_Bit0_DQDQM = 1;
+ ucRev_Bit1_DQDQM = 0;
+ }
+ else
+ {
+ ucDelay = 0;
+ ucDelayB= 0;
+
+ if (use_rev_bit)
+ {
+ ucRev_Bit0 = 0;
+ ucRev_Bit1 = 0;
+ }
+
+ ucDelayDQDQM = 0;
+ ucRev_Bit0_DQDQM = 0;
+ ucRev_Bit1_DQDQM = 0;
+ }
+
+ if (k_type == DutyScan_Calibration_K_DQS)
+ {
+ if (ucdqs_i==0)
+ {
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ1), P_Fld(ucDelay, SHU1_R0_B0_DQ1_RK0_TX_ARDQS0_DLY_B0)
+ | P_Fld(ucDelay, SHU1_R0_B0_DQ1_RK0_TX_ARDQS0B_DLY_B0)
+ | P_Fld(ucDelayB, SHU1_R0_B0_DQ1_RK0_TX_ARDQS0_DLYB_B0)
+ | P_Fld(ucDelayB, SHU1_R0_B0_DQ1_RK0_TX_ARDQS0B_DLYB_B0));
+
+// Lau_rel like Mer_lot, no need to set this to big scale mode, just use small scale mode
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DLL1), P_Fld(ucRev_Bit0, RG_ARDQ_REV_BIT_00_DQS_MCK4X_DLY_EN)
+ | P_Fld(ucRev_Bit1, RG_ARDQ_REV_BIT_01_DQS_MCK4XB_DLY_EN));
+
+ }
+ else
+ {
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ1), P_Fld(ucDelay, SHU1_R0_B1_DQ1_RK0_TX_ARDQS0_DLY_B1)
+ | P_Fld(ucDelay, SHU1_R0_B1_DQ1_RK0_TX_ARDQS0B_DLY_B1)
+ | P_Fld(ucDelayB, SHU1_R0_B1_DQ1_RK0_TX_ARDQS0_DLYB_B1)
+ | P_Fld(ucDelayB, SHU1_R0_B1_DQ1_RK0_TX_ARDQS0B_DLYB_B1));
+
+// Lau_rel like Mer_lot, no need to set this to big scale mode, just use small scale mode
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DLL1), P_Fld(ucRev_Bit0, RG_ARDQ_REV_BIT_00_DQS_MCK4X_DLY_EN)
+ | P_Fld(ucRev_Bit1, RG_ARDQ_REV_BIT_01_DQS_MCK4XB_DLY_EN));
+ }
+
+ }
+
+ if (k_type == DutyScan_Calibration_K_CLK)
+ {
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD1), P_Fld(ucDelay, SHU1_R0_CA_CMD1_RK0_TX_ARCLK_DLY)
+ | P_Fld(ucDelay, SHU1_R0_CA_CMD1_RK0_TX_ARCLKB_DLY));
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD0), P_Fld(ucDelayB, SHU1_R0_CA_CMD0_RK0_TX_ARCLK_DLYB)
+ | P_Fld(ucDelayB, SHU1_R0_CA_CMD0_RK0_TX_ARCLKB_DLYB));
+
+// Lau_rel like Mer_lot, no need to set this to big scale mode, just use small scale mode
+ vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD3), P_Fld(ucRev_Bit0, SHU1_CA_CMD3_RG_TX_ARCMD_PU_BIT0)
+ | P_Fld(ucRev_Bit1, SHU1_CA_CMD3_RG_TX_ARCMD_PU_BIT1));
+ }
+
+#if APPLY_DQDQM_DUTY_CALIBRATION
+ if (k_type == DutyScan_Calibration_K_DQ || k_type == DutyScan_Calibration_K_DQM)
+ {
+ if (ucdqs_i==0)
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B0_DQ10), ucDelayDQDQM, B0_DQ10_RG_ARDQ_DUTYREV_B0_DQ_DUTY_DELAY);
+
+// Lau_rel like Mer_lot, no need to set this to big scale mode, just use small scale mode
+// vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B0_DQ3), P_Fld(ucRev_Bit0_DQDQM, SHU1_B0_DQ3_RG_TX_ARDQS0_PU_PRE_B0_BIT0)
+// | P_Fld(ucRev_Bit1_DQDQM, SHU1_B0_DQ3_RG_TX_ARDQS0_PU_PRE_B0_BIT1));
+ }
+ else
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_B1_DQ10), ucDelayDQDQM, B0_DQ10_RG_ARDQ_DUTYREV_B0_DQ_DUTY_DELAY);
+
+// Lau_rel like Mer_lot, no need to set this to big scale mode, just use small scale mode
+// vIO32WriteFldMulti(DRAMC_REG_ADDR(DDRPHY_B1_DQ3), P_Fld(ucRev_Bit0_DQDQM, SHU1_B0_DQ3_RG_TX_ARDQS0_PU_PRE_B0_BIT0)
+// | P_Fld(ucRev_Bit1_DQDQM, SHU1_B0_DQ3_RG_TX_ARDQS0_PU_PRE_B0_BIT1));
+ }
+ }
+#endif
+
+ for(s4PICnt=s4PIBegin; s4PICnt<=s4PIEnd; s4PICnt+=CLOCK_PI_STEP)
+ {
+ s4PICnt_mod64 = (s4PICnt+64)&0x3f;//s4PICnt_mod64 = (s4PICnt+64)%64;
+#if DutyPrintAllLog
+ //if(scinner_duty_ofst!=DUTY_OFFSET_START)
+ mcSHOW_ERR_MSG(("PI= %d\n", s4PICnt_mod64));
+#endif
+
+ if (k_type == DutyScan_Calibration_K_DQS)
+ {
+ if (ucdqs_i==0)
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), s4PICnt_mod64, SHU1_R0_B0_DQ7_RK0_ARPI_PBYTE_B0);
+ }
+ else
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), s4PICnt_mod64, SHU1_R0_B1_DQ7_RK0_ARPI_PBYTE_B1);
+ }
+ }
+ else
+ if (k_type == DutyScan_Calibration_K_CLK)
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_CA_CMD9), s4PICnt_mod64, SHU1_R0_CA_CMD9_RG_RK0_ARPI_CLK);
+ }
+ else
+ if (k_type == DutyScan_Calibration_K_DQ)
+ {
+ if (ucdqs_i==0)
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), s4PICnt_mod64, SHU1_R0_B0_DQ7_RK0_ARPI_DQ_B0);
+ }
+ else
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), s4PICnt_mod64, SHU1_R0_B1_DQ7_RK0_ARPI_DQ_B1);
+ }
+ }
+ else
+ if (k_type == DutyScan_Calibration_K_DQM)
+ {
+ if (ucdqs_i==0)
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B0_DQ7), s4PICnt_mod64, SHU1_R0_B0_DQ7_RK0_ARPI_DQM_B0);
+ }
+ else
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_R0_B1_DQ7), s4PICnt_mod64, SHU1_R0_B1_DQ7_RK0_ARPI_DQM_B1);
+ }
+ }
+
+ for(swap_idx=0; swap_idx<2; swap_idx++)
+ {
+ if (k_type == DutyScan_Calibration_K_CLK)
+ {
+ if (swap_idx==0)
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_DLL1), 2, RG_ARCMD_REV_BIT_2221_DATA_SWAP);
+ }
+ else
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_DLL1), 3, RG_ARCMD_REV_BIT_2221_DATA_SWAP);
+ }
+
+ vref_sel_value[swap_idx]= 0;
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD5), vref_sel_value[swap_idx]>>1, SHU1_CA_CMD5_RG_RX_ARCMD_VREF_SEL);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD0), (vref_sel_value[swap_idx]&1)==1?0:1, SHU1_CA_CMD0_RG_TX_ARCLK_DRVP_PRE_BIT1);
+ }
+ else
+ {
+ if (ucdqs_i==0)
+ {
+ if (swap_idx==0)
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DLL1), 2, RG_ARDQ_REV_BIT_2221_DATA_SWAP);
+ }
+ else
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DLL1), 3, RG_ARDQ_REV_BIT_2221_DATA_SWAP);
+ }
+
+ vref_sel_value[swap_idx]= 0;
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ5), vref_sel_value[swap_idx]>>1, SHU1_B0_DQ5_RG_RX_ARDQ_VREF_SEL_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ0), (vref_sel_value[swap_idx]&1)==1?0:1, SHU1_B0_DQ0_RG_TX_ARDQS0_DRVP_PRE_B0_BIT1);
+ }
+ else
+ {
+ if (swap_idx==0)
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DLL1), 2, RG_ARDQ_REV_BIT_2221_DATA_SWAP);
+ }
+ else
+ {
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DLL1), 3, RG_ARDQ_REV_BIT_2221_DATA_SWAP);
+ }
+
+ vref_sel_value[swap_idx]= 0;
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ5), vref_sel_value[swap_idx]>>1, SHU1_B1_DQ5_RG_RX_ARDQ_VREF_SEL_B1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ0), (vref_sel_value[swap_idx]&1)==1?0:1, SHU1_B1_DQ0_RG_TX_ARDQS0_DRVP_PRE_B1_BIT1);
+ }
+ }
+
+ for(i=5; i>=0; i--)
+ {
+ if (k_type == DutyScan_Calibration_K_CLK)
+ {
+ vref_sel_value[swap_idx] |= (1<<i);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD5), vref_sel_value[swap_idx]>>1, SHU1_CA_CMD5_RG_RX_ARCMD_VREF_SEL);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_CA_CMD0), (vref_sel_value[swap_idx]&1)==1?0:1, SHU1_CA_CMD0_RG_TX_ARCLK_DRVP_PRE_BIT1);
+
+ mcDELAY_US(1);
+
+ cal_out_value = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_AD_RX_CMD_O1), MISC_AD_RX_CMD_O1_AD_RX_ARCA2_O1);
+
+ if (cal_out_value == 0)
+ {
+ vref_sel_value[swap_idx] &= ~(1<<i);
+ }
+ }
+ else
+ {
+ if (ucdqs_i==0)
+ {
+ vref_sel_value[swap_idx] |= (1<<i);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ5), vref_sel_value[swap_idx]>>1, SHU1_B0_DQ5_RG_RX_ARDQ_VREF_SEL_B0);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B0_DQ0), (vref_sel_value[swap_idx]&1)==1?0:1, SHU1_B0_DQ0_RG_TX_ARDQS0_DRVP_PRE_B0_BIT1);
+
+ mcDELAY_US(1);
+
+ cal_out_value = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_AD_RX_DQ_O1), MISC_AD_RX_DQ_O1_AD_RX_ARDQ_O1_B0_BIT2);
+ }
+ else
+ {
+ vref_sel_value[swap_idx] |= (1<<i);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ5), vref_sel_value[swap_idx]>>1, SHU1_B1_DQ5_RG_RX_ARDQ_VREF_SEL_B1);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DDRPHY_SHU1_B1_DQ0), (vref_sel_value[swap_idx]&1)==1?0:1, SHU1_B1_DQ0_RG_TX_ARDQS0_DRVP_PRE_B1_BIT1);
+
+ mcDELAY_US(1);
+
+ cal_out_value = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DDRPHY_MISC_AD_RX_DQ_O1), MISC_AD_RX_DQ_O1_AD_RX_ARDQ_O1_B1_BIT2);
+ }
+
+#if DutyPrintAllLog
+ //mcSHOW_DBG_MSG(("Fra i=%d vref_sel_value[swap_idx]=%x, cal_out=%d\n",i, vref_sel_value[swap_idx], cal_out_value));
+#endif
+
+ if (cal_out_value == 0)
+ {
+ vref_sel_value[swap_idx] &= ~(1<<i);
+ }
+ }
+ }
+ }
+
+
+ for(swap_idx=0; swap_idx<2; swap_idx++)
+ {
+ if (vref_sel_value[swap_idx]<=31)
+ {
+ duty_value[swap_idx] = (vref_sel_value[swap_idx]-23)*69+5050;
+ }
+ else
+ {
+ duty_value[swap_idx] = (vref_sel_value[swap_idx]-32)*55+5600;
+ }
+ }
+
+#if DutyPrintAllLog
+ mcSHOW_ERR_MSG(("\t[%d][%d] B%d : Vref_Sel=0x%x, Swap Vref_Sel=0x%x\n", scinner_duty_ofst, s4PICnt, ucdqs_i, vref_sel_value[0], vref_sel_value[1]));
+ mcSHOW_ERR_MSG(("\t[%d][%d] B%d : duty_value=%d, Swap duty_value=%d\n", scinner_duty_ofst, s4PICnt, ucdqs_i, duty_value[0], duty_value[1]));
+#endif
+
+ final_duty = 5000+((duty_value[0]-duty_value[1])/2);
+
+ if (final_duty > (S32) ucperiod_duty_max)
+ {
+ ucperiod_duty_max = final_duty;
+ ucperiod_duty_max_clk_dly = s4PICnt;
+ }
+ if (final_duty < (S32) ucperiod_duty_min)
+ {
+ ucperiod_duty_min = final_duty;
+ ucperiod_duty_min_clk_dly = s4PICnt;
+ }
+
+#if DutyPrintAllLog
+ mcSHOW_ERR_MSG(("\t[%d][%d] B%d : Final_Duty=%d\n", scinner_duty_ofst, s4PICnt, ucdqs_i, final_duty));
+#endif
+ }
+
+
+
+ ucperiod_duty_averige = (ucperiod_duty_max + ucperiod_duty_min)>>1;
+
+#if DutyPrintCalibrationLog
+ if (k_type==DutyScan_Calibration_K_CLK)
+ {
+ mcSHOW_ERR_MSG(("[%d] CLK\n",scinner_duty_ofst));
+ /*TINFO="[%d] CLK\n",scinner_duty_ofst */
+ }
+ else
+ {
+ mcSHOW_ERR_MSG(("[%d] %s%d\n",scinner_duty_ofst, str_who_am_I, ucdqs_i));
+ /*TINFO="[%d] %s%d\n",scinner_duty_ofst, str_who_am_I, ucdqs_i */
+ }
+#endif
+
+#if DutyPrintCalibrationLog
+ mcSHOW_ERR_MSG(("\tMAX Duty = %d%%(X100), CLK PI=%d\n",ucperiod_duty_max, ucperiod_duty_max_clk_dly));
+ /*TINFO="\tMAX Duty = %d%%(X100), CLK PI=%d\n",ucperiod_duty_max, ucperiod_duty_max_clk_dly */
+ mcSHOW_ERR_MSG(("\tMIN Duty = %d%%(X100), CLK PI=%d\n",ucperiod_duty_min, ucperiod_duty_min_clk_dly));
+ /*TINFO="\tMIN Duty = %d%%(X100), CLK PI=%d\n",ucperiod_duty_min, ucperiod_duty_min_clk_dly */
+ mcSHOW_ERR_MSG(("\tAVG Duty = %d%%(X100)\n", ucperiod_duty_averige));
+ /*TINFO="\tAVG Duty = %d%%(X100)\n", ucperiod_duty_averige */
+#endif
+
+ if (ucperiod_duty_averige >= ClockDutyMiddleBound)
+ {
+ if ((scinner_duty_ofst<=0 && ((ucperiod_duty_averige-ClockDutyMiddleBound+(ucperiod_duty_max-ucperiod_duty_min)/2) <= ucmost_approach_50_percent)) ||
+ (scinner_duty_ofst>0 && ((ucperiod_duty_averige-ClockDutyMiddleBound+(ucperiod_duty_max-ucperiod_duty_min)/2) < ucmost_approach_50_percent)))
+ {
+ ucmost_approach_50_percent = ucperiod_duty_averige-ClockDutyMiddleBound+(ucperiod_duty_max-ucperiod_duty_min)/2;
+ scFinal_clk_delay_cell[ucdqs_i] = scinner_duty_ofst;
+ ucFinal_period_duty_averige[ucdqs_i] = ucperiod_duty_averige;
+ ucFinal_period_duty_max[ucdqs_i] = ucperiod_duty_max;
+ ucFinal_period_duty_min[ucdqs_i] = ucperiod_duty_min;
+ ucFinal_duty_max_clk_dly[ucdqs_i] = ucperiod_duty_max_clk_dly;
+ ucFinal_duty_min_clk_dly[ucdqs_i] = ucperiod_duty_min_clk_dly;
+#if DutyPrintCalibrationLog
+ mcSHOW_ERR_MSG(("\t!!! ucmost_approach_50_percent = %d%%(X100) !!!\n",ucmost_approach_50_percent));
+ /*TINFO="!!! ucmost_approach_50_percent = %d%%(X100) !!!\n",ucmost_approach_50_percent */
+#endif
+ early_break_count = 0;
+ }
+ else
+ {
+ if (scinner_duty_ofst>0) early_break_count ++;
+#if DutyPrintAllLog==0
+ if (early_break_count>=2) break; //early break;
+#endif
+ }
+ }
+ else
+ {
+ if ((scinner_duty_ofst<=0 && ((ClockDutyMiddleBound-ucperiod_duty_averige+(ucperiod_duty_max-ucperiod_duty_min)/2) <= ucmost_approach_50_percent)) ||
+ (scinner_duty_ofst>0 && ((ClockDutyMiddleBound-ucperiod_duty_averige+(ucperiod_duty_max-ucperiod_duty_min)/2) < ucmost_approach_50_percent)))
+ {
+ ucmost_approach_50_percent = ClockDutyMiddleBound-ucperiod_duty_averige+(ucperiod_duty_max-ucperiod_duty_min)/2;
+ scFinal_clk_delay_cell[ucdqs_i] = scinner_duty_ofst;
+ ucFinal_period_duty_averige[ucdqs_i] = ucperiod_duty_averige;
+ ucFinal_period_duty_max[ucdqs_i] = ucperiod_duty_max;
+ ucFinal_period_duty_min[ucdqs_i] = ucperiod_duty_min;
+ ucFinal_duty_max_clk_dly[ucdqs_i] = ucperiod_duty_max_clk_dly;
+ ucFinal_duty_min_clk_dly[ucdqs_i] = ucperiod_duty_min_clk_dly;
+#if DutyPrintCalibrationLog
+ mcSHOW_ERR_MSG(("\t!!! ucmost_approach_50_percent = %d%%(X100) !!!\n",ucmost_approach_50_percent));
+ /*TINFO="!!! ucmost_approach_50_percent = %d%%(X100) !!!\n",ucmost_approach_50_percent */
+#endif
+ early_break_count = 0;
+ }
+ else
+ {
+ if (scinner_duty_ofst>0) early_break_count ++;
+#if DutyPrintAllLog==0
+ if (early_break_count>=2) break; //early break;
+#endif
+ }
+ }
+
+#if DutyPrintCalibrationLog
+ mcSHOW_ERR_MSG(("\n"));
+ /*TINFO="\n" */
+#endif
+ }
+ }
+
+ for(ucdqs_i=0; ucdqs_i<ucdqs_i_count; ucdqs_i++)
+ {
+ //for SLT, use ERR_MSG to force print log
+ if (k_type == DutyScan_Calibration_K_CLK)
+ {
+ mcSHOW_ERR_MSG(("\n==%s ==\n", str_who_am_I, ucdqs_i));
+ /*TINFO="\n==%s ==\n", str_who_am_I */
+ }
+ else
+ {
+ mcSHOW_ERR_MSG(("\n==%s %d ==\n", str_who_am_I, ucdqs_i));
+ /*TINFO="\n==%s %d ==\n", str_who_am_I, ucdqs_i */
+ }
+ mcSHOW_ERR_MSG(("Final %s duty delay cell = %d\n", str_who_am_I, scFinal_clk_delay_cell[ucdqs_i]));
+ /*TINFO="Final %s duty delay cell = %d\n", str_who_am_I, scFinal_clk_delay_cell[ucdqs_i] */
+ mcSHOW_ERR_MSG(("[%d] MAX Duty = %d%%(X100), DQS PI = %d\n",scFinal_clk_delay_cell[ucdqs_i], ucFinal_period_duty_max[ucdqs_i], ucFinal_duty_max_clk_dly[ucdqs_i]));
+ /*TINFO="[%d] MAX Duty = %d%%(X100), DQS PI = %d\n",scFinal_clk_delay_cell[ucdqs_i], ucFinal_period_duty_max[ucdqs_i], ucFinal_duty_max_clk_dly[ucdqs_i] */
+ mcSHOW_ERR_MSG(("[%d] MIN Duty = %d%%(X100), DQS PI = %d\n",scFinal_clk_delay_cell[ucdqs_i], ucFinal_period_duty_min[ucdqs_i], ucFinal_duty_min_clk_dly[ucdqs_i]));
+ /*TINFO="[%d] MIN Duty = %d%%(X100), DQS PI = %d\n",scFinal_clk_delay_cell[ucdqs_i], ucFinal_period_duty_min[ucdqs_i], ucFinal_duty_min_clk_dly[ucdqs_i] */
+ mcSHOW_ERR_MSG(("[%d] AVG Duty = %d%%(X100)\n", scFinal_clk_delay_cell[ucdqs_i], ucFinal_period_duty_averige[ucdqs_i]));
+ /*TINFO="[%d] AVG Duty = %d%%(X100)\n", scFinal_clk_delay_cell[ucdqs_i], ucFinal_period_duty_averige[ucdqs_i] */
+ }
+
+#if FT_DSIM_USED
+ FT_Duty_Compare_PassFail(p->channel, k_type, ucFinal_period_duty_max[0] , ucFinal_period_duty_min[0],ucFinal_period_duty_max[1] , ucFinal_period_duty_min[1]);
+#else
+ for(ucdqs_i=0; ucdqs_i<ucdqs_i_count; ucdqs_i++)
+ {
+ u4DutyDiff = ucFinal_period_duty_max[ucdqs_i] - ucFinal_period_duty_min[ucdqs_i];
+
+#if DQS_DUTY_SLT_CONDITION_TEST
+ if (k_type == DutyScan_Calibration_K_CLK || (k_type == DutyScan_Calibration_K_DQS))
+ {
+ u4DQSDutyDiff_Rec[p->channel][ucdqs_i][u1GlobalTestCnt]=u4DutyDiff;
+
+ u4DQSDutyDutyDly[p->channel][ucdqs_i] = scFinal_clk_delay_cell[ucdqs_i];
+
+ if(u4DutyDiff > u4DQSDutyDiff_Max[p->channel][ucdqs_i])
+ u4DQSDutyDiff_Max[p->channel][ucdqs_i] = u4DutyDiff;
+
+ if(u4DutyDiff < u4DQSDutyDiff_Min[p->channel][ucdqs_i])
+ u4DQSDutyDiff_Min[p->channel][ucdqs_i] = u4DutyDiff;
+
+ u4DQSDutyDiff_Avrg[p->channel][ucdqs_i] += u4DutyDiff;
+ }
+#endif
+
+#if defined(YH_SWEEP_IC)
+ gYH_Sweep_IC_test_result[k_type][p->channel][ucdqs_i].maxduty = ucFinal_period_duty_max[ucdqs_i];
+ gYH_Sweep_IC_test_result[k_type][p->channel][ucdqs_i].minduty = ucFinal_period_duty_min[ucdqs_i];
+ gYH_Sweep_IC_test_result[k_type][p->channel][ucdqs_i].dutydiff = u4DutyDiff;
+ gYH_Sweep_IC_test_result[k_type][p->channel][ucdqs_i].avgduty = ucFinal_period_duty_averige[ucdqs_i];
+#else
+ if ((((k_type == DutyScan_Calibration_K_CLK) || (k_type == DutyScan_Calibration_K_DQS)) && (u4DutyDiff < u4DutyDiff_Limit)) ||
+#if APPLY_DQDQM_DUTY_CALIBRATION
+ (((k_type == DutyScan_Calibration_K_DQ) || (k_type == DutyScan_Calibration_K_DQM)) && (u4DutyDiff < u4DutyDiff_Limit)))
+#else
+ (((k_type == DutyScan_Calibration_K_DQ) || (k_type == DutyScan_Calibration_K_DQM)) && ((u4DutyDiff < u4DutyDiff_Limit) && (ucFinal_period_duty_averige[ucdqs_i] >= 4550 && ucFinal_period_duty_averige[ucdqs_i] <= 5450))))
+#endif
+ {
+ if (k_type == DutyScan_Calibration_K_CLK)
+ {
+ mcSHOW_ERR_MSG(("\nCH%d %s Duty spec in!! Max-Min= %d%%\n",p->channel, str_who_am_I, u4DutyDiff));
+ /*TINFO="\nCH%d %s Duty spec in!! Max-Min= %d%%\n",p->channel, str_who_am_I, u4DutyDiff */
+ }
+ else
+ {
+ mcSHOW_ERR_MSG(("\nCH%d %s %d Duty spec in!! Max-Min= %d%%\n",p->channel, str_who_am_I, ucdqs_i, u4DutyDiff));
+ /*TINFO="\nCH%d %s %d Duty spec in!! Max-Min= %d%%\n",p->channel, str_who_am_I, ucdqs_i, u4DutyDiff */
+ }
+ }
+ else
+ {
+ if (k_type == DutyScan_Calibration_K_CLK)
+ {
+ mcSHOW_ERR_MSG(("\n\t\t\t\t\t\tCH%d %s Duty spec \033[1;32mout\033[m!! Max-Min= \033[1;32m%d%% >%d%%\033[m\n", p->channel, str_who_am_I, u4DutyDiff, u4DutyDiff_Limit));
+ /*TINFO="\nCH%d %s Duty spec out!! Max-Min= %d%% >8%%\n", p->channel, str_who_am_I, u4DutyDiff */
+ }
+ else
+ {
+ mcSHOW_ERR_MSG(("\n\t\t\t\t\t\tCH%d %s %d Duty spec \033[1;32mout\033[m!! Max-Min= \033[1;32m%d%% >%d%%\033[m\n", p->channel, str_who_am_I, ucdqs_i, u4DutyDiff, u4DutyDiff_Limit));
+ /*TINFO="\nCH%d %s %d Duty spec out!! Max-Min= %d%% >8%%\n", p->channel, str_who_am_I, ucdqs_i, u4DutyDiff */
+ }
+
+ #if defined(SLT)
+ while(1); //stop here
+ #endif
+
+ #if __ETT__
+
+ #if DQS_DUTY_SLT_CONDITION_TEST
+ retStatus = DRAM_FAIL;
+ #else
+ while(1); //stop here
+ #endif
+
+ #endif
+ }
+#endif
+ }
+
+#endif
+
+ if (k_type == DutyScan_Calibration_K_DQS)
+ {
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==0)
+ {
+ p->pSavetimeData->s1DQSDuty_clk_delay_cell[p->channel][0] = scFinal_clk_delay_cell[0];
+ p->pSavetimeData->s1DQSDuty_clk_delay_cell[p->channel][1] = scFinal_clk_delay_cell[1];
+ }
+#endif
+
+ // backup final values
+ gcFinal_K_DQS_delay_cell[p->channel][0] = scFinal_clk_delay_cell[0];
+ gcFinal_K_DQS_delay_cell[p->channel][1] = scFinal_clk_delay_cell[1];
+
+ DQSDutyScan_SetDqsDelayCell(p, scFinal_clk_delay_cell, use_rev_bit);
+
+#ifdef FOR_HQA_TEST_USED
+ gFinalDQSDuty[p->channel][0] = scFinal_clk_delay_cell[0];
+ gFinalDQSDuty[p->channel][1] = scFinal_clk_delay_cell[1];
+ gFinalDQSDutyMinMax[p->channel][0][0] = ucFinal_period_duty_min[0];
+ gFinalDQSDutyMinMax[p->channel][0][1] = ucFinal_period_duty_max[0];
+ gFinalDQSDutyMinMax[p->channel][1][0] = ucFinal_period_duty_min[1];
+ gFinalDQSDutyMinMax[p->channel][1][1] = ucFinal_period_duty_max[1];
+#endif
+ }
+
+ if (k_type == DutyScan_Calibration_K_CLK)
+ {
+ DramcClockDutySetClkDelayCell(p, RANK_0, scFinal_clk_delay_cell[0], use_rev_bit);
+ DramcClockDutySetClkDelayCell(p, RANK_1, scFinal_clk_delay_cell[0], use_rev_bit);
+
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==0)
+ {
+ p->pSavetimeData->s1ClockDuty_clk_delay_cell[p->channel][RANK_0] = scFinal_clk_delay_cell[0];
+ p->pSavetimeData->s1ClockDuty_clk_delay_cell[p->channel][RANK_1] = scFinal_clk_delay_cell[0];
+ }
+#endif
+
+ // backup final values
+ gcFinal_K_CLK_delay_cell[p->channel][0] = scFinal_clk_delay_cell[0];
+ gcFinal_K_CLK_delay_cell[p->channel][1] = scFinal_clk_delay_cell[1];
+
+#ifdef FOR_HQA_TEST_USED
+ gFinalClkDuty[p->channel] = scFinal_clk_delay_cell[0];
+ gFinalClkDutyMinMax[p->channel][0] = ucFinal_period_duty_min[0];
+ gFinalClkDutyMinMax[p->channel][1] = ucFinal_period_duty_max[0];
+#endif
+ }
+
+#if APPLY_DQDQM_DUTY_CALIBRATION
+ if (k_type == DutyScan_Calibration_K_DQ)
+ {
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==0)
+ {
+ p->pSavetimeData->s1DQDuty_clk_delay_cell[p->channel][0] = scFinal_clk_delay_cell[0];
+ p->pSavetimeData->s1DQDuty_clk_delay_cell[p->channel][1] = scFinal_clk_delay_cell[1];
+ }
+#endif
+
+ // backup final values
+ gcFinal_K_DQ_delay_cell[p->channel][0] = scFinal_clk_delay_cell[0];
+ gcFinal_K_DQ_delay_cell[p->channel][1] = scFinal_clk_delay_cell[1];
+
+ DQDQMDutyScan_SetDQDQMDelayCell(p, scFinal_clk_delay_cell, use_rev_bit, DutyScan_Calibration_K_DQ);
+ }
+
+ if (k_type == DutyScan_Calibration_K_DQM)
+ {
+#if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==0)
+ {
+ p->pSavetimeData->s1DQMDuty_clk_delay_cell[p->channel][0] = scFinal_clk_delay_cell[0];
+ p->pSavetimeData->s1DQMDuty_clk_delay_cell[p->channel][1] = scFinal_clk_delay_cell[1];
+ }
+#endif
+
+ // backup final values
+ gcFinal_K_DQM_delay_cell[p->channel][0] = scFinal_clk_delay_cell[0];
+ gcFinal_K_DQM_delay_cell[p->channel][1] = scFinal_clk_delay_cell[1];
+
+ DQDQMDutyScan_SetDQDQMDelayCell(p, scFinal_clk_delay_cell, use_rev_bit, DutyScan_Calibration_K_DQM);
+ }
+#endif
+
+ DramPhyReset(p);
+
+ mcSHOW_ERR_MSG(("[DutyScan_Calibration_Flow] ====Done====\n"));
+ /*TINFO="[DutyScan_Calibration_Flow] ====Done====\n" */
+
+ return DRAM_OK;
+}
+
+void DramcNewDutyCalibration(DRAMC_CTX_T *p)
+{
+ U8 u1backup_channel;
+
+#if(DQS_DUTY_SLT_CONDITION_TEST)
+ U16 u2TestCnt, u2FailCnt=0, u2TestCntTotal =20; //fra 400;
+ U8 u1ByteIdx, u1PI_FB;
+ U32 u4Variance;
+#endif
+ U8 use_rev_bit=0;
+
+ DRAM_STATUS_T u2FailStatusByCh[CHANNEL_NUM]={DRAM_OK,DRAM_OK};
+
+ //backup register value
+#if FT_DSIM_USED==0
+ U32 u4RegBackupAddress[] =
+ {
+ (DDRPHY_B0_DQ6),
+ (DDRPHY_SHU1_B0_DLL1),
+ (DDRPHY_SHU1_B0_DQ5),
+ (DDRPHY_SHU1_B0_DQ0),
+ (DDRPHY_B0_DQ0),
+ (DDRPHY_B0_DQ5),
+ (DDRPHY_B0_DQ8),
+ (DDRPHY_SHU1_R0_B0_DQ7),
+ (DDRPHY_B0_DLL_ARPI0),
+ (DDRPHY_B0_DLL_ARPI2),
+
+ (DDRPHY_B1_DQ6),
+ (DDRPHY_SHU1_B1_DLL1),
+ (DDRPHY_SHU1_B1_DQ5),
+ (DDRPHY_SHU1_B1_DQ0),
+ (DDRPHY_B1_DQ0),
+ (DDRPHY_B1_DQ5),
+ (DDRPHY_B1_DQ8),
+ (DDRPHY_SHU1_R0_B1_DQ7),
+ (DDRPHY_B1_DLL_ARPI0),
+ (DDRPHY_B1_DLL_ARPI2),
+
+
+ (DDRPHY_CA_CMD6),
+ (DDRPHY_SHU1_CA_DLL1),
+ (DDRPHY_SHU1_CA_CMD5),
+ (DDRPHY_SHU1_CA_CMD0),
+ (DDRPHY_CA_CMD0),
+ (DDRPHY_CA_CMD5),
+ (DDRPHY_CA_CMD9),
+// (DDRPHY_SHU1_CA_CMD3),
+ (DDRPHY_SHU1_R0_CA_CMD9),
+ (DDRPHY_CA_DLL_ARPI0),
+ (DDRPHY_CA_DLL_ARPI2),
+
+
+
+ (DDRPHY_B0_DQ6 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_SHU1_B0_DLL1 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_SHU1_B0_DQ5 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_SHU1_B0_DQ0 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_B0_DQ0 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_B0_DQ5 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_B0_DQ8 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_SHU1_R0_B0_DQ7 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_B0_DLL_ARPI0 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_B0_DLL_ARPI2 + SHIFT_TO_CHB_ADDR),
+
+ (DDRPHY_B1_DQ6 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_SHU1_B1_DLL1 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_SHU1_B1_DQ5 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_SHU1_B1_DQ0 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_B1_DQ0 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_B1_DQ5 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_B1_DQ8 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_SHU1_R0_B1_DQ7 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_B1_DLL_ARPI0 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_B1_DLL_ARPI2 + SHIFT_TO_CHB_ADDR),
+
+
+ (DDRPHY_CA_CMD6 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_SHU1_CA_DLL1 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_SHU1_CA_CMD5 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_SHU1_CA_CMD0 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_CA_CMD0 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_CA_CMD5 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_CA_CMD9 + SHIFT_TO_CHB_ADDR),
+// (DDRPHY_SHU1_CA_CMD3 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_SHU1_R0_CA_CMD9 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_CA_DLL_ARPI0 + SHIFT_TO_CHB_ADDR),
+ (DDRPHY_CA_DLL_ARPI2 + SHIFT_TO_CHB_ADDR)
+ };
+#endif
+
+#if !FT_DSIM_USED
+#if DUTY_SCAN_V2_ONLY_K_HIGHEST_FREQ
+ if((p->frequency == u2DFSGetHighestFreq(p)) && (Get_PRE_MIOCK_JMETER_HQA_USED_flag()==0))
+#else
+ if(Get_PRE_MIOCK_JMETER_HQA_USED_flag()==0)
+#endif
+#endif
+ {
+ if(u1IsLP4Family(p->dram_type))
+ {
+ U8 u1ChannelIdx;
+ u1backup_channel = vGetPHY2ChannelMapping(p);
+
+ #if SUPPORT_SAVE_TIME_FOR_CALIBRATION
+ if(p->femmc_Ready==1)
+ {
+ for(u1ChannelIdx=CHANNEL_A; u1ChannelIdx<p->support_channel_num; u1ChannelIdx++)
+ {
+ vSetPHY2ChannelMapping(p, u1ChannelSet[u1ChannelIdx]);
+ DramcClockDutySetClkDelayCell(p, RANK_0, p->pSavetimeData->s1ClockDuty_clk_delay_cell[p->channel][RANK_0], p->pSavetimeData->u1clk_use_rev_bit);
+ DramcClockDutySetClkDelayCell(p, RANK_1, p->pSavetimeData->s1ClockDuty_clk_delay_cell[p->channel][RANK_1], p->pSavetimeData->u1clk_use_rev_bit);
+ DQSDutyScan_SetDqsDelayCell(p, p->pSavetimeData->s1DQSDuty_clk_delay_cell[p->channel], p->pSavetimeData->u1dqs_use_rev_bit);
+ #if APPLY_DQDQM_DUTY_CALIBRATION
+ DQDQMDutyScan_SetDQDQMDelayCell(p, p->pSavetimeData->s1DQMDuty_clk_delay_cell[p->channel], p->pSavetimeData->u1dqm_use_rev_bit, DutyScan_Calibration_K_DQM);
+ DQDQMDutyScan_SetDQDQMDelayCell(p, p->pSavetimeData->s1DQDuty_clk_delay_cell[p->channel], p->pSavetimeData->u1dq_use_rev_bit, DutyScan_Calibration_K_DQ);
+ #endif
+ }
+ vSetPHY2ChannelMapping(p, u1backup_channel);
+ return;
+ }
+ else
+ #endif
+ {
+ //Clk free run
+ EnableDramcPhyDCM(p, 0);
+
+ for(u1ChannelIdx=CHANNEL_A; u1ChannelIdx<p->support_channel_num; u1ChannelIdx++)
+ {
+ vSetPHY2ChannelMapping(p, u1ChannelSet[u1ChannelIdx]);
+
+ //Fix rank to rank0
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANK);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 1, RKCFG_TXRANKFIX);
+
+ //backup register value
+ #if FT_DSIM_USED==0
+ DramcBackupRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+ #endif
+
+ DutyScan_Offset_Calibration(p);
+
+ #if defined(YH_SWEEP_IC)
+ if (p->channel == CHANNEL_B)
+ {
+ u2FailStatusByCh[u1ChannelSet[u1ChannelIdx]]= DutyScan_Calibration_Flow(p, DutyScan_Calibration_K_CLK, 0);
+
+ if (gcFinal_K_CLK_delay_cell[p->channel][0] == 8 || gcFinal_K_CLK_delay_cell[p->channel][0] == -8)
+ {
+ u2FailStatusByCh[u1ChannelIdx]= DutyScan_Calibration_Flow(p, DutyScan_Calibration_K_CLK, 1);
+ }
+ }
+ #else
+ u2FailStatusByCh[u1ChannelSet[u1ChannelIdx]]= DutyScan_Calibration_Flow(p, DutyScan_Calibration_K_CLK, 0);
+
+ if (gcFinal_K_CLK_delay_cell[p->channel][0] == 8 || gcFinal_K_CLK_delay_cell[p->channel][0] == -8)
+ {
+ u2FailStatusByCh[u1ChannelIdx]= DutyScan_Calibration_Flow(p, DutyScan_Calibration_K_CLK, 1);
+ }
+ #endif
+
+ u2FailStatusByCh[u1ChannelSet[u1ChannelIdx]]= DutyScan_Calibration_Flow(p, DutyScan_Calibration_K_DQS, 0);
+ use_rev_bit=0;
+
+ if (gcFinal_K_DQS_delay_cell[p->channel][0] == 8 || gcFinal_K_DQS_delay_cell[p->channel][0] == -8 || gcFinal_K_DQS_delay_cell[p->channel][1] == 8 || gcFinal_K_DQS_delay_cell[p->channel][1] == -8)
+ {
+ u2FailStatusByCh[u1ChannelIdx]= DutyScan_Calibration_Flow(p, DutyScan_Calibration_K_DQS, 1);
+ use_rev_bit=1;
+ }
+
+ #if defined(APPLY_DQDQM_DUTY_CALIBRATION)
+ u2FailStatusByCh[u1ChannelSet[u1ChannelIdx]]|= DutyScan_Calibration_Flow(p, DutyScan_Calibration_K_DQM, 0);
+
+ u2FailStatusByCh[u1ChannelSet[u1ChannelIdx]]|= DutyScan_Calibration_Flow(p, DutyScan_Calibration_K_DQ, 0);
+ #endif
+ #if FT_DSIM_USED==0
+ //restore to orignal value
+ DramcRestoreRegisters(p, u4RegBackupAddress, sizeof(u4RegBackupAddress)/sizeof(U32));
+ #endif
+
+ //Set K DQS MCK4X_DLY_EN and MCK4XB_DLY_EN again, this is especially for K DQS because other bit fields need to be restored.
+ DQSDutyScan_SetDqsDelayCell(p, gcFinal_K_DQS_delay_cell[p->channel], use_rev_bit);
+
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANK);
+ vIO32WriteFldAlign(DRAMC_REG_ADDR(DRAMC_REG_RKCFG), 0, RKCFG_TXRANKFIX);
+ }
+ }
+
+ vSetPHY2ChannelMapping(p, u1backup_channel);
+ }
+
+#if !FT_DSIM_USED
+#if defined(YH_SWEEP_IC)
+ YH_Sweep_IC_Print_Result(p);
+ while(1); //stop here
+#endif
+#endif
+ }
+}
+#endif
+
+
+#ifdef ENABLE_MIOCK_JMETER
+/* "picoseconds per delay cell" depends on Vcore only (frequency doesn't matter)
+ * 1. Retrieve current freq's vcore voltage using pmic API
+ * 2. Perform delay cell time calculation (Bypass if shuffle vcore value is the same as before)
+ */
+static void GetVcoreDelayCellTime(DRAMC_CTX_T *p, U8 shuffleIdx)
+{
+ U32 channel_i;
+
+#if __ETT__
+ static U32 u4previousVcore = 0;
+
+#if (FOR_DV_SIMULATION_USED==0 && SW_CHANGE_FOR_SIMULATION==0)
+ u4gVcore[shuffleIdx] = pmic_vcore_voltage_read();
+#endif
+
+ /* delay cell calculation is skipped if vcore is same as previous shuffle's */
+ if (u4gVcore[shuffleIdx] != u4previousVcore)
+ {
+ u4previousVcore = u4gVcore[shuffleIdx];
+ DramcMiockJmeter(p);
+ }
+#else
+ DramcMiockJmeter(p);
+#endif
+
+ for(channel_i=CHANNEL_A; channel_i < p->support_channel_num; channel_i++)
+ {
+ ucg_num_dlycell_perT_all[shuffleIdx][u1ChannelSet[channel_i]] = ucg_num_dlycell_perT;
+ u2gdelay_cell_ps_all[shuffleIdx][u1ChannelSet[channel_i]] = u2gdelay_cell_ps;
+ }
+#if __ETT__
+ mcSHOW_DBG_MSG(("Freq=%d, CH_%d, VCORE=%d, cell=%d\n", p->frequency, p->channel, u4gVcore[shuffleIdx], u2gdelay_cell_ps_all[shuffleIdx][p->channel]));
+#endif
+
+ return;
+}
+
+
+void DramcMiockJmeterHQA(DRAMC_CTX_T *p)
+{
+ //do MiockJitterMeter@DDR2667
+ U8 shuffleIdx;
+
+ mcSHOW_DBG_MSG(("[MiockJmeterHQA]\n"));
+
+ shuffleIdx = get_shuffleIndex_by_Freq(p);
+
+ if (u1IsLP4Family(p->dram_type))
+ {
+ //if(p->channel == CHANNEL_A)
+ {
+ GetVcoreDelayCellTime(p, shuffleIdx);
+ }
+
+ if((p->support_channel_num != CHANNEL_SINGLE) || (u1ChannelSet[0] == CHANNEL_A))
+ u2gdelay_cell_ps_all[shuffleIdx][CHANNEL_B] = u2gdelay_cell_ps_all[shuffleIdx][CHANNEL_A];
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ GetVcoreDelayCellTime(p, shuffleIdx);
+ }
+#endif /* ENABLE_LP3_SW */
+
+#ifdef FOR_HQA_TEST_USED
+ if (ucg_num_dlycell_perT_all[shuffleIdx][p->channel] == 0) GetVcoreDelayCellTimeFromTable(p); //lookup table
+#endif
+
+ /* Use highest freq's delay cell time measurement results as reference */
+ p->ucnum_dlycell_perT = ucg_num_dlycell_perT_all[shuffleIdx][p->channel];
+ p->u2DelayCellTimex100 = u2gdelay_cell_ps_all[shuffleIdx][p->channel];
+ mcSHOW_DBG_MSG3(("DelayCellTimex100 CH_%d, (VCORE=%d, cell=%d)\n",p->channel, u4gVcore[shuffleIdx], p->u2DelayCellTimex100));
+}
+#endif //#ifdef ENABLE_MIOCK_JMETER
+
+void DramcWriteDBIOnOff(DRAMC_CTX_T *p, U8 onoff)
+{
+ // DRAMC Write-DBI On/Off
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldAlign_All(DRAMC_REG_SHU1_WODT, onoff, SHU1_WODT_DBIWR);
+ mcSHOW_DBG_MSG(("DramC Write-DBI %s\n", ((onoff == DBI_ON) ? "on" : "off")));
+ }
+}
+
+void DramcReadDBIOnOff(DRAMC_CTX_T *p, U8 onoff)
+{
+ // DRAMC Read-DBI On/Off
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldAlign_All(DDRPHY_SHU1_B0_DQ7, onoff, SHU1_B0_DQ7_R_DMDQMDBI_SHU_B0);
+ vIO32WriteFldAlign_All(DDRPHY_SHU1_B1_DQ7, onoff, SHU1_B1_DQ7_R_DMDQMDBI_SHU_B1);
+ mcSHOW_DBG_MSG(("DramC Read-DBI %s\n", ((onoff == DBI_ON) ? "on" : "off")));
+ }
+}
+#if ENABLE_READ_DBI
+void SetDramModeRegForReadDBIOnOff(DRAMC_CTX_T *p, U8 onoff)
+{
+ if(u1IsLP4Family(p->dram_type))
+ {
+#if MRW_CHECK_ONLY
+ mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
+#endif
+ //mcSHOW_DBG_MSG(("--Fsp%d --\n", p->dram_fsp));
+
+ //DRAM MR3[6] read-DBI On/Off
+ u1MR03Value[p->dram_fsp] = ((u1MR03Value[p->dram_fsp] & 0xbf) | (onoff<<6));
+ DramcModeRegWriteByRank(p, p->rank, 3, u1MR03Value[p->dram_fsp]);
+ }
+}
+#endif
+
+#if ENABLE_WRITE_DBI || TX_K_DQM_WITH_WDBI
+void DramcWriteMinus1MCKForWriteDBI(DRAMC_CTX_T *p, S8 iShiftUI)
+{
+ //U8 ucdq_ui_large_dqs0, ucdq_ui_large_dqs1;
+ //U8 ucdq_final_dqm_ui_large_dqs0, ucdq_final_dqm_ui_large_dqs1;
+ REG_TRANSFER_T TransferReg[2];
+
+ if((u1IsLP4Family(p->dram_type))&&(p->DBI_W_onoff[p->dram_fsp]))
+ {
+ //ucdq_ui_large_dqs0 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), SHURK0_SELPH_DQ0_TXDLY_DQ0);
+ //ucdq_ui_large_dqs1 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), SHURK0_SELPH_DQ0_TXDLY_DQ1);
+ //mcSHOW_DBG_MSG(("Before -1MCK, ucdq_final_ui_large_dqs0 = %d, ucdq_final_ui_large_dqs1 = %d\n", ucdq_ui_large_dqs0, ucdq_ui_large_dqs1));
+ // DQ0
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_DQ0;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_DQ0;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+
+ // DQ1
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ2;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ2_DLY_DQ1;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ0;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ0_TXDLY_DQ1;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+
+ //ucdq_ui_large_dqs0 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), SHURK0_SELPH_DQ0_TXDLY_DQ0);
+ //ucdq_ui_large_dqs1 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ0), SHURK0_SELPH_DQ0_TXDLY_DQ1);
+ //mcSHOW_DBG_MSG(("After -1MCK, ucdq_final_ui_large_dqs0 = %d, ucdq_final_ui_large_dqs1 = %d\n", ucdq_ui_large_dqs0, ucdq_ui_large_dqs1));
+
+
+ //ucdq_final_dqm_ui_large_dqs0 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), SHURK0_SELPH_DQ1_TXDLY_DQM0);
+ //ucdq_final_dqm_ui_large_dqs1 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), SHURK0_SELPH_DQ1_TXDLY_DQM1);
+ //mcSHOW_DBG_MSG(("Before -1MCK, ucdq_final_dqm_ui_large_dqs0 = %d, ucdq_final_dqm_ui_large_dqs1 = %d\n", ucdq_final_dqm_ui_large_dqs0, ucdq_final_dqm_ui_large_dqs1));
+ // DQM0
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_DQM0;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_DQM0;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+
+ // DQM1
+ TransferReg[0].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ3;
+ TransferReg[0].u4Fld =SHURK0_SELPH_DQ3_DLY_DQM1;
+ TransferReg[1].u4Addr = DRAMC_REG_SHURK0_SELPH_DQ1;
+ TransferReg[1].u4Fld =SHURK0_SELPH_DQ1_TXDLY_DQM1;
+ ExecuteMoveDramCDelay(p, TransferReg, iShiftUI);
+ //ucdq_final_dqm_ui_large_dqs0 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), SHURK0_SELPH_DQ1_TXDLY_DQM0);
+ //ucdq_final_dqm_ui_large_dqs1 = u4IO32ReadFldAlign(DRAMC_REG_ADDR(DRAMC_REG_SHURK0_SELPH_DQ1), SHURK0_SELPH_DQ1_TXDLY_DQM1);
+ //mcSHOW_DBG_MSG(("After -1MCK, ucdq_final_dqm_ui_large_dqs0 = %d, ucdq_final_dqm_ui_large_dqs1 = %d\n", ucdq_final_dqm_ui_large_dqs0, ucdq_final_dqm_ui_large_dqs1));
+ }
+}
+
+void SetDramModeRegForWriteDBIOnOff(DRAMC_CTX_T *p, U8 onoff)
+{
+ if(u1IsLP4Family(p->dram_type))
+ {
+#if MRW_CHECK_ONLY
+ mcSHOW_MRW_MSG(("\n==[MR Dump] %s==\n", __func__));
+#endif
+ //DRAM MR3[7] write-DBI On/Off
+ u1MR03Value[p->dram_fsp] = ((u1MR03Value[p->dram_fsp] & 0x7F) | (onoff<<7));
+ DramcModeRegWriteByRank(p, p->rank, 3, u1MR03Value[p->dram_fsp]);
+ }
+}
+#endif
+
+#if (SW_CHANGE_FOR_SIMULATION || FOR_DV_SIMULATION_USED)
+void vMR2InitForSimulationTest(DRAMC_CTX_T *p)
+{
+ if(u1IsLP4Family(p->dram_type))
+ {
+ // Dram Init will set MR2's value
+ #if 0
+ if(p->frequency >HIGH_FREQ)
+ {
+ u1MR02Value[p->dram_fsp] = 0x3f;
+ }
+ else if(p->frequency <=DUAL_FREQ_LOW_LP4)
+ {
+ u1MR02Value[p->dram_fsp] = 0x1b;
+ }
+ else
+ {
+ u1MR02Value[p->dram_fsp] = 0x2d;
+ }
+ #endif
+ }
+ #if ENABLE_LP3_SW
+ else
+ {
+ #if SUPPORT_LP3_800
+ if(p->frequency<=400)
+ {
+ u1MR02Value[p->dram_fsp] = 0x18;
+ }
+ else
+ #endif
+ if(p->frequency==533)
+ {
+ u1MR02Value[p->dram_fsp] = 0x16;
+ }
+ else if(p->frequency == 635)
+ {
+ u1MR02Value[p->dram_fsp] = 0x18;
+ }
+ else if(p->frequency == 800)
+ {
+ u1MR02Value[p->dram_fsp] = 0x1a;
+ }
+ else
+ {
+ u1MR02Value[p->dram_fsp] = 0x1c;
+ }
+ }
+ #endif
+}
+#endif
+
+#if ENABLE_WRITE_DBI_Protect
+void ApplyWriteDBIProtect(DRAMC_CTX_T *p, U8 onoff)
+{
+ U8 *uiLPDDR_O1_Mapping;
+ U16 Temp_PinMux_MaskWrite_WriteDBIOn=0;
+ U8 B0_PinMux_MaskWrite_WriteDBIOn=0, B1_PinMux_MaskWrite_WriteDBIOn=0;
+ int DQ_index;
+
+ if(u1IsLP4Family(p->dram_type))
+ {
+ uiLPDDR_O1_Mapping = (U8 *)uiLPDDR4_O1_Mapping_POP[p->channel];
+
+ // Write DMI/DBI Protect Function
+ // Byte0 can not have bit swap between Group1(DQ0/1) and Group2(DQ02~DQ07).
+ // Byte1 can not have bit swap between Group1(DQ8/9) and Group2(DQ10~DQ15).
+ // DBIWR_IMP_EN=1 and DBIWR_PINMUX_EN=1
+ // set DBIWR_OPTB0[7:0] meet with Byte0 pin MUX table.
+ // set DBIWR_OPTB1[7:0] meet with Byte1 pin MUX table.
+
+ for(DQ_index=0; DQ_index<16; DQ_index++)
+ {
+ Temp_PinMux_MaskWrite_WriteDBIOn |= ((0x7C7C >> uiLPDDR_O1_Mapping[DQ_index]) & 0x1) << DQ_index;
+ }
+ B1_PinMux_MaskWrite_WriteDBIOn = (U8)(Temp_PinMux_MaskWrite_WriteDBIOn>>8) & 0xff;
+ B0_PinMux_MaskWrite_WriteDBIOn = (U8) Temp_PinMux_MaskWrite_WriteDBIOn & 0xff;
+
+ vIO32WriteFldMulti_All(DRAMC_REG_ARBCTL, P_Fld(B1_PinMux_MaskWrite_WriteDBIOn, ARBCTL_DBIWR_OPT_B1)
+ | P_Fld(B0_PinMux_MaskWrite_WriteDBIOn, ARBCTL_DBIWR_OPT_B0)
+ | P_Fld(onoff, ARBCTL_DBIWR_PINMUX_EN)
+ | P_Fld(onoff, ARBCTL_DBIWR_IMP_EN));
+ }
+}
+#endif
+
+#if ENABLE_WRITE_DBI
+void ApplyWriteDBIPowerImprove(DRAMC_CTX_T *p, U8 onoff)
+{
+ // set DBIWR_IMP_EN = 1
+ // DBIWR_OPTB0[1:0]=0, DBIWR_OPT_B0[7]=0
+ // DBIWR_OPTB1[1:0]=0, DBIWR_OPT_B1[7]=0
+ if(u1IsLP4Family(p->dram_type))
+ {
+ vIO32WriteFldMulti_All(DRAMC_REG_ARBCTL, P_Fld(0, ARBCTL_DBIWR_OPT_bit15)
+ | P_Fld(0, ARBCTL_DBIWR_OPT_bit9_8)
+ | P_Fld(0, ARBCTL_DBIWR_OPT_bit7)
+ | P_Fld(0, ARBCTL_DBIWR_OPT_bit1_0)
+ | P_Fld(onoff, ARBCTL_DBIWR_IMP_EN));
+ }
+}
+#endif
+
+#if SW_CHANGE_FOR_SIMULATION
+void main(void)
+{
+
+ DRAMC_CTX_T DramConfig;
+ DramConfig.channel = CHANNEL_A;
+ DramConfig.support_rank_num = RANK_DUAL;
+ // DramRank
+ DramConfig.rank = RANK_0;
+ // DRAM type
+ DramConfig.dram_type = TYPE_LPDDR4X;
+ // DRAM Fast switch point type, only for LP4, useless in LP3
+ DramConfig.dram_fsp = FSP_0;
+ // DRAM CBT mode, only for LP4, useless in LP3
+ DramConfig.dram_cbt_mode[RANK_0] = CBT_NORMAL_MODE;
+ DramConfig.dram_cbt_mode[RANK_1] = CBT_NORMAL_MODE;
+ // IC and DRAM read DBI
+ DramConfig.DBI_R_onoff[FSP_0] = DBI_OFF; // only for LP4, uesless in LP3
+ #if ENABLE_READ_DBI
+ DramConfig.DBI_R_onoff[FSP_1] = DBI_ON; // only for LP4, uesless in LP3
+ #else
+ DramConfig.DBI_R_onoff[FSP_1] = DBI_OFF; // only for LP4, uesless in LP3
+ #endif
+ // IC and DRAM write DBI
+ DramConfig.DBI_W_onoff[FSP_0] = DBI_OFF; // only for LP4, uesless in LP3
+ #if ENABLE_WRITE_DBI
+ DramConfig.DBI_W_onoff[FSP_1] = DBI_ON; // only for LP4, uesless in LP3
+ #else
+ DramConfig.DBI_W_onoff[FSP_1] = DBI_OFF; // only for LP4, uesless in LP3
+ #endif
+ // bus width
+ DramConfig.data_width = DATA_WIDTH_32BIT;
+ // DRAMC internal test engine-2 parameters in calibration
+ DramConfig.test2_1 = DEFAULT_TEST2_1_CAL;
+ DramConfig.test2_2 = DEFAULT_TEST2_2_CAL;
+ // DRAMC test pattern in calibration
+ DramConfig.test_pattern = TEST_XTALK_PATTERN;
+ // DRAMC operation clock frequency in MHz
+ DramConfig.frequency = 800;
+
+ DramConfig.enable_rx_scan_vref =DISABLE_VREF_SCAN;
+ DramConfig.enable_tx_scan_vref =DISABLE_VREF_SCAN;
+ //DramConfig.dynamicODT = DISABLE;
+
+ MPLLInit();
+
+ Global_Option_Init(&DramConfig);
+ Global_Option_Init2(&DramConfig);
+
+ // DramC & PHY init for all channels
+ DDRPhyFreqSel(&DramConfig, LP4_DDR1600);
+
+
+#if WRITE_LEVELING_MOVE_DQS_INSTEAD_OF_CLK
+ memset(DramConfig.arfgWriteLevelingInitShif, FALSE, sizeof(DramConfig.arfgWriteLevelingInitShif));
+ //>fgWriteLevelingInitShif= FALSE;
+#endif
+#if TX_PERBIT_INIT_FLOW_CONTROL
+ memset(DramConfig.fgTXPerbifInit, FALSE, sizeof(DramConfig.fgTXPerbifInit));
+#endif
+
+ DramcInit(&DramConfig);
+
+ vApplyConfigBeforeCalibration(&DramConfig);
+ vMR2InitForSimulationTest(&DramConfig);
+
+ vSetPHY2ChannelMapping(&DramConfig, DramConfig.channel);
+
+ #if SIMULATION_SW_IMPED
+ if (u1IsLP4Family(DramConfig.dram_type))
+ {
+ DramcSwImpedanceCal(&DramConfig,1, 1); //within term
+ DramcSwImpedanceCal(&DramConfig,1, 0); //without term
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ DramcSwImpedanceCal(&DramConfig,1, 1); //within term
+ }
+#endif /* ENABLE_LP3_SW */
+ #endif
+
+
+#if SIMULATION_LP4_ZQ
+ if (DramConfig.dram_type == TYPE_LPDDR4 || DramConfig.dram_type == TYPE_LPDDR4X || DramConfig.dram_type == TYPE_LPDDR4P)
+ {
+ DramcZQCalibration(&DramConfig);
+ }
+#endif
+
+ if (u1IsLP4Family(DramConfig.dram_type))
+ {
+ #if SIMUILATION_LP4_CBT
+ CmdBusTrainingLP4(&DramConfig);
+ #endif
+ }
+#if ENABLE_LP3_SW
+ else
+ {
+ #if SIMULATION_LP3_CA_TRAINING
+ vSetRank(DramConfig, RANK_0);
+ CATrainingLP3(&DramConfig);
+ #endif
+ }
+#endif /* ENABLE_LP3_SW */
+
+#if SIMULATION_WRITE_LEVELING
+ DramcWriteLeveling(&DramConfig);
+#endif
+
+ #if SIMULATION_GATING
+ // Gating calibration of single rank
+ DramcRxdqsGatingCal(&DramConfig);
+
+ // Gating calibration of both rank
+ //DualRankDramcRxdqsGatingCal(&DramConfig);
+ #endif
+
+#if SIMUILATION_LP4_RDDQC
+ DramcRxWindowPerbitCal(&DramConfig, 0);
+#endif
+
+ #if SIMULATION_DATLAT
+ // RX Datlat calibration of single rank
+ DramcRxdatlatCal(&DramConfig);
+
+ // RX Datlat calibration of two rank
+ //DramcDualRankRxdatlatCal(&DramConfig);
+ #endif
+
+ #if SIMULATION_RX_PERBIT
+ DramcRxWindowPerbitCal(&DramConfig, 1);
+ #endif
+
+ #if SIMULATION_TX_PERBIT
+ DramcTxWindowPerbitCal(&DramConfig, TX_DQ_DQS_MOVE_DQ_DQM);
+ DramcTxWindowPerbitCal(&DramConfig, TX_DQ_DQS_MOVE_DQ_ONLY);
+ #endif
+
+ #if ENABLE_READ_DBI
+ //Read DBI ON
+ SetDramModeRegForReadDBIOnOff(&DramConfig, DramConfig.DBI_R_onoff[DramConfig.dram_fsp]);
+ #endif
+
+ #if ENABLE_WRITE_DBI
+ //Write DBI ON
+ DramcWriteMinus1MCKForWriteDBI(&DramConfig, -8); //Tx DQ/DQM -1 MCK for write DBI ON
+ SetDramModeRegForWriteDBIOnOff(&DramConfig, DramConfig.DBI_W_onoff[DramConfig.dram_fsp]);
+ #endif
+
+ #if ENABLE_READ_DBI
+ DramcReadDBIOnOff(&DramConfig, DramConfig.DBI_R_onoff[DramConfig.dram_fsp]);
+ #endif
+
+ #if ENABLE_WRITE_DBI
+ DramcWriteDBIOnOff(&DramConfig, DramConfig.DBI_W_onoff[DramConfig.dram_fsp]);
+ #endif
+}
+#endif //SW_CHANGE_FOR_SIMULATION
+