[coreboot-gerrit] Patch set updated for coreboot: nb/amd/mct_ddr3: Add Family 15h tristate enable codes

Timothy Pearson (tpearson@raptorengineeringinc.com) gerrit at coreboot.org
Mon Nov 30 16:56:08 CET 2015


Timothy Pearson (tpearson at raptorengineeringinc.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/12060

-gerrit

commit 3fda6cb75aec1c96c00d971cae8b579c8105a301
Author: Timothy Pearson <tpearson at raptorengineeringinc.com>
Date:   Thu Aug 27 23:37:38 2015 -0500

    nb/amd/mct_ddr3: Add Family 15h tristate enable codes
    
    The Family 15h DRAM initialization did not set up the various
    tristate enable codes in the MCT.
    
    Add Family 15h tristate enable setup.  This fixes multiple
    DIMMs on a single channel.
    
    Change-Id: I0278656e98461882d0a64519dfde54a6cf28ab0f
    Signed-off-by: Timothy Pearson <tpearson at raptorengineeringinc.com>
---
 src/northbridge/amd/amdmct/mct_ddr3/mct_d.c    | 336 ++++++++++++++++++++-----
 src/northbridge/amd/amdmct/mct_ddr3/mct_d.h    |   8 +-
 src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c |   2 +-
 src/northbridge/amd/amdmct/mct_ddr3/mctrci.c   |  26 +-
 src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c   |   4 +
 src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c  |   8 +-
 6 files changed, 310 insertions(+), 74 deletions(-)

diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
index 74d5a8d..cb83fe1 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
@@ -1366,6 +1366,224 @@ static uint8_t fam15h_slow_access_mode(struct DCTStatStruc *pDCTstat, uint8_t dc
 	return slow_access;
 }
 
+static uint8_t fam15h_odt_tristate_enable_code(struct DCTStatStruc *pDCTstat, uint8_t dct)
+{
+	uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH);
+
+	uint8_t package_type;
+	uint8_t odt_tristate_code = 0;
+
+	package_type = mctGet_NVbits(NV_PACK_TYPE);
+
+	/* Obtain number of DIMMs on channel */
+	uint8_t dimm_count = pDCTstat->MAdimms[dct];
+	uint8_t rank_count_dimm0;
+	uint8_t rank_count_dimm1;
+
+	if (package_type == PT_GR) {
+		/* Socket G34 */
+		if (pDCTstat->Status & (1 << SB_Registered)) {
+			/* RDIMM */
+			/* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 104 */
+			if (MaxDimmsInstallable == 1) {
+				rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct];
+
+				if (rank_count_dimm0 == 1)
+					odt_tristate_code = 0xe;
+				else
+					odt_tristate_code = 0xa;
+			} else if (MaxDimmsInstallable == 2) {
+				if (dimm_count == 1) {
+					/* 1 DIMM detected */
+					rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct];
+
+					if (rank_count_dimm1 == 1)
+						odt_tristate_code = 0xd;
+					else
+						odt_tristate_code = 0x5;
+				} else if (dimm_count == 2) {
+					/* 2 DIMMs detected */
+					rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct];
+					rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct];
+
+					if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1))
+						odt_tristate_code = 0xc;
+					else if ((rank_count_dimm0 == 1) && (rank_count_dimm1 >= 2))
+						odt_tristate_code = 0x4;
+					else if ((rank_count_dimm0 >= 2) && (rank_count_dimm1 == 1))
+						odt_tristate_code = 0x8;
+					else
+						odt_tristate_code = 0x0;
+				}
+			} else if (MaxDimmsInstallable == 3) {
+				/* TODO
+				 * 3 DIMM/channel support unimplemented
+				 */
+			}
+		} else if (pDCTstat->Status & (1 << SB_LoadReduced)) {
+			/* LRDIMM */
+
+			/* TODO
+			 * Implement LRDIMM support
+			 * See Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 105
+			 */
+		} else {
+			/* UDIMM */
+			/* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 103 */
+			if (MaxDimmsInstallable == 1) {
+				rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct];
+
+				if (rank_count_dimm0 == 1)
+					odt_tristate_code = 0xe;
+				else
+					odt_tristate_code = 0xa;
+			} else if (MaxDimmsInstallable == 2) {
+				if (dimm_count == 1) {
+					/* 1 DIMM detected */
+					rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct];
+
+					if (rank_count_dimm0 == 1)
+						odt_tristate_code = 0xd;
+					else
+						odt_tristate_code = 0x5;
+				} else if (dimm_count == 2) {
+					/* 2 DIMMs detected */
+					rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct];
+					rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct];
+
+					if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1))
+						odt_tristate_code = 0xc;
+					else if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 2))
+						odt_tristate_code = 0x4;
+					else if ((rank_count_dimm0 == 2) && (rank_count_dimm1 == 1))
+						odt_tristate_code = 0x8;
+					else
+						odt_tristate_code = 0x0;
+				}
+			} else if (MaxDimmsInstallable == 3) {
+				/* TODO
+				 * 3 DIMM/channel support unimplemented
+				 */
+			}
+		}
+	} else {
+		/* TODO
+		 * Other socket support unimplemented
+		 */
+	}
+
+	return odt_tristate_code;
+}
+
+static uint8_t fam15h_cs_tristate_enable_code(struct DCTStatStruc *pDCTstat, uint8_t dct)
+{
+	uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH);
+
+	uint8_t package_type;
+	uint8_t cs_tristate_code = 0;
+
+	package_type = mctGet_NVbits(NV_PACK_TYPE);
+
+	/* Obtain number of DIMMs on channel */
+	uint8_t dimm_count = pDCTstat->MAdimms[dct];
+	uint8_t rank_count_dimm0;
+	uint8_t rank_count_dimm1;
+
+	if (package_type == PT_GR) {
+		/* Socket G34 */
+		if (pDCTstat->Status & (1 << SB_Registered)) {
+			/* RDIMM */
+			/* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 104 */
+			if (MaxDimmsInstallable == 1) {
+				rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct];
+
+				if (rank_count_dimm0 < 4)
+					cs_tristate_code = 0xfc;
+				else
+					cs_tristate_code = 0xcc;
+			} else if (MaxDimmsInstallable == 2) {
+				if (dimm_count == 1) {
+					/* 1 DIMM detected */
+					rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct];
+
+					if (rank_count_dimm1 < 4)
+						cs_tristate_code = 0xf3;
+					else
+						cs_tristate_code = 0x33;
+				} else if (dimm_count == 2) {
+					/* 2 DIMMs detected */
+					rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct];
+					rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct];
+
+					if ((rank_count_dimm0 < 4) && (rank_count_dimm1 < 4))
+						cs_tristate_code = 0xf0;
+					else if ((rank_count_dimm0 < 4) && (rank_count_dimm1 == 4))
+						cs_tristate_code = 0x30;
+					else if ((rank_count_dimm0 == 4) && (rank_count_dimm1 < 4))
+						cs_tristate_code = 0xc0;
+					else
+						cs_tristate_code = 0x0;
+				}
+			} else if (MaxDimmsInstallable == 3) {
+				/* TODO
+				 * 3 DIMM/channel support unimplemented
+				 */
+			}
+		} else if (pDCTstat->Status & (1 << SB_LoadReduced)) {
+			/* LRDIMM */
+
+			/* TODO
+			 * Implement LRDIMM support
+			 * See Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 105
+			 */
+		} else {
+			/* UDIMM */
+			/* Fam15h BKDG Rev. 3.14 section 2.10.5.10.1 Table 103 */
+			if (MaxDimmsInstallable == 1) {
+				rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct];
+
+				if (rank_count_dimm0 == 1)
+					cs_tristate_code = 0xfe;
+				else
+					cs_tristate_code = 0xfc;
+			} else if (MaxDimmsInstallable == 2) {
+				if (dimm_count == 1) {
+					/* 1 DIMM detected */
+					rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct];
+
+					if (rank_count_dimm0 == 1)
+						cs_tristate_code = 0xfb;
+					else
+						cs_tristate_code = 0xf3;
+				} else if (dimm_count == 2) {
+					/* 2 DIMMs detected */
+					rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct];
+					rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct];
+
+					if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 1))
+						cs_tristate_code = 0xfa;
+					else if ((rank_count_dimm0 == 1) && (rank_count_dimm1 == 2))
+						cs_tristate_code = 0xf2;
+					else if ((rank_count_dimm0 == 2) && (rank_count_dimm1 == 1))
+						cs_tristate_code = 0xf8;
+					else
+						cs_tristate_code = 0xf0;
+				}
+			} else if (MaxDimmsInstallable == 3) {
+				/* TODO
+				 * 3 DIMM/channel support unimplemented
+				 */
+			}
+		}
+	} else {
+		/* TODO
+		 * Other socket support unimplemented
+		 */
+	}
+
+	return cs_tristate_code;
+}
+
 static void set_2t_configuration(struct MCTStatStruc *pMCTstat,
 				struct DCTStatStruc *pDCTstat, u8 dct)
 {
@@ -2315,20 +2533,16 @@ static void fam15EnableTrainingMode(struct MCTStatStruc *pMCTstat,
 		if (memclk_index <= 0x6) {
 			delay = 0x5;
 			delay2 = 0x3;
-		}
-		else if (memclk_index == 0xa) {
+		} else if (memclk_index == 0xa) {
 			delay = 0x6;
 			delay2 = 0x3;
-		}
-		else if (memclk_index == 0xe) {
+		} else if (memclk_index == 0xe) {
 			delay = 0x7;
 			delay2 = 0x4;
-		}
-		else if (memclk_index == 0x12) {
+		} else if (memclk_index == 0x12) {
 			delay = 0x8;
 			delay2 = 0x4;
-		}
-		else if (memclk_index == 0x16) {
+		} else if (memclk_index == 0x16) {
 			delay = 0xa;
 			delay2 = 0x5;
 		}
@@ -3346,8 +3560,7 @@ static void SPD2ndTiming(struct MCTStatStruc *pMCTstat,
 			tCK16x = 40;
 		else
 			tCK16x = 48;
-	}
-	else {
+	} else {
 		if (byte == 7)
 			tCK16x = 20;
 		else if (byte == 6)
@@ -4674,13 +4887,13 @@ static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat,
 					else
 						pDCTstat->RegMan1Present |= 1 << i;
 				}
-				/* Get Control word values for RC3. We dont need it. */
+				/* Get control word value for RC3 */
 				byte = pDCTstat->spd_data.spd_bytes[i][70];
-				pDCTstat->CtrlWrd3 |= (byte >> 4) << (i << 2); /* C3 = SPD byte 70 [7:4] */
-				/* Get Control word values for RC4, and RC5 */
+				pDCTstat->CtrlWrd3 |= ((byte >> 4) & 0xf) << (i << 2);	/* RC3 = SPD byte 70 [7:4] */
+				/* Get control word values for RC4 and RC5 */
 				byte = pDCTstat->spd_data.spd_bytes[i][71];
-				pDCTstat->CtrlWrd4 |= (byte & 0xFF) << (i << 2); /* RC4 = SPD byte 71 [3:0] */
-				pDCTstat->CtrlWrd5 |= (byte >> 4) << (i << 2); /* RC5 = SPD byte 71 [7:4] */
+				pDCTstat->CtrlWrd4 |= (byte & 0xf) << (i << 2);		/* RC4 = SPD byte 71 [3:0] */
+				pDCTstat->CtrlWrd5 |= ((byte >> 4) & 0xf) << (i << 2);	/* RC5 = SPD byte 71 [7:4] */
 			}
 		}
 	}
