haswell: Enable 2x Refresh mode Send the PCODE mailbox command to enable 2x refresh mode if it is not already enabled by MRC. BUG=chrome-os-partner:35209 BRANCH=haswell TEST=build and boot on peppy, check /sys/firmware/log for successful report that 2x Refresh is enabled. Ensure it is also enabled after suspend/resume cycle. Change-Id: I8473ace7302674eb79f537d431bc8bf84c4abeaa Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/240701 Reviewed-by: Shawn N <shawnn@chromium.org> (cherry picked from commit 6b0827894d85556d7aa84cadd8c0f72311ab0716) Reviewed-on: https://chromium-review.googlesource.com/252991 Commit-Queue: Steven Jian <steven.jian@intel.com> Tested-by: Steven Jian <steven.jian@intel.com>
diff --git a/src/cpu/intel/haswell/haswell.h b/src/cpu/intel/haswell/haswell.h index 9326140..fb464d0 100644 --- a/src/cpu/intel/haswell/haswell.h +++ b/src/cpu/intel/haswell/haswell.h
@@ -136,6 +136,12 @@ /* Data is passed through bits 31:0 of the data register. */ #define BIOS_MAILBOX_DATA 0x5da0 +#define MAILBOX_BIOS_CMD_READ_DDR_FORCE_2X_REFRESH 0x17 +#define MAILBOX_BIOS_CMD_WRITE_DDR_FORCE_2X_REFRESH 0x18 + +#define FORCE_2X_REFRESH_LOCK (1 << 31) +#define FORCE_2X_REFRESH_ENABLE (1 << 0) + /* Region of SMM space is reserved for multipurpose use. It falls below * the IED region and above the SMM handler. */ #define RESERVED_SMM_SIZE CONFIG_SMM_RESERVED_SIZE
diff --git a/src/cpu/intel/haswell/haswell_init.c b/src/cpu/intel/haswell/haswell_init.c index 3c4ce56..6546f23 100644 --- a/src/cpu/intel/haswell/haswell_init.c +++ b/src/cpu/intel/haswell/haswell_init.c
@@ -304,6 +304,60 @@ return MCHBAR32(BIOS_MAILBOX_DATA); } +static int pcode_mailbox_write(u32 command, u32 data) +{ + if (pcode_ready() < 0) { + printk(BIOS_ERR, "PCODE: mailbox timeout on wait ready.\n"); + return -1; + } + + MCHBAR32(BIOS_MAILBOX_DATA) = data; + + /* Send command and start transaction */ + MCHBAR32(BIOS_MAILBOX_INTERFACE) = command | MAILBOX_RUN_BUSY; + + if (pcode_ready() < 0) { + printk(BIOS_ERR, "PCODE: mailbox timeout on completion.\n"); + return -1; + } + + return 0; +} + +static void enable_2x_refresh(void) +{ + u32 read_command, write_command; + u32 value; + + read_command = MAILBOX_BIOS_CMD_READ_DDR_FORCE_2X_REFRESH; + write_command = MAILBOX_BIOS_CMD_WRITE_DDR_FORCE_2X_REFRESH; + + /* Read 2x Refresh register to see if it needs to be set */ + value = pcode_mailbox_read(read_command); + + if (value & FORCE_2X_REFRESH_ENABLE) { + printk(BIOS_INFO, "2x Refresh already enabled\n"); + return; + } else if (value & FORCE_2X_REFRESH_LOCK) { + printk(BIOS_INFO, "2x Refresh register already locked\n"); + return; + } + + /* Enable 2x Refresh and lock */ + value |= FORCE_2X_REFRESH_ENABLE | FORCE_2X_REFRESH_LOCK; + if (pcode_mailbox_write(write_command, value) < 0) + printk(BIOS_ERR, "Error writing 2x Refresh register"); + + /* Read back 2x Refresh and check if enabled */ + value = pcode_mailbox_read(read_command); + + if (value & FORCE_2X_REFRESH_ENABLE) + printk(BIOS_INFO, "2x Refresh Enabled: 0x%08x\n", value); + else + printk(BIOS_ERR, "ERROR: 2x Refresh NOT enabled: 0x%08x\n", + value); +} + static void initialize_vr_config(void) { msr_t msr; @@ -729,6 +783,8 @@ configure_pch_power_sharing(); } + enable_2x_refresh(); + /* Call through the cpu driver's initialization. */ cpu_initialize(0); }