From 162cfc9db14b515dd154ff683049bd07b994d346 Mon Sep 17 00:00:00 2001
From: Timothy Pearson <tpearson@raptorengineeringinc.com>
Date: Sat, 25 Jul 2015 01:23:17 -0500
Subject: [PATCH 084/143] northbridge/amd/amdmct/mct_ddr3: Fix RDIMM errors
 due to undefined number of slots

Change-Id: I488511d6262ffa8207c442d133314aed0f75acfb
Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com>
---
 src/northbridge/amd/amdmct/mct/mct_d.h         |    2 ++
 src/northbridge/amd/amdmct/mct_ddr3/mct_d.c    |   24 ++++--------------------
 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  |   12 ++----------
 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, 27 insertions(+), 61 deletions(-)

diff --git a/src/northbridge/amd/amdmct/mct/mct_d.h b/src/northbridge/amd/amdmct/mct/mct_d.h
index 7569300..296f3f0 100644
--- a/src/northbridge/amd/amdmct/mct/mct_d.h
+++ b/src/northbridge/amd/amdmct/mct/mct_d.h
@@ -691,6 +691,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 cfdfd43..9a86c08 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;
@@ -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;
@@ -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;
@@ -5870,11 +5858,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 57641a1..9313673 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 85b8378..47ad152 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mhwlc_d.c
@@ -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) {
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 116fb92..c8572ef 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

