Commit | Line | Data |
---|---|---|
841cb11c AH |
1 | /* drivers/rtc/alarm.c |
2 | * | |
3 | * Copyright (C) 2007-2009 Google, Inc. | |
4 | * | |
5 | * This software is licensed under the terms of the GNU General Public | |
6 | * License version 2, as published by the Free Software Foundation, and | |
7 | * may be copied, distributed, and modified under those terms. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | */ | |
15 | ||
d47908b2 | 16 | #include <linux/time.h> |
bf647ea7 | 17 | #include <linux/module.h> |
841cb11c AH |
18 | #include <linux/device.h> |
19 | #include <linux/miscdevice.h> | |
20 | #include <linux/platform_device.h> | |
21 | #include <linux/rtc.h> | |
22 | #include <linux/sched.h> | |
23 | #include <linux/spinlock.h> | |
841cb11c AH |
24 | #include <linux/wakelock.h> |
25 | #include "android_alarm.h" | |
26 | ||
27 | #define ANDROID_ALARM_PRINT_ERROR (1U << 0) | |
28 | #define ANDROID_ALARM_PRINT_INIT_STATUS (1U << 1) | |
29 | #define ANDROID_ALARM_PRINT_TSET (1U << 2) | |
30 | #define ANDROID_ALARM_PRINT_CALL (1U << 3) | |
31 | #define ANDROID_ALARM_PRINT_SUSPEND (1U << 4) | |
32 | #define ANDROID_ALARM_PRINT_INT (1U << 5) | |
33 | #define ANDROID_ALARM_PRINT_FLOW (1U << 6) | |
34 | ||
35 | static int debug_mask = ANDROID_ALARM_PRINT_ERROR | \ | |
36 | ANDROID_ALARM_PRINT_INIT_STATUS; | |
37 | module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); | |
38 | ||
39 | #define pr_alarm(debug_level_mask, args...) \ | |
40 | do { \ | |
41 | if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) { \ | |
42 | pr_info(args); \ | |
43 | } \ | |
44 | } while (0) | |
45 | ||
46 | #define ANDROID_ALARM_WAKEUP_MASK ( \ | |
47 | ANDROID_ALARM_RTC_WAKEUP_MASK | \ | |
48 | ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK) | |
49 | ||
50 | /* support old usespace code */ | |
51 | #define ANDROID_ALARM_SET_OLD _IOW('a', 2, time_t) /* set alarm */ | |
52 | #define ANDROID_ALARM_SET_AND_WAIT_OLD _IOW('a', 3, time_t) | |
53 | ||
54 | struct alarm_queue { | |
55 | struct rb_root alarms; | |
56 | struct rb_node *first; | |
57 | struct hrtimer timer; | |
58 | ktime_t delta; | |
59 | bool stopped; | |
60 | ktime_t stopped_time; | |
61 | }; | |
62 | ||
63 | static struct rtc_device *alarm_rtc_dev; | |
64 | static DEFINE_SPINLOCK(alarm_slock); | |
65 | static DEFINE_MUTEX(alarm_setrtc_mutex); | |
66 | static struct wake_lock alarm_rtc_wake_lock; | |
67 | static struct platform_device *alarm_platform_dev; | |
68 | struct alarm_queue alarms[ANDROID_ALARM_TYPE_COUNT]; | |
69 | static bool suspended; | |
70 | ||
71 | static void update_timer_locked(struct alarm_queue *base, bool head_removed) | |
72 | { | |
73 | struct alarm *alarm; | |
74 | bool is_wakeup = base == &alarms[ANDROID_ALARM_RTC_WAKEUP] || | |
75 | base == &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP]; | |
76 | ||
77 | if (base->stopped) { | |
78 | pr_alarm(FLOW, "changed alarm while setting the wall time\n"); | |
79 | return; | |
80 | } | |
81 | ||
82 | if (is_wakeup && !suspended && head_removed) | |
83 | wake_unlock(&alarm_rtc_wake_lock); | |
84 | ||
85 | if (!base->first) | |
86 | return; | |
87 | ||
88 | alarm = container_of(base->first, struct alarm, node); | |
89 | ||
90 | pr_alarm(FLOW, "selected alarm, type %d, func %pF at %lld\n", | |
91 | alarm->type, alarm->function, ktime_to_ns(alarm->expires)); | |
92 | ||
93 | if (is_wakeup && suspended) { | |
94 | pr_alarm(FLOW, "changed alarm while suspened\n"); | |
95 | wake_lock_timeout(&alarm_rtc_wake_lock, 1 * HZ); | |
96 | return; | |
97 | } | |
98 | ||
99 | hrtimer_try_to_cancel(&base->timer); | |
100 | base->timer.node.expires = ktime_add(base->delta, alarm->expires); | |
101 | base->timer._softexpires = ktime_add(base->delta, alarm->softexpires); | |
102 | hrtimer_start_expires(&base->timer, HRTIMER_MODE_ABS); | |
103 | } | |
104 | ||
105 | static void alarm_enqueue_locked(struct alarm *alarm) | |
106 | { | |
107 | struct alarm_queue *base = &alarms[alarm->type]; | |
108 | struct rb_node **link = &base->alarms.rb_node; | |
109 | struct rb_node *parent = NULL; | |
110 | struct alarm *entry; | |
111 | int leftmost = 1; | |
112 | ||
113 | pr_alarm(FLOW, "added alarm, type %d, func %pF at %lld\n", | |
114 | alarm->type, alarm->function, ktime_to_ns(alarm->expires)); | |
115 | ||
116 | if (base->first == &alarm->node) | |
117 | base->first = rb_next(&alarm->node); | |
118 | if (!RB_EMPTY_NODE(&alarm->node)) { | |
119 | rb_erase(&alarm->node, &base->alarms); | |
120 | RB_CLEAR_NODE(&alarm->node); | |
121 | } | |
122 | ||
123 | while (*link) { | |
124 | parent = *link; | |
125 | entry = rb_entry(parent, struct alarm, node); | |
126 | /* | |
127 | * We dont care about collisions. Nodes with | |
128 | * the same expiry time stay together. | |
129 | */ | |
130 | if (alarm->expires.tv64 < entry->expires.tv64) { | |
131 | link = &(*link)->rb_left; | |
132 | } else { | |
133 | link = &(*link)->rb_right; | |
134 | leftmost = 0; | |
135 | } | |
136 | } | |
137 | if (leftmost) { | |
138 | base->first = &alarm->node; | |
139 | update_timer_locked(base, false); | |
140 | } | |
141 | ||
142 | rb_link_node(&alarm->node, parent, link); | |
143 | rb_insert_color(&alarm->node, &base->alarms); | |
144 | } | |
145 | ||
146 | /** | |
147 | * alarm_init - initialize an alarm | |
148 | * @alarm: the alarm to be initialized | |
149 | * @type: the alarm type to be used | |
150 | * @function: alarm callback function | |
151 | */ | |
152 | void alarm_init(struct alarm *alarm, | |
153 | enum android_alarm_type type, void (*function)(struct alarm *)) | |
154 | { | |
155 | RB_CLEAR_NODE(&alarm->node); | |
156 | alarm->type = type; | |
157 | alarm->function = function; | |
158 | ||
159 | pr_alarm(FLOW, "created alarm, type %d, func %pF\n", type, function); | |
160 | } | |
161 | ||
162 | ||
163 | /** | |
164 | * alarm_start_range - (re)start an alarm | |
165 | * @alarm: the alarm to be added | |
166 | * @start: earliest expiry time | |
167 | * @end: expiry time | |
168 | */ | |
169 | void alarm_start_range(struct alarm *alarm, ktime_t start, ktime_t end) | |
170 | { | |
171 | unsigned long flags; | |
172 | ||
173 | spin_lock_irqsave(&alarm_slock, flags); | |
174 | alarm->softexpires = start; | |
175 | alarm->expires = end; | |
176 | alarm_enqueue_locked(alarm); | |
177 | spin_unlock_irqrestore(&alarm_slock, flags); | |
178 | } | |
179 | ||
180 | /** | |
181 | * alarm_try_to_cancel - try to deactivate an alarm | |
182 | * @alarm: alarm to stop | |
183 | * | |
184 | * Returns: | |
185 | * 0 when the alarm was not active | |
186 | * 1 when the alarm was active | |
187 | * -1 when the alarm may currently be excuting the callback function and | |
188 | * cannot be stopped (it may also be inactive) | |
189 | */ | |
190 | int alarm_try_to_cancel(struct alarm *alarm) | |
191 | { | |
192 | struct alarm_queue *base = &alarms[alarm->type]; | |
193 | unsigned long flags; | |
194 | bool first = false; | |
195 | int ret = 0; | |
196 | ||
197 | spin_lock_irqsave(&alarm_slock, flags); | |
198 | if (!RB_EMPTY_NODE(&alarm->node)) { | |
199 | pr_alarm(FLOW, "canceled alarm, type %d, func %pF at %lld\n", | |
200 | alarm->type, alarm->function, | |
201 | ktime_to_ns(alarm->expires)); | |
202 | ret = 1; | |
203 | if (base->first == &alarm->node) { | |
204 | base->first = rb_next(&alarm->node); | |
205 | first = true; | |
206 | } | |
207 | rb_erase(&alarm->node, &base->alarms); | |
208 | RB_CLEAR_NODE(&alarm->node); | |
209 | if (first) | |
210 | update_timer_locked(base, true); | |
211 | } else | |
212 | pr_alarm(FLOW, "tried to cancel alarm, type %d, func %pF\n", | |
213 | alarm->type, alarm->function); | |
214 | spin_unlock_irqrestore(&alarm_slock, flags); | |
215 | if (!ret && hrtimer_callback_running(&base->timer)) | |
216 | ret = -1; | |
217 | return ret; | |
218 | } | |
219 | ||
220 | /** | |
221 | * alarm_cancel - cancel an alarm and wait for the handler to finish. | |
222 | * @alarm: the alarm to be cancelled | |
223 | * | |
224 | * Returns: | |
225 | * 0 when the alarm was not active | |
226 | * 1 when the alarm was active | |
227 | */ | |
228 | int alarm_cancel(struct alarm *alarm) | |
229 | { | |
230 | for (;;) { | |
231 | int ret = alarm_try_to_cancel(alarm); | |
232 | if (ret >= 0) | |
233 | return ret; | |
234 | cpu_relax(); | |
235 | } | |
236 | } | |
237 | ||
238 | /** | |
239 | * alarm_set_rtc - set the kernel and rtc walltime | |
240 | * @new_time: timespec value containing the new time | |
241 | */ | |
242 | int alarm_set_rtc(struct timespec new_time) | |
243 | { | |
244 | int i; | |
245 | int ret; | |
246 | unsigned long flags; | |
247 | struct rtc_time rtc_new_rtc_time; | |
248 | struct timespec tmp_time; | |
249 | ||
250 | rtc_time_to_tm(new_time.tv_sec, &rtc_new_rtc_time); | |
251 | ||
252 | pr_alarm(TSET, "set rtc %ld %ld - rtc %02d:%02d:%02d %02d/%02d/%04d\n", | |
253 | new_time.tv_sec, new_time.tv_nsec, | |
254 | rtc_new_rtc_time.tm_hour, rtc_new_rtc_time.tm_min, | |
255 | rtc_new_rtc_time.tm_sec, rtc_new_rtc_time.tm_mon + 1, | |
256 | rtc_new_rtc_time.tm_mday, | |
257 | rtc_new_rtc_time.tm_year + 1900); | |
258 | ||
259 | mutex_lock(&alarm_setrtc_mutex); | |
260 | spin_lock_irqsave(&alarm_slock, flags); | |
261 | wake_lock(&alarm_rtc_wake_lock); | |
262 | getnstimeofday(&tmp_time); | |
263 | for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) { | |
264 | hrtimer_try_to_cancel(&alarms[i].timer); | |
265 | alarms[i].stopped = true; | |
266 | alarms[i].stopped_time = timespec_to_ktime(tmp_time); | |
267 | } | |
268 | alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].delta = | |
269 | alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta = | |
270 | ktime_sub(alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta, | |
271 | timespec_to_ktime(timespec_sub(tmp_time, new_time))); | |
272 | spin_unlock_irqrestore(&alarm_slock, flags); | |
273 | ret = do_settimeofday(&new_time); | |
274 | spin_lock_irqsave(&alarm_slock, flags); | |
275 | for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) { | |
276 | alarms[i].stopped = false; | |
277 | update_timer_locked(&alarms[i], false); | |
278 | } | |
279 | spin_unlock_irqrestore(&alarm_slock, flags); | |
280 | if (ret < 0) { | |
281 | pr_alarm(ERROR, "alarm_set_rtc: Failed to set time\n"); | |
282 | goto err; | |
283 | } | |
284 | if (!alarm_rtc_dev) { | |
285 | pr_alarm(ERROR, | |
286 | "alarm_set_rtc: no RTC, time will be lost on reboot\n"); | |
287 | goto err; | |
288 | } | |
289 | ret = rtc_set_time(alarm_rtc_dev, &rtc_new_rtc_time); | |
290 | if (ret < 0) | |
291 | pr_alarm(ERROR, "alarm_set_rtc: " | |
292 | "Failed to set RTC, time will be lost on reboot\n"); | |
293 | err: | |
294 | wake_unlock(&alarm_rtc_wake_lock); | |
295 | mutex_unlock(&alarm_setrtc_mutex); | |
296 | return ret; | |
297 | } | |
298 | ||
299 | /** | |
300 | * alarm_get_elapsed_realtime - get the elapsed real time in ktime_t format | |
301 | * | |
302 | * returns the time in ktime_t format | |
303 | */ | |
304 | ktime_t alarm_get_elapsed_realtime(void) | |
305 | { | |
306 | ktime_t now; | |
307 | unsigned long flags; | |
308 | struct alarm_queue *base = &alarms[ANDROID_ALARM_ELAPSED_REALTIME]; | |
309 | ||
310 | spin_lock_irqsave(&alarm_slock, flags); | |
311 | now = base->stopped ? base->stopped_time : ktime_get_real(); | |
312 | now = ktime_sub(now, base->delta); | |
313 | spin_unlock_irqrestore(&alarm_slock, flags); | |
314 | return now; | |
315 | } | |
316 | ||
317 | static enum hrtimer_restart alarm_timer_triggered(struct hrtimer *timer) | |
318 | { | |
319 | struct alarm_queue *base; | |
320 | struct alarm *alarm; | |
321 | unsigned long flags; | |
322 | ktime_t now; | |
323 | ||
324 | spin_lock_irqsave(&alarm_slock, flags); | |
325 | ||
326 | base = container_of(timer, struct alarm_queue, timer); | |
327 | now = base->stopped ? base->stopped_time : hrtimer_cb_get_time(timer); | |
328 | now = ktime_sub(now, base->delta); | |
329 | ||
330 | pr_alarm(INT, "alarm_timer_triggered type %d at %lld\n", | |
331 | base - alarms, ktime_to_ns(now)); | |
332 | ||
333 | while (base->first) { | |
334 | alarm = container_of(base->first, struct alarm, node); | |
335 | if (alarm->softexpires.tv64 > now.tv64) { | |
336 | pr_alarm(FLOW, "don't call alarm, %pF, %lld (s %lld)\n", | |
337 | alarm->function, ktime_to_ns(alarm->expires), | |
338 | ktime_to_ns(alarm->softexpires)); | |
339 | break; | |
340 | } | |
341 | base->first = rb_next(&alarm->node); | |
342 | rb_erase(&alarm->node, &base->alarms); | |
343 | RB_CLEAR_NODE(&alarm->node); | |
344 | pr_alarm(CALL, "call alarm, type %d, func %pF, %lld (s %lld)\n", | |
345 | alarm->type, alarm->function, | |
346 | ktime_to_ns(alarm->expires), | |
347 | ktime_to_ns(alarm->softexpires)); | |
348 | spin_unlock_irqrestore(&alarm_slock, flags); | |
349 | alarm->function(alarm); | |
350 | spin_lock_irqsave(&alarm_slock, flags); | |
351 | } | |
352 | if (!base->first) | |
353 | pr_alarm(FLOW, "no more alarms of type %d\n", base - alarms); | |
354 | update_timer_locked(base, true); | |
355 | spin_unlock_irqrestore(&alarm_slock, flags); | |
356 | return HRTIMER_NORESTART; | |
357 | } | |
358 | ||
359 | static void alarm_triggered_func(void *p) | |
360 | { | |
361 | struct rtc_device *rtc = alarm_rtc_dev; | |
362 | if (!(rtc->irq_data & RTC_AF)) | |
363 | return; | |
364 | pr_alarm(INT, "rtc alarm triggered\n"); | |
365 | wake_lock_timeout(&alarm_rtc_wake_lock, 1 * HZ); | |
366 | } | |
367 | ||
368 | static int alarm_suspend(struct platform_device *pdev, pm_message_t state) | |
369 | { | |
370 | int err = 0; | |
371 | unsigned long flags; | |
372 | struct rtc_wkalrm rtc_alarm; | |
373 | struct rtc_time rtc_current_rtc_time; | |
374 | unsigned long rtc_current_time; | |
375 | unsigned long rtc_alarm_time; | |
841cb11c | 376 | struct timespec rtc_delta; |
5dd12c29 | 377 | struct timespec wall_time; |
841cb11c AH |
378 | struct alarm_queue *wakeup_queue = NULL; |
379 | struct alarm_queue *tmp_queue = NULL; | |
380 | ||
381 | pr_alarm(SUSPEND, "alarm_suspend(%p, %d)\n", pdev, state.event); | |
382 | ||
383 | spin_lock_irqsave(&alarm_slock, flags); | |
384 | suspended = true; | |
385 | spin_unlock_irqrestore(&alarm_slock, flags); | |
386 | ||
387 | hrtimer_cancel(&alarms[ANDROID_ALARM_RTC_WAKEUP].timer); | |
388 | hrtimer_cancel(&alarms[ | |
389 | ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK].timer); | |
390 | ||
391 | tmp_queue = &alarms[ANDROID_ALARM_RTC_WAKEUP]; | |
392 | if (tmp_queue->first) | |
393 | wakeup_queue = tmp_queue; | |
394 | tmp_queue = &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP]; | |
395 | if (tmp_queue->first && (!wakeup_queue || | |
396 | hrtimer_get_expires(&tmp_queue->timer).tv64 < | |
397 | hrtimer_get_expires(&wakeup_queue->timer).tv64)) | |
398 | wakeup_queue = tmp_queue; | |
399 | if (wakeup_queue) { | |
400 | rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time); | |
5dd12c29 AH |
401 | getnstimeofday(&wall_time); |
402 | rtc_tm_to_time(&rtc_current_rtc_time, &rtc_current_time); | |
403 | set_normalized_timespec(&rtc_delta, | |
404 | wall_time.tv_sec - rtc_current_time, | |
405 | wall_time.tv_nsec); | |
841cb11c AH |
406 | |
407 | rtc_alarm_time = timespec_sub(ktime_to_timespec( | |
408 | hrtimer_get_expires(&wakeup_queue->timer)), | |
409 | rtc_delta).tv_sec; | |
410 | ||
411 | rtc_time_to_tm(rtc_alarm_time, &rtc_alarm.time); | |
412 | rtc_alarm.enabled = 1; | |
413 | rtc_set_alarm(alarm_rtc_dev, &rtc_alarm); | |
414 | rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time); | |
415 | rtc_tm_to_time(&rtc_current_rtc_time, &rtc_current_time); | |
416 | pr_alarm(SUSPEND, | |
417 | "rtc alarm set at %ld, now %ld, rtc delta %ld.%09ld\n", | |
418 | rtc_alarm_time, rtc_current_time, | |
419 | rtc_delta.tv_sec, rtc_delta.tv_nsec); | |
420 | if (rtc_current_time + 1 >= rtc_alarm_time) { | |
421 | pr_alarm(SUSPEND, "alarm about to go off\n"); | |
422 | memset(&rtc_alarm, 0, sizeof(rtc_alarm)); | |
423 | rtc_alarm.enabled = 0; | |
424 | rtc_set_alarm(alarm_rtc_dev, &rtc_alarm); | |
425 | ||
426 | spin_lock_irqsave(&alarm_slock, flags); | |
427 | suspended = false; | |
428 | wake_lock_timeout(&alarm_rtc_wake_lock, 2 * HZ); | |
429 | update_timer_locked(&alarms[ANDROID_ALARM_RTC_WAKEUP], | |
430 | false); | |
431 | update_timer_locked(&alarms[ | |
432 | ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP], false); | |
433 | err = -EBUSY; | |
434 | spin_unlock_irqrestore(&alarm_slock, flags); | |
435 | } | |
436 | } | |
437 | return err; | |
438 | } | |
439 | ||
440 | static int alarm_resume(struct platform_device *pdev) | |
441 | { | |
442 | struct rtc_wkalrm alarm; | |
443 | unsigned long flags; | |
444 | ||
445 | pr_alarm(SUSPEND, "alarm_resume(%p)\n", pdev); | |
446 | ||
447 | memset(&alarm, 0, sizeof(alarm)); | |
448 | alarm.enabled = 0; | |
449 | rtc_set_alarm(alarm_rtc_dev, &alarm); | |
450 | ||
451 | spin_lock_irqsave(&alarm_slock, flags); | |
452 | suspended = false; | |
453 | update_timer_locked(&alarms[ANDROID_ALARM_RTC_WAKEUP], false); | |
454 | update_timer_locked(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP], | |
455 | false); | |
456 | spin_unlock_irqrestore(&alarm_slock, flags); | |
457 | ||
458 | return 0; | |
459 | } | |
460 | ||
461 | static struct rtc_task alarm_rtc_task = { | |
462 | .func = alarm_triggered_func | |
463 | }; | |
464 | ||
465 | static int rtc_alarm_add_device(struct device *dev, | |
466 | struct class_interface *class_intf) | |
467 | { | |
468 | int err; | |
469 | struct rtc_device *rtc = to_rtc_device(dev); | |
470 | ||
471 | mutex_lock(&alarm_setrtc_mutex); | |
472 | ||
473 | if (alarm_rtc_dev) { | |
474 | err = -EBUSY; | |
475 | goto err1; | |
476 | } | |
477 | ||
478 | alarm_platform_dev = | |
479 | platform_device_register_simple("alarm", -1, NULL, 0); | |
480 | if (IS_ERR(alarm_platform_dev)) { | |
481 | err = PTR_ERR(alarm_platform_dev); | |
482 | goto err2; | |
483 | } | |
484 | err = rtc_irq_register(rtc, &alarm_rtc_task); | |
485 | if (err) | |
486 | goto err3; | |
487 | alarm_rtc_dev = rtc; | |
488 | pr_alarm(INIT_STATUS, "using rtc device, %s, for alarms", rtc->name); | |
489 | mutex_unlock(&alarm_setrtc_mutex); | |
490 | ||
491 | return 0; | |
492 | ||
493 | err3: | |
494 | platform_device_unregister(alarm_platform_dev); | |
495 | err2: | |
496 | err1: | |
497 | mutex_unlock(&alarm_setrtc_mutex); | |
498 | return err; | |
499 | } | |
500 | ||
501 | static void rtc_alarm_remove_device(struct device *dev, | |
502 | struct class_interface *class_intf) | |
503 | { | |
504 | if (dev == &alarm_rtc_dev->dev) { | |
505 | pr_alarm(INIT_STATUS, "lost rtc device for alarms"); | |
506 | rtc_irq_unregister(alarm_rtc_dev, &alarm_rtc_task); | |
507 | platform_device_unregister(alarm_platform_dev); | |
508 | alarm_rtc_dev = NULL; | |
509 | } | |
510 | } | |
511 | ||
512 | static struct class_interface rtc_alarm_interface = { | |
513 | .add_dev = &rtc_alarm_add_device, | |
514 | .remove_dev = &rtc_alarm_remove_device, | |
515 | }; | |
516 | ||
517 | static struct platform_driver alarm_driver = { | |
518 | .suspend = alarm_suspend, | |
519 | .resume = alarm_resume, | |
520 | .driver = { | |
521 | .name = "alarm" | |
522 | } | |
523 | }; | |
524 | ||
525 | static int __init alarm_late_init(void) | |
526 | { | |
527 | unsigned long flags; | |
528 | struct timespec tmp_time, system_time; | |
529 | ||
530 | /* this needs to run after the rtc is read at boot */ | |
531 | spin_lock_irqsave(&alarm_slock, flags); | |
532 | /* We read the current rtc and system time so we can later calulate | |
533 | * elasped realtime to be (boot_systemtime + rtc - boot_rtc) == | |
534 | * (rtc - (boot_rtc - boot_systemtime)) | |
535 | */ | |
536 | getnstimeofday(&tmp_time); | |
537 | ktime_get_ts(&system_time); | |
538 | alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].delta = | |
539 | alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta = | |
540 | timespec_to_ktime(timespec_sub(tmp_time, system_time)); | |
541 | ||
542 | spin_unlock_irqrestore(&alarm_slock, flags); | |
543 | return 0; | |
544 | } | |
545 | ||
546 | static int __init alarm_driver_init(void) | |
547 | { | |
548 | int err; | |
549 | int i; | |
550 | ||
551 | for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) { | |
552 | hrtimer_init(&alarms[i].timer, | |
553 | CLOCK_REALTIME, HRTIMER_MODE_ABS); | |
554 | alarms[i].timer.function = alarm_timer_triggered; | |
555 | } | |
556 | hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].timer, | |
557 | CLOCK_MONOTONIC, HRTIMER_MODE_ABS); | |
558 | alarms[ANDROID_ALARM_SYSTEMTIME].timer.function = alarm_timer_triggered; | |
559 | err = platform_driver_register(&alarm_driver); | |
560 | if (err < 0) | |
561 | goto err1; | |
562 | wake_lock_init(&alarm_rtc_wake_lock, WAKE_LOCK_SUSPEND, "alarm_rtc"); | |
563 | rtc_alarm_interface.class = rtc_class; | |
564 | err = class_interface_register(&rtc_alarm_interface); | |
565 | if (err < 0) | |
566 | goto err2; | |
567 | ||
568 | return 0; | |
569 | ||
570 | err2: | |
571 | wake_lock_destroy(&alarm_rtc_wake_lock); | |
572 | platform_driver_unregister(&alarm_driver); | |
573 | err1: | |
574 | return err; | |
575 | } | |
576 | ||
577 | static void __exit alarm_exit(void) | |
578 | { | |
579 | class_interface_unregister(&rtc_alarm_interface); | |
580 | wake_lock_destroy(&alarm_rtc_wake_lock); | |
581 | platform_driver_unregister(&alarm_driver); | |
582 | } | |
583 | ||
584 | late_initcall(alarm_late_init); | |
585 | module_init(alarm_driver_init); | |
586 | module_exit(alarm_exit); | |
587 |