Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1285319 > unrolled thread

[PATCH] RTC/PCF85063: fix reading/setting time/date

Started byJuergen Borleis <jbe@pengutronix.de>
First post2015-12-07 15:00 +0100
Last post2015-12-07 15:00 +0100
Articles 2 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [PATCH] RTC/PCF85063: fix reading/setting time/date Juergen Borleis <jbe@pengutronix.de> - 2015-12-07 15:00 +0100
    [PATCH 2/3] RTC/PCF85063: fix time/date reading (part II) Juergen Borleis <jbe@pengutronix.de> - 2015-12-07 15:00 +0100

#1285319 — [PATCH] RTC/PCF85063: fix reading/setting time/date

FromJuergen Borleis <jbe@pengutronix.de>
Date2015-12-07 15:00 +0100
Subject[PATCH] RTC/PCF85063: fix reading/setting time/date
Message-ID<qD4kW-56d-13@gated-at.bofh.it>
The PCF85063 RTC needs special treatment while setting or reading the
time/date:

 - while reading the 7 time/date registers they are blocked from updating by
   the one second pulse internally. So reading all time/date registers should
   happen in one turn to ensure reading is an atomic operation

 - to let setting the time/date be an atomic operation as well, the clock
   dividers must be kept in reset state to avoid a one second pulse during
   writing the 7 time/date registers

Patch 1 and 2 change reading the time/date. I have kept them separately for
easier review. Squasching both into one patch render it more or less
unreadable.
Patch 3 changes setting the time/date.

Comments are welcome
Juergen

Please keep me on CC as I'm not subscribed to the list.

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1285327 — [PATCH 2/3] RTC/PCF85063: fix time/date reading (part II)

FromJuergen Borleis <jbe@pengutronix.de>
Date2015-12-07 15:00 +0100
Subject[PATCH 2/3] RTC/PCF85063: fix time/date reading (part II)
Message-ID<qD4uD-59N-21@gated-at.bofh.it>
In reply to#1285319
Use the function to read the whole time/date register in one turn and now
check if the RTC signals an invalid time/date (due to a battery power loss
for example). In this case ignore the time/date until it is really set
again.

Signed-off-by: Juergen Borleis <jbe@pengutronix.de>
---
 drivers/rtc/rtc-pcf85063.c | 45 +++++++++++++++++++--------------------------
 1 file changed, 19 insertions(+), 26 deletions(-)

diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index 75f2866..abed934 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -22,6 +22,7 @@
 #define PCF85063_REG_CTRL2		0x01
 
 #define PCF85063_REG_SC			0x04 /* datetime */
+#define PCF85063_REG_SC_OS		0x80
 #define PCF85063_REG_MN			0x05
 #define PCF85063_REG_HR			0x06
 #define PCF85063_REG_DM			0x07
@@ -77,39 +78,31 @@ static int pcf85063_read_time(struct i2c_client *client, u8 *buf, u16 size)
  */
 static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
 {
+	int rc;
 	struct pcf85063 *pcf85063 = i2c_get_clientdata(client);
-	unsigned char buf[13] = { PCF85063_REG_CTRL1 };
-	struct i2c_msg msgs[] = {
-		{/* setup read ptr */
-			.addr = client->addr,
-			.len = 1,
-			.buf = buf
-		},
-		{/* read status + date */
-			.addr = client->addr,
-			.flags = I2C_M_RD,
-			.len = 13,
-			.buf = buf
-		},
-	};
+	u8 regs[7];
 
-	/* read registers */
-	if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
-		dev_err(&client->dev, "%s: read error\n", __func__);
-		return -EIO;
+	rc = pcf85063_read_time(client, regs, sizeof(regs));
+	if (rc < 0)
+		return rc;
+
+	/* if the clock has lost its power it makes no sense to use its time */
+	if (regs[0] & PCF85063_REG_SC_OS) {
+		dev_warn(&client->dev, "Power loss detected, invalid time\n");
+		return -EINVAL;
 	}
 
-	tm->tm_sec = bcd2bin(buf[PCF85063_REG_SC] & 0x7F);
-	tm->tm_min = bcd2bin(buf[PCF85063_REG_MN] & 0x7F);
-	tm->tm_hour = bcd2bin(buf[PCF85063_REG_HR] & 0x3F); /* rtc hr 0-23 */
-	tm->tm_mday = bcd2bin(buf[PCF85063_REG_DM] & 0x3F);
-	tm->tm_wday = buf[PCF85063_REG_DW] & 0x07;
-	tm->tm_mon = bcd2bin(buf[PCF85063_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
-	tm->tm_year = bcd2bin(buf[PCF85063_REG_YR]);
+	tm->tm_sec = bcd2bin(regs[0] & 0x7F);
+	tm->tm_min = bcd2bin(regs[1] & 0x7F);
+	tm->tm_hour = bcd2bin(regs[2] & 0x3F); /* rtc hr 0-23 */
+	tm->tm_mday = bcd2bin(regs[3] & 0x3F);
+	tm->tm_wday = regs[4] & 0x07;
+	tm->tm_mon = bcd2bin(regs[5] & 0x1F) - 1; /* rtc mn 1-12 */
+	tm->tm_year = bcd2bin(regs[6]);
 	if (tm->tm_year < 70)
 		tm->tm_year += 100;	/* assume we are in 1970...2069 */
 	/* detect the polarity heuristically. see note above. */
-	pcf85063->c_polarity = (buf[PCF85063_REG_MO] & PCF85063_MO_C) ?
+	pcf85063->c_polarity = (regs[5] & PCF85063_MO_C) ?
 		(tm->tm_year >= 100) : (tm->tm_year < 100);
 
 	return rtc_valid_tm(tm);
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web