rtc: ds1307: rx8130: honor Voltage Loss Flag when reading the time
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>
Fri, 25 Jan 2019 14:35:57 +0000 (15:35 +0100)
committerAlexandre Belloni <alexandre.belloni@bootlin.com>
Thu, 7 Feb 2019 19:55:46 +0000 (20:55 +0100)
When voltage dropped since the RTC was last set the reported time is not
reliable. In this case return an error indicator instead of a bogus
time.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
drivers/rtc/rtc-ds1307.c

index 81e2065..974eafd 100644 (file)
@@ -194,6 +194,20 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
        const struct chip_desc *chip = &chips[ds1307->type];
        u8 regs[7];
 
+       if (ds1307->type == rx_8130) {
+               unsigned int regflag;
+               ret = regmap_read(ds1307->regmap, RX8130_REG_FLAG, &regflag);
+               if (ret) {
+                       dev_err(dev, "%s error %d\n", "read", ret);
+                       return ret;
+               }
+
+               if (regflag & RX8130_REG_FLAG_VLF) {
+                       dev_warn_once(dev, "oscillator failed, set time!\n");
+                       return -EINVAL;
+               }
+       }
+
        /* read the RTC date and time registers all at once */
        ret = regmap_bulk_read(ds1307->regmap, chip->offset, regs,
                               sizeof(regs));
@@ -293,6 +307,17 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
                dev_err(dev, "%s error %d\n", "write", result);
                return result;
        }
+
+       if (ds1307->type == rx_8130) {
+               /* clear Voltage Loss Flag as data is available now */
+               result = regmap_write(ds1307->regmap, RX8130_REG_FLAG,
+                                     ~(u8)RX8130_REG_FLAG_VLF);
+               if (result) {
+                       dev_err(dev, "%s error %d\n", "write", result);
+                       return result;
+               }
+       }
+
        return 0;
 }