Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 2 Aug 2011 00:05:46 +0000 (14:05 -1000)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 2 Aug 2011 00:05:46 +0000 (14:05 -1000)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6: (23 commits)
  regulator: Improve WM831x DVS VSEL selection algorithm
  regulator: Bootstrap wm831x DVS VSEL value from ON VSEL if not already set
  regulator: Set up GPIO for WM831x VSEL before enabling VSEL mode
  regulator: Add EPEs to the MODULE_ALIAS() for wm831x-dcdc
  regulator: Fix WM831x DCDC DVS VSEL bootstrapping
  regulator: Fix WM831x regulator ID lookups for multiple WM831xs
  regulator: Fix argument format type errors in error prints
  regulator: Fix memory leak in set_machine_constraints() error paths
  regulator: Make core more chatty about some errors
  regulator: tps65910: Fix array access out of bounds bug
  regulator: tps65910: Add missing breaks in switch/case
  regulator: tps65910: Fix a memory leak in tps65910_probe error path
  regulator: TWL: Remove entry of RES_ID for 6030 macros
  ASoC: tlv320aic3x: Add correct hw registers to Line1 cross connect muxes
  regulator: Add basic per consumer debugfs
  regulator: Add rdev_crit() macro
  regulator: Refactor supply implementation to work as regular consumers
  regulator: Include the device name in the microamps_requested_ file
  regulator: Increase the limit on sysfs file names
  regulator: Properly register dummy regulator driver
  ...

drivers/regulator/core.c
drivers/regulator/dummy.c
drivers/regulator/tps65910-regulator.c
drivers/regulator/twl-regulator.c
drivers/regulator/wm831x-dcdc.c
drivers/regulator/wm831x-ldo.c
drivers/regulator/wm8994-regulator.c
include/linux/regulator/consumer.h
include/linux/regulator/driver.h

index d3e38790906ed889de2b78454516ec1410eb6466..d8e6a429e8ba046027e9fa8550be6444f47ae971 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/debugfs.h>
 #include <linux/device.h>
 #include <linux/slab.h>
+#include <linux/async.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/suspend.h>
@@ -33,6 +34,8 @@
 
 #include "dummy.h"
 
+#define rdev_crit(rdev, fmt, ...)                                      \
+       pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
 #define rdev_err(rdev, fmt, ...)                                       \
        pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
 #define rdev_warn(rdev, fmt, ...)                                      \
@@ -78,11 +81,13 @@ struct regulator {
        char *supply_name;
        struct device_attribute dev_attr;
        struct regulator_dev *rdev;
+#ifdef CONFIG_DEBUG_FS
+       struct dentry *debugfs;
+#endif
 };
 
 static int _regulator_is_enabled(struct regulator_dev *rdev);
-static int _regulator_disable(struct regulator_dev *rdev,
-               struct regulator_dev **supply_rdev_ptr);
+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);
@@ -90,6 +95,9 @@ static void _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);
+static struct regulator *create_regulator(struct regulator_dev *rdev,
+                                         struct device *dev,
+                                         const char *supply_name);
 
 static const char *rdev_get_name(struct regulator_dev *rdev)
 {
@@ -143,8 +151,11 @@ static int regulator_check_voltage(struct regulator_dev *rdev,
        if (*min_uV < rdev->constraints->min_uV)
                *min_uV = rdev->constraints->min_uV;
 
-       if (*min_uV > *max_uV)
+       if (*min_uV > *max_uV) {
+               rdev_err(rdev, "unsupportable voltage range: %d-%duV\n",
+                        *min_uV, *max_uV);
                return -EINVAL;
+       }
 
        return 0;
 }
@@ -197,8 +208,11 @@ static int regulator_check_current_limit(struct regulator_dev *rdev,
        if (*min_uA < rdev->constraints->min_uA)
                *min_uA = rdev->constraints->min_uA;
 
-       if (*min_uA > *max_uA)
+       if (*min_uA > *max_uA) {
+               rdev_err(rdev, "unsupportable current range: %d-%duA\n",
+                        *min_uA, *max_uA);
                return -EINVAL;
+       }
 
        return 0;
 }
@@ -213,6 +227,7 @@ static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode)
        case REGULATOR_MODE_STANDBY:
                break;
        default:
+               rdev_err(rdev, "invalid mode %x specified\n", *mode);
                return -EINVAL;
        }
 
@@ -779,7 +794,6 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
                if (ret < 0) {
                        rdev_err(rdev, "failed to apply %duV constraint\n",
                                 rdev->constraints->min_uV);
-                       rdev->constraints = NULL;
                        return ret;
                }
        }
@@ -882,7 +896,6 @@ static int set_machine_constraints(struct regulator_dev *rdev,
                ret = suspend_prepare(rdev, rdev->constraints->initial_state);
                if (ret < 0) {
                        rdev_err(rdev, "failed to set suspend state\n");
-                       rdev->constraints = NULL;
                        goto out;
                }
        }
@@ -909,13 +922,15 @@ static int set_machine_constraints(struct regulator_dev *rdev,
                ret = ops->enable(rdev);
                if (ret < 0) {
                        rdev_err(rdev, "failed to enable\n");
-                       rdev->constraints = NULL;
                        goto out;
                }
        }
 
        print_constraints(rdev);
+       return 0;
 out:
+       kfree(rdev->constraints);
+       rdev->constraints = NULL;
        return ret;
 }
 
@@ -929,21 +944,20 @@ out:
  * core if it's child is enabled.
  */
 static int set_supply(struct regulator_dev *rdev,
-       struct regulator_dev *supply_rdev)
+                     struct regulator_dev *supply_rdev)
 {
        int err;
 
-       err = sysfs_create_link(&rdev->dev.kobj, &supply_rdev->dev.kobj,
-                               "supply");
-       if (err) {
-               rdev_err(rdev, "could not add device link %s err %d\n",
-                        supply_rdev->dev.kobj.name, err);
-                      goto out;
+       rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev));
+
+       rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY");
+       if (IS_ERR(rdev->supply)) {
+               err = PTR_ERR(rdev->supply);
+               rdev->supply = NULL;
+               return err;
        }
-       rdev->supply = supply_rdev;
-       list_add(&rdev->slist, &supply_rdev->supply_list);
-out:
-       return err;
+
+       return 0;
 }
 
 /**
@@ -1032,7 +1046,7 @@ static void unset_regulator_supplies(struct regulator_dev *rdev)
        }
 }
 
-#define REG_STR_SIZE   32
+#define REG_STR_SIZE   64
 
 static struct regulator *create_regulator(struct regulator_dev *rdev,
                                          struct device *dev,
@@ -1052,8 +1066,9 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
 
        if (dev) {
                /* create a 'requested_microamps_name' sysfs entry */
-               size = scnprintf(buf, REG_STR_SIZE, "microamps_requested_%s",
-                       supply_name);
+               size = scnprintf(buf, REG_STR_SIZE,
+                                "microamps_requested_%s-%s",
+                                dev_name(dev), supply_name);
                if (size >= REG_STR_SIZE)
                        goto overflow_err;
 
@@ -1088,7 +1103,28 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
                                  dev->kobj.name, err);
                        goto link_name_err;
                }
+       } else {
+               regulator->supply_name = kstrdup(supply_name, GFP_KERNEL);
+               if (regulator->supply_name == NULL)
+                       goto attr_err;
+       }
+
+#ifdef CONFIG_DEBUG_FS
+       regulator->debugfs = debugfs_create_dir(regulator->supply_name,
+                                               rdev->debugfs);
+       if (IS_ERR_OR_NULL(regulator->debugfs)) {
+               rdev_warn(rdev, "Failed to create debugfs directory\n");
+               regulator->debugfs = NULL;
+       } else {
+               debugfs_create_u32("uA_load", 0444, regulator->debugfs,
+                                  &regulator->uA_load);
+               debugfs_create_u32("min_uV", 0444, regulator->debugfs,
+                                  &regulator->min_uV);
+               debugfs_create_u32("max_uV", 0444, regulator->debugfs,
+                                  &regulator->max_uV);
        }
+#endif
+
        mutex_unlock(&rdev->mutex);
        return regulator;
 link_name_err:
@@ -1267,13 +1303,17 @@ void regulator_put(struct regulator *regulator)
        mutex_lock(&regulator_list_mutex);
        rdev = regulator->rdev;
 
