gpio: add support of new GPIO direction flag
authorPatrick Delaunay <patrick.delaunay@st.com>
Mon, 13 Jan 2020 10:35:07 +0000 (11:35 +0100)
committerTom Rini <trini@konsulko.com>
Fri, 17 Apr 2020 03:06:54 +0000 (23:06 -0400)
This commit manages the new dir flags that can be used in gpio
specifiers to indicate the pull-up or pull-down resistor
configuration for output gpio (GPIO_PULL_UP, GPIO_PULL_DOWN)
or the Open Drain/Open Source configuration for input gpio
(GPIO_OPEN_DRAIN, GPIO_OPEN_SOURCE).

These flags are already supported in Linux kernel in gpio lib.

This patch only parse and save the direction flags in GPIO
descriptor (desc->flags), it prepares the introduction of new ops
to manage them.
The GPIO uclass supports new GPIO flags from device-tree
(GPIO_XXX define in include/dt-bindings/gpio/gpio.h)
and translate them in the dir flags (GPIOD_XXX):
- GPIO_PULL_UP     => GPIOD_PULL_UP
- GPIO_PULL_DOWN   => GPIOD_PULL_DOWN
- GPIO_OPEN_DRAIN  => GPIOD_OPEN_DRAIN
- GPIO_OPEN_SOURCE => GPIOD_OPEN_SOURCE

This patch also adds protection in the check_dir_flags function for
new invalid configuration of the dir flags.

Signed-off-by: Patrick Delaunay <patrick.delaunay@st.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
drivers/gpio/gpio-uclass.c
include/asm-generic/gpio.h

index 9550e45..2526399 100644 (file)
@@ -145,6 +145,24 @@ int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc,
        if (args->args[1] & GPIO_ACTIVE_LOW)
                desc->flags |= GPIOD_ACTIVE_LOW;
 
+       /*
+        * need to test 2 bits for gpio output binding:
+        * OPEN_DRAIN (0x6) = SINGLE_ENDED (0x2) | LINE_OPEN_DRAIN (0x4)
+        * OPEN_SOURCE (0x2) = SINGLE_ENDED (0x2) | LINE_OPEN_SOURCE (0x0)
+        */
+       if (args->args[1] & GPIO_SINGLE_ENDED) {
+               if (args->args[1] & GPIO_LINE_OPEN_DRAIN)
+                       desc->flags |= GPIOD_OPEN_DRAIN;
+               else
+                       desc->flags |= GPIOD_OPEN_SOURCE;
+       }
+
+       if (args->args[1] & GPIO_PULL_UP)
+               desc->flags |= GPIOD_PULL_UP;
+
+       if (args->args[1] & GPIO_PULL_DOWN)
+               desc->flags |= GPIOD_PULL_DOWN;
+
        return 0;
 }
 
@@ -521,6 +539,18 @@ static int check_dir_flags(ulong flags)
                return -EINVAL;
        }
 
+       if ((flags & GPIOD_PULL_UP) && (flags & GPIOD_PULL_DOWN)) {
+               log_debug("%s: flags 0x%lx has GPIOD_PULL_UP and GPIOD_PULL_DOWN\n",
+                         __func__, flags);
+               return -EINVAL;
+       }
+
+       if ((flags & GPIOD_OPEN_DRAIN) && (flags & GPIOD_OPEN_SOURCE)) {
+               log_debug("%s: flags 0x%lx has GPIOD_OPEN_DRAIN and GPIOD_OPEN_SOURCE\n",
+                         __func__, flags);
+               return -EINVAL;
+       }
+
        return 0;
 }
 
index 1329d02..42c9ab2 100644 (file)
@@ -119,8 +119,12 @@ struct gpio_desc {
        unsigned long flags;
 #define GPIOD_IS_OUT           BIT(1)  /* GPIO is an output */
 #define GPIOD_IS_IN            BIT(2)  /* GPIO is an input */
-#define GPIOD_ACTIVE_LOW       BIT(3)  /* value has active low */
+#define GPIOD_ACTIVE_LOW       BIT(3)  /* GPIO is active when value is low */
 #define GPIOD_IS_OUT_ACTIVE    BIT(4)  /* set output active */
+#define GPIOD_OPEN_DRAIN       BIT(5)  /* GPIO is open drain type */
+#define GPIOD_OPEN_SOURCE      BIT(6)  /* GPIO is open source type */
+#define GPIOD_PULL_UP          BIT(7)  /* GPIO has pull-up enabled */
+#define GPIOD_PULL_DOWN                BIT(8)  /* GPIO has pull-down enabled */
 
        uint offset;            /* GPIO offset within the device */
        /*