diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2012-02-15 14:28:38 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2012-02-15 14:28:38 -0500 |
commit | 8682df25ca9afd3aac30f2c72d00bd98de2118e8 (patch) | |
tree | 6c0f5c1e9797a5b908a1b57d21cdf16c69911154 /drivers | |
parent | 9b612fa627105af2738d9205554e2a6dc8d32228 (diff) | |
parent | 41c7f7424259ff11009449f87c95656f69f9b186 (diff) |
Merge branch 'fortglx/3.4/rtc' of git://git.linaro.org/people/jstultz/linux into timers/core
Diffstat (limited to 'drivers')
-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 | } |