diff options
author | Enric Balletbo i Serra | 2017-01-27 18:43:46 +0100 |
---|---|---|
committer | Alexandre Belloni | 2017-02-01 12:44:23 +0100 |
commit | 4c466872d8ae8e3cdc3e5e1a47e28a15e3020d8b (patch) | |
tree | 12e1940455bb76c712476e5ef2e66244c09b68f0 /drivers/rtc/rtc-bq32k.c | |
parent | 5dff3a3113173a0c835abbda0eef3c0a2a56cc3a (diff) |
rtc: bq32000: add support to enable disable the trickle charge FET bypass
The bq32000 includes a trickle charge circuit to maintain the charge of the
backup supply when a super capacitor is used.
You can enable the charging circuit by setting 'trickle-resistor-ohms',
additionally you can set TCFE to 1 to bypass the internal diode and boost
the charge voltage of the backup supply. You might want to enable/disable
the TCFE switch from userspace (e.g when device is only connected to a
battery)
This patch introduces a new sysfs entry to enable and disable this FET
form userspace.
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Diffstat (limited to 'drivers/rtc/rtc-bq32k.c')
-rw-r--r-- | drivers/rtc/rtc-bq32k.c | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c index 397742446007..2b223935001f 100644 --- a/drivers/rtc/rtc-bq32k.c +++ b/drivers/rtc/rtc-bq32k.c @@ -34,6 +34,7 @@ #define BQ32K_CALIBRATION 0x07 /* CAL_CFG1, calibration and control */ #define BQ32K_TCH2 0x08 /* Trickle charge enable */ #define BQ32K_CFG2 0x09 /* Trickle charger control */ +#define BQ32K_TCFE BIT(6) /* Trickle charge FET bypass */ struct bq32k_regs { uint8_t seconds; @@ -188,6 +189,65 @@ static int trickle_charger_of_init(struct device *dev, struct device_node *node) return 0; } +static ssize_t bq32k_sysfs_show_tricklecharge_bypass(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int reg, error; + + error = bq32k_read(dev, ®, BQ32K_CFG2, 1); + if (error) + return error; + + return sprintf(buf, "%d\n", (reg & BQ32K_TCFE) ? 1 : 0); +} + +static ssize_t bq32k_sysfs_store_tricklecharge_bypass(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int reg, enable, error; + + if (kstrtoint(buf, 0, &enable)) + return -EINVAL; + + error = bq32k_read(dev, ®, BQ32K_CFG2, 1); + if (error) + return error; + + if (enable) { + reg |= BQ32K_TCFE; + error = bq32k_write(dev, ®, BQ32K_CFG2, 1); + if (error) + return error; + + dev_info(dev, "Enabled trickle charge FET bypass.\n"); + } else { + reg &= ~BQ32K_TCFE; + error = bq32k_write(dev, ®, BQ32K_CFG2, 1); + if (error) + return error; + + dev_info(dev, "Disabled trickle charge FET bypass.\n"); + } + + return count; +} + +static DEVICE_ATTR(trickle_charge_bypass, 0644, + bq32k_sysfs_show_tricklecharge_bypass, + bq32k_sysfs_store_tricklecharge_bypass); + +static int bq32k_sysfs_register(struct device *dev) +{ + return device_create_file(dev, &dev_attr_trickle_charge_bypass); +} + +static void bq32k_sysfs_unregister(struct device *dev) +{ + device_remove_file(dev, &dev_attr_trickle_charge_bypass); +} + static int bq32k_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -224,11 +284,26 @@ static int bq32k_probe(struct i2c_client *client, if (IS_ERR(rtc)) return PTR_ERR(rtc); + error = bq32k_sysfs_register(&client->dev); + if (error) { + dev_err(&client->dev, + "Unable to create sysfs entries for rtc bq32000\n"); + return error; + } + + i2c_set_clientdata(client, rtc); return 0; } +static int bq32k_remove(struct i2c_client *client) +{ + bq32k_sysfs_unregister(&client->dev); + + return 0; +} + static const struct i2c_device_id bq32k_id[] = { { "bq32000", 0 }, { } @@ -240,6 +315,7 @@ static struct i2c_driver bq32k_driver = { .name = "bq32k", }, .probe = bq32k_probe, + .remove = bq32k_remove, .id_table = bq32k_id, }; |