diff options
Diffstat (limited to 'arch/mips/dec')
-rw-r--r-- | arch/mips/dec/time.c | 47 |
1 files changed, 11 insertions, 36 deletions
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c index f17d3378e9a6..74cb055d4bf6 100644 --- a/arch/mips/dec/time.c +++ b/arch/mips/dec/time.c | |||
@@ -36,41 +36,13 @@ | |||
36 | #include <asm/dec/ioasic_addrs.h> | 36 | #include <asm/dec/ioasic_addrs.h> |
37 | #include <asm/dec/machtype.h> | 37 | #include <asm/dec/machtype.h> |
38 | 38 | ||
39 | |||
40 | /* | ||
41 | * Returns true if a clock update is in progress | ||
42 | */ | ||
43 | static inline unsigned char dec_rtc_is_updating(void) | ||
44 | { | ||
45 | unsigned char uip; | ||
46 | unsigned long flags; | ||
47 | |||
48 | spin_lock_irqsave(&rtc_lock, flags); | ||
49 | uip = (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); | ||
50 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
51 | return uip; | ||
52 | } | ||
53 | |||
54 | static unsigned long dec_rtc_get_time(void) | 39 | static unsigned long dec_rtc_get_time(void) |
55 | { | 40 | { |
56 | unsigned int year, mon, day, hour, min, sec, real_year; | 41 | unsigned int year, mon, day, hour, min, sec, real_year; |
57 | int i; | ||
58 | unsigned long flags; | 42 | unsigned long flags; |
59 | 43 | ||
60 | /* The Linux interpretation of the DS1287 clock register contents: | ||
61 | * When the Update-In-Progress (UIP) flag goes from 1 to 0, the | ||
62 | * RTC registers show the second which has precisely just started. | ||
63 | * Let's hope other operating systems interpret the RTC the same way. | ||
64 | */ | ||
65 | /* read RTC exactly on falling edge of update flag */ | ||
66 | for (i = 0; i < 1000000; i++) /* may take up to 1 second... */ | ||
67 | if (dec_rtc_is_updating()) | ||
68 | break; | ||
69 | for (i = 0; i < 1000000; i++) /* must try at least 2.228 ms */ | ||
70 | if (!dec_rtc_is_updating()) | ||
71 | break; | ||
72 | spin_lock_irqsave(&rtc_lock, flags); | 44 | spin_lock_irqsave(&rtc_lock, flags); |
73 | /* Isn't this overkill? UIP above should guarantee consistency */ | 45 | |
74 | do { | 46 | do { |
75 | sec = CMOS_READ(RTC_SECONDS); | 47 | sec = CMOS_READ(RTC_SECONDS); |
76 | min = CMOS_READ(RTC_MINUTES); | 48 | min = CMOS_READ(RTC_MINUTES); |
@@ -78,7 +50,16 @@ static unsigned long dec_rtc_get_time(void) | |||
78 | day = CMOS_READ(RTC_DAY_OF_MONTH); | 50 | day = CMOS_READ(RTC_DAY_OF_MONTH); |
79 | mon = CMOS_READ(RTC_MONTH); | 51 | mon = CMOS_READ(RTC_MONTH); |
80 | year = CMOS_READ(RTC_YEAR); | 52 | year = CMOS_READ(RTC_YEAR); |
53 | /* | ||
54 | * The PROM will reset the year to either '72 or '73. | ||
55 | * Therefore we store the real year separately, in one | ||
56 | * of unused BBU RAM locations. | ||
57 | */ | ||
58 | real_year = CMOS_READ(RTC_DEC_YEAR); | ||
81 | } while (sec != CMOS_READ(RTC_SECONDS)); | 59 | } while (sec != CMOS_READ(RTC_SECONDS)); |
60 | |||
61 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
62 | |||
82 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | 63 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { |
83 | sec = BCD2BIN(sec); | 64 | sec = BCD2BIN(sec); |
84 | min = BCD2BIN(min); | 65 | min = BCD2BIN(min); |
@@ -87,13 +68,7 @@ static unsigned long dec_rtc_get_time(void) | |||
87 | mon = BCD2BIN(mon); | 68 | mon = BCD2BIN(mon); |
88 | year = BCD2BIN(year); | 69 | year = BCD2BIN(year); |
89 | } | 70 | } |
90 | /* | 71 | |
91 | * The PROM will reset the year to either '72 or '73. | ||
92 | * Therefore we store the real year separately, in one | ||
93 | * of unused BBU RAM locations. | ||
94 | */ | ||
95 | real_year = CMOS_READ(RTC_DEC_YEAR); | ||
96 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
97 | year += real_year - 72 + 2000; | 72 | year += real_year - 72 + 2000; |
98 | 73 | ||
99 | return mktime(year, mon, day, hour, min, sec); | 74 | return mktime(year, mon, day, hour, min, sec); |