summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Petrov <anpetrov@fb.com>2019-11-27 13:41:36 -0800
committerPatrick Georgi <pgeorgi@google.com>2019-12-05 17:58:23 +0000
commit9ad9b3a682ed51ed933fb46ee3b859ca5274310e (patch)
treef14ad6a90544b4e5f7d033e7b1aa6f44bfdecc8d
parente81f20c36a1d2a29825ed60e543cfb427182ff7e (diff)
downloadcoreboot-9ad9b3a682ed51ed933fb46ee3b859ca5274310e.tar.gz
coreboot-9ad9b3a682ed51ed933fb46ee3b859ca5274310e.tar.bz2
coreboot-9ad9b3a682ed51ed933fb46ee3b859ca5274310e.zip
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>
-rw-r--r--src/soc/intel/fsp_broadwell_de/romstage/memory.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/src/soc/intel/fsp_broadwell_de/romstage/memory.c b/src/soc/intel/fsp_broadwell_de/romstage/memory.c
index afbf97bf5755..b4bc097e84e8 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 @@ static uint32_t get_memory_dclk(void)
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 @@ void save_dimm_info(void)
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);
+ }
}
}
}