diff --git a/drivers/ipm/CMakeLists.txt b/drivers/ipm/CMakeLists.txt index ca2aa03591c3e..02ff646beb41a 100644 --- a/drivers/ipm/CMakeLists.txt +++ b/drivers/ipm/CMakeLists.txt @@ -11,6 +11,7 @@ zephyr_library_sources_ifdef(CONFIG_IPM_STM32_IPCC ipm_stm32_ipcc.c) zephyr_library_sources_ifdef(CONFIG_IPM_NRFX ipm_nrfx_ipc.c) 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_RPI_PICO ipm_rpi_pico.c) zephyr_library_sources_ifdef(CONFIG_IPM_SEDI ipm_sedi.c) zephyr_library_sources_ifdef(CONFIG_IPM_IVSHMEM ipm_ivshmem.c) zephyr_library_sources_ifdef(CONFIG_ESP32_SOFT_IPM ipm_esp32.c) diff --git a/drivers/ipm/Kconfig b/drivers/ipm/Kconfig index ba4571ed7581a..d0b204acac3de 100644 --- a/drivers/ipm/Kconfig +++ b/drivers/ipm/Kconfig @@ -76,6 +76,7 @@ source "drivers/ipm/Kconfig.imx" source "drivers/ipm/Kconfig.stm32" source "drivers/ipm/Kconfig.intel_adsp" source "drivers/ipm/Kconfig.ivshmem" +source "drivers/ipm/Kconfig.rpi_pico" source "drivers/ipm/Kconfig.sedi" diff --git a/drivers/ipm/Kconfig.rpi_pico b/drivers/ipm/Kconfig.rpi_pico new file mode 100644 index 0000000000000..894c7a090cc9d --- /dev/null +++ b/drivers/ipm/Kconfig.rpi_pico @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2025 Dan Collins + +config IPM_RPI_PICO + bool "Raspberry Pi Pico IPM Driver" + default y + depends on DT_HAS_RASPBERRYPI_PICO_SIO_FIFO_ENABLED + help + This option enables the Raspberry Pi Pico Inter-process mailbox driver. diff --git a/drivers/ipm/ipm_rpi_pico.c b/drivers/ipm/ipm_rpi_pico.c new file mode 100644 index 0000000000000..9f982bc5dc13d --- /dev/null +++ b/drivers/ipm/ipm_rpi_pico.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2025 Dan Collins + * Copyright (c) 2025 Dmitrii Sharshakov + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT raspberrypi_pico_sio_fifo + +#include +#include +#include + +#include +#include + +LOG_MODULE_REGISTER(ipm_rpi_pico, CONFIG_IPM_LOG_LEVEL); + +struct rpi_pico_ipm_data { + ipm_callback_t cb; + void *user_data; +}; + +static struct rpi_pico_ipm_data rpi_pico_mailbox_data; + +static int rpi_pico_mailbox_send(const struct device *dev, int wait, uint32_t id, + const void *data, int size) +{ + ARG_UNUSED(wait); + ARG_UNUSED(data); + + if (size != 0) { + return -EMSGSIZE; + } + + while (!(sio_hw->fifo_st & SIO_FIFO_ST_RDY_BITS)) { + k_busy_wait(1); + } + + sio_hw->fifo_wr = id; + + /* Inform other CPU about FIFO update. */ + __SEV(); + + return 0; +} + +static void rpi_pico_mailbox_register_callback(const struct device *dev, ipm_callback_t cb, + void *user_data) +{ + struct rpi_pico_ipm_data *data = dev->data; + uint32_t key; + + key = irq_lock(); + data->user_data = user_data; + data->cb = cb; + irq_unlock(key); +} + +static int rpi_pico_mailbox_max_data_size_get(const struct device *dev) +{ + ARG_UNUSED(dev); + /* + * FIFO mailbox allows a single 32 bit value to be sent - and we + * use that as the channel identifier. + */ + return 0; +} + +static unsigned int rpi_pico_mailbox_max_id_val_get(const struct device *dev) +{ + ARG_UNUSED(dev); + /* + * FIFO mailbox allows a single 32 bit value to be sent - and we + * use that as the channel identifier. + */ + return UINT32_MAX; +} + +static int rpi_pico_mailbox_set_enabled(const struct device *dev, int enable) +{ + ARG_UNUSED(dev); + + if (enable) { + irq_enable(DT_INST_IRQN(0)); + } else { + irq_disable(DT_INST_IRQN(0)); + } + + return 0; +} + +static void rpi_pico_mailbox_isr(const struct device *dev) +{ + /* Clear status */ + sio_hw->fifo_st = 0xff; + + while (sio_hw->fifo_st & SIO_FIFO_ST_VLD_BITS) { + uint32_t msg = sio_hw->fifo_rd; + struct rpi_pico_ipm_data *data = dev->data; + + if (data->cb) { + /* Only send the channel ID to the callback, no data. */ + data->cb(dev, data->user_data, msg, 0); + } + } +} + +static int rpi_pico_mailbox_init(const struct device *dev) +{ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(0, sio_irq_fifo, irq), + DT_INST_IRQ_BY_NAME(0, sio_irq_fifo, priority), rpi_pico_mailbox_isr, + DEVICE_DT_INST_GET(0), 0); + + return 0; +} + +static DEVICE_API(ipm, rpi_pico_mailbox_driver_api) = { + .send = rpi_pico_mailbox_send, + .register_callback = rpi_pico_mailbox_register_callback, + .max_data_size_get = rpi_pico_mailbox_max_data_size_get, + .max_id_val_get = rpi_pico_mailbox_max_id_val_get, + .set_enabled = rpi_pico_mailbox_set_enabled, +}; + +BUILD_ASSERT((DT_INST_REG_ADDR_BY_NAME(0, sio) == SIO_BASE + SIO_FIFO_ST_OFFSET), + "Unsupported SIO FIFO base address"); + +DEVICE_DT_INST_DEFINE(0, &rpi_pico_mailbox_init, NULL, &rpi_pico_mailbox_data, + NULL, POST_KERNEL, + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &rpi_pico_mailbox_driver_api); diff --git a/dts/arm/raspberrypi/rpi_pico/rp2350.dtsi b/dts/arm/raspberrypi/rpi_pico/rp2350.dtsi index 4f16a54c02ecd..8b70f95a61674 100644 --- a/dts/arm/raspberrypi/rpi_pico/rp2350.dtsi +++ b/dts/arm/raspberrypi/rpi_pico/rp2350.dtsi @@ -453,6 +453,17 @@ interrupt-names = "irq0", "irq1"; status = "disabled"; }; + + ipm0: sio-fifo@d0000050 { + compatible = "raspberrypi,pico-sio-fifo"; + reg = <0xd0000050 0xc>; + reg-names = "sio"; + interrupts = <25 RPI_PICO_DEFAULT_IRQ_PRIORITY>; + interrupt-names = "sio_irq_fifo"; + // Accesses go through a bus interface paired to the core, + // so SIO can be shared between cores. + status = "okay"; + }; }; pinctrl: pin-controller { diff --git a/dts/bindings/ipm/raspberrypi,pico-sio-fifo.yaml b/dts/bindings/ipm/raspberrypi,pico-sio-fifo.yaml new file mode 100644 index 0000000000000..f9a1074ef7d68 --- /dev/null +++ b/dts/bindings/ipm/raspberrypi,pico-sio-fifo.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2025 Dmitrii Sharshakov +# SPDX-License-Identifier: Apache-2.0 + +description: RP2 SIO FIFO mailbox + +compatible: "raspberrypi,pico-sio-fifo" + +include: base.yaml + +properties: + interrupts: + required: true + + reg: + required: true