[PATCH v13 3/4] gpio: rpmsg: add generic rpmsg GPIO driver

Shah, Tanmay tanmays at amd.com
Tue May 5 08:38:26 PDT 2026



On 5/5/2026 6:16 AM, Beleswar Prasad Padhi wrote:
> Hi Tanmay,
> 
> On 05/05/26 00:49, Shah, Tanmay wrote:
>> Hello all,
>>
>> I have started reviewing this work as well.
>> Thanks Shenwei for this work.
>>
>> I have gone through only the current revision, and would like to provide
>> idea on how to achieve GPIO number multiplexing with the RPMsg protocol.
>> Also, have some bindings related question.
>>
>> Please see below:
>>
>> On 4/30/2026 11:40 AM, Arnaud POULIQUEN wrote:
>>>
>>> On 4/30/26 14:56, Beleswar Prasad Padhi wrote:
>>>> Hello Arnaud,
>>>>
>>>> On 30/04/26 13:05, Arnaud POULIQUEN wrote:
>>>>> Hello,
>>>>>
>>>>> On 4/29/26 21:20, Mathieu Poirier wrote:
>>>>>> On Wed, 29 Apr 2026 at 12:07, Padhi, Beleswar <b-padhi at ti.com> wrote:
>>>>>>> Hi Mathieu,
>>>>>>>
>>>>>>> On 4/29/2026 11:03 PM, Mathieu Poirier wrote:
>>>>>>>> On Wed, 29 Apr 2026 at 10:53, Shenwei Wang <shenwei.wang at nxp.com>
>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>>> -----Original Message-----
>>>>>>>>>> From: Mathieu Poirier <mathieu.poirier at linaro.org>
>>>>>>>>>> Sent: Wednesday, April 29, 2026 10:42 AM
>>>>>>>>>> To: Shenwei Wang <shenwei.wang at nxp.com>
>>>>>>>>>> Cc: Andrew Lunn <andrew at lunn.ch>; Padhi, Beleswar <b-
>>>>>>>>>> padhi at ti.com>; Linus
>>>>>>>>>> Walleij <linusw at kernel.org>; Bartosz Golaszewski
>>>>>>>>>> <brgl at kernel.org>; Jonathan
>>>>>>>>>> Corbet <corbet at lwn.net>; Rob Herring <robh at kernel.org>;
>>>>>>>>>> Krzysztof Kozlowski
>>>>>>>>>> <krzk+dt at kernel.org>; Conor Dooley <conor+dt at kernel.org>; Bjorn
>>>>>>>>>> Andersson
>>>>>>>>>> <andersson at kernel.org>; Frank Li <frank.li at nxp.com>; Sascha Hauer
>>>>>>>>>> <s.hauer at pengutronix.de>; Shuah Khan
>>>>>>>>>> <skhan at linuxfoundation.org>; linux-
>>>>>>>>>> gpio at vger.kernel.org; linux-doc at vger.kernel.org; linux-
>>>>>>>>>> kernel at vger.kernel.org;
>>>>>>>>>> Pengutronix Kernel Team <kernel at pengutronix.de>; Fabio Estevam
>>>>>>>>>> <festevam at gmail.com>; Peng Fan <peng.fan at nxp.com>;
>>>>>>>>>> devicetree at vger.kernel.org; linux-remoteproc at vger.kernel.org;
>>>>>>>>>> imx at lists.linux.dev; linux-arm-kernel at lists.infradead.org; dl-
>>>>>>>>>> linux-imx <linux-
>>>>>>>>>> imx at nxp.com>; Bartosz Golaszewski <brgl at bgdev.pl>
>>>>>>>>>> Subject: [EXT] Re: [PATCH v13 3/4] gpio: rpmsg: add generic
>>>>>>>>>> rpmsg GPIO driver
>>>>>>>>>> On Tue, Apr 28, 2026 at 03:24:59PM +0000, Shenwei Wang wrote:
>>>>>>>>>>>> -----Original Message-----
>>>>>>>>>>>> From: Andrew Lunn <andrew at lunn.ch>
>>>>>>>>>>>> Sent: Monday, April 27, 2026 3:49 PM
>>>>>>>>>>>> To: Shenwei Wang <shenwei.wang at nxp.com>
>>>>>>>>>>>> Cc: Padhi, Beleswar <b-padhi at ti.com>; Linus Walleij
>>>>>>>>>>>> <linusw at kernel.org>; Bartosz Golaszewski <brgl at kernel.org>;
>>>>>>>>>>>> Jonathan
>>>>>>>>>>>> Corbet <corbet at lwn.net>; Rob Herring <robh at kernel.org>; Krzysztof
>>>>>>>>>>>> Kozlowski <krzk+dt at kernel.org>; Conor Dooley
>>>>>>>>>>>> <conor+dt at kernel.org>;
>>>>>>>>>>>> Bjorn Andersson <andersson at kernel.org>; Mathieu Poirier
>>>>>>>>>>>> <mathieu.poirier at linaro.org>; Frank Li <frank.li at nxp.com>; Sascha
>>>>>>>>>>>> Hauer <s.hauer at pengutronix.de>; Shuah Khan
>>>>>>>>>>>> <skhan at linuxfoundation.org>; linux-gpio at vger.kernel.org; linux-
>>>>>>>>>>>> doc at vger.kernel.org; linux-kernel at vger.kernel.org; Pengutronix
>>>>>>>>>>>> Kernel Team <kernel at pengutronix.de>; Fabio Estevam
>>>>>>>>>>>> <festevam at gmail.com>; Peng Fan <peng.fan at nxp.com>;
>>>>>>>>>>>> devicetree at vger.kernel.org; linux- remoteproc at vger.kernel.org;
>>>>>>>>>>>> imx at lists.linux.dev; linux-arm- kernel at lists.infradead.org;
>>>>>>>>>>>> dl-linux-imx <linux-imx at nxp.com>; Bartosz Golaszewski
>>>>>>>>>>>> <brgl at bgdev.pl>
>>>>>>>>>>>> Subject: [EXT] Re: [PATCH v13 3/4] gpio: rpmsg: add generic rpmsg
>>>>>>>>>>>> GPIO driver
>>>>>>>>>>>>>> struct virtio_gpio_response {
>>>>>>>>>>>>>>            __u8 status;
>>>>>>>>>>>>>>            __u8 value;
>>>>>>>>>>>>>> };
>>>>>>>>>>>>> It is the same message format. Please see the message definition
>>>>>>>>>>>> (GET_DIRECTION) below:
>>>>>>>>>>>>
>>>>>>>>>>>>> +   +-----+-----+-----+-----+-----+----+
>>>>>>>>>>>>> +   |0x00 |0x01 |0x02 |0x03 |0x04 |0x05|
>>>>>>>>>>>>> +   | 1   | 2   |port |line | err | dir|
>>>>>>>>>>>>> +   +-----+-----+-----+-----+-----+----+
>>>>>>>>>>>> Sorry, but i don't see how two u8 vs six u8 are the same
>>>>>>>>>>>> message format.
>>>>>>>>>>>>
>>>>>>>>>>> Some changes to the message format are necessary.
>>>>>>>>>>>
>>>>>>>>>>> Virtio uses two communication channels (virtqueues): one for
>>>>>>>>>>> requests and
>>>>>>>>>> replies, and a second one for events.
>>>>>>>>>>> In contrast, rpmsg provides only a single communication
>>>>>>>>>>> channel, so a
>>>>>>>>>>> type field is required to distinguish between different kinds
>>>>>>>>>>> of messages.
>>>>>>>>>>>
>>>>>>>>>>> Since rpmsg replies and events share the same message format,
>>>>>>>>>>> an additional
>>>>>>>>>> line is introduced to handle both cases.
>>>>>>>>>>> Finally, rpmsg supports multiple GPIO controllers, so a port
>>>>>>>>>>> field is added to
>>>>>>>>>> uniquely identify the target controller.
>>>>>>>>>>
>>>>>>>>>> I have commented on this before - RPMSG is already providing
>>>>>>>>>> multiplexing
>>>>>>>>>> capability by way of endpoints.  There is no need for a port
>>>>>>>>>> field.  One endpoint,
>>>>>>>>>> one GPIO controller.
>>>>>>>>>>
>>>>>>>>> You still need a way to let the remote side know which port the
>>>>>>>>> endpoint maps to, either
>>>>>>>>> by embedding the port information in the message (the current
>>>>>>>>> way), or by sending it
>>>>>>>>> separately.
>>>>>>>>>
>>>>>>>> An endpoint is created with every namespace request.  There should be
>>>>>>>> one namespace request for every GPIO controller, which yields a
>>>>>>>> unique
>>>>>>>> endpoint for each controller and eliminates the need for an extra
>>>>>>>> field to identify them.
>>>>>>>
>>>>>>> Right, but this can still be done by just having one namespace
>>>>>>> request.
>>>>>>> We can create new endpoints bound to an existing namespace/channel by
>>>>>>> invoking rpmsg_create_ept(). This is what I suggested here too:
>>>>>>> https://lore.kernel.org/all/29485742-6e49-482e-
>>>>>>> b73d-228295daaeec at ti.com/
>>>>>>>
>>>>>> I will look at your suggestion (i.e link above) later this week or
>>>>>> next week.
>>>>>>
>>>>>>> My mental model looks like this for the complete picture:
>>>>>>>
>>>>>>> 1. namespace/channel#1 = rpmsg-io
>>>>>>>       a. ept1 -> gpio-controller at 1
>>>>>>>       b. ept2 -> gpio-controller at 2
>>>>>>>
>> If my understanding of what gpio-controller is right, than this won't
>> work. We need one rpmsg channel per gpio-controller, and in most cases
>> there will be only one GPIO-controller on the remote side.
> 
> 
> Why so? In the current v13 version, the remote side already
> handles 2 GPIO controllers.
> 
>>  If there are
>> multiple or multiple instances of same controller, than we need separate
>> channel name for that controller just like we would have separate device
>> on the Linux.
> 
> 
> Why so? I think there is some confusion in the terminology:
> 
> GPIO controller = GPIO port (gpio at xyz) defined in the
> Device tree = struct rpmsg_gpio_port in code
> 
> GPIO line = Individual lines within each GPIO port (max =
> GPIOS_PER_PORT_DEFAULT) = struct rpmsg_gpio_line in code
> 

