[coreboot-gerrit] Patch set updated for coreboot: nb/intel/sandybridge/raminit: fix two dimms per channel

Patrick Rudolph (siro@das-labor.org) gerrit at coreboot.org
Mon Jan 25 07:36:10 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/13415

-gerrit

commit 5647370290a95865196aa0b817bd55e3296035e3
Author: Patrick Rudolph <siro at das-labor.org>
Date:   Sun Jan 24 14:07:15 2016 +0100

    nb/intel/sandybridge/raminit: fix two dimms per channel
    
    Issue observed:
    The system boots with 4G in channel 0 and 4G in channel 1.
    The system doesn't boot with any combination of 4G + 1G in
    channel 0 and 4G in channel 1.
    In both cases DIMM1 failed, while DIMM0 showed no issues.
    
    Problem description:
    The CLK to CMD/CTL was off by a half clock cycle.
    The find the issue I X-Y plotted timC vs timB for every
    lane on the failing rank.
    You can see an offset by 32 units for timB, that is not present on
    other ranks.
    It turns out that the XOVER CMD/XOVER CTL enable bit for DIMM1 was
    missing in program_timings(), which caused the clock offset.
    
    Problem solution:
    Add two functions to calculate XOVER CMD and XOVER CTL and use both
    to set XOVER in program_timings() and dram_xover().
    
    Final testing result:
    The system boots with 4G + 1G in channel 0 and 4G in channel 1.
    
    Test system:
     * Intel IvyBridge
     * Gigabyte GA-B75M-D3H
    
    Change-Id: I88694c86054ade77e9d8bb2f1fdaf7bc559c1218
    Signed-off-by: Patrick Rudolph <siro at das-labor.org>
---
 src/northbridge/intel/sandybridge/raminit.c | 46 ++++++++++++++++++++---------
 1 file changed, 32 insertions(+), 14 deletions(-)

diff --git a/src/northbridge/intel/sandybridge/raminit.c b/src/northbridge/intel/sandybridge/raminit.c
index d3dfc23..9a50fd3 100644
--- a/src/northbridge/intel/sandybridge/raminit.c
+++ b/src/northbridge/intel/sandybridge/raminit.c
@@ -499,6 +499,28 @@ static u32 get_COMP2(u32 tCK)
 	return frq_comp2_map[get_FRQ(tCK) - 3];
 }
 
+static u32 get_XOVER_CLK(u8 rankmap)
+{
+	return rankmap << 24;
+}
+
+static u32 get_XOVER_CMD(u8 rankmap)
+{
+	u32 reg;
+
+	// enable xover cmd
+	reg = 0x4000;
+
+	// enable xover ctl
+	if (rankmap & 0x3)
+		reg |= 0x20000;
+
+	if (rankmap & 0xc)
+		reg |= 0x4000000;
+
+	return reg;
+}
+
 static void dram_timing(ramctr_timing * ctrl)
 {
 	u8 val;
@@ -700,20 +722,13 @@ static void dram_xover(ramctr_timing * ctrl)
 
 	FOR_ALL_CHANNELS {
 		// enable xover clk
+		reg = get_XOVER_CLK(ctrl->rankmap[channel]);
 		printram("XOVER CLK [%x] = %x\n", channel * 0x100 + 0xc14,
-		       (ctrl->rankmap[channel] << 24));
-		MCHBAR32(channel * 0x100 + 0xc14) = (ctrl->rankmap[channel] << 24);
+				reg);
+		MCHBAR32(channel * 0x100 + 0xc14) = reg;
 
-		// enable xover ctl
-		reg = 0;
-		if (ctrl->rankmap[channel] & 0x5) {
-			reg |= 0x20000;
-		}
-		if (ctrl->rankmap[channel] & 0xa) {
-			reg |= 0x4000000;
-		}
-		// enable xover cmd
-		reg |= 0x4000;
+		// enable xover ctl & xover cmd
+		reg = get_XOVER_CMD(ctrl->rankmap[channel]);
 		printram("XOVER CMD [%x] = %x\n", 0x100 * channel + 0x320c,
 		       reg);
 		MCHBAR32(0x100 * channel + 0x320c) = reg;
@@ -1489,14 +1504,16 @@ static void program_timings(ramctr_timing * ctrl, int channel)
 			break;
 		}
 
-	reg32 = (1 << 17) | (1 << 14);
+	/* enable CMD XOVER */
+	reg32 = get_XOVER_CMD(ctrl->rankmap[channel]);
 	reg32 |= ((slot320c[0] & 0x3f) << 6) | ((slot320c[0] & 0x40) << 9);
 	reg32 |= (slot320c[1] & 0x7f) << 18;
 	reg32 |= (full_shift & 0x3f) | ((full_shift & 0x40) << 6);
 
 	MCHBAR32(0x320c + 0x100 * channel) = reg32;
 
-	reg_c14 = ctrl->rankmap[channel] << 24;
+	/* enable CLK XOVER */
+	reg_c14 = get_XOVER_CLK(ctrl->rankmap[channel]);
 	reg_c18 = 0;
 
 	FOR_ALL_POPULATED_RANKS {
@@ -1506,6 +1523,7 @@ static void program_timings(ramctr_timing * ctrl, int channel)
 		if (shift < 0)
 			shift = 0;
 		offset_val_c14 = ctrl->reg_c14_offset + shift;
+		/* set CLK phase shift */
 		reg_c14 |= (offset_val_c14 & 0x3f) << (6 * slotrank);
 		reg_c18 |= ((offset_val_c14 >> 6) & 1) << slotrank;
 	}



More information about the coreboot-gerrit mailing list