forked from zephyrproject-rtos/zephyr
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
drivers: mbox: Add support for TI OMAP mailbox
TI OMAP mailbox is the inter-processor mailbox IP found in TI K3 devices (AM62X, AM64X, J721E .etc). The mailbox hardware uses a queued mailbox interrupt mechanism that provides a communication channel between processors through a set of registers and their associated interrupt signals by sending and receiving messages. The interrupt/bank associated with each processor entity is found through the usr_id property from device tree. Signed-off-by: Vaishnav Achath <[email protected]>
- Loading branch information
1 parent
a211999
commit fca38ad
Showing
5 changed files
with
265 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Copyright 2024 Texas Instruments Incorporated. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
config MBOX_TI_OMAP_MAILBOX | ||
bool "TI OMAP Mailbox driver" | ||
default y | ||
depends on DT_HAS_TI_OMAP_MAILBOX_ENABLED | ||
help | ||
Driver for TI OMAP Mailbox. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
/* | ||
* Copyright (c) 2024 Texas Instruments Incorporated. | ||
* | ||
* TI OMAP Mailbox driver for Zephyr's MBOX model. | ||
*/ | ||
|
||
#include <zephyr/devicetree.h> | ||
#include <zephyr/drivers/mbox.h> | ||
#include <zephyr/irq.h> | ||
#include <zephyr/spinlock.h> | ||
#define LOG_LEVEL CONFIG_MBOX_LOG_LEVEL | ||
#include <zephyr/logging/log.h> | ||
LOG_MODULE_REGISTER(ti_omap_mailbox); | ||
|
||
#define DT_DRV_COMPAT ti_omap_mailbox | ||
|
||
#define MAILBOX_IRQ_NEWMSG(m) (1 << (2 * (m))) | ||
#define MAILBOX_IRQ_NOTFULL(m) (1 << (2 * (m) + 1)) | ||
#define OMAP_MAILBOX_NUM_MSGS 16 | ||
#define MAILBOX_MAX_CHANNELS 16 | ||
#define OMAP_MAILBOX_NUM_USERS 4 | ||
#define MAILBOX_MBOX_SIZE sizeof(uint32_t) | ||
|
||
#define DEV_CFG(_dev) ((const struct omap_mailbox_config *)(_dev)->config) | ||
#define DEV_DATA(_dev) ((struct omap_mailbox_data *)(_dev)->data) | ||
#define DEV_REG_BASE(dev) ((struct omap_mailbox_regs *)DEVICE_MMIO_NAMED_GET(dev, reg_base)) | ||
|
||
struct omap_mailbox_data { | ||
DEVICE_MMIO_NAMED_RAM(reg_base); | ||
mbox_callback_t cb[MAILBOX_MAX_CHANNELS]; | ||
void *user_data[MAILBOX_MAX_CHANNELS]; | ||
bool channel_enable[MAILBOX_MAX_CHANNELS]; | ||
uint32_t received_data; | ||
struct k_spinlock lock; | ||
}; | ||
|
||
struct omap_mailbox_config { | ||
DEVICE_MMIO_NAMED_ROM(reg_base); | ||
uint32_t irq; | ||
uint32_t usr_id; | ||
}; | ||
|
||
struct omap_mailbox_irq_regs { | ||
uint32_t status_raw; | ||
uint32_t status_clear; | ||
uint32_t enable_set; | ||
uint32_t enable_clear; | ||
}; | ||
|
||
struct omap_mailbox_regs { | ||
uint32_t revision; | ||
uint32_t __pad0[3]; | ||
uint32_t sysconfig; | ||
uint32_t __pad1[11]; | ||
uint32_t message[OMAP_MAILBOX_NUM_MSGS]; | ||
uint32_t fifo_status[OMAP_MAILBOX_NUM_MSGS]; | ||
uint32_t msg_status[OMAP_MAILBOX_NUM_MSGS]; | ||
struct omap_mailbox_irq_regs irq_regs[OMAP_MAILBOX_NUM_USERS]; | ||
}; | ||
|
||
static void omap_mailbox_isr(const struct device *dev) | ||
{ | ||
volatile struct omap_mailbox_regs *regs = DEV_REG_BASE(dev); | ||
const struct omap_mailbox_config *cfg = DEV_CFG(dev); | ||
struct omap_mailbox_data *data = DEV_DATA(dev); | ||
|
||
uint32_t irq_enabled = regs->irq_regs[cfg->usr_id].enable_set; | ||
uint32_t flags = regs->irq_regs[cfg->usr_id].status_clear; | ||
|
||
regs->irq_regs[cfg->usr_id].enable_set = 0; | ||
|
||
for (int i_channel = 0; i_channel < MAILBOX_MAX_CHANNELS; i_channel++) { | ||
if (!data->channel_enable[i_channel]) { | ||
continue; | ||
} | ||
|
||
if ((flags & MAILBOX_IRQ_NEWMSG(i_channel))) { | ||
data->received_data = regs->message[i_channel]; | ||
struct mbox_msg msg = { | ||
.data = (const void *)&data->received_data, | ||
.size = MAILBOX_MBOX_SIZE, | ||
}; | ||
|
||
if (data->cb[i_channel]) { | ||
data->cb[i_channel](dev, i_channel, data->user_data[i_channel], | ||
&msg); | ||
} | ||
} | ||
} | ||
|
||
regs->irq_regs[cfg->usr_id].status_clear = flags; | ||
regs->irq_regs[cfg->usr_id].enable_set = irq_enabled; | ||
} | ||
|
||
static int omap_mailbox_send(const struct device *dev, uint32_t channel, const struct mbox_msg *msg) | ||
{ | ||
uint32_t __aligned(4) data32; | ||
|
||
volatile struct omap_mailbox_regs *regs = DEV_REG_BASE(dev); | ||
struct omap_mailbox_data *data = DEV_DATA(dev); | ||
k_spinlock_key_t key; | ||
|
||
if (channel >= MAILBOX_MAX_CHANNELS) { | ||
return -EINVAL; | ||
} | ||
|
||
if (regs->fifo_status[channel]) { | ||
return -EBUSY; | ||
} | ||
|
||
key = k_spin_lock(&data->lock); | ||
if (!msg) { | ||
regs->message[channel] = 0; | ||
k_spin_unlock(&data->lock, key); | ||
return 0; | ||
} | ||
|
||
if (msg->size > MAILBOX_MBOX_SIZE) { | ||
k_spin_unlock(&data->lock, key); | ||
return -EMSGSIZE; | ||
} | ||
|
||
memcpy(&data32, msg->data, msg->size); | ||
regs->message[channel] = data32; | ||
k_spin_unlock(&data->lock, key); | ||
|
||
return 0; | ||
} | ||
|
||
static int omap_mailbox_register_callback(const struct device *dev, uint32_t channel, | ||
mbox_callback_t cb, void *user_data) | ||
{ | ||
struct omap_mailbox_data *data = DEV_DATA(dev); | ||
k_spinlock_key_t key; | ||
|
||
if (channel >= MAILBOX_MAX_CHANNELS) { | ||
return -EINVAL; | ||
} | ||
|
||
key = k_spin_lock(&data->lock); | ||
data->cb[channel] = cb; | ||
data->user_data[channel] = user_data; | ||
k_spin_unlock(&data->lock, key); | ||
|
||
return 0; | ||
} | ||
|
||
static int omap_mailbox_mtu_get(const struct device *dev) | ||
{ | ||
ARG_UNUSED(dev); | ||
|
||
return MAILBOX_MBOX_SIZE; | ||
} | ||
|
||
static uint32_t omap_mailbox_max_channels_get(const struct device *dev) | ||
{ | ||
ARG_UNUSED(dev); | ||
|
||
return MAILBOX_MAX_CHANNELS; | ||
} | ||
|
||
static int omap_mailbox_set_enabled(const struct device *dev, uint32_t channel, bool enable) | ||
{ | ||
const struct omap_mailbox_config *cfg = DEV_CFG(dev); | ||
struct omap_mailbox_data *data = DEV_DATA(dev); | ||
volatile struct omap_mailbox_regs *regs; | ||
k_spinlock_key_t key; | ||
uint32_t irqstatus; | ||
|
||
if (channel >= MAILBOX_MAX_CHANNELS) { | ||
return -EINVAL; | ||
} | ||
|
||
if (enable && data->channel_enable[channel]) { | ||
return -EALREADY; | ||
} | ||
|
||
key = k_spin_lock(&data->lock); | ||
regs = DEV_REG_BASE(dev); | ||
irqstatus = regs->irq_regs[cfg->usr_id].enable_set; | ||
|
||
if (enable) { | ||
irqstatus |= MAILBOX_IRQ_NEWMSG(channel); | ||
} else { | ||
irqstatus &= ~MAILBOX_IRQ_NEWMSG(channel); | ||
} | ||
|
||
regs->irq_regs[cfg->usr_id].enable_set = irqstatus; | ||
data->channel_enable[channel] = enable; | ||
|
||
if (enable) { | ||
irq_enable(cfg->irq); | ||
} else { | ||
irq_disable(cfg->irq); | ||
} | ||
|
||
k_spin_unlock(&data->lock, key); | ||
|
||
return 0; | ||
} | ||
|
||
static const struct mbox_driver_api omap_mailbox_driver_api = { | ||
.send = omap_mailbox_send, | ||
.register_callback = omap_mailbox_register_callback, | ||
.mtu_get = omap_mailbox_mtu_get, | ||
.max_channels_get = omap_mailbox_max_channels_get, | ||
.set_enabled = omap_mailbox_set_enabled, | ||
}; | ||
|
||
#define MAILBOX_INSTANCE_DEFINE(idx) \ | ||
static struct omap_mailbox_data omap_mailbox_##idx##_data; \ | ||
const static struct omap_mailbox_config omap_mailbox_##idx##_config = { \ | ||
DEVICE_MMIO_NAMED_ROM_INIT(reg_base, DT_DRV_INST(idx)), \ | ||
.irq = DT_INST_IRQN(idx), \ | ||
.usr_id = DT_INST_PROP(idx, usr_id), \ | ||
}; \ | ||
static int omap_mailbox_##idx##_init(const struct device *dev) \ | ||
{ \ | ||
DEVICE_MMIO_NAMED_MAP(dev, reg_base, K_MEM_CACHE_NONE); \ | ||
IRQ_CONNECT(DT_INST_IRQN(idx), DT_INST_IRQ(idx, priority), omap_mailbox_isr, \ | ||
DEVICE_DT_INST_GET(idx), \ | ||
COND_CODE_1(DT_INST_IRQ_HAS_CELL(idx, flags), \ | ||
(DT_INST_IRQ(idx, flags)), (0))); \ | ||
return 0; \ | ||
} \ | ||
DEVICE_DT_INST_DEFINE(idx, omap_mailbox_##idx##_init, NULL, &omap_mailbox_##idx##_data, \ | ||
&omap_mailbox_##idx##_config, POST_KERNEL, \ | ||
CONFIG_MBOX_INIT_PRIORITY, &omap_mailbox_driver_api) | ||
|
||
DT_INST_FOREACH_STATUS_OKAY(MAILBOX_INSTANCE_DEFINE) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Copyright 2024 Texas Instruments Incorporated. | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
description: TI OMAP MAILBOX | ||
|
||
compatible: "ti,omap-mailbox" | ||
|
||
include: [base.yaml, mailbox-controller.yaml] | ||
|
||
properties: | ||
reg: | ||
required: true | ||
|
||
interrupts: | ||
required: true | ||
|
||
usr-id: | ||
type: int | ||
required: true | ||
description: User ID for processor | ||
|
||
mbox-cells: | ||
- channel |