| From 1330bb213d5359301a54b8a8bee21fdec208be57 Mon Sep 17 00:00:00 2001 |
| From: "Rafael J. Wysocki" <rjw@sisk.pl> |
| Date: Fri, 1 Jul 2011 22:13:29 +0200 |
| Subject: PM / Domains: Wakeup devices support for system sleep transitions |
| |
| There is the problem how to handle devices set up to wake up the |
| system from sleep states during system-wide power transitions. |
| In some cases, those devices can be turned off entirely, because the |
| wakeup signals will be generated on their behalf anyway. In some |
| other cases, they will generate wakeup signals if their clocks are |
| stopped, but only if power is not removed from them. Finally, in |
| some cases, they can only generate wakeup signals if power is not |
| removed from them and their clocks are enabled. |
| |
| To allow platform-specific code to decide whether or not to put |
| wakeup devices (and their PM domains) into low-power state during |
| system-wide transitions, such as system suspend, introduce a new |
| generic PM domain callback, .active_wakeup(), that will be used |
| during the "noirq" phase of system suspend and hibernation (after |
| image creation) to decide what to do with wakeup devices. |
| Specifically, if this callback is present and returns "true", the |
| generic PM domain code will not execute .stop_device() for the |
| given wakeup device and its PM domain won't be powered off. |
| |
| Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> |
| Acked-by: Kevin Hilman <khilman@ti.com> |
| (cherry picked from commit d4f2d87a8b46c14c4307c690c92bd08229f66ecf) |
| |
| Signed-off-by: Simon Horman <horms@verge.net.au> |
| --- |
| drivers/base/power/domain.c | 8 ++++++++ |
| include/linux/pm_domain.h | 1 + |
| 2 files changed, 9 insertions(+) |
| |
| diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c |
| index 33086e9..1aed94c 100644 |
| --- a/drivers/base/power/domain.c |
| +++ b/drivers/base/power/domain.c |
| @@ -450,6 +450,10 @@ static int pm_genpd_suspend_noirq(struct device *dev) |
| if (ret) |
| return ret; |
| |
| + if (device_may_wakeup(dev) |
| + && genpd->active_wakeup && genpd->active_wakeup(dev)) |
| + return 0; |
| + |
| if (genpd->stop_device) |
| genpd->stop_device(dev); |
| |
| @@ -670,6 +674,10 @@ static int pm_genpd_dev_poweroff_noirq(struct device *dev) |
| if (ret) |
| return ret; |
| |
| + if (device_may_wakeup(dev) |
| + && genpd->active_wakeup && genpd->active_wakeup(dev)) |
| + return 0; |
| + |
| if (genpd->stop_device) |
| genpd->stop_device(dev); |
| |
| diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h |
| index 7961b0d..98491ee 100644 |
| --- a/include/linux/pm_domain.h |
| +++ b/include/linux/pm_domain.h |
| @@ -38,6 +38,7 @@ struct generic_pm_domain { |
| int (*power_on)(struct generic_pm_domain *domain); |
| int (*start_device)(struct device *dev); |
| int (*stop_device)(struct device *dev); |
| + bool (*active_wakeup)(struct device *dev); |
| }; |
| |
| static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd) |
| -- |
| 1.7.10.1.362.g242cab3 |
| |