+#ifdef CONFIG_DEBUG_FS
+       debugfs_remove_recursive(regulator->debugfs);
+#endif
+
        /* remove any sysfs entries */
        if (regulator->dev) {
                sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
-               kfree(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);
 
@@ -1301,19 +1341,6 @@ static int _regulator_enable(struct regulator_dev *rdev)
 {
        int ret, delay;
 
-       if (rdev->use_count == 0) {
-               /* do we need to enable the supply regulator first */
-               if (rdev->supply) {
-                       mutex_lock(&rdev->supply->mutex);
-                       ret = _regulator_enable(rdev->supply);
-                       mutex_unlock(&rdev->supply->mutex);
-                       if (ret < 0) {
-                               rdev_err(rdev, "failed to enable: %d\n", ret);
-                               return ret;
-                       }
-               }
-       }
-
        /* check voltage and requested load before enabling */
        if (rdev->constraints &&
            (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS))
@@ -1388,19 +1415,27 @@ int regulator_enable(struct regulator *regulator)
        struct regulator_dev *rdev = regulator->rdev;
        int ret = 0;
 
+       if (rdev->supply) {
+               ret = regulator_enable(rdev->supply);
+               if (ret != 0)
+                       return ret;
+       }
+
        mutex_lock(&rdev->mutex);
        ret = _regulator_enable(rdev);
        mutex_unlock(&rdev->mutex);
+
+       if (ret != 0)
+               regulator_disable(rdev->supply);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(regulator_enable);
 
 /* locks held by regulator_disable() */
-static int _regulator_disable(struct regulator_dev *rdev,
-               struct regulator_dev **supply_rdev_ptr)
+static int _regulator_disable(struct regulator_dev *rdev)
 {
        int ret = 0;
-       *supply_rdev_ptr = NULL;
 
        if (WARN(rdev->use_count <= 0,
                 "unbalanced disables for %s\n", rdev_get_name(rdev)))
@@ -1427,9 +1462,6 @@ static int _regulator_disable(struct regulator_dev *rdev,
                                             NULL);
                }
 
-               /* decrease our supplies ref count and disable if required */
-               *supply_rdev_ptr = rdev->supply;
-
                rdev->use_count = 0;
        } else if (rdev->use_count > 1) {
 
@@ -1440,6 +1472,7 @@ static int _regulator_disable(struct regulator_dev *rdev,
 
                rdev->use_count--;
        }
+
        return ret;
 }
 
@@ -1458,29 +1491,21 @@ static int _regulator_disable(struct regulator_dev *rdev,
 int regulator_disable(struct regulator *regulator)
 {
        struct regulator_dev *rdev = regulator->rdev;
-       struct regulator_dev *supply_rdev = NULL;
        int ret = 0;
 
        mutex_lock(&rdev->mutex);
-       ret = _regulator_disable(rdev, &supply_rdev);
+       ret = _regulator_disable(rdev);
        mutex_unlock(&rdev->mutex);
 
-       /* decrease our supplies ref count and disable if required */
-       while (supply_rdev != NULL) {
-               rdev = supply_rdev;
-
-               mutex_lock(&rdev->mutex);
-               _regulator_disable(rdev, &supply_rdev);
-               mutex_unlock(&rdev->mutex);
-       }
+       if (ret == 0 && rdev->supply)
+               regulator_disable(rdev->supply);
 
        return ret;
 }
 EXPORT_SYMBOL_GPL(regulator_disable);
 
 /* locks held by regulator_force_disable() */
-static int _regulator_force_disable(struct regulator_dev *rdev,
-               struct regulator_dev **supply_rdev_ptr)
+static int _regulator_force_disable(struct regulator_dev *rdev)
 {
        int ret = 0;
 
@@ -1497,10 +1522,6 @@ static int _regulator_force_disable(struct regulator_dev *rdev,
                        REGULATOR_EVENT_DISABLE, NULL);
        }
 
-       /* decrease our supplies ref count and disable if required */
-       *supply_rdev_ptr = rdev->supply;
-
-       rdev->use_count = 0;
        return ret;
 }
 
@@ -1516,16 +1537,16 @@ static int _regulator_force_disable(struct regulator_dev *rdev,
 int regulator_force_disable(struct regulator *regulator)
 {
        struct regulator_dev *rdev = regulator->rdev;
-       struct regulator_dev *supply_rdev = NULL;
        int ret;
 
        mutex_lock(&rdev->mutex);
        regulator->uA_load = 0;
-       ret = _regulator_force_disable(rdev, &supply_rdev);
+       ret = _regulator_force_disable(regulator->rdev);
        mutex_unlock(&rdev->mutex);
 
-       if (supply_rdev)
-               regulator_disable(get_device_regulator(rdev_get_dev(supply_rdev)));
+       if (rdev->supply)
+               while (rdev->open_count--)
+                       regulator_disable(rdev->supply);
 
        return ret;
 }
@@ -2136,7 +2157,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load)
        /* get input voltage */
        input_uV = 0;
        if (rdev->supply)
-               input_uV = _regulator_get_voltage(rdev->supply);
+               input_uV = regulator_get_voltage(rdev->supply);
        if (input_uV <= 0)
                input_uV = rdev->constraints->input_uV;
        if (input_uV <= 0) {
@@ -2206,17 +2227,8 @@ EXPORT_SYMBOL_GPL(regulator_unregister_notifier);
 static void _notifier_call_chain(struct regulator_dev *rdev,
                                  unsigned long event, void *data)
 {
-       struct regulator_dev *_rdev;
-
        /* call rdev chain first */
        blocking_notifier_call_chain(&rdev->notifier, event, NULL);
-
-       /* now notify regulator we supply */
-       list_for_each_entry(_rdev, &rdev->supply_list, slist) {
-               mutex_lock(&_rdev->mutex);
-               _notifier_call_chain(_rdev, event, data);
-               mutex_unlock(&_rdev->mutex);
-       }
 }
 
 /**
@@ -2264,6 +2276,13 @@ err:
 }
 EXPORT_SYMBOL_GPL(regulator_bulk_get);
 
+static void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
+{
+       struct regulator_bulk_data *bulk = data;
+
+       bulk->ret = regulator_enable(bulk->consumer);
+}
+
 /**
  * regulator_bulk_enable - enable multiple regulator consumers
  *
@@ -2279,21 +2298,33 @@ EXPORT_SYMBOL_GPL(regulator_bulk_get);
 int regulator_bulk_enable(int num_consumers,
                          struct regulator_bulk_data *consumers)
 {
+       LIST_HEAD(async_domain);
        int i;
-       int ret;
+       int ret = 0;
+
+       for (i = 0; i < num_consumers; i++)
+               async_schedule_domain(regulator_bulk_enable_async,
+                                     &consumers[i], &async_domain);
+
+       async_synchronize_full_domain(&async_domain);
 
+       /* If any consumer failed we need to unwind any that succeeded */
        for (i = 0; i < num_consumers; i++) {
-               ret = regulator_enable(consumers[i].consumer);
-               if (ret != 0)
+               if (consumers[i].ret != 0) {
+                       ret = consumers[i].ret;
                        goto err;
+               }
        }
 
        return 0;
 
 err:
-       pr_err("Failed to enable %s: %d\n", consumers[i].supply, ret);
-       for (--i; i >= 0; --i)
-               regulator_disable(consumers[i].consumer);
+       for (i = 0; i < num_consumers; i++)
+               if (consumers[i].ret == 0)
+                       regulator_disable(consumers[i].consumer);
+               else
+                       pr_err("Failed to enable %s: %d\n",
+                              consumers[i].supply, consumers[i].ret);
 
        return ret;
 }
@@ -2589,9 +2620,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
        rdev->owner = regulator_desc->owner;
        rdev->desc = regulator_desc;
        INIT_LIST_HEAD(&rdev->consumer_list);
-       INIT_LIST_HEAD(&rdev->supply_list);
        INIT_LIST_HEAD(&rdev->list);
-       INIT_LIST_HEAD(&rdev->slist);
        BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
 
        /* preform any regulator specific init */
@@ -2672,6 +2701,7 @@ unset_supplies:
        unset_regulator_supplies(rdev);
 
 scrub:
+       kfree(rdev->constraints);
        device_unregister(&rdev->dev);
        /* device core frees rdev */
        rdev = ERR_PTR(ret);
@@ -2703,7 +2733,7 @@ void regulator_unregister(struct regulator_dev *rdev)
        unset_regulator_supplies(rdev);
        list_del(&rdev->list);
        if (rdev->supply)
-               sysfs_remove_link(&rdev->dev.kobj, "supply");
+               regulator_put(rdev->supply);
        device_unregister(&rdev->dev);
        kfree(rdev->constraints);
        mutex_unlock(&regulator_list_mutex);
index c7410bde7b5d92ec128bbb79850c62e0e9495d87..f6ef6694ab9896687074c9224e4e60fea919acbc 100644 (file)
@@ -36,6 +36,29 @@ static struct regulator_desc dummy_desc = {
        .ops = &dummy_ops,
 };
 
+static int __devinit dummy_regulator_probe(struct platform_device *pdev)
+{
+       int ret;
+
+       dummy_regulator_rdev = regulator_register(&dummy_desc, NULL,
+                                                 &dummy_initdata, NULL);
+       if (IS_ERR(dummy_regulator_rdev)) {
+               ret = PTR_ERR(dummy_regulator_rdev);
+               pr_err("Failed to register regulator: %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static struct platform_driver dummy_regulator_driver = {
+       .probe          = dummy_regulator_probe,
+       .driver         = {
+               .name           = "reg-dummy",
+               .owner          = THIS_MODULE,
+       },
+};
+
 static struct platform_device *dummy_pdev;
 
 void __init regulator_dummy_init(void)
@@ -55,12 +78,9 @@ void __init regulator_dummy_init(void)
                return;
        }
 
-       dummy_regulator_rdev = regulator_register(&dummy_desc, NULL,
-                                                 &dummy_initdata, NULL);
-       if (IS_ERR(dummy_regulator_rdev)) {
-               ret = PTR_ERR(dummy_regulator_rdev);
-               pr_err("Failed to register regulator: %d\n", ret);
+       ret = platform_driver_register(&dummy_regulator_driver);
+       if (ret != 0) {
+               pr_err("Failed to register dummy regulator driver: %d\n", ret);
                platform_device_unregister(dummy_pdev);
-               return;
        }
 }
index 55dd4e6650db80caa02d42a61f7315b90473b809..66d2d60b436a3e7a28092d64a499fd203db764a5 100644 (file)
@@ -49,7 +49,6 @@
 #define TPS65911_REG_LDO7              11
 #define TPS65911_REG_LDO8              12
 
-#define TPS65910_NUM_REGULATOR         13
 #define TPS65910_SUPPLY_STATE_ENABLED  0x1
 
 /* supported VIO voltages in milivolts */
@@ -264,11 +263,12 @@ static struct tps_info tps65911_regs[] = {
 };
 
 struct tps65910_reg {
-       struct regulator_desc desc[TPS65910_NUM_REGULATOR];
+       struct regulator_desc *desc;
        struct tps65910 *mfd;
-       struct regulator_dev *rdev[TPS65910_NUM_REGULATOR];
-       struct tps_info *info[TPS65910_NUM_REGULATOR];
+       struct regulator_dev **rdev;
+       struct tps_info **info;
        struct mutex mutex;
+       int num_regulators;
        int mode;
        int  (*get_ctrl_reg)(int);
 };
@@ -759,8 +759,13 @@ static int tps65910_list_voltage_dcdc(struct regulator_dev *dev,
                mult = (selector / VDD1_2_NUM_VOLTS) + 1;
                volt = VDD1_2_MIN_VOLT +
                                (selector % VDD1_2_NUM_VOLTS) * VDD1_2_OFFSET;
+               break;
        case TPS65911_REG_VDDCTRL:
                volt = VDDCTRL_MIN_VOLT + (selector * VDDCTRL_OFFSET);
+               break;
+       default:
+               BUG();
+               return -EINVAL;
        }
 
        return  volt * 100 * mult;
@@ -897,16 +902,42 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
        switch(tps65910_chip_id(tps65910)) {
        case TPS65910:
                pmic->get_ctrl_reg = &tps65910_get_ctrl_register;
+               pmic->num_regulators = ARRAY_SIZE(tps65910_regs);
                info = tps65910_regs;
+               break;
        case TPS65911:
                pmic->get_ctrl_reg = &tps65911_get_ctrl_register;
+               pmic->num_regulators = ARRAY_SIZE(tps65911_regs);
                info = tps65911_regs;
+               break;
        default:
                pr_err("Invalid tps chip version\n");
+               kfree(pmic);
                return -ENODEV;
        }
 
-       for (i = 0; i < TPS65910_NUM_REGULATOR; i++, info++, reg_data++) {
+       pmic->desc = kcalloc(pmic->num_regulators,
+                       sizeof(struct regulator_desc), GFP_KERNEL);
+       if (!pmic->desc) {
+               err = -ENOMEM;
+               goto err_free_pmic;
+       }
+
+       pmic->info = kcalloc(pmic->num_regulators,
+                       sizeof(struct tps_info *), GFP_KERNEL);
+       if (!pmic->info) {
+               err = -ENOMEM;
+               goto err_free_desc;
+       }
+
+       pmic->rdev = kcalloc(pmic->num_regulators,
+                       sizeof(struct regulator_dev *), GFP_KERNEL);
+       if (!pmic->rdev) {
+               err = -ENOMEM;
+               goto err_free_info;
+       }
+
+       for (i = 0; i < pmic->num_regulators; i++, info++, reg_data++) {
                /* Register the regulators */
                pmic->info[i] = info;
 
@@ -938,7 +969,7 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
                                "failed to register %s regulator\n",
                                pdev->name);
                        err = PTR_ERR(rdev);
-                       goto err;
+                       goto err_unregister_regulator;
                }
 
                /* Save regulator for cleanup */
@@ -946,23 +977,31 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
        }
        return 0;
 
-err:
+err_unregister_regulator:
        while (--i >= 0)
                regulator_unregister(pmic->rdev[i]);
-
+       kfree(pmic->rdev);
+err_free_info:
+       kfree(pmic->info);
+err_free_desc:
+       kfree(pmic->desc);
+err_free_pmic:
        kfree(pmic);
        return err;
 }
 
 static int __devexit tps65910_remove(struct platform_device *pdev)
 {
-       struct tps65910_reg *tps65910_reg = platform_get_drvdata(pdev);
+       struct tps65910_reg *pmic = platform_get_drvdata(pdev);
        int i;
 
-       for (i = 0; i < TPS65910_NUM_REGULATOR; i++)
-               regulator_unregister(tps65910_reg->rdev[i]);
+       for (i = 0; i < pmic->num_regulators; i++)
+               regulator_unregister(pmic->rdev[i]);
 
-       kfree(tps65910_reg);
+       kfree(pmic->rdev);
+       kfree(pmic->info);
+       kfree(pmic->desc);
+       kfree(pmic);
        return 0;
 }
 
