summaryrefslogtreecommitdiffstats
path: root/resources/libreboot/patch/kgpe-d16/0063-northbridge-amd-amdmct-Clear-memory-before-enabling-.patch
diff options
context:
space:
mode:
Diffstat (limited to 'resources/libreboot/patch/kgpe-d16/0063-northbridge-amd-amdmct-Clear-memory-before-enabling-.patch')
-rw-r--r--resources/libreboot/patch/kgpe-d16/0063-northbridge-amd-amdmct-Clear-memory-before-enabling-.patch185
1 files changed, 185 insertions, 0 deletions
diff --git a/resources/libreboot/patch/kgpe-d16/0063-northbridge-amd-amdmct-Clear-memory-before-enabling-.patch b/resources/libreboot/patch/kgpe-d16/0063-northbridge-amd-amdmct-Clear-memory-before-enabling-.patch
new file mode 100644
index 0000000..da29a67
--- /dev/null
+++ b/resources/libreboot/patch/kgpe-d16/0063-northbridge-amd-amdmct-Clear-memory-before-enabling-.patch
@@ -0,0 +1,185 @@
+From 1900ff138ed07b4cbe30aa4f73cb59b9ec5b4720 Mon Sep 17 00:00:00 2001
+From: Timothy Pearson <tpearson@raptorengineeringinc.com>
+Date: Sat, 20 Jun 2015 20:02:49 -0500
+Subject: [PATCH 063/139] 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.9.1
+