m68k: Fix off-by-one calendar month

This fixes a bug in read_persistent_clock() which causes the system
clock to lag the Real Time Clock by one month. The problem was noticed
on a Mac, but theoretically it must also affect Atari, BVME6000 and Q40.

The tm_mon value in the struct rtc_time passed to mach_hwclk() is
zero-based, and atari_mste_hwclk(), atari_tt_hwclk(), bvme6000_hwclk(),
mac_hwclk() and q40_hwclk() all make this adjustment. Unfortunately,
dn_dummy_hwclk(), mvme147_hwclk(), mvme16x_hwclk(), sun3_hwclk() and
sun3x_hwclk() fail to decrement tm_mon.  Also m68328_hwclk() assumes
a one-based tm_mon.

Bring these platforms into line and fix read_persistent_clock() so it
works correctly on all m68k platforms.

The datasheets for the RTC devices found on the affected platforms
all confirm that the year is stored as a value in the range 0-99 and
the month is stored as a value in the range 1-12. Please refer to the
datasheets for MC146818 (Apollo), DS1643 (MVME), ICM7170 (Sun 3)
and M48T02 (Sun 3x).

Reported-by: Stan Johnson <userm57@yahoo.com>
Signed-off-by: Finn Thain <fthain@telegraphics.com.au>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
This commit is contained in:
Finn Thain
2018-04-23 11:02:57 +10:00
committed by Geert Uytterhoeven
parent 4eee57d68b
commit b65769fc01
7 changed files with 31 additions and 19 deletions

View File

@@ -74,17 +74,17 @@ static irqreturn_t timer_interrupt(int irq, void *dummy)
void read_persistent_clock(struct timespec *ts)
{
struct rtc_time time;
ts->tv_sec = 0;
ts->tv_nsec = 0;
if (mach_hwclk) {
mach_hwclk(0, &time);
if (!mach_hwclk)
return;
if ((time.tm_year += 1900) < 1970)
time.tm_year += 100;
ts->tv_sec = mktime(time.tm_year, time.tm_mon, time.tm_mday,
time.tm_hour, time.tm_min, time.tm_sec);
}
mach_hwclk(0, &time);
ts->tv_sec = mktime(time.tm_year + 1900, time.tm_mon + 1, time.tm_mday,
time.tm_hour, time.tm_min, time.tm_sec);
}
#if defined(CONFIG_ARCH_USES_GETTIMEOFFSET) && IS_ENABLED(CONFIG_RTC_DRV_GENERIC)