summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/drivers/intel/fsp2_0/Kconfig13
-rw-r--r--src/soc/intel/common/fsp_reset.c69
-rw-r--r--src/soc/intel/common/reset.h10
3 files changed, 92 insertions, 0 deletions
diff --git a/src/drivers/intel/fsp2_0/Kconfig b/src/drivers/intel/fsp2_0/Kconfig
index 21327379ae..378f4fb330 100644
--- a/src/drivers/intel/fsp2_0/Kconfig
+++ b/src/drivers/intel/fsp2_0/Kconfig
@@ -389,4 +389,17 @@ config SAVE_MRC_AFTER_FSPS
Save MRC training data after FSP-S. Select this on platforms that generate MRC
cache HOB data as part of FSP-S rather than FSP-M.
+config FSP_MULTIPHASE_SI_INIT_RETURN_BROKEN
+ bool
+ default n
+ depends on PLATFORM_USES_FSP2_2
+ help
+ Select this config for Intel SoC platform where FSP MultiPhaseSiInit API is unable
+ to return ERROR status properly.
+
+ The config option will be selected based on the target SoC platform and if the
+ problem existed inside the FSP MultiPhaseSiInit. At present the problem has only
+ reported with Alder Lake and Raptor Lake FSP where MultiPhaseSiInit API is unable
+ to return any ERROR status.
+
endif
diff --git a/src/soc/intel/common/fsp_reset.c b/src/soc/intel/common/fsp_reset.c
index bf26551524..3a34aaddb5 100644
--- a/src/soc/intel/common/fsp_reset.c
+++ b/src/soc/intel/common/fsp_reset.c
@@ -1,10 +1,35 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <console/console.h>
+#include <fsp/api.h>
#include <fsp/util.h>
#include <soc/intel/common/reset.h>
#include <stdint.h>
+static const uint8_t fsp_reset_guid[16] = {
+ 0xff, 0x97, 0x05, 0xea, 0x58, 0x88, 0xca, 0x41,
+ 0xbb, 0xc1, 0xfe, 0x18, 0xfc, 0xd2, 0x8e, 0x22
+};
+
+static const uint8_t fsp_global_reset_guid[16] = {
+ 0x4c, 0x1b, 0xb3, 0x9d, 0xef, 0xf5, 0xbb, 0x48,
+ 0x94, 0x2b, 0x18, 0x1f, 0x7e, 0x3a, 0x3e, 0x40
+};
+
+/* Platform Reset String as per Intel FSP is "PCH RESET" in unicode */
+#define PLATFORM_RESET_STRING_LENGTH 20
+
+struct pch_reset_data {
+ char reserved[PLATFORM_RESET_STRING_LENGTH];
+ efi_guid_t global_reset_uid;
+};
+
+/* This structure is used to provide information about PCH Reset */
+struct fsp_reset_hob {
+ EFI_RESET_TYPE reset_type;
+ struct pch_reset_data reset_data;
+};
+
void chipset_handle_reset(uint32_t status)
{
if (status == CONFIG_FSP_STATUS_GLOBAL_RESET) {
@@ -15,3 +40,47 @@ void chipset_handle_reset(uint32_t status)
printk(BIOS_ERR, "unhandled reset type %x\n", status);
die("unknown reset type");
}
+
+static uint32_t fsp_reset_type_to_status(EFI_RESET_TYPE reset_type)
+{
+ uint32_t status;
+
+ switch (reset_type) {
+ case EfiResetCold:
+ status = FSP_STATUS_RESET_REQUIRED_COLD;
+ break;
+ case EfiResetWarm:
+ status = FSP_STATUS_RESET_REQUIRED_WARM;
+ break;
+ default:
+ printk(BIOS_ERR, "unhandled reset type %x\n", reset_type);
+ die("unknown reset type");
+ }
+
+ return status;
+}
+
+/*
+ * Return PCH Reset Status
+ * The return status can be between EfiResetCold, EfiResetWarm, EfiResetShutdown
+ * or EfiResetPlatformSpecific.
+ *
+ * If reset type is `EfiResetPlatformSpecific` then relying on pch_reset_data structure
+ * to know if the reset type is a global reset.
+ */
+uint32_t fsp_get_pch_reset_status(void)
+{
+ assert(CONFIG(FSP_MULTIPHASE_SI_INIT_RETURN_BROKEN));
+
+ size_t size;
+ const struct fsp_reset_hob *hob = fsp_find_extension_hob_by_guid(fsp_reset_guid, &size);
+ if (!hob)
+ return 0;
+
+ if ((hob->reset_type == EfiResetPlatformSpecific) &&
+ fsp_guid_compare((void *)&(hob->reset_data.global_reset_uid),
+ fsp_global_reset_guid))
+ return CONFIG_FSP_STATUS_GLOBAL_RESET;
+
+ return fsp_reset_type_to_status(hob->reset_type);
+}
diff --git a/src/soc/intel/common/reset.h b/src/soc/intel/common/reset.h
index e1f6aabbf6..d9c6ac6228 100644
--- a/src/soc/intel/common/reset.h
+++ b/src/soc/intel/common/reset.h
@@ -13,4 +13,14 @@ void do_global_reset(void);
/* Prepare for reset, run do_global_reset(), halt. */
__noreturn void global_reset(void);
+/*
+ * Return PCH Reset Status
+ * The return status can be between EfiResetCold, EfiResetWarm, EfiResetShutdown
+ * or EfiResetPlatformSpecific.
+ *
+ * If reset type if `EfiResetPlatformSpecific` then relying on pch_reset_data structure
+ * to know if the reset type is a global reset.
+ */
+uint32_t fsp_get_pch_reset_status(void);
+
#endif /* _INTEL_COMMON_RESET_H_ */