summaryrefslogtreecommitdiffstats
path: root/resources/libreboot/patch/kgpe-d16/0085-northbridge-amd-amdmct-mct_ddr3-Fix-RDIMM-errors-due.patch
diff options
context:
space:
mode:
Diffstat (limited to 'resources/libreboot/patch/kgpe-d16/0085-northbridge-amd-amdmct-mct_ddr3-Fix-RDIMM-errors-due.patch')
-rw-r--r--resources/libreboot/patch/kgpe-d16/0085-northbridge-amd-amdmct-mct_ddr3-Fix-RDIMM-errors-due.patch411
1 files changed, 411 insertions, 0 deletions
diff --git a/resources/libreboot/patch/kgpe-d16/0085-northbridge-amd-amdmct-mct_ddr3-Fix-RDIMM-errors-due.patch b/resources/libreboot/patch/kgpe-d16/0085-northbridge-amd-amdmct-mct_ddr3-Fix-RDIMM-errors-due.patch
new file mode 100644
index 0000000..351906e
--- /dev/null
+++ b/resources/libreboot/patch/kgpe-d16/0085-northbridge-amd-amdmct-mct_ddr3-Fix-RDIMM-errors-due.patch
@@ -0,0 +1,411 @@
+From 4faf00104dc3474340520213fc0e5f15f14e7146 Mon Sep 17 00:00:00 2001
+From: Timothy Pearson <kb9vqf@pearsoncomputing.net>
+Date: Sat, 25 Jul 2015 01:23:17 -0500
+Subject: [PATCH 085/146] northbridge/amd/amdmct/mct_ddr3: Fix RDIMM errors
+ due to undefined number of slots
+
+---
+ src/northbridge/amd/amdmct/mct/mct_d.h | 2 ++
+ src/northbridge/amd/amdmct/mct_ddr3/mct_d.c | 40 +++++++-----------------
+ src/northbridge/amd/amdmct/mct_ddr3/mct_d.h | 2 ++
+ src/northbridge/amd/amdmct/mct_ddr3/mctproc.c | 6 +---
+ src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c | 12 ++-----
+ src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c | 6 +---
+ src/northbridge/amd/amdmct/mct_ddr3/mctwl.c | 2 --
+ src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c | 24 +++++---------
+ src/northbridge/amd/amdmct/mct_ddr3/modtrdim.c | 11 ++++---
+ src/northbridge/amd/amdmct/mct_ddr3/mwlc_d.h | 4 ---
+ src/northbridge/amd/amdmct/wrappers/mcti_d.c | 7 +++++
+ 11 files changed, 41 insertions(+), 75 deletions(-)
+
+diff --git a/src/northbridge/amd/amdmct/mct/mct_d.h b/src/northbridge/amd/amdmct/mct/mct_d.h
+index 6b6194d..34f7f4c 100644
+--- a/src/northbridge/amd/amdmct/mct/mct_d.h
++++ b/src/northbridge/amd/amdmct/mct/mct_d.h
+@@ -688,6 +688,8 @@ struct DCTStatStruc { /* A per Node structure*/
+ xx0b = disable
+ yy1b = enable with DctSelIntLvAddr set to yyb */
+
++#define NV_MAX_DIMMS_PER_CH 64 /* Maximum number of DIMMs per channel */
++
+ /*===============================================================================
+ CBMEM storage
+ ===============================================================================*/
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
+index 6de8140..030372d 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
+@@ -803,11 +803,7 @@ static uint32_t fam15h_phy_predriver_clk_calibration_code(struct DCTStatStruc *p
+
+ static uint32_t fam15h_output_driver_compensation_code(struct DCTStatStruc *pDCTstat, uint8_t dct)
+ {
+- /* FIXME
+- * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
+- * For now assume a maximum of 2 DIMMs per channel can be installed
+- */
+- uint8_t MaxDimmsInstallable = 2;
++ uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH);
+
+ uint8_t package_type;
+ uint32_t calibration_code = 0;
+@@ -877,7 +873,7 @@ static uint32_t fam15h_output_driver_compensation_code(struct DCTStatStruc *pDCT
+ /* 2 DIMMs detected */
+ rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct];
+ rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct];
+-
++
+ if (MemClkFreq == 0x4) {
+ /* DDR3-667 */
+ calibration_code = 0x10222222;
+@@ -945,7 +941,7 @@ static uint32_t fam15h_output_driver_compensation_code(struct DCTStatStruc *pDCT
+ /* 2 DIMMs detected */
+ rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct];
+ rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct];
+-
++
+ if (MemClkFreq == 0x4) {
+ /* DDR3-667 */
+ calibration_code = 0x10222222;
+@@ -983,11 +979,7 @@ static uint32_t fam15h_output_driver_compensation_code(struct DCTStatStruc *pDCT
+
+ static uint32_t fam15h_address_timing_compensation_code(struct DCTStatStruc *pDCTstat, uint8_t dct)
+ {
+- /* FIXME
+- * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
+- * For now assume a maximum of 2 DIMMs per channel can be installed
+- */
+- uint8_t MaxDimmsInstallable = 2;
++ uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH);
+
+ uint8_t package_type;
+ uint32_t calibration_code = 0;
+@@ -1066,7 +1058,7 @@ static uint32_t fam15h_address_timing_compensation_code(struct DCTStatStruc *pDC
+ /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 73 */
+ if (MaxDimmsInstallable == 1) {
+ rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct];
+-
++
+ if (MemClkFreq == 0x4) {
+ /* DDR3-667 */
+ if (rank_count_dimm0 == 1)
+@@ -1099,7 +1091,7 @@ static uint32_t fam15h_address_timing_compensation_code(struct DCTStatStruc *pDC
+ if (dimm_count == 1) {
+ /* 1 DIMM detected */
+ rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct];
+-
++
+ if (MemClkFreq == 0x4) {
+ /* DDR3-667 */
+ if (rank_count_dimm0 == 1)
+@@ -1129,7 +1121,7 @@ static uint32_t fam15h_address_timing_compensation_code(struct DCTStatStruc *pDC
+ /* 2 DIMMs detected */
+ rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct];
+ rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct];
+-
++
+ if (MemClkFreq == 0x4) {
+ /* DDR3-667 */
+ calibration_code = 0x00390039;
+@@ -1165,11 +1157,7 @@ static uint32_t fam15h_address_timing_compensation_code(struct DCTStatStruc *pDC
+
+ static uint8_t fam15h_slow_access_mode(struct DCTStatStruc *pDCTstat, uint8_t dct)
+ {
+- /* FIXME
+- * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
+- * For now assume a maximum of 2 DIMMs per channel can be installed
+- */
+- uint8_t MaxDimmsInstallable = 2;
++ uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH);
+
+ uint8_t package_type;
+ uint32_t slow_access = 0;
+@@ -1197,7 +1185,7 @@ static uint8_t fam15h_slow_access_mode(struct DCTStatStruc *pDCTstat, uint8_t dc
+ /* Fam15h BKDG Rev. 3.14 section 2.10.5.3.4 Table 73 */
+ if (MaxDimmsInstallable == 1) {
+ rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct];
+-
++
+ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)
+ || (MemClkFreq == 0xa) | (MemClkFreq == 0xe)) {
+ /* DDR3-667 - DDR3-1333 */
+@@ -1213,7 +1201,7 @@ static uint8_t fam15h_slow_access_mode(struct DCTStatStruc *pDCTstat, uint8_t dc
+ if (dimm_count == 1) {
+ /* 1 DIMM detected */
+ rank_count_dimm0 = pDCTstat->DimmRanks[(1 * 2) + dct];
+-
++
+ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)
+ || (MemClkFreq == 0xa) | (MemClkFreq == 0xe)) {
+ /* DDR3-667 - DDR3-1333 */
+@@ -1229,7 +1217,7 @@ static uint8_t fam15h_slow_access_mode(struct DCTStatStruc *pDCTstat, uint8_t dc
+ /* 2 DIMMs detected */
+ rank_count_dimm0 = pDCTstat->DimmRanks[(0 * 2) + dct];
+ rank_count_dimm1 = pDCTstat->DimmRanks[(1 * 2) + dct];
+-
++
+ if ((MemClkFreq == 0x4) || (MemClkFreq == 0x6)
+ || (MemClkFreq == 0xa)) {
+ /* DDR3-667 - DDR3-1066 */
+@@ -5857,11 +5845,7 @@ static void mct_ProgramODT_D(struct MCTStatStruc *pMCTstat,
+
+ printk(BIOS_DEBUG, "%s: Start\n", __func__);
+
+- /* FIXME
+- * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
+- * For now assume a maximum of 2 DIMMs per channel can be installed
+- */
+- uint8_t MaxDimmsInstallable = 2;
++ uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH);
+
+ if (is_fam15h()) {
+ /* Obtain number of DIMMs on channel */
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
+index 7bc392b..6b5d8c1 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.h
+@@ -957,6 +957,8 @@ struct amd_s3_persistent_data {
+ xx0b = disable
+ yy1b = enable with DctSelIntLvAddr set to yyb */
+
++#define NV_MAX_DIMMS_PER_CH 64 /* Maximum number of DIMMs per channel */
++
+ /*===============================================================================
+ CBMEM storage
+ ===============================================================================*/
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c b/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c
+index 32b447f..738304e 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mctproc.c
+@@ -23,11 +23,7 @@ u32 mct_SetDramConfigMisc2(struct DCTStatStruc *pDCTstat, u8 dct, u32 misc2)
+ {
+ u32 val;
+
+- /* FIXME
+- * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
+- * For now assume a maximum of 2 DIMMs per channel can be installed
+- */
+- uint8_t MaxDimmsInstallable = 2;
++ uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH);
+
+ if (pDCTstat->LogicalCPUID & AMD_FAM15_ALL) {
+ uint8_t cs_mux_45;
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c b/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c
+index dfbd2d9..6a2c2a7 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mctsdi.c
+@@ -51,11 +51,7 @@ static uint8_t fam15_rttwr(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t d
+ else
+ frequency_index = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x7;
+
+- /* FIXME
+- * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
+- * For now assume a maximum of 2 DIMMs per channel can be installed
+- */
+- uint8_t MaxDimmsInstallable = 2;
++ uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH);
+
+ if (is_fam15h()) {
+ if (pDCTstat->Status & (1 << SB_LoadReduced)) {
+@@ -184,11 +180,7 @@ static uint8_t fam15_rttnom(struct DCTStatStruc *pDCTstat, uint8_t dct, uint8_t
+ else
+ frequency_index = Get_NB32_DCT(pDCTstat->dev_dct, dct, 0x94) & 0x7;
+
+- /* FIXME
+- * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
+- * For now assume a maximum of 2 DIMMs per channel can be installed
+- */
+- uint8_t MaxDimmsInstallable = 2;
++ uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH);
+
+ if (is_fam15h()) {
+ if (pDCTstat->Status & (1 << SB_LoadReduced)) {
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c
+index 1d41aa4..3655e84 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mctsrc.c
+@@ -105,11 +105,7 @@ static uint16_t fam15_receiver_enable_training_seed(struct DCTStatStruc *pDCTsta
+ uint32_t dword;
+ uint16_t seed = 0;
+
+- /* FIXME
+- * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
+- * For now assume a maximum of 2 DIMMs per channel can be installed
+- */
+- uint8_t MaxDimmsInstallable = 2;
++ uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH);
+
+ uint8_t channel = dct;
+ if (package_type == PT_GR) {
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c b/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c
+index 0ff4484..6b63ba0 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mctwl.c
+@@ -31,8 +31,6 @@ void PrepareC_MCT(struct MCTStatStruc *pMCTstat,
+ struct DCTStatStruc *pDCTstat)
+ {
+ pDCTstat->C_MCTPtr->AgesaDelay = AgesaDelay;
+- pDCTstat->C_MCTPtr->PlatMaxTotalDimms = mctGet_NVbits(NV_MAX_DIMMS);
+- pDCTstat->C_MCTPtr->PlatMaxDimmsDct = pDCTstat->C_MCTPtr->PlatMaxTotalDimms >> 1;
+ }
+
+ void PrepareC_DCT(struct MCTStatStruc *pMCTstat,
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
+index 9c18d12..26e1374 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
+@@ -191,7 +191,7 @@ uint8_t AgesaHwWlPhase2(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCT
+ uint8_t index = (uint8_t)(MAX_BYTE_LANES * dimm);
+
+ /* Calculate the Critical Gross Delay */
+- for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
++ for (ByteLane = 0; ByteLane < MAX_BYTE_LANES; ByteLane++) {
+ /* Calculate the gross delay differential for this lane */
+ gross_diff[ByteLane] = pDCTData->WLSeedGrossDelay[index+ByteLane] + pDCTData->WLGrossDelay[index+ByteLane];
+ gross_diff[ByteLane] -= pDCTData->WLSeedPreGrossDelay[index+ByteLane];
+@@ -419,11 +419,7 @@ static uint16_t unbuffered_dimm_nominal_termination_emrs(uint8_t number_of_dimms
+ {
+ uint16_t term;
+
+- /* FIXME
+- * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
+- * For now assume a maximum of 2 DIMMs per channel can be installed
+- */
+- uint8_t MaxDimmsInstallable = 2;
++ uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH);
+
+ if (number_of_dimms == 1) {
+ if (MaxDimmsInstallable < 3) {
+@@ -452,11 +448,7 @@ static uint16_t unbuffered_dimm_dynamic_termination_emrs(uint8_t number_of_dimms
+ {
+ uint16_t term;
+
+- /* FIXME
+- * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
+- * For now assume a maximum of 2 DIMMs per channel can be installed
+- */
+- uint8_t MaxDimmsInstallable = 2;
++ uint8_t MaxDimmsInstallable = mctGet_NVbits(NV_MAX_DIMMS_PER_CH);
+
+ if (number_of_dimms == 1) {
+ if (MaxDimmsInstallable < 3) {
+@@ -574,8 +566,8 @@ void prepareDimms(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat,
+ if (number_of_dimms > 1) {
+ if (rank == 0) {
+ /* Get Rtt_WR for the current DIMM and rank */
+- uint16_t dynamic_term = unbuffered_dimm_dynamic_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[currDimm]);
+-
++ uint16_t dynamic_term = unbuffered_dimm_dynamic_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm]);
++
+ /* Convert dynamic termination code to corresponding nominal termination code */
+ if (dynamic_term == 0x200)
+ tempW1 = 0x04;
+@@ -584,13 +576,13 @@ void prepareDimms(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat,
+ else
+ tempW1 = 0x0;
+ } else {
+- tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[currDimm], rank);
++ tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm], rank);
+ }
+ } else {
+- tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[currDimm], rank);
++ tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm], rank);
+ }
+ } else {
+- tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[currDimm], rank);
++ tempW1 = unbuffered_dimm_nominal_termination_emrs(pDCTData->MaxDimmsInstalled, MemClkFreq, pDCTData->DimmRanks[dimm], rank);
+ }
+ }
+ }
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/modtrdim.c b/src/northbridge/amd/amdmct/mct_ddr3/modtrdim.c
+index c92143c..bb4c3c0 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/modtrdim.c
++++ b/src/northbridge/amd/amdmct/mct_ddr3/modtrdim.c
+@@ -2,6 +2,7 @@
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010 Advanced Micro Devices, Inc.
++ * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -57,7 +58,7 @@ static u32 RttNomTargetRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 d
+ u32 tempW1;
+ tempW1 = 0;
+ if (wl) {
+- switch (pMCTData->PlatMaxDimmsDct) {
++ switch (mctGet_NVbits(NV_MAX_DIMMS_PER_CH)) {
+ case 2:
+ /* 2 dimms per channel */
+ if (pDCTData->MaxDimmsInstalled == 1) {
+@@ -111,7 +112,7 @@ static u32 RttNomTargetRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 d
+ ASSERT (FALSE);
+ }
+ } else {
+- switch (pMCTData->PlatMaxDimmsDct) {
++ switch (mctGet_NVbits(NV_MAX_DIMMS_PER_CH)) {
+ case 2:
+ /* 2 dimms per channel */
+ if ((pDCTData->DimmRanks[dimm] == 4) && (rank == 1)) {
+@@ -167,7 +168,7 @@ static u32 RttNomTargetRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 d
+ */
+ static u32 RttNomNonTargetRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BOOL wl, u8 MemClkFreq, u8 rank)
+ {
+- if ((wl) && (pMCTData->PlatMaxDimmsDct == 2) && (pDCTData->DimmRanks[dimm] == 2) && (rank == 1)) {
++ if ((wl) && (mctGet_NVbits(NV_MAX_DIMMS_PER_CH) == 2) && (pDCTData->DimmRanks[dimm] == 2) && (rank == 1)) {
+ return 0x00; /* for non-target dimm during WL, the second rank of a DR dimm need to have Rtt_Nom = OFF */
+ } else {
+ return RttNomTargetRegDimm (pMCTData, pDCTData, dimm, FALSE, MemClkFreq, rank); /* otherwise, the same as target dimm in normal mode. */
+@@ -197,7 +198,7 @@ static u32 RttWrRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm, BO
+ if (wl) {
+ tempW1 = 0x00; /* Rtt_WR = OFF */
+ } else {
+- switch (pMCTData->PlatMaxDimmsDct) {
++ switch (mctGet_NVbits(NV_MAX_DIMMS_PER_CH)) {
+ case 2:
+ if (pDCTData->MaxDimmsInstalled == 1) {
+ if (pDCTData->DimmRanks[dimm] != 4) {
+@@ -262,7 +263,7 @@ static u8 WrLvOdtRegDimm (sMCTStruct *pMCTData, sDCTStruct *pDCTData, u8 dimm)
+ }
+ i += 2;
+ }
+- if (pMCTData->PlatMaxDimmsDct == 2) {
++ if (mctGet_NVbits(NV_MAX_DIMMS_PER_CH) == 2) {
+ if ((pDCTData->DimmRanks[dimm] == 4) && (pDCTData->MaxDimmsInstalled != 1)) {
+ if (dimm >= 2) {
+ WrLvOdt1 = (u8)bitTestReset (WrLvOdt1, (dimm - 2));
+diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mwlc_d.h b/src/northbridge/amd/amdmct/mct_ddr3/mwlc_d.h
+index 162340e..12e7c4a 100644
+--- a/src/northbridge/amd/amdmct/mct_ddr3/mwlc_d.h
++++ b/src/northbridge/amd/amdmct/mct_ddr3/mwlc_d.h
+@@ -109,10 +109,6 @@
+
+ typedef struct _sMCTStruct
+ {
+- u8 PlatMaxTotalDimms; /* IBV defined total number of DIMMs */
+- /* on a particular node */
+- u8 PlatMaxDimmsDct; /* IBV defined maximum number of */
+- /* DIMMs on a DCT */
+ void (*AgesaDelay)(u32 delayval); /* IBV defined Delay Function */
+ } sMCTStruct;
+
+diff --git a/src/northbridge/amd/amdmct/wrappers/mcti_d.c b/src/northbridge/amd/amdmct/wrappers/mcti_d.c
+index 2376b20..85f117b 100644
+--- a/src/northbridge/amd/amdmct/wrappers/mcti_d.c
++++ b/src/northbridge/amd/amdmct/wrappers/mcti_d.c
+@@ -74,6 +74,13 @@ static u16 mctGet_NVbits(u8 index)
+ val = MAX_DIMMS_SUPPORTED;
+ //val = 8;
+ break;
++ case NV_MAX_DIMMS_PER_CH:
++ /* FIXME
++ * Mainboards need to be able to specify the maximum number of DIMMs installable per channel
++ * For now assume a maximum of 2 DIMMs per channel can be installed
++ */
++ val = 2;
++ break;
+ case NV_MAX_MEMCLK:
+ /* Maximum platform supported memclk */
+ val = MEM_MAX_LOAD_FREQ;
+--
+1.7.9.5
+