* [PATCH v7 0/4] Enable Remote GPIO over RPMSG on i.MX Platform
@ 2026-02-10 17:08 Shenwei Wang
2026-02-10 17:08 ` [PATCH v7 1/4] dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode support Shenwei Wang
` (3 more replies)
0 siblings, 4 replies; 13+ messages in thread
From: Shenwei Wang @ 2026-02-10 17:08 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Mathieu Poirier, Shawn Guo, Sascha Hauer, Jonathan Corbet
Cc: Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan,
linux-gpio, devicetree, linux-kernel, linux-remoteproc, imx,
linux-arm-kernel, linux-doc, linux-imx, arnaud.pouliquen
Support the remote devices on the remote processor via the RPMSG bus on
i.MX platform.
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 (4):
dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode support
docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus
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 | 236 +++++++
Documentation/driver-api/gpio/index.rst | 1 +
arch/arm64/boot/dts/freescale/imx8ulp.dtsi | 27 +
drivers/gpio/Kconfig | 16 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-rpmsg.c | 583 ++++++++++++++++++
8 files changed, 972 insertions(+)
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] 13+ messages in thread* [PATCH v7 1/4] dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode support 2026-02-10 17:08 [PATCH v7 0/4] Enable Remote GPIO over RPMSG on i.MX Platform Shenwei Wang @ 2026-02-10 17:08 ` Shenwei Wang 2026-02-10 20:48 ` Rob Herring (Arm) 2026-02-10 17:08 ` [PATCH v7 2/4] docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus Shenwei Wang ` (2 subsequent siblings) 3 siblings, 1 reply; 13+ messages in thread From: Shenwei Wang @ 2026-02-10 17:08 UTC (permalink / raw) To: Linus Walleij, Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Mathieu Poirier, Shawn Guo, Sascha Hauer, Jonathan Corbet Cc: Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan, linux-gpio, devicetree, linux-kernel, linux-remoteproc, imx, linux-arm-kernel, linux-doc, linux-imx, arnaud.pouliquen 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 57d75acb0b5e..2f9dca2b71f7 100644 --- a/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml +++ b/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml @@ -84,6 +84,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-channel: + 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 @@ -146,5 +174,30 @@ examples: &mu 3 1>; memory-region = <&vdev0buffer>, <&vdev0vring0>, <&vdev0vring1>, <&rsc_table>; syscon = <&src>; + + rpmsg { + rpmsg-io-channel { + #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] 13+ messages in thread
* Re: [PATCH v7 1/4] dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode support 2026-02-10 17:08 ` [PATCH v7 1/4] dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode support Shenwei Wang @ 2026-02-10 20:48 ` Rob Herring (Arm) 2026-02-11 17:26 ` Shenwei Wang 0 siblings, 1 reply; 13+ messages in thread From: Rob Herring (Arm) @ 2026-02-10 20:48 UTC (permalink / raw) To: Shenwei Wang Cc: Bartosz Golaszewski, linux-imx, devicetree, Linus Walleij, arnaud.pouliquen, Krzysztof Kozlowski, Sascha Hauer, Shawn Guo, linux-gpio, Bjorn Andersson, Pengutronix Kernel Team, linux-arm-kernel, linux-remoteproc, Peng Fan, Conor Dooley, imx, Jonathan Corbet, Mathieu Poirier, Fabio Estevam, linux-doc, linux-kernel On Tue, 10 Feb 2026 11:08:11 -0600, Shenwei Wang wrote: > 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 > My bot found errors running 'make dt_binding_check' on your patch: yamllint warnings/errors: dtschema/dtc warnings/errors: doc reference errors (make refcheckdocs): Warning: Documentation/devicetree/bindings/gpio/gpio-rpmsg.yaml references a file that doesn't exist: Documentation/driver-api/gpio/gpio-rpmsg.rst Documentation/devicetree/bindings/gpio/gpio-rpmsg.yaml: Documentation/driver-api/gpio/gpio-rpmsg.rst See https://patchwork.kernel.org/project/devicetree/patch/20260210170814.406883-2-shenwei.wang@nxp.com The base for the series is generally the latest rc1. A different dependency should be noted in *this* patch. If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date: pip3 install dtschema --upgrade Please check and re-submit after running the above command yourself. Note that DT_SCHEMA_FILES can be set to your schema file to speed up checking your schema. However, it must be unset to test all examples with your schema. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v7 1/4] dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode support 2026-02-10 20:48 ` Rob Herring (Arm) @ 2026-02-11 17:26 ` Shenwei Wang 2026-02-11 20:53 ` Rob Herring 0 siblings, 1 reply; 13+ messages in thread From: Shenwei Wang @ 2026-02-11 17:26 UTC (permalink / raw) To: Rob Herring (Arm) Cc: Bartosz Golaszewski, dl-linux-imx, devicetree@vger.kernel.org, Linus Walleij, arnaud.pouliquen@foss.st.com, Krzysztof Kozlowski, Sascha Hauer, Shawn Guo, linux-gpio@vger.kernel.org, Bjorn Andersson, Pengutronix Kernel Team, linux-arm-kernel@lists.infradead.org, linux-remoteproc@vger.kernel.org, Peng Fan, Conor Dooley, imx@lists.linux.dev, Jonathan Corbet, Mathieu Poirier, Fabio Estevam, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org > -----Original Message----- > From: Rob Herring (Arm) <robh@kernel.org> > Sent: Tuesday, February 10, 2026 2:48 PM > To: Shenwei Wang <shenwei.wang@nxp.com> > Cc: Bartosz Golaszewski <brgl@kernel.org>; dl-linux-imx <linux-imx@nxp.com>; > devicetree@vger.kernel.org; Linus Walleij <linusw@kernel.org>; > arnaud.pouliquen@foss.st.com; Krzysztof Kozlowski <krzk+dt@kernel.org>; > Sascha Hauer <s.hauer@pengutronix.de>; Shawn Guo <shawnguo@kernel.org>; > linux-gpio@vger.kernel.org; Bjorn Andersson <andersson@kernel.org>; > Pengutronix Kernel Team <kernel@pengutronix.de>; linux-arm- > kernel@lists.infradead.org; linux-remoteproc@vger.kernel.org; Peng Fan > <peng.fan@nxp.com>; Conor Dooley <conor+dt@kernel.org>; > imx@lists.linux.dev; Jonathan Corbet <corbet@lwn.net>; Mathieu Poirier > <mathieu.poirier@linaro.org>; Fabio Estevam <festevam@gmail.com>; linux- > doc@vger.kernel.org; linux-kernel@vger.kernel.org > Subject: [EXT] Re: [PATCH v7 1/4] dt-bindings: remoteproc: imx_rproc: Add > "rpmsg" subnode support > > On Tue, 10 Feb 2026 11:08:11 -0600, Shenwei Wang wrote: > > 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 > > > > My bot found errors running 'make dt_binding_check' on your patch: > > yamllint warnings/errors: > > dtschema/dtc warnings/errors: > > > doc reference errors (make refcheckdocs): > Warning: Documentation/devicetree/bindings/gpio/gpio-rpmsg.yaml references > a file that doesn't exist: Documentation/driver-api/gpio/gpio-rpmsg.rst > Documentation/devicetree/bindings/gpio/gpio-rpmsg.yaml: > Documentation/driver-api/gpio/gpio-rpmsg.rst > The .rst file mentioned in the description is included in this same patch set. Thanks, Shenwei > See > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork > .kernel.org%2Fproject%2Fdevicetree%2Fpatch%2F20260210170814.406883-2- > shenwei.wang%40nxp.com&data=05%7C02%7Cshenwei.wang%40nxp.com%7C > ec16fbf197124fe4a79408de68e5b709%7C686ea1d3bc2b4c6fa92cd99c5c301635 > %7C0%7C0%7C639063532995959644%7CUnknown%7CTWFpbGZsb3d8eyJFbXB > 0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCI > sIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=if3xgNzIUU4Abj9FiShAH8aJ9LU9S > OcBUbKqAn%2FcUbw%3D&reserved=0 > > The base for the series is generally the latest rc1. A different dependency should > be noted in *this* patch. > > If you already ran 'make dt_binding_check' and didn't see the above error(s), then > make sure 'yamllint' is installed and dt-schema is up to > date: > > pip3 install dtschema --upgrade > > Please check and re-submit after running the above command yourself. Note that > DT_SCHEMA_FILES can be set to your schema file to speed up checking your > schema. However, it must be unset to test all examples with your schema. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v7 1/4] dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode support 2026-02-11 17:26 ` Shenwei Wang @ 2026-02-11 20:53 ` Rob Herring 0 siblings, 0 replies; 13+ messages in thread From: Rob Herring @ 2026-02-11 20:53 UTC (permalink / raw) To: Shenwei Wang Cc: Bartosz Golaszewski, dl-linux-imx, devicetree@vger.kernel.org, Linus Walleij, arnaud.pouliquen@foss.st.com, Krzysztof Kozlowski, Sascha Hauer, Shawn Guo, linux-gpio@vger.kernel.org, Bjorn Andersson, Pengutronix Kernel Team, linux-arm-kernel@lists.infradead.org, linux-remoteproc@vger.kernel.org, Peng Fan, Conor Dooley, imx@lists.linux.dev, Jonathan Corbet, Mathieu Poirier, Fabio Estevam, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org On Wed, Feb 11, 2026 at 05:26:06PM +0000, Shenwei Wang wrote: > > > > -----Original Message----- > > From: Rob Herring (Arm) <robh@kernel.org> > > Sent: Tuesday, February 10, 2026 2:48 PM > > To: Shenwei Wang <shenwei.wang@nxp.com> > > Cc: Bartosz Golaszewski <brgl@kernel.org>; dl-linux-imx <linux-imx@nxp.com>; > > devicetree@vger.kernel.org; Linus Walleij <linusw@kernel.org>; > > arnaud.pouliquen@foss.st.com; Krzysztof Kozlowski <krzk+dt@kernel.org>; > > Sascha Hauer <s.hauer@pengutronix.de>; Shawn Guo <shawnguo@kernel.org>; > > linux-gpio@vger.kernel.org; Bjorn Andersson <andersson@kernel.org>; > > Pengutronix Kernel Team <kernel@pengutronix.de>; linux-arm- > > kernel@lists.infradead.org; linux-remoteproc@vger.kernel.org; Peng Fan > > <peng.fan@nxp.com>; Conor Dooley <conor+dt@kernel.org>; > > imx@lists.linux.dev; Jonathan Corbet <corbet@lwn.net>; Mathieu Poirier > > <mathieu.poirier@linaro.org>; Fabio Estevam <festevam@gmail.com>; linux- > > doc@vger.kernel.org; linux-kernel@vger.kernel.org > > Subject: [EXT] Re: [PATCH v7 1/4] dt-bindings: remoteproc: imx_rproc: Add > > "rpmsg" subnode support > > > > On Tue, 10 Feb 2026 11:08:11 -0600, Shenwei Wang wrote: > > > 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 > > > > > > > My bot found errors running 'make dt_binding_check' on your patch: > > > > yamllint warnings/errors: > > > > dtschema/dtc warnings/errors: > > > > > > doc reference errors (make refcheckdocs): > > Warning: Documentation/devicetree/bindings/gpio/gpio-rpmsg.yaml references > > a file that doesn't exist: Documentation/driver-api/gpio/gpio-rpmsg.rst > > Documentation/devicetree/bindings/gpio/gpio-rpmsg.yaml: > > Documentation/driver-api/gpio/gpio-rpmsg.rst > > > > The .rst file mentioned in the description is included in this same patch set. Then can't the .rst doc come first? Really, bindings should not reference kernel docs as they are used outside the kernel. However, since there is no other definition of the protocol, I think it is fine here. Rob ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v7 2/4] docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus 2026-02-10 17:08 [PATCH v7 0/4] Enable Remote GPIO over RPMSG on i.MX Platform Shenwei Wang 2026-02-10 17:08 ` [PATCH v7 1/4] dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode support Shenwei Wang @ 2026-02-10 17:08 ` Shenwei Wang 2026-02-10 17:08 ` [PATCH v7 3/4] gpio: rpmsg: add generic rpmsg GPIO driver Shenwei Wang 2026-02-10 17:08 ` [PATCH v7 4/4] arm64: dts: imx8ulp: Add rpmsg node under imx_rproc Shenwei Wang 3 siblings, 0 replies; 13+ messages in thread From: Shenwei Wang @ 2026-02-10 17:08 UTC (permalink / raw) To: Linus Walleij, Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Mathieu Poirier, Shawn Guo, Sascha Hauer, Jonathan Corbet Cc: Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan, linux-gpio, devicetree, linux-kernel, linux-remoteproc, imx, linux-arm-kernel, linux-doc, linux-imx, arnaud.pouliquen 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 | 236 +++++++++++++++++++ Documentation/driver-api/gpio/index.rst | 1 + 2 files changed, 237 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..6964de309471 --- /dev/null +++ b/Documentation/driver-api/gpio/gpio-rpmsg.rst @@ -0,0 +1,236 @@ +.. SPDX-License-Identifier: GPL-2.0-or-later + +GPIO RPMSG Protocol +=================== + +The GPIO RPMSG transport protocol is used for communication and interaction +with GPIO controllers located on remote cores on the RPMSG bus. + +Message Format +-------------- + +The RPMSG message consists of a 14-byte packet with the following layout: + +.. code-block:: none + + +-----+-------+--------+-----+-----+------------+-----+-----+-----+----+ + |0x00 |0x01 |0x02 |0x03 |0x04 |0x05..0x09 |0x0A |0x0B |0x0C |0x0D| + | ID |vendor |version |type |cmd |reserved[5] |line |port | data | + +-----+-------+--------+-----+-----+------------+-----+-----+-----+----+ + +- **ID (Message Identification Code)**: Must be 0x5. Indicates the GPIO message. + +- **Vendor**: Vendor ID number. + - 0: Reserved + - 1: NXP + +- **Version**: Vendor-specific version number (such as software release). + +- **Type (Message Type)**: The message type can be one of: + + - 0: GPIO_RPMSG_SETUP + - 1: GPIO_RPMSG_REPLY + - 2: GPIO_RPMSG_NOTIFY + +- **Cmd**: Command code, used for GPIO_RPMSG_SETUP messages. + +- **reserved[5]**: Reserved bytes. Should always be 0. + +- **line**: The GPIO line(pin) index of the port. + +- **port**: The GPIO port(bank) index. + +- **data**: See details in the command description below. + +GPIO Commands +------------- + +Commands are specified in the **Cmd** field for **GPIO_RPMSG_SETUP** (Type=0) messages. + +The SETUP message is always sent from Linux to the remote firmware. Each +SETUP 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. + +GPIO_RPMSG_INPUT_INIT (Cmd=0) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Request:** + +.. code-block:: none + + +-----+-----+-----+-----+-----+-----------+-----+-----+-----+----+ + |0x00 |0x01 |0x02 |0x03 |0x04 |0x05..0x09 |0x0A |0x0B |0x0C |0x0D| + | 5 | 1 | 0 | 0 | 0 | 0 |line |port | val | wk | + +-----+-----+-----+-----+-----+-----------+-----+-----+-----+----+ + +- **val**: Interrupt trigger type. + + - 0: Interrupt disabled + - 1: Rising edge trigger + - 2: Falling edge trigger + - 3: Both edge trigger + - 4: Low level trigger + - 5: High level trigger + +- **wk**: 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 |0x03 |0x04 |0x05..0x09 |0x0A |0x0B |0x0C |0x0D| + | 5 | 1 | 0 | 1 | 1 | 0 |line |port | err | 0 | + +-----+-----+-----+-----+-----+-----------+-----+-----+-----+----+ + +- **err**: Error code from the remote core. + + - 0: Success + - 1: General error (Early remote software only returns this unclassified error) + - 2: Not supported (A command is not supported by the remote firmware) + - 3: Resource not available (The resource is not allocated to Linux) + - 4: Resource busy (The resource is already in use) + - 5: Parameter error + +GPIO_RPMSG_OUTPUT_INIT (Cmd=1) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Request:** + +.. code-block:: none + + +-----+-----+-----+-----+-----+-----------+-----+-----+-----+----+ + |0x00 |0x01 |0x02 |0x03 |0x04 |0x05..0x09 |0x0A |0x0B |0x0C |0x0D| + | 5 | 1 | 0 | 0 | 1 | 0 |line |port | val | 0 | + +-----+-----+-----+-----+-----+-----------+-----+-----+-----+----+ + +- **val**: Output level. + + - 0: Low + - 1: High + +**Reply:** + +.. code-block:: none + + +-----+-----+-----+-----+-----+-----------+-----+-----+-----+----+ + |0x00 |0x01 |0x02 |0x03 |0x04 |0x05..0x09 |0x0A |0x0B |0x0C |0x0D| + | 5 | 1 | 0 | 1 | 1 | 0 |line |port | err | 0 | + +-----+-----+-----+-----+-----+-----------+-----+-----+-----+----+ + +- **err**: See above for definitions. + +GPIO_RPMSG_INPUT_GET (Cmd=2) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Request:** + +.. code-block:: none + + +-----+-----+-----+-----+-----+-----------+-----+-----+-----+----+ + |0x00 |0x01 |0x02 |0x03 |0x04 |0x05..0x09 |0x0A |0x0B |0x0C |0x0D| + | 5 | 1 | 0 | 0 | 2 | 0 |line |port | 0 | 0 | + +-----+-----+-----+-----+-----+-----------+-----+-----+-----+----+ + +**Reply:** + +.. code-block:: none + + +-----+-----+-----+-----+-----+-----------+-----+-----+-----+-----+ + |0x00 |0x01 |0x02 |0x03 |0x04 |0x05..0x09 |0x0A |0x0B |0x0C |0x0D | + | 5 | 1 | 0 | 1 | 2 | 0 |line |port | err |level| + +-----+-----+-----+-----+-----+-----------+-----+-----+-----+-----+ + +- **err**: See above for definitions. + +- **level**: Input level. + + - 0: Low + - 1: High + +GPIO_RPMSG_GET_DIRECTION (Cmd=3) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**Request:** + +.. code-block:: none + + +-----+-----+-----+-----+-----+-----------+-----+-----+-----+----+ + |0x00 |0x01 |0x02 |0x03 |0x04 |0x05..0x09 |0x0A |0x0B |0x0C |0x0D| + | 5 | 1 | 0 | 0 | 3 | 0 |line |port | 0 | 0 | + +-----+-----+-----+-----+-----+-----------+-----+-----+-----+----+ + +**Reply:** + +.. code-block:: none + + +-----+-----+-----+-----+-----+-----------+-----+-----+-----+-----+ + |0x00 |0x01 |0x02 |0x03 |0x04 |0x05..0x09 |0x0A |0x0B |0x0C |0x0D | + | 5 | 1 | 0 | 1 | 3 | 0 |line |port | err | dir | + +-----+-----+-----+-----+-----+-----------+-----+-----+-----+-----+ + +- **err**: See above for definitions. + +- **dir**: Direction. + + - 0: Output + - 1: Input + +GPIO_RPMSG_NOTIFY_REPLY (Cmd=4) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The reply message for the notification is optional. The remote firmware can +implement it to simulate the interrupt acknowledgment behavior. + +**Request:** + +.. code-block:: none + + +-----+-----+-----+-----+-----+-----------+-----+-----+-----+----+ + |0x00 |0x01 |0x02 |0x03 |0x04 |0x05..0x09 |0x0A |0x0B |0x0C |0x0D| + | 5 | 1 | 0 | 0 | 4 | 0 |line |port |level| 0 | + +-----+-----+-----+-----+-----+-----------+-----+-----+-----+----+ + +- **line**: The GPIO line(pin) index of the port. +- **port**: The GPIO port(bank) index. + +Notification Message +-------------------- + +Notifications are sent with **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 +**GPIO_RPMSG_INPUT_INIT** command to the firmware to unmask the interrupt. + +A Notification message can arrive between a SETUP and its REPLY message, +and the driver is expected to handle this scenario. + +.. code-block:: none + + +-----+-----+-----+-----+-----+-----------+-----+-----+-----+----+ + |0x00 |0x01 |0x02 |0x03 |0x04 |0x05..0x09 |0x0A |0x0B |0x0C |0x0D| + | 5 | 1 | 0 | 2 | 0 | 0 |line |port |type | 0 | + +-----+-----+-----+-----+-----+-----------+-----+-----+-----+----+ + +- **line**: The GPIO line(pin) index of the port. +- **port**: The GPIO port(bank) index. +- **type**: Optional pamameter 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] 13+ messages in thread
* [PATCH v7 3/4] gpio: rpmsg: add generic rpmsg GPIO driver 2026-02-10 17:08 [PATCH v7 0/4] Enable Remote GPIO over RPMSG on i.MX Platform Shenwei Wang 2026-02-10 17:08 ` [PATCH v7 1/4] dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode support Shenwei Wang 2026-02-10 17:08 ` [PATCH v7 2/4] docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus Shenwei Wang @ 2026-02-10 17:08 ` Shenwei Wang 2026-02-10 17:48 ` Andrew Lunn ` (2 more replies) 2026-02-10 17:08 ` [PATCH v7 4/4] arm64: dts: imx8ulp: Add rpmsg node under imx_rproc Shenwei Wang 3 siblings, 3 replies; 13+ messages in thread From: Shenwei Wang @ 2026-02-10 17:08 UTC (permalink / raw) To: Linus Walleij, Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Mathieu Poirier, Shawn Guo, Sascha Hauer, Jonathan Corbet Cc: Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan, linux-gpio, devicetree, linux-kernel, linux-remoteproc, imx, linux-arm-kernel, linux-doc, linux-imx, arnaud.pouliquen, Bartosz Golaszewski, Andrew Lunn On an AMP platform, the system may include two processors: - An MCU running an RTOS - An MPU running Linux These processors communicate via the RPMSG protocol. The driver implements the standard GPIO interface, allowing the Linux side to control GPIO controllers which reside in the remote processor via RPMSG protocol. Cc: Bartosz Golaszewski <brgl@bgdev.pl> Cc: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Shenwei Wang <shenwei.wang@nxp.com> --- drivers/gpio/Kconfig | 16 ++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-rpmsg.c | 583 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 600 insertions(+) create mode 100644 drivers/gpio/gpio-rpmsg.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index bd185482a7fd..00ea0c1d8035 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1883,6 +1883,22 @@ config GPIO_SODAVILLE endmenu +menu "RPMSG GPIO drivers" + depends on RPMSG + +config GPIO_RPMSG + tristate "Generic RPMSG GPIO support" + 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 2421a8fd3733..b1373ec274c8 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -156,6 +156,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..8c235d9dc336 --- /dev/null +++ b/drivers/gpio/gpio-rpmsg.c @@ -0,0 +1,583 @@ +// 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> + +#define RPMSG_GPIO_ID 5 +#define RPMSG_VENDOR 1 +#define RPMSG_VERSION 0 + +#define GPIOS_PER_PORT 32 +#define RPMSG_TIMEOUT 1000 + +/* GPIO RPMSG header type */ +#define GPIO_RPMSG_SETUP 0 +#define GPIO_RPMSG_REPLY 1 +#define GPIO_RPMSG_NOTIFY 2 + +/* GPIO Interrupt trigger type */ +#define GPIO_RPMSG_TRI_IGNORE 0 +#define GPIO_RPMSG_TRI_RISING 1 +#define GPIO_RPMSG_TRI_FALLING 2 +#define GPIO_RPMSG_TRI_BOTH_EDGE 3 +#define GPIO_RPMSG_TRI_LOW_LEVEL 4 +#define GPIO_RPMSG_TRI_HIGH_LEVEL 5 + +/* GPIO RPMSG commands */ +#define GPIO_RPMSG_INPUT_INIT 0 +#define GPIO_RPMSG_OUTPUT_INIT 1 +#define GPIO_RPMSG_INPUT_GET 2 +#define GPIO_RPMSG_DIRECTION_GET 3 + +#define MAX_PORT_PER_CHANNEL 10 + +/* + * @rproc_name: the name of the remote proc. + * @channel_devices: an array of the devices related to the rpdev. + */ +struct rpdev_drvdata { + const char *rproc_name; + void *channel_devices[MAX_PORT_PER_CHANNEL]; +}; + +struct gpio_rpmsg_head { + u8 id; /* Message ID Code */ + u8 vendor; /* Vendor ID number */ + u8 version; /* Vendor-specific version number */ + u8 type; /* Message type */ + u8 cmd; /* Command code */ + u8 reserved[5]; +} __packed; + +struct gpio_rpmsg_packet { + struct gpio_rpmsg_head header; + u8 pin_idx; + u8 port_idx; + union { + u8 event; + u8 retcode; + u8 value; + } out; + union { + u8 wakeup; + u8 value; + } in; +} __packed __aligned(8); + +struct gpio_rpmsg_pin { + u8 irq_shutdown; + u8 irq_unmask; + u8 irq_mask; + u32 irq_wake_enable; + u32 irq_type; + struct gpio_rpmsg_packet msg; +}; + +struct gpio_rpmsg_info { + struct rpmsg_device *rpdev; + struct gpio_rpmsg_packet *reply_msg; + struct completion cmd_complete; + struct mutex lock; + void **port_store; +}; + +struct rpmsg_gpio_port { + struct gpio_chip gc; + struct gpio_rpmsg_pin gpio_pins[GPIOS_PER_PORT]; + struct gpio_rpmsg_info info; + int idx; +}; + +static int gpio_send_message(struct rpmsg_gpio_port *port, + struct gpio_rpmsg_packet *msg, + bool sync) +{ + struct gpio_rpmsg_info *info = &port->info; + int err; + + reinit_completion(&info->cmd_complete); + err = rpmsg_send(info->rpdev->ept, msg, sizeof(struct gpio_rpmsg_packet)); + if (err) { + dev_err(&info->rpdev->dev, "rpmsg_send failed: %d\n", err); + return err; + } + + if (sync) { + err = wait_for_completion_timeout(&info->cmd_complete, + msecs_to_jiffies(RPMSG_TIMEOUT)); + if (!err) { + dev_err(&info->rpdev->dev, "rpmsg_send timeout!\n"); + return -ETIMEDOUT; + } + + if (info->reply_msg->out.retcode != 0) { + dev_err(&info->rpdev->dev, "remote core replies an error: %d!\n", + info->reply_msg->out.retcode); + return -EINVAL; + } + + /* copy the reply message */ + memcpy(&port->gpio_pins[info->reply_msg->pin_idx].msg, + info->reply_msg, sizeof(*info->reply_msg)); + } + + return 0; +} + +static struct gpio_rpmsg_packet *gpio_setup_msg_header(struct rpmsg_gpio_port *port, + unsigned int offset, + u8 cmd) +{ + struct gpio_rpmsg_packet *msg = &port->gpio_pins[offset].msg; + + memset(msg, 0, sizeof(struct gpio_rpmsg_packet)); + msg->header.id = RPMSG_GPIO_ID; + msg->header.vendor = RPMSG_VENDOR; + msg->header.version = RPMSG_VERSION; + msg->header.type = GPIO_RPMSG_SETUP; + msg->header.cmd = cmd; + msg->pin_idx = offset; + msg->port_idx = port->idx; + + return msg; +} + +static int rpmsg_gpio_get(struct gpio_chip *gc, unsigned int gpio) +{ + struct rpmsg_gpio_port *port = gpiochip_get_data(gc); + struct gpio_rpmsg_packet *msg; + int ret; + + guard(mutex)(&port->info.lock); + + msg = gpio_setup_msg_header(port, gpio, GPIO_RPMSG_INPUT_GET); + + ret = gpio_send_message(port, msg, true); + if (!ret) + ret = !!port->gpio_pins[gpio].msg.in.value; + + return ret; +} + +static int rpmsg_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio) +{ + struct rpmsg_gpio_port *port = gpiochip_get_data(gc); + struct gpio_rpmsg_packet *msg; + int ret; + + guard(mutex)(&port->info.lock); + + msg = gpio_setup_msg_header(port, gpio, GPIO_RPMSG_DIRECTION_GET); + + ret = gpio_send_message(port, msg, true); + if (!ret) + ret = !!port->gpio_pins[gpio].msg.in.value; + + return ret; +} + +static int rpmsg_gpio_direction_input(struct gpio_chip *gc, unsigned int gpio) +{ + struct rpmsg_gpio_port *port = gpiochip_get_data(gc); + struct gpio_rpmsg_packet *msg; + + guard(mutex)(&port->info.lock); + + msg = gpio_setup_msg_header(port, gpio, GPIO_RPMSG_INPUT_INIT); + + return gpio_send_message(port, msg, true); +} + +static int rpmsg_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) +{ + struct rpmsg_gpio_port *port = gpiochip_get_data(gc); + struct gpio_rpmsg_packet *msg; + + guard(mutex)(&port->info.lock); + + msg = gpio_setup_msg_header(port, gpio, GPIO_RPMSG_OUTPUT_INIT); + msg->out.value = val; + + return gpio_send_message(port, msg, true); +} + +static int rpmsg_gpio_direction_output(struct gpio_chip *gc, + unsigned int gpio, + int val) +{ + return rpmsg_gpio_set(gc, gpio, val); +} + +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 gpio_idx = d->hwirq; + int edge = 0; + int ret = 0; + + switch (type) { + case IRQ_TYPE_EDGE_RISING: + edge = GPIO_RPMSG_TRI_RISING; + irq_set_handler_locked(d, handle_simple_irq); + break; + case IRQ_TYPE_EDGE_FALLING: + edge = GPIO_RPMSG_TRI_FALLING; + irq_set_handler_locked(d, handle_simple_irq); + break; + case IRQ_TYPE_EDGE_BOTH: + edge = GPIO_RPMSG_TRI_BOTH_EDGE; + irq_set_handler_locked(d, handle_simple_irq); + break; + case IRQ_TYPE_LEVEL_LOW: + edge = GPIO_RPMSG_TRI_LOW_LEVEL; + irq_set_handler_locked(d, handle_level_irq); + break; + case IRQ_TYPE_LEVEL_HIGH: + edge = GPIO_RPMSG_TRI_HIGH_LEVEL; + irq_set_handler_locked(d, handle_level_irq); + break; + default: + ret = -EINVAL; + irq_set_handler_locked(d, handle_bad_irq); + break; + } + + port->gpio_pins[gpio_idx].irq_type = edge; + + return ret; +} + +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 gpio_idx = d->hwirq; + + port->gpio_pins[gpio_idx].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 gpio_idx = d->hwirq; + + port->gpio_pins[gpio_idx].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 gpio_idx = 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->gpio_pins[gpio_idx].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 gpio_idx = d->hwirq; + + port->gpio_pins[gpio_idx].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->info.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); + struct gpio_rpmsg_packet *msg = NULL; + u32 gpio_idx = d->hwirq; + + /* + * For mask irq, do nothing here. + * The remote system will mask interrupt after an interrupt occurs, + * and then send a notify to Linux system. + * After Linux system dealt with the notify, it will send an rpmsg to + * the remote system to unmask this interrupt again. + */ + if (port->gpio_pins[gpio_idx].irq_mask && !port->gpio_pins[gpio_idx].irq_unmask) { + port->gpio_pins[gpio_idx].irq_mask = 0; + mutex_unlock(&port->info.lock); + return; + } + + msg = gpio_setup_msg_header(port, gpio_idx, GPIO_RPMSG_INPUT_INIT); + + if (port->gpio_pins[gpio_idx].irq_shutdown) { + msg->out.event = GPIO_RPMSG_TRI_IGNORE; + msg->in.wakeup = 0; + port->gpio_pins[gpio_idx].irq_shutdown = 0; + } else { + /* if not set irq type, then use low level as trigger type */ + msg->out.event = port->gpio_pins[gpio_idx].irq_type; + if (!msg->out.event) + msg->out.event = GPIO_RPMSG_TRI_LOW_LEVEL; + if (port->gpio_pins[gpio_idx].irq_unmask) { + msg->in.wakeup = 0; + port->gpio_pins[gpio_idx].irq_unmask = 0; + } else /* irq set wake */ + msg->in.wakeup = port->gpio_pins[gpio_idx].irq_wake_enable; + } + + gpio_send_message(port, msg, false); + mutex_unlock(&port->info.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 void rpmsg_gpio_remove_action(void *data) +{ + struct rpmsg_gpio_port *port = data; + + port->info.port_store[port->idx] = NULL; +} + +static int rpmsg_gpiochip_register(struct rpmsg_device *rpdev, struct device_node *np) +{ + struct rpdev_drvdata *drvdata = dev_get_drvdata(&rpdev->dev); + 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; + + if (port->idx >= MAX_PORT_PER_CHANNEL) + return -EINVAL; + + ret = devm_mutex_init(&rpdev->dev, &port->info.lock); + if (ret) + return ret; + + init_completion(&port->info.cmd_complete); + port->info.reply_msg = devm_kzalloc(&rpdev->dev, + sizeof(struct gpio_rpmsg_packet), + GFP_KERNEL); + port->info.port_store = drvdata->channel_devices; + port->info.port_store[port->idx] = port; + port->info.rpdev = rpdev; + + gc = &port->gc; + gc->owner = THIS_MODULE; + gc->parent = &rpdev->dev; + gc->fwnode = of_fwnode_handle(np); + gc->ngpio = GPIOS_PER_PORT; + gc->base = -1; + gc->label = devm_kasprintf(&rpdev->dev, GFP_KERNEL, "%s-gpio%d", + drvdata->rproc_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_kasprintf(&rpdev->dev, GFP_KERNEL, "%s-gpio%d", + drvdata->rproc_name, port->idx); + + ret = devm_add_action_or_reset(&rpdev->dev, rpmsg_gpio_remove_action, port); + if (ret) + return ret; + + 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_get_channel_ofnode(struct rpmsg_device *rpdev, char *chan_name) +{ + struct device_node *np_chan = NULL, *np; + struct rproc *rproc; + + rproc = rproc_get_by_child(&rpdev->dev); + if (!rproc) + return NULL; + + np = of_node_get(rproc->dev.of_node); + if (!np && rproc->dev.parent) + np = of_node_get(rproc->dev.parent->of_node); + + if (np) { + /* Balance the of_node_put() performed by of_find_node_by_name(). */ + of_node_get(np); + np_chan = of_find_node_by_name(np, chan_name); + of_node_put(np); + } + + return np_chan; +} + +static int +rpmsg_gpio_channel_callback(struct rpmsg_device *rpdev, void *data, + int len, void *priv, u32 src) +{ + struct gpio_rpmsg_packet *msg = data; + struct rpmsg_gpio_port *port = NULL; + struct rpdev_drvdata *drvdata; + + drvdata = dev_get_drvdata(&rpdev->dev); + if (drvdata && msg && (msg->port_idx < MAX_PORT_PER_CHANNEL)) + port = drvdata->channel_devices[msg->port_idx]; + + if (!port) + return -ENODEV; + + if (msg->header.type == GPIO_RPMSG_REPLY) { + *port->info.reply_msg = *msg; + complete(&port->info.cmd_complete); + } else if (msg->header.type == GPIO_RPMSG_NOTIFY) { + generic_handle_domain_irq_safe(port->gc.irq.domain, msg->pin_idx); + } else + dev_err(&rpdev->dev, "wrong command type!\n"); + + return 0; +} + +static int rpmsg_gpio_channel_probe(struct rpmsg_device *rpdev) +{ + struct device *dev = &rpdev->dev; + struct rpdev_drvdata *drvdata; + struct device_node *np; + int ret; + + if (!dev->of_node) { + np = rpmsg_get_channel_ofnode(rpdev, rpdev->id.name); + if (np) { + dev->of_node = np; + set_primary_fwnode(dev, of_fwnode_handle(np)); + } + return -EPROBE_DEFER; + } + + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); + if (!drvdata) + return -ENOMEM; + + drvdata->rproc_name = rpmsg_get_rproc_node_name(rpdev); + dev_set_drvdata(dev, drvdata); + + for_each_child_of_node_scoped(dev->of_node, child) { + if (!of_device_is_available(child)) + continue; + + if (!of_match_node(dev->driver->of_match_table, child)) + continue; + + ret = rpmsg_gpiochip_register(rpdev, child); + if (ret < 0) + dev_err(dev, "Failed to register: %pOF\n", child); + } + + return 0; +} + +static void rpmsg_gpio_channel_remove(struct rpmsg_device *rpdev) +{ + dev_info(&rpdev->dev, "rpmsg gpio channel driver is removed\n"); +} + +static const struct of_device_id rpmsg_gpio_dt_ids[] = { + { .compatible = "rpmsg-gpio" }, + { /* sentinel */ } +}; + +static struct rpmsg_device_id rpmsg_gpio_channel_id_table[] = { + { .name = "rpmsg-io-channel" }, + { }, +}; +MODULE_DEVICE_TABLE(rpmsg, rpmsg_gpio_channel_id_table); + +static struct rpmsg_driver rpmsg_gpio_channel_client = { + .drv.name = KBUILD_MODNAME, + .drv.of_match_table = rpmsg_gpio_dt_ids, + .id_table = rpmsg_gpio_channel_id_table, + .probe = rpmsg_gpio_channel_probe, + .callback = rpmsg_gpio_channel_callback, + .remove = rpmsg_gpio_channel_remove, +}; +module_rpmsg_driver(rpmsg_gpio_channel_client); + +MODULE_AUTHOR("Shenwei Wang <shenwei.wang@nxp.com>"); +MODULE_DESCRIPTION("generic rpmsg gpio driver"); +MODULE_LICENSE("GPL"); -- 2.43.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v7 3/4] gpio: rpmsg: add generic rpmsg GPIO driver 2026-02-10 17:08 ` [PATCH v7 3/4] gpio: rpmsg: add generic rpmsg GPIO driver Shenwei Wang @ 2026-02-10 17:48 ` Andrew Lunn 2026-02-10 20:17 ` Shenwei Wang 2026-02-11 5:56 ` kernel test robot 2026-02-11 14:37 ` kernel test robot 2 siblings, 1 reply; 13+ messages in thread From: Andrew Lunn @ 2026-02-10 17:48 UTC (permalink / raw) To: Shenwei Wang Cc: Linus Walleij, Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Mathieu Poirier, Shawn Guo, Sascha Hauer, Jonathan Corbet, Pengutronix Kernel Team, Fabio Estevam, Peng Fan, linux-gpio, devicetree, linux-kernel, linux-remoteproc, imx, linux-arm-kernel, linux-doc, linux-imx, arnaud.pouliquen, Bartosz Golaszewski > +#define GPIOS_PER_PORT 32 Maybe this should be from DT, using "ngpios". The Documentation says: Optionally, a GPIO controller may have a "ngpios" property. This property indicates the number of in-use slots of available slots for GPIOs. The typical example is something like this: the hardware register is 32 bits wide, but only 18 of the bits have a physical counterpart. The driver is generally written so that all 32 bits can be used, but the IP block is reused in a lot of designs, some using all 32 bits, some using 18 and some using 12. In this case, setting "ngpios = <18>;" informs the driver that only the first 18 GPIOs, at local offset 0 .. 17, are in use. Just because your hardware has 32 does not mean every vendor does. > +struct gpio_rpmsg_head { > + u8 id; /* Message ID Code */ > + u8 vendor; /* Vendor ID number */ > + u8 version; /* Vendor-specific version number */ > + u8 type; /* Message type */ > + u8 cmd; /* Command code */ > + u8 reserved[5]; > +} __packed; I still think this should be a clean design from scratch, and you modify your firmware. This data structure is 10 bytes. Are these all needed for a generic GPIO controller? version, type, command and one reserved byte seems like enough, and it is then 4 bytes, so there is no need for __packed. > +struct gpio_rpmsg_packet { > + struct gpio_rpmsg_head header; > + u8 pin_idx; > + u8 port_idx; > + union { > + u8 event; > + u8 retcode; > + u8 value; > + } out; > + union { > + u8 wakeup; > + u8 value; > + } in; > +} __packed __aligned(8); This then becomes 8 bytes, so there is no need for __packed or __aligned(8). I don't want to force this, it is something i think which should be discussed. Do we adopt your design, which is not so nice, but at least has one working implementation, or do we do a clean design? > +static int gpio_send_message(struct rpmsg_gpio_port *port, > + struct gpio_rpmsg_packet *msg, > + bool sync) > +{ > + struct gpio_rpmsg_info *info = &port->info; > + int err; > + > + reinit_completion(&info->cmd_complete); > + err = rpmsg_send(info->rpdev->ept, msg, sizeof(struct gpio_rpmsg_packet)); > + if (err) { > + dev_err(&info->rpdev->dev, "rpmsg_send failed: %d\n", err); > + return err; > + } > + > + if (sync) { > + err = wait_for_completion_timeout(&info->cmd_complete, > + msecs_to_jiffies(RPMSG_TIMEOUT)); > + if (!err) { > + dev_err(&info->rpdev->dev, "rpmsg_send timeout!\n"); > + return -ETIMEDOUT; > + } I _think_ you need to handle negative values of err. It looks like do_wait_for_common() can return -ERESTARTSYS; > +static struct gpio_rpmsg_packet *gpio_setup_msg_header(struct rpmsg_gpio_port *port, > + unsigned int offset, > + u8 cmd) > +{ > + struct gpio_rpmsg_packet *msg = &port->gpio_pins[offset].msg; > + > + memset(msg, 0, sizeof(struct gpio_rpmsg_packet)); > + msg->header.id = RPMSG_GPIO_ID; > + msg->header.vendor = RPMSG_VENDOR; > + msg->header.version = RPMSG_VERSION; > + msg->header.type = GPIO_RPMSG_SETUP; > + msg->header.cmd = cmd; > + msg->pin_idx = offset; > + msg->port_idx = port->idx; Why is a function called gpio_setup_msg_header() setting things outside of the header? > +static int rpmsg_gpio_get(struct gpio_chip *gc, unsigned int gpio) > +{ > + struct rpmsg_gpio_port *port = gpiochip_get_data(gc); > + struct gpio_rpmsg_packet *msg; > + int ret; > + > + guard(mutex)(&port->info.lock); > + > + msg = gpio_setup_msg_header(port, gpio, GPIO_RPMSG_INPUT_GET); > + > + ret = gpio_send_message(port, msg, true); If gpio_setup_msg_header() does what it sounds like it should do, what is setting up the message body before you send the message? Andrew ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v7 3/4] gpio: rpmsg: add generic rpmsg GPIO driver 2026-02-10 17:48 ` Andrew Lunn @ 2026-02-10 20:17 ` Shenwei Wang 0 siblings, 0 replies; 13+ messages in thread From: Shenwei Wang @ 2026-02-10 20:17 UTC (permalink / raw) To: Andrew Lunn Cc: Linus Walleij, Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Mathieu Poirier, Shawn Guo, Sascha Hauer, Jonathan Corbet, Pengutronix Kernel Team, Fabio Estevam, Peng Fan, linux-gpio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-remoteproc@vger.kernel.org, imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, dl-linux-imx, arnaud.pouliquen@foss.st.com, Bartosz Golaszewski > -----Original Message----- > From: Andrew Lunn <andrew@lunn.ch> > Sent: Tuesday, February 10, 2026 11:48 AM > To: Shenwei Wang <shenwei.wang@nxp.com> > Cc: Linus Walleij <linusw@kernel.org>; Bartosz Golaszewski <brgl@kernel.org>; > 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>; Shawn > Guo <shawnguo@kernel.org>; Sascha Hauer <s.hauer@pengutronix.de>; > Jonathan Corbet <corbet@lwn.net>; Pengutronix Kernel Team > <kernel@pengutronix.de>; Fabio Estevam <festevam@gmail.com>; Peng Fan > <peng.fan@nxp.com>; linux-gpio@vger.kernel.org; devicetree@vger.kernel.org; > linux-kernel@vger.kernel.org; linux-remoteproc@vger.kernel.org; > imx@lists.linux.dev; linux-arm-kernel@lists.infradead.org; linux- > doc@vger.kernel.org; dl-linux-imx <linux-imx@nxp.com>; > arnaud.pouliquen@foss.st.com; Bartosz Golaszewski <brgl@bgdev.pl> > Subject: [EXT] Re: [PATCH v7 3/4] gpio: rpmsg: add generic rpmsg GPIO driver > > +#define GPIOS_PER_PORT 32 > > Maybe this should be from DT, using "ngpios". The Documentation says: > > Optionally, a GPIO controller may have a "ngpios" property. This > property indicates the number of in-use slots of available slots for > GPIOs. The typical example is something like this: the hardware > register is 32 bits wide, but only 18 of the bits have a physical > counterpart. The driver is generally written so that all 32 bits can > be used, but the IP block is reused in a lot of designs, some using > all 32 bits, some using 18 and some using 12. In this case, setting > "ngpios = <18>;" informs the driver that only the first 18 GPIOs, at > local offset 0 .. 17, are in use. > > Just because your hardware has 32 does not mean every vendor does. > 32 just represents the maximum number of GPIO lines that the driver can support, so there's no need to declare all of them as in use. Adding support for the ngpios property is a good suggestion, and I'll include this property in the next version. > > +struct gpio_rpmsg_head { > > + u8 id; /* Message ID Code */ > > + u8 vendor; /* Vendor ID number */ > > + u8 version; /* Vendor-specific version number */ > > + u8 type; /* Message type */ > > + u8 cmd; /* Command code */ > > + u8 reserved[5]; > > +} __packed; > > I still think this should be a clean design from scratch, and you modify your > firmware. > I do need to take the existing constraints into account. It's always ideal to start with a clean design, but I also have to maintain compatibility with the current products in the field. The approach should break what already exists. However, as the companion firmware is updated over time, the driver can be refined accordingly. > This data structure is 10 bytes. Are these all needed for a generic GPIO > controller? version, type, command and one reserved byte seems like enough, > and it is then 4 bytes, so there is no need for __packed. > > > +struct gpio_rpmsg_packet { > > + struct gpio_rpmsg_head header; > > + u8 pin_idx; > > + u8 port_idx; > > + union { > > + u8 event; > > + u8 retcode; > > + u8 value; > > + } out; > > + union { > > + u8 wakeup; > > + u8 value; > > + } in; > > +} __packed __aligned(8); > > This then becomes 8 bytes, so there is no need for __packed or __aligned(8). > Even though the struct currently evaluates to 8 bytes, that doesn't make __packed or __aligned(8) unnecessary. Because struct layout and default alignment vary between compilers and architectures, these attributes still serve specific purposes-__packed ensures there's no internal padding, and __aligned(8) enforces the external alignment. Without them, the layout may not be consistent across toolchains or build configurations. > I don't want to force this, it is something i think which should be discussed. Do we > adopt your design, which is not so nice, but at least has one working > implementation, or do we do a clean design? > I'd lean toward getting a working solution in place first and then improving the design over time. This approach lets us ensure functionality for current users while still giving us room to evolve toward a cleaner, more consistent design as the code and firmware mature. > > +static int gpio_send_message(struct rpmsg_gpio_port *port, > > + struct gpio_rpmsg_packet *msg, > > + bool sync) > > +{ > > + struct gpio_rpmsg_info *info = &port->info; > > + int err; > > + > > + reinit_completion(&info->cmd_complete); > > + err = rpmsg_send(info->rpdev->ept, msg, sizeof(struct gpio_rpmsg_packet)); > > + if (err) { > > + dev_err(&info->rpdev->dev, "rpmsg_send failed: %d\n", err); > > + return err; > > + } > > + > > + if (sync) { > > + err = wait_for_completion_timeout(&info->cmd_complete, > > + msecs_to_jiffies(RPMSG_TIMEOUT)); > > + if (!err) { > > + dev_err(&info->rpdev->dev, "rpmsg_send timeout!\n"); > > + return -ETIMEDOUT; > > + } > > I _think_ you need to handle negative values of err. It looks like > do_wait_for_common() can return -ERESTARTSYS; > > > +static struct gpio_rpmsg_packet *gpio_setup_msg_header(struct > rpmsg_gpio_port *port, > > + unsigned int offset, > > + u8 cmd) { > > + struct gpio_rpmsg_packet *msg = &port->gpio_pins[offset].msg; > > + > > + memset(msg, 0, sizeof(struct gpio_rpmsg_packet)); > > + msg->header.id = RPMSG_GPIO_ID; > > + msg->header.vendor = RPMSG_VENDOR; > > + msg->header.version = RPMSG_VERSION; > > + msg->header.type = GPIO_RPMSG_SETUP; > > + msg->header.cmd = cmd; > > + msg->pin_idx = offset; > > + msg->port_idx = port->idx; > > Why is a function called gpio_setup_msg_header() setting things outside of the > header? > How about change to gpio_setup_msg_common()? Thanks, Shenwei > > +static int rpmsg_gpio_get(struct gpio_chip *gc, unsigned int gpio) { > > + struct rpmsg_gpio_port *port = gpiochip_get_data(gc); > > + struct gpio_rpmsg_packet *msg; > > + int ret; > > + > > + guard(mutex)(&port->info.lock); > > + > > + msg = gpio_setup_msg_header(port, gpio, GPIO_RPMSG_INPUT_GET); > > + > > + ret = gpio_send_message(port, msg, true); > > If gpio_setup_msg_header() does what it sounds like it should do, what is setting > up the message body before you send the message? > > Andrew ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v7 3/4] gpio: rpmsg: add generic rpmsg GPIO driver 2026-02-10 17:08 ` [PATCH v7 3/4] gpio: rpmsg: add generic rpmsg GPIO driver Shenwei Wang 2026-02-10 17:48 ` Andrew Lunn @ 2026-02-11 5:56 ` kernel test robot 2026-02-11 14:37 ` kernel test robot 2 siblings, 0 replies; 13+ messages in thread From: kernel test robot @ 2026-02-11 5:56 UTC (permalink / raw) To: Shenwei Wang, Linus Walleij, Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Mathieu Poirier, Shawn Guo, Sascha Hauer, Jonathan Corbet Cc: oe-kbuild-all, Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan, linux-gpio, devicetree, linux-kernel, linux-remoteproc, imx, linux-arm-kernel, linux-doc, linux-imx, arnaud.pouliquen, Andrew Lunn Hi Shenwei, kernel test robot noticed the following build errors: [auto build test ERROR on brgl/gpio/for-next] [also build test ERROR on robh/for-next remoteproc/rproc-next linus/master v6.19 next-20260210] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Shenwei-Wang/dt-bindings-remoteproc-imx_rproc-Add-rpmsg-subnode-support/20260211-011505 base: https://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux.git gpio/for-next patch link: https://lore.kernel.org/r/20260210170814.406883-4-shenwei.wang%40nxp.com patch subject: [PATCH v7 3/4] gpio: rpmsg: add generic rpmsg GPIO driver config: nios2-randconfig-r054-20260211 (https://download.01.org/0day-ci/archive/20260211/202602111320.C3eHRtNV-lkp@intel.com/config) compiler: nios2-linux-gcc (GCC) 9.5.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260211/202602111320.C3eHRtNV-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202602111320.C3eHRtNV-lkp@intel.com/ All errors (new ones prefixed by >>): nios2-linux-ld: drivers/gpio/gpio-rpmsg.o: in function `rpmsg_get_channel_ofnode': >> drivers/gpio/gpio-rpmsg.c:473: undefined reference to `rproc_get_by_child' >> drivers/gpio/gpio-rpmsg.c:473:(.text+0x454): relocation truncated to fit: R_NIOS2_CALL26 against `rproc_get_by_child' nios2-linux-ld: drivers/gpio/gpio-rpmsg.o: in function `rpmsg_get_rproc_node_name': drivers/gpio/gpio-rpmsg.c:450: undefined reference to `rproc_get_by_child' drivers/gpio/gpio-rpmsg.c:450:(.text+0x4e0): relocation truncated to fit: R_NIOS2_CALL26 against `rproc_get_by_child' vim +473 drivers/gpio/gpio-rpmsg.c 466 467 static struct device_node * 468 rpmsg_get_channel_ofnode(struct rpmsg_device *rpdev, char *chan_name) 469 { 470 struct device_node *np_chan = NULL, *np; 471 struct rproc *rproc; 472 > 473 rproc = rproc_get_by_child(&rpdev->dev); 474 if (!rproc) 475 return NULL; 476 477 np = of_node_get(rproc->dev.of_node); 478 if (!np && rproc->dev.parent) 479 np = of_node_get(rproc->dev.parent->of_node); 480 481 if (np) { 482 /* Balance the of_node_put() performed by of_find_node_by_name(). */ 483 of_node_get(np); 484 np_chan = of_find_node_by_name(np, chan_name); 485 of_node_put(np); 486 } 487 488 return np_chan; 489 } 490 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v7 3/4] gpio: rpmsg: add generic rpmsg GPIO driver 2026-02-10 17:08 ` [PATCH v7 3/4] gpio: rpmsg: add generic rpmsg GPIO driver Shenwei Wang 2026-02-10 17:48 ` Andrew Lunn 2026-02-11 5:56 ` kernel test robot @ 2026-02-11 14:37 ` kernel test robot 2 siblings, 0 replies; 13+ messages in thread From: kernel test robot @ 2026-02-11 14:37 UTC (permalink / raw) To: Shenwei Wang, Linus Walleij, Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Mathieu Poirier, Shawn Guo, Sascha Hauer, Jonathan Corbet Cc: oe-kbuild-all, Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan, linux-gpio, devicetree, linux-kernel, linux-remoteproc, imx, linux-arm-kernel, linux-doc, linux-imx, arnaud.pouliquen, Andrew Lunn Hi Shenwei, kernel test robot noticed the following build errors: [auto build test ERROR on brgl/gpio/for-next] [also build test ERROR on robh/for-next remoteproc/rproc-next linus/master v6.19 next-20260210] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Shenwei-Wang/dt-bindings-remoteproc-imx_rproc-Add-rpmsg-subnode-support/20260211-011505 base: https://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux.git gpio/for-next patch link: https://lore.kernel.org/r/20260210170814.406883-4-shenwei.wang%40nxp.com patch subject: [PATCH v7 3/4] gpio: rpmsg: add generic rpmsg GPIO driver config: sparc-randconfig-r133-20260211 (https://download.01.org/0day-ci/archive/20260211/202602112252.gWFirLCA-lkp@intel.com/config) compiler: sparc-linux-gcc (GCC) 13.4.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260211/202602112252.gWFirLCA-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202602112252.gWFirLCA-lkp@intel.com/ All errors (new ones prefixed by >>): sparc-linux-ld: drivers/gpio/gpio-rpmsg.o: in function `rpmsg_gpio_channel_probe': >> gpio-rpmsg.c:(.text+0x788): undefined reference to `rproc_get_by_child' >> sparc-linux-ld: gpio-rpmsg.c:(.text+0x834): undefined reference to `rproc_get_by_child' -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v7 4/4] arm64: dts: imx8ulp: Add rpmsg node under imx_rproc 2026-02-10 17:08 [PATCH v7 0/4] Enable Remote GPIO over RPMSG on i.MX Platform Shenwei Wang ` (2 preceding siblings ...) 2026-02-10 17:08 ` [PATCH v7 3/4] gpio: rpmsg: add generic rpmsg GPIO driver Shenwei Wang @ 2026-02-10 17:08 ` Shenwei Wang 3 siblings, 0 replies; 13+ messages in thread From: Shenwei Wang @ 2026-02-10 17:08 UTC (permalink / raw) To: Linus Walleij, Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Mathieu Poirier, Shawn Guo, Sascha Hauer, Jonathan Corbet Cc: Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan, linux-gpio, devicetree, linux-kernel, linux-remoteproc, imx, linux-arm-kernel, linux-doc, linux-imx, arnaud.pouliquen 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 | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi index 13b01f3aa2a4..93846435c6c1 100644 --- a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi @@ -191,6 +191,33 @@ scmi_sensor: protocol@15 { cm33: remoteproc-cm33 { compatible = "fsl,imx8ulp-cm33"; status = "disabled"; + + rpmsg { + rpmsg-io-channel { + #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; + interrupt-parent = <&rpmsg_gpioa>; + }; + + rpmsg_gpiob: gpio@1 { + compatible = "rpmsg-gpio"; + reg = <1>; + gpio-controller; + #gpio-cells = <2>; + #interrupt-cells = <2>; + interrupt-controller; + interrupt-parent = <&rpmsg_gpiob>; + }; + }; + }; }; soc: soc@0 { -- 2.43.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v7 0/4] Enable Remote GPIO over RPMSG on i.MX Platform
@ 2026-02-10 17:04 Shenwei Wang
2026-02-10 17:04 ` [PATCH v7 1/4] dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode support Shenwei Wang
0 siblings, 1 reply; 13+ messages in thread
From: Shenwei Wang @ 2026-02-10 17:04 UTC (permalink / raw)
To: Linus Walleij, Bartosz Golaszewski, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
Mathieu Poirier, Shawn Guo, Sascha Hauer, Jonathan Corbet
Cc: Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan,
linux-gpio, devicetree, linux-kernel, linux-remoteproc, imx,
linux-arm-kernel, linux-doc, linux-imx, arnaud.pouliquen
Support the remote devices on the remote processor via the RPMSG bus on
i.MX platform.
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 (4):
dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode support
docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus
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 | 236 +++++++
Documentation/driver-api/gpio/index.rst | 1 +
arch/arm64/boot/dts/freescale/imx8ulp.dtsi | 27 +
drivers/gpio/Kconfig | 16 +
drivers/gpio/Makefile | 1 +
drivers/gpio/gpio-rpmsg.c | 583 ++++++++++++++++++
8 files changed, 972 insertions(+)
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] 13+ messages in thread* [PATCH v7 1/4] dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode support 2026-02-10 17:04 [PATCH v7 0/4] Enable Remote GPIO over RPMSG on i.MX Platform Shenwei Wang @ 2026-02-10 17:04 ` Shenwei Wang 0 siblings, 0 replies; 13+ messages in thread From: Shenwei Wang @ 2026-02-10 17:04 UTC (permalink / raw) To: Linus Walleij, Bartosz Golaszewski, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson, Mathieu Poirier, Shawn Guo, Sascha Hauer, Jonathan Corbet Cc: Pengutronix Kernel Team, Fabio Estevam, Shenwei Wang, Peng Fan, linux-gpio, devicetree, linux-kernel, linux-remoteproc, imx, linux-arm-kernel, linux-doc, linux-imx, arnaud.pouliquen 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 57d75acb0b5e..2f9dca2b71f7 100644 --- a/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml +++ b/Documentation/devicetree/bindings/remoteproc/fsl,imx-rproc.yaml @@ -84,6 +84,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-channel: + 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 @@ -146,5 +174,30 @@ examples: &mu 3 1>; memory-region = <&vdev0buffer>, <&vdev0vring0>, <&vdev0vring1>, <&rsc_table>; syscon = <&src>; + + rpmsg { + rpmsg-io-channel { + #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] 13+ messages in thread
end of thread, other threads:[~2026-02-11 20:54 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-02-10 17:08 [PATCH v7 0/4] Enable Remote GPIO over RPMSG on i.MX Platform Shenwei Wang 2026-02-10 17:08 ` [PATCH v7 1/4] dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode support Shenwei Wang 2026-02-10 20:48 ` Rob Herring (Arm) 2026-02-11 17:26 ` Shenwei Wang 2026-02-11 20:53 ` Rob Herring 2026-02-10 17:08 ` [PATCH v7 2/4] docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus Shenwei Wang 2026-02-10 17:08 ` [PATCH v7 3/4] gpio: rpmsg: add generic rpmsg GPIO driver Shenwei Wang 2026-02-10 17:48 ` Andrew Lunn 2026-02-10 20:17 ` Shenwei Wang 2026-02-11 5:56 ` kernel test robot 2026-02-11 14:37 ` kernel test robot 2026-02-10 17:08 ` [PATCH v7 4/4] arm64: dts: imx8ulp: Add rpmsg node under imx_rproc Shenwei Wang -- strict thread matches above, loose matches on Subject: below -- 2026-02-10 17:04 [PATCH v7 0/4] Enable Remote GPIO over RPMSG on i.MX Platform Shenwei Wang 2026-02-10 17:04 ` [PATCH v7 1/4] dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode support Shenwei Wang
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox