diff options
author | Pavel Machek <pavel@ucw.cz> | 2014-10-13 18:52:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-13 20:18:18 -0400 |
commit | 765a98a6b9e71702fd8e3822b654f9041a206b47 (patch) | |
tree | 56a77592d6fd41ce9d53cce849fed327dce24f55 /drivers/rtc | |
parent | 33b04b7b7c03d04584be3f91ebc1eb40eb1ed33c (diff) |
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')
-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 @@ | |||
2 | * Driver for TI BQ32000 RTC. | 2 | * Driver for TI BQ32000 RTC. |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Semihalf. | 4 | * Copyright (C) 2009 Semihalf. |
5 | * Copyright (C) 2014 Pavel Machek <pavel@denx.de> | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
8 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | * | ||
11 | * You can get hardware description at | ||
12 | * http://www.ti.com/lit/ds/symlink/bq32000.pdf | ||
9 | */ | 13 | */ |
10 | 14 | ||
11 | #include <linux/module.h> | 15 | #include <linux/module.h> |
@@ -27,6 +31,10 @@ | |||
27 | #define BQ32K_CENT 0x40 /* Century flag */ | 31 | #define BQ32K_CENT 0x40 /* Century flag */ |
28 | #define BQ32K_CENT_EN 0x80 /* Century flag enable bit */ | 32 | #define BQ32K_CENT_EN 0x80 /* Century flag enable bit */ |
29 | 33 | ||
34 | #define BQ32K_CALIBRATION 0x07 /* CAL_CFG1, calibration and control */ | ||
35 | #define BQ32K_TCH2 0x08 /* Trickle charge enable */ | ||
36 | #define BQ32K_CFG2 0x09 /* Trickle charger control */ | ||
37 | |||
30 | struct bq32k_regs { | 38 | struct bq32k_regs { |
31 | uint8_t seconds; | 39 | uint8_t seconds; |
32 | uint8_t minutes; | 40 | uint8_t minutes; |
@@ -122,6 +130,57 @@ static const struct rtc_class_ops bq32k_rtc_ops = { | |||
122 | .set_time = bq32k_rtc_set_time, | 130 | .set_time = bq32k_rtc_set_time, |
123 | }; | 131 | }; |
124 | 132 | ||
133 | static int trickle_charger_of_init(struct device *dev, struct device_node *node) | ||
134 | { | ||
135 | unsigned char reg; | ||
136 | int error; | ||
137 | u32 ohms = 0; | ||
138 | |||
139 | if (of_property_read_u32(node, "trickle-resistor-ohms" , &ohms)) | ||
140 | return 0; | ||
141 | |||
142 | switch (ohms) { | ||
143 | case 180+940: | ||
144 | /* | ||
145 | * TCHE[3:0] == 0x05, TCH2 == 1, TCFE == 0 (charging | ||
146 | * over diode and 940ohm resistor) | ||
147 | */ | ||
148 | |||
149 | if (of_property_read_bool(node, "trickle-diode-disable")) { | ||
150 | dev_err(dev, "diode and resistor mismatch\n"); | ||
151 | return -EINVAL; | ||
152 | } | ||
153 | reg = 0x05; | ||
154 | break; | ||
155 | |||
156 | case 180+20000: | ||
157 | /* diode disabled */ | ||
158 | |||
159 | if (!of_property_read_bool(node, "trickle-diode-disable")) { | ||
160 | dev_err(dev, "bq32k: diode and resistor mismatch\n"); | ||
161 | return -EINVAL; | ||
162 | } | ||
163 | reg = 0x25; | ||
164 | break; | ||
165 | |||
166 | default: | ||
167 | dev_err(dev, "invalid resistor value (%d)\n", ohms); | ||
168 | return -EINVAL; | ||
169 | } | ||
170 | |||
171 | error = bq32k_write(dev, ®, BQ32K_CFG2, 1); | ||
172 | if (error) | ||
173 | return error; | ||
174 | |||
175 | reg = 0x20; | ||
176 | error = bq32k_write(dev, ®, BQ32K_TCH2, 1); | ||
177 | if (error) | ||
178 | return error; | ||
179 | |||
180 | dev_info(dev, "Enabled trickle RTC battery charge.\n"); | ||
181 | return 0; | ||
182 | } | ||
183 | |||
125 | static int bq32k_probe(struct i2c_client *client, | 184 | static int bq32k_probe(struct i2c_client *client, |
126 | const struct i2c_device_id *id) | 185 | const struct i2c_device_id *id) |
127 | { | 186 | { |
@@ -153,6 +212,9 @@ static int bq32k_probe(struct i2c_client *client, | |||
153 | if (error) | 212 | if (error) |
154 | return error; | 213 | return error; |
155 | 214 | ||
215 | if (client && client->dev.of_node) | ||
216 | trickle_charger_of_init(dev, client->dev.of_node); | ||
217 | |||
156 | rtc = devm_rtc_device_register(&client->dev, bq32k_driver.driver.name, | 218 | rtc = devm_rtc_device_register(&client->dev, bq32k_driver.driver.name, |
157 | &bq32k_rtc_ops, THIS_MODULE); | 219 | &bq32k_rtc_ops, THIS_MODULE); |
158 | if (IS_ERR(rtc)) | 220 | if (IS_ERR(rtc)) |