rtc: rv3029: Add device tree property for trickle charger

The trickle charger resistor can be enabled via device tree
property trickle-resistor-ohms.

Signed-off-by: Michael Buesch <m@bues.ch>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
This commit is contained in:
Michael Büsch 2016-03-04 22:41:19 +01:00 committed by Alexandre Belloni
parent a7f6e28741
commit e27e21603e
1 changed files with 103 additions and 3 deletions

View File

@ -10,9 +10,6 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* NOTE: Currently this driver only supports the bare minimum for read
* and write the RTC and alarms. The extra features provided by this chip
* (trickle charger, eeprom, T° compensation) are unavailable.
*/
#include <linux/module.h>
@ -528,6 +525,107 @@ static int rv3029_rtc_set_time(struct device *dev, struct rtc_time *tm)
return rv3029_i2c_set_time(to_i2c_client(dev), tm);
}
static const struct rv3029_trickle_tab_elem {
u32 r; /* resistance in ohms */
u8 conf; /* trickle config bits */
} rv3029_trickle_tab[] = {
{
.r = 1076,
.conf = RV3029_TRICKLE_1K | RV3029_TRICKLE_5K |
RV3029_TRICKLE_20K | RV3029_TRICKLE_80K,
}, {
.r = 1091,
.conf = RV3029_TRICKLE_1K | RV3029_TRICKLE_5K |
RV3029_TRICKLE_20K,
}, {
.r = 1137,
.conf = RV3029_TRICKLE_1K | RV3029_TRICKLE_5K |
RV3029_TRICKLE_80K,
}, {
.r = 1154,
.conf = RV3029_TRICKLE_1K | RV3029_TRICKLE_5K,
}, {
.r = 1371,
.conf = RV3029_TRICKLE_1K | RV3029_TRICKLE_20K |
RV3029_TRICKLE_80K,
}, {
.r = 1395,
.conf = RV3029_TRICKLE_1K | RV3029_TRICKLE_20K,
}, {
.r = 1472,
.conf = RV3029_TRICKLE_1K | RV3029_TRICKLE_80K,
}, {
.r = 1500,
.conf = RV3029_TRICKLE_1K,
}, {
.r = 3810,
.conf = RV3029_TRICKLE_5K | RV3029_TRICKLE_20K |
RV3029_TRICKLE_80K,
}, {
.r = 4000,
.conf = RV3029_TRICKLE_5K | RV3029_TRICKLE_20K,
}, {
.r = 4706,
.conf = RV3029_TRICKLE_5K | RV3029_TRICKLE_80K,
}, {
.r = 5000,
.conf = RV3029_TRICKLE_5K,
}, {
.r = 16000,
.conf = RV3029_TRICKLE_20K | RV3029_TRICKLE_80K,
}, {
.r = 20000,
.conf = RV3029_TRICKLE_20K,
}, {
.r = 80000,
.conf = RV3029_TRICKLE_80K,
},
};
static void rv3029_trickle_config(struct i2c_client *client)
{
struct device_node *of_node = client->dev.of_node;
const struct rv3029_trickle_tab_elem *elem;
int i, err;
u32 ohms;
u8 eectrl;
if (!of_node)
return;
/* Configure the trickle charger. */
err = rv3029_eeprom_read(client, RV3029_CONTROL_E2P_EECTRL,
&eectrl, 1);
if (err < 0) {
dev_err(&client->dev,
"Failed to read trickle charger config\n");
return;
}
err = of_property_read_u32(of_node, "trickle-resistor-ohms", &ohms);
if (err) {
/* Disable trickle charger. */
eectrl &= ~RV3029_TRICKLE_MASK;
} else {
/* Enable trickle charger. */
for (i = 0; i < ARRAY_SIZE(rv3029_trickle_tab); i++) {
elem = &rv3029_trickle_tab[i];
if (elem->r >= ohms)
break;
}
eectrl &= ~RV3029_TRICKLE_MASK;
eectrl |= elem->conf;
dev_info(&client->dev,
"Trickle charger enabled at %d ohms resistance.\n",
elem->r);
}
err = rv3029_eeprom_write(client, RV3029_CONTROL_E2P_EECTRL,
&eectrl, 1);
if (err < 0) {
dev_err(&client->dev,
"Failed to write trickle charger config\n");
}
}
static const struct rtc_class_ops rv3029_rtc_ops = {
.read_time = rv3029_rtc_read_time,
.set_time = rv3029_rtc_set_time,
@ -558,6 +656,8 @@ static int rv3029_probe(struct i2c_client *client,
return rc;
}
rv3029_trickle_config(client);
rtc = devm_rtc_device_register(&client->dev, client->name,
&rv3029_rtc_ops, THIS_MODULE);