Unverified Commit 27b9ecc7 authored by Corentin Labbe's avatar Corentin Labbe Committed by Mark Brown
Browse files

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: default avatarCorentin Labbe <clabbe@baylibre.com>
Link: https://lore.kernel.org/r/20221115073603.3425396-2-clabbe@baylibre.com


Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 9abf2313
Loading
Loading
Loading
Loading
+92 −0
Original line number Diff line number Diff line
@@ -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);
+8 −0
Original line number Diff line number Diff line
@@ -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)
{