regulator: Add of_regulator_bulk_get_all

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>
This commit is contained in:
Corentin Labbe 2022-11-15 07:36:01 +00:00 committed by Mark Brown
parent 9abf2313ad
commit 27b9ecc7a9
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
2 changed files with 100 additions and 0 deletions

View 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);

View 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)
{