linux-gpio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Gilles BULOZ <gilles.buloz@kontron.com>
To: Kent Gibson <warthog618@gmail.com>
Cc: Bartosz Golaszewski <brgl@bgdev.pl>, linux-gpio@vger.kernel.org
Subject: Re: [questions] : gpiolib and gpioset behaviour
Date: Fri, 26 Apr 2024 15:08:33 +0200	[thread overview]
Message-ID: <76794fbe-db97-a00b-c16c-b3e4296c3b9d@kontron.com> (raw)
In-Reply-To: <20240426020720.GA9777@rigel>

On Fri, Apr 26, 2024 at 04:07 AM, Kent Gibson wrote :
> On Mon, Apr 22, 2024 at 06:49:05PM +0200, Gilles BULOZ wrote:
>> On Mon, Apr 22, 2024 at 3:55 PM Bartosz Golaszewski wrote :
>>> On Mon, Apr 22, 2024 at 2:44 PM Gilles BULOZ <gilles.buloz@kontron.com> wrote:
>>>>
>>>> Hi Bartosz,
>>>>
>>>> Several years after our discussions about GPIOs, some things are still unclear
>>>> to me.
>>>>
>>>> 1 - The gpioset command has this in its help : "Note: the state of a GPIO line
>>>> controlled over the character device reverts to default when the last process
>>>> referencing the file descriptor representing the device file exits. This means
>>>> that it's wrong to run gpioset, have it exit and expect the line to continue
>>>> being driven high or low. It may happen if given pin is floating but it must
>>>> be interpreted as undefined behavior." But up to now I've never seen such
>>>> behaviour and I'm glad to have the GPIO set by gpioset keep their state once
>>>> the command exits. Is reverting to default an optional behaviour in the GPIO
>>>> chip driver, or in the gpiolib stack ?
>>>>
>>>
>>> This behavior is driver-specific. Meaning: you're in-kernel GPIO
>>> driver may actually retain the state.
>>>
>>
>> Which method should the driver implement to restore the state on GPIO when the
>> last process referencing the character device exits ?
>>
>>>> 2 - I've recently wrote a GPIO driver for an I2C FPGA design having ~112 GPIOs
>>>> and wanted to use get_multiple() and set_multiple to have more efficent
>>>> accesses, but realized that the line number was limited to 63 because of the
>>>> unsigned long mask/bits. But I've noticed that working on a line number >= 64
>>>> was unexpectedly calling these methods with a mask at 0 instead of calling
>>>> get/set methods, and that the only way to have things working was to not
>>>> define get_multiple/set_multiple but only get/set. Is it the expected
>>>> behaviour ?
>>>> At the end I've split the GPIOs into two banks (first with 64 and second with
>>>> 48 GPIOs) to be able to use get_multiple/set_multiple.
>>>>
>>>
>>> Please use libgpiod v2. That won't help you with the max requested
>>> line limit but at least it's more modern API and actively developed.
>>>
>>
>
> I suspect you are referring to gpiolib here - the mask in gc->get_multiple()
> being unsigned long*.
>
> The uAPI that libgpiod uses is limited to 64 lines per request, but that is
> only relevant if you want to request more than 64 lines at once from userspace
> (you would have to break that into two requests to access all 112 lines).
>
> Note that the mask in gc->get_multiple() is unsigned long*, so it is a
> pointer to an array of unsigned long.  Its width is not limited by
> unsigned long, but by the bits parameter.  In your case the mask you pass
> should contain multiple unsigned longs to achieve 112 bits.
> Refer to gpiod_get_array_value_complex() for an example of building bitmap
> masks to pass to gc->get_multiple(), in that case via
> gpio_chip_get_multiple().
>

I was refering the get_multiple/set_multiple callbacks in struct gpio_chip
that are defined like this :
 int (*get_multiple)(struct gpio_chip *gc, unsigned long *mask, unsigned long *bits);
 void (*set_multiple)(struct gpio_chip *gc, unsigned long *mask, unsigned long *bits);
With some debug in my GPIO chip driver implementing these functions, I saw that
the bits set in "mask" and the ones used in "bits" are the ones whose bit
numbers are directly matching the GPIO offset/line numbers of the chip. But I
only used unsigned long, not arrays, so I thought I was limited to offset/line
31 on 32bit arch, and 63 on 64bit arch.
As you suggested, I'm currently having a look to gpiod_get_array_value_complex()
but I must admit I'm currently a little bit lost. I've never thought GPIO
implementation could become so complex for my brain :-)

>> OK
>>
>>>> 3 - Is there some way to request a GPIO already owned by another process as
>>>> input or output, just to get the current level on the input or the level
>>>> driven on output ? This would be much more efficient for real-time
>>>> applications than asking the owner such information.
>>>>
>>>
>>> Ha! Please help me help you. Take a look at the DBus daemon I recently
>>> posted[1]. With the daemon running, the behavior will be exactly what
>>> you expect. You'll be able to get/set values and have the command-line
>>> tool exit while the daemon retains the state.
>>>
>>
>> I was thinking about some specific "watcher" ioctl to do so, not a DBus
>> daemon because this is not welcome in the real-time and embedded world.
>> The only workaround I've found is to directly read the GPIO chip registers
>> but this is bad to do so.
>>
>
> No there isn't, and I can't say I'm a fan of using GPIOs as shared memory,
> though it does seems to be a common use case for those accustomed to accessing
> hardware registers directly.
>

As a workaround, using debugfs in the driver to report the current state of
GPIOs to all processes requiring them is probably cleaner that doing a direct
access to the register. But this is not as clean as a specific "watcher"
ioctl could be.

> I would question whether "much more efficient" is true, as going through all
> the gpiolib machinery, including the device driver, to perform the get could
> even turn out to be slower than some IPC options - such as actual shared
> memory.
>

Yes, you're probably right. "more efficient" was refering to the less you have
layers the more is is supposed to be fast, but there's still some machinery
to go through.

> Cheers,
> Kent.
> .

Thanks a lot,
Gilles
.


  reply	other threads:[~2024-04-26 13:08 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-22 12:44 [questions] : gpiolib and gpioset behaviour Gilles BULOZ
2024-04-22 15:55 ` Bartosz Golaszewski
2024-04-22 16:49   ` Gilles BULOZ
2024-04-22 18:04     ` Bartosz Golaszewski
2024-04-26  2:07     ` Kent Gibson
2024-04-26 13:08       ` Gilles BULOZ [this message]
2024-04-26 13:37         ` Kent Gibson
2024-04-26 16:16           ` Gilles BULOZ
2024-04-27  0:23             ` Kent Gibson
2024-04-27 12:09       ` Kent Gibson
2024-04-29  8:50         ` Gilles BULOZ

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=76794fbe-db97-a00b-c16c-b3e4296c3b9d@kontron.com \
    --to=gilles.buloz@kontron.com \
    --cc=brgl@bgdev.pl \
    --cc=linux-gpio@vger.kernel.org \
    --cc=warthog618@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).