summaryrefslogtreecommitdiff
path: root/src/northbridge/amd
diff options
context:
space:
mode:
authorTimothy Pearson <tpearson@raptorengineeringinc.com>2015-08-27 23:37:38 -0500
committerMartin Roth <martinroth@google.com>2015-12-01 16:31:02 +0100
commit5edc6695f8fb129a89a80af592b8b3342377a871 (patch)
treee8f0190406a76578a4f455e206c2f2d40b672538 /src/northbridge/amd
parentd45a3477b79df14ed13a64e580a26380ebfb2565 (diff)
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@raptorengineeringinc.com> Reviewed-on: https://review.coreboot.org/12060 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth <martinroth@google.com> Tested-by: Raptor Engineering Automated Test Stand <noreply@raptorengineeringinc.com>
Diffstat (limited to 'src/northbridge/amd')
-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);
}