summaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorAlexandre Belloni <alexandre.belloni@bootlin.com>2019-12-14 23:10:16 +0100
committerAlexandre Belloni <alexandre.belloni@bootlin.com>2019-12-18 10:38:02 +0100
commitf630f728a9b114865bcfe16c1d91dff11e89a4b9 (patch)
treecaaee4c4d386e57f60683a59198745659bd953c0 /drivers/rtc
parent7518dd9a93b9ed1cdcf10caba269d2f3f79ca798 (diff)
downloadlinux-f630f728a9b114865bcfe16c1d91dff11e89a4b9.tar.bz2
rtc: rv3029: add RTC_VL_READ and RTC_VL_CLEAR support
The RV3029 can report three different conditions: power on, voltage dropped and data is lost and voltage is low and temperature compensation has stopped. The first two conditions amount to the same status, the RTC data is invalid. VLOW1 has to be cleared manually to resume temperature compensation, this is achieved using RTC_VL_CLEAR. Link: https://lore.kernel.org/r/20191214221022.622482-11-alexandre.belloni@bootlin.com Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/rtc-rv3029c2.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c
index 2985c0f44d53..f4c6d6e3b165 100644
--- a/drivers/rtc/rtc-rv3029c2.c
+++ b/drivers/rtc/rtc-rv3029c2.c
@@ -459,6 +459,35 @@ static int rv3029_set_time(struct device *dev, struct rtc_time *tm)
RV3029_STATUS_PON, 0);
}
+static int rv3029_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+ struct rv3029_data *rv3029 = dev_get_drvdata(dev);
+ unsigned long vl = 0;
+ int sr, ret = 0;
+
+ switch (cmd) {
+ case RTC_VL_READ:
+ ret = regmap_read(rv3029->regmap, RV3029_STATUS, &sr);
+ if (ret < 0)
+ return ret;
+
+ if (sr & RV3029_STATUS_VLOW1)
+ vl = RTC_VL_ACCURACY_LOW;
+
+ if (sr & (RV3029_STATUS_VLOW2 | RV3029_STATUS_PON))
+ vl |= RTC_VL_DATA_INVALID;
+
+ return put_user(vl, (unsigned int __user *)arg);
+
+ case RTC_VL_CLR:
+ return regmap_update_bits(rv3029->regmap, RV3029_STATUS,
+ RV3029_STATUS_VLOW1, 0);
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
static const struct rv3029_trickle_tab_elem {
u32 r; /* resistance in ohms */
u8 conf; /* trickle config bits */
@@ -672,6 +701,7 @@ static void rv3029_hwmon_register(struct device *dev, const char *name)
static struct rtc_class_ops rv3029_rtc_ops = {
.read_time = rv3029_read_time,
.set_time = rv3029_set_time,
+ .ioctl = rv3029_ioctl,
};
static int rv3029_probe(struct device *dev, struct regmap *regmap, int irq,