Patrick Rudolph (siro@das-labor.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14082
-gerrit
commit 57dccde3e45d6d8b5bcb9f4d3bae42aa2579312f Author: Patrick Rudolph siro@das-labor.org Date: Sun Mar 13 11:07:45 2016 +0100
nb/intel/sandybridge/raminit: always use mrccache
Always use MRC cache if possible. Added a CRC array to make sure the DIMMs haven't been replaced. In case one of the CRCs doesn't match, start RAM training.
Should speed up boot time.
Test system: * Gigabyte GA-B75M-D3H * Intel Pentium CPU G2130
Test result: Doesn't work ! Needs to find out why MRC cache is always empty.
Change-Id: I974c5bce70692a706410180c2a512eb071364be0 Signed-off-by: Patrick Rudolph siro@das-labor.org --- src/northbridge/intel/sandybridge/raminit.c | 78 ++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 25 deletions(-)
diff --git a/src/northbridge/intel/sandybridge/raminit.c b/src/northbridge/intel/sandybridge/raminit.c index 0b27fe5..975b91e 100644 --- a/src/northbridge/intel/sandybridge/raminit.c +++ b/src/northbridge/intel/sandybridge/raminit.c @@ -135,6 +135,7 @@ struct ram_rank_timings { struct ramctr_timing_st;
typedef struct ramctr_timing_st { + u16 spd_crc[NUM_CHANNELS][NUM_SLOTS]; int mobile;
u16 cas_supported; @@ -184,6 +185,7 @@ typedef struct ramctr_timing_st { int rank_mirror[NUM_CHANNELS][NUM_SLOTRANKS];
struct ram_rank_timings timings[NUM_CHANNELS][NUM_SLOTRANKS]; + dimm_info info; } ramctr_timing;
#define SOUTHBRIDGE PCI_DEV(0, 0x1f, 0) @@ -377,6 +379,7 @@ static void dram_find_spds_ddr3(spd_raw_data * spd, dimm_info * dimm,
dram_print_spd_ddr3(&dimm->dimm[channel][slot]); dimms++; + ctrl->spd_crc[channel][slot] = spd_ddr3_calc_crc(spd[spd_slot], sizeof(spd_raw_data)); ctrl->rank_mirror[channel][slot * 2] = 0; ctrl->rank_mirror[channel][slot * 2 + 1] = dimm->dimm[channel][slot].flags.pins_mirrored; ctrl->channel_size_mb[channel] += dimm->dimm[channel][slot].size_mb; @@ -3943,7 +3946,10 @@ void init_dram_ddr3(spd_raw_data * spds, int mobile, int min_tck, { int me_uma_size; int cbmem_was_inited; - dimm_info info; + int fast_boot; + ramctr_timing ctrl; + struct mrc_data_container *mrc_cache; + ramctr_timing *ctrl_cached;
MCHBAR32(0x5f00) |= 1;
@@ -3971,45 +3977,67 @@ void init_dram_ddr3(spd_raw_data * spds, int mobile, int min_tck, halt(); }
- ramctr_timing ctrl; - memset(&ctrl, 0, sizeof (ctrl));
early_pch_init_native(); early_thermal_init();
- ctrl.mobile = mobile; - ctrl.tCK = min_tck; - - /* FIXME: for non-S3 we should be able to use timing caching with - proper verification. Right now we use timings only for S3 case. - */ - if (s3resume) { - struct mrc_data_container *mrc_cache; - - mrc_cache = find_current_mrc_cache(); - if (!mrc_cache || mrc_cache->mrc_data_size < sizeof (ctrl)) { + /* try to find timings in MRC cache */ + mrc_cache = find_current_mrc_cache(); + if (!mrc_cache || mrc_cache->mrc_data_size < sizeof (ctrl)) { + if (s3resume) { /* Failed S3 resume, reset to come up cleanly */ outb(0x6, 0xcf9); halt(); } - memcpy(&ctrl, mrc_cache->mrc_data, sizeof (ctrl)); + ctrl_cached = NULL; + } else { + ctrl_cached = (ramctr_timing *)mrc_cache->mrc_data; + } + + /* verify MRC cache for fast boot */ + if (ctrl_cached) { + fast_boot = 1; + + /* check SPD CRC16 to make sure the DIMMs haven't been replaced */ + fast_boot &= ctrl_cached->spd_crc[0][0] == + spd_ddr3_calc_crc(spds[0], sizeof(spd_raw_data)); + + fast_boot &= ctrl_cached->spd_crc[0][1] == + spd_ddr3_calc_crc(spds[1], sizeof(spd_raw_data)); + + fast_boot &= ctrl_cached->spd_crc[1][0] == + spd_ddr3_calc_crc(spds[2], sizeof(spd_raw_data)); + + fast_boot &= ctrl_cached->spd_crc[1][1] == + spd_ddr3_calc_crc(spds[3], sizeof(spd_raw_data)); + } else { + fast_boot = 0; }
- if (!s3resume) { + + if (fast_boot) { + memcpy(&ctrl, ctrl_cached, sizeof (ctrl)); + printk(BIOS_DEBUG, "Using stored timings. Skipping RAM training.\n"); + } else { + ctrl.mobile = mobile; + ctrl.tCK = min_tck; + + printk(BIOS_DEBUG, "No valid stored timings found. Starting RAM training.\n"); + /* Get DDR3 SPD data */ - dram_find_spds_ddr3(spds, &info, &ctrl); + dram_find_spds_ddr3(spds, &ctrl.info, &ctrl);
/* Find fastest common supported parameters */ - dram_find_common_params(&info, &ctrl); + dram_find_common_params(&ctrl.info, &ctrl);
- dram_dimm_mapping(&info, &ctrl); + dram_dimm_mapping(&ctrl.info, &ctrl); }
/* Set MCU frequency */ dram_freq(&ctrl);
- if (!s3resume) { + if (!fast_boot) { /* Calculate timings */ dram_timing(&ctrl); } @@ -4052,7 +4080,7 @@ void init_dram_ddr3(spd_raw_data * spds, int mobile, int min_tck,
udelay(1);
- if (s3resume) { + if (fast_boot) { restore_timings(&ctrl); } else { /* Do jedec ddr3 reset sequence */ @@ -4090,7 +4118,7 @@ void init_dram_ddr3(spd_raw_data * spds, int mobile, int min_tck,
write_controller_mr(&ctrl);
- if (!s3resume) { + if (!fast_boot) { channel_test(&ctrl); }
@@ -4106,7 +4134,7 @@ void init_dram_ddr3(spd_raw_data * spds, int mobile, int min_tck, /* Zone config */ dram_zones(&ctrl, 0);
- if (!s3resume) + if (!fast_boot) quick_ram_check();
intel_early_me_status(); @@ -4116,7 +4144,7 @@ void init_dram_ddr3(spd_raw_data * spds, int mobile, int min_tck, report_memory_config();
cbmem_was_inited = !cbmem_recovery(s3resume); - if (!s3resume) + if (!fast_boot) save_timings(&ctrl); if (s3resume && !cbmem_was_inited) { /* Failed S3 resume, reset to come up cleanly */ @@ -4124,7 +4152,7 @@ void init_dram_ddr3(spd_raw_data * spds, int mobile, int min_tck, halt(); }
- fill_smbios17(&info, (1000 << 8) / ctrl.tCK); + fill_smbios17(&ctrl.info, (1000 << 8) / ctrl.tCK); }
#define HOST_BRIDGE PCI_DEVFN(0, 0)