Merge branch 'regulator-drivers' into regulator-next
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Sun, 22 Jul 2012 18:32:00 +0000 (19:32 +0100)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Sun, 22 Jul 2012 18:32:00 +0000 (19:32 +0100)
drivers/regulator/core.c
drivers/regulator/fixed-helper.c
include/linux/regulator/consumer.h
include/linux/regulator/driver.h
include/linux/regulator/fixed.h

index 08ccf03..2e31dff 100644 (file)
@@ -109,28 +109,6 @@ static const char *rdev_get_name(struct regulator_dev *rdev)
                return "";
 }
 
-/* gets the regulator for a given consumer device */
-static struct regulator *get_device_regulator(struct device *dev)
-{
-       struct regulator *regulator = NULL;
-       struct regulator_dev *rdev;
-
-       mutex_lock(&regulator_list_mutex);
-       list_for_each_entry(rdev, &regulator_list, list) {
-               mutex_lock(&rdev->mutex);
-               list_for_each_entry(regulator, &rdev->consumer_list, list) {
-                       if (regulator->dev == dev) {
-                               mutex_unlock(&rdev->mutex);
-                               mutex_unlock(&regulator_list_mutex);
-                               return regulator;
-                       }
-               }
-               mutex_unlock(&rdev->mutex);
-       }
-       mutex_unlock(&regulator_list_mutex);
-       return NULL;
-}
-
 /**
  * of_get_regulator - get a regulator device node based on supply name
  * @dev: Device pointer for the consumer (of regulator) device
@@ -304,18 +282,6 @@ static int regulator_check_drms(struct regulator_dev *rdev)
        return 0;
 }
 
-static ssize_t device_requested_uA_show(struct device *dev,
-                            struct device_attribute *attr, char *buf)
-{
-       struct regulator *regulator;
-
-       regulator = get_device_regulator(dev);
-       if (regulator == NULL)
-               return 0;
-
-       return sprintf(buf, "%d\n", regulator->uA_load);
-}
-
 static ssize_t regulator_uV_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
@@ -428,6 +394,9 @@ static ssize_t regulator_status_show(struct device *dev,
        case REGULATOR_STATUS_STANDBY:
                label = "standby";
                break;
+       case REGULATOR_STATUS_UNDEFINED:
+               label = "undefined";
+               break;
        default:
                return -ERANGE;
        }
@@ -1106,48 +1075,29 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
        list_add(&regulator->list, &rdev->consumer_list);
 
        if (dev) {
-               /* create a 'requested_microamps_name' sysfs entry */
-               size = scnprintf(buf, REG_STR_SIZE,
-                                "microamps_requested_%s-%s",
-                                dev_name(dev), supply_name);
-               if (size >= REG_STR_SIZE)
-                       goto overflow_err;
-
                regulator->dev = dev;
-               sysfs_attr_init(&regulator->dev_attr.attr);
-               regulator->dev_attr.attr.name = kstrdup(buf, GFP_KERNEL);
-               if (regulator->dev_attr.attr.name == NULL)
-                       goto attr_name_err;
-
-               regulator->dev_attr.attr.mode = 0444;
-               regulator->dev_attr.show = device_requested_uA_show;
-               err = device_create_file(dev, &regulator->dev_attr);
-               if (err < 0) {
-                       rdev_warn(rdev, "could not add regulator_dev requested microamps sysfs entry\n");
-                       goto attr_name_err;
-               }
 
-               /* also add a link to the device sysfs entry */
+               /* Add a link to the device sysfs entry */
                size = scnprintf(buf, REG_STR_SIZE, "%s-%s",
                                 dev->kobj.name, supply_name);
                if (size >= REG_STR_SIZE)
-                       goto attr_err;
+                       goto overflow_err;
 
                regulator->supply_name = kstrdup(buf, GFP_KERNEL);
                if (regulator->supply_name == NULL)
