diff options
author | Stefan Agner <stefan@agner.ch> | 2015-05-21 17:29:35 +0200 |
---|---|---|
committer | Alexandre Belloni <alexandre.belloni@free-electrons.com> | 2015-06-25 01:13:38 +0200 |
commit | 119434f44c78df8c4b6d67f835448542a4bd7e91 (patch) | |
tree | 2b04a007a701505d64b3107e33117a19cb9209f0 /drivers/rtc | |
parent | 6c95fa80e6f3e111b738949111a94bfac5021721 (diff) |
rtc: snvs: fix wakealarm by call enable_irq_wake earlier
When entering suspend while an wakeup alarm is set, enable_set_wake
should make sure that the RTC interrupt keep being enabled and the
.irq_set_wake for the RTC interrupt get called. However, since the
driver uses the suspend_noirq callback, the call to enable_irq_wake
has been made after disabling the interrupts. While .irq_set_wake
has been called properly, the interrupt remained disabled.
Use the suspend callback to call enable_irq_wake early enough to
ensure the RTC interrupt remains enabled.
Fixes: 7654e9d4fd8f ("drivers/rtc/rtc-snvs: fix suspend/resume")
Cc: <stable@vger.kernel.org> # 3.19
Signed-off-by: Stefan Agner <stefan@agner.ch>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Diffstat (limited to 'drivers/rtc')
-rw-r--r-- | drivers/rtc/rtc-snvs.c | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c index 0479e807a776..d87a85cefb66 100644 --- a/drivers/rtc/rtc-snvs.c +++ b/drivers/rtc/rtc-snvs.c @@ -322,6 +322,13 @@ static int snvs_rtc_suspend(struct device *dev) if (device_may_wakeup(dev)) enable_irq_wake(data->irq); + return 0; +} + +static int snvs_rtc_suspend_noirq(struct device *dev) +{ + struct snvs_rtc_data *data = dev_get_drvdata(dev); + if (data->clk) clk_disable_unprepare(data->clk); @@ -331,23 +338,28 @@ static int snvs_rtc_suspend(struct device *dev) static int snvs_rtc_resume(struct device *dev) { struct snvs_rtc_data *data = dev_get_drvdata(dev); - int ret; if (device_may_wakeup(dev)) - disable_irq_wake(data->irq); + return disable_irq_wake(data->irq); - if (data->clk) { - ret = clk_prepare_enable(data->clk); - if (ret) - return ret; - } + return 0; +} + +static int snvs_rtc_resume_noirq(struct device *dev) +{ + struct snvs_rtc_data *data = dev_get_drvdata(dev); + + if (data->clk) + return clk_prepare_enable(data->clk); return 0; } static const struct dev_pm_ops snvs_rtc_pm_ops = { - .suspend_noirq = snvs_rtc_suspend, - .resume_noirq = snvs_rtc_resume, + .suspend = snvs_rtc_suspend, + .suspend_noirq = snvs_rtc_suspend_noirq, + .resume = snvs_rtc_resume, + .resume_noirq = snvs_rtc_resume_noirq, }; #define SNVS_RTC_PM_OPS (&snvs_rtc_pm_ops) |