summaryrefslogtreecommitdiff
path: root/src/soc/intel
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/intel')
-rw-r--r--src/soc/intel/alderlake/include/soc/meminit.h2
-rw-r--r--src/soc/intel/alderlake/meminit.c5
-rw-r--r--src/soc/intel/common/block/include/intelblocks/meminit.h4
-rw-r--r--src/soc/intel/common/block/memory/Kconfig8
-rw-r--r--src/soc/intel/common/block/memory/meminit.c51
-rw-r--r--src/soc/intel/tigerlake/meminit.c4
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);