diff options
Diffstat (limited to 'drivers/base/power')
-rw-r--r-- | drivers/base/power/domain.c | 68 |
1 files changed, 56 insertions, 12 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 94afaa2686a6..3c9451b10427 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c | |||
@@ -56,6 +56,16 @@ static int genpd_start_dev(struct generic_pm_domain *genpd, struct device *dev) | |||
56 | return GENPD_DEV_CALLBACK(genpd, int, start, dev); | 56 | return GENPD_DEV_CALLBACK(genpd, int, start, dev); |
57 | } | 57 | } |
58 | 58 | ||
59 | static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev) | ||
60 | { | ||
61 | return GENPD_DEV_CALLBACK(genpd, int, save_state, dev); | ||
62 | } | ||
63 | |||
64 | static int genpd_restore_dev(struct generic_pm_domain *genpd, struct device *dev) | ||
65 | { | ||
66 | return GENPD_DEV_CALLBACK(genpd, int, restore_state, dev); | ||
67 | } | ||
68 | |||
59 | static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd) | 69 | static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd) |
60 | { | 70 | { |
61 | bool ret = false; | 71 | bool ret = false; |
@@ -217,7 +227,6 @@ static int __pm_genpd_save_device(struct pm_domain_data *pdd, | |||
217 | { | 227 | { |
218 | struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd); | 228 | struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd); |
219 | struct device *dev = pdd->dev; | 229 | struct device *dev = pdd->dev; |
220 | struct device_driver *drv = dev->driver; | ||
221 | int ret = 0; | 230 | int ret = 0; |
222 | 231 | ||
223 | if (gpd_data->need_restore) | 232 | if (gpd_data->need_restore) |
@@ -225,11 +234,9 @@ static int __pm_genpd_save_device(struct pm_domain_data *pdd, | |||
225 | 234 | ||
226 | mutex_unlock(&genpd->lock); | 235 | mutex_unlock(&genpd->lock); |
227 | 236 | ||
228 | if (drv && drv->pm && drv->pm->runtime_suspend) { | 237 | genpd_start_dev(genpd, dev); |
229 | genpd_start_dev(genpd, dev); | 238 | ret = genpd_save_dev(genpd, dev); |
230 | ret = drv->pm->runtime_suspend(dev); | 239 | genpd_stop_dev(genpd, dev); |
231 | genpd_stop_dev(genpd, dev); | ||
232 | } | ||
233 | 240 | ||
234 | mutex_lock(&genpd->lock); | 241 | mutex_lock(&genpd->lock); |
235 | 242 | ||
@@ -250,18 +257,15 @@ static void __pm_genpd_restore_device(struct pm_domain_data *pdd, | |||
250 | { | 257 | { |
251 | struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd); | 258 | struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd); |
252 | struct device *dev = pdd->dev; | 259 | struct device *dev = pdd->dev; |
253 | struct device_driver *drv = dev->driver; | ||
254 | 260 | ||
255 | if (!gpd_data->need_restore) | 261 | if (!gpd_data->need_restore) |
256 | return; | 262 | return; |
257 | 263 | ||
258 | mutex_unlock(&genpd->lock); | 264 | mutex_unlock(&genpd->lock); |
259 | 265 | ||
260 | if (drv && drv->pm && drv->pm->runtime_resume) { | 266 | genpd_start_dev(genpd, dev); |
261 | genpd_start_dev(genpd, dev); | 267 | genpd_restore_dev(genpd, dev); |
262 | drv->pm->runtime_resume(dev); | 268 | genpd_stop_dev(genpd, dev); |
263 | genpd_stop_dev(genpd, dev); | ||
264 | } | ||
265 | 269 | ||
266 | mutex_lock(&genpd->lock); | 270 | mutex_lock(&genpd->lock); |
267 | 271 | ||
@@ -1358,6 +1362,44 @@ int pm_genpd_remove_callbacks(struct device *dev) | |||
1358 | EXPORT_SYMBOL_GPL(pm_genpd_remove_callbacks); | 1362 | EXPORT_SYMBOL_GPL(pm_genpd_remove_callbacks); |
1359 | 1363 | ||
1360 | /** | 1364 | /** |
1365 | * pm_genpd_default_save_state - Default "save device state" for PM domians. | ||
1366 | * @dev: Device to handle. | ||
1367 | */ | ||
1368 | static int pm_genpd_default_save_state(struct device *dev) | ||
1369 | { | ||
1370 | int (*cb)(struct device *__dev); | ||
1371 | struct device_driver *drv = dev->driver; | ||
1372 | |||
1373 | cb = dev_gpd_data(dev)->ops.save_state; | ||
1374 | if (cb) | ||
1375 | return cb(dev); | ||
1376 | |||
1377 | if (drv && drv->pm && drv->pm->runtime_suspend) | ||
1378 | return drv->pm->runtime_suspend(dev); | ||
1379 | |||
1380 | return 0; | ||
1381 | } | ||
1382 | |||
1383 | /** | ||
1384 | * pm_genpd_default_restore_state - Default PM domians "restore device state". | ||
1385 | * @dev: Device to handle. | ||
1386 | */ | ||
1387 | static int pm_genpd_default_restore_state(struct device *dev) | ||
1388 | { | ||
1389 | int (*cb)(struct device *__dev); | ||
1390 | struct device_driver *drv = dev->driver; | ||
1391 | |||
1392 | cb = dev_gpd_data(dev)->ops.restore_state; | ||
1393 | if (cb) | ||
1394 | return cb(dev); | ||
1395 | |||
1396 | if (drv && drv->pm && drv->pm->runtime_resume) | ||
1397 | return drv->pm->runtime_resume(dev); | ||
1398 | |||
1399 | return 0; | ||
1400 | } | ||
1401 | |||
1402 | /** | ||
1361 | * pm_genpd_init - Initialize a generic I/O PM domain object. | 1403 | * pm_genpd_init - Initialize a generic I/O PM domain object. |
1362 | * @genpd: PM domain object to initialize. | 1404 | * @genpd: PM domain object to initialize. |
1363 | * @gov: PM domain governor to associate with the domain (may be NULL). | 1405 | * @gov: PM domain governor to associate with the domain (may be NULL). |
@@ -1400,6 +1442,8 @@ void pm_genpd_init(struct generic_pm_domain *genpd, | |||
1400 | genpd->domain.ops.restore_noirq = pm_genpd_restore_noirq; | 1442 | genpd->domain.ops.restore_noirq = pm_genpd_restore_noirq; |
1401 | genpd->domain.ops.restore = pm_genpd_restore; | 1443 | genpd->domain.ops.restore = pm_genpd_restore; |
1402 | genpd->domain.ops.complete = pm_genpd_complete; | 1444 | genpd->domain.ops.complete = pm_genpd_complete; |
1445 | genpd->dev_ops.save_state = pm_genpd_default_save_state; | ||
1446 | genpd->dev_ops.restore_state = pm_genpd_default_restore_state; | ||
1403 | mutex_lock(&gpd_list_lock); | 1447 | mutex_lock(&gpd_list_lock); |
1404 | list_add(&genpd->gpd_list_node, &gpd_list); | 1448 | list_add(&genpd->gpd_list_node, &gpd_list); |
1405 | mutex_unlock(&gpd_list_lock); | 1449 | mutex_unlock(&gpd_list_lock); |