Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions drivers/ipm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions drivers/ipm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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"


Expand Down
9 changes: 9 additions & 0 deletions drivers/ipm/Kconfig.rpi_pico
Original file line number Diff line number Diff line change
@@ -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.
131 changes: 131 additions & 0 deletions drivers/ipm/ipm_rpi_pico.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* Copyright (c) 2025 Dan Collins
* Copyright (c) 2025 Dmitrii Sharshakov <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT raspberrypi_pico_sio_fifo

#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/ipm.h>

#include <zephyr/logging/log.h>
#include <hardware/structs/sio.h>

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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it okay not to use spinlock for exclusion here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, not sure, it could cause an issue when there're 3 items in the mailbox, we checked in 2 threads, one pushed and another is yet to push, which will discard the message. This fn has to be wrapped in some thread safety method, yes, thanks


/* 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;
Comment on lines +63 to +67
Copy link
Member Author

@dsseng dsseng Aug 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could it maybe make sense to do some kind of a split, like 1/3 or 2/2 byte split for ID/Data? 2^32 seems like quite a huge number of channels for most applications, while sending some data as well might be a cool feature for debugging or if any IPM/MBOX consumers want to transfer some data as well

}

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);
11 changes: 11 additions & 0 deletions dts/arm/raspberrypi/rpi_pico/rp2350.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"sio_fifo" is better here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, thanks. Now this range only covers 3 FIFO registers

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 {
Expand Down
15 changes: 15 additions & 0 deletions dts/bindings/ipm/raspberrypi,pico-sio-fifo.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright (c) 2025 Dmitrii Sharshakov <[email protected]>
# 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