]> Pileus Git - ~andy/linux/blobdiff - drivers/regulator/core.c
Merge branch 'for-linus' of git://git.kernel.dk/linux-block
[~andy/linux] / drivers / regulator / core.c
index 046fb1bd86199c46561774a8a2bbd2a6118a52fc..09a737c868b573227d22226926a081f35a29e6b2 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/suspend.h>
 #include <linux/delay.h>
 #include <linux/of.h>
+#include <linux/regmap.h>
 #include <linux/regulator/of_regulator.h>
 #include <linux/regulator/consumer.h>
 #include <linux/regulator/driver.h>
@@ -74,6 +75,7 @@ struct regulator_map {
 struct regulator {
        struct device *dev;
        struct list_head list;
+       unsigned int always_on:1;
        int uA_load;
        int min_uV;
        int max_uV;
@@ -155,6 +157,17 @@ static struct device_node *of_get_regulator(struct device *dev, const char *supp
        return regnode;
 }
 
+static int _regulator_can_change_status(struct regulator_dev *rdev)
+{
+       if (!rdev->constraints)
+               return 0;
+
+       if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS)
+               return 1;
+       else
+               return 0;
+}
+
 /* Platform voltage constraint check */
 static int regulator_check_voltage(struct regulator_dev *rdev,
                                   int *min_uV, int *max_uV)
@@ -649,7 +662,7 @@ static void drms_uA_update(struct regulator_dev *rdev)
        /* get input voltage */
        input_uV = 0;
        if (rdev->supply)
-               input_uV = _regulator_get_voltage(rdev);
+               input_uV = regulator_get_voltage(rdev->supply);
        if (input_uV <= 0)
                input_uV = rdev->constraints->input_uV;
        if (input_uV <= 0)
@@ -673,17 +686,14 @@ static int suspend_set_state(struct regulator_dev *rdev,
        struct regulator_state *rstate)
 {
        int ret = 0;
-       bool can_set_state;
-
-       can_set_state = rdev->desc->ops->set_suspend_enable &&
-               rdev->desc->ops->set_suspend_disable;
 
        /* If we have no suspend mode configration don't set anything;
-        * only warn if the driver actually makes the suspend mode
-        * configurable.
+        * only warn if the driver implements set_suspend_voltage or
+        * set_suspend_mode callback.
         */
        if (!rstate->enabled && !rstate->disabled) {
-               if (can_set_state)
+               if (rdev->desc->ops->set_suspend_voltage ||
+                   rdev->desc->ops->set_suspend_mode)
                        rdev_warn(rdev, "No configuration\n");
                return 0;
        }
@@ -693,15 +703,13 @@ static int suspend_set_state(struct regulator_dev *rdev,
                return -EINVAL;
        }
 
-       if (!can_set_state) {
-               rdev_err(rdev, "no way to set suspend state\n");
-               return -EINVAL;
-       }
-
-       if (rstate->enabled)
+       if (rstate->enabled && rdev->desc->ops->set_suspend_enable)
                ret = rdev->desc->ops->set_suspend_enable(rdev);
-       else
+       else if (rstate->disabled && rdev->desc->ops->set_suspend_disable)
                ret = rdev->desc->ops->set_suspend_disable(rdev);
+       else /* OK if set_suspend_enable or set_suspend_disable is NULL */
+               ret = 0;
+
        if (ret < 0) {
                rdev_err(rdev, "failed to enabled/disable\n");
                return ret;
@@ -1146,6 +1154,15 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
                                   &regulator->max_uV);
        }
 
+       /*
+        * Check now if the regulator is an always on regulator - if
+        * it is then we don't need to do nearly so much work for
+        * enable/disable calls.
+        */
+       if (!_regulator_can_change_status(rdev) &&
+           _regulator_is_enabled(rdev))
+               regulator->always_on = true;
+
        mutex_unlock(&rdev->mutex);
        return regulator;
 link_name_err:
@@ -1169,26 +1186,52 @@ static int _regulator_get_enable_time(struct regulator_dev *rdev)
 }
 
 static struct regulator_dev *regulator_dev_lookup(struct device *dev,
-                                                        const char *supply)
+                                                 const char *supply,
+                                                 int *ret)
 {
        struct regulator_dev *r;
        struct device_node *node;
+       struct regulator_map *map;
+       const char *devname = NULL;
 
        /* first do a dt based lookup */
        if (dev && dev->of_node) {
                node = of_get_regulator(dev, supply);
-               if (node)
+               if (node) {
                        list_for_each_entry(r, &regulator_list, list)
                                if (r->dev.parent &&
                                        node == r->dev.of_node)
                                        return r;
+               } else {
+                       /*
+                        * If we couldn't even get the node then it's
+                        * not just that the device didn't register
+                        * yet, there's no node and we'll never
+                        * succeed.
+                        */
+                       *ret = -ENODEV;
+               }
        }
 
        /* if not found, try doing it non-dt way */
+       if (dev)
+               devname = dev_name(dev);
+
        list_for_each_entry(r, &regulator_list, list)
                if (strcmp(rdev_get_name(r), supply) == 0)
                        return r;
 
+       list_for_each_entry(map, &regulator_map_list, list) {
+               /* If the mapping has a device set up it must match */
+               if (map->dev_name &&
+                   (!devname || strcmp(map->dev_name, devname)))
+                       continue;
+
+               if (strcmp(map->supply, supply) == 0)
+                       return map->regulator;
+       }
+
+
        return NULL;
 }
 
