intel: Extend SiP service to support mailbox's RSU
Introduce support for RSU that can be initiated through SMC calls.
Added features as below:
- RSU status
- RSU update
- RSU HPS notify
- RSU get sub-partition
Signed-off-by: Hadi Asyrafi <muhammad.hadi.asyrafi.abdul.halim@intel.com>
Change-Id: I78d5a07688e43da99f03d77dfd45ffb4a78f2e4c
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 <lib/mmio.h>
#include <lib/xlat_tables/xlat_tables.h>
+#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/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..620126e 100644
--- a/plat/intel/soc/common/socfpga_sip_svc.c
+++ b/plat/intel/soc/common/socfpga_sip_svc.c
@@ -365,6 +365,41 @@
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;
+}
+
/*
* This function is responsible for handling all SiP calls from the NS world
*/
@@ -381,6 +416,7 @@
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;
switch (smc_fid) {
@@ -446,6 +482,33 @@
(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);
+ }
+
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 <plat/common/platform.h>
#include <platform_def.h>
+#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[] = {