drivers: ipm: added IPM over IVSHMEM driver
This driver is built on top of the IVSHMEM doorbell notification mechanism providing an unified way to generate inter VM interrupts. Signed-off-by: Felipe Neves <felipe.neves@linaro.org>
This commit is contained in:
parent
bb8b515ffa
commit
7ca59d7bfe
6 changed files with 181 additions and 0 deletions
|
@ -346,6 +346,7 @@
|
||||||
/drivers/ipm/ipm_stm32_ipcc.c @arnopo
|
/drivers/ipm/ipm_stm32_ipcc.c @arnopo
|
||||||
/drivers/ipm/ipm_stm32_hsem.c @cameled
|
/drivers/ipm/ipm_stm32_hsem.c @cameled
|
||||||
/drivers/ipm/ipm_esp32.c @uLipe
|
/drivers/ipm/ipm_esp32.c @uLipe
|
||||||
|
/drivers/ipm/ipm_ivshmem.c @uLipe
|
||||||
/drivers/kscan/ @VenkatKotakonda @franciscomunoz @sjvasanth1
|
/drivers/kscan/ @VenkatKotakonda @franciscomunoz @sjvasanth1
|
||||||
/drivers/kscan/*xec* @franciscomunoz @sjvasanth1
|
/drivers/kscan/*xec* @franciscomunoz @sjvasanth1
|
||||||
/drivers/kscan/*ft5336* @MaureenHelm
|
/drivers/kscan/*ft5336* @MaureenHelm
|
||||||
|
|
|
@ -15,3 +15,4 @@ zephyr_library_sources_ifdef(CONFIG_IPM_STM32_HSEM ipm_stm32_hsem.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_IPM_CAVS_HOST ipm_cavs_host.c)
|
zephyr_library_sources_ifdef(CONFIG_IPM_CAVS_HOST ipm_cavs_host.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_ESP32_SOFT_IPM ipm_esp32.c)
|
zephyr_library_sources_ifdef(CONFIG_ESP32_SOFT_IPM ipm_esp32.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE ipm_handlers.c)
|
zephyr_library_sources_ifdef(CONFIG_USERSPACE ipm_handlers.c)
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_IPM_IVSHMEM ipm_ivshmem.c)
|
||||||
|
|
|
@ -38,10 +38,21 @@ config ESP32_SOFT_IPM
|
||||||
help
|
help
|
||||||
Interprocessor driver for ESP32 when using AMP.
|
Interprocessor driver for ESP32 when using AMP.
|
||||||
|
|
||||||
|
config IPM_IVSHMEM
|
||||||
|
bool "IPM driver based on IVSHMEM-Doorbell"
|
||||||
|
default y
|
||||||
|
depends on DT_HAS_LINARO_IVSHMEM_IPM_ENABLED
|
||||||
|
depends on IVSHMEM
|
||||||
|
depends on IVSHMEM_DOORBELL
|
||||||
|
help
|
||||||
|
Interprocessor driver using IVSHMEM Doorbell mechanism.
|
||||||
|
|
||||||
source "drivers/ipm/Kconfig.nrfx"
|
source "drivers/ipm/Kconfig.nrfx"
|
||||||
source "drivers/ipm/Kconfig.imx"
|
source "drivers/ipm/Kconfig.imx"
|
||||||
source "drivers/ipm/Kconfig.stm32"
|
source "drivers/ipm/Kconfig.stm32"
|
||||||
source "drivers/ipm/Kconfig.intel_adsp"
|
source "drivers/ipm/Kconfig.intel_adsp"
|
||||||
|
source "drivers/ipm/Kconfig.ivshmem"
|
||||||
|
|
||||||
|
|
||||||
module = IPM
|
module = IPM
|
||||||
module-str = ipm
|
module-str = ipm
|
||||||
|
|
18
drivers/ipm/Kconfig.ivshmem
Normal file
18
drivers/ipm/Kconfig.ivshmem
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
# Copyright (c) 2023, Linaro
|
||||||
|
|
||||||
|
if IPM_IVSHMEM
|
||||||
|
|
||||||
|
config IPM_IVSHMEM_EVENT_LOOP_STACK_SIZE
|
||||||
|
int "Stack size in bytes of IVSHMEM IPM Event loop task"
|
||||||
|
default 8192
|
||||||
|
help
|
||||||
|
Adjust the stack size, in bytes of the ivshmem event loop task.
|
||||||
|
|
||||||
|
config IPM_IVSHMEM_EVENT_LOOP_PRIO
|
||||||
|
int "Priority of IVSHMEM IPM Event loop task"
|
||||||
|
default 2
|
||||||
|
help
|
||||||
|
Adjust the priority of the ivshmem event loop task.
|
||||||
|
|
||||||
|
endif
|
135
drivers/ipm/ipm_ivshmem.c
Normal file
135
drivers/ipm/ipm_ivshmem.c
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Linaro.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT linaro_ivshmem_ipm
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/drivers/ipm.h>
|
||||||
|
#include <zephyr/drivers/virtualization/ivshmem.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
LOG_MODULE_REGISTER(ipm_ivshmem, CONFIG_IPM_LOG_LEVEL);
|
||||||
|
|
||||||
|
K_THREAD_STACK_DEFINE(ivshmem_ev_loop_stack, CONFIG_IPM_IVSHMEM_EVENT_LOOP_STACK_SIZE);
|
||||||
|
static struct k_thread ivshmem_ev_loop_thread;
|
||||||
|
|
||||||
|
struct ivshmem_ipm_data {
|
||||||
|
ipm_callback_t cb;
|
||||||
|
void *user_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ivshmem_ipm_config {
|
||||||
|
const struct device *ivshmem_dev;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ivshmem_ipm_event_loop_thread(void *arg, void *p2, void *p3)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(p2);
|
||||||
|
ARG_UNUSED(p3);
|
||||||
|
|
||||||
|
unsigned int poll_signaled;
|
||||||
|
int ivshmem_vector_rx;
|
||||||
|
struct k_poll_signal sig;
|
||||||
|
struct k_poll_event events[] = {
|
||||||
|
K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
|
||||||
|
K_POLL_MODE_NOTIFY_ONLY,
|
||||||
|
&sig),
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct device *dev = (const struct device *)arg;
|
||||||
|
struct ivshmem_ipm_data *dev_data = (struct ivshmem_ipm_data *)dev->data;
|
||||||
|
struct ivshmem_ipm_config *dev_cfg = (struct ivshmem_ipm_config *)dev->config;
|
||||||
|
|
||||||
|
k_poll_signal_init(&sig);
|
||||||
|
int ret = ivshmem_register_handler(dev_cfg->ivshmem_dev, &sig, 0);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("registering handlers must be supported: %d\n", ret);
|
||||||
|
k_panic();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
LOG_DBG("%s: waiting interrupt from client...\n", __func__);
|
||||||
|
ret = k_poll(events, ARRAY_SIZE(events), K_FOREVER);
|
||||||
|
|
||||||
|
k_poll_signal_check(&sig, &poll_signaled, &ivshmem_vector_rx);
|
||||||
|
/* get ready for next signal */
|
||||||
|
k_poll_signal_reset(&sig);
|
||||||
|
|
||||||
|
if (dev_data->cb)
|
||||||
|
dev_data->cb(dev, dev_data->user_data, 0, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ivshmem_ipm_send(const struct device *dev, int wait, uint32_t id,
|
||||||
|
const void *data, int size)
|
||||||
|
{
|
||||||
|
ARG_UNUSED(wait);
|
||||||
|
ARG_UNUSED(data);
|
||||||
|
ARG_UNUSED(size);
|
||||||
|
|
||||||
|
struct ivshmem_ipm_config *dev_cfg = (struct ivshmem_ipm_config *)dev->config;
|
||||||
|
|
||||||
|
LOG_DBG("sending notification to the peer id 0x%x\n", id);
|
||||||
|
return ivshmem_int_peer(dev_cfg->ivshmem_dev, id, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ivshmem_ipm_register_callback(const struct device *dev,
|
||||||
|
ipm_callback_t cb,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
struct ivshmem_ipm_data *dev_data = (struct ivshmem_ipm_data *)dev->data;
|
||||||
|
|
||||||
|
dev_data->cb = cb;
|
||||||
|
dev_data->user_data = user_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ivshmem_ipm_set_enabled(const struct device *dev, int enable)
|
||||||
|
{
|
||||||
|
/* some subsystems needs this minimal function just return success here*/
|
||||||
|
ARG_UNUSED(dev);
|
||||||
|
ARG_UNUSED(enable);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ivshmem_ipm_init(const struct device *dev)
|
||||||
|
{
|
||||||
|
k_thread_create(&ivshmem_ev_loop_thread,
|
||||||
|
ivshmem_ev_loop_stack,
|
||||||
|
CONFIG_IPM_IVSHMEM_EVENT_LOOP_STACK_SIZE,
|
||||||
|
(k_thread_entry_t)ivshmem_ipm_event_loop_thread,
|
||||||
|
(void *)dev, NULL, NULL,
|
||||||
|
CONFIG_IPM_IVSHMEM_EVENT_LOOP_PRIO,
|
||||||
|
0, K_NO_WAIT);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct ipm_driver_api ivshmem_ipm_driver_api = {
|
||||||
|
.send = ivshmem_ipm_send,
|
||||||
|
.register_callback = ivshmem_ipm_register_callback,
|
||||||
|
.set_enabled = ivshmem_ipm_set_enabled
|
||||||
|
};
|
||||||
|
|
||||||
|
#define IPM_IVSHMEM_INIT(inst) \
|
||||||
|
static const struct ivshmem_ipm_config ivshmem_ipm_cfg_##inst = { \
|
||||||
|
.ivshmem_dev = \
|
||||||
|
DEVICE_DT_GET(DT_INST_PHANDLE(inst, ivshmem))\
|
||||||
|
}; \
|
||||||
|
static struct ivshmem_ipm_data ivshmem_ipm_data_##inst = { \
|
||||||
|
.cb = NULL, \
|
||||||
|
.user_data = NULL, \
|
||||||
|
}; \
|
||||||
|
DEVICE_DT_INST_DEFINE(inst, \
|
||||||
|
ivshmem_ipm_init, \
|
||||||
|
NULL, \
|
||||||
|
&ivshmem_ipm_data_##inst, &ivshmem_ipm_cfg_##inst, \
|
||||||
|
POST_KERNEL, CONFIG_APPLICATION_INIT_PRIORITY, \
|
||||||
|
&ivshmem_ipm_driver_api); \
|
||||||
|
|
||||||
|
DT_INST_FOREACH_STATUS_OKAY(IPM_IVSHMEM_INIT);
|
15
dts/bindings/ipm/linaro,ivshmem-ipm.yaml
Normal file
15
dts/bindings/ipm/linaro,ivshmem-ipm.yaml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# Copyright (c) 2023 Linaro
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
description: Inter processor message based on IVSHMEM
|
||||||
|
|
||||||
|
compatible: "linaro,ivshmem-ipm"
|
||||||
|
|
||||||
|
include: base.yaml
|
||||||
|
|
||||||
|
properties:
|
||||||
|
|
||||||
|
ivshmem:
|
||||||
|
type: phandle
|
||||||
|
required: true
|
||||||
|
description: ivshmem device node
|
Loading…
Add table
Add a link
Reference in a new issue