diff options
author | Pavel Machek <pavel@ucw.cz> | 2014-10-13 15:52:50 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-14 02:18:18 +0200 |
commit | 765a98a6b9e71702fd8e3822b654f9041a206b47 (patch) | |
tree | 56a77592d6fd41ce9d53cce849fed327dce24f55 /drivers/rtc/rtc-bq32k.c | |
parent | 33b04b7b7c03d04584be3f91ebc1eb40eb1ed33c (diff) | |
download | lwn-765a98a6b9e71702fd8e3822b654f9041a206b47.tar.gz lwn-765a98a6b9e71702fd8e3822b654f9041a206b47.zip |
rtc: bq32000: add trickle charger option, with device tree binding
BQ32000 devices have "trickle chargers". Introduce a code to enable the
charger, based on device tree.
Without charger, RTC does not keep time after power off.
[akpm@linux-foundation.org: coding-style fixes]
Signed-off-by: Pavel Machek <pavel@denx.de>
Cc: Jason Cooper <jason@lakedameon.net>
Cc: Matti Vaittinen <matti.vaittinen@nsn.com>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rtc/rtc-bq32k.c')
-rw-r--r-- | drivers/rtc/rtc-bq32k.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c index c74bf0dc52cc..314129e66d6e 100644 --- a/drivers/rtc/rtc-bq32k.c +++ b/drivers/rtc/rtc-bq32k.c @@ -2,10 +2,14 @@ * Driver for TI BQ32000 RTC. * * Copyright (C) 2009 Semihalf. + * Copyright (C) 2014 Pavel Machek <pavel@denx.de> * * 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. + * + * You can get hardware description at + * http://www.ti.com/lit/ds/symlink/bq32000.pdf */ #include <linux/module.h> @@ -27,6 +31,10 @@ #define BQ32K_CENT 0x40 /* Century flag */ #define BQ32K_CENT_EN 0x80 /* Century flag enable bit */ +#define BQ32K_CALIBRATION 0x07 /* CAL_CFG1, calibration and control */ +#define BQ32K_TCH2 0x08 /* Trickle charge enable */ +#define BQ32K_CFG2 0x09 /* Trickle charger control */ + struct bq32k_regs { uint8_t seconds; uint8_t minutes; @@ -122,6 +130,57 @@ static const struct rtc_class_ops bq32k_rtc_ops = { .set_time = bq32k_rtc_set_time, }; +static int trickle_charger_of_init(struct device *dev, struct device_node *node) +{ + unsigned char reg; + int error; + u32 ohms = 0; + + if (of_property_read_u32(node, "trickle-resistor-ohms" , &ohms)) + return 0; + + switch (ohms) { + case 180+940: + /* + * TCHE[3:0] == 0x05, TCH2 == 1, TCFE == 0 (charging + * over diode and 940ohm resistor) + */ + + if (of_property_read_bool(node, "trickle-diode-disable")) { + dev_err(dev, "diode and resistor mismatch\n"); + return -EINVAL; + } + reg = 0x05; + break; + + case 180+20000: + /* diode disabled */ + + if (!of_property_read_bool(node, "trickle-diode-disable")) { + dev_err(dev, "bq32k: diode and resistor mismatch\n"); + return -EINVAL; + } + reg = 0x25; + break; + + default: + dev_err(dev, "invalid resistor value (%d)\n", ohms); + return -EINVAL; + } + + error = bq32k_write(dev, ®, BQ32K_CFG2, 1); + if (error) + return error; + + reg = 0x20; + error = bq32k_write(dev, ®, BQ32K_TCH2, 1); + if (error) + return error; + + dev_info(dev, "Enabled trickle RTC battery charge.\n"); + return 0; +} + static int bq32k_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -153,6 +212,9 @@ static int bq32k_probe(struct i2c_client *client, if (error) return error; + if (client && client->dev.of_node) + trickle_charger_of_init(dev, client->dev.of_node); + rtc = devm_rtc_device_register(&client->dev, bq32k_driver.driver.name, &bq32k_rtc_ops, THIS_MODULE); if (IS_ERR(rtc)) |