diff options
author | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
---|---|---|
committer | raywu <raywu0301@gmail.com> | 2018-06-15 00:00:50 +0800 |
commit | b7c51c9cf4864df6aabb99a1ae843becd577237c (patch) | |
tree | eebe9b0d0ca03062955223097e57da84dd618b9a /ReferenceCode/Chipset/SystemAgent/MemoryInit/Pei/Source/McConfiguration/MrcTimingConfiguration.c | |
download | zprj-master.tar.xz |
Diffstat (limited to 'ReferenceCode/Chipset/SystemAgent/MemoryInit/Pei/Source/McConfiguration/MrcTimingConfiguration.c')
-rw-r--r-- | ReferenceCode/Chipset/SystemAgent/MemoryInit/Pei/Source/McConfiguration/MrcTimingConfiguration.c | 921 |
1 files changed, 921 insertions, 0 deletions
diff --git a/ReferenceCode/Chipset/SystemAgent/MemoryInit/Pei/Source/McConfiguration/MrcTimingConfiguration.c b/ReferenceCode/Chipset/SystemAgent/MemoryInit/Pei/Source/McConfiguration/MrcTimingConfiguration.c new file mode 100644 index 0000000..8f98dd2 --- /dev/null +++ b/ReferenceCode/Chipset/SystemAgent/MemoryInit/Pei/Source/McConfiguration/MrcTimingConfiguration.c @@ -0,0 +1,921 @@ +/** @file + This module configures the memory controller timing parameters. + +@copyright + Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and uniquely + identified as "Intel Reference Module" and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement. + +**/ +#include "MrcTimingConfiguration.h" + +/** +@brief + This function returns the tCKE value for the specified frequency. + + @param[in] DdrType - DDR type + @param[in] Frequency - The memory frequency. + + @retval The tCKE value for the specified frequency. +**/ +static +U32 +tCKEValue ( + IN MrcDdrType DdrType, + IN const MrcFrequency Frequency + ) +{ + U32 tCKE; + +#if (SUPPORT_LPDDR3 == SUPPORT) + if (DdrType == MRC_DDR_TYPE_LPDDR3) { + if (Frequency <= f1067) { + tCKE = tCKE_LPDDR_1067; + } else if (Frequency <= f1333) { + tCKE = tCKE_LPDDR_1333; + } else { + tCKE = tCKE_LPDDR_1600; + } + return tCKE; + } +#endif // SUPPORT_LPDDR3 + + if (Frequency <= f800) { + tCKE = TCKE_800; + } else if (Frequency <= f1067) { + tCKE = TCKE_1067; + } else if (Frequency <= f1333) { + tCKE = TCKE_1333; + } else if (Frequency <= f1600) { + tCKE = TCKE_1600; + } else if (Frequency <= f1867) { + tCKE = TCKE_1867; + } else if (Frequency <= f2133) { + tCKE = TCKE_2133; + } else if (Frequency <= f2400) { + tCKE = TCKE_2400; + } else { + tCKE = TCKE_2667; + } + + return tCKE; +} + +/** +@brief + This function returns the tXPDLL value for the specified frequency. + + @param[in] Frequency - The memory frequency. + + @retval The tXPDLL value for the specified frequency. +**/ +static +U32 +tXPDLLValue ( + IN const MrcFrequency Frequency + ) +{ + U32 tXPDLL; + + if (Frequency <= f800) { + tXPDLL = TXPDLL_800; + } else if (Frequency <= f1067) { + tXPDLL = TXPDLL_1067; + } else if (Frequency <= f1333) { + tXPDLL = TXPDLL_1333; + } else if (Frequency <= f1600) { + tXPDLL = TXPDLL_1600; + } else if (Frequency <= f1867) { + tXPDLL = TXPDLL_1867; + } else if (Frequency <= f2133) { + tXPDLL = TXPDLL_2133; + } else if (Frequency <= f2400) { + tXPDLL = TXPDLL_2400; + } else { + tXPDLL = TXPDLL_2667; + } + + return tXPDLL; +} + +/** +@brief + This function returns the tXP value for the specified frequency. + + @param[in] DdrType - DDR type + @param[in] Frequency - The memory frequency. + @param[in] NMode - Command mode to lookup. + + @retval The tXP value for the specified frequency. +**/ +U32 +tXPValue ( + IN MrcDdrType DdrType, + IN const MrcFrequency Frequency, + IN U8 NMode + ) +{ + U32 tXP; + +#if (SUPPORT_LPDDR3 == SUPPORT) + if (DdrType == MRC_DDR_TYPE_LPDDR3) { + if (Frequency <= f1333) { + tXP = tXP_LPDDR_1333; + } else { + tXP = tXP_LPDDR_1600; + } + } else +#endif // SUPPORT_LPDDR3 + { + if (Frequency <= f1600) { + tXP = ((MC_tXP_1600_1N - 1) + NMode); + } else if (Frequency <= f1867) { + tXP = ((NMode <= 2) ? MC_tXP_1867_2N : MC_tXP_1867_3N); + } else if (Frequency <= f2133) { + tXP = (MC_tXP_2133_1N); + } else { + tXP = MC_tXP_MAX; + } + } + return (tXP); +} + +/** +@brief + This function returns the tAONPD value for the specified frequency. + + @param[in] Frequency - The memory frequency. + + @retval The tAONPD value for the specified frequency. +**/ +static +U32 +tAONPDValue ( + IN const MrcFrequency Frequency + ) +{ + U32 tAONPD; + + if (Frequency <= f800) { + tAONPD = TAONPD_800; + } else if (Frequency <= f1067) { + tAONPD = TAONPD_1067; + } else if (Frequency <= f1333) { + tAONPD = TAONPD_1333; + } else if (Frequency <= f1600) { + tAONPD = TAONPD_1600; + } else if (Frequency <= f1867) { + tAONPD = TAONPD_1867; + } else if (Frequency <= f2133) { + tAONPD = TAONPD_2133; + } else if (Frequency <= f2400) { + tAONPD = TAONPD_2400; + } else { + tAONPD = TAONPD_2667; + } + + return tAONPD; +} + +/** +@brief + This function sets up the TC-BANK register, + which includes the tRCD, tRP, tRAS, tRDPRE, tRTP, tWRPRE, and tRRD values. + + @param[in, out] MrcData - Include all MRC global data. + @param[in] Channel - Channel select. + + @retval Nothing. +**/ +static +void +SetTcBankReg ( + IN OUT MrcParameters *const MrcData, + IN const U32 Channel + ) +{ + const MrcInput *Inputs; + const MrcDebug *Debug; + MrcOutput *Outputs; + MrcChannelOut *ChannelOut; + MrcTiming *Timing; + MCHBAR_CH0_CR_TC_BANK_STRUCT CrTcBank; + U32 tWRPRE; + + Inputs = &MrcData->SysIn.Inputs; + Debug = &Inputs->Debug; + Outputs = &MrcData->SysOut.Outputs; + ChannelOut = &Outputs->Controller[0].Channel[Channel]; + Timing = &ChannelOut->Timing[Inputs->MemoryProfile]; + + // + // tWRPRE is = 4tCK + tWR + tWL = 4DCLK + tWR + tWL + // + tWRPRE = 4 + Timing->tCWL + Timing->tWR; + + CrTcBank.Data = 0; + CrTcBank.Bits.tRCD = MIN (MCHBAR_CH0_CR_TC_BANK_tRCD_MAX, Timing->tRCD); + CrTcBank.Bits.tRP = MIN (MCHBAR_CH0_CR_TC_BANK_tRP_MAX, Timing->tRP); + CrTcBank.Bits.tRAS = MIN (MCHBAR_CH0_CR_TC_BANK_tRAS_MAX, Timing->tRAS); + CrTcBank.Bits.tRDPRE = MIN (MCHBAR_CH0_CR_TC_BANK_tRDPRE_MAX, Timing->tRTP); + CrTcBank.Bits.tWRPRE = MIN (MCHBAR_CH0_CR_TC_BANK_tWRPRE_MAX, tWRPRE); + CrTcBank.Bits.tRRD = MIN (MCHBAR_CH0_CR_TC_BANK_tRRD_MAX, Timing->tRRD); +#ifdef ULT_FLAG + if (Outputs->DdrType == MRC_DDR_TYPE_LPDDR3) { + CrTcBank.Bits.tRPab_ext = MIN (MCHBAR_CH0_CR_TC_BANK_tRPab_ext_MAX, Timing->tRPab - Timing->tRP); + } +#endif + MrcWriteCR ( + MrcData, + MCHBAR_CH0_CR_TC_BANK_REG + ((MCHBAR_CH1_CR_TC_BANK_REG - MCHBAR_CH0_CR_TC_BANK_REG) * Channel), + CrTcBank.Data + ); + + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, "Channel %u:\n tRCD = %u\n", Channel, CrTcBank.Bits.tRCD); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tRP = %u\n", CrTcBank.Bits.tRP); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tRAS = %u\n", CrTcBank.Bits.tRAS); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tRDPRE = %u\n", CrTcBank.Bits.tRDPRE); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tWRPRE = %u\n", CrTcBank.Bits.tWRPRE); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tRRD = %u\n", CrTcBank.Bits.tRRD); +#ifdef ULT_FLAG + if (Outputs->DdrType == MRC_DDR_TYPE_LPDDR3) { + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tRPab_ext = %u\n", CrTcBank.Bits.tRPab_ext); + } +#endif + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " TC_BANK = %Xh\n", CrTcBank.Data); + + // + // Save in MrcData structure + // + ChannelOut->MchbarBANK = CrTcBank.Data; + + return; +} + +/** +@brief + This function sets up the TC_BANK_RANK_D register, + which includes the tCL and tWCL values. + + @param[in, out] MrcData - Include all MRC global data. + @param[in] Channel - Channel select. + + @retval Nothing. +**/ +static +void +SetTcBankRankDReg ( + IN OUT MrcParameters *const MrcData, + IN const U32 Channel + ) +{ + const MrcInput *Inputs; + const MrcDebug *Debug; + MrcOutput *Outputs; + MrcChannelOut *ChannelOut; + MrcTiming *Timing; + MCHBAR_CH0_CR_TC_BANK_RANK_D_STRUCT TcBankRankD; + U32 OdtReadDelay; +#ifdef ULT_FLAG + U32 OdtWriteDelay; + U32 OdtWriteDuration; + U32 DclkPs; +#endif // ULT_FLAG + + Inputs = &MrcData->SysIn.Inputs; + Outputs = &MrcData->SysOut.Outputs; + Debug = &Inputs->Debug; + ChannelOut = &MrcData->SysOut.Outputs.Controller[0].Channel[Channel]; + Timing = &ChannelOut->Timing[Inputs->MemoryProfile]; + + // + // @todo: Need to make sure this value, after power on, follows the restrictions in the XML description. + // + OdtReadDelay = Timing->tCL - Timing->tCWL; + + TcBankRankD.Data = 0; + TcBankRankD.Bits.tWCL = MIN (MCHBAR_CH0_CR_TC_BANK_RANK_D_tWCL_MAX, Timing->tCWL); + TcBankRankD.Bits.tCL = MIN (MCHBAR_CH0_CR_TC_BANK_RANK_D_tCL_MAX, Timing->tCL); + TcBankRankD.Bits.tCPDED = MCHBAR_CH0_CR_TC_BANK_RANK_D_tCPDED_DEF; + TcBankRankD.Bits.tPRPDEN = MCHBAR_CH0_CR_TC_BANK_RANK_D_tPRPDEN_DEF; + TcBankRankD.Bits.Odt_Read_Delay = MIN (MCHBAR_CH0_CR_TC_BANK_RANK_D_Odt_Read_Delay_MAX, OdtReadDelay); + +#ifdef ULT_FLAG + if (Outputs->DdrType == MRC_DDR_TYPE_LPDDR3) { + if (Inputs->LpddrDramOdt) { + // + // Only ODT[0] is used in ULT, need to use it for both ranks + // + TcBankRankD.UltBits.Odt_Always_Rank0 = 1; + } + + // + // Timing->tCWL has 1 extra clock because of tDQSS - subtract it here. + // + TcBankRankD.Bits.tWCL--; + + // + // JEDEC Spec requires tCPDED should be 2 clocks for all LPDDR3 frequencies + // + TcBankRankD.Bits.tCPDED = 2; + + DclkPs = Outputs->Qclkps * 2; + + // + // Odt_Write_Delay = WL - 1 - RU(tODTon(max)) + // + OdtWriteDelay = Timing->tCWL - 1 - (tODT_ON_MAX + DclkPs - 1) / DclkPs; + + // + // Odt_Write_Duration = 6 + RU(tODTon(max)-tODToff(min)) - 6 + 1 + // + OdtWriteDuration = 1 + (tODT_ON_MAX - tODT_OFF_MIN + DclkPs - 1) / DclkPs; + + TcBankRankD.UltBits.Odt_Write_Delay = MIN (MCHBAR_CH0_CR_TC_BANK_RANK_D_Odt_Write_Delay_Ult_MAX, OdtWriteDelay); + TcBankRankD.UltBits.Odt_Write_Duration = MIN (MCHBAR_CH0_CR_TC_BANK_RANK_D_Odt_Write_Duration_Ult_MAX, OdtWriteDuration); + } +#endif // ULT_FLAG + + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, "Channel %u:\n tCL = %u\n", Channel, TcBankRankD.Bits.tCL); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tWCL = %u\n", TcBankRankD.Bits.tWCL); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tCPDED = %u\n", TcBankRankD.Bits.tCPDED); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tPRPDEN = %u\n", TcBankRankD.Bits.tPRPDEN); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " Odt_Read_Delay = %u\n", TcBankRankD.Bits.Odt_Read_Delay); +#ifdef ULT_FLAG + if (Outputs->DdrType == MRC_DDR_TYPE_LPDDR3) { + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " Odt_Write_Delay = %u\n", TcBankRankD.UltBits.Odt_Write_Delay); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " Odt_Write_Duration = %u\n", TcBankRankD.UltBits.Odt_Write_Duration); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " Odt_Always_Rank0 = %u\n", TcBankRankD.UltBits.Odt_Always_Rank0); + } +#endif // ULT_FLAG + + MrcWriteCR ( + MrcData, + MCHBAR_CH0_CR_TC_BANK_RANK_D_REG + ((MCHBAR_CH1_CR_TC_BANK_RANK_D_REG - MCHBAR_CH0_CR_TC_BANK_RANK_D_REG) * Channel), + TcBankRankD.Data + ); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " TC_BANK_RANK_D = %Xh\n", TcBankRankD.Data); + + // + // Save in MrcData structure + // + ChannelOut->MchbarBANKRANKD = TcBankRankD.Data; + + return; +} + +/** +@brief + This function sets up the TC_BANK_RANK_A register. + which includes the tCKE, tFAW, tRDRD, tRDRD_dr, tRDRD_dd, tRDPDEN, and command rate mode. + + @param[in, out] MrcData - Include all MRC global data. + @param[in] Channel - Channel select. + + @retval Nothing. +**/ +static +void +SetTcBankRankAReg ( + IN OUT MrcParameters *const MrcData, + IN const U32 Channel + ) +{ + const MrcInput *Inputs; + const MrcDebug *Debug; + MrcOutput *Outputs; + MrcTiming *Timing; + MrcDdrType DdrType; + MCHBAR_CH0_CR_TC_BANK_RANK_A_STRUCT TcBankRankA; + U32 CRValue; + + Inputs = &MrcData->SysIn.Inputs; + Debug = &Inputs->Debug; + Outputs = &MrcData->SysOut.Outputs; + Timing = &Outputs->Controller[0].Channel[Channel].Timing[Inputs->MemoryProfile]; + DdrType = Outputs->DdrType; + TcBankRankA.Data = 0; + + // + // Get the tCKE value. + // + CRValue = tCKEValue (DdrType, Outputs->Frequency); + TcBankRankA.Bits.tCKE = MIN (MCHBAR_CH1_CR_TC_BANK_RANK_A_tCKE_MAX, CRValue); + + // + // Get the command rate mode value. + // Use 3N mode during training steps + // +#ifdef ULT_FLAG + if (Outputs->DdrType == MRC_DDR_TYPE_LPDDR3) { + // + // Need to use 1N mode for LPDDR + // + TcBankRankA.Bits.CMD_stretch = 0; + } else +#endif // ULT_FLAG + { + TcBankRankA.Bits.CMD_stretch = MIN (MCHBAR_CH1_CR_TC_BANK_RANK_A_CMD_stretch_MAX, 3); + } + // + // Program tFAW value + // + TcBankRankA.Bits.tFAW = MIN (MCHBAR_CH1_CR_TC_BANK_RANK_A_tFAW_MAX, Timing->tFAW); + + // + // Calculate tRDRD + // + TcBankRankA.Bits.tRDRD = MIN (MCHBAR_CH1_CR_TC_BANK_RANK_A_tRDRD_MAX, TCCD_ALL_FREQ); + + // + // Calculate tRDRD_dr = BL/2 + max(tRTR, ODT(R,R,DR)) + tRPRE + // + CRValue = 4 + 1 + TRPRE_ALL_FREQ; + +#ifdef ULT_FLAG + if (Outputs->DdrType == MRC_DDR_TYPE_LPDDR3) { + // + // Increase tRDRD_dr from 6 to 7 DCLKs on LPDDR3 + // + CRValue++; + } +#endif // ULT_FLAG + + TcBankRankA.Bits.tRDRD_dr = MIN (MCHBAR_CH1_CR_TC_BANK_RANK_A_tRDRD_dr_MAX, CRValue); + + // + // Calculate tRDRD_dd = BL/2 + max(tRTR, ODT(R,R,DD)) + tRPRE + // + TcBankRankA.Bits.tRDRD_dd = MIN (MCHBAR_CH1_CR_TC_BANK_RANK_A_tRDRD_dd_MAX, CRValue); + + // + // Calculate tRDPDEN = tCL + BL/2 +1 + // + CRValue = Timing->tCL + 5; + TcBankRankA.Bits.tRDPDEN = MIN (MCHBAR_CH1_CR_TC_BANK_RANK_A_tRDPDEN_MAX, CRValue); + + // + // Disable command tri state before training. + // + TcBankRankA.Bits.CMD_3st = 1; + + MrcWriteCR ( + MrcData, + MCHBAR_CH0_CR_TC_BANK_RANK_A_REG + ((MCHBAR_CH1_CR_TC_BANK_RANK_A_REG - MCHBAR_CH0_CR_TC_BANK_RANK_A_REG) * Channel), + TcBankRankA.Data + ); + + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, "Channel %u:\n tCKE = %u\n", Channel, TcBankRankA.Bits.tCKE); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " NMode = %u\n", TcBankRankA.Bits.CMD_stretch); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tFAW = %u\n", TcBankRankA.Bits.tFAW); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tRDRD = %u\n", TcBankRankA.Bits.tRDRD); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tRDRD_dr = %u\n", TcBankRankA.Bits.tRDRD_dr); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tRDRD_dd = %u\n", TcBankRankA.Bits.tRDRD_dd); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tRDPDEN = %u\n", TcBankRankA.Bits.tRDPDEN); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " CMD_3st = %u\n", TcBankRankA.Bits.CMD_3st); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " TC_BANK_RANK_A = %Xh\n", TcBankRankA.Data); + + // + // Save in MrcData structure + // + Outputs->Controller[0].Channel[Channel].MchbarBANKRANKA = TcBankRankA.Data; + + return; +} + +/** +@brief + This function sets up the TC_BANK_RANK_B register, which includes + Dec_WRD, tWRPDEN, tWRWR_dd, tWRWR_dr, tWRWR, tWRRD_dd, tWRRD_dr and tWRRD. + + @param[in, out] MrcData - Include all MRC global data. + @param[in] Channel - Channel select. + + @retval Nothing. +**/ +static +void +SetTcBankRankBReg ( + IN OUT MrcParameters *const MrcData, + IN const U32 Channel + ) +{ + const MrcInput *Inputs; + const MrcDebug *Debug; + MrcOutput *Outputs; + MrcTiming *Timing; + MCHBAR_CH0_CR_TC_BANK_RANK_B_STRUCT TcBankRankB; + MCHBAR_CH0_CR_TC_BANK_RANK_D_STRUCT TcBankRankD; + MCHBAR_CH0_CR_SC_WR_ADD_DELAY_STRUCT ScWrAddDelay; + U32 CRValue; + U32 tWRRD_dr; + U32 tWRWR_dr; + U32 Offset; + + Inputs = &MrcData->SysIn.Inputs; + Debug = &Inputs->Debug; + Outputs = &MrcData->SysOut.Outputs; + Timing = &Outputs->Controller[0].Channel[Channel].Timing[Inputs->MemoryProfile]; + TcBankRankB.Data = 0; + + // + // Calculate tWRRD = tCCD + tCWL + tWTR + max(tWrCAS2RdCAS_sr,ODT(W,R,SR)). + // + CRValue = TCCD_ALL_FREQ + Timing->tCWL + Timing->tWTR + 2; + TcBankRankB.Bits.tWRRD = MIN (MCHBAR_CH0_CR_TC_BANK_RANK_B_tWRRD_MAX, CRValue); + + // + // Calculate tWRRD_dr = tCWL-tCL + BL/2 + max(tWRDRDD,ODT(W,R,DR)) + tRPRE + // + tWRRD_dr = Timing->tCWL - Timing->tCL + 4 + 2 + TRPRE_ALL_FREQ; + +#ifdef ULT_FLAG + if (Outputs->DdrType == MRC_DDR_TYPE_LPDDR3) { + // + // tWRRD_dr is 8 for all LPDDR bins + // + tWRRD_dr = 8; + } +#endif // ULT_FLAG + + TcBankRankB.Bits.tWRRD_dr = MIN (MCHBAR_CH0_CR_TC_BANK_RANK_B_tWRRD_dr_MAX, tWRRD_dr); + + // + // Calculate tWRRD_dd = tCWL-tCL + BL/2 + max(tWRDRDD,ODT(W,R,DR)) + tRPRE + // + TcBankRankB.Bits.tWRRD_dd = MIN (MCHBAR_CH0_CR_TC_BANK_RANK_B_tWRRD_dd_MAX, tWRRD_dr); + + // + // Calculate tWRWR + // + TcBankRankB.Bits.tWRWR = MIN (MCHBAR_CH0_CR_TC_BANK_RANK_B_tWRWR_MAX, TCCD_ALL_FREQ); + + // + // Calculate tWRWR_dr = BL/2 + max(tWWDR,ODT(W,W,DR)) + tWPRE + // + tWRWR_dr = 4 + 2 + TWPRE_ALL_FREQ; + TcBankRankB.Bits.tWRWR_dr = MIN (MCHBAR_CH0_CR_TC_BANK_RANK_B_tWRWR_dr_MAX, tWRWR_dr); + + // + // Calculate tWRWR_dd = BL/2 + max(tWWDD,ODT(W,W,DR)) + tWPRE + // + TcBankRankB.Bits.tWRWR_dd = MIN (MCHBAR_CH0_CR_TC_BANK_RANK_B_tWRWR_dd_MAX, tWRWR_dr); + + // + // Calculate tWRPDEN = tWR+tWL+BL/2 + // + CRValue = Timing->tWR + Timing->tCWL + 4; + TcBankRankB.Bits.tWRPDEN = MIN (MCHBAR_CH0_CR_TC_BANK_RANK_B_tWRPDEN_MAX, CRValue); + + // + // Set Dec_WRD. + // Can be set to 1 only if tWCL is 6 or more. + // + Offset = MCHBAR_CH0_CR_TC_BANK_RANK_D_REG + + (MCHBAR_CH1_CR_TC_BANK_RANK_D_REG - MCHBAR_CH0_CR_TC_BANK_RANK_D_REG) * Channel; + TcBankRankD.Data = MrcReadCR (MrcData, Offset); + if (TcBankRankD.Bits.tWCL >= 6) { + TcBankRankB.Bits.Dec_WRD = 1; + } else { + TcBankRankB.Bits.Dec_WRD = 0; + } + + MrcWriteCR ( + MrcData, + MCHBAR_CH0_CR_TC_BANK_RANK_B_REG + ((MCHBAR_CH1_CR_TC_BANK_RANK_B_REG - MCHBAR_CH0_CR_TC_BANK_RANK_B_REG) * Channel), + TcBankRankB.Data + ); + + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, "Channel %u:\n tWRRD = %u\n", Channel, TcBankRankB.Bits.tWRRD); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tWRRD_dr = %u\n", TcBankRankB.Bits.tWRRD_dr); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tWRRD_dd = %u\n", TcBankRankB.Bits.tWRRD_dd); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tWRWR = %u\n", TcBankRankB.Bits.tWRWR); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tWRWR_dr = %u\n", TcBankRankB.Bits.tWRWR_dr); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tWRWR_dd = %u\n", TcBankRankB.Bits.tWRWR_dd); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tWRPDEN = %u\n", TcBankRankB.Bits.tWRPDEN); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " Dec_WRD = %u\n", TcBankRankB.Bits.Dec_WRD); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " TC_BANK_RANK_B = %Xh\n", TcBankRankB.Data); + + // + // Save in MrcData structure + // + Outputs->Controller[0].Channel[Channel].MchbarBANKRANKB = TcBankRankB.Data; + + // + // Set sc_wr_add_delay accordingly = 1 + Dec_WRD + // + CRValue = TcBankRankB.Bits.Dec_WRD + 1; + ScWrAddDelay.Data = 0; + ScWrAddDelay.Bits.D1R1 = MIN (MCHBAR_CH0_CR_SC_WR_ADD_DELAY_D1R1_MAX, CRValue); + ScWrAddDelay.Bits.D1R0 = MIN (MCHBAR_CH0_CR_SC_WR_ADD_DELAY_D1R0_MAX, CRValue); + ScWrAddDelay.Bits.D0R1 = MIN (MCHBAR_CH0_CR_SC_WR_ADD_DELAY_D0R1_MAX, CRValue); + ScWrAddDelay.Bits.D0R0 = MIN (MCHBAR_CH0_CR_SC_WR_ADD_DELAY_D0R0_MAX, CRValue); + MrcWriteCR8 ( + MrcData, + MCHBAR_CH0_CR_SC_WR_ADD_DELAY_REG + + ((MCHBAR_CH1_CR_SC_WR_ADD_DELAY_REG - MCHBAR_CH0_CR_SC_WR_ADD_DELAY_REG) * Channel), + (U8) ScWrAddDelay.Data + ); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " SC_WR_ADD_Delay = %Xh\n", ScWrAddDelay.Data); + + return; +} + +/** +@brief + This function sets up the TC_BANK_RANK_C register, which includes + TAONPD, tXP, tXPDLL, tRDWR, tRDWR_dr, and tRDWR_dd. + + @param[in, out] MrcData - Include all MRC global data. + @param[in] Channel - Channel select. + + @retval Nothing. +**/ +static +void +SetTcBankRankCReg ( + IN OUT MrcParameters *const MrcData, + IN const U32 Channel + ) +{ + const MrcInput *Inputs; + const MrcDebug *Debug; + MrcOutput *Outputs; + MrcTiming *Timing; + MrcDdrType DdrType; + MCHBAR_CH0_CR_TC_BANK_RANK_C_STRUCT TcBankRankC; + U32 Value; + U32 DclkPs; + + Inputs = &MrcData->SysIn.Inputs; + Debug = &Inputs->Debug; + Outputs = &MrcData->SysOut.Outputs; + Timing = &Outputs->Controller[0].Channel[Channel].Timing[Inputs->MemoryProfile]; + DdrType = Outputs->DdrType; + TcBankRankC.Data = 0; + + Value = tXPDLLValue (Outputs->Frequency); + TcBankRankC.Bits.tXPDLL = MIN (MCHBAR_CH0_CR_TC_BANK_RANK_C_tXPDLL_MAX, Value); + + Value = tXPValue (DdrType, Outputs->Frequency, 3); + TcBankRankC.Bits.tXP = MIN (MCHBAR_CH0_CR_TC_BANK_RANK_C_tXP_MAX, Value); + + Value = tAONPDValue (Outputs->Frequency); + TcBankRankC.Bits.TAONPD = MIN (MCHBAR_CH0_CR_TC_BANK_RANK_C_TAONPD_MAX, Value); + + // + // Calculate tRDWR = tCL-tCWL+tCCD+tWPRE+max(tRWSR,ODT(R,W,SR)) + // tWPRE - Write Preamble + // + Value = Timing->tCL - Timing->tCWL + TCCD_ALL_FREQ + TWPRE_ALL_FREQ + 2; + // + // Add 1 for frequencies above 1333. + // + if (Outputs->Frequency > f1333) { + Value++; + } + + DclkPs = Outputs->Qclkps * 2; + +#ifdef ULT_FLAG + if (DdrType == MRC_DDR_TYPE_LPDDR3) { + // + // tRDWR = tCL - tCWL + tDQSCK_max + tCCD + tWPRE + ElectricalTurnaround + // + Value = Timing->tCL - Timing->tCWL + (tDQSCK_MAX + DclkPs - 1) / DclkPs + + TCCD_ALL_FREQ + TWPRE_ALL_FREQ + 1; + } +#endif // ULT_FLAG + + TcBankRankC.Bits.tRDWR = MIN (MCHBAR_CH0_CR_TC_BANK_RANK_C_tRDWR_MAX, Value); + + // + // Calculate tRDWR_dr = tCL-tCWL+tCCD+tWPRE+max(tRWSR,ODT(R,W,SR)) + // + TcBankRankC.Bits.tRDWR_dr = MIN (MCHBAR_CH0_CR_TC_BANK_RANK_C_tRDWR_dr_MAX, Value); + + // + // Calculate tRDWR_dd = tCL-tCWL+tCCD+tWPRE+max(tRWSR,ODT(R,W,SR)) + // + TcBankRankC.Bits.tRDWR_dd = MIN (MCHBAR_CH0_CR_TC_BANK_RANK_C_tRDWR_dd_MAX, Value); + + MrcWriteCR ( + MrcData, + MCHBAR_CH0_CR_TC_BANK_RANK_C_REG + ((MCHBAR_CH1_CR_TC_BANK_RANK_C_REG - MCHBAR_CH0_CR_TC_BANK_RANK_C_REG) * Channel), + TcBankRankC.Data + ); + + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, "Channel %u:\n tXPDLL = %u\n", Channel, TcBankRankC.Bits.tXPDLL); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tXP = %u\n", TcBankRankC.Bits.tXP); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tAONPD = %u\n", TcBankRankC.Bits.TAONPD); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tRDWR = %u\n", TcBankRankC.Bits.tRDWR); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tRDWR_dr = %u\n", TcBankRankC.Bits.tRDWR_dr); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " tRDWR_dd = %u\n", TcBankRankC.Bits.tRDWR_dd); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, " TC_BANK_RANK_C = %Xh\n", TcBankRankC.Data); + + // + // Save in MrcData structure + // + Outputs->Controller[0].Channel[Channel].MchbarBANKRANKC = TcBankRankC.Data; + + return; +} + +/** +@brief + This function configures the memory controller timings. + + @param[in] MrcData - Include all MRC global data. + + @retval Nothing. +**/ +void +MrcTimingConfiguration ( + IN MrcParameters *const MrcData + ) +{ + U8 Channel; + + for (Channel = 0; Channel < MAX_CHANNEL; Channel++) { + if (MrcChannelExist (&MrcData->SysOut.Outputs, Channel)) { + // + // setup TC-BANK register + // + SetTcBankReg (MrcData, Channel); + + // + // setup TC-BANK_RANK_D register + // + SetTcBankRankDReg (MrcData, Channel); + + // + // setup TC-BANK_RANK_A register + // + SetTcBankRankAReg (MrcData, Channel); + + // + // setup TC-BANK_RANK_B register + // + SetTcBankRankBReg (MrcData, Channel); + + // + // setup TC-BANK_RANK_C register + // + SetTcBankRankCReg (MrcData, Channel); + } + } + + // + // Check RawCard Types and adjust Read ODT if needed + // + RdOdtStretch (MrcData); + + return; +} + +/** +@brief + This function sets up the Read ODTD values based on RawCard types and adjusts the tDRRD2RD, tDDRD2RD, tDRRD2WR and tDDRD2WR + + @param[in, out] MrcData - Include all MRC global data. + + @retval Nothing. +**/ +void +RdOdtStretch ( + IN OUT MrcParameters *const MrcData + ) +{ + const MrcDebug *Debug; + const MrcInput *Inputs; + MrcControllerOut *ControllerOut; + MrcChannelOut *ChannelOut; + U8 Channel; + U8 ChBitMask; + U8 RankMaskCh; + S8 OdtStretch; +#if SUPPORT_SODIMM == SUPPORT + MrcDimmOut *DimmOut; + BOOL SoDimm; + U8 Value; + U8 Dimm; + U8 DimmRawCardType[MAX_DIMMS_IN_CHANNEL]; + MCHBAR_CH0_CR_TC_BANK_RANK_A_STRUCT TcBankRankA; + MCHBAR_CH0_CR_TC_BANK_RANK_C_STRUCT TcBankRankC; +#endif //SUPPORT_SODIMM == SUPPORT + + Inputs = &MrcData->SysIn.Inputs; + Debug = &Inputs->Debug; + ControllerOut = &MrcData->SysOut.Outputs.Controller[0]; + + ChBitMask = 0; + + for (Channel = 0; Channel < MAX_CHANNEL; Channel++) { + ChannelOut = &ControllerOut->Channel[Channel]; + if (ChannelOut->ValidRankBitMask && (ChannelOut->DimmCount == 2)) { + ChBitMask |= (MRC_BIT0 << Channel); + } + } + + for (Channel = 0; Channel < MAX_CHANNEL; Channel++) { + if (!((MRC_BIT0 << Channel) & ChBitMask)) { + // + // Skip any channels that do not have 2 DIMMs populated + // + continue; + } + + ChannelOut = &ControllerOut->Channel[Channel]; + RankMaskCh = ChannelOut->ValidRankBitMask; + // + // Start with the most aggressive setting + // + OdtStretch = 6; + +#if SUPPORT_SODIMM == SUPPORT + SoDimm = FALSE; + for (Dimm = 0; Dimm < MAX_DIMMS_IN_CHANNEL; Dimm++) { + DimmOut = &ChannelOut->Dimm[Dimm]; + if (((DimmOut->ModuleType == MRC_MODULE_TYPE_SODIMM) || (DimmOut->ModuleType == MRC_MODULE_72B_SO_UDIMM)) + && (SoDimm == FALSE)) { + SoDimm = TRUE; + } + if (SoDimm) { + DimmRawCardType[Dimm] = DimmOut->ReferenceRawCard; + } + } + + if (SoDimm) { + if ((DimmRawCardType[0] == rcF || DimmRawCardType[1] == rcF) + && (DimmRawCardType[0] != DimmRawCardType[1])) { + OdtStretch = 7; + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE,"Rd Odt Stretch F\n"); + } + } +#endif //SUPPORT_SODIMM == SUPPORT + // + // Program Rdodtd value + // + UpdateTAParamOffset (MrcData, Channel, 0, rdodtd, OdtStretch, 1, 1, RankMaskCh); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, "Selected RdOdtD Offset for channel %d is = %d\n", Channel, OdtStretch); + +#if SUPPORT_SODIMM == SUPPORT + if (OdtStretch > 6) { + TcBankRankA.Data = ChannelOut->MchbarBANKRANKA; + Value = (U8)(TcBankRankA.Bits.tRDRD_dr); + Value += OdtStretch - 6; + // + // Program Different Rank RD 2 RD value + // + UpdateTAParamOffset (MrcData, Channel, 0, drrd2rd, Value, 1, 1, RankMaskCh); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, "Selected DR RD2RD Offset for channel %d is = %d\n", Channel, Value); + + Value = (U8)(TcBankRankA.Bits.tRDRD_dd); + Value += OdtStretch - 6; + // + // Program Different DIMM RD 2 RD value + // + UpdateTAParamOffset (MrcData, Channel, 0, ddrd2rd, Value, 1, 1, RankMaskCh); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, "Selected DD RD2RD Offset for channel %d is = %d\n", Channel, Value); + + TcBankRankC.Data = ChannelOut->MchbarBANKRANKC; + Value = (U8)(TcBankRankC.Bits.tRDWR_dr); + Value += OdtStretch - 6; + // + // Program Different Rank RD 2 WR value + // + UpdateTAParamOffset (MrcData, Channel, 0, drrd2wr, Value, 1, 1, RankMaskCh); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, "Selected DR RD2WR Offset for channel %d is = %d\n", Channel, Value); + + Value = (U8)(TcBankRankC.Bits.tRDWR_dd); + Value += OdtStretch - 6; + // + // Program Different DIMM RD 2 WR value + // + UpdateTAParamOffset (MrcData, Channel, 0, ddrd2wr, Value, 1, 1, RankMaskCh); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, "Selected DD RD2WR Offset for channel %d is = %d\n", Channel, Value); + + Value = (U8)(TcBankRankC.Bits.tRDWR); + Value += OdtStretch - 6; + // + // Program Same Rank RD 2 WR value + // + UpdateTAParamOffset (MrcData, Channel, 0, srrd2wr, Value, 1, 1, RankMaskCh); + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, "Selected SR RD2WR Offset for channel %d is = %d\n", Channel, Value); + } +#endif //SUPPORT_SODIMM == SUPPORT + } + +} |