Skip to content

Commit

Permalink
drivers: ipm: added IPM over IVSHMEM driver
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
uLipe authored and fabiobaltieri committed Jul 20, 2023
1 parent bb8b515 commit 7ca59d7
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 0 deletions.
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@
/drivers/ipm/ipm_stm32_ipcc.c @arnopo
/drivers/ipm/ipm_stm32_hsem.c @cameled
/drivers/ipm/ipm_esp32.c @uLipe
/drivers/ipm/ipm_ivshmem.c @uLipe
/drivers/kscan/ @VenkatKotakonda @franciscomunoz @sjvasanth1
/drivers/kscan/*xec* @franciscomunoz @sjvasanth1
/drivers/kscan/*ft5336* @MaureenHelm
Expand Down
1 change: 1 addition & 0 deletions drivers/ipm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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_ESP32_SOFT_IPM ipm_esp32.c)
zephyr_library_sources_ifdef(CONFIG_USERSPACE ipm_handlers.c)
zephyr_library_sources_ifdef(CONFIG_IPM_IVSHMEM ipm_ivshmem.c)
11 changes: 11 additions & 0 deletions drivers/ipm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,21 @@ config ESP32_SOFT_IPM
help
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.imx"
source "drivers/ipm/Kconfig.stm32"
source "drivers/ipm/Kconfig.intel_adsp"
source "drivers/ipm/Kconfig.ivshmem"


module = IPM
module-str = ipm
Expand Down
18 changes: 18 additions & 0 deletions drivers/ipm/Kconfig.ivshmem
Original file line number Diff line number Diff line change
@@ -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 changes: 135 additions & 0 deletions drivers/ipm/ipm_ivshmem.c
Original file line number Diff line number Diff line change
@@ -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 changes: 15 additions & 0 deletions dts/bindings/ipm/linaro,ivshmem-ipm.yaml
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 7ca59d7

Please sign in to comment.