Patrick Georgi has submitted this change. ( https://review.coreboot.org/c/coreboot/+/37303 )
Change subject: soc/intel/broadwell_de: Re-read SPD on CRC error ......................................................................
soc/intel/broadwell_de: Re-read SPD on CRC error
I2C bus does not guarantee data integrity. As result, sometimes we end up detecting CRC errors and not adding DIMMs to SMBIOS tables. This change adds re-tries on such errors.
TEST=let OCP monolake run without fan and try reading SPD data in tight loop. CRC errors were reported but subsequent retries were error free.
Change-Id: I650c8cd80f75b603db332024748a91af6171f096 Signed-off-by: Andrey Petrov anpetrov@fb.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/37303 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Werner Zeh werner.zeh@siemens.com --- M src/soc/intel/fsp_broadwell_de/romstage/memory.c 1 file changed, 29 insertions(+), 3 deletions(-)
Approvals: build bot (Jenkins): Verified Werner Zeh: Looks good to me, approved
diff --git a/src/soc/intel/fsp_broadwell_de/romstage/memory.c b/src/soc/intel/fsp_broadwell_de/romstage/memory.c index afbf97b..b4bc097 100644 --- a/src/soc/intel/fsp_broadwell_de/romstage/memory.c +++ b/src/soc/intel/fsp_broadwell_de/romstage/memory.c @@ -20,6 +20,8 @@ #include <soc/memory.h> #include <spd_bin.h>
+#define MAX_SPD_READ_TRIES 3 + static uint32_t get_memory_dclk(void) { uint32_t reg32 = @@ -30,7 +32,7 @@ void save_dimm_info(void) { int index = 0; - uint32_t dclk_mhz = 0; + uint32_t dclk_mhz = 0, tries;
/* * When talking to SPD chips through IMC slave offset of 0x50 is automagically added @@ -53,9 +55,33 @@ for (int slot = 0; slot < CONFIG_DIMM_MAX / IMC_MAX_CHANNELS; slot++) { dimm_attr dimm = {0}; u8 *spd_data = blk.spd_array[index]; - if (spd_decode_ddr4(&dimm, spd_data) == SPD_STATUS_OK) - spd_add_smbios17_ddr4(channel, slot, dclk_mhz, &dimm); + int res = SPD_STATUS_OK; + tries = MAX_SPD_READ_TRIES; + /* + * SMBus controller can't validate data integrity. So on CRC + * error retry a few times. + */ + do { + res = spd_decode_ddr4(&dimm, spd_data); + if (res == SPD_STATUS_CRC_ERROR) { + printk(BIOS_ERR, + "SPD CRC error, channel %u slot %u " + "try %u\n", channel, slot, tries); + get_spd_smbus(&blk); + } + } while (tries-- && res == SPD_STATUS_CRC_ERROR); + index++; + + if (res == SPD_STATUS_CRC_ERROR) { + printk(BIOS_WARNING, "Gave up reading CRC on channel %u" + " slot %u\n", channel, slot); + continue; + } + + if (res == SPD_STATUS_OK) { + spd_add_smbios17_ddr4(channel, slot, dclk_mhz, &dimm); + } } } }