Unverified Commit db6f6ba7 authored by Mark Brown's avatar Mark Brown
Browse files

regulator: Add of_regulator_bulk_get_all()

Merge series from Corentin Labbe <clabbe@baylibre.com>:

This adds a new 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.
parents bc64f30e 27b9ecc7
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);
@@ -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)
{