drivers: mbox: add initial driver for nRF VEVIF event

Add a mailbox driver for VEVIF events (VPR irq).
The driver can be built in either 'rx' or 'tx' configuration.
The VPR sends the event, so it uses the 'tx' configuration,
while the master core uses the 'rx' configuration of the driver
to receive the VPR events.

Signed-off-by: Jakub Zymelka <jakub.zymelka@nordicsemi.no>
This commit is contained in:
Jakub Zymelka 2024-05-20 13:21:30 +02:00 committed by Anas Nashif
parent 25fa41c209
commit bace4a102d
7 changed files with 329 additions and 0 deletions

View file

@ -12,6 +12,8 @@ zephyr_library_sources_ifdef(CONFIG_MBOX_NXP_MAILBOX mbox_nxp_mailbox.c)
zephyr_library_sources_ifdef(CONFIG_MBOX_ANDES_PLIC_SW mbox_andes_plic_sw.c)
zephyr_library_sources_ifdef(CONFIG_MBOX_NRF_VEVIF_LOCAL mbox_nrf_vevif_local.c)
zephyr_library_sources_ifdef(CONFIG_MBOX_NRF_VEVIF_REMOTE mbox_nrf_vevif_remote.c)
zephyr_library_sources_ifdef(CONFIG_MBOX_NRF_VEVIF_EVENT_RX mbox_nrf_vevif_event_rx.c)
zephyr_library_sources_ifdef(CONFIG_MBOX_NRF_VEVIF_EVENT_TX mbox_nrf_vevif_event_tx.c)
zephyr_library_sources_ifdef(CONFIG_MBOX_NRF_BELLBOARD_LOCAL mbox_nrf_bellboard_local.c)
zephyr_library_sources_ifdef(CONFIG_MBOX_NRF_BELLBOARD_REMOTE mbox_nrf_bellboard_remote.c)
zephyr_library_sources_ifdef(CONFIG_MBOX_STM32_HSEM mbox_stm32_hsem.c)

View file

@ -18,6 +18,7 @@ source "drivers/mbox/Kconfig.nxp_imx"
source "drivers/mbox/Kconfig.nxp_mailbox"
source "drivers/mbox/Kconfig.andes"
source "drivers/mbox/Kconfig.nrf_vevif"
source "drivers/mbox/Kconfig.nrf_vevif_event"
source "drivers/mbox/Kconfig.nrf_bellboard"
source "drivers/mbox/Kconfig.stm32_hsem"

View file

@ -0,0 +1,16 @@
# Copyright (c) 2024 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
config MBOX_NRF_VEVIF_EVENT_RX
bool "nRF VEVIF event RX driver"
depends on DT_HAS_NORDIC_NRF_VEVIF_EVENT_RX_ENABLED
default y
help
Mailbox driver for receiving events triggered by VPR
config MBOX_NRF_VEVIF_EVENT_TX
bool "nRF VEVIF event TX driver"
depends on DT_HAS_NORDIC_NRF_VEVIF_EVENT_TX_ENABLED
default y
help
Mailbox driver for transmitting events from VPR to a remote core

View file

@ -0,0 +1,152 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT nordic_nrf_vevif_event_rx
#include <zephyr/devicetree.h>
#include <zephyr/drivers/mbox.h>
#include <haly/nrfy_vpr.h>
#if defined(CONFIG_SOC_NRF54L15_ENGA_CPUAPP)
#define EVENTS_IDX_MIN 11U
#define EVENTS_IDX_MAX 17U
#else
#define EVENTS_IDX_MIN NRF_VPR_EVENTS_TRIGGERED_MIN
#define EVENTS_IDX_MAX NRF_VPR_EVENTS_TRIGGERED_MAX
#endif
/* callbacks */
struct mbox_vevif_event_rx_cbs {
mbox_callback_t cb[EVENTS_IDX_MAX - EVENTS_IDX_MIN + 1U];
void *user_data[EVENTS_IDX_MAX - EVENTS_IDX_MIN + 1U];
uint32_t enabled_mask;
};
struct mbox_vevif_event_rx_conf {
NRF_VPR_Type *vpr;
uint32_t events_mask;
uint8_t events;
void (*irq_connect)(void);
};
static void vevif_event_rx_isr(const void *device)
{
const struct device *dev = (struct device *)device;
const struct mbox_vevif_event_rx_conf *config = dev->config;
struct mbox_vevif_event_rx_cbs *cbs = dev->data;
for (uint8_t id = EVENTS_IDX_MIN; id < EVENTS_IDX_MAX + 1U; id++) {
nrf_vpr_event_t event = nrfy_vpr_triggered_event_get(id);
if (nrfy_vpr_event_check(config->vpr, event)) {
nrfy_vpr_event_clear(config->vpr, event);
uint8_t idx = id - EVENTS_IDX_MIN;
if ((cbs->enabled_mask & BIT(id)) && (cbs->cb[idx] != NULL)) {
cbs->cb[idx](dev, id, cbs->user_data[idx], NULL);
}
}
}
}
static inline bool vevif_event_rx_event_is_valid(uint32_t events_mask, uint32_t id)
{
return ((id <= EVENTS_IDX_MAX) && ((events_mask & BIT(id)) != 0U));
}
static uint32_t vevif_event_rx_max_channels_get(const struct device *dev)
{
const struct mbox_vevif_event_rx_conf *config = dev->config;
return config->events;
}
static int vevif_event_rx_register_callback(const struct device *dev, uint32_t id,
mbox_callback_t cb, void *user_data)
{
const struct mbox_vevif_event_rx_conf *config = dev->config;
struct mbox_vevif_event_rx_cbs *cbs = dev->data;
uint8_t idx = id - EVENTS_IDX_MIN;
if (!vevif_event_rx_event_is_valid(config->events_mask, id)) {
return -EINVAL;
}
cbs->cb[idx] = cb;
cbs->user_data[idx] = user_data;
return 0;
}
static int vevif_event_rx_set_enabled(const struct device *dev, uint32_t id, bool enable)
{
const struct mbox_vevif_event_rx_conf *config = dev->config;
struct mbox_vevif_event_rx_cbs *cbs = dev->data;
if (!vevif_event_rx_event_is_valid(config->events_mask, id)) {
return -EINVAL;
}
if (enable) {
if ((cbs->enabled_mask & BIT(id)) != 0U) {
return -EALREADY;
}
cbs->enabled_mask |= BIT(id);
nrfy_vpr_int_enable(config->vpr, BIT(id));
} else {
if ((cbs->enabled_mask & BIT(id)) == 0U) {
return -EALREADY;
}
cbs->enabled_mask &= ~BIT(id);
nrfy_vpr_int_disable(config->vpr, BIT(id));
}
return 0;
}
static const struct mbox_driver_api vevif_event_rx_driver_api = {
.max_channels_get = vevif_event_rx_max_channels_get,
.register_callback = vevif_event_rx_register_callback,
.set_enabled = vevif_event_rx_set_enabled,
};
static int vevif_event_rx_init(const struct device *dev)
{
const struct mbox_vevif_event_rx_conf *config = dev->config;
config->irq_connect();
return 0;
}
#define VEVIF_EVENT_RX_DEFINE(inst) \
BUILD_ASSERT(DT_INST_PROP(inst, nordic_events) <= NRF_VPR_EVENTS_TRIGGERED_COUNT, \
"Number of events exceeds maximum"); \
\
static void irq_connect##inst(void) \
{ \
IRQ_CONNECT(DT_IRQN(DT_DRV_INST(inst)), DT_IRQ(DT_DRV_INST(inst), priority), \
vevif_event_rx_isr, (const void *)DEVICE_DT_GET(DT_DRV_INST(inst)), \
0); \
irq_enable(DT_IRQN(DT_DRV_INST(inst))); \
}; \
\
static struct mbox_vevif_event_rx_cbs data##inst = { \
.enabled_mask = 0, \
}; \
static const struct mbox_vevif_event_rx_conf conf##inst = { \
.vpr = (NRF_VPR_Type *)DT_INST_REG_ADDR(inst), \
.events = DT_INST_PROP(inst, nordic_events), \
.events_mask = DT_INST_PROP(inst, nordic_events_mask), \
.irq_connect = irq_connect##inst, \
}; \
\
DEVICE_DT_INST_DEFINE(inst, vevif_event_rx_init, NULL, &data##inst, &conf##inst, \
POST_KERNEL, CONFIG_MBOX_INIT_PRIORITY, &vevif_event_rx_driver_api);
DT_INST_FOREACH_STATUS_OKAY(VEVIF_EVENT_RX_DEFINE)

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT nordic_nrf_vevif_event_tx
#include <zephyr/devicetree.h>
#include <zephyr/drivers/mbox.h>
#include <hal/nrf_vpr.h>
#include <hal/nrf_vpr_csr.h>
#include <hal/nrf_vpr_csr_vevif.h>
#if defined(CONFIG_SOC_NRF54L15_ENGA_CPUFLPR)
#define EVENTS_IDX_MAX 17U
#else
#define EVENTS_IDX_MAX NRF_VPR_EVENTS_TRIGGERED_MAX
#endif
#define VEVIF_EVENTS_NUM DT_INST_PROP(0, nordic_events)
#define VEVIF_EVENTS_MASK DT_INST_PROP(0, nordic_events_mask)
BUILD_ASSERT(DT_INST_PROP(0, nordic_events) <= NRF_VPR_EVENTS_TRIGGERED_COUNT,
"Number of events exceeds maximum");
static inline bool vevif_event_tx_is_valid(uint32_t id)
{
return (id < EVENTS_IDX_MAX) && ((VEVIF_EVENTS_MASK & BIT(id)) != 0U);
}
static int vevif_event_tx_send(const struct device *dev, uint32_t id, const struct mbox_msg *msg)
{
ARG_UNUSED(dev);
if (!vevif_event_tx_is_valid(id)) {
return -EINVAL;
}
if (msg != NULL) {
return -ENOTSUP;
}
nrf_vpr_csr_vevif_events_trigger(BIT(id));
return 0;
}
static int vevif_event_tx_mtu_get(const struct device *dev)
{
ARG_UNUSED(dev);
return 0;
}
static uint32_t vevif_event_tx_max_channels_get(const struct device *dev)
{
ARG_UNUSED(dev);
return VEVIF_EVENTS_NUM;
}
static const struct mbox_driver_api vevif_event_tx_driver_api = {
.send = vevif_event_tx_send,
.mtu_get = vevif_event_tx_mtu_get,
.max_channels_get = vevif_event_tx_max_channels_get,
};
DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, NULL, POST_KERNEL, CONFIG_MBOX_INIT_PRIORITY,
&vevif_event_tx_driver_api);

