diff options
Diffstat (limited to 'drivers/rtc/interface.c')
-rw-r--r-- | drivers/rtc/interface.c | 50 |
1 files changed, 40 insertions, 10 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 8e286259a007..3bcc7cfcaba7 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
@@ -73,6 +73,8 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm) | |||
73 | err = -EINVAL; | 73 | err = -EINVAL; |
74 | 74 | ||
75 | mutex_unlock(&rtc->ops_lock); | 75 | mutex_unlock(&rtc->ops_lock); |
76 | /* A timer might have just expired */ | ||
77 | schedule_work(&rtc->irqwork); | ||
76 | return err; | 78 | return err; |
77 | } | 79 | } |
78 | EXPORT_SYMBOL_GPL(rtc_set_time); | 80 | EXPORT_SYMBOL_GPL(rtc_set_time); |
@@ -112,6 +114,8 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs) | |||
112 | err = -EINVAL; | 114 | err = -EINVAL; |
113 | 115 | ||
114 | mutex_unlock(&rtc->ops_lock); | 116 | mutex_unlock(&rtc->ops_lock); |
117 | /* A timer might have just expired */ | ||
118 | schedule_work(&rtc->irqwork); | ||
115 | 119 | ||
116 | return err; | 120 | return err; |
117 | } | 121 | } |
@@ -319,6 +323,20 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
319 | } | 323 | } |
320 | EXPORT_SYMBOL_GPL(rtc_read_alarm); | 324 | EXPORT_SYMBOL_GPL(rtc_read_alarm); |
321 | 325 | ||
326 | static int ___rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | ||
327 | { | ||
328 | int err; | ||
329 | |||
330 | if (!rtc->ops) | ||
331 | err = -ENODEV; | ||
332 | else if (!rtc->ops->set_alarm) | ||
333 | err = -EINVAL; | ||
334 | else | ||
335 | err = rtc->ops->set_alarm(rtc->dev.parent, alarm); | ||
336 | |||
337 | return err; | ||
338 | } | ||
339 | |||
322 | static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | 340 | static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |
323 | { | 341 | { |
324 | struct rtc_time tm; | 342 | struct rtc_time tm; |
@@ -342,14 +360,7 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
342 | * over right here, before we set the alarm. | 360 | * over right here, before we set the alarm. |
343 | */ | 361 | */ |
344 | 362 | ||
345 | if (!rtc->ops) | 363 | return ___rtc_set_alarm(rtc, alarm); |
346 | err = -ENODEV; | ||
347 | else if (!rtc->ops->set_alarm) | ||
348 | err = -EINVAL; | ||
349 | else | ||
350 | err = rtc->ops->set_alarm(rtc->dev.parent, alarm); | ||
351 | |||
352 | return err; | ||
353 | } | 364 | } |
354 | 365 | ||
355 | int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | 366 | int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |
@@ -396,6 +407,8 @@ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
396 | timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node); | 407 | timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node); |
397 | } | 408 | } |
398 | mutex_unlock(&rtc->ops_lock); | 409 | mutex_unlock(&rtc->ops_lock); |
410 | /* maybe that was in the past.*/ | ||
411 | schedule_work(&rtc->irqwork); | ||
399 | return err; | 412 | return err; |
400 | } | 413 | } |
401 | EXPORT_SYMBOL_GPL(rtc_initialize_alarm); | 414 | EXPORT_SYMBOL_GPL(rtc_initialize_alarm); |
@@ -763,6 +776,20 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) | |||
763 | return 0; | 776 | return 0; |
764 | } | 777 | } |
765 | 778 | ||
779 | static void rtc_alarm_disable(struct rtc_device *rtc) | ||
780 | { | ||
781 | struct rtc_wkalrm alarm; | ||
782 | struct rtc_time tm; | ||
783 | |||
784 | __rtc_read_time(rtc, &tm); | ||
785 | |||
786 | alarm.time = rtc_ktime_to_tm(ktime_add(rtc_tm_to_ktime(tm), | ||
787 | ktime_set(300, 0))); | ||
788 | alarm.enabled = 0; | ||
789 | |||
790 | ___rtc_set_alarm(rtc, &alarm); | ||
791 | } | ||
792 | |||
766 | /** | 793 | /** |
767 | * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue | 794 | * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue |
768 | * @rtc rtc device | 795 | * @rtc rtc device |
@@ -784,8 +811,10 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) | |||
784 | struct rtc_wkalrm alarm; | 811 | struct rtc_wkalrm alarm; |
785 | int err; | 812 | int err; |
786 | next = timerqueue_getnext(&rtc->timerqueue); | 813 | next = timerqueue_getnext(&rtc->timerqueue); |
787 | if (!next) | 814 | if (!next) { |
815 | rtc_alarm_disable(rtc); | ||
788 | return; | 816 | return; |
817 | } | ||
789 | alarm.time = rtc_ktime_to_tm(next->expires); | 818 | alarm.time = rtc_ktime_to_tm(next->expires); |
790 | alarm.enabled = 1; | 819 | alarm.enabled = 1; |
791 | err = __rtc_set_alarm(rtc, &alarm); | 820 | err = __rtc_set_alarm(rtc, &alarm); |
@@ -847,7 +876,8 @@ again: | |||
847 | err = __rtc_set_alarm(rtc, &alarm); | 876 | err = __rtc_set_alarm(rtc, &alarm); |
848 | if (err == -ETIME) | 877 | if (err == -ETIME) |
849 | goto again; | 878 | goto again; |
850 | } | 879 | } else |
880 | rtc_alarm_disable(rtc); | ||
851 | 881 | ||
852 | mutex_unlock(&rtc->ops_lock); | 882 | mutex_unlock(&rtc->ops_lock); |
853 | } | 883 | } |