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>
This commit is contained in:
Marek Szyprowski 2018-11-13 12:32:50 +01:00 committed by Alexandre Belloni
parent f1bd154d88
commit 50c8aec421
1 changed files with 0 additions and 6 deletions

View File

@ -327,7 +327,6 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
struct rtc_time *tm = &alrm->time; struct rtc_time *tm = &alrm->time;
unsigned int alrm_en; unsigned int alrm_en;
int ret; int ret;
int year = tm->tm_year - 100;
dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n", dev_dbg(dev, "s3c_rtc_setalarm: %d, %04d.%02d.%02d %02d:%02d:%02d\n",
alrm->enabled, 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); 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) { if (tm->tm_mon < 12 && tm->tm_mon >= 0) {
alrm_en |= S3C2410_RTCALM_MONEN; alrm_en |= S3C2410_RTCALM_MONEN;
writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_ALMMON); writeb(bin2bcd(tm->tm_mon + 1), info->base + S3C2410_ALMMON);