diff options
Diffstat (limited to 'ReferenceCode/Chipset/SystemAgent/MemoryInit/Pei/Source/McConfiguration/MrcAddressDecodeConfiguration.c')
-rw-r--r-- | ReferenceCode/Chipset/SystemAgent/MemoryInit/Pei/Source/McConfiguration/MrcAddressDecodeConfiguration.c | 368 |
1 files changed, 368 insertions, 0 deletions
diff --git a/ReferenceCode/Chipset/SystemAgent/MemoryInit/Pei/Source/McConfiguration/MrcAddressDecodeConfiguration.c b/ReferenceCode/Chipset/SystemAgent/MemoryInit/Pei/Source/McConfiguration/MrcAddressDecodeConfiguration.c new file mode 100644 index 0000000..e4d17ee --- /dev/null +++ b/ReferenceCode/Chipset/SystemAgent/MemoryInit/Pei/Source/McConfiguration/MrcAddressDecodeConfiguration.c @@ -0,0 +1,368 @@ +/** @file + This module configures the memory controller address decoder. +@copyright + Copyright (c) 1999 - 2013 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 "MrcAddressDecodeConfiguration.h" + +#if (MAX_CHANNEL > 2) +#error This module only supports a maximum of 2 channels. +#endif +#if (MAX_DIMMS_IN_CHANNEL > 2) +#error This module only supports a maximum of 2 DIMMs per channel. +#endif + +/** +@brief + This function configures the zone configuration registers MAD-CR and MAD-ZR-CR. + + @param[in, out] MrcData - Include all MRC global data. + + @retval Nothing. +**/ +void +ZoneConfiguration ( + IN OUT MrcParameters *const MrcData +) +{ + MrcInput *Inputs; + MrcOutput *Outputs; + MrcDebug *Debug; + MrcControllerOut *ControllerOut; + MrcChannelOut *ChannelOut; + MrcChannelOut *ChannelOut0; + MrcChannelOut *ChannelOut1; + MCDECS_CR_MAD_CHNL_MCMAIN_STRUCT MadChnl; + MCDECS_CR_MAD_ZR_MCMAIN_STRUCT MadZr; + MCDECS_CR_CHANNEL_HASH_MCMAIN_STRUCT ChannelHash; + U32 ChannelSizeMin; + U32 ChannelSizeBC; + U32 ChannelSize2BC; + U32 ChannelSize[MAX_CHANNEL]; + U8 Channel; + U8 Dimm; + + MadChnl.Data = 0; + MadZr.Data = 0; + ChannelHash.Data = 0; + Inputs = &MrcData->SysIn.Inputs; + Debug = &Inputs->Debug; + Outputs = &MrcData->SysOut.Outputs; + ControllerOut = &MrcData->SysOut.Outputs.Controller[0]; + + // + // Add up the amount of memory in each channel. + // + for (Channel = 0; Channel < MAX_CHANNEL; Channel++) { + ChannelOut = &ControllerOut->Channel[Channel]; + ChannelSize[Channel] = 0; + if (ChannelOut->Status == CHANNEL_PRESENT) { + for (Dimm = 0; Dimm < MAX_DIMMS_IN_CHANNEL; Dimm++) { + if(ChannelOut->Dimm[Dimm].Status == DIMM_PRESENT) { + ChannelSize[Channel] += ChannelOut->Dimm[Dimm].DimmCapacity; + } + } + } + } + // + // Define MAD_ZR register: + // MAD-ZR-CR [29:24] = channel C size: ch_c_size + // MAD-ZR-CR [23:16] = (channel C size) * 3: ch_3c_size + // MAD-ZR-CR [15:8] = (channel B size) * 2 + (channel C size): ch_b_2c_size + // MAD-ZR-CR [7:0] = (channel B size) + (channel C size): ch_b_c_size + // + ChannelOut0 = &ControllerOut->Channel[cCHANNEL0]; + ChannelOut1 = &ControllerOut->Channel[cCHANNEL1]; + if (ChannelSize[cCHANNEL1] <= ChannelSize[cCHANNEL0]) { + MadChnl.Bits.CH_A = 0; + MadChnl.Bits.CH_B = 1; + + // + // Set the virtual channel type according to the address decoding decision. + // + ChannelOut0->VirtualChannel = vcA; + ChannelOut1->VirtualChannel = vcB; + + ChannelSizeMin = ChannelSize[cCHANNEL1]; + } else { + // + // ChannelSize0 < ChannelSize1 + // + MadChnl.Bits.CH_A = 1; + MadChnl.Bits.CH_B = 0; + + // + // Set the virtual channel type according to the address decoding decision. + // + ChannelOut0->VirtualChannel = vcB; + ChannelOut1->VirtualChannel = vcA; + + ChannelSizeMin = ChannelSize[cCHANNEL0]; + } + // + // Divided by 256 because the channel size is in 256 MB units. + // + ChannelSizeBC = ChannelSizeMin / 256; + ChannelSize2BC = ChannelSizeBC << 1; + MadZr.Bits.BandC = MIN (ChannelSizeBC, MCDECS_CR_MAD_ZR_MCMAIN_BandC_MAX); + MadZr.Bits.TwoBandC = MIN (ChannelSize2BC, MCDECS_CR_MAD_ZR_MCMAIN_TwoBandC_MAX); + MadChnl.Bits.CH_C = 2; + +#ifdef ULT_FLAG + MadChnl.Bits.LPDDR = (Outputs->DdrType == MRC_DDR_TYPE_LPDDR3) ? 1 : 0; +#endif + // + // Interleaved mode + // Check for any Channel hash support + // + if (Inputs->ChHashEnable) { + ChannelHash.Bits.Mask = MIN (Inputs->ChHashMask, MCDECS_CR_CHANNEL_HASH_MCMAIN_Mask_MAX); + ChannelHash.Bits.LSB_mask_bit = MIN (Inputs->ChHashInterleaveBit, MCDECS_CR_CHANNEL_HASH_MCMAIN_LSB_mask_bit_MAX); + ChannelHash.Bits.Enable = 1; + MRC_DEBUG_MSG (Debug, MSG_LEVEL_NOTE, "Channel HASH Enabled\n"); + } + + if (Inputs->MemoryTrace) { + if (ChannelSize[cCHANNEL0] == ChannelSize[cCHANNEL1]) { + // + // Enable the Stacked Mode for memory tracing + // + MadChnl.Bits.STKD_MODE = 1; + MadChnl.Bits.STKD_MODE_CH_BITS = MrcLog2 (ChannelSizeMin) - 9; + ChannelHash.Bits.Enable = 1; + MRC_DEBUG_MSG ( + Debug, + MSG_LEVEL_NOTE, + "Enabling Stacked Mode for Memory Trace, Stacked Mode Ch bit = %u (%u MB per channel)\n", + MadChnl.Bits.STKD_MODE_CH_BITS + 28, + ChannelSizeMin + ); + } else { + Inputs->MemoryTrace = 0; + MRC_DEBUG_MSG (Debug, MSG_LEVEL_ERROR, "Channels are not equal in size, cannot enable Memory Trace !\n"); + } + } + + MRC_DEBUG_MSG ( + Debug, + MSG_LEVEL_NOTE, + "CHANNEL_HASH = 0x%08X\nMAD_CHNL = 0x%08X\nMAD_ZR = 0x%08X\n", + ChannelHash.Data, + MadChnl.Data, + MadZr.Data + ); + MrcWriteCR (MrcData, MCDECS_CR_CHANNEL_HASH_MCMAIN_REG, ChannelHash.Data); + MrcWriteCR (MrcData, MCDECS_CR_MAD_CHNL_MCMAIN_REG, MadChnl.Data); + MrcWriteCR (MrcData, MCDECS_CR_MAD_ZR_MCMAIN_REG, MadZr.Data); + return; +} + +/** +@brief + This function configures the MAD_DIMM_CH0/1 register. + + @param[in] MrcData - Include all MRC global data. + @param[in] ChannelIndex - Channel index + + @retval Nothing. +**/ +void +ChannelAddressDecodeConfiguration ( + IN MrcParameters *const MrcData, + IN const U32 ChannelIndex +) +{ + const MrcInput *Inputs; + MrcOutput *Outputs; + MrcChannelOut *ChannelOut; + MrcDimmOut *DimmA; + MrcDimmOut *DimmB; + MCDECS_CR_MAD_DIMM_CH0_MCMAIN_STRUCT MadDimm; + U32 DimmCapacity; + U32 Dimm0Capacity; + U32 Dimm1Capacity; + U32 Scratch; +#ifdef ULT_FLAG + MCHBAR_CH0_CR_LPDDR_MR_PARAMS_STRUCT LpddrMrParams; +#endif //ULT_FLAG + + Inputs = &MrcData->SysIn.Inputs; + Outputs = &MrcData->SysOut.Outputs; + ChannelOut = &Outputs->Controller[0].Channel[ChannelIndex]; + MadDimm.Data = 0; + if (ChannelOut->Dimm[dDIMM0].Status == DIMM_PRESENT) { + Dimm0Capacity = ChannelOut->Dimm[dDIMM0].DimmCapacity; + } else { + Dimm0Capacity = 0; + } + + if (ChannelOut->Dimm[dDIMM1].Status == DIMM_PRESENT) { + Dimm1Capacity = (MAX_DIMMS_IN_CHANNEL > 1) ? ChannelOut->Dimm[dDIMM1].DimmCapacity : 0; + } else { + Dimm1Capacity = 0; + } + + // + // larger dimm will be located to Dimm A and small dimm will be located to dimm B + // + if (Dimm1Capacity <= Dimm0Capacity) { + DimmA = &ChannelOut->Dimm[dDIMM0]; + DimmB = &ChannelOut->Dimm[dDIMM1]; + // + // larger DIMM in capacity 0 - DIMM 0 or 1 - DIMM 1 + // + MadDimm.Bits.DAS = 0; + } else { + DimmA = &ChannelOut->Dimm[dDIMM1]; + DimmB = &ChannelOut->Dimm[dDIMM0]; + // + // larger DIMM in capacity 0 - DIMM 0 or 1 - DIMM 1 + // + MadDimm.Bits.DAS = 1; + } + // + // Dimm A + // + if ((0 < DimmA->RankInDIMM) && (DimmA->Status == DIMM_PRESENT)) { + DimmCapacity = DimmA->DimmCapacity / 256; + MadDimm.Bits.DIMM_A_Size = MIN (DimmCapacity, MCDECS_CR_MAD_DIMM_CH0_MCMAIN_DIMM_A_Size_MAX); + // + // RankInDIMM must be 1 or 2, we test the case that the value is 0 + // + Scratch = DimmA->RankInDIMM - 1; + MadDimm.Bits.DANOR = MIN (Scratch, MCDECS_CR_MAD_DIMM_CH0_MCMAIN_DANOR_MAX); + // + // SDRAM width x8 or x32 set to 0, x16 set to 1 + // + MadDimm.Bits.DAW = (DimmA->SdramWidth == 16) ? 1 : 0; + } + // + // Dimm B + // + if ((MAX_DIMMS_IN_CHANNEL > 1) && (0 < DimmB->RankInDIMM) && (DimmB->Status == DIMM_PRESENT)) { + DimmCapacity = DimmB->DimmCapacity / 256; + MadDimm.Bits.DIMM_B_Size = MIN (DimmCapacity, MCDECS_CR_MAD_DIMM_CH0_MCMAIN_DIMM_B_Size_MAX); + // + // RankInDIMM must be 1 or 2, we test the case that this value is 0. + // + Scratch = DimmB->RankInDIMM - 1; + MadDimm.Bits.DBNOR = MIN (Scratch, MCDECS_CR_MAD_DIMM_CH0_MCMAIN_DBNOR_MAX); + + // + // SDRAM width x8 or x32 set to 0, x16 set to 1 + // + MadDimm.Bits.DBW = (DimmB->SdramWidth == 16) ? 1 : 0; + } + +#ifdef ULT_FLAG + if (Inputs->CpuModel == cmHSW_ULT) { + // + // On HSW-ULT only 1DPC is supported, and DBW should have the same value as DAW + // + MadDimm.Bits.DBW = MadDimm.Bits.DAW; + } +#endif + + if (Inputs->RankInterleave) { + MadDimm.Bits.RI = MRC_DIMM_RANK_INTERLEAVE; + } + if (Inputs->EnhancedInterleave) { + MadDimm.Bits.Enh_Interleave = MRC_ENHANCED_INTERLEAVE_MODE; + } + + MRC_DEBUG_MSG (&Inputs->Debug, MSG_LEVEL_NOTE, "MAD_DIMM_CH%u = 0x%08X\n", ChannelIndex, MadDimm.Data); + MrcWriteCR ( + MrcData, + MCDECS_CR_MAD_DIMM_CH0_MCMAIN_REG + + (ChannelIndex * (MCDECS_CR_MAD_DIMM_CH1_MCMAIN_REG - MCDECS_CR_MAD_DIMM_CH0_MCMAIN_REG)), + MadDimm.Data + ); + +#ifdef ULT_FLAG + if (Outputs->DdrType == MRC_DDR_TYPE_LPDDR3) { + LpddrMrParams.Data = 0; + LpddrMrParams.Bits.MR4_PERIOD = 0x200D; + + if (DimmA->SdramWidth == 32) { + LpddrMrParams.Bits.Rank_0_x32 = 1; + LpddrMrParams.Bits.Rank_1_x32 = 1; + } + + MrcWriteCR ( + MrcData, + MCHBAR_CH0_CR_LPDDR_MR_PARAMS_REG + + (ChannelIndex * (MCHBAR_CH1_CR_LPDDR_MR_PARAMS_REG - MCHBAR_CH0_CR_LPDDR_MR_PARAMS_REG)), + LpddrMrParams.Data + ); + } +#endif // ULT_FLAG + return; +} + +/** +@brief + This function is the main address decoding configuration function. + + @param[in] MrcData - Include all MRC global data. + + @retval Nothing. +**/ +void +MrcAdConfiguration ( + IN MrcParameters *const MrcData +) +{ + MrcOutput *Outputs; + MrcChannelOut *ChannelOut; + MrcControllerOut *ControllerOut; + MrcDimmOut *DimmOut; + U8 Controller; + U8 Channel; + U8 Dimm; + + ZoneConfiguration (MrcData); + + Outputs = &MrcData->SysOut.Outputs; + for (Controller = 0; Controller < MAX_CONTROLLERS; Controller++) { + ControllerOut = &Outputs->Controller[Controller]; + for (Channel = 0; Channel < MAX_CHANNEL; Channel++) { + if (!MrcChannelExist (Outputs, Channel)) { + continue; + } + ChannelOut = &ControllerOut->Channel[Channel]; + + ChannelAddressDecodeConfiguration (MrcData, Channel); + + for (Dimm = 0; Dimm < MAX_DIMMS_IN_CHANNEL; ++Dimm) { + DimmOut = &ChannelOut->Dimm[Dimm]; + if (DimmOut->Status == DIMM_PRESENT) { + MRC_DEBUG_MSG ( + &MrcData->SysIn.Inputs.Debug, + MSG_LEVEL_NOTE, + "Channel: %u, Dimm %d Rank in DIMM is: %u\n", + Channel, + Dimm, + DimmOut->RankInDIMM + ); + } + } // for Dimm + } // for Channel + } // for Controller + + return; +} |