The patch titled Subject: rtc: add rtc-abx805, a driver for the Abracon AB 1805 i2c rtc has been added to the -mm tree. Its filename is rtc-add-rtc-abx805-a-driver-for-the-abracon-ab-1805-i2c-rtc.patch This patch should soon appear at http://ozlabs.org/~akpm/mmots/broken-out/rtc-add-rtc-abx805-a-driver-for-the-abracon-ab-1805-i2c-rtc.patch and later at http://ozlabs.org/~akpm/mmotm/broken-out/rtc-add-rtc-abx805-a-driver-for-the-abracon-ab-1805-i2c-rtc.patch Before you just go and hit "reply", please: a) Consider who else should be cc'ed b) Prefer to cc a suitable mailing list as well c) Ideally: find the original patch on the mailing list and do a reply-to-all to that, adding suitable additional cc's *** Remember to use Documentation/SubmitChecklist when testing your code *** The -mm tree is included into linux-next and is updated there every 3-4 working days ------------------------------------------------------ From: Philippe De Muyter <phdm@xxxxxxxxx> Subject: rtc: add rtc-abx805, a driver for the Abracon AB 1805 i2c rtc This is a basic driver for the ultra-low-power Abracon AB 1805 RTC chip. It allows reading and writing the time, and enables the supercapacitor/ battery charger. Signed-off-by: Philippe De Muyter <phdm@xxxxxxxxx> Cc: Alessandro Zummo <a.zummo@xxxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- drivers/rtc/Kconfig | 7 + drivers/rtc/Makefile | 1 drivers/rtc/rtc-abx805.c | 223 +++++++++++++++++++++++++++++++++++++ 3 files changed, 231 insertions(+) diff -puN drivers/rtc/Kconfig~rtc-add-rtc-abx805-a-driver-for-the-abracon-ab-1805-i2c-rtc drivers/rtc/Kconfig --- a/drivers/rtc/Kconfig~rtc-add-rtc-abx805-a-driver-for-the-abracon-ab-1805-i2c-rtc +++ a/drivers/rtc/Kconfig @@ -1081,6 +1081,13 @@ config RTC_DRV_AB8500 Select this to enable the ST-Ericsson AB8500 power management IC RTC support. This chip contains a battery- and capacitor-backed RTC. +config RTC_DRV_ABX805 + tristate "Abracon AB X805 RTC" + help + Select this to enable support for the Abracon AB X805 RTC. + AB X805 is the i2c flavour of the AB 18X5 family of ultra-low-power + battery- and capacitor-backed RTC.. + config RTC_DRV_NUC900 tristate "NUC910/NUC920 RTC driver" depends on ARCH_W90X900 diff -puN drivers/rtc/Makefile~rtc-add-rtc-abx805-a-driver-for-the-abracon-ab-1805-i2c-rtc drivers/rtc/Makefile --- a/drivers/rtc/Makefile~rtc-add-rtc-abx805-a-driver-for-the-abracon-ab-1805-i2c-rtc +++ a/drivers/rtc/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_RTC_DRV_88PM80X) += rtc-88p 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_ABX805) += rtc-abx805.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 -puN /dev/null drivers/rtc/rtc-abx805.c --- /dev/null +++ a/drivers/rtc/rtc-abx805.c @@ -0,0 +1,223 @@ +/* + * A driver for the I2C members of the Abracon AB 18X5 RTC family, + * and compatible: AB 1805 and AB 0805 + * + * Copyright 2014-2015 Macq S.A. + * + * Author: Philippe De Muyter <phdm@xxxxxxxxx> + * + * Based on rtc-em3027.c by Mike Rapoport <mike@xxxxxxxxxxxxxx> + * + * 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/i2c.h> +#include <linux/rtc.h> +#include <linux/bcd.h> +#include <linux/module.h> + +/* Registers */ + +#define ABX805_REG_SECONDS 0x01 +#define ABX805_REG_CONFIGURATION_KEY 0x1f +#define KEY_ENABLE_MISC_REGISTERS_WRITE_ACCESS 0x90 +#define ABX805_REG_TRICKLE 0x20 +#define TRICKLE_CHARGE_ENABLE 0xA0 +#define TRICKLE_STANDARD_DIODE 0x8 +#define TRICKLE_SCHOTTKY_DIODE 0x4 +#define TRICKLE_OUTPUT_RESISTOR_3KOHM 0x1 +#define TRICKLE_OUTPUT_RESISTOR_6KOHM 0x2 +#define TRICKLE_OUTPUT_RESISTOR_11KOHM 0x3 +#define ABX805_REG_ID0 0x28 + +static struct i2c_driver abx805_driver; + +static int abx805_read_multiple_regs(struct i2c_client *client, + u8 *buf, u8 addr0, int len) +{ + u8 addr = addr0; + struct i2c_msg msgs[] = { + {/* setup read addr */ + .addr = client->addr, + .len = 1, + .buf = &addr + }, + {/* read into buf */ + .addr = client->addr, + .flags = I2C_M_RD, + .len = len, + .buf = buf + }, + }; + + if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { + dev_err(&client->dev, "%s: read error\n", __func__); + return -EIO; + } + + return 0; +} + +static int abx805_enable_trickle_charger(struct i2c_client *client) +{ + u8 buf[2]; + struct i2c_msg msg = { + .addr = client->addr, + .len = 2, + .buf = buf, + }; + + /* + * Write 0x90 in the configuration key register (0x1F) to enable + * the access to the Trickle register + */ + buf[0] = ABX805_REG_CONFIGURATION_KEY; + buf[1] = 0x9D; + + /* write register */ + if ((i2c_transfer(client->adapter, &msg, 1)) != 1) { + dev_err(&client->dev, "%s: write error\n", __func__); + return -EIO; + } + + buf[0] = ABX805_REG_TRICKLE; + buf[1] = TRICKLE_CHARGE_ENABLE | TRICKLE_SCHOTTKY_DIODE | + TRICKLE_OUTPUT_RESISTOR_3KOHM; + + /* write register */ + if ((i2c_transfer(client->adapter, &msg, 1)) != 1) { + dev_err(&client->dev, "%s: write error\n", __func__); + return -EIO; + } + return 0; +} + +static int abx805_get_time(struct device *dev, struct rtc_time *tm) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 buf[7]; + int err; + + dev_dbg(dev, "abx805_get_time\n"); + /* read time/date registers */ + err = abx805_read_multiple_regs(client, buf, ABX805_REG_SECONDS, + sizeof(buf)); + if (err) { + dev_err(&client->dev, "%s: read error\n", __func__); + return err; + } + + tm->tm_sec = bcd2bin(buf[0]); + tm->tm_min = bcd2bin(buf[1]); + tm->tm_hour = bcd2bin(buf[2]); + tm->tm_mday = bcd2bin(buf[3]); + tm->tm_mon = bcd2bin(buf[4]) - 1; + tm->tm_year = bcd2bin(buf[5]) + 100; + tm->tm_wday = bcd2bin(buf[6]); + + return 0; +} + +static int abx805_set_time(struct device *dev, struct rtc_time *tm) +{ + struct i2c_client *client = to_i2c_client(dev); + u8 buf[8]; + + struct i2c_msg msg = { + .addr = client->addr, + .len = 8, + .buf = buf, /* write time/date */ + }; + + dev_dbg(dev, "abx805_set_time\n"); + buf[0] = ABX805_REG_SECONDS; + buf[1] = bin2bcd(tm->tm_sec); + buf[2] = bin2bcd(tm->tm_min); + buf[3] = bin2bcd(tm->tm_hour); + buf[4] = bin2bcd(tm->tm_mday); + buf[5] = bin2bcd(tm->tm_mon + 1); + buf[6] = bin2bcd(tm->tm_year % 100); + buf[7] = bin2bcd(tm->tm_wday); + + /* write time/date registers */ + if ((i2c_transfer(client->adapter, &msg, 1)) != 1) { + dev_err(&client->dev, "%s: write error\n", __func__); + return -EIO; + } + + return 0; +} + +static const struct rtc_class_ops abx805_rtc_ops = { + .read_time = abx805_get_time, + .set_time = abx805_set_time, +}; + +static int abx805_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int err; + struct rtc_device *rtc; + char buf[7]; + unsigned int partnumber; + unsigned int majrev, minrev; + unsigned int lot; + unsigned int wafer; + unsigned int uid; + + dev_info(&client->dev, "abx805_probe\n"); + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -ENODEV; + + err = abx805_read_multiple_regs(client, buf, ABX805_REG_ID0, + sizeof(buf)); + if (err) + return err; + + partnumber = (buf[0] << 8) | buf[1]; + majrev = buf[2] >> 3; + minrev = buf[2] & 0x7; + lot = ((buf[4] & 0x80) << 2) | ((buf[6] & 0x80) << 1) | buf[3]; + uid = ((buf[4] & 0x7f) << 8) | buf[5]; + wafer = (buf[6] & 0x7c) >> 2; + dev_info(&client->dev, "model %04x, revision %u.%u, lot %x, wafer %x, uid %x\n", + partnumber, majrev, minrev, lot, wafer, uid); + + abx805_enable_trickle_charger(client); + + rtc = devm_rtc_device_register(&client->dev, abx805_driver.driver.name, + &abx805_rtc_ops, THIS_MODULE); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); + + i2c_set_clientdata(client, rtc); + + return 0; +} + +static int abx805_remove(struct i2c_client *client) +{ + return 0; +} + +static struct i2c_device_id abx805_id[] = { + { "abx805-rtc", 0 }, + { } +}; + +static struct i2c_driver abx805_driver = { + .driver = { + .name = "abx805-rtc", + }, + .probe = &abx805_probe, + .remove = &abx805_remove, + .id_table = abx805_id, +}; + +module_i2c_driver(abx805_driver); + +MODULE_AUTHOR("Philippe De Muyter <phdm@xxxxxxxxx>"); +MODULE_DESCRIPTION("Abracon AB X805 RTC driver"); +MODULE_LICENSE("GPL"); _ Patches currently in -mm which might be from phdm@xxxxxxxxx are rtc-add-rtc-abx805-a-driver-for-the-abracon-ab-1805-i2c-rtc.patch -- To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html