diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c index d45970f8dd8f019bca761e1043830dffbae5d4f0..8cc619640a8f74582063058f4ce29649bab87c41 100644 --- a/drivers/power/supply/bq27xxx_battery.c +++ b/drivers/power/supply/bq27xxx_battery.c @@ -2150,8 +2150,66 @@ static enum power_supply_property charger_props[] = { POWER_SUPPLY_PROP_ONLINE, }; +static ssize_t battery_reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + bool reset; + int err; + struct bq27xxx_device_info *di = dev_get_drvdata(dev->parent); + struct bq27xxx_dm_buf_cache cache; + bool updated; + + memset (&cache, 0, sizeof(cache)); + + err = kstrtobool(buf, &reset); + if (err) + return err; + + if (!reset) + return count; + + dev_info(di->dev, "RESET FOR %s\n", di->name); + cancel_delayed_work_sync(&di->work); + + err = bq27xxx_battery_unseal(di); + if (err) { + count = err; + goto restart_delayed_work; + } + + bq27xxx_battery_update_dm_reg(di, &cache, BQ27XXX_DM_CYCLE_COUNT, 0); + updated = bq27xxx_battery_cache_flush (di, &cache); + + if (updated > 0 && !(di->opts & BQ27XXX_O_CFGUP)) { + dev_info(di->dev, "Resetting due to update options"); + bq27xxx_write(di, BQ27XXX_REG_CTRL, BQ27XXX_RESET, false); + BQ27XXX_MSLEEP(300); /* reset time is not documented */ + } + + bq27xxx_battery_seal(di); + +restart_delayed_work: + schedule_delayed_work (&di->work, 0); + return count; +} + +static DEVICE_ATTR_WO(battery_reset); + +static struct attribute *bq27xxx_battery_attrs[] = { + &dev_attr_battery_reset.attr, + NULL, +}; + +static const struct attribute_group bq27xxx_battery_attr_group = { + .attrs = bq27xxx_battery_attrs, +}; + + int bq27xxx_battery_setup(struct bq27xxx_device_info *di) { + int ret; struct power_supply_desc *psy_desc, *psy_desc_charger; struct power_supply_config psy_cfg = { .of_node = di->dev->of_node, @@ -2183,6 +2241,13 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) return PTR_ERR(di->bat); } + ret = sysfs_create_group(&di->bat->dev.kobj, + &bq27xxx_battery_attr_group); + if (ret) { + dev_err(&di->bat->dev, "failed to create sysfs files\n"); + return ret; + } + /* TODO only allocate charger iff there is one, probably via a dt * property */ psy_desc_charger = devm_kzalloc(di->dev, sizeof(*psy_desc_charger), GFP_KERNEL);