diff options
Diffstat (limited to 'src/soc/intel')
-rw-r--r-- | src/soc/intel/alderlake/include/soc/meminit.h | 2 | ||||
-rw-r--r-- | src/soc/intel/alderlake/meminit.c | 5 | ||||
-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 | ||||
-rw-r--r-- | src/soc/intel/tigerlake/meminit.c | 4 |
6 files changed, 65 insertions, 9 deletions
diff --git a/src/soc/intel/alderlake/include/soc/meminit.h b/src/soc/intel/alderlake/include/soc/meminit.h index debdef2ed4..98482e33cc 100644 --- a/src/soc/intel/alderlake/include/soc/meminit.h +++ b/src/soc/intel/alderlake/include/soc/meminit.h @@ -110,6 +110,6 @@ struct mb_cfg { }; void memcfg_init(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *mb_cfg, - const struct mem_spd *spd_info, bool half_populated); + const struct mem_spd *spd_info, bool half_populated, bool *dimms_changed); #endif /* _SOC_ALDERLAKE_MEMINIT_H_ */ diff --git a/src/soc/intel/alderlake/meminit.c b/src/soc/intel/alderlake/meminit.c index 9c1f667b57..8b54cb190e 100644 --- a/src/soc/intel/alderlake/meminit.c +++ b/src/soc/intel/alderlake/meminit.c @@ -236,7 +236,7 @@ static void ddr5_fill_dimm_module_info(FSP_M_CONFIG *mem_cfg, const struct mb_cf } void memcfg_init(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *mb_cfg, - const struct mem_spd *spd_info, bool half_populated) + const struct mem_spd *spd_info, bool half_populated, bool *dimms_changed) { struct mem_channel_data data; bool dq_dqs_auto_detect = false; @@ -278,7 +278,8 @@ void memcfg_init(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *mb_cfg, die("Unsupported memory type(%d)\n", mb_cfg->type); } - mem_populate_channel_data(&soc_mem_cfg[mb_cfg->type], spd_info, half_populated, &data); + mem_populate_channel_data(&soc_mem_cfg[mb_cfg->type], spd_info, half_populated, &data, + dimms_changed); mem_init_spd_upds(mem_cfg, &data); mem_init_dq_upds(mem_cfg, &data, mb_cfg, dq_dqs_auto_detect); mem_init_dqs_upds(mem_cfg, &data, mb_cfg, dq_dqs_auto_detect); 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"); diff --git a/src/soc/intel/tigerlake/meminit.c b/src/soc/intel/tigerlake/meminit.c index ce6316ed41..e8c7b6827b 100644 --- a/src/soc/intel/tigerlake/meminit.c +++ b/src/soc/intel/tigerlake/meminit.c @@ -151,11 +151,13 @@ void memcfg_init(FSP_M_CONFIG *mem_cfg, const struct mb_cfg *mb_cfg, const struct mem_spd *spd_info, bool half_populated) { struct mem_channel_data data; + bool dimms_changed = false; if (mb_cfg->type >= ARRAY_SIZE(soc_mem_cfg)) die("Invalid memory type(%x)!\n", mb_cfg->type); - mem_populate_channel_data(&soc_mem_cfg[mb_cfg->type], spd_info, half_populated, &data); + mem_populate_channel_data(&soc_mem_cfg[mb_cfg->type], spd_info, half_populated, &data, + &dimms_changed); mem_init_spd_upds(mem_cfg, &data); mem_init_dq_upds(mem_cfg, &data, mb_cfg); mem_init_dqs_upds(mem_cfg, &data, mb_cfg); |