diff options
Diffstat (limited to 'drivers/rtc/rtc-abx80x.c')
-rw-r--r-- | drivers/rtc/rtc-abx80x.c | 71 |
1 files changed, 67 insertions, 4 deletions
diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c index 4d24f7288ad7..6ddcad642d1e 100644 --- a/drivers/rtc/rtc-abx80x.c +++ b/drivers/rtc/rtc-abx80x.c @@ -5,7 +5,7 @@ * Copyright 2014-2015 Macq S.A. * * Author: Philippe De Muyter <phdm@macqel.be> - * Author: Alexandre Belloni <alexandre.belloni@free-electrons.com> + * Author: Alexandre Belloni <alexandre.belloni@bootlin.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -46,6 +46,9 @@ #define ABX8XX_CTRL_ARST BIT(2) #define ABX8XX_CTRL_12_24 BIT(6) +#define ABX8XX_REG_CTRL2 0x11 +#define ABX8XX_CTRL2_RSVD BIT(5) + #define ABX8XX_REG_IRQ 0x12 #define ABX8XX_IRQ_AIE BIT(2) #define ABX8XX_IRQ_IM_1_4 (0x3 << 5) @@ -78,6 +81,9 @@ #define ABX8XX_REG_ID0 0x28 +#define ABX8XX_REG_OUT_CTRL 0x30 +#define ABX8XX_OUT_CTRL_EXDS BIT(4) + #define ABX8XX_REG_TRICKLE 0x20 #define ABX8XX_TRICKLE_CHARGE_ENABLE 0xa0 #define ABX8XX_TRICKLE_STANDARD_DIODE 0x8 @@ -86,7 +92,7 @@ static u8 trickle_resistors[] = {0, 3, 6, 11}; enum abx80x_chip {AB0801, AB0803, AB0804, AB0805, - AB1801, AB1803, AB1804, AB1805, ABX80X}; + AB1801, AB1803, AB1804, AB1805, RV1805, ABX80X}; struct abx80x_cap { u16 pn; @@ -103,6 +109,7 @@ static struct abx80x_cap abx80x_caps[] = { [AB1803] = {.pn = 0x1803}, [AB1804] = {.pn = 0x1804, .has_tc = true, .has_wdog = true}, [AB1805] = {.pn = 0x1805, .has_tc = true, .has_wdog = true}, + [RV1805] = {.pn = 0x1805, .has_tc = true, .has_wdog = true}, [ABX80X] = {.pn = 0} }; @@ -723,6 +730,62 @@ static int abx80x_probe(struct i2c_client *client, return -EIO; } + /* Configure RV1805 specifics */ + if (part == RV1805) { + /* + * Avoid accidentally entering test mode. This can happen + * on the RV1805 in case the reserved bit 5 in control2 + * register is set. RV-1805-C3 datasheet indicates that + * the bit should be cleared in section 11h - Control2. + */ + data = i2c_smbus_read_byte_data(client, ABX8XX_REG_CTRL2); + if (data < 0) { + dev_err(&client->dev, + "Unable to read control2 register\n"); + return -EIO; + } + + err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CTRL2, + data & ~ABX8XX_CTRL2_RSVD); + if (err < 0) { + dev_err(&client->dev, + "Unable to write control2 register\n"); + return -EIO; + } + + /* + * Avoid extra power leakage. The RV1805 uses smaller + * 10pin package and the EXTI input is not present. + * Disable it to avoid leakage. + */ + data = i2c_smbus_read_byte_data(client, ABX8XX_REG_OUT_CTRL); + if (data < 0) { + dev_err(&client->dev, + "Unable to read output control register\n"); + return -EIO; + } + + /* + * Write the configuration key register to enable access to + * the config2 register + */ + err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CFG_KEY, + ABX8XX_CFG_KEY_MISC); + if (err < 0) { + dev_err(&client->dev, + "Unable to write configuration key\n"); + return -EIO; + } + + err = i2c_smbus_write_byte_data(client, ABX8XX_REG_OUT_CTRL, + data | ABX8XX_OUT_CTRL_EXDS); + if (err < 0) { + dev_err(&client->dev, + "Unable to write output control register\n"); + return -EIO; + } + } + /* part autodetection */ if (part == ABX80X) { for (i = 0; abx80x_caps[i].pn; i++) @@ -826,7 +889,7 @@ static const struct i2c_device_id abx80x_id[] = { { "ab1803", AB1803 }, { "ab1804", AB1804 }, { "ab1805", AB1805 }, - { "rv1805", AB1805 }, + { "rv1805", RV1805 }, { } }; MODULE_DEVICE_TABLE(i2c, abx80x_id); @@ -843,6 +906,6 @@ static struct i2c_driver abx80x_driver = { module_i2c_driver(abx80x_driver); MODULE_AUTHOR("Philippe De Muyter <phdm@macqel.be>"); -MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@free-electrons.com>"); +MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@bootlin.com>"); MODULE_DESCRIPTION("Abracon ABX80X RTC driver"); MODULE_LICENSE("GPL v2"); |