diff --git a/CODEOWNERS b/CODEOWNERS index 69c4c894d21452..05d7ad42ca0fac 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -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 diff --git a/drivers/ipm/CMakeLists.txt b/drivers/ipm/CMakeLists.txt index 63148148e87e3c..1da9b759b289f8 100644 --- a/drivers/ipm/CMakeLists.txt +++ b/drivers/ipm/CMakeLists.txt @@ -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) diff --git a/drivers/ipm/Kconfig b/drivers/ipm/Kconfig index c693213496458e..d8aef8e0d3c329 100644 --- a/drivers/ipm/Kconfig +++ b/drivers/ipm/Kconfig @@ -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 diff --git a/drivers/ipm/Kconfig.ivshmem b/drivers/ipm/Kconfig.ivshmem new file mode 100644 index 00000000000000..7e693f044cab5e --- /dev/null +++ b/drivers/ipm/Kconfig.ivshmem @@ -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 diff --git a/drivers/ipm/ipm_ivshmem.c b/drivers/ipm/ipm_ivshmem.c new file mode 100644 index 00000000000000..deda3f519506d3 --- /dev/null +++ b/drivers/ipm/ipm_ivshmem.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2023 Linaro. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT linaro_ivshmem_ipm + +#include +#include +#include +#include +#include +#include +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); diff --git a/dts/bindings/ipm/linaro,ivshmem-ipm.yaml b/dts/bindings/ipm/linaro,ivshmem-ipm.yaml new file mode 100644 index 00000000000000..7d2b660ff42476 --- /dev/null +++ b/dts/bindings/ipm/linaro,ivshmem-ipm.yaml @@ -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