diff options
Diffstat (limited to 'drivers/rtc/interface.c')
-rw-r--r-- | drivers/rtc/interface.c | 99 |
1 files changed, 52 insertions, 47 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 28bd767e03a0..ccb7d6b4da3b 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
@@ -84,11 +84,12 @@ static int rtc_valid_range(struct rtc_device *rtc, struct rtc_time *tm) | |||
84 | static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) | 84 | static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) |
85 | { | 85 | { |
86 | int err; | 86 | int err; |
87 | if (!rtc->ops) | 87 | |
88 | if (!rtc->ops) { | ||
88 | err = -ENODEV; | 89 | err = -ENODEV; |
89 | else if (!rtc->ops->read_time) | 90 | } else if (!rtc->ops->read_time) { |
90 | err = -EINVAL; | 91 | err = -EINVAL; |
91 | else { | 92 | } else { |
92 | memset(tm, 0, sizeof(struct rtc_time)); | 93 | memset(tm, 0, sizeof(struct rtc_time)); |
93 | err = rtc->ops->read_time(rtc->dev.parent, tm); | 94 | err = rtc->ops->read_time(rtc->dev.parent, tm); |
94 | if (err < 0) { | 95 | if (err < 0) { |
@@ -144,14 +145,13 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm) | |||
144 | err = -ENODEV; | 145 | err = -ENODEV; |
145 | else if (rtc->ops->set_time) | 146 | else if (rtc->ops->set_time) |
146 | err = rtc->ops->set_time(rtc->dev.parent, tm); | 147 | err = rtc->ops->set_time(rtc->dev.parent, tm); |
147 | else if (rtc->ops->set_mmss64) { | 148 | else if (rtc->ops->set_mmss64) |
148 | time64_t secs64 = rtc_tm_to_time64(tm); | 149 | err = rtc->ops->set_mmss64(rtc->dev.parent, |
149 | 150 | rtc_tm_to_time64(tm)); | |
150 | err = rtc->ops->set_mmss64(rtc->dev.parent, secs64); | 151 | else if (rtc->ops->set_mmss) |
151 | } else if (rtc->ops->set_mmss) { | 152 | err = rtc->ops->set_mmss(rtc->dev.parent, |
152 | time64_t secs64 = rtc_tm_to_time64(tm); | 153 | rtc_tm_to_time64(tm)); |
153 | err = rtc->ops->set_mmss(rtc->dev.parent, secs64); | 154 | else |
154 | } else | ||
155 | err = -EINVAL; | 155 | err = -EINVAL; |
156 | 156 | ||
157 | pm_stay_awake(rtc->dev.parent); | 157 | pm_stay_awake(rtc->dev.parent); |
@@ -164,7 +164,8 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm) | |||
164 | } | 164 | } |
165 | EXPORT_SYMBOL_GPL(rtc_set_time); | 165 | EXPORT_SYMBOL_GPL(rtc_set_time); |
166 | 166 | ||
167 | static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | 167 | static int rtc_read_alarm_internal(struct rtc_device *rtc, |
168 | struct rtc_wkalrm *alarm) | ||
168 | { | 169 | { |
169 | int err; | 170 | int err; |
170 | 171 | ||
@@ -172,11 +173,11 @@ static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *al | |||
172 | if (err) | 173 | if (err) |
173 | return err; | 174 | return err; |
174 | 175 | ||
175 | if (rtc->ops == NULL) | 176 | if (!rtc->ops) { |
176 | err = -ENODEV; | 177 | err = -ENODEV; |
177 | else if (!rtc->ops->read_alarm) | 178 | } else if (!rtc->ops->read_alarm) { |
178 | err = -EINVAL; | 179 | err = -EINVAL; |
179 | else { | 180 | } else { |
180 | alarm->enabled = 0; | 181 | alarm->enabled = 0; |
181 | alarm->pending = 0; | 182 | alarm->pending = 0; |
182 | alarm->time.tm_sec = -1; | 183 | alarm->time.tm_sec = -1; |
@@ -204,7 +205,7 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
204 | int first_time = 1; | 205 | int first_time = 1; |
205 | time64_t t_now, t_alm; | 206 | time64_t t_now, t_alm; |
206 | enum { none, day, month, year } missing = none; | 207 | enum { none, day, month, year } missing = none; |
207 | unsigned days; | 208 | unsigned int days; |
208 | 209 | ||
209 | /* The lower level RTC driver may return -1 in some fields, | 210 | /* The lower level RTC driver may return -1 in some fields, |
210 | * creating invalid alarm->time values, for reasons like: | 211 | * creating invalid alarm->time values, for reasons like: |
@@ -273,10 +274,10 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
273 | return err; | 274 | return err; |
274 | 275 | ||
275 | /* note that tm_sec is a "don't care" value here: */ | 276 | /* note that tm_sec is a "don't care" value here: */ |
276 | } while ( before.tm_min != now.tm_min | 277 | } while (before.tm_min != now.tm_min || |
277 | || before.tm_hour != now.tm_hour | 278 | before.tm_hour != now.tm_hour || |
278 | || before.tm_mon != now.tm_mon | 279 | before.tm_mon != now.tm_mon || |
279 | || before.tm_year != now.tm_year); | 280 | before.tm_year != now.tm_year); |
280 | 281 | ||
281 | /* Fill in the missing alarm fields using the timestamp; we | 282 | /* Fill in the missing alarm fields using the timestamp; we |
282 | * know there's at least one since alarm->time is invalid. | 283 | * know there's at least one since alarm->time is invalid. |
@@ -293,7 +294,7 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
293 | alarm->time.tm_mday = now.tm_mday; | 294 | alarm->time.tm_mday = now.tm_mday; |
294 | missing = day; | 295 | missing = day; |
295 | } | 296 | } |
296 | if ((unsigned)alarm->time.tm_mon >= 12) { | 297 | if ((unsigned int)alarm->time.tm_mon >= 12) { |
297 | alarm->time.tm_mon = now.tm_mon; | 298 | alarm->time.tm_mon = now.tm_mon; |
298 | if (missing == none) | 299 | if (missing == none) |
299 | missing = month; | 300 | missing = month; |
@@ -318,7 +319,6 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
318 | goto done; | 319 | goto done; |
319 | 320 | ||
320 | switch (missing) { | 321 | switch (missing) { |
321 | |||
322 | /* 24 hour rollover ... if it's now 10am Monday, an alarm that | 322 | /* 24 hour rollover ... if it's now 10am Monday, an alarm that |
323 | * that will trigger at 5am will do so at 5am Tuesday, which | 323 | * that will trigger at 5am will do so at 5am Tuesday, which |
324 | * could also be in the next month or year. This is a common | 324 | * could also be in the next month or year. This is a common |
@@ -338,14 +338,14 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
338 | case month: | 338 | case month: |
339 | dev_dbg(&rtc->dev, "alarm rollover: %s\n", "month"); | 339 | dev_dbg(&rtc->dev, "alarm rollover: %s\n", "month"); |
340 | do { | 340 | do { |
341 | if (alarm->time.tm_mon < 11) | 341 | if (alarm->time.tm_mon < 11) { |
342 | alarm->time.tm_mon++; | 342 | alarm->time.tm_mon++; |
343 | else { | 343 | } else { |
344 | alarm->time.tm_mon = 0; | 344 | alarm->time.tm_mon = 0; |
345 | alarm->time.tm_year++; | 345 | alarm->time.tm_year++; |
346 | } | 346 | } |
347 | days = rtc_month_days(alarm->time.tm_mon, | 347 | days = rtc_month_days(alarm->time.tm_mon, |
348 | alarm->time.tm_year); | 348 | alarm->time.tm_year); |
349 | } while (days < alarm->time.tm_mday); | 349 | } while (days < alarm->time.tm_mday); |
350 | break; | 350 | break; |
351 | 351 | ||
@@ -354,8 +354,8 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
354 | dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year"); | 354 | dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year"); |
355 | do { | 355 | do { |
356 | alarm->time.tm_year++; | 356 | alarm->time.tm_year++; |
357 | } while (!is_leap_year(alarm->time.tm_year + 1900) | 357 | } while (!is_leap_year(alarm->time.tm_year + 1900) && |
358 | && rtc_valid_tm(&alarm->time) != 0); | 358 | rtc_valid_tm(&alarm->time) != 0); |
359 | break; | 359 | break; |
360 | 360 | ||
361 | default: | 361 | default: |
@@ -366,7 +366,8 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
366 | 366 | ||
367 | done: | 367 | done: |
368 | if (err) | 368 | if (err) |
369 | dev_warn(&rtc->dev, "invalid alarm value: %ptR\n", &alarm->time); | 369 | dev_warn(&rtc->dev, "invalid alarm value: %ptR\n", |
370 | &alarm->time); | ||
370 | 371 | ||
371 | return err; | 372 | return err; |
372 | } | 373 | } |
@@ -378,11 +379,11 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
378 | err = mutex_lock_interruptible(&rtc->ops_lock); | 379 | err = mutex_lock_interruptible(&rtc->ops_lock); |
379 | if (err) | 380 | if (err) |
380 | return err; | 381 | return err; |
381 | if (rtc->ops == NULL) | 382 | if (!rtc->ops) { |
382 | err = -ENODEV; | 383 | err = -ENODEV; |
383 | else if (!rtc->ops->read_alarm) | 384 | } else if (!rtc->ops->read_alarm) { |
384 | err = -EINVAL; | 385 | err = -EINVAL; |
385 | else { | 386 | } else { |
386 | memset(alarm, 0, sizeof(struct rtc_wkalrm)); | 387 | memset(alarm, 0, sizeof(struct rtc_wkalrm)); |
387 | alarm->enabled = rtc->aie_timer.enabled; | 388 | alarm->enabled = rtc->aie_timer.enabled; |
388 | alarm->time = rtc_ktime_to_tm(rtc->aie_timer.node.expires); | 389 | alarm->time = rtc_ktime_to_tm(rtc->aie_timer.node.expires); |
@@ -491,7 +492,6 @@ int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
491 | /* Alarm has to be enabled & in the future for us to enqueue it */ | 492 | /* Alarm has to be enabled & in the future for us to enqueue it */ |
492 | if (alarm->enabled && (rtc_tm_to_ktime(now) < | 493 | if (alarm->enabled && (rtc_tm_to_ktime(now) < |
493 | rtc->aie_timer.node.expires)) { | 494 | rtc->aie_timer.node.expires)) { |
494 | |||
495 | rtc->aie_timer.enabled = 1; | 495 | rtc->aie_timer.enabled = 1; |
496 | timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node); | 496 | timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node); |
497 | trace_rtc_timer_enqueue(&rtc->aie_timer); | 497 | trace_rtc_timer_enqueue(&rtc->aie_timer); |
@@ -503,7 +503,9 @@ EXPORT_SYMBOL_GPL(rtc_initialize_alarm); | |||
503 | 503 | ||
504 | int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled) | 504 | int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled) |
505 | { | 505 | { |
506 | int err = mutex_lock_interruptible(&rtc->ops_lock); | 506 | int err; |
507 | |||
508 | err = mutex_lock_interruptible(&rtc->ops_lock); | ||
507 | if (err) | 509 | if (err) |
508 | return err; | 510 | return err; |
509 | 511 | ||
@@ -532,7 +534,9 @@ EXPORT_SYMBOL_GPL(rtc_alarm_irq_enable); | |||
532 | 534 | ||
533 | int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) | 535 | int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) |
534 | { | 536 | { |
535 | int err = mutex_lock_interruptible(&rtc->ops_lock); | 537 | int err; |
538 | |||
539 | err = mutex_lock_interruptible(&rtc->ops_lock); | ||
536 | if (err) | 540 | if (err) |
537 | return err; | 541 | return err; |
538 | 542 | ||
@@ -561,8 +565,9 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) | |||
561 | rtc->uie_rtctimer.node.expires = ktime_add(now, onesec); | 565 | rtc->uie_rtctimer.node.expires = ktime_add(now, onesec); |
562 | rtc->uie_rtctimer.period = ktime_set(1, 0); | 566 | rtc->uie_rtctimer.period = ktime_set(1, 0); |
563 | err = rtc_timer_enqueue(rtc, &rtc->uie_rtctimer); | 567 | err = rtc_timer_enqueue(rtc, &rtc->uie_rtctimer); |
564 | } else | 568 | } else { |
565 | rtc_timer_remove(rtc, &rtc->uie_rtctimer); | 569 | rtc_timer_remove(rtc, &rtc->uie_rtctimer); |
570 | } | ||
566 | 571 | ||
567 | out: | 572 | out: |
568 | mutex_unlock(&rtc->ops_lock); | 573 | mutex_unlock(&rtc->ops_lock); |
@@ -577,11 +582,9 @@ out: | |||
577 | err = rtc_dev_update_irq_enable_emul(rtc, enabled); | 582 | err = rtc_dev_update_irq_enable_emul(rtc, enabled); |
578 | #endif | 583 | #endif |
579 | return err; | 584 | return err; |
580 | |||
581 | } | 585 | } |
582 | EXPORT_SYMBOL_GPL(rtc_update_irq_enable); | 586 | EXPORT_SYMBOL_GPL(rtc_update_irq_enable); |
583 | 587 | ||
584 | |||
585 | /** | 588 | /** |
586 | * rtc_handle_legacy_irq - AIE, UIE and PIE event hook | 589 | * rtc_handle_legacy_irq - AIE, UIE and PIE event hook |
587 | * @rtc: pointer to the rtc device | 590 | * @rtc: pointer to the rtc device |
@@ -596,14 +599,13 @@ void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode) | |||
596 | 599 | ||
597 | /* mark one irq of the appropriate mode */ | 600 | /* mark one irq of the appropriate mode */ |
598 | spin_lock_irqsave(&rtc->irq_lock, flags); | 601 | spin_lock_irqsave(&rtc->irq_lock, flags); |
599 | rtc->irq_data = (rtc->irq_data + (num << 8)) | (RTC_IRQF|mode); | 602 | rtc->irq_data = (rtc->irq_data + (num << 8)) | (RTC_IRQF | mode); |
600 | spin_unlock_irqrestore(&rtc->irq_lock, flags); | 603 | spin_unlock_irqrestore(&rtc->irq_lock, flags); |
601 | 604 | ||
602 | wake_up_interruptible(&rtc->irq_queue); | 605 | wake_up_interruptible(&rtc->irq_queue); |
603 | kill_fasync(&rtc->async_queue, SIGIO, POLL_IN); | 606 | kill_fasync(&rtc->async_queue, SIGIO, POLL_IN); |
604 | } | 607 | } |
605 | 608 | ||
606 | |||
607 | /** | 609 | /** |
608 | * rtc_aie_update_irq - AIE mode rtctimer hook | 610 | * rtc_aie_update_irq - AIE mode rtctimer hook |
609 | * @rtc: pointer to the rtc_device | 611 | * @rtc: pointer to the rtc_device |
@@ -615,7 +617,6 @@ void rtc_aie_update_irq(struct rtc_device *rtc) | |||
615 | rtc_handle_legacy_irq(rtc, 1, RTC_AF); | 617 | rtc_handle_legacy_irq(rtc, 1, RTC_AF); |
616 | } | 618 | } |
617 | 619 | ||
618 | |||
619 | /** | 620 | /** |
620 | * rtc_uie_update_irq - UIE mode rtctimer hook | 621 | * rtc_uie_update_irq - UIE mode rtctimer hook |
621 | * @rtc: pointer to the rtc_device | 622 | * @rtc: pointer to the rtc_device |
@@ -627,7 +628,6 @@ void rtc_uie_update_irq(struct rtc_device *rtc) | |||
627 | rtc_handle_legacy_irq(rtc, 1, RTC_UF); | 628 | rtc_handle_legacy_irq(rtc, 1, RTC_UF); |
628 | } | 629 | } |
629 | 630 | ||
630 | |||
631 | /** | 631 | /** |
632 | * rtc_pie_update_irq - PIE mode hrtimer hook | 632 | * rtc_pie_update_irq - PIE mode hrtimer hook |
633 | * @timer: pointer to the pie mode hrtimer | 633 | * @timer: pointer to the pie mode hrtimer |
@@ -641,6 +641,7 @@ enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer) | |||
641 | struct rtc_device *rtc; | 641 | struct rtc_device *rtc; |
642 | ktime_t period; | 642 | ktime_t period; |
643 | int count; | 643 | int count; |
644 | |||
644 | rtc = container_of(timer, struct rtc_device, pie_timer); | 645 | rtc = container_of(timer, struct rtc_device, pie_timer); |
645 | 646 | ||
646 | period = NSEC_PER_SEC / rtc->irq_freq; | 647 | period = NSEC_PER_SEC / rtc->irq_freq; |
@@ -659,7 +660,7 @@ enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer) | |||
659 | * Context: any | 660 | * Context: any |
660 | */ | 661 | */ |
661 | void rtc_update_irq(struct rtc_device *rtc, | 662 | void rtc_update_irq(struct rtc_device *rtc, |
662 | unsigned long num, unsigned long events) | 663 | unsigned long num, unsigned long events) |
663 | { | 664 | { |
664 | if (IS_ERR_OR_NULL(rtc)) | 665 | if (IS_ERR_OR_NULL(rtc)) |
665 | return; | 666 | return; |
@@ -808,6 +809,7 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) | |||
808 | if (!next || ktime_before(timer->node.expires, next->expires)) { | 809 | if (!next || ktime_before(timer->node.expires, next->expires)) { |
809 | struct rtc_wkalrm alarm; | 810 | struct rtc_wkalrm alarm; |
810 | int err; | 811 | int err; |
812 | |||
811 | alarm.time = rtc_ktime_to_tm(timer->node.expires); | 813 | alarm.time = rtc_ktime_to_tm(timer->node.expires); |
812 | alarm.enabled = 1; | 814 | alarm.enabled = 1; |
813 | err = __rtc_set_alarm(rtc, &alarm); | 815 | err = __rtc_set_alarm(rtc, &alarm); |
@@ -848,12 +850,14 @@ static void rtc_alarm_disable(struct rtc_device *rtc) | |||
848 | static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) | 850 | static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) |
849 | { | 851 | { |
850 | struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue); | 852 | struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue); |
853 | |||
851 | timerqueue_del(&rtc->timerqueue, &timer->node); | 854 | timerqueue_del(&rtc->timerqueue, &timer->node); |
852 | trace_rtc_timer_dequeue(timer); | 855 | trace_rtc_timer_dequeue(timer); |
853 | timer->enabled = 0; | 856 | timer->enabled = 0; |
854 | if (next == &timer->node) { | 857 | if (next == &timer->node) { |
855 | struct rtc_wkalrm alarm; | 858 | struct rtc_wkalrm alarm; |
856 | int err; | 859 | int err; |
860 | |||
857 | next = timerqueue_getnext(&rtc->timerqueue); | 861 | next = timerqueue_getnext(&rtc->timerqueue); |
858 | if (!next) { | 862 | if (!next) { |
859 | rtc_alarm_disable(rtc); | 863 | rtc_alarm_disable(rtc); |
@@ -926,9 +930,9 @@ again: | |||
926 | alarm.enabled = 1; | 930 | alarm.enabled = 1; |
927 | reprogram: | 931 | reprogram: |
928 | err = __rtc_set_alarm(rtc, &alarm); | 932 | err = __rtc_set_alarm(rtc, &alarm); |
929 | if (err == -ETIME) | 933 | if (err == -ETIME) { |
930 | goto again; | 934 | goto again; |
931 | else if (err) { | 935 | } else if (err) { |
932 | if (retry-- > 0) | 936 | if (retry-- > 0) |
933 | goto reprogram; | 937 | goto reprogram; |
934 | 938 | ||
@@ -939,14 +943,14 @@ reprogram: | |||
939 | dev_err(&rtc->dev, "__rtc_set_alarm: err=%d\n", err); | 943 | dev_err(&rtc->dev, "__rtc_set_alarm: err=%d\n", err); |
940 | goto again; | 944 | goto again; |
941 | } | 945 | } |
942 | } else | 946 | } else { |
943 | rtc_alarm_disable(rtc); | 947 | rtc_alarm_disable(rtc); |
948 | } | ||
944 | 949 | ||
945 | pm_relax(rtc->dev.parent); | 950 | pm_relax(rtc->dev.parent); |
946 | mutex_unlock(&rtc->ops_lock); | 951 | mutex_unlock(&rtc->ops_lock); |
947 | } | 952 | } |
948 | 953 | ||
949 | |||
950 | /* rtc_timer_init - Initializes an rtc_timer | 954 | /* rtc_timer_init - Initializes an rtc_timer |
951 | * @timer: timer to be intiialized | 955 | * @timer: timer to be intiialized |
952 | * @f: function pointer to be called when timer fires | 956 | * @f: function pointer to be called when timer fires |
@@ -972,9 +976,10 @@ void rtc_timer_init(struct rtc_timer *timer, void (*f)(struct rtc_device *r), | |||
972 | * Kernel interface to set an rtc_timer | 976 | * Kernel interface to set an rtc_timer |
973 | */ | 977 | */ |
974 | int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer *timer, | 978 | int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer *timer, |
975 | ktime_t expires, ktime_t period) | 979 | ktime_t expires, ktime_t period) |
976 | { | 980 | { |
977 | int ret = 0; | 981 | int ret = 0; |
982 | |||
978 | mutex_lock(&rtc->ops_lock); | 983 | mutex_lock(&rtc->ops_lock); |
979 | if (timer->enabled) | 984 | if (timer->enabled) |
980 | rtc_timer_remove(rtc, timer); | 985 | rtc_timer_remove(rtc, timer); |