diff options
Diffstat (limited to 'drivers/rtc/interface.c')
| -rw-r--r-- | drivers/rtc/interface.c | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 8a1c031391d6..dc87eda65814 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 | } |
| @@ -380,18 +384,27 @@ EXPORT_SYMBOL_GPL(rtc_set_alarm); | |||
| 380 | int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | 384 | int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |
| 381 | { | 385 | { |
| 382 | int err; | 386 | int err; |
| 387 | struct rtc_time now; | ||
| 383 | 388 | ||
| 384 | err = rtc_valid_tm(&alarm->time); | 389 | err = rtc_valid_tm(&alarm->time); |
| 385 | if (err != 0) | 390 | if (err != 0) |
| 386 | return err; | 391 | return err; |
| 387 | 392 | ||
| 393 | err = rtc_read_time(rtc, &now); | ||
| 394 | if (err) | ||
| 395 | return err; | ||
| 396 | |||
| 388 | err = mutex_lock_interruptible(&rtc->ops_lock); | 397 | err = mutex_lock_interruptible(&rtc->ops_lock); |
| 389 | if (err) | 398 | if (err) |
| 390 | return err; | 399 | return err; |
| 391 | 400 | ||
| 392 | rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); | 401 | rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); |
| 393 | rtc->aie_timer.period = ktime_set(0, 0); | 402 | rtc->aie_timer.period = ktime_set(0, 0); |
| 394 | if (alarm->enabled) { | 403 | |
| 404 | /* Alarm has to be enabled & in the futrure for us to enqueue it */ | ||
| 405 | if (alarm->enabled && (rtc_tm_to_ktime(now).tv64 < | ||
| 406 | rtc->aie_timer.node.expires.tv64)) { | ||
| 407 | |||
| 395 | rtc->aie_timer.enabled = 1; | 408 | rtc->aie_timer.enabled = 1; |
| 396 | timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node); | 409 | timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node); |
| 397 | } | 410 | } |
| @@ -763,6 +776,14 @@ 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 | if (!rtc->ops || !rtc->ops->alarm_irq_enable) | ||
| 782 | return; | ||
| 783 | |||
| 784 | rtc->ops->alarm_irq_enable(rtc->dev.parent, false); | ||
| 785 | } | ||
| 786 | |||
| 766 | /** | 787 | /** |
| 767 | * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue | 788 | * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue |
| 768 | * @rtc rtc device | 789 | * @rtc rtc device |
| @@ -784,8 +805,10 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) | |||
| 784 | struct rtc_wkalrm alarm; | 805 | struct rtc_wkalrm alarm; |
| 785 | int err; | 806 | int err; |
| 786 | next = timerqueue_getnext(&rtc->timerqueue); | 807 | next = timerqueue_getnext(&rtc->timerqueue); |
| 787 | if (!next) | 808 | if (!next) { |
| 809 | rtc_alarm_disable(rtc); | ||
| 788 | return; | 810 | return; |
| 811 | } | ||
| 789 | alarm.time = rtc_ktime_to_tm(next->expires); | 812 | alarm.time = rtc_ktime_to_tm(next->expires); |
| 790 | alarm.enabled = 1; | 813 | alarm.enabled = 1; |
| 791 | err = __rtc_set_alarm(rtc, &alarm); | 814 | err = __rtc_set_alarm(rtc, &alarm); |
| @@ -847,7 +870,8 @@ again: | |||
| 847 | err = __rtc_set_alarm(rtc, &alarm); | 870 | err = __rtc_set_alarm(rtc, &alarm); |
| 848 | if (err == -ETIME) | 871 | if (err == -ETIME) |
| 849 | goto again; | 872 | goto again; |
| 850 | } | 873 | } else |
| 874 | rtc_alarm_disable(rtc); | ||
| 851 | 875 | ||
| 852 | mutex_unlock(&rtc->ops_lock); | 876 | mutex_unlock(&rtc->ops_lock); |
| 853 | } | 877 | } |
