OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [char/] [rtc.c] - Blame information for rev 199

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 *      Real Time Clock interface for Linux
3
 *
4
 *      Copyright (C) 1996 Paul Gortmaker
5
 *
6
 *      This driver allows use of the real time clock (built into
7
 *      nearly all computers) from user space. It exports the /dev/rtc
8
 *      interface supporting various ioctl() and also the /proc/rtc
9
 *      pseudo-file for status information.
10
 *
11
 *      The ioctls can be used to set the interrupt behaviour and
12
 *      generation rate from the RTC via IRQ 8. Then the /dev/rtc
13
 *      interface can be used to make use of these timer interrupts,
14
 *      be they interval or alarm based.
15
 *
16
 *      The /dev/rtc interface will block on reads until an interrupt
17
 *      has been received. If a RTC interrupt has already happened,
18
 *      it will output an unsigned long and then block. The output value
19
 *      contains the interrupt status in the low byte and the number of
20
 *      interrupts since the last read in the remaining high bytes. The
21
 *      /dev/rtc interface can also be used with the select(2) call.
22
 *
23
 *      This program is free software; you can redistribute it and/or
24
 *      modify it under the terms of the GNU General Public License
25
 *      as published by the Free Software Foundation; either version
26
 *      2 of the License, or (at your option) any later version.
27
 *
28
 *      Based on other minimal char device drivers, like Alan's
29
 *      watchdog, Ted's random, etc. etc.
30
 *
31
 *      1.07    Paul Gortmaker.
32
 *      1.08    Miquel van Smoorenburg: disallow certain things on the
33
 *              DEC Alpha as the CMOS clock is also used for other things.
34
 *      1.09    Nikita Schmidt: epoch support and some Alpha cleanup.
35
 *
36
 */
37
 
38
#define RTC_VERSION             "1.09"
39
 
40
#define RTC_IRQ         8       /* Can't see this changing soon.        */
41
#define RTC_IO_EXTENT   0x10    /* Only really two ports, but...        */
42
 
43
/*
44
 *      Note that *all* calls to CMOS_READ and CMOS_WRITE are done with
45
 *      interrupts disabled. Due to the index-port/data-port (0x70/0x71)
46
 *      design of the RTC, we don't want two different things trying to
47
 *      get to it at once. (e.g. the periodic 11 min sync from time.c vs.
48
 *      this driver.)
49
 */
50
 
51
#include <linux/types.h>
52
#include <linux/errno.h>
53
#include <linux/miscdevice.h>
54
#include <linux/malloc.h>
55
#include <linux/ioport.h>
56
#include <linux/fcntl.h>
57
#include <linux/mc146818rtc.h>
58
 
59
#include <asm/io.h>
60
#include <asm/segment.h>
61
#include <asm/system.h>
62
 
63
/*
64
 *      We sponge a minor off of the misc major. No need slurping
65
 *      up another valuable major dev number for this.
66
 */
67
 
68
#define RTC_MINOR       135
69
 
70
static struct wait_queue *rtc_wait;
71
 
72
static struct timer_list rtc_irq_timer;
73
 
74
static int rtc_lseek(struct inode *inode, struct file *file, off_t offset,
75
                        int origin);
76
 
77
static int rtc_read(struct inode *inode, struct file *file,
78
                        char *buf, int count);
79
 
80
static int rtc_ioctl(struct inode *inode, struct file *file,
81
                        unsigned int cmd, unsigned long arg);
82
 
83
static int rtc_select(struct inode *inode, struct file *file,
84
                        int sel_type, select_table *wait);
85
 
86
void get_rtc_time (struct rtc_time *rtc_tm);
87
void get_rtc_alm_time (struct rtc_time *alm_tm);
88
void rtc_dropped_irq(unsigned long data);
89
 
90
void set_rtc_irq_bit(unsigned char bit);
91
void mask_rtc_irq_bit(unsigned char bit);
92
 
93
static inline unsigned char rtc_is_updating(void);
94
 
95
/*
96
 *      Bits in rtc_status. (7 bits of room for future expansion)
97
 */
98
 
