From 399221ccf45106455c163bb34b4e66256c0ae233 Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Tue, 15 Mar 2016 00:29:33 +0100 Subject: rtc: rv3029: stop mentioning rv3029c2 rv3029c2 is actually rv3029. c2 denotes an option. Signed-off-by: Alexandre Belloni --- drivers/rtc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 544bd3493852..3e84315c6f12 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -589,7 +589,7 @@ config RTC_DRV_RV3029_HWMON default y help Say Y here if you want to expose temperature sensor data on - rtc-rv3029c2. + rtc-rv3029. config RTC_DRV_RV8803 tristate "Micro Crystal RV8803" -- cgit v1.2.3-58-ga151 From ae6e00b4c01f701a9a268adf35371c018396cd05 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 14 Mar 2016 22:38:38 -0300 Subject: rtc: s3c: Don't print an error on probe deferral The clock and source clock looked up by the driver may not be available just because the clock controller driver was not probed yet so printing an error in this case is not correct and only adds confusion to users. However, knowing that a driver's probe was deferred may be useful so it can be printed as a debug information. Signed-off-by: Javier Martinez Canillas Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-s3c.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index ffb860d18701..d01ad7e8078e 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -501,18 +501,27 @@ static int s3c_rtc_probe(struct platform_device *pdev) info->rtc_clk = devm_clk_get(&pdev->dev, "rtc"); if (IS_ERR(info->rtc_clk)) { - dev_err(&pdev->dev, "failed to find rtc clock\n"); - return PTR_ERR(info->rtc_clk); + ret = PTR_ERR(info->rtc_clk); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "failed to find rtc clock\n"); + else + dev_dbg(&pdev->dev, "probe deferred due to missing rtc clk\n"); + return ret; } clk_prepare_enable(info->rtc_clk); if (info->data->needs_src_clk) { info->rtc_src_clk = devm_clk_get(&pdev->dev, "rtc_src"); if (IS_ERR(info->rtc_src_clk)) { - dev_err(&pdev->dev, - "failed to find rtc source clock\n"); + ret = PTR_ERR(info->rtc_src_clk); + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, + "failed to find rtc source clock\n"); + else + dev_dbg(&pdev->dev, + "probe deferred due to missing rtc src clk\n"); clk_disable_unprepare(info->rtc_clk); - return PTR_ERR(info->rtc_src_clk); + return ret; } clk_prepare_enable(info->rtc_src_clk); } -- cgit v1.2.3-58-ga151 From bcebd81d00a062af5a4cf900b08c8ca22a26d52f Mon Sep 17 00:00:00 2001 From: Stefan Christ Date: Tue, 15 Mar 2016 14:22:26 +0100 Subject: rtc: m41t80: avoid out of range year values Avoid saving an out of range year value to the RTC. Reading that value from the RTC again returns a totally wrong time value. For Example $ timedatectl set-ntp no $ timedatectl set-time "1990-01-01 12:12:00" # Reboot rtc-m41t80 0-0068: setting system clock to 2090-01-01 12:12:35 UTC (3786955955) Signed-off-by: Stefan Christ Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-m41t80.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index a82937e2f824..d107a8e72a7d 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -176,7 +176,13 @@ static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm) bin2bcd(tm->tm_mday) | (buf[M41T80_REG_DAY] & ~0x3f); buf[M41T80_REG_MON] = bin2bcd(tm->tm_mon + 1) | (buf[M41T80_REG_MON] & ~0x1f); + /* assume 20YY not 19YY */ + if (tm->tm_year < 100 || tm->tm_year > 199) { + dev_err(&client->dev, "Year must be between 2000 and 2099. It's %d.\n", + tm->tm_year + 1900); + return -EINVAL; + } buf[M41T80_REG_YEAR] = bin2bcd(tm->tm_year % 100); if (i2c_transfer(client->adapter, msgs, 1) != 1) { -- cgit v1.2.3-58-ga151 From 15c6ea6f81328b0071cf63fb00b324199a9b8647 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 15 Mar 2016 22:44:31 +0100 Subject: rtc: asm9260: remove incorrect __init/__exit annotations The probe and remove callbacks of the platform driver are marked __init and __exit, respectively. However, this is not a correct way to annotate them, as it will result in those sections to be discarded at link time or after boot, while we can actually call them again based on manual unbinding, or deferred probing. Kbuild warns about the problem: WARNING: drivers/rtc/rtc-asm9260.o(.data+0x0): Section mismatch in reference from the variable asm9260_rtc_driver to the function .init.text:asm9260_rtc_probe() This removes the annotations, so we no longer branch into missing code and avoid the warning. Signed-off-by: Arnd Bergmann Fixes: 125e550fd257 ("rtc: add Alphascale asm9260 driver") Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-asm9260.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-asm9260.c b/drivers/rtc/rtc-asm9260.c index 14e08c4c1a01..355fdb97a006 100644 --- a/drivers/rtc/rtc-asm9260.c +++ b/drivers/rtc/rtc-asm9260.c @@ -255,7 +255,7 @@ static const struct rtc_class_ops asm9260_rtc_ops = { .alarm_irq_enable = asm9260_alarm_irq_enable, }; -static int __init asm9260_rtc_probe(struct platform_device *pdev) +static int asm9260_rtc_probe(struct platform_device *pdev) { struct asm9260_rtc_priv *priv; struct device *dev = &pdev->dev; @@ -323,7 +323,7 @@ err_return: return ret; } -static int __exit asm9260_rtc_remove(struct platform_device *pdev) +static int asm9260_rtc_remove(struct platform_device *pdev) { struct asm9260_rtc_priv *priv = platform_get_drvdata(pdev); -- cgit v1.2.3-58-ga151 From 7f8a58925b4c0198c12344025b6ffd5dd7d9f1f5 Mon Sep 17 00:00:00 2001 From: Emil Bartczak Date: Mon, 21 Mar 2016 01:06:10 +0100 Subject: rtc: mcp795: add devicetree support Add device tree support to the rtc-mcp795 driver. Signed-off-by: Emil Bartczak Acked-by: Rob Herring Signed-off-by: Alexandre Belloni --- Documentation/devicetree/bindings/rtc/maxim,mcp795.txt | 11 +++++++++++ drivers/rtc/rtc-mcp795.c | 10 ++++++++++ 2 files changed, 21 insertions(+) create mode 100644 Documentation/devicetree/bindings/rtc/maxim,mcp795.txt diff --git a/Documentation/devicetree/bindings/rtc/maxim,mcp795.txt b/Documentation/devicetree/bindings/rtc/maxim,mcp795.txt new file mode 100644 index 000000000000..a59fdd8c236d --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/maxim,mcp795.txt @@ -0,0 +1,11 @@ +* Maxim MCP795 SPI Serial Real-Time Clock + +Required properties: +- compatible: Should contain "maxim,mcp795". +- reg: SPI address for chip + +Example: + mcp795: rtc@0 { + compatible = "maxim,mcp795"; + reg = <0>; + }; diff --git a/drivers/rtc/rtc-mcp795.c b/drivers/rtc/rtc-mcp795.c index 1c91ce8a6d75..025bb33b9cd2 100644 --- a/drivers/rtc/rtc-mcp795.c +++ b/drivers/rtc/rtc-mcp795.c @@ -20,6 +20,7 @@ #include #include #include +#include /* MCP795 Instructions, see datasheet table 3-1 */ #define MCP795_EEREAD 0x03 @@ -183,9 +184,18 @@ static int mcp795_probe(struct spi_device *spi) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id mcp795_of_match[] = { + { .compatible = "maxim,mcp795" }, + { } +}; +MODULE_DEVICE_TABLE(of, mcp795_of_match); +#endif + static struct spi_driver mcp795_driver = { .driver = { .name = "rtc-mcp795", + .of_match_table = of_match_ptr(mcp795_of_match), }, .probe = mcp795_probe, }; -- cgit v1.2.3-58-ga151 From 85062c9b990b1dc8bbb8971ee7d3044a999cf25f Mon Sep 17 00:00:00 2001 From: Alexandre Belloni Date: Mon, 21 Mar 2016 15:58:38 +0100 Subject: rtc: rv8803: workaround i2c HW issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rv8803 has a 60µs window where it will not answer on the i2c bus. It also means there will be no ack for the communication. Make sure communication is tried multiple times when this happens (the i2c subsystem mandates -ENXIO is that case but the number of retries is host specific). The critical parts are the probe function and the alarm callback so make sure we handle the failure there. Cc: stable@vger.kernel.org # v4.4 Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-rv8803.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c index 8d9f35ceb808..f623038e586e 100644 --- a/drivers/rtc/rtc-rv8803.c +++ b/drivers/rtc/rtc-rv8803.c @@ -61,11 +61,14 @@ static irqreturn_t rv8803_handle_irq(int irq, void *dev_id) struct i2c_client *client = dev_id; struct rv8803_data *rv8803 = i2c_get_clientdata(client); unsigned long events = 0; - int flags; + int flags, try = 0; mutex_lock(&rv8803->flags_lock); - flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); + do { + flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); + try++; + } while ((flags == -ENXIO) && (try < 3)); if (flags <= 0) { mutex_unlock(&rv8803->flags_lock); return IRQ_NONE; @@ -424,7 +427,7 @@ static int rv8803_probe(struct i2c_client *client, { struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct rv8803_data *rv8803; - int err, flags; + int err, flags, try = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK)) { @@ -441,7 +444,16 @@ static int rv8803_probe(struct i2c_client *client, rv8803->client = client; i2c_set_clientdata(client, rv8803); - flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); + /* + * There is a 60µs window where the RTC may not reply on the i2c bus in + * that case, the transfer is not ACKed. In that case, ensure there are + * multiple attempts. + */ + do { + flags = i2c_smbus_read_byte_data(client, RV8803_FLAG); + try++; + } while ((flags == -ENXIO) && (try < 3)); + if (flags < 0) return flags; @@ -476,8 +488,12 @@ static int rv8803_probe(struct i2c_client *client, return PTR_ERR(rv8803->rtc); } - err = i2c_smbus_write_byte_data(rv8803->client, RV8803_EXT, - RV8803_EXT_WADA); + try = 0; + do { + err = i2c_smbus_write_byte_data(rv8803->client, RV8803_EXT, + RV8803_EXT_WADA); + try++; + } while ((err == -ENXIO) && (try < 3)); if (err) return err; -- cgit v1.2.3-58-ga151 From 59a8383adb75459c9d6766656bccc05950b783ea Mon Sep 17 00:00:00 2001 From: Mylène Josserand Date: Mon, 21 Mar 2016 18:06:09 +0100 Subject: rtc: abx80x: handle autocalibration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The autocalibration is separated in two bits to set in Oscillator Control register (0x1c) : - OSEL bit to select the oscillator type (XT or RC). - ACAL bit to select the autocalibration type. These functionnalities are exported in sysfs entries : "oscillator" and "autocalibration". Respectively, the values are "xtal" for XT oscillator and "rc" for RC oscillator and 0 to disable the autocalibration cycle, 512 for a 512 seconds autocalibration cycle and 1024 for a cycle of 1024 seconds. Examples : Set to XT Oscillator echo xtal > /sys/class/rtc/rtc0/device/oscillator Activate an autocalibration every 512 seconds echo 512 > /sys/class/rtc/rtc0/device/autocalibration Signed-off-by: Mylène Josserand Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-abx80x.c | 219 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c index d41bbcd653f6..0e4c9a0989d1 100644 --- a/drivers/rtc/rtc-abx80x.c +++ b/drivers/rtc/rtc-abx80x.c @@ -49,7 +49,19 @@ #define ABX8XX_REG_CD_TIMER_CTL 0x18 +#define ABX8XX_REG_OSC 0x1c +#define ABX8XX_OSC_FOS BIT(3) +#define ABX8XX_OSC_BOS BIT(4) +#define ABX8XX_OSC_ACAL_512 BIT(5) +#define ABX8XX_OSC_ACAL_1024 BIT(6) + +#define ABX8XX_OSC_OSEL BIT(7) + +#define ABX8XX_REG_OSS 0x1d +#define ABX8XX_OSS_OMODE BIT(4) + #define ABX8XX_REG_CFG_KEY 0x1f +#define ABX8XX_CFG_KEY_OSC 0xa1 #define ABX8XX_CFG_KEY_MISC 0x9d #define ABX8XX_REG_ID0 0x28 @@ -81,6 +93,20 @@ static struct abx80x_cap abx80x_caps[] = { [ABX80X] = {.pn = 0} }; +static int abx80x_is_rc_mode(struct i2c_client *client) +{ + int flags = 0; + + flags = i2c_smbus_read_byte_data(client, ABX8XX_REG_OSS); + if (flags < 0) { + dev_err(&client->dev, + "Failed to read autocalibration attribute\n"); + return flags; + } + + return (flags & ABX8XX_OSS_OMODE) ? 1 : 0; +} + static int abx80x_enable_trickle_charger(struct i2c_client *client, u8 trickle_cfg) { @@ -248,6 +274,174 @@ static int abx80x_set_alarm(struct device *dev, struct rtc_wkalrm *t) return 0; } +static int abx80x_rtc_set_autocalibration(struct device *dev, + int autocalibration) +{ + struct i2c_client *client = to_i2c_client(dev); + int retval, flags = 0; + + if ((autocalibration != 0) && (autocalibration != 1024) && + (autocalibration != 512)) { + dev_err(dev, "autocalibration value outside permitted range\n"); + return -EINVAL; + } + + flags = i2c_smbus_read_byte_data(client, ABX8XX_REG_OSC); + if (flags < 0) + return flags; + + if (autocalibration == 0) { + flags &= ~(ABX8XX_OSC_ACAL_512 | ABX8XX_OSC_ACAL_1024); + } else if (autocalibration == 1024) { + /* 1024 autocalibration is 0x10 */ + flags |= ABX8XX_OSC_ACAL_1024; + flags &= ~(ABX8XX_OSC_ACAL_512); + } else { + /* 512 autocalibration is 0x11 */ + flags |= (ABX8XX_OSC_ACAL_1024 | ABX8XX_OSC_ACAL_512); + } + + /* Unlock write access to Oscillator Control Register */ + retval = i2c_smbus_write_byte_data(client, ABX8XX_REG_CFG_KEY, + ABX8XX_CFG_KEY_OSC); + if (retval < 0) { + dev_err(dev, "Failed to write CONFIG_KEY register\n"); + return retval; + } + + retval = i2c_smbus_write_byte_data(client, ABX8XX_REG_OSC, flags); + + return retval; +} + +static int abx80x_rtc_get_autocalibration(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + int flags = 0, autocalibration; + + flags = i2c_smbus_read_byte_data(client, ABX8XX_REG_OSC); + if (flags < 0) + return flags; + + if (flags & ABX8XX_OSC_ACAL_512) + autocalibration = 512; + else if (flags & ABX8XX_OSC_ACAL_1024) + autocalibration = 1024; + else + autocalibration = 0; + + return autocalibration; +} + +static ssize_t autocalibration_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int retval; + unsigned long autocalibration = 0; + + retval = kstrtoul(buf, 10, &autocalibration); + if (retval < 0) { + dev_err(dev, "Failed to store RTC autocalibration attribute\n"); + return -EINVAL; + } + + retval = abx80x_rtc_set_autocalibration(dev, autocalibration); + + return retval ? retval : count; +} + +static ssize_t autocalibration_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int autocalibration = 0; + + autocalibration = abx80x_rtc_get_autocalibration(dev); + if (autocalibration < 0) { + dev_err(dev, "Failed to read RTC autocalibration\n"); + sprintf(buf, "0\n"); + return autocalibration; + } + + return sprintf(buf, "%d\n", autocalibration); +} + +static DEVICE_ATTR_RW(autocalibration); + +static ssize_t oscillator_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + int retval, flags, rc_mode = 0; + + if (strncmp(buf, "rc", 2) == 0) { + rc_mode = 1; + } else if (strncmp(buf, "xtal", 4) == 0) { + rc_mode = 0; + } else { + dev_err(dev, "Oscillator selection value outside permitted ones\n"); + return -EINVAL; + } + + flags = i2c_smbus_read_byte_data(client, ABX8XX_REG_OSC); + if (flags < 0) + return flags; + + if (rc_mode == 0) + flags &= ~(ABX8XX_OSC_OSEL); + else + flags |= (ABX8XX_OSC_OSEL); + + /* Unlock write access on Oscillator Control register */ + retval = i2c_smbus_write_byte_data(client, ABX8XX_REG_CFG_KEY, + ABX8XX_CFG_KEY_OSC); + if (retval < 0) { + dev_err(dev, "Failed to write CONFIG_KEY register\n"); + return retval; + } + + retval = i2c_smbus_write_byte_data(client, ABX8XX_REG_OSC, flags); + if (retval < 0) { + dev_err(dev, "Failed to write Oscillator Control register\n"); + return retval; + } + + return retval ? retval : count; +} + +static ssize_t oscillator_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int rc_mode = 0; + struct i2c_client *client = to_i2c_client(dev); + + rc_mode = abx80x_is_rc_mode(client); + + if (rc_mode < 0) { + dev_err(dev, "Failed to read RTC oscillator selection\n"); + sprintf(buf, "\n"); + return rc_mode; + } + + if (rc_mode) + return sprintf(buf, "rc\n"); + else + return sprintf(buf, "xtal\n"); +} + +static DEVICE_ATTR_RW(oscillator); + +static struct attribute *rtc_calib_attrs[] = { + &dev_attr_autocalibration.attr, + &dev_attr_oscillator.attr, + NULL, +}; + +static const struct attribute_group rtc_calib_attr_group = { + .attrs = rtc_calib_attrs, +}; + static int abx80x_alarm_irq_enable(struct device *dev, unsigned int enabled) { struct i2c_client *client = to_i2c_client(dev); @@ -303,6 +497,13 @@ static int abx80x_dt_trickle_cfg(struct device_node *np) return (trickle_cfg | i); } +static void rtc_calib_remove_sysfs_group(void *_dev) +{ + struct device *dev = _dev; + + sysfs_remove_group(&dev->kobj, &rtc_calib_attr_group); +} + static int abx80x_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -405,6 +606,24 @@ static int abx80x_probe(struct i2c_client *client, } } + /* Export sysfs entries */ + err = sysfs_create_group(&(&client->dev)->kobj, &rtc_calib_attr_group); + if (err) { + dev_err(&client->dev, "Failed to create sysfs group: %d\n", + err); + return err; + } + + err = devm_add_action(&client->dev, rtc_calib_remove_sysfs_group, + &client->dev); + if (err) { + rtc_calib_remove_sysfs_group(&client->dev); + dev_err(&client->dev, + "Failed to add sysfs cleanup action: %d\n", + err); + return err; + } + return 0; } -- cgit v1.2.3-58-ga151 From ee087744247c421c83abea7f01217bfd39b8f5a9 Mon Sep 17 00:00:00 2001 From: Mylène Josserand Date: Mon, 21 Mar 2016 18:06:10 +0100 Subject: rtc: abx80x: handle the oscillator failure bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-abx80x.c | 33 +++++++++++++++++++++++++++++++-- 1 file 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; } -- cgit v1.2.3-58-ga151