blob: da1d52576ec9c7e1f41d30396fa851125f3b774e [file] [log] [blame]
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001/*
2 * drivers/base/power/domain.c - Common code related to device power domains.
3 *
4 * Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Renesas Electronics Corp.
5 *
6 * This file is released under the GPLv2.
7 */
8
9#include <linux/init.h>
10#include <linux/kernel.h>
11#include <linux/io.h>
12#include <linux/pm_runtime.h>
13#include <linux/pm_domain.h>
Rafael J. Wysocki6ff7bb0d02012-05-01 21:34:07 +020014#include <linux/pm_qos.h>
Rafael J. Wysockif7218892011-07-01 22:12:45 +020015#include <linux/slab.h>
16#include <linux/err.h>
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +020017#include <linux/sched.h>
18#include <linux/suspend.h>
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +010019#include <linux/export.h>
20
21#define GENPD_DEV_CALLBACK(genpd, type, callback, dev) \
22({ \
23 type (*__routine)(struct device *__d); \
24 type __ret = (type)0; \
25 \
26 __routine = genpd->dev_ops.callback; \
27 if (__routine) { \
28 __ret = __routine(dev); \
29 } else { \
30 __routine = dev_gpd_data(dev)->ops.callback; \
31 if (__routine) \
32 __ret = __routine(dev); \
33 } \
34 __ret; \
35})
Rafael J. Wysockif7218892011-07-01 22:12:45 +020036
Rafael J. Wysocki0140d8b2011-12-01 00:02:17 +010037#define GENPD_DEV_TIMED_CALLBACK(genpd, type, callback, dev, field, name) \
38({ \
39 ktime_t __start = ktime_get(); \
40 type __retval = GENPD_DEV_CALLBACK(genpd, type, callback, dev); \
41 s64 __elapsed = ktime_to_ns(ktime_sub(ktime_get(), __start)); \
Rafael J. Wysocki6ff7bb0d02012-05-01 21:34:07 +020042 struct gpd_timing_data *__td = &dev_gpd_data(dev)->td; \
43 if (!__retval && __elapsed > __td->field) { \
44 __td->field = __elapsed; \
Rafael J. Wysocki0140d8b2011-12-01 00:02:17 +010045 dev_warn(dev, name " latency exceeded, new value %lld ns\n", \
46 __elapsed); \
Rafael J. Wysocki6ff7bb0d02012-05-01 21:34:07 +020047 genpd->max_off_time_changed = true; \
48 __td->constraint_changed = true; \
Rafael J. Wysocki0140d8b2011-12-01 00:02:17 +010049 } \
50 __retval; \
51})
52
Rafael J. Wysocki5125bbf2011-07-13 12:31:52 +020053static LIST_HEAD(gpd_list);
54static DEFINE_MUTEX(gpd_list_lock);
55
Rafael J. Wysocki52480512011-07-01 22:13:10 +020056#ifdef CONFIG_PM
57
Rafael J. Wysockib02c9992011-12-01 00:02:05 +010058struct generic_pm_domain *dev_to_genpd(struct device *dev)
Rafael J. Wysocki52480512011-07-01 22:13:10 +020059{
60 if (IS_ERR_OR_NULL(dev->pm_domain))
61 return ERR_PTR(-EINVAL);
62
Rafael J. Wysocki596ba342011-07-01 22:13:19 +020063 return pd_to_genpd(dev->pm_domain);
Rafael J. Wysocki52480512011-07-01 22:13:10 +020064}
Rafael J. Wysockif7218892011-07-01 22:12:45 +020065
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +010066static int genpd_stop_dev(struct generic_pm_domain *genpd, struct device *dev)
67{
Rafael J. Wysocki0140d8b2011-12-01 00:02:17 +010068 return GENPD_DEV_TIMED_CALLBACK(genpd, int, stop, dev,
69 stop_latency_ns, "stop");
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +010070}
71
72static int genpd_start_dev(struct generic_pm_domain *genpd, struct device *dev)
73{
Rafael J. Wysocki0140d8b2011-12-01 00:02:17 +010074 return GENPD_DEV_TIMED_CALLBACK(genpd, int, start, dev,
75 start_latency_ns, "start");
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +010076}
77
Rafael J. Wysockiecf00472011-11-27 13:11:44 +010078static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev)
79{
Rafael J. Wysocki0140d8b2011-12-01 00:02:17 +010080 return GENPD_DEV_TIMED_CALLBACK(genpd, int, save_state, dev,
81 save_state_latency_ns, "state save");
Rafael J. Wysockiecf00472011-11-27 13:11:44 +010082}
83
84static int genpd_restore_dev(struct generic_pm_domain *genpd, struct device *dev)
85{
Rafael J. Wysocki0140d8b2011-12-01 00:02:17 +010086 return GENPD_DEV_TIMED_CALLBACK(genpd, int, restore_state, dev,
87 restore_state_latency_ns,
88 "state restore");
Rafael J. Wysockiecf00472011-11-27 13:11:44 +010089}
90
Rafael J. Wysockic4bb3162011-08-08 23:43:04 +020091static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd)
Rafael J. Wysockif7218892011-07-01 22:12:45 +020092{
Rafael J. Wysockic4bb3162011-08-08 23:43:04 +020093 bool ret = false;
94
95 if (!WARN_ON(atomic_read(&genpd->sd_count) == 0))
96 ret = !!atomic_dec_and_test(&genpd->sd_count);
97
98 return ret;
99}
100
101static void genpd_sd_counter_inc(struct generic_pm_domain *genpd)
102{
103 atomic_inc(&genpd->sd_count);
104 smp_mb__after_atomic_inc();
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200105}
106
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200107static void genpd_acquire_lock(struct generic_pm_domain *genpd)
108{
109 DEFINE_WAIT(wait);
110
111 mutex_lock(&genpd->lock);
112 /*
113 * Wait for the domain to transition into either the active,
114 * or the power off state.
115 */
116 for (;;) {
117 prepare_to_wait(&genpd->status_wait_queue, &wait,
118 TASK_UNINTERRUPTIBLE);
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200119 if (genpd->status == GPD_STATE_ACTIVE
120 || genpd->status == GPD_STATE_POWER_OFF)
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200121 break;
122 mutex_unlock(&genpd->lock);
123
124 schedule();
125
126 mutex_lock(&genpd->lock);
127 }
128 finish_wait(&genpd->status_wait_queue, &wait);
129}
130
131static void genpd_release_lock(struct generic_pm_domain *genpd)
132{
133 mutex_unlock(&genpd->lock);
134}
135
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200136static void genpd_set_active(struct generic_pm_domain *genpd)
137{
138 if (genpd->resume_count == 0)
139 genpd->status = GPD_STATE_ACTIVE;
140}
141
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200142/**
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +0200143 * __pm_genpd_poweron - Restore power to a given PM domain and its masters.
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200144 * @genpd: PM domain to power up.
145 *
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +0200146 * Restore power to @genpd and all of its masters so that it is possible to
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200147 * resume a device belonging to it.
148 */
Rafael J. Wysocki3f241772011-08-08 23:43:29 +0200149int __pm_genpd_poweron(struct generic_pm_domain *genpd)
150 __releases(&genpd->lock) __acquires(&genpd->lock)
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200151{
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +0200152 struct gpd_link *link;
Rafael J. Wysocki3f241772011-08-08 23:43:29 +0200153 DEFINE_WAIT(wait);
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200154 int ret = 0;
155
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +0200156 /* If the domain's master is being waited for, we have to wait too. */
Rafael J. Wysocki3f241772011-08-08 23:43:29 +0200157 for (;;) {
158 prepare_to_wait(&genpd->status_wait_queue, &wait,
159 TASK_UNINTERRUPTIBLE);
Rafael J. Wysocki17877eb2011-08-08 23:43:50 +0200160 if (genpd->status != GPD_STATE_WAIT_MASTER)
Rafael J. Wysocki3f241772011-08-08 23:43:29 +0200161 break;
162 mutex_unlock(&genpd->lock);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200163
Rafael J. Wysocki3f241772011-08-08 23:43:29 +0200164 schedule();
Rafael J. Wysocki9e08cf42011-08-08 23:43:22 +0200165
Rafael J. Wysocki3f241772011-08-08 23:43:29 +0200166 mutex_lock(&genpd->lock);
167 }
168 finish_wait(&genpd->status_wait_queue, &wait);
169
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200170 if (genpd->status == GPD_STATE_ACTIVE
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200171 || (genpd->prepared_count > 0 && genpd->suspend_power_off))
Rafael J. Wysocki3f241772011-08-08 23:43:29 +0200172 return 0;
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200173
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200174 if (genpd->status != GPD_STATE_POWER_OFF) {
175 genpd_set_active(genpd);
Rafael J. Wysocki3f241772011-08-08 23:43:29 +0200176 return 0;
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200177 }
178
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +0200179 /*
180 * The list is guaranteed not to change while the loop below is being
181 * executed, unless one of the masters' .power_on() callbacks fiddles
182 * with it.
183 */
184 list_for_each_entry(link, &genpd->slave_links, slave_node) {
185 genpd_sd_counter_inc(link->master);
Rafael J. Wysocki17877eb2011-08-08 23:43:50 +0200186 genpd->status = GPD_STATE_WAIT_MASTER;
Rafael J. Wysocki3c07cbc2011-08-08 23:43:14 +0200187
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200188 mutex_unlock(&genpd->lock);
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200189
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +0200190 ret = pm_genpd_poweron(link->master);
Rafael J. Wysocki9e08cf42011-08-08 23:43:22 +0200191
192 mutex_lock(&genpd->lock);
193
Rafael J. Wysocki3f241772011-08-08 23:43:29 +0200194 /*
195 * The "wait for parent" status is guaranteed not to change
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +0200196 * while the master is powering on.
Rafael J. Wysocki3f241772011-08-08 23:43:29 +0200197 */
198 genpd->status = GPD_STATE_POWER_OFF;
199 wake_up_all(&genpd->status_wait_queue);
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +0200200 if (ret) {
201 genpd_sd_counter_dec(link->master);
Rafael J. Wysocki9e08cf42011-08-08 23:43:22 +0200202 goto err;
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +0200203 }
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200204 }
205
Rafael J. Wysocki9e08cf42011-08-08 23:43:22 +0200206 if (genpd->power_on) {
Rafael J. Wysocki0140d8b2011-12-01 00:02:17 +0100207 ktime_t time_start = ktime_get();
208 s64 elapsed_ns;
209
Rafael J. Wysockife202fd2011-08-05 21:45:11 +0200210 ret = genpd->power_on(genpd);
Rafael J. Wysocki9e08cf42011-08-08 23:43:22 +0200211 if (ret)
212 goto err;
Rafael J. Wysocki0140d8b2011-12-01 00:02:17 +0100213
214 elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
Rafael J. Wysockie84b2c22011-12-06 22:19:54 +0100215 if (elapsed_ns > genpd->power_on_latency_ns) {
Rafael J. Wysocki0140d8b2011-12-01 00:02:17 +0100216 genpd->power_on_latency_ns = elapsed_ns;
Rafael J. Wysocki6ff7bb0d02012-05-01 21:34:07 +0200217 genpd->max_off_time_changed = true;
Rafael J. Wysockie84b2c22011-12-06 22:19:54 +0100218 if (genpd->name)
219 pr_warning("%s: Power-on latency exceeded, "
220 "new value %lld ns\n", genpd->name,
221 elapsed_ns);
222 }
Rafael J. Wysocki3c07cbc2011-08-08 23:43:14 +0200223 }
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200224
Rafael J. Wysocki9e08cf42011-08-08 23:43:22 +0200225 genpd_set_active(genpd);
226
Rafael J. Wysocki3f241772011-08-08 23:43:29 +0200227 return 0;
Rafael J. Wysocki9e08cf42011-08-08 23:43:22 +0200228
229 err:
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +0200230 list_for_each_entry_continue_reverse(link, &genpd->slave_links, slave_node)
231 genpd_sd_counter_dec(link->master);
Rafael J. Wysocki9e08cf42011-08-08 23:43:22 +0200232
Rafael J. Wysocki3f241772011-08-08 23:43:29 +0200233 return ret;
234}
235
236/**
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +0200237 * pm_genpd_poweron - Restore power to a given PM domain and its masters.
Rafael J. Wysocki3f241772011-08-08 23:43:29 +0200238 * @genpd: PM domain to power up.
239 */
240int pm_genpd_poweron(struct generic_pm_domain *genpd)
241{
242 int ret;
243
244 mutex_lock(&genpd->lock);
245 ret = __pm_genpd_poweron(genpd);
246 mutex_unlock(&genpd->lock);
247 return ret;
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200248}
249
250#endif /* CONFIG_PM */
251
252#ifdef CONFIG_PM_RUNTIME
253
Rafael J. Wysocki6ff7bb0d02012-05-01 21:34:07 +0200254static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
255 unsigned long val, void *ptr)
256{
257 struct generic_pm_domain_data *gpd_data;
258 struct device *dev;
259
260 gpd_data = container_of(nb, struct generic_pm_domain_data, nb);
261
262 mutex_lock(&gpd_data->lock);
263 dev = gpd_data->base.dev;
264 if (!dev) {
265 mutex_unlock(&gpd_data->lock);
266 return NOTIFY_DONE;
267 }
268 mutex_unlock(&gpd_data->lock);
269
270 for (;;) {
271 struct generic_pm_domain *genpd;
272 struct pm_domain_data *pdd;
273
274 spin_lock_irq(&dev->power.lock);
275
276 pdd = dev->power.subsys_data ?
277 dev->power.subsys_data->domain_data : NULL;
278 if (pdd) {
279 to_gpd_data(pdd)->td.constraint_changed = true;
280 genpd = dev_to_genpd(dev);
281 } else {
282 genpd = ERR_PTR(-ENODATA);
283 }
284
285 spin_unlock_irq(&dev->power.lock);
286
287 if (!IS_ERR(genpd)) {
288 mutex_lock(&genpd->lock);
289 genpd->max_off_time_changed = true;
290 mutex_unlock(&genpd->lock);
291 }
292
293 dev = dev->parent;
294 if (!dev || dev->power.ignore_children)
295 break;
296 }
297
298 return NOTIFY_DONE;
299}
300
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200301/**
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200302 * __pm_genpd_save_device - Save the pre-suspend state of a device.
Rafael J. Wysocki4605ab62011-08-25 15:34:12 +0200303 * @pdd: Domain data of the device to save the state of.
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200304 * @genpd: PM domain the device belongs to.
305 */
Rafael J. Wysocki4605ab62011-08-25 15:34:12 +0200306static int __pm_genpd_save_device(struct pm_domain_data *pdd,
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200307 struct generic_pm_domain *genpd)
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200308 __releases(&genpd->lock) __acquires(&genpd->lock)
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200309{
Rafael J. Wysockicd0ea672011-09-26 20:22:02 +0200310 struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
Rafael J. Wysocki4605ab62011-08-25 15:34:12 +0200311 struct device *dev = pdd->dev;
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200312 int ret = 0;
313
Rafael J. Wysockicd0ea672011-09-26 20:22:02 +0200314 if (gpd_data->need_restore)
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200315 return 0;
316
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200317 mutex_unlock(&genpd->lock);
318
Rafael J. Wysockiecf00472011-11-27 13:11:44 +0100319 genpd_start_dev(genpd, dev);
320 ret = genpd_save_dev(genpd, dev);
321 genpd_stop_dev(genpd, dev);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200322
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200323 mutex_lock(&genpd->lock);
324
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200325 if (!ret)
Rafael J. Wysockicd0ea672011-09-26 20:22:02 +0200326 gpd_data->need_restore = true;
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200327
328 return ret;
329}
330
331/**
332 * __pm_genpd_restore_device - Restore the pre-suspend state of a device.
Rafael J. Wysocki4605ab62011-08-25 15:34:12 +0200333 * @pdd: Domain data of the device to restore the state of.
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200334 * @genpd: PM domain the device belongs to.
335 */
Rafael J. Wysocki4605ab62011-08-25 15:34:12 +0200336static void __pm_genpd_restore_device(struct pm_domain_data *pdd,
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200337 struct generic_pm_domain *genpd)
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200338 __releases(&genpd->lock) __acquires(&genpd->lock)
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200339{
Rafael J. Wysockicd0ea672011-09-26 20:22:02 +0200340 struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
Rafael J. Wysocki4605ab62011-08-25 15:34:12 +0200341 struct device *dev = pdd->dev;
Rafael J. Wysocki80de3d72012-06-16 00:02:34 +0200342 bool need_restore = gpd_data->need_restore;
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200343
Rafael J. Wysocki80de3d72012-06-16 00:02:34 +0200344 gpd_data->need_restore = false;
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200345 mutex_unlock(&genpd->lock);
346
Rafael J. Wysockiecf00472011-11-27 13:11:44 +0100347 genpd_start_dev(genpd, dev);
Rafael J. Wysocki80de3d72012-06-16 00:02:34 +0200348 if (need_restore)
349 genpd_restore_dev(genpd, dev);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200350
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200351 mutex_lock(&genpd->lock);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200352}
353
354/**
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200355 * genpd_abort_poweroff - Check if a PM domain power off should be aborted.
356 * @genpd: PM domain to check.
357 *
358 * Return true if a PM domain's status changed to GPD_STATE_ACTIVE during
359 * a "power off" operation, which means that a "power on" has occured in the
360 * meantime, or if its resume_count field is different from zero, which means
361 * that one of its devices has been resumed in the meantime.
362 */
363static bool genpd_abort_poweroff(struct generic_pm_domain *genpd)
364{
Rafael J. Wysocki17877eb2011-08-08 23:43:50 +0200365 return genpd->status == GPD_STATE_WAIT_MASTER
Rafael J. Wysocki3f241772011-08-08 23:43:29 +0200366 || genpd->status == GPD_STATE_ACTIVE || genpd->resume_count > 0;
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200367}
368
369/**
Rafael J. Wysocki56375fd2011-07-12 00:40:03 +0200370 * genpd_queue_power_off_work - Queue up the execution of pm_genpd_poweroff().
371 * @genpd: PM domait to power off.
372 *
373 * Queue up the execution of pm_genpd_poweroff() unless it's already been done
374 * before.
375 */
Rafael J. Wysocki0bc5b2d2011-07-14 20:59:07 +0200376void genpd_queue_power_off_work(struct generic_pm_domain *genpd)
Rafael J. Wysocki56375fd2011-07-12 00:40:03 +0200377{
378 if (!work_pending(&genpd->power_off_work))
379 queue_work(pm_wq, &genpd->power_off_work);
380}
381
382/**
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200383 * pm_genpd_poweroff - Remove power from a given PM domain.
384 * @genpd: PM domain to power down.
385 *
386 * If all of the @genpd's devices have been suspended and all of its subdomains
387 * have been powered down, run the runtime suspend callbacks provided by all of
388 * the @genpd's devices' drivers and remove power from @genpd.
389 */
390static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200391 __releases(&genpd->lock) __acquires(&genpd->lock)
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200392{
Rafael J. Wysocki4605ab62011-08-25 15:34:12 +0200393 struct pm_domain_data *pdd;
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +0200394 struct gpd_link *link;
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200395 unsigned int not_suspended;
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200396 int ret = 0;
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200397
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200398 start:
399 /*
400 * Do not try to power off the domain in the following situations:
401 * (1) The domain is already in the "power off" state.
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +0200402 * (2) The domain is waiting for its master to power up.
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200403 * (3) One of the domain's devices is being resumed right now.
Rafael J. Wysocki3f241772011-08-08 23:43:29 +0200404 * (4) System suspend is in progress.
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200405 */
Rafael J. Wysocki3f241772011-08-08 23:43:29 +0200406 if (genpd->status == GPD_STATE_POWER_OFF
Rafael J. Wysocki17877eb2011-08-08 23:43:50 +0200407 || genpd->status == GPD_STATE_WAIT_MASTER
Rafael J. Wysocki3f241772011-08-08 23:43:29 +0200408 || genpd->resume_count > 0 || genpd->prepared_count > 0)
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200409 return 0;
410
Rafael J. Wysockic4bb3162011-08-08 23:43:04 +0200411 if (atomic_read(&genpd->sd_count) > 0)
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200412 return -EBUSY;
413
414 not_suspended = 0;
Rafael J. Wysocki4605ab62011-08-25 15:34:12 +0200415 list_for_each_entry(pdd, &genpd->dev_list, list_node)
Rafael J. Wysocki0aa2a222011-08-25 15:37:04 +0200416 if (pdd->dev->driver && (!pm_runtime_suspended(pdd->dev)
Rafael J. Wysocki1e78a0c2012-03-13 22:39:48 +0100417 || pdd->dev->power.irq_safe || to_gpd_data(pdd)->always_on))
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200418 not_suspended++;
419
420 if (not_suspended > genpd->in_progress)
421 return -EBUSY;
422
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200423 if (genpd->poweroff_task) {
424 /*
425 * Another instance of pm_genpd_poweroff() is executing
426 * callbacks, so tell it to start over and return.
427 */
428 genpd->status = GPD_STATE_REPEAT;
429 return 0;
430 }
431
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200432 if (genpd->gov && genpd->gov->power_down_ok) {
433 if (!genpd->gov->power_down_ok(&genpd->domain))
434 return -EAGAIN;
435 }
436
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200437 genpd->status = GPD_STATE_BUSY;
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200438 genpd->poweroff_task = current;
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200439
Rafael J. Wysocki4605ab62011-08-25 15:34:12 +0200440 list_for_each_entry_reverse(pdd, &genpd->dev_list, list_node) {
Rafael J. Wysocki3c07cbc2011-08-08 23:43:14 +0200441 ret = atomic_read(&genpd->sd_count) == 0 ?
Rafael J. Wysocki4605ab62011-08-25 15:34:12 +0200442 __pm_genpd_save_device(pdd, genpd) : -EBUSY;
Rafael J. Wysocki3f241772011-08-08 23:43:29 +0200443
444 if (genpd_abort_poweroff(genpd))
445 goto out;
446
Rafael J. Wysocki697a7f32011-07-12 00:39:48 +0200447 if (ret) {
448 genpd_set_active(genpd);
449 goto out;
450 }
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200451
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200452 if (genpd->status == GPD_STATE_REPEAT) {
453 genpd->poweroff_task = NULL;
454 goto start;
455 }
456 }
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200457
Rafael J. Wysocki3c07cbc2011-08-08 23:43:14 +0200458 if (genpd->power_off) {
Rafael J. Wysocki0140d8b2011-12-01 00:02:17 +0100459 ktime_t time_start;
460 s64 elapsed_ns;
461
Rafael J. Wysocki3c07cbc2011-08-08 23:43:14 +0200462 if (atomic_read(&genpd->sd_count) > 0) {
463 ret = -EBUSY;
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200464 goto out;
465 }
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200466
Rafael J. Wysocki0140d8b2011-12-01 00:02:17 +0100467 time_start = ktime_get();
468
Rafael J. Wysocki3c07cbc2011-08-08 23:43:14 +0200469 /*
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +0200470 * If sd_count > 0 at this point, one of the subdomains hasn't
471 * managed to call pm_genpd_poweron() for the master yet after
Rafael J. Wysocki3c07cbc2011-08-08 23:43:14 +0200472 * incrementing it. In that case pm_genpd_poweron() will wait
473 * for us to drop the lock, so we can call .power_off() and let
474 * the pm_genpd_poweron() restore power for us (this shouldn't
475 * happen very often).
476 */
Rafael J. Wysockid2805402011-07-14 20:59:20 +0200477 ret = genpd->power_off(genpd);
478 if (ret == -EBUSY) {
479 genpd_set_active(genpd);
Rafael J. Wysockid2805402011-07-14 20:59:20 +0200480 goto out;
481 }
Rafael J. Wysocki0140d8b2011-12-01 00:02:17 +0100482
483 elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
Rafael J. Wysockie84b2c22011-12-06 22:19:54 +0100484 if (elapsed_ns > genpd->power_off_latency_ns) {
Rafael J. Wysocki0140d8b2011-12-01 00:02:17 +0100485 genpd->power_off_latency_ns = elapsed_ns;
Rafael J. Wysocki6ff7bb0d02012-05-01 21:34:07 +0200486 genpd->max_off_time_changed = true;
Rafael J. Wysockie84b2c22011-12-06 22:19:54 +0100487 if (genpd->name)
488 pr_warning("%s: Power-off latency exceeded, "
489 "new value %lld ns\n", genpd->name,
490 elapsed_ns);
491 }
Rafael J. Wysockid2805402011-07-14 20:59:20 +0200492 }
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200493
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200494 genpd->status = GPD_STATE_POWER_OFF;
Rafael J. Wysocki221e9b52011-12-01 00:02:10 +0100495
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +0200496 list_for_each_entry(link, &genpd->slave_links, slave_node) {
497 genpd_sd_counter_dec(link->master);
498 genpd_queue_power_off_work(link->master);
499 }
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200500
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200501 out:
502 genpd->poweroff_task = NULL;
503 wake_up_all(&genpd->status_wait_queue);
504 return ret;
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200505}
506
507/**
508 * genpd_power_off_work_fn - Power off PM domain whose subdomain count is 0.
509 * @work: Work structure used for scheduling the execution of this function.
510 */
511static void genpd_power_off_work_fn(struct work_struct *work)
512{
513 struct generic_pm_domain *genpd;
514
515 genpd = container_of(work, struct generic_pm_domain, power_off_work);
516
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200517 genpd_acquire_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200518 pm_genpd_poweroff(genpd);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200519 genpd_release_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200520}
521
522/**
523 * pm_genpd_runtime_suspend - Suspend a device belonging to I/O PM domain.
524 * @dev: Device to suspend.
525 *
526 * Carry out a runtime suspend of a device under the assumption that its
527 * pm_domain field points to the domain member of an object of type
528 * struct generic_pm_domain representing a PM domain consisting of I/O devices.
529 */
530static int pm_genpd_runtime_suspend(struct device *dev)
531{
532 struct generic_pm_domain *genpd;
Rafael J. Wysockib02c9992011-12-01 00:02:05 +0100533 bool (*stop_ok)(struct device *__dev);
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +0100534 int ret;
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200535
536 dev_dbg(dev, "%s()\n", __func__);
537
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200538 genpd = dev_to_genpd(dev);
539 if (IS_ERR(genpd))
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200540 return -EINVAL;
541
Rafael J. Wysocki0aa2a222011-08-25 15:37:04 +0200542 might_sleep_if(!genpd->dev_irq_safe);
543
Rafael J. Wysocki1e78a0c2012-03-13 22:39:48 +0100544 if (dev_gpd_data(dev)->always_on)
545 return -EBUSY;
546
Rafael J. Wysockib02c9992011-12-01 00:02:05 +0100547 stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL;
548 if (stop_ok && !stop_ok(dev))
549 return -EBUSY;
550
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +0100551 ret = genpd_stop_dev(genpd, dev);
552 if (ret)
553 return ret;
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200554
Rafael J. Wysocki0aa2a222011-08-25 15:37:04 +0200555 /*
556 * If power.irq_safe is set, this routine will be run with interrupts
557 * off, so it can't use mutexes.
558 */
559 if (dev->power.irq_safe)
560 return 0;
561
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200562 mutex_lock(&genpd->lock);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200563 genpd->in_progress++;
564 pm_genpd_poweroff(genpd);
565 genpd->in_progress--;
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200566 mutex_unlock(&genpd->lock);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200567
568 return 0;
569}
570
571/**
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200572 * pm_genpd_runtime_resume - Resume a device belonging to I/O PM domain.
573 * @dev: Device to resume.
574 *
575 * Carry out a runtime resume of a device under the assumption that its
576 * pm_domain field points to the domain member of an object of type
577 * struct generic_pm_domain representing a PM domain consisting of I/O devices.
578 */
579static int pm_genpd_runtime_resume(struct device *dev)
580{
581 struct generic_pm_domain *genpd;
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200582 DEFINE_WAIT(wait);
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200583 int ret;
584
585 dev_dbg(dev, "%s()\n", __func__);
586
Rafael J. Wysocki52480512011-07-01 22:13:10 +0200587 genpd = dev_to_genpd(dev);
588 if (IS_ERR(genpd))
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200589 return -EINVAL;
590
Rafael J. Wysocki0aa2a222011-08-25 15:37:04 +0200591 might_sleep_if(!genpd->dev_irq_safe);
592
593 /* If power.irq_safe, the PM domain is never powered off. */
594 if (dev->power.irq_safe)
Rafael J. Wysocki80de3d72012-06-16 00:02:34 +0200595 return genpd_start_dev(genpd, dev);
Rafael J. Wysocki0aa2a222011-08-25 15:37:04 +0200596
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200597 mutex_lock(&genpd->lock);
Rafael J. Wysocki3f241772011-08-08 23:43:29 +0200598 ret = __pm_genpd_poweron(genpd);
599 if (ret) {
600 mutex_unlock(&genpd->lock);
601 return ret;
602 }
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200603 genpd->status = GPD_STATE_BUSY;
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200604 genpd->resume_count++;
605 for (;;) {
606 prepare_to_wait(&genpd->status_wait_queue, &wait,
607 TASK_UNINTERRUPTIBLE);
608 /*
609 * If current is the powering off task, we have been called
610 * reentrantly from one of the device callbacks, so we should
611 * not wait.
612 */
613 if (!genpd->poweroff_task || genpd->poweroff_task == current)
614 break;
615 mutex_unlock(&genpd->lock);
616
617 schedule();
618
619 mutex_lock(&genpd->lock);
620 }
621 finish_wait(&genpd->status_wait_queue, &wait);
Rafael J. Wysockicd0ea672011-09-26 20:22:02 +0200622 __pm_genpd_restore_device(dev->power.subsys_data->domain_data, genpd);
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200623 genpd->resume_count--;
624 genpd_set_active(genpd);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200625 wake_up_all(&genpd->status_wait_queue);
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +0200626 mutex_unlock(&genpd->lock);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200627
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200628 return 0;
629}
630
Rafael J. Wysocki17f2ae72011-08-14 13:34:31 +0200631/**
632 * pm_genpd_poweroff_unused - Power off all PM domains with no devices in use.
633 */
634void pm_genpd_poweroff_unused(void)
635{
636 struct generic_pm_domain *genpd;
637
638 mutex_lock(&gpd_list_lock);
639
640 list_for_each_entry(genpd, &gpd_list, gpd_list_node)
641 genpd_queue_power_off_work(genpd);
642
643 mutex_unlock(&gpd_list_lock);
644}
645
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200646#else
647
Rafael J. Wysocki6ff7bb0d02012-05-01 21:34:07 +0200648static inline int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
649 unsigned long val, void *ptr)
650{
651 return NOTIFY_DONE;
652}
653
Rafael J. Wysockif7218892011-07-01 22:12:45 +0200654static inline void genpd_power_off_work_fn(struct work_struct *work) {}
655
656#define pm_genpd_runtime_suspend NULL
657#define pm_genpd_runtime_resume NULL
658
659#endif /* CONFIG_PM_RUNTIME */
660
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200661#ifdef CONFIG_PM_SLEEP
662
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +0100663static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd,
664 struct device *dev)
665{
666 return GENPD_DEV_CALLBACK(genpd, bool, active_wakeup, dev);
667}
668
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +0100669static int genpd_suspend_dev(struct generic_pm_domain *genpd, struct device *dev)
670{
671 return GENPD_DEV_CALLBACK(genpd, int, suspend, dev);
672}
673
674static int genpd_suspend_late(struct generic_pm_domain *genpd, struct device *dev)
675{
676 return GENPD_DEV_CALLBACK(genpd, int, suspend_late, dev);
677}
678
679static int genpd_resume_early(struct generic_pm_domain *genpd, struct device *dev)
680{
681 return GENPD_DEV_CALLBACK(genpd, int, resume_early, dev);
682}
683
684static int genpd_resume_dev(struct generic_pm_domain *genpd, struct device *dev)
685{
686 return GENPD_DEV_CALLBACK(genpd, int, resume, dev);
687}
688
689static int genpd_freeze_dev(struct generic_pm_domain *genpd, struct device *dev)
690{
691 return GENPD_DEV_CALLBACK(genpd, int, freeze, dev);
692}
693
694static int genpd_freeze_late(struct generic_pm_domain *genpd, struct device *dev)
695{
696 return GENPD_DEV_CALLBACK(genpd, int, freeze_late, dev);
697}
698
699static int genpd_thaw_early(struct generic_pm_domain *genpd, struct device *dev)
700{
701 return GENPD_DEV_CALLBACK(genpd, int, thaw_early, dev);
702}
703
704static int genpd_thaw_dev(struct generic_pm_domain *genpd, struct device *dev)
705{
706 return GENPD_DEV_CALLBACK(genpd, int, thaw, dev);
707}
708
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200709/**
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +0200710 * pm_genpd_sync_poweroff - Synchronously power off a PM domain and its masters.
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200711 * @genpd: PM domain to power off, if possible.
712 *
713 * Check if the given PM domain can be powered off (during system suspend or
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +0200714 * hibernation) and do that if so. Also, in that case propagate to its masters.
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200715 *
716 * This function is only called in "noirq" stages of system power transitions,
717 * so it need not acquire locks (all of the "noirq" callbacks are executed
718 * sequentially, so it is guaranteed that it will never run twice in parallel).
719 */
720static void pm_genpd_sync_poweroff(struct generic_pm_domain *genpd)
721{
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +0200722 struct gpd_link *link;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200723
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200724 if (genpd->status == GPD_STATE_POWER_OFF)
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200725 return;
726
Rafael J. Wysockic4bb3162011-08-08 23:43:04 +0200727 if (genpd->suspended_count != genpd->device_count
728 || atomic_read(&genpd->sd_count) > 0)
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200729 return;
730
731 if (genpd->power_off)
732 genpd->power_off(genpd);
733
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200734 genpd->status = GPD_STATE_POWER_OFF;
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +0200735
736 list_for_each_entry(link, &genpd->slave_links, slave_node) {
737 genpd_sd_counter_dec(link->master);
738 pm_genpd_sync_poweroff(link->master);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200739 }
740}
741
742/**
Rafael J. Wysocki4ecd6e62011-07-12 00:39:57 +0200743 * resume_needed - Check whether to resume a device before system suspend.
744 * @dev: Device to check.
745 * @genpd: PM domain the device belongs to.
746 *
747 * There are two cases in which a device that can wake up the system from sleep
748 * states should be resumed by pm_genpd_prepare(): (1) if the device is enabled
749 * to wake up the system and it has to remain active for this purpose while the
750 * system is in the sleep state and (2) if the device is not enabled to wake up
751 * the system from sleep states and it generally doesn't generate wakeup signals
752 * by itself (those signals are generated on its behalf by other parts of the
753 * system). In the latter case it may be necessary to reconfigure the device's
754 * wakeup settings during system suspend, because it may have been set up to
755 * signal remote wakeup from the system's working state as needed by runtime PM.
756 * Return 'true' in either of the above cases.
757 */
758static bool resume_needed(struct device *dev, struct generic_pm_domain *genpd)
759{
760 bool active_wakeup;
761
762 if (!device_can_wakeup(dev))
763 return false;
764
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +0100765 active_wakeup = genpd_dev_active_wakeup(genpd, dev);
Rafael J. Wysocki4ecd6e62011-07-12 00:39:57 +0200766 return device_may_wakeup(dev) ? active_wakeup : !active_wakeup;
767}
768
769/**
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200770 * pm_genpd_prepare - Start power transition of a device in a PM domain.
771 * @dev: Device to start the transition of.
772 *
773 * Start a power transition of a device (during a system-wide power transition)
774 * under the assumption that its pm_domain field points to the domain member of
775 * an object of type struct generic_pm_domain representing a PM domain
776 * consisting of I/O devices.
777 */
778static int pm_genpd_prepare(struct device *dev)
779{
780 struct generic_pm_domain *genpd;
Rafael J. Wysockib6c10c82011-07-12 00:39:21 +0200781 int ret;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200782
783 dev_dbg(dev, "%s()\n", __func__);
784
785 genpd = dev_to_genpd(dev);
786 if (IS_ERR(genpd))
787 return -EINVAL;
788
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200789 /*
790 * If a wakeup request is pending for the device, it should be woken up
791 * at this point and a system wakeup event should be reported if it's
792 * set up to wake up the system from sleep states.
793 */
794 pm_runtime_get_noresume(dev);
795 if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
796 pm_wakeup_event(dev, 0);
797
798 if (pm_wakeup_pending()) {
799 pm_runtime_put_sync(dev);
800 return -EBUSY;
801 }
802
Rafael J. Wysocki4ecd6e62011-07-12 00:39:57 +0200803 if (resume_needed(dev, genpd))
804 pm_runtime_resume(dev);
805
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200806 genpd_acquire_lock(genpd);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200807
Rafael J. Wysocki65533bb2012-03-13 22:39:37 +0100808 if (genpd->prepared_count++ == 0) {
809 genpd->suspended_count = 0;
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200810 genpd->suspend_power_off = genpd->status == GPD_STATE_POWER_OFF;
Rafael J. Wysocki65533bb2012-03-13 22:39:37 +0100811 }
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200812
813 genpd_release_lock(genpd);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200814
815 if (genpd->suspend_power_off) {
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200816 pm_runtime_put_noidle(dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200817 return 0;
818 }
819
820 /*
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200821 * The PM domain must be in the GPD_STATE_ACTIVE state at this point,
822 * so pm_genpd_poweron() will return immediately, but if the device
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +0100823 * is suspended (e.g. it's been stopped by genpd_stop_dev()), we need
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200824 * to make it operational.
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200825 */
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200826 pm_runtime_resume(dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200827 __pm_runtime_disable(dev, false);
828
Rafael J. Wysockib6c10c82011-07-12 00:39:21 +0200829 ret = pm_generic_prepare(dev);
830 if (ret) {
831 mutex_lock(&genpd->lock);
832
833 if (--genpd->prepared_count == 0)
834 genpd->suspend_power_off = false;
835
836 mutex_unlock(&genpd->lock);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200837 pm_runtime_enable(dev);
Rafael J. Wysockib6c10c82011-07-12 00:39:21 +0200838 }
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +0200839
840 pm_runtime_put_sync(dev);
Rafael J. Wysockib6c10c82011-07-12 00:39:21 +0200841 return ret;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200842}
843
844/**
845 * pm_genpd_suspend - Suspend a device belonging to an I/O PM domain.
846 * @dev: Device to suspend.
847 *
848 * Suspend a device under the assumption that its pm_domain field points to the
849 * domain member of an object of type struct generic_pm_domain representing
850 * a PM domain consisting of I/O devices.
851 */
852static int pm_genpd_suspend(struct device *dev)
853{
854 struct generic_pm_domain *genpd;
855
856 dev_dbg(dev, "%s()\n", __func__);
857
858 genpd = dev_to_genpd(dev);
859 if (IS_ERR(genpd))
860 return -EINVAL;
861
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +0100862 return genpd->suspend_power_off ? 0 : genpd_suspend_dev(genpd, dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200863}
864
865/**
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +0100866 * pm_genpd_suspend_late - Late suspend of a device from an I/O PM domain.
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200867 * @dev: Device to suspend.
868 *
869 * Carry out a late suspend of a device under the assumption that its
870 * pm_domain field points to the domain member of an object of type
871 * struct generic_pm_domain representing a PM domain consisting of I/O devices.
872 */
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +0100873static int pm_genpd_suspend_late(struct device *dev)
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200874{
875 struct generic_pm_domain *genpd;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200876
877 dev_dbg(dev, "%s()\n", __func__);
878
879 genpd = dev_to_genpd(dev);
880 if (IS_ERR(genpd))
881 return -EINVAL;
882
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +0100883 return genpd->suspend_power_off ? 0 : genpd_suspend_late(genpd, dev);
884}
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200885
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +0100886/**
887 * pm_genpd_suspend_noirq - Completion of suspend of device in an I/O PM domain.
888 * @dev: Device to suspend.
889 *
890 * Stop the device and remove power from the domain if all devices in it have
891 * been stopped.
892 */
893static int pm_genpd_suspend_noirq(struct device *dev)
894{
895 struct generic_pm_domain *genpd;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200896
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +0100897 dev_dbg(dev, "%s()\n", __func__);
898
899 genpd = dev_to_genpd(dev);
900 if (IS_ERR(genpd))
901 return -EINVAL;
902
Rafael J. Wysocki1e78a0c2012-03-13 22:39:48 +0100903 if (genpd->suspend_power_off || dev_gpd_data(dev)->always_on
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +0100904 || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev)))
Rafael J. Wysockid4f2d872011-07-01 22:13:29 +0200905 return 0;
906
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +0100907 genpd_stop_dev(genpd, dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200908
909 /*
910 * Since all of the "noirq" callbacks are executed sequentially, it is
911 * guaranteed that this function will never run twice in parallel for
912 * the same PM domain, so it is not necessary to use locking here.
913 */
914 genpd->suspended_count++;
915 pm_genpd_sync_poweroff(genpd);
916
917 return 0;
918}
919
920/**
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +0100921 * pm_genpd_resume_noirq - Start of resume of device in an I/O PM domain.
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200922 * @dev: Device to resume.
923 *
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +0100924 * Restore power to the device's PM domain, if necessary, and start the device.
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200925 */
926static int pm_genpd_resume_noirq(struct device *dev)
927{
928 struct generic_pm_domain *genpd;
929
930 dev_dbg(dev, "%s()\n", __func__);
931
932 genpd = dev_to_genpd(dev);
933 if (IS_ERR(genpd))
934 return -EINVAL;
935
Rafael J. Wysocki1e78a0c2012-03-13 22:39:48 +0100936 if (genpd->suspend_power_off || dev_gpd_data(dev)->always_on
Rafael J. Wysockicc85b202012-03-13 22:39:31 +0100937 || (dev->power.wakeup_path && genpd_dev_active_wakeup(genpd, dev)))
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200938 return 0;
939
940 /*
941 * Since all of the "noirq" callbacks are executed sequentially, it is
942 * guaranteed that this function will never run twice in parallel for
943 * the same PM domain, so it is not necessary to use locking here.
944 */
945 pm_genpd_poweron(genpd);
946 genpd->suspended_count--;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200947
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +0100948 return genpd_start_dev(genpd, dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200949}
950
951/**
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +0100952 * pm_genpd_resume_early - Early resume of a device in an I/O PM domain.
953 * @dev: Device to resume.
954 *
955 * Carry out an early resume of a device under the assumption that its
956 * pm_domain field points to the domain member of an object of type
957 * struct generic_pm_domain representing a power domain consisting of I/O
958 * devices.
959 */
960static int pm_genpd_resume_early(struct device *dev)
961{
962 struct generic_pm_domain *genpd;
963
964 dev_dbg(dev, "%s()\n", __func__);
965
966 genpd = dev_to_genpd(dev);
967 if (IS_ERR(genpd))
968 return -EINVAL;
969
970 return genpd->suspend_power_off ? 0 : genpd_resume_early(genpd, dev);
971}
972
973/**
974 * pm_genpd_resume - Resume of device in an I/O PM domain.
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200975 * @dev: Device to resume.
976 *
977 * Resume a device under the assumption that its pm_domain field points to the
978 * domain member of an object of type struct generic_pm_domain representing
979 * a power domain consisting of I/O devices.
980 */
981static int pm_genpd_resume(struct device *dev)
982{
983 struct generic_pm_domain *genpd;
984
985 dev_dbg(dev, "%s()\n", __func__);
986
987 genpd = dev_to_genpd(dev);
988 if (IS_ERR(genpd))
989 return -EINVAL;
990
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +0100991 return genpd->suspend_power_off ? 0 : genpd_resume_dev(genpd, dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200992}
993
994/**
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +0100995 * pm_genpd_freeze - Freezing a device in an I/O PM domain.
Rafael J. Wysocki596ba342011-07-01 22:13:19 +0200996 * @dev: Device to freeze.
997 *
998 * Freeze a device under the assumption that its pm_domain field points to the
999 * domain member of an object of type struct generic_pm_domain representing
1000 * a power domain consisting of I/O devices.
1001 */
1002static int pm_genpd_freeze(struct device *dev)
1003{
1004 struct generic_pm_domain *genpd;
1005
1006 dev_dbg(dev, "%s()\n", __func__);
1007
1008 genpd = dev_to_genpd(dev);
1009 if (IS_ERR(genpd))
1010 return -EINVAL;
1011
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +01001012 return genpd->suspend_power_off ? 0 : genpd_freeze_dev(genpd, dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001013}
1014
1015/**
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001016 * pm_genpd_freeze_late - Late freeze of a device in an I/O PM domain.
1017 * @dev: Device to freeze.
1018 *
1019 * Carry out a late freeze of a device under the assumption that its
1020 * pm_domain field points to the domain member of an object of type
1021 * struct generic_pm_domain representing a power domain consisting of I/O
1022 * devices.
1023 */
1024static int pm_genpd_freeze_late(struct device *dev)
1025{
1026 struct generic_pm_domain *genpd;
1027
1028 dev_dbg(dev, "%s()\n", __func__);
1029
1030 genpd = dev_to_genpd(dev);
1031 if (IS_ERR(genpd))
1032 return -EINVAL;
1033
1034 return genpd->suspend_power_off ? 0 : genpd_freeze_late(genpd, dev);
1035}
1036
1037/**
1038 * pm_genpd_freeze_noirq - Completion of freezing a device in an I/O PM domain.
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001039 * @dev: Device to freeze.
1040 *
1041 * Carry out a late freeze of a device under the assumption that its
1042 * pm_domain field points to the domain member of an object of type
1043 * struct generic_pm_domain representing a power domain consisting of I/O
1044 * devices.
1045 */
1046static int pm_genpd_freeze_noirq(struct device *dev)
1047{
1048 struct generic_pm_domain *genpd;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001049
1050 dev_dbg(dev, "%s()\n", __func__);
1051
1052 genpd = dev_to_genpd(dev);
1053 if (IS_ERR(genpd))
1054 return -EINVAL;
1055
Rafael J. Wysocki1e78a0c2012-03-13 22:39:48 +01001056 return genpd->suspend_power_off || dev_gpd_data(dev)->always_on ?
1057 0 : genpd_stop_dev(genpd, dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001058}
1059
1060/**
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001061 * pm_genpd_thaw_noirq - Early thaw of device in an I/O PM domain.
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001062 * @dev: Device to thaw.
1063 *
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001064 * Start the device, unless power has been removed from the domain already
1065 * before the system transition.
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001066 */
1067static int pm_genpd_thaw_noirq(struct device *dev)
1068{
1069 struct generic_pm_domain *genpd;
1070
1071 dev_dbg(dev, "%s()\n", __func__);
1072
1073 genpd = dev_to_genpd(dev);
1074 if (IS_ERR(genpd))
1075 return -EINVAL;
1076
Rafael J. Wysocki1e78a0c2012-03-13 22:39:48 +01001077 return genpd->suspend_power_off || dev_gpd_data(dev)->always_on ?
1078 0 : genpd_start_dev(genpd, dev);
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001079}
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001080
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001081/**
1082 * pm_genpd_thaw_early - Early thaw of device in an I/O PM domain.
1083 * @dev: Device to thaw.
1084 *
1085 * Carry out an early thaw of a device under the assumption that its
1086 * pm_domain field points to the domain member of an object of type
1087 * struct generic_pm_domain representing a power domain consisting of I/O
1088 * devices.
1089 */
1090static int pm_genpd_thaw_early(struct device *dev)
1091{
1092 struct generic_pm_domain *genpd;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001093
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001094 dev_dbg(dev, "%s()\n", __func__);
1095
1096 genpd = dev_to_genpd(dev);
1097 if (IS_ERR(genpd))
1098 return -EINVAL;
1099
1100 return genpd->suspend_power_off ? 0 : genpd_thaw_early(genpd, dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001101}
1102
1103/**
1104 * pm_genpd_thaw - Thaw a device belonging to an I/O power domain.
1105 * @dev: Device to thaw.
1106 *
1107 * Thaw a device under the assumption that its pm_domain field points to the
1108 * domain member of an object of type struct generic_pm_domain representing
1109 * a power domain consisting of I/O devices.
1110 */
1111static int pm_genpd_thaw(struct device *dev)
1112{
1113 struct generic_pm_domain *genpd;
1114
1115 dev_dbg(dev, "%s()\n", __func__);
1116
1117 genpd = dev_to_genpd(dev);
1118 if (IS_ERR(genpd))
1119 return -EINVAL;
1120
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +01001121 return genpd->suspend_power_off ? 0 : genpd_thaw_dev(genpd, dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001122}
1123
1124/**
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001125 * pm_genpd_restore_noirq - Start of restore of device in an I/O PM domain.
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001126 * @dev: Device to resume.
1127 *
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001128 * Make sure the domain will be in the same power state as before the
1129 * hibernation the system is resuming from and start the device if necessary.
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001130 */
1131static int pm_genpd_restore_noirq(struct device *dev)
1132{
1133 struct generic_pm_domain *genpd;
1134
1135 dev_dbg(dev, "%s()\n", __func__);
1136
1137 genpd = dev_to_genpd(dev);
1138 if (IS_ERR(genpd))
1139 return -EINVAL;
1140
1141 /*
1142 * Since all of the "noirq" callbacks are executed sequentially, it is
1143 * guaranteed that this function will never run twice in parallel for
1144 * the same PM domain, so it is not necessary to use locking here.
Rafael J. Wysocki65533bb2012-03-13 22:39:37 +01001145 *
1146 * At this point suspended_count == 0 means we are being run for the
1147 * first time for the given domain in the present cycle.
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001148 */
Rafael J. Wysocki65533bb2012-03-13 22:39:37 +01001149 if (genpd->suspended_count++ == 0) {
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001150 /*
Rafael J. Wysocki65533bb2012-03-13 22:39:37 +01001151 * The boot kernel might put the domain into arbitrary state,
1152 * so make it appear as powered off to pm_genpd_poweron(), so
1153 * that it tries to power it on in case it was really off.
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001154 */
Rafael J. Wysocki65533bb2012-03-13 22:39:37 +01001155 genpd->status = GPD_STATE_POWER_OFF;
1156 if (genpd->suspend_power_off) {
1157 /*
1158 * If the domain was off before the hibernation, make
1159 * sure it will be off going forward.
1160 */
1161 if (genpd->power_off)
1162 genpd->power_off(genpd);
1163
1164 return 0;
1165 }
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001166 }
1167
Rafael J. Wysocki18dd2ec2012-03-19 10:38:14 +01001168 if (genpd->suspend_power_off)
1169 return 0;
1170
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001171 pm_genpd_poweron(genpd);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001172
Rafael J. Wysocki1e78a0c2012-03-13 22:39:48 +01001173 return dev_gpd_data(dev)->always_on ? 0 : genpd_start_dev(genpd, dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001174}
1175
1176/**
1177 * pm_genpd_complete - Complete power transition of a device in a power domain.
1178 * @dev: Device to complete the transition of.
1179 *
1180 * Complete a power transition of a device (during a system-wide power
1181 * transition) under the assumption that its pm_domain field points to the
1182 * domain member of an object of type struct generic_pm_domain representing
1183 * a power domain consisting of I/O devices.
1184 */
1185static void pm_genpd_complete(struct device *dev)
1186{
1187 struct generic_pm_domain *genpd;
1188 bool run_complete;
1189
1190 dev_dbg(dev, "%s()\n", __func__);
1191
1192 genpd = dev_to_genpd(dev);
1193 if (IS_ERR(genpd))
1194 return;
1195
1196 mutex_lock(&genpd->lock);
1197
1198 run_complete = !genpd->suspend_power_off;
1199 if (--genpd->prepared_count == 0)
1200 genpd->suspend_power_off = false;
1201
1202 mutex_unlock(&genpd->lock);
1203
1204 if (run_complete) {
1205 pm_generic_complete(dev);
Rafael J. Wysocki6f00ff72011-07-12 00:39:10 +02001206 pm_runtime_set_active(dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001207 pm_runtime_enable(dev);
Rafael J. Wysocki6f00ff72011-07-12 00:39:10 +02001208 pm_runtime_idle(dev);
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001209 }
1210}
1211
1212#else
1213
1214#define pm_genpd_prepare NULL
1215#define pm_genpd_suspend NULL
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001216#define pm_genpd_suspend_late NULL
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001217#define pm_genpd_suspend_noirq NULL
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001218#define pm_genpd_resume_early NULL
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001219#define pm_genpd_resume_noirq NULL
1220#define pm_genpd_resume NULL
1221#define pm_genpd_freeze NULL
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001222#define pm_genpd_freeze_late NULL
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001223#define pm_genpd_freeze_noirq NULL
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001224#define pm_genpd_thaw_early NULL
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001225#define pm_genpd_thaw_noirq NULL
1226#define pm_genpd_thaw NULL
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001227#define pm_genpd_restore_noirq NULL
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001228#define pm_genpd_complete NULL
1229
1230#endif /* CONFIG_PM_SLEEP */
1231
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001232/**
Rafael J. Wysockib02c9992011-12-01 00:02:05 +01001233 * __pm_genpd_add_device - Add a device to an I/O PM domain.
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001234 * @genpd: PM domain to add the device to.
1235 * @dev: Device to be added.
Rafael J. Wysockib02c9992011-12-01 00:02:05 +01001236 * @td: Set of PM QoS timing parameters to attach to the device.
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001237 */
Rafael J. Wysockib02c9992011-12-01 00:02:05 +01001238int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
1239 struct gpd_timing_data *td)
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001240{
Rafael J. Wysockicd0ea672011-09-26 20:22:02 +02001241 struct generic_pm_domain_data *gpd_data;
Rafael J. Wysocki4605ab62011-08-25 15:34:12 +02001242 struct pm_domain_data *pdd;
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001243 int ret = 0;
1244
1245 dev_dbg(dev, "%s()\n", __func__);
1246
1247 if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev))
1248 return -EINVAL;
1249
Rafael J. Wysocki6ff7bb0d02012-05-01 21:34:07 +02001250 gpd_data = kzalloc(sizeof(*gpd_data), GFP_KERNEL);
1251 if (!gpd_data)
1252 return -ENOMEM;
1253
1254 mutex_init(&gpd_data->lock);
1255 gpd_data->nb.notifier_call = genpd_dev_pm_qos_notifier;
1256 dev_pm_qos_add_notifier(dev, &gpd_data->nb);
1257
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001258 genpd_acquire_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001259
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001260 if (genpd->prepared_count > 0) {
1261 ret = -EAGAIN;
1262 goto out;
1263 }
1264
Rafael J. Wysocki4605ab62011-08-25 15:34:12 +02001265 list_for_each_entry(pdd, &genpd->dev_list, list_node)
1266 if (pdd->dev == dev) {
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001267 ret = -EINVAL;
1268 goto out;
1269 }
1270
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001271 genpd->device_count++;
Rafael J. Wysocki6ff7bb0d02012-05-01 21:34:07 +02001272 genpd->max_off_time_changed = true;
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001273
Rafael J. Wysocki4605ab62011-08-25 15:34:12 +02001274 dev_pm_get_subsys_data(dev);
Rafael J. Wysocki6ff7bb0d02012-05-01 21:34:07 +02001275
1276 mutex_lock(&gpd_data->lock);
1277 spin_lock_irq(&dev->power.lock);
1278 dev->pm_domain = &genpd->domain;
Rafael J. Wysockicd0ea672011-09-26 20:22:02 +02001279 dev->power.subsys_data->domain_data = &gpd_data->base;
1280 gpd_data->base.dev = dev;
Rafael J. Wysockicd0ea672011-09-26 20:22:02 +02001281 list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
Rafael J. Wysockica1d72f2012-05-14 21:45:52 +02001282 gpd_data->need_restore = genpd->status == GPD_STATE_POWER_OFF;
Rafael J. Wysockib02c9992011-12-01 00:02:05 +01001283 if (td)
1284 gpd_data->td = *td;
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001285
Rafael J. Wysocki6ff7bb0d02012-05-01 21:34:07 +02001286 gpd_data->td.constraint_changed = true;
1287 gpd_data->td.effective_constraint_ns = -1;
1288 spin_unlock_irq(&dev->power.lock);
1289 mutex_unlock(&gpd_data->lock);
1290
1291 genpd_release_lock(genpd);
1292
1293 return 0;
1294
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001295 out:
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001296 genpd_release_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001297
Rafael J. Wysocki6ff7bb0d02012-05-01 21:34:07 +02001298 dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
1299 kfree(gpd_data);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001300 return ret;
1301}
1302
1303/**
Thomas Abrahamc8aa1302012-01-27 15:22:07 +09001304 * __pm_genpd_of_add_device - Add a device to an I/O PM domain.
1305 * @genpd_node: Device tree node pointer representing a PM domain to which the
1306 * the device is added to.
1307 * @dev: Device to be added.
1308 * @td: Set of PM QoS timing parameters to attach to the device.
1309 */
1310int __pm_genpd_of_add_device(struct device_node *genpd_node, struct device *dev,
1311 struct gpd_timing_data *td)
1312{
1313 struct generic_pm_domain *genpd = NULL, *gpd;
1314
1315 dev_dbg(dev, "%s()\n", __func__);
1316
1317 if (IS_ERR_OR_NULL(genpd_node) || IS_ERR_OR_NULL(dev))
1318 return -EINVAL;
1319
1320 mutex_lock(&gpd_list_lock);
1321 list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
1322 if (gpd->of_node == genpd_node) {
1323 genpd = gpd;
1324 break;
1325 }
1326 }
1327 mutex_unlock(&gpd_list_lock);
1328
1329 if (!genpd)
1330 return -EINVAL;
1331
1332 return __pm_genpd_add_device(genpd, dev, td);
1333}
1334
1335/**
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001336 * pm_genpd_remove_device - Remove a device from an I/O PM domain.
1337 * @genpd: PM domain to remove the device from.
1338 * @dev: Device to be removed.
1339 */
1340int pm_genpd_remove_device(struct generic_pm_domain *genpd,
1341 struct device *dev)
1342{
Rafael J. Wysocki6ff7bb0d02012-05-01 21:34:07 +02001343 struct generic_pm_domain_data *gpd_data;
Rafael J. Wysocki4605ab62011-08-25 15:34:12 +02001344 struct pm_domain_data *pdd;
Rafael J. Wysockiefa69022012-05-01 21:33:53 +02001345 int ret = 0;
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001346
1347 dev_dbg(dev, "%s()\n", __func__);
1348
Rafael J. Wysockiefa69022012-05-01 21:33:53 +02001349 if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev)
1350 || IS_ERR_OR_NULL(dev->pm_domain)
1351 || pd_to_genpd(dev->pm_domain) != genpd)
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001352 return -EINVAL;
1353
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001354 genpd_acquire_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001355
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001356 if (genpd->prepared_count > 0) {
1357 ret = -EAGAIN;
1358 goto out;
1359 }
1360
Rafael J. Wysocki6ff7bb0d02012-05-01 21:34:07 +02001361 genpd->device_count--;
1362 genpd->max_off_time_changed = true;
1363
1364 spin_lock_irq(&dev->power.lock);
Rafael J. Wysockiefa69022012-05-01 21:33:53 +02001365 dev->pm_domain = NULL;
1366 pdd = dev->power.subsys_data->domain_data;
1367 list_del_init(&pdd->list_node);
1368 dev->power.subsys_data->domain_data = NULL;
Rafael J. Wysocki6ff7bb0d02012-05-01 21:34:07 +02001369 spin_unlock_irq(&dev->power.lock);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001370
Rafael J. Wysocki6ff7bb0d02012-05-01 21:34:07 +02001371 gpd_data = to_gpd_data(pdd);
1372 mutex_lock(&gpd_data->lock);
1373 pdd->dev = NULL;
1374 mutex_unlock(&gpd_data->lock);
1375
1376 genpd_release_lock(genpd);
1377
1378 dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
1379 kfree(gpd_data);
1380 dev_pm_put_subsys_data(dev);
1381 return 0;
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001382
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001383 out:
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001384 genpd_release_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001385
1386 return ret;
1387}
1388
1389/**
Rafael J. Wysocki1e78a0c2012-03-13 22:39:48 +01001390 * pm_genpd_dev_always_on - Set/unset the "always on" flag for a given device.
1391 * @dev: Device to set/unset the flag for.
1392 * @val: The new value of the device's "always on" flag.
1393 */
1394void pm_genpd_dev_always_on(struct device *dev, bool val)
1395{
1396 struct pm_subsys_data *psd;
1397 unsigned long flags;
1398
1399 spin_lock_irqsave(&dev->power.lock, flags);
1400
1401 psd = dev_to_psd(dev);
1402 if (psd && psd->domain_data)
1403 to_gpd_data(psd->domain_data)->always_on = val;
1404
1405 spin_unlock_irqrestore(&dev->power.lock, flags);
1406}
1407EXPORT_SYMBOL_GPL(pm_genpd_dev_always_on);
1408
1409/**
Rafael J. Wysockica1d72f2012-05-14 21:45:52 +02001410 * pm_genpd_dev_need_restore - Set/unset the device's "need restore" flag.
1411 * @dev: Device to set/unset the flag for.
1412 * @val: The new value of the device's "need restore" flag.
1413 */
1414void pm_genpd_dev_need_restore(struct device *dev, bool val)
1415{
1416 struct pm_subsys_data *psd;
1417 unsigned long flags;
1418
1419 spin_lock_irqsave(&dev->power.lock, flags);
1420
1421 psd = dev_to_psd(dev);
1422 if (psd && psd->domain_data)
1423 to_gpd_data(psd->domain_data)->need_restore = val;
1424
1425 spin_unlock_irqrestore(&dev->power.lock, flags);
1426}
1427EXPORT_SYMBOL_GPL(pm_genpd_dev_need_restore);
1428
1429/**
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001430 * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
1431 * @genpd: Master PM domain to add the subdomain to.
Rafael J. Wysockibc0403f2011-08-08 23:43:59 +02001432 * @subdomain: Subdomain to be added.
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001433 */
1434int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
Rafael J. Wysockibc0403f2011-08-08 23:43:59 +02001435 struct generic_pm_domain *subdomain)
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001436{
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +02001437 struct gpd_link *link;
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001438 int ret = 0;
1439
Rafael J. Wysockibc0403f2011-08-08 23:43:59 +02001440 if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001441 return -EINVAL;
1442
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001443 start:
1444 genpd_acquire_lock(genpd);
Rafael J. Wysockibc0403f2011-08-08 23:43:59 +02001445 mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001446
Rafael J. Wysockibc0403f2011-08-08 23:43:59 +02001447 if (subdomain->status != GPD_STATE_POWER_OFF
1448 && subdomain->status != GPD_STATE_ACTIVE) {
1449 mutex_unlock(&subdomain->lock);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001450 genpd_release_lock(genpd);
1451 goto start;
1452 }
1453
1454 if (genpd->status == GPD_STATE_POWER_OFF
Rafael J. Wysockibc0403f2011-08-08 23:43:59 +02001455 && subdomain->status != GPD_STATE_POWER_OFF) {
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001456 ret = -EINVAL;
1457 goto out;
1458 }
1459
Huang Ying4fcac102012-05-07 21:35:45 +02001460 list_for_each_entry(link, &genpd->master_links, master_node) {
Rafael J. Wysockibc0403f2011-08-08 23:43:59 +02001461 if (link->slave == subdomain && link->master == genpd) {
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001462 ret = -EINVAL;
1463 goto out;
1464 }
1465 }
1466
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +02001467 link = kzalloc(sizeof(*link), GFP_KERNEL);
1468 if (!link) {
1469 ret = -ENOMEM;
1470 goto out;
1471 }
1472 link->master = genpd;
1473 list_add_tail(&link->master_node, &genpd->master_links);
Rafael J. Wysockibc0403f2011-08-08 23:43:59 +02001474 link->slave = subdomain;
1475 list_add_tail(&link->slave_node, &subdomain->slave_links);
1476 if (subdomain->status != GPD_STATE_POWER_OFF)
Rafael J. Wysockic4bb3162011-08-08 23:43:04 +02001477 genpd_sd_counter_inc(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001478
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001479 out:
Rafael J. Wysockibc0403f2011-08-08 23:43:59 +02001480 mutex_unlock(&subdomain->lock);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001481 genpd_release_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001482
1483 return ret;
1484}
1485
1486/**
1487 * pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain.
1488 * @genpd: Master PM domain to remove the subdomain from.
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +02001489 * @subdomain: Subdomain to be removed.
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001490 */
1491int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +02001492 struct generic_pm_domain *subdomain)
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001493{
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +02001494 struct gpd_link *link;
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001495 int ret = -EINVAL;
1496
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +02001497 if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001498 return -EINVAL;
1499
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001500 start:
1501 genpd_acquire_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001502
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +02001503 list_for_each_entry(link, &genpd->master_links, master_node) {
1504 if (link->slave != subdomain)
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001505 continue;
1506
1507 mutex_lock_nested(&subdomain->lock, SINGLE_DEPTH_NESTING);
1508
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001509 if (subdomain->status != GPD_STATE_POWER_OFF
1510 && subdomain->status != GPD_STATE_ACTIVE) {
1511 mutex_unlock(&subdomain->lock);
1512 genpd_release_lock(genpd);
1513 goto start;
1514 }
1515
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +02001516 list_del(&link->master_node);
1517 list_del(&link->slave_node);
1518 kfree(link);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001519 if (subdomain->status != GPD_STATE_POWER_OFF)
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001520 genpd_sd_counter_dec(genpd);
1521
1522 mutex_unlock(&subdomain->lock);
1523
1524 ret = 0;
1525 break;
1526 }
1527
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001528 genpd_release_lock(genpd);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001529
1530 return ret;
1531}
1532
1533/**
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +01001534 * pm_genpd_add_callbacks - Add PM domain callbacks to a given device.
1535 * @dev: Device to add the callbacks to.
1536 * @ops: Set of callbacks to add.
Rafael J. Wysockib02c9992011-12-01 00:02:05 +01001537 * @td: Timing data to add to the device along with the callbacks (optional).
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +01001538 */
Rafael J. Wysockib02c9992011-12-01 00:02:05 +01001539int pm_genpd_add_callbacks(struct device *dev, struct gpd_dev_ops *ops,
1540 struct gpd_timing_data *td)
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +01001541{
1542 struct pm_domain_data *pdd;
1543 int ret = 0;
1544
1545 if (!(dev && dev->power.subsys_data && ops))
1546 return -EINVAL;
1547
1548 pm_runtime_disable(dev);
1549 device_pm_lock();
1550
1551 pdd = dev->power.subsys_data->domain_data;
1552 if (pdd) {
1553 struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
1554
1555 gpd_data->ops = *ops;
Rafael J. Wysockib02c9992011-12-01 00:02:05 +01001556 if (td)
1557 gpd_data->td = *td;
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +01001558 } else {
1559 ret = -EINVAL;
1560 }
1561
1562 device_pm_unlock();
1563 pm_runtime_enable(dev);
1564
1565 return ret;
1566}
1567EXPORT_SYMBOL_GPL(pm_genpd_add_callbacks);
1568
1569/**
Rafael J. Wysockib02c9992011-12-01 00:02:05 +01001570 * __pm_genpd_remove_callbacks - Remove PM domain callbacks from a given device.
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +01001571 * @dev: Device to remove the callbacks from.
Rafael J. Wysockib02c9992011-12-01 00:02:05 +01001572 * @clear_td: If set, clear the device's timing data too.
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +01001573 */
Rafael J. Wysockib02c9992011-12-01 00:02:05 +01001574int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td)
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +01001575{
1576 struct pm_domain_data *pdd;
1577 int ret = 0;
1578
1579 if (!(dev && dev->power.subsys_data))
1580 return -EINVAL;
1581
1582 pm_runtime_disable(dev);
1583 device_pm_lock();
1584
1585 pdd = dev->power.subsys_data->domain_data;
1586 if (pdd) {
1587 struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
1588
1589 gpd_data->ops = (struct gpd_dev_ops){ 0 };
Rafael J. Wysockib02c9992011-12-01 00:02:05 +01001590 if (clear_td)
1591 gpd_data->td = (struct gpd_timing_data){ 0 };
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +01001592 } else {
1593 ret = -EINVAL;
1594 }
1595
1596 device_pm_unlock();
1597 pm_runtime_enable(dev);
1598
1599 return ret;
1600}
Rafael J. Wysockib02c9992011-12-01 00:02:05 +01001601EXPORT_SYMBOL_GPL(__pm_genpd_remove_callbacks);
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +01001602
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +01001603/* Default device callbacks for generic PM domains. */
1604
Rafael J. Wysockid5e4cbf2011-11-27 13:11:36 +01001605/**
Rafael J. Wysockiecf00472011-11-27 13:11:44 +01001606 * pm_genpd_default_save_state - Default "save device state" for PM domians.
1607 * @dev: Device to handle.
1608 */
1609static int pm_genpd_default_save_state(struct device *dev)
1610{
1611 int (*cb)(struct device *__dev);
Rafael J. Wysockiecf00472011-11-27 13:11:44 +01001612
1613 cb = dev_gpd_data(dev)->ops.save_state;
1614 if (cb)
1615 return cb(dev);
1616
Rafael J. Wysocki0b589742012-06-16 00:02:22 +02001617 if (dev->type && dev->type->pm)
1618 cb = dev->type->pm->runtime_suspend;
1619 else if (dev->class && dev->class->pm)
1620 cb = dev->class->pm->runtime_suspend;
1621 else if (dev->bus && dev->bus->pm)
1622 cb = dev->bus->pm->runtime_suspend;
1623 else
1624 cb = NULL;
Rafael J. Wysockiecf00472011-11-27 13:11:44 +01001625
Rafael J. Wysocki0b589742012-06-16 00:02:22 +02001626 if (!cb && dev->driver && dev->driver->pm)
1627 cb = dev->driver->pm->runtime_suspend;
1628
1629 return cb ? cb(dev) : 0;
Rafael J. Wysockiecf00472011-11-27 13:11:44 +01001630}
1631
1632/**
1633 * pm_genpd_default_restore_state - Default PM domians "restore device state".
1634 * @dev: Device to handle.
1635 */
1636static int pm_genpd_default_restore_state(struct device *dev)
1637{
1638 int (*cb)(struct device *__dev);
Rafael J. Wysockiecf00472011-11-27 13:11:44 +01001639
1640 cb = dev_gpd_data(dev)->ops.restore_state;
1641 if (cb)
1642 return cb(dev);
1643
Rafael J. Wysocki0b589742012-06-16 00:02:22 +02001644 if (dev->type && dev->type->pm)
1645 cb = dev->type->pm->runtime_resume;
1646 else if (dev->class && dev->class->pm)
1647 cb = dev->class->pm->runtime_resume;
1648 else if (dev->bus && dev->bus->pm)
1649 cb = dev->bus->pm->runtime_resume;
1650 else
1651 cb = NULL;
Rafael J. Wysockiecf00472011-11-27 13:11:44 +01001652
Rafael J. Wysocki0b589742012-06-16 00:02:22 +02001653 if (!cb && dev->driver && dev->driver->pm)
1654 cb = dev->driver->pm->runtime_resume;
1655
1656 return cb ? cb(dev) : 0;
Rafael J. Wysockiecf00472011-11-27 13:11:44 +01001657}
1658
Rafael J. Wysocki0f1d6982012-01-14 00:39:25 +01001659#ifdef CONFIG_PM_SLEEP
1660
Rafael J. Wysockiecf00472011-11-27 13:11:44 +01001661/**
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +01001662 * pm_genpd_default_suspend - Default "device suspend" for PM domians.
1663 * @dev: Device to handle.
1664 */
1665static int pm_genpd_default_suspend(struct device *dev)
1666{
Rafael J. Wysockic9914852011-12-06 23:16:47 +01001667 int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.suspend;
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +01001668
1669 return cb ? cb(dev) : pm_generic_suspend(dev);
1670}
1671
1672/**
1673 * pm_genpd_default_suspend_late - Default "late device suspend" for PM domians.
1674 * @dev: Device to handle.
1675 */
1676static int pm_genpd_default_suspend_late(struct device *dev)
1677{
Rafael J. Wysockic9914852011-12-06 23:16:47 +01001678 int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.suspend_late;
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +01001679
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001680 return cb ? cb(dev) : pm_generic_suspend_late(dev);
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +01001681}
1682
1683/**
1684 * pm_genpd_default_resume_early - Default "early device resume" for PM domians.
1685 * @dev: Device to handle.
1686 */
1687static int pm_genpd_default_resume_early(struct device *dev)
1688{
Rafael J. Wysockic9914852011-12-06 23:16:47 +01001689 int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.resume_early;
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +01001690
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001691 return cb ? cb(dev) : pm_generic_resume_early(dev);
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +01001692}
1693
1694/**
1695 * pm_genpd_default_resume - Default "device resume" for PM domians.
1696 * @dev: Device to handle.
1697 */
1698static int pm_genpd_default_resume(struct device *dev)
1699{
Rafael J. Wysockic9914852011-12-06 23:16:47 +01001700 int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.resume;
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +01001701
1702 return cb ? cb(dev) : pm_generic_resume(dev);
1703}
1704
1705/**
1706 * pm_genpd_default_freeze - Default "device freeze" for PM domians.
1707 * @dev: Device to handle.
1708 */
1709static int pm_genpd_default_freeze(struct device *dev)
1710{
1711 int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.freeze;
1712
1713 return cb ? cb(dev) : pm_generic_freeze(dev);
1714}
1715
1716/**
1717 * pm_genpd_default_freeze_late - Default "late device freeze" for PM domians.
1718 * @dev: Device to handle.
1719 */
1720static int pm_genpd_default_freeze_late(struct device *dev)
1721{
1722 int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.freeze_late;
1723
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001724 return cb ? cb(dev) : pm_generic_freeze_late(dev);
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +01001725}
1726
1727/**
1728 * pm_genpd_default_thaw_early - Default "early device thaw" for PM domians.
1729 * @dev: Device to handle.
1730 */
1731static int pm_genpd_default_thaw_early(struct device *dev)
1732{
1733 int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.thaw_early;
1734
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001735 return cb ? cb(dev) : pm_generic_thaw_early(dev);
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +01001736}
1737
1738/**
1739 * pm_genpd_default_thaw - Default "device thaw" for PM domians.
1740 * @dev: Device to handle.
1741 */
1742static int pm_genpd_default_thaw(struct device *dev)
1743{
1744 int (*cb)(struct device *__dev) = dev_gpd_data(dev)->ops.thaw;
1745
1746 return cb ? cb(dev) : pm_generic_thaw(dev);
1747}
1748
Rafael J. Wysocki0f1d6982012-01-14 00:39:25 +01001749#else /* !CONFIG_PM_SLEEP */
1750
1751#define pm_genpd_default_suspend NULL
1752#define pm_genpd_default_suspend_late NULL
1753#define pm_genpd_default_resume_early NULL
1754#define pm_genpd_default_resume NULL
1755#define pm_genpd_default_freeze NULL
1756#define pm_genpd_default_freeze_late NULL
1757#define pm_genpd_default_thaw_early NULL
1758#define pm_genpd_default_thaw NULL
1759
1760#endif /* !CONFIG_PM_SLEEP */
1761
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +01001762/**
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001763 * pm_genpd_init - Initialize a generic I/O PM domain object.
1764 * @genpd: PM domain object to initialize.
1765 * @gov: PM domain governor to associate with the domain (may be NULL).
1766 * @is_off: Initial value of the domain's power_is_off field.
1767 */
1768void pm_genpd_init(struct generic_pm_domain *genpd,
1769 struct dev_power_governor *gov, bool is_off)
1770{
1771 if (IS_ERR_OR_NULL(genpd))
1772 return;
1773
Rafael J. Wysocki5063ce12011-08-08 23:43:40 +02001774 INIT_LIST_HEAD(&genpd->master_links);
1775 INIT_LIST_HEAD(&genpd->slave_links);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001776 INIT_LIST_HEAD(&genpd->dev_list);
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001777 mutex_init(&genpd->lock);
1778 genpd->gov = gov;
1779 INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
1780 genpd->in_progress = 0;
Rafael J. Wysockic4bb3162011-08-08 23:43:04 +02001781 atomic_set(&genpd->sd_count, 0);
Rafael J. Wysocki17b75ec2011-07-12 00:39:29 +02001782 genpd->status = is_off ? GPD_STATE_POWER_OFF : GPD_STATE_ACTIVE;
1783 init_waitqueue_head(&genpd->status_wait_queue);
Rafael J. Wysockic6d22b32011-07-12 00:39:36 +02001784 genpd->poweroff_task = NULL;
1785 genpd->resume_count = 0;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001786 genpd->device_count = 0;
Rafael J. Wysocki221e9b52011-12-01 00:02:10 +01001787 genpd->max_off_time_ns = -1;
Rafael J. Wysocki6ff7bb0d02012-05-01 21:34:07 +02001788 genpd->max_off_time_changed = true;
Rafael J. Wysockif7218892011-07-01 22:12:45 +02001789 genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend;
1790 genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume;
1791 genpd->domain.ops.runtime_idle = pm_generic_runtime_idle;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001792 genpd->domain.ops.prepare = pm_genpd_prepare;
1793 genpd->domain.ops.suspend = pm_genpd_suspend;
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001794 genpd->domain.ops.suspend_late = pm_genpd_suspend_late;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001795 genpd->domain.ops.suspend_noirq = pm_genpd_suspend_noirq;
1796 genpd->domain.ops.resume_noirq = pm_genpd_resume_noirq;
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001797 genpd->domain.ops.resume_early = pm_genpd_resume_early;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001798 genpd->domain.ops.resume = pm_genpd_resume;
1799 genpd->domain.ops.freeze = pm_genpd_freeze;
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001800 genpd->domain.ops.freeze_late = pm_genpd_freeze_late;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001801 genpd->domain.ops.freeze_noirq = pm_genpd_freeze_noirq;
1802 genpd->domain.ops.thaw_noirq = pm_genpd_thaw_noirq;
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001803 genpd->domain.ops.thaw_early = pm_genpd_thaw_early;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001804 genpd->domain.ops.thaw = pm_genpd_thaw;
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +01001805 genpd->domain.ops.poweroff = pm_genpd_suspend;
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001806 genpd->domain.ops.poweroff_late = pm_genpd_suspend_late;
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +01001807 genpd->domain.ops.poweroff_noirq = pm_genpd_suspend_noirq;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001808 genpd->domain.ops.restore_noirq = pm_genpd_restore_noirq;
Rafael J. Wysocki0496c8a2012-01-29 20:39:02 +01001809 genpd->domain.ops.restore_early = pm_genpd_resume_early;
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +01001810 genpd->domain.ops.restore = pm_genpd_resume;
Rafael J. Wysocki596ba342011-07-01 22:13:19 +02001811 genpd->domain.ops.complete = pm_genpd_complete;
Rafael J. Wysockiecf00472011-11-27 13:11:44 +01001812 genpd->dev_ops.save_state = pm_genpd_default_save_state;
1813 genpd->dev_ops.restore_state = pm_genpd_default_restore_state;
Rafael J. Wysockic9914852011-12-06 23:16:47 +01001814 genpd->dev_ops.suspend = pm_genpd_default_suspend;
1815 genpd->dev_ops.suspend_late = pm_genpd_default_suspend_late;
1816 genpd->dev_ops.resume_early = pm_genpd_default_resume_early;
1817 genpd->dev_ops.resume = pm_genpd_default_resume;
Rafael J. Wysockid23b9b02011-11-27 13:11:51 +01001818 genpd->dev_ops.freeze = pm_genpd_default_freeze;
1819 genpd->dev_ops.freeze_late = pm_genpd_default_freeze_late;
1820 genpd->dev_ops.thaw_early = pm_genpd_default_thaw_early;
1821 genpd->dev_ops.thaw = pm_genpd_default_thaw;
Rafael J. Wysocki5125bbf2011-07-13 12:31:52 +02001822 mutex_lock(&gpd_list_lock);
1823 list_add(&genpd->gpd_list_node, &gpd_list);
1824 mutex_unlock(&gpd_list_lock);
1825}