99
#define RTC_IS_OPEN             0x01    /* means /dev/rtc is in use     */
100
#define RTC_TIMER_ON            0x02    /* missed irq timer active      */
101
 
102
unsigned char rtc_status = 0;            /* bitmapped status byte.       */
103
unsigned long rtc_freq = 0;              /* Current periodic IRQ rate    */
104
unsigned long rtc_irq_data = 0;          /* our output to the world      */
105
 
106
/*
107
 *      If this driver ever becomes modularised, it will be really nice
108
 *      to make the epoch retain its value across module reload...
109
 */
110
 
111
static unsigned long epoch = 1900;      /* year corresponding to 0x00   */
112
 
113
unsigned char days_in_mo[] =
114
                {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
115
 
116
/*
117
 *      A very tiny interrupt handler. It runs with SA_INTERRUPT set,
118
 *      so that there is no possibility of conflicting with the
119
 *      set_rtc_mmss() call that happens during some timer interrupts.
120
 *      (See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.)
121
 *
122
 *      On Alpha we won't get any interrupts anyway, as they all end up
123
 *      in the system timer code.
124
 */
125
 
126
#ifndef __alpha__
127
static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
128
{
129
        /*
130
         *      Can be an alarm interrupt, update complete interrupt,
131
         *      or a periodic interrupt. We store the status in the
132
         *      low byte and the number of interrupts received since
133
         *      the last read in the remainder of rtc_irq_data.
134
         */
135
 
136
        rtc_irq_data += 0x100;
137
        rtc_irq_data &= ~0xff;
138
        rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);
139
        wake_up_interruptible(&rtc_wait);
140
 
141
        if (rtc_status & RTC_TIMER_ON) {
142
                del_timer(&rtc_irq_timer);
143
                rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100;
144
                add_timer(&rtc_irq_timer);
145
        }
146
}
147
#endif
148
 
149
/*
150
 *      Now all the various file operations that we export.
151
 *      They are all useless on Alpha...  *sigh*.
152
 */
153
 
154
static int rtc_lseek(struct inode *inode, struct file *file, off_t offset,
155
        int origin)
156
{
157
        return -ESPIPE;
158
}
159
 
160
static int rtc_read(struct inode *inode, struct file *file, char *buf, int count)
161
{
162
#ifdef __alpha__
163
        return -EIO;
164
#else
165
        struct wait_queue wait = { current, NULL };
166
        int retval;
167
 
168
        if (count < sizeof(unsigned long))
169
                return -EINVAL;
170
 
171
        retval = verify_area(VERIFY_WRITE, buf, sizeof(unsigned long));
172
        if (retval)
173
                return retval;
174
 
175
        add_wait_queue(&rtc_wait, &wait);
176
 
177
        current->state = TASK_INTERRUPTIBLE;
178
 
179
        while (rtc_irq_data == 0) {
180
                if (file->f_flags & O_NONBLOCK) {
181
                        retval = -EAGAIN;
182
                        break;
183
                }
184
                if (current->signal & ~current->blocked) {
185
                        retval = -ERESTARTSYS;
186
                        break;
187
                }
188
                schedule();
189
        }
190
 
191
        if (retval == 0) {
192
                unsigned long data, flags;
193
                save_flags(flags);
194
                cli();
195
                data = rtc_irq_data;
196
                rtc_irq_data = 0;
197
                restore_flags(flags);
198
                memcpy_tofs(buf, &data, sizeof(unsigned long));
199
                retval = sizeof(unsigned long);
200
        }
201
 
202
        current->state = TASK_RUNNING;
203
        remove_wait_queue(&rtc_wait, &wait);
204
 
205
        return retval;
206
#endif
207
}
208
 
209
static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
210
        unsigned long arg)
211
{
212
 
213
        unsigned long flags;
214
 
215
        switch (cmd) {
216
#ifndef __alpha__
217
                case RTC_AIE_OFF:       /* Mask alarm int. enab. bit    */
218
                {
219
                        mask_rtc_irq_bit(RTC_AIE);
220
                        return 0;
221
                }
222
                case RTC_AIE_ON:        /* Allow alarm interrupts.      */
223
                {
224
                        set_rtc_irq_bit(RTC_AIE);
225
                        return 0;
226
                }
227
                case RTC_PIE_OFF:       /* Mask periodic int. enab. bit */
228
                {
229
                        mask_rtc_irq_bit(RTC_PIE);
230
                        if (rtc_status & RTC_TIMER_ON) {
231
                                del_timer(&rtc_irq_timer);
232
                                rtc_status &= ~RTC_TIMER_ON;
233
                        }
234
                        return 0;
235
                }
236
                case RTC_PIE_ON:        /* Allow periodic ints          */
237
                {
238
 
239
                        /*
240
                         * We don't really want Joe User enabling more
241
                         * than 64Hz of interrupts on a multi-user machine.
242
                         */
243
                        if ((rtc_freq > 64) && (!suser()))
244
                                return -EACCES;
245
 
246
                        if (!(rtc_status & RTC_TIMER_ON)) {
247
                                rtc_status |= RTC_TIMER_ON;
248
                                rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100;
249
                                add_timer(&rtc_irq_timer);
250
                        }
251
                        set_rtc_irq_bit(RTC_PIE);
252
                        return 0;
253
                }
254
                case RTC_UIE_OFF:       /* Mask ints from RTC updates.  */
255
                {
256
                        mask_rtc_irq_bit(RTC_UIE);
257
                        return 0;
258
                }
259
                case RTC_UIE_ON:        /* Allow ints for RTC updates.  */
260
                {
261
                        set_rtc_irq_bit(RTC_UIE);
262
                        return 0;
263
                }
264
#endif
265
                case RTC_ALM_READ:      /* Read the present alarm time */
266
                {
267
                        /*
268
                         * This returns a struct rtc_time. Reading >= 0xc0
269
                         * means "don't care" or "match all". Only the tm_hour,
270
                         * tm_min, and tm_sec values are filled in.
271
                         */
272
                        int retval;
273
                        struct rtc_time alm_tm;
274
 
275
                        retval = verify_area(VERIFY_WRITE, (struct rtc_time*)arg, sizeof(struct rtc_time));
276
                        if (retval != 0 )
277
                                return retval;
278
 
279
                        get_rtc_alm_time(&alm_tm);
280
 
281
                        memcpy_tofs((struct rtc_time*)arg, &alm_tm, sizeof(struct rtc_time));
282
 
283
                        return 0;
284
                }
285
                case RTC_ALM_SET:       /* Store a time into the alarm */
286
                {
287
                        /*
288
                         * This expects a struct rtc_time. Writing 0xff means
289
                         * "don't care" or "match all". Only the tm_hour,
290
                         * tm_min and tm_sec are used.
291
                         */
292
                        int retval;
293
                        unsigned char hrs, min, sec;
294
                        struct rtc_time alm_tm;
295
 
296
                        retval = verify_area(VERIFY_READ, (struct rtc_time*)arg, sizeof(struct rtc_time));
297
                        if (retval != 0 )
298
                                return retval;
299
 
300
                        memcpy_fromfs(&alm_tm, (struct rtc_time*)arg, sizeof(struct rtc_time));
301
 
302
                        hrs = alm_tm.tm_hour;
303
                        min = alm_tm.tm_min;
304
                        sec = alm_tm.tm_sec;
305
 
306
                        if (hrs >= 24)
307
                                hrs = 0xff;
308
 
309
                        if (min >= 60)
310
                                min = 0xff;
311
 
312
                        if (sec >= 60)
313
                                sec = 0xff;
314
 
315
                        save_flags(flags);
316
                        cli();
317
                        if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) ||
318
                                                        RTC_ALWAYS_BCD)
319
                        {
320
                                BIN_TO_BCD(sec);
321
                                BIN_TO_BCD(min);
322
                                BIN_TO_BCD(hrs);
323
                        }
324
                        CMOS_WRITE(hrs, RTC_HOURS_ALARM);
325
                        CMOS_WRITE(min, RTC_MINUTES_ALARM);
326
                        CMOS_WRITE(sec, RTC_SECONDS_ALARM);
327
                        restore_flags(flags);
328
 
329
                        return 0;
330
                }
331
                case RTC_RD_TIME:       /* Read the time/date from RTC  */
