Merge remote-tracking branch 'regulator/topic/gpio' into v3.9-rc8
[sfrench/cifs-2.6.git] / drivers / regulator / core.c
index 6c8c82406cd9b5e3a8a77e90168953c6e64d7080..6e501784158266d990fc6cad8fb6e0ee7733d923 100644 (file)
@@ -130,7 +130,7 @@ static const char *rdev_get_name(struct regulator_dev *rdev)
  * @supply: regulator supply name
  *
  * Extract the regulator device node corresponding to the supply name.
- * retruns the device node corresponding to the regulator if found, else
+ * returns the device node corresponding to the regulator if found, else
  * returns NULL.
  */
 static struct device_node *of_get_regulator(struct device *dev, const char *supply)
@@ -1243,7 +1243,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
        struct regulator_dev *rdev;
        struct regulator *regulator = ERR_PTR(-EPROBE_DEFER);
        const char *devname = NULL;
-       int ret;
+       int ret = 0;
 
        if (id == NULL) {
                pr_err("get() with no identifier\n");
@@ -1259,6 +1259,15 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
        if (rdev)
                goto found;
 
+       /*
+        * If we have return value from dev_lookup fail, we do not expect to
+        * succeed, so, quit with appropriate error value
+        */
+       if (ret) {
+               regulator = ERR_PTR(ret);
+               goto out;
+       }
+
        if (board_wants_dummy_regulator) {
                rdev = dummy_regulator_rdev;
                goto found;
@@ -1905,7 +1914,10 @@ int regulator_is_enabled_regmap(struct regulator_dev *rdev)
        if (ret != 0)
                return ret;
 
-       return (val & rdev->desc->enable_mask) != 0;
+       if (rdev->desc->enable_is_inverted)
+               return (val & rdev->desc->enable_mask) == 0;
+       else
+               return (val & rdev->desc->enable_mask) != 0;
 }
 EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap);
 
@@ -1920,9 +1932,15 @@ EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap);
  */
 int regulator_enable_regmap(struct regulator_dev *rdev)
 {
+       unsigned int val;
+
+       if (rdev->desc->enable_is_inverted)
+               val = 0;
+       else
+               val = rdev->desc->enable_mask;
+
        return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-                                 rdev->desc->enable_mask,
-                                 rdev->desc->enable_mask);
+                                 rdev->desc->enable_mask, val);
 }
 EXPORT_SYMBOL_GPL(regulator_enable_regmap);
 
@@ -1937,8 +1955,15 @@ EXPORT_SYMBOL_GPL(regulator_enable_regmap);
  */
 int regulator_disable_regmap(struct regulator_dev *rdev)
 {
+       unsigned int val;
+
+       if (rdev->desc->enable_is_inverted)
+               val = rdev->desc->enable_mask;
+       else
+               val = 0;
+
        return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
-                                 rdev->desc->enable_mask, 0);
+                                 rdev->desc->enable_mask, val);
 }
 EXPORT_SYMBOL_GPL(regulator_disable_regmap);
 
@@ -2248,6 +2273,37 @@ int regulator_map_voltage_iterate(struct regulator_dev *rdev,
 }
 EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate);
 
+/**
+ * regulator_map_voltage_ascend - map_voltage() for ascendant voltage list
+ *
+ * @rdev: Regulator to operate on
+ * @min_uV: Lower bound for voltage
+ * @max_uV: Upper bound for voltage
+ *
+ * Drivers that have ascendant voltage list can use this as their
+ * map_voltage() operation.
+ */
+int regulator_map_voltage_ascend(struct regulator_dev *rdev,
+                                int min_uV, int max_uV)
+{
+       int i, ret;
+
+       for (i = 0; i < rdev->desc->n_voltages; i++) {
+               ret = rdev->desc->ops->list_voltage(rdev, i);
+               if (ret < 0)
+                       continue;
+
+               if (ret > max_uV)
+                       break;
+
+               if (ret >= min_uV && ret <= max_uV)
+                       return i;
+       }
+
+       return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(regulator_map_voltage_ascend);
+
 /**
  * regulator_map_voltage_linear - map_voltage() for simple linear mappings
  *
@@ -2941,7 +2997,7 @@ EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap);
  * regulator_allow_bypass - allow the regulator to go into bypass mode
  *
  * @regulator: Regulator to configure
- * @allow: enable or disable bypass mode
+ * @enable: enable or disable bypass mode
  *
  * Allow the regulator to go into bypass mode if all other consumers
  * for the regulator also enable bypass mode and the machine
@@ -3168,9 +3224,13 @@ int regulator_bulk_enable(int num_consumers,
        return 0;
 
 err:
-       pr_err("Failed to enable %s: %d\n", consumers[i].supply, ret);
-       while (--i >= 0)
-               regulator_disable(consumers[i].consumer);
+       for (i = 0; i < num_consumers; i++) {
+               if (consumers[i].ret < 0)
+                       pr_err("Failed to enable %s: %d\n", consumers[i].supply,
+                              consumers[i].ret);
+               else
+                       regulator_disable(consumers[i].consumer);
+       }
 
        return ret;
 }
@@ -3583,7 +3643,14 @@ regulator_register(const struct regulator_desc *regulator_desc,
 
                r = regulator_dev_lookup(dev, supply, &ret);
 
-               if (!r) {
+               if (ret == -ENODEV) {
+                       /*
+                        * No supply was specified for this regulator and
+                        * there will never be one.
+                        */
+                       ret = 0;
+                       goto add_dev;
+               } else if (!r) {
                        dev_err(dev, "Failed to find supply %s\n", supply);
                        ret = -EPROBE_DEFER;
                        goto scrub;
@@ -3601,6 +3668,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
                }
        }
 
+add_dev:
        /* add consumers devices */
        if (init_data) {
                for (i = 0; i < init_data->num_consumer_supplies; i++) {