index 87fe0f75a56eed01375e0e2a393dbea6c1cd98b2..ee8747f4fa08b187ef2f79dbb51e3f69a770bc21 100644 (file)
@@ -835,8 +835,8 @@ static struct regulator_ops twlsmps_ops = {
                        remap_conf) \
                TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
                        remap_conf, TWL4030, twl4030fixed_ops)
-#define TWL6030_FIXED_LDO(label, offset, mVolts, num, turnon_delay) \
-               TWL_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
+#define TWL6030_FIXED_LDO(label, offset, mVolts, turnon_delay) \
+               TWL_FIXED_LDO(label, offset, mVolts, 0x0, turnon_delay, \
                        0x0, TWL6030, twl6030fixed_ops)
 
 #define TWL4030_ADJUSTABLE_LDO(label, offset, num, turnon_delay, remap_conf) { \
@@ -856,24 +856,22 @@ static struct regulator_ops twlsmps_ops = {
                }, \
        }
 
-#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num) { \
+#define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) { \
        .base = offset, \
-       .id = num, \
        .min_mV = min_mVolts, \
        .max_mV = max_mVolts, \
        .desc = { \
                .name = #label, \
                .id = TWL6030_REG_##label, \
-               .n_voltages = (max_mVolts - min_mVolts)/100, \
+               .n_voltages = (max_mVolts - min_mVolts)/100 + 1, \
                .ops = &twl6030ldo_ops, \
                .type = REGULATOR_VOLTAGE, \
                .owner = THIS_MODULE, \
                }, \
        }
 
