Re: gpiobus: setting output value while in input mode

From: Ian Lepore <ian_at_freebsd.org>
Date: Thu, 24 Oct 2019 09:38:34 -0600
On Thu, 2019-10-24 at 17:04 +0300, Andriy Gapon wrote:
> For a lack of a more specific mailing list (or my not being aware of it), asking
> here.
> 
> gpioiic, a very simple driver, has this code:
> ===========================================================================
> static void
> gpioiic_setsda(device_t dev, int val)
> {
>         struct gpioiic_softc            *sc = device_get_softc(dev);
> 
>         if (val == 0) {
>                 GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev, sc->sda_pin, 0);
>                 GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->sda_pin,
>                     GPIO_PIN_OUTPUT);
>         } else {
>                 GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->sda_pin,
>                     GPIO_PIN_INPUT);
>         }
> }
> ===========================================================================
> 
> The interesting case is val == 0.
> 
> I know that there are GPIO controllers where input and output values are
> represented by different bits, so it is possible to set a future output value
> while the pin is in input mode.
> At the same time, there are controllers where there is a single bit per pin and
> while the pin is input mode the bit is read-only.  So, it is impossible to
> preset the pin.
> 
> How should controllers of the second type handle GPIOBUS_PIN_SET when the pin is
> in input mode?
> I see three options:
> 1) just silently ignore GPIOBUS_PIN_SET or do it in a more glorious way: go all
> the way to the hardware without caring if that does anything;
> 2) return an error that would hint that the operation is not possible at this time;
> 3) try to emulate the first class of controllers; that is, stash the value to
> apply it when the pin is switched to output mode.
> 
> I personally prefer 2, it's not hard to do (unlike 3) and there would be at
> least some visibility into the problem.
> 

A couple years ago I added new flags GPIO_PIN_PRESET_{LOW,HIGH}.  Maybe
we should document (where?) that the proper way to achieve the effect
the code wants in the val==0 case is to use the preset flag along with
the OUTPUT flag.  The driver will preset the pin before changing it to
output if it is able to do so, otherwise it will do the best it can,
which is to set the pin to output, then set its value, perhaps
generating a brief bogus state followed by a transition to the right
state.  Then of course we'd have to fix all existing drivers to behave
that way, but I don't think that will be hard.

My problem with #2 is that whenever you push the problem out to the
child drivers, one of two things happens:  drivers ignore the error, or
all drivers have to have essentially identical code to handle the
error.  In this case, what could a child driver do except react to the
error by doing the operations in the reverse order?

The current gpio(4) documentation really only covers gpiobus(4) and a
mentions a few of its older children and how to configure them via
hints.  We need manpages for some of the newer drivers, and we
especially need a manpage that documents sys/gpio.h (which is used both
from userland and internally with gpio_if.m).  I can probably find some
manpage-writing time over the new few weeks.

-- Ian
Received on Thu Oct 24 2019 - 13:38:38 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:41:22 UTC