Okay, I understand now. So, same gpio controller has multiple instances.

>>>>>>> 1. namespace/channel#1 = rpmsg-io
>>>>>>>       a. ept1 -> gpio-controller at 1
>>>>>>>       b. ept2 -> gpio-controller at 2

So, In that case above mentioned approach doesn't work.

Because, this approach is mapping endpoint to the gpio-controller. From
linux's perspective, it needs to map rpmsg *channel* to the
gpio-controller not the endpoint.

To be more specific:

Linux:                               remote:

ch1: rpmsg-gpio.-1.1024 ->     gpio-controller at 1024
    - gpio-line ept1
    - gpio-line ept2    ->     They all map to same callback_ept_1024.
    - gpio-line ept3

ch2: rpmsg-gpio.-1.1025 ->     gpio-controller at 1025
    - gpio-line ept1
    - gpio-line ept2    ->     They all map to same callback_ept_1025.
    - gpio-line ept3

On the remote side, we have to hardcode Which rpmsg controller is mapped
to which endpoint.



>>
>>>>>> I've asked for one endpoint per GPIO controller since the very
>>>>>> beginning.  I don't yet have a strong opinion on whether to use one
>>>>>> namespace request per GPIO controller or a single request that spins
>>>>>> off multiple endpoints.  I'll have to look at your link and reflect on
>>>>>> that.  Regardless of how we proceed on that front, multiplexing needs
>>>>>> to happen at the endpoint level rather than the packet level.  This is
>>>>>> the only way this work can move forward.
>>>>>>
>>>>> I would be more in favor of Mathieu’s proposal: “An endpoint is
>>>>> created with every namespace request.”
>>>>>
>>>>> If the endpoint is created only on the Linux side, how do we match
>>>>> the Linux endpoint address with the local port field on the remote side?
>>>>
>>>> Simply by sending a message to the remote containing the newly created
>>>> endpoint and the port idx. Note that is this done just one time, after
>>>> this
>>>> Linux need not have the port field in the message everytime its sending
>>>> a message.
>>>>
>>>>> With a multi-namespace approach, the namespace could be rpmsg-io-
>>>>> [addr], where [addr] corresponds to the GPIO controller address in
>>>>> the DT. This would:
>>>>
>>>> You will face the same problem in this case also that you asked above:
>>>> "how do we match the Linux endpoint address with the local port field
>>>> on the remote side?"
>>> Sorry I probably introduced confusion here
>>> my sentence should be;
>>>  With a multi-namespace approach, the namespace could be rpmsg-io-[port],
>>>  where [port] corresponds to the GPIO controller port in the DT.
>>>
>>>
>>> For instance:
>>>
>>>       rpmsg {
>>>         rpmsg-io {
>>>           #address-cells = <1>;
>>>           #size-cells = <0>;
>>>
>>>           gpio at 25 {
>>>             compatible = "rpmsg-gpio";
>>>             reg = <25>;
>>>             gpio-controller;
>>>             #gpio-cells = <2>;
>>>             #interrupt-cells = <2>;
>>>             interrupt-controller;
>>>           };
>>>
>>>           gpio at 32 {
>>>             compatible = "rpmsg-gpio";
>>>             reg = <32>;
>>>             gpio-controller;
>>>             #gpio-cells = <2>;
>>>             #interrupt-cells = <2>;
>>>             interrupt-controller;
>>>           };
>>>         };
>>>       };
>>>
>>>  rpmsg-io-25  would match with gpio at 25
>>>  rpmsg-io-32  would match with gpio at 32
>>>
>> The problem with this approach is, we will endup creating way too many
>> RPMsg devices/channels. i.e. one channel per one GPIO. That limits how
>> many GPIOs can be handled by remote from memory perspective. At
>> somepoint we might just run-out of number ept & channels created by the
>> remote. As of now, open-amp library supports 128 epts I think.
> 
> 
> Arnaud was suggesting one channel per gpio controller,
> not per line. We will not have 128 gpio controllers....
> 
>>
>>>> Because the endpoint that is created on a namespace request is also
>>>> dynamic in nature. How will the remote know which endpoint addr
>>>> Linux allocated for a namespace that it announced?
>>>>
>>>> As an example/PoC, I created a firmware example which announces
>>>> 2 name services to Linux, one is the standard "rpmsg_chrdev" and
>>>> the other is a TI specific name service "ti.ipc4.ping-pong". You can
>>>> see it created 2 different addresses (0x400 and 0x401) for each of
>>>> the name service request from the same firmware:
>>>>
>>>> root at j784s4-evm:~# dmesg | grep virtio0 | grep -i channel
>>>> [    9.290275] virtio_rpmsg_bus virtio0: creating channel
>>>> ti.ipc4.ping-pong addr 0xd
>>>> [    9.311230] virtio_rpmsg_bus virtio0: creating channel rpmsg_chrdev
>>>> addr 0xe
>>>> [    9.496645] rpmsg_chrdev virtio0.rpmsg_chrdev.-1.14: DEBUG: Channel
>>>> formed from src = 0x400 to dst = 0xe
>>>> [    9.707255] rpmsg_client_sample virtio0.ti.ipc4.ping-pong.-1.13:
>>>> new channel: 0x401 -> 0xd!
>>>>
>>>> So in this case, rpmsg-io-1 can have different ept addr than rpmsg-io-2
>>>> Back to same problem. Simple solution is to reply to remote with the
>>>> created ept addr and the index.
>>> That why I would like to suggest to use the name service field to
>>> identify the port/controller, instead of the endpoint address.
>>>>  
>>>>> - match the RPMsg probe with the DT,
>>>>
>>>> We can probe from all controllers with a single name service
>>>> announcement too.
>>>>
>>>>> - provide a simple mapping between the port and the endpoint on both
>>>>> sides,
>>>>
>>>> We are trying to get rid of this mapping from Linux side to adapt
>>>> the gpio-virtio design.
>>>>
>>>>> - allow multiple endpoints on the remote side,
>>>>
>>>> We can support this as well with single nameservice model.
>>>> There is no limitation. Remote has to send a message with
>>>> its newly created ept that's all.
>>>>
>>>>> - provide a simple discovery mechanism for remote capabilities.
>>>>
>>>> A single announcement: "rpmsg-io" is also discovery mechanism.
>>>>
>>>> Feel free to let me know if you have concerns with any of the
>>>> suggestions!
>>> My only concern, whatever the solution, is that we find a smart
>>> solution to associate the correct endpoint with the correct GPIO
>>> port/controller defined in the DT.
>>>
>>> I may have misunderstood your solution. Could you please help me
>>> understand your proposal by explaining how you would handle three
>>> GPIO ports defined in the DT, considering that the endpoint
>>> addresses on the Linux side can be random?
>>> If I assume there is a unique endpoint on the remote side,
>>> I do not understand how you can match, on the firmware side,
>>> the Linux endpoint address to the GPIO port.
>>>
>>> Thanks and Regards,Arnaud
>>>
>>>> Thanks,
>>>> Beleswar
>>>>
>>>>> Regards,
>>>>> Arnaud
>>>>>
>>>>>>> 2. namespace/channel#2 = rpmsg-i2c
>>>>>>>       a. ept1 -> i2c at 1
>>>>>>>       b. ept2 -> i2c at 2
>>>>>>>       c. ept3 -> i2c at 3
>>>>>>>
>>>>>>> etc...
>>>>>>>
>> Just want to clear-up few terms before I jump to the solution:
>>
>> **RPMsg channel/device**:
>>   - These are devices announced by the remote processor, and created by
>> linux. They are created at: /sys/bus/rpmsg/devices
>>   - The channel format: <name>.<src ept>.<dst ept>
>>
>> **RPMsg endpoint**:
>>   - Endpoint is differnt than channel. Single channel can have multiple
>> endpoints, and represented in the linux with: /dev/rpmsg? devices.
>>
>> To create endpoint device, we have rpmsg_create_ept API, which takes
>> channel information as input, which has src-ept, dst-ept.
>>
>> Following is proposed solution:
>>
>> 1) Assign RPMsg channel/device per rpmsg-gpio controller (Not per GPIO
>> pin/port).
> 
> 
> One channel per pin was not suggested earlier...
> 
>>   - In our case that would be, single rpmsg-io node. (That makes me
>> question if bindings are correct or not).
>>
>> 2) Assign GPIO number as src ept.
>>
>> i.e. *rpmsg-io.<GPIO number>.<dst ept>*. Do not randomly assign src
>> endpoint.
>>
>> Now, RPMSG channel by spec reserves first 1024 endpoints [1], so we can
>> add 1024 offset to the GPIO number:
>>
>> so, when calling rpmsg_create_ept() API, we assing src_endpoint as:
>> (GPIO_NUMBER + RPMSG_RESERVED_ADDRESSES)
>>
>> Now on the remote side, there is single channel and only single-endpoint
>> is needed that is mapped to the rpmsg-io channel callback.
>>
>> That callback will receive all the payloads from the Linux, which will
>> have src-ept i.e. (RPMSG_RESERVED_ADDRESSES + GPIO_NUMBER).
>>
>> It can retrieve GPIO_NUMBER easily, and convert to appropriate pin based
>> on platform specific logic.
>>
>> This doesn't need PORT information at all. Also it makes sure that
>> remote is using only single-endpoint so not much memory is used.
>>
>> *Example*:
>> If only rpmsg-gpio channel is created by the remote side, than following
>> is the representation of the devices when GPIO 25, 26, 27 is assigned to
>> the rpmsg-io controller:
>>
>> Linux                                                      Remote
>>
>> rpmsg-channel: rpmsg-gpio.0x400.0x400
>>
>> /dev/rpmsg0 - GPIO25 ept (rpmsg-gpio.0x419.0x400)-|
>>                                                   |
>> /dev/rpmsg1 - GPIO26 ept (rpmsg-gpio.0x41a.0x400)-|-> rpmsg-gpio.*.0x400
>>                                                   |
>> /dev/rpmsg2 - GPIO27 ept (rpmsg-gpio.0x41b.0x400)-|  0x400 ept callback.
>>
>>
>> *On remote side*:
>>
>> ept_0x400_callback(..., int src_ept, ...,)
>> {
>> 	int gpio_num = src_ept - RPMSG_RESERVED_ADDRESSES;
>> 	// platform specific logic to convert gpio num to proper pin,
>> 	// just like you would convert gpio num to pin on a linux gpio controller.
>> }
>>
>> My question on the binding:
>>
>> Why each GPIO is represented with the separate node? I think rpmsg-gpio
>> can be represented just any other GPIO controller? Please let me know if
>> I am missing something.
> 
> 
> These are separate GPIO controllers, not separate pins within
> the same GPIO controller. Could you revisit your solution with
> this update.
> 
> Thanks for your time,
> Beleswar
> 




More information about the linux-arm-kernel mailing list