332
                {
333
                        int retval;
334
                        struct rtc_time rtc_tm;
335
 
336
                        retval = verify_area(VERIFY_WRITE, (struct rtc_time*)arg, sizeof(struct rtc_time));
337
                        if (retval !=0 )
338
                                return retval;
339
 
340
                        get_rtc_time(&rtc_tm);
341
                        memcpy_tofs((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time));
342
                        return 0;
343
                }
344
                case RTC_SET_TIME:      /* Set the RTC */
345
                {
346
                        int retval;
347
                        struct rtc_time rtc_tm;
348
                        unsigned char mon, day, hrs, min, sec, leap_yr;
349
                        unsigned char save_control, save_freq_select;
350
                        unsigned int yrs;
351
                        unsigned long flags;
352
 
353
                        if (!suser())
354
                                return -EACCES;
355
 
356
                        retval = verify_area(VERIFY_READ, (struct rtc_time*)arg, sizeof(struct rtc_time));
357
                        if (retval !=0 )
358
                                return retval;
359
 
360
                        memcpy_fromfs(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time));
361
 
362
                        yrs = rtc_tm.tm_year + 1900;
363
                        mon = rtc_tm.tm_mon + 1;   /* tm_mon starts at zero */
364
                        day = rtc_tm.tm_mday;
365
                        hrs = rtc_tm.tm_hour;
366
                        min = rtc_tm.tm_min;
367
                        sec = rtc_tm.tm_sec;
368
 
369
                        if (yrs < 1970)
370
                                return -EINVAL;
371
 
372
                        leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
373
 
374
                        if ((mon > 12) || (day == 0))
375
                                return -EINVAL;
376
 
377
                        if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
378
                                return -EINVAL;
379
 
380
                        if ((hrs >= 24) || (min >= 60) || (sec >= 60))
381
                                return -EINVAL;
382
 
383
                        if ((yrs -= epoch) > 255)    /* They are unsigned */
384
                                return -EINVAL;
385
 
386
                        save_flags(flags);
387
                        cli();
388
                        if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
389
                                if (yrs > 169) {
390
                                        restore_flags(flags);
391
                                        return -EINVAL;
392
                                }
393
                                if (yrs >= 100)
394
                                        yrs -= 100;
395
 
396
                                BIN_TO_BCD(sec);
397
                                BIN_TO_BCD(min);
398
                                BIN_TO_BCD(hrs);
399
                                BIN_TO_BCD(day);
400
                                BIN_TO_BCD(mon);
401
                                BIN_TO_BCD(yrs);
402
                        }
403
 
404
                        save_control = CMOS_READ(RTC_CONTROL);
405
                        CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
406
                        save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
407
                        CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
408
 
409
                        CMOS_WRITE(yrs, RTC_YEAR);
410
                        CMOS_WRITE(mon, RTC_MONTH);
411
                        CMOS_WRITE(day, RTC_DAY_OF_MONTH);
412
                        CMOS_WRITE(hrs, RTC_HOURS);
413
                        CMOS_WRITE(min, RTC_MINUTES);
414
                        CMOS_WRITE(sec, RTC_SECONDS);
415
 
416
                        CMOS_WRITE(save_control, RTC_CONTROL);
417
                        CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
418
 
419
                        restore_flags(flags);
420
                        return 0;
421
                }
422
                case RTC_IRQP_READ:     /* Read the periodic IRQ rate.  */
423
                {
424
                        int retval;
425
 
426
                        retval = verify_area(VERIFY_WRITE, (unsigned long*)arg, sizeof(unsigned long));
427
                        if (retval != 0)
428
                                return retval;
429
 
430
                        memcpy_tofs((unsigned long*)arg, &rtc_freq, sizeof(unsigned long));
431
                        return 0;
432
                }
433
#ifndef __alpha__
434
                case RTC_IRQP_SET:      /* Set periodic IRQ rate.       */
