Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
genrtc.c
Go to the documentation of this file.
1 /*
2  * Real Time Clock interface for
3  * - q40 and other m68k machines,
4  * - HP PARISC machines
5  * - PowerPC machines
6  * emulate some RTC irq capabilities in software
7  *
8  * Copyright (C) 1999 Richard Zidlicky
9  *
10  * based on Paul Gortmaker's rtc.c device and
11  * Sam Creasey Generic rtc driver
12  *
13  * This driver allows use of the real time clock (built into
14  * nearly all computers) from user space. It exports the /dev/rtc
15  * interface supporting various ioctl() and also the /proc/driver/rtc
16  * pseudo-file for status information.
17  *
18  * The ioctls can be used to set the interrupt behaviour where
19  * supported.
20  *
21  * The /dev/rtc interface will block on reads until an interrupt
22  * has been received. If a RTC interrupt has already happened,
23  * it will output an unsigned long and then block. The output value
24  * contains the interrupt status in the low byte and the number of
25  * interrupts since the last read in the remaining high bytes. The
26  * /dev/rtc interface can also be used with the select(2) call.
27  *
28  * This program is free software; you can redistribute it and/or
29  * modify it under the terms of the GNU General Public License
30  * as published by the Free Software Foundation; either version
31  * 2 of the License, or (at your option) any later version.
32  *
33 
34  * 1.01 fix for 2.3.X [email protected]
35  * 1.02 merged with code from genrtc.c [email protected]
36  * 1.03 make it more portable [email protected]
37  * 1.04 removed useless timer code [email protected]
38  * 1.05 portable RTC_UIE emulation [email protected]
39  * 1.06 set_rtc_time can return an error [email protected]
40  * 1.07 ported to HP PARISC (hppa) Helge Deller <[email protected]>
41  */
42 
43 #define RTC_VERSION "1.07"
44 
45 #include <linux/module.h>
46 #include <linux/sched.h>
47 #include <linux/errno.h>
48 #include <linux/miscdevice.h>
49 #include <linux/fcntl.h>
50 
51 #include <linux/rtc.h>
52 #include <linux/init.h>
53 #include <linux/poll.h>
54 #include <linux/proc_fs.h>
55 #include <linux/mutex.h>
56 #include <linux/workqueue.h>
57 
58 #include <asm/uaccess.h>
59 #include <asm/rtc.h>
60 
61 /*
62  * We sponge a minor off of the misc major. No need slurping
63  * up another valuable major dev number for this. If you add
64  * an ioctl, make sure you don't conflict with SPARC's RTC
65  * ioctls.
66  */
67 
68 static DEFINE_MUTEX(gen_rtc_mutex);
69 static DECLARE_WAIT_QUEUE_HEAD(gen_rtc_wait);
70 
71 /*
72  * Bits in gen_rtc_status.
73  */
74 
75 #define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */
76 
77 static unsigned char gen_rtc_status; /* bitmapped status byte. */
78 static unsigned long gen_rtc_irq_data; /* our output to the world */
79 
80 /* months start at 0 now */
81 static unsigned char days_in_mo[] =
82 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
83 
84 static int irq_active;
85 
86 #ifdef CONFIG_GEN_RTC_X
87 static struct work_struct genrtc_task;
88 static struct timer_list timer_task;
89 
90 static unsigned int oldsecs;
91 static int lostint;
92 static unsigned long tt_exp;
93 
94 static void gen_rtc_timer(unsigned long data);
95 
96 static volatile int stask_active; /* schedule_work */
97 static volatile int ttask_active; /* timer_task */
98 static int stop_rtc_timers; /* don't requeue tasks */
99 static DEFINE_SPINLOCK(gen_rtc_lock);
100 
101 static void gen_rtc_interrupt(unsigned long arg);
102 
103 /*
104  * Routine to poll RTC seconds field for change as often as possible,
105  * after first RTC_UIE use timer to reduce polling
106  */
107 static void genrtc_troutine(struct work_struct *work)
108 {
109  unsigned int tmp = get_rtc_ss();
110 
111  if (stop_rtc_timers) {
112  stask_active = 0;
113  return;
114  }
115 
116  if (oldsecs != tmp){
117  oldsecs = tmp;
118 
119  timer_task.function = gen_rtc_timer;
120  timer_task.expires = jiffies + HZ - (HZ/10);
121  tt_exp=timer_task.expires;
122  ttask_active=1;
123  stask_active=0;
124  add_timer(&timer_task);
125 
126  gen_rtc_interrupt(0);
127  } else if (schedule_work(&genrtc_task) == 0)
128  stask_active = 0;
129 }
130 
131 static void gen_rtc_timer(unsigned long data)
132 {
133  lostint = get_rtc_ss() - oldsecs ;
134  if (lostint<0)
135  lostint = 60 - lostint;
136  if (time_after(jiffies, tt_exp))
137  printk(KERN_INFO "genrtc: timer task delayed by %ld jiffies\n",
138  jiffies-tt_exp);
139  ttask_active=0;
140  stask_active=1;
141  if ((schedule_work(&genrtc_task) == 0))
142  stask_active = 0;
143 }
144 
145 /*
146  * call gen_rtc_interrupt function to signal an RTC_UIE,
147  * arg is unused.
148  * Could be invoked either from a real interrupt handler or
149  * from some routine that periodically (eg 100HZ) monitors
150  * whether RTC_SECS changed
151  */
152 static void gen_rtc_interrupt(unsigned long arg)
153 {
154  /* We store the status in the low byte and the number of
155  * interrupts received since the last read in the remainder
156  * of rtc_irq_data. */
157 
158  gen_rtc_irq_data += 0x100;
159  gen_rtc_irq_data &= ~0xff;
160  gen_rtc_irq_data |= RTC_UIE;
161 
162  if (lostint){
163  printk("genrtc: system delaying clock ticks?\n");
164  /* increment count so that userspace knows something is wrong */
165  gen_rtc_irq_data += ((lostint-1)<<8);
166  lostint = 0;
167  }
168 
169  wake_up_interruptible(&gen_rtc_wait);
170 }
171 
172 /*
173  * Now all the various file operations that we export.
174  */
175 static ssize_t gen_rtc_read(struct file *file, char __user *buf,
176  size_t count, loff_t *ppos)
177 {
178  unsigned long data;
179  ssize_t retval;
180 
181  if (count != sizeof (unsigned int) && count != sizeof (unsigned long))
182  return -EINVAL;
183 
184  if (file->f_flags & O_NONBLOCK && !gen_rtc_irq_data)
185  return -EAGAIN;
186 
187  retval = wait_event_interruptible(gen_rtc_wait,
188  (data = xchg(&gen_rtc_irq_data, 0)));
189  if (retval)
190  goto out;
191 
192  /* first test allows optimizer to nuke this case for 32-bit machines */
193  if (sizeof (int) != sizeof (long) && count == sizeof (unsigned int)) {
194  unsigned int uidata = data;
195  retval = put_user(uidata, (unsigned int __user *)buf) ?:
196  sizeof(unsigned int);
197  }
198  else {
199  retval = put_user(data, (unsigned long __user *)buf) ?:
200  sizeof(unsigned long);
201  }
202 out:
203  return retval;
204 }
205 
206 static unsigned int gen_rtc_poll(struct file *file,
207  struct poll_table_struct *wait)
208 {
209  poll_wait(file, &gen_rtc_wait, wait);
210  if (gen_rtc_irq_data != 0)
211  return POLLIN | POLLRDNORM;
212  return 0;
213 }
214 
215 #endif
216 
217 /*
218  * Used to disable/enable interrupts, only RTC_UIE supported
219  * We also clear out any old irq data after an ioctl() that
220  * meddles with the interrupt enable/disable bits.
221  */
222 
223 static inline void gen_clear_rtc_irq_bit(unsigned char bit)
224 {
225 #ifdef CONFIG_GEN_RTC_X
226  stop_rtc_timers = 1;
227  if (ttask_active){
228  del_timer_sync(&timer_task);
229  ttask_active = 0;
230  }
231  while (stask_active)
232  schedule();
233 
234  spin_lock(&gen_rtc_lock);
235  irq_active = 0;
236  spin_unlock(&gen_rtc_lock);
237 #endif
238 }
239 
240 static inline int gen_set_rtc_irq_bit(unsigned char bit)
241 {
242 #ifdef CONFIG_GEN_RTC_X
243  spin_lock(&gen_rtc_lock);
244  if ( !irq_active ) {
245  irq_active = 1;
246  stop_rtc_timers = 0;
247  lostint = 0;
248  INIT_WORK(&genrtc_task, genrtc_troutine);
249  oldsecs = get_rtc_ss();
250  init_timer(&timer_task);
251 
252  stask_active = 1;
253  if (schedule_work(&genrtc_task) == 0){
254  stask_active = 0;
255  }
256  }
257  spin_unlock(&gen_rtc_lock);
258  gen_rtc_irq_data = 0;
259  return 0;
260 #else
261  return -EINVAL;
262 #endif
263 }
264 
265 static int gen_rtc_ioctl(struct file *file,
266  unsigned int cmd, unsigned long arg)
267 {
268  struct rtc_time wtime;
269  struct rtc_pll_info pll;
270  void __user *argp = (void __user *)arg;
271 
272  switch (cmd) {
273 
274  case RTC_PLL_GET:
275  if (get_rtc_pll(&pll))
276  return -EINVAL;
277  else
278  return copy_to_user(argp, &pll, sizeof pll) ? -EFAULT : 0;
279 
280  case RTC_PLL_SET:
281  if (!capable(CAP_SYS_TIME))
282  return -EACCES;
283  if (copy_from_user(&pll, argp, sizeof(pll)))
284  return -EFAULT;
285  return set_rtc_pll(&pll);
286 
287  case RTC_UIE_OFF: /* disable ints from RTC updates. */
288  gen_clear_rtc_irq_bit(RTC_UIE);
289  return 0;
290 
291  case RTC_UIE_ON: /* enable ints for RTC updates. */
292  return gen_set_rtc_irq_bit(RTC_UIE);
293 
294  case RTC_RD_TIME: /* Read the time/date from RTC */
295  /* this doesn't get week-day, who cares */
296  memset(&wtime, 0, sizeof(wtime));
297  get_rtc_time(&wtime);
298 
299  return copy_to_user(argp, &wtime, sizeof(wtime)) ? -EFAULT : 0;
300 
301  case RTC_SET_TIME: /* Set the RTC */
302  {
303  int year;
304  unsigned char leap_yr;
305 
306  if (!capable(CAP_SYS_TIME))
307  return -EACCES;
308 
309  if (copy_from_user(&wtime, argp, sizeof(wtime)))
310  return -EFAULT;
311 
312  year = wtime.tm_year + 1900;
313  leap_yr = ((!(year % 4) && (year % 100)) ||
314  !(year % 400));
315 
316  if ((wtime.tm_mon < 0 || wtime.tm_mon > 11) || (wtime.tm_mday < 1))
317  return -EINVAL;
318 
319  if (wtime.tm_mday < 0 || wtime.tm_mday >
320  (days_in_mo[wtime.tm_mon] + ((wtime.tm_mon == 1) && leap_yr)))
321  return -EINVAL;
322 
323  if (wtime.tm_hour < 0 || wtime.tm_hour >= 24 ||
324  wtime.tm_min < 0 || wtime.tm_min >= 60 ||
325  wtime.tm_sec < 0 || wtime.tm_sec >= 60)
326  return -EINVAL;
327 
328  return set_rtc_time(&wtime);
329  }
330  }
331 
332  return -EINVAL;
333 }
334 
335 static long gen_rtc_unlocked_ioctl(struct file *file, unsigned int cmd,
336  unsigned long arg)
337 {
338  int ret;
339 
340  mutex_lock(&gen_rtc_mutex);
341  ret = gen_rtc_ioctl(file, cmd, arg);
342  mutex_unlock(&gen_rtc_mutex);
343 
344  return ret;
345 }
346 
347 /*
348  * We enforce only one user at a time here with the open/close.
349  * Also clear the previous interrupt data on an open, and clean
350  * up things on a close.
351  */
352 
353 static int gen_rtc_open(struct inode *inode, struct file *file)
354 {
355  mutex_lock(&gen_rtc_mutex);
356  if (gen_rtc_status & RTC_IS_OPEN) {
357  mutex_unlock(&gen_rtc_mutex);
358  return -EBUSY;
359  }
360 
361  gen_rtc_status |= RTC_IS_OPEN;
362  gen_rtc_irq_data = 0;
363  irq_active = 0;
364  mutex_unlock(&gen_rtc_mutex);
365 
366  return 0;
367 }
368 
369 static int gen_rtc_release(struct inode *inode, struct file *file)
370 {
371  /*
372  * Turn off all interrupts once the device is no longer
373  * in use and clear the data.
374  */
375 
376  gen_clear_rtc_irq_bit(RTC_PIE|RTC_AIE|RTC_UIE);
377 
378  gen_rtc_status &= ~RTC_IS_OPEN;
379  return 0;
380 }
381 
382 
383 #ifdef CONFIG_PROC_FS
384 
385 /*
386  * Info exported via "/proc/driver/rtc".
387  */
388 
389 static int gen_rtc_proc_output(char *buf)
390 {
391  char *p;
392  struct rtc_time tm;
393  unsigned int flags;
394  struct rtc_pll_info pll;
395 
396  p = buf;
397 
398  flags = get_rtc_time(&tm);
399 
400  p += sprintf(p,
401  "rtc_time\t: %02d:%02d:%02d\n"
402  "rtc_date\t: %04d-%02d-%02d\n"
403  "rtc_epoch\t: %04u\n",
405  tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 1900);
406 
407  tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
408 
409  p += sprintf(p, "alarm\t\t: ");
410  if (tm.tm_hour <= 24)
411  p += sprintf(p, "%02d:", tm.tm_hour);
412  else
413  p += sprintf(p, "**:");
414 
415  if (tm.tm_min <= 59)
416  p += sprintf(p, "%02d:", tm.tm_min);
417  else
418  p += sprintf(p, "**:");
419 
420  if (tm.tm_sec <= 59)
421  p += sprintf(p, "%02d\n", tm.tm_sec);
422  else
423  p += sprintf(p, "**\n");
424 
425  p += sprintf(p,
426  "DST_enable\t: %s\n"
427  "BCD\t\t: %s\n"
428  "24hr\t\t: %s\n"
429  "square_wave\t: %s\n"
430  "alarm_IRQ\t: %s\n"
431  "update_IRQ\t: %s\n"
432  "periodic_IRQ\t: %s\n"
433  "periodic_freq\t: %ld\n"
434  "batt_status\t: %s\n",
435  (flags & RTC_DST_EN) ? "yes" : "no",
436  (flags & RTC_DM_BINARY) ? "no" : "yes",
437  (flags & RTC_24H) ? "yes" : "no",
438  (flags & RTC_SQWE) ? "yes" : "no",
439  (flags & RTC_AIE) ? "yes" : "no",
440  irq_active ? "yes" : "no",
441  (flags & RTC_PIE) ? "yes" : "no",
442  0L /* freq */,
443  (flags & RTC_BATT_BAD) ? "bad" : "okay");
444  if (!get_rtc_pll(&pll))
445  p += sprintf(p,
446  "PLL adjustment\t: %d\n"
447  "PLL max +ve adjustment\t: %d\n"
448  "PLL max -ve adjustment\t: %d\n"
449  "PLL +ve adjustment factor\t: %d\n"
450  "PLL -ve adjustment factor\t: %d\n"
451  "PLL frequency\t: %ld\n",
452  pll.pll_value,
453  pll.pll_max,
454  pll.pll_min,
455  pll.pll_posmult,
456  pll.pll_negmult,
457  pll.pll_clock);
458  return p - buf;
459 }
460 
461 static int gen_rtc_read_proc(char *page, char **start, off_t off,
462  int count, int *eof, void *data)
463 {
464  int len = gen_rtc_proc_output (page);
465  if (len <= off+count) *eof = 1;
466  *start = page + off;
467  len -= off;
468  if (len>count) len = count;
469  if (len<0) len = 0;
470  return len;
471 }
472 
473 static int __init gen_rtc_proc_init(void)
474 {
475  struct proc_dir_entry *r;
476 
477  r = create_proc_read_entry("driver/rtc", 0, NULL, gen_rtc_read_proc, NULL);
478  if (!r)
479  return -ENOMEM;
480  return 0;
481 }
482 #else
483 static inline int gen_rtc_proc_init(void) { return 0; }
484 #endif /* CONFIG_PROC_FS */
485 
486 
487 /*
488  * The various file operations we support.
489  */
490 
491 static const struct file_operations gen_rtc_fops = {
492  .owner = THIS_MODULE,
493 #ifdef CONFIG_GEN_RTC_X
494  .read = gen_rtc_read,
495  .poll = gen_rtc_poll,
496 #endif
497  .unlocked_ioctl = gen_rtc_unlocked_ioctl,
498  .open = gen_rtc_open,
499  .release = gen_rtc_release,
500  .llseek = noop_llseek,
501 };
502 
503 static struct miscdevice rtc_gen_dev =
504 {
505  .minor = RTC_MINOR,
506  .name = "rtc",
507  .fops = &gen_rtc_fops,
508 };
509 
510 static int __init rtc_generic_init(void)
511 {
512  int retval;
513 
514  printk(KERN_INFO "Generic RTC Driver v%s\n", RTC_VERSION);
515 
516  retval = misc_register(&rtc_gen_dev);
517  if (retval < 0)
518  return retval;
519 
520  retval = gen_rtc_proc_init();
521  if (retval) {
522  misc_deregister(&rtc_gen_dev);
523  return retval;
524  }
525 
526  return 0;
527 }
528 
529 static void __exit rtc_generic_exit(void)
530 {
531  remove_proc_entry ("driver/rtc", NULL);
532  misc_deregister(&rtc_gen_dev);
533 }
534 
535 
536 module_init(rtc_generic_init);
537 module_exit(rtc_generic_exit);
538 
539 MODULE_AUTHOR("Richard Zidlicky");
540 MODULE_LICENSE("GPL");