diff mbox series

[v4,1/3] regulator: Add of_regulator_bulk_get_all

Message ID 20221115073603.3425396-2-clabbe@baylibre.com (mailing list archive)
State New, archived
Headers show
Series arm64: add ethernet to orange pi 3 | expand

Commit Message

Corentin LABBE Nov. 15, 2022, 7:36 a.m. UTC
It work exactly like regulator_bulk_get() but instead of working on a
provided list of names, it seek all consumers properties matching
xxx-supply.

Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
---
 drivers/regulator/of_regulator.c   | 92 ++++++++++++++++++++++++++++++
 include/linux/regulator/consumer.h |  8 +++
 2 files changed, 100 insertions(+)

Comments

Mark Brown Nov. 15, 2022, 10:03 a.m. UTC | #1
On Tue, Nov 15, 2022 at 07:36:01AM +0000, Corentin Labbe wrote:

> It work exactly like regulator_bulk_get() but instead of working on a
> provided list of names, it seek all consumers properties matching
> xxx-supply.

What's the use case - why would a device not know which supplies
it requires?  This just looks like an invitation to badly written
consumers TBH.
Corentin LABBE Nov. 15, 2022, 10:18 a.m. UTC | #2
Le Tue, Nov 15, 2022 at 10:03:14AM +0000, Mark Brown a écrit :
> On Tue, Nov 15, 2022 at 07:36:01AM +0000, Corentin Labbe wrote:
> 
> > It work exactly like regulator_bulk_get() but instead of working on a
> > provided list of names, it seek all consumers properties matching
> > xxx-supply.
> 
> What's the use case - why would a device not know which supplies
> it requires?  This just looks like an invitation to badly written
> consumers TBH.

Hello

The device know which supply it have, but I found only this way to made all maintainers happy.
See https://lore.kernel.org/netdev/0518eef1-75a6-fbfe-96d8-bb1fc4e5178a@linaro.org/t/#m7a2e012f4c7c7058478811929774ab2af9bfcbf6

Regards
Mark Brown Nov. 15, 2022, 10:34 a.m. UTC | #3
On Tue, Nov 15, 2022 at 11:18:50AM +0100, Corentin LABBE wrote:
> Le Tue, Nov 15, 2022 at 10:03:14AM +0000, Mark Brown a écrit :

> > What's the use case - why would a device not know which supplies
> > it requires?  This just looks like an invitation to badly written
> > consumers TBH.

> The device know which supply it have, but I found only this way to made all maintainers happy.
> See https://lore.kernel.org/netdev/0518eef1-75a6-fbfe-96d8-bb1fc4e5178a@linaro.org/t/#m7a2e012f4c7c7058478811929774ab2af9bfcbf6

Well, it's not making this maintainer happy :/  If we know what
PHY is there why not just look up the set of supplies based on
the compatible of the PHY?
Russell King (Oracle) Nov. 15, 2022, 10:42 a.m. UTC | #4
On Tue, Nov 15, 2022 at 10:34:41AM +0000, Mark Brown wrote:
> On Tue, Nov 15, 2022 at 11:18:50AM +0100, Corentin LABBE wrote:
> > Le Tue, Nov 15, 2022 at 10:03:14AM +0000, Mark Brown a écrit :
> 
> > > What's the use case - why would a device not know which supplies
> > > it requires?  This just looks like an invitation to badly written
> > > consumers TBH.
> 
> > The device know which supply it have, but I found only this way to made all maintainers happy.
> > See https://lore.kernel.org/netdev/0518eef1-75a6-fbfe-96d8-bb1fc4e5178a@linaro.org/t/#m7a2e012f4c7c7058478811929774ab2af9bfcbf6
> 
> Well, it's not making this maintainer happy :/  If we know what
> PHY is there why not just look up the set of supplies based on
> the compatible of the PHY?

It looks to me like this series fetches the regulators before the PHY
is bound to the driver, so what you're proposing would mean that the
core PHY code would need a table of all compatibles (which is pretty
hard to do, they encode the vendor/device ID, not some descriptive
name) and then a list of the regulator names. IMHO that doesn't scale.
Mark Brown Nov. 15, 2022, 11:16 a.m. UTC | #5
On Tue, Nov 15, 2022 at 10:42:50AM +0000, Russell King (Oracle) wrote:
> On Tue, Nov 15, 2022 at 10:34:41AM +0000, Mark Brown wrote:

