/** * A Family Specific Workaround method, to sync internal node 1 SbiAddr setting. * * @param[in] Data The table data value (unused in this routine) * @param[in] StdHeader Config handle for library and services * *--------------------------------------------------------------------------------------- **/ VOID STATIC F10RevDSyncInternalNode1SbiAddr ( IN UINT32 Data, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Socket; UINT32 Module; UINT32 DataOr; UINT32 DataAnd; UINT32 ModuleType; PCI_ADDR PciAddress; AGESA_STATUS AgesaStatus; UINT32 SyncToModule; AP_MAIL_INFO ApMailboxInfo; UINT32 LocalPciRegister; ApMailboxInfo.Info = 0; GetApMailbox (&ApMailboxInfo.Info, StdHeader); ASSERT (ApMailboxInfo.Fields.Socket < MAX_SOCKETS); ASSERT (ApMailboxInfo.Fields.Module < MAX_DIES); Socket = ApMailboxInfo.Fields.Socket; Module = ApMailboxInfo.Fields.Module; ModuleType = ApMailboxInfo.Fields.ModuleType; // sync is just needed on multinode cpu if (ModuleType != 0) { // check if it is internal node 0 of every socket if (Module == 0) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &AgesaStatus)) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = 0x1E4; // read internal node 0 F3x1E4[6:4] LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); DataOr = LocalPciRegister & ((UINT32) (7 << 4)); DataAnd = ~(UINT32) (7 << 4); for (SyncToModule = 1; SyncToModule < GetPlatformNumberOfModules (); SyncToModule++) { if (GetPciAddress (StdHeader, Socket, SyncToModule, &PciAddress, &AgesaStatus)) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = 0x1E4; // sync the other internal node F3x1E4[6:4] LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); LocalPciRegister &= DataAnd; LocalPciRegister |= DataOr; LibAmdPciWrite (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); } } } } } }
/** * Writes to all nodes on the executing core's socket. * * @param[in] PciAddress The Function and Register to update * @param[in] Mask The bitwise AND mask to apply to the current register value * @param[in] Data The bitwise OR mask to apply to the current register value * @param[in] StdHeader Header for library and services. * */ VOID ModifyCurrSocketPciMulti ( IN PCI_ADDR *PciAddress, IN UINT32 Mask, IN UINT32 Data, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Socket; UINT32 Module; UINT32 Core; UINT32 LocalPciRegister; AGESA_STATUS AgesaStatus; PCI_ADDR Reg; IdentifyCore (StdHeader, &Socket, &Module, &Core, &AgesaStatus); for (Module = 0; Module < (UINT8)GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &Reg, &AgesaStatus)) { Reg.Address.Function = PciAddress->Address.Function; Reg.Address.Register = PciAddress->Address.Register; LibAmdPciRead (AccessWidth32, Reg, &LocalPciRegister, StdHeader); LocalPciRegister &= Mask; LocalPciRegister |= Data; LibAmdPciWrite (AccessWidth32, Reg, &LocalPciRegister, StdHeader); } } }
/** * Check to see if the input CPU supports L3 dependent features. * * @param[in] L3FeatureServices L3 Feature family services. * @param[in] Socket Processor socket to check. * @param[in] StdHeader Config Handle for library, services. * @param[in] PlatformConfig Contains the runtime modifiable feature input data. * * @retval TRUE L3 dependent features are supported. * @retval FALSE L3 dependent features are not supported. * */ BOOLEAN STATIC F10IsL3FeatureSupported ( IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices, IN UINT32 Socket, IN AMD_CONFIG_PARAMS *StdHeader, IN PLATFORM_CONFIGURATION *PlatformConfig ) { UINT32 Module; UINT32 LocalPciRegister; BOOLEAN IsSupported; PCI_ADDR PciAddress; AGESA_STATUS IgnoredStatus; IsSupported = FALSE; if (PlatformConfig->PlatformProfile.UseHtAssist) { for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredStatus)) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = NB_CAPS_REG; LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); if (((NB_CAPS_REGISTER *) &LocalPciRegister)->L3Capable == 1) { IsSupported = TRUE; } break; } } } return IsSupported; }
/** * Main entry point for initializing the Thermal Control * safety net feature. * * This must be run by all Family 10h core 0s in the system. * * @param[in] FamilySpecificServices The current Family Specific Services. * @param[in] CpuEarlyParamsPtr Service parameters. * @param[in] StdHeader Config handle for library and services. */ VOID F10PmThermalInit ( IN CPU_SPECIFIC_SERVICES *FamilySpecificServices, IN AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Core; UINT32 Module; UINT32 LocalPciRegister; UINT32 Socket; PCI_ADDR PciAddress; AGESA_STATUS IgnoredSts; IdentifyCore (StdHeader, &Socket, &Module, &Core, &IgnoredSts); ASSERT (Core == 0); if (GetPciAddress (StdHeader, Socket, 0, &PciAddress, &IgnoredSts)) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = NB_CAPS_REG; LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); if (((NB_CAPS_REGISTER *) &LocalPciRegister)->HtcCapable == 1) { // Enable HTC PciAddress.Address.Register = HTC_REG; LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); ((HTC_REGISTER *) &LocalPciRegister)->HtcSlewSel = 0; ((HTC_REGISTER *) &LocalPciRegister)->HtcEn = 1; LibAmdPciWrite (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); } } }
/** * Multisocket call to determine if the BIOS is responsible for updating the * northbridge operating frequency and voltage. * * This function loops through all possible socket locations, checking whether * any populated sockets require NB COF VID programming. * * @param[in] StdHeader Config handle for library and services * * @retval TRUE BIOS needs to set up NB frequency and voltage * @retval FALSE BIOS does not need to set up NB frequency and voltage * */ BOOLEAN GetSystemNbCofVidUpdateMulti ( IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 Module; UINT32 Socket; UINT32 NumberOfSockets; BOOLEAN IgnoredBool; BOOLEAN AtLeast1RequiresUpdate; PCI_ADDR PciAddress; AGESA_STATUS Ignored; CPU_SPECIFIC_SERVICES *FamilySpecificServices; NumberOfSockets = GetPlatformNumberOfSockets (); AtLeast1RequiresUpdate = FALSE; for (Socket = 0; Socket < NumberOfSockets; Socket++) { if (IsProcessorPresent (Socket, StdHeader)) { GetCpuServicesOfSocket (Socket, (CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader); for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, (UINT8) Socket, Module, &PciAddress, &Ignored)) { break; } } if (FamilySpecificServices->IsNbCofInitNeeded (FamilySpecificServices, &PciAddress, &IgnoredBool, StdHeader)) { AtLeast1RequiresUpdate = TRUE; break; } } } return AtLeast1RequiresUpdate; }
/** * Clear EnableCf8ExtCfg on all socket * * Clear F3x8C bit 14 EnableCf8ExtCfg * * @param[in] StdHeader Config handle for library and services * * */ VOID DisableCf8ExtCfg ( IN AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS AgesaStatus; PCI_ADDR PciAddress; UINT32 Socket; UINT32 Module; UINT32 PciData; UINT32 LegacyPciAccess; ASSERT (IsBsp (StdHeader, &AgesaStatus)); for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &AgesaStatus)) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = NB_CFG_HIGH_REG; LegacyPciAccess = ((1 << 31) + (PciAddress.Address.Register & 0xFC) + (PciAddress.Address.Function << 8) + (PciAddress.Address.Device << 11) + (PciAddress.Address.Bus << 16) + ((PciAddress.Address.Register & 0xF00) << (24 - 8))); // read from PCI register LibAmdIoWrite (AccessWidth32, IOCF8, &LegacyPciAccess, StdHeader); LibAmdIoRead (AccessWidth32, IOCFC, &PciData, StdHeader); // Disable Cf8ExtCfg PciData &= 0xFFFFBFFF; // write to PCI register LibAmdIoWrite (AccessWidth32, IOCF8, &LegacyPciAccess, StdHeader); LibAmdIoWrite (AccessWidth32, IOCFC, &PciData, StdHeader); } } } }
/** * Ids Write PCI register to All node * * * @param[in] PciAddress Pci address * @param[in] Highbit High bit position of the field in DWORD * @param[in] Lowbit Low bit position of the field in DWORD * @param[in] Value Pointer to input value * @param[in] StdHeader Standard configuration header * */ VOID IdsLibPciWriteBitsToAllNode ( IN PCI_ADDR PciAddress, IN UINT8 Highbit, IN UINT8 Lowbit, IN UINT32 *Value, IN OUT AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Socket; UINT32 Module; AGESA_STATUS IgnoreStatus; PCI_ADDR PciAddr; for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddr, &IgnoreStatus)) { PciAddr.Address.Function = PciAddress.Address.Function; PciAddr.Address.Register = PciAddress.Address.Register; LibAmdPciWriteBits (PciAddr, Highbit, Lowbit, Value, StdHeader); } } } }
/** * Check to see if the input CPU supports HT Assist. * * @param[in] HtAssistServices HT Assist family services. * @param[in] Socket Processor socket to check. * @param[in] StdHeader Config Handle for library, services. * * @retval TRUE HT Assist is supported. * @retval FALSE HT Assist cannot be enabled. * */ BOOLEAN STATIC F10IsHtAssistSupported ( IN HT_ASSIST_FAMILY_SERVICES *HtAssistServices, IN UINT32 Socket, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Module; UINT32 PciRegister; BOOLEAN IsSupported; PCI_ADDR PciAddress; AGESA_STATUS IgnoredStatus; IsSupported = FALSE; for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredStatus)) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = NB_CAPS_REG; LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); if (((NB_CAPS_REGISTER *) &PciRegister)->L3Capable == 1) { IsSupported = TRUE; } break; } } return IsSupported; }
/** * This routine checks whether any non-coherent links in the system * runs in HT1 mode; used to determine whether certain features * should be disabled when this routine returns TRUE. * * @param[in] StdHeader Standard AMD configuration parameters. * * @retval TRUE One of the non-coherent links in the * system runs in HT1 mode * @retval FALSE None of the non-coherent links in the * system is running in HT1 mode */ BOOLEAN IsNonCoherentHt1 ( IN AMD_CONFIG_PARAMS *StdHeader ) { UINTN Link; UINT32 Socket; UINT32 Module; PCI_ADDR PciAddress; AGESA_STATUS AgesaStatus; HT_HOST_FEATS HtHostFeats; CPU_SPECIFIC_SERVICES *CpuServices; for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { if (IsProcessorPresent (Socket, StdHeader)) { GetCpuServicesOfSocket (Socket, &CpuServices, StdHeader); for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &AgesaStatus)) { HtHostFeats.HtHostValue = 0; Link = 0; while (CpuServices->GetNextHtLinkFeatures (CpuServices, &Link, &PciAddress, &HtHostFeats, StdHeader)) { // Return TRUE and exit routine once we find a non-coherent link in HT1 if ((HtHostFeats.HtHostFeatures.NonCoherent == 1) && (HtHostFeats.HtHostFeatures.Ht1 == 1)) { return TRUE; } } } } } } return FALSE; }
/** * * InitializeCacheFlushOnHaltFeature * * CPU feature leveling. Enable Cpu Cache Flush On Halt Function * * @param[in] EntryPoint Timepoint designator. * @param[in] PlatformConfig Contains the runtime modifiable feature input data. * @param[in,out] StdHeader Pointer to AMD_CONFIG_PARAMS struct. * * @return The most severe status of any family specific service. */ STATIC AGESA_STATUS InitializeCacheFlushOnHaltFeature ( IN UINT64 EntryPoint, IN PLATFORM_CONFIGURATION *PlatformConfig, IN OUT AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Socket; UINT32 Module; UINT32 AndMask; UINT32 OrMask; UINT32 PciRegister; PCI_ADDR PciAddress; PCI_ADDR CfohPciAddress; AGESA_STATUS AgesaStatus; CPU_CFOH_FAMILY_SERVICES *FamilySpecificServices; ASSERT (IsBsp (StdHeader, &AgesaStatus)); FamilySpecificServices = NULL; AndMask = 0xFFFFFFFF; OrMask = 0x00000000; PciRegister = 0; AgesaStatus = AGESA_SUCCESS; for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { if (IsProcessorPresent (Socket, StdHeader)) { // Get services for the socket GetFeatureServicesOfSocket (&CacheFlushOnHaltFamilyServiceTable, Socket, (CONST VOID **)&FamilySpecificServices, StdHeader); if (FamilySpecificServices != NULL) { FamilySpecificServices->GetCacheFlushOnHaltRegister (FamilySpecificServices, &CfohPciAddress, &AndMask, &OrMask, StdHeader); // Get the Or Mask value from IDS IDS_OPTION_HOOK (IDS_CACHE_FLUSH_HLT, &OrMask, StdHeader); // Set Cache Flush On Halt register for (Module = 0; Module < (UINT8)GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &AgesaStatus)) { PciAddress.Address.Function = CfohPciAddress.Address.Function; PciAddress.Address.Register = CfohPciAddress.Address.Register; LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); PciRegister &= AndMask; PciRegister |= OrMask; LibAmdPciWrite (AccessWidth32, PciAddress, &PciRegister, StdHeader); } } } } } return AgesaStatus; }
/** * Multisocket call to loop through all possible socket locations and Nb Pstates, * comparing the NB frequencies to determine the slowest system and P0 frequency * * @param[in] PlatformConfig Platform profile/build option config structure. * @param[out] MinSysNbFreq NB frequency numerator for the system in MHz * @param[out] MinP0NbFreq NB frequency numerator for P0 in MHz * @param[in] StdHeader Config handle for library and services */ VOID GetMinNbCofMulti ( IN PLATFORM_CONFIGURATION *PlatformConfig, OUT UINT32 *MinSysNbFreq, OUT UINT32 *MinP0NbFreq, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Socket; UINT32 Module; UINT32 CurrMinFreq; UINT32 CurrMaxFreq; PCI_ADDR PciAddress; AGESA_STATUS Ignored; CPU_SPECIFIC_SERVICES *FamilySpecificServices; AGESA_STATUS AgesaStatus; *MinSysNbFreq = 0xFFFFFFFF; *MinP0NbFreq = 0xFFFFFFFF; for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { if (IsProcessorPresent (Socket, StdHeader)) { GetCpuServicesOfSocket (Socket, (CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader); for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &Ignored )) { break; } } AgesaStatus = FamilySpecificServices->GetMinMaxNbFrequency (FamilySpecificServices, PlatformConfig, &PciAddress, &CurrMinFreq, &CurrMaxFreq, StdHeader); ASSERT (AgesaStatus == AGESA_SUCCESS); ASSERT ((CurrMinFreq != 0) && (CurrMaxFreq != 0)); // Determine the slowest NB Pmin frequency if (CurrMinFreq < *MinSysNbFreq) { *MinSysNbFreq = CurrMinFreq; } // Determine the slowest NB P0 frequency if (CurrMaxFreq < *MinP0NbFreq) { *MinP0NbFreq = CurrMaxFreq; } } } }
/** * Family 10h core 0 entry point for performing the necessary steps after * a warm reset has occurred. * * The steps are as follows: * 1. Modify F3xDC[PstateMaxVal] to reflect the lowest performance P-state * supported, as indicated in MSRC001_00[68:64][PstateEn] * 2. If MSRC001_0071[CurNbDid] = 0, set MSRC001_001F[GfxNbPstateDis] * 3. If MSRC001_0071[CurPstate] != F3xDC[PstateMaxVal], go to step 20 * 4. If F3xDC[PstateMaxVal] = 0 or F3xDC[PstateMaxVal] != 4, go to step 7 * 5. If MSRC001_0061[CurPstateLimit] <= F3xDC[PstateMaxVal]-1, go to step 17 * 6. Exit the sequence * 7. Copy the P-state register pointed to by F3xDC[PstateMaxVal] to the P-state * register pointed to by F3xDC[PstateMaxVal]+1 * 8. Write F3xDC[PstateMaxVal]+1 to F3xDC[PstateMaxVal] * 9. Write (the new) F3xDC[PstateMaxVal] to MSRC001_0062[PstateCmd] * 10. Wait for MSRC001_0071[CurCpuFid/CurCpuDid] = CpuFid/CpuDid from the P-state * register pointed to by (the new) F3xDC[PstateMaxVal] * 11. Copy (the new) F3xDC[PstateMaxVal]-1 to MSRC001_0062[PstateCmd] * 12. Wait for MSRC001_0071[CurCpuFid/CurCpuDid] = CpuFid/CpuDid from the P-state * register pointed to by (the new) F3xDC[PstateMaxVal]-1 * 13. If MSRC001_0071[CurNbDid] = 1, set MSRC001_001F[GfxNbPstateDis] * 14. If required, transition the NB COF and VID to the NbDid and NbVid from the * P-state register pointed to by MSRC001_0061[CurPstateLimit] using the NB COF * and VID transition sequence after a warm reset * 15. Write MSRC001_00[68:64][PstateEn]=0 for the P-state pointed to by F3xDC[PstateMaxVal] * 16. Write (the new) F3xDC[PstateMaxVal]-1 to F3xDC[PstateMaxVal] and exit the sequence * 17. Copy F3xDC[PstateMaxVal]-1 to MSRC001_0062[PstateCmd] * 18. Wait for MSRC001_0071[CurCpuFid/CurCpuDid] = CpuFid/CpuDid from the P-state * register pointed to by F3xDC[PstateMaxVal]-1 * 19. If MSRC001_0071[CurNbDid] = 0, set MSRC001_001F[GfxNbPstateDis] * 20. Copy F3xDC[PstateMaxVal] to MSRC001_0062[PstateCmd] * 21. Wait for MSRC001_0071[CurCpuFid/CurCpuDid] = CpuFid/CpuDid from the P-state * register pointed to by F3xDC[PstateMaxVal] * 22. If MSRC001_0071[CurNbDid] = 1, set MSRC001_001F[GfxNbPstateDis] * 23. Issue an LDTSTOP assertion in the IO hub and exit sequence * 24. If required, transition the NB COF and VID to the NbDid and NbVid from the * P-state register pointed to by F3xDC[PstateMaxVal] using the NB COF and VID * transition sequence after a warm reset * * @param[in] FamilySpecificServices The current Family Specific Services. * @param[in] CpuEarlyParamsPtr Service parameters * @param[in] StdHeader Config handle for library and services. * */ VOID F10PmAfterReset ( IN CPU_SPECIFIC_SERVICES *FamilySpecificServices, IN AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Socket; UINT32 Module; UINT32 PsMaxVal; UINT32 CoreNum; UINT32 MsrAddr; UINT32 Core; UINT32 AndMask; UINT32 OrMask; UINT64 LocalMsrRegister; PCI_ADDR PciAddress; AP_TASK TaskPtr; AGESA_STATUS IgnoredSts; IdentifyCore (StdHeader, &Socket, &Module, &Core, &IgnoredSts); GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts); GetActiveCoresInCurrentSocket (&CoreNum, StdHeader); ASSERT (Core == 0); // Step 1 Modify F3xDC[PstateMaxVal] to reflect the lowest performance // P-state supported, as indicated in MSRC001_00[68:64][PstateEn] for (MsrAddr = PS_MAX_REG; MsrAddr > PS_REG_BASE; --MsrAddr) { LibAmdMsrRead (MsrAddr, &LocalMsrRegister, StdHeader); if (((PSTATE_MSR *) &LocalMsrRegister)->PsEnable == 1) { break; } } PsMaxVal = MsrAddr - PS_REG_BASE; PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = CPTC2_REG; AndMask = 0xFFFFFFFF; OrMask = 0x00000000; ((CLK_PWR_TIMING_CTRL2_REGISTER *) &AndMask)->PstateMaxVal = 0; ((CLK_PWR_TIMING_CTRL2_REGISTER *) &OrMask)->PstateMaxVal = PsMaxVal; ModifyCurrentSocketPci (&PciAddress, AndMask, OrMask, StdHeader); // Launch each local core to perform the remaining steps. TaskPtr.FuncAddress.PfApTask = F10PmAfterResetCore; TaskPtr.DataTransfer.DataSizeInDwords = 0; TaskPtr.ExeFlags = WAIT_FOR_CORE; ApUtilRunCodeOnAllLocalCoresAtEarly (&TaskPtr, StdHeader, CpuEarlyParamsPtr); }
/** * Check to see if the input CPU is running in the optimal configuration. * * @param[in] HtAssistServices HT Assist family services. * @param[in] Socket Processor socket to check. * @param[in] StdHeader Config Handle for library, services. * * @retval TRUE HT Assist is running sub-optimally. * @retval FALSE HT Assist is running optimally. * */ STATIC BOOLEAN F10IsNonOptimalConfig ( IN HT_ASSIST_FAMILY_SERVICES *HtAssistServices, IN UINT32 Socket, IN AMD_CONFIG_PARAMS *StdHeader ) { BOOLEAN IsNonOptimal; BOOLEAN IsMemoryPresent; UINT32 Module; UINT32 PciRegister; PCI_ADDR PciAddress; AGESA_STATUS IgnoredStatus; IsNonOptimal = FALSE; for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredStatus)) { IsMemoryPresent = FALSE; PciAddress.Address.Function = FUNC_2; PciAddress.Address.Register = DRAM_CFG_HI_REG0; LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); if (((DRAM_CFG_HI_REGISTER *) &PciRegister)->MemClkFreqVal == 1) { IsMemoryPresent = TRUE; if (((DRAM_CFG_HI_REGISTER *) &PciRegister)->MemClkFreq < 4) { IsNonOptimal = TRUE; break; } } PciAddress.Address.Register = DRAM_CFG_HI_REG1; LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); if (((DRAM_CFG_HI_REGISTER *) &PciRegister)->MemClkFreqVal == 1) { IsMemoryPresent = TRUE; if (((DRAM_CFG_HI_REGISTER *) &PciRegister)->MemClkFreq < 4) { IsNonOptimal = TRUE; break; } } if (!IsMemoryPresent) { IsNonOptimal = TRUE; break; } } } return IsNonOptimal; }
UINT8 PciRead8 ( UINT8 Segment, UINT8 Bus, UINT8 DevFunc, UINT8 Register ) /*++ Routine Description: Perform an one byte PCI config cycle read Arguments: Segment - PCI Segment ACPI _SEG Bus - PCI Bus DevFunc - PCI Device(7:3) and Func(2:0) Register - PCI config space register Returns: Data read from PCI config space --*/ { EFI_STATUS Status; UINT32 PciAddress; UINT32 PciAddress1; UINT8 Data; PciAddress = GetPciAddress (Segment, Bus, DevFunc, Register); // // Set bit 31 for PCI config access // PciAddress1 = PciAddress; PciAddress = ((PciAddress & 0xFFFFFFFC) | (0x80000000)); Status = EfiIoWrite (EfiCpuIoWidthUint32, PCI_CONFIG_INDEX_PORT, 1, &PciAddress); if (EFI_ERROR (Status)) { return 0; } EfiIoRead (EfiCpuIoWidthUint8, (PCI_CONFIG_DATA_PORT + (PciAddress1 & 0x3)), 1, &Data); return Data; }
/** * Hook before the probe filter initialization sequence. * * @param[in] HtAssistServices HT Assist family services. * @param[in] Socket Processor socket to check. * @param[in] StdHeader Config Handle for library, services. * */ VOID STATIC F10HookBeforeInit ( IN HT_ASSIST_FAMILY_SERVICES *HtAssistServices, IN UINT32 Socket, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Module; UINT32 PciRegister; UINT32 PfCtrlRegister; PCI_ADDR PciAddress; CPU_LOGICAL_ID LogicalId; AGESA_STATUS IgnoredStatus; UINT32 PackageType; GetLogicalIdOfSocket (Socket, &LogicalId, StdHeader); PackageType = LibAmdGetPackageType (StdHeader); PciRegister = 0; ((PROBE_FILTER_CTRL_REGISTER *) &PciRegister)->PFWayNum = 2; ((PROBE_FILTER_CTRL_REGISTER *) &PciRegister)->PFSubCacheEn = 15; ((PROBE_FILTER_CTRL_REGISTER *) &PciRegister)->PFLoIndexHashEn = 1; for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredStatus)) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = PROBE_FILTER_CTRL_REG; LibAmdPciRead (AccessWidth32, PciAddress, &PfCtrlRegister, StdHeader); ((PROBE_FILTER_CTRL_REGISTER *) &PciRegister)->PFPreferredSORepl = ((PROBE_FILTER_CTRL_REGISTER *) &PfCtrlRegister)->PFPreferredSORepl; LibAmdPciWrite (AccessWidth32, PciAddress, &PciRegister, StdHeader); // Assumption: all socket use the same CPU package. if (((LogicalId.Revision & AMD_F10_D0) != 0) && (PackageType == PACKAGE_TYPE_C32)) { // Apply erratum #384 // Set F2x11C[13:12] = 11b PciAddress.Address.Function = FUNC_2; PciAddress.Address.Register = 0x11C; LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); PciRegister |= 0x3000; LibAmdPciWrite (AccessWidth32, PciAddress, &PciRegister, StdHeader); } } } }
VOID PciWrite32 ( UINT8 Segment, UINT8 Bus, UINT8 DevFunc, UINT8 Register, UINT32 Data ) /*++ Routine Description: Perform an four byte PCI config cycle write Arguments: Segment - PCI Segment ACPI _SEG Bus - PCI Bus DevFunc - PCI Device(7:3) and Func(2:0) Register - PCI config space register Data - Data to write Returns: NONE --*/ { EFI_STATUS Status; UINT32 PciAddress; UINT32 PciAddress1; PciAddress = GetPciAddress (Segment, Bus, DevFunc, Register); // // Set bit 31 for PCI config access // PciAddress1 = PciAddress; PciAddress = ((PciAddress & 0xFFFFFFFC) | (0x80000000)); Status = EfiIoWrite (EfiCpuIoWidthUint32, PCI_CONFIG_INDEX_PORT, 1, &PciAddress); if (EFI_ERROR (Status)) { return ; } EfiIoWrite (EfiCpuIoWidthUint32, (PCI_CONFIG_DATA_PORT + (PciAddress1 & 0x3)), 1, &Data); }
/** * Save the current settings of the scrubbers, and disabled them. * * @param[in] HtAssistServices HT Assist family services. * @param[in] Socket Processor socket to check. * @param[in] ScrubSettings Location to store current L3 scrubber settings. * @param[in] StdHeader Config Handle for library, services. * */ VOID STATIC F10GetL3ScrubCtrl ( IN HT_ASSIST_FAMILY_SERVICES *HtAssistServices, IN UINT32 Socket, IN UINT32 ScrubSettings[L3_SCRUBBER_CONTEXT_ARRAY_SIZE], IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Module; UINT32 ScrubCtrl; UINT32 ScrubAddr; PCI_ADDR PciAddress; AGESA_STATUS IgnoredStatus; for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredStatus)) { ASSERT (Module < L3_SCRUBBER_CONTEXT_ARRAY_SIZE); PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = DRAM_SCRUB_ADDR_LOW_REG; LibAmdPciRead (AccessWidth32, PciAddress, &ScrubAddr, StdHeader); PciAddress.Address.Register = SCRUB_RATE_CTRL_REG; LibAmdPciRead (AccessWidth32, PciAddress, &ScrubCtrl, StdHeader); ((F10_SCRUB_CONTEXT *) &ScrubSettings[Module])->DramScrub = ((SCRUB_RATE_CTRL_REGISTER *) &ScrubCtrl)->DramScrub; ((F10_SCRUB_CONTEXT *) &ScrubSettings[Module])->L3Scrub = ((SCRUB_RATE_CTRL_REGISTER *) &ScrubCtrl)->L3Scrub; ((F10_SCRUB_CONTEXT *) &ScrubSettings[Module])->Redirect = ((DRAM_SCRUB_ADDR_LOW_REGISTER *) &ScrubAddr)->ScrubReDirEn; ((SCRUB_RATE_CTRL_REGISTER *) &ScrubCtrl)->DramScrub = 0; ((SCRUB_RATE_CTRL_REGISTER *) &ScrubCtrl)->L3Scrub = 0; ((DRAM_SCRUB_ADDR_LOW_REGISTER *) &ScrubAddr)->ScrubReDirEn = 0; LibAmdPciWrite (AccessWidth32, PciAddress, &ScrubCtrl, StdHeader); PciAddress.Address.Register = DRAM_SCRUB_ADDR_LOW_REG; LibAmdPciWrite (AccessWidth32, PciAddress, &ScrubAddr, StdHeader); } } }
/** * Enable the Probe filter feature. * * @param[in] HtAssistServices HT Assist family services. * @param[in] Socket Processor socket to check. * @param[in] StdHeader Config Handle for library, services. * */ VOID STATIC F10HtAssistInit ( IN HT_ASSIST_FAMILY_SERVICES *HtAssistServices, IN UINT32 Socket, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Module; UINT32 PciRegister; PCI_ADDR PciAddress; AGESA_STATUS IgnoredStatus; for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredStatus)) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = L3_CACHE_PARAM_REG; LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); ((L3_CACHE_PARAM_REGISTER *) &PciRegister)->L3TagInit = 1; LibAmdPciWrite (AccessWidth32, PciAddress, &PciRegister, StdHeader); do { LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); } while (((L3_CACHE_PARAM_REGISTER *) &PciRegister)->L3TagInit != 0); PciAddress.Address.Register = PROBE_FILTER_CTRL_REG; LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); ((PROBE_FILTER_CTRL_REGISTER *) &PciRegister)->PFMode = 0; LibAmdPciWrite (AccessWidth32, PciAddress, &PciRegister, StdHeader); F10RevDProbeFilterCritical (PciAddress, PciRegister); do { LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); } while (((PROBE_FILTER_CTRL_REGISTER *) &PciRegister)->PFInitDone != 1); IDS_OPTION_HOOK (IDS_HT_ASSIST, &PciAddress, StdHeader); } } }
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); }
/** * * * MemSocketScan - Scan all nodes, recording the physical Socket number, * Die Number (relative to the socket), and PCI Device address of each * populated socket. * * This information is used by the northbridge block to map a dram * channel on a particular DCT, on a particular CPU Die, in a particular * socket to a the DRAM SPD Data for the DIMMS physically connected to * that channel. * * Also, the customer socket map is populated with pointers to the * appropriate channel structures, so that the customer can locate the * appropriate channel configuration data. * * This socket scan will always result in Die 0 as the BSP. * * @param[in,out] *mmPtr - Pointer to the MEM_MAIN_DATA_BLOCK * */ AGESA_STATUS MemSocketScan ( IN OUT MEM_MAIN_DATA_BLOCK *mmPtr ) { MEM_DATA_STRUCT *MemPtr; UINT8 DieIndex; UINT8 DieCount; UINT32 SocketId; UINT32 DieId; UINT8 Die; PCI_ADDR Address; AGESA_STATUS AgesaStatus; ALLOCATE_HEAP_PARAMS AllocHeapParams; ASSERT (mmPtr != NULL); ASSERT (mmPtr->MemPtr != NULL); MemPtr = mmPtr->MemPtr; // // Count the number of dies in the system // DieCount = 0; for (Die = 0; Die < MAX_NODES_SUPPORTED; Die++) { if (GetSocketModuleOfNode ((UINT32)Die, &SocketId, &DieId, (VOID *)MemPtr)) { DieCount++; } } MemPtr->DieCount = DieCount; mmPtr->DieCount = DieCount; if (DieCount > 0) { // // Allocate buffer for DIE_STRUCTs // AllocHeapParams.RequestedBufferSize = ((UINT16)DieCount * 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) { MemPtr->DiesPerSystem = (DIE_STRUCT *)AllocHeapParams.BufferPtr; // // Find SocketId, DieId, and PCI address of each node // DieIndex = 0; for (Die = 0; Die < MAX_NODES_SUPPORTED; Die++) { if (GetSocketModuleOfNode ((UINT32)Die, &SocketId, &DieId, (VOID *)MemPtr)) { if (GetPciAddress ((VOID *)MemPtr, (UINT8)SocketId, (UINT8)DieId, &Address, &AgesaStatus)) { MemPtr->DiesPerSystem[DieIndex].SocketId = (UINT8)SocketId; MemPtr->DiesPerSystem[DieIndex].DieId = (UINT8)DieId; MemPtr->DiesPerSystem[DieIndex].PciAddr.AddressValue = Address.AddressValue; DieIndex++; } } } AgesaStatus = AGESA_SUCCESS; } else { ASSERT(FALSE); // Heap allocation failed for DIE_STRUCTs AgesaStatus = AGESA_FATAL; } } else { ASSERT(FALSE); // No die in the system AgesaStatus = AGESA_FATAL; } return AgesaStatus; }
/** * Family 10h core 0 entry point for performing power plane initialization. * * The steps are as follows: * 1. If single plane, program lower VID code of CpuVid & NbVid for all * enabled P-States. * 2. Configure F3xA0[SlamMode] & F3xD8[VsRampTime & VsSlamTime] based on * platform requirements. * 3. Configure F3xD4[PowerStepUp & PowerStepDown] * 4. Optionally configure F3xA0[PsiVidEn & PsiVid] * * @param[in] FamilySpecificServices The current Family Specific Services. * @param[in] CpuEarlyParams Service parameters * @param[in] StdHeader Config handle for library and services. * */ VOID F10CpuAmdPmPwrPlaneInit ( IN CPU_SPECIFIC_SERVICES *FamilySpecificServices, IN AMD_CPU_EARLY_PARAMS *CpuEarlyParams, IN AMD_CONFIG_PARAMS *StdHeader ) { BOOLEAN PviModeFlag; PCI_ADDR PciAddress; UINT16 PowerStepTime; UINT32 PowerStepEncoded; UINT32 PciRegister; UINT32 VsSlamTime; UINT32 Socket; UINT32 Module; UINT32 Core; UINT32 NumOfCores; UINT32 LowCore; UINT32 AndMask; UINT32 OrMask; UINT64 MsrRegister; AP_TASK TaskPtr; AGESA_STATUS IgnoredSts; PLATFORM_FEATS Features; CPU_LOGICAL_ID LogicalId; // Initialize the union Features.PlatformValue = 0; GetPlatformFeatures (&Features, &CpuEarlyParams->PlatformConfig, StdHeader); IdentifyCore (StdHeader, &Socket, &Module, &Core, &IgnoredSts); GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts); ASSERT (Core == 0); GetLogicalIdOfCurrentCore (&LogicalId, StdHeader); // Set SlamVidMode PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = PW_CTL_MISC_REG; LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); AndMask = 0xFFFFFFFF; OrMask = 0x00000000; if (((POWER_CTRL_MISC_REGISTER *) &PciRegister)->PviMode == 1) { PviModeFlag = TRUE; ((POWER_CTRL_MISC_REGISTER *) &AndMask)->SlamVidMode = 0; // Have all single plane cores adjust their NB and CPU VID fields TaskPtr.FuncAddress.PfApTask = F10PmPwrPlaneInitPviCore; TaskPtr.DataTransfer.DataSizeInDwords = 0; TaskPtr.ExeFlags = WAIT_FOR_CORE; ApUtilRunCodeOnAllLocalCoresAtEarly (&TaskPtr, StdHeader, CpuEarlyParams); } else { PviModeFlag = FALSE; ((POWER_CTRL_MISC_REGISTER *) &OrMask)->SlamVidMode = 1; } ModifyCurrentSocketPci (&PciAddress, AndMask, OrMask, StdHeader); F10ProgramVSSlamTimeOnSocket (&PciAddress, CpuEarlyParams, StdHeader); // Configure PowerStepUp/PowerStepDown PciAddress.Address.Register = CPTC0_REG; if ((Features.PlatformFeatures.PlatformSingleLink == 1) || (Features.PlatformFeatures.PlatformUma == 1) || (Features.PlatformFeatures.PlatformUmaIfcm == 1) || (Features.PlatformFeatures.PlatformIfcm == 1) || (Features.PlatformFeatures.PlatformIommu == 1)) { PowerStepEncoded = 0x8; } else { GetGivenModuleCoreRange ((UINT32) Socket, (UINT32) Module, &LowCore, &NumOfCores, StdHeader); NumOfCores = ((NumOfCores - LowCore) + 1); PowerStepTime = (UINT16) (400 / NumOfCores); for (PowerStepEncoded = 0xF; PowerStepEncoded > 0; PowerStepEncoded--) { if (PowerStepTime <= PowerStepEncodings[PowerStepEncoded]) { break; } } } AndMask = 0xFFFFFFFF; ((CLK_PWR_TIMING_CTRL_REGISTER *) &AndMask)->PowerStepUp = 0; ((CLK_PWR_TIMING_CTRL_REGISTER *) &AndMask)->PowerStepDown = 0; OrMask = 0x00000000; ((CLK_PWR_TIMING_CTRL_REGISTER *) &OrMask)->PowerStepUp = PowerStepEncoded; ((CLK_PWR_TIMING_CTRL_REGISTER *) &OrMask)->PowerStepDown = PowerStepEncoded; ModifyCurrentSocketPci (&PciAddress, AndMask, OrMask, StdHeader); if ((LogicalId.Revision & AMD_F10_C3) != 0) { // Set up Pop up P-state register PciAddress.Address.Register = CPTC2_REG; LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); AndMask = 0xFFFFFFFF; ((POPUP_PSTATE_REGISTER *) &AndMask)->PopupPstate = 0; ((POPUP_PSTATE_REGISTER *) &AndMask)->PopupCpuVid = 0; ((POPUP_PSTATE_REGISTER *) &AndMask)->PopupCpuFid = 0; ((POPUP_PSTATE_REGISTER *) &AndMask)->PopupCpuDid = 0; OrMask = 0x00000000; ((POPUP_PSTATE_REGISTER *) &OrMask)->PopupEn = 0; ((POPUP_PSTATE_REGISTER *) &OrMask)->PopupPstate = ((CLK_PWR_TIMING_CTRL2_REGISTER *) &PciRegister)->PstateMaxVal; LibAmdMsrRead ((((CLK_PWR_TIMING_CTRL2_REGISTER *) &PciRegister)->PstateMaxVal + PS_REG_BASE), &MsrRegister, StdHeader); ((POPUP_PSTATE_REGISTER *) &OrMask)->PopupCpuVid = (UINT32) ((PSTATE_MSR *) &MsrRegister)->CpuVid; ((POPUP_PSTATE_REGISTER *) &OrMask)->PopupCpuFid = (UINT32) ((PSTATE_MSR *) &MsrRegister)->CpuFid; ((POPUP_PSTATE_REGISTER *) &OrMask)->PopupCpuDid = (UINT32) ((PSTATE_MSR *) &MsrRegister)->CpuDid; PciAddress.Address.Register = POPUP_PSTATE_REG; ModifyCurrentSocketPci (&PciAddress, AndMask, OrMask, StdHeader); // Set AltVidStart PciAddress.Address.Register = CPTC1_REG; AndMask = 0xFFFFFFFF; ((CLK_PWR_TIMING_CTRL1_REGISTER *) &AndMask)->AltVidStart = 0; OrMask = 0x00000000; ((CLK_PWR_TIMING_CTRL1_REGISTER *) &OrMask)->AltVidStart = (UINT32) ((PSTATE_MSR *) &MsrRegister)->CpuVid; ModifyCurrentSocketPci (&PciAddress, AndMask, OrMask, StdHeader); // Set up Altvid slam time PciAddress.Address.Register = CPTC2_REG; VsSlamTime = F10CalculateAltvidVSSlamTimeOnCore (PviModeFlag, &PciAddress, CpuEarlyParams, StdHeader); AndMask = 0xFFFFFFFF; ((CLK_PWR_TIMING_CTRL2_REGISTER *) &AndMask)->AltvidVSSlamTime = 0; ((CLK_PWR_TIMING_CTRL2_REGISTER *) &AndMask)->SlamTimeMode = 0; OrMask = 0x00000000; ((CLK_PWR_TIMING_CTRL2_REGISTER *) &OrMask)->AltvidVSSlamTime = VsSlamTime; ((CLK_PWR_TIMING_CTRL2_REGISTER *) &OrMask)->SlamTimeMode = 2; ModifyCurrentSocketPci (&PciAddress, AndMask, OrMask, StdHeader); } if (IsWarmReset (StdHeader) && !PviModeFlag) { // Configure PsiVid F10PmVrmLowPowerModeEnable (FamilySpecificServices, CpuEarlyParams, StdHeader); } }
/** * Set down core register on Mullins * * This function set F3x190 Downcore Control Register[5:0] * * @param[in] FamilySpecificServices The current Family Specific Services. * @param[in] Socket Socket ID. * @param[in] Module Module ID in socket. * @param[in] LeveledCores Number of core. * @param[in] CoreLevelMode Core level mode. * @param[in] StdHeader Header for library and services. * * @retval TRUE Down Core register is updated. * @retval FALSE Down Core register is not updated. */ BOOLEAN F16MlSetDownCoreRegister ( IN CPU_CORE_LEVELING_FAMILY_SERVICES *FamilySpecificServices, IN UINT32 *Socket, IN UINT32 *Module, IN UINT32 *LeveledCores, IN CORE_LEVELING_TYPE CoreLevelMode, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 NumOfComputeUnit; UINT8 CoresPerComputeUnit; UINT32 LocalPciRegister; UINT32 CoreDisableBits; UINT32 TempVar32_a; PCI_ADDR PciAddress; BOOLEAN IsUpdated; AGESA_STATUS AgesaStatus; IsUpdated = FALSE; CoreDisableBits = 0; TempVar32_a = 1; CoresPerComputeUnit = 1; switch (CoreLevelMode) { // There's no 'break' except 'case CORE_LEVEL_COMPUTE_UNIT'. // It's for generating CoreDisableBits and CoresPerComputeUnit case CORE_LEVEL_COMPUTE_UNIT_THREE: TempVar32_a = TempVar32_a << 1; CoresPerComputeUnit++; case CORE_LEVEL_COMPUTE_UNIT_TWO: TempVar32_a = TempVar32_a << 1; CoresPerComputeUnit++; case CORE_LEVEL_COMPUTE_UNIT: TempVar32_a = (TempVar32_a << 1) - 1; TempVar32_a = FOUR_CORE_COMPUTE_UNIT_BITMAP & (~TempVar32_a); NumOfComputeUnit = (UINT8) ((*LeveledCores) / CoresPerComputeUnit); for (CoreDisableBits = 0; NumOfComputeUnit > 0; NumOfComputeUnit--) { CoreDisableBits <<= FOUR_CORE_COMPUTE_UNIT_BITWIDTH; CoreDisableBits |= TempVar32_a; } break; default: TempVar32_a = *LeveledCores; if (TempVar32_a == 1) { CoreDisableBits = DOWNCORE_MASK_SINGLE; } else { CoreDisableBits = ALL_CORES_DISABLE_BITMAP; TempVar32_a = ((1 << TempVar32_a) - 1); CoreDisableBits &= ~TempVar32_a; } } if (CoreDisableBits != 0) { if (GetPciAddress (StdHeader, (UINT8) *Socket, (UINT8) *Module, &PciAddress, &AgesaStatus)) { PciAddress.Address.Function = FUNC_5; PciAddress.Address.Register = NORTH_BRIDGE_CAPABILITIES_2_REG; LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); LocalPciRegister = (LocalPciRegister & 0xFF) + 1; LocalPciRegister = (1 << LocalPciRegister) - 1; CoreDisableBits &= LocalPciRegister; PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = DOWNCORE_CTRL; LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); if ((LocalPciRegister | CoreDisableBits) != LocalPciRegister) { LocalPciRegister |= CoreDisableBits; LibAmdPciWrite (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); IsUpdated = TRUE; } } } return IsUpdated; }
/**-------------------------------------------------------------------------------------- * * PStateLevelingMain * * Description: * This is the common routine for creating the ACPI information tables. * * Parameters: * @param[in,out] *PStateStrucPtr * @param[in] *StdHeader * * @retval AGESA_STATUS * *--------------------------------------------------------------------------------------- **/ AGESA_STATUS PStateLevelingMain ( IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 i; UINT32 k; UINT32 m; UINT32 TotalIterations; UINT32 LogicalSocketCount; UINT32 TempVar_a; UINT32 TempVar_b; UINT32 TempVar_c; UINT32 TempVar_d; UINT32 TempVar_e; UINT32 TempVar_f; PCI_ADDR PciAddress; UINT32 TempFreqArray[20]; UINT32 TempPowerArray[20]; UINT32 TempIddValueArray[20]; UINT32 TempIddDivArray[20]; UINT32 TempSocketPiArray[20]; UINT32 TempSwP0Array[MAX_SOCKETS_SUPPORTED]; BOOLEAN TempFlag1; BOOLEAN TempFlag2; BOOLEAN TempFlag3; BOOLEAN TempFlag4; BOOLEAN AllCoresHaveHtcCapEquToZeroFlag; BOOLEAN AllCoreHaveMaxOnePStateFlag; BOOLEAN PstateMaxValEquToPstateHtcLimitFlag; BOOLEAN AtLeastOneCoreHasPstateHtcLimitEquToOneFlag; BOOLEAN PstateMaxValMinusHtcPstateLimitLessThan2Flag; PSTATE_LEVELING *PStateBufferPtr; PSTATE_LEVELING *PStateBufferPtrTmp; UINT32 MaxPstateInNode; AGESA_STATUS Status; TempFlag1 = FALSE; TempFlag2 = FALSE; TempFlag3 = FALSE; TempFlag4 = FALSE; AllCoresHaveHtcCapEquToZeroFlag = FALSE; AllCoreHaveMaxOnePStateFlag = FALSE; PstateMaxValEquToPstateHtcLimitFlag = FALSE; AtLeastOneCoreHasPstateHtcLimitEquToOneFlag = FALSE; PstateMaxValMinusHtcPstateLimitLessThan2Flag = FALSE; PStateBufferPtr = PStateStrucPtr->PStateLevelingStruc; Status = AGESA_SUCCESS; if (PStateBufferPtr[0].SetPState0 == PSTATE_FLAG_1) { PStateBufferPtr[0].AllCpusHaveIdenticalPStates = TRUE; PStateBufferPtr[0].InitStruct = 1; return AGESA_UNSUPPORTED; } LogicalSocketCount = PStateStrucPtr->TotalSocketInSystem; ASSERT (LogicalSocketCount <= MAX_SOCKETS_SUPPORTED); // This section of code will execute only for "core 0" i.e. BSP // Read P-States of all the cores. if (PStateBufferPtr[0].InitStruct == 0) { // Determine 'software' P0 indices for each socket for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); TempSwP0Array[i] = (UINT32) (PStateBufferPtrTmp->PStateCoreStruct[0].NumberOfBoostedStates); } // Check if core frequency and power are same across all sockets. TempFlag1 = FALSE; m = TempSwP0Array[0]; for (i = 1; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue != PStateBufferPtr[0].PStateCoreStruct[0].PStateMaxValue)) { TempFlag1 = TRUE; break; } MaxPstateInNode = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue; for (k = TempSwP0Array[i]; k <= MaxPstateInNode; k++, m++) { if ((PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[m].CoreFreq != PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].CoreFreq) || (PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[m].Power != PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].Power)) { TempFlag1 = TRUE; break; // Come out of the inner FOR loop } } if (TempFlag1) { break; // Come out of the outer FOR loop } } if (!TempFlag1) { // No need to do pStateLeveling, or writing to pState MSR registers // if all CPUs have Identical PStates PStateBufferPtr[0].AllCpusHaveIdenticalPStates = TRUE; PStateBufferPtr[0].InitStruct = 1; PutAllCoreInPState0 (PStateBufferPtr, StdHeader); return AGESA_UNSUPPORTED; } else { PStateBufferPtr[0].AllCpusHaveIdenticalPStates = FALSE; } // 1_b) & 1_c) TempFlag1 = FALSE; TempFlag2 = FALSE; for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue == TempSwP0Array[i]) { TempFlag1 = TRUE; } else { TempFlag2 = TRUE; } if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcCapable == 0) { TempFlag3 = TRUE; } else { TempFlag4 = TRUE; } if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) < 2) { PstateMaxValMinusHtcPstateLimitLessThan2Flag = TRUE; } if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue == PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) { PstateMaxValEquToPstateHtcLimitFlag = TRUE; } if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit == 1) { AtLeastOneCoreHasPstateHtcLimitEquToOneFlag = TRUE; } } // Do general setup of flags, that we may use later // Implementation of (1_b) if (TempFlag1 && TempFlag2) { // //Processors with only one enabled P-state (F3xDC[PstateMaxVal]=000b) cannot be mixed in a system with //processors with more than one enabled P-state (F3xDC[PstateMaxVal]!=000b). // PStateBufferPtr[0].InitStruct = 1; PStateBufferPtr[0].CreateAcpiTables = 0; PutAllCoreInPState0 (PStateBufferPtr, StdHeader); return AGESA_UNSUPPORTED; } else if (TempFlag1 && !TempFlag2) { // //all processors have only 1 enabled P-state // AllCoreHaveMaxOnePStateFlag = TRUE; PStateBufferPtr[0].OnlyOneEnabledPState = TRUE; } // Processors with F3xE8[HTC_CAPABLE] = 1 can not be // mixed in system with processors with F3xE8[HTC_CAPABLE] = 0. if (TempFlag3 && TempFlag4) { PStateBufferPtr[0].InitStruct = 1; for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); PStateBufferPtrTmp[0].CreateAcpiTables = 0; } PutAllCoreInPState0 (PStateBufferPtr, StdHeader); return AGESA_UNSUPPORTED; } if (TempFlag3) { // //If code run to here means that all processors do not have HTC_CAPABLE. // AllCoresHaveHtcCapEquToZeroFlag = TRUE; } //-------------------------------------------------------------------------------- // S T E P - 2 //-------------------------------------------------------------------------------- // Now run the PState Leveling Algorithm which will create mixed CPU P-State // Tables. // Follow the algorithm in the latest BKDG // ------------------------------------------------------------------------------- // Match P0 CPU COF for all CPU cores to the lowest P0 CPU COF value in the // coherent fabric, and match P0 power for all CPU cores to the highest P0 power // value in the coherent fabric. // 2_a) If all processors have only 1 enabled P-State BIOS must write the // appropriate CpuFid value resulting from the matched CPU COF to all // copies of MSRC001_0070[CpuFid], and exit the sequence (No further // steps are executed) //-------------------------------------------------------------------------------- // Identify the lowest P0 Frequency and maximum P0 Power TempVar_d = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSwP0Array[0]].CoreFreq; TempVar_e = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSwP0Array[0]].Power; TempVar_a = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSwP0Array[0]].IddValue; TempVar_b = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSwP0Array[0]].IddDiv; for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); if (TempVar_d > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].CoreFreq) { TempVar_d = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].CoreFreq; } if (TempVar_e < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].Power) { TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].Power; TempVar_a = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].IddValue; TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].IddDiv; } } // Set P0 Frequency and Power for all CPUs for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].CoreFreq = TempVar_d; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].Power = TempVar_e; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].IddValue = TempVar_a; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].IddDiv = TempVar_b; } // 2_a) if (!AllCoreHaveMaxOnePStateFlag) { //-------------------------------------------------------------------------- // STEP - 3 //-------------------------------------------------------------------------- // Match the CPU COF and power for P-states used by HTC. Skip to step 4 // is any processor reports F3xE8[HTC_Capable] = 0; // 3_a) Set F3x64[HtcPstateLimit] = 001b and F3x68[StcPstateLimit] = 001b for // processors with F3x64[HtcPstateLimit] = 000b. // 3_b) Identify the lowest CPU COF for all processors in the P-state // pointed to by [The Hardware Thermal Control (HTC) Register] // F3x64[HtcPstateLimit] // 3_c) Modify the CPU COF pointed to by [The Hardware Thermal Control // (HTC) Register] F3x64[HtcPstateLimit] for all processors to the // previously identified lowest CPU COF value. // 3_d) Identify the highest power for all processors in the P-state // pointed to by [The Hardware Thermal Control (HTC) Register] // F3x64[HtcPstateLimit]. // 3_e) Modify the power pointed to by [The Hardware Thermal Control (HTC) // Register] F3x64[HtcPstateLimit] to the previously identified // highest power value. if (!AllCoresHaveHtcCapEquToZeroFlag) { // 3_a) for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit == 0) { // To Be Done (Set Htc and Stc PstateLimit values) // for this CPU (using PCI address space) for (k = 0; k < (UINT8)GetPlatformNumberOfModules (); k++) { if (GetPciAddress (StdHeader, PStateBufferPtrTmp->SocketNumber, k, &PciAddress, &Status)) { // Set F3x64[HtcPstateLimit] = 001b PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = HARDWARE_THERMAL_CTRL_REG; LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_d, StdHeader); // Bits 30:28 TempVar_d = (TempVar_d & 0x8FFFFFFF) | 0x10000000; LibAmdPciWrite (AccessWidth32, PciAddress, &TempVar_d, StdHeader); // Set F3x68[StcPstateLimit] = 001b PciAddress.Address.Register = SOFTWARE_THERMAL_CTRL_REG; LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_d, StdHeader); // Bits 28:30 TempVar_d = (TempVar_d & 0x8FFFFFFF) | 0x10000000; LibAmdPciWrite (AccessWidth32, PciAddress, &TempVar_d, StdHeader); } } // Set LocalBuffer PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit = 1; if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - 1) < 2) { PstateMaxValMinusHtcPstateLimitLessThan2Flag = TRUE; } if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue == 1) { PstateMaxValEquToPstateHtcLimitFlag = TRUE; } } if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit == 1) { AtLeastOneCoreHasPstateHtcLimitEquToOneFlag = TRUE; } } // 3_b) and 3_d) TempVar_a = PStateBufferPtr[0].PStateCoreStruct[0].HtcPstateLimit; TempVar_d = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq; TempVar_e = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].Power; TempVar_f = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue; TempVar_c = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv; for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); for (k = 0; k < 1; k++) { TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit; if (TempVar_d > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq) { TempVar_d = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq; } if (TempVar_e < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power) { TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power; TempVar_f = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddValue; TempVar_c = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddDiv; } } } // 3_c) and 3_e) for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); TempVar_a = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq = TempVar_d; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].Power = TempVar_e; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue = TempVar_f; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv = TempVar_c; } } // if(AllCoresHaveHtcCapEquToZeroFlag) //-------------------------------------------------------------------------- // STEP - 4 //-------------------------------------------------------------------------- // Match the CPU COF and power for the lowest performance P-state: // 4_a) If F3xDC[PstateMaxVal] = F3x64[HtcPstateLimit] for any processor, // set PstateEn = 0 for all the P-states greater than // F3x64[HtcPstateLimit] for all processors. // 4_b) Identify the lowest CPU COF for all processors in the P-state // pointed to by F3xDC[PstateMaxVal]. // 4_c) Modify the CPU COF for all processors in the P-state pointed to by // F3xDC[PstateMaxVal] to the previously identified lowest CPU COF // value. // 4_d) Identify the highest power for all processors in the P-state // pointed to by F3xDC[PstateMaxVal]. // 4_e) Modify the power for all processors in the P-state pointed to by // F3xDC[PstateMaxVal] to the previously identified highest power // value. // 4_a) if (PstateMaxValEquToPstateHtcLimitFlag) { for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit + 1; for (k = TempVar_b; k <= PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue; k++) { PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].PStateEnable = 0; } //-------------------------------------------------------------------------- // STEP - 5 //-------------------------------------------------------------------------- // 5_a) Modify F3xDC[PstateMaxVal] to indicate the lowest performance // P-state with PstateEn set for each processor (Step 4 can disable // P-states pointed to by F3xDC[PstateMaxVal]) // Use this value of HtcPstateLimit to program the // F3xDC[pStateMaxValue] TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit; TempVar_e <<= 8; // Bits 10:8 for (m = 0; m < (UINT8)GetPlatformNumberOfModules (); m++) { if (GetPciAddress (StdHeader, PStateBufferPtrTmp->SocketNumber, m, &PciAddress, &Status)) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = CLOCK_POWER_TIMING_CTRL2_REG; LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_d, StdHeader); TempVar_d = (TempVar_d & 0xFFFFF8FF) | TempVar_e; LibAmdPciWrite (AccessWidth32, PciAddress, &TempVar_d, StdHeader); } }//End of step 5 } }// End of 4_a) // 4_b) and 4_d) TempVar_a = PStateBufferPtr[0].PStateCoreStruct[0].PStateMaxValue; TempVar_d = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq; TempVar_e = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].Power; TempVar_f = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue; TempVar_c = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv; for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue; if (TempVar_d > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq) { TempVar_d = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq; } if (TempVar_e < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power) { TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power; TempVar_f = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddValue; TempVar_c = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddDiv; } } // 4_c) and 4_e) for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); TempVar_a = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq = TempVar_d; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].Power = TempVar_e; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue = TempVar_f; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv = TempVar_c; } //-------------------------------------------------------------------------- // STEP - 6 //-------------------------------------------------------------------------- // Match the CPU COF and power for upper intermediate performance // P-state(s): // Upper intermediate PStates = PStates between (Not including) P0 and // F3x64[HtcPstateLimit] // 6_a) If F3x64[HtcPstateLimit] = 001b for any processor, set PstateEn = 0 // for enabled upper intermediate P-states for all processors with // F3x64[HtcPstateLimit] > 001b and skip the remaining actions for // this numbered step. // 6_b) Define each of the available upper intermediate P-states; for each // processor concurrently evaluate the following loop; when any // processor falls out of the loop (runs out of available upper // intermediate Pstates) all other processors have their remaining // upper intermediate P-states invalidated (PstateEn = 0); // for (i = F3x64[HtcPstateLimit] - 1; i > 0; i--) // - Identify the lowest CPU COF for P(i). // - Identify the highest power for P(i). // - Modify P(i) CPU COF for all processors to the previously // identified lowest CPU COF value. // - Modify P(i) power for all processors to the previously // identified highest power value. // 6_a) if (AtLeastOneCoreHasPstateHtcLimitEquToOneFlag) { for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); for (k = TempSwP0Array[i] + 1; k < (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit); k++) { if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit > 1) { // Make a function call to clear the // structure values PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].PStateEnable = 0; } } } } // 6_b) else { // Identify Lowest Frequency and Highest Power TotalIterations = 0; TempFlag1 = TRUE; for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); TempSocketPiArray[i] = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit - 1; } do { //For first socket, try to find a candidate if (TempSocketPiArray[0] != TempSwP0Array[0]) { while (PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].PStateEnable == 0) { TempSocketPiArray[0] = TempSocketPiArray[0] - 1; if (TempSocketPiArray[0] == TempSwP0Array[0]) { TempFlag1 = FALSE; break; } } } else { TempFlag1 = FALSE; } if (TempFlag1) { TempFreqArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].CoreFreq; TempPowerArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].Power; TempIddValueArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddValue; TempIddDivArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddDiv; //Try to find next candidate for (i = 1; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); if (TempSocketPiArray[i] != TempSwP0Array[i]) { while (PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].PStateEnable == 0) { TempSocketPiArray[i]--; if (TempSocketPiArray[i] == TempSwP0Array[i]) { TempFlag1 = FALSE; break; } }//end while } else { TempFlag1 = FALSE; } } //end for LogicalSocketCount } if (TempFlag1) { for (i = 0; i < LogicalSocketCount; i++) { // //Compare // CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); if (TempFreqArray[TotalIterations] > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq) { TempFreqArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq; } if (TempPowerArray[TotalIterations] < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power) { TempPowerArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power; TempIddValueArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue; TempIddDivArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv; } } // Modify (Pi) CPU COF and Power for all the CPUs for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq = TempFreqArray[TotalIterations]; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power = TempPowerArray[TotalIterations]; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue = TempIddValueArray[TotalIterations]; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv = TempIddDivArray[TotalIterations]; TempSocketPiArray[i] = TempSocketPiArray[i] - 1; } } else { for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); for (m = TempSocketPiArray[i]; m > TempSwP0Array[i]; m--) { PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[m].PStateEnable = 0; } } } TotalIterations++; } while (TempFlag1); } // else //-------------------------------------------------------------------------- // STEP - 7 //-------------------------------------------------------------------------- // Match the CPU COF and power for lower intermediate performance P - state(s) // Lower Intermediate Pstates = Pstates between (not including) // F3x64[HtcPstateLimit] and F3xDC[PstateMaxVal] // 7_a) If F3xDC[PstateMaxVal] - F3x64[HtcPstateLimit] < 2 for any // processor, set PstateEn = 0 for enabled lower intermediate P - states // for all processors with (F3xDC[PstateMaxVal] - // F3x64[HtcPstateLimit] > 1) and skip the remaining actions for this // numbered step. // 7_b) Define each of the available lower intermediate P-states; for each // processor concurrently evaluate the following loop; when any // processor falls out of the loop (runs out of available lower // intermediate Pstates) all other processors have their remaining // lower intermediate P-states invalidated (PstateEn = 0); // for (i = F3xDC[PstateMaxVal]-1; i > F3x64[HtcPstateLimit]; i--) // - Identify the lowest CPU COF for P-states between // (not including) F3x64[HtcPstateLimit] and P(i). // - Identify the highest power for P-states between // (not including) F3x64[HtcPstateLimit] and P(i). // - Modify P(i) CPU COF for all processors to the previously // identified lowest CPU COF value. // - Modify P(i) power for all processors to the previously // identified highest power value. // 7_a) if (PstateMaxValMinusHtcPstateLimitLessThan2Flag) { for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); for (k = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - 1; k > PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit; k--) { if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) > 1) { PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].PStateEnable = 0; } } } } // 7_b) else { // Identify Lowest Frequency and Highest Power TotalIterations = 0; TempFlag1 = TRUE; for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); TempSocketPiArray[i] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - 1; } do { //For first socket, try to find a candidate if (TempSocketPiArray[0] != PStateBufferPtr[0].PStateCoreStruct[0].HtcPstateLimit) { while (PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].PStateEnable == 0) { TempSocketPiArray[0] = TempSocketPiArray[0] - 1; if (TempSocketPiArray[0] == PStateBufferPtr[0].PStateCoreStruct[0].HtcPstateLimit) { TempFlag1 = FALSE; break; } } } else { TempFlag1 = FALSE; } if (TempFlag1) { TempFreqArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].CoreFreq; TempPowerArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].Power; TempIddValueArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddValue; TempIddDivArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddDiv; //Try to find next candidate for (i = 1; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); if (TempSocketPiArray[i] != PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) { while (PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].PStateEnable == 0) { TempSocketPiArray[i]--; if (TempSocketPiArray[i] == PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) { TempFlag1 = FALSE; break; } }//end while } else { TempFlag1 = FALSE; } } //end for LogicalSocketCount } if (TempFlag1) { for (i = 0; i < LogicalSocketCount; i++) { // //Compare // CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); if (TempFreqArray[TotalIterations] > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq) { TempFreqArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq; } if (TempPowerArray[TotalIterations] < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power) { TempPowerArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power; TempIddValueArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue; TempIddDivArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv; } } // Modify (Pi) CPU COF and Power for all the CPUs for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq = TempFreqArray[TotalIterations]; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power = TempPowerArray[TotalIterations]; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue = TempIddValueArray[TotalIterations]; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv = TempIddDivArray[TotalIterations]; TempSocketPiArray[i] = TempSocketPiArray[i] - 1; } } else { for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); for (m = TempSocketPiArray[i]; m > PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit; m--) { PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[m].PStateEnable = 0; } } } TotalIterations++; } while (TempFlag1); } // else } // if(!AllCoreHaveMaxOnePStateFlag) PStateBufferPtr[0].InitStruct = 1; } // CurrentCore // Update the pState MSRs // This can be done only by individual core StartPstateMsrModify (PStateStrucPtr, StdHeader); //---------------------------------------------------------------------------------- // STEP - 8 //---------------------------------------------------------------------------------- // Place all cores into a valid COF and VID configuration corresponding to an // enabled P-state: // 8_a) Select an enabled P-state != to the P-state pointed to by // MSRC001_0063[CurPstate] for each core. // 8_b) Transition all cores to the selected P-states by writing the Control value // from the_PSS object corresponding to the selected P-state to // MSRC001_0062[PstateCmd]. // 8_c) Wait for all cores to report the Status value from the _PSS object // corresponding to the selected P-state in MSRC001_0063[CurPstate]. // PutAllCoreInPState0 (PStateBufferPtr, StdHeader); return AGESA_SUCCESS; }
/** * Multisocket call to determine the frequency that the northbridges must run. * * This function loops through all possible socket locations, comparing the * maximum NB frequencies to determine the slowest. This function also * determines if all coherent NB frequencies are equivalent. * * @param[in] NbPstate NB P-state number to check (0 = fastest) * @param[in] PlatformConfig Platform profile/build option config structure. * @param[out] SystemNbCofNumerator NB frequency numerator for the system in MHz * @param[out] SystemNbCofDenominator NB frequency denominator for the system * @param[out] SystemNbCofsMatch Whether or not all NB frequencies are equivalent * @param[out] NbPstateIsEnabledOnAllCPUs Whether or not NbPstate is valid on all CPUs * @param[in] StdHeader Config handle for library and services * * @retval TRUE At least one processor has NbPstate enabled. * @retval FALSE NbPstate is disabled on all CPUs * */ BOOLEAN GetSystemNbCofMulti ( IN UINT32 NbPstate, IN PLATFORM_CONFIGURATION *PlatformConfig, OUT UINT32 *SystemNbCofNumerator, OUT UINT32 *SystemNbCofDenominator, OUT BOOLEAN *SystemNbCofsMatch, OUT BOOLEAN *NbPstateIsEnabledOnAllCPUs, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Socket; UINT8 Module; UINT32 CurrentNbCof; UINT32 CurrentDivisor; UINT32 CurrentFreq; UINT32 LowFrequency; UINT32 Ignored32; BOOLEAN FirstCofNotFound; BOOLEAN NbPstateDisabled; BOOLEAN IsNbPstateEnabledOnAny; PCI_ADDR PciAddress; AGESA_STATUS Ignored; CPU_SPECIFIC_SERVICES *FamilySpecificServices; // Find the slowest NB COF in the system & whether or not all are equivalent LowFrequency = 0xFFFFFFFF; *SystemNbCofsMatch = TRUE; *NbPstateIsEnabledOnAllCPUs = FALSE; IsNbPstateEnabledOnAny = FALSE; FirstCofNotFound = TRUE; NbPstateDisabled = FALSE; for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { if (IsProcessorPresent (Socket, StdHeader)) { GetCpuServicesOfSocket (Socket, (CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader); for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &Ignored)) { break; } } if (FamilySpecificServices->GetNbPstateInfo (FamilySpecificServices, PlatformConfig, &PciAddress, NbPstate, &CurrentNbCof, &CurrentDivisor, &Ignored32, StdHeader)) { ASSERT (CurrentDivisor != 0); CurrentFreq = (CurrentNbCof / CurrentDivisor); if (FirstCofNotFound) { *SystemNbCofNumerator = CurrentNbCof; *SystemNbCofDenominator = CurrentDivisor; LowFrequency = CurrentFreq; IsNbPstateEnabledOnAny = TRUE; if (!NbPstateDisabled) { *NbPstateIsEnabledOnAllCPUs = TRUE; } FirstCofNotFound = FALSE; } else { if (CurrentFreq != LowFrequency) { *SystemNbCofsMatch = FALSE; if (CurrentFreq < LowFrequency) { LowFrequency = CurrentFreq; *SystemNbCofNumerator = CurrentNbCof; *SystemNbCofDenominator = CurrentDivisor; } } } } else { NbPstateDisabled = TRUE; *NbPstateIsEnabledOnAllCPUs = FALSE; } } } return IsNbPstateEnabledOnAny; }
/** * Save and Restore or Initialize the content of the mailbox registers. * * The registers used for AP mailbox should have the content related to their function * preserved. * * @param[in] EntryPoint Timepoint designator. * @param[in] PlatformConfig Contains the runtime modifiable feature input data. * @param[in] StdHeader Config Handle for library, services. * * @return AGESA_SUCCESS Always succeeds. * */ AGESA_STATUS STATIC PreserveMailboxes ( IN UINT64 EntryPoint, IN PLATFORM_CONFIGURATION *PlatformConfig, IN AMD_CONFIG_PARAMS *StdHeader ) { PRESERVE_MAILBOX_FAMILY_SERVICES *FamilySpecificServices; UINT32 Socket; UINT32 Module; PCI_ADDR BaseAddress; PCI_ADDR MailboxRegister; PCI_ADDR *NextRegister; AGESA_STATUS IgnoredStatus; AGESA_STATUS HeapStatus; UINT32 Value; ALLOCATE_HEAP_PARAMS AllocateParams; LOCATE_HEAP_PTR LocateParams; UINT32 RegisterEntryIndex; BaseAddress.AddressValue = ILLEGAL_SBDFO; if (EntryPoint == CPU_FEAT_AFTER_COHERENT_DISCOVERY) { // The save step. Save either the register content or zero (for cold boot, if family specifies that). AllocateParams.BufferHandle = PRESERVE_MAIL_BOX_HANDLE; AllocateParams.RequestedBufferSize = (sizeof (UINT32) * (MAX_PRESERVE_REGISTER_ENTRIES * (MAX_SOCKETS * MAX_DIES))); AllocateParams.Persist = HEAP_SYSTEM_MEM; HeapStatus = HeapAllocateBuffer (&AllocateParams, StdHeader); ASSERT ((HeapStatus == AGESA_SUCCESS) && (AllocateParams.BufferPtr != NULL)); LibAmdMemFill (AllocateParams.BufferPtr, 0xFF, AllocateParams.RequestedBufferSize, StdHeader); RegisterEntryIndex = 0; for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &BaseAddress, &IgnoredStatus)) { GetFeatureServicesOfSocket (&PreserveMailboxFamilyServiceTable, Socket, (const VOID **)&FamilySpecificServices, StdHeader); ASSERT (FamilySpecificServices != NULL); NextRegister = FamilySpecificServices->RegisterList; while (NextRegister->AddressValue != ILLEGAL_SBDFO) { ASSERT (RegisterEntryIndex < (MAX_PRESERVE_REGISTER_ENTRIES * GetPlatformNumberOfSockets () * GetPlatformNumberOfModules ())); if (FamilySpecificServices->IsZeroOnCold && (!IsWarmReset (StdHeader))) { Value = 0; } else { MailboxRegister = BaseAddress; MailboxRegister.Address.Function = NextRegister->Address.Function; MailboxRegister.Address.Register = NextRegister->Address.Register; LibAmdPciRead (AccessWidth32, MailboxRegister, &Value, StdHeader); } (* (MAILBOX_REGISTER_SAVE_ENTRY) AllocateParams.BufferPtr) [RegisterEntryIndex] = Value; RegisterEntryIndex++; NextRegister++; } } } } } else if ((EntryPoint == CPU_FEAT_INIT_LATE_END) || (EntryPoint == CPU_FEAT_AFTER_RESUME_MTRR_SYNC)) { // The restore step. Just write out the saved content in the buffer. LocateParams.BufferHandle = PRESERVE_MAIL_BOX_HANDLE; HeapStatus = HeapLocateBuffer (&LocateParams, StdHeader); ASSERT ((HeapStatus == AGESA_SUCCESS) && (LocateParams.BufferPtr != NULL)); RegisterEntryIndex = 0; for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &BaseAddress, &IgnoredStatus)) { GetFeatureServicesOfSocket (&PreserveMailboxFamilyServiceTable, Socket, (const VOID **)&FamilySpecificServices, StdHeader); NextRegister = FamilySpecificServices->RegisterList; while (NextRegister->AddressValue != ILLEGAL_SBDFO) { ASSERT (RegisterEntryIndex < (MAX_PRESERVE_REGISTER_ENTRIES * GetPlatformNumberOfSockets () * GetPlatformNumberOfModules ())); MailboxRegister = BaseAddress; MailboxRegister.Address.Function = NextRegister->Address.Function; MailboxRegister.Address.Register = NextRegister->Address.Register; Value = (* (MAILBOX_REGISTER_SAVE_ENTRY) LocateParams.BufferPtr) [RegisterEntryIndex]; LibAmdPciWrite (AccessWidth32, MailboxRegister, &Value, StdHeader); RegisterEntryIndex++; NextRegister++; } } } } HeapStatus = HeapDeallocateBuffer (PRESERVE_MAIL_BOX_HANDLE, StdHeader); } return AGESA_SUCCESS; }
/** * Set down core register on Orochi * * This function set F3x190 Downcore Control Register[5:0] * * @param[in] FamilySpecificServices The current Family Specific Services. * @param[in] Socket Socket ID. * @param[in] Module Module ID in socket. * @param[in] LeveledCores Number of core. * @param[in] CoreLevelMode Core level mode. * @param[in] StdHeader Header for library and services. * * @retval TRUE Down Core register is updated. * @retval FALSE Down Core register is not updated. */ BOOLEAN F15OrSetDownCoreRegister ( IN CPU_CORE_LEVELING_FAMILY_SERVICES *FamilySpecificServices, IN UINT32 *Socket, IN UINT32 *Module, IN UINT32 *LeveledCores, IN CORE_LEVELING_TYPE CoreLevelMode, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 Xbar2SriFreeListCBC; UINT8 L3FreeListCBC; UINT32 TempVar32_a; UINT32 CoreDisableBits; UINT32 NumberOfEnabledCores; UINT32 NumberOfEnabledCU; PCI_ADDR PciAddress; BOOLEAN IsUpdated; AGESA_STATUS AgesaStatus; NB_CAPS_REGISTER NbCaps; FREE_LIST_BUFFER_COUNT_REGISTER FreeListBufferCount; L3_BUFFER_COUNT_REGISTER L3BufferCnt; IsUpdated = FALSE; if (CoreLevelMode == CORE_LEVEL_COMPUTE_UNIT) { switch (*LeveledCores) { case 1: CoreDisableBits = DOWNCORE_MASK_SINGLE; break; case 2: CoreDisableBits = DOWNCORE_MASK_DUAL_COMPUTE_UNIT; break; case 3: CoreDisableBits = DOWNCORE_MASK_TRI_COMPUTE_UNIT; break; case 4: CoreDisableBits = DOWNCORE_MASK_FOUR_COMPUTE_UNIT; break; default: CoreDisableBits = 0; break; } } else { switch (*LeveledCores) { case 1: CoreDisableBits = DOWNCORE_MASK_SINGLE; break; case 2: CoreDisableBits = DOWNCORE_MASK_DUAL; break; case 4: CoreDisableBits = DOWNCORE_MASK_FOUR; break; case 6: CoreDisableBits = DOWNCORE_MASK_SIX; break; default: CoreDisableBits = 0; break; } } if (CoreDisableBits != 0) { if (GetPciAddress (StdHeader, (UINT8) *Socket, (UINT8) *Module, &PciAddress, &AgesaStatus)) { PciAddress.Address.Function = FUNC_5; PciAddress.Address.Register = NORTH_BRIDGE_CAPABILITIES_2_REG; LibAmdPciRead (AccessWidth32, PciAddress, &TempVar32_a, StdHeader); TempVar32_a = (TempVar32_a & 0xFF) + 1; TempVar32_a = (1 << TempVar32_a) - 1; CoreDisableBits &= TempVar32_a; NumberOfEnabledCores = ~(CoreDisableBits | ~(TempVar32_a)); PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = DOWNCORE_CTRL; LibAmdPciRead (AccessWidth32, PciAddress, &TempVar32_a, StdHeader); if ((TempVar32_a | CoreDisableBits) != TempVar32_a) { TempVar32_a |= CoreDisableBits; LibAmdPciWrite (AccessWidth32, PciAddress, &TempVar32_a, StdHeader); IsUpdated = TRUE; for (NumberOfEnabledCU = 0; NumberOfEnabledCores != 0; NumberOfEnabledCores >>= 2) { NumberOfEnabledCU += ((NumberOfEnabledCores & 3) != 0) ? 1 : 0; } switch (NumberOfEnabledCU) { case 1: Xbar2SriFreeListCBC = 0x16; L3FreeListCBC = 0x1C; break; case 2: Xbar2SriFreeListCBC = 0x14; L3FreeListCBC = 0x18; break; case 3: Xbar2SriFreeListCBC = 0x12; L3FreeListCBC = 0x14; break; case 4: Xbar2SriFreeListCBC = 0x10; L3FreeListCBC = 0x10; break; default: Xbar2SriFreeListCBC = 0x16; L3FreeListCBC = 0xE; break; } //D18F3x1A0[8:4] L3FreeListCBC: //BIOS: IF (NumOfCompUnitsOnNode==1) THEN 1Ch ELSEIF (NumOfCompUnitsOnNode==2) //THEN 18h ELSEIF (NumOfCompUnitsOnNode==3) THEN 14h ELSEIF //(NumOfCompUnitsOnNode==4) THEN 10h ELSEIF (NumOfCompUnitsOnNode==5) THEN 11h //ELSE 0Eh ENDIF. PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = L3_BUFFER_COUNT_REG; LibAmdPciRead (AccessWidth32, PciAddress, &L3BufferCnt, StdHeader); L3BufferCnt.L3FreeListCBC = L3FreeListCBC; LibAmdPciWrite (AccessWidth32, PciAddress, &L3BufferCnt, StdHeader); //D18F3x7C[4:0]Xbar2SriFreeListCBC: //BIOS: IF (L3Enabled) THEN 16h ELSEIF (D18F5x80[Enabled[3]]==1) THEN 10h ELSEIF //(D18F5x80[Enabled[2]]==1) THEN 12h ELSEIF (D18F5x80[Enabled[1]]==1) THEN 14h ELSE 16h ENDIF. PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = NB_CAPS_REG; LibAmdPciRead (AccessWidth32, PciAddress, &NbCaps, StdHeader); if (NbCaps.L3Capable == 0) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = FREE_LIST_BUFFER_COUNT_REG; LibAmdPciRead (AccessWidth32, PciAddress, &FreeListBufferCount, StdHeader); FreeListBufferCount.Xbar2SriFreeListCBC = Xbar2SriFreeListCBC; LibAmdPciWrite (AccessWidth32, PciAddress, &FreeListBufferCount, StdHeader); } } }
/** * Restores the context of a 'conditional' PCI device. * * This traverses the provided register list restoring PCI registers when appropriate. * * @param[in] StdHeader AMD standard header config param. * @param[in] Device 'conditional' PCI device to restore. * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or * AMD_S3LATE_RESTORE. * @param[in,out] OrMask Current buffer pointer of raw register values. * */ VOID RestoreConditionalPciDevice ( IN AMD_CONFIG_PARAMS *StdHeader, IN CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device, IN CALL_POINTS CallPoint, IN OUT VOID **OrMask ) { UINT8 RegSizeInBytes; UINT8 SpecialCaseIndex; UINT8 *IntermediatePtr; UINT8 BootMode; UINT16 i; UINT32 Socket; UINT32 Module; UINT32 RegValueRead; UINT32 RegValueWrite; UINT32 AndMask; ACCESS_WIDTH AccessWidth; AGESA_STATUS IgnoredSts; PCI_ADDR PciAddress; CPCI_REGISTER_BLOCK_HEADER *RegisterHdr; GetSocketModuleOfNode ((UINT32) Device->Node, &Socket, &Module, StdHeader); GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts); if (CallPoint == INIT_RESUME) { MemFS3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader); } else { S3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader); } BootMode = S3_RESUME_MODE; if (StdHeader->Func == AMD_INIT_POST) { BootMode = RESTORE_TRAINING_MODE | CAPSULE_REBOOT_MODE; } for (i = 0; i < RegisterHdr->NumRegisters; i++) { if (((Device->Mask1 & RegisterHdr->RegisterList[i].Mask1) != 0) && ((Device->Mask2 & RegisterHdr->RegisterList[i].Mask2) != 0)) { PciAddress.Address.Function = RegisterHdr->RegisterList[i].Function; PciAddress.Address.Register = RegisterHdr->RegisterList[i].Offset; RegSizeInBytes = RegisterHdr->RegisterList[i].Type.RegisterSize; switch (RegSizeInBytes) { case 1: AndMask = 0xFFFFFFFF & ((UINT8) RegisterHdr->RegisterList[i].AndMask); RegValueWrite = **(UINT8 **)OrMask; AccessWidth = AccessS3SaveWidth8; break; case 2: AndMask = 0xFFFFFFFF & ((UINT16) RegisterHdr->RegisterList[i].AndMask); RegValueWrite = **(UINT16 **)OrMask; AccessWidth = AccessS3SaveWidth16; break; case 3: // In this case, we don't need to restore a register. We just need to call a special // function to do certain things in the save and resume sequence. // This should not be used in a non-special case. AndMask = 0; RegValueWrite = 0; RegSizeInBytes = 0; AccessWidth = 0; break; default: AndMask = RegisterHdr->RegisterList[i].AndMask; RegSizeInBytes = 4; RegValueWrite = **(UINT32 **)OrMask; AccessWidth = AccessS3SaveWidth32; break; } if ((RegisterHdr->RegisterList[i].BootMode == 0) || ((BootMode & RegisterHdr->RegisterList[i].BootMode) != 0)) { // Do not restore the register if not in the right boot mode // Pointer to the saved data buffer still needs to be adjusted as data will be saved regardless of boot mode if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) { LibAmdPciRead (AccessWidth, PciAddress, &RegValueRead, StdHeader); RegValueWrite |= RegValueRead & (~AndMask); LibAmdPciWrite (AccessWidth, PciAddress, &RegValueWrite, StdHeader); } else { SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex; if (AndMask != 0) { RegisterHdr->SpecialCases[SpecialCaseIndex].Save (AccessWidth, PciAddress, &RegValueRead, StdHeader); RegValueWrite |= RegValueRead & (~AndMask); } RegisterHdr->SpecialCases[SpecialCaseIndex].Restore (AccessWidth, PciAddress, &RegValueWrite, StdHeader); } IDS_OPTION_HOOK (IDS_AFTER_RESTORING_PCI_REG, RegisterHdr, StdHeader); } IntermediatePtr = (UINT8 *) *OrMask; *OrMask = &IntermediatePtr[RegSizeInBytes]; if ((RegSizeInBytes == 0) && (RegValueWrite == RESTART_FROM_BEGINNING_LIST)) { // Restart from the beginning of the register list i = 0xFFFF; } } } }
/** * Should message-based C1e be enabled * * @param[in] PlatformConfig Contains the runtime modifiable feature input data. * @param[in] StdHeader Config Handle for library, services. * * @retval TRUE Message-based C1e is supported. * @retval FALSE Message-based C1e cannot be enabled. * */ BOOLEAN STATIC IsMsgBasedC1eFeatureEnabled ( IN PLATFORM_CONFIGURATION *PlatformConfig, IN AMD_CONFIG_PARAMS *StdHeader ) { UINTN Link; UINTN LinkCount; UINT32 Socket; UINT32 Module; BOOLEAN IsEnabled; PCI_ADDR PciAddress; AGESA_STATUS AgesaStatus; HT_HOST_FEATS HtHostFeats; CPU_SPECIFIC_SERVICES *CpuServices; MSG_BASED_C1E_FAMILY_SERVICES *FamilyServices; ASSERT (PlatformConfig->C1eMode < MaxC1eMode); IsEnabled = FALSE; if (PlatformConfig->C1eMode == C1eModeMsgBased) { ASSERT (PlatformConfig->C1ePlatformData < 0x10000); ASSERT (PlatformConfig->C1ePlatformData != 0); if ((PlatformConfig->C1ePlatformData != 0) && (PlatformConfig->C1ePlatformData < 0xFFFE)) { IsEnabled = TRUE; for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { if (IsProcessorPresent (Socket, StdHeader)) { GetFeatureServicesOfSocket (&MsgBasedC1eFamilyServiceTable, Socket, (CONST VOID **)&FamilyServices, StdHeader); if ((FamilyServices == NULL) || !FamilyServices->IsMsgBasedC1eSupported (FamilyServices, Socket, StdHeader)) { IsEnabled = FALSE; break; } else { // If the CPU revision supports message-based C1e, check whether the feature should // be disabled based on the speed of ncHT links (HT1). GetCpuServicesOfSocket (Socket, &CpuServices, StdHeader); for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &AgesaStatus)) { HtHostFeats.HtHostValue = 0; for (LinkCount = 0; LinkCount < 8; LinkCount++) { if (FindHtHostCapability (LinkCount, &PciAddress, StdHeader)) { CpuServices->GetHtLinkFeatures (CpuServices, &Link, &PciAddress, &HtHostFeats, StdHeader); if ((HtHostFeats.HtHostFeatures.NonCoherent == 1) && (HtHostFeats.HtHostFeatures.Ht1 == 1)) { IsEnabled = FALSE; break; } } } } // Exit for (Module = 0; Module < GetPlatformNumberOfModules; Module++) if (!IsEnabled) { break; } } } } // Exit for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) if (!IsEnabled) { break; } } } } return IsEnabled; }
/** * Saves the context of a 'conditional' PCI device. * * This traverses the provided register list saving PCI registers when appropriate. * * @param[in] StdHeader AMD standard header config param. * @param[in] Device 'conditional' PCI device to restore. * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or * AMD_S3LATE_RESTORE. * @param[in,out] OrMask Current buffer pointer of raw register values. * */ VOID SaveConditionalPciDevice ( IN AMD_CONFIG_PARAMS *StdHeader, IN CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device, IN CALL_POINTS CallPoint, IN OUT VOID **OrMask ) { UINT8 RegSizeInBytes; UINT8 SpecialCaseIndex; UINT8 *IntermediatePtr; UINT16 i; UINT32 Socket; UINT32 Module; UINT32 AndMask; ACCESS_WIDTH AccessWidth; AGESA_STATUS IgnoredSts; PCI_ADDR PciAddress; CPCI_REGISTER_BLOCK_HEADER *RegisterHdr; GetSocketModuleOfNode ((UINT32) Device->Node, &Socket, &Module, StdHeader); GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts); if (CallPoint == INIT_RESUME) { MemFS3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader); } else { S3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader); } for (i = 0; i < RegisterHdr->NumRegisters; i++) { if (((Device->Mask1 & RegisterHdr->RegisterList[i].Mask1) != 0) && ((Device->Mask2 & RegisterHdr->RegisterList[i].Mask2) != 0)) { PciAddress.Address.Function = RegisterHdr->RegisterList[i].Function; PciAddress.Address.Register = RegisterHdr->RegisterList[i].Offset; RegSizeInBytes = RegisterHdr->RegisterList[i].Type.RegisterSize; switch (RegSizeInBytes) { case 1: AndMask = 0xFFFFFFFF & ((UINT8) RegisterHdr->RegisterList[i].AndMask); AccessWidth = AccessS3SaveWidth8; break; case 2: AndMask = 0xFFFFFFFF & ((UINT16) RegisterHdr->RegisterList[i].AndMask); AccessWidth = AccessS3SaveWidth16; break; case 3: // In this case, we don't need to save a register. We just need to call a special // function to do certain things in the save and resume sequence. // This should not be used in a non-special case. AndMask = 0; RegSizeInBytes = 0; AccessWidth = 0; break; default: AndMask = RegisterHdr->RegisterList[i].AndMask; RegSizeInBytes = 4; AccessWidth = AccessS3SaveWidth32; break; } if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) { ASSERT ((AndMask != 0) && (RegSizeInBytes != 0) && (AccessWidth != 0)); LibAmdPciRead (AccessWidth, PciAddress, *OrMask, StdHeader); } else { SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex; RegisterHdr->SpecialCases[SpecialCaseIndex].Save (AccessWidth, PciAddress, *OrMask, StdHeader); } if (AndMask != 0) { // If AndMask is 0, then it is a not-care. Don't need to apply it to the OrMask **((UINT32 **) OrMask) &= AndMask; } if ((RegSizeInBytes == 0) && (**((UINT32 **) OrMask) == RESTART_FROM_BEGINNING_LIST)) { // Restart from the beginning of the register list i = 0xFFFF; } IntermediatePtr = (UINT8 *) *OrMask; *OrMask = &IntermediatePtr[RegSizeInBytes]; // += RegSizeInBytes; } } }
/** * Restores the context of a PCI device. * * This traverses the provided register list restoring PCI registers. * * @param[in] StdHeader AMD standard header config param. * @param[in] Device 'conditional' PCI device to restore. * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or * AMD_S3LATE_RESTORE. * @param[in,out] OrMask Current buffer pointer of raw register values. * */ VOID RestorePciDevice ( IN AMD_CONFIG_PARAMS *StdHeader, IN PCI_DEVICE_DESCRIPTOR *Device, IN CALL_POINTS CallPoint, IN OUT VOID **OrMask ) { UINT8 RegSizeInBytes; UINT8 SpecialCaseIndex; UINT8 *IntermediatePtr; UINT16 i; UINT32 Socket; UINT32 Module; UINT32 AndMask; UINT32 RegValueRead; UINT32 RegValueWrite; ACCESS_WIDTH AccessWidth; AGESA_STATUS IgnoredSts; PCI_ADDR PciAddress; PCI_REGISTER_BLOCK_HEADER *RegisterHdr; GetSocketModuleOfNode ((UINT32) Device->Node, &Socket, &Module, StdHeader); GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts); if (CallPoint == INIT_RESUME) { MemFS3GetPciDeviceRegisterList (Device, &RegisterHdr, StdHeader); } else { S3GetPciDeviceRegisterList (Device, &RegisterHdr, StdHeader); } for (i = 0; i < RegisterHdr->NumRegisters; i++) { PciAddress.Address.Function = RegisterHdr->RegisterList[i].Function; PciAddress.Address.Register = RegisterHdr->RegisterList[i].Offset; RegSizeInBytes = RegisterHdr->RegisterList[i].Type.RegisterSize; switch (RegSizeInBytes) { case 1: AndMask = 0xFFFFFFFF & ((UINT8) RegisterHdr->RegisterList[i].AndMask); RegValueWrite = **(UINT8 **)OrMask; AccessWidth = AccessS3SaveWidth8; break; case 2: AndMask = 0xFFFFFFFF & ((UINT16) RegisterHdr->RegisterList[i].AndMask); RegValueWrite = **(UINT16 **)OrMask; AccessWidth = AccessS3SaveWidth16; break; case 3: // In this case, we don't need to restore a register. We just need to call a special // function to do certain things in the save and resume sequence. // This should not be used in a non-special case. AndMask = 0; RegValueWrite = 0; RegSizeInBytes = 0; AccessWidth = 0; break; default: AndMask = RegisterHdr->RegisterList[i].AndMask; RegSizeInBytes = 4; RegValueWrite = **(UINT32 **)OrMask; AccessWidth = AccessS3SaveWidth32; break; } if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) { ASSERT ((AndMask != 0) && (RegSizeInBytes != 0) && (AccessWidth != 0)); LibAmdPciRead (AccessWidth, PciAddress, &RegValueRead, StdHeader); RegValueWrite |= RegValueRead & (~AndMask); LibAmdPciWrite (AccessWidth, PciAddress, &RegValueWrite, StdHeader); } else { SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex; if (AndMask != 0) { RegisterHdr->SpecialCases[SpecialCaseIndex].Save (AccessWidth, PciAddress, &RegValueRead, StdHeader); RegValueWrite |= RegValueRead & (~AndMask); } RegisterHdr->SpecialCases[SpecialCaseIndex].Restore (AccessWidth, PciAddress, &RegValueWrite, StdHeader); } IntermediatePtr = (UINT8 *) *OrMask; *OrMask = &IntermediatePtr[RegSizeInBytes]; // += RegSizeInBytes; } }