435
                {
436
                        int tmp = 0;
437
                        unsigned char val;
438
 
439
                        /*
440
                         * The max we can do is 8192Hz.
441
                         */
442
                        if ((arg < 2) || (arg > 8192))
443
                                return -EINVAL;
444
                        /*
445
                         * We don't really want Joe User generating more
446
                         * than 64Hz of interrupts on a multi-user machine.
447
                         */
448
                        if ((arg > 64) && (!suser()))
449
                                return -EACCES;
450
 
451
                        while (arg > (1<<tmp))
452
                                tmp++;
453
 
454
                        /*
455
                         * Check that the input was really a power of 2.
456
                         */
457
                        if (arg != (1<<tmp))
458
                                return -EINVAL;
459
 
460
                        rtc_freq = arg;
461
 
462
                        save_flags(flags);
463
                        cli();
464
                        val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
465
                        val |= (16 - tmp);
466
                        CMOS_WRITE(val, RTC_FREQ_SELECT);
467
                        restore_flags(flags);
468
                        return 0;
469
                }
470
#endif
471
#ifdef __alpha__
472
                case RTC_EPOCH_READ:    /* Read the epoch.      */
473
                {
474
                        int retval;
475
 
476
                        retval = verify_area(VERIFY_WRITE, (unsigned long*)arg, sizeof(unsigned long));
477
                        if (retval != 0)
478
                                return retval;
479
 
480
                        memcpy_tofs((unsigned long*)arg, &epoch, sizeof(unsigned long));
481
                        return 0;
482
                }
483
                case RTC_EPOCH_SET:     /* Set the epoch.       */
484
                {
485
                        /*
486
                         * There were no RTC clocks before 1900.
487
                         */
488
                        if (arg < 1900)
489
                                return -EINVAL;
490
 
491
                        if (!suser())
492
                                return -EACCES;
493
 
494
                        epoch = arg;
495
                        return 0;
496
                }
497
#endif
498
                default:
499
                        return -EINVAL;
500
        }
501
}
502
 
503
/*
504
 *      We enforce only one user at a time here with the open/close.
505
 *      Also clear the previous interrupt data on an open, and clean
506
 *      up things on a close.
507
 *      On Alpha we just open, for we don't mess with interrups anyway.
508
 */
509
 
510
static int rtc_open(struct inode *inode, struct file *file)
511
{
512
#ifndef __alpha__
513
        if(rtc_status & RTC_IS_OPEN)
514
                return -EBUSY;
515
 
516
        rtc_status |= RTC_IS_OPEN;
517
        rtc_irq_data = 0;
518
#endif
519
        return 0;
520
}
521
 
522
static void rtc_release(struct inode *inode, struct file *file)
523
{
524
 
525
        /*
526
         * Turn off all interrupts once the device is no longer
527
         * in use, and clear the data.
528
         */
529
 
530
#ifndef __alpha__
531
        unsigned char tmp;
532
        unsigned long flags;
533
 
534
        save_flags(flags);
535
        cli();
536
        tmp = CMOS_READ(RTC_CONTROL);
537
        tmp &=  ~RTC_PIE;
538
        tmp &=  ~RTC_AIE;
539
        tmp &=  ~RTC_UIE;
540
        CMOS_WRITE(tmp, RTC_CONTROL);
541
        CMOS_READ(RTC_INTR_FLAGS);
542
        restore_flags(flags);
543
 
544
        if (rtc_status & RTC_TIMER_ON) {
545
                rtc_status &= ~RTC_TIMER_ON;
546
                del_timer(&rtc_irq_timer);
547
        }
548
 
549
        rtc_irq_data = 0;
550
        rtc_status &= ~RTC_IS_OPEN;
551
#endif
552
}
553
 
554
#ifndef __alpha__
555
static int rtc_select(struct inode *inode, struct file *file,
556
                        int sel_type, select_table *wait)
557
{
558
        if (sel_type == SEL_IN) {
559
                if (rtc_irq_data != 0)
560
                        return 1;
561
                select_wait(&rtc_wait, wait);
562
        }
563
        return 0;
564
}
565
#endif
566
 
567
/*
568
 *      The various file operations we support.
569
 */
570
 
571
static struct file_operations rtc_fops = {
572
        rtc_lseek,
573
        rtc_read,
574
        NULL,           /* No write */
575
        NULL,           /* No readdir */
576
#ifdef __alpha__
577
        NULL,           /* No select on Alpha */
578
#else
579
        rtc_select,
580
#endif
581
        rtc_ioctl,
582
        NULL,           /* No mmap */
583
        rtc_open,
584
        rtc_release
585
};
586
 
