[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
Sun Jul 24 16:27:11 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 35498f4ab3878c72801ff9e2ae5c49bc79942950
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.
    
    NEEDS TESTING
    
    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