From: Mehmet Fide <[email protected]>

regulator_common_of_to_plat() requests the enable GPIO, which probes
the GPIO controller and claims the pin while the consumer's platform
data is still being read. of_to_plat() must not do either: it runs
before the device's pinctrl state is applied, so on SoCs where the
direction lives in the pad register - the output enable on Vybrid is
one - the pinctrl undoes the direction the early claim just set, and a
fixed regulator configured as always-on powers nothing.

Parse the GPIO into the platform data in of_to_plat() and request it in
the new regulator_common_probe(), called from the fixed and fixed-clock
regulator probe methods. The gpio regulator's voltage-control GPIO has
the same problem and moves the same way.

Signed-off-by: Mehmet Fide <[email protected]>
---
 drivers/power/regulator/fixed.c            | 11 ++++++++++
 drivers/power/regulator/gpio-regulator.c   | 21 +++++++++++++++---
 drivers/power/regulator/regulator_common.c | 25 ++++++++++++++++++----
 drivers/power/regulator/regulator_common.h |  3 +++
 4 files changed, 53 insertions(+), 7 deletions(-)

diff --git a/drivers/power/regulator/fixed.c b/drivers/power/regulator/fixed.c
index 1dd137f493e..b8e3af0f0ca 100644
--- a/drivers/power/regulator/fixed.c
+++ b/drivers/power/regulator/fixed.c
@@ -38,6 +38,11 @@ static int fixed_regulator_of_to_plat(struct udevice *dev)
        return regulator_common_of_to_plat(dev, plat, gpios ? "gpios" : "gpio");
 }
 
