aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2009-03-16 15:36:34 -0400
committerLiam Girdwood <lrg@slimlogic.co.uk>2009-03-31 04:56:29 -0400
commitca7255614e0861e36480103f4a402a115803d7b5 (patch)
treebf66ae726a640b95841578de070a855e7744840e /drivers
parent50f075963f127d713ff0c30359baefc0f89d9ae2 (diff)
regulator: Support disabling of unused regulators by machines
At present it is not possible for machine constraints to disable regulators which have been left on when the system starts, for example as a result of fixed default configurations in hardware. This means that power may be wasted by these regulators if they are not in use. Provide intial support for this with a late_initcall which will disable any unused regulators if the machine has enabled this feature by calling regulator_has_full_constraints(). If this has not been called then print a warning to encourage users to fully specify their constraints so that we can change this to be the default behaviour in future. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/regulator/core.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 8588a2490e0a..01f7702a805d 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -28,6 +28,7 @@
28static DEFINE_MUTEX(regulator_list_mutex); 28static DEFINE_MUTEX(regulator_list_mutex);
29static LIST_HEAD(regulator_list); 29static LIST_HEAD(regulator_list);
30static LIST_HEAD(regulator_map_list); 30static LIST_HEAD(regulator_map_list);
31static int has_full_constraints;
31 32
32/* 33/*
33 * struct regulator_map 34 * struct regulator_map
@@ -2143,6 +2144,23 @@ out:
2143EXPORT_SYMBOL_GPL(regulator_suspend_prepare); 2144EXPORT_SYMBOL_GPL(regulator_suspend_prepare);
2144 2145
2145/** 2146/**
2147 * regulator_has_full_constraints - the system has fully specified constraints
2148 *
2149 * Calling this function will cause the regulator API to disable all
2150 * regulators which have a zero use count and don't have an always_on
2151 * constraint in a late_initcall.
2152 *
2153 * The intention is that this will become the default behaviour in a
2154 * future kernel release so users are encouraged to use this facility
2155 * now.
2156 */
2157void regulator_has_full_constraints(void)
2158{
2159 has_full_constraints = 1;
2160}
2161EXPORT_SYMBOL_GPL(regulator_has_full_constraints);
2162
2163/**
2146 * rdev_get_drvdata - get rdev regulator driver data 2164 * rdev_get_drvdata - get rdev regulator driver data
2147 * @rdev: regulator 2165 * @rdev: regulator
2148 * 2166 *
@@ -2209,3 +2227,77 @@ static int __init regulator_init(void)
2209 2227
2210/* init early to allow our consumers to complete system booting */ 2228/* init early to allow our consumers to complete system booting */
2211core_initcall(regulator_init); 2229core_initcall(regulator_init);
2230
2231static int __init regulator_init_complete(void)
2232{
2233 struct regulator_dev *rdev;
2234 struct regulator_ops *ops;
2235 struct regulation_constraints *c;
2236 int enabled, ret;
2237 const char *name;
2238
2239 mutex_lock(&regulator_list_mutex);
2240
2241 /* If we have a full configuration then disable any regulators
2242 * which are not in use or always_on. This will become the
2243 * default behaviour in the future.
2244 */
2245 list_for_each_entry(rdev, &regulator_list, list) {
2246 ops = rdev->desc->ops;
2247 c = rdev->constraints;
2248
2249 if (c->name)
2250 name = c->name;
2251 else if (rdev->desc->name)
2252 name = rdev->desc->name;
2253 else
2254 name = "regulator";
2255
2256 if (!ops->disable || c->always_on)
2257 continue;
2258
2259 mutex_lock(&rdev->mutex);
2260
2261 if (rdev->use_count)
2262 goto unlock;
2263
2264 /* If we can't read the status assume it's on. */
2265 if (ops->is_enabled)
2266 enabled = ops->is_enabled(rdev);
2267 else
2268 enabled = 1;
2269
2270 if (!enabled)
2271 goto unlock;
2272
2273 if (has_full_constraints) {
2274 /* We log since this may kill the system if it
2275 * goes wrong. */
2276 printk(KERN_INFO "%s: disabling %s\n",
2277 __func__, name);
2278 ret = ops->disable(rdev);
2279 if (ret != 0) {
2280 printk(KERN_ERR
2281 "%s: couldn't disable %s: %d\n",
2282 __func__, name, ret);
2283 }
2284 } else {
2285 /* The intention is that in future we will
2286 * assume that full constraints are provided
2287 * so warn even if we aren't going to do
2288 * anything here.
2289 */
2290 printk(KERN_WARNING
2291 "%s: incomplete constraints, leaving %s on\n",
2292 __func__, name);
2293 }
2294
2295unlock:
2296 mutex_unlock(&rdev->mutex);
2297 }
2298
2299 mutex_unlock(&regulator_list_mutex);
2300
2301 return 0;
2302}
2303late_initcall(regulator_init_complete);