summaryrefslogtreecommitdiff
path: root/src/soc/intel/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/intel/common')
-rw-r--r--src/soc/intel/common/block/cse/Kconfig19
-rw-r--r--src/soc/intel/common/block/cse/cse.c11
-rw-r--r--src/soc/intel/common/block/cse/cse_eop.c148
3 files changed, 133 insertions, 45 deletions
diff --git a/src/soc/intel/common/block/cse/Kconfig b/src/soc/intel/common/block/cse/Kconfig
index f1f53d6537..33d703fb50 100644
--- a/src/soc/intel/common/block/cse/Kconfig
+++ b/src/soc/intel/common/block/cse/Kconfig
@@ -67,6 +67,25 @@ config SOC_INTEL_CSE_SEND_EOP_LATE
Starting with Jasper Lake, coreboot sends EOP before loading payload hence, this
config is applicable for those platforms.
+config SOC_INTEL_CSE_SEND_EOP_ASYNC
+ bool
+ depends on SOC_INTEL_COMMON_BLOCK_CSE
+ depends on !SOC_INTEL_CSE_SEND_EOP_LATE
+ depends on !SOC_INTEL_CSE_SEND_EOP_EARLY
+ help
+ Use this config to handle End Of Post (EOP) completion
+ asynchronously. The EOP command is sent first and the result
+ is checked later leaving time to CSE to complete the
+ operation while coreboot perform other activities.
+ Performing EOP asynchronously reduces the time spent
+ actively waiting for command completion which can have a
+ significant impact on boot time.
+
+ Using this asynchronous approach comes with the limitation
+ that no HECI command should be sent between the time the EOP
+ request is posted (at CSE .final device operation) and the
+ time coreboot check for its completion (BS_PAYLOAD_LOAD).
+
config SOC_INTEL_CSE_LITE_SKU
bool
default n
diff --git a/src/soc/intel/common/block/cse/cse.c b/src/soc/intel/common/block/cse/cse.c
index 9902094180..6c4bb73cee 100644
--- a/src/soc/intel/common/block/cse/cse.c
+++ b/src/soc/intel/common/block/cse/cse.c
@@ -1407,7 +1407,8 @@ static void cse_final_end_of_firmware(void)
*/
void cse_late_finalize(void)
{
- if (!CONFIG(SOC_INTEL_CSE_SEND_EOP_LATE))
+ if (!CONFIG(SOC_INTEL_CSE_SEND_EOP_LATE) &&
+ !CONFIG(SOC_INTEL_CSE_SEND_EOP_ASYNC))
return;
if (!CONFIG(USE_FSP_NOTIFY_PHASE_READY_TO_BOOT))
@@ -1431,6 +1432,14 @@ static void cse_final(struct device *dev)
if (CONFIG(SOC_INTEL_CSE_SET_EOP))
cse_send_end_of_post();
+ /*
+ * In asynchronous mode, the EOP command has most likely not been
+ * completed yet. Finalization steps will be run once the EOP command
+ * has successfully been completed.
+ */
+ if (CONFIG(SOC_INTEL_CSE_SEND_EOP_ASYNC))
+ return;
+
if (!CONFIG(USE_FSP_NOTIFY_PHASE_READY_TO_BOOT))
cse_final_ready_to_boot();
diff --git a/src/soc/intel/common/block/cse/cse_eop.c b/src/soc/intel/common/block/cse/cse_eop.c
index 53a4fa555e..dd67e595bb 100644
--- a/src/soc/intel/common/block/cse/cse_eop.c
+++ b/src/soc/intel/common/block/cse/cse_eop.c
@@ -67,36 +67,62 @@ static enum cse_cmd_result cse_disable_mei_bus(void)
return CSE_CMD_RESULT_SUCCESS;
}
-static enum cse_cmd_result cse_send_eop(void)
+static enum cse_cmd_result cse_receive_eop(void)
{
- enum cse_tx_rx_status ret;
enum {
EOP_REQUESTED_ACTION_CONTINUE = 0,
EOP_REQUESTED_ACTION_GLOBAL_RESET = 1,
};
- struct end_of_post_msg {
- struct mkhi_hdr hdr;
- } __packed msg = {
- .hdr = {
- .group_id = MKHI_GROUP_ID_GEN,
- .command = MKHI_END_OF_POST,
- },
- };
+ enum cse_tx_rx_status ret;
struct end_of_post_resp {
struct mkhi_hdr hdr;
uint32_t requested_actions;
} __packed resp = {};
size_t resp_size = sizeof(resp);
- /* For a CSE-Lite SKU, if the CSE is running RO FW and the board is
- running vboot in recovery mode, the CSE is expected to be in SOFT
- TEMP DISABLE state. */
- if (CONFIG(SOC_INTEL_CSE_LITE_SKU) && vboot_recovery_mode_enabled() &&
- cse_is_hfs1_com_soft_temp_disable()) {
- printk(BIOS_INFO, "HECI: coreboot in recovery mode; found CSE in expected SOFT "
- "TEMP DISABLE state, skipping EOP\n");
+ ret = heci_receive(&resp, &resp_size);
+ if (ret)
+ return decode_heci_send_receive_error(ret);
+
+ if (resp.hdr.group_id != MKHI_GROUP_ID_GEN ||
+ resp.hdr.command != MKHI_END_OF_POST) {
+ printk(BIOS_ERR, "HECI: EOP Unexpected response group or command.\n");
+ if (CONFIG(SOC_INTEL_CSE_SEND_EOP_ASYNC))
+ printk(BIOS_ERR, "HECI: It could be a HECI command conflict.\n");
+ return CSE_CMD_RESULT_ERROR;
+ }
+
+ if (resp.hdr.result) {
+ printk(BIOS_ERR, "HECI: EOP Resp Failed: %u\n", resp.hdr.result);
+ return CSE_CMD_RESULT_ERROR;
+ }
+
+ printk(BIOS_INFO, "CSE: EOP requested action: ");
+
+ switch (resp.requested_actions) {
+ case EOP_REQUESTED_ACTION_GLOBAL_RESET:
+ printk(BIOS_INFO, "global reset\n");
+ return CSE_CMD_RESULT_GLOBAL_RESET_REQUESTED;
+ case EOP_REQUESTED_ACTION_CONTINUE:
+ printk(BIOS_INFO, "continue boot\n");
return CSE_CMD_RESULT_SUCCESS;
+ default:
+ printk(BIOS_INFO, "unknown %u\n", resp.requested_actions);
+ return CSE_CMD_RESULT_ERROR;
}
+}
+
+static enum cse_cmd_result cse_send_eop(void)
+{
+ enum cse_tx_rx_status ret;
+ struct end_of_post_msg {
+ struct mkhi_hdr hdr;
+ } __packed msg = {
+ .hdr = {
+ .group_id = MKHI_GROUP_ID_GEN,
+ .command = MKHI_END_OF_POST,
+ },
+ };
/*
* Prerequisites:
@@ -119,28 +145,22 @@ static enum cse_cmd_result cse_send_eop(void)
printk(BIOS_INFO, "HECI: Sending End-of-Post\n");
- ret = heci_send_receive(&msg, sizeof(msg), &resp, &resp_size, HECI_MKHI_ADDR);
+ ret = heci_send(&msg, sizeof(msg), BIOS_HOST_ADDR, HECI_MKHI_ADDR);
if (ret)
return decode_heci_send_receive_error(ret);
- if (resp.hdr.result) {
- printk(BIOS_ERR, "HECI: EOP Resp Failed: %u\n", resp.hdr.result);
- return CSE_CMD_RESULT_ERROR;
- }
+ return CSE_CMD_RESULT_SUCCESS;
+}
- printk(BIOS_INFO, "CSE: EOP requested action: ");
+static enum cse_cmd_result cse_send_and_receive_eop(void)
+{
+ enum cse_cmd_result ret;
- switch (resp.requested_actions) {
- case EOP_REQUESTED_ACTION_GLOBAL_RESET:
- printk(BIOS_INFO, "global reset\n");
- return CSE_CMD_RESULT_GLOBAL_RESET_REQUESTED;
- case EOP_REQUESTED_ACTION_CONTINUE:
- printk(BIOS_INFO, "continue boot\n");
- return CSE_CMD_RESULT_SUCCESS;
- default:
- printk(BIOS_INFO, "unknown %u\n", resp.requested_actions);
- return CSE_CMD_RESULT_ERROR;
- }
+ ret = cse_send_eop();
+ if (ret != CSE_CMD_RESULT_SUCCESS)
+ return ret;
+
+ return cse_receive_eop();
}
static enum cse_cmd_result cse_send_cmd_retries(enum cse_cmd_result (*cse_send_command)(void))
@@ -199,11 +219,12 @@ static void handle_cse_eop_result(enum cse_cmd_result result)
}
}
-static void do_send_end_of_post(void)
+static void do_send_end_of_post(bool wait_for_completion)
{
- static bool eop_sent = false;
+ static bool eop_sent = false, eop_complete = false;
+ enum cse_cmd_result ret;
- if (eop_sent) {
+ if (eop_complete) {
printk(BIOS_WARNING, "EOP already sent\n");
return;
}
@@ -222,26 +243,65 @@ static void do_send_end_of_post(void)
return;
}
- set_cse_device_state(PCH_DEVFN_CSE, DEV_ACTIVE);
+ if (!eop_sent) {
+ set_cse_device_state(PCH_DEVFN_CSE, DEV_ACTIVE);
+ timestamp_add_now(TS_ME_END_OF_POST_START);
+ ret = cse_send_cmd_retries(cse_send_eop);
+ if (ret == CSE_CMD_RESULT_SUCCESS)
+ eop_sent = true;
+ }
- timestamp_add_now(TS_ME_END_OF_POST_START);
- handle_cse_eop_result(cse_send_cmd_retries(cse_send_eop));
+ if (!wait_for_completion)
+ return;
+
+ set_cse_device_state(PCH_DEVFN_CSE, DEV_ACTIVE);
+ ret = cse_receive_eop();
+ if (ret != CSE_CMD_RESULT_SUCCESS) {
+ ret = cse_send_cmd_retries(cse_send_and_receive_eop);
+ handle_cse_eop_result(ret);
+ }
timestamp_add_now(TS_ME_END_OF_POST_END);
set_cse_device_state(PCH_DEVFN_CSE, DEV_IDLE);
- eop_sent = true;
+ eop_complete = true;
+}
+
+/*
+ * Don't send EOP if the following conditions are met:
+ * 1. "The platform is running CSE-Lite SKU" AND
+ * 2. 'The CSE is running the RO FW" AND
+ * 3. "The board is in recovery mode"
+ *
+ * The above conditions summarize that the CSE is in "SOFT TEMP DISABLE" state,
+ * hence, don't send the EOP command to CSE.
+ */
+static bool is_cse_eop_supported(void)
+{
+ if (CONFIG(SOC_INTEL_CSE_LITE_SKU) && vboot_recovery_mode_enabled() &&
+ cse_is_hfs1_com_soft_temp_disable()) {
+ printk(BIOS_INFO, "HECI: coreboot in recovery mode; found CSE in expected SOFT "
+ "TEMP DISABLE state, skipping EOP\n");
+ return false;
+ }
+ return true;
}
void cse_send_end_of_post(void)
{
- return do_send_end_of_post();
+ if (!is_cse_eop_supported())
+ return;
+
+ return do_send_end_of_post(!CONFIG(SOC_INTEL_CSE_SEND_EOP_ASYNC));
}
static void send_cse_eop_with_late_finalize(void *unused)
{
- do_send_end_of_post();
- if (CONFIG(SOC_INTEL_CSE_SEND_EOP_LATE))
+ if (is_cse_eop_supported())
+ do_send_end_of_post(true);
+
+ if (CONFIG(SOC_INTEL_CSE_SEND_EOP_LATE) ||
+ CONFIG(SOC_INTEL_CSE_SEND_EOP_ASYNC))
cse_late_finalize();
}