From 09fc4b90ebfdb81914f6b89b676db101a417414a Mon Sep 17 00:00:00 2001 From: Angel Pons Date: Thu, 19 Nov 2020 12:02:07 +0100 Subject: 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 Reviewed-on: https://review.coreboot.org/c/coreboot/+/47746 Tested-by: build bot (Jenkins) Reviewed-by: Arthur Heymans --- src/northbridge/intel/sandybridge/Kconfig | 9 ++++++ src/northbridge/intel/sandybridge/raminit_common.c | 34 +++++++++++++++------- src/northbridge/intel/sandybridge/raminit_common.h | 9 ++++++ 3 files changed, 41 insertions(+), 11 deletions(-) (limited to 'src') 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; -- cgit v1.2.3