From dabebc3716bac1dbe9445dfb2bbbbb833ee21de1 Mon Sep 17 00:00:00 2001 From: Dan Elkouby Date: Fri, 13 Apr 2018 18:47:10 +0300 Subject: [PATCH] nb/intel/sandybridge: support more XMP timings Tested with a pair of GSkill F3-1866C9-8GSR. This makes sure in particular that we honor the CMD rate requested by the XMP profile. This memory kit needs a CMD rate of 2 to be stable at DDR3-1600 and up, even though it passes training at 1. Also respect requested CWL to match vendor firmware and for a potential increase in performance. The tested kit requests a tighter value than the per-frequency table provides and has shown to be stable using that setting. Change-Id: I634bed764d76345c27f02a2fae5abb2d81b38fd9 Signed-off-by: Dan Elkouby Reviewed-on: https://review.coreboot.org/25664 Reviewed-by: Patrick Rudolph Reviewed-by: Paul Menzel Tested-by: build bot (Jenkins) --- src/northbridge/intel/sandybridge/raminit_common.c | 8 +++++++- src/northbridge/intel/sandybridge/raminit_common.h | 2 ++ src/northbridge/intel/sandybridge/raminit_ivy.c | 5 ++++- src/northbridge/intel/sandybridge/raminit_sandy.c | 5 ++++- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/northbridge/intel/sandybridge/raminit_common.c b/src/northbridge/intel/sandybridge/raminit_common.c index 0a44220bd6..5f6753fefc 100644 --- a/src/northbridge/intel/sandybridge/raminit_common.c +++ b/src/northbridge/intel/sandybridge/raminit_common.c @@ -160,6 +160,8 @@ void dram_find_common_params(ramctr_timing *ctrl) ctrl->tWTR = MAX(ctrl->tWTR, dimm->tWTR); ctrl->tRTP = MAX(ctrl->tRTP, dimm->tRTP); ctrl->tFAW = MAX(ctrl->tFAW, dimm->tFAW); + ctrl->tCWL = MAX(ctrl->tCWL, dimm->tCWL); + ctrl->tCMD = MAX(ctrl->tCMD, dimm->tCMD); } if (!ctrl->cas_supported) @@ -2350,12 +2352,16 @@ int command_training(ramctr_timing *ctrl) * will fail in write training. * Workaround: Skip 1T in dual DIMM mode, that's only * supported by a few DIMMs. - * TODO: How to detect "1T" DIMMs ? + * Only try 1T mode for XMP DIMMs that request it in dual DIMM + * mode. * * Single DIMM per channel: * Try command rate 1T and 2T */ cmdrate = ((ctrl->rankmap[channel] & 0x5) == 0x5); + if (ctrl->tCMD) + /* XMP gives the CMD rate in clock ticks, not ns */ + cmdrate = MIN(DIV_ROUND_UP(ctrl->tCMD, 256) - 1, 1); for (; cmdrate < 2; cmdrate++) { err = try_cmd_stretch(ctrl, channel, cmdrate << 1); diff --git a/src/northbridge/intel/sandybridge/raminit_common.h b/src/northbridge/intel/sandybridge/raminit_common.h index ab6e592f07..1f32dcddc4 100644 --- a/src/northbridge/intel/sandybridge/raminit_common.h +++ b/src/northbridge/intel/sandybridge/raminit_common.h @@ -94,6 +94,8 @@ typedef struct ramctr_timing_st { u32 tWTR; u32 tRTP; u32 tFAW; + u32 tCWL; + u32 tCMD; /* Latencies in terms of clock cycles * They are saved separately as they are needed for DRAM MRS commands*/ u8 CAS; /* CAS read latency */ diff --git a/src/northbridge/intel/sandybridge/raminit_ivy.c b/src/northbridge/intel/sandybridge/raminit_ivy.c index 675ac7181c..19dea2f2e1 100644 --- a/src/northbridge/intel/sandybridge/raminit_ivy.c +++ b/src/northbridge/intel/sandybridge/raminit_ivy.c @@ -479,7 +479,10 @@ static void dram_timing(ramctr_timing *ctrl) /* DLL_CONFIG_MDLL_W_TIMER */ ctrl->reg_5064b0 = (128000 / ctrl->tCK) + 3; - ctrl->CWL = get_CWL(ctrl->tCK); + if (ctrl->tCWL) + ctrl->CWL = DIV_ROUND_UP(ctrl->tCWL, ctrl->tCK); + else + ctrl->CWL = get_CWL(ctrl->tCK); printk(BIOS_DEBUG, "Selected CWL latency : %uT\n", ctrl->CWL); /* Find tRCD */ diff --git a/src/northbridge/intel/sandybridge/raminit_sandy.c b/src/northbridge/intel/sandybridge/raminit_sandy.c index 3acc5631a3..99c107ec06 100644 --- a/src/northbridge/intel/sandybridge/raminit_sandy.c +++ b/src/northbridge/intel/sandybridge/raminit_sandy.c @@ -251,7 +251,10 @@ static void dram_timing(ramctr_timing *ctrl) /* DLL_CONFIG_MDLL_W_TIMER */ ctrl->reg_5064b0 = (128000 / ctrl->tCK) + 3; - ctrl->CWL = get_CWL(ctrl->tCK); + if (ctrl->tCWL) + ctrl->CWL = DIV_ROUND_UP(ctrl->tCWL, ctrl->tCK); + else + ctrl->CWL = get_CWL(ctrl->tCK); printk(BIOS_DEBUG, "Selected CWL latency : %uT\n", ctrl->CWL); /* Find tRCD */