diff options
Diffstat (limited to 'drivers/rtc/interface.c')
-rw-r--r-- | drivers/rtc/interface.c | 291 |
1 files changed, 264 insertions, 27 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 90384b9f6b2c..ef6316acec43 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
@@ -16,6 +16,9 @@ | |||
16 | #include <linux/log2.h> | 16 | #include <linux/log2.h> |
17 | #include <linux/workqueue.h> | 17 | #include <linux/workqueue.h> |
18 | 18 | ||
19 | static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer); | ||
20 | static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer); | ||
21 | |||
19 | static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) | 22 | static int __rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm) |
20 | { | 23 | { |
21 | int err; | 24 | int err; |
@@ -113,6 +116,186 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs) | |||
113 | } | 116 | } |
114 | EXPORT_SYMBOL_GPL(rtc_set_mmss); | 117 | EXPORT_SYMBOL_GPL(rtc_set_mmss); |
115 | 118 | ||
119 | static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | ||
120 | { | ||
121 | int err; | ||
122 | |||
123 | err = mutex_lock_interruptible(&rtc->ops_lock); | ||
124 | if (err) | ||
125 | return err; | ||
126 | |||
127 | if (rtc->ops == NULL) | ||
128 | err = -ENODEV; | ||
129 | else if (!rtc->ops->read_alarm) | ||
130 | err = -EINVAL; | ||
131 | else { | ||
132 | memset(alarm, 0, sizeof(struct rtc_wkalrm)); | ||
133 | err = rtc->ops->read_alarm(rtc->dev.parent, alarm); | ||
134 | } | ||
135 | |||
136 | mutex_unlock(&rtc->ops_lock); | ||
137 | return err; | ||
138 | } | ||
139 | |||
140 | int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | ||
141 | { | ||
142 | int err; | ||
143 | struct rtc_time before, now; | ||
144 | int first_time = 1; | ||
145 | unsigned long t_now, t_alm; | ||
146 | enum { none, day, month, year } missing = none; | ||
147 | unsigned days; | ||
148 | |||
149 | /* The lower level RTC driver may return -1 in some fields, | ||
150 | * creating invalid alarm->time values, for reasons like: | ||
151 | * | ||
152 | * - The hardware may not be capable of filling them in; | ||
153 | * many alarms match only on time-of-day fields, not | ||
154 | * day/month/year calendar data. | ||
155 | * | ||
156 | * - Some hardware uses illegal values as "wildcard" match | ||
157 | * values, which non-Linux firmware (like a BIOS) may try | ||
158 | * to set up as e.g. "alarm 15 minutes after each hour". | ||
159 | * Linux uses only oneshot alarms. | ||
160 | * | ||
161 | * When we see that here, we deal with it by using values from | ||
162 | * a current RTC timestamp for any missing (-1) values. The | ||
163 | * RTC driver prevents "periodic alarm" modes. | ||
164 | * | ||
165 | * But this can be racey, because some fields of the RTC timestamp | ||
166 | * may have wrapped in the interval since we read the RTC alarm, | ||
167 | * which would lead to us inserting inconsistent values in place | ||
168 | * of the -1 fields. | ||
169 | * | ||
170 | * Reading the alarm and timestamp in the reverse sequence | ||
171 | * would have the same race condition, and not solve the issue. | ||
172 | * | ||
173 | * So, we must first read the RTC timestamp, | ||
174 | * then read the RTC alarm value, | ||
175 | * and then read a second RTC timestamp. | ||
176 | * | ||
177 | * If any fields of the second timestamp have changed | ||
178 | * when compared with the first timestamp, then we know | ||
179 | * our timestamp may be inconsistent with that used by | ||
180 | * the low-level rtc_read_alarm_internal() function. | ||
181 | * | ||
182 | * So, when the two timestamps disagree, we just loop and do | ||
183 | * the process again to get a fully consistent set of values. | ||
184 | * | ||
185 | * This could all instead be done in the lower level driver, | ||
186 | * but since more than one lower level RTC implementation needs it, | ||
187 | * then it's probably best best to do it here instead of there.. | ||
188 | */ | ||
189 | |||
190 | /* Get the "before" timestamp */ | ||
191 | err = rtc_read_time(rtc, &before); | ||
192 | if (err < 0) | ||
193 | return err; | ||
194 | do { | ||
195 | if (!first_time) | ||
196 | memcpy(&before, &now, sizeof(struct rtc_time)); | ||
197 | first_time = 0; | ||
198 | |||
199 | /* get the RTC alarm values, which may be incomplete */ | ||
200 | err = rtc_read_alarm_internal(rtc, alarm); | ||
201 | if (err) | ||
202 | return err; | ||
203 | |||
204 | /* full-function RTCs won't have such missing fields */ | ||
205 | if (rtc_valid_tm(&alarm->time) == 0) | ||
206 | return 0; | ||
207 | |||
208 | /* get the "after" timestamp, to detect wrapped fields */ | ||
209 | err = rtc_read_time(rtc, &now); | ||
210 | if (err < 0) | ||
211 | return err; | ||
212 | |||
213 | /* note that tm_sec is a "don't care" value here: */ | ||
214 | } while ( before.tm_min != now.tm_min | ||
215 | || before.tm_hour != now.tm_hour | ||
216 | || before.tm_mon != now.tm_mon | ||
217 | || before.tm_year != now.tm_year); | ||
218 | |||
219 | /* Fill in the missing alarm fields using the timestamp; we | ||
220 | * know there's at least one since alarm->time is invalid. | ||
221 | */ | ||
222 | if (alarm->time.tm_sec == -1) | ||
223 | alarm->time.tm_sec = now.tm_sec; | ||
224 | if (alarm->time.tm_min == -1) | ||
225 | alarm->time.tm_min = now.tm_min; | ||
226 | if (alarm->time.tm_hour == -1) | ||
227 | alarm->time.tm_hour = now.tm_hour; | ||
228 | |||
229 | /* For simplicity, only support date rollover for now */ | ||
230 | if (alarm->time.tm_mday == -1) { | ||
231 | alarm->time.tm_mday = now.tm_mday; | ||
232 | missing = day; | ||
233 | } | ||
234 | if (alarm->time.tm_mon == -1) { | ||
235 | alarm->time.tm_mon = now.tm_mon; | ||
236 | if (missing == none) | ||
237 | missing = month; | ||
238 | } | ||
239 | if (alarm->time.tm_year == -1) { | ||
240 | alarm->time.tm_year = now.tm_year; | ||
241 | if (missing == none) | ||
242 | missing = year; | ||
243 | } | ||
244 | |||
245 | /* with luck, no rollover is needed */ | ||
246 | rtc_tm_to_time(&now, &t_now); | ||
247 | rtc_tm_to_time(&alarm->time, &t_alm); | ||
248 | if (t_now < t_alm) | ||
249 | goto done; | ||
250 | |||
251 | switch (missing) { | ||
252 | |||
253 | /* 24 hour rollover ... if it's now 10am Monday, an alarm that | ||
254 | * that will trigger at 5am will do so at 5am Tuesday, which | ||
255 | * could also be in the next month or year. This is a common | ||
256 | * case, especially for PCs. | ||
257 | */ | ||
258 | case day: | ||
259 | dev_dbg(&rtc->dev, "alarm rollover: %s\n", "day"); | ||
260 | t_alm += 24 * 60 * 60; | ||
261 | rtc_time_to_tm(t_alm, &alarm->time); | ||
262 | break; | ||
263 | |||
264 | /* Month rollover ... if it's the 31th, an alarm on the 3rd will | ||
265 | * be next month. An alarm matching on the 30th, 29th, or 28th | ||
266 | * may end up in the month after that! Many newer PCs support | ||
267 | * this type of alarm. | ||
268 | */ | ||
269 | case month: | ||
270 | dev_dbg(&rtc->dev, "alarm rollover: %s\n", "month"); | ||
271 | do { | ||
272 | if (alarm->time.tm_mon < 11) | ||
273 | alarm->time.tm_mon++; | ||
274 | else { | ||
275 | alarm->time.tm_mon = 0; | ||
276 | alarm->time.tm_year++; | ||
277 | } | ||
278 | days = rtc_month_days(alarm->time.tm_mon, | ||
279 | alarm->time.tm_year); | ||
280 | } while (days < alarm->time.tm_mday); | ||
281 | break; | ||
282 | |||
283 | /* Year rollover ... easy except for leap years! */ | ||
284 | case year: | ||
285 | dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year"); | ||
286 | do { | ||
287 | alarm->time.tm_year++; | ||
288 | } while (rtc_valid_tm(&alarm->time) != 0); | ||
289 | break; | ||
290 | |||
291 | default: | ||
292 | dev_warn(&rtc->dev, "alarm rollover not handled\n"); | ||
293 | } | ||
294 | |||
295 | done: | ||
296 | return 0; | ||
297 | } | ||
298 | |||
116 | int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | 299 | int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) |
117 | { | 300 | { |
118 | int err; | 301 | int err; |
@@ -120,12 +303,18 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
120 | err = mutex_lock_interruptible(&rtc->ops_lock); | 303 | err = mutex_lock_interruptible(&rtc->ops_lock); |
121 | if (err) | 304 | if (err) |
122 | return err; | 305 | return err; |
123 | alarm->enabled = rtc->aie_timer.enabled; | 306 | if (rtc->ops == NULL) |
124 | if (alarm->enabled) | 307 | err = -ENODEV; |
308 | else if (!rtc->ops->read_alarm) | ||
309 | err = -EINVAL; | ||
310 | else { | ||
311 | memset(alarm, 0, sizeof(struct rtc_wkalrm)); | ||
312 | alarm->enabled = rtc->aie_timer.enabled; | ||
125 | alarm->time = rtc_ktime_to_tm(rtc->aie_timer.node.expires); | 313 | alarm->time = rtc_ktime_to_tm(rtc->aie_timer.node.expires); |
314 | } | ||
126 | mutex_unlock(&rtc->ops_lock); | 315 | mutex_unlock(&rtc->ops_lock); |
127 | 316 | ||
128 | return 0; | 317 | return err; |
129 | } | 318 | } |
130 | EXPORT_SYMBOL_GPL(rtc_read_alarm); | 319 | EXPORT_SYMBOL_GPL(rtc_read_alarm); |
131 | 320 | ||
@@ -175,19 +364,43 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
175 | return err; | 364 | return err; |
176 | if (rtc->aie_timer.enabled) { | 365 | if (rtc->aie_timer.enabled) { |
177 | rtc_timer_remove(rtc, &rtc->aie_timer); | 366 | rtc_timer_remove(rtc, &rtc->aie_timer); |
178 | rtc->aie_timer.enabled = 0; | ||
179 | } | 367 | } |
180 | rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); | 368 | rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); |
181 | rtc->aie_timer.period = ktime_set(0, 0); | 369 | rtc->aie_timer.period = ktime_set(0, 0); |
182 | if (alarm->enabled) { | 370 | if (alarm->enabled) { |
183 | rtc->aie_timer.enabled = 1; | 371 | err = rtc_timer_enqueue(rtc, &rtc->aie_timer); |
184 | rtc_timer_enqueue(rtc, &rtc->aie_timer); | ||
185 | } | 372 | } |
186 | mutex_unlock(&rtc->ops_lock); | 373 | mutex_unlock(&rtc->ops_lock); |
187 | return 0; | 374 | return err; |
188 | } | 375 | } |
189 | EXPORT_SYMBOL_GPL(rtc_set_alarm); | 376 | EXPORT_SYMBOL_GPL(rtc_set_alarm); |
190 | 377 | ||
378 | /* Called once per device from rtc_device_register */ | ||
379 | int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | ||
380 | { | ||
381 | int err; | ||
382 | |||
383 | err = rtc_valid_tm(&alarm->time); | ||
384 | if (err != 0) | ||
385 | return err; | ||
386 | |||
387 | err = mutex_lock_interruptible(&rtc->ops_lock); | ||
388 | if (err) | ||
389 | return err; | ||
390 | |||
391 | rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time); | ||
392 | rtc->aie_timer.period = ktime_set(0, 0); | ||
393 | if (alarm->enabled) { | ||
394 | rtc->aie_timer.enabled = 1; | ||
395 | timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node); | ||
396 | } | ||
397 | mutex_unlock(&rtc->ops_lock); | ||
398 | return err; | ||
399 | } | ||
400 | EXPORT_SYMBOL_GPL(rtc_initialize_alarm); | ||
401 | |||
402 | |||
403 | |||
191 | int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled) | 404 | int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled) |
192 | { | 405 | { |
193 | int err = mutex_lock_interruptible(&rtc->ops_lock); | 406 | int err = mutex_lock_interruptible(&rtc->ops_lock); |
@@ -195,16 +408,15 @@ int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled) | |||
195 | return err; | 408 | return err; |
196 | 409 | ||
197 | if (rtc->aie_timer.enabled != enabled) { | 410 | if (rtc->aie_timer.enabled != enabled) { |
198 | if (enabled) { | 411 | if (enabled) |
199 | rtc->aie_timer.enabled = 1; | 412 | err = rtc_timer_enqueue(rtc, &rtc->aie_timer); |
200 | rtc_timer_enqueue(rtc, &rtc->aie_timer); | 413 | else |
201 | } else { | ||
202 | rtc_timer_remove(rtc, &rtc->aie_timer); | 414 | rtc_timer_remove(rtc, &rtc->aie_timer); |
203 | rtc->aie_timer.enabled = 0; | ||
204 | } | ||
205 | } | 415 | } |
206 | 416 | ||
207 | if (!rtc->ops) | 417 | if (err) |
418 | /* nothing */; | ||
419 | else if (!rtc->ops) | ||
208 | err = -ENODEV; | 420 | err = -ENODEV; |
209 | else if (!rtc->ops->alarm_irq_enable) | 421 | else if (!rtc->ops->alarm_irq_enable) |
210 | err = -EINVAL; | 422 | err = -EINVAL; |
@@ -222,6 +434,12 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) | |||
222 | if (err) | 434 | if (err) |
223 | return err; | 435 | return err; |
224 | 436 | ||
437 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | ||
438 | if (enabled == 0 && rtc->uie_irq_active) { | ||
439 | mutex_unlock(&rtc->ops_lock); | ||
440 | return rtc_dev_update_irq_enable_emul(rtc, 0); | ||
441 | } | ||
442 | #endif | ||
225 | /* make sure we're changing state */ | 443 | /* make sure we're changing state */ |
226 | if (rtc->uie_rtctimer.enabled == enabled) | 444 | if (rtc->uie_rtctimer.enabled == enabled) |
227 | goto out; | 445 | goto out; |
@@ -235,15 +453,22 @@ int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) | |||
235 | now = rtc_tm_to_ktime(tm); | 453 | now = rtc_tm_to_ktime(tm); |
236 | rtc->uie_rtctimer.node.expires = ktime_add(now, onesec); | 454 | rtc->uie_rtctimer.node.expires = ktime_add(now, onesec); |
237 | rtc->uie_rtctimer.period = ktime_set(1, 0); | 455 | rtc->uie_rtctimer.period = ktime_set(1, 0); |
238 | rtc->uie_rtctimer.enabled = 1; | 456 | err = rtc_timer_enqueue(rtc, &rtc->uie_rtctimer); |
239 | rtc_timer_enqueue(rtc, &rtc->uie_rtctimer); | 457 | } else |
240 | } else { | ||
241 | rtc_timer_remove(rtc, &rtc->uie_rtctimer); | 458 | rtc_timer_remove(rtc, &rtc->uie_rtctimer); |
242 | rtc->uie_rtctimer.enabled = 0; | ||
243 | } | ||
244 | 459 | ||
245 | out: | 460 | out: |
246 | mutex_unlock(&rtc->ops_lock); | 461 | mutex_unlock(&rtc->ops_lock); |
462 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | ||
463 | /* | ||
464 | * Enable emulation if the driver did not provide | ||
465 | * the update_irq_enable function pointer or if returned | ||
466 | * -EINVAL to signal that it has been configured without | ||
467 | * interrupts or that are not available at the moment. | ||
468 | */ | ||
469 | if (err == -EINVAL) | ||
470 | err = rtc_dev_update_irq_enable_emul(rtc, enabled); | ||
471 | #endif | ||
247 | return err; | 472 | return err; |
248 | 473 | ||
249 | } | 474 | } |
@@ -255,11 +480,11 @@ EXPORT_SYMBOL_GPL(rtc_update_irq_enable); | |||
255 | * @rtc: pointer to the rtc device | 480 | * @rtc: pointer to the rtc device |
256 | * | 481 | * |
257 | * This function is called when an AIE, UIE or PIE mode interrupt | 482 | * This function is called when an AIE, UIE or PIE mode interrupt |
258 | * has occured (or been emulated). | 483 | * has occurred (or been emulated). |
259 | * | 484 | * |
260 | * Triggers the registered irq_task function callback. | 485 | * Triggers the registered irq_task function callback. |
261 | */ | 486 | */ |
262 | static void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode) | 487 | void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode) |
263 | { | 488 | { |
264 | unsigned long flags; | 489 | unsigned long flags; |
265 | 490 | ||
@@ -460,6 +685,9 @@ int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) | |||
460 | int err = 0; | 685 | int err = 0; |
461 | unsigned long flags; | 686 | unsigned long flags; |
462 | 687 | ||
688 | if (freq <= 0) | ||
689 | return -EINVAL; | ||
690 | |||
463 | spin_lock_irqsave(&rtc->irq_task_lock, flags); | 691 | spin_lock_irqsave(&rtc->irq_task_lock, flags); |
464 | if (rtc->irq_task != NULL && task == NULL) | 692 | if (rtc->irq_task != NULL && task == NULL) |
465 | err = -EBUSY; | 693 | err = -EBUSY; |
@@ -488,10 +716,13 @@ EXPORT_SYMBOL_GPL(rtc_irq_set_freq); | |||
488 | * Enqueues a timer onto the rtc devices timerqueue and sets | 716 | * Enqueues a timer onto the rtc devices timerqueue and sets |
489 | * the next alarm event appropriately. | 717 | * the next alarm event appropriately. |
490 | * | 718 | * |
719 | * Sets the enabled bit on the added timer. | ||
720 | * | ||
491 | * Must hold ops_lock for proper serialization of timerqueue | 721 | * Must hold ops_lock for proper serialization of timerqueue |
492 | */ | 722 | */ |
493 | void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) | 723 | static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) |
494 | { | 724 | { |
725 | timer->enabled = 1; | ||
495 | timerqueue_add(&rtc->timerqueue, &timer->node); | 726 | timerqueue_add(&rtc->timerqueue, &timer->node); |
496 | if (&timer->node == timerqueue_getnext(&rtc->timerqueue)) { | 727 | if (&timer->node == timerqueue_getnext(&rtc->timerqueue)) { |
497 | struct rtc_wkalrm alarm; | 728 | struct rtc_wkalrm alarm; |
@@ -501,7 +732,13 @@ void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) | |||
501 | err = __rtc_set_alarm(rtc, &alarm); | 732 | err = __rtc_set_alarm(rtc, &alarm); |
502 | if (err == -ETIME) | 733 | if (err == -ETIME) |
503 | schedule_work(&rtc->irqwork); | 734 | schedule_work(&rtc->irqwork); |
735 | else if (err) { | ||
736 | timerqueue_del(&rtc->timerqueue, &timer->node); | ||
737 | timer->enabled = 0; | ||
738 | return err; | ||
739 | } | ||
504 | } | 740 | } |
741 | return 0; | ||
505 | } | 742 | } |
506 | 743 | ||
507 | /** | 744 | /** |
@@ -512,13 +749,15 @@ void rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) | |||
512 | * Removes a timer onto the rtc devices timerqueue and sets | 749 | * Removes a timer onto the rtc devices timerqueue and sets |
513 | * the next alarm event appropriately. | 750 | * the next alarm event appropriately. |
514 | * | 751 | * |
752 | * Clears the enabled bit on the removed timer. | ||
753 | * | ||
515 | * Must hold ops_lock for proper serialization of timerqueue | 754 | * Must hold ops_lock for proper serialization of timerqueue |
516 | */ | 755 | */ |
517 | void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) | 756 | static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer) |
518 | { | 757 | { |
519 | struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue); | 758 | struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue); |
520 | timerqueue_del(&rtc->timerqueue, &timer->node); | 759 | timerqueue_del(&rtc->timerqueue, &timer->node); |
521 | 760 | timer->enabled = 0; | |
522 | if (next == &timer->node) { | 761 | if (next == &timer->node) { |
523 | struct rtc_wkalrm alarm; | 762 | struct rtc_wkalrm alarm; |
524 | int err; | 763 | int err; |
@@ -626,8 +865,7 @@ int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer* timer, | |||
626 | timer->node.expires = expires; | 865 | timer->node.expires = expires; |
627 | timer->period = period; | 866 | timer->period = period; |
628 | 867 | ||
629 | timer->enabled = 1; | 868 | ret = rtc_timer_enqueue(rtc, timer); |
630 | rtc_timer_enqueue(rtc, timer); | ||
631 | 869 | ||
632 | mutex_unlock(&rtc->ops_lock); | 870 | mutex_unlock(&rtc->ops_lock); |
633 | return ret; | 871 | return ret; |
@@ -645,7 +883,6 @@ int rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer* timer) | |||
645 | mutex_lock(&rtc->ops_lock); | 883 | mutex_lock(&rtc->ops_lock); |
646 | if (timer->enabled) | 884 | if (timer->enabled) |
647 | rtc_timer_remove(rtc, timer); | 885 | rtc_timer_remove(rtc, timer); |
648 | timer->enabled = 0; | ||
649 | mutex_unlock(&rtc->ops_lock); | 886 | mutex_unlock(&rtc->ops_lock); |
650 | return ret; | 887 | return ret; |
651 | } | 888 | } |