* [PATCH v14 0/5] Enable Remote GPIO over RPMSG on i.MX Platform
@ 2026-06-25 15:54 Shenwei Wang
2026-06-25 15:54 ` [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus Shenwei Wang
` (5 more replies)
0 siblings, 6 replies; 17+ messages in thread
From: Shenwei Wang @ 2026-06-25 15:54 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Jonathan Corbet, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Mathieu Poirier, Frank Li, Sascha Hauer
Cc: Shuah Khan, linux-gpio, linux-doc, linux-kernel,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan,
devicetree, linux-remoteproc, imx, linux-arm-kernel, linux-imx,
Arnaud POULIQUEN, b-padhi, Andrew Lunn
From: Shenwei Wang <shenwei.wang@nxp.com>
Support the remote devices on the remote processor via the RPMSG bus on
i.MX platform.
Changes in v14:
- Update gpio-rpmsg.rst per Mathieu’s feedback.
- Align the rpmsg-gpio driver with the revised gpio-rpmsg.rst.
- Modify rpmsg-core to enable prefix-based matching of RPMSG device IDs.
Changes in v13:
- drop the support for legacy NXP firmware.
- remove the fixed_up hooks from the rpmsg gpio driver.
- code cleanup.
Changes in v12:
- Fixed the "underline" warning reported by Randy.
Changes in v11:
- Expand RPMSG for the first time per Shuah's review comment.
Changes in v10:
- Update gpio-rpmsg.rst according to Daniel Baluta's review comments.
- Add a kernel CONFIG for fixed up handlers and only enable it on
i.MX products.
- Fixed bugs reported by kernel test robot.
Changes in v9:
- Reuse the gpio-virtio design for command and IRQ type definitions.
- Remove msg_id, version, and vendor fields from the generic protocol.
- Add fixed-up handlers to support legacy firmware.
Changes in v8:
- Add "depends on REMOTEPROC" in Kconfig to fix the build error reported
by the kernel test robot.
- Move the .rst patch before the .yaml patch.
- Handle the "ngpios" DT property based on Andrew's feedback.
Changes in v7:
- Reworked the driver to use the rpmsg_driver framework instead of
platform_driver, based on feedback from Bjorn and Arnaud.
- Updated gpio-rpmsg.yaml and imx_rproc.yaml according to comments from
Rob and Arnaud.
- Further refinements to gpio-rpmsg.yaml per Arnaud's feedback.
Changes in v6:
- make the driver more generic with the actions below:
rename the driver file to gpio-rpmsg.c
remove the imx related info in the function and variable names
rename the imx_rpmsg.h to rpdev_info.h
create a gpio-rpmsg.yaml and refer it in imx_rproc.yaml
- update the gpio-rpmsg.rst according to the feedback from Andrew and
move the source file to driver-api/gpio
- fix the bug reported by Zhongqiu Han
- remove the I2C related info
Changes in v5:
- move the gpio-rpmsg.rst from admin-guide to staging directory after
discussion with Randy Dunlap.
- add include files with some code improvements per Bartosz's comments.
Changes in v4:
- add a documentation to describe the transport protocol per Andrew's
comments.
- add a new handler to get the gpio direction.
Changes in v3:
- fix various format issue and return value check per Peng 's review
comments.
- add the logic to also populate the subnodes which are not in the
device map per Arnaud's request. (in imx_rproc.c)
- update the yaml per Frank's review comments.
Changes in v2:
- re-implemented the gpio driver per Linus Walleij's feedback by using
GPIOLIB_IRQCHIP helper library.
- fix various format issue per Mathieu/Peng 's review comments.
- update the yaml doc per Rob's feedback
Shenwei Wang (5):
docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus
dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode support
rpmsg: core: match rpmsg device IDs by prefix
gpio: rpmsg: add generic rpmsg GPIO driver
arm64: dts: imx8ulp: Add rpmsg node under imx_rproc
.../devicetree/bindings/gpio/gpio-rpmsg.yaml | 55 ++
.../bindings/remoteproc/fsl,imx-rproc.yaml | 53 ++
Documentation/driver-api/gpio/gpio-rpmsg.rst | 271 +++++++++
Documentation/driver-api/gpio/index.rst | 1 +
arch/arm64/boot/dts/freescale/imx8ulp.dtsi | 25 +
drivers/gpio/Kconfig | 17 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-rpmsg.c | 568 ++++++++++++++++++
drivers/rpmsg/rpmsg_core.c | 4 +-
9 files changed, 994 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/gpio/gpio-rpmsg.yaml
create mode 100644 Documentation/driver-api/gpio/gpio-rpmsg.rst
create mode 100644 drivers/gpio/gpio-rpmsg.c
--
2.43.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus
2026-06-25 15:54 [PATCH v14 0/5] Enable Remote GPIO over RPMSG on i.MX Platform Shenwei Wang
@ 2026-06-25 15:54 ` Shenwei Wang
2026-07-13 17:16 ` Mathieu Poirier
2026-06-25 15:54 ` [PATCH v14 2/5] dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode support Shenwei Wang
` (4 subsequent siblings)
5 siblings, 1 reply; 17+ messages in thread
From: Shenwei Wang @ 2026-06-25 15:54 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Jonathan Corbet, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Mathieu Poirier, Frank Li, Sascha Hauer
Cc: Shuah Khan, linux-gpio, linux-doc, linux-kernel,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan,
devicetree, linux-remoteproc, imx, linux-arm-kernel, linux-imx,
Arnaud POULIQUEN, b-padhi, Andrew Lunn
From: Shenwei Wang <shenwei.wang@nxp.com>
Describes the gpio rpmsg transport protocol over the rpmsg bus between
the remote system and Linux.
Signed-off-by: Shenwei Wang <shenwei.wang@nxp.com>
---
Documentation/driver-api/gpio/gpio-rpmsg.rst | 271 +++++++++++++++++++
Documentation/driver-api/gpio/index.rst | 1 +
2 files changed, 272 insertions(+)
create mode 100644 Documentation/driver-api/gpio/gpio-rpmsg.rst
diff --git a/Documentation/driver-api/gpio/gpio-rpmsg.rst b/Documentation/driver-api/gpio/gpio-rpmsg.rst
new file mode 100644
index 000000000000..7d351ff0adb0
--- /dev/null
+++ b/Documentation/driver-api/gpio/gpio-rpmsg.rst
@@ -0,0 +1,271 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+GPIO RPMSG (Remote Processor Messaging) Protocol
+================================================
+
+The GPIO RPMSG transport protocol is used for communication and interaction
+with GPIO controllers on remote processors via the RPMSG bus.
+
+Message Format
+--------------
+
+The RPMSG message consists of a 8-byte packet with the following layout:
+
+.. code-block:: none
+
+ +------+------+------+------+------+------+------+------+
+ | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
+ | cmd | line | value |
+ +------+------+------+------+------+------+------+------+
+
+- **cmd**: Command code, used for GPIO_RPMSG_SEND messages.
+
+- **line**: The GPIO line (pin) index of the port.
+
+- **value**: See details in the command description below.
+
+
+GPIO Commands
+-------------
+
+Commands are specified in the **Cmd** field.
+
+The SEND message is always sent from Linux to the remote firmware. Each
+SEND corresponds to a single REPLY message. The GPIO driver should
+serialize messages and determine whether a REPLY message is required. If a
+REPLY message is expected but not received within the specified timeout
+period (currently 1 second in the Linux driver), the driver should return
+-ETIMEOUT.
+
+GET_DIRECTION (Cmd=2)
+~~~~~~~~~~~~~~~~~~~~~
+
+**Request:**
+
+.. code-block:: none
+
+ +------+------+------+------+------+------+------+------+
+ | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
+ | 2 | line | 0 |
+ +------+------+------+------+------+------+------+------+
+
+**Reply:**
+
+.. code-block:: none
+
+ +------+--------+--------+
+ | 0x00 | 0x01 | 0x02 |
+ | 1 | status | value |
+ +------+--------+--------+
+
+- **status**:
+
+ - 0: Ok
+ - 1: Error
+
+- **value**: Direction.
+
+ - 0: None
+ - 1: Output
+ - 2: Input
+
+
+SET_DIRECTION (Cmd=3)
+~~~~~~~~~~~~~~~~~~~~~
+
+**Request:**
+
+.. code-block:: none
+
+ +------+------+------+------+------+------+------+------+
+ | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
+ | 3 | line | value |
+ +------+------+------+------+------+------+------+------+
+
+- **value**: Direction.
+
+ - 0: None
+ - 1: Output
+ - 2: Input
+
+**Reply:**
+
+.. code-block:: none
+
+ +------+--------+--------+
+ | 0x00 | 0x01 | 0x02 |
+ | 1 | status | 0 |
+ +------+--------+--------+
+
+- **status**:
+
+ - 0: Ok
+ - 1: Error
+
+
+GET_VALUE (Cmd=4)
+~~~~~~~~~~~~~~~~~
+
+**Request:**
+
+.. code-block:: none
+
+ +------+------+------+------+------+------+------+------+
+ | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
+ | 4 | line | 0 |
+ +------+------+------+------+------+------+------+------+
+
+**Reply:**
+
+.. code-block:: none
+
+ +------+--------+--------+
+ | 0x00 | 0x01 | 0x02 |
+ | 1 | status | value |
+ +------+--------+--------+
+
+- **status**:
+
+ - 0: Ok
+ - 1: Error
+
+- **value**: Level.
+
+ - 0: Low
+ - 1: High
+
+
+SET_VALUE (Cmd=5)
+~~~~~~~~~~~~~~~~~
+
+**Request:**
+
+.. code-block:: none
+
+ +------+------+------+------+------+------+------+------+
+ | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
+ | 5 | line | value |
+ +------+------+------+------+------+------+------+------+
+
+- **value**: Output level.
+
+ - 0: Low
+ - 1: High
+
+**Reply:**
+
+.. code-block:: none
+
+ +------+--------+--------+
+ | 0x00 | 0x01 | 0x02 |
+ | 1 | status | 0 |
+ +------+--------+--------+
+
+- **status**:
+
+ - 0: Ok
+ - 1: Error
+
+
+SET_IRQ_TYPE (Cmd=6)
+~~~~~~~~~~~~~~~~~~~~
+
+**Request:**
+
+.. code-block:: none
+
+ +------+------+------+------+------+------+------+------+
+ | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
+ | 6 | line | value |
+ +------+------+------+------+------+------+------+------+
+
+- **value**: IRQ types.
+
+ - 0: Interrupt disabled
+ - 1: Rising edge trigger
+ - 2: Falling edge trigger
+ - 3: Both edge trigger
+ - 4: High level trigger
+ - 8: Low level trigger
+
+**Reply:**
+
+.. code-block:: none
+
+ +------+--------+--------+
+ | 0x00 | 0x01 | 0x02 |
+ | 1 | status | 0 |
+ +------+--------+--------+
+
+- **status**:
+
+ - 0: Ok
+ - 1: Error
+
+SET_WAKEUP (Cmd=16)
+~~~~~~~~~~~~~~~~~~~
+
+**Request:**
+
+.. code-block:: none
+
+ +------+------+------+------+------+------+------+------+
+ | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
+ | 1 | line | value |
+ +------+------+------+------+------+------+------+------+
+
+- **value**: Wakeup enable.
+
+ The remote system should always aim to stay in a power-efficient state by
+ shutting down or clock-gating the GPIO blocks that aren't in use. Since
+ the remoteproc driver is responsible for managing the power states of the
+ remote firmware, the GPIO driver does not require to know the firmware's
+ running states.
+
+ When the wakeup bit is set, the remote firmware should configure the line
+ as a wakeup source. The firmware should send the notification message to
+ Linux after it is woken from the GPIO line.
+
+ - 0: Disable wakeup from GPIO
+ - 1: Enable wakeup from GPIO
+
+**Reply:**
+
+.. code-block:: none
+
+ +------+--------+--------+
+ | 0x00 | 0x01 | 0x02 |
+ | 1 | status | 0 |
+ +------+--------+--------+
+
+- **status**:
+
+ - 0: Ok
+ - 1: Error
+
+Notification Message
+--------------------
+
+Notifications are sent by the remote core and they have
+**Type=2 (GPIO_RPMSG_NOTIFY)**:
+
+When a GPIO line asserts an interrupt on the remote processor, the firmware
+should immediately mask the corresponding interrupt source and send a
+notification message to the Linux. Upon completion of the interrupt
+handling on the Linux side, the driver should issue a
+command **SET_IRQ_TYPE** to the firmware to unmask the interrupt.
+
+A Notification message can arrive between a SEND and its REPLY message,
+and the driver is expected to handle this scenario.
+
+.. code-block:: none
+
+ +------+------+--------+
+ | 0x00 | 0x01 | 0x02 |
+ | 2 | line | trigger|
+ +------+------+--------+
+
+- **line**: The GPIO line (pin) index of the port.
+
+- **trigger**: Optional parameter to indicate the trigger event type.
+
diff --git a/Documentation/driver-api/gpio/index.rst b/Documentation/driver-api/gpio/index.rst
index bee58f709b9a..e5eb1f82f01f 100644
--- a/Documentation/driver-api/gpio/index.rst
+++ b/Documentation/driver-api/gpio/index.rst
@@ -16,6 +16,7 @@ Contents:
drivers-on-gpio
bt8xxgpio
pca953x
+ gpio-rpmsg
Core
====
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v14 2/5] dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode support
2026-06-25 15:54 [PATCH v14 0/5] Enable Remote GPIO over RPMSG on i.MX Platform Shenwei Wang
2026-06-25 15:54 ` [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus Shenwei Wang
@ 2026-06-25 15:54 ` Shenwei Wang
2026-06-25 15:54 ` [PATCH v14 3/5] rpmsg: core: match rpmsg device IDs by prefix Shenwei Wang
` (3 subsequent siblings)
5 siblings, 0 replies; 17+ messages in thread
From: Shenwei Wang @ 2026-06-25 15:54 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Jonathan Corbet, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Mathieu Poirier, Frank Li, Sascha Hauer
Cc: Shuah Khan, linux-gpio, linux-doc, linux-kernel,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan,
devicetree, linux-remoteproc, imx, linux-arm-kernel, linux-imx,
Arnaud POULIQUEN, b-padhi, Andrew Lunn
From: Shenwei Wang <shenwei.wang@nxp.com>
Remote processors may announce multiple GPIO controllers over an RPMSG
channel. These GPIO controllers may require corresponding device tree
nodes, especially when acting as providers, to supply phandles for their
consumers.
Define an RPMSG node to work as a container for a group of RPMSG channels
under the imx_rproc node. Each subnode within "rpmsg" represents an
individual RPMSG channel. The name of each subnode corresponds to the
channel name as defined by the remote processor.
All remote devices associated with a given channel are defined as child
nodes under the corresponding channel node.
Signed-off-by: Shenwei Wang <shenwei.wang@nxp.com>
---
.../devicetree/bindings/gpio/gpio-rpmsg.yaml | 55 +++++++++++++++++++
.../bindings/remoteproc/fsl,imx-rproc.yaml | 53 ++++++++++++++++++
2 files changed, 108 insertions(+)
create mode 100644 Documentation/devicetree/bindings/gpio/gpio-rpmsg.yaml
diff --git a/Documentation/devicetree/bindings/gpio/gpio-rpmsg.yaml b/Documentation/devicetree/bindings/gpio/gpio-rpmsg.yaml
new file mode 100644
index 000000000000..6c78b6850321
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-rpmsg.yaml
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpio/gpio-rpmsg.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Generic RPMSG GPIO Controller
+
+maintainers:
+ - Shenwei Wang <shenwei.wang@nxp.com>
+
+description:
+ On an AMP platform, some GPIO controllers are exposed by the remote processor
+ through the RPMSG bus. The RPMSG GPIO transport protocol defines the packet
+ structure and communication flow between Linux and the remote firmware. Those
+ controllers are managed via this transport protocol. For more details of the
+ protocol, check the document below.
+ Documentation/driver-api/gpio/gpio-rpmsg.rst
+
+properties:
+ compatible:
+ oneOf:
+ - items:
+ - enum:
+ - fsl,rpmsg-gpio
+ - const: rpmsg-gpio
+ - const: rpmsg-gpio
+
+ reg:
+ description:
+ The reg property represents the index of the GPIO controllers. Since
+ the driver manages controllers on a remote system, this index tells
+ the remote system which controller to operate.
+ maxItems: 1
+
+ "#gpio-cells":
+ const: 2
+
+ gpio-controller: true
+
+ interrupt-controller: true
+
+ "#interrupt-cells":
+ const: 2
+
+required:
+ - compatible
+ - reg
+ - "#gpio-cells"
+ - "#interrupt-cells"
+
+allOf:
+ - $ref: /schemas/gpio/gpio.yaml#
+
+unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml
index ce8ec0119469..aea33205a881 100644
--- a/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml
@@ -85,6 +85,34 @@ properties:
This property is to specify the resource id of the remote processor in SoC
which supports SCFW
+ rpmsg:
+ type: object
+ additionalProperties: false
+ description:
+ Represents the RPMSG bus between Linux and the remote system. Contains
+ a group of RPMSG channel devices running on the bus.
+
+ properties:
+ rpmsg-io:
+ type: object
+ additionalProperties: false
+ properties:
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+ patternProperties:
+ "gpio@[0-9a-f]+$":
+ type: object
+ $ref: /schemas/gpio/gpio-rpmsg.yaml#
+ unevaluatedProperties: false
+
+ required:
+ - '#address-cells'
+ - '#size-cells'
+
required:
- compatible
@@ -147,5 +175,30 @@ examples:
&mu 3 1>;
memory-region = <&vdev0buffer>, <&vdev0vring0>, <&vdev0vring1>, <&rsc_table>;
syscon = <&src>;
+
+ rpmsg {
+ rpmsg-io {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio@0 {
+ compatible = "rpmsg-gpio";
+ reg = <0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ };
+
+ gpio@1 {
+ compatible = "rpmsg-gpio";
+ reg = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ };
+ };
+ };
};
...
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v14 3/5] rpmsg: core: match rpmsg device IDs by prefix
2026-06-25 15:54 [PATCH v14 0/5] Enable Remote GPIO over RPMSG on i.MX Platform Shenwei Wang
2026-06-25 15:54 ` [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus Shenwei Wang
2026-06-25 15:54 ` [PATCH v14 2/5] dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode support Shenwei Wang
@ 2026-06-25 15:54 ` Shenwei Wang
2026-06-25 15:54 ` [PATCH v14 4/5] gpio: rpmsg: add generic rpmsg GPIO driver Shenwei Wang
` (2 subsequent siblings)
5 siblings, 0 replies; 17+ messages in thread
From: Shenwei Wang @ 2026-06-25 15:54 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Jonathan Corbet, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Mathieu Poirier, Frank Li, Sascha Hauer
Cc: Shuah Khan, linux-gpio, linux-doc, linux-kernel,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan,
devicetree, linux-remoteproc, imx, linux-arm-kernel, linux-imx,
Arnaud POULIQUEN, b-padhi, Andrew Lunn
From: Shenwei Wang <shenwei.wang@nxp.com>
The current rpmsg_id_match() implementation requires an exact
string match between the driver id_table entry and the rpmsg
device name using strncmp() with RPMSG_NAME_SIZE.
This makes it impossible for a driver to match a group of
rpmsg devices sharing a common prefix (e.g. dynamically
suffixed channel names).
Update the matching logic to compare only the length of the
id->name string, allowing id_table entries to act as prefixes.
This enables drivers to bind to devices whose names start with
the specified id->name.
The implementation is copied from a reply by Mathieu.
Signed-off-by: Shenwei Wang <shenwei.wang@nxp.com>
---
drivers/rpmsg/rpmsg_core.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index e7f7831d37f8..f95bfc9965d4 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -414,7 +414,9 @@ ATTRIBUTE_GROUPS(rpmsg_dev);
static inline int rpmsg_id_match(const struct rpmsg_device *rpdev,
const struct rpmsg_device_id *id)
{
- return strncmp(id->name, rpdev->id.name, RPMSG_NAME_SIZE) == 0;
+ size_t len = strnlen(id->name, RPMSG_NAME_SIZE);
+
+ return strncmp(id->name, rpdev->id.name, len) == 0;
}
/* match rpmsg channel and rpmsg driver */
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v14 4/5] gpio: rpmsg: add generic rpmsg GPIO driver
2026-06-25 15:54 [PATCH v14 0/5] Enable Remote GPIO over RPMSG on i.MX Platform Shenwei Wang
` (2 preceding siblings ...)
2026-06-25 15:54 ` [PATCH v14 3/5] rpmsg: core: match rpmsg device IDs by prefix Shenwei Wang
@ 2026-06-25 15:54 ` Shenwei Wang
2026-06-25 20:32 ` Andrew Davis
2026-06-25 22:17 ` Julian Braha
2026-06-25 15:54 ` [PATCH v14 5/5] arm64: dts: imx8ulp: Add rpmsg node under imx_rproc Shenwei Wang
2026-07-06 15:40 ` [PATCH v14 0/5] Enable Remote GPIO over RPMSG on i.MX Platform Shenwei Wang (OSS)
5 siblings, 2 replies; 17+ messages in thread
From: Shenwei Wang @ 2026-06-25 15:54 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Jonathan Corbet, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Mathieu Poirier, Frank Li, Sascha Hauer
Cc: Shuah Khan, linux-gpio, linux-doc, linux-kernel,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan,
devicetree, linux-remoteproc, imx, linux-arm-kernel, linux-imx,
Arnaud POULIQUEN, b-padhi, Andrew Lunn, Bartosz Golaszewski
From: Shenwei Wang <shenwei.wang@nxp.com>
On an AMP platform, the system may include multiple processors:
- MCUs 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 <brgl@bgdev.pl>
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 | 568 ++++++++++++++++++++++++++++++++++++++
3 files changed, 586 insertions(+)
create mode 100644 drivers/gpio/gpio-rpmsg.c
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 020e51e30317..4ad299fe3c6f 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1917,6 +1917,23 @@ config GPIO_SODAVILLE
endmenu
+menu "RPMSG GPIO drivers"
+ depends on RPMSG
+
+config GPIO_RPMSG
+ tristate "Generic RPMSG GPIO support"
+ depends on OF && REMOTEPROC
+ select GPIOLIB_IRQCHIP
+ default REMOTEPROC
+ 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_MASTER
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index b267598b517d..ee75c0e65b8b 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -157,6 +157,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.o
diff --git a/drivers/gpio/gpio-rpmsg.c b/drivers/gpio/gpio-rpmsg.c
new file mode 100644
index 000000000000..332e2925a830
--- /dev/null
+++ b/drivers/gpio/gpio-rpmsg.c
@@ -0,0 +1,568 @@
+// 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.
+ */
+
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio/driver.h>
+#include <linux/init.h>
+#include <linux/irqdomain.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/remoteproc.h>
+#include <linux/rpmsg.h>
+#include <linux/virtio_gpio.h>
+
+#define GPIOS_PER_PORT_DEFAULT 32
+#define RPMSG_TIMEOUT 1000
+
+/* Additional commands beyond virtio-gpio */
+#define VIRTIO_GPIO_MSG_SET_WAKEUP 0x0010
+
+/* GPIO Receive MSG Type */
+#define GPIO_RPMSG_REPLY 1
+#define GPIO_RPMSG_NOTIFY 2
+
+#define CHAN_NAME_PREFIX "rpmsg-io-"
+#define GPIO_COMPAT_STR "rpmsg-gpio"
+
+struct rpmsg_gpio_response {
+ __u8 type;
+ union {
+ /* command reply */
+ struct {
+ __u8 status;
+ __u8 value;
+ };
+
+ /* interrupt notification */
+ struct {
+ __u8 line;
+ __u8 trigger; /* rising/falling/high/low */
+ };
+ };
+};
+
+struct rpmsg_gpio_line {
+ u8 irq_shutdown;
+ u8 irq_unmask;
+ u8 irq_mask;
+ u32 irq_wake_enable;
+ u32 irq_type;
+};
+
+struct rpmsg_gpio_port {
+ struct gpio_chip gc;
+ struct rpmsg_device *rpdev;
+ struct virtio_gpio_request *send_msg;
+ struct rpmsg_gpio_response *recv_msg;
+ struct completion cmd_complete;
+ struct mutex lock;
+ u32 ngpios;
+ u32 idx;
+ struct rpmsg_gpio_line lines[GPIOS_PER_PORT_DEFAULT];
+};
+
+static int rpmsg_gpio_send_message(struct rpmsg_gpio_port *port)
+{
+ int ret;
+
+ reinit_completion(&port->cmd_complete);
+
+ ret = rpmsg_send(port->rpdev->ept, port->send_msg, sizeof(*port->send_msg));
+ if (ret) {
+ dev_err(&port->rpdev->dev, "rpmsg_send failed: cmd=%d ret=%d\n",
+ port->send_msg->type, ret);
+ return ret;
+ }
+
+ ret = wait_for_completion_timeout(&port->cmd_complete,
+ msecs_to_jiffies(RPMSG_TIMEOUT));
+ if (ret == 0) {
+ dev_err(&port->rpdev->dev, "rpmsg_send timeout! cmd=%d\n",
+ port->send_msg->type);
+ return -ETIMEDOUT;
+ }
+
+ if (unlikely(port->recv_msg->status != VIRTIO_GPIO_STATUS_OK)) {
+ dev_err(&port->rpdev->dev, "remote core replies an error: cmd=%d!\n",
+ port->send_msg->type);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct virtio_gpio_request *
+rpmsg_gpio_msg_prepare(struct rpmsg_gpio_port *port, u16 line, u16 cmd, u32 val)
+{
+ struct virtio_gpio_request *msg = port->send_msg;
+
+ msg->type = cmd;
+ msg->gpio = line;
+ msg->value = val;
+
+ return msg;
+}
+
+static int rpmsg_gpio_get(struct gpio_chip *gc, unsigned int line)
+{
+ struct rpmsg_gpio_port *port = gpiochip_get_data(gc);
+ int ret;
+
+ guard(mutex)(&port->lock);
+
+ rpmsg_gpio_msg_prepare(port, line, VIRTIO_GPIO_MSG_GET_VALUE, 0);
+
+ ret = rpmsg_gpio_send_message(port);
+ return ret ? ret : port->recv_msg->value;
+}
+
+static int rpmsg_gpio_get_direction(struct gpio_chip *gc, unsigned int line)
+{
+ struct rpmsg_gpio_port *port = gpiochip_get_data(gc);
+ int ret;
+
+ guard(mutex)(&port->lock);
+
+ rpmsg_gpio_msg_prepare(port, line, VIRTIO_GPIO_MSG_GET_DIRECTION, 0);
+
+ ret = rpmsg_gpio_send_message(port);
+ if (ret)
+ return ret;
+
+ switch (port->recv_msg->value) {
+ case VIRTIO_GPIO_DIRECTION_IN:
+ return GPIO_LINE_DIRECTION_IN;
+ case VIRTIO_GPIO_DIRECTION_OUT:
+ return GPIO_LINE_DIRECTION_OUT;
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static int rpmsg_gpio_direction_input(struct gpio_chip *gc, unsigned int line)
+{
+ struct rpmsg_gpio_port *port = gpiochip_get_data(gc);
+
+ guard(mutex)(&port->lock);
+
+ rpmsg_gpio_msg_prepare(port, line, VIRTIO_GPIO_MSG_SET_DIRECTION,
+ VIRTIO_GPIO_DIRECTION_IN);
+
+ return rpmsg_gpio_send_message(port);
+}
+
+static int rpmsg_gpio_set(struct gpio_chip *gc, unsigned int line, int val)
+{
+ struct rpmsg_gpio_port *port = gpiochip_get_data(gc);
+
+ guard(mutex)(&port->lock);
+
+ rpmsg_gpio_msg_prepare(port, line, VIRTIO_GPIO_MSG_SET_VALUE, val);
+
+ return rpmsg_gpio_send_message(port);
+}
+
+static int rpmsg_gpio_direction_output(struct gpio_chip *gc, unsigned int line, int val)
+{
+ struct rpmsg_gpio_port *port = gpiochip_get_data(gc);
+ int ret;
+
+ guard(mutex)(&port->lock);
+
+ rpmsg_gpio_msg_prepare(port, line, VIRTIO_GPIO_MSG_SET_DIRECTION,
+ VIRTIO_GPIO_DIRECTION_OUT);
+
+ ret = rpmsg_gpio_send_message(port);
+ if (ret)
+ return ret;
+
+ rpmsg_gpio_msg_prepare(port, line, VIRTIO_GPIO_MSG_SET_VALUE, val);
+
+ return rpmsg_gpio_send_message(port);
+}
+
+static int gpio_rpmsg_irq_set_type(struct irq_data *d, u32 type)
+{
+ struct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);
+ u32 line = d->hwirq;
+
+ switch (type) {
+ case IRQ_TYPE_EDGE_RISING:
+ type = VIRTIO_GPIO_IRQ_TYPE_EDGE_RISING;
+ irq_set_handler_locked(d, handle_simple_irq);
+ break;
+ case IRQ_TYPE_EDGE_FALLING:
+ type = VIRTIO_GPIO_IRQ_TYPE_EDGE_FALLING;
+ irq_set_handler_locked(d, handle_simple_irq);
+ break;
+ case IRQ_TYPE_EDGE_BOTH:
+ type = VIRTIO_GPIO_IRQ_TYPE_EDGE_BOTH;
+ irq_set_handler_locked(d, handle_simple_irq);
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ type = VIRTIO_GPIO_IRQ_TYPE_LEVEL_LOW;
+ irq_set_handler_locked(d, handle_level_irq);
+ break;
+ case IRQ_TYPE_LEVEL_HIGH:
+ type = VIRTIO_GPIO_IRQ_TYPE_LEVEL_HIGH;
+ irq_set_handler_locked(d, handle_level_irq);
+ break;
+ default:
+ dev_err(&port->rpdev->dev, "unsupported irq type: %u\n", type);
+ return -EINVAL;
+ }
+
+ port->lines[line].irq_type = type;
+
+ return 0;
+}
+
+static int gpio_rpmsg_irq_set_wake(struct irq_data *d, u32 enable)
+{
+ struct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);
+ u32 line = d->hwirq;
+
+ port->lines[line].irq_wake_enable = enable;
+
+ return 0;
+}
+
+/*
+ * This unmask/mask function is invoked in two situations:
+ * - when an interrupt is being set up, and
+ * - after an interrupt has occurred.
+ *
+ * The GPIO driver does not access hardware registers directly.
+ * Instead, it caches all relevant information locally, and then sends
+ * the accumulated state to the remote system at this stage.
+ */
+static void gpio_rpmsg_unmask_irq(struct irq_data *d)
+{
+ struct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);
+ u32 line = d->hwirq;
+
+ port->lines[line].irq_unmask = 1;
+}
+
+static void gpio_rpmsg_mask_irq(struct irq_data *d)
+{
+ struct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);
+ u32 line = d->hwirq;
+
+ /*
+ * When an interrupt occurs, the remote system masks the interrupt
+ * and then sends a notification to Linux. After Linux processes
+ * that notification, it sends an RPMsg command back to the remote
+ * system to unmask the interrupt again.
+ */
+ port->lines[line].irq_mask = 1;
+}
+
+static void gpio_rpmsg_irq_shutdown(struct irq_data *d)
+{
+ struct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);
+ u32 line = d->hwirq;
+
+ port->lines[line].irq_shutdown = 1;
+}
+
+static void gpio_rpmsg_irq_bus_lock(struct irq_data *d)
+{
+ struct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);
+
+ mutex_lock(&port->lock);
+}
+
+static void gpio_rpmsg_irq_bus_sync_unlock(struct irq_data *d)
+{
+ struct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);
+ u32 line = d->hwirq;
+
+ rpmsg_gpio_msg_prepare(port, line, VIRTIO_GPIO_MSG_SET_WAKEUP,
+ port->lines[line].irq_wake_enable);
+ rpmsg_gpio_send_message(port);
+
+ /*
+ * For mask irq, do nothing here.
+ * The remote system will mask interrupt after an interrupt occurs,
+ * and then send a notification to Linux system. After Linux system
+ * handles the notification, it sends an rpmsg back to the remote
+ * system to unmask this interrupt again.
+ */
+ if (port->lines[line].irq_mask && !port->lines[line].irq_unmask) {
+ port->lines[line].irq_mask = 0;
+ mutex_unlock(&port->lock);
+ return;
+ }
+
+ if (port->lines[line].irq_shutdown) {
+ rpmsg_gpio_msg_prepare(port, line, VIRTIO_GPIO_MSG_IRQ_TYPE,
+ VIRTIO_GPIO_IRQ_TYPE_NONE);
+ port->lines[line].irq_shutdown = 0;
+ } else {
+ rpmsg_gpio_msg_prepare(port, line, VIRTIO_GPIO_MSG_IRQ_TYPE,
+ port->lines[line].irq_type);
+
+ if (port->lines[line].irq_unmask)
+ port->lines[line].irq_unmask = 0;
+ }
+
+ rpmsg_gpio_send_message(port);
+ mutex_unlock(&port->lock);
+}
+
+static const struct irq_chip gpio_rpmsg_irq_chip = {
+ .irq_mask = gpio_rpmsg_mask_irq,
+ .irq_unmask = gpio_rpmsg_unmask_irq,
+ .irq_set_wake = gpio_rpmsg_irq_set_wake,
+ .irq_set_type = gpio_rpmsg_irq_set_type,
+ .irq_shutdown = gpio_rpmsg_irq_shutdown,
+ .irq_bus_lock = gpio_rpmsg_irq_bus_lock,
+ .irq_bus_sync_unlock = gpio_rpmsg_irq_bus_sync_unlock,
+ .flags = IRQCHIP_IMMUTABLE,
+};
+
+static int rpmsg_gpiochip_register(struct rpmsg_device *rpdev,
+ struct device_node *np, const char *name)
+{
+ struct rpmsg_gpio_port *port;
+ struct gpio_irq_chip *girq;
+ struct gpio_chip *gc;
+ int ret;
+
+ port = devm_kzalloc(&rpdev->dev, sizeof(*port), GFP_KERNEL);
+ if (!port)
+ return -ENOMEM;
+
+ ret = of_property_read_u32(np, "reg", &port->idx);
+ if (ret)
+ return ret;
+
+ ret = devm_mutex_init(&rpdev->dev, &port->lock);
+ if (ret)
+ return ret;
+
+ ret = of_property_read_u32(np, "ngpios", &port->ngpios);
+ if (ret || port->ngpios > GPIOS_PER_PORT_DEFAULT)
+ port->ngpios = GPIOS_PER_PORT_DEFAULT;
+
+ port->send_msg = devm_kzalloc(&rpdev->dev,
+ sizeof(*port->send_msg),
+ GFP_KERNEL);
+
+ port->recv_msg = devm_kzalloc(&rpdev->dev,
+ sizeof(*port->recv_msg),
+ GFP_KERNEL);
+ if (!port->send_msg || !port->recv_msg)
+ return -ENOMEM;
+
+ init_completion(&port->cmd_complete);
+ port->rpdev = rpdev;
+
+ gc = &port->gc;
+ gc->owner = THIS_MODULE;
+ gc->parent = &rpdev->dev;
+ gc->fwnode = of_fwnode_handle(np);
+ gc->ngpio = port->ngpios;
+ gc->base = -1;
+ gc->label = devm_kasprintf(&rpdev->dev, GFP_KERNEL, "%s-gpio%d",
+ name, port->idx);
+
+ gc->direction_input = rpmsg_gpio_direction_input;
+ gc->direction_output = rpmsg_gpio_direction_output;
+ gc->get_direction = rpmsg_gpio_get_direction;
+ gc->get = rpmsg_gpio_get;
+ gc->set = rpmsg_gpio_set;
+
+ girq = &gc->irq;
+ gpio_irq_chip_set_chip(girq, &gpio_rpmsg_irq_chip);
+ girq->parent_handler = NULL;
+ girq->num_parents = 0;
+ girq->parents = NULL;
+ girq->chip->name = devm_kstrdup(&rpdev->dev, gc->label, GFP_KERNEL);
+
+ dev_set_drvdata(&rpdev->dev, port);
+
+ return devm_gpiochip_add_data(&rpdev->dev, gc, port);
+}
+
+static const char *rpmsg_get_rproc_node_name(struct rpmsg_device *rpdev)
+{
+ const char *name = NULL;
+ struct device_node *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) {
+ name = devm_kstrdup(&rpdev->dev, np->name, GFP_KERNEL);
+ of_node_put(np);
+ }
+
+ return name;
+}
+
+static struct device_node *
+rpmsg_find_child_by_compat_reg(struct device_node *parent, const char *compat, u32 idx)
+{
+ struct device_node *child;
+ u32 reg;
+
+ for_each_available_child_of_node(parent, child) {
+ if (!of_device_is_compatible(child, compat))
+ continue;
+
+ if (of_property_read_u32(child, "reg", ®))
+ continue;
+
+ if (reg == idx)
+ return child;
+ }
+
+ return NULL;
+}
+
+static struct device_node *
+rpmsg_get_channel_ofnode(struct rpmsg_device *rpdev, const char *compat, u32 idx)
+{
+ 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)
+ np_chan = rpmsg_find_child_by_compat_reg(np, compat, idx);
+
+ return np_chan;
+}
+
+static int rpmsg_get_gpio_index(const char *name, const char *prefix)
+{
+ const char *p;
+ int base = 10;
+ int val;
+
+ if (!name)
+ return -EINVAL;
+
+ /* Ensure correct prefix */
+ if (!str_has_prefix(name, prefix))
+ return -EINVAL;
+
+ /* Find last '-' */
+ p = strrchr(name, '-');
+
+ if (!p || *(p + 1) == '\0')
+ return -EINVAL;
+
+ if (p[1] == '0' && (p[2] == 'x' || p[2] == 'X'))
+ base = 16;
+
+ if (kstrtoint(p + 1, base, &val))
+ return -EINVAL;
+
+ return val;
+}
+
+static int rpmsg_gpio_channel_callback(struct rpmsg_device *rpdev, void *data,
+ int len, void *priv, u32 src)
+{
+ struct rpmsg_gpio_response *msg = data;
+ struct rpmsg_gpio_port *port = NULL;
+
+ port = dev_get_drvdata(&rpdev->dev);
+
+ if (!port) {
+ dev_err(&rpdev->dev, "port is null\n");
+ return -EINVAL;
+ }
+
+ if (msg->type == GPIO_RPMSG_REPLY) {
+ *port->recv_msg = *msg;
+ complete(&port->cmd_complete);
+ } else if (msg->type == GPIO_RPMSG_NOTIFY) {
+ generic_handle_domain_irq_safe(port->gc.irq.domain, msg->line);
+ } else {
+ dev_err(&rpdev->dev, "wrong message type (0x%x)\n", msg->type);
+ }
+
+ return 0;
+}
+
+static int rpmsg_gpio_channel_probe(struct rpmsg_device *rpdev)
+{
+ struct device *dev = &rpdev->dev;
+ struct device_node *np;
+ const char *rproc_name;
+ int idx;
+
+ idx = rpmsg_get_gpio_index(rpdev->id.name, CHAN_NAME_PREFIX);
+ if (idx < 0)
+ return -EINVAL;
+
+ if (!dev->of_node) {
+ np = rpmsg_get_channel_ofnode(rpdev, GPIO_COMPAT_STR, idx);
+ if (!np)
+ return -ENODEV;
+
+ dev->of_node = np;
+ set_primary_fwnode(dev, of_fwnode_handle(np));
+ return -EPROBE_DEFER;
+ }
+
+ rproc_name = rpmsg_get_rproc_node_name(rpdev);
+
+ return rpmsg_gpiochip_register(rpdev, dev->of_node, rproc_name);
+}
+
+static const struct of_device_id rpmsg_gpio_dt_ids[] = {
+ { .compatible = GPIO_COMPAT_STR },
+ { /* sentinel */ }
+};
+
+static struct rpmsg_device_id rpmsg_gpio_channel_id_table[] = {
+ { .name = CHAN_NAME_PREFIX },
+ { },
+};
+MODULE_DEVICE_TABLE(rpmsg, rpmsg_gpio_channel_id_table);
+
+static struct rpmsg_driver rpmsg_gpio_channel_client = {
+ .callback = rpmsg_gpio_channel_callback,
+ .id_table = rpmsg_gpio_channel_id_table,
+ .probe = rpmsg_gpio_channel_probe,
+ .drv = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = rpmsg_gpio_dt_ids,
+ },
+};
+module_rpmsg_driver(rpmsg_gpio_channel_client);
+
+MODULE_AUTHOR("Shenwei Wang <shenwei.wang@nxp.com>");
+MODULE_DESCRIPTION("generic rpmsg gpio driver");
+MODULE_LICENSE("GPL");
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH v14 5/5] arm64: dts: imx8ulp: Add rpmsg node under imx_rproc
2026-06-25 15:54 [PATCH v14 0/5] Enable Remote GPIO over RPMSG on i.MX Platform Shenwei Wang
` (3 preceding siblings ...)
2026-06-25 15:54 ` [PATCH v14 4/5] gpio: rpmsg: add generic rpmsg GPIO driver Shenwei Wang
@ 2026-06-25 15:54 ` Shenwei Wang
2026-07-06 15:40 ` [PATCH v14 0/5] Enable Remote GPIO over RPMSG on i.MX Platform Shenwei Wang (OSS)
5 siblings, 0 replies; 17+ messages in thread
From: Shenwei Wang @ 2026-06-25 15:54 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Jonathan Corbet, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Mathieu Poirier, Frank Li, Sascha Hauer
Cc: Shuah Khan, linux-gpio, linux-doc, linux-kernel,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan,
devicetree, linux-remoteproc, imx, linux-arm-kernel, linux-imx,
Arnaud POULIQUEN, b-padhi, Andrew Lunn
From: Shenwei Wang <shenwei.wang@nxp.com>
Add the RPMSG bus node along with its GPIO subnodes to the device
tree.
Enable remote device communication and GPIO control via RPMSG on
the i.MX platform.
Signed-off-by: Shenwei Wang <shenwei.wang@nxp.com>
---
arch/arm64/boot/dts/freescale/imx8ulp.dtsi | 25 ++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
index 1de3ad60c6aa..f1b984eb1203 100644
--- a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
@@ -190,6 +190,31 @@ scmi_sensor: protocol@15 {
cm33: remoteproc-cm33 {
compatible = "fsl,imx8ulp-cm33";
status = "disabled";
+
+ rpmsg {
+ rpmsg-io {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rpmsg_gpioa: gpio@0 {
+ compatible = "rpmsg-gpio";
+ reg = <0>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ };
+
+ rpmsg_gpiob: gpio@1 {
+ compatible = "rpmsg-gpio";
+ reg = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ };
+ };
+ };
};
soc: soc@0 {
--
2.43.0
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH v14 4/5] gpio: rpmsg: add generic rpmsg GPIO driver
2026-06-25 15:54 ` [PATCH v14 4/5] gpio: rpmsg: add generic rpmsg GPIO driver Shenwei Wang
@ 2026-06-25 20:32 ` Andrew Davis
2026-06-29 18:26 ` Shenwei Wang (OSS)
2026-06-25 22:17 ` Julian Braha
1 sibling, 1 reply; 17+ messages in thread
From: Andrew Davis @ 2026-06-25 20:32 UTC (permalink / raw)
To: Shenwei Wang, Linus Walleij, Bartosz Golaszewski, Jonathan Corbet,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Mathieu Poirier, Frank Li, Sascha Hauer
Cc: Shuah Khan, linux-gpio, linux-doc, linux-kernel,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan,
devicetree, linux-remoteproc, imx, linux-arm-kernel, linux-imx,
Arnaud POULIQUEN, b-padhi, Andrew Lunn, Bartosz Golaszewski
On 6/25/26 10:54 AM, Shenwei Wang wrote:
> From: Shenwei Wang <shenwei.wang@nxp.com>
>
> On an AMP platform, the system may include multiple processors:
> - MCUs 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 <brgl@bgdev.pl>
> 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 | 568 ++++++++++++++++++++++++++++++++++++++
> 3 files changed, 586 insertions(+)
> create mode 100644 drivers/gpio/gpio-rpmsg.c
>
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index 020e51e30317..4ad299fe3c6f 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -1917,6 +1917,23 @@ config GPIO_SODAVILLE
>
> endmenu
>
> +menu "RPMSG GPIO drivers"
> + depends on RPMSG
> +
> +config GPIO_RPMSG
> + tristate "Generic RPMSG GPIO support"
> + depends on OF && REMOTEPROC
> + select GPIOLIB_IRQCHIP
> + default REMOTEPROC
> + 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.
The support would depend on if the right firmware is loaded/running on the given
remote core. Also if you want to make this generic, then any vendor should be able
to make a firmware that implements this protocol and make use of this driver.
Suggest dropping this NXP specific device list.
> +
> + If unsure, say N.
> +
> +endmenu
> +
> menu "SPI GPIO expanders"
> depends on SPI_MASTER
>
> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
> index b267598b517d..ee75c0e65b8b 100644
> --- a/drivers/gpio/Makefile
> +++ b/drivers/gpio/Makefile
> @@ -157,6 +157,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.o
> diff --git a/drivers/gpio/gpio-rpmsg.c b/drivers/gpio/gpio-rpmsg.c
> new file mode 100644
> index 000000000000..332e2925a830
> --- /dev/null
> +++ b/drivers/gpio/gpio-rpmsg.c
> @@ -0,0 +1,568 @@
> +// 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.
> + */
> +
> +#include <linux/completion.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/gpio/driver.h>
> +#include <linux/init.h>
> +#include <linux/irqdomain.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/module.h>
> +#include <linux/mutex.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/remoteproc.h>
> +#include <linux/rpmsg.h>
> +#include <linux/virtio_gpio.h>
> +
> +#define GPIOS_PER_PORT_DEFAULT 32
> +#define RPMSG_TIMEOUT 1000
> +
> +/* Additional commands beyond virtio-gpio */
> +#define VIRTIO_GPIO_MSG_SET_WAKEUP 0x0010
> +
> +/* GPIO Receive MSG Type */
> +#define GPIO_RPMSG_REPLY 1
> +#define GPIO_RPMSG_NOTIFY 2
> +
> +#define CHAN_NAME_PREFIX "rpmsg-io-"
> +#define GPIO_COMPAT_STR "rpmsg-gpio"
> +
> +struct rpmsg_gpio_response {
> + __u8 type;
> + union {
> + /* command reply */
> + struct {
> + __u8 status;
> + __u8 value;
> + };
> +
> + /* interrupt notification */
> + struct {
> + __u8 line;
> + __u8 trigger; /* rising/falling/high/low */
> + };
> + };
> +};
> +
> +struct rpmsg_gpio_line {
> + u8 irq_shutdown;
> + u8 irq_unmask;
> + u8 irq_mask;
> + u32 irq_wake_enable;
> + u32 irq_type;
> +};
> +
> +struct rpmsg_gpio_port {
> + struct gpio_chip gc;
> + struct rpmsg_device *rpdev;
> + struct virtio_gpio_request *send_msg;
> + struct rpmsg_gpio_response *recv_msg;
> + struct completion cmd_complete;
> + struct mutex lock;
> + u32 ngpios;
> + u32 idx;
> + struct rpmsg_gpio_line lines[GPIOS_PER_PORT_DEFAULT];
> +};
> +
> +static int rpmsg_gpio_send_message(struct rpmsg_gpio_port *port)
> +{
> + int ret;
> +
> + reinit_completion(&port->cmd_complete);
> +
> + ret = rpmsg_send(port->rpdev->ept, port->send_msg, sizeof(*port->send_msg));
> + if (ret) {
> + dev_err(&port->rpdev->dev, "rpmsg_send failed: cmd=%d ret=%d\n",
> + port->send_msg->type, ret);
> + return ret;
> + }
> +
> + ret = wait_for_completion_timeout(&port->cmd_complete,
> + msecs_to_jiffies(RPMSG_TIMEOUT));
> + if (ret == 0) {
> + dev_err(&port->rpdev->dev, "rpmsg_send timeout! cmd=%d\n",
> + port->send_msg->type);
> + return -ETIMEDOUT;
> + }
> +
> + if (unlikely(port->recv_msg->status != VIRTIO_GPIO_STATUS_OK)) {
> + dev_err(&port->rpdev->dev, "remote core replies an error: cmd=%d!\n",
> + port->send_msg->type);
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +static struct virtio_gpio_request *
> +rpmsg_gpio_msg_prepare(struct rpmsg_gpio_port *port, u16 line, u16 cmd, u32 val)
> +{
> + struct virtio_gpio_request *msg = port->send_msg;
> +
> + msg->type = cmd;
> + msg->gpio = line;
> + msg->value = val;
> +
> + return msg;
> +}
> +
> +static int rpmsg_gpio_get(struct gpio_chip *gc, unsigned int line)
> +{
> + struct rpmsg_gpio_port *port = gpiochip_get_data(gc);
> + int ret;
> +
> + guard(mutex)(&port->lock);
> +
> + rpmsg_gpio_msg_prepare(port, line, VIRTIO_GPIO_MSG_GET_VALUE, 0);
> +
> + ret = rpmsg_gpio_send_message(port);
> + return ret ? ret : port->recv_msg->value;
> +}
> +
> +static int rpmsg_gpio_get_direction(struct gpio_chip *gc, unsigned int line)
> +{
> + struct rpmsg_gpio_port *port = gpiochip_get_data(gc);
> + int ret;
> +
> + guard(mutex)(&port->lock);
> +
> + rpmsg_gpio_msg_prepare(port, line, VIRTIO_GPIO_MSG_GET_DIRECTION, 0);
> +
> + ret = rpmsg_gpio_send_message(port);
> + if (ret)
> + return ret;
> +
> + switch (port->recv_msg->value) {
> + case VIRTIO_GPIO_DIRECTION_IN:
> + return GPIO_LINE_DIRECTION_IN;
> + case VIRTIO_GPIO_DIRECTION_OUT:
> + return GPIO_LINE_DIRECTION_OUT;
> + default:
> + break;
> + }
> +
> + return -EINVAL;
> +}
> +
> +static int rpmsg_gpio_direction_input(struct gpio_chip *gc, unsigned int line)
> +{
> + struct rpmsg_gpio_port *port = gpiochip_get_data(gc);
> +
> + guard(mutex)(&port->lock);
> +
> + rpmsg_gpio_msg_prepare(port, line, VIRTIO_GPIO_MSG_SET_DIRECTION,
> + VIRTIO_GPIO_DIRECTION_IN);
> +
> + return rpmsg_gpio_send_message(port);
> +}
> +
> +static int rpmsg_gpio_set(struct gpio_chip *gc, unsigned int line, int val)
> +{
> + struct rpmsg_gpio_port *port = gpiochip_get_data(gc);
> +
> + guard(mutex)(&port->lock);
> +
> + rpmsg_gpio_msg_prepare(port, line, VIRTIO_GPIO_MSG_SET_VALUE, val);
> +
> + return rpmsg_gpio_send_message(port);
> +}
> +
> +static int rpmsg_gpio_direction_output(struct gpio_chip *gc, unsigned int line, int val)
> +{
> + struct rpmsg_gpio_port *port = gpiochip_get_data(gc);
> + int ret;
> +
> + guard(mutex)(&port->lock);
> +
> + rpmsg_gpio_msg_prepare(port, line, VIRTIO_GPIO_MSG_SET_DIRECTION,
> + VIRTIO_GPIO_DIRECTION_OUT);
> +
> + ret = rpmsg_gpio_send_message(port);
> + if (ret)
> + return ret;
> +
> + rpmsg_gpio_msg_prepare(port, line, VIRTIO_GPIO_MSG_SET_VALUE, val);
> +
> + return rpmsg_gpio_send_message(port);
> +}
> +
> +static int gpio_rpmsg_irq_set_type(struct irq_data *d, u32 type)
> +{
> + struct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);
> + u32 line = d->hwirq;
> +
> + switch (type) {
> + case IRQ_TYPE_EDGE_RISING:
> + type = VIRTIO_GPIO_IRQ_TYPE_EDGE_RISING;
> + irq_set_handler_locked(d, handle_simple_irq);
> + break;
> + case IRQ_TYPE_EDGE_FALLING:
> + type = VIRTIO_GPIO_IRQ_TYPE_EDGE_FALLING;
> + irq_set_handler_locked(d, handle_simple_irq);
> + break;
> + case IRQ_TYPE_EDGE_BOTH:
> + type = VIRTIO_GPIO_IRQ_TYPE_EDGE_BOTH;
> + irq_set_handler_locked(d, handle_simple_irq);
> + break;
> + case IRQ_TYPE_LEVEL_LOW:
> + type = VIRTIO_GPIO_IRQ_TYPE_LEVEL_LOW;
> + irq_set_handler_locked(d, handle_level_irq);
> + break;
> + case IRQ_TYPE_LEVEL_HIGH:
> + type = VIRTIO_GPIO_IRQ_TYPE_LEVEL_HIGH;
> + irq_set_handler_locked(d, handle_level_irq);
> + break;
> + default:
> + dev_err(&port->rpdev->dev, "unsupported irq type: %u\n", type);
> + return -EINVAL;
> + }
> +
> + port->lines[line].irq_type = type;
> +
> + return 0;
> +}
> +
> +static int gpio_rpmsg_irq_set_wake(struct irq_data *d, u32 enable)
> +{
> + struct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);
> + u32 line = d->hwirq;
> +
> + port->lines[line].irq_wake_enable = enable;
> +
> + return 0;
> +}
> +
> +/*
> + * This unmask/mask function is invoked in two situations:
> + * - when an interrupt is being set up, and
> + * - after an interrupt has occurred.
> + *
> + * The GPIO driver does not access hardware registers directly.
> + * Instead, it caches all relevant information locally, and then sends
> + * the accumulated state to the remote system at this stage.
> + */
> +static void gpio_rpmsg_unmask_irq(struct irq_data *d)
> +{
> + struct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);
> + u32 line = d->hwirq;
> +
> + port->lines[line].irq_unmask = 1;
> +}
> +
> +static void gpio_rpmsg_mask_irq(struct irq_data *d)
> +{
> + struct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);
> + u32 line = d->hwirq;
> +
> + /*
> + * When an interrupt occurs, the remote system masks the interrupt
> + * and then sends a notification to Linux. After Linux processes
> + * that notification, it sends an RPMsg command back to the remote
> + * system to unmask the interrupt again.
> + */
> + port->lines[line].irq_mask = 1;
> +}
> +
> +static void gpio_rpmsg_irq_shutdown(struct irq_data *d)
> +{
> + struct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);
> + u32 line = d->hwirq;
> +
> + port->lines[line].irq_shutdown = 1;
> +}
> +
> +static void gpio_rpmsg_irq_bus_lock(struct irq_data *d)
> +{
> + struct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);
> +
> + mutex_lock(&port->lock);
> +}
> +
> +static void gpio_rpmsg_irq_bus_sync_unlock(struct irq_data *d)
> +{
> + struct rpmsg_gpio_port *port = irq_data_get_irq_chip_data(d);
> + u32 line = d->hwirq;
> +
> + rpmsg_gpio_msg_prepare(port, line, VIRTIO_GPIO_MSG_SET_WAKEUP,
> + port->lines[line].irq_wake_enable);
> + rpmsg_gpio_send_message(port);
> +
> + /*
> + * For mask irq, do nothing here.
> + * The remote system will mask interrupt after an interrupt occurs,
> + * and then send a notification to Linux system. After Linux system
> + * handles the notification, it sends an rpmsg back to the remote
> + * system to unmask this interrupt again.
> + */
> + if (port->lines[line].irq_mask && !port->lines[line].irq_unmask) {
> + port->lines[line].irq_mask = 0;
> + mutex_unlock(&port->lock);
> + return;
> + }
> +
> + if (port->lines[line].irq_shutdown) {
> + rpmsg_gpio_msg_prepare(port, line, VIRTIO_GPIO_MSG_IRQ_TYPE,
> + VIRTIO_GPIO_IRQ_TYPE_NONE);
> + port->lines[line].irq_shutdown = 0;
> + } else {
> + rpmsg_gpio_msg_prepare(port, line, VIRTIO_GPIO_MSG_IRQ_TYPE,
> + port->lines[line].irq_type);
> +
> + if (port->lines[line].irq_unmask)
> + port->lines[line].irq_unmask = 0;
> + }
> +
> + rpmsg_gpio_send_message(port);
> + mutex_unlock(&port->lock);
> +}
> +
> +static const struct irq_chip gpio_rpmsg_irq_chip = {
> + .irq_mask = gpio_rpmsg_mask_irq,
> + .irq_unmask = gpio_rpmsg_unmask_irq,
> + .irq_set_wake = gpio_rpmsg_irq_set_wake,
> + .irq_set_type = gpio_rpmsg_irq_set_type,
> + .irq_shutdown = gpio_rpmsg_irq_shutdown,
> + .irq_bus_lock = gpio_rpmsg_irq_bus_lock,
> + .irq_bus_sync_unlock = gpio_rpmsg_irq_bus_sync_unlock,
> + .flags = IRQCHIP_IMMUTABLE,
> +};
> +
> +static int rpmsg_gpiochip_register(struct rpmsg_device *rpdev,
> + struct device_node *np, const char *name)
> +{
> + struct rpmsg_gpio_port *port;
> + struct gpio_irq_chip *girq;
> + struct gpio_chip *gc;
> + int ret;
> +
> + port = devm_kzalloc(&rpdev->dev, sizeof(*port), GFP_KERNEL);
> + if (!port)
> + return -ENOMEM;
> +
> + ret = of_property_read_u32(np, "reg", &port->idx);
> + if (ret)
> + return ret;
> +
> + ret = devm_mutex_init(&rpdev->dev, &port->lock);
> + if (ret)
> + return ret;
> +
> + ret = of_property_read_u32(np, "ngpios", &port->ngpios);
> + if (ret || port->ngpios > GPIOS_PER_PORT_DEFAULT)
> + port->ngpios = GPIOS_PER_PORT_DEFAULT;
> +
> + port->send_msg = devm_kzalloc(&rpdev->dev,
> + sizeof(*port->send_msg),
> + GFP_KERNEL);
> +
> + port->recv_msg = devm_kzalloc(&rpdev->dev,
> + sizeof(*port->recv_msg),
> + GFP_KERNEL);
> + if (!port->send_msg || !port->recv_msg)
> + return -ENOMEM;
> +
> + init_completion(&port->cmd_complete);
> + port->rpdev = rpdev;
> +
> + gc = &port->gc;
> + gc->owner = THIS_MODULE;
> + gc->parent = &rpdev->dev;
> + gc->fwnode = of_fwnode_handle(np);
> + gc->ngpio = port->ngpios;
> + gc->base = -1;
> + gc->label = devm_kasprintf(&rpdev->dev, GFP_KERNEL, "%s-gpio%d",
> + name, port->idx);
> +
> + gc->direction_input = rpmsg_gpio_direction_input;
> + gc->direction_output = rpmsg_gpio_direction_output;
> + gc->get_direction = rpmsg_gpio_get_direction;
> + gc->get = rpmsg_gpio_get;
> + gc->set = rpmsg_gpio_set;
> +
> + girq = &gc->irq;
> + gpio_irq_chip_set_chip(girq, &gpio_rpmsg_irq_chip);
> + girq->parent_handler = NULL;
> + girq->num_parents = 0;
> + girq->parents = NULL;
> + girq->chip->name = devm_kstrdup(&rpdev->dev, gc->label, GFP_KERNEL);
> +
> + dev_set_drvdata(&rpdev->dev, port);
> +
> + return devm_gpiochip_add_data(&rpdev->dev, gc, port);
> +}
> +
> +static const char *rpmsg_get_rproc_node_name(struct rpmsg_device *rpdev)
> +{
> + const char *name = NULL;
> + struct device_node *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) {
> + name = devm_kstrdup(&rpdev->dev, np->name, GFP_KERNEL);
> + of_node_put(np);
> + }
> +
> + return name;
> +}
> +
> +static struct device_node *
> +rpmsg_find_child_by_compat_reg(struct device_node *parent, const char *compat, u32 idx)
> +{
> + struct device_node *child;
> + u32 reg;
> +
> + for_each_available_child_of_node(parent, child) {
> + if (!of_device_is_compatible(child, compat))
> + continue;
> +
> + if (of_property_read_u32(child, "reg", ®))
> + continue;
> +
> + if (reg == idx)
> + return child;
> + }
> +
> + return NULL;
> +}
> +
> +static struct device_node *
> +rpmsg_get_channel_ofnode(struct rpmsg_device *rpdev, const char *compat, u32 idx)
> +{
> + 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)
> + np_chan = rpmsg_find_child_by_compat_reg(np, compat, idx);
> +
> + return np_chan;
> +}
> +
> +static int rpmsg_get_gpio_index(const char *name, const char *prefix)
> +{
> + const char *p;
> + int base = 10;
> + int val;
> +
> + if (!name)
> + return -EINVAL;
> +
> + /* Ensure correct prefix */
> + if (!str_has_prefix(name, prefix))
> + return -EINVAL;
> +
> + /* Find last '-' */
> + p = strrchr(name, '-');
> +
> + if (!p || *(p + 1) == '\0')
> + return -EINVAL;
> +
> + if (p[1] == '0' && (p[2] == 'x' || p[2] == 'X'))
> + base = 16;
> +
> + if (kstrtoint(p + 1, base, &val))
> + return -EINVAL;
> +
> + return val;
> +}
> +
> +static int rpmsg_gpio_channel_callback(struct rpmsg_device *rpdev, void *data,
> + int len, void *priv, u32 src)
> +{
> + struct rpmsg_gpio_response *msg = data;
> + struct rpmsg_gpio_port *port = NULL;
> +
> + port = dev_get_drvdata(&rpdev->dev);
> +
> + if (!port) {
> + dev_err(&rpdev->dev, "port is null\n");
> + return -EINVAL;
> + }
> +
> + if (msg->type == GPIO_RPMSG_REPLY) {
> + *port->recv_msg = *msg;
> + complete(&port->cmd_complete);
> + } else if (msg->type == GPIO_RPMSG_NOTIFY) {
> + generic_handle_domain_irq_safe(port->gc.irq.domain, msg->line);
> + } else {
> + dev_err(&rpdev->dev, "wrong message type (0x%x)\n", msg->type);
> + }
> +
> + return 0;
> +}
> +
> +static int rpmsg_gpio_channel_probe(struct rpmsg_device *rpdev)
> +{
> + struct device *dev = &rpdev->dev;
> + struct device_node *np;
> + const char *rproc_name;
> + int idx;
> +
> + idx = rpmsg_get_gpio_index(rpdev->id.name, CHAN_NAME_PREFIX);
> + if (idx < 0)
> + return -EINVAL;
> +
> + if (!dev->of_node) {
> + np = rpmsg_get_channel_ofnode(rpdev, GPIO_COMPAT_STR, idx);
> + if (!np)
> + return -ENODEV;
This seems to imply that DT nodes are required. RPMSG is a discoverable
bus with a nameservice that can bind/probe new devices. While then optionally
binding to a DT node when available so sub-devices can be described in DT is
fine, I don't see why it should be required.
> +
> + dev->of_node = np;
> + set_primary_fwnode(dev, of_fwnode_handle(np));
> + return -EPROBE_DEFER;
> + }
> +
> + rproc_name = rpmsg_get_rproc_node_name(rpdev);
> +
> + return rpmsg_gpiochip_register(rpdev, dev->of_node, rproc_name);
> +}
> +
> +static const struct of_device_id rpmsg_gpio_dt_ids[] = {
> + { .compatible = GPIO_COMPAT_STR },
> + { /* sentinel */ }
> +};
> +
> +static struct rpmsg_device_id rpmsg_gpio_channel_id_table[] = {
> + { .name = CHAN_NAME_PREFIX },
> + { },
> +};
> +MODULE_DEVICE_TABLE(rpmsg, rpmsg_gpio_channel_id_table);
> +
> +static struct rpmsg_driver rpmsg_gpio_channel_client = {
> + .callback = rpmsg_gpio_channel_callback,
> + .id_table = rpmsg_gpio_channel_id_table,
> + .probe = rpmsg_gpio_channel_probe,
> + .drv = {
> + .name = KBUILD_MODNAME,
> + .of_match_table = rpmsg_gpio_dt_ids,
Does this line actually do anything anymore? Maybe it did when
this was a platform_driver, but this is a rpmsg_driver and
will probe though .id_table matches.
Andrew
> + },
> +};
> +module_rpmsg_driver(rpmsg_gpio_channel_client);
> +
> +MODULE_AUTHOR("Shenwei Wang <shenwei.wang@nxp.com>");
> +MODULE_DESCRIPTION("generic rpmsg gpio driver");
> +MODULE_LICENSE("GPL");
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v14 4/5] gpio: rpmsg: add generic rpmsg GPIO driver
2026-06-25 15:54 ` [PATCH v14 4/5] gpio: rpmsg: add generic rpmsg GPIO driver Shenwei Wang
2026-06-25 20:32 ` Andrew Davis
@ 2026-06-25 22:17 ` Julian Braha
1 sibling, 0 replies; 17+ messages in thread
From: Julian Braha @ 2026-06-25 22:17 UTC (permalink / raw)
To: Shenwei Wang, Linus Walleij, Bartosz Golaszewski, Jonathan Corbet,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Mathieu Poirier, Frank Li, Sascha Hauer
Cc: Shuah Khan, linux-gpio, linux-doc, linux-kernel,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan,
devicetree, linux-remoteproc, imx, linux-arm-kernel, linux-imx,
Arnaud POULIQUEN, b-padhi, Andrew Lunn, Bartosz Golaszewski
Hi Shenwei,
On 6/25/26 16:54, Shenwei Wang wrote:
> +config GPIO_RPMSG
> + tristate "Generic RPMSG GPIO support"
> + depends on OF && REMOTEPROC
> + select GPIOLIB_IRQCHIP
> + default REMOTEPROC
> + 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.
You've got GPIO_RPMSG defaulting to REMOTEPROC, which is also a
dependency, so it's effectively the same as using 'default y'.
But then you've got "If unsure, say N" in the help text. Usually this is
used when the default is N.
- Julian Braha
^ permalink raw reply [flat|nested] 17+ messages in thread
* RE: [PATCH v14 4/5] gpio: rpmsg: add generic rpmsg GPIO driver
2026-06-25 20:32 ` Andrew Davis
@ 2026-06-29 18:26 ` Shenwei Wang (OSS)
2026-06-29 19:22 ` Andrew Davis
0 siblings, 1 reply; 17+ messages in thread
From: Shenwei Wang (OSS) @ 2026-06-29 18:26 UTC (permalink / raw)
To: Andrew Davis, Linus Walleij, Bartosz Golaszewski, Jonathan Corbet,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Mathieu Poirier, Frank Li, Sascha Hauer
Cc: Shuah Khan, linux-gpio@vger.kernel.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, Pengutronix Kernel Team,
Fabio Estevam, Shenwei Wang, Peng Fan, devicetree@vger.kernel.org,
linux-remoteproc@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org, dl-linux-imx,
Arnaud POULIQUEN, b-padhi@ti.com, Andrew Lunn,
Bartosz Golaszewski
> -----Original Message-----
> From: Andrew Davis <afd@ti.com>
> Sent: Thursday, June 25, 2026 3:32 PM
...
> Subject: Re: [PATCH v14 4/5] gpio: rpmsg: add generic rpmsg GPIO driver
> > + 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.
>
> The support would depend on if the right firmware is loaded/running on the given
> remote core. Also if you want to make this generic, then any vendor should be
> able to make a firmware that implements this protocol and make use of this
> driver.
> Suggest dropping this NXP specific device list.
>
Agree.
> > +
> > + If unsure, say N.
> > +
> > +endmenu
> > +
> > menu "SPI GPIO expanders"
> > depends on SPI_MASTER
> >
> > diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index
> > b267598b517d..ee75c0e65b8b 100644
> > --- a/drivers/gpio/Makefile
> > +++ b/drivers/gpio/Makefile
> > @@ -157,6 +157,7 @@ obj-$(CONFIG_GPIO_RDC321X) += gpio-
...
> > +
> > +static int rpmsg_gpio_channel_probe(struct rpmsg_device *rpdev) {
> > + struct device *dev = &rpdev->dev;
> > + struct device_node *np;
> > + const char *rproc_name;
> > + int idx;
> > +
> > + idx = rpmsg_get_gpio_index(rpdev->id.name, CHAN_NAME_PREFIX);
> > + if (idx < 0)
> > + return -EINVAL;
> > +
> > + if (!dev->of_node) {
> > + np = rpmsg_get_channel_ofnode(rpdev, GPIO_COMPAT_STR, idx);
> > + if (!np)
> > + return -ENODEV;
>
> This seems to imply that DT nodes are required. RPMSG is a discoverable bus
> with a nameservice that can bind/probe new devices. While then optionally
> binding to a DT node when available so sub-devices can be described in DT is fine,
> I don't see why it should be required.
>
First, a GPIO node typically acts as a provider for other devices.
Second, by requiring a DT node, we can ensure that only explicitly enabled GPIO resources are managed and accessible.
> > +static struct rpmsg_driver rpmsg_gpio_channel_client = {
> > + .callback = rpmsg_gpio_channel_callback,
> > + .id_table = rpmsg_gpio_channel_id_table,
> > + .probe = rpmsg_gpio_channel_probe,
> > + .drv = {
> > + .name = KBUILD_MODNAME,
> > + .of_match_table = rpmsg_gpio_dt_ids,
>
> Does this line actually do anything anymore? Maybe it did when this was a
> platform_driver, but this is a rpmsg_driver and will probe though .id_table
> matches.
>
Yes, it can be removed because the driver will find the dt node on its own.
Thanks,
Shenwei
> Andrew
>
> > + },
> > +};
> > +module_rpmsg_driver(rpmsg_gpio_channel_client);
> > +
> > +MODULE_AUTHOR("Shenwei Wang <shenwei.wang@nxp.com>");
> > +MODULE_DESCRIPTION("generic rpmsg gpio driver");
> > +MODULE_LICENSE("GPL");
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v14 4/5] gpio: rpmsg: add generic rpmsg GPIO driver
2026-06-29 18:26 ` Shenwei Wang (OSS)
@ 2026-06-29 19:22 ` Andrew Davis
0 siblings, 0 replies; 17+ messages in thread
From: Andrew Davis @ 2026-06-29 19:22 UTC (permalink / raw)
To: Shenwei Wang (OSS), Linus Walleij, Bartosz Golaszewski,
Jonathan Corbet, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Mathieu Poirier, Frank Li, Sascha Hauer
Cc: Shuah Khan, linux-gpio@vger.kernel.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, Pengutronix Kernel Team,
Fabio Estevam, Shenwei Wang, Peng Fan, devicetree@vger.kernel.org,
linux-remoteproc@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org, dl-linux-imx,
Arnaud POULIQUEN, b-padhi@ti.com, Andrew Lunn,
Bartosz Golaszewski
On 6/29/26 1:26 PM, Shenwei Wang (OSS) wrote:
>
>
>> -----Original Message-----
>> From: Andrew Davis <afd@ti.com>
>> Sent: Thursday, June 25, 2026 3:32 PM
>
> ...
>> Subject: Re: [PATCH v14 4/5] gpio: rpmsg: add generic rpmsg GPIO driver
>>> + 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.
>>
>> The support would depend on if the right firmware is loaded/running on the given
>> remote core. Also if you want to make this generic, then any vendor should be
>> able to make a firmware that implements this protocol and make use of this
>> driver.
>> Suggest dropping this NXP specific device list.
>>
>
> Agree.
>
>>> +
>>> + If unsure, say N.
>>> +
>>> +endmenu
>>> +
>>> menu "SPI GPIO expanders"
>>> depends on SPI_MASTER
>>>
>>> diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index
>>> b267598b517d..ee75c0e65b8b 100644
>>> --- a/drivers/gpio/Makefile
>>> +++ b/drivers/gpio/Makefile
>>> @@ -157,6 +157,7 @@ obj-$(CONFIG_GPIO_RDC321X) += gpio-
>
> ...
>>> +
>>> +static int rpmsg_gpio_channel_probe(struct rpmsg_device *rpdev) {
>>> + struct device *dev = &rpdev->dev;
>>> + struct device_node *np;
>>> + const char *rproc_name;
>>> + int idx;
>>> +
>>> + idx = rpmsg_get_gpio_index(rpdev->id.name, CHAN_NAME_PREFIX);
>>> + if (idx < 0)
>>> + return -EINVAL;
>>> +
>>> + if (!dev->of_node) {
>>> + np = rpmsg_get_channel_ofnode(rpdev, GPIO_COMPAT_STR, idx);
>>> + if (!np)
>>> + return -ENODEV;
>>
>> This seems to imply that DT nodes are required. RPMSG is a discoverable bus
>> with a nameservice that can bind/probe new devices. While then optionally
>> binding to a DT node when available so sub-devices can be described in DT is fine,
>> I don't see why it should be required.
>>
>
> First, a GPIO node typically acts as a provider for other devices.
Not necessarily, there is a userspace API for interacting with GPIOs.
And there are ways to get/attach GPIO lines to other devices without DT.
> Second, by requiring a DT node, we can ensure that only explicitly enabled GPIO resources are managed and accessible.
Not sure I follow here, you have a firmware that provides GPIOs to Linux,
Linux should register those with the GPIO framework. Not sure why DT
is required to be involved. Some systems don't do DT, but they have
firmware and GPIOs.
I'm not saying if the system does use DT and has a node specifically
for this firmware/gpio then we shouldn't bind to that and use it,
just questioning making that "required".
Andrew
>
>>> +static struct rpmsg_driver rpmsg_gpio_channel_client = {
>>> + .callback = rpmsg_gpio_channel_callback,
>>> + .id_table = rpmsg_gpio_channel_id_table,
>>> + .probe = rpmsg_gpio_channel_probe,
>>> + .drv = {
>>> + .name = KBUILD_MODNAME,
>>> + .of_match_table = rpmsg_gpio_dt_ids,
>>
>> Does this line actually do anything anymore? Maybe it did when this was a
>> platform_driver, but this is a rpmsg_driver and will probe though .id_table
>> matches.
>>
>
> Yes, it can be removed because the driver will find the dt node on its own.
>
> Thanks,
> Shenwei
>
>> Andrew
>>
>>> + },
>>> +};
>>> +module_rpmsg_driver(rpmsg_gpio_channel_client);
>>> +
>>> +MODULE_AUTHOR("Shenwei Wang <shenwei.wang@nxp.com>");
>>> +MODULE_DESCRIPTION("generic rpmsg gpio driver");
>>> +MODULE_LICENSE("GPL");
>>
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* RE: [PATCH v14 0/5] Enable Remote GPIO over RPMSG on i.MX Platform
2026-06-25 15:54 [PATCH v14 0/5] Enable Remote GPIO over RPMSG on i.MX Platform Shenwei Wang
` (4 preceding siblings ...)
2026-06-25 15:54 ` [PATCH v14 5/5] arm64: dts: imx8ulp: Add rpmsg node under imx_rproc Shenwei Wang
@ 2026-07-06 15:40 ` Shenwei Wang (OSS)
2026-07-06 15:57 ` Mathieu Poirier
5 siblings, 1 reply; 17+ messages in thread
From: Shenwei Wang (OSS) @ 2026-07-06 15:40 UTC (permalink / raw)
To: Shenwei Wang (OSS), Linus Walleij, Bartosz Golaszewski,
Jonathan Corbet, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bjorn Andersson, Mathieu Poirier, Frank Li, Sascha Hauer
Cc: Shuah Khan, linux-gpio@vger.kernel.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, Pengutronix Kernel Team,
Fabio Estevam, Shenwei Wang, Peng Fan, devicetree@vger.kernel.org,
linux-remoteproc@vger.kernel.org, imx@lists.linux.dev,
linux-arm-kernel@lists.infradead.org, dl-linux-imx,
Arnaud POULIQUEN, b-padhi@ti.com, Andrew Lunn
> -----Original Message-----
> From: Shenwei Wang (OSS)
> Sent: Thursday, June 25, 2026 10:55 AM
> To: Linus Walleij <linusw@kernel.org>; Bartosz Golaszewski <brgl@kernel.org>;
> Jonathan Corbet <corbet@lwn.net>; Rob Herring <robh@kernel.org>; Krzysztof
> Kozlowski <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Bjorn
> Andersson <andersson@kernel.org>; Mathieu Poirier
> <mathieu.poirier@linaro.org>; Frank Li <frank.li@nxp.com>; Sascha Hauer
> <s.hauer@pengutronix.de>
> Cc: Shuah Khan <skhan@linuxfoundation.org>; linux-gpio@vger.kernel.org; linux-
> doc@vger.kernel.org; linux-kernel@vger.kernel.org; Pengutronix Kernel Team
> <kernel@pengutronix.de>; Fabio Estevam <festevam@gmail.com>; Shenwei
> Wang <shenwei.wang@nxp.com>; Peng Fan <peng.fan@nxp.com>;
> devicetree@vger.kernel.org; linux-remoteproc@vger.kernel.org;
> imx@lists.linux.dev; linux-arm-kernel@lists.infradead.org; dl-linux-imx <linux-
> imx@nxp.com>; Arnaud POULIQUEN <arnaud.pouliquen@foss.st.com>; b-
> padhi@ti.com; Andrew Lunn <andrew@lunn.ch>
> Subject: [PATCH v14 0/5] Enable Remote GPIO over RPMSG on i.MX Platform
>
> From: Shenwei Wang <shenwei.wang@nxp.com>
>
> Support the remote devices on the remote processor via the RPMSG bus on i.MX
> platform.
>
> Changes in v14:
> - Update gpio-rpmsg.rst per Mathieu’s feedback.
Hi Mathieu,
Could you please let me know if you have any further comments on this version?
Thanks,
Shenwei
> - Align the rpmsg-gpio driver with the revised gpio-rpmsg.rst.
> - Modify rpmsg-core to enable prefix-based matching of RPMSG device IDs.
>
> Changes in v13:
> - drop the support for legacy NXP firmware.
> - remove the fixed_up hooks from the rpmsg gpio driver.
> - code cleanup.
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v14 0/5] Enable Remote GPIO over RPMSG on i.MX Platform
2026-07-06 15:40 ` [PATCH v14 0/5] Enable Remote GPIO over RPMSG on i.MX Platform Shenwei Wang (OSS)
@ 2026-07-06 15:57 ` Mathieu Poirier
0 siblings, 0 replies; 17+ messages in thread
From: Mathieu Poirier @ 2026-07-06 15:57 UTC (permalink / raw)
To: Shenwei Wang (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Jonathan Corbet, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Frank Li,
Sascha Hauer, Shuah Khan, linux-gpio@vger.kernel.org,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan,
devicetree@vger.kernel.org, linux-remoteproc@vger.kernel.org,
imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
dl-linux-imx, Arnaud POULIQUEN, b-padhi@ti.com, Andrew Lunn
On Mon, 6 Jul 2026 at 09:40, Shenwei Wang (OSS)
<shenwei.wang@oss.nxp.com> wrote:
>
>
>
> > -----Original Message-----
> > From: Shenwei Wang (OSS)
> > Sent: Thursday, June 25, 2026 10:55 AM
> > To: Linus Walleij <linusw@kernel.org>; Bartosz Golaszewski <brgl@kernel.org>;
> > Jonathan Corbet <corbet@lwn.net>; Rob Herring <robh@kernel.org>; Krzysztof
> > Kozlowski <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Bjorn
> > Andersson <andersson@kernel.org>; Mathieu Poirier
> > <mathieu.poirier@linaro.org>; Frank Li <frank.li@nxp.com>; Sascha Hauer
> > <s.hauer@pengutronix.de>
> > Cc: Shuah Khan <skhan@linuxfoundation.org>; linux-gpio@vger.kernel.org; linux-
> > doc@vger.kernel.org; linux-kernel@vger.kernel.org; Pengutronix Kernel Team
> > <kernel@pengutronix.de>; Fabio Estevam <festevam@gmail.com>; Shenwei
> > Wang <shenwei.wang@nxp.com>; Peng Fan <peng.fan@nxp.com>;
> > devicetree@vger.kernel.org; linux-remoteproc@vger.kernel.org;
> > imx@lists.linux.dev; linux-arm-kernel@lists.infradead.org; dl-linux-imx <linux-
> > imx@nxp.com>; Arnaud POULIQUEN <arnaud.pouliquen@foss.st.com>; b-
> > padhi@ti.com; Andrew Lunn <andrew@lunn.ch>
> > Subject: [PATCH v14 0/5] Enable Remote GPIO over RPMSG on i.MX Platform
> >
> > From: Shenwei Wang <shenwei.wang@nxp.com>
> >
> > Support the remote devices on the remote processor via the RPMSG bus on i.MX
> > platform.
> >
> > Changes in v14:
> > - Update gpio-rpmsg.rst per Mathieu’s feedback.
>
> Hi Mathieu,
>
> Could you please let me know if you have any further comments on this version?
I intend to review your patches but other people's work is ahead of yours.
>
> Thanks,
> Shenwei
>
> > - Align the rpmsg-gpio driver with the revised gpio-rpmsg.rst.
> > - Modify rpmsg-core to enable prefix-based matching of RPMSG device IDs.
> >
> > Changes in v13:
> > - drop the support for legacy NXP firmware.
> > - remove the fixed_up hooks from the rpmsg gpio driver.
> > - code cleanup.
> >
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus
2026-06-25 15:54 ` [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus Shenwei Wang
@ 2026-07-13 17:16 ` Mathieu Poirier
2026-07-14 14:29 ` Shenwei Wang (OSS)
2026-07-14 19:04 ` Shenwei Wang (OSS)
0 siblings, 2 replies; 17+ messages in thread
From: Mathieu Poirier @ 2026-07-13 17:16 UTC (permalink / raw)
To: Shenwei Wang
Cc: Linus Walleij, Bartosz Golaszewski, Jonathan Corbet, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Frank Li,
Sascha Hauer, Shuah Khan, linux-gpio, linux-doc, linux-kernel,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan,
devicetree, linux-remoteproc, imx, linux-arm-kernel, linux-imx,
Arnaud POULIQUEN, b-padhi, Andrew Lunn
On Thu, Jun 25, 2026 at 10:54:26AM -0500, Shenwei Wang wrote:
> From: Shenwei Wang <shenwei.wang@nxp.com>
>
> Describes the gpio rpmsg transport protocol over the rpmsg bus between
> the remote system and Linux.
>
> Signed-off-by: Shenwei Wang <shenwei.wang@nxp.com>
> ---
> Documentation/driver-api/gpio/gpio-rpmsg.rst | 271 +++++++++++++++++++
> Documentation/driver-api/gpio/index.rst | 1 +
> 2 files changed, 272 insertions(+)
> create mode 100644 Documentation/driver-api/gpio/gpio-rpmsg.rst
>
> diff --git a/Documentation/driver-api/gpio/gpio-rpmsg.rst b/Documentation/driver-api/gpio/gpio-rpmsg.rst
> new file mode 100644
> index 000000000000..7d351ff0adb0
> --- /dev/null
> +++ b/Documentation/driver-api/gpio/gpio-rpmsg.rst
> @@ -0,0 +1,271 @@
> +.. SPDX-License-Identifier: GPL-2.0-or-later
> +
> +GPIO RPMSG (Remote Processor Messaging) Protocol
> +================================================
> +
> +The GPIO RPMSG transport protocol is used for communication and interaction
> +with GPIO controllers on remote processors via the RPMSG bus.
> +
> +Message Format
> +--------------
> +
> +The RPMSG message consists of a 8-byte packet with the following layout:
> +
> +.. code-block:: none
> +
> + +------+------+------+------+------+------+------+------+
> + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> + | cmd | line | value |
> + +------+------+------+------+------+------+------+------+
> +
> +- **cmd**: Command code, used for GPIO_RPMSG_SEND messages.
> +
> +- **line**: The GPIO line (pin) index of the port.
Here and throughout, please remove any mention of 'port'. This is handled by
the endpoint device, i.e one GPIO controller (port) per endpoint.
> +
> +- **value**: See details in the command description below.
> +
> +
> +GPIO Commands
> +-------------
> +
> +Commands are specified in the **Cmd** field.
> +
> +The SEND message is always sent from Linux to the remote firmware. Each
> +SEND corresponds to a single REPLY message. The GPIO driver should
> +serialize messages and determine whether a REPLY message is required. If a
> +REPLY message is expected but not received within the specified timeout
> +period (currently 1 second in the Linux driver), the driver should return
> +-ETIMEOUT.
> +
> +GET_DIRECTION (Cmd=2)
> +~~~~~~~~~~~~~~~~~~~~~
> +
> +**Request:**
> +
> +.. code-block:: none
> +
> + +------+------+------+------+------+------+------+------+
> + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> + | 2 | line | 0 |
> + +------+------+------+------+------+------+------+------+
> +
> +**Reply:**
> +
> +.. code-block:: none
> +
> + +------+--------+--------+
> + | 0x00 | 0x01 | 0x02 |
> + | 1 | status | value |
> + +------+--------+--------+
> +
> +- **status**:
> +
> + - 0: Ok
> + - 1: Error
> +
> +- **value**: Direction.
> +
> + - 0: None
> + - 1: Output
> + - 2: Input
> +
> +
> +SET_DIRECTION (Cmd=3)
> +~~~~~~~~~~~~~~~~~~~~~
> +
> +**Request:**
> +
> +.. code-block:: none
> +
> + +------+------+------+------+------+------+------+------+
> + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> + | 3 | line | value |
> + +------+------+------+------+------+------+------+------+
> +
> +- **value**: Direction.
> +
> + - 0: None
> + - 1: Output
> + - 2: Input
> +
> +**Reply:**
> +
> +.. code-block:: none
> +
> + +------+--------+--------+
> + | 0x00 | 0x01 | 0x02 |
> + | 1 | status | 0 |
> + +------+--------+--------+
> +
> +- **status**:
> +
> + - 0: Ok
> + - 1: Error
> +
> +
> +GET_VALUE (Cmd=4)
> +~~~~~~~~~~~~~~~~~
> +
> +**Request:**
> +
> +.. code-block:: none
> +
> + +------+------+------+------+------+------+------+------+
> + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> + | 4 | line | 0 |
> + +------+------+------+------+------+------+------+------+
> +
> +**Reply:**
> +
> +.. code-block:: none
> +
> + +------+--------+--------+
> + | 0x00 | 0x01 | 0x02 |
> + | 1 | status | value |
> + +------+--------+--------+
> +
> +- **status**:
> +
> + - 0: Ok
> + - 1: Error
> +
> +- **value**: Level.
> +
> + - 0: Low
> + - 1: High
> +
> +
> +SET_VALUE (Cmd=5)
> +~~~~~~~~~~~~~~~~~
> +
> +**Request:**
> +
> +.. code-block:: none
> +
> + +------+------+------+------+------+------+------+------+
> + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> + | 5 | line | value |
> + +------+------+------+------+------+------+------+------+
> +
> +- **value**: Output level.
> +
> + - 0: Low
> + - 1: High
> +
> +**Reply:**
> +
> +.. code-block:: none
> +
> + +------+--------+--------+
> + | 0x00 | 0x01 | 0x02 |
> + | 1 | status | 0 |
> + +------+--------+--------+
> +
> +- **status**:
> +
> + - 0: Ok
> + - 1: Error
> +
> +
> +SET_IRQ_TYPE (Cmd=6)
> +~~~~~~~~~~~~~~~~~~~~
> +
> +**Request:**
> +
> +.. code-block:: none
> +
> + +------+------+------+------+------+------+------+------+
> + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> + | 6 | line | value |
> + +------+------+------+------+------+------+------+------+
> +
> +- **value**: IRQ types.
> +
> + - 0: Interrupt disabled
> + - 1: Rising edge trigger
> + - 2: Falling edge trigger
> + - 3: Both edge trigger
> + - 4: High level trigger
> + - 8: Low level trigger
I'm in agreement with cmd 3, 4, 5 and 6.
> +
> +**Reply:**
> +
> +.. code-block:: none
> +
> + +------+--------+--------+
> + | 0x00 | 0x01 | 0x02 |
> + | 1 | status | 0 |
> + +------+--------+--------+
> +
> +- **status**:
> +
> + - 0: Ok
> + - 1: Error
> +
> +SET_WAKEUP (Cmd=16)
> +~~~~~~~~~~~~~~~~~~~
I already commented on messages that are not part of the virtio-gpio
specification.
> +
> +**Request:**
> +
> +.. code-block:: none
> +
> + +------+------+------+------+------+------+------+------+
> + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> + | 1 | line | value |
> + +------+------+------+------+------+------+------+------+
> +
> +- **value**: Wakeup enable.
> +
> + The remote system should always aim to stay in a power-efficient state by
> + shutting down or clock-gating the GPIO blocks that aren't in use. Since
> + the remoteproc driver is responsible for managing the power states of the
> + remote firmware, the GPIO driver does not require to know the firmware's
> + running states.
> +
> + When the wakeup bit is set, the remote firmware should configure the line
> + as a wakeup source. The firmware should send the notification message to
> + Linux after it is woken from the GPIO line.
> +
> + - 0: Disable wakeup from GPIO
> + - 1: Enable wakeup from GPIO
> +
> +**Reply:**
> +
> +.. code-block:: none
> +
> + +------+--------+--------+
> + | 0x00 | 0x01 | 0x02 |
> + | 1 | status | 0 |
> + +------+--------+--------+
> +
> +- **status**:
> +
> + - 0: Ok
> + - 1: Error
> +
> +Notification Message
> +--------------------
"Interrupt Messages"
> +
> +Notifications are sent by the remote core and they have
> +**Type=2 (GPIO_RPMSG_NOTIFY)**:
> +
> +When a GPIO line asserts an interrupt on the remote processor, the firmware
> +should immediately mask the corresponding interrupt source and send a
> +notification message to the Linux. Upon completion of the interrupt
> +handling on the Linux side, the driver should issue a
> +command **SET_IRQ_TYPE** to the firmware to unmask the interrupt.
> +
> +A Notification message can arrive between a SEND and its REPLY message,
> +and the driver is expected to handle this scenario.
> +
> +.. code-block:: none
> +
> + +------+------+--------+
> + | 0x00 | 0x01 | 0x02 |
> + | 2 | line | trigger|
> + +------+------+--------+
2 things here:
1) You did not include messages that mask and unmask interrupts at the driver
side.
2) We are carrying virtio-gpio messages on top of RPMSG and as such, this whole
protocol should be about thar:
+------+------+--------+--------
| 0x00 | payload |
| Q | |
+------+------+--------+--------
Q = 0 requestq
Q = 1 eventq
The "payload" part is simply the format of the messages as found in the
virtio-gpio specification. From there, the only thing left to mention is which
messages are not supported, i.e get line names.
> +
> +- **line**: The GPIO line (pin) index of the port.
> +
> +- **trigger**: Optional parameter to indicate the trigger event type.
Not part of the spec - remove.
Given the refactoring work that is still needed, I will not look at the
implementation.
Thanks,
Mathieu
> +
> diff --git a/Documentation/driver-api/gpio/index.rst b/Documentation/driver-api/gpio/index.rst
> index bee58f709b9a..e5eb1f82f01f 100644
> --- a/Documentation/driver-api/gpio/index.rst
> +++ b/Documentation/driver-api/gpio/index.rst
> @@ -16,6 +16,7 @@ Contents:
> drivers-on-gpio
> bt8xxgpio
> pca953x
> + gpio-rpmsg
>
> Core
> ====
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* RE: [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus
2026-07-13 17:16 ` Mathieu Poirier
@ 2026-07-14 14:29 ` Shenwei Wang (OSS)
2026-07-14 16:35 ` Mathieu Poirier
2026-07-14 19:04 ` Shenwei Wang (OSS)
1 sibling, 1 reply; 17+ messages in thread
From: Shenwei Wang (OSS) @ 2026-07-14 14:29 UTC (permalink / raw)
To: Mathieu Poirier, Shenwei Wang (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Jonathan Corbet, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Frank Li,
Sascha Hauer, Shuah Khan, linux-gpio@vger.kernel.org,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan,
devicetree@vger.kernel.org, linux-remoteproc@vger.kernel.org,
imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
dl-linux-imx, Arnaud POULIQUEN, b-padhi@ti.com, Andrew Lunn
> -----Original Message-----
> From: Mathieu Poirier <mathieu.poirier@linaro.org>
> Sent: Monday, July 13, 2026 12:17 PM
> To: Shenwei Wang (OSS) <shenwei.wang@oss.nxp.com>
> Cc: Linus Walleij <linusw@kernel.org>; Bartosz Golaszewski <brgl@kernel.org>;
> Jonathan Corbet <corbet@lwn.net>; Rob Herring <robh@kernel.org>; Krzysztof
> Kozlowski <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Bjorn
> Andersson <andersson@kernel.org>; Frank Li <frank.li@nxp.com>; Sascha Hauer
> <s.hauer@pengutronix.de>; Shuah Khan <skhan@linuxfoundation.org>; linux-
> gpio@vger.kernel.org; linux-doc@vger.kernel.org; linux-kernel@vger.kernel.org;
> Pengutronix Kernel Team <kernel@pengutronix.de>; Fabio Estevam
> <festevam@gmail.com>; Shenwei Wang <shenwei.wang@nxp.com>; Peng Fan
> <peng.fan@nxp.com>; devicetree@vger.kernel.org; linux-
> remoteproc@vger.kernel.org; imx@lists.linux.dev; linux-arm-
> kernel@lists.infradead.org; dl-linux-imx <linux-imx@nxp.com>; Arnaud
> POULIQUEN <arnaud.pouliquen@foss.st.com>; b-padhi@ti.com; Andrew Lunn
> <andrew@lunn.ch>
> Subject: Re: [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg
> bus
>
> On Thu, Jun 25, 2026 at 10:54:26AM -0500, Shenwei Wang wrote:
> > From: Shenwei Wang <shenwei.wang@nxp.com>
> >
> > Describes the gpio rpmsg transport protocol over the rpmsg bus between
> > the remote system and Linux.
> >
> > Signed-off-by: Shenwei Wang <shenwei.wang@nxp.com>
> > ---
> > Documentation/driver-api/gpio/gpio-rpmsg.rst | 271 +++++++++++++++++++
> > Documentation/driver-api/gpio/index.rst | 1 +
> > 2 files changed, 272 insertions(+)
> > create mode 100644 Documentation/driver-api/gpio/gpio-rpmsg.rst
> >
> > diff --git a/Documentation/driver-api/gpio/gpio-rpmsg.rst
> > b/Documentation/driver-api/gpio/gpio-rpmsg.rst
> > new file mode 100644
> > index 000000000000..7d351ff0adb0
> > --- /dev/null
> > +++ b/Documentation/driver-api/gpio/gpio-rpmsg.rst
> > @@ -0,0 +1,271 @@
> > +.. SPDX-License-Identifier: GPL-2.0-or-later
> > +
> > +GPIO RPMSG (Remote Processor Messaging) Protocol
> > +================================================
> > +
> > +The GPIO RPMSG transport protocol is used for communication and
> > +interaction with GPIO controllers on remote processors via the RPMSG bus.
> > +
> > +Message Format
> > +--------------
> > +
> > +The RPMSG message consists of a 8-byte packet with the following layout:
> > +
> > +.. code-block:: none
> > +
> > + +------+------+------+------+------+------+------+------+
> > + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> > + | cmd | line | value |
> > + +------+------+------+------+------+------+------+------+
> > +
> > +- **cmd**: Command code, used for GPIO_RPMSG_SEND messages.
> > +
> > +- **line**: The GPIO line (pin) index of the port.
>
> Here and throughout, please remove any mention of 'port'. This is handled by the
> endpoint device, i.e one GPIO controller (port) per endpoint.
>
> > +
> > +- **value**: See details in the command description below.
> > +
> > +
> > +GPIO Commands
> > +-------------
> > +
> > +Commands are specified in the **Cmd** field.
> > +
> > +The SEND message is always sent from Linux to the remote firmware.
> > +Each SEND corresponds to a single REPLY message. The GPIO driver
> > +should serialize messages and determine whether a REPLY message is
> > +required. If a REPLY message is expected but not received within the
> > +specified timeout period (currently 1 second in the Linux driver),
> > +the driver should return -ETIMEOUT.
> > +
> > +GET_DIRECTION (Cmd=2)
> > +~~~~~~~~~~~~~~~~~~~~~
> > +
> > +**Request:**
> > +
> > +.. code-block:: none
> > +
> > + +------+------+------+------+------+------+------+------+
> > + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> > + | 2 | line | 0 |
> > + +------+------+------+------+------+------+------+------+
> > +
> > +**Reply:**
> > +
> > +.. code-block:: none
> > +
> > + +------+--------+--------+
> > + | 0x00 | 0x01 | 0x02 |
> > + | 1 | status | value |
> > + +------+--------+--------+
> > +
> > +- **status**:
> > +
> > + - 0: Ok
> > + - 1: Error
> > +
> > +- **value**: Direction.
> > +
> > + - 0: None
> > + - 1: Output
> > + - 2: Input
> > +
> > +
> > +SET_DIRECTION (Cmd=3)
> > +~~~~~~~~~~~~~~~~~~~~~
> > +
> > +**Request:**
> > +
> > +.. code-block:: none
> > +
> > + +------+------+------+------+------+------+------+------+
> > + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> > + | 3 | line | value |
> > + +------+------+------+------+------+------+------+------+
> > +
> > +- **value**: Direction.
> > +
> > + - 0: None
> > + - 1: Output
> > + - 2: Input
> > +
> > +**Reply:**
> > +
> > +.. code-block:: none
> > +
> > + +------+--------+--------+
> > + | 0x00 | 0x01 | 0x02 |
> > + | 1 | status | 0 |
> > + +------+--------+--------+
> > +
> > +- **status**:
> > +
> > + - 0: Ok
> > + - 1: Error
> > +
> > +
> > +GET_VALUE (Cmd=4)
> > +~~~~~~~~~~~~~~~~~
> > +
> > +**Request:**
> > +
> > +.. code-block:: none
> > +
> > + +------+------+------+------+------+------+------+------+
> > + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> > + | 4 | line | 0 |
> > + +------+------+------+------+------+------+------+------+
> > +
> > +**Reply:**
> > +
> > +.. code-block:: none
> > +
> > + +------+--------+--------+
> > + | 0x00 | 0x01 | 0x02 |
> > + | 1 | status | value |
> > + +------+--------+--------+
> > +
> > +- **status**:
> > +
> > + - 0: Ok
> > + - 1: Error
> > +
> > +- **value**: Level.
> > +
> > + - 0: Low
> > + - 1: High
> > +
> > +
> > +SET_VALUE (Cmd=5)
> > +~~~~~~~~~~~~~~~~~
> > +
> > +**Request:**
> > +
> > +.. code-block:: none
> > +
> > + +------+------+------+------+------+------+------+------+
> > + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> > + | 5 | line | value |
> > + +------+------+------+------+------+------+------+------+
> > +
> > +- **value**: Output level.
> > +
> > + - 0: Low
> > + - 1: High
> > +
> > +**Reply:**
> > +
> > +.. code-block:: none
> > +
> > + +------+--------+--------+
> > + | 0x00 | 0x01 | 0x02 |
> > + | 1 | status | 0 |
> > + +------+--------+--------+
> > +
> > +- **status**:
> > +
> > + - 0: Ok
> > + - 1: Error
> > +
> > +
> > +SET_IRQ_TYPE (Cmd=6)
> > +~~~~~~~~~~~~~~~~~~~~
> > +
> > +**Request:**
> > +
> > +.. code-block:: none
> > +
> > + +------+------+------+------+------+------+------+------+
> > + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> > + | 6 | line | value |
> > + +------+------+------+------+------+------+------+------+
> > +
> > +- **value**: IRQ types.
> > +
> > + - 0: Interrupt disabled
> > + - 1: Rising edge trigger
> > + - 2: Falling edge trigger
> > + - 3: Both edge trigger
> > + - 4: High level trigger
> > + - 8: Low level trigger
>
> I'm in agreement with cmd 3, 4, 5 and 6.
>
How about cmd 2?
> > +
> > +**Reply:**
> > +
> > +.. code-block:: none
> > +
> > + +------+--------+--------+
> > + | 0x00 | 0x01 | 0x02 |
> > + | 1 | status | 0 |
> > + +------+--------+--------+
> > +
> > +- **status**:
> > +
> > + - 0: Ok
> > + - 1: Error
> > +
> > +SET_WAKEUP (Cmd=16)
> > +~~~~~~~~~~~~~~~~~~~
>
> I already commented on messages that are not part of the virtio-gpio
> specification.
>
I don't believe virtio-gpio needs a SET_WAKEUP command.
In the RPMSG case, SET_WAKEUP is required because it performs an operation on the
remote processor, so the remote side must be explicitly notified.
For virtio-gpio, however, everything is handled locally. The other side does not need to
perform any action, so sending a SET_WAKEUP command appears unnecessary.
> > +
> > +**Request:**
> > +
> > +.. code-block:: none
> > +
> > + +------+------+------+------+------+------+------+------+
> > + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> > + | 1 | line | value |
> > + +------+------+------+------+------+------+------+------+
> > +
> > +- **value**: Wakeup enable.
> > +
> > + The remote system should always aim to stay in a power-efficient
> > + state by shutting down or clock-gating the GPIO blocks that aren't
> > + in use. Since the remoteproc driver is responsible for managing the
> > + power states of the remote firmware, the GPIO driver does not
> > + require to know the firmware's running states.
> > +
> > + When the wakeup bit is set, the remote firmware should configure
> > + the line as a wakeup source. The firmware should send the
> > + notification message to Linux after it is woken from the GPIO line.
> > +
> > + - 0: Disable wakeup from GPIO
> > + - 1: Enable wakeup from GPIO
> > +
> > +**Reply:**
> > +
> > +.. code-block:: none
> > +
> > + +------+--------+--------+
> > + | 0x00 | 0x01 | 0x02 |
> > + | 1 | status | 0 |
> > + +------+--------+--------+
> > +
> > +- **status**:
> > +
> > + - 0: Ok
> > + - 1: Error
> > +
> > +Notification Message
> > +--------------------
>
> "Interrupt Messages"
>
> > +
> > +Notifications are sent by the remote core and they have
> > +**Type=2 (GPIO_RPMSG_NOTIFY)**:
> > +
> > +When a GPIO line asserts an interrupt on the remote processor, the
> > +firmware should immediately mask the corresponding interrupt source
> > +and send a notification message to the Linux. Upon completion of the
> > +interrupt handling on the Linux side, the driver should issue a
> > +command **SET_IRQ_TYPE** to the firmware to unmask the interrupt.
> > +
> > +A Notification message can arrive between a SEND and its REPLY
> > +message, and the driver is expected to handle this scenario.
> > +
> > +.. code-block:: none
> > +
> > + +------+------+--------+
> > + | 0x00 | 0x01 | 0x02 |
> > + | 2 | line | trigger|
> > + +------+------+--------+
>
> 2 things here:
>
> 1) You did not include messages that mask and unmask interrupts at the driver
> side.
Interrupt masking and unmasking are handled entirely on the local processor.
When an interrupt occurs, the remote system masks the interrupt and then sends a notification
to Linux. After Linux processes the notification, it sends a SET_IRQ_TYPE message back to the
remote system, which then unmasks the interrupt.
Thanks,
Shenwei
>
> 2) We are carrying virtio-gpio messages on top of RPMSG and as such, this whole
> protocol should be about thar:
>
> +------+------+--------+--------
> | 0x00 | payload |
> | Q | |
> +------+------+--------+--------
>
> Q = 0 requestq
> Q = 1 eventq
>
> The "payload" part is simply the format of the messages as found in the virtio-
> gpio specification. From there, the only thing left to mention is which messages
> are not supported, i.e get line names.
>
> > +
> > +- **line**: The GPIO line (pin) index of the port.
> > +
> > +- **trigger**: Optional parameter to indicate the trigger event type.
>
> Not part of the spec - remove.
>
> Given the refactoring work that is still needed, I will not look at the
> implementation.
>
> Thanks,
> Mathieu
>
> > +
> > diff --git a/Documentation/driver-api/gpio/index.rst
> > b/Documentation/driver-api/gpio/index.rst
> > index bee58f709b9a..e5eb1f82f01f 100644
> > --- a/Documentation/driver-api/gpio/index.rst
> > +++ b/Documentation/driver-api/gpio/index.rst
> > @@ -16,6 +16,7 @@ Contents:
> > drivers-on-gpio
> > bt8xxgpio
> > pca953x
> > + gpio-rpmsg
> >
> > Core
> > ====
> > --
> > 2.43.0
> >
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus
2026-07-14 14:29 ` Shenwei Wang (OSS)
@ 2026-07-14 16:35 ` Mathieu Poirier
2026-07-14 18:43 ` Shenwei Wang (OSS)
0 siblings, 1 reply; 17+ messages in thread
From: Mathieu Poirier @ 2026-07-14 16:35 UTC (permalink / raw)
To: Shenwei Wang (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Jonathan Corbet, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Frank Li,
Sascha Hauer, Shuah Khan, linux-gpio@vger.kernel.org,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan,
devicetree@vger.kernel.org, linux-remoteproc@vger.kernel.org,
imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
dl-linux-imx, Arnaud POULIQUEN, b-padhi@ti.com, Andrew Lunn
On Tue, Jul 14, 2026 at 02:29:12PM +0000, Shenwei Wang (OSS) wrote:
>
>
> > -----Original Message-----
> > From: Mathieu Poirier <mathieu.poirier@linaro.org>
> > Sent: Monday, July 13, 2026 12:17 PM
> > To: Shenwei Wang (OSS) <shenwei.wang@oss.nxp.com>
> > Cc: Linus Walleij <linusw@kernel.org>; Bartosz Golaszewski <brgl@kernel.org>;
> > Jonathan Corbet <corbet@lwn.net>; Rob Herring <robh@kernel.org>; Krzysztof
> > Kozlowski <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Bjorn
> > Andersson <andersson@kernel.org>; Frank Li <frank.li@nxp.com>; Sascha Hauer
> > <s.hauer@pengutronix.de>; Shuah Khan <skhan@linuxfoundation.org>; linux-
> > gpio@vger.kernel.org; linux-doc@vger.kernel.org; linux-kernel@vger.kernel.org;
> > Pengutronix Kernel Team <kernel@pengutronix.de>; Fabio Estevam
> > <festevam@gmail.com>; Shenwei Wang <shenwei.wang@nxp.com>; Peng Fan
> > <peng.fan@nxp.com>; devicetree@vger.kernel.org; linux-
> > remoteproc@vger.kernel.org; imx@lists.linux.dev; linux-arm-
> > kernel@lists.infradead.org; dl-linux-imx <linux-imx@nxp.com>; Arnaud
> > POULIQUEN <arnaud.pouliquen@foss.st.com>; b-padhi@ti.com; Andrew Lunn
> > <andrew@lunn.ch>
> > Subject: Re: [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg
> > bus
> >
> > On Thu, Jun 25, 2026 at 10:54:26AM -0500, Shenwei Wang wrote:
> > > From: Shenwei Wang <shenwei.wang@nxp.com>
> > >
> > > Describes the gpio rpmsg transport protocol over the rpmsg bus between
> > > the remote system and Linux.
> > >
> > > Signed-off-by: Shenwei Wang <shenwei.wang@nxp.com>
> > > ---
> > > Documentation/driver-api/gpio/gpio-rpmsg.rst | 271 +++++++++++++++++++
> > > Documentation/driver-api/gpio/index.rst | 1 +
> > > 2 files changed, 272 insertions(+)
> > > create mode 100644 Documentation/driver-api/gpio/gpio-rpmsg.rst
> > >
> > > diff --git a/Documentation/driver-api/gpio/gpio-rpmsg.rst
> > > b/Documentation/driver-api/gpio/gpio-rpmsg.rst
> > > new file mode 100644
> > > index 000000000000..7d351ff0adb0
> > > --- /dev/null
> > > +++ b/Documentation/driver-api/gpio/gpio-rpmsg.rst
> > > @@ -0,0 +1,271 @@
> > > +.. SPDX-License-Identifier: GPL-2.0-or-later
> > > +
> > > +GPIO RPMSG (Remote Processor Messaging) Protocol
> > > +================================================
> > > +
> > > +The GPIO RPMSG transport protocol is used for communication and
> > > +interaction with GPIO controllers on remote processors via the RPMSG bus.
> > > +
> > > +Message Format
> > > +--------------
> > > +
> > > +The RPMSG message consists of a 8-byte packet with the following layout:
> > > +
> > > +.. code-block:: none
> > > +
> > > + +------+------+------+------+------+------+------+------+
> > > + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> > > + | cmd | line | value |
> > > + +------+------+------+------+------+------+------+------+
> > > +
> > > +- **cmd**: Command code, used for GPIO_RPMSG_SEND messages.
> > > +
> > > +- **line**: The GPIO line (pin) index of the port.
> >
> > Here and throughout, please remove any mention of 'port'. This is handled by the
> > endpoint device, i.e one GPIO controller (port) per endpoint.
> >
> > > +
> > > +- **value**: See details in the command description below.
> > > +
> > > +
> > > +GPIO Commands
> > > +-------------
> > > +
> > > +Commands are specified in the **Cmd** field.
> > > +
> > > +The SEND message is always sent from Linux to the remote firmware.
> > > +Each SEND corresponds to a single REPLY message. The GPIO driver
> > > +should serialize messages and determine whether a REPLY message is
> > > +required. If a REPLY message is expected but not received within the
> > > +specified timeout period (currently 1 second in the Linux driver),
> > > +the driver should return -ETIMEOUT.
> > > +
> > > +GET_DIRECTION (Cmd=2)
> > > +~~~~~~~~~~~~~~~~~~~~~
> > > +
> > > +**Request:**
> > > +
> > > +.. code-block:: none
> > > +
> > > + +------+------+------+------+------+------+------+------+
> > > + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> > > + | 2 | line | 0 |
> > > + +------+------+------+------+------+------+------+------+
> > > +
> > > +**Reply:**
> > > +
> > > +.. code-block:: none
> > > +
> > > + +------+--------+--------+
> > > + | 0x00 | 0x01 | 0x02 |
> > > + | 1 | status | value |
> > > + +------+--------+--------+
> > > +
> > > +- **status**:
> > > +
> > > + - 0: Ok
> > > + - 1: Error
> > > +
> > > +- **value**: Direction.
> > > +
> > > + - 0: None
> > > + - 1: Output
> > > + - 2: Input
> > > +
> > > +
> > > +SET_DIRECTION (Cmd=3)
> > > +~~~~~~~~~~~~~~~~~~~~~
> > > +
> > > +**Request:**
> > > +
> > > +.. code-block:: none
> > > +
> > > + +------+------+------+------+------+------+------+------+
> > > + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> > > + | 3 | line | value |
> > > + +------+------+------+------+------+------+------+------+
> > > +
> > > +- **value**: Direction.
> > > +
> > > + - 0: None
> > > + - 1: Output
> > > + - 2: Input
> > > +
> > > +**Reply:**
> > > +
> > > +.. code-block:: none
> > > +
> > > + +------+--------+--------+
> > > + | 0x00 | 0x01 | 0x02 |
> > > + | 1 | status | 0 |
> > > + +------+--------+--------+
> > > +
> > > +- **status**:
> > > +
> > > + - 0: Ok
> > > + - 1: Error
> > > +
> > > +
> > > +GET_VALUE (Cmd=4)
> > > +~~~~~~~~~~~~~~~~~
> > > +
> > > +**Request:**
> > > +
> > > +.. code-block:: none
> > > +
> > > + +------+------+------+------+------+------+------+------+
> > > + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> > > + | 4 | line | 0 |
> > > + +------+------+------+------+------+------+------+------+
> > > +
> > > +**Reply:**
> > > +
> > > +.. code-block:: none
> > > +
> > > + +------+--------+--------+
> > > + | 0x00 | 0x01 | 0x02 |
> > > + | 1 | status | value |
> > > + +------+--------+--------+
> > > +
> > > +- **status**:
> > > +
> > > + - 0: Ok
> > > + - 1: Error
> > > +
> > > +- **value**: Level.
> > > +
> > > + - 0: Low
> > > + - 1: High
> > > +
> > > +
> > > +SET_VALUE (Cmd=5)
> > > +~~~~~~~~~~~~~~~~~
> > > +
> > > +**Request:**
> > > +
> > > +.. code-block:: none
> > > +
> > > + +------+------+------+------+------+------+------+------+
> > > + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> > > + | 5 | line | value |
> > > + +------+------+------+------+------+------+------+------+
> > > +
> > > +- **value**: Output level.
> > > +
> > > + - 0: Low
> > > + - 1: High
> > > +
> > > +**Reply:**
> > > +
> > > +.. code-block:: none
> > > +
> > > + +------+--------+--------+
> > > + | 0x00 | 0x01 | 0x02 |
> > > + | 1 | status | 0 |
> > > + +------+--------+--------+
> > > +
> > > +- **status**:
> > > +
> > > + - 0: Ok
> > > + - 1: Error
> > > +
> > > +
> > > +SET_IRQ_TYPE (Cmd=6)
> > > +~~~~~~~~~~~~~~~~~~~~
> > > +
> > > +**Request:**
> > > +
> > > +.. code-block:: none
> > > +
> > > + +------+------+------+------+------+------+------+------+
> > > + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> > > + | 6 | line | value |
> > > + +------+------+------+------+------+------+------+------+
> > > +
> > > +- **value**: IRQ types.
> > > +
> > > + - 0: Interrupt disabled
> > > + - 1: Rising edge trigger
> > > + - 2: Falling edge trigger
> > > + - 3: Both edge trigger
> > > + - 4: High level trigger
> > > + - 8: Low level trigger
> >
> > I'm in agreement with cmd 3, 4, 5 and 6.
> >
>
> How about cmd 2?
Yes, I forgot cmd 2.
>
> > > +
> > > +**Reply:**
> > > +
> > > +.. code-block:: none
> > > +
> > > + +------+--------+--------+
> > > + | 0x00 | 0x01 | 0x02 |
> > > + | 1 | status | 0 |
> > > + +------+--------+--------+
> > > +
> > > +- **status**:
> > > +
> > > + - 0: Ok
> > > + - 1: Error
> > > +
> > > +SET_WAKEUP (Cmd=16)
> > > +~~~~~~~~~~~~~~~~~~~
> >
> > I already commented on messages that are not part of the virtio-gpio
> > specification.
> >
>
> I don't believe virtio-gpio needs a SET_WAKEUP command.
>
> In the RPMSG case, SET_WAKEUP is required because it performs an operation on the
> remote processor, so the remote side must be explicitly notified.
What operations would that be?
>
> For virtio-gpio, however, everything is handled locally. The other side does not need to
> perform any action, so sending a SET_WAKEUP command appears unnecessary.
What is "everything"?
>
>
> > > +
> > > +**Request:**
> > > +
> > > +.. code-block:: none
> > > +
> > > + +------+------+------+------+------+------+------+------+
> > > + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> > > + | 1 | line | value |
> > > + +------+------+------+------+------+------+------+------+
> > > +
> > > +- **value**: Wakeup enable.
> > > +
> > > + The remote system should always aim to stay in a power-efficient
> > > + state by shutting down or clock-gating the GPIO blocks that aren't
> > > + in use. Since the remoteproc driver is responsible for managing the
> > > + power states of the remote firmware, the GPIO driver does not
> > > + require to know the firmware's running states.
> > > +
> > > + When the wakeup bit is set, the remote firmware should configure
> > > + the line as a wakeup source. The firmware should send the
> > > + notification message to Linux after it is woken from the GPIO line.
> > > +
> > > + - 0: Disable wakeup from GPIO
> > > + - 1: Enable wakeup from GPIO
> > > +
> > > +**Reply:**
> > > +
> > > +.. code-block:: none
> > > +
> > > + +------+--------+--------+
> > > + | 0x00 | 0x01 | 0x02 |
> > > + | 1 | status | 0 |
> > > + +------+--------+--------+
> > > +
> > > +- **status**:
> > > +
> > > + - 0: Ok
> > > + - 1: Error
> > > +
> > > +Notification Message
> > > +--------------------
> >
> > "Interrupt Messages"
> >
> > > +
> > > +Notifications are sent by the remote core and they have
> > > +**Type=2 (GPIO_RPMSG_NOTIFY)**:
> > > +
> > > +When a GPIO line asserts an interrupt on the remote processor, the
> > > +firmware should immediately mask the corresponding interrupt source
> > > +and send a notification message to the Linux. Upon completion of the
> > > +interrupt handling on the Linux side, the driver should issue a
> > > +command **SET_IRQ_TYPE** to the firmware to unmask the interrupt.
> > > +
> > > +A Notification message can arrive between a SEND and its REPLY
> > > +message, and the driver is expected to handle this scenario.
> > > +
> > > +.. code-block:: none
> > > +
> > > + +------+------+--------+
> > > + | 0x00 | 0x01 | 0x02 |
> > > + | 2 | line | trigger|
> > > + +------+------+--------+
> >
> > 2 things here:
> >
> > 1) You did not include messages that mask and unmask interrupts at the driver
> > side.
>
> Interrupt masking and unmasking are handled entirely on the local processor.
>
> When an interrupt occurs, the remote system masks the interrupt and then sends a notification
> to Linux. After Linux processes the notification, it sends a SET_IRQ_TYPE message back to the
> remote system, which then unmasks the interrupt.
This is the kind of information that should be part of this documentation.
>
> Thanks,
> Shenwei
>
> >
> > 2) We are carrying virtio-gpio messages on top of RPMSG and as such, this whole
> > protocol should be about thar:
> >
> > +------+------+--------+--------
> > | 0x00 | payload |
> > | Q | |
> > +------+------+--------+--------
> >
> > Q = 0 requestq
> > Q = 1 eventq
> >
> > The "payload" part is simply the format of the messages as found in the virtio-
> > gpio specification. From there, the only thing left to mention is which messages
> > are not supported, i.e get line names.
> >
> > > +
> > > +- **line**: The GPIO line (pin) index of the port.
> > > +
> > > +- **trigger**: Optional parameter to indicate the trigger event type.
> >
> > Not part of the spec - remove.
> >
> > Given the refactoring work that is still needed, I will not look at the
> > implementation.
> >
> > Thanks,
> > Mathieu
> >
> > > +
> > > diff --git a/Documentation/driver-api/gpio/index.rst
> > > b/Documentation/driver-api/gpio/index.rst
> > > index bee58f709b9a..e5eb1f82f01f 100644
> > > --- a/Documentation/driver-api/gpio/index.rst
> > > +++ b/Documentation/driver-api/gpio/index.rst
> > > @@ -16,6 +16,7 @@ Contents:
> > > drivers-on-gpio
> > > bt8xxgpio
> > > pca953x
> > > + gpio-rpmsg
> > >
> > > Core
> > > ====
> > > --
> > > 2.43.0
> > >
^ permalink raw reply [flat|nested] 17+ messages in thread
* RE: [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus
2026-07-14 16:35 ` Mathieu Poirier
@ 2026-07-14 18:43 ` Shenwei Wang (OSS)
0 siblings, 0 replies; 17+ messages in thread
From: Shenwei Wang (OSS) @ 2026-07-14 18:43 UTC (permalink / raw)
To: Mathieu Poirier, Shenwei Wang (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Jonathan Corbet, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Frank Li,
Sascha Hauer, Shuah Khan, linux-gpio@vger.kernel.org,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan,
devicetree@vger.kernel.org, linux-remoteproc@vger.kernel.org,
imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
dl-linux-imx, Arnaud POULIQUEN, b-padhi@ti.com, Andrew Lunn
> -----Original Message-----
> From: Mathieu Poirier <mathieu.poirier@linaro.org>
> Sent: Tuesday, July 14, 2026 11:36 AM
> To: Shenwei Wang (OSS) <shenwei.wang@oss.nxp.com>
> Cc: Linus Walleij <linusw@kernel.org>; Bartosz Golaszewski <brgl@kernel.org>;
> Jonathan Corbet <corbet@lwn.net>; Rob Herring <robh@kernel.org>; Krzysztof
> Kozlowski <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Bjorn
> Andersson <andersson@kernel.org>; Frank Li <frank.li@nxp.com>; Sascha Hauer
> <s.hauer@pengutronix.de>; Shuah Khan <skhan@linuxfoundation.org>; linux-
> gpio@vger.kernel.org; linux-doc@vger.kernel.org; linux-kernel@vger.kernel.org;
> Pengutronix Kernel Team <kernel@pengutronix.de>; Fabio Estevam
> <festevam@gmail.com>; Shenwei Wang <shenwei.wang@nxp.com>; Peng Fan
> <peng.fan@nxp.com>; devicetree@vger.kernel.org; linux-
> remoteproc@vger.kernel.org; imx@lists.linux.dev; linux-arm-
> kernel@lists.infradead.org; dl-linux-imx <linux-imx@nxp.com>; Arnaud
> POULIQUEN <arnaud.pouliquen@foss.st.com>; b-padhi@ti.com; Andrew Lunn
> <andrew@lunn.ch>
> Subject: Re: [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg
> bus
>
> On Tue, Jul 14, 2026 at 02:29:12PM +0000, Shenwei Wang (OSS) wrote:
d
> > > > + - 3: Both edge trigger
> > > > + - 4: High level trigger
> > > > + - 8: Low level trigger
> > >
> > > I'm in agreement with cmd 3, 4, 5 and 6.
> > >
> >
> > How about cmd 2?
>
> Yes, I forgot cmd 2.
>
> >
> > > > +
> > > > +**Reply:**
> > > > +
> > > > +.. code-block:: none
> > > > +
> > > > + +------+--------+--------+
> > > > + | 0x00 | 0x01 | 0x02 |
> > > > + | 1 | status | 0 |
> > > > + +------+--------+--------+
> > > > +
> > > > +- **status**:
> > > > +
> > > > + - 0: Ok
> > > > + - 1: Error
> > > > +
> > > > +SET_WAKEUP (Cmd=16)
> > > > +~~~~~~~~~~~~~~~~~~~
> > >
> > > I already commented on messages that are not part of the virtio-gpio
> > > specification.
> > >
> >
> > I don't believe virtio-gpio needs a SET_WAKEUP command.
> >
> > In the RPMSG case, SET_WAKEUP is required because it performs an
> > operation on the remote processor, so the remote side must be explicitly
> notified.
>
> What operations would that be?
>
The operation is enabling the line as a wakeup source. In practice, this involves configuring
hardware-specific wakeup settings (e.g., register bits) on the remote processor, so the remote
side must be explicitly notified through SET_WAKEUP.
> >
> > For virtio-gpio, however, everything is handled locally. The other
> > side does not need to perform any action, so sending a SET_WAKEUP command
> appears unnecessary.
>
> What is "everything"?
>
I mean masking, unmasking, and marking the interrupt as a wakeup source. All of
these operations are handled on local processor.
Shenwei
> >
> >
> > > > +
> > > > +**Request:**
> > > > +
> > > > +.. code-block:: none
> > > > +
> > > > + +------+------+------+------+------+------+------+------+
> > > > + | 0x00 | 0x01 | 0x02 | 0x03 | 0x04 | 0x05 | 0x06 | 0x07 |
> > > > + | 1 | line | value |
> > > > + +------+------+------+------+------+------+------+------+
> > > > +
> > > > +- **value**: Wakeup enable.
> > > > +
> > > > + The remote system should always aim to stay in a
> > > > + power-efficient state by shutting down or clock-gating the GPIO
> > > > + blocks that aren't in use. Since the remoteproc driver is
> > > > + responsible for managing the power states of the remote
> > > > + firmware, the GPIO driver does not require to know the firmware's
> running states.
> > > > +
> > > > + When the wakeup bit is set, the remote firmware should
> > > > + configure the line as a wakeup source. The firmware should send
> > > > + the notification message to Linux after it is woken from the GPIO line.
> > > > +
> > > > + - 0: Disable wakeup from GPIO
> > > > + - 1: Enable wakeup from GPIO
> > > > +
> > > > +**Reply:**
> > > > +
> > > > +.. code-block:: none
> > > > +
> > > > + +------+--------+--------+
> > > > + | 0x00 | 0x01 | 0x02 |
> > > > + | 1 | status | 0 |
> > > > + +------+--------+--------+
> > > > +
> > > > +- **status**:
> > > > +
> > > > + - 0: Ok
> > > > + - 1: Error
> > > > +
> > > > +Notification Message
> > > > +--------------------
> > >
> > > "Interrupt Messages"
> > >
> > > > +
> > > > +Notifications are sent by the remote core and they have
> > > > +**Type=2 (GPIO_RPMSG_NOTIFY)**:
> > > > +
> > > > +When a GPIO line asserts an interrupt on the remote processor,
> > > > +the firmware should immediately mask the corresponding interrupt
> > > > +source and send a notification message to the Linux. Upon
> > > > +completion of the interrupt handling on the Linux side, the
> > > > +driver should issue a command **SET_IRQ_TYPE** to the firmware to
> unmask the interrupt.
> > > > +
> > > > +A Notification message can arrive between a SEND and its REPLY
> > > > +message, and the driver is expected to handle this scenario.
> > > > +
> > > > +.. code-block:: none
> > > > +
> > > > + +------+------+--------+
> > > > + | 0x00 | 0x01 | 0x02 |
> > > > + | 2 | line | trigger|
> > > > + +------+------+--------+
> > >
> > > 2 things here:
> > >
> > > 1) You did not include messages that mask and unmask interrupts at
> > > the driver side.
> >
> > Interrupt masking and unmasking are handled entirely on the local processor.
> >
> > When an interrupt occurs, the remote system masks the interrupt and
> > then sends a notification to Linux. After Linux processes the
> > notification, it sends a SET_IRQ_TYPE message back to the remote system,
> which then unmasks the interrupt.
>
> This is the kind of information that should be part of this documentation.
>
> >
> > Thanks,
> > Shenwei
> >
> > >
> > > 2) We are carrying virtio-gpio messages on top of RPMSG and as such,
> > > this whole protocol should be about thar:
> > >
> > > +------+------+--------+--------
> > > | 0x00 | payload |
> > > | Q | |
> > > +------+------+--------+--------
> > >
> > > Q = 0 requestq
> > > Q = 1 eventq
> > >
> > > The "payload" part is simply the format of the messages as found in
> > > the virtio- gpio specification. From there, the only thing left to
> > > mention is which messages are not supported, i.e get line names.
> > >
> > > > +
> > > > +- **line**: The GPIO line (pin) index of the port.
> > > > +
> > > > +- **trigger**: Optional parameter to indicate the trigger event type.
> > >
> > > Not part of the spec - remove.
> > >
> > > Given the refactoring work that is still needed, I will not look at
> > > the implementation.
> > >
> > > Thanks,
> > > Mathieu
> > >
> > > > +
> > > > diff --git a/Documentation/driver-api/gpio/index.rst
> > > > b/Documentation/driver-api/gpio/index.rst
> > > > index bee58f709b9a..e5eb1f82f01f 100644
> > > > --- a/Documentation/driver-api/gpio/index.rst
> > > > +++ b/Documentation/driver-api/gpio/index.rst
> > > > @@ -16,6 +16,7 @@ Contents:
> > > > drivers-on-gpio
> > > > bt8xxgpio
> > > > pca953x
> > > > + gpio-rpmsg
> > > >
> > > > Core
> > > > ====
> > > > --
> > > > 2.43.0
> > > >
^ permalink raw reply [flat|nested] 17+ messages in thread
* RE: [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus
2026-07-13 17:16 ` Mathieu Poirier
2026-07-14 14:29 ` Shenwei Wang (OSS)
@ 2026-07-14 19:04 ` Shenwei Wang (OSS)
1 sibling, 0 replies; 17+ messages in thread
From: Shenwei Wang (OSS) @ 2026-07-14 19:04 UTC (permalink / raw)
To: Mathieu Poirier, Shenwei Wang (OSS)
Cc: Linus Walleij, Bartosz Golaszewski, Jonathan Corbet, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Frank Li,
Sascha Hauer, Shuah Khan, linux-gpio@vger.kernel.org,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan,
devicetree@vger.kernel.org, linux-remoteproc@vger.kernel.org,
imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
dl-linux-imx, Arnaud POULIQUEN, b-padhi@ti.com, Andrew Lunn
> -----Original Message-----
> From: Mathieu Poirier <mathieu.poirier@linaro.org>
> Sent: Monday, July 13, 2026 12:17 PM
> To: Shenwei Wang (OSS) <shenwei.wang@oss.nxp.com>
> Cc: Linus Walleij <linusw@kernel.org>; Bartosz Golaszewski <brgl@kernel.org>;
> Jonathan Corbet <corbet@lwn.net>; Rob Herring <robh@kernel.org>; Krzysztof
> Kozlowski <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Bjorn
> Andersson <andersson@kernel.org>; Frank Li <frank.li@nxp.com>; Sascha Hauer
> <s.hauer@pengutronix.de>; Shuah Khan <skhan@linuxfoundation.org>; linux-
> gpio@vger.kernel.org; linux-doc@vger.kernel.org; linux-kernel@vger.kernel.org;
> Pengutronix Kernel Team <kernel@pengutronix.de>; Fabio Estevam
> <festevam@gmail.com>; Shenwei Wang <shenwei.wang@nxp.com>; Peng Fan
> <peng.fan@nxp.com>; devicetree@vger.kernel.org; linux-
> remoteproc@vger.kernel.org; imx@lists.linux.dev; linux-arm-
> kernel@lists.infradead.org; dl-linux-imx <linux-imx@nxp.com>; Arnaud
> POULIQUEN <arnaud.pouliquen@foss.st.com>; b-padhi@ti.com; Andrew Lunn
> <andrew@lunn.ch>
> Subject: Re: [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg
> bus
>
> > +
> > +The RPMSG message consists of a 8-byte packet with the following layout:
> > +
> > +.. code-block:: none
> > +.. code-block:: none
> > +
> > + +------+------+--------+
> > + | 0x00 | 0x01 | 0x02 |
> > + | 2 | line | trigger|
> > + +------+------+--------+
>
> 2 things here:
>
> 1) You did not include messages that mask and unmask interrupts at the driver
> side.
>
> 2) We are carrying virtio-gpio messages on top of RPMSG and as such, this whole
> protocol should be about thar:
>
> +------+------+--------+--------
> | 0x00 | payload |
> | Q | |
> +------+------+--------+--------
>
> Q = 0 requestq
> Q = 1 eventq
>
> The "payload" part is simply the format of the messages as found in the virtio-
> gpio specification. From there, the only thing left to mention is which messages
> are not supported, i.e get line names.
>
> > +
> > +- **line**: The GPIO line (pin) index of the port.
> > +
> > +- **trigger**: Optional parameter to indicate the trigger event type.
>
> Not part of the spec - remove.
>
The two fields above are required for rpmsg-gpio, but not for virtio-gpio.
In the rpmsg-gpio case, interrupt detection and handling occur on the remote processor. The
interrupt information (such as the GPIO line and trigger type) must therefore be sent to Linux
through this notification message.
In contrast, for virtio-gpio, interrupt handling is performed on the local processor. Since Linux already
has all the necessary interrupt context, the information is not needed.
Shenwei
> Given the refactoring work that is still needed, I will not look at the
> implementation.
>
> Thanks,
> Mathieu
>
> > +
> > diff --git a/Documentation/driver-api/gpio/index.rst
> > b/Documentation/driver-api/gpio/index.rst
> > index bee58f709b9a..e5eb1f82f01f 100644
> > --- a/Documentation/driver-api/gpio/index.rst
> > +++ b/Documentation/driver-api/gpio/index.rst
> > @@ -16,6 +16,7 @@ Contents:
> > drivers-on-gpio
> > bt8xxgpio
> > pca953x
> > + gpio-rpmsg
> >
> > Core
> > ====
> > --
> > 2.43.0
> >
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2026-07-14 19:04 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-25 15:54 [PATCH v14 0/5] Enable Remote GPIO over RPMSG on i.MX Platform Shenwei Wang
2026-06-25 15:54 ` [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus Shenwei Wang
2026-07-13 17:16 ` Mathieu Poirier
2026-07-14 14:29 ` Shenwei Wang (OSS)
2026-07-14 16:35 ` Mathieu Poirier
2026-07-14 18:43 ` Shenwei Wang (OSS)
2026-07-14 19:04 ` Shenwei Wang (OSS)
2026-06-25 15:54 ` [PATCH v14 2/5] dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode support Shenwei Wang
2026-06-25 15:54 ` [PATCH v14 3/5] rpmsg: core: match rpmsg device IDs by prefix Shenwei Wang
2026-06-25 15:54 ` [PATCH v14 4/5] gpio: rpmsg: add generic rpmsg GPIO driver Shenwei Wang
2026-06-25 20:32 ` Andrew Davis
2026-06-29 18:26 ` Shenwei Wang (OSS)
2026-06-29 19:22 ` Andrew Davis
2026-06-25 22:17 ` Julian Braha
2026-06-25 15:54 ` [PATCH v14 5/5] arm64: dts: imx8ulp: Add rpmsg node under imx_rproc Shenwei Wang
2026-07-06 15:40 ` [PATCH v14 0/5] Enable Remote GPIO over RPMSG on i.MX Platform Shenwei Wang (OSS)
2026-07-06 15:57 ` Mathieu Poirier
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox