rtc: abx80x: handle the oscillator failure bit
authorMylène Josserand <mylene.josserand@free-electrons.com>
Mon, 21 Mar 2016 17:06:10 +0000 (18:06 +0100)
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>
Fri, 25 Mar 2016 01:41:13 +0000 (02:41 +0100)
Handle the Oscillator Failure ('OF') bit from Oscillator Status register
(0x1D). This bit is cleared on set_time function and is read each time the
date/time is read, but only in case of XT Oscillator selection.
In RC mode, this bit is always set.

Signed-off-by: Mylène Josserand <mylene.josserand@free-electrons.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
drivers/rtc/rtc-abx80x.c

index 0e4c9a0..ba0d619 100644 (file)
@@ -58,6 +58,7 @@
 #define ABX8XX_OSC_OSEL                BIT(7)
 
 #define ABX8XX_REG_OSS         0x1d
+#define ABX8XX_OSS_OF          BIT(1)
 #define ABX8XX_OSS_OMODE       BIT(4)
 
 #define ABX8XX_REG_CFG_KEY     0x1f
@@ -138,7 +139,23 @@ static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
        struct i2c_client *client = to_i2c_client(dev);
        unsigned char buf[8];
-       int err;
+       int err, flags, rc_mode = 0;
+
+       /* Read the Oscillator Failure only in XT mode */
+       rc_mode = abx80x_is_rc_mode(client);
+       if (rc_mode < 0)
+               return rc_mode;
+
+       if (!rc_mode) {
+               flags = i2c_smbus_read_byte_data(client, ABX8XX_REG_OSS);
+               if (flags < 0)
+                       return flags;
+
+               if (flags & ABX8XX_OSS_OF) {
+                       dev_err(dev, "Oscillator failure, data is invalid.\n");
+                       return -EINVAL;
+               }
+       }
 
        err = i2c_smbus_read_i2c_block_data(client, ABX8XX_REG_HTH,
                                            sizeof(buf), buf);
@@ -166,7 +183,7 @@ static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
        struct i2c_client *client = to_i2c_client(dev);
        unsigned char buf[8];
-       int err;
+       int err, flags;
 
        if (tm->tm_year < 100)
                return -EINVAL;
@@ -187,6 +204,18 @@ static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
                return -EIO;
        }
 
+       /* Clear the OF bit of Oscillator Status Register */
+       flags = i2c_smbus_read_byte_data(client, ABX8XX_REG_OSS);
+       if (flags < 0)
+               return flags;
+
+       err = i2c_smbus_write_byte_data(client, ABX8XX_REG_OSS,
+                                       flags & ~ABX8XX_OSS_OF);
+       if (err < 0) {
+               dev_err(&client->dev, "Unable to write oscillator status register\n");
+               return err;
+       }
+
        return 0;
 }