-
Notifications
You must be signed in to change notification settings - Fork 9.1k
PRE_KERNEL polling support for TISCI and Secure Proxy #105343
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
579e1c0
1907eeb
dd8e9dc
972f3f5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,9 +4,11 @@ | |
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| #include <zephyr/drivers/mbox/mbox_ti_secproxy.h> | ||
| #include <stdint.h> | ||
| #include <stdio.h> | ||
| #define DT_DRV_COMPAT ti_k2g_sci | ||
| #define DT_DRV_COMPAT ti_k2g_sci | ||
| #define DT_SECPROXY_COMPAT ti_secure_proxy | ||
| #include <zephyr/drivers/mbox.h> | ||
| #include <zephyr/device.h> | ||
| #include "tisci.h" | ||
|
|
@@ -32,6 +34,9 @@ struct tisci_config { | |
| int max_msg_size; | ||
| int max_rx_timeout_ms; | ||
| bool is_secure; | ||
| int (*send_pre_kernel)(const struct mbox_dt_spec *rx_spec, | ||
| const struct mbox_dt_spec *tx_spec, | ||
| const struct mbox_msg *tx_msg); | ||
| }; | ||
|
|
||
| /** | ||
|
|
@@ -66,7 +71,9 @@ static struct tisci_xfer *tisci_setup_one_xfer(const struct device *dev, uint16_ | |
| { | ||
| struct tisci_data *data = dev->data; | ||
|
|
||
| k_sem_take(&data->data_sem, K_FOREVER); | ||
| if (!k_is_pre_kernel()) { | ||
| k_sem_take(&data->data_sem, K_FOREVER); | ||
| } | ||
|
|
||
| const struct tisci_config *config = dev->config; | ||
| struct tisci_xfer *xfer = &data->xfer; | ||
|
|
@@ -75,7 +82,9 @@ static struct tisci_xfer *tisci_setup_one_xfer(const struct device *dev, uint16_ | |
| if (rx_message_size > config->max_msg_size || tx_message_size > config->max_msg_size || | ||
| (rx_message_size > 0 && rx_message_size < sizeof(*hdr)) || | ||
| tx_message_size < sizeof(*hdr)) { | ||
| k_sem_give(&data->data_sem); | ||
| if (!k_is_pre_kernel()) { | ||
| k_sem_give(&data->data_sem); | ||
| } | ||
| return NULL; | ||
| } | ||
|
|
||
|
|
@@ -104,7 +113,9 @@ static void callback(const struct device *dev, mbox_channel_id_t channel_id, voi | |
| { | ||
| struct rx_msg *msg = user_data; | ||
|
|
||
| k_sem_give(msg->response_ready_sem); | ||
| if (!k_is_pre_kernel()) { | ||
| k_sem_give(msg->response_ready_sem); | ||
| } | ||
| } | ||
|
|
||
| static bool tisci_is_response_ack(void *r) | ||
|
|
@@ -123,24 +134,27 @@ static int tisci_get_response(const struct device *dev, struct tisci_xfer *xfer) | |
| struct tisci_data *data = dev->data; | ||
| const struct tisci_config *config = dev->config; | ||
| struct tisci_msg_hdr *hdr; | ||
| int ret = 0; | ||
|
|
||
| if (!xfer->rx_message.buf) { | ||
| LOG_ERR("No response buffer provided"); | ||
| k_sem_give(&data->data_sem); | ||
| return -EINVAL; | ||
| ret = -EINVAL; | ||
| goto release_sem; | ||
| } | ||
|
|
||
| if (k_sem_take(data->rx_message.response_ready_sem, K_MSEC(config->max_rx_timeout_ms)) != | ||
| 0) { | ||
| LOG_ERR("Timeout waiting for response"); | ||
| k_sem_give(&data->data_sem); | ||
| return -ETIMEDOUT; | ||
| if (!k_is_pre_kernel()) { | ||
| if (k_sem_take(data->rx_message.response_ready_sem, | ||
| K_MSEC(config->max_rx_timeout_ms)) != 0) { | ||
| LOG_ERR("Timeout waiting for response"); | ||
| ret = -ETIMEDOUT; | ||
| goto release_sem; | ||
| } | ||
| } | ||
|
|
||
| if (xfer->rx_message.size > config->max_msg_size) { | ||
| LOG_ERR("rx_message.size [ %d ] > max_msg_size\n", xfer->rx_message.size); | ||
| k_sem_give(&data->data_sem); | ||
| return -EINVAL; | ||
| ret = -EINVAL; | ||
| goto release_sem; | ||
| } | ||
|
|
||
| if (config->is_secure) { | ||
|
|
@@ -151,8 +165,8 @@ static int tisci_get_response(const struct device *dev, struct tisci_xfer *xfer) | |
| if (data->rx_message.size < xfer->rx_message.size) { | ||
| LOG_ERR("rx_message.size [ %zu ] < xfer->rx_message.size [ %zu ]\n", | ||
| data->rx_message.size, xfer->rx_message.size); | ||
| k_sem_give(&data->data_sem); | ||
| return -EINVAL; | ||
| ret = -EINVAL; | ||
| goto release_sem; | ||
| } | ||
|
|
||
| if (config->is_secure) { | ||
|
|
@@ -169,12 +183,15 @@ static int tisci_get_response(const struct device *dev, struct tisci_xfer *xfer) | |
| /* Sanity check for message response */ | ||
| if (hdr->seq != data->seq) { | ||
| LOG_ERR("HDR seq != data seq [%d != %d]\n", hdr->seq, data->seq); | ||
| k_sem_give(&data->data_sem); | ||
| return -EINVAL; | ||
| ret = -EINVAL; | ||
| goto release_sem; | ||
| } | ||
|
|
||
| k_sem_give(&data->data_sem); | ||
| return 0; | ||
| release_sem: | ||
| if (!k_is_pre_kernel()) { | ||
| k_sem_give(&data->data_sem); | ||
| } | ||
| return ret; | ||
| } | ||
|
|
||
| static int tisci_do_xfer(const struct device *dev, struct tisci_xfer *xfer) | ||
|
|
@@ -199,8 +216,8 @@ static int tisci_do_xfer(const struct device *dev, struct tisci_xfer *xfer) | |
| if (msg->size + sizeof(struct tisci_secure_msg_hdr) > MAILBOX_MBOX_SIZE) { | ||
| LOG_ERR("Message too large for secure mailbox (%zu + %zu > %d)\n", | ||
| msg->size, sizeof(struct tisci_secure_msg_hdr), MAILBOX_MBOX_SIZE); | ||
| k_sem_give(&data->data_sem); | ||
| return -EMSGSIZE; | ||
| ret = -EMSGSIZE; | ||
| goto release_sem; | ||
| } | ||
|
|
||
| /* Prepare secure header */ | ||
|
|
@@ -217,31 +234,45 @@ static int tisci_do_xfer(const struct device *dev, struct tisci_xfer *xfer) | |
| msg = &secure_msg; | ||
| } | ||
|
|
||
| ret = mbox_send_dt(&config->mbox_tx, msg); | ||
| if (k_is_pre_kernel()) { | ||
| if (config->send_pre_kernel != NULL) { | ||
| ret = config->send_pre_kernel(&config->mbox_rx, &config->mbox_tx, msg); | ||
| } else { | ||
| LOG_ERR("Cannot transceive messages during pre kernel"); | ||
| return -ENOTSUP; | ||
| } | ||
| } else { | ||
| ret = mbox_send_dt(&config->mbox_tx, msg); | ||
| } | ||
|
|
||
| if (ret < 0) { | ||
| LOG_ERR("Could not send on %s path\n", | ||
| config->is_secure ? "secure" : "non-secure"); | ||
| k_sem_give(&data->data_sem); | ||
| return ret; | ||
| LOG_ERR("Could not send on %s path\n", config->is_secure ? "secure" : "non-secure"); | ||
| goto release_sem; | ||
| } | ||
|
|
||
| /* Get response if requested */ | ||
| if (xfer->rx_message.size) { | ||
| ret = tisci_get_response(dev, xfer); | ||
| if (ret) { | ||
| return ret; | ||
| goto release_sem; | ||
| } | ||
| if (!tisci_is_response_ack(xfer->rx_message.buf)) { | ||
| LOG_ERR("TISCI Response in NACK\n"); | ||
| k_sem_give(&data->data_sem); | ||
| return -ENODEV; | ||
| ret = -ENODEV; | ||
| goto release_sem; | ||
| } | ||
| } else { | ||
| /* No response requested, release semaphore */ | ||
| k_sem_give(&data->data_sem); | ||
| goto release_sem; | ||
| } | ||
|
|
||
| return 0; | ||
|
|
||
| release_sem: | ||
| if (!k_is_pre_kernel()) { | ||
| k_sem_give(&data->data_sem); | ||
| } | ||
| return ret; | ||
| } | ||
|
|
||
| /* Clock Management Functions */ | ||
|
|
@@ -1632,6 +1663,9 @@ static int tisci_init(const struct device *dev) | |
| return 0; | ||
| } | ||
|
|
||
| #define TISCI_USES_SECPROXY(_n) \ | ||
| DT_NODE_HAS_COMPAT(DT_INST_PHANDLE(_n, mboxes), DT_SECPROXY_COMPAT) | ||
|
|
||
| /* Device Tree Instantiation */ | ||
| #define TISCI_DEFINE(_n) \ | ||
| static uint8_t rx_message_buf_##_n[MAILBOX_MBOX_SIZE] = {0}; \ | ||
|
|
@@ -1653,6 +1687,9 @@ static int tisci_init(const struct device *dev) | |
| .max_msg_size = MAILBOX_MBOX_SIZE, \ | ||
| .max_rx_timeout_ms = 10000, \ | ||
| .is_secure = DT_INST_PROP_OR(_n, ti_is_secure, false), \ | ||
| .send_pre_kernel = COND_CODE_1(TISCI_USES_SECPROXY(_n), \ | ||
| (secproxy_mailbox_send_then_poll_rx_dt), \ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even with the check for which transport we are using, I do not like this strong coupling between layers. Assume adding a polling API to the mailbox framework would be the better option we can work on. |
||
| (NULL)), \ | ||
| }; \ | ||
| DEVICE_DT_INST_DEFINE(_n, tisci_init, NULL, &tisci_data_##_n, &tisci_config_##_n, \ | ||
| PRE_KERNEL_1, CONFIG_TISCI_INIT_PRIORITY, NULL); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -113,24 +113,20 @@ static inline int secproxy_verify_thread(struct secproxy_thread *spt, uint8_t di | |
| return 0; | ||
| } | ||
|
|
||
| static void secproxy_mailbox_isr(const struct device *dev, uint32_t channel) | ||
| static int secproxy_mailbox_receive(const struct device *dev, uint32_t channel) | ||
| { | ||
| struct secproxy_mailbox_data *data = DEV_DATA(dev); | ||
| struct secproxy_thread spt; | ||
| uint32_t data_word; | ||
| mem_addr_t data_reg; | ||
|
|
||
| if (!data->channel_enable[channel]) { | ||
| return; | ||
| } | ||
|
|
||
| spt.target_data = SEC_PROXY_THREAD(DEV_TDATA(dev), channel); | ||
| spt.rt = SEC_PROXY_THREAD(DEV_RT(dev), channel); | ||
| spt.scfg = SEC_PROXY_THREAD(DEV_SCFG(dev), channel); | ||
|
|
||
| if (secproxy_verify_thread(&spt, THREAD_IS_RX)) { | ||
| /* Silent failure */ | ||
| return; | ||
| return -EIO; | ||
| } | ||
|
|
||
| data_reg = spt.target_data + SEC_PROXY_DATA_START_OFFS; | ||
|
|
@@ -141,12 +137,12 @@ static void secproxy_mailbox_isr(const struct device *dev, uint32_t channel) | |
|
|
||
| if (!rx_data || !rx_data->buf) { | ||
| LOG_ERR("No buffer provided for channel %d", channel); | ||
| return; | ||
| return -EINVAL; | ||
| } | ||
|
|
||
| if (rx_data->size < MAILBOX_MBOX_SIZE) { | ||
| LOG_ERR("Buffer too small for channel %d", channel); | ||
| return; | ||
| return -ENOBUFS; | ||
| } | ||
|
|
||
| uint8_t *buf = (uint8_t *)rx_data->buf; | ||
|
|
@@ -182,6 +178,19 @@ static void secproxy_mailbox_isr(const struct device *dev, uint32_t channel) | |
| if (data->cb[channel]) { | ||
| data->cb[channel](dev, channel, data->user_data[channel], NULL); | ||
| } | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| static void secproxy_mailbox_isr(const struct device *dev, uint32_t channel) | ||
| { | ||
| struct secproxy_mailbox_data *data = DEV_DATA(dev); | ||
|
|
||
| if (!data->channel_enable[channel]) { | ||
| return; | ||
| } | ||
|
|
||
| (void)secproxy_mailbox_receive(dev, channel); | ||
| } | ||
|
|
||
| static int secproxy_mailbox_send(const struct device *dev, uint32_t channel, | ||
|
|
@@ -352,6 +361,43 @@ static DEVICE_API(mbox, secproxy_mailbox_driver_api) = { | |
| .set_enabled = secproxy_mailbox_set_enabled, | ||
| }; | ||
|
|
||
| int secproxy_mailbox_send_then_poll_rx(const struct device *dev, uint32_t rx_channel, | ||
| uint32_t tx_channel, const struct mbox_msg *tx_msg) | ||
| { | ||
| const struct secproxy_mailbox_config *cfg = DEV_CFG(dev); | ||
| mem_addr_t rx_rt = SEC_PROXY_THREAD(DEV_RT(dev), rx_channel); | ||
| bool irq_was_enabled = irq_is_enabled(cfg->interrupts[rx_channel]); | ||
| int rv; | ||
|
|
||
| if (irq_was_enabled) { | ||
| irq_disable(cfg->interrupts[rx_channel]); | ||
| } | ||
|
|
||
| rv = secproxy_mailbox_send(dev, tx_channel, tx_msg); | ||
| if (rv != 0) { | ||
| LOG_ERR("failed to send message on channel %u", tx_channel); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the irq will keep disabled status if send message fial, it can be restore in a common code if send or read message fail
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. true, thanks for pointing that out!
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added a mechanism to restore the irq status |
||
| goto exit; | ||
| } | ||
|
|
||
| /* blocking call */ | ||
| while (!(sys_read32(rx_rt + RT_THREAD_STATUS) & RT_THREAD_STATUS_CUR_CNT_MASK)) { | ||
| } | ||
|
|
||
| rv = secproxy_mailbox_receive(dev, rx_channel); | ||
| if (rv != 0) { | ||
| LOG_ERR("failed to receive message on channel %u", tx_channel); | ||
| goto exit; | ||
| } | ||
|
|
||
| rv = 0; | ||
|
|
||
| exit: | ||
| if (irq_was_enabled) { | ||
| irq_enable(cfg->interrupts[rx_channel]); | ||
| } | ||
| return rv; | ||
| } | ||
|
|
||
| #define SECPROXY_THREAD_ISR(i, idx) \ | ||
| COND_CODE_1(DT_INST_IRQ_HAS_NAME(idx, DT_CAT(rx_, i)), \ | ||
| ( \ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need this new compatible?
ti_k2g_sci(MessageManager) will have the same constraints here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am using this to verify the transport layer for TISCI during PRE_KERNEL. If it is secure proxy, then we poll, otherwise we return failure. The easy way out of this would be to always assume that we will be using secure proxy as the mailbox for TISCI.