diff options
author | Alexandre Belloni <alexandre.belloni@bootlin.com> | 2018-12-31 05:36:16 -0500 |
---|---|---|
committer | Alexandre Belloni <alexandre.belloni@bootlin.com> | 2018-12-31 05:36:16 -0500 |
commit | 36e14f5fdfdf7cec8887b7ff69cd9bb5051ecf62 (patch) | |
tree | 5f014b344dddf644505b582dfa90c013218261c5 /drivers/rtc/rtc-dev.c | |
parent | bba3d2daa8a9bc888902275401f15ef48fcdd378 (diff) |
rtc: rename core files
Rename core files so there is a clearer separation between the RTC core and
the RTC drivers.
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Diffstat (limited to 'drivers/rtc/rtc-dev.c')
-rw-r--r-- | drivers/rtc/rtc-dev.c | 483 |
1 files changed, 0 insertions, 483 deletions
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c deleted file mode 100644 index 43d962a9c210..000000000000 --- a/drivers/rtc/rtc-dev.c +++ /dev/null | |||
@@ -1,483 +0,0 @@ | |||
1 | /* | ||
2 | * RTC subsystem, dev interface | ||
3 | * | ||
4 | * Copyright (C) 2005 Tower Technologies | ||
5 | * Author: Alessandro Zummo <a.zummo@towertech.it> | ||
6 | * | ||
7 | * based on arch/arm/common/rtctime.c | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/rtc.h> | ||
18 | #include <linux/sched/signal.h> | ||
19 | #include "rtc-core.h" | ||
20 | |||
21 | static dev_t rtc_devt; | ||
22 | |||
23 | #define RTC_DEV_MAX 16 /* 16 RTCs should be enough for everyone... */ | ||
24 | |||
25 | static int rtc_dev_open(struct inode *inode, struct file *file) | ||
26 | { | ||
27 | struct rtc_device *rtc = container_of(inode->i_cdev, | ||
28 | struct rtc_device, char_dev); | ||
29 | |||
30 | if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags)) | ||
31 | return -EBUSY; | ||
32 | |||
33 | file->private_data = rtc; | ||
34 | |||
35 | spin_lock_irq(&rtc->irq_lock); | ||
36 | rtc->irq_data = 0; | ||
37 | spin_unlock_irq(&rtc->irq_lock); | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | ||
43 | /* | ||
44 | * Routine to poll RTC seconds field for change as often as possible, | ||
45 | * after first RTC_UIE use timer to reduce polling | ||
46 | */ | ||
47 | static void rtc_uie_task(struct work_struct *work) | ||
48 | { | ||
49 | struct rtc_device *rtc = | ||
50 | container_of(work, struct rtc_device, uie_task); | ||
51 | struct rtc_time tm; | ||
52 | int num = 0; | ||
53 | int err; | ||
54 | |||
55 | err = rtc_read_time(rtc, &tm); | ||
56 | |||
57 | spin_lock_irq(&rtc->irq_lock); | ||
58 | if (rtc->stop_uie_polling || err) { | ||
59 | rtc->uie_task_active = 0; | ||
60 | } else if (rtc->oldsecs != tm.tm_sec) { | ||
61 | num = (tm.tm_sec + 60 - rtc->oldsecs) % 60; | ||
62 | rtc->oldsecs = tm.tm_sec; | ||
63 | rtc->uie_timer.expires = jiffies + HZ - (HZ/10); | ||
64 | rtc->uie_timer_active = 1; | ||
65 | rtc->uie_task_active = 0; | ||
66 | add_timer(&rtc->uie_timer); | ||
67 | } else if (schedule_work(&rtc->uie_task) == 0) { | ||
68 | rtc->uie_task_active = 0; | ||
69 | } | ||
70 | spin_unlock_irq(&rtc->irq_lock); | ||
71 | if (num) | ||
72 | rtc_handle_legacy_irq(rtc, num, RTC_UF); | ||
73 | } | ||
74 | static void rtc_uie_timer(struct timer_list *t) | ||
75 | { | ||
76 | struct rtc_device *rtc = from_timer(rtc, t, uie_timer); | ||
77 | unsigned long flags; | ||
78 | |||
79 | spin_lock_irqsave(&rtc->irq_lock, flags); | ||
80 | rtc->uie_timer_active = 0; | ||
81 | rtc->uie_task_active = 1; | ||
82 | if ((schedule_work(&rtc->uie_task) == 0)) | ||
83 | rtc->uie_task_active = 0; | ||
84 | spin_unlock_irqrestore(&rtc->irq_lock, flags); | ||
85 | } | ||
86 | |||
87 | static int clear_uie(struct rtc_device *rtc) | ||
88 | { | ||
89 | spin_lock_irq(&rtc->irq_lock); | ||
90 | if (rtc->uie_irq_active) { | ||
91 | rtc->stop_uie_polling = 1; | ||
92 | if (rtc->uie_timer_active) { | ||
93 | spin_unlock_irq(&rtc->irq_lock); | ||
94 | del_timer_sync(&rtc->uie_timer); | ||
95 | spin_lock_irq(&rtc->irq_lock); | ||
96 | rtc->uie_timer_active = 0; | ||
97 | } | ||
98 | if (rtc->uie_task_active) { | ||
99 | spin_unlock_irq(&rtc->irq_lock); | ||
100 | flush_scheduled_work(); | ||
101 | spin_lock_irq(&rtc->irq_lock); | ||
102 | } | ||
103 | rtc->uie_irq_active = 0; | ||
104 | } | ||
105 | spin_unlock_irq(&rtc->irq_lock); | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static int set_uie(struct rtc_device *rtc) | ||
110 | { | ||
111 | struct rtc_time tm; | ||
112 | int err; | ||
113 | |||
114 | err = rtc_read_time(rtc, &tm); | ||
115 | if (err) | ||
116 | return err; | ||
117 | spin_lock_irq(&rtc->irq_lock); | ||
118 | if (!rtc->uie_irq_active) { | ||
119 | rtc->uie_irq_active = 1; | ||
120 | rtc->stop_uie_polling = 0; | ||
121 | rtc->oldsecs = tm.tm_sec; | ||
122 | rtc->uie_task_active = 1; | ||
123 | if (schedule_work(&rtc->uie_task) == 0) | ||
124 | rtc->uie_task_active = 0; | ||
125 | } | ||
126 | rtc->irq_data = 0; | ||
127 | spin_unlock_irq(&rtc->irq_lock); | ||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc, unsigned int enabled) | ||
132 | { | ||
133 | if (enabled) | ||
134 | return set_uie(rtc); | ||
135 | else | ||
136 | return clear_uie(rtc); | ||
137 | } | ||
138 | EXPORT_SYMBOL(rtc_dev_update_irq_enable_emul); | ||
139 | |||
140 | #endif /* CONFIG_RTC_INTF_DEV_UIE_EMUL */ | ||
141 | |||
142 | static ssize_t | ||
143 | rtc_dev_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | ||
144 | { | ||
145 | struct rtc_device *rtc = file->private_data; | ||
146 | |||
147 | DECLARE_WAITQUEUE(wait, current); | ||
148 | unsigned long data; | ||
149 | ssize_t ret; | ||
150 | |||
151 | if (count != sizeof(unsigned int) && count < sizeof(unsigned long)) | ||
152 | return -EINVAL; | ||
153 | |||
154 | add_wait_queue(&rtc->irq_queue, &wait); | ||
155 | do { | ||
156 | __set_current_state(TASK_INTERRUPTIBLE); | ||
157 | |||
158 | spin_lock_irq(&rtc->irq_lock); | ||
159 | data = rtc->irq_data; | ||
160 | rtc->irq_data = 0; | ||
161 | spin_unlock_irq(&rtc->irq_lock); | ||
162 | |||
163 | if (data != 0) { | ||
164 | ret = 0; | ||
165 | break; | ||
166 | } | ||
167 | if (file->f_flags & O_NONBLOCK) { | ||
168 | ret = -EAGAIN; | ||
169 | break; | ||
170 | } | ||
171 | if (signal_pending(current)) { | ||
172 | ret = -ERESTARTSYS; | ||
173 | break; | ||
174 | } | ||
175 | schedule(); | ||
176 | } while (1); | ||
177 | set_current_state(TASK_RUNNING); | ||
178 | remove_wait_queue(&rtc->irq_queue, &wait); | ||
179 | |||
180 | if (ret == 0) { | ||
181 | /* Check for any data updates */ | ||
182 | if (rtc->ops->read_callback) | ||
183 | data = rtc->ops->read_callback(rtc->dev.parent, | ||
184 | data); | ||
185 | |||
186 | if (sizeof(int) != sizeof(long) && | ||
187 | count == sizeof(unsigned int)) | ||
188 | ret = put_user(data, (unsigned int __user *)buf) ?: | ||
189 | sizeof(unsigned int); | ||
190 | else | ||
191 | ret = put_user(data, (unsigned long __user *)buf) ?: | ||
192 | sizeof(unsigned long); | ||
193 | } | ||
194 | return ret; | ||
195 | } | ||
196 | |||
197 | static __poll_t rtc_dev_poll(struct file *file, poll_table *wait) | ||
198 | { | ||
199 | struct rtc_device *rtc = file->private_data; | ||
200 | unsigned long data; | ||
201 | |||
202 | poll_wait(file, &rtc->irq_queue, wait); | ||
203 | |||
204 | data = rtc->irq_data; | ||
205 | |||
206 | return (data != 0) ? (EPOLLIN | EPOLLRDNORM) : 0; | ||
207 | } | ||
208 | |||
209 | static long rtc_dev_ioctl(struct file *file, | ||
210 | unsigned int cmd, unsigned long arg) | ||
211 | { | ||
212 | int err = 0; | ||
213 | struct rtc_device *rtc = file->private_data; | ||
214 | const struct rtc_class_ops *ops = rtc->ops; | ||
215 | struct rtc_time tm; | ||
216 | struct rtc_wkalrm alarm; | ||
217 | void __user *uarg = (void __user *) arg; | ||
218 | |||
219 | err = mutex_lock_interruptible(&rtc->ops_lock); | ||
220 | if (err) | ||
221 | return err; | ||
222 | |||
223 | /* check that the calling task has appropriate permissions | ||
224 | * for certain ioctls. doing this check here is useful | ||
225 | * to avoid duplicate code in each driver. | ||
226 | */ | ||
227 | switch (cmd) { | ||
228 | case RTC_EPOCH_SET: | ||
229 | case RTC_SET_TIME: | ||
230 | if (!capable(CAP_SYS_TIME)) | ||
231 | err = -EACCES; | ||
232 | break; | ||
233 | |||
234 | case RTC_IRQP_SET: | ||
235 | if (arg > rtc->max_user_freq && !capable(CAP_SYS_RESOURCE)) | ||
236 | err = -EACCES; | ||
237 | break; | ||
238 | |||
239 | case RTC_PIE_ON: | ||
240 | if (rtc->irq_freq > rtc->max_user_freq && | ||
241 | !capable(CAP_SYS_RESOURCE)) | ||
242 | err = -EACCES; | ||
243 | break; | ||
244 | } | ||
245 | |||
246 | if (err) | ||
247 | goto done; | ||
248 | |||
249 | /* | ||
250 | * Drivers *SHOULD NOT* provide ioctl implementations | ||
251 | * for these requests. Instead, provide methods to | ||
252 | * support the following code, so that the RTC's main | ||
253 | * features are accessible without using ioctls. | ||
254 | * | ||
255 | * RTC and alarm times will be in UTC, by preference, | ||
256 | * but dual-booting with MS-Windows implies RTCs must | ||
257 | * use the local wall clock time. | ||
258 | */ | ||
259 | |||
260 | switch (cmd) { | ||
261 | case RTC_ALM_READ: | ||
262 | mutex_unlock(&rtc->ops_lock); | ||
263 | |||
264 | err = rtc_read_alarm(rtc, &alarm); | ||
265 | if (err < 0) | ||
266 | return err; | ||
267 | |||
268 | if (copy_to_user(uarg, &alarm.time, sizeof(tm))) | ||
269 | err = -EFAULT; | ||
270 | return err; | ||
271 | |||
272 | case RTC_ALM_SET: | ||
273 | mutex_unlock(&rtc->ops_lock); | ||
274 | |||
275 | if (copy_from_user(&alarm.time, uarg, sizeof(tm))) | ||
276 | return -EFAULT; | ||
277 | |||
278 | alarm.enabled = 0; | ||
279 | alarm.pending = 0; | ||
280 | alarm.time.tm_wday = -1; | ||
281 | alarm.time.tm_yday = -1; | ||
282 | alarm.time.tm_isdst = -1; | ||
283 | |||
284 | /* RTC_ALM_SET alarms may be up to 24 hours in the future. | ||
285 | * Rather than expecting every RTC to implement "don't care" | ||
286 | * for day/month/year fields, just force the alarm to have | ||
287 | * the right values for those fields. | ||
288 | * | ||
289 | * RTC_WKALM_SET should be used instead. Not only does it | ||
290 | * eliminate the need for a separate RTC_AIE_ON call, it | ||
291 | * doesn't have the "alarm 23:59:59 in the future" race. | ||
292 | * | ||
293 | * NOTE: some legacy code may have used invalid fields as | ||
294 | * wildcards, exposing hardware "periodic alarm" capabilities. | ||
295 | * Not supported here. | ||
296 | */ | ||
297 | { | ||
298 | time64_t now, then; | ||
299 | |||
300 | err = rtc_read_time(rtc, &tm); | ||
301 | if (err < 0) | ||
302 | return err; | ||
303 | now = rtc_tm_to_time64(&tm); | ||
304 | |||
305 | alarm.time.tm_mday = tm.tm_mday; | ||
306 | alarm.time.tm_mon = tm.tm_mon; | ||
307 | alarm.time.tm_year = tm.tm_year; | ||
308 | err = rtc_valid_tm(&alarm.time); | ||
309 | if (err < 0) | ||
310 | return err; | ||
311 | then = rtc_tm_to_time64(&alarm.time); | ||
312 | |||
313 | /* alarm may need to wrap into tomorrow */ | ||
314 | if (then < now) { | ||
315 | rtc_time64_to_tm(now + 24 * 60 * 60, &tm); | ||
316 | alarm.time.tm_mday = tm.tm_mday; | ||
317 | alarm.time.tm_mon = tm.tm_mon; | ||
318 | alarm.time.tm_year = tm.tm_year; | ||
319 | } | ||
320 | } | ||
321 | |||
322 | return rtc_set_alarm(rtc, &alarm); | ||
323 | |||
324 | case RTC_RD_TIME: | ||
325 | mutex_unlock(&rtc->ops_lock); | ||
326 | |||
327 | err = rtc_read_time(rtc, &tm); | ||
328 | if (err < 0) | ||
329 | return err; | ||
330 | |||
331 | if (copy_to_user(uarg, &tm, sizeof(tm))) | ||
332 | err = -EFAULT; | ||
333 | return err; | ||
334 | |||
335 | case RTC_SET_TIME: | ||
336 | mutex_unlock(&rtc->ops_lock); | ||
337 | |||
338 | if (copy_from_user(&tm, uarg, sizeof(tm))) | ||
339 | return -EFAULT; | ||
340 | |||
341 | return rtc_set_time(rtc, &tm); | ||
342 | |||
343 | case RTC_PIE_ON: | ||
344 | err = rtc_irq_set_state(rtc, 1); | ||
345 | break; | ||
346 | |||
347 | case RTC_PIE_OFF: | ||
348 | err = rtc_irq_set_state(rtc, 0); | ||
349 | break; | ||
350 | |||
351 | case RTC_AIE_ON: | ||
352 | mutex_unlock(&rtc->ops_lock); | ||
353 | return rtc_alarm_irq_enable(rtc, 1); | ||
354 | |||
355 | case RTC_AIE_OFF: | ||
356 | mutex_unlock(&rtc->ops_lock); | ||
357 | return rtc_alarm_irq_enable(rtc, 0); | ||
358 | |||
359 | case RTC_UIE_ON: | ||
360 | mutex_unlock(&rtc->ops_lock); | ||
361 | return rtc_update_irq_enable(rtc, 1); | ||
362 | |||
363 | case RTC_UIE_OFF: | ||
364 | mutex_unlock(&rtc->ops_lock); | ||
365 | return rtc_update_irq_enable(rtc, 0); | ||
366 | |||
367 | case RTC_IRQP_SET: | ||
368 | err = rtc_irq_set_freq(rtc, arg); | ||
369 | break; | ||
370 | |||
371 | case RTC_IRQP_READ: | ||
372 | err = put_user(rtc->irq_freq, (unsigned long __user *)uarg); | ||
373 | break; | ||
374 | |||
375 | case RTC_WKALM_SET: | ||
376 | mutex_unlock(&rtc->ops_lock); | ||
377 | if (copy_from_user(&alarm, uarg, sizeof(alarm))) | ||
378 | return -EFAULT; | ||
379 | |||
380 | return rtc_set_alarm(rtc, &alarm); | ||
381 | |||
382 | case RTC_WKALM_RD: | ||
383 | mutex_unlock(&rtc->ops_lock); | ||
384 | err = rtc_read_alarm(rtc, &alarm); | ||
385 | if (err < 0) | ||
386 | return err; | ||
387 | |||
388 | if (copy_to_user(uarg, &alarm, sizeof(alarm))) | ||
389 | err = -EFAULT; | ||
390 | return err; | ||
391 | |||
392 | default: | ||
393 | /* Finally try the driver's ioctl interface */ | ||
394 | if (ops->ioctl) { | ||
395 | err = ops->ioctl(rtc->dev.parent, cmd, arg); | ||
396 | if (err == -ENOIOCTLCMD) | ||
397 | err = -ENOTTY; | ||
398 | } else | ||
399 | err = -ENOTTY; | ||
400 | break; | ||
401 | } | ||
402 | |||
403 | done: | ||
404 | mutex_unlock(&rtc->ops_lock); | ||
405 | return err; | ||
406 | } | ||
407 | |||
408 | static int rtc_dev_fasync(int fd, struct file *file, int on) | ||
409 | { | ||
410 | struct rtc_device *rtc = file->private_data; | ||
411 | return fasync_helper(fd, file, on, &rtc->async_queue); | ||
412 | } | ||
413 | |||
414 | static int rtc_dev_release(struct inode *inode, struct file *file) | ||
415 | { | ||
416 | struct rtc_device *rtc = file->private_data; | ||
417 | |||
418 | /* We shut down the repeating IRQs that userspace enabled, | ||
419 | * since nothing is listening to them. | ||
420 | * - Update (UIE) ... currently only managed through ioctls | ||
421 | * - Periodic (PIE) ... also used through rtc_*() interface calls | ||
422 | * | ||
423 | * Leave the alarm alone; it may be set to trigger a system wakeup | ||
424 | * later, or be used by kernel code, and is a one-shot event anyway. | ||
425 | */ | ||
426 | |||
427 | /* Keep ioctl until all drivers are converted */ | ||
428 | rtc_dev_ioctl(file, RTC_UIE_OFF, 0); | ||
429 | rtc_update_irq_enable(rtc, 0); | ||
430 | rtc_irq_set_state(rtc, 0); | ||
431 | |||
432 | clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags); | ||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | static const struct file_operations rtc_dev_fops = { | ||
437 | .owner = THIS_MODULE, | ||
438 | .llseek = no_llseek, | ||
439 | .read = rtc_dev_read, | ||
440 | .poll = rtc_dev_poll, | ||
441 | .unlocked_ioctl = rtc_dev_ioctl, | ||
442 | .open = rtc_dev_open, | ||
443 | .release = rtc_dev_release, | ||
444 | .fasync = rtc_dev_fasync, | ||
445 | }; | ||
446 | |||
447 | /* insertion/removal hooks */ | ||
448 | |||
449 | void rtc_dev_prepare(struct rtc_device *rtc) | ||
450 | { | ||
451 | if (!rtc_devt) | ||
452 | return; | ||
453 | |||
454 | if (rtc->id >= RTC_DEV_MAX) { | ||
455 | dev_dbg(&rtc->dev, "too many RTC devices\n"); | ||
456 | return; | ||
457 | } | ||
458 | |||
459 | rtc->dev.devt = MKDEV(MAJOR(rtc_devt), rtc->id); | ||
460 | |||
461 | #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL | ||
462 | INIT_WORK(&rtc->uie_task, rtc_uie_task); | ||
463 | timer_setup(&rtc->uie_timer, rtc_uie_timer, 0); | ||
464 | #endif | ||
465 | |||
466 | cdev_init(&rtc->char_dev, &rtc_dev_fops); | ||
467 | rtc->char_dev.owner = rtc->owner; | ||
468 | } | ||
469 | |||
470 | void __init rtc_dev_init(void) | ||
471 | { | ||
472 | int err; | ||
473 | |||
474 | err = alloc_chrdev_region(&rtc_devt, 0, RTC_DEV_MAX, "rtc"); | ||
475 | if (err < 0) | ||
476 | pr_err("failed to allocate char dev region\n"); | ||
477 | } | ||
478 | |||
479 | void __exit rtc_dev_exit(void) | ||
480 | { | ||
481 | if (rtc_devt) | ||
482 | unregister_chrdev_region(rtc_devt, RTC_DEV_MAX); | ||
483 | } | ||