[PATCH v3] rtc: add rtc-abx80x, a driver for the Abracon AB x80x i2c rtc

2015-04-17 Thread Alexandre Belloni
From: Philippe De Muyter 

This is a basic driver for the ultra-low-power Abracon AB x80x series of RTC
chips. It supports in particular, the supersets AB0805 and AB1805.
It allows reading and writing the time, and enables the supercapacitor/
battery charger.

[a...@arndb.de: abx805 depends on i2c]
Signed-off-by: Philippe De Muyter 
Cc: Alessandro Zummo 
Signed-off-by: Alexandre Belloni 
Signed-off-by: Arnd Bergmann 
Signed-off-by: Andrew Morton 
---
Changes in v3:
 - renamed buffer from date to buf in abx80x_rtc_read_time()


 drivers/rtc/Kconfig  |  10 ++
 drivers/rtc/Makefile |   1 +
 drivers/rtc/rtc-abx80x.c | 307 +++
 3 files changed, 318 insertions(+)
 create mode 100644 drivers/rtc/rtc-abx80x.c

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index b5b5c3d485d6..89507c1858ec 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -164,6 +164,16 @@ config RTC_DRV_ABB5ZES3
  This driver can also be built as a module. If so, the module
  will be called rtc-ab-b5ze-s3.
 
+config RTC_DRV_ABX80X
+   tristate "Abracon ABx80x"
+   help
+ If you say yes here you get support for Abracon AB080X and AB180X
+ families of ultra-low-power  battery- and capacitor-backed real-time
+ clock chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-abx80x.
+
 config RTC_DRV_AS3722
tristate "ams AS3722 RTC driver"
depends on MFD_AS3722
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 69c87062b098..7b20b0462cb6 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_RTC_DRV_88PM80X) += rtc-88pm80x.o
 obj-$(CONFIG_RTC_DRV_AB3100)   += rtc-ab3100.o
 obj-$(CONFIG_RTC_DRV_AB8500)   += rtc-ab8500.o
 obj-$(CONFIG_RTC_DRV_ABB5ZES3) += rtc-ab-b5ze-s3.o
+obj-$(CONFIG_RTC_DRV_ABX80X)   += rtc-abx80x.o
 obj-$(CONFIG_RTC_DRV_ARMADA38X)+= rtc-armada38x.o
 obj-$(CONFIG_RTC_DRV_AS3722)   += rtc-as3722.o
 obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o
diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
new file mode 100644
index ..4337c3bc6ace
--- /dev/null
+++ b/drivers/rtc/rtc-abx80x.c
@@ -0,0 +1,307 @@
+/*
+ * A driver for the I2C members of the Abracon AB x8xx RTC family,
+ * and compatible: AB 1805 and AB 0805
+ *
+ * Copyright 2014-2015 Macq S.A.
+ *
+ * Author: Philippe De Muyter 
+ * Author: Alexandre Belloni 
+ *
+ * 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
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#define ABX8XX_REG_HTH 0x00
+#define ABX8XX_REG_SC  0x01
+#define ABX8XX_REG_MN  0x02
+#define ABX8XX_REG_HR  0x03
+#define ABX8XX_REG_DA  0x04
+#define ABX8XX_REG_MO  0x05
+#define ABX8XX_REG_YR  0x06
+#define ABX8XX_REG_WD  0x07
+
+#define ABX8XX_REG_CTRL1   0x10
+#define ABX8XX_CTRL_WRITE  BIT(1)
+#define ABX8XX_CTRL_12_24  BIT(6)
+
+#define ABX8XX_REG_CFG_KEY 0x1f
+#define ABX8XX_CFG_KEY_MISC0x9d
+
+#define ABX8XX_REG_ID0 0x28
+
+#define ABX8XX_REG_TRICKLE 0x20
+#define ABX8XX_TRICKLE_CHARGE_ENABLE   0xa0
+#define ABX8XX_TRICKLE_STANDARD_DIODE  0x8
+#define ABX8XX_TRICKLE_SCHOTTKY_DIODE  0x4
+
+static u8 trickle_resistors[] = {0, 3, 6, 11};
+
+enum abx80x_chip {AB0801, AB0803, AB0804, AB0805,
+   AB1801, AB1803, AB1804, AB1805, ABX80X};
+
+struct abx80x_cap {
+   u16 pn;
+   bool has_tc;
+};
+
+static struct abx80x_cap abx80x_caps[] = {
+   [AB0801] = {.pn = 0x0801},
+   [AB0803] = {.pn = 0x0803},
+   [AB0804] = {.pn = 0x0804, .has_tc = true},
+   [AB0805] = {.pn = 0x0805, .has_tc = true},
+   [AB1801] = {.pn = 0x1801},
+   [AB1803] = {.pn = 0x1803},
+   [AB1804] = {.pn = 0x1804, .has_tc = true},
+   [AB1805] = {.pn = 0x1805, .has_tc = true},
+   [ABX80X] = {.pn = 0}
+};
+
+static struct i2c_driver abx80x_driver;
+
+static int abx80x_enable_trickle_charger(struct i2c_client *client,
+u8 trickle_cfg)
+{
+   int err;
+
+   /*
+* Write the configuration key register to enable access to the Trickle
+* register
+*/
+   err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CFG_KEY,
+   ABX8XX_CFG_KEY_MISC);
+   if (err < 0) {
+   dev_err(>dev, "Unable to write configuration key\n");
+   return -EIO;
+   }
+
+   err = i2c_smbus_write_byte_data(client, ABX8XX_REG_TRICKLE,
+   ABX8XX_TRICKLE_CHARGE_ENABLE |
+   trickle_cfg);
+   if (err < 0) {
+   dev_err(>dev, "Unable to write trickle register\n");
+   return -EIO;
+   }
+
+   

