[coreboot] New patch to review for coreboot: 364dbdd CPU: Add basic support for Nominal Configurable TDP

Stefan Reinauer (stefan.reinauer@coreboot.org) gerrit at coreboot.org
Tue Jul 24 00:12:30 CEST 2012


Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1304

-gerrit

commit 364dbdd0177ff1fb5bbf398217fcae01ef296d1e
Author: Duncan Laurie <dlaurie at chromium.org>
Date:   Mon Jun 25 09:51:59 2012 -0700

    CPU: Add basic support for Nominal Configurable TDP
    
    Ivybridge B0+ CPUs are capable of supporting multiple TDP levels.
    This complicates the default case because now the registers that
    were reporting max non-turbo ratio are reporting that value for
    the highest possible TDP level.
    
    For now this change just forces everything to use the Nominal TDP
    values instead of the higher (or lower) levels.
    
    - When building P-state tables, determine the P[1] (max non turbo)
    ratio based on the Nominal ratio if available.
    - Set the turbo activation ratio to the Nominal max ratio.
    - Mirror the power level settings in new MCHBAR register after
    they are written, which happens after BIOS_RESET_CPL is set.
    - Set the current ratio to Nominal ratio at boot.
    
    1) Verify that P-state table is generated properly with
    P[0]=1801MHz (ratio 0x1C) and P[1]=1800MHz (ratio 0x12)
    
    PSS: 1801MHz power 17000 control 0x1c00 status 0x1c00
    PSS: 1800MHz power 17000 control 0x1200 status 0x1200
    
    2) Verify power limits in MCHBAR match PKG_POWER_LIMIT:
    
    > rdmsr 0 0x610
    0x800080aa00dc8088
    > mmio_read32 0xfed159a4
    0x000080aa
    > mmio_read32 0xfed159a0
    0x00dc8088
    
    3) Verify turbo activation ratio is set to nominal ratio:
    
    > rdmsr 0 0x64c
    0x0000000000000012
    
    4) Check that proper ratio was set at boot on one core only:
    
    > grep 'frequency set to' /sys/firmware/log
    model_x06ax: frequency set to 1800
    model_x06ax: frequency set to 1800
    model_x06ax: frequency set to 1800
    model_x06ax: frequency set to 1800
    
    Change-Id: I592e60a7740f31b140986a8269dca91b4adbb270
    Signed-off-by: Duncan Laurie <dlaurie at chromium.org>
---
 src/cpu/intel/model_206ax/acpi.c                |   11 +++++-
 src/cpu/intel/model_206ax/model_206ax.h         |    8 ++++
 src/cpu/intel/model_206ax/model_206ax_init.c    |   45 +++++++++++++++++++----
 src/northbridge/intel/sandybridge/northbridge.c |   11 ++++++
 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 5d3f3a0..7b49555 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 3343d11..d482ff0 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 87bc585..0958fe3 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 2fa3504..bfb2166 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>
@@ -422,6 +423,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;
 }




More information about the coreboot mailing list