]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/regulator/of_regulator.c
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[linux.git] / drivers / regulator / of_regulator.c
index 0ead1164e4d63afb52e4e41fddea86971ffcb334..9112faa6a9a0e12830e8f931e83fcd56070e1ac5 100644 (file)
@@ -21,7 +21,8 @@ static const char *const regulator_states[PM_SUSPEND_MAX + 1] = {
        [PM_SUSPEND_MAX]        = "regulator-state-disk",
 };
 
-static void of_get_regulation_constraints(struct device_node *np,
+static int of_get_regulation_constraints(struct device *dev,
+                                       struct device_node *np,
                                        struct regulator_init_data **init_data,
                                        const struct regulator_desc *desc)
 {
@@ -30,8 +31,13 @@ static void of_get_regulation_constraints(struct device_node *np,
        struct device_node *suspend_np;
        unsigned int mode;
        int ret, i, len;
+       int n_phandles;
        u32 pval;
 
+       n_phandles = of_count_phandle_with_args(np, "regulator-coupled-with",
+                                               NULL);
+       n_phandles = max(n_phandles, 0);
+
        constraints->name = of_get_property(np, "regulator-name", NULL);
 
        if (!of_property_read_u32(np, "regulator-min-microvolt", &pval))
@@ -163,9 +169,17 @@ static void of_get_regulation_constraints(struct device_node *np,
        if (!of_property_read_u32(np, "regulator-system-load", &pval))
                constraints->system_load = pval;
 
-       if (!of_property_read_u32(np, "regulator-coupled-max-spread",
-                                 &pval))
-               constraints->max_spread = pval;
+       if (n_phandles) {
+               constraints->max_spread = devm_kzalloc(dev,
+                               sizeof(*constraints->max_spread) * n_phandles,
+                               GFP_KERNEL);
+
+               if (!constraints->max_spread)
+                       return -ENOMEM;
+
+               of_property_read_u32_array(np, "regulator-coupled-max-spread",
+                                          constraints->max_spread, n_phandles);
+       }
 
        if (!of_property_read_u32(np, "regulator-max-step-microvolt",
                                  &pval))
@@ -242,6 +256,8 @@ static void of_get_regulation_constraints(struct device_node *np,
                suspend_state = NULL;
                suspend_np = NULL;
        }
+
+       return 0;
 }
 
 /**
@@ -267,7 +283,9 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
        if (!init_data)
                return NULL; /* Out of memory? */
 
-       of_get_regulation_constraints(node, &init_data, desc);
+       if (of_get_regulation_constraints(dev, node, &init_data, desc))
+               return NULL;
+
        return init_data;
 }
 EXPORT_SYMBOL_GPL(of_get_regulator_init_data);
@@ -398,8 +416,10 @@ device_node *regulator_of_get_init_node(struct device *dev,
                if (!name)
                        name = child->name;
 
-               if (!strcmp(desc->of_match, name))
+               if (!strcmp(desc->of_match, name)) {
+                       of_node_put(search);
                        return of_node_get(child);
+               }
        }
 
        of_node_put(search);
@@ -473,7 +493,8 @@ int of_get_n_coupled(struct regulator_dev *rdev)
 
 /* Looks for "to_find" device_node in src's "regulator-coupled-with" property */
 static bool of_coupling_find_node(struct device_node *src,
-                                 struct device_node *to_find)
+                                 struct device_node *to_find,
+                                 int *index)
 {
        int n_phandles, i;
        bool found = false;
@@ -495,8 +516,10 @@ static bool of_coupling_find_node(struct device_node *src,
 
                of_node_put(tmp);
 
-               if (found)
+               if (found) {
+                       *index = i;
                        break;
+               }
        }
 
        return found;
@@ -517,22 +540,23 @@ static bool of_coupling_find_node(struct device_node *src,
  */
 bool of_check_coupling_data(struct regulator_dev *rdev)
 {
-       int max_spread = rdev->constraints->max_spread;
        struct device_node *node = rdev->dev.of_node;
        int n_phandles = of_get_n_coupled(rdev);
        struct device_node *c_node;
+       int index;
        int i;
        bool ret = true;
 
-       if (max_spread <= 0) {
-               dev_err(&rdev->dev, "max_spread value invalid\n");
-               return false;
-       }
-
        /* iterate over rdev's phandles */
        for (i = 0; i < n_phandles; i++) {
+               int max_spread = rdev->constraints->max_spread[i];
                int c_max_spread, c_n_phandles;
 
+               if (max_spread <= 0) {
+                       dev_err(&rdev->dev, "max_spread value invalid\n");
+                       return false;
+               }
+
                c_node = of_parse_phandle(node,
                                          "regulator-coupled-with", i);
 
@@ -549,22 +573,23 @@ bool of_check_coupling_data(struct regulator_dev *rdev)
                        goto clean;
                }
 
-               if (of_property_read_u32(c_node, "regulator-coupled-max-spread",
-                                        &c_max_spread)) {
+               if (!of_coupling_find_node(c_node, node, &index)) {
+                       dev_err(&rdev->dev, "missing 2-way linking for coupled regulators\n");
                        ret = false;
                        goto clean;
                }
 
-               if (c_max_spread != max_spread) {
-                       dev_err(&rdev->dev,
-                               "coupled regulators max_spread mismatch\n");
+               if (of_property_read_u32_index(c_node, "regulator-coupled-max-spread",
+                                              index, &c_max_spread)) {
                        ret = false;
                        goto clean;
                }
 
-               if (!of_coupling_find_node(c_node, node)) {
-                       dev_err(&rdev->dev, "missing 2-way linking for coupled regulators\n");
+               if (c_max_spread != max_spread) {
+                       dev_err(&rdev->dev,
+                               "coupled regulators max_spread mismatch\n");
                        ret = false;
+                       goto clean;
                }
 
 clean: