summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy Pearson <tpearson@raptorengineeringinc.com>2015-06-04 00:10:03 -0500
committerStefan Reinauer <stefan.reinauer@coreboot.org>2015-11-11 01:20:03 +0100
commit45ded7df0317d2c898ed68e308f63d569e545658 (patch)
tree4b9d1b64c7ca23383be58acfce5ea93f6760a5ae
parent7593bda5a85c79131973b195eda5a61aabe26429 (diff)
downloadcoreboot-45ded7df0317d2c898ed68e308f63d569e545658.tar.xz
amd/amdmct/mct_ddr3: Improve SPD DIMM detect reliability
Upon bootup the hardware reads at minimum 256 * 16 bytes (4Kb, or 32KB) over I2C on a system with all DIMM slots populated. If even one of those reads has a single flipped bit in it (due to EMI, cross coupling with another trace, or just poor margins on some cheap DIMM) the system will hang and require a hard reset. In practice I've seen failure rates as high as 1 failed boot in 50 due to this issue, granted with cheap DIMMs, but even so retrying the read resolves the corruption issue. I2C is not designed for continuous data transmission with high reliability, and there is no hardware error checking, therefore a single retry when transferring this amount of data makes sense. Change-Id: Ifab63eca2233c63a6a42ab8b7e742f8e47fb2a09 Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com> Reviewed-on: http://review.coreboot.org/11975 Tested-by: build bot (Jenkins) Reviewed-by: Patrick Georgi <pgeorgi@google.com>
-rw-r--r--src/northbridge/amd/amdmct/mct_ddr3/mct_d.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
index e726b33150..0718477872 100644
--- a/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
+++ b/src/northbridge/amd/amdmct/mct_ddr3/mct_d.c
@@ -3642,6 +3642,7 @@ static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat,
u8 devwidth;
u16 DimmSlots;
u8 byte = 0, bytex;
+ uint8_t crc_status;
/* preload data structure with addrs */
mctGet_DIMMAddr(pDCTstat, pDCTstat->Node_ID);
@@ -3662,10 +3663,20 @@ static u8 DIMMPresence_D(struct MCTStatStruc *pMCTstat,
int status;
smbaddr = Get_DIMMAddress_D(pDCTstat, i);
status = mctRead_SPD(smbaddr, SPD_ByteUse);
+ if (status >= 0) {
+ /* Verify result */
+ status = mctRead_SPD(smbaddr, SPD_ByteUse);
+ }
if (status >= 0) { /* SPD access is ok */
pDCTstat->DIMMPresent |= 1 << i;
read_spd_bytes(pMCTstat, pDCTstat, i);
- if (crcCheck(pDCTstat, i)) { /* CRC is OK */
+ crc_status = crcCheck(pDCTstat, i);
+ if (!crc_status) {
+ /* Try again in case there was a transient glitch */
+ read_spd_bytes(pMCTstat, pDCTstat, i);
+ crc_status = crcCheck(pDCTstat, i);
+ }
+ if (crc_status) { /* CRC is OK */
byte = pDCTstat->spd_data.spd_bytes[i][SPD_TYPE];
if (byte == JED_DDR3SDRAM) {
/*Dimm is 'Present'*/