+static int fixed_regulator_probe(struct udevice *dev)
+{
+       return regulator_common_probe(dev, dev_get_plat(dev));
+}
+
 static int fixed_regulator_get_value(struct udevice *dev)
 {
        struct dm_regulator_uclass_plat *uc_pdata;
@@ -115,6 +120,11 @@ static int fixed_clock_regulator_set_enable(struct udevice 
*dev, bool enable)
 static int fixed_clock_regulator_probe(struct udevice *dev)
 {
        struct fixed_clock_regulator_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       ret = regulator_common_probe(dev, dev_get_plat(dev));
+       if (ret)
+               return ret;
 
        priv->enable_clock = devm_clk_get(dev, NULL);
        if (IS_ERR(priv->enable_clock))
@@ -150,6 +160,7 @@ U_BOOT_DRIVER(regulator_fixed) = {
        .id = UCLASS_REGULATOR,
        .ops = &fixed_regulator_ops,
        .of_match = fixed_regulator_ids,
+       .probe = fixed_regulator_probe,
        .of_to_plat = fixed_regulator_of_to_plat,
        .plat_auto = sizeof(struct regulator_common_plat),
 };
diff --git a/drivers/power/regulator/gpio-regulator.c 
b/drivers/power/regulator/gpio-regulator.c
index 787f8170234..703a96ff095 100644
--- a/drivers/power/regulator/gpio-regulator.c
+++ b/drivers/power/regulator/gpio-regulator.c
@@ -19,6 +19,7 @@
 
 struct gpio_regulator_plat {
        struct regulator_common_plat common;
+       struct gpio_dt_desc gpio_dt; /* parsed voltage GPIO, requested in probe 
*/
        struct gpio_desc gpio; /* GPIO for regulator voltage control */
        int states[GPIO_REGULATOR_MAX_STATES];
        int voltages[GPIO_REGULATOR_MAX_STATES];
@@ -28,7 +29,6 @@ static int gpio_regulator_of_to_plat(struct udevice *dev)
 {
        struct dm_regulator_uclass_plat *uc_pdata;
        struct gpio_regulator_plat *plat;
-       struct gpio_desc *gpio;
        int ret, count, i, j;
        u32 states_array[GPIO_REGULATOR_MAX_STATES * 2];
 
@@ -47,8 +47,8 @@ static int gpio_regulator_of_to_plat(struct udevice *dev)
         * per gpio-regulator. As of now no instance with multiple
         * gpios is presnt
         */
-       gpio = &plat->gpio;
-       ret = gpio_request_by_name(dev, "gpios", 0, gpio, GPIOD_IS_OUT);
+       ret = gpio_parse_by_name(dev, "gpios", 0, GPIOD_IS_OUT,
+                                &plat->gpio_dt);
        if (ret)
                debug("regulator gpio - not found! Error: %d", ret);
 
@@ -76,6 +76,20 @@ static int gpio_regulator_of_to_plat(struct udevice *dev)
        return regulator_common_of_to_plat(dev, &plat->common, "enable-gpios");
 }
 
+static int gpio_regulator_probe(struct udevice *dev)
+{
+       struct gpio_regulator_plat *plat = dev_get_plat(dev);
+       int ret;
+
+       if (plat->gpio_dt.present) {
+               ret = gpio_request_parsed(dev, &plat->gpio_dt, &plat->gpio);
+               if (ret)
+                       return ret;
+       }
+
+       return regulator_common_probe(dev, &plat->common);
+}
+
 static int gpio_regulator_get_value(struct udevice *dev)
 {
        struct dm_regulator_uclass_plat *uc_pdata;
@@ -153,6 +167,7 @@ U_BOOT_DRIVER(gpio_regulator) = {
        .id = UCLASS_REGULATOR,
        .ops = &gpio_regulator_ops,
        .of_match = gpio_regulator_ids,
+       .probe = gpio_regulator_probe,
        .of_to_plat = gpio_regulator_of_to_plat,
        .plat_auto      = sizeof(struct gpio_regulator_plat),
 };
diff --git a/drivers/power/regulator/regulator_common.c 
b/drivers/power/regulator/regulator_common.c
index c0387eff4fc..99a3cde436e 100644
--- a/drivers/power/regulator/regulator_common.c
+++ b/drivers/power/regulator/regulator_common.c
@@ -16,7 +16,6 @@ int regulator_common_of_to_plat(struct udevice *dev,
                                struct regulator_common_plat *plat,
                                const char *enable_gpio_name)
 {
-       struct gpio_desc *gpio;
        int flags = GPIOD_IS_OUT;
        int ret;
 
@@ -25,10 +24,10 @@ int regulator_common_of_to_plat(struct udevice *dev,
        if (dev_read_bool(dev, "regulator-boot-on"))
                flags |= GPIOD_IS_OUT_ACTIVE;
 
-       /* Get optional enable GPIO desc */
-       gpio = &plat->gpio;
+       /* Read the optional enable GPIO; it is requested in probe() */
        if (CONFIG_IS_ENABLED(DM_GPIO)) {
-               ret = gpio_request_by_name(dev, enable_gpio_name, 0, gpio, 
flags);
+               ret = gpio_parse_by_name(dev, enable_gpio_name, 0, flags,
+                                        &plat->gpio_dt);
                if (ret) {
                        debug("Regulator '%s' optional enable GPIO - not found! 
Error: %d\n",
                              dev->name, ret);
@@ -49,6 +48,24 @@ int regulator_common_of_to_plat(struct udevice *dev,
        return 0;
 }
 
+int regulator_common_probe(struct udevice *dev,
+                          struct regulator_common_plat *plat)
+{
+       int ret;
+
+       if (!CONFIG_IS_ENABLED(DM_GPIO) || !plat->gpio_dt.present)
+               return 0;
+
+       ret = gpio_request_parsed(dev, &plat->gpio_dt, &plat->gpio);
+       if (ret) {
+               debug("Regulator '%s' enable GPIO request failed: %d\n",
+                     dev->name, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
 int regulator_common_get_enable(const struct udevice *dev,
        struct regulator_common_plat *plat)
 {
diff --git a/drivers/power/regulator/regulator_common.h 
b/drivers/power/regulator/regulator_common.h
index d4962899d83..43e32ac48f6 100644
--- a/drivers/power/regulator/regulator_common.h
+++ b/drivers/power/regulator/regulator_common.h
@@ -10,6 +10,7 @@
 #include <asm/gpio.h>
 
 struct regulator_common_plat {
+       struct gpio_dt_desc gpio_dt; /* parsed enable GPIO, requested in probe 
*/
        struct gpio_desc gpio; /* GPIO for regulator enable control */
        unsigned int startup_delay_us;
        unsigned int off_on_delay_us;
@@ -19,6 +20,8 @@ struct regulator_common_plat {
 int regulator_common_of_to_plat(struct udevice *dev,
                                struct regulator_common_plat *plat, const
                                char *enable_gpio_name);
+int regulator_common_probe(struct udevice *dev,
+                          struct regulator_common_plat *plat);
 int regulator_common_get_enable(const struct udevice *dev,
        struct regulator_common_plat *plat);
 /*
-- 
2.54.0

Reply via email to