Skip to content

Commit b3ed386

Browse files
ukleinekgregkh
authored andcommitted
rtc: s35390a: fix reading out alarm
commit f87e904ddd8f0ef120e46045b0addeb1cc88354e upstream. There are several issues fixed in this patch: - When alarm isn't enabled, set .enabled to zero instead of returning -EINVAL. - Ignore how IRQ1 is configured when determining if IRQ2 is on. - The three alarm registers have an enable flag which must be evaluated. - The chip always triggers when the seconds register gets 0. Note that the rtc framework however doesn't handle the result correctly because it doesn't check wday being initialized and so interprets an alarm being set for 10:00 AM in three days as 10:00 AM tomorrow (or today if that's not over yet). Signed-off-by: Uwe Kleine-König <uwe@kleine-koenig.org> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 6280ac9 commit b3ed386

1 file changed

Lines changed: 31 additions & 9 deletions

File tree

drivers/rtc/rtc-s35390a.c

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,8 @@ static int s35390a_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
242242

243243
if (alm->time.tm_wday != -1)
244244
buf[S35390A_ALRM_BYTE_WDAY] = bin2bcd(alm->time.tm_wday) | 0x80;
245+
else
246+
buf[S35390A_ALRM_BYTE_WDAY] = 0;
245247

246248
buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a,
247249
alm->time.tm_hour) | 0x80;
@@ -269,23 +271,43 @@ static int s35390a_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alm)
269271
if (err < 0)
270272
return err;
271273

272-
if (bitrev8(sts) != S35390A_INT2_MODE_ALARM)
273-
return -EINVAL;
274+
if ((bitrev8(sts) & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) {
275+
/*
276+
* When the alarm isn't enabled, the register to configure
277+
* the alarm time isn't accessible.
278+
*/
279+
alm->enabled = 0;
280+
return 0;
281+
} else {
282+
alm->enabled = 1;
283+
}
274284

275285
err = s35390a_get_reg(s35390a, S35390A_CMD_INT2_REG1, buf, sizeof(buf));
276286
if (err < 0)
277287
return err;
278288

279289
/* This chip returns the bits of each byte in reverse order */
280-
for (i = 0; i < 3; ++i) {
290+
for (i = 0; i < 3; ++i)
281291
buf[i] = bitrev8(buf[i]);
282-
buf[i] &= ~0x80;
283-
}
284292

285-
alm->time.tm_wday = bcd2bin(buf[S35390A_ALRM_BYTE_WDAY]);
286-
alm->time.tm_hour = s35390a_reg2hr(s35390a,
287-
buf[S35390A_ALRM_BYTE_HOURS]);
288-
alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS]);
293+
/*
294+
* B0 of the three matching registers is an enable flag. Iff it is set
295+
* the configured value is used for matching.
296+
*/
297+
if (buf[S35390A_ALRM_BYTE_WDAY] & 0x80)
298+
alm->time.tm_wday =
299+
bcd2bin(buf[S35390A_ALRM_BYTE_WDAY] & ~0x80);
300+
301+
if (buf[S35390A_ALRM_BYTE_HOURS] & 0x80)
302+
alm->time.tm_hour =
303+
s35390a_reg2hr(s35390a,
304+
buf[S35390A_ALRM_BYTE_HOURS] & ~0x80);
305+
306+
if (buf[S35390A_ALRM_BYTE_MINS] & 0x80)
307+
alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS] & ~0x80);
308+
309+
/* alarm triggers always at s=0 */
310+
alm->time.tm_sec = 0;
289311

290312
dev_dbg(&client->dev, "%s: alm is mins=%d, hours=%d, wday=%d\n",
291313
__func__, alm->time.tm_min, alm->time.tm_hour,

0 commit comments

Comments
 (0)