feat(intel): implementation of SiPSVC-V3 protocol framework
- Develop SiPSVC-V3 framework to support async/yielding SMC calls.
- Add support for multi clients with multiple jobs running together.
- Add support for SDM doorbell interrupt handling.
- Keep the framework backward compatible with V1 clients.
- Enable the framework on all the platform Agilex7, Agilex5, N5X,
and Stratix10.
Change-Id: I9eb61c48be89867b4227e084493bfcf67cbe7924
Signed-off-by: Girisha Dengi <girisha.dengi@intel.com>
Signed-off-by: Sieu Mun Tang <sieu.mun.tang@altera.com>
diff --git a/plat/intel/soc/agilex/bl31_plat_setup.c b/plat/intel/soc/agilex/bl31_plat_setup.c
index 4c10e7b..a3c3545 100644
--- a/plat/intel/soc/agilex/bl31_plat_setup.c
+++ b/plat/intel/soc/agilex/bl31_plat_setup.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
- * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -175,6 +175,16 @@
mmio_write_64(PLAT_CPU_RELEASE_ADDR,
(uint64_t)plat_secondary_cpus_bl31_entry);
+#if SIP_SVC_V3
+ /*
+ * Re-initialize the mailbox to include V3 specific routines.
+ * In V3, this re-initialize is required because prior to BL31, U-Boot
+ * SPL has its own mailbox settings and this initialization will
+ * override to those settings as required by the V3 framework.
+ */
+ mailbox_init();
+#endif
+
mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL);
}
diff --git a/plat/intel/soc/agilex5/bl31_plat_setup.c b/plat/intel/soc/agilex5/bl31_plat_setup.c
index 17d955a..9e800f8 100644
--- a/plat/intel/soc/agilex5/bl31_plat_setup.c
+++ b/plat/intel/soc/agilex5/bl31_plat_setup.c
@@ -173,6 +173,17 @@
gicv3_distif_init();
gicv3_rdistif_init(plat_my_core_pos());
gicv3_cpuif_enable(plat_my_core_pos());
+
+#if SIP_SVC_V3
+ /*
+ * Re-initialize the mailbox to include V3 specific routines.
+ * In V3, this re-initialize is required because prior to BL31, U-Boot
+ * SPL has its own mailbox settings and this initialization will
+ * override to those settings as required by the V3 framework.
+ */
+ mailbox_init();
+#endif
+
mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL);
}
diff --git a/plat/intel/soc/common/include/platform_def.h b/plat/intel/soc/common/include/platform_def.h
index e2efeb1..6325d35 100644
--- a/plat/intel/soc/common/include/platform_def.h
+++ b/plat/intel/soc/common/include/platform_def.h
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
- * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -207,6 +207,9 @@
#define MAX_IO_DEVICES 4
#define MAX_IO_BLOCK_DEVICES 2
+/* Define this, to support the SiPSVC V3 implementation. */
+#define SIP_SVC_V3 1
+
#ifndef __ASSEMBLER__
struct socfpga_bl31_params {
param_header_t h;
diff --git a/plat/intel/soc/common/include/socfpga_mailbox.h b/plat/intel/soc/common/include/socfpga_mailbox.h
index e27af21..f965b7d 100644
--- a/plat/intel/soc/common/include/socfpga_mailbox.h
+++ b/plat/intel/soc/common/include/socfpga_mailbox.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
- * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -23,20 +23,22 @@
#define MBOX_TEST_BIT BIT(31)
/* Mailbox Shared Memory Register Map */
-#define MBOX_CIN 0x00
-#define MBOX_ROUT 0x04
-#define MBOX_URG 0x08
-#define MBOX_INT 0x0C
-#define MBOX_COUT 0x20
-#define MBOX_RIN 0x24
-#define MBOX_STATUS 0x2C
-#define MBOX_CMD_BUFFER 0x40
-#define MBOX_RESP_BUFFER 0xC0
+#define MBOX_CIN 0x00 /* Command valid offset, to SDM */
+#define MBOX_ROUT 0x04 /* Response output offset, to SDM */
+#define MBOX_URG 0x08 /* Urgent command, to SDM */
+#define MBOX_INT 0x0C /* Interrupt enables, to SDM */
+/* 0x10 - 0x1F, Reserved */
-/* Mailbox SDM doorbell */
-#define MBOX_DOORBELL_TO_SDM 0x400
-#define MBOX_DOORBELL_FROM_SDM 0x480
+#define MBOX_COUT 0x20 /* Command free offset, from SDM */
+#define MBOX_RIN 0x24 /* Response valid offset, from SDM */
+#define MBOX_STATUS 0x2C /* Mailbox status from SDM to client */
+/* 0x30 - 0x3F, Reserved */
+#define MBOX_CMD_BUFFER 0x40 /* Circular buffer, cmds to SDM */
+#define MBOX_RESP_BUFFER 0xC0 /* Circular buffer, resp from SDM */
+
+#define MBOX_DOORBELL_TO_SDM 0x400 /* Doorbell from HPS to SDM */
+#define MBOX_DOORBELL_FROM_SDM 0x480 /* Doorbell from SDM to HPS */
/* Mailbox commands */
@@ -61,12 +63,15 @@
#define MBOX_HWMON_READVOLT 0x18
#define MBOX_HWMON_READTEMP 0x19
-
/* QSPI Commands */
#define MBOX_CMD_QSPI_OPEN 0x32
#define MBOX_CMD_QSPI_CLOSE 0x33
#define MBOX_CMD_QSPI_SET_CS 0x34
+#define MBOX_CMD_QSPI_ERASE 0x38
+#define MBOX_CMD_QSPI_WRITE 0x39
+#define MBOX_CMD_QSPI_READ 0x3A
#define MBOX_CMD_QSPI_DIRECT 0x3B
+#define MBOX_CMD_QSPI_GET_DEV_INFO 0x74
/* SEU Commands */
#define MBOX_CMD_SEU_ERR_READ 0x3C
@@ -94,12 +99,14 @@
#define MBOX_FCS_ECDSA_SHA2_DATA_SIGN_VERIFY 0x87
#define MBOX_FCS_ECDSA_GET_PUBKEY 0x88
#define MBOX_FCS_ECDH_REQUEST 0x89
+#define MBOX_FCS_HKDF_REQUEST 0x8B
#define MBOX_FCS_OPEN_CS_SESSION 0xA0
#define MBOX_FCS_CLOSE_CS_SESSION 0xA1
#define MBOX_FCS_IMPORT_CS_KEY 0xA5
#define MBOX_FCS_EXPORT_CS_KEY 0xA6
#define MBOX_FCS_REMOVE_CS_KEY 0xA7
#define MBOX_FCS_GET_CS_KEY_INFO 0xA8
+#define MBOX_FCS_CREATE_CS_KEY 0xA9
/* PSG SIGMA Commands */
#define MBOX_PSG_SIGMA_TEARDOWN 0xD5
@@ -111,7 +118,9 @@
#define MBOX_GET_MEASUREMENT 0x183
/* Miscellaneous commands */
+#define MBOX_CMD_MCTP_MSG 0x194
#define MBOX_GET_ROM_PATCH_SHA384 0x1B0
+#define MBOX_CMD_GET_DEVICEID 0x500
/* Mailbox Definitions */
@@ -120,6 +129,18 @@
#define CMD_CASUAL 0
#define CMD_URGENT 1
+/* Mailbox command flags and related macros */
+#define MBOX_CMD_FLAG_DIRECT BIT(0)
+#define MBOX_CMD_FLAG_INDIRECT BIT(1)
+#define MBOX_CMD_FLAG_CASUAL BIT(2)
+#define MBOX_CMD_FLAG_URGENT BIT(3)
+
+#define MBOX_CMD_FLAG_CASUAL_INDIRECT (MBOX_CMD_FLAG_CASUAL | \
+ MBOX_CMD_FLAG_INDIRECT)
+
+#define IS_CMD_SET(cmd, _type) ((((cmd) & MBOX_CMD_FLAG_##_type) != 0) ? \
+ 1 : 0)
+
#define MBOX_WORD_BYTE 4U
#define MBOX_RESP_BUFFER_SIZE 16
#define MBOX_CMD_BUFFER_SIZE 32
@@ -171,22 +192,25 @@
+ MBOX_WORD_BYTE * (ptr))
/* Mailbox interrupt flags and masks */
-#define MBOX_INT_FLAG_COE 0x1
-#define MBOX_INT_FLAG_RIE 0x2
-#define MBOX_INT_FLAG_UAE 0x100
-#define MBOX_COE_BIT(INTERRUPT) ((INTERRUPT) & 0x3)
-#define MBOX_UAE_BIT(INTERRUPT) (((INTERRUPT) & (1<<8)))
+#define MBOX_INT_FLAG_COE BIT(0) /* COUT update interrupt enable */
+#define MBOX_INT_FLAG_RIE BIT(1) /* RIN update interrupt enable */
+#define MBOX_INT_FLAG_UAE BIT(8) /* Urgent ACK interrupt enable */
+
+#define MBOX_COE_BIT(INTERRUPT) ((INTERRUPT) & MBOX_INT_FLAG_COE)
+#define MBOX_RIE_BIT(INTERRUPT) ((INTERRUPT) & MBOX_INT_FLAG_RIE)
+#define MBOX_UAE_BIT(INTERRUPT) ((INTERRUPT) & MBOX_INT_FLAG_UAE)
/* Mailbox response and status */
#define MBOX_RESP_ERR(BUFFER) ((BUFFER) & 0x000007ff)
#define MBOX_RESP_LEN(BUFFER) (((BUFFER) & 0x007ff000) >> 12)
#define MBOX_RESP_CLIENT_ID(BUFFER) (((BUFFER) & 0xf0000000) >> 28)
#define MBOX_RESP_JOB_ID(BUFFER) (((BUFFER) & 0x0f000000) >> 24)
+#define MBOX_RESP_TRANSACTION_ID(BUFFER) (((BUFFER) & 0xff000000) >> 24)
#define MBOX_STATUS_UA_MASK (1<<8)
/* Mailbox command and response */
#define MBOX_CLIENT_ID_CMD(CLIENT_ID) ((CLIENT_ID) << 28)
-#define MBOX_JOB_ID_CMD(JOB_ID) (JOB_ID<<24)
+#define MBOX_JOB_ID_CMD(JOB_ID) (JOB_ID << 24)
#define MBOX_CMD_LEN_CMD(CMD_LEN) ((CMD_LEN) << 12)
#define MBOX_INDIRECT(val) ((val) << 11)
#define MBOX_CMD_MASK(header) ((header) & 0x7ff)
@@ -204,6 +228,17 @@
#define CONFIG_STATUS_FW_VER_OFFSET 1
#define CONFIG_STATUS_FW_VER_MASK 0x00FFFFFF
+/* QSPI mailbox command macros */
+#define MBOX_QSPI_SET_CS_OFFSET (28)
+#define MBOX_QSPI_SET_CS_MODE_OFFSET (27)
+#define MBOX_QSPI_SET_CS_CA_OFFSET (26)
+#define MBOX_QSPI_ERASE_SIZE_GRAN (0x400)
+
+#define MBOX_4K_ALIGNED_MASK (0xFFF)
+#define MBOX_IS_4K_ALIGNED(x) ((x) & MBOX_4K_ALIGNED_MASK)
+#define MBOX_IS_WORD_ALIGNED(x) (!((x) & 0x3))
+#define MBOX_QSPI_RW_MAX_WORDS (0x1000)
+
/* Data structure */
typedef struct mailbox_payload {
@@ -264,4 +299,107 @@
int mailbox_send_fpga_config_comp(void);
+#if SIP_SVC_V3
+#define MBOX_CLIENT_ID_SHIFT (28)
+#define MBOX_JOB_ID_SHIFT (24)
+#define MBOX_CMD_LEN_SHIFT (12)
+#define MBOX_INDIRECT_SHIFT (11)
+
+#define MBOX_FRAME_CMD_HEADER(client_id, job_id, args_len, indirect, cmd)\
+ ((client_id << MBOX_CLIENT_ID_SHIFT) | \
+ (job_id << MBOX_JOB_ID_SHIFT) | \
+ (args_len << MBOX_CMD_LEN_SHIFT) | \
+ (indirect << MBOX_CMD_LEN_SHIFT) | \
+ cmd)
+
+#define FLAG_SDM_RESPONSE_IS_VALID BIT(0)
+#define FLAG_SDM_RESPONSE_IS_USED BIT(1)
+#define FLAG_SDM_RESPONSE_IS_IN_PROGRESS BIT(2)
+#define FLAG_SDM_RESPONSE_IS_POLL_ON_INTR BIT(3)
+
+/*
+ * TODO: Re-visit this queue size based on the system load.
+ * 4 bits for client ID and 4 bits for job ID, total 8 bits and we can have up to
+ * 256 transactions. We can tune this based on our system load at any given time
+ */
+#define MBOX_SVC_CMD_QUEUE_SIZE (32)
+#define MBOX_SVC_RESP_QUEUE_SIZE (32)
+#define MBOX_SVC_MAX_JOB_ID (16)
+#define MBOX_SVC_CMD_ARG_SIZE (2)
+#define MBOX_SVC_CMD_IS_USED BIT(0)
+#define MBOX_SVC_CMD_CB_ARGS_SIZE (4)
+#define MBOX_SVC_MAX_CLIENTS (16)
+#define MBOX_SVC_MAX_RESP_DATA_SIZE (32)
+#define MBOX_SVC_SMC_RET_MAX_SIZE (8)
+
+/* Client ID(4bits) + Job ID(4bits) = Transcation ID(TID - 8bits, 256 combinations) */
+#define MBOX_MAX_TIDS (256)
+/* Each transcation ID bitmap holds 64bits */
+#define MBOX_TID_BITMAP_SIZE (sizeof(uint64_t) * 8)
+/* Number of transcation ID bitmaps required to hold 256 combinations */
+#define MBOX_MAX_TIDS_BITMAP (MBOX_MAX_TIDS / MBOX_TID_BITMAP_SIZE)
+
+/* SDM Response State (SRS) enums */
+typedef enum sdm_resp_state {
+ SRS_WAIT_FOR_RESP = 0x00U,
+ SRS_WAIT_FOR_HEADER,
+ SRS_WAIT_FOR_ARGUMENTS,
+ SRS_SYNC_ERROR
+} sdm_resp_state_t;
+
+/* SDM response data structure */
+typedef struct sdm_response {
+ bool is_poll_intr;
+ uint8_t client_id;
+ uint8_t job_id;
+ uint16_t resp_len;
+ uint16_t err_code;
+ uint32_t flags;
+ uint32_t header;
+ uint16_t rcvd_resp_len;
+ uint32_t resp_data[MBOX_SVC_MAX_RESP_DATA_SIZE];
+} sdm_response_t;
+
+/* SDM client callback template */
+typedef uint8_t (*sdm_command_callback)(void *resp, void *cmd,
+ uint32_t *ret_args);
+
+/* SDM command data structure */
+typedef struct sdm_command {
+ uint8_t client_id;
+ uint8_t job_id;
+ uint32_t flags;
+ sdm_command_callback cb;
+ uint32_t *cb_args;
+ uint8_t cb_args_len;
+} sdm_command_t;
+
+/* Get the transcation ID from client ID and job ID. */
+#define MBOX_GET_TRANS_ID(cid, jib) (((cid) << 4) | (jib))
+
+/* Mailbox service data structure */
+typedef struct mailbox_service {
+ sdm_resp_state_t resp_state;
+ sdm_resp_state_t next_resp_state;
+ uint32_t flags;
+ int curr_di;
+ uint64_t received_bitmap[MBOX_MAX_TIDS_BITMAP];
+ uint64_t interrupt_bitmap[MBOX_MAX_TIDS_BITMAP];
+ sdm_command_t cmd_queue[MBOX_SVC_CMD_QUEUE_SIZE];
+ sdm_response_t resp_queue[MBOX_SVC_RESP_QUEUE_SIZE];
+} mailbox_service_t;
+
+int mailbox_send_cmd_async_v3(uint8_t client_id, uint8_t job_id, uint32_t cmd,
+ uint32_t *args, uint32_t args_len, uint8_t cmd_flag,
+ sdm_command_callback cb, uint32_t *cb_args,
+ uint32_t cb_args_len);
+
+int mailbox_response_poll_v3(uint8_t client_id, uint8_t job_id, uint32_t *ret_args,
+ uint32_t *ret_args_size);
+
+int mailbox_response_poll_on_intr_v3(uint8_t *client_id, uint8_t *job_id,
+ uint64_t *bitmap);
+
+#endif /* #if SIP_SVC_V3 */
+
#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 31474c4..ab24dec 100644
--- a/plat/intel/soc/common/include/socfpga_sip_svc.h
+++ b/plat/intel/soc/common/include/socfpga_sip_svc.h
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2019-2023, Intel Corporation. All rights reserved.
- * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -26,6 +26,10 @@
#define INTEL_SIP_SMC_CMD_V2_RANGE_BEGIN 0x400
#define INTEL_SIP_SMC_CMD_V2_RANGE_END 0x4FF
+/* SiP V3 command code range */
+#define INTEL_SIP_SMC_CMD_V3_RANGE_BEGIN 0x00C8
+#define INTEL_SIP_SMC_CMD_V3_RANGE_END 0x01F4
+
/* SiP V2 protocol header */
#define INTEL_SIP_SMC_HEADER_JOB_ID_MASK 0xF
#define INTEL_SIP_SMC_HEADER_JOB_ID_OFFSET 0U
@@ -186,11 +190,11 @@
/*
* Increase if there is any backward compatibility impact
*/
-#define SIP_SVC_VERSION_MAJOR 2
+#define SIP_SVC_VERSION_MAJOR 3
/*
* Increase if there is new SMC function ID being added
*/
-#define SIP_SVC_VERSION_MINOR 2
+#define SIP_SVC_VERSION_MINOR 0
/* Structure Definitions */
@@ -240,4 +244,93 @@
void *handle,
u_register_t flags);
+
+#if SIP_SVC_V3
+#define SMC_RET_ARGS_ONE (1)
+#define SMC_RET_ARGS_TWO (2)
+#define SMC_RET_ARGS_THREE (3)
+#define SMC_RET_ARGS_FOUR (4)
+#define SMC_RET_ARGS_FIVE (5)
+#define SMC_RET_ARGS_SIX (6)
+
+/*
+ * SiP SVC Version3 SMC Functions IDs
+ */
+
+/* Generic response POLL commands */
+#define ALTERA_SIP_SMC_ASYNC_RESP_POLL (0x420000C8)
+#define ALTERA_SIP_SMC_ASYNC_RESP_POLL_ON_INTR (0x420000C9)
+
+/* Hardware monitor */
+#define ALTERA_SIP_SMC_ASYNC_HWMON_READTEMP (0x420000E8)
+#define ALTERA_SIP_SMC_ASYNC_HWMON_READVOLT (0x420000E9)
+
+/* FCS crypto service VAB/SDOS commands */
+#define ALTERA_SIP_SMC_ASYNC_FCS_RANDOM_NUMBER (0x4200012C)
+#define ALTERA_SIP_SMC_ASYNC_FCS_RANDOM_NUMBER_EXT (0x4200012D)
+#define ALTERA_SIP_SMC_ASYNC_FCS_CRYPTION (0x4200012E)
+#define ALTERA_SIP_SMC_ASYNC_FCS_CRYPTION_EXT (0x4200012F)
+#define ALTERA_SIP_SMC_ASYNC_FCS_SERVICE_REQUEST (0x42000130)
+#define ALTERA_SIP_SMC_ASYNC_FCS_SEND_CERTIFICATE (0x42000131)
+#define ALTERA_SIP_SMC_ASYNC_FCS_GET_PROVISION_DATA (0x42000132)
+#define ALTERA_SIP_SMC_ASYNC_FCS_CNTR_SET_PREAUTH (0x42000133)
+#define ALTERA_SIP_SMC_ASYNC_FCS_PSGSIGMA_TEARDOWN (0x42000134)
+#define ALTERA_SIP_SMC_ASYNC_FCS_CHIP_ID (0x42000135)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ATTESTATION_SUBKEY (0x42000136)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ATTESTATION_MEASUREMENTS (0x42000137)
+#define ALTERA_SIP_SMC_ASYNC_FCS_GET_ATTESTATION_CERT (0x42000138)
+#define ALTERA_SIP_SMC_ASYNC_FCS_CREATE_CERT_ON_RELOAD (0x42000139)
+
+/* FCS crypto service session management commands */
+#define ALTERA_SIP_SMC_ASYNC_FCS_OPEN_CS_SESSION (0x4200013A)
+#define ALTERA_SIP_SMC_ASYNC_FCS_CLOSE_CS_SESSION (0x4200013B)
+
+/* FCS crypto service key management commands */
+#define ALTERA_SIP_SMC_ASYNC_FCS_IMPORT_CS_KEY (0x4200013C)
+#define ALTERA_SIP_SMC_ASYNC_FCS_EXPORT_CS_KEY (0x4200013D)
+#define ALTERA_SIP_SMC_ASYNC_FCS_REMOVE_CS_KEY (0x4200013E)
+#define ALTERA_SIP_SMC_ASYNC_FCS_GET_CS_KEY_INFO (0x4200013F)
+#define ALTERA_SIP_SMC_ASYNC_FCS_CREATE_CS_KEY (0x42000167)
+
+/* FCS crypto service primitive commands */
+#define ALTERA_SIP_SMC_ASYNC_FCS_AES_CRYPT_INIT (0x42000140)
+#define ALTERA_SIP_SMC_ASYNC_FCS_AES_CRYPT_UPDATE (0x42000141)
+#define ALTERA_SIP_SMC_ASYNC_FCS_AES_CRYPT_FINALIZE (0x42000142)
+#define ALTERA_SIP_SMC_ASYNC_FCS_GET_DIGEST_INIT (0x42000143)
+#define ALTERA_SIP_SMC_ASYNC_FCS_GET_DIGEST_UPDATE (0x42000144)
+#define ALTERA_SIP_SMC_ASYNC_FCS_GET_DIGEST_FINALIZE (0x42000145)
+#define ALTERA_SIP_SMC_ASYNC_FCS_GET_DIGEST_SMMU_UPDATE (0x42000146)
+#define ALTERA_SIP_SMC_ASYNC_FCS_GET_DIGEST_SMMU_FINALIZE (0x42000147)
+#define ALTERA_SIP_SMC_ASYNC_FCS_MAC_VERIFY_INIT (0x42000148)
+#define ALTERA_SIP_SMC_ASYNC_FCS_MAC_VERIFY_UPDATE (0x42000149)
+#define ALTERA_SIP_SMC_ASYNC_FCS_MAC_VERIFY_FINALIZE (0x4200014A)
+#define ALTERA_SIP_SMC_ASYNC_FCS_MAC_VERIFY_SMMU_UPDATE (0x4200014B)
+#define ALTERA_SIP_SMC_ASYNC_FCS_MAC_VERIFY_SMMU_FINALIZE (0x4200014C)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ECDSA_HASH_SIGN_INIT (0x4200014D)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ECDSA_HASH_SIGN_FINALIZE (0x4200014E)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ECDSA_SHA2_DATA_SIGN_INIT (0x4200014F)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ECDSA_SHA2_DATA_SIGN_UPDATE (0x42000150)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ECDSA_SHA2_DATA_SIGN_FINALIZE (0x42000151)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ECDSA_SHA2_DATA_SIGN_SMMU_UPDATE (0x42000152)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ECDSA_SHA2_DATA_SIGN_SMMU_FINALIZE (0x42000153)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ECDSA_HASH_SIG_VERIFY_INIT (0x42000154)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ECDSA_HASH_SIG_VERIFY_FINALIZE (0x42000155)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ECDSA_SHA2_DATA_SIG_VERIFY_INIT (0x42000156)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ECDSA_SHA2_DATA_SIG_VERIFY_UPDATE (0x42000157)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ECDSA_SHA2_DATA_SIG_VERIFY_FINALIZE (0x42000158)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ECDSA_SHA2_DATA_SIG_VERIFY_SMMU_UPDATE (0x42000159)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ECDSA_SHA2_DATA_SIG_VERIFY_SMMU_FINALIZE (0x4200015A)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ECDSA_GET_PUBKEY_INIT (0x42000160)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ECDSA_GET_PUBKEY_FINALIZE (0x42000161)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ECDH_REQUEST_INIT (0x42000162)
+#define ALTERA_SIP_SMC_ASYNC_FCS_ECDH_REQUEST_FINALIZE (0x42000163)
+#define ALTERA_SIP_SMC_ASYNC_FCS_SDM_REMAPPER_CONFIG (0x42000164)
+#define ALTERA_SIP_SMC_ASYNC_FCS_MCTP (0x42000165)
+#define ALTERA_SIP_SMC_ASYNC_FCS_HKDF_REQUEST (0x42000166)
+
+
+#define GET_CLIENT_ID(x) (((x) & 0xF0) >> 4)
+#define GET_JOB_ID(x) ((x) & 0x0F)
+#endif /* SIP_SVC_V3 */
+
#endif /* SOCFPGA_SIP_SVC_H */
diff --git a/plat/intel/soc/common/soc/socfpga_mailbox.c b/plat/intel/soc/common/soc/socfpga_mailbox.c
index 69f0008..3b3b479 100644
--- a/plat/intel/soc/common/soc/socfpga_mailbox.c
+++ b/plat/intel/soc/common/soc/socfpga_mailbox.c
@@ -1,11 +1,12 @@
/*
* Copyright (c) 2020-2023, Intel Corporation. All rights reserved.
- * Copyright (c) 2024, Altera Corporation. All rights reserved.
+ * Copyright (c) 2024-2025, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <lib/mmio.h>
+#include <lib/spinlock.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <platform_def.h>
@@ -15,6 +16,34 @@
#include "socfpga_sip_svc.h"
#include "socfpga_system_manager.h"
+#if SIP_SVC_V3
+/* Function prototypes */
+void mailbox_init_v3(void);
+static int mailbox_response_handler_fsm(void);
+static inline void mailbox_free_cmd_desc(sdm_command_t *cmd_desc);
+static sdm_response_t *mailbox_get_resp_desc(uint8_t client_id, uint8_t job_id,
+ uint8_t *index);
+static sdm_command_t *mailbox_get_cmd_desc(uint8_t client_id, uint8_t job_id);
+static inline void mailbox_free_resp_desc(uint8_t index);
+static sdm_command_t *mailbox_get_free_cmd_desc(void);
+static sdm_response_t *mailbox_get_resp_desc_cid(uint8_t client_id,
+ uint8_t *index);
+static int mailbox_read_response_v3(uint8_t client_id, uint8_t *job_id,
+ uint32_t *header, uint32_t *resp,
+ uint32_t *resp_len,
+ uint8_t ignore_client_id);
+static int mailbox_poll_response_v3(uint8_t client_id, uint8_t job_id,
+ uint32_t *resp, unsigned int *resp_len,
+ uint32_t urgent);
+
+static spinlock_t mbox_db_lock; /* Mailbox service data base lock */
+static spinlock_t mbox_write_lock; /* Hardware mailbox FIFO write lock */
+static spinlock_t mbox_read_lock; /* Hardware mailbox FIFO read lock */
+
+static mailbox_service_t mbox_svc; /* Mailbox service data base */
+static uint8_t async_v1_job_id;
+#endif /* #if SIP_SVC_V3 */
+
static mailbox_payload_t mailbox_resp_payload;
static mailbox_container_t mailbox_resp_ctr = {0, 0, &mailbox_resp_payload};
@@ -34,13 +63,13 @@
static int wait_for_mailbox_cmdbuf_empty(uint32_t cin)
{
- unsigned int timeout = 200U;
+ unsigned int timeout = 20000U;
do {
if (is_mailbox_cmdbuf_empty(cin)) {
break;
}
- mdelay(10U);
+ udelay(50U);
} while (--timeout != 0U);
if (timeout == 0U) {
@@ -54,7 +83,9 @@
uint32_t data,
bool *is_doorbell_triggered)
{
- unsigned int timeout = 100U;
+ unsigned int timeout = 20000U;
+
+ VERBOSE("MBOX: 0x%x\n", data);
do {
if (is_mailbox_cmdbuf_full(*cin)) {
@@ -63,7 +94,7 @@
MBOX_DOORBELL_TO_SDM, 1U);
*is_doorbell_triggered = true;
}
- mdelay(10U);
+ udelay(50U);
} else {
mmio_write_32(MBOX_ENTRY_TO_ADDR(CMD, (*cin)++), data);
*cin %= MBOX_CMD_BUFFER_SIZE;
@@ -84,6 +115,11 @@
return MBOX_RET_OK;
}
+/*
+ * Function description: Write the command header, and its payload one by one
+ * into the mailbox command buffer. Along with this, check for mailbox buffer
+ * full condition and trigger doorbell to SDM if the command buffer is full.
+ */
static int fill_mailbox_circular_buffer(uint32_t header_cmd, uint32_t *args,
unsigned int len)
{
@@ -92,15 +128,21 @@
int ret;
bool is_doorbell_triggered = false;
+#if SIP_SVC_V3
+ spin_lock(&mbox_write_lock);
+#endif
+
cmd_free_offset = mmio_read_32(MBOX_OFFSET + MBOX_CIN);
sdm_read_offset = mmio_read_32(MBOX_OFFSET + MBOX_COUT);
+ /* Write the command header here */
ret = write_mailbox_cmd_buffer(&cmd_free_offset, sdm_read_offset,
header_cmd, &is_doorbell_triggered);
if (ret != 0) {
goto restart_mailbox;
}
+ /* Write the payload here w.r.to args and its len - one by one. */
for (i = 0U; i < len; i++) {
is_doorbell_triggered = false;
ret = write_mailbox_cmd_buffer(&cmd_free_offset,
@@ -113,6 +155,9 @@
mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U);
+#if SIP_SVC_V3
+ spin_unlock(&mbox_write_lock);
+#endif
return MBOX_RET_OK;
restart_mailbox:
@@ -129,12 +174,21 @@
}
}
+#if SIP_SVC_V3
+ spin_unlock(&mbox_write_lock);
+#endif
return MBOX_TIMEOUT;
}
int mailbox_read_response(unsigned int *job_id, uint32_t *response,
unsigned int *resp_len)
{
+#if SIP_SVC_V3
+ return mailbox_read_response_v3(MBOX_ATF_CLIENT_ID,
+ (uint8_t *)job_id, NULL,
+ response, resp_len,
+ 0);
+#else
uint32_t rin;
uint32_t rout;
uint32_t resp_data;
@@ -174,13 +228,23 @@
return MBOX_RET_OK;
}
+
return MBOX_NO_RESPONSE;
+#endif
}
int mailbox_read_response_async(unsigned int *job_id, uint32_t *header,
uint32_t *response, unsigned int *resp_len,
uint8_t ignore_client_id)
{
+#if SIP_SVC_V3
+ /* Just to avoid the build warning */
+ (void)mailbox_resp_ctr;
+ return mailbox_read_response_v3(MBOX_ATF_CLIENT_ID,
+ (uint8_t *)job_id, header,
+ response, resp_len,
+ ignore_client_id);
+#else
uint32_t rin;
uint32_t rout;
uint32_t resp_data;
@@ -220,7 +284,6 @@
return MBOX_WRONG_ID;
}
}
-
*job_id = MBOX_RESP_JOB_ID(resp_data);
ret_resp_len = MBOX_RESP_LEN(resp_data);
mailbox_resp_ctr.payload->header = resp_data;
@@ -272,11 +335,16 @@
*resp_len = 0;
return (mailbox_resp_ctr.flag & MBOX_PAYLOAD_FLAG_BUSY) ? MBOX_BUSY : MBOX_NO_RESPONSE;
+#endif
}
int mailbox_poll_response(uint32_t job_id, uint32_t urgent, uint32_t *response,
- unsigned int *resp_len)
+ unsigned int *resp_len)
{
+#if SIP_SVC_V3
+ return mailbox_poll_response_v3(MBOX_ATF_CLIENT_ID, (uint8_t)job_id,
+ response, resp_len, urgent);
+#else
unsigned int timeout = 40U;
unsigned int sdm_loop = 255U;
unsigned int ret_resp_len;
@@ -285,7 +353,6 @@
uint32_t resp_data;
while (sdm_loop != 0U) {
-
do {
if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM)
== 1U) {
@@ -310,7 +377,7 @@
}
mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U);
- INFO("Error: Mailbox did not get UA");
+ ERROR("MBOX: Mailbox did not get UA");
return MBOX_RET_ERROR;
}
@@ -324,13 +391,21 @@
rout %= MBOX_RESP_BUFFER_SIZE;
mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
- if (MBOX_RESP_CLIENT_ID(resp_data) != MBOX_ATF_CLIENT_ID
- || MBOX_RESP_JOB_ID(resp_data) != job_id) {
+ if ((MBOX_RESP_CLIENT_ID(resp_data) != MBOX_ATF_CLIENT_ID) ||
+ (MBOX_RESP_JOB_ID(resp_data) != job_id)) {
continue;
}
+ /* Get the return response len from the response header. */
ret_resp_len = MBOX_RESP_LEN(resp_data);
+ /* Print the response header. */
+ VERBOSE("MBOX: RespHdr: cid %d, jid %d, len %d, err_code 0x%x\n",
+ MBOX_RESP_CLIENT_ID(resp_data),
+ MBOX_RESP_JOB_ID(resp_data),
+ MBOX_RESP_LEN(resp_data),
+ MBOX_RESP_ERR(resp_data));
+
if (iterate_resp(ret_resp_len, response, resp_len)
!= MBOX_RET_OK) {
return MBOX_TIMEOUT;
@@ -349,6 +424,7 @@
INFO("Timed out waiting for SDM\n");
return MBOX_TIMEOUT;
+#endif
}
int iterate_resp(uint32_t mbox_resp_len, uint32_t *resp_buf,
@@ -366,8 +442,7 @@
if ((resp_buf != NULL) && (resp_len != NULL)
&& (*resp_len != 0U)) {
- *(resp_buf + total_resp_len)
- = resp_data;
+ *(resp_buf + total_resp_len) = resp_data;
*resp_len = *resp_len - 1;
total_resp_len++;
}
@@ -417,6 +492,9 @@
return status;
}
+#if SIP_SVC_V3
+ async_v1_job_id = (uint8_t)*job_id;
+#endif
*job_id = (*job_id + 1U) % MBOX_MAX_IND_JOB_ID;
return MBOX_RET_OK;
@@ -433,9 +511,7 @@
MBOX_STATUS_UA_MASK;
mmio_write_32(MBOX_OFFSET + MBOX_URG, cmd);
mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U);
- }
-
- else {
+ } else {
status = fill_mailbox_circular_buffer(
MBOX_CLIENT_ID_CMD(MBOX_ATF_CLIENT_ID) |
MBOX_JOB_ID_CMD(job_id) |
@@ -460,12 +536,12 @@
void mailbox_set_int(uint32_t interrupt)
{
-
- mmio_write_32(MBOX_OFFSET+MBOX_INT, MBOX_COE_BIT(interrupt) |
+ mmio_write_32(MBOX_OFFSET+MBOX_INT,
+ MBOX_COE_BIT(interrupt) |
+ MBOX_RIE_BIT(interrupt) |
MBOX_UAE_BIT(interrupt));
}
-
void mailbox_set_qspi_open(void)
{
mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE);
@@ -606,6 +682,7 @@
mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE |
MBOX_INT_FLAG_UAE);
+
mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U);
mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
@@ -616,8 +693,16 @@
return status;
}
+#if SIP_SVC_V3
+ /* Initialize the mailbox version3 implementation, and in V3 we
+ * are interested in only RIE interrupt
+ */
+ mailbox_init_v3();
+ mailbox_set_int(MBOX_INT_FLAG_RIE);
+#else
mailbox_set_int(MBOX_INT_FLAG_COE | MBOX_INT_FLAG_RIE |
MBOX_INT_FLAG_UAE);
+#endif
return MBOX_RET_OK;
}
@@ -730,3 +815,693 @@
return mailbox_send_cmd(MBOX_JOB_ID, MBOX_CMD_SAFE_INJECT_SEU_ERR, arg, len,
CMD_CASUAL, NULL, NULL);
}
+
+#if SIP_SVC_V3
+static int mailbox_fill_cmd_desc(uint8_t client_id, uint8_t job_id,
+ uint32_t *resp_buff)
+{
+ sdm_command_t *cmd_desc = NULL;
+
+ /* Get a free command descriptor */
+ cmd_desc = mailbox_get_free_cmd_desc();
+ if (cmd_desc == NULL) {
+ return MBOX_BUFFER_FULL;
+ }
+
+ /* Record all the given values for the command. */
+ cmd_desc->client_id = client_id;
+ cmd_desc->job_id = job_id;
+ cmd_desc->cb = NULL;
+ cmd_desc->cb_args = resp_buff;
+ cmd_desc->cb_args_len = 0U;
+
+ return MBOX_RET_OK;
+}
+
+/* Returns the command descriptor based on the client and job ID. */
+static sdm_command_t *mailbox_get_cmd_desc(uint8_t client_id, uint8_t job_id)
+{
+ spin_lock(&mbox_db_lock);
+ for (uint32_t count = 0; count < MBOX_SVC_CMD_QUEUE_SIZE; count++) {
+ if ((mbox_svc.cmd_queue[count].client_id == client_id) &&
+ (mbox_svc.cmd_queue[count].job_id == job_id) &&
+ (mbox_svc.cmd_queue[count].flags & MBOX_SVC_CMD_IS_USED)) {
+ spin_unlock(&mbox_db_lock);
+ return &(mbox_svc.cmd_queue[count]);
+ }
+ }
+
+ spin_unlock(&mbox_db_lock);
+ VERBOSE("MBOX: Command descriptor not found for cid %d, jid %d\n",
+ client_id, job_id);
+
+ return NULL;
+}
+
+/* Returns the response descriptor based on only client ID. */
+static sdm_response_t *mailbox_get_resp_desc_cid(uint8_t client_id, uint8_t *index)
+{
+ spin_lock(&mbox_db_lock);
+
+ for (uint32_t count = 0; count < MBOX_SVC_RESP_QUEUE_SIZE; count++) {
+ if ((mbox_svc.resp_queue[count].client_id == client_id) &&
+ (mbox_svc.resp_queue[count].flags & FLAG_SDM_RESPONSE_IS_VALID)) {
+ *index = count;
+ /*
+ * Once we get the valid response descriptor, get the
+ * job ID and mark up the bitmaps.
+ */
+ uint8_t job_id = mbox_svc.resp_queue[count].job_id;
+ uint8_t transaction_id = MBOX_GET_TRANS_ID(client_id, job_id);
+
+ mbox_svc.received_bitmap[transaction_id / MBOX_TID_BITMAP_SIZE] &=
+ ~(1ULL << (transaction_id % MBOX_TID_BITMAP_SIZE));
+ mbox_svc.interrupt_bitmap[transaction_id / MBOX_TID_BITMAP_SIZE] &=
+ ~(1ULL << (transaction_id % MBOX_TID_BITMAP_SIZE));
+ spin_unlock(&mbox_db_lock);
+ return &(mbox_svc.resp_queue[count]);
+ }
+ }
+
+ spin_unlock(&mbox_db_lock);
+ VERBOSE("MBOX: Response descriptor not found for cid %d\n", client_id);
+
+ return NULL;
+}
+
+/* Returns the response descriptor based on the client and job ID. */
+static sdm_response_t *mailbox_get_resp_desc(uint8_t client_id, uint8_t job_id, uint8_t *index)
+{
+ spin_lock(&mbox_db_lock);
+ /*
+ * Let's first check whether we have a response bitmap set for the given
+ * client ID and job ID.
+ */
+ uint8_t transaction_id = MBOX_GET_TRANS_ID(client_id, job_id);
+
+ if ((mbox_svc.received_bitmap[transaction_id / MBOX_TID_BITMAP_SIZE] &
+ (1ULL << (transaction_id % MBOX_TID_BITMAP_SIZE))) == 0) {
+ spin_unlock(&mbox_db_lock);
+ VERBOSE("MBOX: Response bitmap not set for cid %d, jid %d, bitmap 0x%16lx\n",
+ client_id, job_id, mbox_svc.received_bitmap[transaction_id / 64]);
+ return NULL;
+ }
+
+ for (uint32_t count = 0; count < MBOX_SVC_RESP_QUEUE_SIZE; count++) {
+ if (mbox_svc.resp_queue[count].flags & FLAG_SDM_RESPONSE_IS_VALID) {
+ if ((mbox_svc.resp_queue[count].client_id == client_id) &&
+ (mbox_svc.resp_queue[count].job_id == job_id)) {
+ *index = count;
+ mbox_svc.received_bitmap[transaction_id / MBOX_TID_BITMAP_SIZE] &=
+ ~(1ULL << (transaction_id % MBOX_TID_BITMAP_SIZE));
+ mbox_svc.interrupt_bitmap[transaction_id / MBOX_TID_BITMAP_SIZE] &=
+ ~(1ULL << (transaction_id % MBOX_TID_BITMAP_SIZE));
+ spin_unlock(&mbox_db_lock);
+ return &(mbox_svc.resp_queue[count]);
+ }
+ }
+ }
+
+ spin_unlock(&mbox_db_lock);
+ VERBOSE("MBOX: Response descriptor not found for cid %d, jid %d\n",
+ client_id, job_id);
+
+ return NULL;
+}
+
+static int32_t mailbox_get_free_resp_desc(void)
+{
+ spin_lock(&mbox_db_lock);
+ static uint32_t free_index = MBOX_SVC_RESP_QUEUE_SIZE - 1;
+ uint32_t count = 0U, try = 0U;
+
+ for (try = 0; try < MBOX_SVC_RESP_QUEUE_SIZE; try++) {
+ free_index = (free_index + 1) % MBOX_SVC_RESP_QUEUE_SIZE;
+ if ((mbox_svc.resp_queue[free_index].flags &
+ FLAG_SDM_RESPONSE_IS_USED) != 0U) {
+ count = free_index;
+ spin_unlock(&mbox_db_lock);
+ return count;
+ }
+ }
+
+ /* No free descriptors are available */
+ spin_unlock(&mbox_db_lock);
+ VERBOSE("MBOX: No free response descriptors are available\n");
+
+ return MBOX_BUFFER_FULL;
+}
+
+static sdm_command_t *mailbox_get_free_cmd_desc(void)
+{
+ spin_lock(&mbox_db_lock);
+ static uint32_t free_index;
+
+ /* Rollover the command queue free index */
+ if (free_index == (MBOX_SVC_CMD_QUEUE_SIZE - 1)) {
+ free_index = 0U;
+ }
+
+ for (; free_index < MBOX_SVC_CMD_QUEUE_SIZE; free_index++) {
+ if ((mbox_svc.cmd_queue[free_index].flags &
+ MBOX_SVC_CMD_IS_USED) != 0U) {
+ mbox_svc.cmd_queue[free_index].flags |= MBOX_SVC_CMD_IS_USED;
+ spin_unlock(&mbox_db_lock);
+ return &(mbox_svc.cmd_queue[free_index]);
+ }
+ }
+
+ /* No free command descriptors are available */
+ spin_unlock(&mbox_db_lock);
+ VERBOSE("MBOX: No free command descriptors available\n");
+
+ return NULL;
+}
+
+static inline void mailbox_free_cmd_desc(sdm_command_t *cmd_desc)
+{
+ if (cmd_desc == NULL) {
+ return;
+ }
+
+ spin_lock(&mbox_db_lock);
+ memset((void *)cmd_desc, 0, sizeof(sdm_command_t));
+ spin_unlock(&mbox_db_lock);
+}
+
+static inline void mailbox_free_resp_desc(uint8_t index)
+{
+ if (index >= MBOX_SVC_RESP_QUEUE_SIZE) {
+ return;
+ }
+
+ spin_lock(&mbox_db_lock);
+ memset((void *)&mbox_svc.resp_queue[index], 0, sizeof(sdm_response_t));
+ spin_unlock(&mbox_db_lock);
+}
+
+/*
+ * This function serves the V1 _sync_read and _async_read functionality, and it
+ * is introduced as part of V3 framework to keep backward compatible with V1
+ * clients.
+ */
+static int mailbox_read_response_v3(uint8_t client_id, uint8_t *job_id,
+ uint32_t *header, uint32_t *resp,
+ uint32_t *resp_len,
+ uint8_t ignore_client_id)
+{
+ uint8_t di = 0U;
+ int status = MBOX_RET_OK;
+ sdm_response_t *resp_desc = NULL;
+ sdm_command_t *cmd_desc = NULL;
+
+ /*
+ * In the V1, the client ID is always MBOX_ATF_CLIENT_ID and in this
+ * routine we will collect the response which only belongs to this
+ * client ID. So safe to ignore this input.
+ */
+ (void)ignore_client_id;
+
+ /* Clear the SDM doorbell interrupt */
+ if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM) == 1U)
+ mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
+
+ /* Fill the command descriptor index and get the same */
+ status = mailbox_fill_cmd_desc(client_id, async_v1_job_id, resp);
+ if (status != MBOX_RET_OK) {
+ return status;
+ }
+
+ cmd_desc = mailbox_get_cmd_desc(client_id, async_v1_job_id);
+
+ /* Get the response from SDM, just go through one cycle */
+ status = mailbox_response_handler_fsm();
+ if (status != MBOX_RET_OK) {
+ mailbox_free_cmd_desc(cmd_desc);
+ *resp_len = 0U;
+ return status;
+ }
+
+ /* Check the local response queue with the given client ID */
+ resp_desc = mailbox_get_resp_desc_cid(client_id, &di);
+ if (resp_desc == NULL) {
+ mailbox_free_cmd_desc(cmd_desc);
+ *resp_len = 0U;
+ return MBOX_NO_RESPONSE;
+ }
+
+ /* Update the received mailbox response length, job ID and header */
+ *job_id = resp_desc->job_id;
+ *resp_len = resp_desc->rcvd_resp_len;
+ if (header != NULL) {
+ *header = resp_desc->header;
+ }
+
+ /* Check the mailbox response error code */
+ if (MBOX_RESP_ERR(resp_desc->header) > 0U) {
+ INFO("MBOX: Error in async response: %x\n", resp_desc->header);
+ status = -MBOX_RESP_ERR(resp_desc->header);
+ }
+
+ /* Free up the response and command descriptors */
+ mailbox_free_resp_desc(di);
+ mailbox_free_cmd_desc(cmd_desc);
+
+ return status;
+}
+
+int mailbox_send_cmd_async_v3(uint8_t client_id, uint8_t job_id, uint32_t cmd,
+ uint32_t *args, uint32_t args_len, uint8_t cmd_flag,
+ sdm_command_callback cb, uint32_t *cb_args,
+ uint32_t cb_args_len)
+{
+ int status = 0;
+ sdm_command_t *cmd_desc = NULL;
+
+ VERBOSE("MBOX: cid: %d, jid: %d, cmd: %d, cmd_flag: %d\n",
+ client_id, job_id, cmd, cmd_flag);
+
+ if (IS_CMD_SET(cmd_flag, URGENT)) {
+ mmio_write_32(MBOX_OFFSET + MBOX_URG, cmd);
+ mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U);
+ } else {
+ /* Get a free command descriptor */
+ cmd_desc = mailbox_get_free_cmd_desc();
+ if (cmd_desc == NULL) {
+ return MBOX_BUFFER_FULL;
+ }
+
+ /* Record all the given values for the command. */
+ cmd_desc->client_id = client_id;
+ cmd_desc->job_id = job_id;
+ cmd_desc->cb = cb;
+ cmd_desc->cb_args = cb_args;
+ cmd_desc->cb_args_len = cb_args_len;
+
+ /* Push the command to mailbox FIFO */
+ status = fill_mailbox_circular_buffer(
+ MBOX_FRAME_CMD_HEADER(client_id, job_id,
+ args_len, IS_CMD_SET(cmd_flag, INDIRECT), cmd),
+ args,
+ args_len);
+
+ if (status != MBOX_RET_OK) {
+ INFO("MBOX: Failed to push the command to mailbox FIFO\n");
+ /* Free the command descriptor. */
+ mailbox_free_cmd_desc(cmd_desc);
+ }
+ }
+
+ INFO("MBOX: %s: status: %d\n", __func__, status);
+
+ return status;
+}
+
+static int mailbox_poll_response_v3(uint8_t client_id, uint8_t job_id,
+ uint32_t *resp, unsigned int *resp_len,
+ uint32_t urgent)
+{
+ unsigned int timeout = 40U;
+ unsigned int sdm_loop = 255U;
+ bool is_cmd_desc_fill = false;
+ uint8_t di = 0U;
+ sdm_response_t *resp_desc = NULL;
+ sdm_command_t *cmd_desc = NULL;
+
+ while (sdm_loop != 0U) {
+ do {
+ if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM)
+ == 1U) {
+ break;
+ }
+ mdelay(10U);
+ } while (--timeout != 0U);
+
+ if (timeout == 0U) {
+ INFO("%s: Timed out waiting for SDM intr\n", __func__);
+ break;
+ }
+
+ mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
+
+ if ((urgent & 1U) != 0U) {
+ mdelay(5U);
+ if ((mmio_read_32(MBOX_OFFSET + MBOX_STATUS) &
+ MBOX_STATUS_UA_MASK) ^
+ (urgent & MBOX_STATUS_UA_MASK)) {
+ mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U);
+ return MBOX_RET_OK;
+ }
+
+ mmio_write_32(MBOX_OFFSET + MBOX_URG, 0U);
+ ERROR("MBOX: Mailbox did not get UA");
+ return MBOX_RET_ERROR;
+ }
+
+ /* Fill the command descriptor index and get the same. */
+ if (!is_cmd_desc_fill) {
+ if (mailbox_fill_cmd_desc(client_id, job_id, resp) !=
+ MBOX_RET_OK) {
+ return MBOX_BUFFER_FULL;
+ }
+
+ cmd_desc = mailbox_get_cmd_desc(client_id, job_id);
+ is_cmd_desc_fill = true;
+ }
+
+ /* Since it is sync call, will try to read till it time out */
+ (void)mailbox_response_handler_fsm();
+
+ /* Check the response queue with the given client ID and job ID */
+ resp_desc = mailbox_get_resp_desc(client_id, job_id, &di);
+ if (resp_desc != NULL) {
+ VERBOSE("%s: Resp received for cid %d, jid %d\n",
+ __func__, resp_desc->client_id, resp_desc->job_id);
+
+ uint16_t header = resp_desc->header;
+
+ /* Update the return response length */
+ if (resp_len != NULL) {
+ *resp_len = resp_desc->rcvd_resp_len;
+ }
+
+ /* Free the response and command descriptor */
+ mailbox_free_resp_desc(di);
+ mailbox_free_cmd_desc(cmd_desc);
+
+ if (MBOX_RESP_ERR(header) > 0U) {
+ INFO("%s: SDM err code: 0x%x\n", __func__,
+ MBOX_RESP_ERR(header));
+ return -MBOX_RESP_ERR(header);
+ }
+
+ VERBOSE("%s: MBOX_RET_OK\n", __func__);
+ return MBOX_RET_OK;
+ }
+ sdm_loop--;
+ }
+
+ INFO("%s: Timed out waiting for SDM\n", __func__);
+ return MBOX_TIMEOUT;
+}
+
+/* SDM response parser handler state machine. */
+static void mailbox_response_parser(void)
+{
+ int di = -1; /* Descriptor index */
+ uint32_t rin;
+ uint32_t rout;
+
+ switch (mbox_svc.next_resp_state) {
+ case SRS_WAIT_FOR_RESP:
+ {
+ mbox_svc.resp_state = SRS_WAIT_FOR_RESP;
+
+ rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
+ rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
+ if (rin != rout) {
+ mbox_svc.next_resp_state = SRS_WAIT_FOR_HEADER;
+ }
+
+ break;
+ }
+
+ case SRS_WAIT_FOR_HEADER:
+ {
+ mbox_svc.resp_state = SRS_WAIT_FOR_HEADER;
+ uint32_t resp_hdr;
+ uint8_t trans_id = 0U;
+
+ rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
+ rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
+ if (rin != rout) {
+ /* Read the header and dequeue from the queue. */
+ resp_hdr = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++));
+ rout %= MBOX_RESP_BUFFER_SIZE;
+ mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
+
+ /* Allocate a new response descriptor */
+ di = mailbox_get_free_resp_desc();
+ if (di != -1) {
+ mbox_svc.curr_di = di;
+ mbox_svc.resp_queue[di].header = resp_hdr;
+ mbox_svc.resp_queue[di].client_id = MBOX_RESP_CLIENT_ID(resp_hdr);
+ mbox_svc.resp_queue[di].job_id = MBOX_RESP_JOB_ID(resp_hdr);
+ mbox_svc.resp_queue[di].resp_len = MBOX_RESP_LEN(resp_hdr);
+ mbox_svc.resp_queue[di].flags |= (FLAG_SDM_RESPONSE_IS_USED |
+ FLAG_SDM_RESPONSE_IS_IN_PROGRESS);
+ mbox_svc.resp_queue[di].err_code = MBOX_RESP_ERR(resp_hdr);
+ trans_id = MBOX_RESP_TRANSACTION_ID(resp_hdr);
+
+ VERBOSE("MBOX: Resp Hdr: cid %d, jid %d, len %d, err_code 0x%x\n",
+ mbox_svc.resp_queue[di].client_id,
+ mbox_svc.resp_queue[di].job_id,
+ mbox_svc.resp_queue[di].resp_len,
+ mbox_svc.resp_queue[di].err_code);
+
+ /* Check if the response is an argument response */
+ if (mbox_svc.resp_queue[di].resp_len > 0) {
+ mbox_svc.next_resp_state = SRS_WAIT_FOR_ARGUMENTS;
+ } else {
+ VERBOSE("MBOX: Received complete response with no args\n");
+ /* Non argument response, done */
+ mbox_svc.resp_queue[mbox_svc.curr_di].flags |=
+ FLAG_SDM_RESPONSE_IS_VALID;
+
+ /* Go back to waiting for new response */
+ mbox_svc.next_resp_state = SRS_WAIT_FOR_RESP;
+ mbox_svc.curr_di = -1;
+
+ /* Mark the transaction ID as received */
+ spin_lock(&mbox_db_lock);
+ mbox_svc.received_bitmap[trans_id / MBOX_TID_BITMAP_SIZE] |=
+ (1ULL << (trans_id % MBOX_TID_BITMAP_SIZE));
+ spin_unlock(&mbox_db_lock);
+ }
+ } else {
+ mbox_svc.next_resp_state = SRS_SYNC_ERROR;
+ }
+ }
+ break;
+ }
+
+ case SRS_WAIT_FOR_ARGUMENTS:
+ {
+ mbox_svc.resp_state = SRS_WAIT_FOR_ARGUMENTS;
+ uint16_t mbox_resp_len = mbox_svc.resp_queue[mbox_svc.curr_di].resp_len;
+ uint32_t *read_buff = NULL;
+ uint16_t read_len = 0U;
+ uint16_t read_max_len = 0U;
+ uint32_t timeout = 0U;
+
+ /* Determine where to copy the buffer. */
+ sdm_command_t *cmd_desc = mailbox_get_cmd_desc(
+ mbox_svc.resp_queue[mbox_svc.curr_di].client_id,
+ mbox_svc.resp_queue[mbox_svc.curr_di].job_id);
+ if (cmd_desc != NULL && cmd_desc->cb_args != NULL) {
+ read_buff = cmd_desc->cb_args;
+ read_max_len = mbox_resp_len;
+ } else {
+ read_buff = (uint32_t *)mbox_svc.resp_queue[mbox_svc.curr_di].resp_data;
+ read_max_len = MBOX_SVC_MAX_RESP_DATA_SIZE;
+ }
+
+ rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
+ rout = mmio_read_32(MBOX_OFFSET + MBOX_ROUT);
+
+ while ((read_len < mbox_resp_len) && (rin != rout) && (read_len < read_max_len)) {
+ timeout = 10000U;
+
+ /* Copy the response data to the buffer */
+ read_buff[read_len++] = mmio_read_32(MBOX_ENTRY_TO_ADDR(RESP, (rout)++));
+
+ VERBOSE("MBOX: 0x%x\n", read_buff[read_len - 1]);
+
+ /* Update the read out buffer index */
+ rout %= MBOX_RESP_BUFFER_SIZE;
+ mmio_write_32(MBOX_OFFSET + MBOX_ROUT, rout);
+
+ /*
+ * The response buffer is of 16 words size, this loop checks
+ * if the response buffer is empty and if empty trigger an
+ * interrupt to SDM and wait for the response buffer to fill
+ */
+ do {
+ if (read_len == mbox_resp_len)
+ break;
+
+ rin = mmio_read_32(MBOX_OFFSET + MBOX_RIN);
+ if (rout == rin) {
+ mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U);
+ udelay(100);
+ } else {
+ break;
+ }
+ timeout--;
+ } while ((read_len < mbox_resp_len) && (timeout != 0U));
+
+ if (timeout == 0U) {
+ INFO("MBOX: Timeout waiting for response data\n");
+ mbox_svc.next_resp_state = SRS_SYNC_ERROR;
+ break;
+ }
+ }
+
+ /* Check if we have received all the arguments */
+ mbox_svc.resp_queue[mbox_svc.curr_di].rcvd_resp_len = read_len;
+ if (mbox_resp_len == read_len) {
+ uint8_t transaction_id =
+ ((mbox_svc.resp_queue[mbox_svc.curr_di].client_id << 4) |
+ (mbox_svc.resp_queue[mbox_svc.curr_di].job_id));
+ VERBOSE("MBOX: Received all the response data len %d, transaction_id %d\n",
+ read_len, transaction_id);
+
+ spin_lock(&mbox_db_lock);
+ mbox_svc.received_bitmap[transaction_id / MBOX_TID_BITMAP_SIZE] |=
+ (1ULL << (transaction_id % MBOX_TID_BITMAP_SIZE));
+ spin_unlock(&mbox_db_lock);
+
+ mbox_svc.resp_queue[mbox_svc.curr_di].flags |= FLAG_SDM_RESPONSE_IS_VALID;
+ mbox_svc.next_resp_state = SRS_WAIT_FOR_RESP;
+ mbox_svc.curr_di = -1;
+ } else {
+ mbox_svc.next_resp_state = SRS_SYNC_ERROR;
+ VERBOSE("MBOX: Received partial response data len %d, max len %d\n",
+ read_len, read_max_len);
+ }
+ break;
+ }
+
+ case SRS_SYNC_ERROR:
+ {
+ mbox_svc.resp_state = SRS_SYNC_ERROR;
+ INFO("MBOX: Error in response handling\n");
+ break;
+ }
+
+ default:
+ break;
+ } /* switch */
+}
+
+static int mailbox_response_handler_fsm(void)
+{
+ int status = MBOX_RET_OK;
+
+ spin_lock(&mbox_read_lock);
+ /* Mailbox peripheral response parser */
+ do {
+ /* Iterate till the state machine transition ends */
+ mailbox_response_parser();
+
+ /* Note down if there is any error in the response parsing */
+ if (mbox_svc.next_resp_state == SRS_SYNC_ERROR) {
+ status = MBOX_RET_ERROR;
+ }
+
+ } while (mbox_svc.resp_state != mbox_svc.next_resp_state);
+ spin_unlock(&mbox_read_lock);
+
+ return status;
+}
+
+int mailbox_response_poll_on_intr_v3(uint8_t *client_id, uint8_t *job_id,
+ uint64_t *bitmap)
+{
+ uint32_t i = 0U;
+ int status = MBOX_RET_OK;
+
+ /* Clear the SDM doorbell interrupt immediately */
+ if (mmio_read_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM) == 1U) {
+ mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_FROM_SDM, 0U);
+ }
+
+ /* Check mailbox FIFO for any pending responses available to read. */
+ status = mailbox_response_handler_fsm();
+ if (status != MBOX_RET_OK) {
+ return status;
+ }
+
+ /*
+ * Once we read the complete mailbox FIFO, let's mark up the bitmap for
+ * available responses with respect to each transcation IDs.
+ */
+ status = MBOX_NO_RESPONSE;
+ spin_lock(&mbox_db_lock);
+ for (i = 0; i < MBOX_MAX_TIDS_BITMAP; i++) {
+ bitmap[i] = mbox_svc.interrupt_bitmap[i] ^ mbox_svc.received_bitmap[i];
+ if (bitmap[i] != 0 && status == MBOX_NO_RESPONSE) {
+ status = MBOX_RET_OK;
+ }
+
+ mbox_svc.interrupt_bitmap[i] = mbox_svc.received_bitmap[i];
+ }
+ spin_unlock(&mbox_db_lock);
+
+ return status;
+}
+
+int mailbox_response_poll_v3(uint8_t client_id, uint8_t job_id,
+ uint32_t *ret_args, uint32_t *ret_args_len)
+{
+ sdm_command_t *cmd_desc = NULL;
+ sdm_response_t *resp_desc = NULL;
+ uint8_t di = 0U;
+ int status = MBOX_RET_OK;
+
+ /*
+ * Let's first check the local response queue with the given
+ * client ID and job ID
+ */
+ resp_desc = mailbox_get_resp_desc(client_id, job_id, &di);
+ if (resp_desc == NULL) {
+ /* Not available in the local queue, let's read mailbox FIFO */
+ status = mailbox_response_handler_fsm();
+ if (status != MBOX_RET_OK) {
+ return status;
+ }
+
+ resp_desc = mailbox_get_resp_desc(client_id, job_id, &di);
+ }
+ cmd_desc = mailbox_get_cmd_desc(client_id, job_id);
+
+ if (cmd_desc != NULL && resp_desc != NULL) {
+ VERBOSE("MBOX: Resp found for cid %d, jid %d\n", client_id, job_id);
+
+ /* Command callback function */
+ *ret_args_len = cmd_desc->cb(resp_desc, cmd_desc, ret_args);
+
+ /* Free the command and response descriptors. */
+ mailbox_free_cmd_desc(cmd_desc);
+ mailbox_free_resp_desc(di);
+
+ return MBOX_RET_OK;
+ }
+
+ INFO("MBOX: No resp found for cid: %d, jid: %d\n", client_id, job_id);
+
+ return MBOX_NO_RESPONSE;
+}
+
+void mailbox_init_v3(void)
+{
+ uint32_t count;
+
+ memset((void *)&mbox_svc, 0, sizeof(mbox_svc));
+
+ mbox_svc.next_resp_state = SRS_WAIT_FOR_RESP;
+ mbox_svc.resp_state = SRS_WAIT_FOR_RESP;
+
+ /* Free all entries from the response queue. */
+ for (count = 0; count < MBOX_SVC_RESP_QUEUE_SIZE; count++) {
+ mbox_svc.resp_queue[count].flags = 0;
+ }
+
+ /* Free all entries from the command queue. */
+ for (count = 0; count < MBOX_SVC_CMD_QUEUE_SIZE; count++) {
+ mbox_svc.cmd_queue[count].flags = 0;
+ }
+
+ mbox_svc.curr_di = -1;
+}
+#endif /* #if SIP_SVC_V3 */
diff --git a/plat/intel/soc/common/socfpga_sip_svc.c b/plat/intel/soc/common/socfpga_sip_svc.c
index d64ead7..703a778 100644
--- a/plat/intel/soc/common/socfpga_sip_svc.c
+++ b/plat/intel/soc/common/socfpga_sip_svc.c
@@ -801,6 +801,128 @@
}
#endif
+#if SIP_SVC_V3
+uint8_t sip_smc_cmd_cb_ret3(void *resp_desc, void *cmd_desc, uint32_t *ret_args)
+{
+ uint8_t ret_args_len = 0U;
+ sdm_response_t *resp = (sdm_response_t *)resp_desc;
+ sdm_command_t *cmd = (sdm_command_t *)cmd_desc;
+
+ (void)cmd;
+ /* Returns 3 SMC arguments for SMC_RET3 */
+ ret_args[ret_args_len++] = INTEL_SIP_SMC_STATUS_OK;
+ ret_args[ret_args_len++] = resp->err_code;
+ ret_args[ret_args_len++] = resp->resp_data[0];
+
+ return ret_args_len;
+}
+
+static uintptr_t smc_ret(void *handle, uint32_t *ret_args, uint32_t ret_args_len)
+{
+ switch (ret_args_len) {
+ case SMC_RET_ARGS_ONE:
+ SMC_RET1(handle, ret_args[0]);
+ break;
+
+ case SMC_RET_ARGS_TWO:
+ SMC_RET2(handle, ret_args[0], ret_args[1]);
+ break;
+
+ case SMC_RET_ARGS_THREE:
+ SMC_RET3(handle, ret_args[0], ret_args[1], ret_args[2]);
+ break;
+
+ case SMC_RET_ARGS_FOUR:
+ SMC_RET4(handle, ret_args[0], ret_args[1], ret_args[2], ret_args[3]);
+ break;
+
+ case SMC_RET_ARGS_FIVE:
+ SMC_RET5(handle, ret_args[0], ret_args[1], ret_args[2], ret_args[3], ret_args[4]);
+ break;
+
+ default:
+ SMC_RET1(handle, INTEL_SIP_SMC_STATUS_ERROR);
+ break;
+ }
+}
+
+/*
+ * This function is responsible for handling all SiP SVC V3 calls from the
+ * non-secure world.
+ */
+static uintptr_t sip_smc_handler_v3(uint32_t smc_fid,
+ u_register_t x1,
+ u_register_t x2,
+ u_register_t x3,
+ u_register_t x4,
+ void *cookie,
+ void *handle,
+ u_register_t flags)
+{
+ int status = 0;
+
+ VERBOSE("MBOX: SVC-V3: x0 0x%x, x1 0x%lx, x2 0x%lx, x3 0x%lx, x4 0x%lx\n",
+ smc_fid, x1, x2, x3, x4);
+
+ switch (smc_fid) {
+ case ALTERA_SIP_SMC_ASYNC_RESP_POLL:
+ {
+ uint32_t ret_args[8] = {0}; /* X0 to X7 return arguments */
+ uint32_t ret_args_len;
+
+ status = mailbox_response_poll_v3(GET_CLIENT_ID(x1),
+ GET_JOB_ID(x1),
+ ret_args,
+ &ret_args_len);
+ /* Always reserve [0] index for command status. */
+ ret_args[0] = status;
+
+ /* Return SMC call based on the number of return arguments */
+ return smc_ret(handle, ret_args, ret_args_len);
+ }
+
+ case ALTERA_SIP_SMC_ASYNC_RESP_POLL_ON_INTR:
+ {
+ uint8_t client_id = 0U;
+ uint8_t job_id = 0U;
+ uint64_t trans_id_bitmap[4] = {0U};
+
+ status = mailbox_response_poll_on_intr_v3(&client_id,
+ &job_id,
+ trans_id_bitmap);
+
+ SMC_RET5(handle, status, trans_id_bitmap[0], trans_id_bitmap[1],
+ trans_id_bitmap[2], trans_id_bitmap[3]);
+ break;
+ }
+
+ case ALTERA_SIP_SMC_ASYNC_HWMON_READVOLT:
+ case ALTERA_SIP_SMC_ASYNC_HWMON_READTEMP:
+ {
+ uint32_t channel = (uint32_t)x2;
+ uint32_t mbox_cmd = ((smc_fid == ALTERA_SIP_SMC_ASYNC_HWMON_READVOLT) ?
+ MBOX_HWMON_READVOLT : MBOX_HWMON_READTEMP);
+
+ status = mailbox_send_cmd_async_v3(GET_CLIENT_ID(x1),
+ GET_JOB_ID(x1),
+ mbox_cmd,
+ &channel,
+ 1U,
+ MBOX_CMD_FLAG_CASUAL,
+ sip_smc_cmd_cb_ret3,
+ NULL,
+ 0);
+
+ SMC_RET1(handle, status);
+ }
+
+ default:
+ return socfpga_sip_handler(smc_fid, x1, x2, x3, x4,
+ cookie, handle, flags);
+ } /* switch (smc_fid) */
+}
+#endif
+
/*
* This function is responsible for handling all SiP calls from the NS world
*/
@@ -1375,7 +1497,16 @@
cmd <= INTEL_SIP_SMC_CMD_V2_RANGE_END) {
return sip_smc_handler_v2(smc_fid, x1, x2, x3, x4,
cookie, handle, flags);
- } else {
+ }
+#if SIP_SVC_V3
+ else if ((cmd >= INTEL_SIP_SMC_CMD_V3_RANGE_BEGIN) &&
+ (cmd <= INTEL_SIP_SMC_CMD_V3_RANGE_END)) {
+ uintptr_t ret = sip_smc_handler_v3(smc_fid, x1, x2, x3, x4,
+ cookie, handle, flags);
+ return ret;
+ }
+#endif
+ else {
return sip_smc_handler_v1(smc_fid, x1, x2, x3, x4,
cookie, handle, flags);
}
diff --git a/plat/intel/soc/n5x/bl31_plat_setup.c b/plat/intel/soc/n5x/bl31_plat_setup.c
index cb5ced6..65de036 100644
--- a/plat/intel/soc/n5x/bl31_plat_setup.c
+++ b/plat/intel/soc/n5x/bl31_plat_setup.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2020-2022, Intel Corporation. All rights reserved.
+ * Copyright (c) 2025, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -115,6 +116,16 @@
mmio_write_64(PLAT_CPU_RELEASE_ADDR,
(uint64_t)plat_secondary_cpus_bl31_entry);
+#if SIP_SVC_V3
+ /*
+ * Re-initialize the mailbox to include V3 specific routines.
+ * In V3, this re-initialize is required because prior to BL31, U-Boot
+ * SPL has its own mailbox settings and this initialization will
+ * override to those settings as required by the V3 framework.
+ */
+ mailbox_init();
+#endif
+
mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL);
}
diff --git a/plat/intel/soc/stratix10/bl31_plat_setup.c b/plat/intel/soc/stratix10/bl31_plat_setup.c
index d0aa972..5c25e43 100644
--- a/plat/intel/soc/stratix10/bl31_plat_setup.c
+++ b/plat/intel/soc/stratix10/bl31_plat_setup.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2022, Intel Corporation. All rights reserved.
+ * Copyright (c) 2025, Altera Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -122,6 +123,16 @@
mmio_write_64(PLAT_CPU_RELEASE_ADDR,
(uint64_t)plat_secondary_cpus_bl31_entry);
+#if SIP_SVC_V3
+ /*
+ * Re-initialize the mailbox to include V3 specific routines.
+ * In V3, this re-initialize is required because prior to BL31, U-Boot
+ * SPL has its own mailbox settings and this initialization will
+ * override to those settings as required by the V3 framework.
+ */
+ mailbox_init();
+#endif
+
mailbox_hps_stage_notify(HPS_EXECUTION_STATE_SSBL);
}