Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions boards/ti/am243x_evm/am243x_evm_am2434_r5f0_0_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,15 @@ CONFIG_UART_CONSOLE=y

# Enable MPU
CONFIG_ARM_MPU=y

# Enable TISCI
CONFIG_TISCI=y

# Enable Power Management
CONFIG_POWER_DOMAIN=y
CONFIG_PM=y
CONFIG_PM_DEVICE=y
CONFIG_PM_DEVICE_RUNTIME=y

# Enable Clock Management
CONFIG_CLOCK_CONTROL=y
97 changes: 67 additions & 30 deletions drivers/firmware/tisci/tisci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Copy Markdown
Contributor

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.

Copy link
Copy Markdown
Contributor Author

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.

#include <zephyr/drivers/mbox.h>
#include <zephyr/device.h>
#include "tisci.h"
Expand All @@ -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);
};

/**
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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)
Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -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)
Expand All @@ -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 */
Expand All @@ -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 */
Expand Down Expand Up @@ -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}; \
Expand All @@ -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), \
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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);
Expand Down
62 changes: 54 additions & 8 deletions drivers/mbox/mbox_ti_secproxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true, thanks for pointing that out!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The 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)), \
( \
Expand Down
Loading
Loading