587
static struct miscdevice rtc_dev=
588
{
589
        RTC_MINOR,
590
        "rtc",
591
        &rtc_fops
592
};
593
 
594
int rtc_init(void)
595
{
596
        unsigned long flags;
597
#ifdef __alpha__
598
        unsigned int year, ctrl;
599
        unsigned long uip_watchdog;
600
        char *guess = NULL;
601
#endif
602
 
603
        printk("Real Time Clock Driver v%s\n", RTC_VERSION);
604
#ifndef __alpha__
605
        if(request_irq(RTC_IRQ, rtc_interrupt, SA_INTERRUPT, "rtc", NULL))
606
        {
607
                /* Yeah right, seeing as irq 8 doesn't even hit the bus. */
608
                printk("rtc: IRQ %d is not free.\n", RTC_IRQ);
609
                return -EIO;
610
        }
611
#endif
612
        misc_register(&rtc_dev);
613
        /* Check region? Naaah! Just snarf it up. */
614
        request_region(RTC_PORT(0), RTC_IO_EXTENT, "rtc");
615
#ifdef __alpha__
616
        rtc_freq = HZ;
617
 
618
        /* Each operating system on an Alpha uses its own epoch.
619
           Let's try to guess which one we are using now. */
620
 
621
        uip_watchdog = jiffies;
622
        if (rtc_is_updating() != 0)
623
                while (jiffies - uip_watchdog < 2*HZ/100)
624
                        barrier();
625
 
626
        save_flags(flags);
627
        cli();
628
        year = CMOS_READ(RTC_YEAR);
629
        ctrl = CMOS_READ(RTC_CONTROL);
630
        restore_flags(flags);
631
 
632
        if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
633
                BCD_TO_BIN(year);       /* This should never happen... */
634
 
635
        if (year > 10 && year < 44) {
636
                epoch = 1980;
637
                guess = "ARC console";
638
        } else if (year < 96) {
639
                epoch = 1952;
640
                guess = "Digital UNIX";
641
        }
642
        if (guess)
643
                printk("rtc: %s epoch (%ld) detected\n", guess, epoch);
644
#else
645
        init_timer(&rtc_irq_timer);
646
        rtc_irq_timer.function = rtc_dropped_irq;
647
        rtc_wait = NULL;
648
        save_flags(flags);
649
        cli();
650
        /* Initialize periodic freq. to CMOS reset default, which is 1024Hz */
651
        CMOS_WRITE(((CMOS_READ(RTC_FREQ_SELECT) & 0xF0) | 0x06), RTC_FREQ_SELECT);
652
        restore_flags(flags);
653
        rtc_freq = 1024;
654
#endif
655
        return 0;
656
}
657
 
658
/*
659
 *      At IRQ rates >= 4096Hz, an interrupt may get lost altogether.
660
 *      (usually during an IDE disk interrupt, with IRQ unmasking off)
661
 *      Since the interrupt handler doesn't get called, the IRQ status
662
 *      byte doesn't get read, and the RTC stops generating interrupts.
663
 *      A timer is set, and will call this function if/when that happens.
664
 *      To get it out of this stalled state, we just read the status.
665
 *      At least a jiffy of interrupts (rtc_freq/HZ) will have been lost.
666
 *      (You *really* shouldn't be trying to use a non-realtime system
667
 *      for something that requires a steady > 1KHz signal anyways.)
668
 */
669
 
670
#ifndef __alpha__
671
void rtc_dropped_irq(unsigned long data)
672
{
673
        unsigned long flags;
674
 
675
        printk(KERN_INFO "rtc: lost some interrupts at %ldHz.\n", rtc_freq);
676
        del_timer(&rtc_irq_timer);
677
        rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100;
678
        add_timer(&rtc_irq_timer);
679
 
680
        save_flags(flags);
681
        cli();
682
        rtc_irq_data += ((rtc_freq/HZ)<<8);
683
        rtc_irq_data &= ~0xff;
684
        rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);     /* restart */
685
        restore_flags(flags);
