[coreboot-gerrit] New patch to review for coreboot: 82d6326 haswell: configure c-states

Stefan Reinauer (stefan.reinauer@coreboot.org) gerrit at coreboot.org
Mon Nov 18 23:04:31 CET 2013


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

-gerrit

commit 82d63269d3aa315251bc4ead223c06333ec279b1
Author: Aaron Durbin <adurbin at chromium.org>
Date:   Wed Apr 10 14:46:25 2013 -0500

    haswell: configure c-states
    
    The c-states are configured according to the BWG, however the
    package c-states are disabled as they currently cause platform
    instability. The exposed ACPI c-state to processor c-state mapping
    are as follows for ULT boards:
    	ACPI(C1) = MWAIT(C1E)
    	ACPI(C2) = MWAIT(C7S long latency)
    	ACPI(C3) = MWAIT(C10)
    The non-ULT boards have an expoed c-state mapping:
    	ACPI(C1) = MWAIT(C1E)
    	ACPI(C2) = MWAIT(C3)
    	ACPI(C3) = MWAIT(C7S)
    
    Included in this patch is removing the updating of current limit
    registers as some of the MSRs are different and the proper values
    are currently unknown. Lastly, some of the MSRs were renamed to
    match the BWG.
    
    Booted 3.8 kernel and used powertop to note package, core, and acpi
    c-state residency.
    
    Change-Id: Ia428d4a4979ba3cba44eb9faa96f74b7d3f22dfe
    Signed-off-by: Aaron Durbin <adurbin at chromium.org>
    Reviewed-on: https://gerrit.chromium.org/gerrit/48291
    Commit-Queue: Stefan Reinauer <reinauer at google.com>
    Tested-by: Stefan Reinauer <reinauer at google.com>
---
 src/cpu/intel/haswell/haswell.h                |  14 +-
 src/cpu/intel/haswell/haswell_init.c           | 249 +++++++++++++++----------
 src/mainboard/intel/baskingridge/devicetree.cb |  12 +-
 src/mainboard/intel/wtm2/devicetree.cb         |  12 +-
 4 files changed, 168 insertions(+), 119 deletions(-)

diff --git a/src/cpu/intel/haswell/haswell.h b/src/cpu/intel/haswell/haswell.h
index ac082b8..ab1cef4 100644
--- a/src/cpu/intel/haswell/haswell.h
+++ b/src/cpu/intel/haswell/haswell.h
@@ -59,9 +59,12 @@
 #define MSR_TURBO_RATIO_LIMIT		0x1ad
 #define MSR_POWER_CTL			0x1fc
 
-#define MSR_PKGC3_IRTL			0x60a
-#define MSR_PKGC6_IRTL			0x60b
-#define MSR_PKGC7_IRTL			0x60c
+#define MSR_C_STATE_LATENCY_CONTROL_0	0x60a
+#define MSR_C_STATE_LATENCY_CONTROL_1	0x60b
+#define MSR_C_STATE_LATENCY_CONTROL_2	0x60c
+#define MSR_C_STATE_LATENCY_CONTROL_3	0x633
+#define MSR_C_STATE_LATENCY_CONTROL_4	0x634
+#define MSR_C_STATE_LATENCY_CONTROL_5	0x635
 #define  IRTL_VALID			(1 << 15)
 #define  IRTL_1_NS			(0 << 10)
 #define  IRTL_32_NS			(1 << 10)
@@ -79,12 +82,7 @@
 #define  PKG_POWER_LIMIT_TIME_SHIFT	17
 #define  PKG_POWER_LIMIT_TIME_MASK	0x7f
 
-#define MSR_PP0_CURRENT_CONFIG		0x601
 #define MSR_VR_CURRENT_CONFIG		0x601
-#define  PP0_CURRENT_LIMIT		(112 << 3) /* 112 A */
-#define MSR_PP1_CURRENT_CONFIG		0x602
-#define  PP1_CURRENT_LIMIT_SNB		(35 << 3) /* 35 A */
-#define  PP1_CURRENT_LIMIT_IVB		(50 << 3) /* 50 A */
 #define MSR_PKG_POWER_SKU_UNIT		0x606
 #define MSR_PKG_POWER_SKU		0x614
 #define MSR_PP0_POWER_LIMIT		0x638
diff --git a/src/cpu/intel/haswell/haswell_init.c b/src/cpu/intel/haswell/haswell_init.c
index 85f6afd..5b53afe 100644
--- a/src/cpu/intel/haswell/haswell_init.c
+++ b/src/cpu/intel/haswell/haswell_init.c
@@ -35,87 +35,118 @@
 #include <cpu/x86/cache.h>
 #include <cpu/x86/name.h>
 #include <pc80/mc146818rtc.h>
+#include <northbridge/intel/haswell/haswell.h>
+#include <southbridge/intel/lynxpoint/pch.h>
 #include "haswell.h"
 #include "chip.h"
 
+/* Intel suggested latency times in units of 1024ns. */
+#define C_STATE_LATENCY_CONTROL_0_LIMIT 0x42
+#define C_STATE_LATENCY_CONTROL_1_LIMIT 0x73
+#define C_STATE_LATENCY_CONTROL_2_LIMIT 0x91
+#define C_STATE_LATENCY_CONTROL_3_LIMIT 0xe4
+#define C_STATE_LATENCY_CONTROL_4_LIMIT 0x145
+#define C_STATE_LATENCY_CONTROL_5_LIMIT 0x1ef
+
+#define C_STATE_LATENCY_MICRO_SECONDS(limit, base) \
+	(((1 << ((base)*5)) * (limit)) / 1000)
+#define C_STATE_LATENCY_FROM_LAT_REG(reg) \
+	C_STATE_LATENCY_MICRO_SECONDS(C_STATE_LATENCY_CONTROL_ ##reg## _LIMIT, \
+	                              (IRTL_1024_NS >> 10))
+
 /*
- * List of supported C-states in this processor
- *
- * Latencies are typical worst-case package exit time in uS
- * taken from the SandyBridge BIOS specification.
+ * List of supported C-states in this processor. Only the ULT parts support C8,
+ * C9, and C10.
  */
-#if 0
-static acpi_cstate_t cstate_map[] = {
-	{	/* 0: C0 */
-	},{	/* 1: C1 */
-		.latency = 1,
+enum {
+	C_STATE_C0,             /* 0 */
+	C_STATE_C1,             /* 1 */
+	C_STATE_C1E,            /* 2 */
+	C_STATE_C3,             /* 3 */
+	C_STATE_C6_SHORT_LAT,   /* 4 */
+	C_STATE_C6_LONG_LAT,    /* 5 */
+	C_STATE_C7_SHORT_LAT,   /* 6 */
+	C_STATE_C7_LONG_LAT,    /* 7 */
+	C_STATE_C7S_SHORT_LAT,  /* 8 */
+	C_STATE_C7S_LONG_LAT,   /* 9 */
+	C_STATE_C8,             /* 10 */
+	C_STATE_C9,             /* 11 */
+	C_STATE_C10,            /* 12 */
+	NUM_C_STATES
+};
+
+#define MWAIT_RES(state, sub_state)                         \
+	{                                                   \
+		.addrl = (((state) << 4) | (sub_state)),    \
+		.space_id = ACPI_ADDRESS_SPACE_FIXED,       \
+		.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,    \
+		.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,    \
+		.access_size = ACPI_FFIXEDHW_FLAG_HW_COORD, \
+	}
+
+static acpi_cstate_t cstate_map[NUM_C_STATES] = {
+	[C_STATE_C0] = { },
+	[C_STATE_C1] = {
+		.latency = 0,
 		.power = 1000,
-		.resource = {
-			.addrl = 0x00,	/* MWAIT State 0 */
-			.space_id = ACPI_ADDRESS_SPACE_FIXED,
-			.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
-			.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
-			.resv = ACPI_FFIXEDHW_FLAG_HW_COORD,
-		}
+		.resource = MWAIT_RES(0,0),
 	},
-	{	/* 2: C1E */
-		.latency = 1,
+	[C_STATE_C1E] = {
+		.latency = 0,
 		.power = 1000,
-		.resource = {
-			.addrl = 0x01,	/* MWAIT State 0 Sub-state 1 */
-			.space_id = ACPI_ADDRESS_SPACE_FIXED,
-			.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
-			.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
-			.resv = ACPI_FFIXEDHW_FLAG_HW_COORD,
-		}
+		.resource = MWAIT_RES(0,1),
 	},
-	{	/* 3: C3 */
-		.latency = 63,
-		.power = 500,
-		.resource = {
-			.addrl = 0x10,	/* MWAIT State 1 */
-			.space_id = ACPI_ADDRESS_SPACE_FIXED,
-			.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
-			.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
-			.resv = ACPI_FFIXEDHW_FLAG_HW_COORD,
-		}
+	[C_STATE_C3] = {
+		.latency = C_STATE_LATENCY_FROM_LAT_REG(0),
+		.power = 900,
+		.resource = MWAIT_RES(1, 0),
+	},
+	[C_STATE_C6_SHORT_LAT] = {
+		.latency = C_STATE_LATENCY_FROM_LAT_REG(1),
+		.power = 800,
+		.resource = MWAIT_RES(2, 0),
+	},
+	[C_STATE_C6_LONG_LAT] = {
+		.latency = C_STATE_LATENCY_FROM_LAT_REG(2),
+		.power = 800,
+		.resource = MWAIT_RES(2, 1),
+	},
+	[C_STATE_C7_SHORT_LAT] = {
+		.latency = C_STATE_LATENCY_FROM_LAT_REG(1),
+		.power = 700,
+		.resource = MWAIT_RES(3, 0),
 	},
-	{	/* 4: C6 */
-		.latency = 87,
-		.power = 350,
-		.resource = {
-			.addrl = 0x20,	/* MWAIT State 2 */
-			.space_id = ACPI_ADDRESS_SPACE_FIXED,
-			.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
-			.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
-			.resv = ACPI_FFIXEDHW_FLAG_HW_COORD,
-		}
+	[C_STATE_C7_LONG_LAT] = {
+		.latency = C_STATE_LATENCY_FROM_LAT_REG(2),
+		.power = 700,
+		.resource = MWAIT_RES(3, 1),
 	},
-	{	/* 5: C7 */
-		.latency = 90,
-		.power = 200,
-		.resource = {
-			.addrl = 0x30,	/* MWAIT State 3 */
-			.space_id = ACPI_ADDRESS_SPACE_FIXED,
-			.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
-			.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
-			.resv = ACPI_FFIXEDHW_FLAG_HW_COORD,
-		}
+	[C_STATE_C7S_SHORT_LAT] = {
+		.latency = C_STATE_LATENCY_FROM_LAT_REG(1),
+		.power = 700,
+		.resource = MWAIT_RES(3, 2),
 	},
-	{	/* 6: C7S */
-		.latency = 90,
-		.power = 200,
-		.resource = {
-			.addrl = 0x31,	/* MWAIT State 3 Sub-state 1 */
-			.space_id = ACPI_ADDRESS_SPACE_FIXED,
-			.bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
-			.bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
-			.resv = ACPI_FFIXEDHW_FLAG_HW_COORD,
-		}
+	[C_STATE_C7S_LONG_LAT] = {
+		.latency = C_STATE_LATENCY_FROM_LAT_REG(2),
+		.power = 700,
+		.resource = MWAIT_RES(3, 3),
+	},
+	[C_STATE_C8] = {
+		.latency = C_STATE_LATENCY_FROM_LAT_REG(3),
+		.power = 600,
+		.resource = MWAIT_RES(4, 0),
+	},
+	[C_STATE_C9] = {
+		.latency = C_STATE_LATENCY_FROM_LAT_REG(4),
+		.power = 500,
+		.resource = MWAIT_RES(5, 0),
+	},
+	[C_STATE_C10] = {
+		.latency = C_STATE_LATENCY_FROM_LAT_REG(5),
+		.power = 400,
+		.resource = MWAIT_RES(6, 0),
 	},
-	{ 0 }
 };
-#endif
 
 /* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */
 static const u8 power_limit_time_sec_to_msr[] = {
@@ -175,6 +206,17 @@ static const u8 power_limit_time_msr_to_sec[] = {
 	[0x11] = 128,
 };
 
+/* Dynamically determine if the part is ULT. */
+static int is_ult(void)
+{
+	static int ult = -1;
+
+	if (ult < 0)
+		ult = (cpuid_eax(1) > 0x40650);
+
+	return ult;
+}
+
 int cpu_config_tdp_levels(void)
 {
 	msr_t platform_info;
@@ -250,24 +292,28 @@ void set_power_limits(u8 power_limit_1_time)
 	}
 }
 
-#if 0
 static void configure_c_states(void)
 {
 	msr_t msr;
 
 	msr = rdmsr(MSR_PMG_CST_CONFIG_CONTROL);
+	msr.lo |= (1 << 30);	// Package c-state Undemotion Enable
+	msr.lo |= (1 << 29);	// Package c-state Demotion Enable
 	msr.lo |= (1 << 28);	// C1 Auto Undemotion Enable
 	msr.lo |= (1 << 27);	// C3 Auto Undemotion Enable
 	msr.lo |= (1 << 26);	// C1 Auto Demotion Enable
 	msr.lo |= (1 << 25);	// C3 Auto Demotion Enable
 	msr.lo &= ~(1 << 10);	// Disable IO MWAIT redirection
-	msr.lo |= 7;		// No package C-state limit
+	msr.lo &= ~(0xf);	// Clear deepest package c-state
+	/* FIXME: The deepest package c-state is set to C0/C1 to work around
+	 * platform instability when package C3 or deeper c-states are used. */
+	msr.lo |= 0;		// Deepeset package c-state is C0/C1.
 	wrmsr(MSR_PMG_CST_CONFIG_CONTROL, msr);
 
 	msr = rdmsr(MSR_PMG_IO_CAPTURE_BASE);
-	msr.lo &= ~0x7ffff;
-	msr.lo |= (get_pmbase() + 4);	// LVL_2 base address
-	msr.lo |= (2 << 16);		// CST Range: C7 is max C-state
+	msr.lo &= ~0xffff;
+	msr.lo |= (get_pmbase() + 0x14);	// LVL_2 base address
+	/* The deepest package c-state defaults to factory-configured value. */
 	wrmsr(MSR_PMG_IO_CAPTURE_BASE, msr);
 
 	msr = rdmsr(MSR_MISC_PWR_MGMT);
@@ -280,37 +326,42 @@ static void configure_c_states(void)
 	msr.lo |= (1 << 0);	// Bi-directional PROCHOT#
 	wrmsr(MSR_POWER_CTL, msr);
 
-	/* C3 Interrupt Response Time Limit */
+	/* C-state Interrupt Response Latency Control 0 - package C3 latency */
 	msr.hi = 0;
-	msr.lo = IRTL_VALID | IRTL_1024_NS | 0x50;
-	wrmsr(MSR_PKGC3_IRTL, msr);
+	msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_0_LIMIT;
+	wrmsr(MSR_C_STATE_LATENCY_CONTROL_0, msr);
 
-	/* C6 Interrupt Response Time Limit */
+	/* C-state Interrupt Response Latency Control 1 */
 	msr.hi = 0;
-	msr.lo = IRTL_VALID | IRTL_1024_NS | 0x68;
-	wrmsr(MSR_PKGC6_IRTL, msr);
+	msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_1_LIMIT;
+	wrmsr(MSR_C_STATE_LATENCY_CONTROL_1, msr);
 
-	/* C7 Interrupt Response Time Limit */
+	/* C-state Interrupt Response Latency Control 2 - package C6/C7 short */
 	msr.hi = 0;
-	msr.lo = IRTL_VALID | IRTL_1024_NS | 0x6D;
-	wrmsr(MSR_PKGC7_IRTL, msr);
-
-	/* Primary Plane Current Limit */
-	msr = rdmsr(MSR_PP0_CURRENT_CONFIG);
-	msr.lo &= ~0x1fff;
-	msr.lo |= PP0_CURRENT_LIMIT;
-	wrmsr(MSR_PP0_CURRENT_CONFIG, msr);
-
-	/* Secondary Plane Current Limit */
-	msr = rdmsr(MSR_PP1_CURRENT_CONFIG);
-	msr.lo &= ~0x1fff;
-	if (cpuid_eax(1) >= 0x30600)
-		msr.lo |= PP1_CURRENT_LIMIT_IVB;
-	else
-		msr.lo |= PP1_CURRENT_LIMIT_SNB;
-	wrmsr(MSR_PP1_CURRENT_CONFIG, msr);
+	msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_2_LIMIT;
+	wrmsr(MSR_C_STATE_LATENCY_CONTROL_2, msr);
+
+	/* Haswell ULT only supoprts the 3-5 latency response registers.*/
+	if (is_ult()) {
+		/* C-state Interrupt Response Latency Control 3 - package C8 */
+		msr.hi = 0;
+		msr.lo = IRTL_VALID | IRTL_1024_NS |
+		         C_STATE_LATENCY_CONTROL_3_LIMIT;
+		wrmsr(MSR_C_STATE_LATENCY_CONTROL_3, msr);
+
+		/* C-state Interrupt Response Latency Control 4 - package C9 */
+		msr.hi = 0;
+		msr.lo = IRTL_VALID | IRTL_1024_NS |
+		         C_STATE_LATENCY_CONTROL_4_LIMIT;
+		wrmsr(MSR_C_STATE_LATENCY_CONTROL_4, msr);
+
+		/* C-state Interrupt Response Latency Control 5 - package C10 */
+		msr.hi = 0;
+		msr.lo = IRTL_VALID | IRTL_1024_NS |
+		         C_STATE_LATENCY_CONTROL_5_LIMIT;
+		wrmsr(MSR_C_STATE_LATENCY_CONTROL_5, msr);
+	}
 }
-#endif
 
 static void configure_thermal_target(void)
 {
@@ -481,7 +532,7 @@ static void haswell_init(device_t cpu)
 	setup_lapic();
 
 	/* Configure C States */
-	//configure_c_states();
+	configure_c_states();
 
 	/* Configure Enhanced SpeedStep and Thermal Sensors */
 	configure_misc();
@@ -555,6 +606,6 @@ static struct cpu_device_id cpu_table[] = {
 static const struct cpu_driver driver __cpu_driver = {
 	.ops      = &cpu_dev_ops,
 	.id_table = cpu_table,
-	/* .cstates  = cstate_map, */
+	.cstates  = cstate_map,
 };
 
diff --git a/src/mainboard/intel/baskingridge/devicetree.cb b/src/mainboard/intel/baskingridge/devicetree.cb
index fa3f3e7..a173aaa 100644
--- a/src/mainboard/intel/baskingridge/devicetree.cb
+++ b/src/mainboard/intel/baskingridge/devicetree.cb
@@ -17,13 +17,13 @@ chip northbridge/intel/haswell
 			# Magic APIC ID to locate this chip
 			device lapic 0xACAC off end
 
-			register "c1_battery" = "3"	# ACPI(C1) = MWAIT(C3)
-			register "c2_battery" = "4"	# ACPI(C2) = MWAIT(C6)
-			register "c3_battery" = "5"	# ACPI(C3) = MWAIT(C7)
+			register "c1_battery" = "2"	# ACPI(C1) = MWAIT(C1E)
+			register "c2_battery" = "3"	# ACPI(C2) = MWAIT(C3)
+			register "c3_battery" = "9"	# ACPI(C3) = MWAIT(C7S)
 
-			register "c1_acpower" = "3"	# ACPI(C1) = MWAIT(C3)
-			register "c2_acpower" = "4"	# ACPI(C2) = MWAIT(C6)
-			register "c3_acpower" = "5"	# ACPI(C3) = MWAIT(C7)
+			register "c1_acpower" = "2"	# ACPI(C1) = MWAIT(C1E)
+			register "c2_acpower" = "3"	# ACPI(C2) = MWAIT(C3)
+			register "c3_acpower" = "9"	# ACPI(C3) = MWAIT(C7S)
 		end
 	end
 
diff --git a/src/mainboard/intel/wtm2/devicetree.cb b/src/mainboard/intel/wtm2/devicetree.cb
index 5e1ca3a..3193369 100644
--- a/src/mainboard/intel/wtm2/devicetree.cb
+++ b/src/mainboard/intel/wtm2/devicetree.cb
@@ -17,13 +17,13 @@ chip northbridge/intel/haswell
 			# Magic APIC ID to locate this chip
 			device lapic 0xACAC off end
 
-			register "c1_battery" = "3"	# ACPI(C1) = MWAIT(C3)
-			register "c2_battery" = "4"	# ACPI(C2) = MWAIT(C6)
-			register "c3_battery" = "5"	# ACPI(C3) = MWAIT(C7)
+			register "c1_battery" = "2"	# ACPI(C1) = MWAIT(C1E)
+			register "c2_battery" = "9"	# ACPI(C2) = MWAIT(C7S)
+			register "c3_battery" = "12"	# ACPI(C3) = MWAIT(C10)
 
-			register "c1_acpower" = "3"	# ACPI(C1) = MWAIT(C3)
-			register "c2_acpower" = "4"	# ACPI(C2) = MWAIT(C6)
-			register "c3_acpower" = "5"	# ACPI(C3) = MWAIT(C7)
+			register "c1_acpower" = "2"	# ACPI(C1) = MWAIT(C1E)
+			register "c2_acpower" = "9"	# ACPI(C2) = MWAIT(C7S)
+			register "c3_acpower" = "12"	# ACPI(C3) = MWAIT(C10)
 		end
 	end
 



More information about the coreboot-gerrit mailing list