Commit dd9cd732 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] sh: RTC fixes

From: Paul Mundt <lethal@linux-sh.org>

Re-read RTC registers if MSB of R64CNT was changed while reading them on SH-4
which has unreliable CF bit.

Patch from SUGIOKA Toshinobu and Masaki Saitoh.
parent 70fa9749
...@@ -23,10 +23,12 @@ ...@@ -23,10 +23,12 @@
void sh_rtc_gettimeofday(struct timespec *ts) void sh_rtc_gettimeofday(struct timespec *ts)
{ {
unsigned int sec128, sec, min, hr, wk, day, mon, yr, yr100; unsigned int sec128, sec, sec2, min, hr, wk, day, mon, yr, yr100, cf_bit;
unsigned long flags;
again: again:
do { do {
local_irq_save(flags);
ctrl_outb(0, RCR1); /* Clear CF-bit */ ctrl_outb(0, RCR1); /* Clear CF-bit */
sec128 = ctrl_inb(R64CNT); sec128 = ctrl_inb(R64CNT);
sec = ctrl_inb(RSECCNT); sec = ctrl_inb(RSECCNT);
...@@ -43,15 +45,10 @@ void sh_rtc_gettimeofday(struct timespec *ts) ...@@ -43,15 +45,10 @@ void sh_rtc_gettimeofday(struct timespec *ts)
yr = ctrl_inb(RYRCNT); yr = ctrl_inb(RYRCNT);
yr100 = (yr == 0x99) ? 0x19 : 0x20; yr100 = (yr == 0x99) ? 0x19 : 0x20;
#endif #endif
} while ((ctrl_inb(RCR1) & RCR1_CF) != 0); sec2 = ctrl_inb(R64CNT);
cf_bit = ctrl_inb(RCR1) & RCR1_CF;
#if RTC_BIT_INVERTED != 0 local_irq_restore(flags);
/* Work around to avoid reading incorrect value. */ } while (cf_bit != 0 || ((sec128 ^ sec2) & RTC_BIT_INVERTED) != 0);
if (sec128 == RTC_BIT_INVERTED) {
schedule_timeout(1);
goto again;
}
#endif
BCD_TO_BIN(yr100); BCD_TO_BIN(yr100);
BCD_TO_BIN(yr); BCD_TO_BIN(yr);
...@@ -65,6 +62,7 @@ void sh_rtc_gettimeofday(struct timespec *ts) ...@@ -65,6 +62,7 @@ void sh_rtc_gettimeofday(struct timespec *ts)
hr > 23 || min > 59 || sec > 59) { hr > 23 || min > 59 || sec > 59) {
printk(KERN_ERR printk(KERN_ERR
"SH RTC: invalid value, resetting to 1 Jan 2000\n"); "SH RTC: invalid value, resetting to 1 Jan 2000\n");
local_irq_save(flags);
ctrl_outb(RCR2_RESET, RCR2); /* Reset & Stop */ ctrl_outb(RCR2_RESET, RCR2); /* Reset & Stop */
ctrl_outb(0, RSECCNT); ctrl_outb(0, RSECCNT);
ctrl_outb(0, RMINCNT); ctrl_outb(0, RMINCNT);
...@@ -99,7 +97,9 @@ int sh_rtc_settimeofday(const time_t secs) ...@@ -99,7 +97,9 @@ int sh_rtc_settimeofday(const time_t secs)
{ {
int retval = 0; int retval = 0;
int real_seconds, real_minutes, cmos_minutes; int real_seconds, real_minutes, cmos_minutes;
unsigned long flags;
local_irq_save(flags);
ctrl_outb(RCR2_RESET, RCR2); /* Reset pre-scaler & stop RTC */ ctrl_outb(RCR2_RESET, RCR2); /* Reset pre-scaler & stop RTC */
cmos_minutes = ctrl_inb(RMINCNT); cmos_minutes = ctrl_inb(RMINCNT);
...@@ -130,6 +130,7 @@ int sh_rtc_settimeofday(const time_t secs) ...@@ -130,6 +130,7 @@ int sh_rtc_settimeofday(const time_t secs)
} }
ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2); /* Start RTC */ ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2); /* Start RTC */
local_irq_restore(flags);
return retval; return retval;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment