aboutsummaryrefslogtreecommitdiff
path: root/src/cpu/intel/haswell/haswell_init.c
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 /src/cpu/intel/haswell/haswell_init.c
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>
Diffstat (limited to 'src/cpu/intel/haswell/haswell_init.c')
-rw-r--r--src/cpu/intel/haswell/haswell_init.c249
1 files changed, 150 insertions, 99 deletions
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,
};