/** * * * This function initialize needed data structures for S3 resume. * * @param[in, out] **S3NBPtr - Pointer to the pointer of northbridge block. * @param[in, out] *MemPtr - Pointer to MEM_DATA_STRUCT. * @param[in, out] *mmData - Pointer to MEM_MAIN_DATA_BLOCK. * @param[in] *StdHeader - Config handle for library and services. * * @return AGESA_STATUS * - AGESA_ALERT * - AGESA_FATAL * - AGESA_SUCCESS * - AGESA_WARNING */ AGESA_STATUS MemS3InitNB ( IN OUT S3_MEM_NB_BLOCK **S3NBPtr, IN OUT MEM_DATA_STRUCT **MemPtr, IN OUT MEM_MAIN_DATA_BLOCK *mmData, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 i; AGESA_STATUS RetVal; LOCATE_HEAP_PTR LocHeap; MEM_NB_BLOCK *NBPtr; ALLOCATE_HEAP_PARAMS AllocHeapParams; UINT8 Die; UINT8 DieCount; BOOLEAN SkipScan; SkipScan = FALSE; LocHeap.BufferHandle = AMD_MEM_DATA_HANDLE; if (HeapLocateBuffer (&LocHeap, StdHeader) == AGESA_SUCCESS) { // NB block has already been constructed by main block. // No need to construct it here. *MemPtr = (MEM_DATA_STRUCT *)LocHeap.BufferPtr; SkipScan = TRUE; } else { AllocHeapParams.RequestedBufferSize = sizeof (MEM_DATA_STRUCT); AllocHeapParams.BufferHandle = AMD_MEM_DATA_HANDLE; AllocHeapParams.Persist = HEAP_SYSTEM_MEM; if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) != AGESA_SUCCESS) { ASSERT(FALSE); // Allocate failed for MEM_DATA_STRUCT return AGESA_FATAL; } *MemPtr = (MEM_DATA_STRUCT *)AllocHeapParams.BufferPtr; } LibAmdMemCopy (&(*MemPtr)->StdHeader, StdHeader, sizeof (AMD_CONFIG_PARAMS), StdHeader); mmData->MemPtr = *MemPtr; if (!SkipScan) { RetVal = MemSocketScan (mmData); if (RetVal == AGESA_FATAL) { return RetVal; } } else { // We already have initialize data block, no need to do it again. mmData->DieCount = mmData->MemPtr->DieCount; } DieCount = mmData->DieCount; //--------------------------------------------- // Creation of NB Block for S3 resume //--------------------------------------------- // 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_S3_NB_HANDLE; if (HeapLocateBuffer (&LocHeap, StdHeader) == AGESA_SUCCESS) { // NB block has already been constructed by main block. // No need to construct it here. *S3NBPtr = (S3_MEM_NB_BLOCK *)LocHeap.BufferPtr; } else { AllocHeapParams.RequestedBufferSize = (DieCount * (sizeof (S3_MEM_NB_BLOCK))); AllocHeapParams.BufferHandle = AMD_MEM_S3_NB_HANDLE; AllocHeapParams.Persist = HEAP_SYSTEM_MEM; if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) != AGESA_SUCCESS) { ASSERT(FALSE); // Could not allocate space for "S3_MEM_NB_BLOCK" return AGESA_FATAL; } *S3NBPtr = (S3_MEM_NB_BLOCK *)AllocHeapParams.BufferPtr; LocHeap.BufferHandle = AMD_MEM_AUTO_HANDLE; if (HeapLocateBuffer (&LocHeap, StdHeader) == AGESA_SUCCESS) { // NB block has already been constructed by main block. // No need to construct it here. NBPtr = (MEM_NB_BLOCK *)LocHeap.BufferPtr; } else { AllocHeapParams.RequestedBufferSize = (DieCount * (sizeof (MEM_NB_BLOCK))); AllocHeapParams.BufferHandle = AMD_MEM_AUTO_HANDLE; AllocHeapParams.Persist = HEAP_SYSTEM_MEM; if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) != AGESA_SUCCESS) { ASSERT(FALSE); // Allocate failed for "MEM_NB_BLOCK" return AGESA_FATAL; } NBPtr = (MEM_NB_BLOCK *)AllocHeapParams.BufferPtr; } // Construct each die. for (Die = 0; Die < DieCount; Die ++) { i = 0; ((*S3NBPtr)[Die]).NBPtr = &NBPtr[Die]; while (memNBInstalled[i].MemS3ResumeConstructNBBlock != 0) { if (memNBInstalled[i].MemS3ResumeConstructNBBlock ((VOID *)&((*S3NBPtr)[Die]), *MemPtr, Die)) { break; } i++; }; if (memNBInstalled[i].MemS3ResumeConstructNBBlock == 0) { ASSERT(FALSE); // S3 resume NB constructor not found return AGESA_FATAL; } } } return AGESA_SUCCESS; }
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; } } } i = 0; while (memNBInstalled[i].MemIdentifyDimmConstruct != 0) { if ((RetVal = memNBInstalled[i].MemTransSysAddrToCs (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 = AmdDimmIdentify->ChipSelect / 2; AmdDimmIdentify->ChipSelect %= 2; break; } i++; }; return RetVal; }
/** * * * This function is the main memory configuration function for DR 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 AmdMemAuto ( IN OUT MEM_DATA_STRUCT *MemPtr ) { MEM_SHARED_DATA mmSharedData; MEM_MAIN_DATA_BLOCK mmData; MEM_NB_BLOCK *NBPtr; MEM_TECH_BLOCK *TechPtr; ALLOCATE_HEAP_PARAMS AllocHeapParams; AGESA_STATUS Retval; UINT8 i; UINT8 Die; UINT8 DieCount; UINT8 Tab; CPU_SPECIFIC_SERVICES *FamilySpecificServices; ASSERT (MemPtr != NULL); AGESA_TESTPOINT (TpProcMemAmdMemAuto, &MemPtr->StdHeader); IDS_HDT_CONSOLE (MEM_FLOW, "MEM PARAMS:\n"); IDS_HDT_CONSOLE (MEM_FLOW, "\tBottomIo : %04x\n", MemPtr->ParameterListPtr->BottomIo); IDS_HDT_CONSOLE (MEM_FLOW, "\tMemHoleRemap : %d\n", MemPtr->ParameterListPtr->MemHoleRemapping); IDS_HDT_CONSOLE (MEM_FLOW, "\tLimitBelow1TB : %d\n", MemPtr->ParameterListPtr->LimitMemoryToBelow1Tb); IDS_HDT_CONSOLE (MEM_FLOW, "\tUserTimingMode : %d\n", MemPtr->ParameterListPtr->UserTimingMode); IDS_HDT_CONSOLE (MEM_FLOW, "\tMemClockValue : %d\n", MemPtr->ParameterListPtr->MemClockValue); IDS_HDT_CONSOLE (MEM_FLOW, "\tBankIntlv : %d\n", MemPtr->ParameterListPtr->EnableBankIntlv); IDS_HDT_CONSOLE (MEM_FLOW, "\tNodeIntlv : %d\n", MemPtr->ParameterListPtr->EnableNodeIntlv); IDS_HDT_CONSOLE (MEM_FLOW, "\tChannelIntlv : %d\n", MemPtr->ParameterListPtr->EnableChannelIntlv); IDS_HDT_CONSOLE (MEM_FLOW, "\tEccFeature : %d\n", MemPtr->ParameterListPtr->EnableEccFeature); IDS_HDT_CONSOLE (MEM_FLOW, "\tPowerDown : %d\n", MemPtr->ParameterListPtr->EnablePowerDown); IDS_HDT_CONSOLE (MEM_FLOW, "\tOnLineSpare : %d\n", MemPtr->ParameterListPtr->EnableOnLineSpareCtl); IDS_HDT_CONSOLE (MEM_FLOW, "\tParity : %d\n", MemPtr->ParameterListPtr->EnableParity); IDS_HDT_CONSOLE (MEM_FLOW, "\tBankSwizzle : %d\n", MemPtr->ParameterListPtr->EnableBankSwizzle); IDS_HDT_CONSOLE (MEM_FLOW, "\tMemClr : %d\n", MemPtr->ParameterListPtr->EnableMemClr); IDS_HDT_CONSOLE (MEM_FLOW, "\tUmaMode : %d\n", MemPtr->ParameterListPtr->UmaMode); IDS_HDT_CONSOLE (MEM_FLOW, "\tUmaSize : %d\n", MemPtr->ParameterListPtr->UmaSize); IDS_HDT_CONSOLE (MEM_FLOW, "\tMemRestoreCtl : %d\n", MemPtr->ParameterListPtr->MemRestoreCtl); IDS_HDT_CONSOLE (MEM_FLOW, "\tSaveMemContextCtl : %d\n", MemPtr->ParameterListPtr->SaveMemContextCtl); IDS_HDT_CONSOLE (MEM_FLOW, "\tExternalVrefCtl : %d\n", MemPtr->ParameterListPtr->ExternalVrefCtl ); IDS_HDT_CONSOLE (MEM_FLOW, "\tForceTrainMode : %d\n\n", MemPtr->ParameterListPtr->ForceTrainMode ); //---------------------------------------------------------------------------- // Get TSC rate, which will be used later in Wait10ns routine //---------------------------------------------------------------------------- GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, &MemPtr->StdHeader); FamilySpecificServices->GetTscRate (FamilySpecificServices, &MemPtr->TscRate, &MemPtr->StdHeader); //---------------------------------------------------------------------------- // Read In SPD Data //---------------------------------------------------------------------------- AGESA_TESTPOINT (TpProcMemBeforeSpdProcessing, &MemPtr->StdHeader); MemSPDDataProcess (MemPtr); //---------------------------------------------------------------- // Initialize Main Data Block //---------------------------------------------------------------- mmData.MemPtr = MemPtr; mmData.mmSharedPtr = &mmSharedData; LibAmdMemFill (&mmSharedData, 0, sizeof (mmSharedData), &MemPtr->StdHeader); mmSharedData.DimmExcludeFlag = NORMAL; mmSharedData.NodeIntlv.IsValid = FALSE; //---------------------------------------------------------------- // Discover populated CPUs // //---------------------------------------------------------------- Retval = MemSocketScan (&mmData); if (Retval == AGESA_FATAL) { return Retval; } DieCount = mmData.DieCount; //---------------------------------------------------------------- // // Allocate Memory for NB and Tech Blocks // // NBPtr[Die]----+ // | // V // +---+---+---+---+---+---+---+---+ // | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | NB Blocks // +---+---+---+---+---+---+---+---+ // | | | | | | | | // | | | | | | | | // v v v v v v v v // +---+---+---+---+---+---+---+---+ // | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | Tech Blocks // +---+---+---+---+---+---+---+---+ // // //---------------------------------------------------------------- AllocHeapParams.RequestedBufferSize = (DieCount * (sizeof (MEM_NB_BLOCK) + sizeof (MEM_TECH_BLOCK))); AllocHeapParams.BufferHandle = AMD_MEM_AUTO_HANDLE; AllocHeapParams.Persist = HEAP_LOCAL_CACHE; if (AGESA_SUCCESS != HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader)) { ASSERT(FALSE); // NB and Tech Block Heap allocate error return AGESA_FATAL; } NBPtr = (MEM_NB_BLOCK *)AllocHeapParams.BufferPtr; TechPtr = (MEM_TECH_BLOCK *) (&NBPtr[DieCount]); mmData.NBPtr = NBPtr; mmData.TechPtr = TechPtr; //---------------------------------------------------------------- // Create NB Blocks // //---------------------------------------------------------------- for (Die = 0 ; Die < DieCount ; Die++ ) { i = 0; while (memNBInstalled[i].MemConstructNBBlock != 0) { if (memNBInstalled[i].MemConstructNBBlock (&NBPtr[Die], MemPtr, memNBInstalled[i].MemFeatBlock, &mmSharedData, Die) == TRUE) { break; } i++; } // Couldn't find a NB which supported this family if (memNBInstalled[i].MemConstructNBBlock == 0) { return AGESA_FATAL; } } //---------------------------------------------------------------- // Create Technology Blocks // //---------------------------------------------------------------- for (Die = 0 ; Die < DieCount ; Die++ ) { i = 0; while (memTechInstalled[i] != NULL) { if (memTechInstalled[i] (&TechPtr[Die], &NBPtr[Die])) { NBPtr[Die].TechPtr = &TechPtr[Die]; break; } i++; } // Couldn't find a Tech block which supported this family if (memTechInstalled[i] == NULL) { return AGESA_FATAL; } } //---------------------------------------------------------------- // // MEMORY INITIALIZATION TASKS // //---------------------------------------------------------------- i = 0; while (memFlowControlInstalled[i] != NULL) { Retval = memFlowControlInstalled[i] (&mmData); if (MemPtr->IsFlowControlSupported == TRUE) { break; } i++; } //---------------------------------------------------------------- // Deallocate NB register tables //---------------------------------------------------------------- for (Tab = 0; Tab < NumberOfNbRegTables; Tab++) { HeapDeallocateBuffer (GENERATE_MEM_HANDLE (ALLOC_NB_REG_TABLE, Tab, 0, 0), &MemPtr->StdHeader); } //---------------------------------------------------------------- // Check for errors and return //---------------------------------------------------------------- AGESA_TESTPOINT (TpProcMemEnd, &MemPtr->StdHeader); for (Die = 0; Die < DieCount; Die++) { if (NBPtr[Die].MCTPtr->ErrCode > Retval) { Retval = NBPtr[Die].MCTPtr->ErrCode; } } return Retval; }