diff options
Diffstat (limited to 'src/cpu')
-rw-r--r-- | src/cpu/intel/common/common.h | 8 | ||||
-rw-r--r-- | src/cpu/intel/common/common_init.c | 180 |
2 files changed, 188 insertions, 0 deletions
diff --git a/src/cpu/intel/common/common.h b/src/cpu/intel/common/common.h index 0d0b954886..81c9f16d19 100644 --- a/src/cpu/intel/common/common.h +++ b/src/cpu/intel/common/common.h @@ -17,4 +17,12 @@ void set_vmx(void); +/* + * Init CPPC block with MSRs for Intel Enhanced Speed Step Technology. + * Version 2 is suggested--this function's implementation of version 3 + * may have room for improvment. + */ +struct cppc_config; +void cpu_init_cppc_config(struct cppc_config *config, u32 version); + #endif diff --git a/src/cpu/intel/common/common_init.c b/src/cpu/intel/common/common_init.c index 44a316b641..8dd8559d23 100644 --- a/src/cpu/intel/common/common_init.c +++ b/src/cpu/intel/common/common_init.c @@ -15,6 +15,7 @@ * GNU General Public License for more details. */ +#include <arch/acpigen.h> #include <console/console.h> #include <cpu/x86/msr.h> #include "common.h" @@ -71,3 +72,182 @@ void set_vmx(void) enable ? "enabled" : "disabled", lock ? "locked" : "unlocked"); } + +/* + * Init cppc_config in a way that's appropriate for Intel + * processors with Intel Enhanced Speed Step Technology. + * NOTE: version 2 is expected to be the typical use case. + * For now this function 'punts' on version 3 and just + * populates the additional fields with 'unsupported'. + */ +void cpu_init_cppc_config(struct cppc_config *config, u32 version) +{ + acpi_addr_t msr = { + .space_id = ACPI_ADDRESS_SPACE_FIXED, + .bit_width = 8, + .bit_offset = 0, + { + .access_size = 4 + }, + .addrl = 0, + .addrh = 0, + }; + static const acpi_addr_t unsupported = { + .space_id = ACPI_ADDRESS_SPACE_MEMORY, + .bit_width = 0, + .bit_offset = 0, + { + .resv = 0 + }, + .addrl = 0, + .addrh = 0, + }; + + config->version = version; + + msr.addrl = MSR_IA32_HWP_CAPABILITIES; + + /* + * Highest Performance: + * ResourceTemplate(){Register(FFixedHW, 0x08, 0x00, 0x771, 0x04,)}, + */ + config->regs[CPPC_HIGHEST_PERF] = msr; + + /* + * Nominal Performance -> Guaranteed Performance: + * ResourceTemplate(){Register(FFixedHW, 0x08, 0x08, 0x771, 0x04,)}, + */ + msr.bit_offset = 8; + config->regs[CPPC_NOMINAL_PERF] = msr; + + /* + * Lowest Nonlinear Performance -> Most Efficient Performance: + * ResourceTemplate(){Register(FFixedHW, 0x08, 0x10, 0x771, 0x04,)}, + */ + msr.bit_offset = 16; + config->regs[CPPC_LOWEST_NONL_PERF] = msr; + + /* + * Lowest Performance: + * ResourceTemplate(){Register(FFixedHW, 0x08, 0x18, 0x771, 0x04,)}, + */ + msr.bit_offset = 24; + config->regs[CPPC_LOWEST_PERF] = msr; + + /* + * Guaranteed Performance Register: + * ResourceTemplate(){Register(FFixedHW, 0x08, 0x08, 0x771, 0x04,)}, + */ + msr.bit_offset = 8; + config->regs[CPPC_GUARANTEED_PERF] = msr; + + msr.addrl = MSR_IA32_HWP_REQUEST; + + /* + * Desired Performance Register: + * ResourceTemplate(){Register(FFixedHW, 0x08, 0x10, 0x774, 0x04,)}, + */ + msr.bit_offset = 16; + config->regs[CPPC_DESIRED_PERF] = msr; + + /* + * Minimum Performance Register: + * ResourceTemplate(){Register(FFixedHW, 0x08, 0x00, 0x774, 0x04,)}, + */ + msr.bit_offset = 0; + config->regs[CPPC_MIN_PERF] = msr; + + /* + * Maximum Performance Register: + * ResourceTemplate(){Register(FFixedHW, 0x08, 0x08, 0x774, 0x04,)}, + */ + msr.bit_offset = 8; + config->regs[CPPC_MAX_PERF] = msr; + + /* + * Performance Reduction Tolerance Register: + * ResourceTemplate(){Register(SystemMemory, 0x00, 0x00, 0x0,,)}, + */ + config->regs[CPPC_PERF_REDUCE_TOLERANCE] = unsupported; + + /* + * Time Window Register: + * ResourceTemplate(){Register(SystemMemory, 0x00, 0x00, 0x0,,)}, + */ + config->regs[CPPC_TIME_WINDOW] = unsupported; + + /* + * Counter Wraparound Time: + * ResourceTemplate(){Register(SystemMemory, 0x00, 0x00, 0x0,,)}, + */ + config->regs[CPPC_COUNTER_WRAP] = unsupported; + + msr.addrl = MSR_IA32_MPERF; + + /* + * Reference Performance Counter Register: + * ResourceTemplate(){Register(FFixedHW, 0x40, 0x00, 0x0E7, 0x04,)}, + */ + msr.bit_width = 64; + msr.bit_offset = 0; + config->regs[CPPC_REF_PERF_COUNTER] = msr; + + msr.addrl = MSR_IA32_APERF; + + /* + * Delivered Performance Counter Register: + * ResourceTemplate(){Register(FFixedHW, 0x40, 0x00, 0x0E8, 0x04,)}, + */ + config->regs[CPPC_DELIVERED_PERF_COUNTER] = msr; + + msr.addrl = MSR_IA32_HWP_STATUS; + + /* + * Performance Limited Register: + * ResourceTemplate(){Register(FFixedHW, 0x01, 0x02, 0x777, 0x04,)}, + */ + msr.bit_width = 1; + msr.bit_offset = 2; + config->regs[CPPC_PERF_LIMITED] = msr; + + msr.addrl = MSR_IA32_PM_ENABLE; + + /* + * CPPC Enable Register: + * ResourceTemplate(){Register(FFixedHW, 0x01, 0x00, 0x770, 0x04,)}, + */ + msr.bit_offset = 0; + config->regs[CPPC_ENABLE] = msr; + + if (version >= 2) { + /* Autonomous Selection Enable is populated below */ + + /* Autonomous Activity Window Register */ + config->regs[CPPC_AUTO_ACTIVITY_WINDOW] = unsupported; + + /* Energy Performance Preference Register */ + config->regs[CPPC_PERF_PREF] = unsupported; + + /* Reference Performance */ + config->regs[CPPC_REF_PERF] = unsupported; + + if (version >= 3) { + /* Lowest Frequency */ + config->regs[CPPC_LOWEST_FREQ] = unsupported; + /* Nominal Frequency */ + config->regs[CPPC_NOMINAL_FREQ] = unsupported; + } + + /* + * Autonomous Selection Enable = 1 + * This field is actually the first addition in version 2 but + * it's so unlike the others I'm populating it last. + */ + msr.space_id = ACPI_ADDRESS_SPACE_MEMORY; + msr.bit_width = 32; + msr.bit_offset = 0; + msr.access_size = 0; + msr.addrl = 1; + config->regs[CPPC_AUTO_SELECT] = msr; + } +} |