Merge tag 'lsk-v3.10-15.04-android'
[firefly-linux-kernel-4.4.55.git] / drivers / regulator / core.c
index 874dd261b2480066ad2e5c2e7ecb630d846da878..8553f7b840e6cfad4843847d952ad29488b5b6b7 100644 (file)
@@ -36,6 +36,7 @@
 #include <trace/events/regulator.h>
 
 #include "dummy.h"
+#include "internal.h"
 
 #define rdev_crit(rdev, fmt, ...)                                      \
        pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
@@ -82,31 +83,12 @@ struct regulator_enable_gpio {
        unsigned int ena_gpio_invert:1;
 };
 
-/*
- * struct regulator
- *
- * One for each consumer device.
- */
-struct regulator {
-       struct device *dev;
-       struct list_head list;
-       unsigned int always_on:1;
-       unsigned int bypass:1;
-       int uA_load;
-       int min_uV;
-       int max_uV;
-       char *supply_name;
-       struct device_attribute dev_attr;
-       struct regulator_dev *rdev;
-       struct dentry *debugfs;
-};
-
 static int _regulator_is_enabled(struct regulator_dev *rdev);
 static int _regulator_disable(struct regulator_dev *rdev);
 static int _regulator_get_voltage(struct regulator_dev *rdev);
 static int _regulator_get_current_limit(struct regulator_dev *rdev);
 static unsigned int _regulator_get_mode(struct regulator_dev *rdev);
-static void _notifier_call_chain(struct regulator_dev *rdev,
+static int _notifier_call_chain(struct regulator_dev *rdev,
                                  unsigned long event, void *data);
 static int _regulator_do_set_voltage(struct regulator_dev *rdev,
                                     int min_uV, int max_uV);
@@ -1354,35 +1336,6 @@ static void devm_regulator_release(struct device *dev, void *res)
        regulator_put(*(struct regulator **)res);
 }
 
-/**
- * devm_regulator_get - Resource managed regulator_get()
- * @dev: device for regulator "consumer"
- * @id: Supply name or regulator ID.
- *
- * Managed regulator_get(). Regulators returned from this function are
- * automatically regulator_put() on driver detach. See regulator_get() for more
- * information.
- */
-struct regulator *devm_regulator_get(struct device *dev, const char *id)
-{
-       struct regulator **ptr, *regulator;
-
-       ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
-       if (!ptr)
-               return ERR_PTR(-ENOMEM);
-
-       regulator = regulator_get(dev, id);
-       if (!IS_ERR(regulator)) {
-               *ptr = regulator;
-               devres_add(dev, ptr);
-       } else {
-               devres_free(ptr);
-       }
-
-       return regulator;
-}
-EXPORT_SYMBOL_GPL(devm_regulator_get);
-
 /**
  * regulator_get_exclusive - obtain exclusive access to a regulator.
  * @dev: device for regulator "consumer"
@@ -1410,7 +1363,36 @@ struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
 }
 EXPORT_SYMBOL_GPL(regulator_get_exclusive);
 
-/* Locks held by regulator_put() */
+/**
+ * regulator_get_optional - obtain optional access to a regulator.
+ * @dev: device for regulator "consumer"
+ * @id: Supply name or regulator ID.
+ *
+ * Returns a struct regulator corresponding to the regulator producer,
+ * or IS_ERR() condition containing errno.  Other consumers will be
+ * unable to obtain this reference is held and the use count for the
+ * regulator will be initialised to reflect the current state of the
+ * regulator.
+ *
+ * This is intended for use by consumers for devices which can have
+ * some supplies unconnected in normal use, such as some MMC devices.
+ * It can allow the regulator core to provide stub supplies for other
+ * supplies requested using normal regulator_get() calls without
+ * disrupting the operation of drivers that can handle absent
+ * supplies.
+ *
+ * Use of supply names configured via regulator_set_device_supply() is
+ * strongly encouraged.  It is recommended that the supply name used
+ * should match the name used for the supply and/or the relevant
+ * device pins in the datasheet.
+ */
+struct regulator *regulator_get_optional(struct device *dev, const char *id)
+{
+       return _regulator_get(dev, id, 0);
+}
+EXPORT_SYMBOL_GPL(regulator_get_optional);
+
+/* regulator_list_mutex lock held by regulator_put() */
 static void _regulator_put(struct regulator *regulator)
 {
        struct regulator_dev *rdev;
@@ -1425,12 +1407,14 @@ static void _regulator_put(struct regulator *regulator)
        /* remove any sysfs entries */
        if (regulator->dev)
                sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
+       mutex_lock(&rdev->mutex);
        kfree(regulator->supply_name);
        list_del(&regulator->list);
        kfree(regulator);
 
        rdev->open_count--;
        rdev->exclusive = 0;
+       mutex_unlock(&rdev->mutex);
 
        module_put(rdev->owner);
 }
