Few drivers have a need of getting regulator supplies without knowing their names: 1. The Simple Framebuffer driver works on setup provided by bootloader (outside of scope of kernel); 2. Generic power sequence driver may be attached to any device node. Add a Device Tree helper for parsing "-supply" properties and returning allocated bulk regulator consumers. Signed-off-by: Krzysztof Kozlowski <k.kozlowski@xxxxxxxxxxx> --- drivers/regulator/of_regulator.c | 86 ++++++++++++++++++++++++++++++++++ include/linux/regulator/of_regulator.h | 13 +++++ 2 files changed, 99 insertions(+) diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index cd828dbf9d52..0d2c8dd0ebc0 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -350,3 +350,89 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev, return init_data; } + +/** + * devm_of_regulator_all_get - get all regulator consumers + * + * @dev: Device to supply + * @num_consumers Number of consumers registered (only on success) + * @consumers: Configuration of consumers; names of supplies and clients + * are stored here; allocated only on success (NULL otherwise); + * + * @return 0 on success, an errno on failure. + * + * This helper function allows drivers to get all regulator consumers + * for given device in one operation. The names of regulator supplies + * do not have to be provided. If any of the regulators cannot be + * acquired then any regulators that were allocated will be freed + * before returning to the caller. + */ +int devm_of_regulator_all_get(struct device *dev, unsigned int *num_consumers, + struct regulator_bulk_data **consumers) +{ + struct device_node *np = dev->of_node; + struct regulator_bulk_data *bulk; + unsigned int count = 0, i = 0; + struct property *prop; + const char *p; + int ret; + + if (!np) { + ret = 0; + goto err; /* Not really an error */ + } + + /* Count the number of regulator supplies */ + for_each_property_of_node(np, prop) { + p = strstr(prop->name, "-supply"); + if (p && p != prop->name) + count++; + } + + if (!count) { + ret = 0; + goto err; /* Not really an error */ + } + + bulk = devm_kcalloc(dev, count, sizeof(**consumers), GFP_KERNEL); + if (!bulk) { + ret = -ENOMEM; + goto err; + } + + /* Get all the names for supplies */ + for_each_property_of_node(np, prop) { + char *name; + int len; + + p = strstr(prop->name, "-supply"); + if (!p || p == prop->name) + continue; + + len = strlen(prop->name) - strlen("-supply") + 1; + name = devm_kzalloc(dev, len, GFP_KERNEL); + if (!name) { + ret = -ENOMEM; + goto err; + } + + strlcpy(name, prop->name, len); + bulk[i++].supply = name; + } + + ret = devm_regulator_bulk_get(dev, i, bulk); + if (ret) + goto err; + + *consumers = bulk; + *num_consumers = i; + + return 0; + +err: + *num_consumers = 0; + *consumers = NULL; + + return ret; +} +EXPORT_SYMBOL_GPL(devm_of_regulator_all_get); diff --git a/include/linux/regulator/of_regulator.h b/include/linux/regulator/of_regulator.h index 763953f7e3b8..93a3b7fe92e8 100644 --- a/include/linux/regulator/of_regulator.h +++ b/include/linux/regulator/of_regulator.h @@ -7,6 +7,7 @@ #define __LINUX_OF_REG_H struct regulator_desc; +struct regulator_bulk_data; struct of_regulator_match { const char *name; @@ -24,6 +25,9 @@ extern struct regulator_init_data extern int of_regulator_match(struct device *dev, struct device_node *node, struct of_regulator_match *matches, unsigned int num_matches); +extern int devm_of_regulator_all_get(struct device *dev, + unsigned int *num_consumers, + struct regulator_bulk_data **consumers); #else static inline struct regulator_init_data *of_get_regulator_init_data(struct device *dev, @@ -40,6 +44,15 @@ static inline int of_regulator_match(struct device *dev, { return 0; } +static inline int devm_of_regulator_all_get(struct device *dev, + unsigned int *num_consumers, + struct regulator_bulk_data **consumers) +{ + *num_consumers = 0; + *consumers = NULL; + + return 0; +} #endif /* CONFIG_OF */ #endif /* __LINUX_OF_REG_H */ -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html