There are GPIO controllers which only supports static pinctrl
configurations to enable pull-up or pull-downs. E.g. that is common on
the k3 SoCs.

To switch between pull-up and pull-down, the device tree has to provide
a pinctrl configuration for both. These are then applied at once.

Signed-off-by: Michael Walle <[email protected]>
---
 drivers/gpio/gpio-uclass.c | 31 ++++++++++++++++++++++++-------
 include/asm-generic/gpio.h |  4 ++++
 2 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c
index 38151ef1bee..ab29a38d24b 100644
--- a/drivers/gpio/gpio-uclass.c
+++ b/drivers/gpio/gpio-uclass.c
@@ -12,6 +12,7 @@
 #include <dm/device_compat.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
+#include <dm/pinctrl.h>
 #include <dm/uclass-internal.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <errno.h>
@@ -1043,8 +1044,9 @@ int dm_gpio_get_values_as_int(const struct gpio_desc 
*desc_list, int count)
        return vector;
 }
 
-int dm_gpio_get_values_as_int_base3(struct gpio_desc *desc_list,
-                                   int count)
+int dm_gpio_get_values_as_int_base3_pctrl(struct udevice *pinctrl,
+                                         struct gpio_desc *desc_list,
+                                         int count)
 {
        static const char tristate[] = "01z";
        enum {
@@ -1065,11 +1067,20 @@ int dm_gpio_get_values_as_int_base3(struct gpio_desc 
*desc_list,
        assert(count < 20);
 
        for (i = 0; i < NUM_OPTIONS; i++) {
-               uint flags = GPIOD_IS_IN;
-
-               flags |= (i == PULLDOWN) ? GPIOD_PULL_DOWN : GPIOD_PULL_UP;
-               ret = dm_gpios_clrset_flags(desc_list, count, GPIOD_MASK_PULL,
-                                           flags);
+               if (CONFIG_IS_ENABLED(PINCTRL) && pinctrl) {
+                       const char *state = (i == PULLDOWN) ? "pull-down" :
+                                                             "pull-up";
+                       ret = pinctrl_select_state(pinctrl, state);
+               } else if (pinctrl) {
+                       return log_msg_ret("no pinctrl", -EINVAL);
+               } else {
+                       uint flags = GPIOD_IS_IN;
+
+                       flags |= (i == PULLDOWN) ? GPIOD_PULL_DOWN :
+                                                  GPIOD_PULL_UP;
+                       ret = dm_gpios_clrset_flags(desc_list, count,
+                                                   GPIOD_MASK_PULL, flags);
+               }
                if (ret)
                        return log_msg_ret("pu", ret);
 
@@ -1108,6 +1119,12 @@ int dm_gpio_get_values_as_int_base3(struct gpio_desc 
*desc_list,
        return vector;
 }
 
+int dm_gpio_get_values_as_int_base3(struct gpio_desc *desc_list,
+                                   int count)
+{
+       return dm_gpio_get_values_as_int_base3_pctrl(NULL, desc_list, count);
+}
+
 /**
  * gpio_request_tail: common work for requesting a gpio.
  *
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index a21c606f2b8..a69b8144973 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -525,6 +525,10 @@ int dm_gpio_get_values_as_int(const struct gpio_desc 
*desc_list, int count);
 int dm_gpio_get_values_as_int_base3(struct gpio_desc *desc_list,
                                    int count);
 
+int dm_gpio_get_values_as_int_base3_pctrl(struct udevice *pinctrl,
+                                         struct gpio_desc *desc_list,
+                                         int count);
+
 /**
  * gpio_claim_vector() - claim a number of GPIOs for input
  *
-- 
2.47.3

Reply via email to