-#define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts, num) { \
+#define TWL6025_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) { \
        .base = offset, \
-       .id = num, \
        .min_mV = min_mVolts, \
        .max_mV = max_mVolts, \
        .desc = { \
@@ -903,9 +901,8 @@ static struct regulator_ops twlsmps_ops = {
                }, \
        }
 
-#define TWL6030_FIXED_RESOURCE(label, offset, num, turnon_delay) { \
+#define TWL6030_FIXED_RESOURCE(label, offset, turnon_delay) { \
        .base = offset, \
-       .id = num, \
        .delay = turnon_delay, \
        .desc = { \
                .name = #label, \
@@ -916,9 +913,8 @@ static struct regulator_ops twlsmps_ops = {
                }, \
        }
 
-#define TWL6025_ADJUSTABLE_SMPS(label, offset, num) { \
+#define TWL6025_ADJUSTABLE_SMPS(label, offset) { \
        .base = offset, \
-       .id = num, \
        .min_mV = 600, \
        .max_mV = 2100, \
        .desc = { \
@@ -961,32 +957,32 @@ static struct twlreg_info twl_regs[] = {
        /* 6030 REG with base as PMC Slave Misc : 0x0030 */
        /* Turnon-delay and remap configuration values for 6030 are not
           verified since the specification is not public */
-       TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300, 1),
-       TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300, 2),
-       TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300, 3),
-       TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300, 4),
-       TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300, 5),
-       TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300, 7),
-       TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0),
-       TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0),
-       TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0),
-       TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0),
-       TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 48, 0),
+       TWL6030_ADJUSTABLE_LDO(VAUX1_6030, 0x54, 1000, 3300),
+       TWL6030_ADJUSTABLE_LDO(VAUX2_6030, 0x58, 1000, 3300),
+       TWL6030_ADJUSTABLE_LDO(VAUX3_6030, 0x5c, 1000, 3300),
+       TWL6030_ADJUSTABLE_LDO(VMMC, 0x68, 1000, 3300),
+       TWL6030_ADJUSTABLE_LDO(VPP, 0x6c, 1000, 3300),
+       TWL6030_ADJUSTABLE_LDO(VUSIM, 0x74, 1000, 3300),
+       TWL6030_FIXED_LDO(VANA, 0x50, 2100, 0),
+       TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 0),
+       TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 0),
+       TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 0),
+       TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 0),
 
        /* 6025 are renamed compared to 6030 versions */
