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>
This commit is contained in:
parent
33b04b7b7c
commit
765a98a6b9
@ -2,10 +2,14 @@
|
|||||||
* Driver for TI BQ32000 RTC.
|
* Driver for TI BQ32000 RTC.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009 Semihalf.
|
* Copyright (C) 2009 Semihalf.
|
||||||
|
* Copyright (C) 2014 Pavel Machek <pavel@denx.de>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
* published by the Free Software Foundation.
|
* 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>
|
#include <linux/module.h>
|
||||||
@ -27,6 +31,10 @@
|
|||||||
#define BQ32K_CENT 0x40 /* Century flag */
|
#define BQ32K_CENT 0x40 /* Century flag */
|
||||||
#define BQ32K_CENT_EN 0x80 /* Century flag enable bit */
|
#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 {
|
struct bq32k_regs {
|
||||||
uint8_t seconds;
|
uint8_t seconds;
|
||||||
uint8_t minutes;
|
uint8_t minutes;
|
||||||
@ -122,6 +130,57 @@ static const struct rtc_class_ops bq32k_rtc_ops = {
|
|||||||
.set_time = bq32k_rtc_set_time,
|
.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,
|
static int bq32k_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
@ -153,6 +212,9 @@ static int bq32k_probe(struct i2c_client *client,
|
|||||||
if (error)
|
if (error)
|
||||||
return 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,
|
rtc = devm_rtc_device_register(&client->dev, bq32k_driver.driver.name,
|
||||||
&bq32k_rtc_ops, THIS_MODULE);
|
&bq32k_rtc_ops, THIS_MODULE);
|
||||||
if (IS_ERR(rtc))
|
if (IS_ERR(rtc))
|
||||||
|
Loading…
Reference in New Issue
Block a user