summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAngel Pons <th3fanbus@gmail.com>2020-11-19 12:02:07 +0100
committerPatrick Georgi <pgeorgi@google.com>2020-11-22 22:13:18 +0000
commit09fc4b90ebfdb81914f6b89b676db101a417414a (patch)
tree83bc2c85c49be6c2327a6bb0764306eb4ce844e3 /src
parent2ad03a43ecf0c97634f27ebcc2132b8e4286ceb3 (diff)
nb/intel/sandybridge: Refine power-down mode logic
When memory is running at fast frequencies, power-down modes can lessen system stability. Check tXP and tXPDLL values and use safer power down modes if their values are high. Do not use APD with DLL-off on mobile: vendor firmware does not use it, and it can influence system stability. Change-Id: Ic8e98162ca86ae454a8c951be163d58960940e0e Signed-off-by: Angel Pons <th3fanbus@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/47746 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Diffstat (limited to 'src')
-rw-r--r--src/northbridge/intel/sandybridge/Kconfig9
-rw-r--r--src/northbridge/intel/sandybridge/raminit_common.c34
-rw-r--r--src/northbridge/intel/sandybridge/raminit_common.h9
3 files changed, 41 insertions, 11 deletions
diff --git a/src/northbridge/intel/sandybridge/Kconfig b/src/northbridge/intel/sandybridge/Kconfig
index ef6dc3daf5..9cd522f85b 100644
--- a/src/northbridge/intel/sandybridge/Kconfig
+++ b/src/northbridge/intel/sandybridge/Kconfig
@@ -99,6 +99,15 @@ config DCACHE_RAM_MRC_VAR_SIZE
hex
default 0x0
+config RAMINIT_ALWAYS_ALLOW_DLL_OFF
+ bool "Also enable memory DLL-off mode on desktops and servers"
+ default n
+ help
+ If enabled, allow enabling DLL-off mode for platforms other than
+ mobile. Saves power at the expense of higher exit latencies. Has
+ no effect on mobile platforms, where DLL-off is always allowed.
+ Power down is disabled for stability when running at high clocks.
+
config RAMINIT_ENABLE_ECC
bool "Enable ECC if supported"
default y
diff --git a/src/northbridge/intel/sandybridge/raminit_common.c b/src/northbridge/intel/sandybridge/raminit_common.c
index b06734c0e0..d533ca8a30 100644
--- a/src/northbridge/intel/sandybridge/raminit_common.c
+++ b/src/northbridge/intel/sandybridge/raminit_common.c
@@ -688,11 +688,29 @@ static void write_mrreg(ramctr_timing *ctrl, int channel, int slotrank, int reg,
iosav_run_once(channel);
}
+/* Obtain optimal power down mode for current configuration */
+static enum pdwm_mode get_power_down_mode(ramctr_timing *ctrl)
+{
+ if (ctrl->tXP > 8)
+ return PDM_NONE;
+
+ if (ctrl->tXPDLL > 32)
+ return PDM_PPD;
+
+ if (CONFIG(RAMINIT_ALWAYS_ALLOW_DLL_OFF) || get_platform_type() == PLATFORM_MOBILE)
+ return PDM_DLL_OFF;
+
+ return PDM_APD_PPD;
+}
+
static u32 make_mr0(ramctr_timing *ctrl, u8 rank)
{
u16 mr0reg, mch_cas, mch_wr;
static const u8 mch_wr_t[12] = { 1, 2, 3, 4, 0, 5, 0, 6, 0, 7, 0, 0 };
- const size_t is_mobile = get_platform_type() == PLATFORM_MOBILE;
+
+ const enum pdwm_mode power_down = get_power_down_mode(ctrl);
+
+ const bool slow_exit = power_down == PDM_DLL_OFF || power_down == PDM_APD_DLL_OFF;
/* Convert CAS to MCH register friendly */
if (ctrl->CAS < 12) {
@@ -712,8 +730,8 @@ static u32 make_mr0(ramctr_timing *ctrl, u8 rank)
mr0reg |= (mch_cas & 0xe) << 3;
mr0reg |= mch_wr << 9;
- /* Precharge PD - Fast (desktop) 1 or slow (mobile) 0 - mostly power-saving feature */
- mr0reg |= !is_mobile << 12;
+ /* Precharge PD - Use slow exit when DLL-off is used - mostly power-saving feature */
+ mr0reg |= !slow_exit << 12;
return mr0reg;
}
@@ -2830,8 +2848,6 @@ static int encode_wm(int ns)
/* FIXME: values in this function should be hardware revision-dependent */
void final_registers(ramctr_timing *ctrl)
{
- const bool is_mobile = get_platform_type() == PLATFORM_MOBILE;
-
int channel;
int t1_cycles = 0, t1_ns = 0, t2_ns;
int t3_ns;
@@ -2848,12 +2864,8 @@ void final_registers(ramctr_timing *ctrl)
MCHBAR32(TC_OTHP_ch(channel)) = tc_othp.raw;
}
- if (is_mobile)
- /* APD - DLL Off, 64 DCLKs until idle, decision per rank */
- MCHBAR32(PM_PDWN_CONFIG) = 0x00000740;
- else
- /* APD - PPD, 64 DCLKs until idle, decision per rank */
- MCHBAR32(PM_PDWN_CONFIG) = 0x00000340;
+ /* 64 DCLKs until idle, decision per rank */
+ MCHBAR32(PM_PDWN_CONFIG) = get_power_down_mode(ctrl) << 8 | 64;
FOR_ALL_CHANNELS
MCHBAR32(PM_TRML_M_CONFIG_ch(channel)) = 0x00000aaa;
diff --git a/src/northbridge/intel/sandybridge/raminit_common.h b/src/northbridge/intel/sandybridge/raminit_common.h
index 050aa7047c..80d30744a2 100644
--- a/src/northbridge/intel/sandybridge/raminit_common.h
+++ b/src/northbridge/intel/sandybridge/raminit_common.h
@@ -273,6 +273,15 @@ void iosav_write_memory_test_sequence(ramctr_timing *ctrl, int channel, int slot
*/
#define MRC_CACHE_VERSION 5
+enum pdwm_mode {
+ PDM_NONE = 0,
+ PDM_APD = 1,
+ PDM_PPD = 2,
+ PDM_APD_PPD = 3,
+ PDM_DLL_OFF = 6,
+ PDM_APD_DLL_OFF = 7,
+};
+
typedef struct odtmap_st {
u16 rttwr;
u16 rttnom;