-       TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300, 1),
-       TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300, 2),
-       TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300, 3),
-       TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300, 4),
-       TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300, 5),
-       TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300, 7),
-       TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300, 16),
-       TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300, 17),
-       TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300, 18),
-
-       TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34, 1),
-       TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10, 2),
-       TWL6025_ADJUSTABLE_SMPS(VIO, 0x16, 3),
+       TWL6025_ADJUSTABLE_LDO(LDO2, 0x54, 1000, 3300),
+       TWL6025_ADJUSTABLE_LDO(LDO4, 0x58, 1000, 3300),
+       TWL6025_ADJUSTABLE_LDO(LDO3, 0x5c, 1000, 3300),
+       TWL6025_ADJUSTABLE_LDO(LDO5, 0x68, 1000, 3300),
+       TWL6025_ADJUSTABLE_LDO(LDO1, 0x6c, 1000, 3300),
+       TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300),
+       TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300),
+       TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300),
+       TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300),
+
+       TWL6025_ADJUSTABLE_SMPS(SMPS3, 0x34),
+       TWL6025_ADJUSTABLE_SMPS(SMPS4, 0x10),
+       TWL6025_ADJUSTABLE_SMPS(VIO, 0x16),
 };
 
 static u8 twl_get_smps_offset(void)
index a0982e80985198004ae990218c38718d8616eec6..bd3531d8b2ac9364fb48c182c4947a00696d7c34 100644 (file)
@@ -267,23 +267,6 @@ static int wm831x_buckv_select_min_voltage(struct regulator_dev *rdev,
        return vsel;
 }
 
-static int wm831x_buckv_select_max_voltage(struct regulator_dev *rdev,
-                                          int min_uV, int max_uV)
-{
-       u16 vsel;
-
-       if (max_uV < 600000 || max_uV > 1800000)
-               return -EINVAL;
-
-       vsel = ((max_uV - 600000) / 12500) + 8;
-
-       if (wm831x_buckv_list_voltage(rdev, vsel) < min_uV ||
-           wm831x_buckv_list_voltage(rdev, vsel) < max_uV)
-               return -EINVAL;
-
-       return vsel;
-}
-
 static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state)
 {
        struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
@@ -338,28 +321,23 @@ static int wm831x_buckv_set_voltage(struct regulator_dev *rdev,
        if (ret < 0)
                return ret;
 
-       /* Set the high voltage as the DVS voltage.  This is optimised
-        * for CPUfreq usage, most processors will keep the maximum
-        * voltage constant and lower the minimum with the frequency. */
-       vsel = wm831x_buckv_select_max_voltage(rdev, min_uV, max_uV);
-       if (vsel < 0) {
-               /* This should never happen - at worst the same vsel
-                * should be chosen */
-               WARN_ON(vsel < 0);
-               return 0;
+       /*
+        * If this VSEL is higher than the last one we've seen then
+        * remember it as the DVS VSEL.  This is optimised for CPUfreq
+        * usage where we want to get to the highest voltage very
+        * quickly.
+        */
+       if (vsel > dcdc->dvs_vsel) {
+               ret = wm831x_set_bits(wm831x, dvs_reg,
+                                     WM831X_DC1_DVS_VSEL_MASK,
+                                     dcdc->dvs_vsel);
+               if (ret == 0)
+                       dcdc->dvs_vsel = vsel;
+               else
+                       dev_warn(wm831x->dev,
+                                "Failed to set DCDC DVS VSEL: %d\n", ret);
        }
 
-       /* Don't bother if it's the same VSEL we're already using */
-       if (vsel == dcdc->on_vsel)
-               return 0;
-
-       ret = wm831x_set_bits(wm831x, dvs_reg, WM831X_DC1_DVS_VSEL_MASK, vsel);
-       if (ret == 0)
-               dcdc->dvs_vsel = vsel;
-       else
-               dev_warn(wm831x->dev, "Failed to set DCDC DVS VSEL: %d\n",
-                        ret);
-
        return 0;
 }
 
@@ -456,27 +434,6 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
        if (!pdata || !pdata->dvs_gpio)
                return;
 
-       switch (pdata->dvs_control_src) {
-       case 1:
-               ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT;
-               break;
-       case 2:
-               ctrl = 3 << WM831X_DC1_DVS_SRC_SHIFT;
-               break;
-       default:
-               dev_err(wm831x->dev, "Invalid DVS control source %d for %s\n",
-                       pdata->dvs_control_src, dcdc->name);
-               return;
-       }
-
-       ret = wm831x_set_bits(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL,
-                             WM831X_DC1_DVS_SRC_MASK, ctrl);
-       if (ret < 0) {
-               dev_err(wm831x->dev, "Failed to set %s DVS source: %d\n",
-                       dcdc->name, ret);
-               return;
-       }
-
        ret = gpio_request(pdata->dvs_gpio, "DCDC DVS");
        if (ret < 0) {
                dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n",
@@ -498,17 +455,57 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
        }
 
        dcdc->dvs_gpio = pdata->dvs_gpio;
+
+       switch (pdata->dvs_control_src) {
+       case 1:
+               ctrl = 2 << WM831X_DC1_DVS_SRC_SHIFT;
+               break;
+       case 2:
+               ctrl = 3 << WM831X_DC1_DVS_SRC_SHIFT;
+               break;
+       default:
+               dev_err(wm831x->dev, "Invalid DVS control source %d for %s\n",
+                       pdata->dvs_control_src, dcdc->name);
+               return;
+       }
+
+       /* If DVS_VSEL is set to the minimum value then raise it to ON_VSEL
+        * to make bootstrapping a bit smoother.
+        */
+       if (!dcdc->dvs_vsel) {
+               ret = wm831x_set_bits(wm831x,
+                                     dcdc->base + WM831X_DCDC_DVS_CONTROL,
+                                     WM831X_DC1_DVS_VSEL_MASK, dcdc->on_vsel);
+               if (ret == 0)
+                       dcdc->dvs_vsel = dcdc->on_vsel;
+               else
+                       dev_warn(wm831x->dev, "Failed to set DVS_VSEL: %d\n",
+                                ret);
+       }
+
+       ret = wm831x_set_bits(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL,
+                             WM831X_DC1_DVS_SRC_MASK, ctrl);
+       if (ret < 0) {
+               dev_err(wm831x->dev, "Failed to set %s DVS source: %d\n",
+                       dcdc->name, ret);
+       }
 }
 
 static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
-       int id = pdev->id % ARRAY_SIZE(pdata->dcdc);
+       int id;
        struct wm831x_dcdc *dcdc;
        struct resource *res;
        int ret, irq;
 
+       if (pdata && pdata->wm831x_num)
+               id = (pdata->wm831x_num * 10) + 1;
+       else
+               id = 0;
+       id = pdev->id - id;
+
        dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1);
 
        if (pdata == NULL || pdata->dcdc[id] == NULL)
