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

From: "Shah, Tanmay" <[email-masked]>
Date: Tue, 5 May 2026 10:52:50 -0500

On 5/5/2026 4:28 AM, Arnaud POULIQUEN wrote:
> Hi Tanmay,
> 
> On 5/4/26 21:19, 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 <[email-masked]> wrote:
>>>>>>>
>>>>>>> Hi Mathieu,
>>>>>>>
>>>>>>> On 4/29/2026 11:03 PM, Mathieu Poirier wrote:
>>>>>>>> On Wed, 29 Apr 2026 at 10:53, Shenwei Wang <[email-masked]>
>>>>>>>> wrote:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>> -----Original Message-----
>>>>>>>>>> From: Mathieu Poirier <[email-masked]>
>>>>>>>>>> Sent: Wednesday, April 29, 2026 10:42 AM
>>>>>>>>>> To: Shenwei Wang <[email-masked]>
>>>>>>>>>> Cc: Andrew Lunn <[email-masked]>; Padhi, Beleswar <b-
>>>>>>>>>> [email-masked]>; Linus
>>>>>>>>>> Walleij <[email-masked]>; Bartosz Golaszewski
>>>>>>>>>> <[email-masked]>; Jonathan
>>>>>>>>>> Corbet <[email-masked]>; Rob Herring <[email-masked]>;
>>>>>>>>>> Krzysztof Kozlowski
>>>>>>>>>> <[email-masked]>; Conor Dooley <[email-masked]>; Bjorn
>>>>>>>>>> Andersson
>>>>>>>>>> <[email-masked]>; Frank Li <[email-masked]>; Sascha Hauer
>>>>>>>>>> <[email-masked]>; Shuah Khan
>>>>>>>>>> <[email-masked]>; linux-
>>>>>>>>>> [email-masked]; [email-masked]; linux-
>>>>>>>>>> [email-masked];
>>>>>>>>>> Pengutronix Kernel Team <[email-masked]>; Fabio Estevam
>>>>>>>>>> <[email-masked]>; Peng Fan <[email-masked]>;
>>>>>>>>>> [email-masked]; [email-masked];
>>>>>>>>>> [email-masked]; [email-masked]; dl-
>>>>>>>>>> linux-imx <linux-
>>>>>>>>>> [email-masked]>; Bartosz Golaszewski <[email-masked]>
>>>>>>>>>> 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 <[email-masked]>
>>>>>>>>>>>> Sent: Monday, April 27, 2026 3:49 PM
>>>>>>>>>>>> To: Shenwei Wang <[email-masked]>
>>>>>>>>>>>> Cc: Padhi, Beleswar <[email-masked]>; Linus Walleij
>>>>>>>>>>>> <[email-masked]>; Bartosz Golaszewski <[email-masked]>;
>>>>>>>>>>>> Jonathan
>>>>>>>>>>>> Corbet <[email-masked]>; Rob Herring <[email-masked]>;
>>>>>>>>>>>> Krzysztof
>>>>>>>>>>>> Kozlowski <[email-masked]>; Conor Dooley
>>>>>>>>>>>> <[email-masked]>;
>>>>>>>>>>>> Bjorn Andersson <[email-masked]>; Mathieu Poirier
>>>>>>>>>>>> <[email-masked]>; Frank Li <[email-masked]>;
>>>>>>>>>>>> Sascha
>>>>>>>>>>>> Hauer <[email-masked]>; Shuah Khan
>>>>>>>>>>>> <[email-masked]>; [email-masked]; linux-
>>>>>>>>>>>> [email-masked]; [email-masked]; Pengutronix
>>>>>>>>>>>> Kernel Team <[email-masked]>; Fabio Estevam
>>>>>>>>>>>> <[email-masked]>; Peng Fan <[email-masked]>;
>>>>>>>>>>>> [email-masked]; linux- [email-masked];
>>>>>>>>>>>> [email-masked]; linux-arm- [email-masked];
>>>>>>>>>>>> dl-linux-imx <[email-masked]>; Bartosz Golaszewski
>>>>>>>>>>>> <[email-masked]>
>>>>>>>>>>>> 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-
>>>>>>> [email-masked]/
>>>>>>>
>>>>>>
>>>>>> 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@1
>>>>>>>        b. ept2 -> gpio-controller@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. 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.
> 
> As done in ehe rpmsg_tty driver it could be instantiated several times with
> the same channel/service name. This would imply a specific rpmsg to
> retreive
> the gpio controller index from the remote side.
>>
>>>>>>
>>>>>> 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@25 {
>>>              compatible = "rpmsg-gpio";
>>>              reg = <25>;
>>>              gpio-controller;
>>>              #gpio-cells = <2>;
>>>              #interrupt-cells = <2>;
>>>              interrupt-controller;
>>>            };
>>>
>>>            gpio@32 {
>>>              compatible = "rpmsg-gpio";
>>>              reg = <32>;
>>>              gpio-controller;
>>>              #gpio-cells = <2>;
>>>              #interrupt-cells = <2>;
>>>              interrupt-controller;
>>>            };
>>>          };
>>>        };
>>>
>>>   rpmsg-io-25  would match with gpio@25
>>>   rpmsg-io-32  would match with gpio@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.
> 
> Right, I proposed a solution in my previous answer to Beleswar who has
> the same concern.
> 
>>
>>>
>>>>
>>>> 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@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@1
>>>>>>>        b. ept2 -> i2c@2
>>>>>>>        c. ept3 -> i2c@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).
>>    - 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).
> 
> 
> Interesting approach. I also tried to find a similar solution.
> 
> The question here is: how can we guarantee continuous addresses? Given
> the static and dynamic allocation of endpoint addresses that are
> implemented, my conclusion was that it is not reliable enough.
> 
> but perhaps I missed something...
> 
>>
>> 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. So rpmsg channel/rpmsg device is not created per
>> GPIO, but per controller. GPIO number multiplexing should be done with
>> rpmsg src ept, that removes the need of having each GPIO as a separate
>> node.
>>
>>
>> rpmsg_gpio: rpmsg-gpio@0 {
>>         compatible = "rpmsg-gpio";
>>         reg = <0>;
>>         gpio-controller;
>>         #gpio-cells = <2>;
>>         #interrupt-cells = <2>;
>>         interrupt-controller;
>>     };
>>
>> Then in DT, use like regular GPIO, but with the rpmsg-gpio controller:
>>
>> rpmsg-gpios = <&rpmsg_gpio (GPIO NUM) (flags)>;
>>
>> If the intent to create separate gpio nodes was only for the channel
>> creation, then it's not really needed.
>>
>> [1]
>> https://github.com/torvalds/linux/
>> blob/6d35786de28116ecf78797a62b84e6bf3c45aa5a/drivers/rpmsg/
>> virtio_rpmsg_bus.c#L136
>>
> 
> It is already the case. bindings declare GPIO controllers, not directly
> GPIOs in:
> 
> [PATCH v13 2/4] dt-bindings: remoteproc: imx_rproc: Add "rpmsg" subnode
> support
> 
> The discussion is around having an unique RPmsg endpoint for all
> GPIO controller or one RPmsg endpoint per GPIO controller.
> 

