From 7599efdbd3f19a7d57036a9f6b56da8253fab4ce Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sat, 20 Jun 2015 20:02:49 -0500 Subject: [PATCH 065/146] northbridge/amd/amdmct: Clear memory before enabling ECC --- 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 28f8d18..e39ce17 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); @@ -1494,10 +1492,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++) { @@ -2087,9 +2086,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, @@ -2377,26 +2373,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) { @@ -2417,9 +2393,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) @@ -3082,6 +3061,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; @@ -3106,6 +3087,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 c930380..99cccb8 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<