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: 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>
- Loading branch information
1 parent
bb8b515
commit 7ca59d7
Showing
6 changed files
with
181 additions
and
0 deletions.
There are no files selected for viewing
Validating CODEOWNERS rules …
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
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,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 |
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,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); |
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,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 |