summaryrefslogtreecommitdiff
path: root/src/vendorcode/amd/agesa/f14/Proc/CPU/Family/0x10/cpuF10Pstate.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/amd/agesa/f14/Proc/CPU/Family/0x10/cpuF10Pstate.c')
-rw-r--r--src/vendorcode/amd/agesa/f14/Proc/CPU/Family/0x10/cpuF10Pstate.c863
1 files changed, 863 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f14/Proc/CPU/Family/0x10/cpuF10Pstate.c b/src/vendorcode/amd/agesa/f14/Proc/CPU/Family/0x10/cpuF10Pstate.c
new file mode 100644
index 0000000000..ed476a166d
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f14/Proc/CPU/Family/0x10/cpuF10Pstate.c
@@ -0,0 +1,863 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD Family_10 Pstate feature support functions.
+ *
+ * Provides the functions necessary to initialize the Pstate feature.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: CPU/F10
+ * @e \$Revision: 37640 $ @e \$Date: 2010-09-08 23:01:59 +0800 (Wed, 08 Sep 2010) $
+ *
+ */
+/*
+ *****************************************************************************
+ *
+ * Copyright (c) 2011, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ***************************************************************************
+ *
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "amdlib.h"
+#include "GeneralServices.h"
+#include "cpuPstateTables.h"
+#include "Table.h"
+#include "cpuFamilyTranslation.h"
+#include "cpuFamRegisters.h"
+#include "cpuF10Utilities.h"
+#include "cpuF10PowerMgmt.h"
+#include "CommonReturns.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_CPU_FAMILY_0X10_CPUF10PSTATE_FILECODE
+
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+VOID
+STATIC
+F10GetPowerStepValueInTime (
+ IN OUT UINT32 *PowerStepPtr
+ );
+
+VOID
+STATIC
+F10GetPllValueInTime (
+ IN OUT UINT32 *PllLockTimePtr
+ );
+
+AGESA_STATUS
+STATIC
+F10GetFrequencyXlatRegInfo (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN UINT8 PStateNumber,
+ IN UINT32 Frequency,
+ OUT UINT32 *CpuFidPtr,
+ OUT UINT32 *CpuDidPtr1,
+ OUT UINT32 *CpuDidPtr2,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+extern BUILD_OPT_CFG UserOptions;
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to check if Pstate PSD is dependent.
+ *
+ * @param[in] PstateCpuServices Pstate CPU services.
+ * @param[in,out] PlatformConfig Contains the runtime modifiable feature input data.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ * @retval TRUE PSD is dependent.
+ * @retval FALSE PSD is independent.
+ *
+ */
+BOOLEAN
+STATIC
+F10IsPstatePsdDependent (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN OUT PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ CPU_LOGICAL_ID CpuLogicalId;
+ PLATFORM_FEATS Features;
+
+ // Initialize the union
+ Features.PlatformValue = 0;
+ GetLogicalIdOfCurrentCore (&CpuLogicalId, StdHeader);
+ GetPlatformFeatures (&Features, PlatformConfig, StdHeader);
+
+ //
+ // RevC Single link has PSD option, default is dependent.
+ // If multi-link, always return independent.
+ //
+ if ((Features.PlatformFeatures.PlatformSingleLink) && ((CpuLogicalId.Revision & AMD_F10_Cx) != 0)) {
+ if (PlatformConfig->ForcePstateIndependent) {
+ return FALSE;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Family specific call to set core TscFreqSel.
+ *
+ * @param[in] PstateCpuServices Pstate CPU services.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ */
+VOID
+STATIC
+F10SetTscFreqSel (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT64 MsrValue;
+
+ LibAmdMsrRead (MSR_HWCR, &MsrValue, StdHeader);
+ if (UserOptions.OptionMultisocket) {
+ //
+ // If Agesa need to do p-state leveling on multi-socket, changing the P0
+ // frequency after setting this bit has no effect on the TSC rate.
+ //
+ ASSERT ((MsrValue & BIT24) == 0);
+ }
+ MsrValue = MsrValue | BIT24;
+ LibAmdMsrWrite (MSR_HWCR, &MsrValue, StdHeader);
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to get Pstate Transition Latency.
+ *
+ * Calculate TransitionLatency by power step value and pll value.
+ *
+ * @param[in] PstateCpuServices Pstate CPU services.
+ * @param[in] PStateLevelingBufferStructPtr Pstate row data buffer pointer
+ * @param[in] PciAddress Pci address
+ * @param[out] TransitionLatency The transition latency.
+ * @param[in] StdHeader Header for library and services
+ *
+ * @retval AGESA_SUCCESS Always succeeds.
+ */
+AGESA_STATUS
+F10GetPstateTransLatency (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN PSTATE_LEVELING *PStateLevelingBufferStructPtr,
+ IN PCI_ADDR *PciAddress,
+ OUT UINT32 *TransitionLatency,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 TempVar_b;
+ UINT32 TempVar_c;
+ UINT32 TempVar_d;
+ UINT32 TempVar8_a;
+ UINT32 TempVar8_b;
+ UINT32 Ignored;
+ UINT32 k;
+ UINT32 CpuFidSameFlag;
+ UINT8 PStateMaxValueOnCurrentCore;
+ UINT32 TransAndBusMastLatency;
+
+ CpuFidSameFlag = 1;
+
+ F10GetFrequencyXlatRegInfo (
+ PstateCpuServices,
+ 0,
+ PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateStruct[0].CoreFreq,
+ &TempVar_b,
+ &TempVar_c,
+ &Ignored,
+ StdHeader
+ );
+
+ TempVar_d = TempVar_b;
+ PStateMaxValueOnCurrentCore = PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateMaxValue;
+
+ //
+ //Check if MSRC001_00[68:64][CpuFid] is the same value for all P-states where
+ //MSRC001_00[68:64][PstateEn]=1
+ //
+ for (k = 1; k <= PStateMaxValueOnCurrentCore; k++) {
+ if (PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateStruct[k].PStateEnable != 0) {
+ F10GetFrequencyXlatRegInfo (
+ PstateCpuServices,
+ (UINT8) k,
+ PStateLevelingBufferStructPtr->PStateCoreStruct[0].PStateStruct[k].CoreFreq,
+ &TempVar_b,
+ &TempVar_c,
+ &Ignored,
+ StdHeader
+ );
+ }
+
+ if (TempVar_d != TempVar_b) {
+ CpuFidSameFlag = 0;
+ break;
+ }
+ }
+
+ PciAddress->Address.Register = 0xD4;
+ PciAddress->Address.Function = FUNC_3;
+ LibAmdPciRead (AccessWidth32, *PciAddress, &TempVar_d, StdHeader);
+
+ // PowerStepDown - Bits 20:23
+ TempVar8_a = (TempVar_d & 0x00F00000) >> 20;
+
+ // PowerStepUp - Bits 24:27
+ TempVar8_b = (TempVar_d & 0x0F000000) >> 24;
+
+ // Convert the raw numbers in TempVar8_a and TempVar8_b into time
+ F10GetPowerStepValueInTime (&TempVar8_a);
+ F10GetPowerStepValueInTime (&TempVar8_b);
+
+ //
+ //(12 * (F3xD4[PowerStepDown] + F3xD4[PowerStepUp]) /1000) us
+ //
+ TransAndBusMastLatency =
+ (12 * (TempVar8_a + TempVar8_b) + 999) / 1000;
+
+ if (CpuFidSameFlag == 0) {
+ //
+ //+ F3xA0[PllLockTime]
+ //
+ PciAddress->Address.Register = 0xA0;
+ LibAmdPciRead (AccessWidth32, *PciAddress, &TempVar_d, StdHeader);
+
+ TempVar8_a = (0x00003800 & TempVar_d) >> 11;
+ F10GetPllValueInTime (&TempVar8_a);
+ TransAndBusMastLatency += TempVar8_a;
+ }
+
+ *TransitionLatency = TransAndBusMastLatency;
+
+ return (AGESA_SUCCESS);
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to calculates the frequency in megahertz of the desired P-state.
+ *
+ * @param[in] PstateCpuServices Pstate CPU services.
+ * @param[in] StateNumber The P-State to analyze.
+ * @param[out] FrequencyInMHz The P-State's frequency in MegaHertz
+ * @param[in] StdHeader Header for library and services
+ *
+ * @retval AGESA_SUCCESS Always Succeeds.
+ */
+AGESA_STATUS
+F10GetPstateFrequency (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN UINT8 StateNumber,
+ OUT UINT32 *FrequencyInMHz,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT8 TempValue;
+ UINT32 CpuDid;
+ UINT32 CpuFid;
+ UINT64 MsrRegister;
+
+ ASSERT (StateNumber < NM_PS_REG);
+ LibAmdMsrRead (PS_REG_BASE + (UINT32) StateNumber, &MsrRegister, StdHeader);
+ ASSERT (((PSTATE_MSR *) &MsrRegister)->PsEnable == 1);
+ CpuDid = (UINT32) (((PSTATE_MSR *) &MsrRegister)->CpuDid);
+ CpuFid = (UINT32) (((PSTATE_MSR *) &MsrRegister)->CpuFid);
+
+ switch (CpuDid) {
+ case 0:
+ TempValue = 1;
+ break;
+ case 1:
+ TempValue = 2;
+ break;
+ case 2:
+ TempValue = 4;
+ break;
+ case 3:
+ TempValue = 8;
+ break;
+ case 4:
+ TempValue = 16;
+ break;
+ default:
+ // CpuDid is set to an undefined value. This is due to either a misfused CPU, or
+ // an invalid P-state MSR write.
+ ASSERT (FALSE);
+ TempValue = 1;
+ break;
+ }
+ *FrequencyInMHz = (100 * (CpuFid + 0x10) / TempValue);
+ return (AGESA_SUCCESS);
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to sets the Pstate MSR to each APs base on Pstate Buffer.
+ *
+ * @param[in] PstateCpuServices Pstate CPU services.
+ * @param[in] CpuAmdPState Gathered P-state data structure for whole system.
+ * @param[in] StdHeader Config for library and services.
+ *
+ * @retval AGESA_SUCCESS Always succeeds.
+ *
+ */
+AGESA_STATUS
+F10PstateLevelingCoreMsrModify (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN S_CPU_AMD_PSTATE *CpuAmdPState,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 i;
+ UINT32 Ignored;
+ UINT32 k;
+ UINT32 TempVar_d;
+ UINT32 TempVar_e;
+ UINT32 TempVar_f;
+ UINT32 LogicalSocketCount;
+ UINT32 PciRegister;
+ UINT32 Socket;
+ UINT32 Module;
+ UINT32 Core;
+ UINT64 MsrValue;
+ AGESA_STATUS Status;
+ PSTATE_LEVELING *PStateBufferPtr;
+ PSTATE_LEVELING *PStateBufferPtrTmp;
+ S_CPU_AMD_PSTATE *CpuAmdPstatePtr;
+ PCI_ADDR PciAddress;
+ CPU_SPECIFIC_SERVICES *FamilySpecificServices;
+
+ GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader);
+ ASSERT (FamilySpecificServices != NULL);
+
+ Ignored = 0;
+ CpuAmdPstatePtr = (S_CPU_AMD_PSTATE *) CpuAmdPState;
+ PStateBufferPtrTmp = CpuAmdPstatePtr->PStateLevelingStruc;
+ PStateBufferPtr = CpuAmdPstatePtr->PStateLevelingStruc;
+ LogicalSocketCount = CpuAmdPstatePtr->TotalSocketInSystem;
+ PciAddress.AddressValue = 0;
+
+ //
+ //Try to find the Pstate buffer specific to this core(socket).
+ //
+ IdentifyCore (StdHeader, &Socket, &Module, &Core, &Status);
+ for (i = 0; i < LogicalSocketCount; i++) {
+ CpuGetPStateLevelStructure (&PStateBufferPtrTmp, CpuAmdPstatePtr, i, StdHeader);
+ if (PStateBufferPtrTmp->SocketNumber == Socket) {
+ break;
+ }
+ }
+
+ if (PStateBufferPtr[0].OnlyOneEnabledPState) {
+ //
+ //If all processors have only 1 enabled P-state, the following sequence should be performed on all cores:
+ //
+
+ //1. Write the appropriate CpuFid value resulting from the matched CPU COF to MSRC001_0064[CpuFid].
+ LibAmdMsrRead (MSR_PSTATE_0, &MsrValue, StdHeader);
+ Status = F10GetFrequencyXlatRegInfo (PstateCpuServices, 0, PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[0].CoreFreq, &TempVar_d, &TempVar_e, &Ignored, StdHeader);
+ // Bits 5:0
+ ((PSTATE_MSR *) &MsrValue)->CpuFid = TempVar_d;
+ // Bits 8:6
+ ((PSTATE_MSR *) &MsrValue)->CpuDid = TempVar_e;
+ // Bits 39:32
+ ((PSTATE_MSR *) &MsrValue)->IddValue = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[0].IddValue;
+ // Bits 41:40
+ ((PSTATE_MSR *) &MsrValue)->IddDiv = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[0].IddDiv;
+ // Enable the P-State
+ ((PSTATE_MSR *) &MsrValue)->PsEnable = 1;
+ LibAmdMsrWrite (MSR_PSTATE_0, &MsrValue, StdHeader);
+
+ //2. Copy MSRC001_0064 to MSRC001_0065.
+ LibAmdMsrWrite (MSR_PSTATE_1, &MsrValue, StdHeader);
+
+ //3. Write 001b to F3xDC[PstatemaxVal].
+ GetPciAddress (StdHeader, Socket, Module, &PciAddress, &Status);
+ PciAddress.Address.Register = CPTC2_REG;
+ PciAddress.Address.Function = FUNC_3;
+ LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader);
+ ((CLK_PWR_TIMING_CTRL2_REGISTER *) &PciRegister)->PstateMaxVal = 1;
+ LibAmdPciWrite (AccessWidth32, PciAddress, &PciRegister, StdHeader);
+
+ //4. Write 001b to MSRC001_0062[PstateCmd].
+ FamilySpecificServices->TransitionPstate (FamilySpecificServices, (UINT8) 1, (BOOLEAN) FALSE, StdHeader);
+
+ //5. Wait for MSRC001_0071[CurCpuFid] = MSRC001_0065[CpuFid].
+ do {
+ LibAmdMsrRead (MSR_COFVID_STS, &MsrValue, StdHeader);
+ } while (((COFVID_STS_MSR *) &MsrValue)->CurCpuFid != TempVar_d);
+
+ //6. Write 000b to MSRC001_0062[PstateCmd].
+ FamilySpecificServices->TransitionPstate (FamilySpecificServices, (UINT8) 0, (BOOLEAN) FALSE, StdHeader);
+
+ //7. Wait for MSRC001_0071[CurCpuFid] = MSRC001_0064[CpuFid].
+ do {
+ LibAmdMsrRead (MSR_COFVID_STS, &MsrValue, StdHeader);
+ } while (((COFVID_STS_MSR *) &MsrValue)->CurCpuFid != TempVar_d);
+
+ //8. Write 0b to MSRC001_0065[PstateEn].
+ LibAmdMsrRead (MSR_PSTATE_1, &MsrValue, StdHeader);
+ ((PSTATE_MSR *) &MsrValue)->PsEnable = 0;
+ LibAmdMsrWrite (MSR_PSTATE_1, &MsrValue, StdHeader);
+
+ //9. Write 000b to F3xDC[PstateMaxVal] and exit the sequence (no further steps are required).
+ LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader);
+ ((CLK_PWR_TIMING_CTRL2_REGISTER *) &PciRegister)->PstateMaxVal = 0;
+ LibAmdPciWrite (AccessWidth32, PciAddress, &PciRegister, StdHeader);
+
+ } else {
+ TempVar_f = MSR_PSTATE_0;
+
+ for (k = 0; k <= PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue; k++, TempVar_f++) {
+ // If pState is not disabled then do update
+ LibAmdMsrRead (TempVar_f, &MsrValue, StdHeader);
+
+ if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].PStateEnable == 1) {
+ Status = F10GetFrequencyXlatRegInfo (PstateCpuServices, (UINT8) k, PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].CoreFreq, &TempVar_d, &TempVar_e, &Ignored, StdHeader);
+ if (Status != AGESA_ERROR) {
+ // Bits 5:0
+ ((PSTATE_MSR *) &MsrValue)->CpuFid = TempVar_d;
+ // Bits 8:6
+ ((PSTATE_MSR *) &MsrValue)->CpuDid = TempVar_e;
+ }
+
+ // Bits 39:32
+ ((PSTATE_MSR *) &MsrValue)->IddValue = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].IddValue;
+ // Bits 41:40
+ ((PSTATE_MSR *) &MsrValue)->IddDiv = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].IddDiv;
+ // Enable the P-State
+ ((PSTATE_MSR *) &MsrValue)->PsEnable = 1;
+ LibAmdMsrWrite (TempVar_f, &MsrValue, StdHeader);
+ } else {
+ // Disable the P-State
+ ((PSTATE_MSR *) &MsrValue)->PsEnable = 0;
+ LibAmdMsrWrite (TempVar_f, &MsrValue, StdHeader);
+ }
+ }
+ }
+ return AGESA_SUCCESS;
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to calculates the power in milliWatts of the desired P-state.
+ *
+ * @param[in] PstateCpuServices Pstate CPU services.
+ * @param[in] StateNumber Which P-state to analyze
+ * @param[out] PowerInMw The Power in milliWatts of that P-State
+ * @param[in] StdHeader Header for library and services
+ *
+ * @retval AGESA_SUCCESS Always succeeds.
+ */
+AGESA_STATUS
+F10GetPstatePower (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN UINT8 StateNumber,
+ OUT UINT32 *PowerInMw,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 CpuVid;
+ UINT32 IddValue;
+ UINT32 IddDiv;
+ UINT32 Socket;
+ UINT32 Module;
+ UINT32 Ignored;
+ BOOLEAN PviFlag;
+ UINT32 V_x10000;
+ UINT32 Power;
+ PCI_ADDR PciAddress;
+ UINT32 TempVar_a;
+ UINT64 MsrRegister;
+ AGESA_STATUS IgnoredSts;
+
+ ASSERT (StateNumber < NM_PS_REG);
+ LibAmdMsrRead (PS_REG_BASE + (UINT32) StateNumber, &MsrRegister, StdHeader);
+ ASSERT (((PSTATE_MSR *) &MsrRegister)->PsEnable == 1);
+ CpuVid = (UINT32) (((PSTATE_MSR *) &MsrRegister)->CpuVid);
+ IddValue = (UINT32) (((PSTATE_MSR *) &MsrRegister)->IddValue);
+ IddDiv = (UINT32) (((PSTATE_MSR *) &MsrRegister)->IddDiv);
+
+ IdentifyCore (StdHeader, &Socket, &Module, &Ignored, &IgnoredSts);
+ GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts);
+
+ PciAddress.Address.Function = FUNC_3;
+ PciAddress.Address.Register = POWER_CTRL_MISCELLANEOUS_REG;
+ LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_a, StdHeader);
+ if ((TempVar_a & 0x00000100) != 0) {
+ PviFlag = TRUE;
+ } else {
+ PviFlag = FALSE;
+ }
+ if (PviFlag) {
+ // Set CpuVid value in case CPU is in PVI mode
+ if (CpuVid > 0x5D) {
+ CpuVid = 0x3F;
+ } else if (CpuVid > 0x3E) {
+ CpuVid = CpuVid - 0x1F;
+ } else {
+ CpuVid = (CpuVid >> 1);
+ }
+
+ // PVI Encoding
+ if (CpuVid >= 0x20) {
+ V_x10000 = 7625L - (125L * (CpuVid - 0x20));
+ } else {
+ V_x10000 = 15500L - (250L * CpuVid);
+ }
+ } else {
+ if (CpuVid >= 0x7C) {
+ V_x10000 = 0;
+ } else {
+ V_x10000 = 15500L - (125L * CpuVid);
+ }
+ }
+
+ Power = V_x10000 * IddValue;
+
+ switch (IddDiv) {
+ case 0:
+ *PowerInMw = Power / 10L;
+ break;
+ case 1:
+ *PowerInMw = Power / 100L;
+ break;
+ case 2:
+ *PowerInMw = Power / 1000L;
+ break;
+ default:
+ // IddDiv is set to an undefined value. This is due to either a misfused CPU, or
+ // an invalid P-state MSR write.
+ ASSERT (FALSE);
+ *PowerInMw = 0;
+ break;
+ }
+ return (AGESA_SUCCESS);
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to get CPU pstate max state.
+ *
+ * @param[in] PstateCpuServices Pstate CPU services.
+ * @param[out] MaxPStateNumber Boolean flag return pstate enable.
+ * @param[in] StdHeader Handle of Header for calling lib functions and services.
+ *
+ * @retval AGESA_SUCCESS Always succeeds.
+ */
+AGESA_STATUS
+F10GetPstateMaxState (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ OUT UINT32 *MaxPStateNumber,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT64 MsrValue;
+ UINT32 PciRegister;
+ PCI_ADDR PciAddress;
+ CPUID_DATA CpuidData;
+
+ PciRegister = 0;
+
+ // Check if CPB is supported. if yes, skip boosted p-state. The boosted p-state number = F4x15C[NumBoostStates].
+ LibAmdCpuidRead (AMD_CPUID_APM, &CpuidData, StdHeader);
+ if (((CpuidData.EDX_Reg & 0x00000200) >> 9) == 1) {
+ PciAddress.AddressValue = CPB_CTRL_PCI_ADDR;
+ LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); // F4x15C
+ }
+
+ //
+ // Read PstateMaxVal [6:4] from MSR C001_0061
+ // So, we will know the max pstate state in this socket.
+ //
+ LibAmdMsrRead (MSR_PSTATE_CURRENT_LIMIT, &MsrValue, StdHeader);
+ *MaxPStateNumber = (UINT32) (((PSTATE_CURLIM_MSR *) &MsrValue)->PstateMaxVal) + (UINT32) (((CPB_CTRL_REGISTER *) &PciRegister)->NumBoostStates);
+
+ return (AGESA_SUCCESS);
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to get CPU pstate register information.
+ *
+ * @param[in] PstateCpuServices Pstate CPU services.
+ * @param[in] PState Input Pstate number for query.
+ * @param[out] PStateEnabled Boolean flag return pstate enable.
+ * @param[in,out] IddVal Pstate current value.
+ * @param[in,out] IddDiv Pstate current divisor.
+ * @param[out] SwPstateNumber Software P-state number.
+ * @param[in] StdHeader Handle of Header for calling lib functions and services.
+ *
+ * @retval AGESA_SUCCESS Always succeeds.
+ */
+AGESA_STATUS
+F10GetPstateRegisterInfo (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN UINT32 PState,
+ OUT BOOLEAN *PStateEnabled,
+ IN OUT UINT32 *IddVal,
+ IN OUT UINT32 *IddDiv,
+ OUT UINT32 *SwPstateNumber,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT64 MsrRegister;
+ UINT32 PciRegister;
+ PCI_ADDR PciAddress;
+ CPUID_DATA CpuidData;
+
+ PciRegister = 0;
+ ASSERT (PState < NM_PS_REG);
+
+ // Check if CPB is supported. if yes, skip boosted p-state. The boosted p-state number = F4x15C[NumBoostStates].
+ LibAmdCpuidRead (AMD_CPUID_APM, &CpuidData, StdHeader);
+ if (((CpuidData.EDX_Reg & 0x00000200) >> 9) == 1) {
+ PciAddress.AddressValue = CPB_CTRL_PCI_ADDR;
+ LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); // F4x15C
+ }
+
+ *SwPstateNumber = PState;
+
+ // Read PSTATE MSRs
+ LibAmdMsrRead (PS_REG_BASE + (UINT32) PState, &MsrRegister, StdHeader);
+
+ if (((PSTATE_MSR *) &MsrRegister)->PsEnable == 1) {
+ // PState enable = bit 63
+ *PStateEnabled = TRUE;
+ // Check input pstate belongs to Boosted-Pstate, if yes, return *PStateEnabled = FALSE.
+ if (PState < ((CPB_CTRL_REGISTER *) &PciRegister)->NumBoostStates) {
+ *PStateEnabled = FALSE;
+ } else {
+ *SwPstateNumber = PState - ((CPB_CTRL_REGISTER *) &PciRegister)->NumBoostStates;
+ }
+ } else {
+ *PStateEnabled = FALSE;
+ }
+
+ // Bits 39:32 (high 32 bits [7:0])
+ *IddVal = (UINT32) ((PSTATE_MSR *) &MsrRegister)->IddValue;
+ // Bits 41:40 (high 32 bits [9:8])
+ *IddDiv = (UINT32) ((PSTATE_MSR *) &MsrRegister)->IddDiv;
+
+ return (AGESA_SUCCESS);
+}
+
+CONST PSTATE_CPU_FAMILY_SERVICES ROMDATA F10PstateServices =
+{
+ 0,
+ (PF_PSTATE_PSD_IS_NEEDED) CommonReturnTrue,
+ F10IsPstatePsdDependent,
+ F10SetTscFreqSel,
+ F10GetPstateTransLatency,
+ F10GetPstateFrequency,
+ F10PstateLevelingCoreMsrModify,
+ F10GetPstatePower,
+ F10GetPstateMaxState,
+ F10GetPstateRegisterInfo
+};
+
+
+/*---------------------------------------------------------------------------------------
+ * L O C A L F U N C T I O N S
+ *---------------------------------------------------------------------------------------
+ */
+
+
+/**
+ *---------------------------------------------------------------------------------------
+ *
+ * F10GetPowerStepValueInTime
+ *
+ * Description:
+ * Convert power step value in time
+ *
+ * Parameters:
+ * @param[out] *PowerStepPtr
+ *
+ * @retval VOID
+ *
+ *---------------------------------------------------------------------------------------
+ **/
+VOID
+STATIC
+F10GetPowerStepValueInTime (
+ IN OUT UINT32 *PowerStepPtr
+ )
+{
+ UINT32 TempVar_a;
+
+ TempVar_a = *PowerStepPtr;
+
+ if (TempVar_a < 0x4) {
+ *PowerStepPtr = 400 - (TempVar_a * 100);
+ } else if (TempVar_a < 0x9) {
+ *PowerStepPtr = 130 - (TempVar_a * 10);
+ } else {
+ *PowerStepPtr = 90 - (TempVar_a * 5);
+ }
+}
+
+
+/**
+ *---------------------------------------------------------------------------------------
+ *
+ * F10GetPllValueInTime
+ *
+ * Description:
+ * Convert PLL Value in time
+ *
+ * Parameters:
+ * @param[out] *PllLockTimePtr
+ *
+ * @retval VOID
+ *
+ *---------------------------------------------------------------------------------------
+ **/
+VOID
+STATIC
+F10GetPllValueInTime (
+ IN OUT UINT32 *PllLockTimePtr
+ )
+{
+ if (*PllLockTimePtr < 4) {
+ *PllLockTimePtr = *PllLockTimePtr + 1;
+ } else if (*PllLockTimePtr == 4) {
+ *PllLockTimePtr = 8;
+ } else if (*PllLockTimePtr == 5) {
+ *PllLockTimePtr = 16;
+ } else
+ *PllLockTimePtr = 0;
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * This function will return the CpuFid and CpuDid in MHz, using the formula
+ * described in the BKDG MSRC001_00[68:64] P-State [4:0] Registers:bit 8:0
+ *
+ * @param[in] PstateCpuServices The current Family Specific Services.
+ * @param[in] PStateNumber P-state number to check.
+ * @param[in] Frequency Leveled target frequency for PStateNumber.
+ * @param[out] *CpuFidPtr New leveled FID.
+ * @param[out] *CpuDidPtr1 New leveled DID info 1.
+ * @param[out] *CpuDidPtr2 New leveled DID info 2.
+ * @param[in] *StdHeader Header for library and services.
+ *
+ * @retval AGESA_WARNING This P-State does not need to be modified.
+ * @retval AGESA_SUCCESS This P-State must be modified to be level.
+ */
+AGESA_STATUS
+STATIC
+F10GetFrequencyXlatRegInfo (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN UINT8 PStateNumber,
+ IN UINT32 Frequency,
+ OUT UINT32 *CpuFidPtr,
+ OUT UINT32 *CpuDidPtr1,
+ OUT UINT32 *CpuDidPtr2,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 i;
+ UINT32 j;
+ AGESA_STATUS Status;
+ UINT32 FrequencyInMHz;
+
+ FrequencyInMHz = 0;
+ *CpuDidPtr2 = 0xFFFF;
+
+ Status = AGESA_SUCCESS;
+
+ PstateCpuServices->GetPstateFrequency (PstateCpuServices, PStateNumber, &FrequencyInMHz, StdHeader);
+ if (FrequencyInMHz == Frequency) {
+ Status |= AGESA_WARNING;
+ }
+
+ // CPU Frequency = 100 MHz * (CpuFid + 10h) / (2^CpuDid)
+ // In this for loop i = 2^CpuDid
+
+
+ for (i = 1; i < 17; (i += i)) {
+ for (j = 0; j < 64; j++) {
+ if (Frequency == ((100 * (j + 0x10)) / i )) {
+ *CpuFidPtr = j;
+ if (i == 1) {
+ *CpuDidPtr1 = 0;
+ } else if (i == 2) {
+ *CpuDidPtr1 = 1;
+ } else if (i == 4) {
+ *CpuDidPtr1 = 2;
+ } else if (i == 8) {
+ *CpuDidPtr1 = 3;
+ } else if (i == 16) {
+ *CpuDidPtr1 = 4;
+ } else {
+ *CpuFidPtr = 0xFFFF;
+ *CpuDidPtr1 = 0xFFFF;
+ }
+ // Success
+ return Status;
+ }
+ }
+ }
+
+ // Error Condition
+ *CpuFidPtr = 0x00FF;
+ *CpuDidPtr1 = 0x00FF;
+ *CpuDidPtr2 = 0x00FF;
+
+ return AGESA_ERROR;
+}
+