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>
This commit is contained in:
parent
14ebf951e4
commit
7fd3ef57cb
2 changed files with 46 additions and 30 deletions
|
@ -47,8 +47,6 @@ static void DCTMemClr_Init_D(struct MCTStatStruc *pMCTstat,
|
||||||
struct DCTStatStruc *pDCTstat);
|
struct DCTStatStruc *pDCTstat);
|
||||||
static void DCTMemClr_Sync_D(struct MCTStatStruc *pMCTstat,
|
static void DCTMemClr_Sync_D(struct MCTStatStruc *pMCTstat,
|
||||||
struct DCTStatStruc *pDCTstat);
|
struct DCTStatStruc *pDCTstat);
|
||||||
static void MCTMemClrSync_D(struct MCTStatStruc *pMCTstat,
|
|
||||||
struct DCTStatStruc *pDCTstatA);
|
|
||||||
static u8 NodePresent_D(u8 Node);
|
static u8 NodePresent_D(u8 Node);
|
||||||
static void SyncDCTsReady_D(struct MCTStatStruc *pMCTstat,
|
static void SyncDCTsReady_D(struct MCTStatStruc *pMCTstat,
|
||||||
struct DCTStatStruc *pDCTstatA);
|
struct DCTStatStruc *pDCTstatA);
|
||||||
|
@ -1507,10 +1505,11 @@ restartinit:
|
||||||
InterleaveChannels_D(pMCTstat, pDCTstatA);
|
InterleaveChannels_D(pMCTstat, pDCTstatA);
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "mctAutoInitMCT_D: ECCInit_D\n");
|
printk(BIOS_DEBUG, "mctAutoInitMCT_D: ECCInit_D\n");
|
||||||
if (ECCInit_D(pMCTstat, pDCTstatA)) { /* Setup ECC control and ECC check-bits*/
|
ECCInit_D(pMCTstat, pDCTstatA); /* Setup ECC control and ECC check-bits*/
|
||||||
printk(BIOS_DEBUG, "mctAutoInitMCT_D: MCTMemClr_D\n");
|
|
||||||
MCTMemClr_D(pMCTstat,pDCTstatA);
|
/* mctDoWarmResetMemClr_D(); */
|
||||||
}
|
printk(BIOS_DEBUG, "mctAutoInitMCT_D: MCTMemClr_D\n");
|
||||||
|
MCTMemClr_D(pMCTstat,pDCTstatA);
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "mctAutoInitMCT_D: mct_ForceNBPState0_Dis_Fam15\n");
|
printk(BIOS_DEBUG, "mctAutoInitMCT_D: mct_ForceNBPState0_Dis_Fam15\n");
|
||||||
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
|
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
|
||||||
|
@ -2102,9 +2101,6 @@ static void DQSTiming_D(struct MCTStatStruc *pMCTstat,
|
||||||
|
|
||||||
/* FIXME - currently uses calculated value TrainMaxReadLatency_D(pMCTstat, pDCTstatA); */
|
/* FIXME - currently uses calculated value TrainMaxReadLatency_D(pMCTstat, pDCTstatA); */
|
||||||
mctHookAfterAnyTraining();
|
mctHookAfterAnyTraining();
|
||||||
|
|
||||||
/* mctDoWarmResetMemClr_D(); */
|
|
||||||
MCTMemClr_D(pMCTstat, pDCTstatA);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat,
|
static void LoadDQSSigTmgRegs_D(struct MCTStatStruc *pMCTstat,
|
||||||
|
@ -2392,26 +2388,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,
|
static void DCTMemClr_Sync_D(struct MCTStatStruc *pMCTstat,
|
||||||
struct DCTStatStruc *pDCTstat)
|
struct DCTStatStruc *pDCTstat)
|
||||||
{
|
{
|
||||||
|
@ -3097,6 +3073,8 @@ static void GetPresetmaxF_D(struct MCTStatStruc *pMCTstat,
|
||||||
u16 proposedFreq;
|
u16 proposedFreq;
|
||||||
u16 word;
|
u16 word;
|
||||||
|
|
||||||
|
printk(BIOS_DEBUG, "%s: Start\n", __func__);
|
||||||
|
|
||||||
/* Get CPU Si Revision defined limit (NPT) */
|
/* Get CPU Si Revision defined limit (NPT) */
|
||||||
if (is_fam15h())
|
if (is_fam15h())
|
||||||
proposedFreq = 933;
|
proposedFreq = 933;
|
||||||
|
@ -3121,6 +3099,8 @@ static void GetPresetmaxF_D(struct MCTStatStruc *pMCTstat,
|
||||||
pDCTstat->PresetmaxFreq = word;
|
pDCTstat->PresetmaxFreq = word;
|
||||||
}
|
}
|
||||||
/* Check F3xE8[DdrMaxRate] for maximum DRAM data rate support */
|
/* Check F3xE8[DdrMaxRate] for maximum DRAM data rate support */
|
||||||
|
|
||||||
|
printk(BIOS_DEBUG, "%s: Done\n", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat,
|
static void SPDGetTCL_D(struct MCTStatStruc *pMCTstat,
|
||||||
|
|
|
@ -84,6 +84,10 @@ u8 ECCInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA)
|
||||||
u32 val;
|
u32 val;
|
||||||
u16 nvbits;
|
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();
|
mctHookBeforeECC();
|
||||||
|
|
||||||
/* Construct these booleans, based on setup options, for easy handling
|
/* 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);
|
nvbits = mctGet_NVbits(NV_DramBKScrub);
|
||||||
OF_ScrubCTL |= nvbits;
|
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;
|
AllECC = 1;
|
||||||
MemClrECC = 0;
|
MemClrECC = 0;
|
||||||
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
|
for (Node = 0; Node < MAX_NODES_SUPPORTED; Node++) {
|
||||||
|
@ -153,7 +176,7 @@ u8 ECCInit_D(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstatA)
|
||||||
} /* Node has Dram */
|
} /* Node has Dram */
|
||||||
|
|
||||||
if (MemClrECC) {
|
if (MemClrECC) {
|
||||||
MCTMemClrSync_D(pMCTstat, pDCTstatA);
|
DCTMemClr_Sync_D(pMCTstat, pDCTstat);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pDCTstat->LogicalCPUID & (AMD_DR_GT_D0 | AMD_FAM15_ALL)) {
|
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 */
|
} /* 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)
|
if(AllECC)
|
||||||
pMCTstat->GStatus |= 1<<GSB_ECCDIMMs;
|
pMCTstat->GStatus |= 1<<GSB_ECCDIMMs;
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in a new issue