summaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-pcf2127.c
diff options
context:
space:
mode:
authorAndrea Scian <andrea.scian@dave.eu>2015-06-16 05:39:47 -0400
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>2015-09-05 07:19:06 -0400
commit653ebd75e9e469e99a40ab14128d915386dc78c6 (patch)
tree1afde5a872c74e71f4e06fcdcb895757661bba88 /drivers/rtc/rtc-pcf2127.c
parent821f51c4da869706356ddecfeeac286bf4df9b98 (diff)
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: Andrea Scian <andrea.scian@dave.eu> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Diffstat (limited to 'drivers/rtc/rtc-pcf2127.c')
-rw-r--r--drivers/rtc/rtc-pcf2127.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 350c5c7cb678..baf45c9ca65e 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -33,11 +33,14 @@
33#define PCF2127_REG_MO (0x08) 33#define PCF2127_REG_MO (0x08)
34#define PCF2127_REG_YR (0x09) 34#define PCF2127_REG_YR (0x09)
35 35
36#define PCF2127_OSF BIT(7) /* Oscillator Fail flag */
37
36static struct i2c_driver pcf2127_driver; 38static struct i2c_driver pcf2127_driver;
37 39
38struct pcf2127 { 40struct pcf2127 {
39 struct rtc_device *rtc; 41 struct rtc_device *rtc;
40 int voltage_low; /* indicates if a low_voltage was detected */ 42 int voltage_low; /* indicates if a low_voltage was detected */
43 int oscillator_failed; /* OSF was detected and date is unreliable */
41}; 44};
42 45
43/* 46/*
@@ -59,7 +62,18 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
59 if (buf[PCF2127_REG_CTRL3] & 0x04) { 62 if (buf[PCF2127_REG_CTRL3] & 0x04) {
60 pcf2127->voltage_low = 1; 63 pcf2127->voltage_low = 1;
61 dev_info(&client->dev, 64 dev_info(&client->dev,
62 "low voltage detected, date/time is not reliable.\n"); 65 "low voltage detected, check/replace RTC battery.\n");
66 }
67
68 if (buf[PCF2127_REG_SC] & PCF2127_OSF) {
69 /*
70 * no need clear the flag here,
71 * it will be cleared once the new date is saved
72 */
73 pcf2127->oscillator_failed = 1;
74 dev_warn(&client->dev,
75 "oscillator stop detected, date/time is not reliable\n");
76 return -EINVAL;
63 } 77 }
64 78
65 dev_dbg(&client->dev, 79 dev_dbg(&client->dev,
@@ -93,6 +107,7 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
93 107
94static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm) 108static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
95{ 109{
110 struct pcf2127 *pcf2127 = i2c_get_clientdata(client);
96 unsigned char buf[8]; 111 unsigned char buf[8];
97 int i = 0, err; 112 int i = 0, err;
98 113
@@ -106,7 +121,7 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
106 buf[i++] = PCF2127_REG_SC; 121 buf[i++] = PCF2127_REG_SC;
107 122
108 /* hours, minutes and seconds */ 123 /* hours, minutes and seconds */
109 buf[i++] = bin2bcd(tm->tm_sec); 124 buf[i++] = bin2bcd(tm->tm_sec); /* this will also clear OSF flag */
110 buf[i++] = bin2bcd(tm->tm_min); 125 buf[i++] = bin2bcd(tm->tm_min);
111 buf[i++] = bin2bcd(tm->tm_hour); 126 buf[i++] = bin2bcd(tm->tm_hour);
112 buf[i++] = bin2bcd(tm->tm_mday); 127 buf[i++] = bin2bcd(tm->tm_mday);
@@ -126,6 +141,9 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
126 return -EIO; 141 return -EIO;
127 } 142 }
128 143
144 /* clear OSF flag in client data */
145 pcf2127->oscillator_failed = 0;
146
129 return 0; 147 return 0;
130} 148}
131 149
@@ -138,7 +156,9 @@ static int pcf2127_rtc_ioctl(struct device *dev,
138 switch (cmd) { 156 switch (cmd) {
139 case RTC_VL_READ: 157 case RTC_VL_READ:
140 if (pcf2127->voltage_low) 158 if (pcf2127->voltage_low)
141 dev_info(dev, "low voltage detected, date/time is not reliable.\n"); 159 dev_info(dev, "low voltage detected, check/replace battery\n");
160 if (pcf2127->oscillator_failed)
161 dev_info(dev, "oscillator stop detected, date/time is not reliable\n");
142 162
143 if (copy_to_user((void __user *)arg, &pcf2127->voltage_low, 163 if (copy_to_user((void __user *)arg, &pcf2127->voltage_low,
144 sizeof(int))) 164 sizeof(int)))