> > Well, it's not making this maintainer happy :/  If we know what
> > PHY is there why not just look up the set of supplies based on
> > the compatible of the PHY?

> It looks to me like this series fetches the regulators before the PHY
> is bound to the driver, so what you're proposing would mean that the
> core PHY code would need a table of all compatibles (which is pretty
> hard to do, they encode the vendor/device ID, not some descriptive
> name) and then a list of the regulator names. IMHO that doesn't scale.

Oh, PHYs have interesting enough drivers to dynamically load
here? The last time I was looking at MDIO stuff it was all
running from generic class devices but that was quite a while
ago.
Russell King (Oracle) Nov. 15, 2022, 11:38 a.m. UTC | #6
On Tue, Nov 15, 2022 at 11:16:53AM +0000, Mark Brown wrote:
> On Tue, Nov 15, 2022 at 10:42:50AM +0000, Russell King (Oracle) wrote:
> > On Tue, Nov 15, 2022 at 10:34:41AM +0000, Mark Brown wrote:
> 
> > > Well, it's not making this maintainer happy :/  If we know what
> > > PHY is there why not just look up the set of supplies based on
> > > the compatible of the PHY?
> 
> > It looks to me like this series fetches the regulators before the PHY
> > is bound to the driver, so what you're proposing would mean that the
> > core PHY code would need a table of all compatibles (which is pretty
> > hard to do, they encode the vendor/device ID, not some descriptive
> > name) and then a list of the regulator names. IMHO that doesn't scale.
> 
> Oh, PHYs have interesting enough drivers to dynamically load
> here? The last time I was looking at MDIO stuff it was all
> running from generic class devices but that was quite a while
> ago.

There's a couple of generic drivers which are used if there isn't a
specific driver available for the vendor/device ID that has either
been probed from the hardware, or discovered encoded in the firmware's
compatible property.
Andrew Lunn Nov. 15, 2022, 1:48 p.m. UTC | #7
On Tue, Nov 15, 2022 at 11:16:53AM +0000, Mark Brown wrote:
> On Tue, Nov 15, 2022 at 10:42:50AM +0000, Russell King (Oracle) wrote:
> > On Tue, Nov 15, 2022 at 10:34:41AM +0000, Mark Brown wrote:
> 
> > > Well, it's not making this maintainer happy :/  If we know what
> > > PHY is there why not just look up the set of supplies based on
> > > the compatible of the PHY?
> 
> > It looks to me like this series fetches the regulators before the PHY
> > is bound to the driver, so what you're proposing would mean that the
> > core PHY code would need a table of all compatibles (which is pretty
> > hard to do, they encode the vendor/device ID, not some descriptive
> > name) and then a list of the regulator names. IMHO that doesn't scale.
> 
> Oh, PHYs have interesting enough drivers to dynamically load
> here?

Yes. And you sometimes have the chicken/egg problem that you don't
know what PHY it is until you have turned its regulators on and you
can talk to it. So the PHY code will poke around in the DT
description, and turn on the regulator before enumerating the bus.

	Andrew
Mark Brown Nov. 18, 2022, 4:14 p.m. UTC | #8
On Tue, Nov 15, 2022 at 07:36:01AM +0000, Corentin Labbe wrote:
> It work exactly like regulator_bulk_get() but instead of working on a
> provided list of names, it seek all consumers properties matching
> xxx-supply.

The following changes since commit 9abf2313adc1ca1b6180c508c25f22f9395cc780:

  Linux 6.1-rc1 (2022-10-16 15:36:24 -0700)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git tags/of_regulator_bulk_get_all

for you to fetch changes up to 27b9ecc7a9ba1d0014779bfe5a6dbf630899c6e7:

  regulator: Add of_regulator_bulk_get_all (2022-11-18 15:13:34 +0000)

----------------------------------------------------------------
regulator: Add of_regulator_bulk_get_all()

This adds a new of_regulator_bulk_get_all() which grab all supplies
properties in a DT node, for use in implementing generic handling
for things like MDIO PHYs where the physical standardisation of
the bus does not extend to power supplies.

