nb/amd/mct_ddr3: Add support for non-ECC DIMMs on AMD Family 15h

While some stubs existed before this patch to handle non-ECC
memory initialization, there were a number of ECC detect unaware
sections of code.  Add ECC support detection to those sections.

Change-Id: I56dad8a0f6833b2f42796212afb9777e9cc73d6d
Tested-On: ASUS KGPE-D16
Tested-With: 1x Opteron 6262
Tested-With: 1x SuperTalent 4G non-ECC DIMM in slot A2
Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com>
Reviewed-on: https://review.coreboot.org/14737
Tested-by: build bot (Jenkins)
Tested-by: Raptor Engineering Automated Test Stand <noreply@raptorengineeringinc.com>
Reviewed-by: Damien Zammit <damien@zamaudio.com>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
Timothy Pearson 2016-05-07 16:05:05 -05:00
parent 12a8aba418
commit d112f46bed
3 changed files with 14 additions and 10 deletions

View File

@ -341,11 +341,9 @@ uint8_t is_ecc_enabled(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTs
if (!pMCTstat->try_ecc) if (!pMCTstat->try_ecc)
ecc_enabled = 0; ecc_enabled = 0;
if (pDCTstat->NodePresent && pDCTstat->DIMMValid) { if (pDCTstat->NodePresent && (pDCTstat->DIMMValidDCT[0] || pDCTstat->DIMMValidDCT[1]))
if (!(pDCTstat->Status & (1 << SB_ECCDIMMs))) { if (!(pDCTstat->Status & (1 << SB_ECCDIMMs)))
ecc_enabled = 0; ecc_enabled = 0;
}
}
return !!ecc_enabled; return !!ecc_enabled;
} }

View File

@ -2,7 +2,7 @@
* This file is part of the coreboot project. * This file is part of the coreboot project.
* *
* Copyright (C) 2010 Advanced Micro Devices, Inc. * Copyright (C) 2010 Advanced Micro Devices, Inc.
* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering * Copyright (C) 2015 - 2016 Raptor Engineering, LLC
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -1085,7 +1085,10 @@ static void read_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat,
Set_NB32_DCT(dev, dct, 0x274, ~0xffffffff); Set_NB32_DCT(dev, dct, 0x274, ~0xffffffff);
Set_NB32_DCT(dev, dct, 0x278, ~0xffffffff); Set_NB32_DCT(dev, dct, 0x278, ~0xffffffff);
dword = Get_NB32_DCT(dev, dct, 0x27c); dword = Get_NB32_DCT(dev, dct, 0x27c);
dword &= ~(0xff); /* EccMask = 0x0 */ if (get_available_lane_count(pMCTstat, pDCTstat) < 9)
dword |= 0xff; /* EccMask = 0xff */
else
dword &= ~(0xff); /* EccMask = 0x0 */
Set_NB32_DCT(dev, dct, 0x27c, dword); Set_NB32_DCT(dev, dct, 0x27c, dword);
} else { } else {
Set_NB32_DCT(dev, dct, 0x274, ~0x0); Set_NB32_DCT(dev, dct, 0x274, ~0x0);
@ -1178,7 +1181,10 @@ static void write_dram_dqs_training_pattern_fam15(struct MCTStatStruc *pMCTstat,
Set_NB32_DCT(dev, dct, 0x274, ~0xffffffff); Set_NB32_DCT(dev, dct, 0x274, ~0xffffffff);
Set_NB32_DCT(dev, dct, 0x278, ~0xffffffff); Set_NB32_DCT(dev, dct, 0x278, ~0xffffffff);
dword = Get_NB32_DCT(dev, dct, 0x27c); dword = Get_NB32_DCT(dev, dct, 0x27c);
dword &= ~(0xff); /* EccMask = 0x0 */ if (get_available_lane_count(pMCTstat, pDCTstat) < 9)
dword |= 0xff; /* EccMask = 0xff */
else
dword &= ~(0xff); /* EccMask = 0x0 */
Set_NB32_DCT(dev, dct, 0x27c, dword); Set_NB32_DCT(dev, dct, 0x27c, dword);
} else { } else {
Set_NB32_DCT(dev, dct, 0x274, ~0x0); Set_NB32_DCT(dev, dct, 0x274, ~0x0);
@ -1790,7 +1796,7 @@ static void TrainDQSReceiverEnCyc_D_Fam15(struct MCTStatStruc *pMCTstat,
Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0030 | (lane << 8), dword); Set_NB32_index_wait_DCT(dev, dct, index_reg, 0x0d0f0030 | (lane << 8), dword);
} }
for (lane = 0; lane < MAX_BYTE_LANES; lane++) { for (lane = 0; lane < lane_count; lane++) {
if (!lane_training_success[lane]) { if (!lane_training_success[lane]) {
dct_training_success = 0; dct_training_success = 0;
Errors |= 1 << SB_NODQSPOS; Errors |= 1 << SB_NODQSPOS;

View File

@ -1657,7 +1657,7 @@ static void dqsTrainMaxRdLatency_SW_Fam15(struct MCTStatStruc *pMCTstat,
read_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg); read_dqs_receiver_enable_control_registers(current_total_delay, dev, Channel, dimm, index_reg);
read_dqs_read_data_timing_registers(current_rdqs_total_delay, dev, Channel, dimm, index_reg); read_dqs_read_data_timing_registers(current_rdqs_total_delay, dev, Channel, dimm, index_reg);
for (lane = 0; lane < 8; lane++) { for (lane = 0; lane < lane_count; lane++) {
current_total_delay[lane] += current_rdqs_total_delay[lane]; current_total_delay[lane] += current_rdqs_total_delay[lane];
if (current_total_delay[lane] > current_worst_case_total_delay_value) { if (current_total_delay[lane] > current_worst_case_total_delay_value) {
current_worst_case_total_delay_dimm = dimm; current_worst_case_total_delay_dimm = dimm;
@ -1666,7 +1666,7 @@ static void dqsTrainMaxRdLatency_SW_Fam15(struct MCTStatStruc *pMCTstat,
} }
#if DQS_TRAIN_DEBUG > 0 #if DQS_TRAIN_DEBUG > 0
for (lane = 0; lane < 8; lane++) for (lane = 0; lane < lane_count; lane++)
print_debug_dqs_pair("\t\tTrainMaxRdLatency56: Lane ", lane, " current_total_delay ", current_total_delay[lane], 2); print_debug_dqs_pair("\t\tTrainMaxRdLatency56: Lane ", lane, " current_total_delay ", current_total_delay[lane], 2);
#endif #endif
} }