Skip to content
Snippets Groups Projects
Commit d0660cdc authored by Sjoerd Simons's avatar Sjoerd Simons
Browse files

power: supply: bq27xxx_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 cycle count to 0. This attribute is
used to init a battery after replacement.

Signed-off-by: default avatarSjoerd Simons <sjoerd.simons@collabora.co.uk>
parent b720a321
No related branches found
No related tags found
No related merge requests found
...@@ -2150,8 +2150,66 @@ static enum power_supply_property charger_props[] = { ...@@ -2150,8 +2150,66 @@ static enum power_supply_property charger_props[] = {
POWER_SUPPLY_PROP_ONLINE, 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 bq27xxx_battery_setup(struct bq27xxx_device_info *di)
{ {
int ret;
struct power_supply_desc *psy_desc, *psy_desc_charger; struct power_supply_desc *psy_desc, *psy_desc_charger;
struct power_supply_config psy_cfg = { struct power_supply_config psy_cfg = {
.of_node = di->dev->of_node, .of_node = di->dev->of_node,
...@@ -2183,6 +2241,13 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di) ...@@ -2183,6 +2241,13 @@ int bq27xxx_battery_setup(struct bq27xxx_device_info *di)
return PTR_ERR(di->bat); 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 /* TODO only allocate charger iff there is one, probably via a dt
* property */ * property */
psy_desc_charger = devm_kzalloc(di->dev, sizeof(*psy_desc_charger), GFP_KERNEL); psy_desc_charger = devm_kzalloc(di->dev, sizeof(*psy_desc_charger), GFP_KERNEL);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment