aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2013-04-10 14:46:25 -0500
committerAlexandru Gagniuc <mr.nuke.me@gmail.com>2013-11-24 16:01:38 +0100
commit7c351316429f8b991df7ea233a5528f4efb3b8e0 (patch)
tree499507d3d5f20c6b334653dd01c5e1a7c6313566
parent15de7cb4224b6add9a65d083e9a2e8484ae511b8 (diff)
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@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/48291 Commit-Queue: Stefan Reinauer <reinauer@google.com> Tested-by: Stefan Reinauer <reinauer@google.com> Reviewed-on: http://review.coreboot.org/4133 Tested-by: build bot (Jenkins) Reviewed-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
-rw-r--r--src/cpu/intel/haswell/haswell.h14
-rw-r--r--src/cpu/intel/haswell/haswell_init.c249
-rw-r--r--src/mainboard/intel/baskingridge/devicetree.cb12
-rw-r--r--src/mainboard/intel/wtm2/devicetree.cb12
4 files changed, 168 insertions, 119 deletions
diff --git a/src/cpu/intel/haswell/haswell.h b/src/cpu/intel/haswell/haswell.h
index ac082b86eb..ab1cef470c 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 85f6afd031..5b53afedf5 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 fa3f3e7773..a173aaa662 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 5e1ca3aba4..31933690bf 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