From 337818cec631161582a2e65d73cf3e1f9a611bb7 Mon Sep 17 00:00:00 2001
From: Timothy Pearson <tpearson@raptorengineeringinc.com>
Date: Sat, 20 Jun 2015 20:02:49 -0500
Subject: [PATCH 064/143] northbridge/amd/amdmct: Clear memory before enabling
 ECC

Change-Id: I992e7040520570893ba6a213138dd57bfa14733b
Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com>
---
 src/northbridge/amd/amdmct/mct_ddr3/mct_d.c    |   45 ++++++++----------------
 src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c |   38 +++++++++++++++++++-
 2 files changed, 51 insertions(+), 32 deletions(-)

diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
index f4859d0..d8a09f0 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
@@ -51,8 +51,6 @@ static void DCTMemClr_Init_D(struct MCTStatStruc *pMCTstat,
 				struct DCTStatStruc *pDCTstat);
 static void DCTMemClr_Sync_D(struct MCTStatStruc *pMCTstat,
 				struct DCTStatStruc *pDCTstat);
-static void MCTMemClrSync_D(struct MCTStatStruc *pMCTstat,
-				struct DCTStatStruc *pDCTstatA);
 static u8 NodePresent_D(u8 Node);
 static void SyncDCTsReady_D(struct MCTStatStruc *pMCTstat,
 				struct DCTStatStruc *pDCTstatA);
@@ -1500,10 +1498,11 @@ restartinit:
 		InterleaveChannels_D(pMCTstat, pDCTstatA);
 
 		printk(BIOS_DEBUG, "mctAutoInitMCT_D: ECCInit_D\n");
-		if (ECCInit_D(pMCTstat, pDCTstatA)) {		/* Setup ECC control and ECC check-bits*/
-			printk(BIOS_DEBUG, "mctAutoInitMCT_D: MCTMemClr_D\n");
-			MCTMemClr_D(pMCTstat,pDCTstatA);
-		}
+		ECCInit_D(pMCTstat, pDCTstatA);			/* Setup ECC control and ECC check-bits*/
+
+		/* mctDoWarmResetMemClr_D(); */
+		printk(BIOS_DEBUG, "mctAutoInitMCT_D: MCTMemClr_D\n");
+		MCTMemClr_D(pMCTstat,pDCTstatA);
 
 		printk(BIOS_DEBUG, "mctAutoInitMCT_D: mct_ForceNBPState0_Dis_Fam15\n");
 		for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
@@ -2094,9 +2093,6 @@ static void DQSTiming_D(struct MCTStatStruc *pMCTstat,
 
 	/* FIXME - currently uses calculated value	TrainMaxReadLatency_D(pMCTstat, pDCTstatA); */
 	mctHookAfterAnyTraining();
-
-	/* mctDoWarmResetMemClr_D(); */
-	MCTMemClr_D(pMCTstat, pDCTstatA);
 }
 
 static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat,
@@ -2384,26 +2380,6 @@ static void DCTMemClr_Init_D(struct MCTStatStruc *pMCTstat,
 	}
 }
 
-static void MCTMemClrSync_D(struct MCTStatStruc *pMCTstat,
-				struct DCTStatStruc *pDCTstatA)
-{
-	/* Ensures that memory clear has completed on all node.*/
-	u8 Node;
-	struct DCTStatStruc *pDCTstat;
-
-	if (!mctGet_NVbits(NV_DQSTrainCTL)){
-		/* callback to wrapper: mctDoWarmResetMemClr_D */
-	} else {	/* NV_DQSTrainCTL == 1 */
-		for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
-			pDCTstat = pDCTstatA + Node;
-
-			if (pDCTstat->NodePresent) {
-				DCTMemClr_Sync_D(pMCTstat, pDCTstat);
-			}
-		}
-	}
-}
-
 static void DCTMemClr_Sync_D(struct MCTStatStruc *pMCTstat,
 				struct DCTStatStruc *pDCTstat)
 {
@@ -2424,9 +2400,12 @@ static void DCTMemClr_Sync_D(struct MCTStatStruc *pMCTstat,
 		} while (!(val & (1 << Dr_MemClrStatus)));
 	}
 
-	val = 0x0FE40FC0;		/* BKDG recommended */
+	if (is_fam15h())
+		val = 0x0ce00f41;	/* BKDG recommended */
+	else
+		val = 0x0fe40fc0;	/* BKDG recommended */
 	val |= MCCH_FlushWrOnStpGnt;	/* Set for S3 */
-	Set_NB32(dev, 0x11C, val);
+	Set_NB32(dev, 0x11c, val);
 }
 
 static u8 NodePresent_D(u8 Node)
@@ -3089,6 +3068,8 @@ static void GetPresetmaxF_D(struct MCTStatStruc *pMCTstat,
 	u16 proposedFreq;
 	u16 word;
 
+	printk(BIOS_DEBUG, "%s: Start\n", __func__);
+
 	/* Get CPU Si Revision defined limit (NPT) */
 	if (is_fam15h())
 		proposedFreq = 933;
@@ -3113,6 +3094,8 @@ static void GetPresetmaxF_D(struct MCTStatStruc *pMCTstat,
 		pDCTstat->PresetmaxFreq = word;
 	}
 	/* Check F3xE8[DdrMaxRate] for maximum DRAM data rate support */
+
+	printk(BIOS_DEBUG, "%s: Done\n", __func__);
 }
 
 static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat,
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c
index 3a9fecc..918e91e 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c
@@ -88,6 +88,10 @@ u8 ECCInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA)
 	u32 val;
 	u16 nvbits;
 
+	uint32_t dword;
+	uint8_t sync_flood_on_dram_err[MAX_NODES_SUPPORTED];
+	uint8_t sync_flood_on_any_uc_err[MAX_NODES_SUPPORTED];
+
 	mctHookBeforeECC();
 
 	/* Construct these booleans, based on setup options, for easy handling
@@ -111,6 +115,25 @@ u8 ECCInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA)
 	nvbits = mctGet_NVbits(NV_DramBKScrub);
 	OF_ScrubCTL |= nvbits;
 
+	/* Prevent lockups on DRAM errors during ECC init */
+	for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
+		struct DCTStatStruc *pDCTstat;
+		pDCTstat = pDCTstatA + Node;
+
+		if (NodePresent_D(Node)) {
+			dword = Get_NB32(pDCTstat->dev_nbmisc, 0x44);
+			sync_flood_on_dram_err[Node] = (dword >> 30) & 0x1;
+			sync_flood_on_any_uc_err[Node] = (dword >> 21) & 0x1;
+			dword &= ~(0x1 << 30);
+			dword &= ~(0x1 << 21);
+			Set_NB32(pDCTstat->dev_nbmisc, 0x44, dword);
+
+			/* Clear the RAM before enabling ECC to prevent MCE-related lockups */
+			DCTMemClr_Init_D(pMCTstat, pDCTstat);
+			DCTMemClr_Sync_D(pMCTstat, pDCTstat);
+		}
+	}
+
 	AllECC = 1;
 	MemClrECC = 0;
 	for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
@@ -157,7 +180,7 @@ u8 ECCInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA)
 			}	/* Node has Dram */
 
 			if (MemClrECC) {
-				MCTMemClrSync_D(pMCTstat, pDCTstatA);
+				DCTMemClr_Sync_D(pMCTstat, pDCTstat);
 			}
 
 			if (pDCTstat->LogicalCPUID & (AMD_DR_GT_D0 | AMD_FAM15_ALL)) {
@@ -170,6 +193,19 @@ u8 ECCInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA)
 		}	/* if Node present */
 	}
 
+	/* Restore previous MCA error handling settings */
+	for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
+		struct DCTStatStruc *pDCTstat;
+		pDCTstat = pDCTstatA + Node;
+
+		if (NodePresent_D(Node)) {
+			dword = Get_NB32(pDCTstat->dev_nbmisc, 0x44);
+			dword |= (sync_flood_on_dram_err[Node] & 0x1) << 30;
+			dword |= (sync_flood_on_any_uc_err[Node] & 0x1) << 21;
+			Set_NB32(pDCTstat->dev_nbmisc, 0x44, dword);
+		}
+	}
+
 	if(AllECC)
 		pMCTstat->GStatus |= 1<<GSB_ECCDIMMs;
 	else
-- 
1.7.9.5