----------------------------------------------------------------
Corentin Labbe (1):
      regulator: Add of_regulator_bulk_get_all

 drivers/regulator/of_regulator.c   | 92 ++++++++++++++++++++++++++++++++++++++
 include/linux/regulator/consumer.h |  8 ++++
 2 files changed, 100 insertions(+)
diff mbox series

Patch

diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 0aff1c2886b5..584c92f1a317 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -701,3 +701,95 @@  struct regulator_dev *of_parse_coupled_regulator(struct regulator_dev *rdev,
 
 	return c_rdev;
 }
+
+/*
+ * Check if name is a supply name according to the '*-supply' pattern
+ * return 0 if false
+ * return length of supply name without the -supply
+ */
+static int is_supply_name(const char *name)
+{
+	int strs, i;
+
+	strs = strlen(name);
+	/* string need to be at minimum len(x-supply) */
+	if (strs < 8)
+		return 0;
+	for (i = strs - 6; i > 0; i--) {
+		/* find first '-' and check if right part is supply */
+		if (name[i] != '-')
+			continue;
+		if (strcmp(name + i + 1, "supply") != 0)
+			return 0;
+		return i;
+	}
+	return 0;
+}
+
+/*
+ * of_regulator_bulk_get_all - get multiple regulator consumers
+ *
+ * @dev:	Device to supply
+ * @np:		device node to search for consumers
+ * @consumers:  Configuration of consumers; clients are stored here.
+ *
+ * @return number of regulators on success, an errno on failure.
+ *
+ * This helper function allows drivers to get several regulator
+ * consumers in one operation.  If any of the regulators cannot be
+ * acquired then any regulators that were allocated will be freed
+ * before returning to the caller.
+ */
+int of_regulator_bulk_get_all(struct device *dev, struct device_node *np,
+			      struct regulator_bulk_data **consumers)
+{
+	int num_consumers = 0;
+	struct regulator *tmp;
+	struct property *prop;
+	int i, n = 0, ret;
+	char name[64];
+
+	*consumers = NULL;
+
+	/*
+	 * first pass: get numbers of xxx-supply
+	 * second pass: fill consumers
+	 */
+restart:
+	for_each_property_of_node(np, prop) {
+		i = is_supply_name(prop->name);
+		if (i == 0)
+			continue;
+		if (!*consumers) {
+			num_consumers++;
+			continue;
+		} else {
+			memcpy(name, prop->name, i);
+			name[i] = '\0';
+			tmp = regulator_get(dev, name);
+			if (!tmp) {
+				ret = -EINVAL;
+				goto error;
+			}
+			(*consumers)[n].consumer = tmp;
+			n++;
+			continue;
+		}
+	}
+	if (*consumers)
+		return num_consumers;
+	if (num_consumers == 0)
+		return 0;
+	*consumers = kmalloc_array(num_consumers,
+				   sizeof(struct regulator_bulk_data),
+				   GFP_KERNEL);
+	if (!*consumers)
+		return -ENOMEM;
+	goto restart;
+
+error:
+	while (--n >= 0)
+		regulator_put(consumers[n]->consumer);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(of_regulator_bulk_get_all);
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index 628a52b8e63f..39b666b40ea6 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -244,6 +244,8 @@  int regulator_disable_deferred(struct regulator *regulator, int ms);
 
 int __must_check regulator_bulk_get(struct device *dev, int num_consumers,
 				    struct regulator_bulk_data *consumers);
+int __must_check of_regulator_bulk_get_all(struct device *dev, struct device_node *np,
+					   struct regulator_bulk_data **consumers);
 int __must_check devm_regulator_bulk_get(struct device *dev, int num_consumers,
 					 struct regulator_bulk_data *consumers);
 void devm_regulator_bulk_put(struct regulator_bulk_data *consumers);
@@ -481,6 +483,12 @@  static inline int devm_regulator_bulk_get(struct device *dev, int num_consumers,
 	return 0;
 }
 
+static inline int of_regulator_bulk_get_all(struct device *dev, struct device_node *np,
+					    struct regulator_bulk_data **consumers)
+{
+	return 0;
+}
+
 static inline int regulator_bulk_enable(int num_consumers,
 					struct regulator_bulk_data *consumers)
 {