@@ -1197,7 +1240,6 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
                                        int exclusive)
 {
        struct regulator_dev *rdev;
-       struct regulator_map *map;
        struct regulator *regulator = ERR_PTR(-EPROBE_DEFER);
        const char *devname = NULL;
        int ret;
@@ -1212,22 +1254,10 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
 
        mutex_lock(&regulator_list_mutex);
 
-       rdev = regulator_dev_lookup(dev, id);
+       rdev = regulator_dev_lookup(dev, id, &ret);
        if (rdev)
                goto found;
 
-       list_for_each_entry(map, &regulator_map_list, list) {
-               /* If the mapping has a device set up it must match */
-               if (map->dev_name &&
-                   (!devname || strcmp(map->dev_name, devname)))
-                       continue;
-
-               if (strcmp(map->supply, id) == 0) {
-                       rdev = map->regulator;
-                       goto found;
-               }
-       }
-
        if (board_wants_dummy_regulator) {
                rdev = dummy_regulator_rdev;
                goto found;
@@ -1438,17 +1468,6 @@ void devm_regulator_put(struct regulator *regulator)
 }
 EXPORT_SYMBOL_GPL(devm_regulator_put);
 
-static int _regulator_can_change_status(struct regulator_dev *rdev)
-{
-       if (!rdev->constraints)
-               return 0;
-
-       if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS)
-               return 1;
-       else
-               return 0;
-}
-
 /* locks held by regulator_enable() */
 static int _regulator_enable(struct regulator_dev *rdev)
 {
@@ -1528,6 +1547,9 @@ int regulator_enable(struct regulator *regulator)
        struct regulator_dev *rdev = regulator->rdev;
        int ret = 0;
 
+       if (regulator->always_on)
+               return 0;
+
        if (rdev->supply) {
                ret = regulator_enable(rdev->supply);
                if (ret != 0)
@@ -1606,6 +1628,9 @@ int regulator_disable(struct regulator *regulator)
        struct regulator_dev *rdev = regulator->rdev;
        int ret = 0;
 
+       if (regulator->always_on)
+               return 0;
+
        mutex_lock(&rdev->mutex);
        ret = _regulator_disable(rdev);
        mutex_unlock(&rdev->mutex);
@@ -1714,6 +1739,9 @@ int regulator_disable_deferred(struct regulator *regulator, int ms)
        struct regulator_dev *rdev = regulator->rdev;
        int ret;
 
+       if (regulator->always_on)
+               return 0;
+
        mutex_lock(&rdev->mutex);
        rdev->deferred_disables++;
        mutex_unlock(&rdev->mutex);
@@ -1727,6 +1755,61 @@ int regulator_disable_deferred(struct regulator *regulator, int ms)
 }
 EXPORT_SYMBOL_GPL(regulator_disable_deferred);
 
+/**
+ * regulator_is_enabled_regmap - standard is_enabled() for regmap users
+ *
+ * @rdev: regulator to operate on
+ *
+ * Regulators that use regmap for their register I/O can set the
+ * enable_reg and enable_mask fields in their descriptor and then use
+ * this as their is_enabled operation, saving some code.
+ */
+int regulator_is_enabled_regmap(struct regulator_dev *rdev)
+{
+       unsigned int val;
+       int ret;
+
+       ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
+       if (ret != 0)
+               return ret;
+
+       return (val & rdev->desc->enable_mask) != 0;
+}
+EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap);
+
+/**
+ * regulator_enable_regmap - standard enable() for regmap users
+ *
+ * @rdev: regulator to operate on
+ *
+ * Regulators that use regmap for their register I/O can set the
+ * enable_reg and enable_mask fields in their descriptor and then use
+ * this as their enable() operation, saving some code.
+ */
+int regulator_enable_regmap(struct regulator_dev *rdev)
+{
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask,
+                                 rdev->desc->enable_mask);
+}
+EXPORT_SYMBOL_GPL(regulator_enable_regmap);
+
+/**
+ * regulator_disable_regmap - standard disable() for regmap users
+ *
+ * @rdev: regulator to operate on
+ *
+ * Regulators that use regmap for their register I/O can set the
+ * enable_reg and enable_mask fields in their descriptor and then use
+ * this as their disable() operation, saving some code.
+ */
+int regulator_disable_regmap(struct regulator_dev *rdev)
+{
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask, 0);
+}
+EXPORT_SYMBOL_GPL(regulator_disable_regmap);
+
 static int _regulator_is_enabled(struct regulator_dev *rdev)
 {
        /* If we don't know then assume that the regulator is always on */
@@ -1752,6 +1835,9 @@ int regulator_is_enabled(struct regulator *regulator)
 {
        int ret;
 
+       if (regulator->always_on)
+               return 1;
+
        mutex_lock(&regulator->rdev->mutex);
        ret = _regulator_is_enabled(regulator->rdev);
        mutex_unlock(&regulator->rdev->mutex);
@@ -1776,6 +1862,26 @@ int regulator_count_voltages(struct regulator *regulator)
 }
 EXPORT_SYMBOL_GPL(regulator_count_voltages);
 
+/**
+ * regulator_list_voltage_linear - List voltages with simple calculation
+ *
+ * @rdev: Regulator device
+ * @selector: Selector to convert into a voltage
+ *
+ * Regulators with a simple linear mapping between voltages and
+ * selectors can set min_uV and uV_step in the regulator descriptor
+ * and then use this function as their list_voltage() operation,
+ */
+int regulator_list_voltage_linear(struct regulator_dev *rdev,
+                                 unsigned int selector)
+{
+       if (selector >= rdev->desc->n_voltages)
+               return -EINVAL;
+
+       return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
+}
+EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
+
 /**
  * regulator_list_voltage - enumerate supported voltages
  * @regulator: regulator source
@@ -1840,75 +1946,186 @@ int regulator_is_supported_voltage(struct regulator *regulator,
 }
 EXPORT_SYMBOL_GPL(regulator_is_supported_voltage);
 
+/**
+ * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users
+ *
+ * @rdev: regulator to operate on
+ *
+ * Regulators that use regmap for their register I/O can set the
+ * vsel_reg and vsel_mask fields in their descriptor and then use this
+ * as their get_voltage_vsel operation, saving some code.
+ */
+int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev)
+{
+       unsigned int val;
+       int ret;
+
+       ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
+       if (ret != 0)
+               return ret;
+
+       val &= rdev->desc->vsel_mask;
+       val >>= ffs(rdev->desc->vsel_mask) - 1;
+
+       return val;
+}
+EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap);
+
+/**
+ * regulator_set_voltage_sel_regmap - standard set_voltage_sel for regmap users
+ *
+ * @rdev: regulator to operate on
+ * @sel: Selector to set
+ *
+ * Regulators that use regmap for their register I/O can set the
+ * vsel_reg and vsel_mask fields in their descriptor and then use this
+ * as their set_voltage_vsel operation, saving some code.
+ */
+int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel)
+{
+       sel <<= ffs(rdev->desc->vsel_mask) - 1;
+
+       return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
+                                 rdev->desc->vsel_mask, sel);
+}
+EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap);
+
+/**
+ * regulator_map_voltage_iterate - map_voltage() based on list_voltage()
+ *
+ * @rdev: Regulator to operate on
+ * @min_uV: Lower bound for voltage
+ * @max_uV: Upper bound for voltage
+ *
+ * Drivers implementing set_voltage_sel() and list_voltage() can use
+ * this as their map_voltage() operation.  It will find a suitable
+ * voltage by calling list_voltage() until it gets something in bounds
+ * for the requested voltages.
+ */
+int regulator_map_voltage_iterate(struct regulator_dev *rdev,
+                                 int min_uV, int max_uV)
+{
+       int best_val = INT_MAX;
+       int selector = 0;
+       int i, ret;
+
+       /* Find the smallest voltage that falls within the specified
+        * range.
+        */
+       for (i = 0; i < rdev->desc->n_voltages; i++) {
+               ret = rdev->desc->ops->list_voltage(rdev, i);
+               if (ret < 0)
+                       continue;
+
+               if (ret < best_val && ret >= min_uV && ret <= max_uV) {
+                       best_val = ret;
+                       selector = i;
+               }
+       }
+
+       if (best_val != INT_MAX)
+               return selector;
+       else
+               return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate);
+
+/**
+ * regulator_map_voltage_linear - map_voltage() for simple linear mappings
+ *
+ * @rdev: Regulator to operate on
+ * @min_uV: Lower bound for voltage
+ * @max_uV: Upper bound for voltage
+ *
+ * Drivers providing min_uV and uV_step in their regulator_desc can
+ * use this as their map_voltage() operation.
+ */
+int regulator_map_voltage_linear(struct regulator_dev *rdev,
+                                int min_uV, int max_uV)
+{
+       int ret, voltage;
+
+       if (!rdev->desc->uV_step) {
+               BUG_ON(!rdev->desc->uV_step);
+               return -EINVAL;
+       }
+
+       if (min_uV < rdev->desc->min_uV)
+               min_uV = rdev->desc->min_uV;
+
+       ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step);
+       if (ret < 0)
+               return ret;
+
+       /* Map back into a voltage to verify we're still in bounds */
+       voltage = rdev->desc->ops->list_voltage(rdev, ret);
+       if (voltage < min_uV || voltage > max_uV)
+               return -EINVAL;
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_map_voltage_linear);
+
 static int _regulator_do_set_voltage(struct regulator_dev *rdev,
                                     int min_uV, int max_uV)
 {
        int ret;
        int delay = 0;
+       int best_val;
        unsigned int selector;
+       int old_selector = -1;
 
        trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
 
        min_uV += rdev->constraints->uV_offset;
        max_uV += rdev->constraints->uV_offset;
 
+       /*
+        * If we can't obtain the old selector there is not enough
+        * info to call set_voltage_time_sel().
+        */
+       if (rdev->desc->ops->set_voltage_time_sel &&
+           rdev->desc->ops->get_voltage_sel) {
+               old_selector = rdev->desc->ops->get_voltage_sel(rdev);
+               if (old_selector < 0)
+                       return old_selector;
+       }
+
        if (rdev->desc->ops->set_voltage) {
                ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV,
                                                   &selector);
-
-               if (rdev->desc->ops->list_voltage)
-                       selector = rdev->desc->ops->list_voltage(rdev,
-                                                                selector);
-               else
-                       selector = -1;
        } else if (rdev->desc->ops->set_voltage_sel) {
-               int best_val = INT_MAX;
-               int i;
-
-               selector = 0;
-
-               /* Find the smallest voltage that falls within the specified
-                * range.
-                */
-               for (i = 0; i < rdev->desc->n_voltages; i++) {
-                       ret = rdev->desc->ops->list_voltage(rdev, i);
-                       if (ret < 0)
-                               continue;
+               if (rdev->desc->ops->map_voltage)
+                       ret = rdev->desc->ops->map_voltage(rdev, min_uV,
+                                                          max_uV);
+               else
+                       ret = regulator_map_voltage_iterate(rdev, min_uV,
+                                                           max_uV);
 
-                       if (ret < best_val && ret >= min_uV && ret <= max_uV) {
-                               best_val = ret;
-                               selector = i;
-                       }
+               if (ret >= 0) {
+                       selector = ret;
+                       ret = rdev->desc->ops->set_voltage_sel(rdev, ret);
                }
+       } else {
+               ret = -EINVAL;
+       }
 
-               /*
-                * If we can't obtain the old selector there is not enough
-                * info to call set_voltage_time_sel().
-                */
-               if (rdev->desc->ops->set_voltage_time_sel &&
-                   rdev->desc->ops->get_voltage_sel) {
-                       unsigned int old_selector = 0;
+       if (rdev->desc->ops->list_voltage)
+               best_val = rdev->desc->ops->list_voltage(rdev, selector);
+       else
+               best_val = -1;
 
-                       ret = rdev->desc->ops->get_voltage_sel(rdev);
-                       if (ret < 0)
-                               return ret;
-                       old_selector = ret;
-                       ret = rdev->desc->ops->set_voltage_time_sel(rdev,
-                                               old_selector, selector);
-                       if (ret < 0)
-                               rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", ret);
-                       else
-                               delay = ret;
-               }
+       /* Call set_voltage_time_sel if successfully obtained old_selector */
+       if (ret == 0 && old_selector >= 0 &&
+           rdev->desc->ops->set_voltage_time_sel) {
 
-               if (best_val != INT_MAX) {
-                       ret = rdev->desc->ops->set_voltage_sel(rdev, selector);
-                       selector = best_val;
-               } else {
-                       ret = -EINVAL;
+               delay = rdev->desc->ops->set_voltage_time_sel(rdev,
+                                               old_selector, selector);
+               if (delay < 0) {
+                       rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n",
+                                 delay);
+                       delay = 0;
                }
-       } else {
-               ret = -EINVAL;
        }
 
        /* Insert any necessary delays */
@@ -1923,7 +2140,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
                _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
                                     NULL);
 