View file

@ -0,0 +1,48 @@
# Copyright (c) 2024 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
description: |
Nordic VEVIF (VPR Event Interface) - EVENT RX MODE
VEVIF provides support for inter-domain software signaling. It implements a set of events
intended for signaling within the interprocessor communication (IPC) framework.
When used in the event rx mode, the VEVIF events are used to receive IRQs that are
triggered by the VPR core.
Example definition:
cpuppr_vpr: vpr@deadbeef {
...
cpuflpr_vevif_event_rx: mailbox@0 {
compatible = "nordic,nrf-vevif-event-rx";
reg = <0x0 0x1000>;
interrupts = <76 NRF_DEFAULT_IRQ_PRIORITY>;
#mbox-cells = <1>;
nordic,events = <1>;
nordic,events-mask = <0x00008000>;
};
};
compatible: "nordic,nrf-vevif-event-rx"
include: [base.yaml, mailbox-controller.yaml]
properties:
nordic,events:
type: int
required: true
description: Number of events supported by the VEVIF instance.
nordic,events-mask:
type: int
required: true
description: Mask of events supported by the VEVIF instance.
interrupts:
required: true
reg:
required: true
mbox-cells:
- channel

View file

@ -0,0 +1,40 @@
# Copyright (c) 2024 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
description: |
Nordic VEVIF (VPR Event Interface) - EVENT TX MODE
VEVIF provides support for inter-domain software signaling. It implements a set of events
intended for signaling within the interprocessor communication (IPC) framework.
When used in the event tx mode, the VEVIF events are used to trigger IRQs from VPR
to a remote core.
Example definition:
cpuppr_vpr: vpr@deadbeef{
...
cpuflpr_vevif_event_tx: mailbox {
compatible = "nordic,nrf-vevif-event-tx";
#mbox-cells = <1>;
nordic,events = <1>;
nordic,events-mask = <0x00008000>;
};
};
compatible: "nordic,nrf-vevif-event-tx"
include: [base.yaml, mailbox-controller.yaml]
properties:
nordic,events:
type: int
required: true
description: Number of events supported by the VEVIF instance.
nordic,events-mask:
type: int
required: true
description: Mask of events supported by the VEVIF instance.
mbox-cells:
- channel