summaryrefslogtreecommitdiff
path: root/src/soc
diff options
context:
space:
mode:
authorAndrey Petrov <andrey.petrov@intel.com>2017-03-12 00:51:34 -0800
committerAaron Durbin <adurbin@chromium.org>2017-03-15 03:43:05 +0100
commitc5f3685f4486a875c0957b713932e241c46ea537 (patch)
treee851ab27c2e6539135e3a979daf1be2eccaed64b /src/soc
parent2e726f605de73ed1c45efb678366861723b19b62 (diff)
downloadcoreboot-c5f3685f4486a875c0957b713932e241c46ea537.tar.xz
soc/intel/apollolake: Cache FPF status value in flash
Since asking CSE to read FPF status turned out to be slow in some cases, cache and save returned value on first boot only. Value is read from flash on consequent boots. BUG=b:35586975 BRANCH=reef TEST=boot twice, make sure cached FPF status is loaded from flash the second time. Change-Id: I6e56a35407c9097616ccb05a557fded7b639c88a Signed-off-by: Andrey Petrov <andrey.petrov@intel.com> Reviewed-on: https://review.coreboot.org/18774 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'src/soc')
-rw-r--r--src/soc/intel/apollolake/cse.c66
1 files changed, 56 insertions, 10 deletions
diff --git a/src/soc/intel/apollolake/cse.c b/src/soc/intel/apollolake/cse.c
index a8e3b5b97f..a7c888a470 100644
--- a/src/soc/intel/apollolake/cse.c
+++ b/src/soc/intel/apollolake/cse.c
@@ -15,7 +15,9 @@
#include <arch/io.h>
#include <bootstate.h>
+#include <commonlib/region.h>
#include <console/console.h>
+#include <fmap.h>
#include <intelblocks/cse.h>
#include <soc/pci_devs.h>
#include <stdint.h>
@@ -38,7 +40,14 @@
#define FUSE_LOCK_FILE "/fpf/intel/SocCfgLock"
-static int8_t g_fuse_status;
+/* Status values are made in such a way erase is not needed */
+static enum fuse_flash_state {
+ FUSE_FLASH_FUSED = 0xfc,
+ FUSE_FLASH_UNFUSED = 0xfe,
+ FUSE_FLASH_UNKNOWN = 0xff,
+} g_fuse_state;
+
+#define FPF_STATUS_FMAP "FPF_STATUS"
/*
* Read file from CSE internal filesystem.
@@ -115,16 +124,53 @@ static int read_cse_file(const char *path, void *buff, size_t *size,
return 1;
}
+static enum fuse_flash_state load_cached_fpf(struct region_device *rdev)
+{
+ enum fuse_flash_state state;
+ uint8_t buff;
+
+ state = FUSE_FLASH_UNKNOWN;
+
+ if (rdev_readat(rdev, &buff, 0, sizeof(buff)) >= 0) {
+ state = read8(&buff);
+ return state;
+ }
+
+ printk(BIOS_WARNING, "failed to load cached FPF value\n");
+
+ return state;
+}
+
+static
+int save_fpf_state(enum fuse_flash_state state, struct region_device *rdev)
+{
+ uint8_t buff;
+
+ write8(&buff, (uint8_t) state);
+ return rdev_writeat(rdev, &buff, 0, sizeof(buff));
+}
+
static void fpf_blown(void *unused)
{
- int8_t fuse;
+ uint8_t fuse;
+ struct region_device rdev;
size_t sz = sizeof(fuse);
+ bool rdev_valid = false;
- if (read_cse_file(FUSE_LOCK_FILE, &fuse, &sz, 0, READ_FILE_FLAG_HW)) {
- g_fuse_status = fuse;
- return;
+ if (fmap_locate_area_as_rdev_rw(FPF_STATUS_FMAP, &rdev) == 0) {
+ rdev_valid = true;
+ g_fuse_state = load_cached_fpf(&rdev);
+ if (g_fuse_state != FUSE_FLASH_UNKNOWN)
+ return;
}
- g_fuse_status = -1;
+
+ if (!read_cse_file(FUSE_LOCK_FILE, &fuse, &sz, 0, READ_FILE_FLAG_HW))
+ return;
+
+ g_fuse_state = fuse == 1 ? FUSE_FLASH_FUSED : FUSE_FLASH_UNFUSED;
+
+ if (rdev_valid && (save_fpf_state(g_fuse_state, &rdev) < 0))
+ printk(BIOS_CRIT, "failed to save FPF state\n");
}
static uint32_t dump_status(int index, int reg_addr)
@@ -154,15 +200,15 @@ static void dump_cse_state(void *unused)
(fwsts1 & (1 << 0x4)) ? "YES" : "NO");
printk(BIOS_DEBUG, "ME: FPF status : ");
- switch (g_fuse_status) {
- case 0:
+ switch (g_fuse_state) {
+ case FUSE_FLASH_UNFUSED:
printk(BIOS_DEBUG, "unfused");
break;
- case 1:
+ case FUSE_FLASH_FUSED:
printk(BIOS_DEBUG, "fused");
break;
default:
- case -1:
+ case FUSE_FLASH_UNKNOWN:
printk(BIOS_DEBUG, "unknown");
}
printk(BIOS_DEBUG, "\n");