-       trace_regulator_set_voltage_complete(rdev_get_name(rdev), selector);
+       trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val);
 
        return ret;
 }
@@ -2327,6 +2544,9 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
         */
        ret = -EINVAL;
 
+       if (!rdev->desc->ops->set_mode)
+               goto out;
+
        /* get output voltage */
        output_uV = _regulator_get_voltage(rdev);
        if (output_uV <= 0) {
@@ -2528,9 +2748,13 @@ int regulator_bulk_enable(int num_consumers,
        int i;
        int ret = 0;
 
-       for (i = 0; i < num_consumers; i++)
-               async_schedule_domain(regulator_bulk_enable_async,
-                                     &consumers[i], &async_domain);
+       for (i = 0; i < num_consumers; i++) {
+               if (consumers[i].consumer->always_on)
+                       consumers[i].ret = 0;
+               else
+                       async_schedule_domain(regulator_bulk_enable_async,
+                                             &consumers[i], &async_domain);
+       }
 
        async_synchronize_full_domain(&async_domain);
 
@@ -2569,7 +2793,7 @@ int regulator_bulk_disable(int num_consumers,
                           struct regulator_bulk_data *consumers)
 {
        int i;
-       int ret;
+       int ret, r;
 
        for (i = num_consumers - 1; i >= 0; --i) {
                ret = regulator_disable(consumers[i].consumer);
@@ -2581,8 +2805,12 @@ int regulator_bulk_disable(int num_consumers,
 
 err:
        pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret);
-       for (++i; i < num_consumers; ++i)
-               regulator_enable(consumers[i].consumer);
+       for (++i; i < num_consumers; ++i) {
+               r = regulator_enable(consumers[i].consumer);
+               if (r != 0)
+                       pr_err("Failed to reename %s: %d\n",
+                              consumers[i].supply, r);
+       }
 
        return ret;
 }
@@ -2759,10 +2987,6 @@ static int add_regulator_attributes(struct regulator_dev *rdev)
                        return status;
        }
 
-       /* suspend mode constraints need multiple supporting methods */
-       if (!(ops->set_suspend_enable && ops->set_suspend_disable))
-               return status;
-
        status = device_create_file(dev, &dev_attr_suspend_standby_state);
        if (status < 0)
                return status;
@@ -2823,28 +3047,29 @@ static void rdev_init_debugfs(struct regulator_dev *rdev)
 /**
  * regulator_register - register regulator
  * @regulator_desc: regulator to register
- * @dev: struct device for the regulator
- * @init_data: platform provided init data, passed through by driver
- * @driver_data: private regulator data
- * @of_node: OpenFirmware node to parse for device tree bindings (may be
- *           NULL).
+ * @config: runtime configuration for regulator
  *
  * Called by regulator drivers to register a regulator.
  * Returns 0 on success.
  */
-struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
-       struct device *dev, const struct regulator_init_data *init_data,
-       void *driver_data, struct device_node *of_node)
+struct regulator_dev *
+regulator_register(const struct regulator_desc *regulator_desc,
+                  const struct regulator_config *config)
 {
        const struct regulation_constraints *constraints = NULL;
+       const struct regulator_init_data *init_data;
        static atomic_t regulator_no = ATOMIC_INIT(0);
        struct regulator_dev *rdev;
+       struct device *dev;
        int ret, i;
        const char *supply = NULL;
 
-       if (regulator_desc == NULL)
+       if (regulator_desc == NULL || config == NULL)
                return ERR_PTR(-EINVAL);
 
+       dev = config->dev;
+       WARN_ON(!dev);
+
        if (regulator_desc->name == NULL || regulator_desc->ops == NULL)
                return ERR_PTR(-EINVAL);
 
@@ -2868,6 +3093,8 @@ struct regulator_dev *regulator_register(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);
@@ -2875,9 +3102,10 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
        mutex_lock(&regulator_list_mutex);
 
        mutex_init(&rdev->mutex);
-       rdev->reg_data = driver_data;
+       rdev->reg_data = config->driver_data;
        rdev->owner = regulator_desc->owner;
        rdev->desc = regulator_desc;
+       rdev->regmap = config->regmap;
        INIT_LIST_HEAD(&rdev->consumer_list);
        INIT_LIST_HEAD(&rdev->list);
        BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
@@ -2892,7 +3120,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
 
        /* register with sysfs */
        rdev->dev.class = &regulator_class;
-       rdev->dev.of_node = of_node;
+       rdev->dev.of_node = config->of_node;
        rdev->dev.parent = dev;
        dev_set_name(&rdev->dev, "regulator.%d",
                     atomic_inc_return(&regulator_no) - 1);
@@ -2925,7 +3153,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
        if (supply) {
                struct regulator_dev *r;
 
-               r = regulator_dev_lookup(dev, supply);
+               r = regulator_dev_lookup(dev, supply, &ret);
 
                if (!r) {
                        dev_err(dev, "Failed to find supply %s\n", supply);
@@ -2938,8 +3166,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
                        goto scrub;
 
                /* Enable supply if rail is enabled */
-               if (rdev->desc->ops->is_enabled &&
-                               rdev->desc->ops->is_enabled(rdev)) {
+               if (_regulator_is_enabled(rdev)) {
                        ret = regulator_enable(rdev->supply);
                        if (ret < 0)
                                goto scrub;
@@ -2971,6 +3198,8 @@ unset_supplies:
        unset_regulator_supplies(rdev);
 
 scrub:
+       if (rdev->supply)
+               regulator_put(rdev->supply);
        kfree(rdev->constraints);
        device_unregister(&rdev->dev);
        /* device core frees rdev */
@@ -3069,7 +3298,7 @@ int regulator_suspend_finish(void)
                                goto unlock;
                        if (!ops->disable)
                                goto unlock;
-                       if (ops->is_enabled && !ops->is_enabled(rdev))
+                       if (!_regulator_is_enabled(rdev))
                                goto unlock;
 
                        error = ops->disable(rdev);