From 5e09e69db23106a0494aa32017f5c82484659fe3 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 21 Dec 2009 12:21:52 +0000 Subject: [PATCH] --- yaml --- r: 185657 b: refs/heads/master c: 31aae2beeb3d601d556b6a8c39085940ad1e9f42 h: refs/heads/master i: 185655: 4daa343ac8cb36c8f3522a67c729223cebbe0d6d v: v3 --- [refs] | 2 +- trunk/drivers/regulator/core.c | 41 ++++++++++++++++++++++---- trunk/include/linux/regulator/driver.h | 6 ++++ 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/[refs] b/[refs] index ec22171db834..aeefb489d8bd 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 84b6826306119dc3c41ef9d7ed6c408112f63301 +refs/heads/master: 31aae2beeb3d601d556b6a8c39085940ad1e9f42 diff --git a/trunk/drivers/regulator/core.c b/trunk/drivers/regulator/core.c index 6d2ce8a05331..ca8e1642538b 100644 --- a/trunk/drivers/regulator/core.c +++ b/trunk/drivers/regulator/core.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -1084,6 +1085,13 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, return NULL; } +static int _regulator_get_enable_time(struct regulator_dev *rdev) +{ + if (!rdev->desc->ops->enable_time) + return 0; + return rdev->desc->ops->enable_time(rdev); +} + /* Internal regulator request function */ static struct regulator *_regulator_get(struct device *dev, const char *id, int exclusive) @@ -1251,7 +1259,7 @@ static int _regulator_can_change_status(struct regulator_dev *rdev) /* locks held by regulator_enable() */ static int _regulator_enable(struct regulator_dev *rdev) { - int ret; + int ret, delay; /* do we need to enable the supply regulator first */ if (rdev->supply) { @@ -1275,13 +1283,34 @@ static int _regulator_enable(struct regulator_dev *rdev) if (!_regulator_can_change_status(rdev)) return -EPERM; - if (rdev->desc->ops->enable) { - ret = rdev->desc->ops->enable(rdev); - if (ret < 0) - return ret; - } else { + if (!rdev->desc->ops->enable) return -EINVAL; + + /* Query before enabling in case configuration + * dependant. */ + ret = _regulator_get_enable_time(rdev); + if (ret >= 0) { + delay = ret; + } else { + printk(KERN_WARNING + "%s: enable_time() failed for %s: %d\n", + __func__, rdev_get_name(rdev), + ret); + delay = 0; } + + /* Allow the regulator to ramp; it would be useful + * to extend this for bulk operations so that the + * regulators can ramp together. */ + ret = rdev->desc->ops->enable(rdev); + if (ret < 0) + return ret; + + if (delay >= 1000) + mdelay(delay / 1000); + else if (delay) + udelay(delay); + } else if (ret < 0) { printk(KERN_ERR "%s: is_enabled() failed for %s: %d\n", __func__, rdev_get_name(rdev), ret); diff --git a/trunk/include/linux/regulator/driver.h b/trunk/include/linux/regulator/driver.h index 31f2055eae28..592cd7c642c2 100644 --- a/trunk/include/linux/regulator/driver.h +++ b/trunk/include/linux/regulator/driver.h @@ -58,6 +58,9 @@ enum regulator_status { * @get_optimum_mode: Get the most efficient operating mode for the regulator * when running with the specified parameters. * + * @enable_time: Time taken for the regulator voltage output voltage to + * stabalise after being enabled, in microseconds. + * * @set_suspend_voltage: Set the voltage for the regulator when the system * is suspended. * @set_suspend_enable: Mark the regulator as enabled when the system is @@ -93,6 +96,9 @@ struct regulator_ops { int (*set_mode) (struct regulator_dev *, unsigned int mode); unsigned int (*get_mode) (struct regulator_dev *); + /* Time taken to enable the regulator */ + int (*enable_time) (struct regulator_dev *); + /* report regulator status ... most other accessors report * control inputs, this reports results of combining inputs * from Linux (and other sources) with the actual load.