Re: [PATCH v8 3/4] gpio: rpmsg: add generic rpmsg GPIO driver
From: Bartosz Golaszewski <brgl@kernel.org>
Date: 2026-02-18 10:20:14
Also in:
imx, linux-devicetree, linux-doc, linux-gpio, linux-remoteproc, lkml
On Thu, 12 Feb 2026 22:36:55 +0100, Shenwei Wang [off-list ref] said:
quoted hunk ↗ jump to hunk
On an AMP platform, the system may include two processors: - An MCU running an RTOS - An MPU running Linux These processors communicate via the RPMSG protocol. The driver implements the standard GPIO interface, allowing the Linux side to control GPIO controllers which reside in the remote processor via RPMSG protocol. Cc: Bartosz Golaszewski <redacted> Cc: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Shenwei Wang <shenwei.wang@nxp.com> --- drivers/gpio/Kconfig | 17 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-rpmsg.c | 588 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 606 insertions(+) create mode 100644 drivers/gpio/gpio-rpmsg.cdiff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b45fb799e36c..3179a54f0634 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig@@ -1892,6 +1892,23 @@ config GPIO_SODAVILLE endmenu +menu "RPMSG GPIO drivers" + depends on RPMSG + +config GPIO_RPMSG + tristate "Generic RPMSG GPIO support" + depends on REMOTEPROC + select GPIOLIB_IRQCHIP + default REMOTEPROC
You're using a lot of OF-centric APIs here, don't you need to depend on OF? Alternatively, it seems that only rpmsg_get_channel_ofnode() really requires OF-nodes and everything else could just use firmware node API.
quoted hunk ↗ jump to hunk
+ help + Say yes here to support the generic GPIO functions over the RPMSG + bus. Currently supported devices: i.MX7ULP, i.MX8ULP, i.MX8x, and + i.MX9x. + + If unsure, say N. + +endmenu + menu "SPI GPIO expanders" depends on SPI_MASTERdiff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index c05f7d795c43..501aba56ad68 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile@@ -158,6 +158,7 @@ obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o obj-$(CONFIG_GPIO_REALTEK_OTTO) += gpio-realtek-otto.o obj-$(CONFIG_GPIO_REG) += gpio-reg.o obj-$(CONFIG_GPIO_ROCKCHIP) += gpio-rockchip.o +obj-$(CONFIG_GPIO_RPMSG) += gpio-rpmsg.o obj-$(CONFIG_GPIO_RTD) += gpio-rtd.o obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) += gpio-sama5d2-piobu.odiff --git a/drivers/gpio/gpio-rpmsg.c b/drivers/gpio/gpio-rpmsg.c new file mode 100644 index 000000000000..163f51fd45b5 --- /dev/null +++ b/drivers/gpio/gpio-rpmsg.c@@ -0,0 +1,588 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2026 NXP + * + * The driver exports a standard gpiochip interface to control + * the GPIO controllers via RPMSG on a remote processor. + */
Add newline here. [snip]
+
+static struct device_node *
+rpmsg_get_channel_ofnode(struct rpmsg_device *rpdev, char *chan_name)
+{
+ struct device_node *np_chan = NULL, *np;
+ struct rproc *rproc;
+
+ rproc = rproc_get_by_child(&rpdev->dev);
+ if (!rproc)
+ return NULL;
+
+ np = of_node_get(rproc->dev.of_node);
+ if (!np && rproc->dev.parent)
+ np = of_node_get(rproc->dev.parent->of_node);
+
+ if (np) {
+ /* Balance the of_node_put() performed by of_find_node_by_name(). */
+ of_node_get(np);
+ np_chan = of_find_node_by_name(np, chan_name);
+ of_node_put(np);If you put np here, why even bother with "balancing". If you don't do of_node_get() before calling of_find_node_by_name(), you'll be in the same place, no?
+ }
+
+ return np_chan;
+}
+
+static int
+rpmsg_gpio_channel_callback(struct rpmsg_device *rpdev, void *data,
+ int len, void *priv, u32 src)
+{
+ struct gpio_rpmsg_packet *msg = data;
+ struct rpmsg_gpio_port *port = NULL;
+ struct rpdev_drvdata *drvdata;
+
+ drvdata = dev_get_drvdata(&rpdev->dev);
+ if (drvdata && msg && msg->port_idx < MAX_PORT_PER_CHANNEL)
+ port = drvdata->channel_devices[msg->port_idx];
+
+ if (!port)
+ return -ENODEV;
+
+ if (msg->header.type == GPIO_RPMSG_REPLY) {
+ *port->info.reply_msg = *msg;
+ complete(&port->info.cmd_complete);
+ } else if (msg->header.type == GPIO_RPMSG_NOTIFY) {
+ generic_handle_domain_irq_safe(port->gc.irq.domain, msg->pin_idx);
+ } else
+ dev_err(&rpdev->dev, "wrong command type!\n");
+
+ return 0;
+}
+
+static int rpmsg_gpio_channel_probe(struct rpmsg_device *rpdev)
+{
+ struct device *dev = &rpdev->dev;
+ struct rpdev_drvdata *drvdata;
+ struct device_node *np;
+ int ret;
+
+ if (!dev->of_node) {
+ np = rpmsg_get_channel_ofnode(rpdev, rpdev->id.name);
+ if (np) {
+ dev->of_node = np;
+ set_primary_fwnode(dev, of_fwnode_handle(np));
+ }
+ return -EPROBE_DEFER;
+ }
+
+ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+
+ drvdata->rproc_name = rpmsg_get_rproc_node_name(rpdev);
+ dev_set_drvdata(dev, drvdata);
+
+ for_each_child_of_node_scoped(dev->of_node, child) {
Like mentioned above: this could be:
device_for_each_child_node() {
fwnode_device_is_available();
...
}
+ if (!of_device_is_available(child))
+ continue;
+
+ if (!of_match_node(dev->driver->of_match_table, child))
+ continue;
+
+ ret = rpmsg_gpiochip_register(rpdev, child);
+ if (ret < 0)
+ dev_err(dev, "Failed to register: %pOF\n", child);
+ }
+
+ return 0;
+}
+
+static void rpmsg_gpio_channel_remove(struct rpmsg_device *rpdev)
+{
+ dev_info(&rpdev->dev, "rpmsg gpio channel driver is removed\n");
+}Please drop this, no need to log it,
+
+static const struct of_device_id rpmsg_gpio_dt_ids[] = {
+ { .compatible = "rpmsg-gpio" },
+ { /* sentinel */ }
+};
+
+static struct rpmsg_device_id rpmsg_gpio_channel_id_table[] = {
+ { .name = "rpmsg-io-channel" },
+ { },
+};
+MODULE_DEVICE_TABLE(rpmsg, rpmsg_gpio_channel_id_table);
+
+static struct rpmsg_driver rpmsg_gpio_channel_client = {
+ .drv.name = KBUILD_MODNAME,
+ .drv.of_match_table = rpmsg_gpio_dt_ids,
Can you please do:
.drv = {
.name = "open-coded-name",
.of_match_table = ...
};
?
Bartosz
+ .id_table = rpmsg_gpio_channel_id_table,
+ .probe = rpmsg_gpio_channel_probe,
+ .callback = rpmsg_gpio_channel_callback,
+ .remove = rpmsg_gpio_channel_remove,
+};
+module_rpmsg_driver(rpmsg_gpio_channel_client);
+
+MODULE_AUTHOR("Shenwei Wang [off-list ref]");
+MODULE_DESCRIPTION("generic rpmsg gpio driver");
+MODULE_LICENSE("GPL");
--
2.43.0