| /*----------------------------------------------------------------------------* |
| * 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 |
| |