diff mbox

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

Message ID 1449496174-7813-3-git-send-email-jbe@pengutronix.de
State Superseded
Headers show

Commit Message

Juergen Borleis Dec. 7, 2015, 1:49 p.m. UTC
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(-)

Comments

Alexandre Belloni Dec. 20, 2015, 11:35 a.m. UTC | #1
Hi,

On 07/12/2015 at 14:49:33 +0100, Juergen Borleis wrote :
> 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;

Isn't that already reading the time and date register in one block? I'd
say you are simply reading less registers. Also, maybe you could use
i2c_smbus_read_block_data?


> +	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;
>  	}

That part is more useful and as I understand it is what you are trying
to fix.
Juergen Borleis Jan. 7, 2016, 10:12 a.m. UTC | #2
Hi Alexandre,

(please keep me on CC...)

> [...]
> > -	/* read registers */
> > -	if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
> > -		dev_err(&client->dev, "%s: read error\n", __func__);
> > -		return -EIO;
>
> Isn't that already reading the time and date register in one block? I'd
> say you are simply reading less registers. Also, maybe you could use
> i2c_smbus_read_block_data?

Its just a "try" to make the code more readable, by a named subfunction and 
more comments why things must happen that way.
Will check for the suggested smbus function.

Regards,
Juergen
Alexandre Belloni Jan. 21, 2016, 12:04 a.m. UTC | #3
Hi Jurgen,

On 07/01/2016 at 11:12:52 +0100, Juergen Borleis wrote :
> Hi Alexandre,
> 
> (please keep me on CC...)
> 

I've just checked again and now I'm pretty sure you were in To:. Should
I also add you in Cc? Maybe you should check your filters ;)
diff mbox

Patch

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);