Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rtc: max8907: weekday encoding fixes

The current MAX8907 driver has two issues related to weekday value
handling:

1)

The HW WEEKDAY register has range 0..6 rather than 1..7 as documented.
Note that I validated the actual HW range by observing the HW register
roll from 6->0 rather than 6->7->1 as would otherwise be expected.

This matches Linux's tm_wday range of 0..6.

When the CMOS RAM content is lost, the date returned from the device is
2007-01-01 00:00:00, which is a Monday. The WEEKDAY register reads 1 in
this case. This matches the numbering in Linux's tm_wday field.

Hence we should write Linux's tm_wday value to the register without
modifying it. Hence, remove the +1/-1 calculations for WEEKDAY/tm_wday.

2)

There's no need to make alarms match on the WEEKDAY register, since the
other fields together uniquely define the alarm date/time. Ignoring the
WEEKDAY value in the match isolates the driver from any incorrect value in
the current time copy of the WEEKDAY register.

Each change individually, or both together, solves an issue that I
observed; "hwclock -r" would time out waiting for its alarm to fire if the
CMOS RAM content had been lost, and hence the WEEKDAY register value
mismatched what the driver expected it to be. "hwclock -w" would solve
this by over-writing the HW default WEEKDAY register value with what the
driver expected.

Signed-off-by: Stephen Warren <swarren@nvidia.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Stephen Warren and committed by
Linus Torvalds
75ea799d 28ed893c

+5 -6
+5 -6
drivers/rtc/rtc-max8907.c
··· 51 51 { 52 52 struct max8907_rtc *rtc = data; 53 53 54 - regmap_update_bits(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 0x7f, 0); 54 + regmap_write(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 0); 55 55 56 56 rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF); 57 57 ··· 64 64 bcd2bin(regs[RTC_YEAR1]) - 1900; 65 65 tm->tm_mon = bcd2bin(regs[RTC_MONTH] & 0x1f) - 1; 66 66 tm->tm_mday = bcd2bin(regs[RTC_DATE] & 0x3f); 67 - tm->tm_wday = (regs[RTC_WEEKDAY] & 0x07) - 1; 67 + tm->tm_wday = (regs[RTC_WEEKDAY] & 0x07); 68 68 if (regs[RTC_HOUR] & HOUR_12) { 69 69 tm->tm_hour = bcd2bin(regs[RTC_HOUR] & 0x01f); 70 70 if (tm->tm_hour == 12) ··· 88 88 regs[RTC_YEAR1] = bin2bcd(low); 89 89 regs[RTC_MONTH] = bin2bcd(tm->tm_mon + 1); 90 90 regs[RTC_DATE] = bin2bcd(tm->tm_mday); 91 - regs[RTC_WEEKDAY] = tm->tm_wday + 1; 91 + regs[RTC_WEEKDAY] = tm->tm_wday; 92 92 regs[RTC_HOUR] = bin2bcd(tm->tm_hour); 93 93 regs[RTC_MIN] = bin2bcd(tm->tm_min); 94 94 regs[RTC_SEC] = bin2bcd(tm->tm_sec); ··· 153 153 tm_to_regs(&alrm->time, regs); 154 154 155 155 /* Disable alarm while we update the target time */ 156 - ret = regmap_update_bits(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 0x7f, 0); 156 + ret = regmap_write(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 0); 157 157 if (ret < 0) 158 158 return ret; 159 159 ··· 163 163 return ret; 164 164 165 165 if (alrm->enabled) 166 - ret = regmap_update_bits(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 167 - 0x7f, 0x7f); 166 + ret = regmap_write(rtc->regmap, MAX8907_REG_ALARM0_CNTL, 0x77); 168 167 169 168 return ret; 170 169 }