[PATCH v3] rtc: add rtc-abx80x, a driver for the Abracon AB x80x i2c rtc

2015-04-17 Thread Alexandre Belloni
From: Philippe De Muyter p...@macqel.be

This is a basic driver for the ultra-low-power Abracon AB x80x series of RTC
chips. It supports in particular, the supersets AB0805 and AB1805.
It allows reading and writing the time, and enables the supercapacitor/
battery charger.

[a...@arndb.de: abx805 depends on i2c]
Signed-off-by: Philippe De Muyter p...@macqel.be
Cc: Alessandro Zummo a.zu...@towertech.it
Signed-off-by: Alexandre Belloni alexandre.bell...@free-electrons.com
Signed-off-by: Arnd Bergmann a...@arndb.de
Signed-off-by: Andrew Morton a...@linux-foundation.org
---
Changes in v3:
 - renamed buffer from date to buf in abx80x_rtc_read_time()


 drivers/rtc/Kconfig  |  10 ++
 drivers/rtc/Makefile |   1 +
 drivers/rtc/rtc-abx80x.c | 307 +++
 3 files changed, 318 insertions(+)
 create mode 100644 drivers/rtc/rtc-abx80x.c

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index b5b5c3d485d6..89507c1858ec 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -164,6 +164,16 @@ config RTC_DRV_ABB5ZES3
  This driver can also be built as a module. If so, the module
  will be called rtc-ab-b5ze-s3.
 
+config RTC_DRV_ABX80X
+   tristate Abracon ABx80x
+   help
+ If you say yes here you get support for Abracon AB080X and AB180X
+ families of ultra-low-power  battery- and capacitor-backed real-time
+ clock chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-abx80x.
+
 config RTC_DRV_AS3722
tristate ams AS3722 RTC driver
depends on MFD_AS3722
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 69c87062b098..7b20b0462cb6 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_RTC_DRV_88PM80X) += rtc-88pm80x.o
 obj-$(CONFIG_RTC_DRV_AB3100)   += rtc-ab3100.o
 obj-$(CONFIG_RTC_DRV_AB8500)   += rtc-ab8500.o
 obj-$(CONFIG_RTC_DRV_ABB5ZES3) += rtc-ab-b5ze-s3.o
+obj-$(CONFIG_RTC_DRV_ABX80X)   += rtc-abx80x.o
 obj-$(CONFIG_RTC_DRV_ARMADA38X)+= rtc-armada38x.o
 obj-$(CONFIG_RTC_DRV_AS3722)   += rtc-as3722.o
 obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o
diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
new file mode 100644
index ..4337c3bc6ace
--- /dev/null
+++ b/drivers/rtc/rtc-abx80x.c
@@ -0,0 +1,307 @@
+/*
+ * A driver for the I2C members of the Abracon AB x8xx RTC family,
+ * and compatible: AB 1805 and AB 0805
+ *
+ * Copyright 2014-2015 Macq S.A.
+ *
+ * Author: Philippe De Muyter p...@macqel.be
+ * Author: Alexandre Belloni alexandre.bell...@free-electrons.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
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include linux/bcd.h
+#include linux/i2c.h
+#include linux/module.h
+#include linux/rtc.h
+
+#define ABX8XX_REG_HTH 0x00
+#define ABX8XX_REG_SC  0x01
+#define ABX8XX_REG_MN  0x02
+#define ABX8XX_REG_HR  0x03
+#define ABX8XX_REG_DA  0x04
+#define ABX8XX_REG_MO  0x05
+#define ABX8XX_REG_YR  0x06
+#define ABX8XX_REG_WD  0x07
+
+#define ABX8XX_REG_CTRL1   0x10
+#define ABX8XX_CTRL_WRITE  BIT(1)
+#define ABX8XX_CTRL_12_24  BIT(6)
+
+#define ABX8XX_REG_CFG_KEY 0x1f
+#define ABX8XX_CFG_KEY_MISC0x9d
+
+#define ABX8XX_REG_ID0 0x28
+
+#define ABX8XX_REG_TRICKLE 0x20
+#define ABX8XX_TRICKLE_CHARGE_ENABLE   0xa0
+#define ABX8XX_TRICKLE_STANDARD_DIODE  0x8
+#define ABX8XX_TRICKLE_SCHOTTKY_DIODE  0x4
+
+static u8 trickle_resistors[] = {0, 3, 6, 11};
+
+enum abx80x_chip {AB0801, AB0803, AB0804, AB0805,
+   AB1801, AB1803, AB1804, AB1805, ABX80X};
+
+struct abx80x_cap {
+   u16 pn;
+   bool has_tc;
+};
+
+static struct abx80x_cap abx80x_caps[] = {
+   [AB0801] = {.pn = 0x0801},
+   [AB0803] = {.pn = 0x0803},
+   [AB0804] = {.pn = 0x0804, .has_tc = true},
+   [AB0805] = {.pn = 0x0805, .has_tc = true},
+   [AB1801] = {.pn = 0x1801},
+   [AB1803] = {.pn = 0x1803},
+   [AB1804] = {.pn = 0x1804, .has_tc = true},
+   [AB1805] = {.pn = 0x1805, .has_tc = true},
+   [ABX80X] = {.pn = 0}
+};
+
+static struct i2c_driver abx80x_driver;
+
+static int abx80x_enable_trickle_charger(struct i2c_client *client,
+u8 trickle_cfg)
+{
+   int err;
+
+   /*
+* Write the configuration key register to enable access to the Trickle
+* 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_TRICKLE,
+