[coreboot-gerrit] Patch set updated for coreboot: nb/i945/raminit.c: Fix cas and frequency selection

Arthur Heymans (arthur@aheymans.xyz) gerrit at coreboot.org
Wed Jan 18 17:53:24 CET 2017


Arthur Heymans (arthur at aheymans.xyz) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/18159

-gerrit

commit ef1224b20f40fa15ce7ce632e577c37d3e195e5c
Author: Arthur Heymans <arthur at aheymans.xyz>
Date:   Tue Jan 17 16:47:42 2017 +0100

    nb/i945/raminit.c: Fix cas and frequency selection
    
    If a dimm supports a CAS latency higher than 5 the wrong spd offset is
    used to obtain the tCLK and tAC latencies.
    
    Previously probing SPD for supported CAS and computing highest
    supported CAS was done for each frequency attempted. This should be
    done only once, since this information is constant.
    
    Also remove printing 'lowest_common_cas' since this is of no practical
    use.
    
    TESTED on thinkpad X60 and asus P5GC-MX (fixes too fast CAS on
    underclocked dimm)
    
    Change-Id: If2fee02b1269a0314d781815deaf54e87fbc1ce0
    Signed-off-by: Arthur Heymans <arthur at aheymans.xyz>
---
 src/northbridge/intel/i945/raminit.c | 58 +++++++++++++++++++++---------------
 1 file changed, 34 insertions(+), 24 deletions(-)

diff --git a/src/northbridge/intel/i945/raminit.c b/src/northbridge/intel/i945/raminit.c
index cc227cc..f0ce543 100644
--- a/src/northbridge/intel/i945/raminit.c
+++ b/src/northbridge/intel/i945/raminit.c
@@ -477,8 +477,9 @@ static u8 sdram_possible_cas_latencies(struct sys_info * sysinfo)
 static void sdram_detect_cas_latency_and_ram_speed(struct sys_info * sysinfo, u8 cas_mask)
 {
 	int i, j, idx;
-	int lowest_common_cas = 0;
 	int max_ram_speed = 0;
+	u8 highest_supported_cas[2 * DIMM_SOCKETS];
+	u8 supported_cas[2 * DIMM_SOCKETS];
 
 	const u8 ddr2_speeds_table[] = {
 		0x50, 0x60,	/* DDR2 400: tCLK = 5.0ns  tAC = 0.6ns  */
@@ -501,42 +502,43 @@ static void sdram_detect_cas_latency_and_ram_speed(struct sys_info * sysinfo, u8
 	sysinfo->memory_frequency = 0;
 	sysinfo->cas = 0;
 
-	if (cas_mask & SPD_CAS_LATENCY_DDR2_3) {
-		lowest_common_cas = 3;
-	} else if (cas_mask & SPD_CAS_LATENCY_DDR2_4) {
-		lowest_common_cas = 4;
-	} else if (cas_mask & SPD_CAS_LATENCY_DDR2_5) {
-		lowest_common_cas = 5;
+	for(i = 0; i < 2 * DIMM_SOCKETS; i++) {
+		int device = get_dimm_spd_address(sysinfo, i);
+		PRINTK_DEBUG("  DIMM: %d\n", i);
+		if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
+			continue;
+		}
+		supported_cas[i] = spd_read_byte(device, SPD_ACCEPTABLE_CAS_LATENCIES);
+		if (supported_cas[i] & SPD_CAS_LATENCY_DDR2_7) {
+			highest_supported_cas[i] = 7;
+		} else if (supported_cas[i] & SPD_CAS_LATENCY_DDR2_6) {
+			highest_supported_cas[i] = 6;
+		} else if (supported_cas[i] & SPD_CAS_LATENCY_DDR2_5) {
+			highest_supported_cas[i] = 5;
+		} else if (supported_cas[i] & SPD_CAS_LATENCY_DDR2_4) {
+			highest_supported_cas[i] = 4;
+		} else if (supported_cas[i] & SPD_CAS_LATENCY_DDR2_3) {
+			highest_supported_cas[i] = 3;
+		} else {
+			die("Invalid max. CAS.\n");
+		}
 	}
-	PRINTK_DEBUG("lowest common cas = %d\n", lowest_common_cas);
 
 	for (j = max_ram_speed; j>=0; j--) {
 		int freq_cas_mask = cas_mask;
 
 		PRINTK_DEBUG("Probing Speed %d\n", j);
 		for (i = 0; i < 2*DIMM_SOCKETS; i++) {
-			int device = get_dimm_spd_address(sysinfo, i);
-			int current_cas_mask;
-
 			PRINTK_DEBUG("  DIMM: %d\n", i);
 			if (sysinfo->dimm[i] == SYSINFO_DIMM_NOT_POPULATED) {
 				continue;
 			}
 
-			current_cas_mask = spd_read_byte(device, SPD_ACCEPTABLE_CAS_LATENCIES);
-
+			int current_cas_mask = supported_cas[i];
 			while (current_cas_mask) {
-				int highest_supported_cas = 0, current_cas = 0;
+				int current_cas = 0;
+				int device = get_dimm_spd_address(sysinfo, i);
 				PRINTK_DEBUG("    Current CAS mask: %04x; ", current_cas_mask);
-				if (current_cas_mask & SPD_CAS_LATENCY_DDR2_5) {
-					highest_supported_cas = 5;
-				} else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
-					highest_supported_cas = 4;
-				} else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
-					highest_supported_cas = 3;
-				} else {
-					die("Invalid max. CAS.\n");
-				}
 				if (current_cas_mask & SPD_CAS_LATENCY_DDR2_3) {
 					current_cas = 3;
 				} else if (current_cas_mask & SPD_CAS_LATENCY_DDR2_4) {
@@ -547,7 +549,15 @@ static void sdram_detect_cas_latency_and_ram_speed(struct sys_info * sysinfo, u8
 					die("Invalid CAS.\n");
 				}
 
-				idx = highest_supported_cas - current_cas;
+				/*
+				 * A DDR2 SPD only stores latencies for 3 CAS timings.
+				 * Skip supported CAS for which no latency is defined.
+				 */
+				if (highest_supported_cas[i] - current_cas > 2) {
+					current_cas_mask &= ~(1 << (current_cas));
+					continue;
+				}
+				idx = highest_supported_cas[i] - current_cas;
 				PRINTK_DEBUG("idx=%d, ", idx);
 				PRINTK_DEBUG("tCLK=%x, ", spd_read_byte(device, spd_lookup_table[2*idx]));
 				PRINTK_DEBUG("tAC=%x", spd_read_byte(device, spd_lookup_table[(2*idx)+1]));



More information about the coreboot-gerrit mailing list