summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorNicolas Boullis <nboullis@debian.org>2016-04-10 13:23:05 +0200
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>2016-05-20 12:33:51 +0200
commit5919fb97dd85e7ee200ab60151244cca62f61368 (patch)
treea6ffeb2cdca89a68d9979864b31e0c49efc380bf /drivers
parent1d87951c398e35118a0fb67b287022f008513f42 (diff)
downloadlinux-5919fb97dd85e7ee200ab60151244cca62f61368.tar.bz2
rtc: ds1307: ensure that any pending alarm is cleared before a new alarm is enabled
If a previously-set alarm was disabled and then triggered, it may still be pending when a new alarm is configured. Then, if the alarm is enabled before the pending alarm is cleared, then an interrupt is immediately raised. Unfortunately, when the alarm is cleared and enabled during the same I²C block write, the chip (at least the DS1339 I have) considers that the alarm is enabled before it is cleared, and raises an interrupt. This patch ensures that the pending alarm is cleared before the alarm is enabled. Signed-off-by: Nicolas Boullis <nboullis@debian.org> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/rtc/rtc-ds1307.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index eed5c06bf624..f027a95a943f 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -542,12 +542,8 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t)
buf[5] = 0;
buf[6] = 0;
- /* optionally enable ALARM1 */
+ /* disable alarms */
buf[7] = control & ~(DS1337_BIT_A1IE | DS1337_BIT_A2IE);
- if (t->enabled) {
- dev_dbg(dev, "alarm IRQ armed\n");
- buf[7] |= DS1337_BIT_A1IE; /* only ALARM1 is used */
- }
buf[8] = status & ~(DS1337_BIT_A1I | DS1337_BIT_A2I);
ret = ds1307->write_block_data(client,
@@ -557,6 +553,13 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t)
return ret;
}
+ /* optionally enable ALARM1 */
+ if (t->enabled) {
+ dev_dbg(dev, "alarm IRQ armed\n");
+ buf[7] |= DS1337_BIT_A1IE; /* only ALARM1 is used */
+ i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, buf[7]);
+ }
+
return 0;
}