haswell: Misc power management setup and fixes
1) fix enable of power aware interrupt routing 2) set BIOS_RESET_CPL to 3 instead of 1 3) mirror PKG power limit values from MSR to MMIO on all SKUs 4) mirror DDR power limit values from MMIO to MSR 5) remove DMI settings that were from snb/ivb as they do not apply to haswell 1) verify power aware interrupt routing is working by looking in /proc/interrupts to see interrupts routed to both cores instead of always to core0 BEFORE: 58: 4943 0 PCI-MSI-edge ahci AFTER: 58: 4766 334 PCI-MSI-edge ahci 2) read back BIOS_RESET_CPL to verify it is == 3 localhost ~ # iotools mmio_read32 0xfed15da8 0x00000003 3) read PKG power limit from MMIO and verify it is the same as the MSR value localhost ~ # rdmsr 0 0x610 0x0000809600dc8078 localhost ~ # iotools mmio_read32 0xfed159a0 0x00dc8078 localhost ~ # iotools mmio_read32 0xfed159a4 0x00008096 4) read DDR power limit from MSR and verify it is the same as the MMIO value (note this is zero based on current MRC input) localhost ~ # rdmsr 0 0x618 0x0000000000000000 localhost ~ # iotools mmio_read32 0xfed158e0 0x00000000 localhost ~ # iotools mmio_read32 0xfed158e4 0x00000000 Change-Id: I6cc4c5b2a81304e9deaad8cffcaf604ebad60b29 Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/60544 Reviewed-on: http://review.coreboot.org/4333 Reviewed-by: Alexandru Gagniuc <mr.nuke.me@gmail.com> Tested-by: build bot (Jenkins)
This commit is contained in:
parent
ddf68901f7
commit
c70353f1eb
|
@ -85,6 +85,7 @@
|
||||||
#define MSR_VR_CURRENT_CONFIG 0x601
|
#define MSR_VR_CURRENT_CONFIG 0x601
|
||||||
#define MSR_PKG_POWER_SKU_UNIT 0x606
|
#define MSR_PKG_POWER_SKU_UNIT 0x606
|
||||||
#define MSR_PKG_POWER_SKU 0x614
|
#define MSR_PKG_POWER_SKU 0x614
|
||||||
|
#define MSR_DDR_RAPL_LIMIT 0x618
|
||||||
#define MSR_PP0_POWER_LIMIT 0x638
|
#define MSR_PP0_POWER_LIMIT 0x638
|
||||||
#define MSR_PP1_POWER_LIMIT 0x640
|
#define MSR_PP1_POWER_LIMIT 0x640
|
||||||
|
|
||||||
|
|
|
@ -361,7 +361,7 @@ void set_power_limits(u8 power_limit_1_time)
|
||||||
u8 power_limit_1_val;
|
u8 power_limit_1_val;
|
||||||
|
|
||||||
if (power_limit_1_time > ARRAY_SIZE(power_limit_time_sec_to_msr))
|
if (power_limit_1_time > ARRAY_SIZE(power_limit_time_sec_to_msr))
|
||||||
return;
|
power_limit_1_time = 28;
|
||||||
|
|
||||||
if (!(msr.lo & PLATFORM_INFO_SET_TDP))
|
if (!(msr.lo & PLATFORM_INFO_SET_TDP))
|
||||||
return;
|
return;
|
||||||
|
@ -401,10 +401,19 @@ void set_power_limits(u8 power_limit_1_time)
|
||||||
limit.hi = 0;
|
limit.hi = 0;
|
||||||
limit.hi |= ((tdp * 125) / 100) & PKG_POWER_LIMIT_MASK;
|
limit.hi |= ((tdp * 125) / 100) & PKG_POWER_LIMIT_MASK;
|
||||||
limit.hi |= PKG_POWER_LIMIT_EN;
|
limit.hi |= PKG_POWER_LIMIT_EN;
|
||||||
/* Power limit 2 time is only programmable on SNB EP/EX */
|
/* Power limit 2 time is only programmable on server SKU */
|
||||||
|
|
||||||
wrmsr(MSR_PKG_POWER_LIMIT, limit);
|
wrmsr(MSR_PKG_POWER_LIMIT, limit);
|
||||||
|
|
||||||
|
/* Set power limit values in MCHBAR as well */
|
||||||
|
MCHBAR32(MCH_PKG_POWER_LIMIT_LO) = limit.lo;
|
||||||
|
MCHBAR32(MCH_PKG_POWER_LIMIT_HI) = limit.hi;
|
||||||
|
|
||||||
|
/* Set DDR RAPL power limit by copying from MMIO to MSR */
|
||||||
|
msr.lo = MCHBAR32(MCH_DDR_POWER_LIMIT_LO);
|
||||||
|
msr.hi = MCHBAR32(MCH_DDR_POWER_LIMIT_HI);
|
||||||
|
wrmsr(MSR_DDR_RAPL_LIMIT, msr);
|
||||||
|
|
||||||
/* Use nominal TDP values for CPUs with configurable TDP */
|
/* Use nominal TDP values for CPUs with configurable TDP */
|
||||||
if (cpu_config_tdp_levels()) {
|
if (cpu_config_tdp_levels()) {
|
||||||
msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
|
msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
|
||||||
|
|
|
@ -125,6 +125,12 @@
|
||||||
|
|
||||||
#define BIOS_RESET_CPL 0x5da8 /* 8bit */
|
#define BIOS_RESET_CPL 0x5da8 /* 8bit */
|
||||||
|
|
||||||
|
/* Some power MSRs are also represented in MCHBAR */
|
||||||
|
#define MCH_PKG_POWER_LIMIT_LO 0x59a0
|
||||||
|
#define MCH_PKG_POWER_LIMIT_HI 0x59a4
|
||||||
|
#define MCH_DDR_POWER_LIMIT_LO 0x58e0
|
||||||
|
#define MCH_DDR_POWER_LIMIT_HI 0x58e4
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* EPBAR - Egress Port Root Complex Register Block
|
* EPBAR - Egress Port Root Complex Register Block
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -436,84 +436,22 @@ static void intel_set_subsystem(device_t dev, unsigned vendor, unsigned device)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void northbridge_dmi_init(struct device *dev)
|
|
||||||
{
|
|
||||||
u32 reg32;
|
|
||||||
|
|
||||||
/* Clear error status bits */
|
|
||||||
DMIBAR32(0x1c4) = 0xffffffff;
|
|
||||||
DMIBAR32(0x1d0) = 0xffffffff;
|
|
||||||
|
|
||||||
/* Steps prior to DMI ASPM */
|
|
||||||
if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_SNB) {
|
|
||||||
reg32 = DMIBAR32(0x250);
|
|
||||||
reg32 &= ~((1 << 22)|(1 << 20));
|
|
||||||
reg32 |= (1 << 21);
|
|
||||||
DMIBAR32(0x250) = reg32;
|
|
||||||
}
|
|
||||||
|
|
||||||
reg32 = DMIBAR32(0x238);
|
|
||||||
reg32 |= (1 << 29);
|
|
||||||
DMIBAR32(0x238) = reg32;
|
|
||||||
|
|
||||||
if (bridge_silicon_revision() >= SNB_STEP_D0) {
|
|
||||||
reg32 = DMIBAR32(0x1f8);
|
|
||||||
reg32 |= (1 << 16);
|
|
||||||
DMIBAR32(0x1f8) = reg32;
|
|
||||||
} else if (bridge_silicon_revision() >= SNB_STEP_D1) {
|
|
||||||
reg32 = DMIBAR32(0x1f8);
|
|
||||||
reg32 &= ~(1 << 26);
|
|
||||||
reg32 |= (1 << 16);
|
|
||||||
DMIBAR32(0x1f8) = reg32;
|
|
||||||
|
|
||||||
reg32 = DMIBAR32(0x1fc);
|
|
||||||
reg32 |= (1 << 12) | (1 << 23);
|
|
||||||
DMIBAR32(0x1fc) = reg32;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Enable ASPM on SNB link, should happen before PCH link */
|
|
||||||
if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_SNB) {
|
|
||||||
reg32 = DMIBAR32(0xd04);
|
|
||||||
reg32 |= (1 << 4);
|
|
||||||
DMIBAR32(0xd04) = reg32;
|
|
||||||
}
|
|
||||||
|
|
||||||
reg32 = DMIBAR32(0x88);
|
|
||||||
reg32 |= (1 << 1) | (1 << 0);
|
|
||||||
DMIBAR32(0x88) = reg32;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void northbridge_init(struct device *dev)
|
static void northbridge_init(struct device *dev)
|
||||||
{
|
{
|
||||||
u8 bios_reset_cpl;
|
u8 bios_reset_cpl, pair;
|
||||||
u32 bridge_type;
|
|
||||||
|
|
||||||
northbridge_dmi_init(dev);
|
/* Enable Power Aware Interrupt Routing */
|
||||||
|
pair = MCHBAR8(0x5418);
|
||||||
bridge_type = MCHBAR32(0x5f10);
|
pair &= ~0x7; /* Clear 2:0 */
|
||||||
bridge_type &= ~0xff;
|
pair |= 0x4; /* Fixed Priority */
|
||||||
|
MCHBAR8(0x5418) = pair;
|
||||||
if ((bridge_silicon_revision() & BASE_REV_MASK) == BASE_REV_IVB) {
|
|
||||||
/* Enable Power Aware Interrupt Routing */
|
|
||||||
u8 pair = MCHBAR8(0x5418);
|
|
||||||
pair &= ~0xf; /* Clear 3:0 */
|
|
||||||
pair |= 0x4; /* Fixed Priority */
|
|
||||||
MCHBAR8(0x5418) = pair;
|
|
||||||
|
|
||||||
/* 30h for IvyBridge */
|
|
||||||
bridge_type |= 0x30;
|
|
||||||
} else {
|
|
||||||
/* 20h for Sandybridge */
|
|
||||||
bridge_type |= 0x20;
|
|
||||||
}
|
|
||||||
MCHBAR32(0x5f10) = bridge_type;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set bit 0 of BIOS_RESET_CPL to indicate to the CPU
|
* Set bits 0+1 of BIOS_RESET_CPL to indicate to the CPU
|
||||||
* that BIOS has initialized memory and power management
|
* that BIOS has initialized memory and power management
|
||||||
*/
|
*/
|
||||||
bios_reset_cpl = MCHBAR8(BIOS_RESET_CPL);
|
bios_reset_cpl = MCHBAR8(BIOS_RESET_CPL);
|
||||||
bios_reset_cpl |= 1;
|
bios_reset_cpl |= 3;
|
||||||
MCHBAR8(BIOS_RESET_CPL) = bios_reset_cpl;
|
MCHBAR8(BIOS_RESET_CPL) = bios_reset_cpl;
|
||||||
printk(BIOS_DEBUG, "Set BIOS_RESET_CPL\n");
|
printk(BIOS_DEBUG, "Set BIOS_RESET_CPL\n");
|
||||||
|
|
||||||
|
@ -521,16 +459,6 @@ static void northbridge_init(struct device *dev)
|
||||||
mdelay(1);
|
mdelay(1);
|
||||||
set_power_limits(28);
|
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 */
|
/* Set here before graphics PM init */
|
||||||
MCHBAR32(0x5500) = 0x00100001;
|
MCHBAR32(0x5500) = 0x00100001;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue