diff --git a/plat/intel/soc/agilex/bl31_plat_setup.c b/plat/intel/soc/agilex/bl31_plat_setup.c index 13099b4..4b11440 100644 --- a/plat/intel/soc/agilex/bl31_plat_setup.c +++ b/plat/intel/soc/agilex/bl31_plat_setup.c @@ -14,6 +14,7 @@ #include #include +#include "socfpga_mailbox.h" #include "socfpga_private.h" static entry_point_info_t bl32_image_ep_info; @@ -107,6 +108,8 @@ /* Signal secondary CPUs to jump to BL31 (BL2 = U-boot SPL) */ mmio_write_64(PLAT_CPU_RELEASE_ADDR, (uint64_t)plat_secondary_cpus_bl31_entry); + + mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL); } const mmap_region_t plat_agilex_mmap[] = { diff --git a/plat/intel/soc/common/include/socfpga_mailbox.h b/plat/intel/soc/common/include/socfpga_mailbox.h index c4b9e59..38f4696 100644 --- a/plat/intel/soc/common/include/socfpga_mailbox.h +++ b/plat/intel/soc/common/include/socfpga_mailbox.h @@ -73,6 +73,29 @@ /* Mailbox REBOOT commands */ #define MBOX_CMD_REBOOT_HPS 71 +/* Mailbox RSU commands */ +#define MBOX_GET_SUBPARTITION_TABLE 90 +#define MBOX_RSU_STATUS 91 +#define MBOX_RSU_UPDATE 92 + +/* Mailbox RSU macros */ +#define RSU_VERSION_ACMF BIT(8) +#define RSU_VERSION_ACMF_MASK 0xff00 + +/* HPS stage notify command */ +#define MBOX_HPS_STAGE_NOTIFY 93 + +/* Execution states for HPS_STAGE_NOTIFY */ +#define HPS_EXECUTION_STATE_FSBL 0 +#define HPS_EXECUTION_STATE_SSBL 1 +#define HPS_EXECUTION_STATE_OS 2 + +/* Mailbox reconfiguration commands */ +#define MBOX_CONFIG_STATUS 4 +#define MBOX_RECONFIG 6 +#define MBOX_RECONFIG_DATA 8 +#define MBOX_RECONFIG_STATUS 9 + /* Generic error handling */ #define MBOX_TIMEOUT -2047 #define MBOX_NO_RESPONSE -2 @@ -98,13 +121,6 @@ #define MBOX_CFGSTAT_STATE_ERROR_BOOT_INFO 0xf0000007 #define MBOX_CFGSTAT_STATE_ERROR_QSPI_ERROR 0xf0000008 -/* Mailbox reconfiguration commands */ -#define MBOX_CONFIG_STATUS 4 -#define MBOX_RECONFIG 6 -#define MBOX_RECONFIG_DATA 8 -#define MBOX_RECONFIG_STATUS 9 - - void mailbox_set_int(int interrupt_input); int mailbox_init(void); void mailbox_set_qspi_close(void); @@ -122,4 +138,9 @@ uint32_t intel_mailbox_get_config_status(uint32_t cmd); int intel_mailbox_is_fpga_not_ready(void); +int mailbox_rsu_get_spt_offset(uint32_t *resp_buf, uint32_t resp_buf_len); +int mailbox_rsu_status(uint32_t *resp_buf, uint32_t resp_buf_len); +int mailbox_rsu_update(uint32_t *flash_offset); +int mailbox_hps_stage_notify(uint32_t execution_stage); + #endif /* SOCFPGA_MBOX_H */ diff --git a/plat/intel/soc/common/include/socfpga_sip_svc.h b/plat/intel/soc/common/include/socfpga_sip_svc.h index 6bb41f3..2b1d983 100644 --- a/plat/intel/soc/common/include/socfpga_sip_svc.h +++ b/plat/intel/soc/common/include/socfpga_sip_svc.h @@ -28,6 +28,7 @@ #define INTEL_SIP_LEGACY_SMC_ECC_DBE 0xC200000D #define INTEL_SIP_SMC_RSU_NOTIFY 0xC200000E #define INTEL_SIP_SMC_RSU_RETRY_COUNTER 0xC200000F +#define INTEL_SIP_SMC_MBOX_SEND_CMD 0xC200001E /* FPGA config helpers */ #define INTEL_SIP_SMC_FPGA_CONFIG_ADDR 0x400000 diff --git a/plat/intel/soc/common/soc/socfpga_mailbox.c b/plat/intel/soc/common/soc/socfpga_mailbox.c index 8d7c1d6..673c2d5 100644 --- a/plat/intel/soc/common/soc/socfpga_mailbox.c +++ b/plat/intel/soc/common/soc/socfpga_mailbox.c @@ -267,6 +267,55 @@ mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_REBOOT_HPS, 0, 0, 0, NULL, 0); } +int mailbox_rsu_get_spt_offset(uint32_t *resp_buf, uint32_t resp_buf_len) +{ + return mailbox_send_cmd(MBOX_JOB_ID, MBOX_GET_SUBPARTITION_TABLE, + NULL, 0, 0, (uint32_t *)resp_buf, + resp_buf_len); +} + +struct rsu_status_info { + uint64_t current_image; + uint64_t fail_image; + uint32_t state; + uint32_t version; + uint32_t error_location; + uint32_t error_details; + uint32_t retry_counter; +}; + +int mailbox_rsu_status(uint32_t *resp_buf, uint32_t resp_buf_len) +{ + int ret; + struct rsu_status_info *info = (struct rsu_status_info *)resp_buf; + + info->retry_counter = ~0; + + ret = mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_STATUS, NULL, 0, 0, + (uint32_t *)resp_buf, resp_buf_len); + + if (ret < 0) + return ret; + + if (info->retry_counter != ~0) + if (!(info->version & RSU_VERSION_ACMF_MASK)) + info->version |= RSU_VERSION_ACMF; + + return ret; +} + +int mailbox_rsu_update(uint32_t *flash_offset) +{ + return mailbox_send_cmd(MBOX_JOB_ID, MBOX_RSU_UPDATE, + (uint32_t *)flash_offset, 2, 0, NULL, 0); +} + +int mailbox_hps_stage_notify(uint32_t execution_stage) +{ + return mailbox_send_cmd(MBOX_JOB_ID, MBOX_HPS_STAGE_NOTIFY, + &execution_stage, 1, 0, NULL, 0); +} + int mailbox_init(void) { int status = 0; diff --git a/plat/intel/soc/common/socfpga_psci.c b/plat/intel/soc/common/socfpga_psci.c index d8a6c19..d27ab9f 100644 --- a/plat/intel/soc/common/socfpga_psci.c +++ b/plat/intel/soc/common/socfpga_psci.c @@ -130,9 +130,14 @@ panic(); } +extern uint64_t intel_rsu_update_address; + static void __dead2 socfpga_system_reset(void) { - mailbox_reset_cold(); + if (intel_rsu_update_address) + mailbox_rsu_update((uint32_t *)&intel_rsu_update_address); + else + mailbox_reset_cold(); while (1) wfi(); diff --git a/plat/intel/soc/common/socfpga_sip_svc.c b/plat/intel/soc/common/socfpga_sip_svc.c index 41dae9e..b4fe6d6 100644 --- a/plat/intel/soc/common/socfpga_sip_svc.c +++ b/plat/intel/soc/common/socfpga_sip_svc.c @@ -365,6 +365,61 @@ return INTEL_SIP_SMC_STATUS_ERROR; } +/* Intel Remote System Update (RSU) services */ +uint64_t intel_rsu_update_address; + +static uint32_t intel_rsu_status(uint64_t *respbuf, uint32_t respbuf_sz) +{ + if (mailbox_rsu_status((uint32_t *)respbuf, respbuf_sz) < 0) + return INTEL_SIP_SMC_STATUS_ERROR; + + return INTEL_SIP_SMC_STATUS_OK; +} + +static uint32_t intel_rsu_update(uint64_t update_address) +{ + intel_rsu_update_address = update_address; + return INTEL_SIP_SMC_STATUS_OK; +} + +static uint32_t intel_rsu_notify(uint64_t execution_stage) +{ + if (mailbox_hps_stage_notify((uint32_t)execution_stage) < 0) + return INTEL_SIP_SMC_STATUS_ERROR; + + return INTEL_SIP_SMC_STATUS_OK; +} + +static uint32_t intel_rsu_retry_counter(uint32_t *respbuf, uint32_t respbuf_sz, + uint32_t *ret_stat) +{ + if (mailbox_rsu_status((uint32_t *)respbuf, respbuf_sz) < 0) + return INTEL_SIP_SMC_STATUS_ERROR; + + *ret_stat = respbuf[8]; + return INTEL_SIP_SMC_STATUS_OK; +} + +/* Mailbox services */ +static uint32_t intel_mbox_send_cmd(uint32_t cmd, uint32_t *args, int len, + int urgent, uint32_t *response, + int resp_len, int *mbox_status, + int *len_in_resp) +{ + int status = mailbox_send_cmd(MBOX_JOB_ID, cmd, args, len, urgent, + response, resp_len); + + if (status < 0) { + *len_in_resp = 0; + *mbox_status = -status; + return INTEL_SIP_SMC_STATUS_ERROR; + } + + *mbox_status = 0; + *len_in_resp = status; + return INTEL_SIP_SMC_STATUS_OK; +} + /* * This function is responsible for handling all SiP calls from the NS world */ @@ -381,7 +436,10 @@ uint32_t val = 0; uint32_t status = INTEL_SIP_SMC_STATUS_OK; uint32_t completed_addr[3]; + uint64_t rsu_respbuf[9]; uint32_t count = 0; + u_register_t x5, x6; + int mbox_status, len_in_resp; switch (smc_fid) { case SIP_SVC_UID: @@ -446,6 +504,41 @@ (uint32_t)x3, &val); SMC_RET3(handle, status, val, x1); + case INTEL_SIP_SMC_RSU_STATUS: + status = intel_rsu_status(rsu_respbuf, + ARRAY_SIZE(rsu_respbuf)); + if (status) { + SMC_RET1(handle, status); + } else { + SMC_RET4(handle, rsu_respbuf[0], rsu_respbuf[1], + rsu_respbuf[2], rsu_respbuf[3]); + } + + case INTEL_SIP_SMC_RSU_UPDATE: + status = intel_rsu_update(x1); + SMC_RET1(handle, status); + + case INTEL_SIP_SMC_RSU_NOTIFY: + status = intel_rsu_notify(x1); + SMC_RET1(handle, status); + + case INTEL_SIP_SMC_RSU_RETRY_COUNTER: + status = intel_rsu_retry_counter((uint32_t *)rsu_respbuf, + ARRAY_SIZE(rsu_respbuf), &val); + if (status) { + SMC_RET1(handle, status); + } else { + SMC_RET2(handle, status, val); + } + + case INTEL_SIP_SMC_MBOX_SEND_CMD: + x5 = SMC_GET_GP(handle, CTX_GPREG_X5); + x6 = SMC_GET_GP(handle, CTX_GPREG_X6); + status = intel_mbox_send_cmd(x1, (uint32_t *)x2, x3, x4, + (uint32_t *)x5, x6, &mbox_status, + &len_in_resp); + SMC_RET4(handle, status, mbox_status, x5, len_in_resp); + default: return socfpga_sip_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags); diff --git a/plat/intel/soc/stratix10/bl31_plat_setup.c b/plat/intel/soc/stratix10/bl31_plat_setup.c index 29f57c4..4c31238 100644 --- a/plat/intel/soc/stratix10/bl31_plat_setup.c +++ b/plat/intel/soc/stratix10/bl31_plat_setup.c @@ -16,6 +16,7 @@ #include #include +#include "socfpga_mailbox.h" #include "socfpga_private.h" #include "socfpga_reset_manager.h" #include "socfpga_system_manager.h" @@ -115,6 +116,8 @@ /* Signal secondary CPUs to jump to BL31 (BL2 = U-boot SPL) */ mmio_write_64(PLAT_CPU_RELEASE_ADDR, (uint64_t)plat_secondary_cpus_bl31_entry); + + mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL); } const mmap_region_t plat_stratix10_mmap[] = {