aboutsummaryrefslogtreecommitdiff
path: root/src/soc
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2016-12-14 15:36:56 -0600
committerAaron Durbin <adurbin@chromium.org>2016-12-15 23:11:57 +0100
commitd09142c136c81e190c78a17eac88153ba9464eff (patch)
tree44e9aaeb1022b40eaf6ed1dbfc258bcae9e53679 /src/soc
parent8f9a5ff8ec338dcaa1c43e4725ce0dbd6a01f37d (diff)
soc/intel/common: provide option to invalide MRC cache on recovery
Allow a board/platform to invalidate the normal MRC cache when hardware retraining is requested in recovery mode. A small 4 byte payload is used to update the latest data written. It will of course fail on MRC cache retreival on next usage. BUG=chrome-os-partner:60592 BRANCH=reef Change-Id: Ic88cd66802664813562d003f50d54e4a4ea375ef Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: https://review.coreboot.org/17870 Tested-by: build bot (Jenkins) Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
Diffstat (limited to 'src/soc')
-rw-r--r--src/soc/intel/common/Kconfig4
-rw-r--r--src/soc/intel/common/mrc_cache.c34
2 files changed, 38 insertions, 0 deletions
diff --git a/src/soc/intel/common/Kconfig b/src/soc/intel/common/Kconfig
index 1cc856eb5e..68bb38af7a 100644
--- a/src/soc/intel/common/Kconfig
+++ b/src/soc/intel/common/Kconfig
@@ -31,6 +31,10 @@ config HAS_RECOVERY_MRC_CACHE
bool
default n
+config MRC_CLEAR_NORMAL_CACHE_ON_RECOVERY_RETRAIN
+ bool
+ default n
+
config MRC_SETTINGS_VARIABLE_DATA
bool
default n
diff --git a/src/soc/intel/common/mrc_cache.c b/src/soc/intel/common/mrc_cache.c
index 69e5b00de1..e0d4b7de01 100644
--- a/src/soc/intel/common/mrc_cache.c
+++ b/src/soc/intel/common/mrc_cache.c
@@ -486,6 +486,37 @@ static void protect_mrc_region(void)
protect_mrc_cache(DEFAULT_MRC_CACHE);
}
+static void invalidate_normal_cache(void)
+{
+ struct region_file cache_file;
+ struct region_device rdev;
+ const char *name = DEFAULT_MRC_CACHE;
+ const uint32_t invalid = ~MRC_DATA_SIGNATURE;
+
+ /* Invalidate only on recovery mode with retraining enabled. */
+ if (!vboot_recovery_mode_enabled())
+ return;
+ if (!vboot_recovery_mode_memory_retrain())
+ return;
+
+ if (fmap_locate_area_as_rdev_rw(name, &rdev) < 0) {
+ printk(BIOS_ERR, "MRC: Couldn't find '%s' region. Invalidation failed\n",
+ name);
+ return;
+ }
+
+ if (region_file_init(&cache_file, &rdev) < 0) {
+ printk(BIOS_ERR, "MRC: region file invalid for '%s'. Invalidation failed\n",
+ name);
+ return;
+ }
+
+ /* Push an update that consists of 4 bytes that is smaller than the
+ * MRC metadata as well as an invalid signature. */
+ if (region_file_update_data(&cache_file, &invalid, sizeof(invalid)) < 0)
+ printk(BIOS_ERR, "MRC: invalidation failed for '%s'.\n", name);
+}
+
static void update_mrc_cache(void *unused)
{
update_mrc_cache_by_type(MRC_TRAINING_DATA);
@@ -493,6 +524,9 @@ static void update_mrc_cache(void *unused)
if (IS_ENABLED(CONFIG_MRC_SETTINGS_VARIABLE_DATA))
update_mrc_cache_by_type(MRC_VARIABLE_DATA);
+ if (IS_ENABLED(CONFIG_MRC_CLEAR_NORMAL_CACHE_ON_RECOVERY_RETRAIN))
+ invalidate_normal_cache();
+
protect_mrc_region();
}