regulator: Add of_regulator_bulk_get_all
authorCorentin Labbe <clabbe@baylibre.com>
Tue, 15 Nov 2022 07:36:01 +0000 (07:36 +0000)
committerMark Brown <broonie@kernel.org>
Fri, 18 Nov 2022 15:13:34 +0000 (15:13 +0000)
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>
Link: https://lore.kernel.org/r/20221115073603.3425396-2-clabbe@baylibre.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/regulator/of_regulator.c
include/linux/regulator/consumer.h

index 0aff1c2886b5dd425e4a20299a47dc7833fb64ea..584c92f1a317c6a6c6e35c39ba3f696fe3286b3b 100644 (file)
@@ -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);
index ee3b4a0146119809e17476e7a30c62b7763125ea..276488dad61d7599ef5737aff4e468330bb63147 100644 (file)
@@ -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);
@@ -479,6 +481,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)
 {