-
Notifications
You must be signed in to change notification settings - Fork 8.1k
drivers: ipm: add ipm_rpi_pico #92923
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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. |
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; | ||
|
||
/* 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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); | ||
dsseng marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
} | ||
|
||
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); | ||
dsseng marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
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); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "sio_fifo" is better here. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 { | ||
|
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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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