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@xxxxxxxxxxx> 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 .