/* $NoKeywords:$ */ /** * @file * * muc.c * * Utility functions * * @xrefitem bom "File Content Label" "Release Content" * @e project: AGESA * @e sub-project: (Mem/Main) * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $ * **/ /***************************************************************************** * * Copyright (c) 2008 - 2012, Advanced Micro Devices, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Advanced Micro Devices, Inc. nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *************************************************************************** * */ /* *---------------------------------------------------------------------------- * MODULES USED * *---------------------------------------------------------------------------- */ #include "AGESA.h" #include "cpuServices.h" #include "amdlib.h" #include "OptionMemory.h" #include "PlatformMemoryConfiguration.h" #include "Ids.h" #include "mport.h" #include "mu.h" #include "cpuFamilyTranslation.h" #include "cpuCacheInit.h" #include "Filecode.h" CODE_GROUP (G1_PEICC) RDATA_GROUP (G1_PEICC) #define FILECODE PROC_MEM_MAIN_MUC_FILECODE /*---------------------------------------------------------------------------- * DEFINITIONS AND MACROS * *---------------------------------------------------------------------------- */ CONST UINT32 Pattern2[16] = { 0x12345678, 0x87654321, 0x23456789, 0x98765432, 0x59385824, 0x30496724, 0x24490795, 0x99938733, 0x40385642, 0x38465245, 0x29432163, 0x05067894, 0x12349045, 0x98723467, 0x12387634, 0x34587623 }; CONST UINT32 MaxLatPat[48] = { 0x6E0E3FAC, 0x0C3CFF52, 0x4A688181, 0x49C5B613, 0x7C780BA6, 0x5C1650E3, 0x0C4F9D76, 0x0C6753E6, 0x205535A5, 0xBABFB6CA, 0x610E6E5F, 0x0C5F1C87, 0x488493CE, 0x14C9C383, 0xF5B9A5CD, 0x9CE8F615, 0xAAD714B5, 0xC38F1B4C, 0x72ED647C, 0x669F7562, 0x5233F802, 0x4A898B30, 0x10A40617, 0x3326B465, 0x55386E04, 0xC807E3D3, 0xAB49E193, 0x14B4E63A, 0x67DF2495, 0xEA517C45, 0x7624CE51, 0xF8140C51, 0x4824BD23, 0xB61DD0C9, 0x072BCFBE, 0xE8F3807D, 0x919EA373, 0x25E30C47, 0xFEB12958, 0x4DA80A5A, 0xE9A0DDF8, 0x792B0076, 0xE81C73DC, 0xF025B496, 0x1DB7E627, 0x808594FE, 0x82668268, 0x655C7783 }; CONST UINT8 PatternJD[9] = {0x44, 0xA6, 0x38, 0x4F, 0x4B, 0x2E, 0xEF, 0xD5, 0x54}; CONST UINT8 PatternJD_256[256] = { 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xF7, 0x08, 0xF7, 0x00, 0xFF, 0x00, 0xF7, 0x00, 0xFF, 0x00, 0xF7, 0x00, 0xF7, 0x08, 0xF7, 0x08, 0xFF, 0x00, 0xFF, 0x08, 0xFF, 0x00, 0xFF, 0x08, 0xFF, 0x08, 0xF7, 0xFB, 0x04, 0xFB, 0xFB, 0x04, 0xFB, 0xFB, 0xFB, 0x04, 0xFB, 0xFB, 0xFB, 0xFB, 0x04, 0xFB, 0x04, 0x04, 0xFB, 0x04, 0x04, 0x04, 0xFB, 0x04, 0x04, 0x04, 0x04, 0xFB, 0x7F, 0x80, 0x7F, 0x00, 0xFF, 0x00, 0x7F, 0x00, 0xFF, 0x00, 0x7F, 0x00, 0x7F, 0x80, 0x7F, 0x80, 0xFF, 0x00, 0xFF, 0x80, 0xFF, 0x00, 0xFF, 0x80, 0xFF, 0x80, 0x7F, 0xBF, 0x40, 0xBF, 0xBF, 0x40, 0xBF, 0xBF, 0xBF, 0x40, 0xBF, 0xBF, 0xBF, 0xBF, 0x40, 0xBF, 0x40, 0x40, 0xBF, 0x40, 0x40, 0x40, 0xBF, 0x40, 0x40, 0x40, 0x40, 0xBF, 0xFD, 0x02, 0xFD, 0x00, 0xFF, 0x00, 0xFD, 0x00, 0xFF, 0x00, 0xFD, 0x00, 0xFD, 0x02, 0xFD, 0x02, 0xFF, 0x00, 0xFF, 0x02, 0xFF, 0x00, 0xFF, 0x02, 0xFF, 0x02, 0xFD, 0xFE, 0x01, 0xFE, 0xFE, 0x01, 0xFE, 0xFE, 0xFE, 0x01, 0xFE, 0xFE, 0xFE, 0xFE, 0x01, 0xFE, 0x01, 0x01, 0xFE, 0x01, 0x01, 0x01, 0xFE, 0x01, 0x01, 0x01, 0x01, 0xFE, 0xDF, 0x20, 0xDF, 0x00, 0xFF, 0x00, 0xDF, 0x00, 0xFF, 0x00, 0xDF, 0x00, 0xDF, 0x20, 0xDF, 0x20, 0xFF, 0x00, 0xFF, 0x20, 0xFF, 0x00, 0xFF, 0x20, 0xFF, 0x20, 0xDF, 0xEF, 0x10, 0xEF, 0xEF, 0x10, 0xEF, 0xEF, 0xEF, 0x10, 0xEF, 0xEF, 0xEF, 0xEF, 0x10, 0xEF, 0x10, 0x10, 0xEF, 0x10, 0x10, 0x10, 0xEF, 0x10, 0x10, 0x10, 0x10, 0xEF, 0xF7, 0x00, 0xFF, 0x04, 0x7F, 0x00, 0xFF, 0x40, 0xFD, 0x00, 0xFF, 0x01, 0xDF }; /*---------------------------------------------------------------------------- * TYPEDEFS AND STRUCTURES * *---------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------- * PROTOTYPES OF LOCAL FUNCTIONS * *---------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------- * EXPORTED FUNCTIONS * *---------------------------------------------------------------------------- */ /* -----------------------------------------------------------------------------*/ /** * * This function returns the (index)th UINT8 * from an indicated test pattern. * * @param[in] Pattern - encoding of test pattern type * @param[in] Buffer[] - buffer to be filled * @param[in] Size - Size of the buffer * * ---------------------------------------------------------------------------- */ VOID MemUFillTrainPattern ( IN TRAIN_PATTERN Pattern, IN UINT8 Buffer[], IN UINT16 Size ) { UINT8 Result; UINT8 i; UINT8 Mask; UINT16 Index; UINT16 k; for (Index = 0; Index < Size; Index++) { k = Index; // get one byte from Pattern switch (Pattern) { case TestPattern0: Result = 0xAA; break; case TestPattern1: Result = 0x55; break; case TestPattern2: ASSERT (Index < sizeof (Pattern2)); Result = ((UINT8 *)Pattern2)[Index]; break; case TestPatternML: if (Size != 6 * 64) { Result = ((UINT8 *)MaxLatPat)[Index]; } else { Result = ((UINT8 *)MaxLatPat)[Index & 0xF7]; } break; case TestPatternJD256B: k >>= 1; // fall through - TestPatternJD256B also need to run TestPatternJD256A sequence case TestPatternJD256A: k >>= 3; ASSERT (k < sizeof (PatternJD_256)); Result = PatternJD_256[k]; break; case TestPatternJD1B: k >>= 1; // fall through - TestPatternJD1B also need to run TestPatternJD1A sequence case TestPatternJD1A: k >>= 3; i = (UINT8) (k >> 3); Mask = (UINT8) (0x80 >> (k & 7)); if (i == 0) { Result = 0; } else { Result = (UINT16)1 << (i - 1); } ASSERT (i < sizeof (PatternJD)); if (PatternJD[i] & Mask) { Result = ~Result; } break; case TestPattern3: Result = 0x36; break; case TestPattern4: Result = 0xC9; break; default: Result = 0; IDS_ERROR_TRAP; } // fill in the Pattern buffer Buffer[Index] = Result; } } /* -----------------------------------------------------------------------------*/ /** * * This function flushes cache lines * * @param[in,out] MemPtr - pointer to MEM_DATA_STRUCTURE * @param[in] ClCount - Number of cache lines * @param[in] Address - System Address [47:16] * * ---------------------------------------------------------------------------- */ VOID MemUProcIOClFlush ( IN UINT32 Address, IN UINT16 ClCount, IN OUT MEM_DATA_STRUCT *MemPtr ) { MemUSetTargetWTIO (Address, MemPtr); MemUFlushPattern (MemUSetUpperFSbase (Address, MemPtr), ClCount); MemUResetTargetWTIO (MemPtr); } /*---------------------------------------------------------------------------- * LOCAL FUNCTIONS * *---------------------------------------------------------------------------- */ /* -----------------------------------------------------------------------------*/ /** * * This function sets the upper 32-bits of the Base address, 4GB aligned) for the FS selector. * @param[in,out] MemPtr - pointer to MEM_DATA_STRUCTURE * @param[in] Address - System Address [47:16] * * @return Address - Lowest 32-bit of physical address * ---------------------------------------------------------------------------- */ UINT32 MemUSetUpperFSbase ( IN UINT32 Address, IN OUT MEM_DATA_STRUCT *MemPtr ) { S_UINT64 SMsr; SMsr.lo = 0; SMsr.hi = Address >> 16; LibAmdMsrWrite (FS_BASE, (UINT64 *)&SMsr, &MemPtr->StdHeader); return Address << 16; } /* -----------------------------------------------------------------------------*/ /** * * This function resets the target address space to Write Through IO by disabling IORRs * * @param[in,out] MemPtr - pointer to MEM_DATA_STRUCTURE * * ---------------------------------------------------------------------------- */ VOID MemUResetTargetWTIO ( IN OUT MEM_DATA_STRUCT *MemPtr ) { S_UINT64 SMsr; SMsr.hi = 0; SMsr.lo = 0; LibAmdMsrWrite (IORR0_MASK, (UINT64 *)&SMsr, &MemPtr->StdHeader); } /* -----------------------------------------------------------------------------*/ /** * * This function sets the target range to WT IO (using an IORR overlapping * the already existing * * @param[in,out] MemPtr - pointer to MEM_DATA_STRUCTURE * @param[in] Address - System Address [47:16] * * ---------------------------------------------------------------------------- */ VOID MemUSetTargetWTIO ( IN UINT32 Address, IN OUT MEM_DATA_STRUCT *MemPtr ) { S_UINT64 SMsr; SMsr.lo = Address << 16; SMsr.hi = Address >> 16; LibAmdMsrWrite (IORR0_BASE,(UINT64 *)&SMsr, &MemPtr->StdHeader); // IORR0 Base SMsr.hi = 0xFFFF; SMsr.lo = 0xFC000800; LibAmdMsrWrite (IORR0_MASK, (UINT64 *)&SMsr, &MemPtr->StdHeader); // 64MB Mask } /* -----------------------------------------------------------------------------*/ /** * * Waits specified number of 10ns cycles * @param[in,out] MemPtr - pointer to MEM_DATA_STRUCTURE * @param[in] Count - Number of 10ns cycles to wait; Note that Count must not exceed 1000000 * * ---------------------------------------------------------------------------- */ VOID MemUWait10ns ( IN UINT32 Count, IN OUT MEM_DATA_STRUCT *MemPtr ) { UINT64 TargetTsc; UINT64 CurrentTsc; ASSERT (Count <= 1000000); MemUMFenceInstr (); LibAmdMsrRead (TSC, &CurrentTsc, &MemPtr->StdHeader); TargetTsc = CurrentTsc + ((Count * MemPtr->TscRate + 99) / 100); IEM_SKIP_CODE (IEM_WAIT) { do { LibAmdMsrRead (TSC, &CurrentTsc, &MemPtr->StdHeader); } while (CurrentTsc < TargetTsc); } } /* -----------------------------------------------------------------------------*/ /** * * Find the entry of platform specific overriding table. * * @param[in] PlatformMemoryConfiguration - Platform config table * @param[in] EntryType - Entry type * @param[in] SocketID - Physical socket ID * @param[in] ChannelID - Physical channel ID * @param[in] DimmID - Physical Dimm ID * @param[in] *LogicalIdPtr - Pointer to the CPU_LOGICAL_ID * @param[in,out] *StdHeader - Pointer of AMD_CONFIG_PARAMS * - If both *LogicalIdPtr and *StdHeader are "NULL" input, * that means, the "EntryType" are not CPU family dependent, * ex. PSO_MAX_DIMMS for NUMBER_OF_DIMMS_SUPPORTED macro. * * * @return NULL - entry could not be found. * @return Pointer - points to the entry's data. * * ---------------------------------------------------------------------------- */ VOID * FindPSOverrideEntry ( IN PSO_TABLE *PlatformMemoryConfiguration, IN PSO_ENTRY EntryType, IN UINT8 SocketID, IN UINT8 ChannelID, IN UINT8 DimmID, IN CPU_LOGICAL_ID *LogicalIdPtr, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 *Buffer; CPU_LOGICAL_ID LogicalCpuId; UINT32 RawCpuId; LogicalCpuId.Family = AMD_FAMILY_UNKNOWN; LogicalCpuId.Revision = 0; RawCpuId = 0; Buffer = PlatformMemoryConfiguration; // // Do not need to look for CPU family specific PSO if LogicalIdPtr and StdHeader are NULL. // if ((LogicalIdPtr != NULL) && (StdHeader != NULL)) { // // Looking for the CPU family signature followed by CPUID value. // And check to see if the CPUID value is matched with current CPU's : // - If matched, Buffer points to following PSO macros' start address. // - If not matched, Buffer points to PlatformMemoryConfiguration for global PSO parsing. // while (Buffer[0] != PSO_END) { if (Buffer[0] == PSO_CPU_FAMILY_TO_OVERRIDE) { RawCpuId = *(UINT32 *)&Buffer[2]; GetLogicalIdFromCpuid (RawCpuId, &LogicalCpuId, StdHeader); if ((LogicalCpuId.Family & LogicalIdPtr->Family) != 0) { if ((LogicalCpuId.Revision & LogicalIdPtr->Revision) != 0) { Buffer += Buffer[1] + 2; break; } } } Buffer += Buffer[1] + 2; } // // If no CPU family specific PSO macros exist, Buffer points to PlatformMemoryConfiguration again // if (Buffer[0] == PSO_END) { Buffer = PlatformMemoryConfiguration; } } while ((Buffer[0] != PSO_END) && (Buffer[0] != PSO_CPU_FAMILY_TO_OVERRIDE)) { if (Buffer[0] == EntryType) { if ((Buffer[2] & ((UINT8) 1 << SocketID)) != 0 ) { if ((Buffer[3] & ((UINT8) 1 << ChannelID)) != 0 ) { if ((Buffer[4] & ((UINT8) 1 << DimmID)) != 0 ) { return &Buffer[5]; } } } } Buffer += Buffer[1] + 2; } return NULL; } /* -----------------------------------------------------------------------------*/ /** * * * This function returns the max dimms for a given memory channel on a given * processor. It first searches the platform override table for the max dimms * value. If it is not provided, the AGESA default value is returned. The target * socket must be a valid present socket. * * @param[in] PlatformMemoryConfiguration - Platform config table * @param[in] SocketID - ID of the processor that owns the channel * @param[in] ChannelID - Channel to get max dimms for * * * @return UINT8 - Max Number of Dimms for that channel */ UINT8 GetMaxDimmsPerChannel ( IN PSO_TABLE *PlatformMemoryConfiguration, IN UINT8 SocketID, IN UINT8 ChannelID ) { UINT8 *DimmsPerChPtr; UINT8 MaxDimmPerCH; DimmsPerChPtr = FindPSOverrideEntry (PlatformMemoryConfiguration, PSO_MAX_DIMMS, SocketID, ChannelID, 0, NULL, NULL); if (DimmsPerChPtr != NULL) { MaxDimmPerCH = *DimmsPerChPtr; } else { MaxDimmPerCH = MAX_DIMMS_PER_CHANNEL; } // Maximum number of dimms per channel cannot be larger than its default value. ASSERT (MaxDimmPerCH <= MAX_DIMMS_PER_CHANNEL); return MaxDimmPerCH; } /* -----------------------------------------------------------------------------*/ /** * * * This function returns the max soldered-down dimms for a given memory channel on a given * processor. It first searches the platform override table for the soldered-down dimms * value. If it is not provided, the AGESA default value is returned. The target * socket must be a valid present socket. * * @param[in] PlatformMemoryConfiguration - Platform config table * @param[in] SocketID - ID of the processor that owns the channel * @param[in] ChannelID - Channel to get max dimms for * * * @return UINT8 - Max Number of soldered-down dimms for that channel */ UINT8 GetMaxSolderedDownDimmsPerChannel ( IN PSO_TABLE *PlatformMemoryConfiguration, IN UINT8 SocketID, IN UINT8 ChannelID ) { UINT8 *DimmsPerChPtr; UINT8 MaxSolderedDownDimmPerCH; DimmsPerChPtr = FindPSOverrideEntry (PlatformMemoryConfiguration, PSO_MAX_SOLDERED_DOWN_DIMMS, SocketID, ChannelID, 0, NULL, NULL); if (DimmsPerChPtr != NULL) { MaxSolderedDownDimmPerCH = *DimmsPerChPtr; } else { MaxSolderedDownDimmPerCH = 0; } // Maximum number of dimms per channel cannot be larger than its default value. ASSERT (MaxSolderedDownDimmPerCH <= MAX_DIMMS_PER_CHANNEL); return MaxSolderedDownDimmPerCH; } /* -----------------------------------------------------------------------------*/ /** * * * This function returns the max memory channels on a given processor. * It first searches the platform override table for the max channels value. * If it is not provided, the AGESA default value is returned. * * @param[in] PlatformMemoryConfiguration - Platform config table * @param[in] SocketID - ID of the processor * @param[in] StdHeader - Header for library and services * * * @return UINT8 - Max Number of Channels on that Processor */ UINT8 GetMaxChannelsPerSocket ( IN PSO_TABLE *PlatformMemoryConfiguration, IN UINT8 SocketID, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 *ChannelsPerSocketPtr; UINT8 MaxChannelsPerSocket; if (IsProcessorPresent (SocketID, StdHeader)) { ChannelsPerSocketPtr = FindPSOverrideEntry (PlatformMemoryConfiguration, PSO_MAX_CHNLS, SocketID, 0, 0, NULL, NULL); if (ChannelsPerSocketPtr != NULL) { MaxChannelsPerSocket = *ChannelsPerSocketPtr; } else { MaxChannelsPerSocket = MAX_CHANNELS_PER_SOCKET; } // Maximum number of channels per socket cannot be larger than its default value. ASSERT (MaxChannelsPerSocket <= MAX_CHANNELS_PER_SOCKET); } else { MaxChannelsPerSocket = 0; } return MaxChannelsPerSocket; } /* -----------------------------------------------------------------------------*/ /** * * * This function returns the max number of chip select on a given channel of * a given processor. It first searches the platform override table for the max * chip select value. If it is not provided, the AGESA default value is returned. * The target socket must be a valid present socket. * * @param[in] PlatformMemoryConfiguration - Platform config table * @param[in] SocketID - ID of the processor * @param[in] ChannelID - ID of a channel * * * @return UINT8 - Max Number of chip selects on the channel of the Processor */ UINT8 GetMaxCSPerChannel ( IN PSO_TABLE *PlatformMemoryConfiguration, IN UINT8 SocketID, IN UINT8 ChannelID ) { UINT8 *CSPerSocketPtr; UINT8 MaxCSPerChannel; CSPerSocketPtr = FindPSOverrideEntry (PlatformMemoryConfiguration, PSO_MAX_CHIPSELS, SocketID, ChannelID, 0, NULL, NULL); if (CSPerSocketPtr != NULL) { MaxCSPerChannel = *CSPerSocketPtr; } else { MaxCSPerChannel = MAX_CS_PER_CHANNEL; } // Max chip select per channel cannot be larger than its default value ASSERT (MaxCSPerChannel <= MAX_CS_PER_CHANNEL); return MaxCSPerChannel; } /* -----------------------------------------------------------------------------*/ /** * * * This function returns the index of the first Dimm SPD structure for a * given processor socket. It checks the Max Dimms per channel for every memory * channel on every processor up to the current one, and adds them together. * * This function may also be used to calculate the maximum dimms per system * by passing the total number of dimm sockets * * @param[in] PlatformMemoryConfiguration - Platform config table * @param[in] SocketID - ID of the processor * @param[in] StdHeader - Header for library and services * * @return UINT8 - SPD Index */ UINT8 GetSpdSocketIndex ( IN PSO_TABLE *PlatformMemoryConfiguration, IN UINT8 SocketID, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 SpdSocketIndex; UINT8 Socket; UINT8 Channel; UINT8 MaxChannelsPerSocket; SpdSocketIndex = 0; for (Socket = 0; Socket < SocketID; Socket++) { MaxChannelsPerSocket = GetMaxChannelsPerSocket (PlatformMemoryConfiguration, Socket, StdHeader); for (Channel = 0; Channel < MaxChannelsPerSocket; Channel++) { SpdSocketIndex = SpdSocketIndex + GetMaxDimmsPerChannel (PlatformMemoryConfiguration, Socket, Channel); } } return SpdSocketIndex; } /* -----------------------------------------------------------------------------*/ /** * * * This function returns the index of the first Dimm SPD structure for a * given channel relative to the processor socket. It checks the Max Dimms per * channel for every memory channel on that processor up to the current one, * and adds them together. * * This function may also be used to calculate the maximum dimms per system * by passing the total number of DIMM sockets * * @param[in] PlatformMemoryConfiguration - Platform config table * @param[in] SocketID - ID of the processor * @param[in] ChannelID - ID of the Channel * @param[in] StdHeader - Header for library and services * * @return UINT8 - SPD Index */ UINT8 GetSpdChannelIndex ( IN PSO_TABLE *PlatformMemoryConfiguration, IN UINT8 SocketID, IN UINT8 ChannelID, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 SpdChannelIndex; UINT8 Channel; SpdChannelIndex = 0; ASSERT (ChannelID < GetMaxChannelsPerSocket (PlatformMemoryConfiguration, SocketID, StdHeader)) for (Channel = 0; Channel < ChannelID; Channel++) { SpdChannelIndex = SpdChannelIndex + GetMaxDimmsPerChannel (PlatformMemoryConfiguration, SocketID, Channel); } return SpdChannelIndex; } /*-----------------------------------------------------------------------------*/ /** * * This function returns the upper 32 bits mask for variable MTRR based on * the CPU_LOGICAL_ID. * @param[in] *LogicalIdPtr - Pointer to the CPU_LOGICAL_ID * @param[in] StdHeader - Header for library and services * * @return UINT32 - MTRR mask for upper 32 bits * */ UINT32 GetVarMtrrHiMsk ( IN CPU_LOGICAL_ID *LogicalIdPtr, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 TempNotCare; CPU_SPECIFIC_SERVICES *FamilySpecificServices; CONST CACHE_INFO *CacheInfoPtr; GetCpuServicesFromLogicalId (LogicalIdPtr, (CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader); FamilySpecificServices->GetCacheInfo (FamilySpecificServices, (CONST VOID **) &CacheInfoPtr, &TempNotCare, StdHeader); return (UINT32) (CacheInfoPtr->VariableMtrrMask >> 32); } /*-----------------------------------------------------------------------------*/ /** * * This function returns number of memclk converted from ns * @param[in] Speed - memclk frequency * @param[in] NumberOfns - number of ns to be converted * * @return UINT32 - number of memclk * */ UINT32 MemUnsToMemClk ( IN MEMORY_BUS_SPEED Speed, IN UINT32 NumberOfns ) { return (UINT32) ((NumberOfns * Speed + 999) / 1000); }