aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/northbridge/amd/amdmct/mct_ddr3/mct_d.c336
-rw-r--r--src/northbridge/amd/amdmct/mct_ddr3/mct_d.h8
-rw-r--r--src/northbridge/amd/amdmct/mct_ddr3/mctdqs_d.c2
-rw-r--r--src/northbridge/amd/amdmct/mct_ddr3/mctrci.c26
-rw-r--r--src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c4
-rw-r--r--src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c8
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 74d5a8d233..cb83fe1448 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 b72b9da59a..5f72ff383f 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 abb84ae488..4cc87de5a8 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 a63fe2e552..4455391d14 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 c1bb89e978..143290f4be 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 5deaca5cf6..f5bf9e3e6c 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);
}