gpio: emulate open drain & open source in dm_gpio_set_value()
authorNeil Armstrong <narmstrong@baylibre.com>
Tue, 5 May 2020 08:43:17 +0000 (10:43 +0200)
committerNeil Armstrong <narmstrong@baylibre.com>
Mon, 11 May 2020 13:12:53 +0000 (15:12 +0200)
Handle the GPIOD_OPEN_DRAIN & GPIOD_OPEN_SOURCE flags to emulate open drain
and open source by setting the GPIO line as input depending on the
requested value.

The behaviour is taken from the Linux gpiolib.

Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
drivers/gpio/gpio-uclass.c

index 757ab7106ee33d3fe03b9d3345fc4d9be8c60c52..d3cea11f76e5115513ed5661b45a578c4d2a705f 100644 (file)
@@ -526,6 +526,21 @@ int dm_gpio_set_value(const struct gpio_desc *desc, int value)
 
        if (desc->flags & GPIOD_ACTIVE_LOW)
                value = !value;
+
+       /*
+        * Emulate open drain by not actively driving the line high or
+        * Emulate open source by not actively driving the line low
+        */
+       if ((desc->flags & GPIOD_OPEN_DRAIN && value) ||
+           (desc->flags & GPIOD_OPEN_SOURCE && !value))
+               return gpio_get_ops(desc->dev)->direction_input(desc->dev,
+                                                               desc->offset);
+       else if (desc->flags & GPIOD_OPEN_DRAIN ||
+                desc->flags & GPIOD_OPEN_SOURCE)
+               return gpio_get_ops(desc->dev)->direction_output(desc->dev,
+                                                               desc->offset,
+                                                               value);
+
        gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value);
        return 0;
 }