summaryrefslogtreecommitdiff
path: root/arch/sh/kernel/rtc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 18:11:38 -0800
committerLinus Torvalds <torvalds@athlon.transmeta.com>2002-02-04 18:11:38 -0800
commit1a0153507ffae9cf3350e76c12d441788c0191e1 (patch)
treed05a502b4fc05202c84c1667019460c08ea088cd /arch/sh/kernel/rtc.c
parentb0683ac8928c4cf40646a6ce3eb6ffe94605acfa (diff)
v2.4.3.2 -> v2.4.3.3
- Hui-Fen Hsu: sis900 driver update - NIIBE Yutaka: Super-H update - Alan Cox: more resyncs (ARM down, but more to go) - David Miller: network zerocopy, Sparc sync, qlogic,FC fix, etc. - David Miller/me: get rid of various drivers hacks to do mmap alignment behind the back of the VM layer. Create a real protocol for it.
Diffstat (limited to 'arch/sh/kernel/rtc.c')
-rw-r--r--arch/sh/kernel/rtc.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/arch/sh/kernel/rtc.c b/arch/sh/kernel/rtc.c
index b978e3208d9d..94dd764bf85d 100644
--- a/arch/sh/kernel/rtc.c
+++ b/arch/sh/kernel/rtc.c
@@ -7,6 +7,7 @@
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/sched.h>
#include <linux/time.h>
#include <asm/io.h>
@@ -44,6 +45,8 @@
#define RMONAR 0xfffffeda
#define RCR1 0xfffffedc
#define RCR2 0xfffffede
+
+#define RTC_BIT_INVERTED 0 /* No bug on SH7708, SH7709A */
#elif defined(__SH4__)
/* SH-4 RTC */
#define R64CNT 0xffc80000
@@ -62,6 +65,8 @@
#define RMONAR 0xffc80034
#define RCR1 0xffc80038
#define RCR2 0xffc8003c
+
+#define RTC_BIT_INVERTED 0x40 /* bug on SH7750, SH7750S */
#endif
#ifndef BCD_TO_BIN
@@ -79,7 +84,7 @@ void sh_rtc_gettimeofday(struct timeval *tv)
again:
do {
ctrl_outb(0, RCR1); /* Clear CF-bit */
- sec128 = ctrl_inb(RSECCNT);
+ sec128 = ctrl_inb(R64CNT);
sec = ctrl_inb(RSECCNT);
min = ctrl_inb(RMINCNT);
hr = ctrl_inb(RHRCNT);
@@ -96,6 +101,14 @@ void sh_rtc_gettimeofday(struct timeval *tv)
#endif
} while ((ctrl_inb(RCR1) & RCR1_CF) != 0);
+#if RTC_BIT_INVERTED != 0
+ /* Work around to avoid reading correct value. */
+ if (sec128 == RTC_BIT_INVERTED) {
+ schedule_timeout(1);
+ goto again;
+ }
+#endif
+
BCD_TO_BIN(yr100);
BCD_TO_BIN(yr);
BCD_TO_BIN(mon);
@@ -125,7 +138,7 @@ void sh_rtc_gettimeofday(struct timeval *tv)
}
tv->tv_sec = mktime(yr100 * 100 + yr, mon, day, hr, min, sec);
- tv->tv_usec = (sec128 * 1000000) / 128;
+ tv->tv_usec = ((sec128 ^ RTC_BIT_INVERTED) * 1000000) / 128;
}
static int set_rtc_time(unsigned long nowtime)
@@ -170,5 +183,9 @@ static int set_rtc_time(unsigned long nowtime)
int sh_rtc_settimeofday(const struct timeval *tv)
{
+#if RTC_BIT_INVERTED != 0
+ /* This is not accurate, but better than nothing. */
+ schedule_timeout(HZ/2);
+#endif
return set_rtc_time(tv->tv_sec);
}