All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mehmet Fide <mehmet.fide@gmail.com>
To: Simon Glass <sjg@chromium.org>
Cc: Tom Rini <trini@konsulko.com>,
	Jaehoon Chung <jh80.chung@samsung.com>,
	Peng Fan <peng.fan@nxp.com>, Vincent Jardin <vjardin@free.fr>,
	Ye Li <ye.li@nxp.com>, Michal Simek <michal.simek@amd.com>,
	Aristo Chen <aristo.chen@canonical.com>,
	u-boot@lists.u-boot-project.org,
	Mehmet Fide <mehmet.fide@screeningeagle.com>
Subject: [PATCH v2 2/4] regulator: claim the enable GPIO at probe time, not in of_to_plat()
Date: Fri, 11 Sep 2026 00:08:16 +0200	[thread overview]
Message-ID: <20260910220818.3093364-3-mehmet.fide@gmail.com> (raw)
In-Reply-To: <20260910220818.3093364-1-mehmet.fide@gmail.com>

From: Mehmet Fide <mehmet.fide@screeningeagle.com>

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 regulator's
probe method. The gpio regulator's voltage-control GPIO has the same
problem and moves the same way.

Two things change on the way. The gpio regulator used to log and carry
on when its voltage GPIO could not be claimed; it now fails to probe for
anything but a missing property, since it cannot switch anything
without that pin. The fixed regulator already returned such errors from
of_to_plat(), so nothing changes there. And the parsed specification
stays in the platform data after probe: priv is not allocated when
of_to_plat() runs, so plat is the only place it can live, a few dozen
bytes per regulator traded for keeping the two phases simple.

The fixed-clock regulator shares the of_to_plat() and used to claim the
GPIO too, although its set_enable() only drives the clock; no
devicetree in the tree gives it one, so it no longer requests it.

Signed-off-by: Mehmet Fide <mehmet.fide@screeningeagle.com>
---

Notes:
    Changes in v2:
    - rely on the -ENOENT contract instead of checking the present flag in
      both probe methods (Simon Glass)
    - drop the request from the fixed-clock regulator, no devicetree uses
      it (Simon Glass)
    - reword the stale debug message in gpio-regulator (Simon Glass)
    - commit message: spell out the gpio-regulator behaviour change and the
      plat footprint (Simon Glass)

 drivers/power/regulator/fixed.c            |  6 +++++
 drivers/power/regulator/gpio-regulator.c   | 21 +++++++++++++----
 drivers/power/regulator/regulator_common.c | 26 ++++++++++++++++++----
 drivers/power/regulator/regulator_common.h |  3 +++
 4 files changed, 48 insertions(+), 8 deletions(-)

diff --git a/drivers/power/regulator/fixed.c b/drivers/power/regulator/fixed.c
index 1dd137f493e..ff01812e8d0 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;
@@ -150,6 +155,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..84a61f1a92c 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_spec 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,10 +47,10 @@ 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);
+		debug("gpio-regulator: cannot parse the voltage GPIO: %d\n", ret);
 
 	ret = dev_read_size(dev, "states");
 	if (ret < 0)
@@ -76,6 +76,18 @@ 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;
+
+	ret = gpio_request_parsed(dev, &plat->gpio_dt, &plat->gpio);
+	if (ret && ret != -ENOENT)
+		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 +165,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..dfc58cd60bf 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,25 @@ 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))
+		return 0;
+
+	/* the enable GPIO is optional: -ENOENT means there is none */
+	ret = gpio_request_parsed(dev, &plat->gpio_dt, &plat->gpio);
+	if (ret == -ENOENT)
+		return 0;
+	if (ret)
+		debug("Regulator '%s' enable GPIO request failed: %d\n",
+		      dev->name, ret);
+
+	return ret;
+}
+
 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..951a02b5416 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_spec 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.55.0


  parent reply	other threads:[~2026-09-10 22:08 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-10 22:08 [PATCH v2 0/4] dm: gpio: read GPIOs in of_to_plat(), request them in probe() Mehmet Fide
2026-09-10 22:08 ` [PATCH v2 1/4] gpio: add a way to parse a GPIO now and request it later Mehmet Fide
2026-09-10 22:08 ` Mehmet Fide [this message]
2026-09-10 22:08 ` [PATCH v2 3/4] doc: driver-model: state that of_to_plat() must not probe or claim Mehmet Fide
2026-09-10 22:08 ` [PATCH v2 4/4] test: dm: check the regulators claim their GPIOs at probe time Mehmet Fide

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260910220818.3093364-3-mehmet.fide@gmail.com \
    --to=mehmet.fide@gmail.com \
    --cc=aristo.chen@canonical.com \
    --cc=jh80.chung@samsung.com \
    --cc=mehmet.fide@screeningeagle.com \
    --cc=michal.simek@amd.com \
    --cc=peng.fan@nxp.com \
    --cc=sjg@chromium.org \
    --cc=trini@konsulko.com \
    --cc=u-boot@lists.u-boot-project.org \
    --cc=vjardin@free.fr \
    --cc=ye.li@nxp.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.