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

Shenwei Wang shenwei.wang at nxp.com
Tue May 5 07:41:49 PDT 2026



> -----Original Message-----
> From: Beleswar Prasad Padhi <b-padhi at ti.com>
> Sent: Monday, May 4, 2026 3:17 AM
> To: Arnaud POULIQUEN <arnaud.pouliquen at foss.st.com>; Mathieu Poirier
> <mathieu.poirier at linaro.org>
> Cc: Shenwei Wang <shenwei.wang at nxp.com>; Andrew Lunn
> <andrew at lunn.ch>; 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
> 
> Caution: This is an external email. Please take care when clicking links or opening
> attachments. When in doubt, report the message using the 'Report this email'
> button
> 
> 
> Hi Arnaud,
> 
> On 30/04/26 22:10, 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:
> >>>>
> 
> [...]
> 
> >>>>> 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
> >>>>>
> >>>>
> >>>> 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
> >
> >
> >>
> >> 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.
> 
> 
> In my solution, there is no need to have this map of endpoint to GPIO port at
> Linux side. This aligns more with virtio-gpio design as well.
> 
> >
> > 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.
> 
> 
> Sure, let me take an example:
> Assumptions: 3 GPIO ports in DT, 3 endpoints in Linux (one per port),
> 1 endpoint in remote (0xd) and 1 rpmsg channel (rpmsg-io)
> 
>        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;
>            };
> 
>            gpio at 35 {
>              compatible = "rpmsg-gpio";
>              reg = <35>;
>              gpio-controller;
>              #gpio-cells = <2>;
>              #interrupt-cells = <2>;
>              interrupt-controller;
>            };
>          };
>        };
> 
> Code Flow:
> 1. "rpmsg-io" channel is announced from remote firmware with unique dst
>     ept = 0xd.
> 
> 2. rpmsg_core.c creates the default dynamic local ept for the channel
>     ept = 0x405.
> 
> 3. rpmsg_core.c assigns the allocated addr to rpdev device:
>     rpdev->src = 0x405 and rpdev->dst = 0xd.
> 
> 4. rpmsg_gpio_channel_probe() is triggered. For *each* of the GPIO ports
>     in DT, it will trigger rpmsg_gpiochip_register() which will now:
>        a. Call port->ept = rpmsg_create_ept(rpdev,
>                                                                    rpmsg_gpio_channel_callback,
>                                                                    port,
>                                                                   {rpdev.id.name,
>                                                                    RPMSG_ADDR_ANY,
>                                                                    RPMSG_ADDR_ANY});
>            Ex- port->ept->addr = 0x408
> 
>        b. Prepare a 8-byte message having 2 fields:
>            port->ept->addr (0x408) and port->idx (25)
> 
>        c. Send this message to remote firmware on default channel ept
>            (0x405 -> 0xd) by:
>            rpmsg_send(rpdev->ept, &message, sizeof(message));
> 
>        d. Remote side receives this message and creates a map of the
>            linux_ept_addr to gpio_port. (0x408 <-> 25)
> 
> 5. After this point, any gpio messages sent from Linux from gpio port
>     endpoints (Ex- 0x408) can be decoded at remote side by looking up
>     its map (Ex- map[0x408] = 25).
> 
> 6. Any messages sent from remote to Linux for a particular gpio port can
>     also be decoded at Linux by simply fetching the priv pointer to get
>     the per-port device:
>     struct rpmsg_gpio_port *port = priv;
> 
> So Linux does not need to send the port idx everytime while sending a gpio
> message anymore.
> 

I support the idea of encoding the port index directly into ept->addr.
To keep the design simple, we can rely on a predefined rule to derive ept->src, rather than 
exchanging additional configuration. One approach is to use the default channel address as 
the base address and encode the port index into the lower bits. For example:

    ept->src = (baseaddr << 8) | port_index;

With this scheme, the endpoint-to-port mapping can be encoded implicitly, eliminating the need 
for an extra message to exchange EPT and port mapping information.

Thanks,
Shenwei

> Thanks,
> Beleswar
> 
> [...]



More information about the linux-arm-kernel mailing list