diff options
Diffstat (limited to 'src/soc/intel/common')
-rw-r--r-- | src/soc/intel/common/block/include/intelblocks/meminit.h | 4 | ||||
-rw-r--r-- | src/soc/intel/common/block/memory/Kconfig | 8 | ||||
-rw-r--r-- | src/soc/intel/common/block/memory/meminit.c | 51 |
3 files changed, 58 insertions, 5 deletions
diff --git a/src/soc/intel/common/block/include/intelblocks/meminit.h b/src/soc/intel/common/block/include/intelblocks/meminit.h index 1fed02f5c6..130249cf71 100644 --- a/src/soc/intel/common/block/include/intelblocks/meminit.h +++ b/src/soc/intel/common/block/include/intelblocks/meminit.h @@ -134,11 +134,13 @@ struct mem_channel_data { * the mainboard. * spd_info : Information about the memory topology. * half_populated: Hint from mainboard if channels are half populated. + * dimms_changed: True if the dimms is changed after caching the spd data. */ void mem_populate_channel_data(const struct soc_mem_cfg *soc_mem_cfg, const struct mem_spd *spd_info, bool half_populated, - struct mem_channel_data *data); + struct mem_channel_data *data, + bool *dimms_changed); /* * Given a channel number and the maximum number of supported channels, this diff --git a/src/soc/intel/common/block/memory/Kconfig b/src/soc/intel/common/block/memory/Kconfig index fdcccbf742..7156be7ff6 100644 --- a/src/soc/intel/common/block/memory/Kconfig +++ b/src/soc/intel/common/block/memory/Kconfig @@ -28,4 +28,12 @@ config MRC_CHANNEL_WIDTH support is expected to set MRC_CHANNEL_WIDTH as per the FSP MRC expectation. +config SPD_CACHE_ENABLE + bool + default n + help + Enable to cache the spd data to the RW_SPD_CACHE region. If + this option is enabled, please make sure the RW_SPD_CACHE + region is added to the flash layout. + endif diff --git a/src/soc/intel/common/block/memory/meminit.c b/src/soc/intel/common/block/memory/meminit.c index 78dc2d443a..89cd4e323e 100644 --- a/src/soc/intel/common/block/memory/meminit.c +++ b/src/soc/intel/common/block/memory/meminit.c @@ -5,6 +5,7 @@ #include <intelblocks/meminit.h> #include <commonlib/region.h> #include <spd_bin.h> +#include <spd_cache.h> #include <string.h> #include <types.h> @@ -96,7 +97,7 @@ static void read_spd_md(const struct soc_mem_cfg *soc_mem_cfg, const struct mem_ static bool read_spd_dimm(const struct soc_mem_cfg *soc_mem_cfg, const struct mem_spd *info, bool half_populated, struct mem_channel_data *channel_data, - size_t *spd_len) + size_t *spd_len, bool *dimms_changed) { size_t ch, dimm; struct spd_block blk = { 0 }; @@ -108,6 +109,7 @@ static bool read_spd_dimm(const struct soc_mem_cfg *soc_mem_cfg, const struct me * channel is marked as populated. */ uint32_t pop_mask = 0; + *dimms_changed = false; if (!(info->topo & MEM_TOPO_DIMM_MODULE)) return false; @@ -119,7 +121,46 @@ static bool read_spd_dimm(const struct soc_mem_cfg *soc_mem_cfg, const struct me } } - get_spd_smbus(&blk); + if (CONFIG(SPD_CACHE_ENABLE)) { + uint8_t *spd_cache; + size_t spd_cache_sz; + bool need_update_cache = false; + bool dimm_changed = true; + + /* load spd cache from RW_SPD_CACHE */ + if (load_spd_cache(&spd_cache, &spd_cache_sz) == CB_SUCCESS) { + if (!spd_cache_is_valid(spd_cache, spd_cache_sz)) { + printk(BIOS_WARNING, "Invalid SPD cache\n"); + } else { + dimm_changed = check_if_dimm_changed(spd_cache, &blk); + if (dimm_changed) { + /* + * Set flag to indicate that the + * mrc_cache need to be invalidated + */ + printk(BIOS_INFO, + "DIMM change, invalidate cache.\n"); + *dimms_changed = true; + } + } + need_update_cache = true; + } + + if (!dimm_changed) { + printk(BIOS_INFO, "Use the SPD cache data\n"); + spd_fill_from_cache(spd_cache, &blk); + } else { + /* Access memory info through SMBUS. */ + get_spd_smbus(&blk); + + if (need_update_cache && + update_spd_cache(&blk) == CB_ERR) + printk(BIOS_ERR, "update SPD cache failed\n"); + } + } else { + get_spd_smbus(&blk); + } + *spd_len = blk.len; for (ch = 0; ch < num_phys_ch; ch++) { @@ -145,7 +186,8 @@ static bool read_spd_dimm(const struct soc_mem_cfg *soc_mem_cfg, const struct me void mem_populate_channel_data(const struct soc_mem_cfg *soc_mem_cfg, const struct mem_spd *spd_info, bool half_populated, - struct mem_channel_data *data) + struct mem_channel_data *data, + bool *dimms_changed) { size_t spd_md_len = 0, spd_dimm_len = 0; bool have_dimms; @@ -153,7 +195,8 @@ void mem_populate_channel_data(const struct soc_mem_cfg *soc_mem_cfg, memset(data, 0, sizeof(*data)); read_spd_md(soc_mem_cfg, spd_info, half_populated, data, &spd_md_len); - have_dimms = read_spd_dimm(soc_mem_cfg, spd_info, half_populated, data, &spd_dimm_len); + have_dimms = read_spd_dimm(soc_mem_cfg, spd_info, half_populated, data, + &spd_dimm_len, dimms_changed); if (data->ch_population_flags == NO_CHANNEL_POPULATED) die("No channels are populated. Incorrect memory configuration!\n"); |