@@ -545,7 +542,7 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
        }
        dcdc->on_vsel = ret & WM831X_DC1_ON_VSEL_MASK;
 
-       ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_ON_CONFIG);
+       ret = wm831x_reg_read(wm831x, dcdc->base + WM831X_DCDC_DVS_CONTROL);
        if (ret < 0) {
                dev_err(wm831x->dev, "Failed to read DVS VSEL: %d\n", ret);
                goto err;
@@ -709,11 +706,17 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
-       int id = pdev->id % ARRAY_SIZE(pdata->dcdc);
+       int id;
        struct wm831x_dcdc *dcdc;
        struct resource *res;
        int ret, irq;
 
+       if (pdata && pdata->wm831x_num)
+               id = (pdata->wm831x_num * 10) + 1;
+       else
+               id = 0;
+       id = pdev->id - id;
+
        dev_dbg(&pdev->dev, "Probing DCDC%d\n", id + 1);
 
        if (pdata == NULL || pdata->dcdc[id] == NULL)
@@ -1046,3 +1049,4 @@ MODULE_DESCRIPTION("WM831x DC-DC convertor driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:wm831x-buckv");
 MODULE_ALIAS("platform:wm831x-buckp");
+MODULE_ALIAS("platform:wm831x-epe");
index 2220cf8defb1625a1c161f026cf5722fd7356ea2..6709710a059e6e78c2267c376903b04ea26820fa 100644 (file)
@@ -310,11 +310,17 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
-       int id = pdev->id % ARRAY_SIZE(pdata->ldo);
+       int id;
        struct wm831x_ldo *ldo;
        struct resource *res;
        int ret, irq;
 
+       if (pdata && pdata->wm831x_num)
+               id = (pdata->wm831x_num * 10) + 1;
+       else
+               id = 0;
+       id = pdev->id - id;
+
        dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
 
        if (pdata == NULL || pdata->ldo[id] == NULL)
@@ -574,11 +580,17 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
-       int id = pdev->id % ARRAY_SIZE(pdata->ldo);
+       int id;
        struct wm831x_ldo *ldo;
        struct resource *res;
        int ret, irq;
 
+       if (pdata && pdata->wm831x_num)
+               id = (pdata->wm831x_num * 10) + 1;
+       else
+               id = 0;
+       id = pdev->id - id;
+
        dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
 
        if (pdata == NULL || pdata->ldo[id] == NULL)
@@ -764,11 +776,18 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
-       int id = pdev->id % ARRAY_SIZE(pdata->ldo);
+       int id;
        struct wm831x_ldo *ldo;
        struct resource *res;
        int ret;
 
+       if (pdata && pdata->wm831x_num)
+               id = (pdata->wm831x_num * 10) + 1;
+       else
+               id = 0;
+       id = pdev->id - id;
+
+
        dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
 
        if (pdata == NULL || pdata->ldo[id] == NULL)
index 35b2958d51064a84950deef280a14603b1e4e0da..1a6a690f24dbecc415c7c7f9c5006573a767ef0b 100644 (file)
@@ -43,7 +43,7 @@ static int wm8994_ldo_enable(struct regulator_dev *rdev)
        if (!ldo->enable)
                return 0;
 
-       gpio_set_value(ldo->enable, 1);
+       gpio_set_value_cansleep(ldo->enable, 1);
        ldo->is_enabled = true;
 
        return 0;
@@ -57,7 +57,7 @@ static int wm8994_ldo_disable(struct regulator_dev *rdev)
        if (!ldo->enable)
                return -EINVAL;
 
-       gpio_set_value(ldo->enable, 0);
+       gpio_set_value_cansleep(ldo->enable, 0);
        ldo->is_enabled = false;
 
        return 0;
index 9e87c1cb7270ff458833471b55ead7e3a440c1a0..26f6ea4444e39fedda935b5505439a6de3301f41 100644 (file)
@@ -122,6 +122,9 @@ struct regulator;
 struct regulator_bulk_data {
        const char *supply;
        struct regulator *consumer;
+
+       /* Internal use */
+       int ret;
 };
 
 #if defined(CONFIG_REGULATOR)
index 6c433b89c80d617da2902caeffa74280fdaa9efd..1a80bc77517d03870ea9f34a6d2c317953445bc4 100644 (file)
@@ -188,18 +188,16 @@ struct regulator_dev {
 
        /* lists we belong to */
        struct list_head list; /* list of all regulators */
-       struct list_head slist; /* list of supplied regulators */
 
        /* lists we own */
        struct list_head consumer_list; /* consumers we supply */
-       struct list_head supply_list; /* regulators we supply */
 
        struct blocking_notifier_head notifier;
        struct mutex mutex; /* consumer lock */
        struct module *owner;
        struct device dev;
        struct regulation_constraints *constraints;
-       struct regulator_dev *supply;   /* for tree */
+       struct regulator *supply;       /* for tree */
 
        void *reg_data;         /* regulator_dev data */