Commit 653ebd75 authored by Andrea Scian's avatar Andrea Scian Committed by Alexandre Belloni

rtc: pcf2127: use OFS flag to detect unreliable date and warn the user

The PCF2127 datasheet states that it's wrong to say that the date in
unreliable if BLF (battery low flag) is set but instead, OSF (seconds
register) should be used to check if oscillator, for any reason, stopped.
Battery may be low (usually below 2V5 threshold) but the date may be anyway
correct (typically date is unreliable when input voltage is below 1V2).
Signed-off-by: default avatarAndrea Scian <andrea.scian@dave.eu>
Signed-off-by: default avatarAlexandre Belloni <alexandre.belloni@free-electrons.com>
parent 821f51c4
......@@ -33,11 +33,14 @@
#define PCF2127_REG_MO (0x08)
#define PCF2127_REG_YR (0x09)
#define PCF2127_OSF BIT(7) /* Oscillator Fail flag */
static struct i2c_driver pcf2127_driver;
struct pcf2127 {
struct rtc_device *rtc;
int voltage_low; /* indicates if a low_voltage was detected */
int oscillator_failed; /* OSF was detected and date is unreliable */
};
/*
......@@ -59,7 +62,18 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
if (buf[PCF2127_REG_CTRL3] & 0x04) {
pcf2127->voltage_low = 1;
dev_info(&client->dev,
"low voltage detected, date/time is not reliable.\n");
"low voltage detected, check/replace RTC battery.\n");
}
if (buf[PCF2127_REG_SC] & PCF2127_OSF) {
/*
* no need clear the flag here,
* it will be cleared once the new date is saved
*/
pcf2127->oscillator_failed = 1;
dev_warn(&client->dev,
"oscillator stop detected, date/time is not reliable\n");
return -EINVAL;
}
dev_dbg(&client->dev,
......@@ -93,6 +107,7 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{
struct pcf2127 *pcf2127 = i2c_get_clientdata(client);
unsigned char buf[8];
int i = 0, err;
......@@ -106,7 +121,7 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
buf[i++] = PCF2127_REG_SC;
/* hours, minutes and seconds */
buf[i++] = bin2bcd(tm->tm_sec);
buf[i++] = bin2bcd(tm->tm_sec); /* this will also clear OSF flag */
buf[i++] = bin2bcd(tm->tm_min);
buf[i++] = bin2bcd(tm->tm_hour);
buf[i++] = bin2bcd(tm->tm_mday);
......@@ -126,6 +141,9 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return -EIO;
}
/* clear OSF flag in client data */
pcf2127->oscillator_failed = 0;
return 0;
}
......@@ -138,7 +156,9 @@ static int pcf2127_rtc_ioctl(struct device *dev,
switch (cmd) {
case RTC_VL_READ:
if (pcf2127->voltage_low)
dev_info(dev, "low voltage detected, date/time is not reliable.\n");
dev_info(dev, "low voltage detected, check/replace battery\n");
if (pcf2127->oscillator_failed)
dev_info(dev, "oscillator stop detected, date/time is not reliable\n");
if (copy_to_user((void __user *)arg, &pcf2127->voltage_low,
sizeof(int)))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment