[coreboot-gerrit] Patch set updated for coreboot: nb/intel/x4x: Fix CAS latency detection and max memory detection

Damien Zammit (damien@zamaudio.com) gerrit at coreboot.org
Tue Jul 26 07:09:12 CEST 2016


Damien Zammit (damien at zamaudio.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15818

-gerrit

commit 621bbf5aa3e36bc1282afb588d707967e809c9f7
Author: Damien Zammit <damien at zamaudio.com>
Date:   Sun Jul 24 03:28:42 2016 +1000

    nb/intel/x4x: Fix CAS latency detection and max memory detection
    
    The current scheme for detecting max memory frequency is flawed,
    but since it is undocumented, revert to old scheme based on gm45 code.
    CAS latency detection also relies on this, and has been cleaned up.
    
    TESTED: on GA-G41M-ES2L
    CPU: E5200 @ 2.50GHz (FSB 800MHz)
    
    2x 1GB 667MHz hynix
    1x 2GB 800Mhz ARAM
    1x 1GB 667Mhz StarRam
    2x 2GB 800Mhz (generic)
    
    All above combinations running at 667MHz worked.
    
    Change-Id: I1ddd7827ee6fe3d4162ba0546f738a8f9decdf93
    Signed-off-by: Damien Zammit <damien at zamaudio.com>
---
 src/northbridge/intel/x4x/raminit.c      | 133 ++++++++++---------------------
 src/northbridge/intel/x4x/raminit_ddr2.c |   5 +-
 2 files changed, 43 insertions(+), 95 deletions(-)

diff --git a/src/northbridge/intel/x4x/raminit.c b/src/northbridge/intel/x4x/raminit.c
index 9be2cd3..5111588 100644
--- a/src/northbridge/intel/x4x/raminit.c
+++ b/src/northbridge/intel/x4x/raminit.c
@@ -111,10 +111,9 @@ static void sdram_read_spds(struct sysinfo *s)
 			s->dimms[i].chip_capacity = s->dimms[i].banks;
 			s->dimms[i].rows = s->dimms[i].spd_data[3];// - 12;
 			s->dimms[i].cols = s->dimms[i].spd_data[4];// - 9;
-			s->dimms[i].cas_latencies = 0x70; // 6,5,4 CL
-			s->dimms[i].cas_latencies &= s->dimms[i].spd_data[18];
+			s->dimms[i].cas_latencies = s->dimms[i].spd_data[18];
 			if (s->dimms[i].cas_latencies == 0)
-				s->dimms[i].cas_latencies = 0x70;
+				s->dimms[i].cas_latencies = 0x60; // 6,5 CL
 			s->dimms[i].tAAmin = s->dimms[i].spd_data[26];
 			s->dimms[i].tCKmin = s->dimms[i].spd_data[25];
 			s->dimms[i].width = (s->dimms[i].spd_data[13] >> 3) - 1;
@@ -248,13 +247,6 @@ static void sdram_read_spds(struct sysinfo *s)
 	}
 }
 
-static u8 lsbpos(u8 val) //Forward
-{
-	u8 i;
-	for (i = 0; (i < 8) && ((val & (1 << i)) == 0); i++);
-	return i;
-}
-
 static u8 msbpos(u8 val) //Reverse
 {
 	u8 i;
@@ -264,8 +256,6 @@ static u8 msbpos(u8 val) //Reverse
 
 static void mchinfo_ddr2(struct sysinfo *s)
 {
-	u8 capablefreq, maxfreq;
-
 	const u32 eax = cpuid_ext(0x04, 0).eax;
 	s->cores = ((eax >> 26) & 0x3f) + 1;
 	printk(BIOS_WARNING, "%d CPU cores\n", s->cores);
@@ -284,19 +274,7 @@ static void mchinfo_ddr2(struct sysinfo *s)
 		printk(BIOS_WARNING, "AMT enabled\n");
 	}
 
-	maxfreq = MEM_CLOCK_800MHz;
-	capablefreq = (u8)((pci_read_config16(PCI_DEV(0, 0, 0), 0xea) >> 4) & 0x3f);
-	capablefreq &= 0x7;
-	if (capablefreq)
-		maxfreq = capablefreq + 1;
-
-	if (maxfreq > MEM_CLOCK_800MHz)
-		maxfreq = MEM_CLOCK_800MHz;
-
-	if (maxfreq < MEM_CLOCK_667MHz)
-		maxfreq = MEM_CLOCK_667MHz;
-
-	s->max_ddr2_mhz = (maxfreq == MEM_CLOCK_800MHz) ? 800 : 667;
+	s->max_ddr2_mhz = (capid & (1<<(53-32)))?667:800;
 	printk(BIOS_WARNING, "Capable of DDR2 of %d MHz or lower\n", s->max_ddr2_mhz);
 
 	if (!(capid & (1<<(48-32)))) {
@@ -308,12 +286,15 @@ static void sdram_detect_ram_speed(struct sysinfo *s)
 {
 	u8 i;
 	u8 commoncas = 0;
-	u8 cas;
-	u8 lowcas;
-	u8 highcas;
+	u8 currcas;
+	u8 currfreq;
 	u8 maxfreq;
 	u8 freq = 0;
 
+	// spdidx,cycletime @CAS				 5	   6
+	u8 idx800[7][2] = {{0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {23,0x30}, {9,0x25}};
+	int found = 0;
+
 	// Find max FSB speed
 	switch (MCHBAR32(0xc00) & 0x7) {
 	case 0x0:
@@ -335,10 +316,11 @@ static void sdram_detect_ram_speed(struct sysinfo *s)
 	if (s->spd_type == DDR2) {
 
 		// Choose max memory frequency for MCH as previously detected
-		freq = (s->max_ddr2_mhz == 800) ? MEM_CLOCK_800MHz : MEM_CLOCK_667MHz;
+		maxfreq = (s->max_ddr2_mhz == 800) ? MEM_CLOCK_800MHz : MEM_CLOCK_667MHz;
+
+		// Choose common CAS latency from {6,5}, 4 does not work
+		commoncas = 0x60;
 
-		// Detect a common CAS latency (Choose from 6,5,4 CL)
-		commoncas = 0x70;
 		FOR_EACH_POPULATED_DIMM(s->dimms, i) {
 			commoncas &= s->dimms[i].cas_latencies;
 		}
@@ -346,74 +328,41 @@ static void sdram_detect_ram_speed(struct sysinfo *s)
 			die("No common CAS among dimms\n");
 		}
 
-		// Start with fastest common CAS
-		cas = 0;
-		highcas = msbpos(commoncas);
-		lowcas = lsbpos(commoncas);
-
-		while (cas == 0 && highcas >= lowcas) {
-			FOR_EACH_POPULATED_DIMM(s->dimms, i) {
-				switch (freq) {
-				case MEM_CLOCK_800MHz:
-					if ((s->dimms[i].spd_data[9] > 0x25) ||
-					    (s->dimms[i].spd_data[10] > 0x40)) {
-						// CAS too fast, lower it
-						highcas--;
-						break;
-					} else {
-						cas = highcas;
-					}
-					break;
-				case MEM_CLOCK_667MHz:
-				default:
-					if ((s->dimms[i].spd_data[9] > 0x30) ||
-					    (s->dimms[i].spd_data[10] > 0x45)) {
-						// CAS too fast, lower it
-						highcas--;
-						break;
-					} else {
-						cas = highcas;
+		// Working from fastest to slowest,
+		// fast->slow 5 at 800 6 at 800 5 at 667
+		found = 0;
+		for (currcas = 5; currcas <= msbpos(commoncas); currcas++) {
+			currfreq = maxfreq;
+			if (currfreq == MEM_CLOCK_800MHz) {
+				found = 1;
+				FOR_EACH_POPULATED_DIMM(s->dimms, i) {
+					if (s->dimms[i].spd_data[idx800[currcas][0]] > idx800[currcas][1]) {
+						// this is too fast
+						found = 0;
 					}
-					break;
 				}
+				if (found)
+					break;
 			}
 		}
-		if (highcas < lowcas) {
-			// Timings not supported by MCH, lower the frequency
-			freq--;
-			cas = 0;
-			highcas = msbpos(commoncas);
-			lowcas = lsbpos(commoncas);
-			while (cas == 0 && highcas >= lowcas) {
-				FOR_EACH_POPULATED_DIMM(s->dimms, i) {
-					switch (freq) {
-					case MEM_CLOCK_800MHz:
-						if ((s->dimms[i].spd_data[23] > 0x25) ||
-						    (s->dimms[i].spd_data[24] > 0x40)) {
-							// CAS too fast, lower it
-							highcas--;
-							break;
-						} else {
-							cas = highcas;
-						}
-						break;
-					case MEM_CLOCK_667MHz:
-					default:
-						if ((s->dimms[i].spd_data[23] > 0x30) ||
-						    (s->dimms[i].spd_data[24] > 0x45)) {
-							// CAS too fast, lower it
-							highcas--;
-							break;
-						} else {
-							cas = highcas;
-						}
-						break;
-					}
+
+		if (!found) {
+			currcas = 5;
+			currfreq = MEM_CLOCK_667MHz;
+			found = 1;
+			FOR_EACH_POPULATED_DIMM(s->dimms, i) {
+				if (s->dimms[i].spd_data[9] > 0x30) {
+					// this is too fast
+					found = 0;
 				}
 			}
 		}
-		s->selected_timings.mem_clk = freq;
-		s->selected_timings.CAS = cas;
+
+		if (!found)
+			die("No valid CAS/frequencies detected\n");
+
+		s->selected_timings.mem_clk = currfreq;
+		s->selected_timings.CAS = currcas;
 
 	} else { // DDR3
 		// Limit frequency for MCH
diff --git a/src/northbridge/intel/x4x/raminit_ddr2.c b/src/northbridge/intel/x4x/raminit_ddr2.c
index 5acb127..5d457e6 100644
--- a/src/northbridge/intel/x4x/raminit_ddr2.c
+++ b/src/northbridge/intel/x4x/raminit_ddr2.c
@@ -293,11 +293,10 @@ static void launch_ddr2(struct sysinfo *s)
 
 	if (s->selected_timings.CAS == 5) {
 		launch2 = 0x00220201;
-	} else if ((s->selected_timings.mem_clk == MEM_CLOCK_800MHz) &&
-		   (s->selected_timings.CAS == 6)) {
+	} else if (s->selected_timings.CAS == 6) {
 		launch2 = 0x00230302;
 	} else {
-		die("Unsupported CAS & Frequency combination detected\n");
+		die("Unsupported CAS\n");
 	}
 
 	FOR_EACH_POPULATED_CHANNEL(s->dimms, i) {



More information about the coreboot-gerrit mailing list