From 1b098e3549181bcdccbd660f2f243a48ffca8a68 Mon Sep 17 00:00:00 2001 From: puranikvinit Date: Fri, 20 Feb 2026 22:37:13 +0530 Subject: [PATCH 01/10] feat(drivers): add ti k3 secure proxy mailbox driver Signed-off-by: puranikvinit --- .../mailbox/inc/drivers/k3_sec_proxy.h | 229 ++++++++++++++ src/platform/drivers/mailbox/k3_sec_proxy.c | 289 ++++++++++++++++++ src/platform/drivers/mailbox/objects.mk | 4 + 3 files changed, 522 insertions(+) create mode 100644 src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h create mode 100644 src/platform/drivers/mailbox/k3_sec_proxy.c create mode 100644 src/platform/drivers/mailbox/objects.mk diff --git a/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h b/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h new file mode 100644 index 000000000..8eeabeb08 --- /dev/null +++ b/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h @@ -0,0 +1,229 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __MBOX_K3_SEC_PROXY_H_ +#define __MBOX_K3_SEC_PROXY_H_ + +#include +#include +#include +#include +#include + +/** + * @brief Defines the specific host function associated with a Secure Proxy + * thread. + */ +typedef enum { + HOST_FUNCTION_NOTIFY, + HOST_FUNCTION_RESPONSE, + HOST_FUNCTION_HIGH_PRIORITY, + HOST_FUNCTION_LOW_PRIORITY, + HOST_FUNCTION_NOTIFY_RESP, +} MBOX_K3_SEC_PROXY_HOST_FUNCTION; + +/** + * @brief Specifies the direction of data flow for a Secure Proxy thread. + */ +typedef enum { + MSG_DRXN_WRITE = 0, + MSG_DRXN_READ = 1, +} MBOX_K3_SEC_PROXY_MSG_DRXN; + +/** + * @brief Status codes returned by Secure Proxy APIs. + */ +typedef enum { + STATUS_CODE_NO_ERROR = 0, + STATUS_CODE_THREAD_CORRUPTED = -1, + STATUS_CODE_INCORRECT_DRXN = -2, + STATUS_CODE_NO_DATA = -4, + STATUS_CODE_INVALID_MSG_LEN = -5, + STATUS_CODE_THREAD_CLEAR_FAILED = -6, +} MBOX_K3_SEC_PROXY_STATUS_CODES; + +/* bit indices */ +#define MBOX_K3_SEC_PROXY_RT_THREAD_STATUS_OFFSET (0x0U) +#define MBOX_K3_SEC_PROXY_RT_THREAD_THRESHOLD_OFFSET (0x4U) + +#define MBOX_K3_SEC_PROXY_RT_STATUS_ERROR_IDX (31) +#define MBOX_K3_SEC_PROXY_RT_STATUS_ERROR_MASK (1U << MBOX_K3_SEC_PROXY_RT_STATUS_ERROR_IDX) + +#define MBOX_K3_SEC_PROXY_RT_STATUS_CUR_CNT_IDX (0) +#define MBOX_K3_SEC_PROXY_RT_STATUS_CUR_CNT_MASK (0xFFU << MBOX_K3_SEC_PROXY_RT_STATUS_CUR_CNT_IDX) + +#define MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_OFFSET (0x1000U) + +#define MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_DIR_IDX (31) +#define MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_DIR_MASK \ + (1U << MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_DIR_IDX) + +#define MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id) (0x1000U * (thread_id)) + +#define MBOX_K3_SEC_PROXY_DATA_START_OFFSET (0x4U) +#define MBOX_K3_SEC_PROXY_DATA_END_OFFSET (0x3CU) /* completion trigger offset */ + +/** + * @brief Structure representing a message to be sent or received via Secure + * Proxy. + */ +typedef struct { + size_t len; /**< Length of the message in bytes */ + uint32_t *buffer; /**< Pointer to the message data buffer */ +} mbox_k3_sec_proxy_msg; + +/** + * @brief Hardware configuration for a Secure Proxy instance. + */ +typedef struct { + /* note: declared as a 32-bit val because it is kept as such in u-boot + * implementation. However, in J721E, there are only 2 supported sec_proxy + * IDs: + * 0 => NAVSS0_SEC_PROXY_0 + * 1 => MCU_NAVSS0_SEC_PROXY0 + * can modify type based on requirements... + */ + uint32_t id; /**< Instance ID (e.g., NAVSS0_SEC_PROXY_0) */ + + paddr_t rt_base; /**< Base address of Real-Time (RT) region */ + size_t rt_size; /**< Size of RT region */ + + paddr_t scfg_base; /**< Base address of Secure Configuration (SCFG) region */ + size_t scfg_size; /**< Size of SCFG region */ + + paddr_t data_base; /**< Base address of Data region */ + size_t data_size; /**< Size of Data region */ + + size_t max_msg_size; +} mbox_k3_sec_proxy_instance; + +/** + * @brief Configuration descriptor for a single Secure Proxy thread. + */ +typedef struct { + uint8_t sec_proxy_thread_id; /**< Secure Proxy thread ID */ + MBOX_K3_SEC_PROXY_MSG_DRXN msg_drxn; /**< Message direction (Read/Write) */ + uint8_t mbox_queue_depth; /**< Depth of the mailbox queue */ + uint8_t host_id; /**< ID of the host associated with this thread */ + MBOX_K3_SEC_PROXY_HOST_FUNCTION + host_function; /**< Function/Role of the thread */ + uint16_t irq_line_threshold; /**< IRQ threshold configuration */ + uint16_t irq_line_error; /**< IRQ error configuration */ +} mbox_k3_sec_proxy_thread_desc; + +/** + * @brief Top-level descriptor aggregating the Secure Proxy instance and its + * thread configurations. + */ +typedef struct { + mbox_k3_sec_proxy_instance thread_inst; /**< Secure Proxy instance configuration */ + mbox_k3_sec_proxy_thread_desc sec_proxy_thread_desc[]; /**< Array of thread descriptors */ +} mbox_k3_sec_proxy_desc; + +// clang-format off +#define MBOX_K3_SEC_PROXY_THREAD_DESC_ENTRY( \ + host, base_thread_id, notify_queue_depth, resp_queue_depth, \ + high_priority_queue_depth, low_priority_queue_depth) \ + [base_thread_id] = \ + (mbox_k3_sec_proxy_thread_desc){ \ + .sec_proxy_thread_id = base_thread_id, \ + .msg_drxn = MSG_DRXN_READ, \ + .mbox_queue_depth = notify_queue_depth, \ + .host_id = host, \ + .host_function = HOST_FUNCTION_NOTIFY}, \ + [base_thread_id + 1] = \ + (mbox_k3_sec_proxy_thread_desc){ \ + .sec_proxy_thread_id = (base_thread_id + 1), \ + .msg_drxn = MSG_DRXN_READ, \ + .mbox_queue_depth = resp_queue_depth, \ + .host_id = host, \ + .host_function = HOST_FUNCTION_RESPONSE}, \ + [base_thread_id + 2] = \ + (mbox_k3_sec_proxy_thread_desc){ \ + .sec_proxy_thread_id = (base_thread_id + 2), \ + .msg_drxn = MSG_DRXN_WRITE, \ + .mbox_queue_depth = high_priority_queue_depth, \ + .host_id = host, \ + .host_function = HOST_FUNCTION_HIGH_PRIORITY}, \ + [base_thread_id + 3] = \ + (mbox_k3_sec_proxy_thread_desc){ \ + .sec_proxy_thread_id = (base_thread_id + 3), \ + .msg_drxn = MSG_DRXN_WRITE, \ + .mbox_queue_depth = low_priority_queue_depth, \ + .host_id = host, \ + .host_function = HOST_FUNCTION_LOW_PRIORITY}, \ + [base_thread_id + 4] = \ + (mbox_k3_sec_proxy_thread_desc) { \ + .sec_proxy_thread_id = (base_thread_id + 4), \ + .msg_drxn = MSG_DRXN_WRITE, \ + .mbox_queue_depth = 2, .host_id = host, \ + .host_function = HOST_FUNCTION_NOTIFY_RESP} +// clang-format on + +extern mbox_k3_sec_proxy_desc sec_proxy_desc; + +/** + * @brief Verifies the status and configuration of a Secure Proxy thread. + * + * @param thread_id The ID of the thread to verify. + * @param msg_drxn Expected message direction (MSG_DRXN_READ or MSG_DRXN_WRITE). + * + * @return int32_t STATUS_CODE_NO_ERROR on success, or respective error codes + * on failure. + */ +int32_t mbox_k3_sec_proxy_verify_thread(uint8_t thread_id, uint8_t msg_drxn); + +/** + * @brief Reads a message from a specific Secure Proxy thread. + * + * @param thread_id The ID of the thread to read from. + * @param msg Pointer to the structure where the read message will be stored. + * + * @return int32_t STATUS_CODE_NO_ERROR on success, or respective error codes + * on failure. + * + * @notes + * - does not support big-endian systems, current implementation only is + * for little-endian. + * - byte-ordering logic for trailing bytes assumes LSB-first memory layout. + */ +int32_t mbox_k3_sec_proxy_read(uint8_t thread_id, mbox_k3_sec_proxy_msg *msg); + +/** + * @brief Writes a message to a specific Secure Proxy thread. + * + * @param thread_id The ID of the thread to write to. + * @param msg Pointer to the structure containing the message to send. + * + * @return int32_t STATUS_CODE_NO_ERROR on success, or an error code on + * failure. + * + * @notes + * - does not support big-endian systems, current implementation only is + * for little-endian. + * - byte-ordering logic for trailing bytes assumes LSB-first memory layout. + */ +int32_t mbox_k3_sec_proxy_write(uint8_t thread_id, mbox_k3_sec_proxy_msg *msg); + +/** + * @brief Clears all pending messages from a Secure Proxy thread. + * + * @param thread_id The ID of the thread to clear. + * + * @return int32_t STATUS_CODE_NO_ERROR on success, or an error code on failure. + */ +int32_t mbox_k3_sec_proxy_clear(uint8_t thread_id); + +/** + * @brief Performs a health check on a Secure Proxy thread and reports status. + * + * @param thread_id The ID of the thread to probe. + * + * @return int32_t STATUS_CODE_NO_ERROR on success, or respective error codes + * on failure. + */ +int32_t mbox_k3_sec_proxy_probe(uint8_t thread_id); + +#endif /* __MBOX_K3_SEC_PROXY_H_ */ diff --git a/src/platform/drivers/mailbox/k3_sec_proxy.c b/src/platform/drivers/mailbox/k3_sec_proxy.c new file mode 100644 index 000000000..e152f749a --- /dev/null +++ b/src/platform/drivers/mailbox/k3_sec_proxy.c @@ -0,0 +1,289 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include +#include + +/** + * @brief Reads a 32-bit value from a memory-mapped register. + * + * @param addr Base address of the peripheral or register block. + * @param offset Offset from the base address to the specific register. + * + * @return The 32-bit value read from the register. + */ +static inline uint32_t read_reg(paddr_t addr, paddr_t offset) +{ + return *((volatile uint32_t*)((paddr_t)(addr + offset))); +} + +/** + * @brief Writes a 32-bit value to a memory-mapped register. + * + * @param addr Base address of the peripheral or register block. + * @param offset Offset from the base address to the specific register. + * @param value The 32-bit value to write. + */ +static inline void write_reg(paddr_t addr, paddr_t offset, uint32_t value) +{ + *((volatile uint32_t*)((paddr_t)(addr + offset))) = value; +} + +/** + * @brief Verifies the status and configuration of a Secure Proxy thread before + * a transaction. + * + * @desc This function checks for thread corruption, validates the thread's + * configured direction (read/write) against its intended usage, and ensures the + * message queue is not empty if reading. + * + * @param thread_id The ID of the thread to verify. + * @param msg_drxn Expected message direction (MSG_DRXN_READ or MSG_DRXN_WRITE). + * + * @return int32_t STATUS_CODE_NO_ERROR if the thread is valid and ready, + * otherwise respective error codes. + */ +int32_t mbox_k3_sec_proxy_verify_thread(uint8_t thread_id, uint8_t msg_drxn) +{ + paddr_t thread_rt_base = + sec_proxy_desc.thread_inst.rt_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id); + paddr_t thread_scfg_base = + sec_proxy_desc.thread_inst.scfg_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id); + + /* check for existing errors */ + if (read_reg(thread_rt_base, MBOX_K3_SEC_PROXY_RT_THREAD_STATUS_OFFSET) & + MBOX_K3_SEC_PROXY_RT_STATUS_ERROR_MASK) { + ERROR("secure_proxy_thread_%d corrupted", thread_id); + return STATUS_CODE_THREAD_CORRUPTED; + } + + /* validate thread drxn config */ + if ((read_reg(thread_scfg_base, MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_OFFSET) & + MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_DIR_MASK) >> + MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_DIR_IDX != + msg_drxn) { + if (MSG_DRXN_WRITE == msg_drxn) { + ERROR("secure_proxy_thread_%d cannot READ on WRITE thread", thread_id); + return STATUS_CODE_INCORRECT_DRXN; + } else { + ERROR("secure_proxy_thread_%d cannot WRITE on READ thread", thread_id); + return STATUS_CODE_INCORRECT_DRXN; + } + } + + /* check if msg queue has entries before txn attempt */ + if ((0 == + (read_reg(thread_rt_base, MBOX_K3_SEC_PROXY_RT_THREAD_STATUS_OFFSET) & + MBOX_K3_SEC_PROXY_RT_STATUS_CUR_CNT_MASK)) && + (MSG_DRXN_READ == msg_drxn)) { + ERROR("secure_proxy_thread_%d no entries in message queue", thread_id); + return STATUS_CODE_NO_DATA; + } + + return STATUS_CODE_NO_ERROR; +} + +/* + * read transaction: + * + * +-------------------------+ + * | 1. verify thread status | + * +-----------+-------------+ + * | + * v + * +-----------+-------------+ +------------------------------------+ + * | 2. read whole words | <---- | regs: base + DATA_START_OFFSET ... | + * +-----------+-------------+ +------------------------------------+ + * | + * v + * +-----------+-------------+ +------------------------------------+ + * | 3. read & unpack trail | <---- | reg: base + N | + * | bytes (little endian)| | (extract from LSB) | + * +-----------+-------------+ +------------------------------------+ + * | + * v + * +-----------+-------------+ +------------------------------------+ + * | 4. read trigger reg if | <---- | trigger: base + DATA_END_OFFSET | + * | not reached yet | +------------------------------------+ + * +-------------------------+ + */ +int32_t mbox_k3_sec_proxy_read(uint8_t thread_id, mbox_k3_sec_proxy_msg* msg) +{ + /* verify thread status */ + int32_t read_status = mbox_k3_sec_proxy_verify_thread(thread_id, MSG_DRXN_READ); + if (STATUS_CODE_NO_ERROR != read_status) { + ERROR("secure_proxy_thread_%d thread verif failed", thread_id); + return read_status; + } + + /* perform read transaction */ + paddr_t data_reg = sec_proxy_desc.thread_inst.data_base + + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id) + MBOX_K3_SEC_PROXY_DATA_START_OFFSET; + + /* read whole words first */ + uint32_t word_iterator; + size_t num_words = msg->len / sizeof(uint32_t); + for (word_iterator = 0; word_iterator < num_words; word_iterator++) { + ((uint32_t*)msg->buffer)[word_iterator] = + read_reg(data_reg, word_iterator * sizeof(uint32_t)); + } + + /* read remaining bytes */ + uint32_t trail_bytes = msg->len % sizeof(uint32_t); + if (0 != trail_bytes) { + uint32_t data_trail = read_reg(data_reg, word_iterator++ * sizeof(uint32_t)); + + size_t trail_iterator = msg->len - trail_bytes; + while (trail_bytes--) { + ((uint8_t*)msg->buffer)[trail_iterator++] = (uint8_t)(data_trail & 0xFFU); + data_trail >>= 8; + } + } + + /* in case the completion trigger register is not accessed during the read, + * the following access is performed, to mark the completion of the + * transaction. */ + if ((MBOX_K3_SEC_PROXY_DATA_START_OFFSET + (word_iterator * sizeof(uint32_t))) <= + MBOX_K3_SEC_PROXY_DATA_END_OFFSET) { + read_reg(data_reg, MBOX_K3_SEC_PROXY_DATA_END_OFFSET - MBOX_K3_SEC_PROXY_DATA_START_OFFSET); + } + + INFO("secure_proxy_thread_%d data READ success", thread_id); + + return read_status; +} + +/* + * write transaction: + * + * +-------------------------+ + * | 1. verify thread status | + * +-----------+-------------+ + * | + * v + * +-----------+-------------+ + * | 2. check message length | + * +-----------+-------------+ + * | + * v + * +-----------+-------------+ +------------------------------------+ + * | 3. write whole words | ----> | regs: base + DATA_START_OFFSET ... | + * +-----------+-------------+ +------------------------------------+ + * | + * v + * +-----------+-------------+ +------------------------------------+ + * | 4. pack & write trail | ----> | reg: base + N | + * | bytes (little endian)| | (right-aligned/LSB) | + * +-----------+-------------+ +------------------------------------+ + * | + * v + * +-----------+-------------+ +------------------------------------+ + * | 5. pad with zeros until | ----> | trigger: base + DATA_END_OFFSET | + * | end offset (trigger) | +------------------------------------+ + * +-------------------------+ + */ +int32_t mbox_k3_sec_proxy_write(uint8_t thread_id, mbox_k3_sec_proxy_msg* msg) +{ + /* verify thread status */ + int32_t write_status = mbox_k3_sec_proxy_verify_thread(thread_id, MSG_DRXN_WRITE); + if (STATUS_CODE_NO_ERROR != write_status) { + ERROR("secure_proxy_thread_%d thread verif failed", thread_id); + return write_status; + } + + /* msg len check */ + if (msg->len > sec_proxy_desc.thread_inst.max_msg_size) { + ERROR("secure_proxy_thread_%d msg len exceeds limit", thread_id); + return STATUS_CODE_INVALID_MSG_LEN; + } + + /* perform write transaction */ + paddr_t data_reg = sec_proxy_desc.thread_inst.data_base + + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id) + MBOX_K3_SEC_PROXY_DATA_START_OFFSET; + + /* write whole words first */ + uint32_t word_iterator; + size_t num_words = msg->len / sizeof(uint32_t); + for (word_iterator = 0; word_iterator < num_words; word_iterator++) { + write_reg(data_reg, word_iterator * sizeof(uint32_t), + ((uint32_t*)msg->buffer)[word_iterator]); + } + + /* write remaining bytes */ + uint32_t trail_bytes = msg->len % sizeof(uint32_t); + if (0 != trail_bytes) { + uint32_t data_trail = 0; + + size_t trail_iterator = msg->len - trail_bytes; + for (uint32_t i = 0; i < trail_bytes; i++) { + data_trail |= (uint32_t)((uint8_t*)msg->buffer)[trail_iterator++] << (i * 8); + } + + write_reg(data_reg, word_iterator++ * sizeof(uint32_t), data_trail); + } + + /* + * Pad the remaining registers with zeros up to the completion trigger offset. + * The Secure Proxy hardware triggers the message transmission ONLY when + * the last register at MBOX_K3_SEC_PROXY_DATA_END_OFFSET is written. + */ + while ((MBOX_K3_SEC_PROXY_DATA_START_OFFSET + (word_iterator * sizeof(uint32_t))) <= + MBOX_K3_SEC_PROXY_DATA_END_OFFSET) { + write_reg(data_reg, word_iterator++ * sizeof(uint32_t), 0U); + } + + INFO("secure_proxy_thread_%d data WRITE success", thread_id); + + return write_status; +} + +int32_t mbox_k3_sec_proxy_clear(uint8_t thread_id) +{ + int32_t clear_status = mbox_k3_sec_proxy_verify_thread(thread_id, MSG_DRXN_READ); + if (STATUS_CODE_NO_ERROR != clear_status) { + ERROR("secure_proxy_thread_%d thread verif failed", thread_id); + return clear_status; + } + + paddr_t thread_rt_base = + sec_proxy_desc.thread_inst.rt_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id); + paddr_t data_reg = + sec_proxy_desc.thread_inst.data_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id); + + uint32_t try_count = 10; + while (0 != + (read_reg(thread_rt_base, MBOX_K3_SEC_PROXY_RT_THREAD_STATUS_OFFSET) & + MBOX_K3_SEC_PROXY_RT_STATUS_CUR_CNT_MASK)) { + if (0 == (try_count--)) { + ERROR("secure_proxy_thread_%d mailbox clear failed", thread_id); + return STATUS_CODE_THREAD_CLEAR_FAILED; + } + + WARNING("secure_proxy_thread_%d mailbox clear in progress", thread_id); + read_reg(data_reg, MBOX_K3_SEC_PROXY_DATA_END_OFFSET); + } + + return STATUS_CODE_NO_ERROR; +} + +int32_t mbox_k3_sec_proxy_probe(uint8_t thread_id) +{ + paddr_t thread_scfg_base = + sec_proxy_desc.thread_inst.scfg_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id); + + uint32_t config = read_reg(thread_scfg_base, MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_OFFSET); + + uint8_t hw_host = (config >> 8) & 0xFF; + uint8_t expected_host = sec_proxy_desc.sec_proxy_thread_desc[thread_id].host_id; + + if (hw_host != expected_host) { + ERROR("sec_proxy_thread_%d probe failed (hw_host=%d, expected=%d)", thread_id, hw_host, + expected_host); + return STATUS_CODE_THREAD_CORRUPTED; + } + + INFO("sec_proxy_thread_%d probe success", thread_id); + return STATUS_CODE_NO_ERROR; +} diff --git a/src/platform/drivers/mailbox/objects.mk b/src/platform/drivers/mailbox/objects.mk new file mode 100644 index 000000000..e23dea275 --- /dev/null +++ b/src/platform/drivers/mailbox/objects.mk @@ -0,0 +1,4 @@ +## SPDX-License-Identifier: Apache-2.0 +## Copyright (c) Bao Project and Contributors. All rights reserved. + +drivers-objs-y+=mailbox/k3_sec_proxy.o From 8db6270d75be0b90045f922637504a61f07c81f7 Mon Sep 17 00:00:00 2001 From: puranikvinit Date: Sat, 21 Feb 2026 10:58:16 +0530 Subject: [PATCH 02/10] feat(drivers/mailbox): add secure proxy health check probe Signed-off-by: puranikvinit --- .../mailbox/inc/drivers/k3_sec_proxy.h | 15 ++++++++ src/platform/drivers/mailbox/k3_sec_proxy.c | 37 ++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h b/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h index 8eeabeb08..72e5b8527 100644 --- a/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h +++ b/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h @@ -11,6 +11,7 @@ #include #include #include +#include /** * @brief Defines the specific host function associated with a Secure Proxy @@ -42,6 +43,7 @@ typedef enum { STATUS_CODE_NO_DATA = -4, STATUS_CODE_INVALID_MSG_LEN = -5, STATUS_CODE_THREAD_CLEAR_FAILED = -6, + STATUS_CODE_DIRTY_HANDOFF = -7, } MBOX_K3_SEC_PROXY_STATUS_CODES; /* bit indices */ @@ -226,4 +228,17 @@ int32_t mbox_k3_sec_proxy_clear(uint8_t thread_id); */ int32_t mbox_k3_sec_proxy_probe(uint8_t thread_id); +/** + * @brief Protocol-level ping test hook. + * + * @param thread_id The ID of the thread to test. + * + * @return int32_t STATUS_CODE_NO_ERROR on success, or an error code on failure. + * + * @notes + * - this is a weak function; a strong implementation should be provided by + * the platform to verify pipeline cleanliness. + */ +int32_t mbox_k3_sec_proxy_ping_test(uint8_t thread_id); + #endif /* __MBOX_K3_SEC_PROXY_H_ */ diff --git a/src/platform/drivers/mailbox/k3_sec_proxy.c b/src/platform/drivers/mailbox/k3_sec_proxy.c index e152f749a..e09606182 100644 --- a/src/platform/drivers/mailbox/k3_sec_proxy.c +++ b/src/platform/drivers/mailbox/k3_sec_proxy.c @@ -4,7 +4,6 @@ */ #include -#include /** * @brief Reads a 32-bit value from a memory-mapped register. @@ -272,18 +271,52 @@ int32_t mbox_k3_sec_proxy_probe(uint8_t thread_id) { paddr_t thread_scfg_base = sec_proxy_desc.thread_inst.scfg_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id); - uint32_t config = read_reg(thread_scfg_base, MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_OFFSET); + paddr_t thread_rt_base = + sec_proxy_desc.thread_inst.rt_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id); + uint8_t hw_host = (config >> 8) & 0xFF; uint8_t expected_host = sec_proxy_desc.sec_proxy_thread_desc[thread_id].host_id; + /* [step-1] verify thread access/host ownership */ if (hw_host != expected_host) { ERROR("sec_proxy_thread_%d probe failed (hw_host=%d, expected=%d)", thread_id, hw_host, expected_host); return STATUS_CODE_THREAD_CORRUPTED; } + /* [step-2] verify if thread is clean */ + int32_t probe_status = mbox_k3_sec_proxy_verify_thread(thread_id, MSG_DRXN_WRITE); + if (STATUS_CODE_NO_ERROR != probe_status) { + INFO("sec_proxy_thread_%d probe failed (error_id=%d)", thread_id, probe_status); + return probe_status; + } + + if (0 != + (read_reg(thread_rt_base, MBOX_K3_SEC_PROXY_RT_THREAD_STATUS_OFFSET) & + MBOX_K3_SEC_PROXY_RT_STATUS_CUR_CNT_MASK)) { + ERROR("secure_proxy_thread_%d probe failed (message queue not clean)", thread_id); + return STATUS_CODE_DIRTY_HANDOFF; + } + + /* [step-3] check pipeline health by pinging sysfw + * + * @notes + * - the hook needs to be implemented by the platform, as the driver is protocol agnostic. + */ + probe_status = mbox_k3_sec_proxy_ping_test(thread_id); + if (STATUS_CODE_NO_ERROR != probe_status) { + ERROR("sec_proxy_thread_%d probe failed (sysfw ping failure)", thread_id); + return probe_status; + } + INFO("sec_proxy_thread_%d probe success", thread_id); + return probe_status; +} + +__attribute__((weak)) int32_t mbox_k3_sec_proxy_ping_test(uint8_t thread_id) +{ + UNUSED_ARG(thread_id); return STATUS_CODE_NO_ERROR; } From 92859336d43797d4e6a1d7bf52f00a72f861306a Mon Sep 17 00:00:00 2001 From: puranikvinit Date: Sat, 21 Feb 2026 14:57:36 +0530 Subject: [PATCH 03/10] ref(drivers/mailbox): flatten mbox APIs to support protocol agnosticism Signed-off-by: puranikvinit --- .../mailbox/inc/drivers/k3_sec_proxy.h | 74 ++++----- src/platform/drivers/mailbox/k3_sec_proxy.c | 144 +++++++++--------- 2 files changed, 109 insertions(+), 109 deletions(-) diff --git a/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h b/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h index 72e5b8527..0a0ffbb93 100644 --- a/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h +++ b/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h @@ -18,32 +18,32 @@ * thread. */ typedef enum { - HOST_FUNCTION_NOTIFY, - HOST_FUNCTION_RESPONSE, - HOST_FUNCTION_HIGH_PRIORITY, - HOST_FUNCTION_LOW_PRIORITY, - HOST_FUNCTION_NOTIFY_RESP, + MBOX_K3_SEC_PROXY_HOST_FUNCTION_NOTIFY, + MBOX_K3_SEC_PROXY_HOST_FUNCTION_RESPONSE, + MBOX_K3_SEC_PROXY_HOST_FUNCTION_HIGH_PRIORITY, + MBOX_K3_SEC_PROXY_HOST_FUNCTION_LOW_PRIORITY, + MBOX_K3_SEC_PROXY_HOST_FUNCTION_NOTIFY_RESP, } MBOX_K3_SEC_PROXY_HOST_FUNCTION; /** * @brief Specifies the direction of data flow for a Secure Proxy thread. */ typedef enum { - MSG_DRXN_WRITE = 0, - MSG_DRXN_READ = 1, + MBOX_K3_SEC_PROXY_MSG_DRXN_WRITE = 0, + MBOX_K3_SEC_PROXY_MSG_DRXN_READ = 1, } MBOX_K3_SEC_PROXY_MSG_DRXN; /** * @brief Status codes returned by Secure Proxy APIs. */ typedef enum { - STATUS_CODE_NO_ERROR = 0, - STATUS_CODE_THREAD_CORRUPTED = -1, - STATUS_CODE_INCORRECT_DRXN = -2, - STATUS_CODE_NO_DATA = -4, - STATUS_CODE_INVALID_MSG_LEN = -5, - STATUS_CODE_THREAD_CLEAR_FAILED = -6, - STATUS_CODE_DIRTY_HANDOFF = -7, + MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR = 0, + MBOX_K3_SEC_PROXY_STATUS_CODE_THREAD_CORRUPTED = -1, + MBOX_K3_SEC_PROXY_STATUS_CODE_INCORRECT_DRXN = -2, + MBOX_K3_SEC_PROXY_STATUS_CODE_NO_DATA = -4, + MBOX_K3_SEC_PROXY_STATUS_CODE_INVALID_MSG_LEN = -5, + MBOX_K3_SEC_PROXY_STATUS_CODE_THREAD_CLEAR_FAILED = -6, + MBOX_K3_SEC_PROXY_STATUS_CODE_DIRTY_HANDOFF = -7, } MBOX_K3_SEC_PROXY_STATUS_CODES; /* bit indices */ @@ -67,15 +67,6 @@ typedef enum { #define MBOX_K3_SEC_PROXY_DATA_START_OFFSET (0x4U) #define MBOX_K3_SEC_PROXY_DATA_END_OFFSET (0x3CU) /* completion trigger offset */ -/** - * @brief Structure representing a message to be sent or received via Secure - * Proxy. - */ -typedef struct { - size_t len; /**< Length of the message in bytes */ - uint32_t *buffer; /**< Pointer to the message data buffer */ -} mbox_k3_sec_proxy_msg; - /** * @brief Hardware configuration for a Secure Proxy instance. */ @@ -164,24 +155,30 @@ typedef struct { .host_function = HOST_FUNCTION_NOTIFY_RESP} // clang-format on -extern mbox_k3_sec_proxy_desc sec_proxy_desc; - /** - * @brief Verifies the status and configuration of a Secure Proxy thread. + * @brief Verifies the status and configuration of a Secure Proxy thread before + * a transaction. + * + * @desc This function checks for thread corruption, validates the thread's + * configured direction (read/write) against its intended usage, and ensures the + * message queue is not empty if reading. * + * @param sec_proxy_desc Pointer to the Secure Proxy descriptor. * @param thread_id The ID of the thread to verify. * @param msg_drxn Expected message direction (MSG_DRXN_READ or MSG_DRXN_WRITE). * - * @return int32_t STATUS_CODE_NO_ERROR on success, or respective error codes - * on failure. + * @return int32_t STATUS_CODE_NO_ERROR if the thread is valid and ready, + * otherwise respective error codes. */ -int32_t mbox_k3_sec_proxy_verify_thread(uint8_t thread_id, uint8_t msg_drxn); +int32_t mbox_k3_sec_proxy_verify_thread(mbox_k3_sec_proxy_desc *sec_proxy_desc, uint8_t thread_id, uint8_t msg_drxn); /** * @brief Reads a message from a specific Secure Proxy thread. * + * @param sec_proxy_desc Pointer to the Secure Proxy descriptor. * @param thread_id The ID of the thread to read from. - * @param msg Pointer to the structure where the read message will be stored. + * @param buffer Pointer to the buffer where the read message will be stored. + * @param len Length of the message to read in bytes. * * @return int32_t STATUS_CODE_NO_ERROR on success, or respective error codes * on failure. @@ -191,13 +188,15 @@ int32_t mbox_k3_sec_proxy_verify_thread(uint8_t thread_id, uint8_t msg_drxn); * for little-endian. * - byte-ordering logic for trailing bytes assumes LSB-first memory layout. */ -int32_t mbox_k3_sec_proxy_read(uint8_t thread_id, mbox_k3_sec_proxy_msg *msg); +int32_t mbox_k3_sec_proxy_read(mbox_k3_sec_proxy_desc *sec_proxy_desc, uint8_t thread_id, void* buffer, size_t len); /** * @brief Writes a message to a specific Secure Proxy thread. * + * @param sec_proxy_desc Pointer to the Secure Proxy descriptor. * @param thread_id The ID of the thread to write to. - * @param msg Pointer to the structure containing the message to send. + * @param buffer Pointer to the buffer containing the message to send. + * @param len Length of the message to send in bytes. * * @return int32_t STATUS_CODE_NO_ERROR on success, or an error code on * failure. @@ -207,30 +206,33 @@ int32_t mbox_k3_sec_proxy_read(uint8_t thread_id, mbox_k3_sec_proxy_msg *msg); * for little-endian. * - byte-ordering logic for trailing bytes assumes LSB-first memory layout. */ -int32_t mbox_k3_sec_proxy_write(uint8_t thread_id, mbox_k3_sec_proxy_msg *msg); +int32_t mbox_k3_sec_proxy_write(mbox_k3_sec_proxy_desc *sec_proxy_desc, uint8_t thread_id, void* buffer, size_t len); /** * @brief Clears all pending messages from a Secure Proxy thread. * + * @param sec_proxy_desc Pointer to the Secure Proxy descriptor. * @param thread_id The ID of the thread to clear. * * @return int32_t STATUS_CODE_NO_ERROR on success, or an error code on failure. */ -int32_t mbox_k3_sec_proxy_clear(uint8_t thread_id); +int32_t mbox_k3_sec_proxy_clear(mbox_k3_sec_proxy_desc *sec_proxy_desc, uint8_t thread_id); /** * @brief Performs a health check on a Secure Proxy thread and reports status. * + * @param sec_proxy_desc Pointer to the Secure Proxy descriptor. * @param thread_id The ID of the thread to probe. * * @return int32_t STATUS_CODE_NO_ERROR on success, or respective error codes * on failure. */ -int32_t mbox_k3_sec_proxy_probe(uint8_t thread_id); +int32_t mbox_k3_sec_proxy_probe(mbox_k3_sec_proxy_desc *sec_proxy_desc, uint8_t thread_id); /** * @brief Protocol-level ping test hook. * + * @param sec_proxy_desc Pointer to the Secure Proxy descriptor. * @param thread_id The ID of the thread to test. * * @return int32_t STATUS_CODE_NO_ERROR on success, or an error code on failure. @@ -239,6 +241,6 @@ int32_t mbox_k3_sec_proxy_probe(uint8_t thread_id); * - this is a weak function; a strong implementation should be provided by * the platform to verify pipeline cleanliness. */ -int32_t mbox_k3_sec_proxy_ping_test(uint8_t thread_id); +int32_t mbox_k3_sec_proxy_ping_test(mbox_k3_sec_proxy_desc *sec_proxy_desc, uint8_t thread_id); #endif /* __MBOX_K3_SEC_PROXY_H_ */ diff --git a/src/platform/drivers/mailbox/k3_sec_proxy.c b/src/platform/drivers/mailbox/k3_sec_proxy.c index e09606182..094cfeb22 100644 --- a/src/platform/drivers/mailbox/k3_sec_proxy.c +++ b/src/platform/drivers/mailbox/k3_sec_proxy.c @@ -30,32 +30,19 @@ static inline void write_reg(paddr_t addr, paddr_t offset, uint32_t value) *((volatile uint32_t*)((paddr_t)(addr + offset))) = value; } -/** - * @brief Verifies the status and configuration of a Secure Proxy thread before - * a transaction. - * - * @desc This function checks for thread corruption, validates the thread's - * configured direction (read/write) against its intended usage, and ensures the - * message queue is not empty if reading. - * - * @param thread_id The ID of the thread to verify. - * @param msg_drxn Expected message direction (MSG_DRXN_READ or MSG_DRXN_WRITE). - * - * @return int32_t STATUS_CODE_NO_ERROR if the thread is valid and ready, - * otherwise respective error codes. - */ -int32_t mbox_k3_sec_proxy_verify_thread(uint8_t thread_id, uint8_t msg_drxn) +int32_t mbox_k3_sec_proxy_verify_thread(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t thread_id, + uint8_t msg_drxn) { paddr_t thread_rt_base = - sec_proxy_desc.thread_inst.rt_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id); + sec_proxy_desc->thread_inst.rt_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id); paddr_t thread_scfg_base = - sec_proxy_desc.thread_inst.scfg_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id); + sec_proxy_desc->thread_inst.scfg_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id); /* check for existing errors */ if (read_reg(thread_rt_base, MBOX_K3_SEC_PROXY_RT_THREAD_STATUS_OFFSET) & MBOX_K3_SEC_PROXY_RT_STATUS_ERROR_MASK) { ERROR("secure_proxy_thread_%d corrupted", thread_id); - return STATUS_CODE_THREAD_CORRUPTED; + return MBOX_K3_SEC_PROXY_STATUS_CODE_THREAD_CORRUPTED; } /* validate thread drxn config */ @@ -63,12 +50,12 @@ int32_t mbox_k3_sec_proxy_verify_thread(uint8_t thread_id, uint8_t msg_drxn) MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_DIR_MASK) >> MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_DIR_IDX != msg_drxn) { - if (MSG_DRXN_WRITE == msg_drxn) { + if (MBOX_K3_SEC_PROXY_MSG_DRXN_WRITE == msg_drxn) { ERROR("secure_proxy_thread_%d cannot READ on WRITE thread", thread_id); - return STATUS_CODE_INCORRECT_DRXN; + return MBOX_K3_SEC_PROXY_STATUS_CODE_INCORRECT_DRXN; } else { ERROR("secure_proxy_thread_%d cannot WRITE on READ thread", thread_id); - return STATUS_CODE_INCORRECT_DRXN; + return MBOX_K3_SEC_PROXY_STATUS_CODE_INCORRECT_DRXN; } } @@ -76,12 +63,12 @@ int32_t mbox_k3_sec_proxy_verify_thread(uint8_t thread_id, uint8_t msg_drxn) if ((0 == (read_reg(thread_rt_base, MBOX_K3_SEC_PROXY_RT_THREAD_STATUS_OFFSET) & MBOX_K3_SEC_PROXY_RT_STATUS_CUR_CNT_MASK)) && - (MSG_DRXN_READ == msg_drxn)) { + (MBOX_K3_SEC_PROXY_MSG_DRXN_READ == msg_drxn)) { ERROR("secure_proxy_thread_%d no entries in message queue", thread_id); - return STATUS_CODE_NO_DATA; + return MBOX_K3_SEC_PROXY_STATUS_CODE_NO_DATA; } - return STATUS_CODE_NO_ERROR; + return MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR; } /* @@ -108,35 +95,36 @@ int32_t mbox_k3_sec_proxy_verify_thread(uint8_t thread_id, uint8_t msg_drxn) * | not reached yet | +------------------------------------+ * +-------------------------+ */ -int32_t mbox_k3_sec_proxy_read(uint8_t thread_id, mbox_k3_sec_proxy_msg* msg) +int32_t mbox_k3_sec_proxy_read(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t thread_id, + void* buffer, size_t len) { /* verify thread status */ - int32_t read_status = mbox_k3_sec_proxy_verify_thread(thread_id, MSG_DRXN_READ); - if (STATUS_CODE_NO_ERROR != read_status) { + int32_t read_status = + mbox_k3_sec_proxy_verify_thread(sec_proxy_desc, thread_id, MBOX_K3_SEC_PROXY_MSG_DRXN_READ); + if (MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR != read_status) { ERROR("secure_proxy_thread_%d thread verif failed", thread_id); return read_status; } /* perform read transaction */ - paddr_t data_reg = sec_proxy_desc.thread_inst.data_base + + paddr_t data_reg = sec_proxy_desc->thread_inst.data_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id) + MBOX_K3_SEC_PROXY_DATA_START_OFFSET; /* read whole words first */ uint32_t word_iterator; - size_t num_words = msg->len / sizeof(uint32_t); + size_t num_words = len / sizeof(uint32_t); for (word_iterator = 0; word_iterator < num_words; word_iterator++) { - ((uint32_t*)msg->buffer)[word_iterator] = - read_reg(data_reg, word_iterator * sizeof(uint32_t)); + ((uint32_t*)buffer)[word_iterator] = read_reg(data_reg, word_iterator * sizeof(uint32_t)); } /* read remaining bytes */ - uint32_t trail_bytes = msg->len % sizeof(uint32_t); + uint32_t trail_bytes = len % sizeof(uint32_t); if (0 != trail_bytes) { uint32_t data_trail = read_reg(data_reg, word_iterator++ * sizeof(uint32_t)); - size_t trail_iterator = msg->len - trail_bytes; + size_t trail_iterator = len - trail_bytes; while (trail_bytes--) { - ((uint8_t*)msg->buffer)[trail_iterator++] = (uint8_t)(data_trail & 0xFFU); + ((uint8_t*)buffer)[trail_iterator++] = (uint8_t)(data_trail & 0xFFU); data_trail >>= 8; } } @@ -183,41 +171,42 @@ int32_t mbox_k3_sec_proxy_read(uint8_t thread_id, mbox_k3_sec_proxy_msg* msg) * | end offset (trigger) | +------------------------------------+ * +-------------------------+ */ -int32_t mbox_k3_sec_proxy_write(uint8_t thread_id, mbox_k3_sec_proxy_msg* msg) +int32_t mbox_k3_sec_proxy_write(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t thread_id, + void* buffer, size_t len) { /* verify thread status */ - int32_t write_status = mbox_k3_sec_proxy_verify_thread(thread_id, MSG_DRXN_WRITE); - if (STATUS_CODE_NO_ERROR != write_status) { + int32_t write_status = mbox_k3_sec_proxy_verify_thread(sec_proxy_desc, thread_id, + MBOX_K3_SEC_PROXY_MSG_DRXN_WRITE); + if (MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR != write_status) { ERROR("secure_proxy_thread_%d thread verif failed", thread_id); return write_status; } /* msg len check */ - if (msg->len > sec_proxy_desc.thread_inst.max_msg_size) { + if (len > sec_proxy_desc->thread_inst.max_msg_size) { ERROR("secure_proxy_thread_%d msg len exceeds limit", thread_id); - return STATUS_CODE_INVALID_MSG_LEN; + return MBOX_K3_SEC_PROXY_STATUS_CODE_INVALID_MSG_LEN; } /* perform write transaction */ - paddr_t data_reg = sec_proxy_desc.thread_inst.data_base + + paddr_t data_reg = sec_proxy_desc->thread_inst.data_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id) + MBOX_K3_SEC_PROXY_DATA_START_OFFSET; /* write whole words first */ uint32_t word_iterator; - size_t num_words = msg->len / sizeof(uint32_t); + size_t num_words = len / sizeof(uint32_t); for (word_iterator = 0; word_iterator < num_words; word_iterator++) { - write_reg(data_reg, word_iterator * sizeof(uint32_t), - ((uint32_t*)msg->buffer)[word_iterator]); + write_reg(data_reg, word_iterator * sizeof(uint32_t), ((uint32_t*)buffer)[word_iterator]); } /* write remaining bytes */ - uint32_t trail_bytes = msg->len % sizeof(uint32_t); + uint32_t trail_bytes = len % sizeof(uint32_t); if (0 != trail_bytes) { uint32_t data_trail = 0; - size_t trail_iterator = msg->len - trail_bytes; + size_t trail_iterator = len - trail_bytes; for (uint32_t i = 0; i < trail_bytes; i++) { - data_trail |= (uint32_t)((uint8_t*)msg->buffer)[trail_iterator++] << (i * 8); + data_trail |= (uint32_t)((uint8_t*)buffer)[trail_iterator++] << (i * 8); } write_reg(data_reg, word_iterator++ * sizeof(uint32_t), data_trail); @@ -238,18 +227,19 @@ int32_t mbox_k3_sec_proxy_write(uint8_t thread_id, mbox_k3_sec_proxy_msg* msg) return write_status; } -int32_t mbox_k3_sec_proxy_clear(uint8_t thread_id) +int32_t mbox_k3_sec_proxy_clear(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t thread_id) { - int32_t clear_status = mbox_k3_sec_proxy_verify_thread(thread_id, MSG_DRXN_READ); - if (STATUS_CODE_NO_ERROR != clear_status) { + int32_t clear_status = + mbox_k3_sec_proxy_verify_thread(sec_proxy_desc, thread_id, MBOX_K3_SEC_PROXY_MSG_DRXN_READ); + if (MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR != clear_status) { ERROR("secure_proxy_thread_%d thread verif failed", thread_id); return clear_status; } paddr_t thread_rt_base = - sec_proxy_desc.thread_inst.rt_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id); + sec_proxy_desc->thread_inst.rt_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id); paddr_t data_reg = - sec_proxy_desc.thread_inst.data_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id); + sec_proxy_desc->thread_inst.data_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id); uint32_t try_count = 10; while (0 != @@ -257,47 +247,52 @@ int32_t mbox_k3_sec_proxy_clear(uint8_t thread_id) MBOX_K3_SEC_PROXY_RT_STATUS_CUR_CNT_MASK)) { if (0 == (try_count--)) { ERROR("secure_proxy_thread_%d mailbox clear failed", thread_id); - return STATUS_CODE_THREAD_CLEAR_FAILED; + return MBOX_K3_SEC_PROXY_STATUS_CODE_THREAD_CLEAR_FAILED; } WARNING("secure_proxy_thread_%d mailbox clear in progress", thread_id); read_reg(data_reg, MBOX_K3_SEC_PROXY_DATA_END_OFFSET); } - return STATUS_CODE_NO_ERROR; + return MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR; } -int32_t mbox_k3_sec_proxy_probe(uint8_t thread_id) +int32_t mbox_k3_sec_proxy_probe(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t thread_id) { paddr_t thread_scfg_base = - sec_proxy_desc.thread_inst.scfg_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id); + sec_proxy_desc->thread_inst.scfg_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id); uint32_t config = read_reg(thread_scfg_base, MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_OFFSET); - paddr_t thread_rt_base = - sec_proxy_desc.thread_inst.rt_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id); - uint8_t hw_host = (config >> 8) & 0xFF; - uint8_t expected_host = sec_proxy_desc.sec_proxy_thread_desc[thread_id].host_id; + uint8_t expected_host = sec_proxy_desc->sec_proxy_thread_desc[thread_id].host_id; /* [step-1] verify thread access/host ownership */ if (hw_host != expected_host) { ERROR("sec_proxy_thread_%d probe failed (hw_host=%d, expected=%d)", thread_id, hw_host, expected_host); - return STATUS_CODE_THREAD_CORRUPTED; + return MBOX_K3_SEC_PROXY_STATUS_CODE_THREAD_CORRUPTED; } /* [step-2] verify if thread is clean */ - int32_t probe_status = mbox_k3_sec_proxy_verify_thread(thread_id, MSG_DRXN_WRITE); - if (STATUS_CODE_NO_ERROR != probe_status) { - INFO("sec_proxy_thread_%d probe failed (error_id=%d)", thread_id, probe_status); - return probe_status; - } + int32_t probe_status = mbox_k3_sec_proxy_verify_thread(sec_proxy_desc, thread_id, + sec_proxy_desc->sec_proxy_thread_desc[thread_id].msg_drxn); - if (0 != - (read_reg(thread_rt_base, MBOX_K3_SEC_PROXY_RT_THREAD_STATUS_OFFSET) & - MBOX_K3_SEC_PROXY_RT_STATUS_CUR_CNT_MASK)) { + if (MBOX_K3_SEC_PROXY_MSG_DRXN_READ == + sec_proxy_desc->sec_proxy_thread_desc[thread_id].msg_drxn && + MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR == probe_status) { ERROR("secure_proxy_thread_%d probe failed (message queue not clean)", thread_id); - return STATUS_CODE_DIRTY_HANDOFF; + return MBOX_K3_SEC_PROXY_STATUS_CODE_DIRTY_HANDOFF; + } + + if (MBOX_K3_SEC_PROXY_MSG_DRXN_READ == + sec_proxy_desc->sec_proxy_thread_desc[thread_id].msg_drxn && + MBOX_K3_SEC_PROXY_STATUS_CODE_NO_DATA == probe_status) { + probe_status = MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR; + } + + if (MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR != probe_status) { + INFO("sec_proxy_thread_%d probe failed (error_id=%d)", thread_id, probe_status); + return probe_status; } /* [step-3] check pipeline health by pinging sysfw @@ -305,8 +300,8 @@ int32_t mbox_k3_sec_proxy_probe(uint8_t thread_id) * @notes * - the hook needs to be implemented by the platform, as the driver is protocol agnostic. */ - probe_status = mbox_k3_sec_proxy_ping_test(thread_id); - if (STATUS_CODE_NO_ERROR != probe_status) { + probe_status = mbox_k3_sec_proxy_ping_test(sec_proxy_desc, thread_id); + if (MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR != probe_status) { ERROR("sec_proxy_thread_%d probe failed (sysfw ping failure)", thread_id); return probe_status; } @@ -315,8 +310,11 @@ int32_t mbox_k3_sec_proxy_probe(uint8_t thread_id) return probe_status; } -__attribute__((weak)) int32_t mbox_k3_sec_proxy_ping_test(uint8_t thread_id) +__attribute__((weak)) int32_t mbox_k3_sec_proxy_ping_test(mbox_k3_sec_proxy_desc* sec_proxy_desc, + uint8_t thread_id) { UNUSED_ARG(thread_id); - return STATUS_CODE_NO_ERROR; + UNUSED_ARG(sec_proxy_desc); + + return MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR; } From 610178d99bb357022bd3ee5c77b22fddce59c05d Mon Sep 17 00:00:00 2001 From: puranikvinit Date: Sat, 21 Feb 2026 21:53:44 +0530 Subject: [PATCH 04/10] fix(drivers/mailbox): poll cur_cnt reg with configurable timeout Signed-off-by: puranikvinit --- .../armv8/aarch64/inc/arch/subarch/sysregs.h | 1 + .../drivers/mailbox/inc/drivers/k3_sec_proxy.h | 2 ++ src/platform/drivers/mailbox/k3_sec_proxy.c | 16 +++++++++++----- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/arch/armv8/aarch64/inc/arch/subarch/sysregs.h b/src/arch/armv8/aarch64/inc/arch/subarch/sysregs.h index 949f85cc3..ab6fee9bb 100644 --- a/src/arch/armv8/aarch64/inc/arch/subarch/sysregs.h +++ b/src/arch/armv8/aarch64/inc/arch/subarch/sysregs.h @@ -75,6 +75,7 @@ SYSREG_GEN_ACCESSORS(cntvoff_el2) SYSREG_GEN_ACCESSORS(sctlr_el1) SYSREG_GEN_ACCESSORS(cntkctl_el1) SYSREG_GEN_ACCESSORS(cntfrq_el0) +SYSREG_GEN_ACCESSORS(cntpct_el0) SYSREG_GEN_ACCESSORS(pmcr_el0) SYSREG_GEN_ACCESSORS(par_el1) SYSREG_GEN_ACCESSORS(tcr_el2) diff --git a/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h b/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h index 0a0ffbb93..7f42acaba 100644 --- a/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h +++ b/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h @@ -12,6 +12,7 @@ #include #include #include +#include /** * @brief Defines the specific host function associated with a Secure Proxy @@ -112,6 +113,7 @@ typedef struct { */ typedef struct { mbox_k3_sec_proxy_instance thread_inst; /**< Secure Proxy instance configuration */ + uint32_t read_timeout_us; /**< timeout before read operation fails due to no data in the mbox queue */ mbox_k3_sec_proxy_thread_desc sec_proxy_thread_desc[]; /**< Array of thread descriptors */ } mbox_k3_sec_proxy_desc; diff --git a/src/platform/drivers/mailbox/k3_sec_proxy.c b/src/platform/drivers/mailbox/k3_sec_proxy.c index 094cfeb22..3cd597a46 100644 --- a/src/platform/drivers/mailbox/k3_sec_proxy.c +++ b/src/platform/drivers/mailbox/k3_sec_proxy.c @@ -60,12 +60,18 @@ int32_t mbox_k3_sec_proxy_verify_thread(mbox_k3_sec_proxy_desc* sec_proxy_desc, } /* check if msg queue has entries before txn attempt */ - if ((0 == + if (MBOX_K3_SEC_PROXY_MSG_DRXN_READ == msg_drxn) { + uint64_t tick_start = sysreg_cntpct_el0_read(); + uint64_t ticks_per_us = sysreg_cntfrq_el0_read() / 1000000U; + while (0 == (read_reg(thread_rt_base, MBOX_K3_SEC_PROXY_RT_THREAD_STATUS_OFFSET) & - MBOX_K3_SEC_PROXY_RT_STATUS_CUR_CNT_MASK)) && - (MBOX_K3_SEC_PROXY_MSG_DRXN_READ == msg_drxn)) { - ERROR("secure_proxy_thread_%d no entries in message queue", thread_id); - return MBOX_K3_SEC_PROXY_STATUS_CODE_NO_DATA; + MBOX_K3_SEC_PROXY_RT_STATUS_CUR_CNT_MASK)) { + if ((sysreg_cntpct_el0_read() - tick_start) > + (sec_proxy_desc->read_timeout_us * ticks_per_us)) { + ERROR("secure_proxy_thread_%d no entries in message queue", thread_id); + return MBOX_K3_SEC_PROXY_STATUS_CODE_NO_DATA; + } + } } return MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR; From b4d65a8cf7c6fbc9cd32acdf0761f628569293f5 Mon Sep 17 00:00:00 2001 From: puranikvinit Date: Sun, 22 Feb 2026 11:57:29 +0530 Subject: [PATCH 05/10] feat(drivers): add tisci transport protocol driver Signed-off-by: puranikvinit --- .../drivers/firmware/inc/drivers/tisci.h | 186 ++++++++++++++++++ src/platform/drivers/firmware/objects.mk | 4 + src/platform/drivers/firmware/tisci.c | 163 +++++++++++++++ 3 files changed, 353 insertions(+) create mode 100644 src/platform/drivers/firmware/inc/drivers/tisci.h create mode 100644 src/platform/drivers/firmware/objects.mk create mode 100644 src/platform/drivers/firmware/tisci.c diff --git a/src/platform/drivers/firmware/inc/drivers/tisci.h b/src/platform/drivers/firmware/inc/drivers/tisci.h new file mode 100644 index 000000000..94e4fa25b --- /dev/null +++ b/src/platform/drivers/firmware/inc/drivers/tisci.h @@ -0,0 +1,186 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __TISCI_H_ +#define __TISCI_H_ + +#include +#include +#include +#include + +/** + * @brief TISCI Status Codes + */ +typedef enum { + TISCI_STATUS_CODE_NO_ERROR = 0, + TISCI_STATUS_CODE_INVALID_MSG_LEN = -1, + TISCI_STATUS_CODE_MSG_RCV_FAILED = -2, + TISCI_STATUS_CODE_MSG_SEND_FAILED = -3, + TISCI_STATUS_CODE_MSG_RX_TIMEOUT = -4, + TISCI_STATUS_CODE_NO_ACK_RCVD = -5, +} TISCI_STATUS_CODES; + +#define TISCI_HOST_DMSC (0U) + +/* msg request flags */ +#define TISCI_MSG_REQ_FLAG_RESERVED0_IDX (0) +#define TISCI_MSG_REQ_FLAG_AOP_IDX (1) +#define TISCI_MSG_REQ_FLAG_REQ_NOTFWD2DM_IDX (3) + +#define TISCI_MSG_REQ_FLAG_RESERVED0 (1 << TISCI_MSG_REQ_FLAG_RESERVED0_IDX) +#define TISCI_MSG_REQ_FLAG_AOP \ + (1 << TISCI_MSG_REQ_FLAG_AOP_IDX) /* ACK On Processed (AOP) - set if msg \ + requires ACK from DMSC */ +#define TISCI_MSG_REQ_FLAG_REQ_NOTFWD2DM (1 << TISCI_MSG_REQ_FLAG_REQ_NOTFWD2DM_IDX) + +/* msg response flags */ +#define TISCI_MSG_RSP_FLAG_ACK_IDX (1) + +#define TISCI_MSG_RSP_FLAG_ACK (1 << TISCI_MSG_RSP_FLAG_ACK_IDX) +#define TISCI_MSG_RSP_FLAG_NAK (0 << TISCI_MSG_RSP_FLAG_ACK_IDX) + +#define TISCI_MSG_MAX_SIZE (56U) +#define TISCI_MSG_TXN_TIMEOUT (1000) /* 1000ms */ +#define TISCI_MSG_NUM_RETRIES (5) + +/** + * review the version of the currently running sysfw + * secure thread msg => NO + */ +#define TISCI_MSG_VERSION (0x0002U) + +/* + * tisci msg format + * + * ^ +-----------------------+ +----------------------+ + * | | secure header (4B) |------>| integrity check (2B) | + * | +-----------------------+ +----------------------+ + * min: 12B | | | | reserved (2B) | + * | | TISCI header (8B) | +----------------------+ + * | | | + * + +-----------------------+ + * | | | + * | | | + * max: 56B | | payload (max 44B) | + * | | | + * | | | + * v +-----------------------+ + * + */ + +/** + * @brief TISCI generic msg header for ALL msg and rsp + */ +typedef struct __attribute__((packed)) { + /** Message type ID */ + uint16_t type; + + /** + * logically distinct high level software entity identifier, used to select + * the set of channels to communicate with the DMSC + */ + uint8_t host_id; + + /** + * sequence identifier that will be returned back to the hypervisor for the + * response corresponding to the message + */ + uint8_t seq_id; + + /** Message flags */ + uint32_t msg_flags; +} tisci_msg_header; + +/** + * @brief Prefix header for all TISCI msg sent over secure transport. + */ +typedef struct __attribute__((packed)) { + /** msg integrity checksum, calculated for total msg in the request path */ + uint16_t integ_check; + + /** reserved for future use */ + uint16_t reserved; +} tisci_secure_msg_header; + +/** + * @brief TISCI Transport Operations + * + * Platform specific transport operations for sending and receiving messages. + */ +typedef struct { + /** + * @brief Send a message over a specific channel. + * + * @param chan_id The channel ID to send the message on. + * @param buffer Pointer to the data to send. + * @param len Length of the data in bytes. + * + * @return TISCI_STATUS_CODE_NO_ERROR on success, error code otherwise. + */ + int32_t (*send)(uint8_t chan_id, void* buffer, size_t len); + + /** + * @brief Receive a message from a specific channel. + * + * @param chan_id The channel ID to receive the message from. + * @param buffer Pointer to the buffer to store received data. + * @param len Maximum length of the buffer. + * + * @return TISCI_STATUS_CODE_NO_ERROR on success, error code otherwise. + */ + int32_t (*recv)(uint8_t chan_id, void* buffer, size_t len); +} tisci_ops; + +/** + * @brief TISCI Driver Context + * + * Holds the state and configuration for the TISCI driver instance. + */ +typedef struct { + /** Transport operations for sending/receiving messages */ + tisci_ops ops; + /** Lock to protect sequence ID generation */ + spinlock_t seq_id_lock; + /** Current sequence ID counter */ + uint8_t seq_id; +} tisci_ctx; + +/** + * @brief Response structure for TISCI_MSG_VERSION + * + * Returns version information of the currently running System Firmware (SYSFW). + */ +typedef struct __attribute__((packed)) { + /** Standard TISCI message header */ + tisci_msg_header msg_header; + /** Description string of the SYSFW */ + char sysfw_desc[32]; + /** SYSFW version number */ + uint16_t sysfw_version; + /** SYSFW ABI major version */ + uint8_t sysfw_abi_major; + /** SYSFW ABI minor version */ + uint8_t sysfw_abi_minor; + /** SYSFW sub-version number */ + uint8_t sysfw_sub_version; + /** SYSFW patch version number */ + uint8_t sysfw_patch_version; +} tisci_msg_version_rsp; + +/** + * @brief Retrieves the revision of the System Firmware. + * + * @param ctx Pointer to the TISCI driver context. + * @param host_id The Host ID to be used in the message header. + * @param chan_id The channel ID to use for the transaction. + * @param ver_rsp Pointer to the structure where the version response will be stored. + * + * @return TISCI_STATUS_CODE_NO_ERROR on success, or a negative error code on failure. + */ +int32_t tisci_get_revision(tisci_ctx* ctx, uint8_t host_id, uint8_t chan_id, + tisci_msg_version_rsp* ver_rsp); + +#endif /* __TISCI_H_ */ diff --git a/src/platform/drivers/firmware/objects.mk b/src/platform/drivers/firmware/objects.mk new file mode 100644 index 000000000..86824188b --- /dev/null +++ b/src/platform/drivers/firmware/objects.mk @@ -0,0 +1,4 @@ +## SPDX-License-Identifier: Apache-2.0 +## Copyright (c) Bao Project and Contributors. All rights reserved. + +drivers-objs-y+=firmware/tisci.o diff --git a/src/platform/drivers/firmware/tisci.c b/src/platform/drivers/firmware/tisci.c new file mode 100644 index 000000000..734fa008b --- /dev/null +++ b/src/platform/drivers/firmware/tisci.c @@ -0,0 +1,163 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include + +/** + * @brief Prepares the TISCI message header. + * + * Assigns a new sequence ID to the message and sets the 'ACK On Processed' (AOP) flag + * to ensure the DMSC sends a response. + * + * @param ctx The driver context containing the sequence ID counter. + * @param tx_buf Pointer to the transmit buffer containing the message header. + * @param tx_len Length of the transmit buffer. + * + * @return TISCI_STATUS_CODE_NO_ERROR on success, error code on failure. + */ +static int32_t _setup_hdr(tisci_ctx* ctx, void* tx_buf, size_t tx_len) +{ + tisci_msg_header* msg_hdr; + + if (tx_len > TISCI_MSG_MAX_SIZE || tx_len < sizeof(tisci_msg_header)) { + return TISCI_STATUS_CODE_INVALID_MSG_LEN; + } + + msg_hdr = (tisci_msg_header*)tx_buf; + + /* increment and assign sequence ID for tracking this specific transaction */ + msg_hdr->seq_id = ++ctx->seq_id; + msg_hdr->msg_flags |= TISCI_MSG_REQ_FLAG_AOP; + + return TISCI_STATUS_CODE_NO_ERROR; +} + +/** + * @brief Receives a response from the TISCI channel. + * + * This function polls the receive channel for a response. It verifies: + * 1. The message was received successfully. + * 2. The received sequence ID matches the expected one (from the context). + * 3. The response has the ACK flag set. + * + * It checks up to TISCI_MSG_NUM_RETRIES times to handle mismatched messages (e.g. stale responses). + * The actual timeout is handled by the underlying recv operation. + * + * @param ctx The driver context. + * @param chan_id The channel ID to receive from. + * @param rx_buf Pointer to the receive buffer. + * @param rx_len Length of the receive buffer. + * @param expected_seq_id Expected Sequence ID for the received message. + * + * @return TISCI_STATUS_CODE_NO_ERROR on success, error code on failure. + */ +static int32_t _get_rsp(tisci_ctx* ctx, uint8_t chan_id, void* rx_buf, size_t rx_len, + uint8_t expected_seq_id) +{ + tisci_msg_header* msg_hdr; + + /* Validate buffer size before receiving to prevent overflow */ + if (rx_len > TISCI_MSG_MAX_SIZE) { + ERROR("channel_%d expected msg len too long", chan_id); + return TISCI_STATUS_CODE_INVALID_MSG_LEN; + } + + unsigned int retry_iterator = TISCI_MSG_NUM_RETRIES; + for (; retry_iterator > 0; retry_iterator--) { + int32_t recv_status = ctx->ops.recv(chan_id, rx_buf, rx_len); + if (TISCI_STATUS_CODE_NO_ERROR != recv_status) { + ERROR("channel_%d tisci msg rcv failed", chan_id); + return TISCI_STATUS_CODE_MSG_RCV_FAILED; + } + + msg_hdr = (tisci_msg_header*)rx_buf; + /* Verify that the response corresponds to the request we just sent */ + if (msg_hdr->seq_id == expected_seq_id) { + break; + } else { + WARNING("channel_%d unexpected seq_id (rcvd=%d, expected=%d)", chan_id, msg_hdr->seq_id, + expected_seq_id); + } + } + + if (0 == retry_iterator) { + ERROR("channel_%d timed out waiting for msg", chan_id); + return TISCI_STATUS_CODE_MSG_RX_TIMEOUT; + } + + /* Check if the DMSC acknowledged the request */ + if (0 == (msg_hdr->msg_flags & TISCI_MSG_RSP_FLAG_ACK)) { + ERROR("channel_%d no ack rcvd", chan_id); + return TISCI_STATUS_CODE_NO_ACK_RCVD; + } + + return TISCI_STATUS_CODE_NO_ERROR; +} + +/** + * @brief Performs a full TISCI transaction (Send + Receive). + * + * Wraps the send and receive operations. It first sends the request, + * then immediately waits for the corresponding response. + * + * @param ctx The driver context. + * @param chan_id The channel ID for the transaction. + * @param tx_buf Pointer to the transmit buffer. + * @param tx_len Length of data to transmit. + * @param rx_buf Pointer to the receive buffer. + * @param rx_len Length of the receive buffer. + * @param expected_seq_id Expected Sequence ID for the received message. + * + * @return TISCI_STATUS_CODE_NO_ERROR on success, error code on failure. + */ +static int32_t _perform_txn(tisci_ctx* ctx, uint8_t chan_id, void* tx_buf, size_t tx_len, + void* rx_buf, size_t rx_len, uint8_t seq_id) +{ + int32_t txn_status = ctx->ops.send(chan_id, tx_buf, tx_len); + if (TISCI_STATUS_CODE_NO_ERROR != txn_status) { + ERROR("channel_%d txn - write failed", chan_id); + return TISCI_STATUS_CODE_MSG_SEND_FAILED; + } + + txn_status = _get_rsp(ctx, chan_id, rx_buf, rx_len, seq_id); + if (TISCI_STATUS_CODE_NO_ERROR != txn_status) { + ERROR("channel_%d txn - read failed", chan_id); + return txn_status; + } + + return TISCI_STATUS_CODE_NO_ERROR; +} + +int32_t tisci_get_revision(tisci_ctx* ctx, uint8_t host_id, uint8_t chan_id, + tisci_msg_version_rsp* ver_rsp) +{ + tisci_msg_header msg_header = { + .host_id = host_id, + .type = TISCI_MSG_VERSION, + }; + + /* critical section - aquire a spinlock on hdr setup to ensure atomic updates to seq_id and + * store them for the current txn */ + spin_lock(&(ctx->seq_id_lock)); + + int32_t rev_status = _setup_hdr(ctx, &msg_header, sizeof(msg_header)); + if (TISCI_STATUS_CODE_NO_ERROR != rev_status) { + ERROR("channel_%d msg hdr setup failed", chan_id); + spin_unlock(&(ctx->seq_id_lock)); + return rev_status; + } + + uint8_t cur_seq_id = ctx->seq_id; + spin_unlock(&(ctx->seq_id_lock)); + + rev_status = _perform_txn(ctx, chan_id, &msg_header, sizeof(msg_header), ver_rsp, + sizeof(*ver_rsp), cur_seq_id); + if (TISCI_STATUS_CODE_NO_ERROR != rev_status) { + ERROR("channel_%d tisci txn failed", chan_id); + return rev_status; + } + + return TISCI_STATUS_CODE_NO_ERROR; +} From 8022fe65c91421dda0126539c41eb34b6e592b55 Mon Sep 17 00:00:00 2001 From: puranikvinit Date: Sun, 22 Feb 2026 19:26:52 +0530 Subject: [PATCH 06/10] feat(drivers/mailbox): add helper func to get threads by host_id feat(drivers/mailbox): add helper function to get threads by host_id and host_function fix(drivers/mailbox): code lint fixes Signed-off-by: puranikvinit --- .../mailbox/inc/drivers/k3_sec_proxy.h | 105 ++++++++++-------- src/platform/drivers/mailbox/k3_sec_proxy.c | 28 ++--- 2 files changed, 68 insertions(+), 65 deletions(-) diff --git a/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h b/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h index 7f42acaba..fddc3a0eb 100644 --- a/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h +++ b/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h @@ -24,6 +24,7 @@ typedef enum { MBOX_K3_SEC_PROXY_HOST_FUNCTION_HIGH_PRIORITY, MBOX_K3_SEC_PROXY_HOST_FUNCTION_LOW_PRIORITY, MBOX_K3_SEC_PROXY_HOST_FUNCTION_NOTIFY_RESP, + MBOX_K3_SEC_PROXY_NUM_HOST_FUNCTIONS, } MBOX_K3_SEC_PROXY_HOST_FUNCTION; /** @@ -48,25 +49,25 @@ typedef enum { } MBOX_K3_SEC_PROXY_STATUS_CODES; /* bit indices */ -#define MBOX_K3_SEC_PROXY_RT_THREAD_STATUS_OFFSET (0x0U) +#define MBOX_K3_SEC_PROXY_RT_THREAD_STATUS_OFFSET (0x0U) #define MBOX_K3_SEC_PROXY_RT_THREAD_THRESHOLD_OFFSET (0x4U) -#define MBOX_K3_SEC_PROXY_RT_STATUS_ERROR_IDX (31) -#define MBOX_K3_SEC_PROXY_RT_STATUS_ERROR_MASK (1U << MBOX_K3_SEC_PROXY_RT_STATUS_ERROR_IDX) +#define MBOX_K3_SEC_PROXY_RT_STATUS_ERROR_IDX (31) +#define MBOX_K3_SEC_PROXY_RT_STATUS_ERROR_MASK (1U << MBOX_K3_SEC_PROXY_RT_STATUS_ERROR_IDX) -#define MBOX_K3_SEC_PROXY_RT_STATUS_CUR_CNT_IDX (0) -#define MBOX_K3_SEC_PROXY_RT_STATUS_CUR_CNT_MASK (0xFFU << MBOX_K3_SEC_PROXY_RT_STATUS_CUR_CNT_IDX) +#define MBOX_K3_SEC_PROXY_RT_STATUS_CUR_CNT_IDX (0) +#define MBOX_K3_SEC_PROXY_RT_STATUS_CUR_CNT_MASK (0xFFU << MBOX_K3_SEC_PROXY_RT_STATUS_CUR_CNT_IDX) -#define MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_OFFSET (0x1000U) +#define MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_OFFSET (0x1000U) -#define MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_DIR_IDX (31) -#define MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_DIR_MASK \ +#define MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_DIR_IDX (31) +#define MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_DIR_MASK \ (1U << MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_DIR_IDX) #define MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id) (0x1000U * (thread_id)) -#define MBOX_K3_SEC_PROXY_DATA_START_OFFSET (0x4U) -#define MBOX_K3_SEC_PROXY_DATA_END_OFFSET (0x3CU) /* completion trigger offset */ +#define MBOX_K3_SEC_PROXY_DATA_START_OFFSET (0x4U) +#define MBOX_K3_SEC_PROXY_DATA_END_OFFSET (0x3CU) /* completion trigger offset */ /** * @brief Hardware configuration for a Secure Proxy instance. @@ -79,10 +80,10 @@ typedef struct { * 1 => MCU_NAVSS0_SEC_PROXY0 * can modify type based on requirements... */ - uint32_t id; /**< Instance ID (e.g., NAVSS0_SEC_PROXY_0) */ + uint32_t id; /**< Instance ID (e.g., NAVSS0_SEC_PROXY_0) */ - paddr_t rt_base; /**< Base address of Real-Time (RT) region */ - size_t rt_size; /**< Size of RT region */ + paddr_t rt_base; /**< Base address of Real-Time (RT) region */ + size_t rt_size; /**< Size of RT region */ paddr_t scfg_base; /**< Base address of Secure Configuration (SCFG) region */ size_t scfg_size; /**< Size of SCFG region */ @@ -101,10 +102,9 @@ typedef struct { MBOX_K3_SEC_PROXY_MSG_DRXN msg_drxn; /**< Message direction (Read/Write) */ uint8_t mbox_queue_depth; /**< Depth of the mailbox queue */ uint8_t host_id; /**< ID of the host associated with this thread */ - MBOX_K3_SEC_PROXY_HOST_FUNCTION - host_function; /**< Function/Role of the thread */ - uint16_t irq_line_threshold; /**< IRQ threshold configuration */ - uint16_t irq_line_error; /**< IRQ error configuration */ + MBOX_K3_SEC_PROXY_HOST_FUNCTION host_function; /**< Function/Role of the thread */ + uint16_t irq_line_threshold; /**< IRQ threshold configuration */ + uint16_t irq_line_error; /**< IRQ error configuration */ } mbox_k3_sec_proxy_thread_desc; /** @@ -113,8 +113,10 @@ typedef struct { */ typedef struct { mbox_k3_sec_proxy_instance thread_inst; /**< Secure Proxy instance configuration */ - uint32_t read_timeout_us; /**< timeout before read operation fails due to no data in the mbox queue */ - mbox_k3_sec_proxy_thread_desc sec_proxy_thread_desc[]; /**< Array of thread descriptors */ + uint32_t read_timeout_us; /**< timeout before read operation fails due to no data in the mbox + queue */ + mbox_k3_sec_proxy_thread_desc* sec_proxy_thread_desc; /**< Array of thread descriptors */ + size_t num_threads; /**< Number of entries in the sec_proxy_thread_desc array */ } mbox_k3_sec_proxy_desc; // clang-format off @@ -122,39 +124,40 @@ typedef struct { host, base_thread_id, notify_queue_depth, resp_queue_depth, \ high_priority_queue_depth, low_priority_queue_depth) \ [base_thread_id] = \ - (mbox_k3_sec_proxy_thread_desc){ \ + { \ .sec_proxy_thread_id = base_thread_id, \ - .msg_drxn = MSG_DRXN_READ, \ + .msg_drxn = MBOX_K3_SEC_PROXY_MSG_DRXN_READ, \ .mbox_queue_depth = notify_queue_depth, \ .host_id = host, \ - .host_function = HOST_FUNCTION_NOTIFY}, \ + .host_function = MBOX_K3_SEC_PROXY_HOST_FUNCTION_NOTIFY}, \ [base_thread_id + 1] = \ - (mbox_k3_sec_proxy_thread_desc){ \ + { \ .sec_proxy_thread_id = (base_thread_id + 1), \ - .msg_drxn = MSG_DRXN_READ, \ + .msg_drxn = MBOX_K3_SEC_PROXY_MSG_DRXN_READ, \ .mbox_queue_depth = resp_queue_depth, \ .host_id = host, \ - .host_function = HOST_FUNCTION_RESPONSE}, \ + .host_function = MBOX_K3_SEC_PROXY_HOST_FUNCTION_RESPONSE}, \ [base_thread_id + 2] = \ - (mbox_k3_sec_proxy_thread_desc){ \ + { \ .sec_proxy_thread_id = (base_thread_id + 2), \ - .msg_drxn = MSG_DRXN_WRITE, \ + .msg_drxn = MBOX_K3_SEC_PROXY_MSG_DRXN_WRITE, \ .mbox_queue_depth = high_priority_queue_depth, \ .host_id = host, \ - .host_function = HOST_FUNCTION_HIGH_PRIORITY}, \ + .host_function = MBOX_K3_SEC_PROXY_HOST_FUNCTION_HIGH_PRIORITY}, \ [base_thread_id + 3] = \ - (mbox_k3_sec_proxy_thread_desc){ \ + { \ .sec_proxy_thread_id = (base_thread_id + 3), \ - .msg_drxn = MSG_DRXN_WRITE, \ + .msg_drxn = MBOX_K3_SEC_PROXY_MSG_DRXN_WRITE, \ .mbox_queue_depth = low_priority_queue_depth, \ .host_id = host, \ - .host_function = HOST_FUNCTION_LOW_PRIORITY}, \ + .host_function = MBOX_K3_SEC_PROXY_HOST_FUNCTION_LOW_PRIORITY}, \ [base_thread_id + 4] = \ - (mbox_k3_sec_proxy_thread_desc) { \ + { \ .sec_proxy_thread_id = (base_thread_id + 4), \ - .msg_drxn = MSG_DRXN_WRITE, \ - .mbox_queue_depth = 2, .host_id = host, \ - .host_function = HOST_FUNCTION_NOTIFY_RESP} + .msg_drxn = MBOX_K3_SEC_PROXY_MSG_DRXN_WRITE, \ + .mbox_queue_depth = 2, \ + .host_id = host, \ + .host_function = MBOX_K3_SEC_PROXY_HOST_FUNCTION_NOTIFY_RESP} // clang-format on /** @@ -172,7 +175,8 @@ typedef struct { * @return int32_t STATUS_CODE_NO_ERROR if the thread is valid and ready, * otherwise respective error codes. */ -int32_t mbox_k3_sec_proxy_verify_thread(mbox_k3_sec_proxy_desc *sec_proxy_desc, uint8_t thread_id, uint8_t msg_drxn); +int32_t mbox_k3_sec_proxy_verify_thread(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t thread_id, + uint8_t msg_drxn); /** * @brief Reads a message from a specific Secure Proxy thread. @@ -190,7 +194,8 @@ int32_t mbox_k3_sec_proxy_verify_thread(mbox_k3_sec_proxy_desc *sec_proxy_desc, * for little-endian. * - byte-ordering logic for trailing bytes assumes LSB-first memory layout. */ -int32_t mbox_k3_sec_proxy_read(mbox_k3_sec_proxy_desc *sec_proxy_desc, uint8_t thread_id, void* buffer, size_t len); +int32_t mbox_k3_sec_proxy_read(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t thread_id, + void* buffer, size_t len); /** * @brief Writes a message to a specific Secure Proxy thread. @@ -208,7 +213,8 @@ int32_t mbox_k3_sec_proxy_read(mbox_k3_sec_proxy_desc *sec_proxy_desc, uint8_t t * for little-endian. * - byte-ordering logic for trailing bytes assumes LSB-first memory layout. */ -int32_t mbox_k3_sec_proxy_write(mbox_k3_sec_proxy_desc *sec_proxy_desc, uint8_t thread_id, void* buffer, size_t len); +int32_t mbox_k3_sec_proxy_write(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t thread_id, + void* buffer, size_t len); /** * @brief Clears all pending messages from a Secure Proxy thread. @@ -218,7 +224,7 @@ int32_t mbox_k3_sec_proxy_write(mbox_k3_sec_proxy_desc *sec_proxy_desc, uint8_t * * @return int32_t STATUS_CODE_NO_ERROR on success, or an error code on failure. */ -int32_t mbox_k3_sec_proxy_clear(mbox_k3_sec_proxy_desc *sec_proxy_desc, uint8_t thread_id); +int32_t mbox_k3_sec_proxy_clear(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t thread_id); /** * @brief Performs a health check on a Secure Proxy thread and reports status. @@ -229,20 +235,23 @@ int32_t mbox_k3_sec_proxy_clear(mbox_k3_sec_proxy_desc *sec_proxy_desc, uint8_t * @return int32_t STATUS_CODE_NO_ERROR on success, or respective error codes * on failure. */ -int32_t mbox_k3_sec_proxy_probe(mbox_k3_sec_proxy_desc *sec_proxy_desc, uint8_t thread_id); +int32_t mbox_k3_sec_proxy_probe(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t thread_id); /** - * @brief Protocol-level ping test hook. + * @brief Finds a thread descriptor based on Host Function. * - * @param sec_proxy_desc Pointer to the Secure Proxy descriptor. - * @param thread_id The ID of the thread to test. + * Searches the descriptor's thread array for an entry matching both the + * provided host identifier and the specific function role. * - * @return int32_t STATUS_CODE_NO_ERROR on success, or an error code on failure. + * @param sec_proxy_desc Pointer to the Secure Proxy descriptor. + * @param host_id The hardware Host ID to search for. + * @param host_function The specific role (e.g., RESPONSE, HIGH_PRIORITY). * - * @notes - * - this is a weak function; a strong implementation should be provided by - * the platform to verify pipeline cleanliness. + * @return mbox_k3_sec_proxy_thread_desc* Pointer to the matching thread + * descriptor, or NULL if no match is found. */ -int32_t mbox_k3_sec_proxy_ping_test(mbox_k3_sec_proxy_desc *sec_proxy_desc, uint8_t thread_id); +mbox_k3_sec_proxy_thread_desc* +mbox_k3_sec_proxy_get_thread_by_host_func(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t host_id, + MBOX_K3_SEC_PROXY_HOST_FUNCTION host_function); #endif /* __MBOX_K3_SEC_PROXY_H_ */ diff --git a/src/platform/drivers/mailbox/k3_sec_proxy.c b/src/platform/drivers/mailbox/k3_sec_proxy.c index 3cd597a46..7d7d7940c 100644 --- a/src/platform/drivers/mailbox/k3_sec_proxy.c +++ b/src/platform/drivers/mailbox/k3_sec_proxy.c @@ -301,26 +301,20 @@ int32_t mbox_k3_sec_proxy_probe(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t return probe_status; } - /* [step-3] check pipeline health by pinging sysfw - * - * @notes - * - the hook needs to be implemented by the platform, as the driver is protocol agnostic. - */ - probe_status = mbox_k3_sec_proxy_ping_test(sec_proxy_desc, thread_id); - if (MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR != probe_status) { - ERROR("sec_proxy_thread_%d probe failed (sysfw ping failure)", thread_id); - return probe_status; - } - INFO("sec_proxy_thread_%d probe success", thread_id); return probe_status; } -__attribute__((weak)) int32_t mbox_k3_sec_proxy_ping_test(mbox_k3_sec_proxy_desc* sec_proxy_desc, - uint8_t thread_id) +mbox_k3_sec_proxy_thread_desc* +mbox_k3_sec_proxy_get_thread_by_host_func(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t host_id, + MBOX_K3_SEC_PROXY_HOST_FUNCTION host_function) { - UNUSED_ARG(thread_id); - UNUSED_ARG(sec_proxy_desc); - - return MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR; + for (size_t thread_iterator = 0; thread_iterator < sec_proxy_desc->num_threads; + thread_iterator++) { + if (sec_proxy_desc->sec_proxy_thread_desc[thread_iterator].host_id == host_id && + sec_proxy_desc->sec_proxy_thread_desc[thread_iterator].host_function == host_function) { + return &sec_proxy_desc->sec_proxy_thread_desc[thread_iterator]; + } + } + return NULL; } From 61a74668616a15bd36a8382bcb3d39b13c968699 Mon Sep 17 00:00:00 2001 From: puranikvinit Date: Sun, 22 Feb 2026 19:27:48 +0530 Subject: [PATCH 07/10] fix(drivers/firmware): differentiate between tx and rx channel ids Signed-off-by: puranikvinit --- .../drivers/firmware/inc/drivers/tisci.h | 5 +++-- src/platform/drivers/firmware/tisci.c | 20 +++++++++---------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/platform/drivers/firmware/inc/drivers/tisci.h b/src/platform/drivers/firmware/inc/drivers/tisci.h index 94e4fa25b..ce6b6c7c8 100644 --- a/src/platform/drivers/firmware/inc/drivers/tisci.h +++ b/src/platform/drivers/firmware/inc/drivers/tisci.h @@ -175,12 +175,13 @@ typedef struct __attribute__((packed)) { * * @param ctx Pointer to the TISCI driver context. * @param host_id The Host ID to be used in the message header. - * @param chan_id The channel ID to use for the transaction. + * @param tx_chan_id The channel ID to use for the send transaction. + * @param rx_chan_id The channel ID to use for the recv transaction. * @param ver_rsp Pointer to the structure where the version response will be stored. * * @return TISCI_STATUS_CODE_NO_ERROR on success, or a negative error code on failure. */ -int32_t tisci_get_revision(tisci_ctx* ctx, uint8_t host_id, uint8_t chan_id, +int32_t tisci_get_revision(tisci_ctx* ctx, uint8_t host_id, uint8_t tx_chan_id, uint8_t rx_chan_id, tisci_msg_version_rsp* ver_rsp); #endif /* __TISCI_H_ */ diff --git a/src/platform/drivers/firmware/tisci.c b/src/platform/drivers/firmware/tisci.c index 734fa008b..8f3e28b85 100644 --- a/src/platform/drivers/firmware/tisci.c +++ b/src/platform/drivers/firmware/tisci.c @@ -112,25 +112,25 @@ static int32_t _get_rsp(tisci_ctx* ctx, uint8_t chan_id, void* rx_buf, size_t rx * * @return TISCI_STATUS_CODE_NO_ERROR on success, error code on failure. */ -static int32_t _perform_txn(tisci_ctx* ctx, uint8_t chan_id, void* tx_buf, size_t tx_len, - void* rx_buf, size_t rx_len, uint8_t seq_id) +static int32_t _perform_txn(tisci_ctx* ctx, uint8_t tx_chan_id, uint8_t rx_chan_id, void* tx_buf, + size_t tx_len, void* rx_buf, size_t rx_len, uint8_t seq_id) { - int32_t txn_status = ctx->ops.send(chan_id, tx_buf, tx_len); + int32_t txn_status = ctx->ops.send(tx_chan_id, tx_buf, tx_len); if (TISCI_STATUS_CODE_NO_ERROR != txn_status) { - ERROR("channel_%d txn - write failed", chan_id); + ERROR("channel_%d txn - write failed", tx_chan_id); return TISCI_STATUS_CODE_MSG_SEND_FAILED; } - txn_status = _get_rsp(ctx, chan_id, rx_buf, rx_len, seq_id); + txn_status = _get_rsp(ctx, rx_chan_id, rx_buf, rx_len, seq_id); if (TISCI_STATUS_CODE_NO_ERROR != txn_status) { - ERROR("channel_%d txn - read failed", chan_id); + ERROR("channel_%d txn - read failed", rx_chan_id); return txn_status; } return TISCI_STATUS_CODE_NO_ERROR; } -int32_t tisci_get_revision(tisci_ctx* ctx, uint8_t host_id, uint8_t chan_id, +int32_t tisci_get_revision(tisci_ctx* ctx, uint8_t host_id, uint8_t tx_chan_id, uint8_t rx_chan_id, tisci_msg_version_rsp* ver_rsp) { tisci_msg_header msg_header = { @@ -144,7 +144,7 @@ int32_t tisci_get_revision(tisci_ctx* ctx, uint8_t host_id, uint8_t chan_id, int32_t rev_status = _setup_hdr(ctx, &msg_header, sizeof(msg_header)); if (TISCI_STATUS_CODE_NO_ERROR != rev_status) { - ERROR("channel_%d msg hdr setup failed", chan_id); + ERROR("channel_%d msg hdr setup failed", tx_chan_id); spin_unlock(&(ctx->seq_id_lock)); return rev_status; } @@ -152,10 +152,10 @@ int32_t tisci_get_revision(tisci_ctx* ctx, uint8_t host_id, uint8_t chan_id, uint8_t cur_seq_id = ctx->seq_id; spin_unlock(&(ctx->seq_id_lock)); - rev_status = _perform_txn(ctx, chan_id, &msg_header, sizeof(msg_header), ver_rsp, + rev_status = _perform_txn(ctx, tx_chan_id, rx_chan_id, &msg_header, sizeof(msg_header), ver_rsp, sizeof(*ver_rsp), cur_seq_id); if (TISCI_STATUS_CODE_NO_ERROR != rev_status) { - ERROR("channel_%d tisci txn failed", chan_id); + ERROR("channel_%d tisci txn failed", tx_chan_id); return rev_status; } From c6769ab927120687d5c5e4a578b746475757ef4b Mon Sep 17 00:00:00 2001 From: puranikvinit Date: Fri, 27 Feb 2026 19:44:37 +0530 Subject: [PATCH 08/10] feat(platform): add support for beaglebone ai-64 Signed-off-by: puranikvinit --- README.md | 1 + src/platform/beaglebone-ai64/bb-ai64_desc.c | 130 ++++++++++++++++++ .../beaglebone-ai64/inc/plat/platform.h | 23 ++++ src/platform/beaglebone-ai64/inc/plat/psci.h | 20 +++ src/platform/beaglebone-ai64/objects.mk | 4 + src/platform/beaglebone-ai64/platform.mk | 18 +++ .../mailbox/inc/drivers/k3_sec_proxy.h | 3 + src/platform/drivers/mailbox/k3_sec_proxy.c | 17 +++ 8 files changed, 216 insertions(+) create mode 100644 src/platform/beaglebone-ai64/bb-ai64_desc.c create mode 100644 src/platform/beaglebone-ai64/inc/plat/platform.h create mode 100644 src/platform/beaglebone-ai64/inc/plat/psci.h create mode 100644 src/platform/beaglebone-ai64/objects.mk create mode 100644 src/platform/beaglebone-ai64/platform.mk diff --git a/README.md b/README.md index dc32502a3..67e57b43b 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ platforms is presented below: - [x] Arm Fixed Virtual Platforms - [x] Toradex Verdin iMX8M Plus (w/ Dahlia Carrier Board) - [ ] NXP S32G +- [x] BeagleBone AI-64 **Armv7-A / Armv8-A AArch32** - [x] Arm Fixed Virtual Platforms diff --git a/src/platform/beaglebone-ai64/bb-ai64_desc.c b/src/platform/beaglebone-ai64/bb-ai64_desc.c new file mode 100644 index 000000000..a9d49b311 --- /dev/null +++ b/src/platform/beaglebone-ai64/bb-ai64_desc.c @@ -0,0 +1,130 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#include + +struct platform platform = { + .cpu_num = 2, + .region_num = 2, + .regions = + (struct mem_region[]){ + { + .base = 0x80000000, + .size = 0x80000000, + }, + { + .base = 0x880000000, + .size = 0x80000000, + }, + }, + .console = + { + .base = 0x02800000, + }, + .arch = + { + .gic = + { + .gicd_addr = 0x01800000, + .gicr_addr = 0x01900000, + .gicc_addr = 0x6f000000, + .gich_addr = 0x6f010000, + .gicv_addr = 0x6f020000, + .maintenance_id = 25, + }, + }, +}; + +#ifndef GENERATING_DEFS + +static mbox_k3_sec_proxy_thread_desc sec_proxy_thread_desc[] = { + MBOX_K3_SEC_PROXY_THREAD_DESC_ENTRY(J721E_HOST_ID_MAIN_A72_CONTEXT_0_SECURE, 0, 2, 30, 10, 20), + MBOX_K3_SEC_PROXY_THREAD_DESC_ENTRY(J721E_HOST_ID_MAIN_A72_CONTEXT_1_SECURE, 5, 2, 30, 10, 20), + MBOX_K3_SEC_PROXY_THREAD_DESC_ENTRY(J721E_HOST_ID_MAIN_A72_CONTEXT_2_NON_SECURE, 10, 2, 22, 2, + 20), + MBOX_K3_SEC_PROXY_THREAD_DESC_ENTRY(J721E_HOST_ID_MAIN_A72_CONTEXT_3_NON_SECURE, 15, 2, 7, 2, 5), + MBOX_K3_SEC_PROXY_THREAD_DESC_ENTRY(J721E_HOST_ID_MAIN_A72_CONTEXT_4_NON_SECURE, 20, 2, 7, 2, 5), + MBOX_K3_SEC_PROXY_THREAD_DESC_ENTRY(J721E_HOST_ID_MAIN_A72_CONTEXT_5_NON_SECURE, 55, 2, 7, 2, 5), +}; + +static mbox_k3_sec_proxy_desc k3_sec_proxy = { + .thread_inst = + { + .id = 0U, + .rt_base = 0x0032400000U, + .rt_size = 0x100000U, + .scfg_base = 0x0032800000U, + .scfg_size = 0x100000U, + .data_base = 0x0032C00000, + .data_size = 0x100000, + .max_msg_size = TISCI_MSG_MAX_SIZE, + }, + .read_timeout_us = TISCI_MSG_TXN_TIMEOUT, + .sec_proxy_thread_desc = sec_proxy_thread_desc, + .num_threads = sizeof(sec_proxy_thread_desc) / sizeof(sec_proxy_thread_desc[0]), +}; + +static int32_t platform_tisci_send(uint8_t chan_id, void* buffer, size_t len) +{ + return mbox_k3_sec_proxy_write(&k3_sec_proxy, chan_id, buffer, len); +} + +static int32_t platform_tisci_recv(uint8_t chan_id, void* buffer, size_t len) +{ + return mbox_k3_sec_proxy_read(&k3_sec_proxy, chan_id, buffer, len); +} + +static tisci_ctx tisci_context = { + .ops = + { + .send = platform_tisci_send, + .recv = platform_tisci_recv, + }, + .seq_id_lock = {0, 0}, + .seq_id = 0U, +}; + +void platform_default_init(void) +{ + if (cpu_is_master()) { + cpu_sync_init(&cpu_glb_sync, platform.cpu_num); + } + + mbox_k3_sec_proxy_init(&k3_sec_proxy); + cpu_sync_barrier(&cpu_glb_sync); + + uint8_t cur_host_id = cpu_is_master() ? J721E_HOST_ID_MAIN_A72_CONTEXT_2_NON_SECURE : + J721E_HOST_ID_MAIN_A72_CONTEXT_3_NON_SECURE; + + mbox_k3_sec_proxy_thread_desc* host_threads = + mbox_k3_sec_proxy_get_thread_by_host_func(&k3_sec_proxy, cur_host_id, 0U); + if (NULL == host_threads) { + ERROR("platform init failed, no secure proxy threads found"); + return; + } + + /* probe all secure proxy threads owned by this host */ + for (uint8_t func_iterator = 0U; func_iterator < MBOX_K3_SEC_PROXY_NUM_HOST_FUNCTIONS; + func_iterator++) { + int32_t probe_status = + mbox_k3_sec_proxy_probe(&k3_sec_proxy, host_threads[func_iterator].sec_proxy_thread_id); + if (MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR != probe_status) { + ERROR("platform init failed, k3 secure_proxy_thread_%d probe status=%d", + host_threads[func_iterator].sec_proxy_thread_id, probe_status); + return; + } + } + + /* ping test to ensure that host<->sysfw pipeline is clean */ + tisci_msg_version_rsp ping_rsp = { 0 }; + int32_t ping_status = tisci_get_revision(&tisci_context, cur_host_id, + host_threads[MBOX_K3_SEC_PROXY_HOST_FUNCTION_LOW_PRIORITY].sec_proxy_thread_id, + host_threads[MBOX_K3_SEC_PROXY_HOST_FUNCTION_RESPONSE].sec_proxy_thread_id, &ping_rsp); + if (TISCI_STATUS_CODE_NO_ERROR != ping_status) { + ERROR("platform init failed, ping to sysfw failed, ping_status=%d", ping_status); + } +} + +#endif /* ifndef GENERATING_DEFS */ diff --git a/src/platform/beaglebone-ai64/inc/plat/platform.h b/src/platform/beaglebone-ai64/inc/plat/platform.h new file mode 100644 index 000000000..f029794a6 --- /dev/null +++ b/src/platform/beaglebone-ai64/inc/plat/platform.h @@ -0,0 +1,23 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved + */ + +#ifndef __PLAT_PLATFORM_H__ +#define __PLAT_PLATFORM_H__ + +#define UART8250_REG_WIDTH (4U) + +#include +#include +#include + +/* j721e host id enumeration */ +#define J721E_HOST_ID_MAIN_A72_CONTEXT_0_SECURE (10) +#define J721E_HOST_ID_MAIN_A72_CONTEXT_1_SECURE (11) +#define J721E_HOST_ID_MAIN_A72_CONTEXT_2_NON_SECURE (12) +#define J721E_HOST_ID_MAIN_A72_CONTEXT_3_NON_SECURE (13) +#define J721E_HOST_ID_MAIN_A72_CONTEXT_4_NON_SECURE (14) +#define J721E_HOST_ID_MAIN_A72_CONTEXT_5_NON_SECURE (30) + +#endif diff --git a/src/platform/beaglebone-ai64/inc/plat/psci.h b/src/platform/beaglebone-ai64/inc/plat/psci.h new file mode 100644 index 000000000..82f96ee16 --- /dev/null +++ b/src/platform/beaglebone-ai64/inc/plat/psci.h @@ -0,0 +1,20 @@ +/** + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) Bao Project and Contributors. All rights reserved. + */ + +#ifndef __PLAT_PSCI_H__ +#define __PLAT_PSCI_H__ + +#define PSCI_POWER_STATE_LVL_0 (0x0U) + +#define PSCI_STATE_TYPE_STANDBY (0x0U) +#define PSCI_STATE_TYPE_BIT (1UL << 16) + +#define PSCI_STATE_ID_RUN (0x0U) +#define PSCI_STATE_ID_RETENTION (0x1U) +#define PSCI_STATE_ID_POWERDOWN (0x2U) + +#define PSCI_STATE_TYPE_POWERDOWN PSCI_STATE_TYPE_BIT | PSCI_STATE_ID_POWERDOWN + +#endif // __PLAT_PSCI_H__ diff --git a/src/platform/beaglebone-ai64/objects.mk b/src/platform/beaglebone-ai64/objects.mk new file mode 100644 index 000000000..9f55c3dcf --- /dev/null +++ b/src/platform/beaglebone-ai64/objects.mk @@ -0,0 +1,4 @@ +## SPDX-License-Identifier: Apache-2.0 +## Copyright (c) Bao Project and Contributors. All rights reserved. + +boards-objs-y+=bb-ai64_desc.o diff --git a/src/platform/beaglebone-ai64/platform.mk b/src/platform/beaglebone-ai64/platform.mk new file mode 100644 index 000000000..fbaf62945 --- /dev/null +++ b/src/platform/beaglebone-ai64/platform.mk @@ -0,0 +1,18 @@ +## SPDX-License-Identifier: Apache-2.0 +## Copyright (c) Bao Project and Contributors. All rights reserved. + +# Architecture definition +ARCH:=armv8 +# CPU definition +CPU:=cortex-a72 + +#needs to be checked +GIC_VERSION:=GICV3 + +drivers = 8250_uart mailbox firmware + +platform_description:=bb-ai64_desc.c + +platform-cflags = -mtune=$(CPU) +platform-asflags = +platform-ldflags = diff --git a/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h b/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h index fddc3a0eb..2f531dd77 100644 --- a/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h +++ b/src/platform/drivers/mailbox/inc/drivers/k3_sec_proxy.h @@ -7,6 +7,7 @@ #define __MBOX_K3_SEC_PROXY_H_ #include +#include #include #include #include @@ -254,4 +255,6 @@ mbox_k3_sec_proxy_thread_desc* mbox_k3_sec_proxy_get_thread_by_host_func(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t host_id, MBOX_K3_SEC_PROXY_HOST_FUNCTION host_function); +void mbox_k3_sec_proxy_init(mbox_k3_sec_proxy_desc* sec_proxy_desc); + #endif /* __MBOX_K3_SEC_PROXY_H_ */ diff --git a/src/platform/drivers/mailbox/k3_sec_proxy.c b/src/platform/drivers/mailbox/k3_sec_proxy.c index 7d7d7940c..4ffa0e9ae 100644 --- a/src/platform/drivers/mailbox/k3_sec_proxy.c +++ b/src/platform/drivers/mailbox/k3_sec_proxy.c @@ -318,3 +318,20 @@ mbox_k3_sec_proxy_get_thread_by_host_func(mbox_k3_sec_proxy_desc* sec_proxy_desc } return NULL; } + +void mbox_k3_sec_proxy_init(mbox_k3_sec_proxy_desc* sec_proxy_desc) +{ + if (cpu_is_master()) { + sec_proxy_desc->thread_inst.rt_base = (vaddr_t)mem_alloc_map_dev(&cpu()->as, SEC_HYP_GLOBAL, + INVALID_VA, sec_proxy_desc->thread_inst.rt_base, + NUM_PAGES(sec_proxy_desc->thread_inst.rt_size)); + + sec_proxy_desc->thread_inst.scfg_base = (vaddr_t)mem_alloc_map_dev(&cpu()->as, + SEC_HYP_GLOBAL, INVALID_VA, sec_proxy_desc->thread_inst.scfg_base, + NUM_PAGES(sec_proxy_desc->thread_inst.scfg_size)); + + sec_proxy_desc->thread_inst.data_base = (vaddr_t)mem_alloc_map_dev(&cpu()->as, + SEC_HYP_GLOBAL, INVALID_VA, sec_proxy_desc->thread_inst.data_base, + NUM_PAGES(sec_proxy_desc->thread_inst.data_size)); + } +} From 40ba5682f83d90738a278f0e7558ff4dd5b29385 Mon Sep 17 00:00:00 2001 From: puranikvinit Date: Sat, 28 Feb 2026 12:09:05 +0530 Subject: [PATCH 09/10] feat(drivers/firmware): add tisci irq set and release rm APIs Signed-off-by: puranikvinit --- .../drivers/firmware/inc/drivers/tisci.h | 156 +++++++++++++++++- src/platform/drivers/firmware/tisci.c | 141 ++++++++++++++-- 2 files changed, 275 insertions(+), 22 deletions(-) diff --git a/src/platform/drivers/firmware/inc/drivers/tisci.h b/src/platform/drivers/firmware/inc/drivers/tisci.h index ce6b6c7c8..8bc6996b3 100644 --- a/src/platform/drivers/firmware/inc/drivers/tisci.h +++ b/src/platform/drivers/firmware/inc/drivers/tisci.h @@ -10,6 +10,7 @@ #include #include #include +#include /** * @brief TISCI Status Codes @@ -34,23 +35,57 @@ typedef enum { #define TISCI_MSG_REQ_FLAG_AOP \ (1 << TISCI_MSG_REQ_FLAG_AOP_IDX) /* ACK On Processed (AOP) - set if msg \ requires ACK from DMSC */ -#define TISCI_MSG_REQ_FLAG_REQ_NOTFWD2DM (1 << TISCI_MSG_REQ_FLAG_REQ_NOTFWD2DM_IDX) +#define TISCI_MSG_REQ_FLAG_REQ_NOTFWD2DM (1 << TISCI_MSG_REQ_FLAG_REQ_NOTFWD2DM_IDX) /* msg response flags */ -#define TISCI_MSG_RSP_FLAG_ACK_IDX (1) +#define TISCI_MSG_RSP_FLAG_ACK_IDX (1) -#define TISCI_MSG_RSP_FLAG_ACK (1 << TISCI_MSG_RSP_FLAG_ACK_IDX) -#define TISCI_MSG_RSP_FLAG_NAK (0 << TISCI_MSG_RSP_FLAG_ACK_IDX) +#define TISCI_MSG_RSP_FLAG_ACK (1 << TISCI_MSG_RSP_FLAG_ACK_IDX) +#define TISCI_MSG_RSP_FLAG_NAK (0 << TISCI_MSG_RSP_FLAG_ACK_IDX) -#define TISCI_MSG_MAX_SIZE (56U) -#define TISCI_MSG_TXN_TIMEOUT (1000) /* 1000ms */ -#define TISCI_MSG_NUM_RETRIES (5) +#define TISCI_MSG_MAX_SIZE (56U) +#define TISCI_MSG_TXN_TIMEOUT (1000) /* 1000ms */ +#define TISCI_MSG_NUM_RETRIES (5) + +#define TISCI_RM_IRQ_VALID_DEST_ID_IDX (0U) +#define TISCI_RM_IRQ_VALID_DEST_ID (1U << TISCI_RM_IRQ_VALID_DEST_ID_IDX) + +#define TISCI_RM_IRQ_VALID_DEST_HOST_IRQ_IDX (1U) +#define TISCI_RM_IRQ_VALID_DEST_HOST_IRQ (1U << TISCI_RM_IRQ_VALID_DEST_HOST_IRQ_IDX) + +#define TISCI_RM_IRQ_VALID_IA_ID_IDX (2U) +#define TISCI_RM_IRQ_VALID_IA_ID (1U << TISCI_RM_IRQ_VALID_IA_ID_IDX) + +#define TISCI_RM_IRQ_VALID_VIRT_INT_IDX (3U) +#define TISCI_RM_IRQ_VALID_VIRT_INT (1U << TISCI_RM_IRQ_VALID_VIRT_INT_IDX) + +#define TISCI_RM_IRQ_VALID_GLOBAL_EVENT_IDX (4U) +#define TISCI_RM_IRQ_VALID_GLOBAL_EVENT (1U << TISCI_RM_IRQ_VALID_GLOBAL_EVENT_IDX) + +#define TISCI_RM_IRQ_VALID_VIRT_INT_STATUS_BIT_INDEX_IDX (5U) +#define TISCI_RM_IRQ_VALID_VIRT_INT_STATUS_BIT_INDEX \ + (1U << TISCI_RM_IRQ_VALID_VIRT_INT_STATUS_BIT_INDEX_IDX) + +#define TISCI_RM_IRQ_VALID_SEC_HOST_IDX (31U) +#define TISCI_RM_IRQ_VALID_SEC_HOST (1U << TISCI_RM_IRQ_VALID_SEC_HOST_IDX) /** * review the version of the currently running sysfw * secure thread msg => NO */ -#define TISCI_MSG_VERSION (0x0002U) +#define TISCI_MSG_VERSION (0x0002U) + +/** + * configure peripherals within the SoC interrupt architecture + * secure thread msg => NO + */ +#define TISCI_MSG_RM_IRQ_SET (0x1000U) + +/** + * release an IRQ route between a device peripheral and a host processor + * secure thread msg => NO + */ +#define TISCI_MSG_RM_IRQ_RELEASE (0x1001U) /* * tisci msg format @@ -170,6 +205,80 @@ typedef struct __attribute__((packed)) { uint8_t sysfw_patch_version; } tisci_msg_version_rsp; +/** + * @brief Configures peripheral to processor interrupt route according to the valid configuration + * provided. + */ +typedef struct __attribute__((packed)) { + /** Standard TISCI message header */ + tisci_msg_header msg_header; + /** Bitfield defining validity of interrupt route set parameters */ + uint32_t valid_params; + /** ID of interrupt source peripheral */ + uint16_t src_id; + /** Interrupt source index within source peripheral */ + uint16_t src_idx; + /** SoC IR device ID */ + uint16_t dest_id; + /** SoC IR output index */ + uint16_t dest_host_irq; + /** Device ID of interrupt aggregator in which the virtual interrupt resides */ + uint16_t intr_aggr_id; + /** Virtual interrupt number when configuring an interrupt aggregator */ + uint16_t virt_int; + /** Global event mapped to interrupt aggregator virtual interrupt status bit */ + uint16_t global_event; + /** Virtual interrupt status bit to set if the interrupt route utilizes an IA */ + uint8_t virt_int_status_bit_idx; + /** Secondary host value to replace the host value for the message */ + uint8_t sec_host; +} tisci_msg_rm_irq_set_req; + +/** + * @brief Response to setting a peripheral to processor interrupt route. + */ +typedef struct __attribute__((packed)) { + /** Standard TISCI message header */ + tisci_msg_header msg_header; +} tisci_msg_rm_irq_set_rsp; + +/** + * @brief Releases peripheral to processor interrupt route according to the valid configuration + * provided. + */ +typedef struct __attribute__((packed)) { + /** Standard TISCI message header */ + tisci_msg_header msg_header; + /** Bitfield defining validity of interrupt route release parameters */ + uint32_t valid_params; + /** ID of interrupt source peripheral */ + uint16_t src_id; + /** Interrupt source index within source peripheral */ + uint16_t src_idx; + /** SoC IR device ID */ + uint16_t dest_id; + /** SoC IR output index */ + uint16_t dest_host_irq; + /** Device ID of interrupt aggregator in which the virtual interrupt resides */ + uint16_t intr_aggr_id; + /** Virtual interrupt number if the interrupt route is through an interrupt aggregator */ + uint16_t virt_int; + /** Global event mapped to interrupt aggregator virtual interrupt status bit */ + uint16_t global_event; + /** Virtual interrupt status bit to release if the interrupt route utilizes an IA */ + uint8_t virt_int_status_bit_idx; + /** Secondary host value to replace the host value for the message */ + uint8_t sec_host; +} tisci_msg_rm_irq_release_req; + +/** + * @brief Response to releasing a peripheral to processor interrupt route. + */ +typedef struct __attribute__((packed)) { + /** Standard TISCI message header */ + tisci_msg_header msg_header; +} tisci_msg_rm_irq_release_rsp; + /** * @brief Retrieves the revision of the System Firmware. * @@ -184,4 +293,35 @@ typedef struct __attribute__((packed)) { int32_t tisci_get_revision(tisci_ctx* ctx, uint8_t host_id, uint8_t tx_chan_id, uint8_t rx_chan_id, tisci_msg_version_rsp* ver_rsp); +/** + * @brief Configures peripheral to processor interrupt route. + * + * @param ctx Pointer to the TISCI driver context. + * @param host_id The Host ID to be used in the message header. + * @param tx_chan_id The channel ID to use for the send transaction. + * @param rx_chan_id The channel ID to use for the recv transaction. + * @param irq_set_req Pointer to the interrupt route set request. + * @param irq_set_rsp Pointer to the interrupt route set response. + * + * @return TISCI_STATUS_CODE_NO_ERROR on success, or a negative error code on failure. + */ +int32_t tisci_rm_irq_set(tisci_ctx* ctx, uint8_t host_id, uint8_t tx_chan_id, uint8_t rx_chan_id, + tisci_msg_rm_irq_set_req* irq_set_req, tisci_msg_rm_irq_set_rsp* irq_set_rsp); + +/** + * @brief Releases peripheral to processor interrupt route. + * + * @param ctx Pointer to the TISCI driver context. + * @param host_id The Host ID to be used in the message header. + * @param tx_chan_id The channel ID to use for the send transaction. + * @param rx_chan_id The channel ID to use for the recv transaction. + * @param irq_release_req Pointer to the interrupt route release request. + * @param irq_release_rsp Pointer to the interrupt route release response. + * + * @return TISCI_STATUS_CODE_NO_ERROR on success, or a negative error code on failure. + */ +int32_t tisci_rm_irq_release(tisci_ctx* ctx, uint8_t host_id, uint8_t tx_chan_id, + uint8_t rx_chan_id, tisci_msg_rm_irq_release_req* irq_release_req, + tisci_msg_rm_irq_release_rsp* irq_release_rsp); + #endif /* __TISCI_H_ */ diff --git a/src/platform/drivers/firmware/tisci.c b/src/platform/drivers/firmware/tisci.c index 8f3e28b85..e5d27f1f1 100644 --- a/src/platform/drivers/firmware/tisci.c +++ b/src/platform/drivers/firmware/tisci.c @@ -4,6 +4,9 @@ */ #include +#include +#include +#include /** * @brief Prepares the TISCI message header. @@ -96,6 +99,21 @@ static int32_t _get_rsp(tisci_ctx* ctx, uint8_t chan_id, void* rx_buf, size_t rx return TISCI_STATUS_CODE_NO_ERROR; } +/** + * @brief Transaction context for sending and receiving TISCI messages. + * + * Holds the channel ID, buffer, and buffer length required for a single tx or rx operation during a + * TISCI transaction. + */ +typedef struct { + /** Channel ID for the transaction */ + uint8_t chan_id; + /** Pointer to the buffer containing the message data */ + void* buff; + /** Length of the message buffer in bytes */ + size_t buff_len; +} txn_ctx; + /** * @brief Performs a full TISCI transaction (Send + Receive). * @@ -103,27 +121,23 @@ static int32_t _get_rsp(tisci_ctx* ctx, uint8_t chan_id, void* rx_buf, size_t rx * then immediately waits for the corresponding response. * * @param ctx The driver context. - * @param chan_id The channel ID for the transaction. - * @param tx_buf Pointer to the transmit buffer. - * @param tx_len Length of data to transmit. - * @param rx_buf Pointer to the receive buffer. - * @param rx_len Length of the receive buffer. - * @param expected_seq_id Expected Sequence ID for the received message. + * @param tx_ctx Pointer to the tx transaction context. + * @param rx_ctx Pointer to the rx transaction context. + * @param seq_id Expected Sequence ID for the received message. * * @return TISCI_STATUS_CODE_NO_ERROR on success, error code on failure. */ -static int32_t _perform_txn(tisci_ctx* ctx, uint8_t tx_chan_id, uint8_t rx_chan_id, void* tx_buf, - size_t tx_len, void* rx_buf, size_t rx_len, uint8_t seq_id) +static int32_t _perform_txn(tisci_ctx* ctx, txn_ctx* tx_ctx, txn_ctx* rx_ctx, uint8_t seq_id) { - int32_t txn_status = ctx->ops.send(tx_chan_id, tx_buf, tx_len); + int32_t txn_status = ctx->ops.send(tx_ctx->chan_id, tx_ctx->buff, tx_ctx->buff_len); if (TISCI_STATUS_CODE_NO_ERROR != txn_status) { - ERROR("channel_%d txn - write failed", tx_chan_id); + ERROR("channel_%d txn - write failed", tx_ctx->chan_id); return TISCI_STATUS_CODE_MSG_SEND_FAILED; } - txn_status = _get_rsp(ctx, rx_chan_id, rx_buf, rx_len, seq_id); + txn_status = _get_rsp(ctx, rx_ctx->chan_id, rx_ctx->buff, rx_ctx->buff_len, seq_id); if (TISCI_STATUS_CODE_NO_ERROR != txn_status) { - ERROR("channel_%d txn - read failed", rx_chan_id); + ERROR("channel_%d txn - read failed", rx_ctx->chan_id); return txn_status; } @@ -152,8 +166,107 @@ int32_t tisci_get_revision(tisci_ctx* ctx, uint8_t host_id, uint8_t tx_chan_id, uint8_t cur_seq_id = ctx->seq_id; spin_unlock(&(ctx->seq_id_lock)); - rev_status = _perform_txn(ctx, tx_chan_id, rx_chan_id, &msg_header, sizeof(msg_header), ver_rsp, - sizeof(*ver_rsp), cur_seq_id); + txn_ctx tx_ctx = { + .chan_id = tx_chan_id, + .buff = &msg_header, + .buff_len = sizeof(msg_header), + }; + txn_ctx rx_ctx = { + .chan_id = rx_chan_id, + .buff = ver_rsp, + .buff_len = sizeof(*ver_rsp), + }; + rev_status = _perform_txn(ctx, &tx_ctx, &rx_ctx, cur_seq_id); + + if (TISCI_STATUS_CODE_NO_ERROR != rev_status) { + ERROR("channel_%d tisci txn failed", tx_chan_id); + return rev_status; + } + + return TISCI_STATUS_CODE_NO_ERROR; +} + +int32_t tisci_rm_irq_set(tisci_ctx* ctx, uint8_t host_id, uint8_t tx_chan_id, uint8_t rx_chan_id, + tisci_msg_rm_irq_set_req* irq_set_req, tisci_msg_rm_irq_set_rsp* irq_set_rsp) +{ + tisci_msg_header msg_header = { + .host_id = host_id, + .type = TISCI_MSG_RM_IRQ_SET, + }; + + /* critical section - aquire a spinlock on hdr setup to ensure atomic updates to seq_id and + * store them for the current txn */ + spin_lock(&(ctx->seq_id_lock)); + + int32_t rev_status = _setup_hdr(ctx, &msg_header, sizeof(msg_header)); + if (TISCI_STATUS_CODE_NO_ERROR != rev_status) { + ERROR("channel_%d msg hdr setup failed", tx_chan_id); + spin_unlock(&(ctx->seq_id_lock)); + return rev_status; + } + + uint8_t cur_seq_id = ctx->seq_id; + spin_unlock(&(ctx->seq_id_lock)); + + memcpy(&(irq_set_req->msg_header), &msg_header, sizeof(msg_header)); + + txn_ctx tx_ctx = { + .chan_id = tx_chan_id, + .buff = irq_set_req, + .buff_len = sizeof(tisci_msg_rm_irq_set_req), + }; + txn_ctx rx_ctx = { + .chan_id = rx_chan_id, + .buff = irq_set_rsp, + .buff_len = sizeof(tisci_msg_rm_irq_set_rsp), + }; + rev_status = _perform_txn(ctx, &tx_ctx, &rx_ctx, cur_seq_id); + + if (TISCI_STATUS_CODE_NO_ERROR != rev_status) { + ERROR("channel_%d tisci txn failed", tx_chan_id); + return rev_status; + } + + return TISCI_STATUS_CODE_NO_ERROR; +} + +int32_t tisci_rm_irq_release(tisci_ctx* ctx, uint8_t host_id, uint8_t tx_chan_id, + uint8_t rx_chan_id, tisci_msg_rm_irq_release_req* irq_release_req, + tisci_msg_rm_irq_release_rsp* irq_release_rsp) +{ + tisci_msg_header msg_header = { + .host_id = host_id, + .type = TISCI_MSG_RM_IRQ_RELEASE, + }; + + /* critical section - aquire a spinlock on hdr setup to ensure atomic updates to seq_id and + * store them for the current txn */ + spin_lock(&(ctx->seq_id_lock)); + + int32_t rev_status = _setup_hdr(ctx, &msg_header, sizeof(msg_header)); + if (TISCI_STATUS_CODE_NO_ERROR != rev_status) { + ERROR("channel_%d msg hdr setup failed", tx_chan_id); + spin_unlock(&(ctx->seq_id_lock)); + return rev_status; + } + + uint8_t cur_seq_id = ctx->seq_id; + spin_unlock(&(ctx->seq_id_lock)); + + memcpy(&(irq_release_req->msg_header), &msg_header, sizeof(msg_header)); + + txn_ctx tx_ctx = { + .chan_id = tx_chan_id, + .buff = irq_release_req, + .buff_len = sizeof(tisci_msg_rm_irq_release_req), + }; + txn_ctx rx_ctx = { + .chan_id = rx_chan_id, + .buff = irq_release_rsp, + .buff_len = sizeof(tisci_msg_rm_irq_release_rsp), + }; + rev_status = _perform_txn(ctx, &tx_ctx, &rx_ctx, cur_seq_id); + if (TISCI_STATUS_CODE_NO_ERROR != rev_status) { ERROR("channel_%d tisci txn failed", tx_chan_id); return rev_status; From b6cc338c93148f1d52eb61ea62afba2d75d214fc Mon Sep 17 00:00:00 2001 From: puranikvinit Date: Sun, 21 Jun 2026 10:30:44 +0530 Subject: [PATCH 10/10] fix: various system init, build, and K3 driver fixes - Move console initialization before platform initialization. - Remove hw host ownership check from K3 sec proxy probe. - Add missing newlines to logging macros across TISCI and K3 proxy drivers. - Fix definition generation build issue for BeagleBone-AI64. Signed-off-by: puranikvinit --- src/core/init.c | 4 +- .../beaglebone-ai64/inc/plat/platform.h | 2 + src/platform/drivers/firmware/tisci.c | 26 ++++----- src/platform/drivers/mailbox/k3_sec_proxy.c | 57 +++++++------------ 4 files changed, 38 insertions(+), 51 deletions(-) diff --git a/src/core/init.c b/src/core/init.c index c52df010a..88b74e080 100644 --- a/src/core/init.c +++ b/src/core/init.c @@ -24,10 +24,10 @@ void init(cpuid_t cpu_id) /* -------------------------------------------------------------- */ - platform_init(); - console_init(); + platform_init(); + if (cpu_is_master()) { console_printk("Bao Hypervisor\n\r"); } diff --git a/src/platform/beaglebone-ai64/inc/plat/platform.h b/src/platform/beaglebone-ai64/inc/plat/platform.h index f029794a6..2da975459 100644 --- a/src/platform/beaglebone-ai64/inc/plat/platform.h +++ b/src/platform/beaglebone-ai64/inc/plat/platform.h @@ -8,9 +8,11 @@ #define UART8250_REG_WIDTH (4U) +#ifndef GENERATING_DEFS #include #include #include +#endif /* j721e host id enumeration */ #define J721E_HOST_ID_MAIN_A72_CONTEXT_0_SECURE (10) diff --git a/src/platform/drivers/firmware/tisci.c b/src/platform/drivers/firmware/tisci.c index e5d27f1f1..a532a22ab 100644 --- a/src/platform/drivers/firmware/tisci.c +++ b/src/platform/drivers/firmware/tisci.c @@ -63,7 +63,7 @@ static int32_t _get_rsp(tisci_ctx* ctx, uint8_t chan_id, void* rx_buf, size_t rx /* Validate buffer size before receiving to prevent overflow */ if (rx_len > TISCI_MSG_MAX_SIZE) { - ERROR("channel_%d expected msg len too long", chan_id); + ERROR("channel_%d expected msg len too long\n", chan_id); return TISCI_STATUS_CODE_INVALID_MSG_LEN; } @@ -71,7 +71,7 @@ static int32_t _get_rsp(tisci_ctx* ctx, uint8_t chan_id, void* rx_buf, size_t rx for (; retry_iterator > 0; retry_iterator--) { int32_t recv_status = ctx->ops.recv(chan_id, rx_buf, rx_len); if (TISCI_STATUS_CODE_NO_ERROR != recv_status) { - ERROR("channel_%d tisci msg rcv failed", chan_id); + ERROR("channel_%d tisci msg rcv failed\n", chan_id); return TISCI_STATUS_CODE_MSG_RCV_FAILED; } @@ -80,19 +80,19 @@ static int32_t _get_rsp(tisci_ctx* ctx, uint8_t chan_id, void* rx_buf, size_t rx if (msg_hdr->seq_id == expected_seq_id) { break; } else { - WARNING("channel_%d unexpected seq_id (rcvd=%d, expected=%d)", chan_id, msg_hdr->seq_id, + ERROR("channel_%d unexpected seq_id (rcvd=%d, expected=%d)\n", chan_id, msg_hdr->seq_id, expected_seq_id); } } if (0 == retry_iterator) { - ERROR("channel_%d timed out waiting for msg", chan_id); + ERROR("channel_%d timed out waiting for msg\n", chan_id); return TISCI_STATUS_CODE_MSG_RX_TIMEOUT; } /* Check if the DMSC acknowledged the request */ if (0 == (msg_hdr->msg_flags & TISCI_MSG_RSP_FLAG_ACK)) { - ERROR("channel_%d no ack rcvd", chan_id); + ERROR("channel_%d no ack rcvd\n", chan_id); return TISCI_STATUS_CODE_NO_ACK_RCVD; } @@ -131,13 +131,13 @@ static int32_t _perform_txn(tisci_ctx* ctx, txn_ctx* tx_ctx, txn_ctx* rx_ctx, ui { int32_t txn_status = ctx->ops.send(tx_ctx->chan_id, tx_ctx->buff, tx_ctx->buff_len); if (TISCI_STATUS_CODE_NO_ERROR != txn_status) { - ERROR("channel_%d txn - write failed", tx_ctx->chan_id); + ERROR("channel_%d txn - write failed\n", tx_ctx->chan_id); return TISCI_STATUS_CODE_MSG_SEND_FAILED; } txn_status = _get_rsp(ctx, rx_ctx->chan_id, rx_ctx->buff, rx_ctx->buff_len, seq_id); if (TISCI_STATUS_CODE_NO_ERROR != txn_status) { - ERROR("channel_%d txn - read failed", rx_ctx->chan_id); + ERROR("channel_%d txn - read failed\n", rx_ctx->chan_id); return txn_status; } @@ -158,7 +158,7 @@ int32_t tisci_get_revision(tisci_ctx* ctx, uint8_t host_id, uint8_t tx_chan_id, int32_t rev_status = _setup_hdr(ctx, &msg_header, sizeof(msg_header)); if (TISCI_STATUS_CODE_NO_ERROR != rev_status) { - ERROR("channel_%d msg hdr setup failed", tx_chan_id); + ERROR("channel_%d msg hdr setup failed\n", tx_chan_id); spin_unlock(&(ctx->seq_id_lock)); return rev_status; } @@ -179,7 +179,7 @@ int32_t tisci_get_revision(tisci_ctx* ctx, uint8_t host_id, uint8_t tx_chan_id, rev_status = _perform_txn(ctx, &tx_ctx, &rx_ctx, cur_seq_id); if (TISCI_STATUS_CODE_NO_ERROR != rev_status) { - ERROR("channel_%d tisci txn failed", tx_chan_id); + ERROR("channel_%d tisci txn failed\n", tx_chan_id); return rev_status; } @@ -200,7 +200,7 @@ int32_t tisci_rm_irq_set(tisci_ctx* ctx, uint8_t host_id, uint8_t tx_chan_id, ui int32_t rev_status = _setup_hdr(ctx, &msg_header, sizeof(msg_header)); if (TISCI_STATUS_CODE_NO_ERROR != rev_status) { - ERROR("channel_%d msg hdr setup failed", tx_chan_id); + ERROR("channel_%d msg hdr setup failed\n", tx_chan_id); spin_unlock(&(ctx->seq_id_lock)); return rev_status; } @@ -223,7 +223,7 @@ int32_t tisci_rm_irq_set(tisci_ctx* ctx, uint8_t host_id, uint8_t tx_chan_id, ui rev_status = _perform_txn(ctx, &tx_ctx, &rx_ctx, cur_seq_id); if (TISCI_STATUS_CODE_NO_ERROR != rev_status) { - ERROR("channel_%d tisci txn failed", tx_chan_id); + ERROR("channel_%d tisci txn failed\n", tx_chan_id); return rev_status; } @@ -245,7 +245,7 @@ int32_t tisci_rm_irq_release(tisci_ctx* ctx, uint8_t host_id, uint8_t tx_chan_id int32_t rev_status = _setup_hdr(ctx, &msg_header, sizeof(msg_header)); if (TISCI_STATUS_CODE_NO_ERROR != rev_status) { - ERROR("channel_%d msg hdr setup failed", tx_chan_id); + ERROR("channel_%d msg hdr setup failed\n", tx_chan_id); spin_unlock(&(ctx->seq_id_lock)); return rev_status; } @@ -268,7 +268,7 @@ int32_t tisci_rm_irq_release(tisci_ctx* ctx, uint8_t host_id, uint8_t tx_chan_id rev_status = _perform_txn(ctx, &tx_ctx, &rx_ctx, cur_seq_id); if (TISCI_STATUS_CODE_NO_ERROR != rev_status) { - ERROR("channel_%d tisci txn failed", tx_chan_id); + ERROR("channel_%d tisci txn failed\n", tx_chan_id); return rev_status; } diff --git a/src/platform/drivers/mailbox/k3_sec_proxy.c b/src/platform/drivers/mailbox/k3_sec_proxy.c index 4ffa0e9ae..858258425 100644 --- a/src/platform/drivers/mailbox/k3_sec_proxy.c +++ b/src/platform/drivers/mailbox/k3_sec_proxy.c @@ -14,9 +14,7 @@ * @return The 32-bit value read from the register. */ static inline uint32_t read_reg(paddr_t addr, paddr_t offset) -{ - return *((volatile uint32_t*)((paddr_t)(addr + offset))); -} +{ return *((volatile uint32_t*)((paddr_t)(addr + offset))); } /** * @brief Writes a 32-bit value to a memory-mapped register. @@ -26,9 +24,7 @@ static inline uint32_t read_reg(paddr_t addr, paddr_t offset) * @param value The 32-bit value to write. */ static inline void write_reg(paddr_t addr, paddr_t offset, uint32_t value) -{ - *((volatile uint32_t*)((paddr_t)(addr + offset))) = value; -} +{ *((volatile uint32_t*)((paddr_t)(addr + offset))) = value; } int32_t mbox_k3_sec_proxy_verify_thread(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t thread_id, uint8_t msg_drxn) @@ -41,7 +37,7 @@ int32_t mbox_k3_sec_proxy_verify_thread(mbox_k3_sec_proxy_desc* sec_proxy_desc, /* check for existing errors */ if (read_reg(thread_rt_base, MBOX_K3_SEC_PROXY_RT_THREAD_STATUS_OFFSET) & MBOX_K3_SEC_PROXY_RT_STATUS_ERROR_MASK) { - ERROR("secure_proxy_thread_%d corrupted", thread_id); + ERROR("secure_proxy_thread_%d corrupted\n", thread_id); return MBOX_K3_SEC_PROXY_STATUS_CODE_THREAD_CORRUPTED; } @@ -51,10 +47,10 @@ int32_t mbox_k3_sec_proxy_verify_thread(mbox_k3_sec_proxy_desc* sec_proxy_desc, MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_DIR_IDX != msg_drxn) { if (MBOX_K3_SEC_PROXY_MSG_DRXN_WRITE == msg_drxn) { - ERROR("secure_proxy_thread_%d cannot READ on WRITE thread", thread_id); + ERROR("secure_proxy_thread_%d cannot READ on WRITE thread\n", thread_id); return MBOX_K3_SEC_PROXY_STATUS_CODE_INCORRECT_DRXN; } else { - ERROR("secure_proxy_thread_%d cannot WRITE on READ thread", thread_id); + ERROR("secure_proxy_thread_%d cannot WRITE on READ thread\n", thread_id); return MBOX_K3_SEC_PROXY_STATUS_CODE_INCORRECT_DRXN; } } @@ -68,7 +64,6 @@ int32_t mbox_k3_sec_proxy_verify_thread(mbox_k3_sec_proxy_desc* sec_proxy_desc, MBOX_K3_SEC_PROXY_RT_STATUS_CUR_CNT_MASK)) { if ((sysreg_cntpct_el0_read() - tick_start) > (sec_proxy_desc->read_timeout_us * ticks_per_us)) { - ERROR("secure_proxy_thread_%d no entries in message queue", thread_id); return MBOX_K3_SEC_PROXY_STATUS_CODE_NO_DATA; } } @@ -108,7 +103,11 @@ int32_t mbox_k3_sec_proxy_read(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t t int32_t read_status = mbox_k3_sec_proxy_verify_thread(sec_proxy_desc, thread_id, MBOX_K3_SEC_PROXY_MSG_DRXN_READ); if (MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR != read_status) { - ERROR("secure_proxy_thread_%d thread verif failed", thread_id); + if (MBOX_K3_SEC_PROXY_STATUS_CODE_NO_DATA == read_status) { + ERROR("secure_proxy_thread_%d no entries in message queue\n", thread_id); + } else { + ERROR("secure_proxy_thread_%d thread verif failed\n", thread_id); + } return read_status; } @@ -143,7 +142,7 @@ int32_t mbox_k3_sec_proxy_read(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t t read_reg(data_reg, MBOX_K3_SEC_PROXY_DATA_END_OFFSET - MBOX_K3_SEC_PROXY_DATA_START_OFFSET); } - INFO("secure_proxy_thread_%d data READ success", thread_id); + INFO("secure_proxy_thread_%d data READ success\n", thread_id); return read_status; } @@ -184,13 +183,13 @@ int32_t mbox_k3_sec_proxy_write(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t int32_t write_status = mbox_k3_sec_proxy_verify_thread(sec_proxy_desc, thread_id, MBOX_K3_SEC_PROXY_MSG_DRXN_WRITE); if (MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR != write_status) { - ERROR("secure_proxy_thread_%d thread verif failed", thread_id); + ERROR("secure_proxy_thread_%d thread verif failed\n", thread_id); return write_status; } /* msg len check */ if (len > sec_proxy_desc->thread_inst.max_msg_size) { - ERROR("secure_proxy_thread_%d msg len exceeds limit", thread_id); + ERROR("secure_proxy_thread_%d msg len exceeds limit\n", thread_id); return MBOX_K3_SEC_PROXY_STATUS_CODE_INVALID_MSG_LEN; } @@ -228,7 +227,7 @@ int32_t mbox_k3_sec_proxy_write(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t write_reg(data_reg, word_iterator++ * sizeof(uint32_t), 0U); } - INFO("secure_proxy_thread_%d data WRITE success", thread_id); + INFO("secure_proxy_thread_%d data WRITE success\n", thread_id); return write_status; } @@ -238,7 +237,7 @@ int32_t mbox_k3_sec_proxy_clear(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t int32_t clear_status = mbox_k3_sec_proxy_verify_thread(sec_proxy_desc, thread_id, MBOX_K3_SEC_PROXY_MSG_DRXN_READ); if (MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR != clear_status) { - ERROR("secure_proxy_thread_%d thread verif failed", thread_id); + ERROR("secure_proxy_thread_%d thread verif failed\n", thread_id); return clear_status; } @@ -252,11 +251,11 @@ int32_t mbox_k3_sec_proxy_clear(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t (read_reg(thread_rt_base, MBOX_K3_SEC_PROXY_RT_THREAD_STATUS_OFFSET) & MBOX_K3_SEC_PROXY_RT_STATUS_CUR_CNT_MASK)) { if (0 == (try_count--)) { - ERROR("secure_proxy_thread_%d mailbox clear failed", thread_id); + ERROR("secure_proxy_thread_%d mailbox clear failed\n", thread_id); return MBOX_K3_SEC_PROXY_STATUS_CODE_THREAD_CLEAR_FAILED; } - WARNING("secure_proxy_thread_%d mailbox clear in progress", thread_id); + WARNING("secure_proxy_thread_%d mailbox clear in progress\n", thread_id); read_reg(data_reg, MBOX_K3_SEC_PROXY_DATA_END_OFFSET); } @@ -265,28 +264,14 @@ int32_t mbox_k3_sec_proxy_clear(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t int32_t mbox_k3_sec_proxy_probe(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t thread_id) { - paddr_t thread_scfg_base = - sec_proxy_desc->thread_inst.scfg_base + MBOX_K3_SEC_PROXY_THREAD_OFFSET(thread_id); - uint32_t config = read_reg(thread_scfg_base, MBOX_K3_SEC_PROXY_SCFG_THREAD_CTRL_OFFSET); - - uint8_t hw_host = (config >> 8) & 0xFF; - uint8_t expected_host = sec_proxy_desc->sec_proxy_thread_desc[thread_id].host_id; - - /* [step-1] verify thread access/host ownership */ - if (hw_host != expected_host) { - ERROR("sec_proxy_thread_%d probe failed (hw_host=%d, expected=%d)", thread_id, hw_host, - expected_host); - return MBOX_K3_SEC_PROXY_STATUS_CODE_THREAD_CORRUPTED; - } - - /* [step-2] verify if thread is clean */ + /* verify if thread is clean */ int32_t probe_status = mbox_k3_sec_proxy_verify_thread(sec_proxy_desc, thread_id, sec_proxy_desc->sec_proxy_thread_desc[thread_id].msg_drxn); if (MBOX_K3_SEC_PROXY_MSG_DRXN_READ == sec_proxy_desc->sec_proxy_thread_desc[thread_id].msg_drxn && MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR == probe_status) { - ERROR("secure_proxy_thread_%d probe failed (message queue not clean)", thread_id); + ERROR("secure_proxy_thread_%d probe failed (message queue not clean)\n", thread_id); return MBOX_K3_SEC_PROXY_STATUS_CODE_DIRTY_HANDOFF; } @@ -297,11 +282,11 @@ int32_t mbox_k3_sec_proxy_probe(mbox_k3_sec_proxy_desc* sec_proxy_desc, uint8_t } if (MBOX_K3_SEC_PROXY_STATUS_CODE_NO_ERROR != probe_status) { - INFO("sec_proxy_thread_%d probe failed (error_id=%d)", thread_id, probe_status); + INFO("sec_proxy_thread_%d probe failed (error_id=%d)\n", thread_id, probe_status); return probe_status; } - INFO("sec_proxy_thread_%d probe success", thread_id); + INFO("sec_proxy_thread_%d probe success\n", thread_id); return probe_status; }