@@ -1451,35 +1435,6 @@ void regulator_put(struct regulator *regulator)
 }
 EXPORT_SYMBOL_GPL(regulator_put);
 
-static int devm_regulator_match(struct device *dev, void *res, void *data)
-{
-       struct regulator **r = res;
-       if (!r || !*r) {
-               WARN_ON(!r || !*r);
-               return 0;
-       }
-       return *r == data;
-}
-
-/**
- * devm_regulator_put - Resource managed regulator_put()
- * @regulator: regulator to free
- *
- * Deallocate a regulator allocated with devm_regulator_get(). Normally
- * this function will not need to be called and the resource management
- * code will ensure that the resource is freed.
- */
-void devm_regulator_put(struct regulator *regulator)
-{
-       int rc;
-
-       rc = devres_release(regulator->dev, devm_regulator_release,
-                           devm_regulator_match, regulator);
-       if (rc != 0)
-               WARN_ON(rc);
-}
-EXPORT_SYMBOL_GPL(devm_regulator_put);
-
 /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */
 static int regulator_ena_gpio_request(struct regulator_dev *rdev,
                                const struct regulator_config *config)
@@ -1594,10 +1549,12 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
        trace_regulator_enable(rdev_get_name(rdev));
 
        if (rdev->ena_pin) {
-               ret = regulator_ena_gpio_ctrl(rdev, true);
-               if (ret < 0)
-                       return ret;
-               rdev->ena_gpio_state = 1;
+               if (!rdev->ena_gpio_state) {
+                       ret = regulator_ena_gpio_ctrl(rdev, true);
+                       if (ret < 0)
+                               return ret;
+                       rdev->ena_gpio_state = 1;
+               }
        } else if (rdev->desc->ops->enable) {
                ret = rdev->desc->ops->enable(rdev);
                if (ret < 0)
@@ -1699,10 +1656,12 @@ static int _regulator_do_disable(struct regulator_dev *rdev)
        trace_regulator_disable(rdev_get_name(rdev));
 
        if (rdev->ena_pin) {
-               ret = regulator_ena_gpio_ctrl(rdev, false);
-               if (ret < 0)
-                       return ret;
-               rdev->ena_gpio_state = 0;
+               if (rdev->ena_gpio_state) {
+                       ret = regulator_ena_gpio_ctrl(rdev, false);
+                       if (ret < 0)
+                               return ret;
+                       rdev->ena_gpio_state = 0;
+               }
 
        } else if (rdev->desc->ops->disable) {
                ret = rdev->desc->ops->disable(rdev);
@@ -2351,6 +2310,55 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev,
 }
 EXPORT_SYMBOL_GPL(regulator_map_voltage_linear);
 
+static int _regulator_call_set_voltage(struct regulator_dev *rdev,
+                                      int min_uV, int max_uV,
+                                      unsigned *selector)
+{
+       struct pre_voltage_change_data data;
+       int ret;
+
+       data.old_uV = _regulator_get_voltage(rdev);
+       data.min_uV = min_uV;
+       data.max_uV = max_uV;
+       ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE,
+                                  &data);
+       if (ret & NOTIFY_STOP_MASK)
+               return -EINVAL;
+
+       ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector);
+       if (ret >= 0)
+               return ret;
+
+       _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE,
+                            (void *)data.old_uV);
+
+       return ret;
+}
+
+static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev,
+                                          int uV, unsigned selector)
+{
+       struct pre_voltage_change_data data;
+       int ret;
+
+       data.old_uV = _regulator_get_voltage(rdev);
+       data.min_uV = uV;
+       data.max_uV = uV;
+       ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE,
+                                  &data);
+       if (ret & NOTIFY_STOP_MASK)
+               return -EINVAL;
+
+       ret = rdev->desc->ops->set_voltage_sel(rdev, selector);
+       if (ret >= 0)
+               return ret;
+
+       _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE,
+                            (void *)data.old_uV);
+
+       return ret;
+}
+
 static int _regulator_do_set_voltage(struct regulator_dev *rdev,
                                     int min_uV, int max_uV)
 {
@@ -2378,8 +2386,8 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
        }
 
        if (rdev->desc->ops->set_voltage) {
-               ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV,
-                                                  &selector);
+               ret = _regulator_call_set_voltage(rdev, min_uV, max_uV,
+                                                 &selector);
 
                if (ret >= 0) {
                        if (rdev->desc->ops->list_voltage)
@@ -2410,8 +2418,8 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
                                if (old_selector == selector)
                                        ret = 0;
                                else
-                                       ret = rdev->desc->ops->set_voltage_sel(
-                                                               rdev, ret);
+                                       ret = _regulator_call_set_voltage_sel(
+                                               rdev, best_val, selector);
                        } else {
                                ret = -EINVAL;
                        }
