diff options
Diffstat (limited to 'resources/libreboot/patch/kgpe-d16/0127-northbridge-amd-amdmct-mct_ddr3-Fix-broken-support-f.patch')
-rw-r--r-- | resources/libreboot/patch/kgpe-d16/0127-northbridge-amd-amdmct-mct_ddr3-Fix-broken-support-f.patch | 602 |
1 files changed, 602 insertions, 0 deletions
diff --git a/resources/libreboot/patch/kgpe-d16/0127-northbridge-amd-amdmct-mct_ddr3-Fix-broken-support-f.patch b/resources/libreboot/patch/kgpe-d16/0127-northbridge-amd-amdmct-mct_ddr3-Fix-broken-support-f.patch new file mode 100644 index 00000000..d7cedd75 --- /dev/null +++ b/resources/libreboot/patch/kgpe-d16/0127-northbridge-amd-amdmct-mct_ddr3-Fix-broken-support-f.patch @@ -0,0 +1,602 @@ +From aabb2b44191d7a2716dd89a0b9f3488b2d657cb9 Mon Sep 17 00:00:00 2001 +From: Timothy Pearson <tpearson@raptorengineeringinc.com> +Date: Thu, 27 Aug 2015 23:37:38 -0500 +Subject: [PATCH 127/139] northbridge/amd/amdmct/mct_ddr3: Fix broken support + for multiple DIMMs on single channel + +Change-Id: I0278656e98461882d0a64519dfde54a6cf28ab0f +Signed-off-by: Timothy Pearson <tpearson@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 a11b227..5bc80f4 100644 +--- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c ++++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c +@@ -1360,6 +1360,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) + { +@@ -2299,20 +2517,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; + } +@@ -3329,8 +3543,7 @@ static void SPD2ndTiming(struct MCTStatStruc *pMCTstat, + tCK16x = 40; + else + tCK16x = 48; +- } +- else { ++ } else { + if (byte == 7) + tCK16x = 20; + else if (byte == 6) +@@ -4657,13 +4870,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] */ + } + } + } +@@ -5849,23 +6062,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, +@@ -5874,7 +6091,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 */ +@@ -5884,15 +6100,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, +@@ -5902,42 +6116,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 */ +@@ -6507,7 +6723,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 ec5658e..8bc4ec2 100644 +--- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h ++++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h +@@ -582,7 +582,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; +@@ -592,9 +592,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 d870f17..553a54a 100644 +--- a/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c ++++ b/src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c +@@ -1021,7 +1021,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 8fd2523..dec2bf8 100644 +--- a/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c ++++ b/src/northbridge/amd/amdmct/mct_ddr3/mctrci.c +@@ -18,7 +18,7 @@ + * Foundation, Inc. + */ + +-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); + +@@ -161,7 +161,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 */ +@@ -178,10 +178,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) { +@@ -233,7 +237,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); +@@ -276,6 +284,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 7804a38..5019faa 100644 +--- a/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c ++++ b/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c +@@ -845,6 +845,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 73b231e..5cbadc3 100644 +--- a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c ++++ b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c +@@ -925,7 +925,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]; +@@ -933,6 +933,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; +@@ -967,7 +971,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); + + } + +-- +1.9.1 + |