686
}
687
#endif
688
 
689
/*
690
 *      Info exported via "/proc/rtc".
691
 */
692
 
693
int get_rtc_status(char *buf)
694
{
695
        char *p;
696
        struct rtc_time tm;
697
        unsigned char batt, ctrl;
698
        unsigned long flags;
699
 
700
        save_flags(flags);
701
        cli();
702
        batt = CMOS_READ(RTC_VALID) & RTC_VRT;
703
        ctrl = CMOS_READ(RTC_CONTROL);
704
        restore_flags(flags);
705
 
706
        p = buf;
707
 
708
        get_rtc_time(&tm);
709
 
710
        /*
711
         * There is no way to tell if the luser has the RTC set for local
712
         * time or for Universal Standard Time (GMT). Probably local though.
713
         */
714
        p += sprintf(p,
715
                "rtc_time\t: %02d:%02d:%02d\n"
716
                "rtc_date\t: %04d-%02d-%02d\n",
717
                tm.tm_hour, tm.tm_min, tm.tm_sec,
718
                tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
719
 
720
        get_rtc_alm_time(&tm);
721
 
722
        /*
723
         * We implicitly assume 24hr mode here. Alarm values >= 0xc0 will
724
         * match any value for that particular field. Values that are
725
         * greater than a valid time, but less than 0xc0 shouldn't appear.
726
         */
727
        p += sprintf(p, "alarm\t\t: ");
728
        if (tm.tm_hour <= 24)
729
                p += sprintf(p, "%02d:", tm.tm_hour);
730
        else
731
                p += sprintf(p, "**:");
732
 
733
        if (tm.tm_min <= 59)
734
                p += sprintf(p, "%02d:", tm.tm_min);
735
        else
736
                p += sprintf(p, "**:");
737
 
738
        if (tm.tm_sec <= 59)
739
                p += sprintf(p, "%02d\n", tm.tm_sec);
740
        else
741
                p += sprintf(p, "**\n");
742
 
743
        p += sprintf(p,
744
                "DST_enable\t: %s\n"
745
                "BCD\t\t: %s\n"
746
                "24hr\t\t: %s\n"
747
                "square_wave\t: %s\n"
748
                "alarm_IRQ\t: %s\n"
749
                "update_IRQ\t: %s\n"
750
                "periodic_IRQ\t: %s\n"
751
                "periodic_freq\t: %ld\n"
752
                "batt_status\t: %s\n",
753
                (ctrl & RTC_DST_EN) ? "yes" : "no",
754
                (ctrl & RTC_DM_BINARY) ? "no" : "yes",
755
                (ctrl & RTC_24H) ? "yes" : "no",
756
                (ctrl & RTC_SQWE) ? "yes" : "no",
757
                (ctrl & RTC_AIE) ? "yes" : "no",
758
                (ctrl & RTC_UIE) ? "yes" : "no",
759
                (ctrl & RTC_PIE) ? "yes" : "no",
760
                rtc_freq,
761
                batt ? "okay" : "dead");
762
 
763
        return  p - buf;
764
}
765
 
766
/*
767
 * Returns true if a clock update is in progress
768
 */
769
static inline unsigned char rtc_is_updating(void)
770
{
771
        unsigned long flags;
772
        unsigned char uip;
773
 
774
        save_flags(flags);
775
        cli();
776
        uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
777
        restore_flags(flags);
778
        return uip;
779
}
780
 
781
void get_rtc_time(struct rtc_time *rtc_tm)
782
{
783
 
784
        unsigned long flags, uip_watchdog = jiffies;
785
        unsigned char ctrl;
786
 
787
        /*
788
         * read RTC once any update in progress is done. The update
789
         * can take just over 2ms. We wait 10 to 20ms. There is no need to
790
         * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
791
         * If you need to know *exactly* when a second has started, enable
792
         * periodic update complete interrupts, (via ioctl) and then
793
         * immediately read /dev/rtc which will block until you get the IRQ.
794
         * Once the read clears, read the RTC time (again via ioctl). Easy.
795
         */
796
 
797
        if (rtc_is_updating() != 0)
798
                while (jiffies - uip_watchdog < 2*HZ/100)
799
                        barrier();
800
 
801
        /*
802
         * Only the values that we read from the RTC are set. We leave
803
         * tm_wday, tm_yday and tm_isdst untouched. Even though the
804
         * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
805
         * by the RTC when initially set to a non-zero value.
806
         */
807
        save_flags(flags);
808
        cli();
809
        rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS);
810
        rtc_tm->tm_min = CMOS_READ(RTC_MINUTES);
811
        rtc_tm->tm_hour = CMOS_READ(RTC_HOURS);
812
        rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH);
