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>
This commit is contained in:
Aaron Durbin 2013-04-10 14:46:25 -05:00 committed by Alexandru Gagniuc
parent 15de7cb422
commit 7c35131642
4 changed files with 174 additions and 125 deletions

View File

@ -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

View File

@ -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,
.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,
}
},
{ /* 2: C1E */
.latency = 1,
.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,
}
},
{ /* 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,
}
},
{ /* 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,
}
},
{ /* 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,
}
},
{ /* 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,
}
},
{ 0 }
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 = MWAIT_RES(0,0),
},
[C_STATE_C1E] = {
.latency = 0,
.power = 1000,
.resource = MWAIT_RES(0,1),
},
[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),
},
[C_STATE_C7_LONG_LAT] = {
.latency = C_STATE_LATENCY_FROM_LAT_REG(2),
.power = 700,
.resource = MWAIT_RES(3, 1),
},
[C_STATE_C7S_SHORT_LAT] = {
.latency = C_STATE_LATENCY_FROM_LAT_REG(1),
.power = 700,
.resource = MWAIT_RES(3, 2),
},
[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),
},
};
#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);
msr.lo = IRTL_VALID | IRTL_1024_NS | C_STATE_LATENCY_CONTROL_2_LIMIT;
wrmsr(MSR_C_STATE_LATENCY_CONTROL_2, 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);
/* 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);
/* 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);
/* 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,
};

View File

@ -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

View File

@ -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