summaryrefslogtreecommitdiff
path: root/drivers/rtc/rtc-ds1307.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-07-17 10:03:50 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2019-07-17 10:03:50 -0700
commitedafb6fe42cfa98f4abf8c63acc5f4db011ed7b9 (patch)
tree2865672fc0ece89d303e70ff5e5f17a99452a4f1 /drivers/rtc/rtc-ds1307.c
parent47ebe00b684c2bc183a766bc33c8b5943bc0df85 (diff)
parentf0162d21cc8025c828fafe56ee25801f770f41da (diff)
Merge tag 'rtc-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
Pull RTC updates from Alexandre Belloni: "A quiet cycle this time. - ds1307: properly handle oscillator failure flags - imx-sc: alarm support - pcf2123: alarm support, correct offset handling - sun6i: add R40 support - simplify getting the adapter of an i2c client" * tag 'rtc-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (37 commits) rtc: wm831x: Add IRQF_ONESHOT flag rtc: stm32: remove one condition check in stm32_rtc_set_alarm() rtc: pcf2123: Fix build error rtc: interface: Change type of 'count' from int to u64 rtc: pcf8563: Clear event flags and disable interrupts before requesting irq rtc: pcf8563: Fix interrupt trigger method rtc: pcf2123: fix negative offset rounding rtc: pcf2123: add alarm support rtc: pcf2123: use %ptR rtc: pcf2123: port to regmap rtc: pcf2123: remove sysfs register view rtc: rx8025: simplify getting the adapter of a client rtc: rx8010: simplify getting the adapter of a client rtc: rv8803: simplify getting the adapter of a client rtc: m41t80: simplify getting the adapter of a client rtc: fm3130: simplify getting the adapter of a client rtc: tegra: Drop MODULE_ALIAS rtc: sun6i: Add R40 compatible dt-bindings: rtc: sun6i: Add the R40 RTC compatible dt-bindings: rtc: Convert Allwinner A31 RTC to a schema ...
Diffstat (limited to 'drivers/rtc/rtc-ds1307.c')
-rw-r--r--drivers/rtc/rtc-ds1307.c129
1 files changed, 58 insertions, 71 deletions
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 93d338e7732b..1f7e8aefc1eb 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -222,6 +222,45 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
return -EINVAL;
}
+ tmp = regs[DS1307_REG_SECS];
+ switch (ds1307->type) {
+ case ds_1307:
+ case m41t0:
+ case m41t00:
+ case m41t11:
+ if (tmp & DS1307_BIT_CH)
+ return -EINVAL;
+ break;
+ case ds_1308:
+ case ds_1338:
+ if (tmp & DS1307_BIT_CH)
+ return -EINVAL;
+
+ ret = regmap_read(ds1307->regmap, DS1307_REG_CONTROL, &tmp);
+ if (ret)
+ return ret;
+ if (tmp & DS1338_BIT_OSF)
+ return -EINVAL;
+ break;
+ case ds_1340:
+ if (tmp & DS1340_BIT_nEOSC)
+ return -EINVAL;
+
+ ret = regmap_read(ds1307->regmap, DS1340_REG_FLAG, &tmp);
+ if (ret)
+ return ret;
+ if (tmp & DS1340_BIT_OSF)
+ return -EINVAL;
+ break;
+ case mcp794xx:
+ if (!(tmp & MCP794XX_BIT_ST))
+ return -EINVAL;
+
+ break;
+ default:
+ break;
+ }
+
t->tm_sec = bcd2bin(regs[DS1307_REG_SECS] & 0x7f);
t->tm_min = bcd2bin(regs[DS1307_REG_MIN] & 0x7f);
tmp = regs[DS1307_REG_HOUR] & 0x3f;
@@ -286,7 +325,17 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
if (t->tm_year > 199 && chip->century_bit)
regs[chip->century_reg] |= chip->century_bit;
- if (ds1307->type == mcp794xx) {
+ switch (ds1307->type) {
+ case ds_1308:
+ case ds_1338:
+ regmap_update_bits(ds1307->regmap, DS1307_REG_CONTROL,
+ DS1338_BIT_OSF, 0);
+ break;
+ case ds_1340:
+ regmap_update_bits(ds1307->regmap, DS1340_REG_FLAG,
+ DS1340_BIT_OSF, 0);
+ break;
+ case mcp794xx:
/*
* these bits were cleared when preparing the date/time
* values and need to be set again before writing the
@@ -294,6 +343,9 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
*/
regs[DS1307_REG_SECS] |= MCP794XX_BIT_ST;
regs[DS1307_REG_WDAY] |= MCP794XX_BIT_VBATEN;
+ break;
+ default:
+ break;
}
dev_dbg(dev, "%s: %7ph\n", "write", regs);
@@ -1702,7 +1754,6 @@ static int ds1307_probe(struct i2c_client *client,
break;
}
-read_rtc:
/* read RTC registers */
err = regmap_bulk_read(ds1307->regmap, chip->offset, regs,
sizeof(regs));
@@ -1711,75 +1762,11 @@ read_rtc:
goto exit;
}
- /*
- * minimal sanity checking; some chips (like DS1340) don't
- * specify the extra bits as must-be-zero, but there are
- * still a few values that are clearly out-of-range.
- */
- tmp = regs[DS1307_REG_SECS];
- switch (ds1307->type) {
- case ds_1307:
- case m41t0:
- case m41t00:
- case m41t11:
- /* clock halted? turn it on, so clock can tick. */
- if (tmp & DS1307_BIT_CH) {
- regmap_write(ds1307->regmap, DS1307_REG_SECS, 0);
- dev_warn(ds1307->dev, "SET TIME!\n");
- goto read_rtc;
- }
- break;
- case ds_1308:
- case ds_1338:
- /* clock halted? turn it on, so clock can tick. */
- if (tmp & DS1307_BIT_CH)
- regmap_write(ds1307->regmap, DS1307_REG_SECS, 0);
-
- /* oscillator fault? clear flag, and warn */
- if (regs[DS1307_REG_CONTROL] & DS1338_BIT_OSF) {
- regmap_write(ds1307->regmap, DS1307_REG_CONTROL,
- regs[DS1307_REG_CONTROL] &
- ~DS1338_BIT_OSF);
- dev_warn(ds1307->dev, "SET TIME!\n");
- goto read_rtc;
- }
- break;
- case ds_1340:
- /* clock halted? turn it on, so clock can tick. */
- if (tmp & DS1340_BIT_nEOSC)
- regmap_write(ds1307->regmap, DS1307_REG_SECS, 0);
-
- err = regmap_read(ds1307->regmap, DS1340_REG_FLAG, &tmp);
- if (err) {
- dev_dbg(ds1307->dev, "read error %d\n", err);
- goto exit;
- }
-
- /* oscillator fault? clear flag, and warn */
- if (tmp & DS1340_BIT_OSF) {
- regmap_write(ds1307->regmap, DS1340_REG_FLAG, 0);
- dev_warn(ds1307->dev, "SET TIME!\n");
- }
- break;
- case mcp794xx:
- /* make sure that the backup battery is enabled */
- if (!(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) {
- regmap_write(ds1307->regmap, DS1307_REG_WDAY,
- regs[DS1307_REG_WDAY] |
- MCP794XX_BIT_VBATEN);
- }
-
- /* clock halted? turn it on, so clock can tick. */
- if (!(tmp & MCP794XX_BIT_ST)) {
- regmap_write(ds1307->regmap, DS1307_REG_SECS,
- MCP794XX_BIT_ST);
- dev_warn(ds1307->dev, "SET TIME!\n");
- goto read_rtc;
- }
-
- break;
- default:
- break;
+ if (ds1307->type == mcp794xx &&
+ !(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) {
+ regmap_write(ds1307->regmap, DS1307_REG_WDAY,
+ regs[DS1307_REG_WDAY] |
+ MCP794XX_BIT_VBATEN);
}
tmp = regs[DS1307_REG_HOUR];