Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rtc: pcf8523: don't return invalid date when battery is low

The RTC_VL_READ ioctl reports the low battery condition. Still,
pcf8523_rtc_read_time() happily returns invalid dates in this case.
Check the battery health on pcf8523_rtc_read_time() to avoid that.

Reported-by: Erik Čuk <erik.cuk@domel.com>
Signed-off-by: Baruch Siach <baruch@tkos.co.il>
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>

authored by

Baruch Siach and committed by
Alexandre Belloni
ecb4a353 2cb5e474

+24 -8
+24 -8
drivers/rtc/rtc-pcf8523.c
··· 85 85 return 0; 86 86 } 87 87 88 + static int pcf8523_voltage_low(struct i2c_client *client) 89 + { 90 + u8 value; 91 + int err; 92 + 93 + err = pcf8523_read(client, REG_CONTROL3, &value); 94 + if (err < 0) 95 + return err; 96 + 97 + return !!(value & REG_CONTROL3_BLF); 98 + } 99 + 88 100 static int pcf8523_select_capacitance(struct i2c_client *client, bool high) 89 101 { 90 102 u8 value; ··· 178 166 u8 start = REG_SECONDS, regs[7]; 179 167 struct i2c_msg msgs[2]; 180 168 int err; 169 + 170 + err = pcf8523_voltage_low(client); 171 + if (err < 0) { 172 + return err; 173 + } else if (err > 0) { 174 + dev_err(dev, "low voltage detected, time is unreliable\n"); 175 + return -EINVAL; 176 + } 181 177 182 178 msgs[0].addr = client->addr; 183 179 msgs[0].flags = 0; ··· 271 251 unsigned long arg) 272 252 { 273 253 struct i2c_client *client = to_i2c_client(dev); 274 - u8 value; 275 - int ret = 0, err; 254 + int ret; 276 255 277 256 switch (cmd) { 278 257 case RTC_VL_READ: 279 - err = pcf8523_read(client, REG_CONTROL3, &value); 280 - if (err < 0) 281 - return err; 282 - 283 - if (value & REG_CONTROL3_BLF) 284 - ret = 1; 258 + ret = pcf8523_voltage_low(client); 259 + if (ret < 0) 260 + return ret; 285 261 286 262 if (copy_to_user((void __user *)arg, &ret, sizeof(int))) 287 263 return -EFAULT;