Endpoint where remote side or linux side?

If unique endpoint on remote side per gpio controller then it makes sense.

Unique endpoint on linux side doesn't make sense. Instead, unique
channel per gpio controller makes sense, and each channel will have
multiple endpoints on linux side. As I replied to Beleswar on the other
email, I will copy past my answer here too:

To be more specific:

Linux:                               remote:

ch1: rpmsg-gpio.-1.1024 ->     gpio-controller@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@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.

> Or did I misunderstand your questions?
> 
> Thanks,
> Arnaud
> 

I gave this patch more time yesterday, and I think the 'reg' property
should represent remote endpoint, instead of the gpio-controller index.

So in this approach remote implementation is expected to provide
hard-coded (static) endpoints for each gpio-controller instance, and
that same number should be represented with the 'reg' property.

On remote side:

#define RPMSG_GPIO_0_CONTROLLER_EPT (RPMSG_RESERVED_ADDRESSES + 1) // 1024

ept_1024_callback() {

	// handle appropriate gpio port ()

}

On linux side:

So new representation of controller:

 rpmsg_gpio_0:   gpio@1024 {
             compatible = "rpmsg-gpio";
             reg = <1024>;
             gpio-controller;
             #gpio-cells = <2>;
             #interrupt-cells = <2>;
             interrupt-controller;
          };

 rpmsg_gpio_1:   gpio@1025 {
             compatible = "rpmsg-gpio";
             reg = <1025>;
             gpio-controller;
             #gpio-cells = <2>;
             #interrupt-cells = <2>;
             interrupt-controller;
          };

gpios = <&rpmsg_gpio_0 (GPIO NUM or PIN) flags>,
	<&rpmsg_gpio_1 (GPIO NUM or PIN) flags>;

Now in the linux driver:

You can easily retrieve destination endpoint when we want to send the
command to the gpio controller via device's "reg" property.

This approach also provides built-in security as well. Because now
gpio-controller instance is hardcoded with the endpoint callback, it
can't be modified/addressed without changing the 'reg' property.

Just like you wouldn't change device address for the instance of the
gpio-controller right?

This approach can be easily adapted to all the other rpmsg controllers
as well.

So, dynamic endpoint allocation doesn't make sense in this case. Dynamic
endpoint allocation makes more sense for user-space apps which don't
really care about endpoints and only payloads.

But, here we are multiplexing device-addresses with endpoints, and so it
has to be fixed, and presented via 'reg' property. So, firmware can't
change device-address without Linux knowing it.

Thanks,
Tanmay

> 
>>>>>>> This way device groups are isolated with each channel/namespace, and
>>>>>>> instances within each device groups are also respected with specific
>>>>>>> endpoints.
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Beleswar
>>>>>>>
>>>>>>
>>>>>
>>>
>>>
>>
>