diff options
Diffstat (limited to 'src/vendorcode/amd/agesa/f12/Proc/Recovery/Mem/mrm.c')
-rwxr-xr-x | src/vendorcode/amd/agesa/f12/Proc/Recovery/Mem/mrm.c | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f12/Proc/Recovery/Mem/mrm.c b/src/vendorcode/amd/agesa/f12/Proc/Recovery/Mem/mrm.c new file mode 100755 index 0000000000..10a8b9f83c --- /dev/null +++ b/src/vendorcode/amd/agesa/f12/Proc/Recovery/Mem/mrm.c @@ -0,0 +1,288 @@ +/* $NoKeywords:$ */ +/** + * @file + * + * mrm.c + * + * Main configuration for Recovery mode + * + * @xrefitem bom "File Content Label" "Release Content" + * @e project: AGESA + * @e sub-project: (Proc/Recovery/Mem) + * @e \$Revision: 48317 $ @e \$Date: 2011-03-08 01:38:14 +0800 (Tue, 08 Mar 2011) $ + * + **/ +/***************************************************************************** +* +* Copyright (c) 2011, 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 "Ids.h" +#include "amdlib.h" +#include "GeneralServices.h" +#include "heapManager.h" +#include "cpuRegisters.h" +#include "cpuServices.h" +#include "OptionMemoryRecovery.h" +#include "mm.h" +#include "mn.h" +#include "mt.h" +#include "Filecode.h" +CODE_GROUP (G2_PEI) +RDATA_GROUP (G2_PEI) + +#define FILECODE PROC_RECOVERY_MEM_MRM_FILECODE +/*---------------------------------------------------------------------------- + * DEFINITIONS AND MACROS + * + *---------------------------------------------------------------------------- + */ +#define MAX_DIES_PER_SOCKET 2 + +/*---------------------------------------------------------------------------- + * TYPEDEFS AND STRUCTURES + * + *---------------------------------------------------------------------------- + */ +extern MEM_REC_NB_CONSTRUCTOR* MemRecNBInstalled[]; +extern MEM_REC_TECH_CONSTRUCTOR* MemRecTechInstalled[]; + +/*---------------------------------------------------------------------------- + * PROTOTYPES OF LOCAL FUNCTIONS + * + *---------------------------------------------------------------------------- + */ + +VOID +STATIC +MemRecSPDDataProcess ( + IN OUT MEM_DATA_STRUCT *MemPtr + ); + +/*---------------------------------------------------------------------------- + * EXPORTED FUNCTIONS + * + *---------------------------------------------------------------------------- + */ +/* -----------------------------------------------------------------------------*/ +/** + * + * This function is the Recovery memory configuration function for HY DDR3 + * + * Requirements: + * + * Run-Time Requirements: + * 1. Complete Hypertransport Bus Configuration + * 2. AmdMemInitDataStructDef must be run to set default values + * 3. MSR bit to allow access to high PCI regs set on all nodes + * 4. BSP in Big Real Mode + * 5. Stack available + * 6. MCG_CTL=-1, MC4_EN=0 for all CPUs + * 7. MCi_STS from shutdown/warm reset recorded (if desired) prior to entry + * 8. All var MTRRs reset to zero + * 9. State of NB_CFG.DisDatMsk set properly on all CPUs + * + * @param[in,out] *MemPtr - Pointer to the MEM_DATA_STRUCT + * + * @return AGESA_STATUS + * - AGESA_ALERT + * - AGESA_FATAL + * - AGESA_SUCCESS + * - AGESA_WARNING + */ + +AGESA_STATUS +AmdMemRecovery ( + IN OUT MEM_DATA_STRUCT *MemPtr + ) +{ + UINT8 Socket; + UINT8 Module; + UINT8 i; + AGESA_STATUS AgesaStatus; + PCI_ADDR Address; + MEM_NB_BLOCK NBBlock; + MEM_TECH_BLOCK TechBlock; + LOCATE_HEAP_PTR SocketWithMem; + ALLOCATE_HEAP_PARAMS AllocHeapParams; + + + // + // Read SPD data + // + MemRecSPDDataProcess (MemPtr); + + // + // Get the socket id from heap. + // + SocketWithMem.BufferHandle = AMD_REC_MEM_SOCKET_HANDLE; + if (HeapLocateBuffer (&SocketWithMem, &MemPtr->StdHeader) == AGESA_SUCCESS) { + Socket = *(UINT8 *) SocketWithMem.BufferPtr; + } else { + ASSERT(FALSE); // Socket handle not found + return AGESA_FATAL; + } + + // + // Allocate buffer for memory init structures + // + AllocHeapParams.RequestedBufferSize = MAX_DIES_PER_SOCKET * sizeof (DIE_STRUCT); + AllocHeapParams.BufferHandle = GENERATE_MEM_HANDLE (ALLOC_DIE_STRUCT_HANDLE, 0, 0, 0); + AllocHeapParams.Persist = HEAP_LOCAL_CACHE; + if (HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader) != AGESA_SUCCESS) { + ASSERT(FALSE); // Heap allocation failed to allocate Die struct + return AGESA_FATAL; + } + MemPtr->DiesPerSystem = (DIE_STRUCT *)AllocHeapParams.BufferPtr; + + // + // Discover populated CPUs + // + for (Module = 0; Module < MAX_DIES_PER_SOCKET; Module++) { + if (GetPciAddress ((VOID *)MemPtr, Socket, Module, &Address, &AgesaStatus)) { + MemPtr->DiesPerSystem[Module].SocketId = Socket; + MemPtr->DiesPerSystem[Module].DieId = Module; + MemPtr->DiesPerSystem[Module].PciAddr.AddressValue = Address.AddressValue; + } + } + + i = 0; + while (MemRecNBInstalled[i] != NULL) { + if (MemRecNBInstalled[i] (&NBBlock, MemPtr, 0) == TRUE) { + break; + } + i++; + }; + if (MemRecNBInstalled[i] == NULL) { + ASSERT(FALSE); // No NB installed + return AGESA_FATAL; + } + MemRecTechInstalled[0] (&TechBlock, &NBBlock); + NBBlock.TechPtr = &TechBlock; + + return NBBlock.InitRecovery (&NBBlock); +} + +/*---------------------------------------------------------------------------- + * LOCAL FUNCTIONS + * + *---------------------------------------------------------------------------- + */ +/* -----------------------------------------------------------------------------*/ +/** + * + * This function fills a default SPD buffer with SPD values for all DIMMs installed in the system + * + * @param[in,out] *MemPtr - Pointer to the MEM_DATA_STRUCT + * + */ + +VOID +STATIC +MemRecSPDDataProcess ( + IN OUT MEM_DATA_STRUCT *MemPtr + ) +{ + BOOLEAN FindSocketWithMem; + UINT8 Channel; + UINT8 Dimm; + UINT8 MaxSockets; + UINT8 *SocketWithMem; + UINT8 Socket; + AGESA_STATUS AgesaStatus; + SPD_DEF_STRUCT *DimmSPDPtr; + ALLOCATE_HEAP_PARAMS AllocHeapParams; + AGESA_READ_SPD_PARAMS SpdParam; + ASSERT (MemPtr != NULL); + FindSocketWithMem = FALSE; + // + // Allocate heap to save socket number with memory on it. + // + AllocHeapParams.RequestedBufferSize = sizeof (UINT8); + AllocHeapParams.BufferHandle = AMD_REC_MEM_SOCKET_HANDLE; + AllocHeapParams.Persist = HEAP_LOCAL_CACHE; + if (HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader) == AGESA_SUCCESS) { + SocketWithMem = (UINT8 *) AllocHeapParams.BufferPtr; + *SocketWithMem = 0; + + // + // Allocate heap for the table + // + MaxSockets = (UINT8) GetPlatformNumberOfSockets (); + + AllocHeapParams.RequestedBufferSize = (MaxSockets * MAX_CHANNELS_PER_SOCKET * MAX_DIMMS_PER_CHANNEL * sizeof (SPD_DEF_STRUCT)); + AllocHeapParams.BufferHandle = AMD_MEM_SPD_HANDLE; + AllocHeapParams.Persist = HEAP_LOCAL_CACHE; + if (HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader) == AGESA_SUCCESS) { + MemPtr->SpdDataStructure = (SPD_DEF_STRUCT *) AllocHeapParams.BufferPtr; + // + // Initialize SpdParam Structure + // + LibAmdMemCopy ((VOID *)&SpdParam, (VOID *)MemPtr, (UINTN)sizeof (SpdParam.StdHeader), &MemPtr->StdHeader); + // + // Populate SPDDataBuffer + // + + SpdParam.MemData = MemPtr; + for (Socket = 0; Socket < MaxSockets; Socket ++) { + SpdParam.SocketId = Socket; + for (Channel = 0; Channel < MAX_CHANNELS_PER_SOCKET; Channel++) { + SpdParam.MemChannelId = Channel; + for (Dimm = 0; Dimm < MAX_DIMMS_PER_CHANNEL; Dimm++) { + SpdParam.DimmId = Dimm; + DimmSPDPtr = &(MemPtr->SpdDataStructure[(Socket * MAX_CHANNELS_PER_SOCKET + Channel) * MAX_DIMMS_PER_CHANNEL + Dimm]); + SpdParam.Buffer = DimmSPDPtr->Data; + AgesaStatus = AgesaReadSpdRecovery (0, &SpdParam); + if (AgesaStatus == AGESA_SUCCESS) { + DimmSPDPtr->DimmPresent = TRUE; + IDS_HDT_CONSOLE (MEM_FLOW, "SPD Socket %d Channel %d Dimm %d: %08x\n", Socket, Channel, Dimm, SpdParam.Buffer); + if (!FindSocketWithMem) { + FindSocketWithMem = TRUE; + } + } else { + DimmSPDPtr->DimmPresent = FALSE; + } + } + } + if (FindSocketWithMem) { + *SocketWithMem = Socket; + break; + } + } + } + } +} |