Message ID | 1449496174-7813-3-git-send-email-jbe@pengutronix.de |
---|---|
State | Superseded |
Headers | show |
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.
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
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 --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);
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(-)