diff options
-rw-r--r-- | src/drivers/intel/fsp2_0/Kconfig | 13 | ||||
-rw-r--r-- | src/soc/intel/common/fsp_reset.c | 69 | ||||
-rw-r--r-- | src/soc/intel/common/reset.h | 10 |
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_ */ |