summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/commonlib/include/commonlib/timestamp_serialized.h2
-rw-r--r--src/drivers/intel/fsp2_0/Kconfig13
-rw-r--r--src/drivers/intel/fsp2_0/header_display.c3
-rw-r--r--src/drivers/intel/fsp2_0/include/fsp/api.h5
-rw-r--r--src/drivers/intel/fsp2_0/include/fsp/info_header.h5
-rw-r--r--src/drivers/intel/fsp2_0/include/fsp/upd.h18
-rw-r--r--src/drivers/intel/fsp2_0/include/fsp/util.h12
-rw-r--r--src/drivers/intel/fsp2_0/silicon_init.c116
-rw-r--r--src/drivers/intel/fsp2_0/util.c2
-rw-r--r--src/include/console/post_codes.h14
10 files changed, 176 insertions, 14 deletions
diff --git a/src/commonlib/include/commonlib/timestamp_serialized.h b/src/commonlib/include/commonlib/timestamp_serialized.h
index 132d45b86d..b1e58c9780 100644
--- a/src/commonlib/include/commonlib/timestamp_serialized.h
+++ b/src/commonlib/include/commonlib/timestamp_serialized.h
@@ -115,6 +115,8 @@ enum timestamp_id {
TS_FSP_AFTER_FINALIZE = 959,
TS_FSP_BEFORE_END_OF_FIRMWARE = 960,
TS_FSP_AFTER_END_OF_FIRMWARE = 961,
+ TS_FSP_MULTI_PHASE_SI_INIT_START = 962,
+ TS_FSP_MULTI_PHASE_SI_INIT_END = 963,
/* 1000+ reserved for payloads (1000-1200: ChromeOS depthcharge) */
diff --git a/src/drivers/intel/fsp2_0/Kconfig b/src/drivers/intel/fsp2_0/Kconfig
index 0344116370..c7c44cd849 100644
--- a/src/drivers/intel/fsp2_0/Kconfig
+++ b/src/drivers/intel/fsp2_0/Kconfig
@@ -18,6 +18,19 @@ config PLATFORM_USES_FSP2_1
1. Remove FSP stack switch and use the same stack with boot firmware
2. FSP should support external PPI interface pulled in via FSP_PEIM_TO_PEIM_INTERFACE
+config PLATFORM_USES_FSP2_2
+ bool
+ default n
+ select PLATFORM_USES_FSP2_1
+ help
+ Include FSP 2.2 wrappers and functionality.
+ Features added into FSP 2.2 specification that impact coreboot are:
+ 1. Added multi-phase silicon initialization to increase the modularity of the
+ FspSiliconInit() API
+ 2. FSP_INFO_HEADER changes to add FspMultiPhaseSiInitEntryOffset
+ 3. Added EnableMultiPhaseSiliconInit, bootloaders designed for FSP2.0/2.1 can disable
+ the FspMultiPhaseSiInit() API and continue to use FspSiliconInit() without change.
+
if PLATFORM_USES_FSP2_0
config HAVE_INTEL_FSP_REPO
diff --git a/src/drivers/intel/fsp2_0/header_display.c b/src/drivers/intel/fsp2_0/header_display.c
index 097de46b5c..57e13b5354 100644
--- a/src/drivers/intel/fsp2_0/header_display.c
+++ b/src/drivers/intel/fsp2_0/header_display.c
@@ -40,6 +40,9 @@ void fsp_print_header_info(const struct fsp_header *hdr)
if ((hdr->component_attribute >> 12) == FSP_HDR_ATTRIB_FSPS) {
printk(BIOS_SPEW, "\tSilicon init offset 0x%zx\n",
hdr->silicon_init_entry_offset);
+ if (CONFIG(PLATFORM_USES_FSP2_2))
+ printk(BIOS_SPEW, "\tMultiPhaseSiInit offset 0x%zx\n",
+ hdr->multi_phase_si_init_entry_offset);
printk(BIOS_SPEW, "\tNotify phase offset 0x%zx\n",
hdr->notify_phase_entry_offset);
}
diff --git a/src/drivers/intel/fsp2_0/include/fsp/api.h b/src/drivers/intel/fsp2_0/include/fsp/api.h
index c6c9179867..d2c556f916 100644
--- a/src/drivers/intel/fsp2_0/include/fsp/api.h
+++ b/src/drivers/intel/fsp2_0/include/fsp/api.h
@@ -47,7 +47,10 @@ void fsps_load(bool s3wake);
/* Callbacks for updating stage-specific parameters */
void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version);
void platform_fsp_silicon_init_params_cb(FSPS_UPD *supd);
-
+/* Callbacks for SoC/Mainboard specific overrides */
+void platform_fsp_multi_phase_init_cb(uint32_t phase_index);
+/* Check if SoC sets EnableMultiPhaseSiliconInit UPD */
+int soc_fsp_multi_phase_init_is_enable(void);
/*
* The following functions are used when FSP_PLATFORM_MEMORY_SETTINGS_VERSION
* is employed allowing the mainboard and SoC to supply their own version
diff --git a/src/drivers/intel/fsp2_0/include/fsp/info_header.h b/src/drivers/intel/fsp2_0/include/fsp/info_header.h
index 7755d2a2f9..f237a378f1 100644
--- a/src/drivers/intel/fsp2_0/include/fsp/info_header.h
+++ b/src/drivers/intel/fsp2_0/include/fsp/info_header.h
@@ -6,7 +6,11 @@
#include <types.h>
#define FSP_HDR_OFFSET 0x94
+#if CONFIG(PLATFORM_USES_FSP2_2)
+#define FSP_HDR_LEN 0x4c
+#else
#define FSP_HDR_LEN 0x48
+#endif
#define FSP_HDR_SIGNATURE "FSPH"
#define FSP_HDR_ATTRIB_FSPT 1
#define FSP_HDR_ATTRIB_FSPM 2
@@ -26,6 +30,7 @@ struct fsp_header {
size_t notify_phase_entry_offset;
size_t memory_init_entry_offset;
size_t silicon_init_entry_offset;
+ size_t multi_phase_si_init_entry_offset;
char image_id[sizeof(uint64_t) + 1];
uint8_t revision;
};
diff --git a/src/drivers/intel/fsp2_0/include/fsp/upd.h b/src/drivers/intel/fsp2_0/include/fsp/upd.h
index bcfee6c727..979cff3b91 100644
--- a/src/drivers/intel/fsp2_0/include/fsp/upd.h
+++ b/src/drivers/intel/fsp2_0/include/fsp/upd.h
@@ -54,4 +54,22 @@ struct FSPM_ARCH_UPD {
uint8_t Reserved1[8];
} __packed;
+struct FSPS_ARCH_UPD {
+ ///
+ /// Revision of the structure. For FSP v2.2 value is 1.
+ ///
+ uint8_t Revision;
+ uint8_t Reserved[3];
+ ///
+ /// Length of the structure in bytes. The current value for this field is 32
+ ///
+ uint32_t Length;
+ uint8_t Reserved1[4];
+ ///
+ /// To enable multi-phase silicon initialization the bootloader must set non-zero value
+ ///
+ uint8_t EnableMultiPhaseSiliconInit;
+ uint8_t Reserved2[19];
+} __packed;
+
#endif /* _FSP2_0_UPD_H_ */
diff --git a/src/drivers/intel/fsp2_0/include/fsp/util.h b/src/drivers/intel/fsp2_0/include/fsp/util.h
index 29c393b09c..ad6a4b5260 100644
--- a/src/drivers/intel/fsp2_0/include/fsp/util.h
+++ b/src/drivers/intel/fsp2_0/include/fsp/util.h
@@ -21,6 +21,17 @@ struct fsp_notify_params {
enum fsp_notify_phase phase;
};
+enum fsp_multi_phase_action {
+ GET_NUMBER_OF_PHASES = 0,
+ EXECUTE_PHASE = 1
+};
+
+struct fsp_multi_phase_params {
+ enum fsp_multi_phase_action multi_phase_action;
+ uint32_t phase_index;
+ void *multi_phase_param_ptr;
+};
+
struct hob_resource {
uint8_t owner_guid[16];
uint32_t type;
@@ -115,6 +126,7 @@ typedef asmlinkage uint32_t (*temp_ram_exit_fn)(void *param);
typedef asmlinkage uint32_t (*fsp_memory_init_fn)
(void *raminit_upd, void **hob_list);
typedef asmlinkage uint32_t (*fsp_silicon_init_fn)(void *silicon_upd);
+typedef asmlinkage uint32_t (*fsp_multi_phase_si_init_fn)(struct fsp_multi_phase_params *);
typedef asmlinkage uint32_t (*fsp_notify_fn)(struct fsp_notify_params *);
#include <fsp/debug.h>
diff --git a/src/drivers/intel/fsp2_0/silicon_init.c b/src/drivers/intel/fsp2_0/silicon_init.c
index 6f3781afaf..663b1d7cfd 100644
--- a/src/drivers/intel/fsp2_0/silicon_init.c
+++ b/src/drivers/intel/fsp2_0/silicon_init.c
@@ -16,13 +16,74 @@
struct fsp_header fsps_hdr;
+struct fsp_multi_phase_get_number_of_phases_params {
+ uint32_t number_of_phases;
+ uint32_t phases_executed;
+};
+
+/* Callbacks for SoC/Mainboard specific overrides */
+void __weak platform_fsp_multi_phase_init_cb(uint32_t phase_index)
+{
+ /* Leave for the SoC/Mainboard to implement if necessary. */
+}
+
+int __weak soc_fsp_multi_phase_init_is_enable(void)
+{
+ return 1;
+}
+
+/* FSP Specification < 2.2 has only 1 stage like FspSiliconInit. FSP specification >= 2.2
+ * has multiple stages as below.
+ */
+enum fsp_silicon_init_phases {
+ FSP_SILICON_INIT_API,
+ FSP_MULTI_PHASE_SI_INIT_GET_NUMBER_OF_PHASES_API,
+ FSP_MULTI_PHASE_SI_INIT_EXECUTE_PHASE_API
+};
+
+static void fsps_return_value_handler(enum fsp_silicon_init_phases phases, uint32_t status)
+{
+ uint8_t postcode;
+
+ /* Handle any reset request returned by FSP-S APIs */
+ fsp_handle_reset(status);
+
+ if (status == FSP_SUCCESS)
+ return;
+ /* Handle all other errors returned by FSP-S APIs */
+ /* Assume video failure if attempted to initialize graphics */
+ if (CONFIG(RUN_FSP_GOP) && vbt_get())
+ postcode = POST_VIDEO_FAILURE;
+ else
+ postcode = POST_HW_INIT_FAILURE; /* else generic */
+
+ switch (phases) {
+ case FSP_SILICON_INIT_API:
+ die_with_post_code(postcode, "FspSiliconInit returned with error 0x%08x\n",
+ status);
+ break;
+ case FSP_MULTI_PHASE_SI_INIT_GET_NUMBER_OF_PHASES_API:
+ printk(BIOS_SPEW, "FspMultiPhaseSiInit NumberOfPhases returned 0x%08x\n",
+ status);
+ break;
+ case FSP_MULTI_PHASE_SI_INIT_EXECUTE_PHASE_API:
+ printk(BIOS_SPEW, "FspMultiPhaseSiInit ExecutePhase returned 0x%08x\n",
+ status);
+ break;
+ default:
+ break;
+ }
+}
+
static void do_silicon_init(struct fsp_header *hdr)
{
FSPS_UPD *upd, *supd;
fsp_silicon_init_fn silicon_init;
uint32_t status;
- uint8_t postcode;
const struct cbmem_entry *logo_entry = NULL;
+ fsp_multi_phase_si_init_fn multi_phase_si_init;
+ struct fsp_multi_phase_params multi_phase_params;
+ struct fsp_multi_phase_get_number_of_phases_params multi_phase_get_number;
supd = (FSPS_UPD *) (hdr->cfg_region_offset + hdr->image_base);
@@ -64,20 +125,49 @@ static void do_silicon_init(struct fsp_header *hdr)
cbmem_entry_remove(logo_entry);
fsp_debug_after_silicon_init(status);
+ fsps_return_value_handler(FSP_SILICON_INIT_API, status);
- /* Handle any errors returned by FspSiliconInit */
- fsp_handle_reset(status);
- if (status != FSP_SUCCESS) {
- /* Assume video failure if attempted to initialize graphics */
- if (CONFIG(RUN_FSP_GOP) && vbt_get())
- postcode = POST_VIDEO_FAILURE;
- else
- postcode = POST_HW_INIT_FAILURE; /* else generic */
-
- printk(BIOS_SPEW, "FspSiliconInit returned 0x%08x\n", status);
- die_with_post_code(postcode,
- "FspSiliconInit returned an error!\n");
+ if (!CONFIG(PLATFORM_USES_FSP2_2))
+ return;
+
+ /* Check if SoC user would like to call Multi Phase Init */
+ if (!soc_fsp_multi_phase_init_is_enable())
+ return;
+
+ /* Call MultiPhaseSiInit */
+ multi_phase_si_init = (void *) (hdr->image_base +
+ hdr->multi_phase_si_init_entry_offset);
+
+ /* Implementing multi_phase_si_init() is optional as per FSP 2.2 spec */
+ if (multi_phase_si_init == NULL)
+ return;
+
+ post_code(POST_FSP_MULTI_PHASE_SI_INIT_ENTRY);
+ timestamp_add_now(TS_FSP_MULTI_PHASE_SI_INIT_START);
+ /* Get NumberOfPhases Value */
+ multi_phase_params.multi_phase_action = GET_NUMBER_OF_PHASES;
+ multi_phase_params.phase_index = 0;
+ multi_phase_params.multi_phase_param_ptr = &multi_phase_get_number;
+ status = multi_phase_si_init(&multi_phase_params);
+ fsps_return_value_handler(FSP_MULTI_PHASE_SI_INIT_GET_NUMBER_OF_PHASES_API, status);
+
+ /* Execute Multi Phase Execution */
+ for (int i = 1; i <= multi_phase_get_number.number_of_phases; i++) {
+ printk(BIOS_SPEW, "Executing Phase %d of FspMultiPhaseSiInit\n", i);
+ /*
+ * Give SoC/mainboard a chance to perform any operation before
+ * Multi Phase Execution
+ */
+ platform_fsp_multi_phase_init_cb(i);
+
+ multi_phase_params.multi_phase_action = EXECUTE_PHASE;
+ multi_phase_params.phase_index = i;
+ multi_phase_params.multi_phase_param_ptr = NULL;
+ status = multi_phase_si_init(&multi_phase_params);
+ fsps_return_value_handler(FSP_MULTI_PHASE_SI_INIT_EXECUTE_PHASE_API, status);
}
+ timestamp_add_now(TS_FSP_MULTI_PHASE_SI_INIT_END);
+ post_code(POST_FSP_MULTI_PHASE_SI_INIT_EXIT);
}
static int fsps_get_dest(const struct fsp_load_descriptor *fspld, void **dest,
diff --git a/src/drivers/intel/fsp2_0/util.c b/src/drivers/intel/fsp2_0/util.c
index a00b684624..e8c587628e 100644
--- a/src/drivers/intel/fsp2_0/util.c
+++ b/src/drivers/intel/fsp2_0/util.c
@@ -49,6 +49,8 @@ enum cb_err fsp_identify(struct fsp_header *hdr, const void *fsp_blob)
hdr->notify_phase_entry_offset = read32(raw_hdr + 56);
hdr->memory_init_entry_offset = read32(raw_hdr + 60);
hdr->silicon_init_entry_offset = read32(raw_hdr + 68);
+ if (CONFIG(PLATFORM_USES_FSP2_2))
+ hdr->multi_phase_si_init_entry_offset = read32(raw_hdr + 72);
return CB_SUCCESS;
}
diff --git a/src/include/console/post_codes.h b/src/include/console/post_codes.h
index 00a2ad3dec..0c6655cec8 100644
--- a/src/include/console/post_codes.h
+++ b/src/include/console/post_codes.h
@@ -289,6 +289,20 @@
#define POST_FSP_SILICON_EXIT 0x99
/**
+ * \brief Before calling FSP Multiphase SiliconInit
+ *
+ * Going to call into FSP binary for Multiple phase SI Init
+ */
+#define POST_FSP_MULTI_PHASE_SI_INIT_ENTRY 0xa0
+
+/**
+ * \brief After calling FSP Multiphase SiliconInit
+ *
+ * FSP binary returned from Multiple phase SI Init
+ */
+#define POST_FSP_MULTI_PHASE_SI_INIT_EXIT 0xa1
+
+/**
* \brief Entry into elf boot
*
* This POST code is called right before invoking jmp_to_elf_entry()