aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cpu/intel/model_206ax/acpi.c11
-rw-r--r--src/cpu/intel/model_206ax/model_206ax.h8
-rw-r--r--src/cpu/intel/model_206ax/model_206ax_init.c45
-rw-r--r--src/northbridge/intel/sandybridge/northbridge.c11
4 files changed, 66 insertions, 9 deletions
diff --git a/src/cpu/intel/model_206ax/acpi.c b/src/cpu/intel/model_206ax/acpi.c
index 5d3f3a02bb..7b495558d4 100644
--- a/src/cpu/intel/model_206ax/acpi.c
+++ b/src/cpu/intel/model_206ax/acpi.c
@@ -229,7 +229,16 @@ static int generate_P_state_entries(int core, int cores_per_package)
/* Get bus ratio limits and calculate clock speeds */
msr = rdmsr(MSR_PLATFORM_INFO);
ratio_min = (msr.hi >> (40-32)) & 0xff; /* Max Efficiency Ratio */
- ratio_max = (msr.lo >> 8) & 0xff; /* Max Non-Turbo Ratio */
+
+ /* Determine if this CPU has configurable TDP */
+ if (cpu_config_tdp_levels()) {
+ /* Set max ratio to nominal TDP ratio */
+ msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
+ ratio_max = msr.lo & 0xff;
+ } else {
+ /* Max Non-Turbo Ratio */
+ ratio_max = (msr.lo >> 8) & 0xff;
+ }
clock_max = ratio_max * SANDYBRIDGE_BCLK;
/* Calculate CPU TDP in mW */
diff --git a/src/cpu/intel/model_206ax/model_206ax.h b/src/cpu/intel/model_206ax/model_206ax.h
index 3343d1129b..d482ff0108 100644
--- a/src/cpu/intel/model_206ax/model_206ax.h
+++ b/src/cpu/intel/model_206ax/model_206ax.h
@@ -81,6 +81,13 @@
#define MSR_PP0_POWER_LIMIT 0x638
#define MSR_PP1_POWER_LIMIT 0x640
+#define IVB_CONFIG_TDP_MIN_CPUID 0x306a2
+#define MSR_CONFIG_TDP_NOMINAL 0x648
+#define MSR_CONFIG_TDP_LEVEL1 0x649
+#define MSR_CONFIG_TDP_LEVEL2 0x64a
+#define MSR_CONFIG_TDP_CONTROL 0x64b
+#define MSR_TURBO_ACTIVATION_RATIO 0x64c
+
/* P-state configuration */
#define PSS_MAX_ENTRIES 8
#define PSS_RATIO_STEP 2
@@ -93,6 +100,7 @@ void intel_model_206ax_finalize_smm(void);
#else
/* Configure power limits for turbo mode */
void set_power_limits(u8 power_limit_1_time);
+int cpu_config_tdp_levels(void);
#endif
#endif
diff --git a/src/cpu/intel/model_206ax/model_206ax_init.c b/src/cpu/intel/model_206ax/model_206ax_init.c
index 87bc585d86..0958fe366e 100644
--- a/src/cpu/intel/model_206ax/model_206ax_init.c
+++ b/src/cpu/intel/model_206ax/model_206ax_init.c
@@ -179,6 +179,19 @@ static const u8 power_limit_time_msr_to_sec[] = {
[0x11] = 128,
};
+int cpu_config_tdp_levels(void)
+{
+ msr_t platform_info;
+
+ /* Minimum CPU revision */
+ if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID)
+ return 0;
+
+ /* Bits 34:33 indicate how many levels supported */
+ platform_info = rdmsr(MSR_PLATFORM_INFO);
+ return (platform_info.hi >> 1) & 3;
+}
+
/*
* Configure processor power limits if possible
* This must be done AFTER set of BIOS_RESET_CPL
@@ -235,6 +248,14 @@ void set_power_limits(u8 power_limit_1_time)
/* Power limit 2 time is only programmable on SNB EP/EX */
wrmsr(MSR_PKG_POWER_LIMIT, limit);
+
+ /* Use nominal TDP values for CPUs with configurable TDP */
+ if (cpu_config_tdp_levels()) {
+ msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
+ limit.hi = 0;
+ limit.lo = msr.lo & 0xff;
+ wrmsr(MSR_TURBO_ACTIVATION_RATIO, limit);
+ }
}
static void configure_c_states(void)
@@ -340,16 +361,24 @@ static void configure_dca_cap(void)
static void set_max_ratio(void)
{
- msr_t msr;
-
- /* Platform Info bits 15:8 give max ratio */
- msr = rdmsr(MSR_PLATFORM_INFO);
- msr.hi = 0;
- msr.lo &= 0xff00;
- wrmsr(IA32_PERF_CTL, msr);
+ msr_t msr, perf_ctl;
+
+ perf_ctl.hi = 0;
+
+ /* Check for configurable TDP option */
+ if (cpu_config_tdp_levels()) {
+ /* Set to nominal TDP ratio */
+ msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
+ perf_ctl.lo = (msr.lo & 0xff) << 8;
+ } else {
+ /* Platform Info bits 15:8 give max ratio */
+ msr = rdmsr(MSR_PLATFORM_INFO);
+ perf_ctl.lo = msr.lo & 0xff00;
+ }
+ wrmsr(IA32_PERF_CTL, perf_ctl);
printk(BIOS_DEBUG, "model_x06ax: frequency set to %d\n",
- ((msr.lo >> 8) & 0xff) * 100);
+ ((perf_ctl.lo >> 8) & 0xff) * SANDYBRIDGE_BCLK);
}
static void set_energy_perf_bias(u8 policy)
diff --git a/src/northbridge/intel/sandybridge/northbridge.c b/src/northbridge/intel/sandybridge/northbridge.c
index 756aacfbb4..baf4348f96 100644
--- a/src/northbridge/intel/sandybridge/northbridge.c
+++ b/src/northbridge/intel/sandybridge/northbridge.c
@@ -24,6 +24,7 @@
#include <stdint.h>
#include <delay.h>
#include <cpu/intel/model_206ax/model_206ax.h>
+#include <cpu/x86/msr.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
@@ -403,6 +404,16 @@ static void northbridge_init(struct device *dev)
mdelay(1);
set_power_limits(28);
+ /*
+ * CPUs with configurable TDP also need power limits set
+ * in MCHBAR. Use same values from MSR_PKG_POWER_LIMIT.
+ */
+ if (cpu_config_tdp_levels()) {
+ msr_t msr = rdmsr(MSR_PKG_POWER_LIMIT);
+ MCHBAR32(0x59A0) = msr.lo;
+ MCHBAR32(0x59A4) = msr.hi;
+ }
+
/* Set here before graphics PM init */
MCHBAR32(0x5500) = 0x00100001;
}