]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/regulator/of_regulator.c
Merge tag 'spi-v3.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
[karo-tx-linux.git] / drivers / regulator / of_regulator.c
index ea4f36f2cbe2f1e5432e594711fdb5d4c2c677c6..ee5e67bc8d5bed53b6c1577bd20071f46542da2f 100644 (file)
@@ -19,9 +19,7 @@
 static void of_get_regulation_constraints(struct device_node *np,
                                        struct regulator_init_data **init_data)
 {
-       const __be32 *min_uV, *max_uV, *uV_offset;
-       const __be32 *min_uA, *max_uA, *ramp_delay;
-       struct property *prop;
+       const __be32 *min_uV, *max_uV;
        struct regulation_constraints *constraints = &(*init_data)->constraints;
        int ret;
        u32 pval;
@@ -42,36 +40,29 @@ static void of_get_regulation_constraints(struct device_node *np,
        if (min_uV && max_uV && constraints->min_uV == constraints->max_uV)
                constraints->apply_uV = true;
 
-       uV_offset = of_get_property(np, "regulator-microvolt-offset", NULL);
-       if (uV_offset)
-               constraints->uV_offset = be32_to_cpu(*uV_offset);
-       min_uA = of_get_property(np, "regulator-min-microamp", NULL);
-       if (min_uA)
-               constraints->min_uA = be32_to_cpu(*min_uA);
-       max_uA = of_get_property(np, "regulator-max-microamp", NULL);
-       if (max_uA)
-               constraints->max_uA = be32_to_cpu(*max_uA);
+       if (!of_property_read_u32(np, "regulator-microvolt-offset", &pval))
+               constraints->uV_offset = pval;
+       if (!of_property_read_u32(np, "regulator-min-microamp", &pval))
+               constraints->min_uA = pval;
+       if (!of_property_read_u32(np, "regulator-max-microamp", &pval))
+               constraints->max_uA = pval;
 
        /* Current change possible? */
        if (constraints->min_uA != constraints->max_uA)
                constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT;
 
-       if (of_find_property(np, "regulator-boot-on", NULL))
-               constraints->boot_on = true;
-
-       if (of_find_property(np, "regulator-always-on", NULL))
-               constraints->always_on = true;
-       else /* status change should be possible if not always on. */
+       constraints->boot_on = of_property_read_bool(np, "regulator-boot-on");
+       constraints->always_on = of_property_read_bool(np, "regulator-always-on");
+       if (!constraints->always_on) /* status change should be possible. */
                constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS;
 
        if (of_property_read_bool(np, "regulator-allow-bypass"))
                constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS;
 
-       prop = of_find_property(np, "regulator-ramp-delay", NULL);
-       if (prop && prop->value) {
-               ramp_delay = prop->value;
-               if (*ramp_delay)
-                       constraints->ramp_delay = be32_to_cpu(*ramp_delay);
+       ret = of_property_read_u32(np, "regulator-ramp-delay", &pval);
+       if (!ret) {
+               if (pval)
+                       constraints->ramp_delay = pval;
                else
                        constraints->ramp_disable = true;
        }
@@ -106,6 +97,20 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(of_get_regulator_init_data);
 
+struct devm_of_regulator_matches {
+       struct of_regulator_match *matches;
+       unsigned int num_matches;
+};
+
+static void devm_of_regulator_put_matches(struct device *dev, void *res)
+{
+       struct devm_of_regulator_matches *devm_matches = res;
+       int i;
+
+       for (i = 0; i < devm_matches->num_matches; i++)
+               of_node_put(devm_matches->matches[i].of_node);
+}
+
 /**
  * of_regulator_match - extract multiple regulator init data from device tree.
  * @dev: device requesting the data
@@ -119,7 +124,8 @@ EXPORT_SYMBOL_GPL(of_get_regulator_init_data);
  * regulator. The data parsed from a child node will be matched to a regulator
  * based on either the deprecated property regulator-compatible if present,
  * or otherwise the child node's name. Note that the match table is modified
- * in place.
+ * in place and an additional of_node reference is taken for each matched
+ * regulator.
  *
  * Returns the number of matches found or a negative error code on failure.
  */
@@ -131,10 +137,22 @@ int of_regulator_match(struct device *dev, struct device_node *node,
        unsigned int i;
        const char *name;
        struct device_node *child;
+       struct devm_of_regulator_matches *devm_matches;
 
        if (!dev || !node)
                return -EINVAL;
 
+       devm_matches = devres_alloc(devm_of_regulator_put_matches,
+                                   sizeof(struct devm_of_regulator_matches),
+                                   GFP_KERNEL);
+       if (!devm_matches)
+               return -ENOMEM;
+
+       devm_matches->matches = matches;
+       devm_matches->num_matches = num_matches;
+
+       devres_add(dev, devm_matches);
+
        for (i = 0; i < num_matches; i++) {
                struct of_regulator_match *match = &matches[i];
                match->init_data = NULL;
@@ -162,7 +180,7 @@ int of_regulator_match(struct device *dev, struct device_node *node,
                                        child->name);
                                return -EINVAL;
                        }
-                       match->of_node = child;
+                       match->of_node = of_node_get(child);
                        count++;
                        break;
                }