mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-07 14:24:18 +08:00
power: supply: bq27xxx: Ensure power_supply_changed() is called on current sign changes
[ Upstream commit939a116142
] On gauges where the current register is signed, there is no charging flag in the flags register. So only checking flags will not result in power_supply_changed() getting called when e.g. a charger is plugged in and the current sign changes from negative (discharging) to positive (charging). This causes userspace's notion of the status to lag until userspace does a poll. And when a power_supply_leds.c LED trigger is used to indicate charging status with a LED, this LED will lag until the capacity percentage changes, which may take many minutes (because the LED trigger only is updated on power_supply_changed() calls). Fix this by calling bq27xxx_battery_current_and_status() on gauges with a signed current register and checking if the status has changed. Fixes:297a533b3e
("bq27x00: Cache battery registers") Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
e4c708a9bb
commit
75a7e9de60
@ -1836,6 +1836,7 @@ static int bq27xxx_battery_current_and_status(
|
||||
|
||||
static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
|
||||
{
|
||||
union power_supply_propval status = di->last_status;
|
||||
struct bq27xxx_reg_cache cache = {0, };
|
||||
bool has_singe_flag = di->opts & BQ27XXX_O_ZERO;
|
||||
|
||||
@ -1860,14 +1861,24 @@ static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
|
||||
if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR)
|
||||
cache.cycle_count = bq27xxx_battery_read_cyct(di);
|
||||
|
||||
/*
|
||||
* On gauges with signed current reporting the current must be
|
||||
* checked to detect charging <-> discharging status changes.
|
||||
*/
|
||||
if (!(di->opts & BQ27XXX_O_ZERO))
|
||||
bq27xxx_battery_current_and_status(di, NULL, &status, &cache);
|
||||
|
||||
/* We only have to read charge design full once */
|
||||
if (di->charge_design_full <= 0)
|
||||
di->charge_design_full = bq27xxx_battery_read_dcap(di);
|
||||
}
|
||||
|
||||
if ((di->cache.capacity != cache.capacity) ||
|
||||
(di->cache.flags != cache.flags))
|
||||
(di->cache.flags != cache.flags) ||
|
||||
(di->last_status.intval != status.intval)) {
|
||||
di->last_status.intval = status.intval;
|
||||
power_supply_changed(di->bat);
|
||||
}
|
||||
|
||||
if (memcmp(&di->cache, &cache, sizeof(cache)) != 0)
|
||||
di->cache = cache;
|
||||
|
@ -2,6 +2,8 @@
|
||||
#ifndef __LINUX_BQ27X00_BATTERY_H__
|
||||
#define __LINUX_BQ27X00_BATTERY_H__
|
||||
|
||||
#include <linux/power_supply.h>
|
||||
|
||||
enum bq27xxx_chip {
|
||||
BQ27000 = 1, /* bq27000, bq27200 */
|
||||
BQ27010, /* bq27010, bq27210 */
|
||||
@ -70,6 +72,7 @@ struct bq27xxx_device_info {
|
||||
int charge_design_full;
|
||||
bool removed;
|
||||
unsigned long last_update;
|
||||
union power_supply_propval last_status;
|
||||
struct delayed_work work;
|
||||
struct power_supply *bat;
|
||||
struct list_head list;
|
||||
|
Loading…
Reference in New Issue
Block a user