Commit 119434f4 authored by Stefan Agner's avatar Stefan Agner Committed by Alexandre Belloni
Browse files

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: 7654e9d4 ("drivers/rtc/rtc-snvs: fix suspend/resume")
Cc:  <stable@vger.kernel.org> # 3.19
Signed-off-by: default avatarStefan Agner <stefan@agner.ch>
Signed-off-by: default avatarAlexandre Belloni <alexandre.belloni@free-electrons.com>
parent 6c95fa80
Loading
Loading
Loading
Loading
+21 −9
Original line number Diff line number Diff line
@@ -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)