]>
Commit | Line | Data |
---|---|---|
6c9c5814 GKH |
1 | From ecb4a353d3afd45b9bb30c85d03ee113a0589079 Mon Sep 17 00:00:00 2001 |
2 | From: Baruch Siach <baruch@tkos.co.il> | |
3 | Date: Wed, 5 Dec 2018 17:00:09 +0200 | |
4 | Subject: rtc: pcf8523: don't return invalid date when battery is low | |
5 | MIME-Version: 1.0 | |
6 | Content-Type: text/plain; charset=UTF-8 | |
7 | Content-Transfer-Encoding: 8bit | |
8 | ||
9 | From: Baruch Siach <baruch@tkos.co.il> | |
10 | ||
11 | commit ecb4a353d3afd45b9bb30c85d03ee113a0589079 upstream. | |
12 | ||
13 | The RTC_VL_READ ioctl reports the low battery condition. Still, | |
14 | pcf8523_rtc_read_time() happily returns invalid dates in this case. | |
15 | Check the battery health on pcf8523_rtc_read_time() to avoid that. | |
16 | ||
17 | Reported-by: Erik Čuk <erik.cuk@domel.com> | |
18 | Signed-off-by: Baruch Siach <baruch@tkos.co.il> | |
19 | Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> | |
20 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
21 | ||
22 | --- | |
23 | drivers/rtc/rtc-pcf8523.c | 32 ++++++++++++++++++++++++-------- | |
24 | 1 file changed, 24 insertions(+), 8 deletions(-) | |
25 | ||
26 | --- a/drivers/rtc/rtc-pcf8523.c | |
27 | +++ b/drivers/rtc/rtc-pcf8523.c | |
28 | @@ -82,6 +82,18 @@ static int pcf8523_write(struct i2c_clie | |
29 | return 0; | |
30 | } | |
31 | ||
32 | +static int pcf8523_voltage_low(struct i2c_client *client) | |
33 | +{ | |
34 | + u8 value; | |
35 | + int err; | |
36 | + | |
37 | + err = pcf8523_read(client, REG_CONTROL3, &value); | |
38 | + if (err < 0) | |
39 | + return err; | |
40 | + | |
41 | + return !!(value & REG_CONTROL3_BLF); | |
42 | +} | |
43 | + | |
44 | static int pcf8523_select_capacitance(struct i2c_client *client, bool high) | |
45 | { | |
46 | u8 value; | |
47 | @@ -164,6 +176,14 @@ static int pcf8523_rtc_read_time(struct | |
48 | struct i2c_msg msgs[2]; | |
49 | int err; | |
50 | ||
51 | + err = pcf8523_voltage_low(client); | |
52 | + if (err < 0) { | |
53 | + return err; | |
54 | + } else if (err > 0) { | |
55 | + dev_err(dev, "low voltage detected, time is unreliable\n"); | |
56 | + return -EINVAL; | |
57 | + } | |
58 | + | |
59 | msgs[0].addr = client->addr; | |
60 | msgs[0].flags = 0; | |
61 | msgs[0].len = 1; | |
62 | @@ -248,17 +268,13 @@ static int pcf8523_rtc_ioctl(struct devi | |
63 | unsigned long arg) | |
64 | { | |
65 | struct i2c_client *client = to_i2c_client(dev); | |
66 | - u8 value; | |
67 | - int ret = 0, err; | |
68 | + int ret; | |
69 | ||
70 | switch (cmd) { | |
71 | case RTC_VL_READ: | |
72 | - err = pcf8523_read(client, REG_CONTROL3, &value); | |
73 | - if (err < 0) | |
74 | - return err; | |
75 | - | |
76 | - if (value & REG_CONTROL3_BLF) | |
77 | - ret = 1; | |
78 | + ret = pcf8523_voltage_low(client); | |
79 | + if (ret < 0) | |
80 | + return ret; | |
81 | ||
82 | if (copy_to_user((void __user *)arg, &ret, sizeof(int))) | |
83 | return -EFAULT; |