-                       goto attr_err;
+                       goto overflow_err;
 
                err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj,
                                        buf);
                if (err) {
                        rdev_warn(rdev, "could not add device link %s err %d\n",
                                  dev->kobj.name, err);
-                       goto link_name_err;
+                       /* non-fatal */
                }
        } else {
                regulator->supply_name = kstrdup(supply_name, GFP_KERNEL);
                if (regulator->supply_name == NULL)
-                       goto attr_err;
+                       goto overflow_err;
        }
 
        regulator->debugfs = debugfs_create_dir(regulator->supply_name,
@@ -1174,12 +1124,6 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
 
        mutex_unlock(&rdev->mutex);
        return regulator;
-link_name_err:
-       kfree(regulator->supply_name);
-attr_err:
-       device_remove_file(regulator->dev, &regulator->dev_attr);
-attr_name_err:
-       kfree(regulator->dev_attr.attr.name);
 overflow_err:
        list_del(&regulator->list);
        kfree(regulator);
@@ -1429,11 +1373,8 @@ void regulator_put(struct regulator *regulator)
        debugfs_remove_recursive(regulator->debugfs);
 
        /* remove any sysfs entries */
-       if (regulator->dev) {
+       if (regulator->dev)
                sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
-               device_remove_file(regulator->dev, &regulator->dev_attr);
-               kfree(regulator->dev_attr.attr.name);
-       }
        kfree(regulator->supply_name);
        list_del(&regulator->list);
        kfree(regulator);
@@ -1470,9 +1411,7 @@ void devm_regulator_put(struct regulator *regulator)
 
        rc = devres_release(regulator->dev, devm_regulator_release,
                            devm_regulator_match, regulator);
-       if (rc == 0)
-               regulator_put(regulator);
-       else
+       if (rc != 0)
                WARN_ON(rc);
 }
 EXPORT_SYMBOL_GPL(devm_regulator_put);
@@ -1996,8 +1935,18 @@ EXPORT_SYMBOL_GPL(regulator_list_voltage);
 int regulator_is_supported_voltage(struct regulator *regulator,
                                   int min_uV, int max_uV)
 {
+       struct regulator_dev *rdev = regulator->rdev;
        int i, voltages, ret;
 
+       /* If we can't change voltage check the current voltage */
+       if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
+               ret = regulator_get_voltage(regulator);
+               if (ret >= 0)
+                       return (min_uV >= ret && ret <= max_uV);
+               else
+                       return ret;
+       }
+
        ret = regulator_count_voltages(regulator);
        if (ret < 0)
                return ret;
@@ -2147,7 +2096,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
 {
        int ret;
        int delay = 0;
-       int best_val;
+       int best_val = 0;
        unsigned int selector;
        int old_selector = -1;
 
@@ -2171,29 +2120,45 @@ 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);
+
+               if (ret >= 0) {
+                       if (rdev->desc->ops->list_voltage)
+                               best_val = rdev->desc->ops->list_voltage(rdev,
+                                                                        selector);
+                       else
+                               best_val = _regulator_get_voltage(rdev);
+               }
+
        } else if (rdev->desc->ops->set_voltage_sel) {
-               if (rdev->desc->ops->map_voltage)
+               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);
+               } else {
+                       if (rdev->desc->ops->list_voltage ==
+                           regulator_list_voltage_linear)
+                               ret = regulator_map_voltage_linear(rdev,
+                                                               min_uV, max_uV);
+                       else
+                               ret = regulator_map_voltage_iterate(rdev,
+                                                               min_uV, max_uV);
+               }
 
                if (ret >= 0) {
-                       selector = ret;
-                       ret = rdev->desc->ops->set_voltage_sel(rdev, ret);
+                       best_val = rdev->desc->ops->list_voltage(rdev, ret);
+                       if (min_uV <= best_val && max_uV >= best_val) {
+                               selector = ret;
+                               ret = rdev->desc->ops->set_voltage_sel(rdev,
+                                                                      ret);
+                       } else {
+                               ret = -EINVAL;
+                       }
                }
        } else {
                ret = -EINVAL;
        }
 
-       if (rdev->desc->ops->list_voltage)
-               best_val = rdev->desc->ops->list_voltage(rdev, selector);
-       else
-               best_val = -1;
-
        /* Call set_voltage_time_sel if successfully obtained old_selector */
-       if (_regulator_is_enabled(rdev) && ret == 0 && old_selector >= 0 &&
+       if (ret == 0 && _regulator_is_enabled(rdev) && old_selector >= 0 &&
            rdev->desc->ops->set_voltage_time_sel) {
 
                delay = rdev->desc->ops->set_voltage_time_sel(rdev,
@@ -2203,19 +2168,19 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
                                  delay);
                        delay = 0;
                }
-       }
 
-       /* Insert any necessary delays */
-       if (delay >= 1000) {
-               mdelay(delay / 1000);
-               udelay(delay % 1000);
-       } else if (delay) {
-               udelay(delay);
+               /* Insert any necessary delays */
+               if (delay >= 1000) {
+                       mdelay(delay / 1000);
+                       udelay(delay % 1000);
+               } else if (delay) {
+                       udelay(delay);
+               }
        }
 
-       if (ret == 0)
+       if (ret == 0 && best_val >= 0)
                _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
-                                    NULL);
+                                    (void *)best_val);
 
        trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val);
 
