[coreboot-gerrit] New patch to review for coreboot: nb/intel/sandybridge/raminit: always use mrccache

Patrick Rudolph (siro@das-labor.org) gerrit at coreboot.org
Sun Mar 13 12:31:38 CET 2016


Patrick Rudolph (siro at 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 at 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 at 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)



More information about the coreboot-gerrit mailing list