Author: avg
Date: Fri Oct 25 09:37:54 2019
New Revision: 354065
URL: https://svnweb.freebsd.org/changeset/base/354065

Log:
  gpioiic: set output after switching to output mode if presetting it failed
  
  Some controllers cannot preset future output value while the pin is in
  input mode.  This adds a fallback for those controllers.  The new code
  assumes that a controller reports an error in that case.
  
  For example, all hardware supported by nctgpio behaves in that way.
  
  This is a temporary measure.  In the future we will use
  GPIO_PIN_PRESET_LOW / GPIO_PIN_PRESET_HIGH to preset the output either
  in hardware, if supported, or in software (e.g., in
  gpiobus_pin_setflags).
  
  While here, I extracted common functionality of gpioiic_set{sda,scl} and
  gpioiic_get{sda,scl} to gpioiic_setpin and gpioiic_getpin respectively.
  
  MFC after:    2 weeks

Modified:
  head/sys/dev/gpio/gpioiic.c

Modified: head/sys/dev/gpio/gpioiic.c
==============================================================================
--- head/sys/dev/gpio/gpioiic.c Fri Oct 25 09:24:41 2019        (r354064)
+++ head/sys/dev/gpio/gpioiic.c Fri Oct 25 09:37:54 2019        (r354065)
@@ -168,59 +168,67 @@ gpioiic_reset_bus(device_t dev)
 }
 
 static void
-gpioiic_setsda(device_t dev, int val)
+gpioiic_setpin(struct gpioiic_softc *sc, int pin, int val)
 {
-       struct gpioiic_softc            *sc = device_get_softc(dev);
+       int                             err;
 
        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,
+               err = GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev, pin, 0);
+               GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, pin,
                    GPIO_PIN_OUTPUT);
+
+               /*
+                * Some controllers cannot set output value while a pin is in
+                * input mode.
+                */
+               if (err != 0)
+                       GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev, pin, 0);
        } else {
-               GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->sda_pin,
+               GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, pin,
                    GPIO_PIN_INPUT);
        }
 }
 
 static void
+gpioiic_setsda(device_t dev, int val)
+{
+       struct gpioiic_softc            *sc = device_get_softc(dev);
+
+       gpioiic_setpin(sc, sc->sda_pin, val);
+}
+
+static void
 gpioiic_setscl(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->scl_pin, 0);
-               GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->scl_pin,
-                   GPIO_PIN_OUTPUT);
-       } else {
-               GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->scl_pin,
-                   GPIO_PIN_INPUT);
-       }
+       gpioiic_setpin(sc, sc->scl_pin, val);
 }
 
 static int
-gpioiic_getscl(device_t dev)
+gpioiic_getpin(struct gpioiic_softc *sc, int pin)
 {
-       struct gpioiic_softc            *sc = device_get_softc(dev);
        unsigned int                    val;
 
-       GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->scl_pin,
-           GPIO_PIN_INPUT);
-       GPIOBUS_PIN_GET(sc->sc_busdev, sc->sc_dev, sc->scl_pin, &val);
-
+       GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, pin, GPIO_PIN_INPUT);
+       GPIOBUS_PIN_GET(sc->sc_busdev, sc->sc_dev, pin, &val);
        return ((int)val);
 }
 
 static int
-gpioiic_getsda(device_t dev)
+gpioiic_getscl(device_t dev)
 {
        struct gpioiic_softc            *sc = device_get_softc(dev);
-       unsigned int                    val;
 
-       GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->sda_pin,
-           GPIO_PIN_INPUT);
-       GPIOBUS_PIN_GET(sc->sc_busdev, sc->sc_dev, sc->sda_pin, &val);
+       return (gpioiic_getpin(sc, sc->scl_pin));
+}
 
-       return ((int)val);
+static int
+gpioiic_getsda(device_t dev)
+{
+       struct gpioiic_softc            *sc = device_get_softc(dev);
+
+       return (gpioiic_getpin(sc, sc->sda_pin));
 }
 
 static int
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to