aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/interface.c
diff options
context:
space:
mode:
authorRabin Vincent <rabin.vincent@stericsson.com>2011-11-22 05:03:14 -0500
committerJohn Stultz <john.stultz@linaro.org>2011-11-22 22:25:43 -0500
commitc0afabd3d553c521e003779c127143ffde55a16f (patch)
tree5a4a93f244e2e9cbc87f24958de3e83397f978fb /drivers/rtc/interface.c
parent27c9cd7e601632b3794e1c3344d37b86917ffb43 (diff)
rtc: Disable the alarm in the hardware
Currently, the RTC code does not disable the alarm in the hardware. This means that after a sequence such as the one below (the files are in the RTC sysfs), the box will boot up after 2 minutes even though we've asked for the alarm to be turned off. # echo $((`cat since_epoch`)+120) > wakealarm # echo 0 > wakealarm # poweroff Fix this by disabling the alarm when there are no timers to run. Cc: stable@kernel.org Cc: John Stultz <john.stultz@linaro.org> Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com> Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'drivers/rtc/interface.c')
-rw-r--r--drivers/rtc/interface.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 3195dbd3ec34..e3cf2f54221f 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -318,6 +318,20 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
318} 318}
319EXPORT_SYMBOL_GPL(rtc_read_alarm); 319EXPORT_SYMBOL_GPL(rtc_read_alarm);
320 320
321static int ___rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
322{
323 int err;
324
325 if (!rtc->ops)
326 err = -ENODEV;
327 else if (!rtc->ops->set_alarm)
328 err = -EINVAL;
329 else
330 err = rtc->ops->set_alarm(rtc->dev.parent, alarm);
331
332 return err;
333}
334
321static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) 335static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
322{ 336{
323 struct rtc_time tm; 337 struct rtc_time tm;
@@ -341,14 +355,7 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
341 * over right here, before we set the alarm. 355 * over right here, before we set the alarm.
342 */ 356 */
343 357
344 if (!rtc->ops) 358 return ___rtc_set_alarm(rtc, alarm);
345 err = -ENODEV;
346 else if (!rtc->ops->set_alarm)
347 err = -EINVAL;
348 else
349 err = rtc->ops->set_alarm(rtc->dev.parent, alarm);
350
351 return err;
352} 359}
353 360
354int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) 361int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
@@ -762,6 +769,20 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
762 return 0; 769 return 0;
763} 770}
764 771
772static void rtc_alarm_disable(struct rtc_device *rtc)
773{
774 struct rtc_wkalrm alarm;
775 struct rtc_time tm;
776
777 __rtc_read_time(rtc, &tm);
778
779 alarm.time = rtc_ktime_to_tm(ktime_add(rtc_tm_to_ktime(tm),
780 ktime_set(300, 0)));
781 alarm.enabled = 0;
782
783 ___rtc_set_alarm(rtc, &alarm);
784}
785
765/** 786/**
766 * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue 787 * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue
767 * @rtc rtc device 788 * @rtc rtc device
@@ -783,8 +804,10 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer)
783 struct rtc_wkalrm alarm; 804 struct rtc_wkalrm alarm;
784 int err; 805 int err;
785 next = timerqueue_getnext(&rtc->timerqueue); 806 next = timerqueue_getnext(&rtc->timerqueue);
786 if (!next) 807 if (!next) {
808 rtc_alarm_disable(rtc);
787 return; 809 return;
810 }
788 alarm.time = rtc_ktime_to_tm(next->expires); 811 alarm.time = rtc_ktime_to_tm(next->expires);
789 alarm.enabled = 1; 812 alarm.enabled = 1;
790 err = __rtc_set_alarm(rtc, &alarm); 813 err = __rtc_set_alarm(rtc, &alarm);
@@ -846,7 +869,8 @@ again:
846 err = __rtc_set_alarm(rtc, &alarm); 869 err = __rtc_set_alarm(rtc, &alarm);
847 if (err == -ETIME) 870 if (err == -ETIME)
848 goto again; 871 goto again;
849 } 872 } else
873 rtc_alarm_disable(rtc);
850 874
851 mutex_unlock(&rtc->ops_lock); 875 mutex_unlock(&rtc->ops_lock);
852} 876}