@@ -2745,7 +2710,7 @@ static void _notifier_call_chain(struct regulator_dev *rdev,
                                  unsigned long event, void *data)
 {
        /* call rdev chain first */
-       blocking_notifier_call_chain(&rdev->notifier, event, NULL);
+       blocking_notifier_call_chain(&rdev->notifier, event, data);
 }
 
 /**
@@ -3026,10 +2991,10 @@ int regulator_mode_to_status(unsigned int mode)
                return REGULATOR_STATUS_NORMAL;
        case REGULATOR_MODE_IDLE:
                return REGULATOR_STATUS_IDLE;
-       case REGULATOR_STATUS_STANDBY:
+       case REGULATOR_MODE_STANDBY:
                return REGULATOR_STATUS_STANDBY;
        default:
-               return 0;
+               return REGULATOR_STATUS_UNDEFINED;
        }
 }
 EXPORT_SYMBOL_GPL(regulator_mode_to_status);
@@ -3616,6 +3581,15 @@ static int __init regulator_init_complete(void)
        struct regulation_constraints *c;
        int enabled, ret;
 
+       /*
+        * Since DT doesn't provide an idiomatic mechanism for
+        * enabling full constraints and since it's much more natural
+        * with DT to provide them just assume that a DT enabled
+        * system has full constraints.
+        */
+       if (of_have_populated_dt())
+               has_full_constraints = true;
+
        mutex_lock(&regulator_list_mutex);
 
        /* If we have a full configuration then disable any regulators
index cacd33c..f9d0279 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/slab.h>
+#include <linux/string.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
@@ -13,17 +14,20 @@ static void regulator_fixed_release(struct device *dev)
 {
        struct fixed_regulator_data *data = container_of(dev,
                        struct fixed_regulator_data, pdev.dev);
+       kfree(data->cfg.supply_name);
        kfree(data);
 }
 
 /**
- * regulator_register_fixed - register a no-op fixed regulator
+ * regulator_register_fixed_name - register a no-op fixed regulator
  * @id: platform device id
+ * @name: name to be used for the regulator
  * @supplies: consumers for this regulator
  * @num_supplies: number of consumers
+ * @uv: voltage in microvolts
  */
-struct platform_device *regulator_register_fixed(int id,
-               struct regulator_consumer_supply *supplies, int num_supplies)
+struct platform_device *regulator_register_always_on(int id, const char *name,
+       struct regulator_consumer_supply *supplies, int num_supplies, int uv)
 {
        struct fixed_regulator_data *data;
 
@@ -31,8 +35,13 @@ struct platform_device *regulator_register_fixed(int id,
        if (!data)
                return NULL;
 
-       data->cfg.supply_name = "fixed-dummy";
-       data->cfg.microvolts = 0;
+       data->cfg.supply_name = kstrdup(name, GFP_KERNEL);
+       if (!data->cfg.supply_name) {
+               kfree(data);
+               return NULL;
+       }
+
+       data->cfg.microvolts = uv;
        data->cfg.gpio = -EINVAL;
        data->cfg.enabled_at_boot = 1;
        data->cfg.init_data = &data->init_data;
index 4ed1b30..da339fd 100644 (file)
@@ -290,6 +290,12 @@ static inline int regulator_set_voltage(struct regulator *regulator,
 }
 
 static inline int regulator_get_voltage(struct regulator *regulator)
+{
+       return -EINVAL;
+}
+
+static inline int regulator_is_supported_voltage(struct regulator *regulator,
+                                  int min_uV, int max_uV)
 {
        return 0;
 }
index b1b7b8b..bac4c87 100644 (file)
@@ -32,6 +32,8 @@ enum regulator_status {
        REGULATOR_STATUS_NORMAL,
        REGULATOR_STATUS_IDLE,
        REGULATOR_STATUS_STANDBY,
+       /* in case that any other status doesn't apply */
+       REGULATOR_STATUS_UNDEFINED,
 };
 
 /**
index d6c24c5..48918be 100644 (file)
@@ -60,14 +60,17 @@ struct fixed_voltage_config {
 struct regulator_consumer_supply;
 
 #if IS_ENABLED(CONFIG_REGULATOR)
-struct platform_device *regulator_register_fixed(int id,
-               struct regulator_consumer_supply *supplies, int num_supplies);
+struct platform_device *regulator_register_always_on(int id, const char *name,
+               struct regulator_consumer_supply *supplies, int num_supplies, int uv);
 #else
-static inline struct platform_device *regulator_register_fixed(int id,
-               struct regulator_consumer_supply *supplies, int num_supplies)
+static inline struct platform_device *regulator_register_always_on(int id, const char *name,
+               struct regulator_consumer_supply *supplies, int num_supplies, int uv)
 {
        return NULL;
 }
 #endif
 
+#define regulator_register_fixed(id, s, ns) regulator_register_always_on(id, \
+                                               "fixed-dummy", s, ns, 0)
+
 #endif