summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2018-11-13 12:32:50 +0100
committerAlexandre Belloni <alexandre.belloni@bootlin.com>2018-11-14 10:44:36 +0100
commit50c8aec4212a966817e868056efc9bfbb73337c0 (patch)
tree214c670fd15872fb228552d20de246b5ea3223d4
parentf1bd154d8838f9bddbe0f07292dd1c70a47c8b83 (diff)
downloadlinux-50c8aec4212a966817e868056efc9bfbb73337c0.tar.gz
linux-50c8aec4212a966817e868056efc9bfbb73337c0.tar.bz2
linux-50c8aec4212a966817e868056efc9bfbb73337c0.zip
rtc: s3c-rtc: Avoid using broken ALMYEAR register
(RTC,ALM)YEAR registers of Exynos built-in RTC device contains 3 BCD characters. s3c-rtc driver uses only 2 lower of them and supports years from 2000..2099 range. The third BCD value is typically set to 0, but it looks that handling of it is broken in the hardware. It sometimes defaults to a random (even non-BCD) value. This is not an issue for handling RTCYEAR register, because bcd2bin() properly handles only 8bit values (2 BCD characters, the third one is skipped). The problem is however with ALMYEAR register and proper RTC alarm operation. When YEAREN bit is set for the configured alarm, RTC hardware triggers alarm only when ALMYEAR and RTCYEAR matches. This usually doesn't happen because of the random noise on the third BCD character. Fix this by simply skipping setting ALMYEAR register in alarm configuration. This workaround fixes broken alarm operation on Exynos built-in rtc device. My tests revealed that the issue happens on the following Exynos series: 3250, 4210, 4412, 5250 and 5410. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
-rw-r--r--drivers/rtc/rtc-s3c.c6
1 files changed, 0 insertions, 6 deletions
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 75c8c5033e08..58e03ac3578b 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -327,7 +327,6 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
struct rtc_time *tm = &alrm->time;
unsigned int alrm_en;
int ret;
- int year = tm->tm_year - 100;
dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
alrm->enabled,
@@ -356,11 +355,6 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
writeb(bin2bcd(tm->tm_hour), info->base + S3C2410_ALMHOUR);
}
- if (year < 100 && year >= 0) {
- alrm_en |= S3C2410_RTCALM_YEAREN;
- writeb(bin2bcd(year), info->base + S3C2410_ALMYEAR);
- }
-
if (tm->tm_mon < 12 && tm->tm_mon >= 0) {
alrm_en |= S3C2410_RTCALM_MONEN;
writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_ALMMON);