@@ -5866,23 +6079,27 @@ static void SetCSTriState(struct MCTStatStruc *pMCTstat,
 	u32 val;
 	u32 dev = pDCTstat->dev_dct;
 	u32 index_reg = 0x98;
-	u32 index;
 	u16 word;
 
-	/* Tri-state unused chipselects when motherboard
-	   termination is available */
+	if (is_fam15h()) {
+		word = fam15h_cs_tristate_enable_code(pDCTstat, dct);
+	} else {
+		/* Tri-state unused chipselects when motherboard
+		termination is available */
 
-	/* FIXME: skip for Ax */
+		/* FIXME: skip for Ax */
 
-	word = pDCTstat->CSPresent;
-	if (pDCTstat->Status & (1 << SB_Registered)) {
-		word |= (word & 0x55) << 1;
+		word = pDCTstat->CSPresent;
+		if (pDCTstat->Status & (1 << SB_Registered)) {
+			word |= (word & 0x55) << 1;
+		}
+		word = (~word) & 0xff;
 	}
-	word = (~word) & 0xFF;
-	index  = 0x0c;
-	val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index);
+
+	val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c);
+	val &= ~0xff;
 	val |= word;
-	Set_NB32_index_wait_DCT(dev, dct, index_reg, index, val);
+	Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c, val);
 }
 
 static void SetCKETriState(struct MCTStatStruc *pMCTstat,
@@ -5891,7 +6108,6 @@ static void SetCKETriState(struct MCTStatStruc *pMCTstat,
 	u32 val;
 	u32 dev;
 	u32 index_reg = 0x98;
-	u32 index;
 	u16 word;
 
 	/* Tri-state unused CKEs when motherboard termination is available */
@@ -5901,15 +6117,13 @@ static void SetCKETriState(struct MCTStatStruc *pMCTstat,
 	dev = pDCTstat->dev_dct;
 	word = pDCTstat->CSPresent;
 
-	index  = 0x0c;
-	val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index);
+	val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c);
+	val &= ~(0x3 << 12);
 	if ((word & 0x55) == 0)
 		val |= 1 << 12;
-
-	if ((word & 0xAA) == 0)
+	if ((word & 0xaa) == 0)
 		val |= 1 << 13;
-
-	Set_NB32_index_wait_DCT(dev, dct, index_reg, index, val);
+	Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c, val);
 }
 
 static void SetODTTriState(struct MCTStatStruc *pMCTstat,
@@ -5919,42 +6133,44 @@ static void SetODTTriState(struct MCTStatStruc *pMCTstat,
 	u32 dev;
 	u32 index_reg = 0x98;
 	u8 cs;
-	u32 index;
 	u8 odt;
 	u8 max_dimms;
 
-	/* FIXME: skip for Ax */
-
 	dev = pDCTstat->dev_dct;
 
-	/* Tri-state unused ODTs when motherboard termination is available */
-	max_dimms = (u8) mctGet_NVbits(NV_MAX_DIMMS);
-	odt = 0x0F;	/* ODT tri-state setting */
-
-	if (pDCTstat->Status & (1 <<SB_Registered)) {
-		for (cs = 0; cs < 8; cs += 2) {
-			if (pDCTstat->CSPresent & (1 << cs)) {
-				odt &= ~(1 << (cs / 2));
-				if (mctGet_NVbits(NV_4RANKType) != 0) { /* quad-rank capable platform */
-					if (pDCTstat->CSPresent & (1 << (cs + 1)))
-						odt &= ~(4 << (cs / 2));
+	if (is_fam15h()) {
+		odt = fam15h_odt_tristate_enable_code(pDCTstat, dct);
+	} else {
+		/* FIXME: skip for Ax */
+
+		/* Tri-state unused ODTs when motherboard termination is available */
+		max_dimms = (u8) mctGet_NVbits(NV_MAX_DIMMS);
+		odt = 0x0f;	/* ODT tri-state setting */
+
+		if (pDCTstat->Status & (1 <<SB_Registered)) {
+			for (cs = 0; cs < 8; cs += 2) {
+				if (pDCTstat->CSPresent & (1 << cs)) {
+					odt &= ~(1 << (cs / 2));
+					if (mctGet_NVbits(NV_4RANKType) != 0) { /* quad-rank capable platform */
+						if (pDCTstat->CSPresent & (1 << (cs + 1)))
+							odt &= ~(4 << (cs / 2));
+					}
 				}
 			}
+		} else {		/* AM3 package */
+			val = ~(pDCTstat->CSPresent);
+			odt = val & 9;	/* swap bits 1 and 2 */
+			if (val & (1 << 1))
+				odt |= 1 << 2;
+			if (val & (1 << 2))
+				odt |= 1 << 1;
 		}
-	} else {		/* AM3 package */
-		val = ~(pDCTstat->CSPresent);
-		odt = val & 9;	/* swap bits 1 and 2 */
-		if (val & (1 << 1))
-			odt |= 1 << 2;
-		if (val & (1 << 2))
-			odt |= 1 << 1;
 	}
 
-	index  = 0x0C;
-	val = Get_NB32_index_wait_DCT(dev, dct, index_reg, index);
-	val |= ((odt & 0xFF) << 8);	/* set bits 11:8 ODTTriState[3:0] */
-	Set_NB32_index_wait_DCT(dev, dct, index_reg, index, val);
-
+	val = Get_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c);
+	val &= ~(0xf << 8);		/* ODTTri = odt */
+	val |= (odt & 0xf) << 8;
+	Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0000000c, val);
 }
 
 /* Family 15h */
@@ -6524,7 +6740,7 @@ static void mct_ProgramODT_D(struct MCTStatStruc *pMCTstat,
 		dword |= (read_odt_delay & 0xf);
 		Set_NB32_DCT(dev, dct, 0x240, dword);
 
-		printk(BIOS_SPEW, "Programmed ODT pattern %08x %08x %08x %08x\n", odt_pattern_0, odt_pattern_1, odt_pattern_2, odt_pattern_3);
+		printk(BIOS_SPEW, "Programmed DCT %d ODT pattern %08x %08x %08x %08x\n", dct, odt_pattern_0, odt_pattern_1, odt_pattern_2, odt_pattern_3);
 	} else if (pDCTstat->LogicalCPUID & AMD_DR_Dx) {
 		if (pDCTstat->Speed == 3)
 			dword = 0x00000800;
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
index b72b9da..5f72ff3 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
@@ -578,7 +578,7 @@ struct DCTStatStruc {		/* A per Node structure*/
 	uint8_t NbPstateThreshold;
 	uint8_t NbPstateHi;
 
-/* New for LB Support */
+	/* New for LB Support */
 	u8 NodePresent;
 	u32 dev_host;
 	u32 dev_map;
@@ -588,9 +588,9 @@ struct DCTStatStruc {		/* A per Node structure*/
 	u32 dev_nbctl;
 	u8 TargetFreq;
 	u8 TargetCASL;
-	u8 CtrlWrd3;
-	u8 CtrlWrd4;
-	u8 CtrlWrd5;
+	uint32_t CtrlWrd3;
+	uint32_t CtrlWrd4;
+	uint32_t CtrlWrd5;
 	u8 DqsRdWrPos_Saved;
 	u8 DqsRcvEnGrossMax;
 	u8 DqsRcvEnGrossMin;
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
index 5edb22f..6aba8da 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c
@@ -1017,7 +1017,7 @@ static void Calc_SetMaxRdLatency_D_Fam15(struct MCTStatStruc *pMCTstat,
 		pDCTstat->CH_MaxRdLat[dct] = n - 1;
 
 #if DQS_TRAIN_DEBUG > 0
-	printk(BIOS_DEBUG, "%s: CH_MaxRdLat[%d]: %03x\n", __func__, dct, pDCTstat->CH_MaxRdLat[dct]);
+		printk(BIOS_DEBUG, "%s: CH_MaxRdLat[%d]: %03x\n", __func__, dct, pDCTstat->CH_MaxRdLat[dct]);
 #endif
 	}
 
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c b/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c
index a63fe2e..4455391 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c
@@ -14,7 +14,7 @@
  * GNU General Public License for more details.
  */
 
-static uint8_t fam15h_rdimm_rc2_control_code(struct DCTStatStruc *pDCTstat, uint8_t dct)
+static uint8_t fam15h_rdimm_rc2_ibt_code(struct DCTStatStruc *pDCTstat, uint8_t dct)
 {
 	uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH);
 
@@ -157,7 +157,7 @@ static u32 mct_ControlRC(struct MCTStatStruc *pMCTstat,
 			val = 0xc; /* if single rank, set DBA1 and DBA0 */
 	} else if (CtrlWordNum == 2) {
 		if (is_fam15h()) {
-			val = fam15h_rdimm_rc2_control_code(pDCTstat, dct);
+			val = (fam15h_rdimm_rc2_ibt_code(pDCTstat, dct) & 0x1) << 2;
 		} else {
 			if (package_type == PT_GR) {
 				/* Socket G34 */
@@ -174,10 +174,14 @@ static u32 mct_ControlRC(struct MCTStatStruc *pMCTstat,
 	} else if (CtrlWordNum == 5) {
 		val = (pDCTstat->CtrlWrd5 >> (DimmNum << 2)) & 0xff;
 	} else if (CtrlWordNum == 8) {
-		if (package_type == PT_GR) {
-			/* Socket G34 */
-			if (MaxDimmsInstallable == 2) {
-				val = 0x0;
+		if (is_fam15h()) {
+			val = (fam15h_rdimm_rc2_ibt_code(pDCTstat, dct) & 0xe) >> 1;
+		} else {
+			if (package_type == PT_GR) {
+				/* Socket G34 */
+				if (MaxDimmsInstallable == 2) {
+					val = 0x0;
+				}
 			}
 		}
 	} else if (CtrlWordNum == 9) {
@@ -229,7 +233,11 @@ void mct_DramControlReg_Init_D(struct MCTStatStruc *pMCTstat,
 
 	mct_Wait(1200);
 
-	for (MrsChipSel = 0; MrsChipSel < 8; MrsChipSel ++, MrsChipSel ++) {
+	pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[dct];
+	if (pDCTstat->GangedMode & 1)
+		pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0];
+
+	for (MrsChipSel = 0; MrsChipSel < 8; MrsChipSel += 2) {
 		if (pDCTstat->CSPresent & (1 << MrsChipSel)) {
 			val = Get_NB32_DCT(dev, dct, 0xa8);
 			val &= ~(0xff << 8);
@@ -272,6 +280,10 @@ void FreqChgCtrlWrd(struct MCTStatStruc *pMCTstat,
 	u32 val;
 	uint16_t mem_freq;
 
+	pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[dct];
+	if (pDCTstat->GangedMode & 1)
+		pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0];
+
 	pDCTstat->DIMMAutoSpeed = pDCTstat->TargetFreq;
 	mem_freq = memclk_to_freq(pDCTstat->TargetFreq);
 	for (MrsChipSel=0; MrsChipSel < 8; MrsChipSel++, MrsChipSel++) {
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c b/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c
index c1bb89e..143290f 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c
@@ -841,6 +841,10 @@ void mct_DramInit_Sw_D(struct MCTStatStruc *pMCTstat,
 			 */
 	}
 
+	pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[dct];
+	if (pDCTstat->GangedMode & 1)
+		pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0];
+
 	/* The following steps are performed once for unbuffered DIMMs and once for each
 	 * chip select on registered DIMMs: */
 	for (MrsChipSel = 0; MrsChipSel < 8; MrsChipSel++) {
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
index 5deaca5..f5bf9e3 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
@@ -921,7 +921,7 @@ void prepareDimms(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat,
  *       OUT
  * ----------------------------------------------------------------------------
  */
-void programODT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, uint8_t dct, u8 dimm)
+void programODT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t dimm)
 {
 	sMCTStruct *pMCTData = pDCTstat->C_MCTPtr;
 	sDCTStruct *pDCTData = pDCTstat->C_DCTPtr[dct];
@@ -929,6 +929,10 @@ void programODT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, ui
 	u8 WrLvOdt1=0;
 
 	if (is_fam15h()) {
+		/* On Family15h processors, the value for the specific CS being targetted
+		 * is taken from F2x238 / F2x23C as appropriate, then loaded into F2x9C_x0000_0008
+		 */
+
 		/* Convert DIMM number to CS */
 		uint32_t dword;
 		uint8_t cs;
@@ -963,7 +967,7 @@ void programODT(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat, ui
 	set_DCT_ADDR_Bits(pDCTData, dct, pDCTData->NodeId, FUN_DCT,
 			DRAM_ADD_DCT_PHY_CONTROL_REG, 8, 11, (u32)WrLvOdt1);
 
-	printk(BIOS_SPEW, "Programmed DCT %d write levelling ODT pattern %08x\n", dct, WrLvOdt1);
+	printk(BIOS_SPEW, "Programmed DCT %d write levelling ODT pattern %08x from DIMM %d data\n", dct, WrLvOdt1, dimm);
 
 }
 



More information about the coreboot-gerrit mailing list