@@ -2775,6 +2783,20 @@ int regulator_get_current_limit(struct regulator *regulator)
 }
 EXPORT_SYMBOL_GPL(regulator_get_current_limit);
 
+int regulator_is_supported_mode(struct regulator *regulator, int *mode)
+{
+       struct regulator_dev *rdev = regulator->rdev;
+       int ret;
+
+       mutex_lock(&rdev->mutex);
+
+       ret = regulator_mode_constrain(rdev, mode);
+
+       mutex_unlock(&rdev->mutex);
+
+       return ret;
+}
+
 /**
  * regulator_set_mode - set regulator operating mode
  * @regulator: regulator source
@@ -3080,11 +3102,11 @@ EXPORT_SYMBOL_GPL(regulator_unregister_notifier);
 /* notify regulator consumers and downstream regulator consumers.
  * Note mutex must be held by caller.
  */
-static void _notifier_call_chain(struct regulator_dev *rdev,
+static int _notifier_call_chain(struct regulator_dev *rdev,
                                  unsigned long event, void *data)
 {
        /* call rdev chain first */
-       blocking_notifier_call_chain(&rdev->notifier, event, data);
+       return blocking_notifier_call_chain(&rdev->notifier, event, data);
 }
 
 /**
@@ -3132,52 +3154,6 @@ err:
 }
 EXPORT_SYMBOL_GPL(regulator_bulk_get);
 
-/**
- * devm_regulator_bulk_get - managed get multiple regulator consumers
- *
- * @dev:           Device to supply
- * @num_consumers: Number of consumers to register
- * @consumers:     Configuration of consumers; clients are stored here.
- *
- * @return 0 on success, an errno on failure.
- *
- * This helper function allows drivers to get several regulator
- * consumers in one operation with management, the regulators will
- * automatically be freed when the device is unbound.  If any of the
- * regulators cannot be acquired then any regulators that were
- * allocated will be freed before returning to the caller.
- */
-int devm_regulator_bulk_get(struct device *dev, int num_consumers,
-                           struct regulator_bulk_data *consumers)
-{
-       int i;
-       int ret;
-
-       for (i = 0; i < num_consumers; i++)
-               consumers[i].consumer = NULL;
-
-       for (i = 0; i < num_consumers; i++) {
-               consumers[i].consumer = devm_regulator_get(dev,
-                                                          consumers[i].supply);
-               if (IS_ERR(consumers[i].consumer)) {
-                       ret = PTR_ERR(consumers[i].consumer);
-                       dev_err(dev, "Failed to get supply '%s': %d\n",
-                               consumers[i].supply, ret);
-                       consumers[i].consumer = NULL;
-                       goto err;
-               }
-       }
-
-       return 0;
-
-err:
-       for (i = 0; i < num_consumers && consumers[i].consumer; i++)
-               devm_regulator_put(consumers[i].consumer);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
-
 static void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
 {
        struct regulator_bulk_data *bulk = data;
@@ -3613,12 +3589,6 @@ regulator_register(const struct regulator_desc *regulator_desc,
                                 config->ena_gpio, ret);
                        goto wash;
                }
-
-               if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH)
-                       rdev->ena_gpio_state = 1;
-
-               if (config->ena_gpio_invert)
-                       rdev->ena_gpio_state = !rdev->ena_gpio_state;
        }
 
        /* set regulator constraints */
@@ -3787,9 +3757,11 @@ int regulator_suspend_finish(void)
        list_for_each_entry(rdev, &regulator_list, list) {
                mutex_lock(&rdev->mutex);
                if (rdev->use_count > 0  || rdev->constraints->always_on) {
-                       error = _regulator_do_enable(rdev);
-                       if (error)
-                               ret = error;
+                       if (!_regulator_is_enabled(rdev)) {
+                               error = _regulator_do_enable(rdev);
+                               if (error)
+                                       ret = error;
+                       }
                } else {
                        if (!has_full_constraints)
                                goto unlock;