This source file includes following definitions.
- rtc_interrupt
- rtc_lseek
- rtc_read
- rtc_ioctl
- rtc_open
- rtc_release
- rtc_select
- rtc_init
- get_rtc_status
- rtc_is_updating
- get_rtc_time
- get_rtc_alm_time
- mask_rtc_irq_bit
- set_rtc_irq_bit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 #define RTC_VERSION "1.04"
34
35 #define RTC_IRQ 8
36 #define RTC_IO_BASE 0x70
37 #define RTC_IO_EXTENT 0x10
38
39
40
41
42
43
44
45
46
47 #include <linux/types.h>
48 #include <linux/errno.h>
49 #include <linux/miscdevice.h>
50 #include <linux/malloc.h>
51 #include <linux/ioport.h>
52 #include <linux/fcntl.h>
53 #include <linux/mc146818rtc.h>
54
55 #include <asm/io.h>
56 #include <asm/segment.h>
57 #include <asm/system.h>
58
59 #include <time.h>
60
61
62
63
64
65
66 #define RTC_MINOR 135
67
68 static struct wait_queue *rtc_wait;
69
70 static int rtc_lseek(struct inode *inode, struct file *file, off_t offset,
71 int origin);
72
73 static int rtc_read(struct inode *inode, struct file *file,
74 char *buf, int count);
75
76 static int rtc_ioctl(struct inode *inode, struct file *file,
77 unsigned int cmd, unsigned long arg);
78
79 static int rtc_select(struct inode *inode, struct file *file,
80 int sel_type, select_table *wait);
81
82 void get_rtc_time (struct tm *rtc_tm);
83 void get_rtc_alm_time (struct tm *alm_tm);
84
85 inline void set_rtc_irq_bit(unsigned char bit);
86 inline void mask_rtc_irq_bit(unsigned char bit);
87
88 unsigned char rtc_is_updating(void);
89
90
91
92
93
94 #define RTC_IS_OPEN 0x01
95
96 unsigned char rtc_status = 0;
97 unsigned long rtc_irq_data = 0;
98
99 unsigned char days_in_mo[] =
100 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
101
102
103
104
105
106
107
108
109 static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
110 {
111
112
113
114
115
116
117
118 rtc_irq_data += 0x100;
119 rtc_irq_data &= ~0xff;
120 rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);
121 wake_up_interruptible(&rtc_wait);
122 }
123
124
125
126
127
128 static int rtc_lseek(struct inode *inode, struct file *file, off_t offset,
129 int origin)
130 {
131 return -ESPIPE;
132 }
133
134 static int rtc_read(struct inode *inode, struct file *file, char *buf, int count)
135 {
136 struct wait_queue wait = { current, NULL };
137 int retval;
138
139 if (count < sizeof(unsigned long))
140 return -EINVAL;
141
142 retval = verify_area(VERIFY_WRITE, buf, sizeof(unsigned long));
143 if (retval)
144 return retval;
145
146 add_wait_queue(&rtc_wait, &wait);
147
148 current->state = TASK_INTERRUPTIBLE;
149
150 while (rtc_irq_data == 0) {
151 if (file->f_flags & O_NONBLOCK) {
152 retval = -EAGAIN;
153 break;
154 }
155 if (current->signal & ~current->blocked) {
156 retval = -ERESTARTSYS;
157 break;
158 }
159 schedule();
160 continue;
161 }
162
163 if (retval == 0) {
164 memcpy_tofs(buf, &rtc_irq_data, sizeof(unsigned long));
165 rtc_irq_data = 0;
166 retval = sizeof(unsigned long);
167 }
168
169 current->state = TASK_RUNNING;
170 remove_wait_queue(&rtc_wait, &wait);
171
172 return retval;
173 }
174
175 static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
176 unsigned long arg)
177 {
178
179 unsigned long flags;
180
181 switch (cmd) {
182 case RTC_AIE_OFF:
183 {
184 mask_rtc_irq_bit(RTC_AIE);
185 return 0;
186 }
187 case RTC_AIE_ON:
188 {
189 set_rtc_irq_bit(RTC_AIE);
190 return 0;
191 }
192 case RTC_PIE_OFF:
193 {
194 mask_rtc_irq_bit(RTC_PIE);
195 return 0;
196 }
197 case RTC_PIE_ON:
198 {
199 unsigned int hz;
200 unsigned char tmp;
201
202 save_flags(flags);
203 cli();
204 tmp = CMOS_READ(RTC_FREQ_SELECT) & 0x0f;
205 restore_flags(flags);
206
207 hz = (tmp ? (65536/(1<<tmp)) : 0);
208
209
210
211
212
213 if ((hz > 64) && (!suser()))
214 return -EPERM;
215
216 set_rtc_irq_bit(RTC_PIE);
217 return 0;
218 }
219 case RTC_UIE_OFF:
220 {
221 mask_rtc_irq_bit(RTC_UIE);
222 return 0;
223 }
224 case RTC_UIE_ON:
225 {
226 set_rtc_irq_bit(RTC_UIE);
227 return 0;
228 }
229 case RTC_ALM_READ:
230 {
231
232
233
234
235
236 int retval;
237 struct tm alm_tm;
238
239 retval = verify_area(VERIFY_WRITE, (struct tm*)arg, sizeof(struct tm));
240 if (retval != 0 )
241 return retval;
242
243 get_rtc_alm_time(&alm_tm);
244
245 memcpy_tofs((struct tm*)arg, &alm_tm, sizeof(struct tm));
246
247 return 0;
248 }
249 case RTC_ALM_SET:
250 {
251
252
253
254
255
256 int retval;
257 unsigned char hrs, min, sec;
258 struct tm alm_tm;
259
260 retval = verify_area(VERIFY_READ, (struct tm*)arg, sizeof(struct tm));
261 if (retval != 0 )
262 return retval;
263
264 memcpy_fromfs(&alm_tm, (struct tm*)arg, sizeof(struct tm));
265
266 hrs = alm_tm.tm_hour;
267 min = alm_tm.tm_min;
268 sec = alm_tm.tm_sec;
269
270 if (hrs >= 24)
271 hrs = 0xff;
272
273 if (min >= 60)
274 min = 0xff;
275
276 if (sec >= 60)
277 sec = 0xff;
278
279 save_flags(flags);
280 cli();
281 if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) ||
282 RTC_ALWAYS_BCD)
283 {
284 BIN_TO_BCD(sec);
285 BIN_TO_BCD(min);
286 BIN_TO_BCD(hrs);
287 }
288 CMOS_WRITE(hrs, RTC_HOURS_ALARM);
289 CMOS_WRITE(min, RTC_MINUTES_ALARM);
290 CMOS_WRITE(sec, RTC_SECONDS_ALARM);
291 restore_flags(flags);
292
293 return 0;
294 }
295 case RTC_RD_TIME:
296 {
297 int retval;
298 struct tm rtc_tm;
299
300 retval = verify_area(VERIFY_WRITE, (struct tm*)arg, sizeof(struct tm));
301 if (retval !=0 )
302 return retval;
303
304 get_rtc_time(&rtc_tm);
305 memcpy_tofs((struct tm*)arg, &rtc_tm, sizeof(struct tm));
306 return 0;
307 }
308 case RTC_SET_TIME:
309 {
310 int retval;
311 struct tm rtc_tm;
312 unsigned char mon, day, hrs, min, sec, leap_yr;
313 unsigned char save_control, save_freq_select;
314 unsigned int yrs;
315 unsigned long flags;
316
317 if (!suser())
318 return -EPERM;
319
320 retval = verify_area(VERIFY_READ, (struct tm*)arg, sizeof(struct tm));
321 if (retval !=0 )
322 return retval;
323
324 memcpy_fromfs(&rtc_tm, (struct tm*)arg, sizeof(struct tm));
325
326 yrs = rtc_tm.tm_year + 1900;
327 mon = rtc_tm.tm_mon + 1;
328 day = rtc_tm.tm_mday;
329 hrs = rtc_tm.tm_hour;
330 min = rtc_tm.tm_min;
331 sec = rtc_tm.tm_sec;
332
333 if ((yrs < 1970) || (yrs > 2069))
334 return -EINVAL;
335
336 leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
337
338 if ((mon > 12) || (day == 0))
339 return -EINVAL;
340
341 if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
342 return -EINVAL;
343
344 if ((hrs >= 24) || (min >= 60) || (sec >= 60))
345 return -EINVAL;
346
347 if (yrs >= 2000)
348 yrs -= 2000;
349 else
350 yrs -= 1900;
351
352 save_flags(flags);
353 cli();
354 if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) ||
355 RTC_ALWAYS_BCD)
356 {
357 BIN_TO_BCD(sec);
358 BIN_TO_BCD(min);
359 BIN_TO_BCD(hrs);
360 BIN_TO_BCD(day);
361 BIN_TO_BCD(mon);
362 BIN_TO_BCD(yrs);
363 }
364
365 save_control = CMOS_READ(RTC_CONTROL);
366 CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
367 save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
368 CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
369
370 CMOS_WRITE(yrs, RTC_YEAR);
371 CMOS_WRITE(mon, RTC_MONTH);
372 CMOS_WRITE(day, RTC_DAY_OF_MONTH);
373 CMOS_WRITE(hrs, RTC_HOURS);
374 CMOS_WRITE(min, RTC_MINUTES);
375 CMOS_WRITE(sec, RTC_SECONDS);
376
377 CMOS_WRITE(save_control, RTC_CONTROL);
378 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
379
380 restore_flags(flags);
381 return 0;
382 }
383 case RTC_IRQP_READ:
384 {
385 unsigned long hz;
386 int retval;
387
388 retval = verify_area(VERIFY_WRITE, (unsigned long*)arg, sizeof(unsigned long));
389 if (retval != 0)
390 return retval;
391
392 save_flags(flags);
393 cli();
394 retval = CMOS_READ(RTC_FREQ_SELECT) & 0x0f;
395 restore_flags(flags);
396 hz = (retval ? (65536/(1<<retval)) : 0);
397 memcpy_tofs((unsigned long*)arg, &hz, sizeof(unsigned long));
398 return 0;
399 }
400 case RTC_IRQP_SET:
401 {
402 int tmp = 0;
403 unsigned char val;
404
405
406
407
408 if (arg > 8192)
409 return -EINVAL;
410
411
412
413
414 if ((arg > 64) && (!suser()))
415 return -EPERM;
416
417 while (arg > (1<<tmp))
418 tmp++;
419
420
421
422
423 if ((arg != 0) && (arg != (1<<tmp)))
424 return -EINVAL;
425
426 save_flags(flags);
427 cli();
428 val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
429
430 if (arg == 0) {
431 CMOS_WRITE(val, RTC_FREQ_SELECT);
432 restore_flags(flags);
433 return 0;
434 }
435
436 val |= (16 - tmp);
437 CMOS_WRITE(val, RTC_FREQ_SELECT);
438 restore_flags(flags);
439 return 0;
440 }
441 default:
442 return -EINVAL;
443 }
444 }
445
446
447
448
449
450
451
452 static int rtc_open(struct inode *inode, struct file *file)
453 {
454
455 if(rtc_status & RTC_IS_OPEN)
456 return -EBUSY;
457
458 rtc_status |= RTC_IS_OPEN;
459 rtc_irq_data = 0;
460 return 0;
461 }
462
463 static void rtc_release(struct inode *inode, struct file *file)
464 {
465
466
467
468
469
470
471 unsigned char tmp;
472 unsigned long flags;
473
474 save_flags(flags);
475 cli();
476 tmp = CMOS_READ(RTC_CONTROL);
477 tmp &= ~RTC_PIE;
478 tmp &= ~RTC_AIE;
479 tmp &= ~RTC_UIE;
480 CMOS_WRITE(tmp, RTC_CONTROL);
481 CMOS_READ(RTC_INTR_FLAGS);
482 restore_flags(flags);
483 rtc_irq_data = 0;
484 rtc_status &= ~RTC_IS_OPEN;
485 }
486
487 static int rtc_select(struct inode *inode, struct file *file,
488 int sel_type, select_table *wait)
489 {
490 if (sel_type == SEL_IN) {
491 if (rtc_irq_data != 0)
492 return 1;
493 select_wait(&rtc_wait, wait);
494 }
495 return 0;
496 }
497
498
499
500
501
502 static struct file_operations rtc_fops = {
503 rtc_lseek,
504 rtc_read,
505 NULL,
506 NULL,
507 rtc_select,
508 rtc_ioctl,
509 NULL,
510 rtc_open,
511 rtc_release
512 };
513
514 static struct miscdevice rtc_dev=
515 {
516 RTC_MINOR,
517 "rtc",
518 &rtc_fops
519 };
520
521 int rtc_init(void)
522 {
523 printk("Real Time Clock Driver v%s\n", RTC_VERSION);
524 if(request_irq(RTC_IRQ, rtc_interrupt, SA_INTERRUPT, "rtc", NULL))
525 {
526
527 printk("rtc: IRQ %d is not free.\n", RTC_IRQ);
528 return -EIO;
529 }
530 misc_register(&rtc_dev);
531
532 request_region(RTC_IO_BASE, RTC_IO_EXTENT, "rtc");
533 rtc_wait = NULL;
534 return 0;
535 }
536
537
538
539
540
541 int get_rtc_status(char *buf)
542 {
543 char *p;
544 struct tm tm;
545 unsigned char freq, batt, ctrl;
546 unsigned long flags;
547
548 save_flags(flags);
549 freq = CMOS_READ(RTC_FREQ_SELECT) & 0x0F;
550 batt = CMOS_READ(RTC_VALID) & RTC_VRT;
551 ctrl = CMOS_READ(RTC_CONTROL);
552 restore_flags(flags);
553
554 p = buf;
555
556 get_rtc_time(&tm);
557
558
559
560
561
562 p += sprintf(p, "date : %04d-%02d-%02d\n",
563 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
564 p += sprintf(p, "time : %02d-%02d-%02d\n",
565 tm.tm_hour, tm.tm_min, tm.tm_sec);
566
567 get_rtc_alm_time(&tm);
568
569
570
571
572
573
574 p += sprintf(p, "alarm : ");
575 if (tm.tm_hour <= 24)
576 p += sprintf(p, "%02d", tm.tm_hour);
577 else
578 p += sprintf(p, "**");
579 p += sprintf(p, "-");
580 if (tm.tm_min <= 59)
581 p += sprintf(p, "%02d", tm.tm_min);
582 else
583 p += sprintf(p, "**");
584 p += sprintf(p, "-");
585 if (tm.tm_sec <= 59)
586 p += sprintf(p, "%02d", tm.tm_sec);
587 else
588 p += sprintf(p, "**");
589 p += sprintf(p, "\n");
590
591 p += sprintf(p, "daylight : %s\n",
592 ((ctrl & RTC_DST_EN) ? "yes" : "no" ));
593 p += sprintf(p, "bcd : %s\n",
594 ((ctrl & RTC_DM_BINARY) ? "no" : "yes" ));
595 p += sprintf(p, "24hr : %s\n",
596 ((ctrl & RTC_24H) ? "yes" : "no" ));
597 p += sprintf(p, "sqwave : %s\n",
598 ((ctrl & RTC_SQWE) ? "yes" : "no" ));
599
600 p += sprintf(p, "alarm_int : %s\n",
601 ((ctrl & RTC_AIE) ? "yes" : "no" ));
602 p += sprintf(p, "update_int : %s\n",
603 ((ctrl & RTC_UIE) ? "yes" : "no" ));
604 p += sprintf(p, "periodic_int : %s\n",
605 ((ctrl & RTC_PIE) ? "yes" : "no" ));
606
607 p += sprintf(p, "periodic_freq : %d\n",
608 (freq ? (65536/(1<<freq)) : 0));
609
610 p += sprintf(p, "battery_ok : %s\n",
611 (batt ? "yes" : "no"));
612
613 return p - buf;
614 }
615
616
617
618
619 inline unsigned char rtc_is_updating(void)
620 {
621 unsigned long flags;
622 unsigned char uip;
623
624 save_flags(flags);
625 uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
626 restore_flags(flags);
627 return uip;
628 }
629
630 void get_rtc_time(struct tm *rtc_tm)
631 {
632
633 unsigned long flags, uip_watchdog = jiffies;
634 unsigned char ctrl;
635
636
637
638
639
640
641
642
643
644
645
646 if (rtc_is_updating() != 0)
647 while (jiffies - uip_watchdog < 2*HZ/100)
648 barrier();
649
650
651
652
653
654
655
656 save_flags(flags);
657 cli();
658 rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
659 rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
660 rtc_tm->tm_hour = CMOS_READ(RTC_HOURS);
661 rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
662 rtc_tm->tm_mon = CMOS_READ(RTC_MONTH);
663 rtc_tm->tm_year = CMOS_READ(RTC_YEAR);
664 ctrl = CMOS_READ(RTC_CONTROL);
665 restore_flags(flags);
666
667 if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
668 {
669 BCD_TO_BIN(rtc_tm->tm_sec);
670 BCD_TO_BIN(rtc_tm->tm_min);
671 BCD_TO_BIN(rtc_tm->tm_hour);
672 BCD_TO_BIN(rtc_tm->tm_mday);
673 BCD_TO_BIN(rtc_tm->tm_mon);
674 BCD_TO_BIN(rtc_tm->tm_year);
675 }
676
677
678
679
680
681 if (rtc_tm->tm_year <= 69)
682 rtc_tm->tm_year += 100;
683
684 rtc_tm->tm_mon--;
685 }
686
687 void get_rtc_alm_time(struct tm *alm_tm)
688 {
689 unsigned long flags;
690 unsigned char ctrl;
691
692
693
694
695
696 save_flags(flags);
697 cli();
698 alm_tm->tm_sec = CMOS_READ(RTC_SECONDS_ALARM);
699 alm_tm->tm_min = CMOS_READ(RTC_MINUTES_ALARM);
700 alm_tm->tm_hour = CMOS_READ(RTC_HOURS_ALARM);
701 ctrl = CMOS_READ(RTC_CONTROL);
702 restore_flags(flags);
703
704 if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
705 {
706 BCD_TO_BIN(alm_tm->tm_sec);
707 BCD_TO_BIN(alm_tm->tm_min);
708 BCD_TO_BIN(alm_tm->tm_hour);
709 }
710 }
711
712
713
714
715
716
717
718
719
720
721 inline void mask_rtc_irq_bit(unsigned char bit)
722 {
723 unsigned char val;
724 unsigned long flags;
725
726 save_flags(flags);
727 cli();
728 val = CMOS_READ(RTC_CONTROL);
729 val &= ~bit;
730 CMOS_WRITE(val, RTC_CONTROL);
731 CMOS_READ(RTC_INTR_FLAGS);
732 restore_flags(flags);
733 rtc_irq_data = 0;
734 }
735
736 inline void set_rtc_irq_bit(unsigned char bit)
737 {
738 unsigned char val;
739 unsigned long flags;
740
741 save_flags(flags);
742 cli();
743 val = CMOS_READ(RTC_CONTROL);
744 val |= bit;
745 CMOS_WRITE(val, RTC_CONTROL);
746 CMOS_READ(RTC_INTR_FLAGS);
747 restore_flags(flags);
748 rtc_irq_data = 0;
749 }
750