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);
}