summary refs log tree commit diff
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)
downloadlinux-edafb6fe42cfa98f4abf8c63acc5f4db011ed7b9.tar.gz
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];