ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / char / upd4990a.c
1 /*
2  * NEC PC-9800 Real Time Clock interface for Linux      
3  *
4  * Copyright (C) 1997-2001  Linux/98 project,
5  *                          Kyoto University Microcomputer Club.
6  *
7  * Based on:
8  *      drivers/char/rtc.c by Paul Gortmaker
9  *
10  * Changes:
11  *  2001-02-09  Call check_region on rtc_init and do not request I/O 0033h.
12  *              Call del_timer and release_region on rtc_exit. -- tak
13  *  2001-07-14  Rewrite <linux/upd4990a.h> and split to <linux/upd4990a.h>
14  *              and <asm-i386/upd4990a.h>.
15  *              Introduce a lot of spin_lock/unlock (&rtc_lock).
16  */
17
18 #define RTC98_VERSION   "1.2"
19
20 #include <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/types.h>
23 #include <linux/miscdevice.h>
24 #include <linux/ioport.h>
25 #include <linux/fcntl.h>
26 #include <linux/rtc.h>
27 #include <linux/bcd.h>
28 #include <linux/upd4990a.h>
29 #include <linux/init.h>
30 #include <linux/poll.h>
31 #include <linux/proc_fs.h>
32 #include <linux/spinlock.h>
33
34 #include <asm/io.h>
35 #include <asm/uaccess.h>
36 #include <asm/system.h>
37
38 /*
39  *      We sponge a minor off of the misc major. No need slurping
40  *      up another valuable major dev number for this. If you add
41  *      an ioctl, make sure you don't conflict with SPARC's RTC
42  *      ioctls.
43  */
44
45 static struct fasync_struct *rtc_async_queue;
46
47 static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
48
49 static struct timer_list rtc_uie_timer;
50 static u8 old_refclk;
51
52 static int rtc_ioctl(struct inode *inode, struct file *file,
53                         unsigned int cmd, unsigned long arg);
54
55 static int rtc_read_proc(char *page, char **start, off_t off,
56                           int count, int *eof, void *data);
57
58 /*
59  *      Bits in rtc_status. (5 bits of room for future expansion)
60  */
61
62 #define RTC_IS_OPEN             0x01    /* means /dev/rtc is in use     */
63 #define RTC_TIMER_ON            0x02    /* not used */
64 #define RTC_UIE_TIMER_ON        0x04    /* UIE emulation timer is active */
65
66 /*
67  * rtc_status is never changed by rtc_interrupt, and ioctl/open/close is
68  * protected by the big kernel lock. However, ioctl can still disable the timer
69  * in rtc_status and then with del_timer after the interrupt has read
70  * rtc_status but before mod_timer is called, which would then reenable the
71  * timer (but you would need to have an awful timing before you'd trip on it)
72  */
73 static unsigned char rtc_status;        /* bitmapped status byte.       */
74 static unsigned long rtc_irq_data;      /* our output to the world      */
75
76 static const unsigned char days_in_mo[] = 
77 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
78
79 extern spinlock_t rtc_lock;     /* defined in arch/i386/kernel/time.c */
80
81 static void rtc_uie_intr(unsigned long data)
82 {
83         u8 refclk, tmp;
84
85         /* Kernel timer does del_timer internally before calling
86            each timer entry, so this is unnecessary.
87            del_timer(&rtc_uie_timer);  */
88         spin_lock(&rtc_lock);
89
90         /* Detect rising edge of 1Hz reference clock.  */
91         refclk = UPD4990A_READ_DATA();
92         tmp = old_refclk & refclk;
93         old_refclk = ~refclk;
94         if (!(tmp & 1))
95                 rtc_irq_data += 0x100;
96
97         spin_unlock(&rtc_lock);
98
99         if (!(tmp & 1)) {
100                 /* Now do the rest of the actions */
101                 wake_up_interruptible(&rtc_wait);
102                 kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
103         }
104
105         rtc_uie_timer.expires = jiffies + 1;
106         add_timer(&rtc_uie_timer);
107 }
108
109 /*
110  *      Now all the various file operations that we export.
111  */
112
113 static ssize_t rtc_read(struct file *file, char *buf,
114                         size_t count, loff_t *ppos)
115 {
116         DECLARE_WAITQUEUE(wait, current);
117         unsigned long data;
118         ssize_t retval = 0;
119         
120         if (count < sizeof(unsigned long))
121                 return -EINVAL;
122
123         add_wait_queue(&rtc_wait, &wait);
124
125         set_current_state(TASK_INTERRUPTIBLE);
126
127         do {
128                 /* First make it right. Then make it fast. Putting this whole
129                  * block within the parentheses of a while would be too
130                  * confusing. And no, xchg() is not the answer. */
131                 spin_lock_irq(&rtc_lock);
132                 data = rtc_irq_data;
133                 rtc_irq_data = 0;
134                 spin_unlock_irq(&rtc_lock);
135
136                 if (data != 0)
137                         break;
138                 if (file->f_flags & O_NONBLOCK) {
139                         retval = -EAGAIN;
140                         goto out;
141                 }
142                 if (signal_pending(current)) {
143                         retval = -ERESTARTSYS;
144                         goto out;
145                 }
146                 schedule();
147         } while (1);
148
149         retval = put_user(data, (unsigned long *)buf);
150         if (!retval)
151                 retval = sizeof(unsigned long); 
152  out:
153         set_current_state(TASK_RUNNING);
154         remove_wait_queue(&rtc_wait, &wait);
155
156         return retval;
157 }
158
159 static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
160                      unsigned long arg)
161 {
162         struct rtc_time wtime; 
163         struct upd4990a_raw_data raw;
164
165         switch (cmd) {
166         case RTC_UIE_OFF:       /* Mask ints from RTC updates.  */
167                 spin_lock_irq(&rtc_lock);
168                 if (rtc_status & RTC_UIE_TIMER_ON) {
169                         rtc_status &= ~RTC_UIE_TIMER_ON;
170                         del_timer(&rtc_uie_timer);
171                 }
172                 spin_unlock_irq(&rtc_lock);
173                 return 0;
174
175         case RTC_UIE_ON:        /* Allow ints for RTC updates.  */
176                 spin_lock_irq(&rtc_lock);
177                 rtc_irq_data = 0;
178                 if (!(rtc_status & RTC_UIE_TIMER_ON)) {
179                         rtc_status |= RTC_UIE_TIMER_ON;
180                         rtc_uie_timer.expires = jiffies + 1;
181                         add_timer(&rtc_uie_timer);
182                 }
183                 /* Just in case... */
184                 upd4990a_serial_command(UPD4990A_REGISTER_HOLD);
185                 old_refclk = ~UPD4990A_READ_DATA();
186                 spin_unlock_irq(&rtc_lock);
187                 return 0;
188
189         case RTC_RD_TIME:       /* Read the time/date from RTC  */
190                 spin_lock_irq(&rtc_lock);
191                 upd4990a_get_time(&raw, 0);
192                 spin_unlock_irq(&rtc_lock);
193
194                 wtime.tm_sec    = BCD2BIN(raw.sec);
195                 wtime.tm_min    = BCD2BIN(raw.min);
196                 wtime.tm_hour   = BCD2BIN(raw.hour);
197                 wtime.tm_mday   = BCD2BIN(raw.mday);
198                 wtime.tm_mon    = raw.mon - 1; /* convert to 0-base */
199                 wtime.tm_wday   = raw.wday;
200
201                 /*
202                  * Account for differences between how the RTC uses the values
203                  * and how they are defined in a struct rtc_time;
204                  */
205                 if ((wtime.tm_year = BCD2BIN(raw.year)) < 95)
206                         wtime.tm_year += 100;
207
208                 wtime.tm_isdst = 0;
209                 break;
210
211         case RTC_SET_TIME:      /* Set the RTC */
212         {
213                 int leap_yr;
214
215                 if (!capable(CAP_SYS_TIME))
216                         return -EACCES;
217
218                 if (copy_from_user(&wtime, (struct rtc_time *) arg,
219                                     sizeof (struct rtc_time)))
220                         return -EFAULT;
221
222                 /* Valid year is 1995 - 2094, inclusive.  */
223                 if (wtime.tm_year < 95 || wtime.tm_year > 194)
224                         return -EINVAL;
225
226                 if (wtime.tm_mon > 11 || wtime.tm_mday == 0)
227                         return -EINVAL;
228
229                 /* For acceptable year domain (1995 - 2094),
230                    this IS sufficient.  */
231                 leap_yr = !(wtime.tm_year % 4);
232
233                 if (wtime.tm_mday > (days_in_mo[wtime.tm_mon]
234                                      + (wtime.tm_mon == 2 && leap_yr)))
235                         return -EINVAL;
236                         
237                 if (wtime.tm_hour >= 24
238                     || wtime.tm_min >= 60 || wtime.tm_sec >= 60)
239                         return -EINVAL;
240
241                 if (wtime.tm_wday > 6)
242                         return -EINVAL;
243
244                 raw.sec  = BIN2BCD(wtime.tm_sec);
245                 raw.min  = BIN2BCD(wtime.tm_min);
246                 raw.hour = BIN2BCD(wtime.tm_hour);
247                 raw.mday = BIN2BCD(wtime.tm_mday);
248                 raw.mon  = wtime.tm_mon + 1;
249                 raw.wday = wtime.tm_wday;
250                 raw.year = BIN2BCD(wtime.tm_year % 100);
251
252                 spin_lock_irq(&rtc_lock);
253                 upd4990a_set_time(&raw, 0);
254                 spin_unlock_irq(&rtc_lock);
255
256                 return 0;
257         }
258         default:
259                 return -EINVAL;
260         }
261         return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
262 }
263
264 /*
265  *      We enforce only one user at a time here with the open/close.
266  *      Also clear the previous interrupt data on an open, and clean
267  *      up things on a close.
268  */
269
270 static int rtc_open(struct inode *inode, struct file *file)
271 {
272         spin_lock_irq(&rtc_lock);
273
274         if(rtc_status & RTC_IS_OPEN)
275                 goto out_busy;
276
277         rtc_status |= RTC_IS_OPEN;
278
279         rtc_irq_data = 0;
280         spin_unlock_irq(&rtc_lock);
281         return 0;
282
283  out_busy:
284         spin_unlock_irq(&rtc_lock);
285         return -EBUSY;
286 }
287
288 static int rtc_fasync(int fd, struct file *filp, int on)
289 {
290         return fasync_helper(fd, filp, on, &rtc_async_queue);
291 }
292
293 static int rtc_release(struct inode *inode, struct file *file)
294 {
295         del_timer(&rtc_uie_timer);
296
297         if (file->f_flags & FASYNC)
298                 rtc_fasync(-1, file, 0);
299
300         rtc_irq_data = 0;
301
302         /* No need for locking -- nobody else can do anything until this rmw is
303          * committed, and no timer is running. */
304         rtc_status &= ~(RTC_IS_OPEN | RTC_UIE_TIMER_ON);
305         return 0;
306 }
307
308 static unsigned int rtc_poll(struct file *file, poll_table *wait)
309 {
310         unsigned long l;
311
312         poll_wait(file, &rtc_wait, wait);
313
314         spin_lock_irq(&rtc_lock);
315         l = rtc_irq_data;
316         spin_unlock_irq(&rtc_lock);
317
318         if (l != 0)
319                 return POLLIN | POLLRDNORM;
320         return 0;
321 }
322
323 /*
324  *      The various file operations we support.
325  */
326
327 static struct file_operations rtc_fops = {
328         .owner          = THIS_MODULE,
329         .read           = rtc_read,
330         .poll           = rtc_poll,
331         .ioctl          = rtc_ioctl,
332         .open           = rtc_open,
333         .release        = rtc_release,
334         .fasync         = rtc_fasync,
335 };
336
337 static struct miscdevice rtc_dev=
338 {
339         .minor  = RTC_MINOR,
340         .name   = "rtc",
341         .fops   = &rtc_fops,
342 };
343
344 static int __init rtc_init(void)
345 {
346         int err = 0;
347
348         if (!request_region(UPD4990A_IO, 1, "rtc")) {
349                 printk(KERN_ERR "upd4990a: could not acquire I/O port %#x\n",
350                         UPD4990A_IO);
351                 return -EBUSY;
352         }
353
354         err = misc_register(&rtc_dev);
355         if (err) {
356                 printk(KERN_ERR "upd4990a: can't misc_register() on minor=%d\n",
357                         RTC_MINOR);
358                 release_region(UPD4990A_IO, 1);
359                 return err;
360         }
361                 
362 #if 0
363         printk(KERN_INFO "\xB6\xDA\xDD\xC0\xDE \xC4\xDE\xB9\xB2 Driver\n");  /* Calender Clock Driver */
364 #else
365         printk(KERN_INFO
366                "Real Time Clock driver for NEC PC-9800 v" RTC98_VERSION "\n");
367 #endif
368         create_proc_read_entry("driver/rtc", 0, NULL, rtc_read_proc, NULL);
369
370         init_timer(&rtc_uie_timer);
371         rtc_uie_timer.function = rtc_uie_intr;
372
373         return 0;
374 }
375
376 module_init (rtc_init);
377
378 static void __exit rtc_exit(void)
379 {
380         del_timer(&rtc_uie_timer);
381         release_region(UPD4990A_IO, 1);
382         remove_proc_entry("driver/rtc", NULL);
383         misc_deregister(&rtc_dev);
384 }
385
386 module_exit (rtc_exit);
387
388 /*
389  *      Info exported via "/proc/driver/rtc".
390  */
391
392 static inline int rtc_get_status(char *buf)
393 {
394         char *p;
395         unsigned int year;
396         struct upd4990a_raw_data data;
397
398         p = buf;
399
400         upd4990a_get_time(&data, 0);
401
402         /*
403          * There is no way to tell if the luser has the RTC set for local
404          * time or for Universal Standard Time (GMT). Probably local though.
405          */
406         if ((year = BCD2BIN(data.year) + 1900) < 1995)
407                 year += 100;
408         p += sprintf(p,
409                      "rtc_time\t: %02d:%02d:%02d\n"
410                      "rtc_date\t: %04d-%02d-%02d\n",
411                      BCD2BIN(data.hour), BCD2BIN(data.min),
412                      BCD2BIN(data.sec),
413                      year, data.mon, BCD2BIN(data.mday));
414
415         return  p - buf;
416 }
417
418 static int rtc_read_proc(char *page, char **start, off_t off,
419                          int count, int *eof, void *data)
420 {
421         int len = rtc_get_status(page);
422
423         if (len <= off + count)
424                 *eof = 1;
425         *start = page + off;
426         len -= off;
427         if (len > count)
428                 len = count;
429         if (len < 0)
430                 len = 0;
431         return len;
432 }