diff options
-rw-r--r-- | drivers/regulator/core.c | 92 | ||||
-rw-r--r-- | include/linux/regulator/machine.h | 2 |
2 files changed, 94 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 @@ | |||
28 | static DEFINE_MUTEX(regulator_list_mutex); | 28 | static DEFINE_MUTEX(regulator_list_mutex); |
29 | static LIST_HEAD(regulator_list); | 29 | static LIST_HEAD(regulator_list); |
30 | static LIST_HEAD(regulator_map_list); | 30 | static LIST_HEAD(regulator_map_list); |
31 | static int has_full_constraints; | ||
31 | 32 | ||
32 | /* | 33 | /* |
33 | * struct regulator_map | 34 | * struct regulator_map |
@@ -2143,6 +2144,23 @@ out: | |||
2143 | EXPORT_SYMBOL_GPL(regulator_suspend_prepare); | 2144 | EXPORT_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 | */ | ||
2157 | void regulator_has_full_constraints(void) | ||
2158 | { | ||
2159 | has_full_constraints = 1; | ||
2160 | } | ||
2161 | EXPORT_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 */ |
2211 | core_initcall(regulator_init); | 2229 | core_initcall(regulator_init); |
2230 | |||
2231 | static 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(®ulator_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, ®ulator_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 | |||
2295 | unlock: | ||
2296 | mutex_unlock(&rdev->mutex); | ||
2297 | } | ||
2298 | |||
2299 | mutex_unlock(®ulator_list_mutex); | ||
2300 | |||
2301 | return 0; | ||
2302 | } | ||
2303 | late_initcall(regulator_init_complete); | ||
diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index 5de7aa3b02a6..bac64fa390f2 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h | |||
@@ -166,4 +166,6 @@ struct regulator_init_data { | |||
166 | 166 | ||
167 | int regulator_suspend_prepare(suspend_state_t state); | 167 | int regulator_suspend_prepare(suspend_state_t state); |
168 | 168 | ||
169 | void regulator_has_full_constraints(void); | ||
170 | |||
169 | #endif | 171 | #endif |