summaryrefslogtreecommitdiffstats
path: root/drivers/regulator
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/core.c10
-rw-r--r--drivers/regulator/internal.h4
-rw-r--r--drivers/regulator/of_regulator.c51
3 files changed, 62 insertions, 3 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index a3c3785901f5..496002efd961 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -3516,12 +3516,17 @@ regulator_register(const struct regulator_desc *regulator_desc,
return ERR_PTR(-EINVAL);
}
- init_data = config->init_data;
-
rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL);
if (rdev == NULL)
return ERR_PTR(-ENOMEM);
+ init_data = regulator_of_get_init_data(dev, regulator_desc,
+ &rdev->dev.of_node);
+ if (!init_data) {
+ init_data = config->init_data;
+ rdev->dev.of_node = of_node_get(config->of_node);
+ }
+
mutex_lock(&regulator_list_mutex);
mutex_init(&rdev->mutex);
@@ -3548,7 +3553,6 @@ regulator_register(const struct regulator_desc *regulator_desc,
/* register with sysfs */
rdev->dev.class = &regulator_class;
- rdev->dev.of_node = of_node_get(config->of_node);
rdev->dev.parent = dev;
dev_set_name(&rdev->dev, "regulator.%d",
atomic_inc_return(&regulator_no) - 1);
diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h
index 84bbda10c396..a6043ad32ead 100644
--- a/drivers/regulator/internal.h
+++ b/drivers/regulator/internal.h
@@ -35,4 +35,8 @@ struct regulator {
struct dentry *debugfs;
};
+struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
+ const struct regulator_desc *desc,
+ struct device_node **node);
+
#endif
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index ee5e67bc8d5b..7a51814abdc5 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -14,8 +14,11 @@
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/regulator/machine.h>
+#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
+#include "internal.h"
+
static void of_get_regulation_constraints(struct device_node *np,
struct regulator_init_data **init_data)
{
@@ -189,3 +192,51 @@ int of_regulator_match(struct device *dev, struct device_node *node,
return count;
}
EXPORT_SYMBOL_GPL(of_regulator_match);
+
+struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
+ const struct regulator_desc *desc,
+ struct device_node **node)
+{
+ struct device_node *search, *child;
+ struct regulator_init_data *init_data = NULL;
+ const char *name;
+
+ if (!dev->of_node || !desc->of_match)
+ return NULL;
+
+ if (desc->regulators_node)
+ search = of_get_child_by_name(dev->of_node,
+ desc->regulators_node);
+ else
+ search = dev->of_node;
+
+ if (!search) {
+ dev_err(dev, "Failed to find regulator container node\n");
+ return NULL;
+ }
+
+ for_each_child_of_node(search, child) {
+ name = of_get_property(child, "regulator-compatible", NULL);
+ if (!name)
+ name = child->name;
+
+ if (strcmp(desc->of_match, name))
+ continue;
+
+ init_data = of_get_regulator_init_data(dev, child);
+ if (!init_data) {
+ dev_err(dev,
+ "failed to parse DT for regulator %s\n",
+ child->name);
+ break;
+ }
+
+ of_node_get(child);
+ *node = child;
+ break;
+ }
+
+ of_node_put(search);
+
+ return init_data;
+}