Patrick Rudolph (siro@das-labor.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14173
-gerrit
commit 516d3bdfab807c71a6633665dbb354429a14770c Author: Patrick Rudolph siro@das-labor.org Date: Sat Mar 26 12:16:29 2016 +0100
nb/intel/sandybridge/raminit: add additional fallbacks
Try decreasing clock frequency twice.
Disable failing channel. The system may be able to boot with a single channel enabled.
Change-Id: I3be7034ad25312b3ebf47a54f335a3893f8d7cc1 Signed-off-by: Patrick Rudolph siro@das-labor.org --- src/northbridge/intel/sandybridge/raminit.c | 50 +++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-)
diff --git a/src/northbridge/intel/sandybridge/raminit.c b/src/northbridge/intel/sandybridge/raminit.c index 3bfb900..d370da4 100644 --- a/src/northbridge/intel/sandybridge/raminit.c +++ b/src/northbridge/intel/sandybridge/raminit.c @@ -201,6 +201,7 @@ typedef struct ramctr_timing_st { #define MAX_TIMA 127
#define MAKE_ERR ((channel<<16)|(slotrank<<8)|1) +#define GET_ERR_CHANNEL(x) (x>>16)
static void program_timings(ramctr_timing * ctrl, int channel);
@@ -241,6 +242,18 @@ static void toggle_io_reset(void) { }
/* + * Disable a channel in ramctr_timing. + */ +static void disable_channel(ramctr_timing *ctrl, int channel) { + ctrl->rankmap[channel] = 0; + memset(&ctrl->rank_mirror[channel][0], 0, sizeof(ctrl->rank_mirror[0])); + ctrl->channel_size_mb[channel] = 0; + ctrl->cmd_stretch[channel] = 0; + ctrl->mad_dimm[channel] = 0; + memset(&ctrl->timings[channel][0], 0, sizeof(ctrl->timings[0])); +} + +/* * Fill cbmem with information for SMBIOS type 17. */ static void fill_smbios17(ramctr_timing *ctrl) @@ -4042,6 +4055,8 @@ static int try_init_dram_ddr3(ramctr_timing *ctrl, int fast_boot, { int err;
+ printk(BIOS_DEBUG, "Starting RAM training.\n"); + if (!fast_boot) { /* Find fastest common supported parameters */ dram_find_common_params(ctrl); @@ -4233,16 +4248,47 @@ void init_dram_ddr3(spd_raw_data *spds, int mobile, int min_tck, ctrl.mobile = mobile; ctrl.tCK = min_tck;
- printk(BIOS_DEBUG, "Starting RAM training.\n"); - /* Get DDR3 SPD data */ dram_find_spds_ddr3(spds, &ctrl); }
err = try_init_dram_ddr3(&ctrl, fast_boot, me_uma_size); + if (!err) + goto done; + + /* fallback: lower clock frequency */ + printk(BIOS_ERR, "RAM training failed, trying fallback.\n"); + printram("Decreasing clock frequency.\n"); + ctrl.tCK++; + + err = try_init_dram_ddr3(&ctrl, fast_boot, me_uma_size); + if (!err) + goto done; + + /* fallback: lower clock frequency */ + printk(BIOS_ERR, "RAM training failed, trying fallback.\n"); + printram("Decreasing clock frequency.\n"); + ctrl.tCK++; + + err = try_init_dram_ddr3(&ctrl, fast_boot, me_uma_size); + if (!err) + goto done; + + /* fallback: disable failing channel */ + printk(BIOS_ERR, "RAM training failed, trying fallback.\n"); + printram("Disable failing channel.\n"); + + /* Reset DDR3 frequency */ + dram_find_spds_ddr3(spds, &ctrl); + + /* disable failing channel */ + disable_channel(&ctrl, GET_ERR_CHANNEL(err)); + + err = try_init_dram_ddr3(&ctrl, fast_boot, me_uma_size); if (err) die("raminit failed");
+done: /* FIXME: should be hardware revision-dependent. */ write32(DEFAULT_MCHBAR + 0x5024, 0x00a030ce);