813
        rtc_tm->tm_mon = CMOS_READ(RTC_MONTH);
814
        rtc_tm->tm_year = CMOS_READ(RTC_YEAR);
815
        ctrl = CMOS_READ(RTC_CONTROL);
816
        restore_flags(flags);
817
 
818
        if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
819
        {
820
                BCD_TO_BIN(rtc_tm->tm_sec);
821
                BCD_TO_BIN(rtc_tm->tm_min);
822
                BCD_TO_BIN(rtc_tm->tm_hour);
823
                BCD_TO_BIN(rtc_tm->tm_mday);
824
                BCD_TO_BIN(rtc_tm->tm_mon);
825
                BCD_TO_BIN(rtc_tm->tm_year);
826
        }
827
 
828
        /*
829
         * Account for differences between how the RTC uses the values
830
         * and how they are defined in a struct rtc_time;
831
         */
832
        if ((rtc_tm->tm_year += epoch - 1900) <= 69)
833
                rtc_tm->tm_year += 100;
834
 
835
        rtc_tm->tm_mon--;
836
}
837
 
838
void get_rtc_alm_time(struct rtc_time *alm_tm)
839
{
840
        unsigned long flags;
841
        unsigned char ctrl;
842
 
843
        /*
844
         * Only the values that we read from the RTC are set. That
845
         * means only tm_hour, tm_min, and tm_sec.
846
         */
847
        save_flags(flags);
848
        cli();
849
        alm_tm->tm_sec = CMOS_READ(RTC_SECONDS_ALARM);
850
        alm_tm->tm_min = CMOS_READ(RTC_MINUTES_ALARM);
851
        alm_tm->tm_hour = CMOS_READ(RTC_HOURS_ALARM);
852
        ctrl = CMOS_READ(RTC_CONTROL);
853
        restore_flags(flags);
854
 
855
        if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
856
        {
857
                BCD_TO_BIN(alm_tm->tm_sec);
858
                BCD_TO_BIN(alm_tm->tm_min);
859
                BCD_TO_BIN(alm_tm->tm_hour);
860
        }
861
}
862
 
863
/*
864
 * Used to disable/enable interrupts for any one of UIE, AIE, PIE.
865
 * Rumour has it that if you frob the interrupt enable/disable
866
 * bits in RTC_CONTROL, you should read RTC_INTR_FLAGS, to
867
 * ensure you actually start getting interrupts. Probably for
868
 * compatibility with older/broken chipset RTC implementations.
869
 * We also clear out any old irq data after an ioctl() that
870
 * meddles with the interrupt enable/disable bits.
871
 */
872
 
873
#ifndef __alpha__
874
void mask_rtc_irq_bit(unsigned char bit)
875
{
876
        unsigned char val;
877
        unsigned long flags;
878
 
879
        save_flags(flags);
880
        cli();
881
        val = CMOS_READ(RTC_CONTROL);
882
        val &=  ~bit;
883
        CMOS_WRITE(val, RTC_CONTROL);
884
        CMOS_READ(RTC_INTR_FLAGS);
885
        restore_flags(flags);
886
        rtc_irq_data = 0;
887
}
888
 
889
void set_rtc_irq_bit(unsigned char bit)
890
{
891
        unsigned char val;
892
        unsigned long flags;
893
 
894
        save_flags(flags);
895
        cli();
896
        val = CMOS_READ(RTC_CONTROL);
897
        val |= bit;
898
        CMOS_WRITE(val, RTC_CONTROL);
899
        CMOS_READ(RTC_INTR_FLAGS);
900
        rtc_irq_data = 0;
901
        restore_flags(flags);
902
}
903
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.