drivers/rtc/ab3100: Update driver to address y2038/y2106 issues

This driver has a number of y2038/y2106 issues.

This patch resolves them by:

  - Replacing rtc_tm_to_time() with rtc_tm_to_time64()
  - Replacing rtc_time_to_tm() with rtc_time64_to_tm()
  - Changing ab3100_rtc_set_mmss() to use rtc_class_ops's set_mmss64()

After this patch, the driver should not have any remaining
y2038/y2106 issues.

Signed-off-by: Xunlei Pang <pang.xunlei@linaro.org>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Acked-by: Alessandro Zummo <a.zummo@towertech.it>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1427945681-29972-10-git-send-email-john.stultz@linaro.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Xunlei Pang 2015-04-01 20:34:29 -07:00 committed by Ingo Molnar
parent 4d644ab84c
commit 5c7e11bc66

View File

@ -43,21 +43,21 @@
/* /*
* RTC clock functions and device struct declaration * RTC clock functions and device struct declaration
*/ */
static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs) static int ab3100_rtc_set_mmss(struct device *dev, time64_t secs)
{ {
u8 regs[] = {AB3100_TI0, AB3100_TI1, AB3100_TI2, u8 regs[] = {AB3100_TI0, AB3100_TI1, AB3100_TI2,
AB3100_TI3, AB3100_TI4, AB3100_TI5}; AB3100_TI3, AB3100_TI4, AB3100_TI5};
unsigned char buf[6]; unsigned char buf[6];
u64 fat_time = (u64) secs * AB3100_RTC_CLOCK_RATE * 2; u64 hw_counter = secs * AB3100_RTC_CLOCK_RATE * 2;
int err = 0; int err = 0;
int i; int i;
buf[0] = (fat_time) & 0xFF; buf[0] = (hw_counter) & 0xFF;
buf[1] = (fat_time >> 8) & 0xFF; buf[1] = (hw_counter >> 8) & 0xFF;
buf[2] = (fat_time >> 16) & 0xFF; buf[2] = (hw_counter >> 16) & 0xFF;
buf[3] = (fat_time >> 24) & 0xFF; buf[3] = (hw_counter >> 24) & 0xFF;
buf[4] = (fat_time >> 32) & 0xFF; buf[4] = (hw_counter >> 32) & 0xFF;
buf[5] = (fat_time >> 40) & 0xFF; buf[5] = (hw_counter >> 40) & 0xFF;
for (i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
err = abx500_set_register_interruptible(dev, 0, err = abx500_set_register_interruptible(dev, 0,
@ -75,7 +75,7 @@ static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs)
static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm) static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm)
{ {
unsigned long time; time64_t time;
u8 rtcval; u8 rtcval;
int err; int err;
@ -88,7 +88,7 @@ static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm)
dev_info(dev, "clock not set (lost power)"); dev_info(dev, "clock not set (lost power)");
return -EINVAL; return -EINVAL;
} else { } else {
u64 fat_time; u64 hw_counter;
u8 buf[6]; u8 buf[6];
/* Read out time registers */ /* Read out time registers */
@ -98,22 +98,21 @@ static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm)
if (err != 0) if (err != 0)
return err; return err;
fat_time = ((u64) buf[5] << 40) | ((u64) buf[4] << 32) | hw_counter = ((u64) buf[5] << 40) | ((u64) buf[4] << 32) |
((u64) buf[3] << 24) | ((u64) buf[2] << 16) | ((u64) buf[3] << 24) | ((u64) buf[2] << 16) |
((u64) buf[1] << 8) | (u64) buf[0]; ((u64) buf[1] << 8) | (u64) buf[0];
time = (unsigned long) (fat_time / time = hw_counter / (u64) (AB3100_RTC_CLOCK_RATE * 2);
(u64) (AB3100_RTC_CLOCK_RATE * 2));
} }
rtc_time_to_tm(time, tm); rtc_time64_to_tm(time, tm);
return rtc_valid_tm(tm); return rtc_valid_tm(tm);
} }
static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{ {
unsigned long time; time64_t time;
u64 fat_time; u64 hw_counter;
u8 buf[6]; u8 buf[6];
u8 rtcval; u8 rtcval;
int err; int err;
@ -134,11 +133,11 @@ static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
AB3100_AL0, buf, 4); AB3100_AL0, buf, 4);
if (err) if (err)
return err; return err;
fat_time = ((u64) buf[3] << 40) | ((u64) buf[2] << 32) | hw_counter = ((u64) buf[3] << 40) | ((u64) buf[2] << 32) |
((u64) buf[1] << 24) | ((u64) buf[0] << 16); ((u64) buf[1] << 24) | ((u64) buf[0] << 16);
time = (unsigned long) (fat_time / (u64) (AB3100_RTC_CLOCK_RATE * 2)); time = hw_counter / (u64) (AB3100_RTC_CLOCK_RATE * 2);
rtc_time_to_tm(time, &alarm->time); rtc_time64_to_tm(time, &alarm->time);
return rtc_valid_tm(&alarm->time); return rtc_valid_tm(&alarm->time);
} }
@ -147,17 +146,17 @@ static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{ {
u8 regs[] = {AB3100_AL0, AB3100_AL1, AB3100_AL2, AB3100_AL3}; u8 regs[] = {AB3100_AL0, AB3100_AL1, AB3100_AL2, AB3100_AL3};
unsigned char buf[4]; unsigned char buf[4];
unsigned long secs; time64_t secs;
u64 fat_time; u64 hw_counter;
int err; int err;
int i; int i;
rtc_tm_to_time(&alarm->time, &secs); secs = rtc_tm_to_time64(&alarm->time);
fat_time = (u64) secs * AB3100_RTC_CLOCK_RATE * 2; hw_counter = secs * AB3100_RTC_CLOCK_RATE * 2;
buf[0] = (fat_time >> 16) & 0xFF; buf[0] = (hw_counter >> 16) & 0xFF;
buf[1] = (fat_time >> 24) & 0xFF; buf[1] = (hw_counter >> 24) & 0xFF;
buf[2] = (fat_time >> 32) & 0xFF; buf[2] = (hw_counter >> 32) & 0xFF;
buf[3] = (fat_time >> 40) & 0xFF; buf[3] = (hw_counter >> 40) & 0xFF;
/* Set the alarm */ /* Set the alarm */
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
@ -193,7 +192,7 @@ static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled)
static const struct rtc_class_ops ab3100_rtc_ops = { static const struct rtc_class_ops ab3100_rtc_ops = {
.read_time = ab3100_rtc_read_time, .read_time = ab3100_rtc_read_time,
.set_mmss = ab3100_rtc_set_mmss, .set_mmss64 = ab3100_rtc_set_mmss,
.read_alarm = ab3100_rtc_read_alarm, .read_alarm = ab3100_rtc_read_alarm,
.set_alarm = ab3100_rtc_set_alarm, .set_alarm = ab3100_rtc_set_alarm,
.alarm_irq_enable = ab3100_rtc_irq_enable, .alarm_irq_enable = ab3100_rtc_irq_enable,