summaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorMylène Josserand <mylene.josserand@free-electrons.com>2016-03-21 18:06:10 +0100
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>2016-03-25 02:41:13 +0100
commitee087744247c421c83abea7f01217bfd39b8f5a9 (patch)
tree19addc9c871e45976fec758034e4a5b407fb8daa /drivers/rtc
parent59a8383adb75459c9d6766656bccc05950b783ea (diff)
downloadlinux-ee087744247c421c83abea7f01217bfd39b8f5a9.tar.gz
linux-ee087744247c421c83abea7f01217bfd39b8f5a9.tar.bz2
linux-ee087744247c421c83abea7f01217bfd39b8f5a9.zip
rtc: abx80x: handle the oscillator failure bit
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>
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/rtc-abx80x.c33
1 files changed, 31 insertions, 2 deletions
diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
index 0e4c9a0989d1..ba0d61934d35 100644
--- a/drivers/rtc/rtc-abx80x.c
+++ b/drivers/rtc/rtc-abx80x.c
@@ -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;
}