aboutsummaryrefslogtreecommitdiff
path: root/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c
diff options
context:
space:
mode:
authorTimothy Pearson <tpearson@raptorengineeringinc.com>2015-06-20 20:02:49 -0500
committerStefan Reinauer <stefan.reinauer@coreboot.org>2015-11-12 22:16:09 +0100
commit7fd3ef57cba80f8ef2e9ecc500124e1e56d05325 (patch)
tree0192e10c000be8ee142e462f1044497672e9914f /src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c
parent14ebf951e41c085aa2f8420fcf7452dc5761514e (diff)
northbridge/amd/amdmct: Clear memory before enabling ECC
The existing code enabled ECC before clearing memory. As the AMD CPUs will generate MCEs on any invalid check bits, this resulted in random lockups during memory training due to the uniniailized check bits. Initialize ECC check bits before enabling ECC hardware. Change-Id: I992e7040520570893ba6a213138dd57bfa14733b Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com> Reviewed-on: http://review.coreboot.org/11996 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth <martinroth@google.com>
Diffstat (limited to 'src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c')
-rw-r--r--src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c
index 6ab33a3b1e..8701baebf7 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mctecc_d.c
@@ -84,6 +84,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
@@ -107,6 +111,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++) {
@@ -153,7 +176,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)) {
@@ -166,6 +189,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