From 92fb2212420d0376c83a4baa3cf9f270f57a940e Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra <enric.balletbo@collabora.com> Date: Tue, 18 Jun 2019 18:57:04 +0200 Subject: [PATCH] power: tcl-sbs-battery: Expose a battery_reset attribute to userspace Writing a '1' to this attribute should trigger a reset on battery status and return the battery to its default values. This attribute is used to init a battery after replacement. Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com> --- drivers/power/supply/tcl-sbs-battery.c | 53 ++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/drivers/power/supply/tcl-sbs-battery.c b/drivers/power/supply/tcl-sbs-battery.c index 5d4f2cf63fd6..1bf34dcef318 100644 --- a/drivers/power/supply/tcl-sbs-battery.c +++ b/drivers/power/supply/tcl-sbs-battery.c @@ -63,6 +63,9 @@ /* Firmware version, 1 byte */ #define SBS_FIRMWARE_VERSION 0x7d +/* Command to reset battery after replacement */ +#define SBS_CMD_BATTERY_RESET (SBS_MEMORY_MAP_SIZE + 1) + /* MM SIZE + START(u16) + CHECKSUM(u16) */ #define SPI_MSG_LENGTH (SBS_MEMORY_MAP_SIZE + 4) #define SPI_MSG_DATA_BP 2 @@ -450,7 +453,57 @@ static ssize_t tcl_sbs_battery_program_store(struct device *dev, static DEVICE_ATTR(program, 0644, tcl_sbs_battery_program_show, tcl_sbs_battery_program_store); +static ssize_t battery_reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct tcl_sbs_battery_data *data = dev_get_drvdata(dev->parent); + struct spi_device *spi = data->spi; + u8 cmd, res; + bool reset; + int err; + + err = kstrtobool(buf, &reset); + if (err) + return err; + if (!reset) + return count; + + /* stop polling the MCU */ + cancel_delayed_work_sync(&data->bat_work); + + cmd = SBS_CMD_BATTERY_RESET; + err = spi_write(spi, &cmd, 1); + if (err) { + dev_err(&spi->dev, "failed to write command\n"); + count = err; + goto restart_delayed_work; + } + + err = spi_read(spi, &res, 1); + if (err) { + dev_err(&spi->dev, "failed to read command result\n"); + count = err; + goto restart_delayed_work; + } + + if (res) { + dev_err(&spi->dev, "invalid command %u\n", cmd); + count = -EINVAL; + } + +restart_delayed_work: + /* re-start polling the MCU */ + schedule_delayed_work(&data->bat_work, 0); + + return count; +} + +static DEVICE_ATTR_WO(battery_reset); + static struct attribute *tcl_sbs_battery_attrs[] = { + &dev_attr_battery_reset.attr, &dev_attr_fw_version.attr, &dev_attr_program.attr, NULL, -- GitLab