aboutsummaryrefslogtreecommitdiff
path: root/src/vendorcode/amd/agesa/f12/Proc/CPU/Family/0x12/cpuF12Pstate.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/amd/agesa/f12/Proc/CPU/Family/0x12/cpuF12Pstate.c')
-rwxr-xr-xsrc/vendorcode/amd/agesa/f12/Proc/CPU/Family/0x12/cpuF12Pstate.c481
1 files changed, 481 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f12/Proc/CPU/Family/0x12/cpuF12Pstate.c b/src/vendorcode/amd/agesa/f12/Proc/CPU/Family/0x12/cpuF12Pstate.c
new file mode 100755
index 0000000000..8b4fbd5350
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f12/Proc/CPU/Family/0x12/cpuF12Pstate.c
@@ -0,0 +1,481 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * AMD Family_12 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/F12
+ * @e \$Revision: 44702 $ @e \$Date: 2011-01-05 06:54:00 +0800 (Wed, 05 Jan 2011) $
+ *
+ */
+/*
+ ******************************************************************************
+ *
+ * Copyright (c) 2011, Advanced Micro Devices, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Advanced Micro Devices, Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ ******************************************************************************
+ */
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "amdlib.h"
+#include "Ids.h"
+#include "cpuPstateTables.h"
+#include "cpuFamilyTranslation.h"
+#include "cpuRegisters.h"
+#include "cpuF12Utilities.h"
+#include "cpuF12PowerMgmt.h"
+#include "CommonReturns.h"
+#include "Filecode.h"
+CODE_GROUP (G1_PEICC)
+RDATA_GROUP (G1_PEICC)
+
+#define FILECODE PROC_CPU_FAMILY_0X12_CPUF12PSTATE_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
+ *----------------------------------------------------------------------------------------
+ */
+
+/*----------------------------------------------------------------------------------------
+ * 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
+ *----------------------------------------------------------------------------------------
+ */
+AGESA_STATUS
+F12GetPstateTransLatency (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN PSTATE_LEVELING *PStateLevelingBufferStructPtr,
+ IN PCI_ADDR *PciAddress,
+ OUT UINT32 *TransitionLatency,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+ AGESA_STATUS
+F12GetPstateFrequency (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN UINT8 StateNumber,
+ OUT UINT32 *FrequencyInMHz,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+ AGESA_STATUS
+F12GetPstatePower (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN UINT8 StateNumber,
+ OUT UINT32 *PowerInMw,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+AGESA_STATUS
+F12GetPstateMaxState (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ OUT UINT32 *MaxPStateNumber,
+ OUT UINT8 *NumberOfBoostStates,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+AGESA_STATUS
+F12GetPstateRegisterInfo (
+ 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
+ );
+
+/*----------------------------------------------------------------------------------------
+ * E X P O R T E D F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * 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
+F12IsPstatePsdDependent (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN OUT PLATFORM_CONFIGURATION *PlatformConfig,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ // F12h defaults to dependent PSD; allow Platform Configuration to
+ // overwrite the default setting.
+ if (PlatformConfig->ForcePstateIndependent) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Family specific call to set core TscFreqSel.
+ *
+ * @param[in] PstateCpuServices Pstate CPU services.
+ * @param[in] StdHeader Config Handle for library, services.
+ *
+ */
+VOID
+STATIC
+F12SetTscFreqSel (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT64 MsrValue;
+
+ LibAmdMsrRead (MSR_HWCR, &MsrValue, StdHeader);
+ MsrValue = MsrValue | BIT24;
+ LibAmdMsrWrite (MSR_HWCR, &MsrValue, StdHeader);
+}
+
+/*---------------------------------------------------------------------------------------*/
+/**
+ * Family specific call to get Pstate Transition Latency.
+ *
+ * Follow BKDG, return zero currently.
+ *
+ * @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
+F12GetPstateTransLatency (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN PSTATE_LEVELING *PStateLevelingBufferStructPtr,
+ IN PCI_ADDR *PciAddress,
+ OUT UINT32 *TransitionLatency,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ //
+ // TransitionLatency (us) = BusMasterLatency (us) = 0 us, calculation may
+ // change due to a potential new encoding.
+ //
+ *TransitionLatency = 0;
+ 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
+F12GetPstateFrequency (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN UINT8 StateNumber,
+ OUT UINT32 *FrequencyInMHz,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 CpuDid;
+ UINT32 CpuFid;
+ UINT32 LocalPciRegister;
+ UINT64 LocalMsrRegister;
+ BOOLEAN FrequencyCalculated;
+ PCI_ADDR PciAddress;
+
+ ASSERT (StateNumber < NM_PS_REG);
+
+ LibAmdMsrRead (PS_REG_BASE + (UINT32) StateNumber, &LocalMsrRegister, StdHeader);
+ ASSERT (((PSTATE_MSR *) &LocalMsrRegister)->PsEnable == 1);
+
+ CpuDid = (UINT32) (((PSTATE_MSR *) &LocalMsrRegister)->CpuDid);
+ CpuFid = (UINT32) (((PSTATE_MSR *) &LocalMsrRegister)->CpuFid);
+
+ FrequencyCalculated = FALSE;
+
+ switch (CpuDid) {
+ case 0:
+ CpuDid = 10;
+ break;
+ case 1:
+ CpuDid = 15;
+ break;
+ case 2:
+ CpuDid = 20;
+ break;
+ case 3:
+ CpuDid = 30;
+ break;
+ case 4:
+ CpuDid = 40;
+ break;
+ case 5:
+ CpuDid = 60;
+ break;
+ case 6:
+ CpuDid = 80;
+ break;
+ case 7:
+ CpuDid = 120;
+ break;
+ case 8:
+ CpuDid = 160;
+ break;
+ case 14:
+ if (CpuFid != 0) {
+ CpuDid = 160;
+ } else {
+ FrequencyCalculated = TRUE;
+ *FrequencyInMHz = 100;
+ }
+ 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);
+ CpuDid = 1;
+ break;
+ }
+
+ if (!FrequencyCalculated) {
+ PciAddress.AddressValue = MAKE_SBDFO (0, 0, PCI_DEV_BASE, 4, 0x15C);
+ LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader);
+
+ if ((LocalPciRegister & BIT30) != 0) {
+ CpuFid += 0x20;
+ } else {
+ CpuFid += 0x10;
+ }
+ *FrequencyInMHz = (((100 * 10) * CpuFid) / CpuDid);
+ }
+
+ 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
+F12GetPstatePower (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ IN UINT8 StateNumber,
+ OUT UINT32 *PowerInMw,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 CpuVid;
+ UINT32 IddValue;
+ UINT32 IddDiv;
+ UINT32 V_x10000;
+ UINT32 Power;
+ UINT64 LocalMsrRegister;
+
+ ASSERT (StateNumber < NM_PS_REG);
+ LibAmdMsrRead (PS_REG_BASE + (UINT32) StateNumber, &LocalMsrRegister, StdHeader);
+ ASSERT (((PSTATE_MSR *) &LocalMsrRegister)->PsEnable == 1);
+ CpuVid = (UINT32) (((PSTATE_MSR *) &LocalMsrRegister)->CpuVid);
+ IddValue = (UINT32) (((PSTATE_MSR *) &LocalMsrRegister)->IddValue);
+ IddDiv = (UINT32) (((PSTATE_MSR *) &LocalMsrRegister)->IddDiv);
+
+ 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 The max hw pstate value on the current socket.
+ * @param[out] NumberOfBoostStates The number of boosted P-states on the current socket.
+ * @param[in] StdHeader Handle of Header for calling lib functions and services.
+ *
+ * @retval AGESA_SUCCESS Always succeeds.
+ */
+AGESA_STATUS
+F12GetPstateMaxState (
+ IN PSTATE_CPU_FAMILY_SERVICES *PstateCpuServices,
+ OUT UINT32 *MaxPStateNumber,
+ OUT UINT8 *NumberOfBoostStates,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 NumBoostStates;
+ UINT64 MsrValue;
+ UINT32 LocalPciRegister;
+ PCI_ADDR PciAddress;
+
+ // For F12 CPU, skip boosted p-state. The boosted p-state number = D18F4x15C[NumBoostStates].
+ PciAddress.AddressValue = CPB_CTRL_PCI_ADDR;
+ LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); // D18F4x15C
+
+ NumBoostStates = ((CPB_CTRL_REGISTER *) &LocalPciRegister)->NumBoostStates;
+ *NumberOfBoostStates = (UINT8) NumBoostStates;
+ //
+ // 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) + 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
+F12GetPstateRegisterInfo (
+ 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 LocalMsrRegister;
+ UINT32 LocalPciRegister;
+ PCI_ADDR PciAddress;
+
+ ASSERT (PState < NM_PS_REG);
+
+ // For F12 CPU, skip boosted p-state. The boosted p-state number = D18F4x15C[NumBoostStates].
+ PciAddress.AddressValue = CPB_CTRL_PCI_ADDR;
+ LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); // D18F4x15C
+
+ // Read PSTATE MSRs
+ LibAmdMsrRead (PS_REG_BASE + (UINT32) PState, &LocalMsrRegister, StdHeader);
+
+ *SwPstateNumber = PState;
+
+ if (((PSTATE_MSR *) &LocalMsrRegister)->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 *) &LocalPciRegister)->NumBoostStates) {
+ *PStateEnabled = FALSE;
+ } else {
+ *SwPstateNumber = PState - ((CPB_CTRL_REGISTER *) &LocalPciRegister)->NumBoostStates;
+ }
+ } else {
+ *PStateEnabled = FALSE;
+ }
+
+ // Bits 39:32 (high 32 bits [7:0])
+ *IddVal = (UINT32) ((PSTATE_MSR *) &LocalMsrRegister)->IddValue;
+ // Bits 41:40 (high 32 bits [9:8])
+ *IddDiv = (UINT32) ((PSTATE_MSR *) &LocalMsrRegister)->IddDiv;
+
+ return (AGESA_SUCCESS);
+}
+
+
+CONST PSTATE_CPU_FAMILY_SERVICES ROMDATA F12PstateServices =
+{
+ 0,
+ (PF_PSTATE_PSD_IS_NEEDED) CommonReturnTrue,
+ F12IsPstatePsdDependent,
+ F12SetTscFreqSel,
+ F12GetPstateTransLatency,
+ F12GetPstateFrequency,
+ (PF_CPU_SET_PSTATE_LEVELING_REG) CommonReturnAgesaSuccess,
+ F12GetPstatePower,
+ F12GetPstateMaxState,
+ F12GetPstateRegisterInfo
+};
+