diff options
Diffstat (limited to 'src/vendorcode/amd/agesa/f15/Proc/Mem/Feat/IDENDIMM/mfidendimm.c')
-rw-r--r-- | src/vendorcode/amd/agesa/f15/Proc/Mem/Feat/IDENDIMM/mfidendimm.c | 550 |
1 files changed, 0 insertions, 550 deletions
diff --git a/src/vendorcode/amd/agesa/f15/Proc/Mem/Feat/IDENDIMM/mfidendimm.c b/src/vendorcode/amd/agesa/f15/Proc/Mem/Feat/IDENDIMM/mfidendimm.c deleted file mode 100644 index 7315b8ed1d..0000000000 --- a/src/vendorcode/amd/agesa/f15/Proc/Mem/Feat/IDENDIMM/mfidendimm.c +++ /dev/null @@ -1,550 +0,0 @@ -/* $NoKeywords:$ */ -/** - * @file - * - * mfidendimm.c - * - * Translate physical system address to dimm identification. - * - * @xrefitem bom "File Content Label" "Release Content" - * @e project: AGESA - * @e sub-project: (Mem/Feat) - * - **/ -/***************************************************************************** -* - * 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 "amdlib.h" -#include "mm.h" -#include "mn.h" -#include "Ids.h" -#include "OptionMemory.h" -#include "heapManager.h" -#include "mfidendimm.h" -#include "GeneralServices.h" -#include "Filecode.h" -CODE_GROUP (G2_PEI) -RDATA_GROUP (G2_PEI) - -#define FILECODE PROC_MEM_FEAT_IDENDIMM_MFIDENDIMM_FILECODE -extern MEM_NB_SUPPORT memNBInstalled[]; - -/*---------------------------------------------------------------------------- - * DEFINITIONS AND MACROS - * - *---------------------------------------------------------------------------- - */ -#define MAX_DCTS_PER_DIE 2 ///< Max DCTs per die -#define MAX_CHLS_PER_DCT 1 ///< Max Channels per DCT - -/*---------------------------------------------------------------------------- - * TYPEDEFS AND STRUCTURES - * - *---------------------------------------------------------------------------- - */ - -/*---------------------------------------------------------------------------- - * PROTOTYPES OF LOCAL FUNCTIONS - * - *---------------------------------------------------------------------------- - */ -AGESA_STATUS -STATIC -MemFTransSysAddrToCS ( - IN OUT AMD_IDENTIFY_DIMM *AmdDimmIdentify, - IN MEM_MAIN_DATA_BLOCK *mmPtr - ); - -UINT32 -STATIC -MemFGetPCI ( - IN MEM_NB_BLOCK *NBPtr, - IN UINT8 NodeID, - IN UINT8 DctNum, - IN BIT_FIELD_NAME BitFieldName - ); - -UINT8 -STATIC -MemFUnaryXOR ( - IN UINT32 address - ); - -/*---------------------------------------------------------------------------- - * EXPORTED FUNCTIONS - * - *---------------------------------------------------------------------------- - */ -/*-----------------------------------------------------------------------------*/ -/** -* -* This function identifies the dimm on which the given memory address locates. -* -* @param[in, out] *AmdDimmIdentify - Pointer to the parameter structure AMD_IDENTIFY_DIMM -* -* @retval AGESA_SUCCESS - Successfully translate physical system address -* to dimm identification. -* AGESA_BOUNDS_CHK - Targeted address is out of bound. -* -*/ - -AGESA_STATUS -AmdIdentifyDimm ( - IN OUT AMD_IDENTIFY_DIMM *AmdDimmIdentify - ) -{ - UINT8 i; - AGESA_STATUS RetVal; - MEM_MAIN_DATA_BLOCK mmData; // Main Data block - MEM_NB_BLOCK *NBPtr; - MEM_DATA_STRUCT MemData; - LOCATE_HEAP_PTR LocHeap; - ALLOCATE_HEAP_PARAMS AllocHeapParams; - UINT8 Node; - UINT8 Dct; - UINT8 Die; - UINT8 DieCount; - - LibAmdMemCopy (&(MemData.StdHeader), &(AmdDimmIdentify->StdHeader), sizeof (AMD_CONFIG_PARAMS), &(AmdDimmIdentify->StdHeader)); - mmData.MemPtr = &MemData; - RetVal = MemSocketScan (&mmData); - if (RetVal == AGESA_FATAL) { - return RetVal; - } - DieCount = mmData.DieCount; - - // Search for AMD_MEM_AUTO_HANDLE on the heap first. - // Only apply for space on the heap if cannot find AMD_MEM_AUTO_HANDLE on the heap. - LocHeap.BufferHandle = AMD_MEM_AUTO_HANDLE; - if (HeapLocateBuffer (&LocHeap, &AmdDimmIdentify->StdHeader) == AGESA_SUCCESS) { - // NB block has already been constructed by main block. - // No need to construct it here. - NBPtr = (MEM_NB_BLOCK *)LocHeap.BufferPtr; - mmData.NBPtr = NBPtr; - } else { - AllocHeapParams.RequestedBufferSize = (DieCount * (sizeof (MEM_NB_BLOCK))); - AllocHeapParams.BufferHandle = AMD_MEM_AUTO_HANDLE; - AllocHeapParams.Persist = HEAP_SYSTEM_MEM; - if (HeapAllocateBuffer (&AllocHeapParams, &AmdDimmIdentify->StdHeader) != AGESA_SUCCESS) { - PutEventLog (AGESA_FATAL, MEM_ERROR_HEAP_ALLOCATE_FOR_IDENTIFY_DIMM_MEM_NB_BLOCK, 0, 0, 0, 0, &AmdDimmIdentify->StdHeader); - ASSERT(FALSE); // Could not allocate heap space for NB block for Identify DIMM - return AGESA_FATAL; - } - NBPtr = (MEM_NB_BLOCK *)AllocHeapParams.BufferPtr; - mmData.NBPtr = NBPtr; - // Construct each die. - for (Die = 0; Die < DieCount; Die ++) { - i = 0; - while (memNBInstalled[i].MemIdentifyDimmConstruct != 0) { - if (memNBInstalled[i].MemIdentifyDimmConstruct (&NBPtr[Die], &MemData, Die)) { - break; - } - i++; - }; - if (memNBInstalled[i].MemIdentifyDimmConstruct == 0) { - PutEventLog (AGESA_FATAL, MEM_ERROR_NO_CONSTRUCTOR_FOR_IDENTIFY_DIMM, Die, 0, 0, 0, &AmdDimmIdentify->StdHeader); - ASSERT(FALSE); // No Identify DIMM constructor found - return AGESA_FATAL; - } - } - } - - if ((RetVal = MemFTransSysAddrToCS (AmdDimmIdentify, &mmData)) == AGESA_SUCCESS) { - // Translate Node, DCT and Chip select number to Socket, Channel and Dimm number. - Node = AmdDimmIdentify->SocketId; - Dct = AmdDimmIdentify->MemChannelId; - AmdDimmIdentify->SocketId = MemData.DiesPerSystem[Node].SocketId; - AmdDimmIdentify->MemChannelId = NBPtr[Node].GetSocketRelativeChannel (&NBPtr[Node], Dct, 0); - AmdDimmIdentify->DimmId /= 2; - } - - return RetVal; -} - - -/*---------------------------------------------------------------------------- - * LOCAL FUNCTIONS - * - *---------------------------------------------------------------------------- - */ - -/*-----------------------------------------------------------------------------*/ -/** -* -* This function translates the given physical system address to -* a node, channel select, chip select, bank, row, and column address. -* -* @param[in, out] *AmdDimmIdentify - Pointer to the parameter structure AMD_IDENTIFY_DIMM -* @param[in, out] *mmPtr - Pointer to the MEM_MAIN_DATA_BLOCK -* -* @retval AGESA_SUCCESS - The chip select address is found -* @retval AGESA_BOUNDS_CHK - Targeted address is out of bound. -* -*/ -AGESA_STATUS -STATIC -MemFTransSysAddrToCS ( - IN OUT AMD_IDENTIFY_DIMM *AmdDimmIdentify, - IN MEM_MAIN_DATA_BLOCK *mmPtr - ) -{ - BOOLEAN CSFound; - BOOLEAN DctSelHiRngEn; - BOOLEAN DctSelIntLvEn; - BOOLEAN DctGangEn; - BOOLEAN HiRangeSelected; - BOOLEAN DramHoleValid; - BOOLEAN CSEn; - BOOLEAN SwapDone; - BOOLEAN IntLvRgnSwapEn; - UINT8 DctSelHi; - UINT8 DramEn; - UINT8 range; - UINT8 IntlvEn; - UINT8 IntlvSel; - UINT8 ILog; - UINT8 DctSelIntLvAddr; - UINT8 DctNum; - UINT8 cs; - UINT8 BadDramCs; - UINT8 spare; - UINT8 IntLvRgnBaseAddr; - UINT8 IntLvRgnLmtAddr; - UINT8 IntLvRgnSize; - UINT32 temp; - UINT32 DramHoleOffset; - UINT32 DramHoleBase; - UINT64 DramBase; - UINT64 DramLimit; - UINT64 DramLimitSysAddr; - UINT64 DctSelBaseAddr; - UINT64 DctSelBaseOffset; - UINT64 ChannelAddr; - UINT64 CSBase; - UINT64 CSMask; - UINT64 InputAddr; - UINT64 ChannelOffset; - MEM_NB_BLOCK *NBPtr; - UINT8 Die; - - UINT64 SysAddr; - UINT8 *NodeID; - UINT8 *ChannelSelect; - UINT8 *ChipSelect; - - SysAddr = AmdDimmIdentify->MemoryAddress; - NodeID = &(AmdDimmIdentify->SocketId); - ChannelSelect = &(AmdDimmIdentify->MemChannelId); - ChipSelect = &(AmdDimmIdentify->DimmId); - CSFound = FALSE; - ILog = 0; - NBPtr = mmPtr->NBPtr; - - NBPtr->FamilySpecificHook[FixupSysAddr] (NBPtr, &SysAddr); - - // Loop to determine the dram range - for (Die = 0; Die < mmPtr->DieCount; Die ++) { - range = NBPtr[Die].Node; - - // DRAM Base - temp = MemFGetPCI (NBPtr, 0, 0, BFDramBaseReg0 + range); - DramEn = (UINT8) (temp & 0x3); - IntlvEn = (UINT8) ((temp >> 8) & 0x7); - - DramBase = ((UINT64) (MemFGetPCI (NBPtr, 0, 0, BFDramBaseHiReg0 + range) & 0xFF) << 40) | - (((UINT64) temp & 0xFFFF0000) << 8); - - // DRAM Limit - temp = MemFGetPCI (NBPtr, 0, 0, BFDramLimitReg0 + range); - *NodeID = (UINT8) (temp & 0x7); - IntlvSel = (UINT8) ((temp >> 8) & 0x7); - DramLimit = ((UINT64) (MemFGetPCI (NBPtr, 0, 0, BFDramLimitHiReg0 + range) & 0xFF) << 40) | - (((UINT64) temp << 8) | 0xFFFFFF); - DramLimitSysAddr = (((UINT64) MemFGetPCI (NBPtr, *NodeID, 0, BFDramLimitAddr)) << 27) | 0x7FFFFFF; - ASSERT (DramLimit <= DramLimitSysAddr); - - if ((DramEn != 0) && (DramBase <= SysAddr) && (SysAddr <= DramLimitSysAddr) && - ((IntlvEn == 0) || (IntlvSel == ((SysAddr >> 12) & IntlvEn)))) { - // Determine the number of bit positions consumed by Node Interleaving - switch (IntlvEn) { - - case 0x0: - ILog = 0; - break; - - case 0x1: - ILog = 1; - break; - - case 0x3: - ILog = 2; - break; - - case 0x7: - ILog = 3; - break; - - default: - IDS_ERROR_TRAP; - } - - DramHoleOffset = MemFGetPCI (NBPtr, *NodeID, 0, BFDramHoleOffset) << 23; - DramHoleValid = (BOOLEAN) MemFGetPCI (NBPtr, *NodeID, 0, BFDramHoleValid); - DramHoleBase = MemFGetPCI (NBPtr, *NodeID, 0, BFDramHoleBase) << 24; - // Address belongs to this node based on DramBase/Limit, - // but is in the memory hole so it doesn't map to DRAM - if (DramHoleValid && (DramHoleBase <= SysAddr) && (SysAddr < 0x100000000)) { - return AGESA_BOUNDS_CHK; - } - - // F2x10C Swapped Interleaved Region - IntLvRgnSwapEn = (BOOLEAN) MemFGetPCI (NBPtr, *NodeID, 0, BFIntLvRgnSwapEn); - if (IntLvRgnSwapEn) { - IntLvRgnBaseAddr = (UINT8) MemFGetPCI (NBPtr, *NodeID, 0, BFIntLvRgnBaseAddr); - IntLvRgnLmtAddr = (UINT8) MemFGetPCI (NBPtr, *NodeID, 0, BFIntLvRgnLmtAddr); - IntLvRgnSize = (UINT8) MemFGetPCI (NBPtr, *NodeID, 0, BFIntLvRgnSize); - ASSERT (IntLvRgnSize == (IntLvRgnLmtAddr - IntLvRgnBaseAddr + 1)); - if (((SysAddr >> 34) == 0) && - ((((SysAddr >> 27) >= IntLvRgnBaseAddr) && ((SysAddr >> 27) <= IntLvRgnLmtAddr)) - || ((SysAddr >> 27) < IntLvRgnSize))) { - SysAddr ^= (UINT64) IntLvRgnBaseAddr << 27; - } - } - - // Extract variables from F2x110 DRAM Controller Select Low Register - DctSelHiRngEn = (BOOLEAN) MemFGetPCI (NBPtr, *NodeID, 0, BFDctSelHiRngEn); - DctSelHi = (UINT8) MemFGetPCI (NBPtr, *NodeID, 0, BFDctSelHi); - DctSelIntLvEn = (BOOLEAN) MemFGetPCI (NBPtr, *NodeID, 0, BFDctSelIntLvEn); - DctGangEn = (BOOLEAN) MemFGetPCI (NBPtr, *NodeID, 0, BFDctGangEn); - DctSelIntLvAddr = (UINT8) MemFGetPCI (NBPtr, *NodeID, 0, BFDctSelIntLvAddr); - DctSelBaseAddr = (UINT64) MemFGetPCI (NBPtr, *NodeID, 0, BFDctSelBaseAddr) << 27; - DctSelBaseOffset = (UINT64) MemFGetPCI (NBPtr, *NodeID, 0, BFDctSelBaseOffset) << 26; - - - // Determine if high DCT address range is being selected - if (DctSelHiRngEn && !DctGangEn && (SysAddr >= DctSelBaseAddr)) { - HiRangeSelected = TRUE; - } else { - HiRangeSelected = FALSE; - } - - // Determine Channel - if (DctGangEn) { - *ChannelSelect = (UINT8) ((SysAddr >> 3) & 0x1); - } else if (HiRangeSelected) { - *ChannelSelect = DctSelHi; - } else if (DctSelIntLvEn && (DctSelIntLvAddr == 0)) { - *ChannelSelect = (UINT8) ((SysAddr >> 6) & 0x1); - } else if (DctSelIntLvEn && (((DctSelIntLvAddr >> 1) & 0x1) != 0)) { - temp = MemFUnaryXOR ((UINT32) ((SysAddr >> 16) & 0x1F)); - if ((DctSelIntLvAddr & 0x1) != 0) { - *ChannelSelect = (UINT8) (((SysAddr >> 9) & 0x1) ^ temp); - } else { - *ChannelSelect = (UINT8) (((SysAddr >> 6) & 0x1) ^ temp); - } - } else if (DctSelIntLvEn) { - *ChannelSelect = (UINT8) ((SysAddr >> (12 + ILog)) & 0x1); - } else if (DctSelHiRngEn) { - *ChannelSelect = ~DctSelHi & 0x1; - } else { - *ChannelSelect = 0; - } - ASSERT (*ChannelSelect < NBPtr[*NodeID].DctCount); - - // Determine base address offset - if (HiRangeSelected) { - if ((DctSelBaseAddr < DramHoleBase) && DramHoleValid && (SysAddr >= (UINT64) 0x100000000)) { - ChannelOffset = (UINT64) DramHoleOffset; - } else { - ChannelOffset = DctSelBaseOffset; - } - } else { - if (DramHoleValid && (SysAddr >= (UINT64) 0x100000000)) { - ChannelOffset = (UINT64) DramHoleOffset; - } else { - ChannelOffset = DramBase; - } - } - - // Remove hoisting offset and normalize to DRAM bus addresses - ChannelAddr = SysAddr - ChannelOffset; - - // Remove node interleaving - if (IntlvEn != 0) { - ChannelAddr = ((ChannelAddr >> (12 + ILog)) << 12) | (ChannelAddr & 0xFFF); - } - - // Remove channel interleave - if (DctSelIntLvEn && !HiRangeSelected && !DctGangEn) { - if ((DctSelIntLvAddr & 1) != 1) { - // A[6] Select or Hash 6 - ChannelAddr = ((ChannelAddr >> 7) << 6) | (ChannelAddr & 0x3F); - } else if (DctSelIntLvAddr == 1) { - // A[12] - ChannelAddr = ((ChannelAddr >> 13) << 12) | (ChannelAddr & 0xFFF); - } else { - // Hash 9 - ChannelAddr = ((ChannelAddr >> 10) << 9) | (ChannelAddr & 0x1FF); - } - } - - // Determine the Chip Select - for (cs = 0; cs < MAX_CS_PER_CHANNEL; ++ cs) { - DctNum = DctGangEn ? 0 : *ChannelSelect; - - // Obtain the CS Base - temp = MemFGetPCI (NBPtr, *NodeID, DctNum, BFCSBaseAddr0Reg + cs); - CSEn = (BOOLEAN) (temp & 0x1); - CSBase = ((UINT64) temp & NBPtr->CsRegMsk) << 8; - - // Obtain the CS Mask - CSMask = ((UINT64) MemFGetPCI (NBPtr, *NodeID, DctNum, BFCSMask0Reg + (cs >> 1)) & NBPtr->CsRegMsk) << 8; - - // Adjust the Channel Addr for easy comparison - InputAddr = ((ChannelAddr >> 8) & NBPtr->CsRegMsk) << 8; - - if (CSEn && ((InputAddr & ~CSMask) == (CSBase & ~CSMask))) { - CSFound = TRUE; - - *ChipSelect = cs; - - temp = MemFGetPCI (NBPtr, *NodeID, 0, BFOnLineSpareControl); - SwapDone = (BOOLEAN) ((temp >> (1 + 2 * (*ChannelSelect))) & 0x1); - BadDramCs = (UINT8) ((temp >> (4 + 4 * (*ChannelSelect))) & 0x7); - if (SwapDone && (cs == BadDramCs)) { - // Find the spare rank for the channel - for (spare = 0; spare < MAX_CS_PER_CHANNEL; ++spare) { - if ((MemFGetPCI (NBPtr, *NodeID, DctNum, BFCSBaseAddr0Reg + spare) & 0x2) != 0) { - *ChipSelect = spare; - break; - } - } - } - ASSERT (*ChipSelect < MAX_CS_PER_CHANNEL); - - break; - } - } - } - if (CSFound) { - break; - } - } - - // last ditch sanity check - ASSERT (!CSFound || ((*NodeID < mmPtr->DieCount) && (*ChannelSelect < NBPtr[*NodeID].DctCount) && (*ChipSelect < MAX_CS_PER_CHANNEL))); - if (CSFound) { - return AGESA_SUCCESS; - } else { - return AGESA_BOUNDS_CHK; - } - -} - - -/*-----------------------------------------------------------------------------*/ -/** -* -* This function is the interface to call the PCI register access function -* defined in NB block. -* -* @param[in] *NBPtr - Pointer to the parameter structure MEM_NB_BLOCK -* @param[in] NodeID - Node ID number of the target Northbridge -* @param[in] DctNum - DCT number if applicable, otherwise, put 0 -* @param[in] BitFieldName - targeted bitfield -* -* @retval UINT32 - 32 bits PCI register value -* -*/ -UINT32 -STATIC -MemFGetPCI ( - IN MEM_NB_BLOCK *NBPtr, - IN UINT8 NodeID, - IN UINT8 DctNum, - IN BIT_FIELD_NAME BitFieldName - ) -{ - MEM_NB_BLOCK *LocalNBPtr; - UINT8 Die; - - // Find NBBlock that associates with node NodeID - for (Die = 0; Die < MAX_NODES_SUPPORTED; Die ++) - if (NBPtr[Die].Node == NodeID) - break; - - ASSERT (Die < MAX_NODES_SUPPORTED); - - // Get the northbridge pointer for the targeted node. - LocalNBPtr = &NBPtr[Die]; - LocalNBPtr->FamilySpecificHook[DCTSelectSwitch] (LocalNBPtr, &DctNum); - LocalNBPtr->Dct = DctNum; - // The caller of this function will take care of the ganged/unganged situation. - // So Ganged is set to be false here, and do PCI read on the DCT specified by DctNum. - return LocalNBPtr->GetBitField (LocalNBPtr, BitFieldName); -} - -/*-----------------------------------------------------------------------------*/ -/** -* -* This function returns an even parity bit (making the total # of 1's even) -* {0, 1} = number of set bits in argument is {even, odd}. -* -* @param[in] address - the address on which the parity bit will be calculated -* -* @retval UINT8 - parity bit -* -*/ - -UINT8 -STATIC -MemFUnaryXOR ( - IN UINT32 address - ) -{ - UINT8 parity; - UINT8 index; - parity = 0; - for (index = 0; index < 32; ++ index) { - parity = (UINT8) (parity ^ (address & 0x1)); - address = address >> 1; - } - return parity; -} |