Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
424 giacomo 1
/*
2
 *  include/asm-i386/mach-pc9800/mach_time.h
3
 *
4
 *  Machine specific set RTC function for PC-9800.
5
 *  Written by Osamu Tomita <tomita@cinet.co.jp>
6
 */
7
#ifndef _MACH_TIME_H
8
#define _MACH_TIME_H
9
 
10
#include <linux/bcd.h>
11
#include <linux/upd4990a.h>
12
 
13
/* for check timing call set_rtc_mmss() */
14
/* used in arch/i386/time.c::do_timer_interrupt() */
15
/*
16
 * Because PC-9800's RTC (NEC uPD4990A) does not allow setting
17
 * time partially, we always have to read-modify-write the
18
 * entire time (including year) so that set_rtc_mmss() will
19
 * take quite much time to execute.  You may want to relax
20
 * RTC resetting interval (currently ~11 minuts)...
21
 */
22
#define USEC_AFTER      1000000
23
#define USEC_BEFORE     0
24
 
25
static inline int mach_set_rtc_mmss(unsigned long nowtime)
26
{
27
        int retval = 0;
28
        int real_seconds, real_minutes, cmos_minutes;
29
        struct upd4990a_raw_data data;
30
 
31
        upd4990a_get_time(&data, 1);
32
        cmos_minutes = BCD2BIN(data.min);
33
 
34
        /*
35
         * since we're only adjusting minutes and seconds,
36
         * don't interfere with hour overflow. This avoids
37
         * messing with unknown time zones but requires your
38
         * RTC not to be off by more than 15 minutes
39
         */
40
        real_seconds = nowtime % 60;
41
        real_minutes = nowtime / 60;
42
        if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
43
                real_minutes += 30;     /* correct for half hour time zone */
44
        real_minutes %= 60;
45
 
46
        if (abs(real_minutes - cmos_minutes) < 30) {
47
                u8 temp_seconds = (real_seconds / 10) * 16 + real_seconds % 10;
48
                u8 temp_minutes = (real_minutes / 10) * 16 + real_minutes % 10;
49
 
50
                if (data.sec != temp_seconds || data.min != temp_minutes) {
51
                        data.sec = temp_seconds;
52
                        data.min = temp_minutes;
53
                        upd4990a_set_time(&data, 1);
54
                }
55
        } else {
56
                printk(KERN_WARNING
57
                       "set_rtc_mmss: can't update from %d to %d\n",
58
                       cmos_minutes, real_minutes);
59
                retval = -1;
60
        }
61
 
62
        /* uPD4990A users' manual says we should issue Register Hold
63
         * command after reading time, or future Time Read command
64
         * may not work.  When we have set the time, this also starts
65
         * the clock.
66
         */
67
        upd4990a_serial_command(UPD4990A_REGISTER_HOLD);
68
 
69
        return retval;
70
}
71
 
72
static inline unsigned long mach_get_cmos_time(void)
73
{
74
        int i;
75
        u8 prev, cur;
76
        unsigned int year;
77
        struct upd4990a_raw_data data;
78
 
79
        /* Connect uPD4990A's DATA OUT pin to its 1Hz reference clock. */
80
        upd4990a_serial_command(UPD4990A_REGISTER_HOLD);
81
 
82
        /* Catch rising edge of reference clock.  */
83
        prev = ~UPD4990A_READ_DATA();
84
        for (i = 0; i < 1800000; i++) { /* may take up to 1 second... */
85
                __asm__ ("outb %%al,%0" : : "N" (0x5f)); /* 0.6usec delay */
86
                cur = UPD4990A_READ_DATA();
87
                if (!(prev & cur & 1))
88
                        break;
89
                prev = ~cur;
90
        }
91
 
92
        upd4990a_get_time(&data, 0);
93
 
94
        if ((year = BCD2BIN(data.year) + 1900) < 1995)
95
                year += 100;
96
        return mktime(year, data.mon, BCD2BIN(data.mday), BCD2BIN(data.hour),
97
                        BCD2BIN(data.min), BCD2BIN(data.sec));
98
}
99
 
100
#endif /* !_MACH_TIME_H */