diff options
author | Patrick Rudolph <siro@das-labor.org> | 2016-03-26 12:16:29 +0100 |
---|---|---|
committer | Martin Roth <martinroth@google.com> | 2016-05-04 19:58:46 +0200 |
commit | 2ccb74b6e97381ce2b2f8520076204f7737ade4c (patch) | |
tree | 3cae8b87576b4a21bab443b8e04083eeba6edc7c /src/northbridge/intel | |
parent | 1e302cbd09bb304309476113c149c2c0d09a2a86 (diff) | |
download | coreboot-2ccb74b6e97381ce2b2f8520076204f7737ade4c.tar.xz |
nb/intel/sandybridge/raminit: add additional fallbacks
Add the following fallbacks:
* Try decreasing clock frequency.
In case of DDR1600 the next possible value of DDR1333 is being used.
* Try decreasing clock frequency.
In case of DDR1333 the next possible value of DDR1066 is being used.
* Disable failing channel.
The system may be able to boot with a single channel enabled.
The fallbacks are untested.
Change-Id: I3be7034ad25312b3ebf47a54f335a3893f8d7cc1
Signed-off-by: Patrick Rudolph <siro@das-labor.org>
Reviewed-on: https://review.coreboot.org/14173
Tested-by: build bot (Jenkins)
Reviewed-by: Martin Roth <martinroth@google.com>
Diffstat (limited to 'src/northbridge/intel')
-rw-r--r-- | src/northbridge/intel/sandybridge/raminit.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/src/northbridge/intel/sandybridge/raminit.c b/src/northbridge/intel/sandybridge/raminit.c index 3c606e17c2..0c191b2abd 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) @@ -4252,6 +4265,37 @@ void init_dram_ddr3(spd_raw_data *spds, int mobile, int min_tck, err = try_init_dram_ddr3(&ctrl, fast_boot, s3resume, me_uma_size); } + + if (err && (ctrl.tCK < TCK_400MHZ)) { + /* 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, s3resume, me_uma_size); + } + + if (err && (ctrl.tCK < TCK_400MHZ)) { + /* 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, s3resume, me_uma_size); + } + + if (err) { + /* 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, s3resume, me_uma_size); + } + if (err) die("raminit failed"); |