From befee680da22361fa18b97ec5838b7b67fce81d5 Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Thu, 2 Jun 2016 13:23:39 +0800 Subject: ChvRefCodePkg: Add SilvermontPpmLib. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- .../Library/Silvermont/Smm/SilvermontPpmDefines.h | 442 ++++ .../Library/Silvermont/Smm/SilvermontPpmLib.c | 2331 ++++++++++++++++++++ .../Library/Silvermont/Smm/SilvermontPpmLib.h | 350 +++ .../Library/Silvermont/Smm/SilvermontPpmLib.inf | 32 + 4 files changed, 3155 insertions(+) create mode 100644 ChvRefCodePkg/CherryViewSoc/CPU/PowerManagement/Library/Silvermont/Smm/SilvermontPpmDefines.h create mode 100644 ChvRefCodePkg/CherryViewSoc/CPU/PowerManagement/Library/Silvermont/Smm/SilvermontPpmLib.c create mode 100644 ChvRefCodePkg/CherryViewSoc/CPU/PowerManagement/Library/Silvermont/Smm/SilvermontPpmLib.h create mode 100644 ChvRefCodePkg/CherryViewSoc/CPU/PowerManagement/Library/Silvermont/Smm/SilvermontPpmLib.inf (limited to 'ChvRefCodePkg/CherryViewSoc') diff --git a/ChvRefCodePkg/CherryViewSoc/CPU/PowerManagement/Library/Silvermont/Smm/SilvermontPpmDefines.h b/ChvRefCodePkg/CherryViewSoc/CPU/PowerManagement/Library/Silvermont/Smm/SilvermontPpmDefines.h new file mode 100644 index 0000000000..9ed8c7b79c --- /dev/null +++ b/ChvRefCodePkg/CherryViewSoc/CPU/PowerManagement/Library/Silvermont/Smm/SilvermontPpmDefines.h @@ -0,0 +1,442 @@ +/** @file + This library contains power management configuration functions specific to + Cherryview processors. + + Acronyms: + PPM Processor Power Management + GV Geyserville + TM Thermal Monitor + IST Intel(R) Speedstep technology + HT Hyper-Threading Technology + CMP Core Multi-Processing + + Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SILVERMONT_PPM_DEFINES_H_ +#define _SILVERMONT_PPM_DEFINES_H_ + +// +// Definititons for CPU stepping +// +#define CPU_A0_STEPPING 0 + +#define EFI_CPUID_XAPIC_PROC_TOPOLOGY 0xB + +// +// Definitions for CPUID +// +#define CPUID_STEPPING 0x0000000F + +#define CPUID_FUNCTION_4 0x00000004 + +#define CPUID_FUNCTION_6 0x00000006 + +// +// Extended Feature Flag definitions (CPUID EAX=1 ECX) +// +#define CPUXFF_MONITOR_MWAIT (1 << 3) +#define CPUXFF_GV3 (1 << 7) + +// +// Extended Feature Flag definitions (CPUID EAX=1 EDX) +// +#define CPUXFF_TM1 (1 << 29) +#define CPUXFF_TM2 (1 << 8) +// +// CPUID 5 definitions (ECX) +// +#define MONITOR_MWAIT_EXTENSIONS (1 << 0) +// +// CPUID 5 definitions (EDX) +// +#define CSTATE_SUPPORTED 0x1 +#define ENHANCED_CSTATE_SUPPORTED 0x2 + +// +// CPUID 6 definitions (EAX) +// +#define TURBO_MODE_SUPPORTED (1 << 1) +#define ENERGY_EFFICIENT_P_STATE_CAPABLE (1 << 3) // @NOTE: Not available in VLV +#define FINE_GRAINED_CLOCK_MODULATION (1 << 5) // @NOTE: Not available in VLV + +#define CPUID_PROCESSOR_TOPOLOGY 0xB +// +// CPUID B definitions (EBX) +// +#define FACTORY_CONFIGURED_LOGICAL_PROCESSORS 0xFFFF + +// +// MSR definitions +// +#define MSR_IA32_PLATFORM_ID 0x17 +#define PLATFORM_ID_BITS_MASK (0x7 << 18) // Bits 52:50 +#define VID_MAX_PREFLX_BYTE_MASK 0x7F // Bits 6:0 +#define RATIO_MAX_PFLX_BYTE_MASK 0x3F // Bits 13:8 +#define RATIO_LOCKED (1 << 15) +#define FB_GV3_DISABLED (1 << 17) +#define FB_THERMAL_THROT_DISABLED (1 << 19) +#define EFI_MSR_EBC_HARD_POWERON 0x2A +#define STOP_ENABLE (1 << 19) +#define MSR_FSB_CLOCK_VCC 0xCE +#define BUS_GVL_RATIO_BYTE_MASK 0x1F // Bits 12:8 +#define MAX_RATIO_FUSE_MASK 0x1F // Bits 44:40 +#define VID_MIN_FUSE_MASK 0x7F // Bits 54:48 +#define VID_MAX_FUSE_MASK 0x7F // Bits 62:56 +#define MSR_PLATFORM_INFO 0xCE +#define MSR_IACORE_RATIOS 0x66a +#define MSR_IACORE_VIDS 0x66b +#define MSR_IACORE_TURBO_RATIOS 0x66c +#define MAX_RATIO_4C_OFFSET 24 +#define MAX_RATIO_3C_OFFSET 16 +#define MAX_RATIO_2C_OFFSET 8 +#define MAX_RATIO_1C_OFFSET 0 +#define MAX_RATIO_1C_MASK 0x000000ff +#define MAX_RATIO_2C_MASK 0x0000ff00 +#define MAX_RATIO_3C_MASK 0x00ff0000 +#define MAX_RATIO_4C_MASK 0xff000000 +#define MSR_IACORE_TURBO_VIDS 0x66d +#define MAX_VID_4C_OFFSET 24 +#define MAX_VID_3C_OFFSET 16 +#define MAX_VID_2C_OFFSET 8 +#define MAX_VID_1C_OFFSET 0 +#define MAX_VID_1C_MASK 0x000000ff +#define MAX_VID_2C_MASK 0x0000ff00 +#define MAX_VID_3C_MASK 0x00ff0000 +#define MAX_VID_4C_MASK 0xff000000 + +#define MSR_PM_CFG_CTRL 0xE2 +#define C0_SUB_STATES_MASK 0x0000000f +#define C1_SUB_STATES_MASK 0x000000f0 +#define C2_SUB_STATES_MASK 0x00000f00 +#define C3_SUB_STATES_MASK 0x0000f000 +#define C4_SUB_STATES_MASK 0x000f0000 +#define C5_SUB_STATES_MASK 0x00f00000 +#define C6_SUB_STATES_MASK 0x0f000000 +#define C7_SUB_STATES_MASK 0xf0000000 +#define CSTATE_LIMIT_MASK 0x7 +#define CSTATE_LIMIT_NO_LIMIT 0x0 +#define CSTATE_LIMIT_C1 0x1 +#define CSTATE_LIMIT_C2 0x2 +#define CSTATE_LIMIT_C3 0x3 +#define CSTATE_LIMIT_C4 0x4 +#define CSTATE_LIMIT_C6 0x6 +#define CSTATE_LIMIT_C7 0x7 + +#define DYNAMIC_L2_ENABLE (1 << 3) +#define CSM_SMI_TRIG_MASK (7 << 4) +#define CSM_SMI_TRIG_AUTO (7 << 4) +#define MWAIT_IO_REDIR (1 << 10) +#define HW_COORD_DIS (1 << 11) +#define SINGLE_PCTL (1 << 11) +#define LEVEL_5_READ_DISABLE (1 << 13) +#define CFG_LOCK (1 << 15) +#define C3_AUTO_DEMOTE_ENABLE (1 << 25) +#define C1_AUTO_DEMOTE_ENABLE (1 << 26) +#define C3_UNDEMOTION_ENABLE (1 << 27) +#define C1_UNDEMOTION_ENABLE (1 << 28) +#define L2_SHRINK_THRESHOLD_MASK (0x3F << 16) +#define L2_SHRINK_THRESHOLD_DISABLE (1 << 16) +#define L2_SHRINK_THRESHOLD_DEFAULT (6 << 16) +#define L2_SHRINK_THRESHOLD_OFFSET (16) + +#define MSR_PMG_IO_CAPTURE_BASE 0xE4 +#define MSR_IO_CAPT_ADDR MSR_PMG_IO_CAPTURE_BASE +#define IO_CAPT_RANGE_MASK (0x7 << 16) +#define IO_CAPT_LVL2 (0x0 << 16) // C4 +#define IO_CAPT_LVL3 (0x1 << 16) // C6 +#define IO_CAPT_LVL4 (0x2 << 16) // C6 or C7? +#define IO_CAPT_LVL5 (0x3 << 16) +#define IO_CAPT_LVL6 (0x4 << 16) +#define IO_CAPT_LVL2_BASE_ADDR_MASK (0xFFFF) +#define MSR_IO_CAPT_ADDR_MASK (0x0000FFFF) +#define MSR_IO_CAPT_RANGE_MASK (0x007F0000) // I/O capture range mask. + +#define MSR_BBL_CR_CTL3 0x11E +#define C6_RESIDENCY_ENABLE (1 << 19) +#define L2_WAY_CHUNK_SIZE_MASK (0x7 << 25) +#define L2_WAY_CHUNK_SIZE_32 (0x2 << 25) +#define L2_REDUCTION_MASK (0x3 << 30) +#define L2_REDUCTION_0_AUTO (1 << 30) +#define L2_WAY_RED_MIN_MASK (3 << 30) +#define L2_WAY_RED_MIN_0_STAY (0 << 30) //Reduced cache min. L2 ways = 0, stay. +#define L2_WAY_RED_MIN_0_AUTO (1 << 30) //Reduced cache min. L2 ways = 0, autoexpand. +#define L2_WAY_RED_MIN_2 (2 << 30) //Reduced cache min. L2 ways = 2. +#define L2_WAY_RED_MIN_4 (3 << 30) //Reduced cache min. L2 ways = 4. +#define L2_WAY_CHUNK_SZ_MASK (7 << 25) //L2 way chunk size. +#define L2_WAY_CHUNK_SZ_0 (0 << 25) //L2 chunk size = 0. +#define L2_WAY_CHUNK_SZ_2 (1 << 25) //L2 chunk size = 1/2. +#define L2_WAY_CHUNK_SZ_4 (2 << 25) //L2 chunk size = 1/4. +#define L2_WAY_CHUNK_SZ_8 (3 << 25) //L2 chunk size = 1/8. +#define L2_WAY_CHUNK_SZ_16 (4 << 25) //L2 chunk size = 1/16. +#define L2_WAY_CHUNK_SZ_32 (5 << 25) //L2 chunk size = 1/32. +#define L2_WAY_CHUNK_SZ_64 (6 << 25) //L2 chunk size = 1/64. +#define L2_WAY_CHUNK_SZ_128 (7 << 25) //L2 chunk size = 1/128. + +#define MSR_POWER_MISC 0x120 +#define ENABLE_ULFM_AUTOCM_MASK (1 << 2) +#define ENABLE_INDP_AUTOCM_MASK (1 << 3) +#define ENABLE_IA_UNTRUSTED_MODE (1 << 6) +#define MAX_POWER_LIMIT_1_TIME_IN_SECONDS 32767 +#define AUTO 0 +#define END_OF_TABLE 0xFF + +#define MSR_FLEX_RATIO 0x194 +#define VID_FLEX_BYTE_MASK 0xFF // Bits 6:0 (7 --> Reserved) +#define RATIO_FLEX_BYTE_MASK 0xFF // Bits 13:8 (15:14 --> Reserved) +#define RATIO_FLEX_N2 (1 << 14) + +#define FLEX_RATIO (0xFF << 8) +#define ENABLE_FLEX (1 << 16) +#define MAX_EXTRA_VOLTAGE 0xFF +#define OVERCLOCKING_BINS (0x7 << 17) + +#define MSR_IA32_PERF_STS 0x198 +#define BUS_RATIO_MIN_MASK 0x1F //Bits 28:24 +#define MSR_IA32_PERF_CTL 0x199 +#define P_STATE_TARGET_OFFSET 8 +#define P_STATE_TARGET_MASK (0x3F7F) +#define RATIO_BYTE_MASK 0x1F +#define MSR_IA32_CLOCK_MODULATION 0x19A +#define MSR_IA32_THERM_INTERRUPT 0x19B +#define MSR_GV_THERM 0x19D +#define VID_THROT_BYTE_MASK 0x7F // Bits 6:0 +#define RATIO_THROT_BYTE_MASK 0x3F // Bits 13:8 +#define MSR_IA32_MISC_ENABLES 0x1A0 +#define ACNT2_ENABLE_MASK (1 << 27) +#define MSR_TEMPERATURE_TARGET 0x1A2 +#define MSR_TURBO_RATIO_LIMIT 0x1AD +#define MSR_IA32_ENERGY_PERFORMANCE_BIAS 0x1B0 +#define ENERGY_POLICY_OFFSET 0 +#define ENERGY_POLICY_MASK 0xF +#define MSR_POWER_CTL 0x1FC +#define FAST_BRK_INTERRUPT_ENABLE (1 << 4) +#define FAST_BRK_SNP_ENABLE (1 << 3) +#define MSR_PACKAGE_POWER_SKU_UNIT 0x606 +#define MSR_PKGC3_IRTL 0x60A +#define PKG_IRTL_VALID (1 << 15) +#define INTERRUPT_RESPONSE_TIME_LIMIT_MASK 0x1FF // Bits 9:0 +#define TIME_UNIT_MASK (0x7 << 10) // Bits 12:10 +#define TIME_UNIT_OFFSET 10 +#define TIME_UNIT_1024_NS 0x2 +#define TIME_UNIT_32768_NS 0x3 + +//----------------------------------------------------------------------------- +// Thermal Management Registers +//----------------------------------------------------------------------------- +#define MSR_IA32_CR_THERM_INTERRUPT 0x19b +#define MSR_IA32_CR_THERM_STATUS 0x19c +#define MSR_CPU_THERM_TEMPERATURE 0x1a2 +#define EFI_MSR_TURBO_POWER_LIMIT 0x610 +#define MSR_PKG_TURBO_CFG1 0x670 +#define TURBOMODE (0x0 << TURBOMODE_OFFSET) +#define TURBOMODE_MASK (0x7 << TURBOMODE_OFFSET) +#define TURBOMODE_OFFSET 0 +#define ICCMAX_CTRL (0x2 << ICCMAX_CTRL_OFFSET) +#define ICCMAX_CTRL_MASK (0x3 << ICCMAX_CTRL_OFFSET) +#define ICCMAX_CTRL_OFFSET 3 +#define ICCMAX_CTRL_EN (0x1 << ICCMAX_CTRL_EN_OFFSET) +#define ICCMAX_CTRL_EN_OFFSET 5 +#define SOC_TDP_EN (0x1 << SOC_TDP_EN_OFFSET) +#define SOC_TDP_EN_OFFSET 8 +#define SOC_TDP_POLICY (0x3 << SOC_TDP_POLICY_OFFSET) +#define SOC_TDP_POLICY_MASK (0x7 << SOC_TDP_POLICY_OFFSET) +#define SOC_TDP_POLICY_OFFSET 9 +#define MIN_ENERGY (0x1 << MIN_ENERGY_OFFSET) +#define MIN_ENERGY_MASK (0x1FFF << MIN_ENERGY_OFFSET) +#define MIN_ENERGY_OFFSET 16 +#define MSR_CPU_TURBO_WKLD_CFG1 0x671 +#define C0STL_AFACTOR_THRESH (0x0 << C0STL_AFACTOR_THRESH_OFFSET) +#define C0STL_AFACTOR_THRESH_MASK (0x7 << C0STL_AFACTOR_THRESH_OFFSET) +#define C0STL_AFACTOR_THRESH_OFFSET 3 +#define IPC_THRESH0 (0x2 << IPC_THRESH0_OFFSET) +#define IPC_THRESH0_MASK (0xF << IPC_THRESH0_OFFSET) +#define IPC_THRESH0_OFFSET 8 +#define IPC_THRESH1 (0x3 << IPC_THRESH1_OFFSET) +#define IPC_THRESH1_MASK (0xF << IPC_THRESH1_OFFSET) +#define IPC_THRESH1_OFFSET 12 +#define IPC_THRESH2 (0x6 << IPC_THRESH2_OFFSET) +#define IPC_THRESH2_MASK (0xF << IPC_THRESH2_OFFSET) +#define IPC_THRESH2_OFFSET 16 +#define IPC_THRESH3 (0xB << IPC_THRESH3_OFFSET) +#define IPC_THRESH3_MASK (0xF << IPC_THRESH3_OFFSET) +#define IPC_THRESH3_OFFSET 20 +#define IPC_THRESH4 (0xD << IPC_THRESH4_OFFSET) +#define IPC_THRESH4_MASK (0xF << IPC_THRESH4_OFFSET) +#define IPC_THRESH4_OFFSET 24 +#define MSR_CPU_TURBO_WKLD_CFG2 0x672 +#define AFACTOR0 (0xB << AFACTOR0_OFFSET) +#define AFACTOR0_MASK (0xF << AFACTOR0_OFFSET) +#define AFACTOR0_OFFSET 0 +#define AFACTOR1 (0x9 << AFACTOR1_OFFSET) +#define AFACTOR1_MASK (0xF << AFACTOR1_OFFSET) +#define AFACTOR1_OFFSET 4 +#define AFACTOR2 (0x7 << AFACTOR2_OFFSET) +#define AFACTOR2_MASK (0xF << AFACTOR2_OFFSET) +#define AFACTOR2_OFFSET 8 +#define AFACTOR3 (0x5 << AFACTOR3_OFFSET) +#define AFACTOR3_MASK (0xF << AFACTOR3_OFFSET) +#define AFACTOR3_OFFSET 12 +#define AFACTOR4 (0x3 << AFACTOR4_OFFSET) +#define AFACTOR4_MASK (0xF << AFACTOR4_OFFSET) +#define AFACTOR4_OFFSET 16 + +#define MSR_CPU_THERM_CFG1 0x673 +#define MSR_CPU_THERM_CFG2 0x674 +#define MSR_CPU_THERM_SENS_CFG 0x675 + +#define MSR_PKGC6_IRTL 0x60B +#define MSR_PKGC7_IRTL 0x60C +#define MSR_TURBO_POWER_LIMIT 0x610 +#define MSR_PACKAGE_POWER_SKU 0x614 +//#define MSR_PIC_SENS_CFG MSR_CPU_THERM_SENS_CFG +//#define TM1_AND_TM2_ENABLE (1 << 20) +//#define TM1_LOCK (1 << 21) +//#define IMVP_OPTIMIZATION_DIS (1 << 31) +#define MSR_EBC_HARD_POWERON 0x2A +#define STOP_ENABLE (1 << 19) +#define MSR_PRIMARY_PLANE_CURRENT_CONFIG 0x601 +#define CURRENT_LIMIT_MASK 0x1FFF // Bits 12:0 + +#define MSR_SECONDARY_PLANE_CURRENT_CONFIG 0x602 + +#define MSR_PRIMARY_PLANE_TURBO_POWER_LIMIT 0x638 +#define PP_PWR_LIM_TIME (0 << PP_PWR_LIM_TIME_OFFSET) +#define PP_PWR_LIM_TIME_MASK (0x7F << PP_PWR_LIM_TIME_OFFSET) +#define PP_PWR_LIM_TIME_OFFSET 17 + +#define MSR_SECONDARY_PLANE_TURBO_POWER_LIMIT 0x640 +#define PLANE_POWER_LIMIT_MASK (0x7FFF) +#define PLANE_POWER_LIMIT_ENABLE (1 << 15) +#define PLANE_POWER_LIMIT_TIME_MASK (0x7F) +#define PLANE_POWER_LIMIT_TIME_OFFSET 17 +#define PLANE_POWER_LIMIT_LOCK (1 << 31) + +#define IA32_PERF_STS_VIP (1 << 17) +#define PLATFORMID_LOCKED (1 << 15) +#define VID_MASK (0x3F << 0) +#define MIN_SLT_VID (0x1D << 0) +#define BUS_RATIO_MASK (0x1F << 8) +#define CLK_FLEX_MAX_MASK (0x101F << 0) +#define CLK_FLEX_EN (1 << 16) + +#define ENERGY_EFFICIENT_P_STATE_FEATURE_ENABLE (1 << 18) + +#define STOP_ENABLE (1 << 19) +#define CORE_COUNT_OFFSET (16) +#define CORE_COUNT_MASK (0xFFFF << 16) +#define THREAD_COUNT_MASK (0xFFFF) + +#define PACKAGE_TDP_POWER_MASK (0x7FFF) // Bits 14:0 +#define PACKAGE_MIN_POWER_MASK (0x7FFF) // Bits 14:0 +#define PACKAGE_MAX_POWER_MASK (0x7FFF) // Bits 46:32 +#define PACKAGE_MAX_TIME (0x7F0000) // Bits 54:48 +#define PROG_TDP_LIMITS (1 << 29) +#define PROG_RATIO_LIMITS (1 << 28) +#define PROG_TCC_ACTIVATION_OFFSET (1 << 30) + +// +// Macro deinfition for Turbo related settings. +// +#define POWER_LIMIT_ENABLE (1 << 15) // Used as Bit 15 and Bit 47 +#define POWER_LIMIT_MASK (0x7FFF) // Bits 14:0 and 46:32 +#define POWER_LIMIT_1_TIME_MASK (0xFE0000) // Bits 23:17 +#define POWER_LIMIT_LOCK (1 << 31) // Bit 63 +#define CRITICAL_POWER_CLAMP_ENABLE (1 << 16) // Bit 16 and Bit 48 + +#define TURBO_MODE_DISABLED (1 << 11) +#define DISABLE_TURBO_MODE (1 << (32 - 32)) +#define TM_ENABLE (1 << 3) +#define GV3_ENABLE (1 << GV3_ENABLE_OFFSET) +#define GV3_ENABLE_OFFSET 16 +#define FORCEPR_ENABLE_DC (1 << 21) //Only for MP +#define BIDIR_PHOT_ENABLE_SC (1 << 17) +#define MONITOR_MWAIT_ENABLE (1 << 18) +#define EIST_SELECT_LOCK (1 << 20) +#define LIMIT_CPUID (1 << 22) +#define C1E_ENABLE (1 << 1) +#define C1E_ENABLE_MASK (1 << 1) +#define C2E_ENABLE (1 << 26) +#define C3E_ENABLE (1 << 31) +#define C4E_ENABLE (1 << (32-32)) //C4E enable bit. +#define HARD_C4E_ENABLE (1 << (33-32)) //Hard C4E enable bit. + +#define MONITOR_MWAIT_ENABLE (1 << 18) +#define LIMIT_CPUID (1 << 22) +#define DISABLE_MASTER_TURBO_MODE (1 << (38 - 32)) +#define LOCK_TM_INT (1 << 22) +#define MAX_RATIO_LIMIT_4C_OFFSET 24 +#define MAX_RATIO_LIMIT_4C_MASK (0x3F << MAX_RATIO_LIMIT_4C_OFFSET) +#define MAX_RATIO_LIMIT_3C_OFFSET 16 +#define MAX_RATIO_LIMIT_3C_MASK (0x3F << MAX_RATIO_LIMIT_3C_OFFSET) +#define MAX_RATIO_LIMIT_2C_OFFSET 8 +#define MAX_RATIO_LIMIT_2C_MASK (0x3F << MAX_RATIO_LIMIT_2C_OFFSET) +#define MAX_RATIO_LIMIT_1C_MASK (0x3F) +#define MAX_TURBO_RATIO_LIMIT_MASK (0x3F) + +#define PHOT_ENABLE (1 << 0) +#define PACKAGE_POWER_UNIT_MASK 0xF +#define TCC_ACTIVATION_OFFSET_MASK (0xF << 24) +#define PACKAGE_TIME_UNIT_MASK 0xF0000 + +#define CPU_CACHE_TYPE_MASK 0x1F +#define CPU_CACHE_LEVEL_MASK 0x07 +#define CPU_CACHE_ASSOCIATIVITY_MASK 0x03FF +#define CPU_CACHE_PARTITION_MASK 0x03FF +#define CPU_CACHE_LINE_SIZE_MASK 0x0FFF + +#define MAX_OVERCLOCKING_BINS 0x7 + +#define PROCESSOR_FLAVOR_MOBILE 0x0104 +#define PROCESSOR_FLAVOR_DESKTOP 0x0100 + +// +// Power definitions (Based on EMTS V1.0 for standard voltage 2.4-2.6 GHz dual-core parts.) +// +#define FVID_MAX_POWER_SANDYBRIDGE 35000 +#define FVID_TURBO_POWER_SANDYBRIDGE 35000 +#define FVID_SUPERLFM_POWER_SANDYBRIDGE 12000 +// +// Power definitions for LFM and Turbo mode TBD. +// +#define FVID_MIN_POWER_SANDYBRIDGE 15000 + +// +// Primary and Secondary Plane Current Limit Defaults +// +#define PRIMARY_PLANE_CURRENT_DEFAULT 0x380 +#define SECONDARY_PLANE_CURRENT_DEFAULT 0x118 + +#define FVID_MAX_POWER_SANDYBRIDGE 35000 +#define FVID_TURBO_POWER_SANDYBRIDGE 35000 + +#ifndef SW_SMI_S3_RESTORE_MSR +#define SW_SMI_S3_RESTORE_MSR 0x48 +#endif + +#ifndef SW_SMI_PPM_INTERNAL +#define SW_SMI_PPM_INTERNAL 0x47 +#endif + +#define PPM_ENABLE 1 +#define PPM_DISABLE 0 + +#define EFI_MSR_IA32_PERF_CTL MSR_IA32_PERF_CTL +#define EFI_MSR_IA32_CLOCK_MODULATION MSR_IA32_CLOCK_MODULATION +#define EFI_MSR_IA32_THERM_STATUS 0x19C +#define EFI_MSR_GV_THERM 0x19D + +#define FVID_MAX_POWER_MIDVIEW 2000 +#define FVID_MIN_POWER_MIDVIEW 600 + +#define FAMILYMODELSTEP_SLM 0x30670 +#endif diff --git a/ChvRefCodePkg/CherryViewSoc/CPU/PowerManagement/Library/Silvermont/Smm/SilvermontPpmLib.c b/ChvRefCodePkg/CherryViewSoc/CPU/PowerManagement/Library/Silvermont/Smm/SilvermontPpmLib.c new file mode 100644 index 0000000000..25f06175cc --- /dev/null +++ b/ChvRefCodePkg/CherryViewSoc/CPU/PowerManagement/Library/Silvermont/Smm/SilvermontPpmLib.c @@ -0,0 +1,2331 @@ +/** @file + This library contains power management configuration functions for + Cherryview processors. + + Acronyms: + PPM Processor Power Management + GV Geyserville + TM Thermal Monitor + IST Intel(R) Speedstep technology + HT Hyper-Threading Technology + + Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +// +// Include files +// +#include "SilvermontPpmLib.h" +#include "PpmCommon.h" +#include "CpuPpmLib.h" +#include "CpuRegs.h" + +// +// Global variables +// +// +// Start: Workaround for sighting 4683480, 4683441 for Q8XA IVI SKU +// +STATIC UINT8 mTurboModeNotAvailable = 0; +// +// End: Workaround for sighting 4683480, 4683441 for Q8XA IVI SKU +// + +// +// CPU stepping +// +STATIC UINT16 mProcessorStepping; +// +// Only one instance of this protocol currently supported. +// +PPM_PROCESSOR_SUPPORT_PROTOCOL_2 mPpmProcessorSupportProtocolCherryview = { + 0, // PpmFlags + 0, // PpmFeatureFlags + SetPpmFlagsCherryview, + EnableCStatesCherryview, + InitGv3Cherryview, + ConfigureTurboPowerLimitsCherryview, + InitThermalCherryview, + EnableTmCherryview, + EnableProcHotCherryview, + EnableTscCherryview, + NULL, // EMTTM Not supportted for SLT + S3SaveMsrCherryview, + S3RestoreMsrCherryview, + SetBootPState, + EnableCStateIoRedirectionCherryview, + DisableCStateIoRedirectionCherryview, + EnablePStateHardwareCoordinationCherryview, + DisablePStateHardwareCoordinationCherryview, + NULL, + NULL, // PStateTransition + NULL //PowerSourceChangeCherryview, +}; + +// +// CPUID 01 values +// +STATIC EFI_CPUID_REGISTER mCpuid01 = { 0, 0, 0, 0 }; + +// +// Values for FVID table calculate. +// +STATIC UINT16 mTurboBusRatio = 0; +STATIC UINT16 mTurboBusRatio_3C = 0; +STATIC UINT16 mMaxBusRatio = 0; +STATIC UINT16 mMinBusRatio = 0; +STATIC UINT16 mTurboVid = 0; +STATIC UINT16 mTurboVid_3C = 0; +STATIC UINT16 mMaxVid = 0; +STATIC UINT16 mMinVid = 0; +STATIC UINT16 mProcessorFlavor = 0; +// +// Fractional part of Processor Power Unit in Watts. (i.e. Unit is 1/mProcessorPowerUnit) +// +STATIC UINT8 mProcessorPowerUnit = 0; +// +// Fractional part of Processor Time Unit in seconds. (i.e Unit is 1/mProcessorTimeUnit) +// +STATIC UINT8 mProcessorTimeUnit = 0; +// +// Maximum allowed power limit value in TURBO_POWER_LIMIT_MSR and PRIMARY_PLANE_POWER_LIMIT_MSR +// in units specified by PACKAGE_POWER_SKU_UNIT_MSR +// +STATIC UINT16 mPackageMaxPower = 0; +// +// Minimum allowed power limit value in TURBO_POWER_LIMIT_MSR and PRIMARY_PLANE_POWER_LIMIT_MSR +// in units specified by PACKAGE_POWER_SKU_UNIT_MSR +// +STATIC UINT16 mPackageMinPower = 0; +// +// Processor TDP value in Watts +// +STATIC UINT16 mPackageTdp = 0; +// +// Porgrammable TDP Limit +// +STATIC UINT8 mTdpLimitProgrammble = 0; + +// +// Table to convert Seconds into equivalent MSR values +// This table is used for TDP Time Window programming +// +STATIC UINT8 mSecondsToMsrValueMapTable[][2] = { + // Seconds MSR Value + { 1 , 0x0 }, + { 5 , 0x1 }, + { 10 , 0x2 }, + { 15 , 0x3 }, + { 20 , 0x4 }, + { 25 , 0x5 }, + { 30 , 0x6 }, + { 35 , 0x7 }, + { 40 , 0x8 }, + { 45 , 0x9 }, + { 50 , 0xA }, + {END_OF_TABLE,END_OF_TABLE} +}; + +// +// MSR table for S3 resume +// +STATIC EFI_MSR_VALUES mMsrValues[] = { + { MSR_IA32_CLOCK_MODULATION, 0 }, // 0x19A + { MSR_IA32_PERF_CTL, 0 }, // 0x199 + { MSR_PMG_IO_CAPTURE_BASE, 0 }, // 0x0E4 + { MSR_PM_CFG_CTRL, 0 }, // 0x0E2 + { MSR_IA32_MISC_ENABLES, 0 }, // 0x1A0 + { MSR_POWER_CTL, 0 }, // 0x1FC + { MSR_TURBO_POWER_LIMIT, 0 }, // 0x610 + { MSR_TEMPERATURE_TARGET, 0 }, // 0x1A2 + { MSR_FLEX_RATIO, 0 }, // 0x194 + { MSR_PRIMARY_PLANE_CURRENT_CONFIG, 0 }, // 0x601 + { MSR_IA32_ENERGY_PERFORMANCE_BIAS, 0 }, // 0x1B0 + { MSR_BBL_CR_CTL3, 0 }, // 0x11E + { MSR_IA32_THERM_INTERRUPT, 0 }, // 0x19B + { MSR_POWER_MISC, 0 }, // 0x120 + { MSR_CPU_THERM_SENS_CFG, 0 }, // 0x675 + { MSR_PRIMARY_PLANE_TURBO_POWER_LIMIT, 0 }, // 0x638 + { MSR_CPU_THERM_CFG1, 0 }, // 0x673 + { MSR_CPU_THERM_CFG2, 0 }, // 0x674 + { MSR_PACKAGE_POWER_SKU_UNIT, 0 }, // 0x606 + { MSR_EBC_HARD_POWERON, 0 }, // 0x02A + { MSR_PKG_TURBO_CFG1, 0 }, // 0x670 + { MSR_CPU_TURBO_WKLD_CFG1, 0 }, // 0x671 + { MSR_CPU_TURBO_WKLD_CFG2, 0 } // 0x672 +}; + +// +// Function implemenations +// +#ifdef __GNUC__ +#pragma GCC push_options +#pragma GCC optimize ("O0") +#else +#pragma optimize("", off) +#endif + +/** + Initializes the processor power management library. This must be called + prior to any of the library functions being used. + + @param[in] This Pointer to the PPM support protocol instance + + @retval EFI_SUCCESS Library was initialized successfully + +**/ +EFI_STATUS +InitializeCherryviewPowerManagementLib ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 **This + ) +{ + MSR_REGISTER PackagePowerSKUUnitMsr; + MSR_REGISTER TempMsr; + UINTN remainder; + + MSR_REGISTER PlatformIdMsr; + MSR_REGISTER IaCoreRatios; + MSR_REGISTER IaCoreVids; + + ASSERT (gSmst != NULL); + // + // Read the CPUID information + // + AsmCpuid (EFI_CPUID_VERSION_INFO, &mCpuid01.RegEax, &mCpuid01.RegEbx, &mCpuid01.RegEcx, &mCpuid01.RegEdx); + // + // Check if this library supports the current processor + // + mProcessorStepping = (UINT16) (mCpuid01.RegEax & CPUID_STEPPING); + + // + // Assign the protocol pointer. + // + *This = &mPpmProcessorSupportProtocolCherryview; + + // + // Get Platform ID + // + PlatformIdMsr.Qword = AsmReadMsr64 (MSR_IA32_PLATFORM_ID); + mProcessorFlavor = (UINT8) RShiftU64((PlatformIdMsr.Dwords.High & PLATFORM_ID_BITS_MASK), 18); + + // + // Get the Bus Ratio for the processor + // + // + // Get Maximum Non-Turbo bus ratio (HFM) from IACORE_RATIOS MSR Bits[23:16] + // + IaCoreRatios.Qword = AsmReadMsr64 (MSR_IACORE_RATIOS); + mMaxBusRatio = IaCoreRatios.Bytes.ThirdByte; + + // + // Get Maximum Efficiency bus ratio (LFM) from IACORE_RATIOS MSR Bits[15:8] + // + mMinBusRatio = IaCoreRatios.Bytes.SecondByte; + + // + // Get Max Turbo Ratio from Turbo Ratio Limit MSR Bits [5:0] + // + TempMsr.Qword = AsmReadMsr64 (MSR_IACORE_TURBO_RATIOS); + mTurboBusRatio = (UINT16)(TempMsr.Bytes.FirstByte & MAX_RATIO_1C_MASK); + mTurboBusRatio_3C = (UINT16)(TempMsr.Bytes.ThirdByte & MAX_RATIO_1C_MASK); + + // + // Get the Vid for the processor + // + // + // Get Maximum Non-Turbo Vid (HFM) from IACORE_VIDS MSR Bits[23:16] + // + IaCoreVids.Qword = AsmReadMsr64 (MSR_IACORE_VIDS); + mMaxVid = IaCoreVids.Bytes.ThirdByte; + + // + // Get Maximum Efficiency VID (LFM) from IACORE_VIDS MSR Bits[15:8] + // + mMinVid = IaCoreVids.Bytes.SecondByte; + + // + // Get Max Turbo VID from Turbo Ratio Limit MSR Bits [5:0] + // + TempMsr.Qword = AsmReadMsr64 (MSR_IACORE_TURBO_VIDS); + mTurboVid = (UINT16)(TempMsr.Bytes.FirstByte & MAX_VID_1C_MASK); + mTurboVid_3C = (UINT16)(TempMsr.Bytes.ThirdByte & MAX_VID_1C_MASK); + + // Get Processor TDP from Turbo Power Limit MSR Bits[14:0] + // and convert it to units specified by Package Power SKU + // Unit MSR [3:0] + // + TempMsr.Qword = AsmReadMsr64 (MSR_TURBO_POWER_LIMIT); + + // Get Maximum Power from Turbo Power Limit MSR Bits[14:0] + // and convert it to units specified by Package Power SKU Unit MSR [3:0] + // + PackagePowerSKUUnitMsr.Qword = AsmReadMsr64 (MSR_PACKAGE_POWER_SKU_UNIT); + + mProcessorPowerUnit = (PackagePowerSKUUnitMsr.Bytes.FirstByte & PACKAGE_POWER_UNIT_MASK); + if (mProcessorPowerUnit == 0) { + mProcessorPowerUnit = 1; + } else { + // The actual unit value is calculated by 1mW*Power(2,POWER_UNIT)..Reset value of 5 represents 32mW units. + mProcessorPowerUnit = (UINT8) LShiftU64 (1, (mProcessorPowerUnit)); + } + + // There are two power limits in the same MSR [14:0] and [46:32]. Bit field [14:0] reflects the package TDP. + mPackageTdp = (UINT16) DivU64x32Remainder((TempMsr.Dwords.Low & PACKAGE_TDP_POWER_MASK), mProcessorPowerUnit, (UINT32 *)&remainder); + + /* @NOTE: This may be used in Cherryview, but still keeping this code. */ + mProcessorTimeUnit = (UINT8) RShiftU64((PackagePowerSKUUnitMsr.Dwords.Low & PACKAGE_TIME_UNIT_MASK), 16); + if (mProcessorTimeUnit == 0) { + mProcessorTimeUnit = 1; + } else { + mProcessorTimeUnit = (UINT8) LShiftU64 (1, (mProcessorTimeUnit)); + } + + return EFI_SUCCESS; +} + +#ifdef __GNUC__ +#pragma GCC pop_options +#else +#pragma optimize("", on) +#endif +/** + Set the PPM flags specific to mobile Cherryview processors + + @param[in] This Pointer to the protocol instance + + @retval EFI_SUCCESS PpmFlags updated with the features supported by the processor + +**/ +STATIC +EFI_STATUS +EFIAPI +SetPpmFlagsCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ) +{ + MSR_REGISTER PlatformId; + MSR_REGISTER Ia32MiscEnable; + EFI_CPUID_REGISTER Cpuid01 = {0}; + EFI_CPUID_REGISTER Cpuid05 = {0}; + EFI_CPUID_REGISTER Cpuid06 = {0}; + EFI_CPUID_REGISTER Cpuid0B = {0}; + UINTN States; + UINT8 NumberOfLP = 0; + UINT8 ThreadPerCore = 0; + UINT32 Ecx = 0; + BOOLEAN CpuidLimitingEnabled; + + CpuidLimitingEnabled = FALSE; + + // + // Check if the processor has multiple cores + // + // + // Set the level number to 0 for SMT level of Processor Topology. + // + Ecx = 0; + AsmCpuidEx (EFI_CPUID_XAPIC_PROC_TOPOLOGY, Ecx, &Cpuid0B.RegEax, &Cpuid0B.RegEbx, &Cpuid0B.RegEcx, &Cpuid0B.RegEdx); + ThreadPerCore = (UINT8) Cpuid0B.RegEbx & 0xFF; + + // + // Set the level number to 1 for Core level of Processor Topology. + // + Ecx = 1; + AsmCpuidEx (EFI_CPUID_XAPIC_PROC_TOPOLOGY, Ecx, &Cpuid0B.RegEax, &Cpuid0B.RegEbx, &Cpuid0B.RegEcx, &Cpuid0B.RegEdx); + NumberOfLP = (UINT8) Cpuid0B.RegEbx & 0xFF; + + if (NumberOfLP > 2 && ThreadPerCore == 1) { + This->PpmFlags |= (PPM_QUAD | PPM_CMP); + } else if (NumberOfLP > 1 && ThreadPerCore == 1) { + This->PpmFlags |= PPM_CMP; + } + + // + // Cherryview support TSC updates + // + if (mCpuid01.RegEcx & (1 << 4)) { + This->PpmFlags |= PPM_TSC; + } + + // + // Set PROCHOT# always + // + This->PpmFlags |= PPM_PROC_HOT; + + // + // Check TM capable + // + if (mCpuid01.RegEdx & CPUXFF_TM1) { + This->PpmFlags |= PPM_TM; + + } + + // + // Check GV3/ EIST capable, If EIST capable, also set the boot P-state to HFM flag. + // + +#if (!_PSSD_FIX_) + // + // mCpuid01.RegEcx = 0xD8E23F for PSSD and 0x43D8E3BF for ERB + // Since BIT7 is not set in case of PSSD so skip this check to enable the PPM_GV3 flag + // We are checking this flag to add Cpu0Ist ACPI table in SSDT + // + if (mCpuid01.RegEcx & CPUXFF_GV3) { +#endif + This->PpmFlags |= (PPM_GV3 | PPM_BOOT_P_ST_HFM) ; +#if (!_PSSD_FIX_) + } +#endif + + // + // Check if anything has been disabled + // + PlatformId.Qword = AsmReadMsr64 (EFI_MSR_IA32_PLATFORM_ID); + + // + // Check if EIST has been fuse disabled. + // + if (PlatformId.Qword & FB_GV3_DISABLED) { + This->PpmFlags &= ~(PPM_GV3 | PPM_BOOT_P_ST_HFM ); + } + + // + // Check if any type of automatic internal throttling has been fuse disabled + // + if (PlatformId.Qword & FB_THERMAL_THROT_DISABLED) { + This->PpmFlags &= ~(PPM_TM); + } + + // + // Disable CPUID limiting (and save current setting) if enabled + // and enable MONITOR/MWAIT support + // + Ia32MiscEnable.Qword = AsmReadMsr64 (EFI_MSR_IA32_MISC_ENABLE); + if (Ia32MiscEnable.Qword & LIMIT_CPUID) { + Ia32MiscEnable.Qword &= (~(UINT64)LIMIT_CPUID); + Ia32MiscEnable.Qword |= (UINT64)MONITOR_MWAIT_ENABLE; + AsmWriteMsr64 (EFI_MSR_IA32_MISC_ENABLE, Ia32MiscEnable.Qword); + + CpuidLimitingEnabled = TRUE; + } + + // + // Read the CPUID values we care about. We cannot use the stored + // values because they may have changes since we disabled limiting + // and enabled MONITOR/MWAIT + // + AsmCpuid (1, &Cpuid01.RegEax, &Cpuid01.RegEbx, &Cpuid01.RegEcx, &Cpuid01.RegEdx); + AsmCpuid (5, &Cpuid05.RegEax, &Cpuid05.RegEbx, &Cpuid05.RegEcx, &Cpuid05.RegEdx); + AsmCpuid (6, &Cpuid06.RegEax, &Cpuid06.RegEbx, &Cpuid06.RegEcx, &Cpuid06.RegEdx); + + // + // Determine if the MONITOR/MWAIT instructions are supported. + // + if ((Cpuid01.RegEcx & CPUXFF_MONITOR_MWAIT && Cpuid05.RegEcx & MONITOR_MWAIT_EXTENSIONS)) { + This->PpmFlags |= PPM_MWAIT_EXT; + } + + // + // Determine the C-State and Enhanced C-State support present. + // Monitor/MWAIT parameters function describes the numbers supported. + // + States = (Cpuid05.RegEdx >> 4) & 0xF; + if (States >= ENHANCED_CSTATE_SUPPORTED) { + This->PpmFlags |= PPM_C1 + PPM_C1E; + } else if (States == CSTATE_SUPPORTED) { + This->PpmFlags |= PPM_C1; + } + + States = (Cpuid05.RegEdx >> 8) & 0xF; + if (States >= ENHANCED_CSTATE_SUPPORTED) { + This->PpmFlags |= PPM_C2 + PPM_C2E; + } else if (States == CSTATE_SUPPORTED) { + This->PpmFlags |= PPM_C2; + } + + States = (Cpuid05.RegEdx >> 12) & 0xF; + if (States >= ENHANCED_CSTATE_SUPPORTED) { + This->PpmFlags |= PPM_C3 + PPM_C3E; + } else if (States == CSTATE_SUPPORTED) { + This->PpmFlags |= PPM_C3; + } + + States = (Cpuid05.RegEdx >> 16) & 0xF; + if (States >= ENHANCED_CSTATE_SUPPORTED) { + This->PpmFlags |= PPM_C4 + PPM_C4E; + } else if (States == CSTATE_SUPPORTED) { + This->PpmFlags |= PPM_C4; + } + + States = (Cpuid05.RegEdx >> 24) & 0xF; + if (States >= CSTATE_SUPPORTED) { + This->PpmFlags |= PPM_C6 | PPM_C6S | PPM_C7; +} + + // Check if turbo mode is supported + // + Ia32MiscEnable.Qword = AsmReadMsr64 (MSR_IA32_MISC_ENABLES); + if (((Cpuid06.RegEax & TURBO_MODE_SUPPORTED) == 0) && ((Ia32MiscEnable.Dwords.High & DISABLE_MASTER_TURBO_MODE) == 0)) { + // + // Turbo Mode is not available in this physical processor package. + // BIOS should not attempt to enable Turbo Mode via IA32_MISC_ENABLE MSR. + // BIOS should show Turbo Mode as Disabled and Not Configurable. + // + + // + // Start: Workaround for sighting 4683480, 4683441 for Q8XA IVI SKU + // + mTurboModeNotAvailable = 1; + // + // End: Workaround for sighting 4683480, 4683441 for Q8XA IVI SKU + // + + } else if (((Cpuid06.RegEax & TURBO_MODE_SUPPORTED) == 0) && ((Ia32MiscEnable.Dwords.High & DISABLE_MASTER_TURBO_MODE) != 0)) { + // + // Turbo Mode is available but globally disabled for the all logical + // processors in this processor package. + // BIOS can enable Turbo Mode by IA32_MISC_ENABLE MSR 1A0h bit [38] = 0. + // + This->PpmFlags |= PPM_TURBO; + } else if ((Cpuid06.RegEax & TURBO_MODE_SUPPORTED) == TURBO_MODE_SUPPORTED) { + // + // Turbo Mode is factory-configured as available and enabled for all logical processors in this processor package. + // This case handles the cases where turbo mode is enabled before PPM gets chance to enable it + // + This->PpmFlags |= PPM_TURBO; + } + + // + // Restore the CPUID limit setting. + // + if (CpuidLimitingEnabled == TRUE) { + Ia32MiscEnable.Qword = AsmReadMsr64 (EFI_MSR_IA32_MISC_ENABLE); + Ia32MiscEnable.Qword |= (UINT64)LIMIT_CPUID; + AsmWriteMsr64 (EFI_MSR_IA32_MISC_ENABLE, Ia32MiscEnable.Qword); + } + + // + // Set the T-states flag + // + This->PpmFlags |= PPM_TSTATES; + + // + // Set the S0ix flag + // + This->PpmFlags |= PPM_S0ix; + + return EFI_SUCCESS; +} + +/** + This function will disable Power Control configuration. + + @param[in] Buffer Pointer to the function parameters passed in. + (Pointer to the PPM_PROCESSOR_SUPPORT_PROTOCOL_2 instance.) + + @retval EFI_SUCCESS Processor MSR setting is saved. + +**/ +VOID +EFIAPI +ApSafeDisablePowerControl ( + IN OUT VOID *Buffer + ) +{ + MSR_REGISTER PowerCtl; + + PowerCtl.Qword = AsmReadMsr64 (MSR_POWER_CTL); + PowerCtl.Dwords.Low &= ~C1E_ENABLE; + AsmWriteMsr64 (MSR_POWER_CTL, PowerCtl.Qword); + + return; +} + +/** + This function will Enable Power Control configuration. + + @param[in] Buffer Pointer to the function parameters passed in. + (Pointer to the PPM_PROCESSOR_SUPPORT_PROTOCOL_2 instance.) + + @retval EFI_SUCCESS Processor MSR setting is saved. + +**/ +VOID +EFIAPI +ApSafeEnablePowerControl ( + IN OUT VOID *Buffer + ) +{ + MSR_REGISTER PowerCtl; + + PowerCtl.Qword = AsmReadMsr64 (MSR_POWER_CTL); + PowerCtl.Dwords.Low |= C1E_ENABLE; + AsmWriteMsr64 (MSR_POWER_CTL, PowerCtl.Qword); + + return; +} + +/** + Enables C-State support as specified by the input flags on all logical + processors and sets associated timing requirements in the chipset. + + @param[in, out] This Pointer to the protocol instance + @param[in] C2IoAddress IO address to generate C2 states (PM base + 014 usually) + @param[in] CsmIoAddress IO trap address for CSM generated Cx requests (see PMG_IO_BASE_ADDR and PMG_CST_CONFIG_CONTROL MSR) + + @retval EFI_SUCCESS Processor C state support configured successfully. + +**/ +STATIC +EFI_STATUS +EFIAPI +EnableCStatesCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This, + IN UINT16 C2IoAddress, + IN UINT16 CsmIoAddress + ) +{ + ENABLE_CSTATE_PARAMS EnableCStateParameters; + // + // @NOTE: This code segment may not be valid in VLV due to I/O legacy support + // for C-states is no longer available. But the code is remained. + // + // Load the C-State parameters to pass to the core function. + // + EnableCStateParameters.This = This; + EnableCStateParameters.C2IoAddress = C2IoAddress; + EnableCStateParameters.CsmIoAddress = CsmIoAddress; + // + // Enable C-States on all logical processors. + // + RunOnAllLogicalProcessors(ApSafeEnableCStates, &EnableCStateParameters); + + // + // Configure supported enhanced C-states + // C1E enable bit in Power Ctl MSR has package scope + // + // + // Enable supported states + // + if (This->PpmFlags & PPM_C1E) { + RunOnAllLogicalProcessors(ApSafeEnablePowerControl, This); + } else { + RunOnAllLogicalProcessors(ApSafeDisablePowerControl, This); + + } + + return EFI_SUCCESS; +} + +/** + Enable C-State support as specified by the input flags on a logical processor. + Configure BIOS C1 Coordination (SMI coordination) + Enable IO redirection coordination + Choose proper coordination method + Configure extended C-States + + This function must be MP safe. + + @param[in] Buffer Pointer to a ENABLE_CSTATE_PARAMS containing the necessary + information to enable C-States + + @retval EFI_SUCCESS Processor C-State support configured successfully. + +**/ +VOID +EFIAPI +ApSafeEnableCStates ( + IN OUT VOID *Buffer + ) +{ + MSR_REGISTER PmCfgCtrl; + MSR_REGISTER IoCaptAddr; + MSR_REGISTER BblCrCtl3; + PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This; + UINT16 C2IoAddress; + UINT16 CsmIoAddress; + + // + // Extract parameters from the buffer + // + This = ((ENABLE_CSTATE_PARAMS*) Buffer)->This; + C2IoAddress = ((ENABLE_CSTATE_PARAMS*) Buffer)->C2IoAddress; + CsmIoAddress = ((ENABLE_CSTATE_PARAMS*) Buffer)->CsmIoAddress; + + // + // If C-states are disabled in setup, configure PACK_LIM in CLOCK_CST_CONFIG_CONTROL + // + if (!(This->PpmFlags & PPM_C_STATES)) { + PmCfgCtrl.Qword = AsmReadMsr64 (MSR_PM_CFG_CTRL); + PmCfgCtrl.Dwords.Low &= ~CSTATE_LIMIT_MASK; + AsmWriteMsr64 (MSR_PM_CFG_CTRL, PmCfgCtrl.Qword); + return; + } + + // + // Set c-state package limit to the highest C-state enabled + // + PmCfgCtrl.Qword = AsmReadMsr64 (MSR_PM_CFG_CTRL); + PmCfgCtrl.Dwords.Low &= ~CSTATE_LIMIT_MASK; + if (This->PpmFlags & PPM_C7){ + PmCfgCtrl.Dwords.Low |= CSTATE_LIMIT_C7; + PmCfgCtrl.Dwords.Low |= DYNAMIC_L2_ENABLE; + // + // When GV3 ratio is BELOW or EQUAL to this ratio, L2-reduction + // will be allowed in C6C/C6; + // When Ratio is ABOVE this point, Expand will be requested; + // If Ratio=0, then this feature is OFF (ratio will not be taken + // into account for L2-shrink decision making). + // + PmCfgCtrl.Dwords.Low &= ~L2_SHRINK_THRESHOLD_MASK; + // + //Program L2_SHRINK_THRESH to Max Ratio + // + if (This->PpmFlags & PPM_S0ix){ + PmCfgCtrl.Dwords.Low |= mMinBusRatio << L2_SHRINK_THRESHOLD_OFFSET; + } + else { + PmCfgCtrl.Dwords.Low |= mMaxBusRatio << L2_SHRINK_THRESHOLD_OFFSET; + } + + } + // + //If CPU support C6 + // + else if (This->PpmFlags & PPM_C6) { + PmCfgCtrl.Dwords.Low |= CSTATE_LIMIT_C6; + PmCfgCtrl.Dwords.Low |= DYNAMIC_L2_ENABLE; + // + // When GV3 ratio is BELOW or EQUAL to this ratio, L2-reduction + // will be allowed in C6C/C6; + // When Ratio is ABOVE this point, Expand will be requested; + // If Ratio=0, then this feature is OFF (ratio will not be taken + // into account for L2-shrink decision making). + // + PmCfgCtrl.Dwords.Low &= ~L2_SHRINK_THRESHOLD_MASK; + // + //Program L2_SHRINK_THRESH to Max Ratio + // + if (This->PpmFlags & PPM_S0ix){ + PmCfgCtrl.Dwords.Low |= mMinBusRatio << L2_SHRINK_THRESHOLD_OFFSET; + } + else { + PmCfgCtrl.Dwords.Low |= mMaxBusRatio << L2_SHRINK_THRESHOLD_OFFSET; + } + } + else if (This->PpmFlags & PPM_C4) { + PmCfgCtrl.Dwords.Low |= CSTATE_LIMIT_C4; + } + else if (This->PpmFlags & PPM_C2) { + PmCfgCtrl.Dwords.Low |= CSTATE_LIMIT_C2; + } + else if (This->PpmFlags & PPM_C1) { + PmCfgCtrl.Dwords.Low |= CSTATE_LIMIT_C1; + } + AsmWriteMsr64 (MSR_PM_CFG_CTRL, PmCfgCtrl.Qword); + + // + // Cherryview specific configuration of I/O capture and I/O coordination SMI MSR + // Configure the base port and range in the MSR to match LVL_X settings in ACPI tables + // + // + // Set I/O capture base port and range + // + IoCaptAddr.Qword = AsmReadMsr64 (MSR_PMG_IO_CAPTURE_BASE); + // + // Mask off CST range and set the CST range + // + IoCaptAddr.Dwords.Low &= ~IO_CAPT_RANGE_MASK; + if (This->PpmFlags & PPM_C7) { + IoCaptAddr.Dwords.Low |= IO_CAPT_LVL4; + } else if (This->PpmFlags & PPM_C6) { + IoCaptAddr.Dwords.Low |= IO_CAPT_LVL3; + } else if (This->PpmFlags & PPM_C4) { + IoCaptAddr.Dwords.Low |= IO_CAPT_LVL2; + } + + // + // Set the base CST address + // + IoCaptAddr.Dwords.Low &= ~(IO_CAPT_LVL2_BASE_ADDR_MASK); + IoCaptAddr.Dwords.Low |= (UINT32)C2IoAddress; + + AsmWriteMsr64 (MSR_PMG_IO_CAPTURE_BASE, IoCaptAddr.Qword); + + if (This->PpmFlags & PPM_C4) { + // + // Set the L2 Way Chunk Size to 1/4 before enabling Deep C4. + // From Core 8 Release 57 + // + BblCrCtl3.Qword = AsmReadMsr64 (MSR_BBL_CR_CTL3); + BblCrCtl3.Dwords.Low &= ~L2_WAY_CHUNK_SZ_MASK; + BblCrCtl3.Dwords.Low |= L2_WAY_CHUNK_SZ_4; + + AsmWriteMsr64 (MSR_BBL_CR_CTL3, BblCrCtl3.Qword); + } + return; +} + +/** + This will perform general thermal initialization other then TM1, TM2, or + PROCHOT# on all logical processors. + + @param[in] This Pointer to the protocol instance + + @retval EFI_SUCCESS General thermal initialization completed successfully + +**/ +STATIC +EFI_STATUS +EFIAPI +InitThermalCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This, + IN OUT PPM_PLATFORM_POLICY_PROTOCOL *PPMPolicy + ) +{ + MSR_REGISTER MsrVal; + + // + // Run thermal code on all logical processors. + // + RunOnAllLogicalProcessors(ApSafeInitThermal, PPMPolicy); + + // core thermal initialization + + MsrVal.Qword = AsmReadMsr64 (MSR_CPU_THERM_CFG1); + MsrVal.Dwords.Low = 0x00000305; + AsmWriteMsr64(MSR_CPU_THERM_CFG1, MsrVal.Qword); + + MsrVal.Qword = AsmReadMsr64 (MSR_CPU_THERM_CFG2); + MsrVal.Dwords.Low = 0x0405500D; + AsmWriteMsr64(MSR_CPU_THERM_CFG2, MsrVal.Qword); + + MsrVal.Qword = AsmReadMsr64 (MSR_CPU_THERM_SENS_CFG); + MsrVal.Dwords.Low = 0x00000027; + AsmWriteMsr64(MSR_CPU_THERM_SENS_CFG, MsrVal.Qword); + + MsrVal.Qword = AsmReadMsr64 (MSR_PACKAGE_POWER_SKU_UNIT); + MsrVal.Dwords.Low = 0x00000505; + AsmWriteMsr64(MSR_PACKAGE_POWER_SKU_UNIT, MsrVal.Qword); + + return EFI_SUCCESS; +} + +/** + This will perform general thermal initialization other then TM1, TM2, or PROCHOT#. + This currently disables TM2 if enabled by default. EnableTm2Cherryview will be called + if TM2 is desired. + + @param[in] This Pointer to the protocol instance + @param[in] PpmFlags Processor power management feature flags + + @retval EFI_SUCCESS General thermal initialization completed successfully + +**/ +VOID +EFIAPI +ApSafeInitThermal ( + IN OUT VOID *Buffer + ) +{ + MSR_REGISTER Ia32MiscEnable; + MSR_REGISTER EbcHardPoweron; + PPM_PLATFORM_POLICY_PROTOCOL *This; + + // + // Extract parameters from the buffer + // + This = (PPM_PLATFORM_POLICY_PROTOCOL *) Buffer; + + // + // Configure Adaptive thermal monitor. IA32_MISC_ENABLE[3] + // + Ia32MiscEnable.Qword = AsmReadMsr64 (MSR_IA32_MISC_ENABLES); + Ia32MiscEnable.Dwords.Low &= ~TM_ENABLE; + if (This->FunctionEnables.EnableTm) { + Ia32MiscEnable.Dwords.Low |= TM_ENABLE; + } + + AsmWriteMsr64 (MSR_IA32_MISC_ENABLES, Ia32MiscEnable.Qword); + + // + // @NOTE: Inherit similar setting from CDV to VLV. + // Set the Stop-Enable (STEN) bit for Mermom so internal clocks stop during + // AutoHalt or Stop Clock states. + // + EbcHardPoweron.Qword = AsmReadMsr64 (EFI_MSR_EBC_HARD_POWERON); + EbcHardPoweron.Qword |= (UINT64)STOP_ENABLE; + AsmWriteMsr64 (EFI_MSR_EBC_HARD_POWERON, EbcHardPoweron.Qword); + + return; +} + +/** + Enable TM1 + + @param[in] This Pointer to the protocol instance + + @retval None + +**/ +STATIC +EFI_STATUS +EFIAPI +EnableTmCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ) +{ + + // + // Enable TM1 on all logical processors. + // + RunOnAllLogicalProcessors(ApSafeEnableTm, This); + + return EFI_SUCCESS; +} + +/** + This function will enable TM. + This function must be MP safe. + + @param[in] Buffer Pointer to the function parameters passed in. + (Pointer to the PPM_PROCESSOR_SUPPORT_PROTOCOL_2 instance.) + + @retval EFI_SUCCESS TM1 enabled + +**/ +VOID +EFIAPI +ApSafeEnableTm ( + IN OUT VOID *Buffer + ) +{ + // + // @IMPORTANT NOTES: + // Enable Thermal Monitor features. Thermal throttling should take effect + // when operating thermal conditions are exceeded. TM2 style throttling is + // automatically engaged if GS3_EN is set. Otherwise, TM1 style throttling + // will be engaged. Thermal interrupts to the CPU should also be disabled + // if TM_EN is 0. Additionally, the Turbo range of operation should be + // disallowed when TM_EN=0. + // TM_EN can only be set if FB_THERM_THROT_DIS_FUSE=0. + // 0 - Thermal throttling is disabled + // 1 - Thermal throttling is enabled. + // + + MSR_REGISTER Ia32MiscEnable; + + // + // Enable TM1 in the CPU MSR + // + Ia32MiscEnable.Qword = AsmReadMsr64 (EFI_MSR_IA32_MISC_ENABLE); + Ia32MiscEnable.Qword |= (UINT64)TM_ENABLE; + AsmWriteMsr64 (EFI_MSR_IA32_MISC_ENABLE, Ia32MiscEnable.Qword); + + return; +} + +/** + Enables the bi-directional PROCHOT# signal on all logical processors. + + @param[in] This Pointer to the protocol instance + + @retval EFI_SUCCESS PROCHOT# configured successfully + +**/ +STATIC +EFI_STATUS +EFIAPI +EnableProcHotCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ) +{ + MSR_REGISTER CpuThermCfg2; + // + // Enable PROCHOT# in the CPU MSR if TM is enabled, + // else disable it. + // + CpuThermCfg2.Qword = AsmReadMsr64 (MSR_CPU_THERM_CFG2); + if (This->PpmFlags & (PPM_TM)) { + CpuThermCfg2.Qword |= (UINT64)PHOT_ENABLE; + } else { + // + // Clear the PPM_PROC_HOT flag so that the correct state is reflected. + // + This->PpmFlags &= ~PPM_PROC_HOT; + CpuThermCfg2.Qword &= (~(UINT64)PHOT_ENABLE); + } + + AsmWriteMsr64 (MSR_CPU_THERM_CFG2, CpuThermCfg2.Qword); + + return EFI_SUCCESS; +} + +/** + Enables GV3 support in a logical processor. + + This function must be MP safe. + + @param[in] Buffer Pointer to the function parameters passed in. + (Pointer to the PPM_PROCESSOR_SUPPORT_PROTOCOL_2 instance.) + + @retval EFI_SUCCESS + +**/ +VOID +EFIAPI +ApSafeDisableGv3 ( + IN OUT VOID *Buffer + ) +{ + MSR_REGISTER Ia32MiscEnable; + + // + // Enable GV3 in the CPU MSR + // + Ia32MiscEnable.Qword = AsmReadMsr64 (MSR_IA32_MISC_ENABLES); + Ia32MiscEnable.Qword &= (~(UINT64)GV3_ENABLE); + AsmWriteMsr64 (MSR_IA32_MISC_ENABLES, Ia32MiscEnable.Qword); + + return; +} + +/** + Set processor P state to HFM or LFM. + + @param[in] Buffer Unused + + @retval EFI_SUCCESS Processor MSR setting is saved. + +**/ +VOID +EFIAPI +ApSafeSetBootPState ( + IN OUT VOID *Buffer + ) +{ + MSR_REGISTER Ia32PerfCtl; + + Ia32PerfCtl.Qword = AsmReadMsr64 (MSR_IA32_PERF_CTL); + Ia32PerfCtl.Qword &= (~(UINT64)P_STATE_TARGET_MASK); + if ( mPpmProcessorSupportProtocolCherryview.PpmFlags & PPM_BOOT_P_ST_HFM ) { + // Set to HFM + Ia32PerfCtl.Qword |= LShiftU64 (mMaxBusRatio, P_STATE_TARGET_OFFSET); + Ia32PerfCtl.Qword |= (UINT64)mMaxVid, 0xFF; + } else { + // Set to LFM + Ia32PerfCtl.Qword |= LShiftU64 (mMinBusRatio, P_STATE_TARGET_OFFSET); + Ia32PerfCtl.Qword |= (UINT64)mMinVid, 0xFF; + } + AsmWriteMsr64 (MSR_IA32_PERF_CTL, Ia32PerfCtl.Qword); + return; +} + +/** + Set processor P state to HFM or LFM. + + @param[in] This Pointer to the protocol instance + + @retval EFI_UNSUPPORTED EIST not supported. + @retval EFI_SUCCESS Processor P state has been set. + +**/ +STATIC +EFI_STATUS +EFIAPI +SetBootPState ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ) +{ + MSR_REGISTER Ia32MiscEnable; + BOOLEAN EistEnabled; + + // + // This function will be executed when EIST is enabled and EIST is capable + // So processor can be switched to HFM + // + if ((mCpuid01.RegEcx & CPUXFF_GV3) == 0) { + return EFI_UNSUPPORTED; + } + + // + // Enable EIST + // + Ia32MiscEnable.Qword = AsmReadMsr64 (MSR_IA32_MISC_ENABLES); + EistEnabled = (BOOLEAN)RShiftU64((Ia32MiscEnable.Qword & GV3_ENABLE),GV3_ENABLE_OFFSET); + // + // Check whether EIST is disabled in setup. + // + if ((This->PpmFlags & PPM_GV3) == 0) { + EistEnabled = 0; + } + // + // If EIST is disabled, temporarily enable it + // + if (EistEnabled == 0) { + RunOnAllLogicalProcessors (ApSafeEnableGv3, This); + } + + // + // Set P-state to HFM on all cores + // + RunOnAllLogicalProcessors (ApSafeSetBootPState, This); + + // + // Disable EIST if we enabled it previously + // + if (EistEnabled == 0) { + RunOnAllLogicalProcessors (ApSafeDisableGv3, This); + } + + return EFI_SUCCESS; +} + +/** + Initialize the TSC support. + + @param[in, out] This Pointer to the protocol instance + @param[in, out] FvidPointer Pointer to a table to be updated + @param[in] iFSBFrequency Processor core iFSB Frequency + @param[in, out] PpmCstTmrFlags Flag of update TSC MSR if C3 or C4 + @param[in, out] PpmTscCorrFactor TSC correction factor + @param[in, out] PpmTscCorrFactorRem TSC correction factor remainder + + @retval EFI_SUCCESS Processor TSC support configured successfully. + +**/ +STATIC +EFI_STATUS +EFIAPI +EnableTscCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This, + IN OUT FVID_TABLE *FvidPointer, + IN UINT16 iFSBFrequency, + IN OUT UINT8 *PpmCstTmrFlags, + IN OUT UINTN *PpmTscCorrFactor, + IN OUT UINTN *PpmTscCorrFactorRem + ) +{ + UINT64 FrequencyId; + + // + // Initialize the TSC update variables for Cherryview + // + *PpmCstTmrFlags = CST_UPDT_TSC; + + // + // Initialize the FVID tables, so that the maximum ratio setting is identified. + // + InitFvidTableCherryview (This, FvidPointer, FVID_MAX_STATES, FVID_MIN_STEP_SIZE, FALSE); + ASSERT (FvidPointer->FvidHeader.Gv3States != 0); + + // + // Get the maximum frequency. + // + + FrequencyId = mMaxBusRatio; + // + // Direct multiply Core IFSB with Max Ratio + FrequencyId = MultU64x32 (FrequencyId, iFSBFrequency); + + // + // Divide by timer base frequency + // Save value and remainder + // + *PpmTscCorrFactor = (UINTN) DivU64x32Remainder (FrequencyId, CST_DATA_TBASE, (UINT32 *)PpmTscCorrFactorRem); + + return EFI_SUCCESS; +} + +/** + Save processor MSR runtime settings for S3. + + @param[in] This Pointer to the protocol instance + + @retval EFI_SUCCESS Processor MSR setting is saved. + +**/ +STATIC +EFI_STATUS +EFIAPI +S3SaveMsrCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ) +{ + UINT32 Index; + + for (Index = 0; Index < sizeof (mMsrValues) / sizeof (EFI_MSR_VALUES); Index++) { + mMsrValues[Index].Value = AsmReadMsr64 (mMsrValues[Index].Index); + } + + return EFI_SUCCESS; +} + +/** + Restore processor MSR runtime settings for S3. + + @param[in] This Pointer to the protocol instance + + @retval EFI_SUCCESS Processor MSR setting is restored. + +**/ +STATIC +EFI_STATUS +EFIAPI +S3RestoreMsrCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ) +{ + // + // Restore MSR's on all logical processors. + // + RunOnAllLogicalProcessors(ApSafeRestoreMsr, This); + + return EFI_SUCCESS; +} + +/** + This function will restore MSR settings. + + This function must be MP safe. + + @param[in] Buffer Unused + + @retval EFI_SUCCESS MSR restored + +**/ +VOID +EFIAPI +ApSafeRestoreMsr ( + IN OUT VOID *Buffer + ) +{ + UINT32 Index; + + for (Index = 0; Index < sizeof (mMsrValues) / sizeof (EFI_MSR_VALUES); Index++) { + AsmWriteMsr64 (mMsrValues[Index].Index, mMsrValues[Index].Value); + } + + AsmWriteMsr64 (MSR_POWER_MISC, AsmReadMsr64(MSR_POWER_MISC) | ENABLE_IA_UNTRUSTED_MODE); + return; +} + +/** + Enables IO redirection C-State control on all logical processors. + This should only be enabled if the OS and processor driver support + independent C-State control for C2 and higher. + + This will cause the processor to capture LVL_X reads and perform the requested + C-State transition. + + This cannot be enabled when SMI based C-State coordination is enabled, + so this function will disable SMI based C-State coordination. + + @param[in] This Pointer to the protocol instance + + @retval EFI_SUCCESS Processor IO redirection C-State control enabled. + +**/ +STATIC +EFI_STATUS +EFIAPI +EnableCStateIoRedirectionCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ) +{ + // + // Enable C-State I/O redirection on all logical processors. + // + RunOnAllLogicalProcessors(ApSafeEnableCStateIoRedirection, This); + + return EFI_SUCCESS; +} + +/** + Enables C-State I/O redirection on a logical processor. + + This function must be MP safe. + + @param[in] Buffer Unused + + @retval EFI_SUCCESS Processor IO redirection C-State control enabled. + +**/ +VOID +EFIAPI +ApSafeEnableCStateIoRedirection ( + IN OUT VOID *Buffer + ) +{ + MSR_REGISTER PmCfgCtrl; + + // + // Enable I/O redirection control + // + PmCfgCtrl.Qword = AsmReadMsr64 (MSR_PM_CFG_CTRL); + PmCfgCtrl.Dwords.Low |= MWAIT_IO_REDIR; + AsmWriteMsr64 (MSR_PM_CFG_CTRL, PmCfgCtrl.Qword); + + return ; +} + +/** + Disables C-State IO redirection on all logical processors. + + @param[in] This Pointer to the protocol instance + + @retval EFI_SUCCESS Processor IO redirection C-State control disabled. + +**/ +STATIC +EFI_STATUS +EFIAPI +DisableCStateIoRedirectionCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ) +{ + // + // Disable C-State I/O redirection on all logical processors. + // + RunOnAllLogicalProcessors(ApSafeDisableCStateIoRedirection, This); + + return EFI_SUCCESS; +} + +/** + Disables C-State IO redirection on a logical processor. + + This function must be MP safe. + + @param[in] Buffer Unused + + @retval EFI_SUCCESS Processor IO redirection C-State control disabled. + +**/ +VOID +EFIAPI +ApSafeDisableCStateIoRedirection ( + IN OUT VOID *Buffer + ) +{ + MSR_REGISTER PmCfgCtrl; + + // + // Disable I/O redirection C-State control + // + PmCfgCtrl.Qword = AsmReadMsr64 (MSR_PM_CFG_CTRL); + PmCfgCtrl.Dwords.Low &= ~MWAIT_IO_REDIR; + AsmWriteMsr64 (MSR_PM_CFG_CTRL, PmCfgCtrl.Qword); + + return; +} + +/** + Disable Turbo Mode at package level + + @param[in] This Pointer to the protocol instance + @param[in] PPMPolicy Pointer to policy protocol instance + + @retval None + +**/ +VOID +EFIAPI +ApSafeDisableTurboMode ( + IN OUT VOID *Buffer + ) +{ + MSR_REGISTER Ia32MiscEnableMsr; + + // + // Set Turbo Mode disable bit in IA32 Misc Enable MSR + // + Ia32MiscEnableMsr.Qword = AsmReadMsr64 (MSR_IA32_MISC_ENABLES); + Ia32MiscEnableMsr.Dwords.High |= DISABLE_MASTER_TURBO_MODE; + AsmWriteMsr64 (MSR_IA32_MISC_ENABLES, Ia32MiscEnableMsr.Qword); +} + +/** + Enables Turbo Mode at package level + + @param[in] This Pointer to the protocol instance + @param[in] PPMPolicy Pointer to policy protocol instance + + @retval None + +**/ +VOID +EFIAPI +ApSafeEnableTurboMode ( + IN OUT VOID *Buffer + ) +{ + MSR_REGISTER Ia32MiscEnableMsr; + // + // Clear Turbo Mode disable bit in IA32 Misc Enable MSR + // + Ia32MiscEnableMsr.Qword = AsmReadMsr64 (MSR_IA32_MISC_ENABLES); + Ia32MiscEnableMsr.Dwords.High &= ~DISABLE_MASTER_TURBO_MODE; + AsmWriteMsr64 (MSR_IA32_MISC_ENABLES, Ia32MiscEnableMsr.Qword); + +} + +/** + Initializes required structures for P-State table creation and enables GV3 + support in the processor. + + @param[in, out]This Pointer to the protocol instance + @param[in, out]FvidPointer Table to update, must be initialized. + @param[in, out]PPMPolicy Pointer to policy protocol instance + + @retval EFI_SUCCESS + +**/ +STATIC +EFI_STATUS +EFIAPI +InitGv3Cherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This, + IN OUT FVID_TABLE *FvidPointer, + IN OUT PPM_PLATFORM_POLICY_PROTOCOL *PPMPolicy + ) +{ + MSR_REGISTER TempMsr; + MSR_REGISTER FlexRatioMsr; + MSR_REGISTER PlatformIdMsr; + + PlatformIdMsr.Qword = AsmReadMsr64 (EFI_MSR_IA32_PLATFORM_ID); + // + // If not fuse disabled, then the Max ratio is programmable. + // + if (!(PlatformIdMsr.Dwords.Low & RATIO_LOCKED) && (PPMPolicy->FlexRatioVid & 0x10000)) { + if ((PPMPolicy->FlexRatioVid & 0xFFFF) != 0) { + FlexRatioMsr.Qword = PPMPolicy->FlexRatioVid; + AsmWriteMsr64 (MSR_FLEX_RATIO, FlexRatioMsr.Qword); + } + } + + // + // Test for Turbo Mode supported and initialize if true. + // + + // + // Start: Workaround for sighting 4683480, 4683441 for Q8XA IVI SKU + // + if (mTurboModeNotAvailable==0) { + // + // End: Workaround for sighting 4683480, 4683441 for Q8XA IVI SKU + // + if (This->PpmFlags & PPM_TURBO) { + RunOnAllLogicalProcessors (ApSafeEnableTurboMode, This); + } else { + RunOnAllLogicalProcessors (ApSafeDisableTurboMode, This); + } + // + // Start: Workaround for sighting 4683480, 4683441 for Q8XA IVI SKU + // + } + // + // End: Workaround for sighting 4683480, 4683441 for Q8XA IVI SKU + // + + // + // Initialize the FVID tables. + // + InitFvidTableCherryview (This, FvidPointer, FVID_MAX_STATES, FVID_MIN_STEP_SIZE, FALSE); + ASSERT (FvidPointer->FvidHeader.Gv3States != 0); + + // + // Enable GV3 on all logical processors. + // + RunOnAllLogicalProcessors(ApSafeEnableGv3, This); + + // + // Program Primary Power Plane Current Limit's + // + if( PPMPolicy->PrimaryPlaneCurrentLimit != AUTO ) { + TempMsr.Qword = AsmReadMsr64 (MSR_PRIMARY_PLANE_CURRENT_CONFIG); + TempMsr.Dwords.Low &= ~CURRENT_LIMIT_MASK; + TempMsr.Dwords.Low |= (UINT32)PPMPolicy->PrimaryPlaneCurrentLimit; + AsmWriteMsr64 (MSR_PRIMARY_PLANE_CURRENT_CONFIG, TempMsr.Qword); + } + return EFI_SUCCESS; +} + +/** + Enables GV3 support in a logical processor. + This function must be MP safe. + + @param[in] Buffer Pointer to the function parameters passed in. + (Pointer to the PPM_PROCESSOR_SUPPORT_PROTOCOL_2 instance.) + + @retval EFI_SUCCESS + +**/ +VOID +EFIAPI +ApSafeEnableGv3 ( + IN OUT VOID *Buffer + ) +{ + PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This; + MSR_REGISTER Ia32MiscEnable; + MSR_REGISTER PmCfgCtrl; + MSR_REGISTER PowerMisc; + + // + // Extract parameters from the buffer. + // + This = (PPM_PROCESSOR_SUPPORT_PROTOCOL_2*) Buffer; + + // + // Enable GV3 in the CPU MSR + // + Ia32MiscEnable.Qword = AsmReadMsr64 (MSR_IA32_MISC_ENABLES); + Ia32MiscEnable.Qword |= (UINT64)GV3_ENABLE; + AsmWriteMsr64 (MSR_IA32_MISC_ENABLES, Ia32MiscEnable.Qword); + + PowerMisc.Qword = AsmReadMsr64 (MSR_POWER_MISC); + + // + // If CMP is disabled, disable hardware coordination. + // + if (!(This->PpmFlags & PPM_CMP)) { + PmCfgCtrl.Qword = AsmReadMsr64 (MSR_PM_CFG_CTRL); + PmCfgCtrl.Qword |= (UINT64)HW_COORD_DIS; + AsmWriteMsr64 (MSR_PM_CFG_CTRL, PmCfgCtrl.Qword); + } + + return; +} + +/** + Enables GV3 hardware coordination on all logical processors. + + @param[in] This Pointer to the protocol instance + + @retval EFI_SUCCESS Hardware coordination enabled. + +**/ +STATIC +EFI_STATUS +EFIAPI +EnablePStateHardwareCoordinationCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ) +{ + // + // Enable GV3 hardware coordination on all logical processors. + // + RunOnAllLogicalProcessors(ApSafeEnablePStateHardwareCoordination, This); + + return EFI_SUCCESS; +} + +/** + Enable the hardware coordination of P-states. + This function must be MP safe. + + @param[in] Buffer Unused + + @retval EFI_SUCCESS Hardware coordination enabled. + +**/ +VOID +EFIAPI +ApSafeEnablePStateHardwareCoordination ( + IN OUT VOID *Buffer + ) +{ + MSR_REGISTER PmCfgCtrl; + MSR_REGISTER PowerMisc; + + // + // @NOTE: If Microcode SINGLE_PCTL BUG NOT FIXED + // EHalt should not be set if SINGLE_PCTL=1. + // Each module is a domain. + // OS Must do SW_ALL coordination between Modules to get V^2 power savings. + // Otherwise will get >=linear savings. + // + // @WORKAROUND: To disable hardware coordination by setting SINGLE_PCTL = 1. + // SINGLE_PCTL = 0 implies HW_ALL coordination. + // + // @TODO: To remove this workaround when the bug is fixed. + // + + PmCfgCtrl.Qword = AsmReadMsr64 (MSR_PM_CFG_CTRL); + PmCfgCtrl.Dwords.Low |= SINGLE_PCTL; + AsmWriteMsr64 (MSR_PM_CFG_CTRL, PmCfgCtrl.Qword); + + PowerMisc.Qword = AsmReadMsr64 (MSR_POWER_MISC); + PowerMisc.Qword &= (~(UINT64)(ENABLE_ULFM_AUTOCM_MASK | ENABLE_INDP_AUTOCM_MASK)); + AsmWriteMsr64 (MSR_POWER_MISC, PowerMisc.Qword); + return; +} + +/** + Disable the hardware coordination of P-states. + + @param[in] This Pointer to the protocol instance + + @retval EFI_SUCCESS Hardware coordination disabled. + +**/ +STATIC +EFI_STATUS +EFIAPI +DisablePStateHardwareCoordinationCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ) +{ + // + // Disable GV3 hardware coordination on all logical processors. + // + RunOnAllLogicalProcessors(ApSafeDisablePStateHardwareCoordination, This); + + return EFI_SUCCESS; +} + +/** + Disables GV3 hardware coordination on a logical processor. + + This function must be MP safe. + + @param[in] Buffer Unused + + @retval EFI_SUCCESS Hardware coordination disabled. + +**/ +VOID +EFIAPI +ApSafeDisablePStateHardwareCoordination ( + IN OUT VOID *Buffer + ) +{ + MSR_REGISTER PmCfgCtrl; + + // + // Disable HW coordination + // + PmCfgCtrl.Qword = AsmReadMsr64 (MSR_PM_CFG_CTRL); + PmCfgCtrl.Dwords.Low |= HW_COORD_DIS; + AsmWriteMsr64 (MSR_PM_CFG_CTRL, PmCfgCtrl.Qword); + + return; +} + +/** + This function updates the table provided with the FVID data for the processor. + If CreateDefaultTable is TRUE, a minimam FVID table will be provided. + The maximum number of states must be greater then or equal to two. + The table should be initialized in such a way as for the caller to determine if the + table was updated successfully. This function should be deprecated in the future when + Release 8 is integrated in favor of the EIST protocol calculating FVID information. + + @param[in] This Pointer to the protocol instance + @param[in] FvidPointer Pointer to a table to be updated + @param[in] MaxNumberOfStates Number of entries in the table pointed to by FvidPointer + @param[in] MinStepSize Minimum step size for generating the FVID table + @param[in] CreateDefaultTable Create default FVID table rather then full state support + + @retval EFI_SUCCESS Table pointed to FvidPointer updated with desired FVID states + +**/ +STATIC +EFI_STATUS +InitFvidTableCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This, + IN OUT FVID_TABLE *FvidPointer, + IN UINT16 MaxNumberOfStates, + IN UINT16 MinStepSize, + IN BOOLEAN CreateDefaultTable + ) +{ + EFI_STATUS Status; + MSR_REGISTER PlatformIdMsr; + MSR_REGISTER IaCoreRatios; + MSR_REGISTER IaCoreVids; + MSR_REGISTER ClockFlexMax; + + // + // If the FVID tables have already been created, return. + // + if (FvidPointer[0].FvidHeader.Gv3States != 0) { + return EFI_SUCCESS; + } + PlatformIdMsr.Qword = AsmReadMsr64 (EFI_MSR_IA32_PLATFORM_ID); + + IaCoreRatios.Qword = AsmReadMsr64 (MSR_IACORE_RATIOS); + mMaxBusRatio = IaCoreRatios.Bytes.ThirdByte; + + // + // Get Maximum Efficiency bus ratio (LFM) from IACORE_RATIOS MSR Bits[15:8] + // + mMinBusRatio = IaCoreRatios.Bytes.SecondByte; + + // + // Get the Vid for the processor + // + // + // Get Maximum Non-Turbo Vid (HFM) from IACORE_VIDS MSR Bits[23:16] + // + IaCoreVids.Qword = AsmReadMsr64 (MSR_IACORE_VIDS); + mMaxVid = IaCoreVids.Bytes.ThirdByte; + + // + // Get Maximum Efficiency VID (LFM) from IACORE_VIDS MSR Bits[15:8] + // + mMinVid = IaCoreVids.Bytes.SecondByte; + + // + // If flex settings are enabled, they must be used in place of max. Ratio/VID + // defined in the MSR_PLATFORM_ID MSR used above. In addition, if flex settings are + // enabled, the maximum frequency is limited an Turbo Mode is unavailable. + // + // NOTE: This code does not provide facilities to program the flex settings + // as such code would best be suited for the PEI phase, as a processor + // reset may be required after programming. + // + if (!(PlatformIdMsr.Dwords.Low & RATIO_LOCKED)) { + ClockFlexMax.Qword = AsmReadMsr64 (MSR_FLEX_RATIO); + if (ClockFlexMax.Dwords.Low & ENABLE_FLEX) { + This->PpmFlags &= ~(PPM_TURBO); + mMaxVid = ClockFlexMax.Bytes.FirstByte & VID_FLEX_BYTE_MASK; + mMaxBusRatio = ClockFlexMax.Bytes.SecondByte & RATIO_FLEX_BYTE_MASK; + } + } + + // + // Create FVID table + // + if (CreateDefaultTable) { + CreateDefaultFvidTable (FvidPointer); + This->PpmFlags &= ~(PPM_TURBO | PPM_DYNAMIC_FSB); + } else { + Status = CreateFvidTable (This, FvidPointer, MaxNumberOfStates, MinStepSize); + if (EFI_ERROR (Status)) { + CreateDefaultFvidTable (FvidPointer); + This->PpmFlags &= ~(PPM_TURBO | PPM_DYNAMIC_FSB); + } + } + + return EFI_SUCCESS; +} + +/** + Create default FVID table with max and min states only. + + @param[in] FvidPointer Pointer to a table to be updated + + @retval None. + +**/ +STATIC +VOID +CreateDefaultFvidTable ( + IN OUT FVID_TABLE *FvidPointer + ) +{ + + // + // Fill in the header. + // + FvidPointer[0].FvidHeader.Stepping = (mCpuid01.RegEax & CPUID_FULL_FAMILY_MODEL_STEPPING); + FvidPointer[0].FvidHeader.MaxVid = mMaxVid; + FvidPointer[0].FvidHeader.MaxBusRatio = mMaxBusRatio; + FvidPointer[0].FvidHeader.Gv3States = 2; + + // + // First entry is state 0, highest state. + // + FvidPointer[1].FvidState.State = 0; + FvidPointer[1].FvidState.Vid = mMaxVid; + FvidPointer[1].FvidState.BusRatio = mMaxBusRatio; + FvidPointer[1].FvidState.Power = FVID_MAX_POWER_MIDVIEW; + // + // power is calculated in milliwatts + // + + // + // Second entry is state 1, lowest state. + // + FvidPointer[2].FvidState.State = 1; + FvidPointer[2].FvidState.Vid = (UINT16) mMinVid; + FvidPointer[2].FvidState.BusRatio = (UINT16) mMinBusRatio; + FvidPointer[2].FvidState.Power = FVID_MIN_POWER_MIDVIEW; +} + +/** + Create an FVID table based on the algorithm provided by the BIOS writer's guide. + + @param[in, out]This Pointer to the protocol instance + @param[in, out]FvidPointer Pointer to a table to be updated + @param[in, out]MaxNumberOfStates Number of entries in the table pointed to by FvidPointer + @param[in, out]MinStepSize Minimum step size for generating the FVID table + + @retval EFI_SUCCESS FVID table created successfully. + @retval EFI_INVALID_PARAMETER The VID and/or bus ratio ranges don't permit FVID table calculation; + a default FVID table should be constructed. + +**/ +STATIC +EFI_STATUS +CreateFvidTable ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This, + IN OUT FVID_TABLE *FvidPointer, + IN UINT16 MaxNumberOfStates, + IN UINT16 MinStepSize + ) +{ + UINT16 BusRatioRange; + UINT16 PowerRange; + UINT16 StepSize; + UINT16 NumberOfStates; + UINT16 CurrentBusRatio; + UINT16 i; + UINT16 EntryCount; + UINT16 Turbo; + UINT16 BusRatioRangeX2; + UINT16 VidRange; + + DEBUG((EFI_D_ERROR,"\n\n == == CreateFvidTable == ==\n\n")); + + // + // Determine the bus ratio range + // + Turbo = 0; + BusRatioRange = mMaxBusRatio - mMinBusRatio; + + if (This->PpmFlags & PPM_TURBO) { + Turbo = 1; + BusRatioRange = mTurboBusRatio - mMinBusRatio; + } + if ( ((INT16) BusRatioRange < 0) || ( MaxNumberOfStates == 0 )) { + return EFI_INVALID_PARAMETER; + } + + // + // Determine step size desired + // Step size is BusRatioRange / max states, rounded down to an even state + // + StepSize = 1; + + // + // Determine the number of states + // No Of States = (BusRatioRange / step size) + 1; Add one to BusRatioRange to account for LFM + // eg. LFM = 8 HFM = 10, BusRatioRange = 2, StepSize = 1 No Of States = (2 / 1) + 1 = 3 (8, 9, 10) + // For No of States above 16... + // StepSize = (No of States / Max No of States) + 1 + // eg. LFM = 8 HFM = 28, BusRatioRange = 20 + // StepSize = (21 / 16) + 1 = 2 + // No Of States = (20 / 2) + 1 = 11 (8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28) + // + NumberOfStates = ( BusRatioRange / StepSize ) + 1; + DEBUG((EFI_D_ERROR, "NumberOfStates:[%04x]\n", NumberOfStates)); + + // + // Create a bus ratio range multiplied by 2 to take N/2 into account in calculations. + // + BusRatioRangeX2 = BusRatioRange * 2; + + // + // Determine the Power range + // + PowerRange = FVID_MAX_POWER_MIDVIEW - FVID_MIN_POWER_MIDVIEW; + + // + // Fill in the table header + // + + FvidPointer[0].FvidHeader.Stepping = (Turbo ? (mTurboBusRatio - mMaxBusRatio):1); + FvidPointer[0].FvidHeader.MaxVid = (Turbo ? mTurboVid : mMaxVid); + FvidPointer[0].FvidHeader.MaxBusRatio = (Turbo ? mTurboBusRatio : mMaxBusRatio); + FvidPointer[0].FvidHeader.Gv3States = (UINT16) (NumberOfStates); + + DEBUG ((EFI_D_ERROR, "FVID[00].FvidHeader.Stepping = %x\n", FvidPointer[0].FvidHeader.Stepping)); + DEBUG ((EFI_D_ERROR, "FVID[00].FvidHeader.MaxVid = %x\n", FvidPointer[0].FvidHeader.MaxVid)); + DEBUG ((EFI_D_ERROR, "FVID[00].FvidHeader.MaxBusRatio = %x\n", FvidPointer[0].FvidHeader.MaxBusRatio)); + DEBUG ((EFI_D_ERROR, "FVID[00].FvidHeader.Gv3States = %x\n", FvidPointer[0].FvidHeader.Gv3States)); + + // + // Fill in the first state + // + FvidPointer[1].FvidState.State = 0; + FvidPointer[1].FvidState.Vid = mMaxVid; + FvidPointer[1].FvidState.BusRatio = mMaxBusRatio; + // + // power is calculated in milliwatts + // + FvidPointer[1].FvidState.Power = FVID_MAX_POWER_MIDVIEW; + EntryCount = 1; + if (This->PpmFlags & PPM_TURBO) { + // + // Fill in the first state + // + FvidPointer[1].FvidState.State = 0; + FvidPointer[1].FvidState.Vid = mTurboVid; + FvidPointer[1].FvidState.BusRatio = mTurboBusRatio; + + DEBUG ((EFI_D_ERROR, "FVID[01].State = %x\n", FvidPointer[1].FvidState.State)); + DEBUG ((EFI_D_ERROR, "FVID[01].BusRatio = %x\n", FvidPointer[1].FvidState.BusRatio)); + DEBUG ((EFI_D_ERROR, "FVID[01].vid = %x\n", FvidPointer[1].FvidState.Vid)); + DEBUG ((EFI_D_ERROR, "FVID[01].Power = %x\n\n", FvidPointer[1].FvidState.Power)); + + DEBUG((EFI_D_ERROR,"== == CreateTurbo 1C to 3C == ==\n")); + + BusRatioRange = mTurboBusRatio - mTurboBusRatio_3C; + DEBUG((EFI_D_ERROR, "BusRatioRange = %x\n", BusRatioRange)); + + if (BusRatioRange != 0) { + VidRange = mTurboVid - mTurboVid_3C; + BusRatioRangeX2 = BusRatioRange * 2; + + CurrentBusRatio = mTurboBusRatio; + for (i = 1; i < BusRatioRange + 1; i++) { + FvidPointer[i + 1].FvidState.State = i; + FvidPointer[i + 1].FvidState.BusRatio = CurrentBusRatio - StepSize; + + CurrentBusRatio = CurrentBusRatio - StepSize; + + if (BusRatioRange != 0) { + FvidPointer[i + 1].FvidState.Vid = ((CurrentBusRatio - mTurboBusRatio_3C) * VidRange * 2) / BusRatioRangeX2 + mTurboVid_3C; + } else { + FvidPointer[i + 1].FvidState.Vid = mTurboVid_3C; + } + if (((CurrentBusRatio - mTurboBusRatio_3C) * VidRange * 2) % BusRatioRangeX2) { + // + // Round up if there is a remainder to remain above the minimum voltage + // + FvidPointer[i + 1].FvidState.Vid++; + } + + FvidPointer[i + 1].FvidState.Power = FVID_MAX_POWER_MIDVIEW; + + DEBUG ((EFI_D_ERROR, "FVID[%02d].State = %x\n", (i + 1), FvidPointer[i + 1].FvidState.State)); + DEBUG ((EFI_D_ERROR, "FVID[%02d].BusRatio = %x\n", (i + 1), FvidPointer[i + 1].FvidState.BusRatio )); + DEBUG ((EFI_D_ERROR, "FVID[%02d].Vid = %x\n", (i + 1), FvidPointer[i + 1].FvidState.Vid )); + DEBUG( (EFI_D_ERROR, "FVID[%02d].Power = %x\n\n", (i + 1), FvidPointer[i + 1].FvidState.Power)); + } + EntryCount = i; + } + // + // Determine the VID range + // Do not check for VID range to be zero because some of the ULV and LV processors + // will have the same HFM and LFM VID values + // + + VidRange = mTurboVid_3C - mMaxVid; + BusRatioRange = mTurboBusRatio_3C - mMaxBusRatio; + DEBUG((EFI_D_ERROR, "BusRatioRange = %x\n", BusRatioRange)); + + BusRatioRangeX2 = BusRatioRange * 2; + + // + // Fill in the table starting at the last entry + // The algorithm is available in the processor BIOS writer's guide. + // + CurrentBusRatio = mTurboBusRatio_3C; + DEBUG((EFI_D_ERROR,"== == CreateTurbo 3C to MaxFID == ==\n")); + + for (i = EntryCount; i <= (mTurboBusRatio - mMaxBusRatio); i++) { + FvidPointer[i + 1].FvidState.State = i; + FvidPointer[i + 1].FvidState.BusRatio = CurrentBusRatio - StepSize; + + CurrentBusRatio = CurrentBusRatio - StepSize; + + if (BusRatioRange != 0) { + FvidPointer[i + 1].FvidState.Vid = ((CurrentBusRatio - mMaxBusRatio) * VidRange * 2) / BusRatioRangeX2 + mMaxVid; + } else { + FvidPointer[i + 1].FvidState.Vid = mMaxVid; + } + + if (((CurrentBusRatio - mMaxBusRatio) * VidRange * 2) % BusRatioRangeX2) { + // + // Round up if there is a remainder to remain above the minimum voltage + // + FvidPointer[i + 1].FvidState.Vid++; + } + + FvidPointer[i + 1].FvidState.Power = FVID_MAX_POWER_MIDVIEW; + + DEBUG ((EFI_D_ERROR, "FVID[%02d].State = %x\n", (i + 1), FvidPointer[i + 1].FvidState.State)); + DEBUG ((EFI_D_ERROR, "FVID[%02d].BusRatio = %x\n", (i + 1), FvidPointer[i + 1].FvidState.BusRatio )); + DEBUG ((EFI_D_ERROR, "FVID[%02d].Vid = %x\n", (i + 1), FvidPointer[i + 1].FvidState.Vid )); + DEBUG( (EFI_D_ERROR, "FVID[%02d].Power = %x\n\n", (i + 1), FvidPointer[i + 1].FvidState.Power)); + } + EntryCount = i; + } + + DEBUG((EFI_D_ERROR,"== == CreateTurbo MaxFID to MinFID == ==\n")); + VidRange = mMaxVid - mMinVid; + BusRatioRange = mMaxBusRatio - mMinBusRatio; + BusRatioRangeX2 = BusRatioRange * 2; + + // + // Determine the Power range + // + PowerRange = FVID_MAX_POWER_MIDVIEW - FVID_MIN_POWER_MIDVIEW; + CurrentBusRatio = mMaxBusRatio; + + for (i = EntryCount; i < NumberOfStates; i++) { + + FvidPointer[i + 1].FvidState.State = i; + FvidPointer[i + 1].FvidState.BusRatio = CurrentBusRatio - StepSize; + + CurrentBusRatio = CurrentBusRatio - StepSize; + + if (BusRatioRange != 0) { + FvidPointer[i + 1].FvidState.Vid = ((CurrentBusRatio - mMinBusRatio) * VidRange * 2) / BusRatioRangeX2 + mMinVid; + } else { + FvidPointer[i + 1].FvidState.Vid = mMinVid; + } + + if (((CurrentBusRatio - mMinBusRatio) * VidRange * 2) % BusRatioRangeX2) { + // + // Round up if there is a remainder to remain above the minimum voltage + // + FvidPointer[i + 1].FvidState.Vid++; + } + + if (BusRatioRange != 0) { + FvidPointer[i + 1].FvidState.Power = ((CurrentBusRatio - mMinBusRatio) * PowerRange * 2) / BusRatioRangeX2 + FVID_MIN_POWER_MIDVIEW; + } else { + FvidPointer[i + 1].FvidState.Power = FVID_MIN_POWER_MIDVIEW; + } + + DEBUG ((EFI_D_ERROR, "FVID[%02d].State = %x\n", (i + 1), FvidPointer[i + 1].FvidState.State)); + DEBUG ((EFI_D_ERROR, "FVID[%02d].BusRatio = %x\n", (i + 1), FvidPointer[i + 1].FvidState.BusRatio )); + DEBUG ((EFI_D_ERROR, "FVID[%02d].Vid = %x\n", (i + 1), FvidPointer[i + 1].FvidState.Vid )); + DEBUG( (EFI_D_ERROR, "FVID[%02d].Power = %x\n\n", (i + 1), FvidPointer[i + 1].FvidState.Power)); + } + + return EFI_SUCCESS; +} + +/** + Private helper function to convert various Turbo Power Limit Time from Seconds to CPU units + + @param[in] TimeInSeconds Time in seconds + + @retval Converted time in CPU units + +**/ +UINT8 GetConvertedTime( + IN UINT32 TimeInSeconds + ) +{ + UINT8 ConvertedPowerLimitTime; + UINT8 Index; + + // + // Convert seconds to MSR value. Since not all values are programmable, we'll select + // the entry from mapping table which is either equal to the user selected value. OR to a value in the mapping table + // which is closest (but less than) to the user-selected value. + // + ConvertedPowerLimitTime = mSecondsToMsrValueMapTable[0][1]; + + for (Index = 0; mSecondsToMsrValueMapTable[Index][0] != END_OF_TABLE; Index++) { + if (TimeInSeconds == mSecondsToMsrValueMapTable[Index][0]) { + ConvertedPowerLimitTime = mSecondsToMsrValueMapTable[Index][1]; + break; + } + + if (TimeInSeconds > mSecondsToMsrValueMapTable[Index][0]) { + ConvertedPowerLimitTime = mSecondsToMsrValueMapTable[Index][1]; + } else { + break; + break; + } + } + return ConvertedPowerLimitTime; +} + +/** + Get the updated power configuration register values + + @param[in] None + + @retval None + +**/ +VOID +UpdateCurrentPowerInfo ( + ) +{ + + MSR_REGISTER TempMsr; + + TempMsr.Qword = AsmReadMsr64 (MSR_PLATFORM_INFO); + // + // Check if TDP Limit is programmable + // Platform Info MSR (0xCE) [29] + // + mTdpLimitProgrammble = 1; + + TempMsr.Qword = AsmReadMsr64 (MSR_PACKAGE_POWER_SKU_UNIT); + // + // Get Power Unit MSR [3:0] + // The actual unit value is calculated by 1mW*Power(2,POWER_UNIT)..Reset value of 5 represents 32mW units. + // + mProcessorPowerUnit = (TempMsr.Bytes.FirstByte & PACKAGE_POWER_UNIT_MASK); + + if (mProcessorPowerUnit == 0) { + mProcessorPowerUnit = 1; + } else { + mProcessorPowerUnit = (UINT8) LShiftU64 (2, (mProcessorPowerUnit - 1)); + } + // @Note: This field should be initialized by PUnit to IACORE_GUAR_TDP_FUSE + SOC_GUAR_TDP_FUSE + // Get the pre-si estimated settings for the Turbo from Punit. + mPackageTdp = 0x1F; + mPackageMaxPower = 0xFF; + mPackageMinPower = 0x3F; + + return; + +} + +/** + Runs the specified procedure on all logical processors, passing in the + parameter buffer to the procedure. + + @param[in]Procedure The function to be run. + @param[in] Buffer Pointer to a parameter buffer. + + @retval None + +**/ +STATIC +EFI_STATUS +RunOnAllLogicalProcessors ( + IN OUT EFI_AP_PROCEDURE Procedure, + IN OUT VOID *Buffer + ) +{ + UINTN Index; + EFI_STATUS Status; + // + // Run the procedure on all logical processors. + // + (*Procedure) (Buffer); + for (Index = 0; Index < gSmst->NumberOfCpus; Index++) { + // + // Skip BSP itself. + // + if (Index == gSmst->CurrentlyExecutingCpu) { + continue; + } + + Status = EFI_NOT_READY; + while (Status != EFI_SUCCESS ) { + Status = gSmst->SmmStartupThisAp (Procedure, Index, Buffer); + if ( Status != EFI_SUCCESS ) { + // + // SmmStartupThisAp might return failure if AP is busy executing some other code. Let's wait for sometime and try again. + // + //PchPmTimerStall (PPM_WAIT_PERIOD); + } + } + } + + return EFI_SUCCESS; +} + +/** + Configures following fields of MSR 0x610 based on user configuration: + Configures Long duration Turbo Mode (power limit 1) power level and time window + Configures Short duration turbo mode (power limit 2) + + @param[in] This Pointer to the protocol instance + @param[in] PPMPolicy Pointer to policy protocol instance + + @retval None + +**/ +STATIC +VOID +EFIAPI +ConfigureTurboPowerLimitsCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This, + IN OUT PPM_PLATFORM_POLICY_PROTOCOL *PPMPolicy + ) +{ +// @NOTE: This may be redundant in BIOS boot flow as P-unit will intialize this MSR with Package TDP. + MSR_REGISTER PKGTurboCfg1Msr; + MSR_REGISTER CPUTurboWkldCfg1Msr; + MSR_REGISTER CPUTurboWkldCfg2Msr; + MSR_REGISTER PP1TurboPowerLimitMsr; + MSR_REGISTER TurboPowerLimitMsr; + UINT8 ConvertedPowerLimit1Time; + UINT16 ProgramedPowerLimit1; + UINT16 ConvertedPowerLimit2; + UINT16 ProgramedPowerLimit2; + UINT64 val; + UINT32 Data32; + UINT32 TdpOffset; + + // + // Get the updated power congigurations as these values may be reconfigured by the Punit + // + UpdateCurrentPowerInfo (); + if (mTdpLimitProgrammble) { + TurboPowerLimitMsr.Qword = AsmReadMsr64 (MSR_TURBO_POWER_LIMIT); + // + // Initialize the Power Limit 1 and Power Limit 1 enable bit + // Power Limit 1: Turbo Power Limit MSR [14:0] + // Power Limit 1 Enable: Turbo Power Limit MSR [15] + // + // + // By default, program the value of IACORE_GUAR_TDP_FUSE + SOC_GUAR_TDP_FUSE to Package TDP limit + // + ProgramedPowerLimit1 = mPackageMinPower; + if (PPMPolicy->TurboSettings.PowerLimit1 != AUTO) { + // + // mPackageMinPower, mPackageMaxPower and mPackageTdp are in watts. + // they can directly compare to PPMPolicy->pTurboSettings->PowerLimit1 + // + ProgramedPowerLimit1 = PPMPolicy->TurboSettings.PowerLimit1; + if (PPMPolicy->TurboSettings.PowerLimit1 < mPackageMinPower) { + // + // If new Power Limit 1 is < mPackageMinPower, program Power Limit 1 to mPackageMinPower + // + ProgramedPowerLimit1 = mPackageMinPower; + } else if ( PPMPolicy->TurboSettings.PowerLimit1 > mPackageMaxPower ) { + // + // If new Power Limit 1 is not within bounds, program Power Limit 1 to Package TDP limit + // + ProgramedPowerLimit1 = mPackageMaxPower; + } + // + // PPMPolicy->pTurboSettings->PowerLimit1 is in watts. We need to convert it to + // CPU Power unit, specified in PACKAGE_POWER_SKU_UNIT_MSR[3:0]. + // Since we are converting from Watts to CPU power units, multiply by + // PACKAGE_POWER_SKU_UNIT_MSR[3:0]. + // + } + + TurboPowerLimitMsr.Dwords.Low &= ~POWER_LIMIT_MASK; + TurboPowerLimitMsr.Dwords.Low |= (UINT32) (ProgramedPowerLimit1); + + // + // Force Power Limit 1 override to be enabled + // + TurboPowerLimitMsr.Dwords.Low |= POWER_LIMIT_ENABLE; + + // + // Program Power Limit 1 (Long Duration Turbo) Time Window + // If PowerLimit1Time is AUTO OR If PowerLimit1Time is > MAX_POWER_LIMIT_1_TIME_IN_SECONDS program default values + // + if ( ( PPMPolicy->TurboSettings.PowerLimit1Time == AUTO ) || ( PPMPolicy->TurboSettings.PowerLimit1Time > MAX_POWER_LIMIT_1_TIME_IN_SECONDS ) ) { + // + // For Mobile, default value is 5 seconds + // + PPMPolicy->TurboSettings.PowerLimit1Time = 5; + + } + ConvertedPowerLimit1Time = GetConvertedTime (PPMPolicy->TurboSettings.PowerLimit1Time); + + // + // Configure Power Limit 1 (Long Duration Turbo) time windows: Turbo Power Limit MSR [23:17] + // + TurboPowerLimitMsr.Dwords.Low &= ~POWER_LIMIT_1_TIME_MASK; + TurboPowerLimitMsr.Dwords.Low |= (UINT32) LShiftU64(ConvertedPowerLimit1Time, 17); + + // + // Initialize Short Duration Power limit and enable bit + // Short duration Power Limit: Turbo Power Limit MSR (0x450h) [46:32] + // Short duration Power Limit Enable:Turbo Power Limit MSR (0x450h) [47] + // + // PPMPolicy->pTurboSettings->PowerLimit2 value is in watts. We need to convert it to + // CPU Power unit, specified in PACKAGE_POWER_SKU_UNIT_MSR[3:0]. + // Since we are converting from Watts to CPU power units, multiply by + // PACKAGE_POWER_SKU_UNIT_MSR[3:0] + // + ProgramedPowerLimit2 = mPackageMaxPower; + ConvertedPowerLimit2 = mPackageMaxPower; + ConvertedPowerLimit2 = ConvertedPowerLimit2 * mProcessorPowerUnit; + if (PPMPolicy->TurboSettings.PowerLimit2 != AUTO) { + // + // mPackageMinPower, mPackageMaxPower and mPackageTdp are in watts. + // they can directly compare to PPMPolicy->pTurboSettings->PowerLimit1 + // + ProgramedPowerLimit2 = PPMPolicy->TurboSettings.PowerLimit2; + if (PPMPolicy->TurboSettings.PowerLimit2 < mPackageMinPower) { + // + // If new Power Limit 2 is < mPackageMinPower, program Power Limit 2 to mPackageMinPower + // + ProgramedPowerLimit2 = mPackageMinPower; + } else if ( PPMPolicy->TurboSettings.PowerLimit2 > mPackageMaxPower ) { + // + // If new Power Limit 2 is not within bounds, program Power Limit 2 to Package TDP limit + // + ProgramedPowerLimit2 = mPackageMaxPower; + } + // + // PPMPolicy->pTurboSettings->PowerLimit2 is in watts. We need to convert it to + // CPU Power unit, specified in PACKAGE_POWER_SKU_UNIT_MSR[3:0]. + // Since we are converting from Watts to CPU power units, multiply by + // PACKAGE_POWER_SKU_UNIT_MSR[3:0]. + // + ConvertedPowerLimit2 = (ProgramedPowerLimit2 * mProcessorPowerUnit); + } + TurboPowerLimitMsr.Dwords.High &= ~POWER_LIMIT_MASK; + TurboPowerLimitMsr.Dwords.High |= (UINT32) (ProgramedPowerLimit2); + // set PKG_PWR_LIM2_TIME = 0x0, 1s + TurboPowerLimitMsr.Dwords.High &= ~POWER_LIMIT_1_TIME_MASK; + // force Power Limit 2 override to be enabled + TurboPowerLimitMsr.Dwords.High |= POWER_LIMIT_ENABLE; + + TurboPowerLimitMsr.Dwords.Low &= 0x0; + val = AsmReadMsr64 (EFI_MSR_TURBO_POWER_LIMIT); + Data32 = val & 0xFFF; + if (Data32 == 0) { + val = 0x003880BC; + } else { + TdpOffset = 0; + val = 0x00388000 + Data32 + TdpOffset; + } + TurboPowerLimitMsr.Dwords.Low |= val; + TurboPowerLimitMsr.Dwords.High &= 0x0; + TurboPowerLimitMsr.Dwords.High |= 0x001481D5; // BSW : PL2 = 15W + + AsmWriteMsr64 (MSR_TURBO_POWER_LIMIT, TurboPowerLimitMsr.Qword); + val = AsmReadMsr64 (MSR_TURBO_POWER_LIMIT); + DEBUG ((EFI_D_ERROR, "MSR_TURBO_POWER_LIMIT = %x\n", val)); + } + + // Configure PP1_TURBO_POWER_LIMIT [23:17] = 0x0, 1 second time duration + PP1TurboPowerLimitMsr.Qword = AsmReadMsr64 (MSR_PRIMARY_PLANE_TURBO_POWER_LIMIT); + PP1TurboPowerLimitMsr.Dwords.Low &= ~PP_PWR_LIM_TIME_MASK; + PP1TurboPowerLimitMsr.Dwords.Low |= PP_PWR_LIM_TIME; + AsmWriteMsr64 (MSR_PRIMARY_PLANE_TURBO_POWER_LIMIT, PP1TurboPowerLimitMsr.Qword); + + // Configure PKG_TURBO_CFG1 + PKGTurboCfg1Msr.Qword = AsmReadMsr64 (MSR_PKG_TURBO_CFG1); + // set Msr 0x670 = 0x00000002 (Dynamic Turbo Mode) + PKGTurboCfg1Msr.Dwords.Low &= 0x0; + PKGTurboCfg1Msr.Dwords.Low |= TURBOMODE | BIT1; + AsmWriteMsr64 (MSR_PKG_TURBO_CFG1, PKGTurboCfg1Msr.Qword); + + // Configure CPU_TURBO_WKLD_CFG1 + CPUTurboWkldCfg1Msr.Qword = AsmReadMsr64 (MSR_CPU_TURBO_WKLD_CFG1); + // set Msr 0x671 = 0x00001B14 (power meter weights) + CPUTurboWkldCfg1Msr.Dwords.Low &= 0x0; + CPUTurboWkldCfg1Msr.Dwords.Low |= 0x200B; + AsmWriteMsr64 (MSR_CPU_TURBO_WKLD_CFG1, CPUTurboWkldCfg1Msr.Qword); + + // Configure CPU_TURBO_WKLD_CFG2 + CPUTurboWkldCfg2Msr.Qword = AsmReadMsr64 (MSR_CPU_TURBO_WKLD_CFG2); + // set Msr 0x672 = 0x00000000 + CPUTurboWkldCfg2Msr.Dwords.Low &= 0x0; + AsmWriteMsr64 (MSR_CPU_TURBO_WKLD_CFG2, CPUTurboWkldCfg2Msr.Qword); +} + diff --git a/ChvRefCodePkg/CherryViewSoc/CPU/PowerManagement/Library/Silvermont/Smm/SilvermontPpmLib.h b/ChvRefCodePkg/CherryViewSoc/CPU/PowerManagement/Library/Silvermont/Smm/SilvermontPpmLib.h new file mode 100644 index 0000000000..f351133872 --- /dev/null +++ b/ChvRefCodePkg/CherryViewSoc/CPU/PowerManagement/Library/Silvermont/Smm/SilvermontPpmLib.h @@ -0,0 +1,350 @@ +/** @file + This library contains power management configuration functions specific to + Cherryview processors. + + Acronyms: + PPM Processor Power Management + GV Geyserville + TM Thermal Monitor + IST Intel(R) Speedstep technology + HT Hyper-Threading Technology + CMP Core Multi-Processing + + Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _SILVERMONT_PPM_LIB_H_ +#define _SILVERMONT_PPM_LIB_H_ + +// +// Include files +// +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + UINT32 RegEax; + UINT32 RegEbx; + UINT32 RegEcx; + UINT32 RegEdx; +} EFI_CPUID_REGISTER; +// +// Stall period in microseconds +// +#define PPM_WAIT_PERIOD 15 + +// +// Structure Declarations +// +typedef struct _ENABLE_CSTATE_PARAMS { + PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This; + UINT16 C2IoAddress; + UINT16 CsmIoAddress; +} ENABLE_CSTATE_PARAMS; + +typedef struct _ENABLE_EMTTM_PARAMS { + PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This; + FVID_TABLE *FvidPointer; +} ENABLE_EMTTM_PARAMS; +// +// Function prototypes +// +/** + Initializes the platform power management library. This must be called + prior to any of the library functions being used. + + At this time, we don't properly publish the PPM processor support protocol, + we simply return it if this library implements the protocol. + + If the processor is not supported, the input will not be modified. + + @param[in] This Pointer to the PPM support protocol instance + + @retval EFI_SUCCESS Library was initialized successfully + @retval EFI_NOT_SUPPORTED The library does not support the current processor + +**/ +EFI_STATUS +InitializeCherryviewPowerManagementLib ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 **This + ); + +/** + Configures following fields of MSR 0x610 based on user configuration: + Configures Long duration Turbo Mode (power limit 1) power level and time window + Configures Short duration turbo mode (power limit 2) + + @param[in, out] This Pointer to the protocol instance + @param[in, out] PPMPolicy Pointer to policy protocol instance + + @retval None + +**/ +STATIC VOID EFIAPI ConfigureTurboPowerLimitsCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This, + IN OUT PPM_PLATFORM_POLICY_PROTOCOL *PPMPolicy + ); + +STATIC +EFI_STATUS +EFIAPI +SetPpmFlagsCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ); + +STATIC +EFI_STATUS +EFIAPI +EnableCStatesCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This, + IN UINT16 C2IoAddress, + IN UINT16 CsmIoAddress + ); + +VOID +EFIAPI +ApSafeEnableCStates ( + IN OUT VOID *Buffer + ); + +STATIC +EFI_STATUS +EFIAPI +InitThermalCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This, + IN OUT PPM_PLATFORM_POLICY_PROTOCOL *PPMPolicy + ); + +VOID +EFIAPI +ApSafeInitThermal ( + IN OUT VOID *Buffer + ); + +STATIC +EFI_STATUS +EFIAPI +EnableTmCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ); + +VOID +EFIAPI +ApSafeEnableTm ( + IN OUT VOID *Buffer + ); + +STATIC +EFI_STATUS +EFIAPI +EnableProcHotCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ); + +STATIC +EFI_STATUS +EFIAPI +EnableTscCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This, + IN OUT FVID_TABLE *FvidPointer, + IN UINT16 iFSBFrequency, + IN OUT UINT8 *PpmCstTmrFlags, + IN OUT UINTN *PpmTscCorrFactor, + IN OUT UINTN *PpmTscCorrFactorRem + ); + +STATIC +EFI_STATUS +EFIAPI +S3SaveMsrCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ); + +STATIC +EFI_STATUS +EFIAPI +S3RestoreMsrCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ); + +VOID +EFIAPI +ApSafeRestoreMsr ( + IN OUT VOID *Buffer + ); + +STATIC +EFI_STATUS +EFIAPI +EnableCStateIoRedirectionCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ); + +VOID +EFIAPI +ApSafeEnableCStateIoRedirection ( + IN OUT VOID *Buffer + ); + +STATIC +EFI_STATUS +EFIAPI +DisableCStateIoRedirectionCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ); + +VOID +EFIAPI +ApSafeDisableCStateIoRedirection ( + IN OUT VOID *Buffer + ); + +STATIC +EFI_STATUS +EFIAPI +EnablePStateHardwareCoordinationCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ); + +VOID +EFIAPI +ApSafeEnablePStateHardwareCoordination ( + IN OUT VOID *Buffer + ); + +STATIC +EFI_STATUS +EFIAPI +DisablePStateHardwareCoordinationCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ); + +VOID +EFIAPI +ApSafeDisablePStateHardwareCoordination ( + IN OUT VOID *Buffer + ); + +STATIC +EFI_STATUS +InitFvidTableCherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This, + IN OUT FVID_TABLE *FvidPointer, + IN UINT16 MaxNumberOfStates, + IN UINT16 MinStepSize, + IN BOOLEAN CreateDefaultTable + ); + +VOID +EFIAPI +ApSafeEnableTurboMode ( + IN OUT VOID *Buffer + ); + +STATIC +EFI_STATUS +CreateFvidTable ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This, + IN OUT FVID_TABLE *FvidPointer, + IN UINT16 MaxNumberOfStates, + IN UINT16 MinStepSize + ); + +STATIC +VOID +CreateDefaultFvidTable ( + IN OUT FVID_TABLE *FvidPointer + ); + +STATIC +EFI_STATUS +EFIAPI +InitGv3Cherryview ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This, + IN OUT FVID_TABLE *FvidPointer, + IN OUT PPM_PLATFORM_POLICY_PROTOCOL *PPMPolicy + ); + +VOID +EFIAPI +ApSafeEnableGv3 ( + IN OUT VOID *Buffer + ); + +/** + Lock MSR_PM_CFG_CTRL + This function must be MP safe. + + @param[in] Buffer Not used (needed for API compatibility) + + @retval EFI_SUCCESS Processor C-State locked successfully. + +**/ +VOID +EFIAPI +ApSafeLockDown ( + IN OUT VOID *Buffer + ); + +/** + Runs the specified procedure on all logical processors, passing in the + parameter buffer to the procedure. + + @param[in] Procedure The function to be run. + @param[in] Buffer Pointer to a parameter buffer. + + @retval EFI_SUCCESS + +**/ +STATIC +EFI_STATUS +RunOnAllLogicalProcessors ( + IN OUT EFI_AP_PROCEDURE Procedure, + IN OUT VOID *Buffer + ); + +/** + Set processor P state to HFM or LFM + + @param[in] This Pointer to the protocol instance + + @retval EFI_UNSUPPORTED EIST not supported. + @retval EFI_SUCCESS Processor P state has been set. + +**/ +STATIC +EFI_STATUS +EFIAPI +SetBootPState ( + IN OUT PPM_PROCESSOR_SUPPORT_PROTOCOL_2 *This + ); + +/** + Set processor P state to HFM or LFM. + + @param[in] Buffer Unused + + @retval EFI_SUCCESS Processor MSR setting is saved. + +**/ +VOID +EFIAPI +ApSafeSetBootPState ( + IN OUT VOID *Buffer + ); +#endif diff --git a/ChvRefCodePkg/CherryViewSoc/CPU/PowerManagement/Library/Silvermont/Smm/SilvermontPpmLib.inf b/ChvRefCodePkg/CherryViewSoc/CPU/PowerManagement/Library/Silvermont/Smm/SilvermontPpmLib.inf new file mode 100644 index 0000000000..e6e3e35f5e --- /dev/null +++ b/ChvRefCodePkg/CherryViewSoc/CPU/PowerManagement/Library/Silvermont/Smm/SilvermontPpmLib.inf @@ -0,0 +1,32 @@ +## @file +# Intel(R) Atom(TM) x5 Processor Series Power Management Library +# +# Provides library services of silvermont processsor power management. +# +# Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SilvermontPpmLib2 + FILE_GUID = 710B8CFF-42A5-40c2-A838-4E036E740D5F + MODULE_TYPE = DXE_SMM_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = SilvermontPpmLib + +[sources.common] + SilvermontPpmLib.c + SilvermontPpmLib.h + +[Packages] + MdePkg/MdePkg.dec + ChvRefCodePkg/ChvRefCodePkg.dec -- cgit v1.2.3