diff options
Diffstat (limited to 'src/soc/intel/common')
-rw-r--r-- | src/soc/intel/common/block/cse/Kconfig | 19 | ||||
-rw-r--r-- | src/soc/intel/common/block/cse/cse.c | 11 | ||||
-rw-r--r-- | src/soc/intel/common/block/cse/cse_eop.c | 148 |
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(); } |