Skip to content

Commit 939a116

Browse files
jwrdegoedesre
authored andcommitted
power: supply: bq27xxx: Ensure power_supply_changed() is called on current sign changes
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: 297a533 ("bq27x00: Cache battery registers") Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
1 parent ff4c4a2 commit 939a116

2 files changed

Lines changed: 15 additions & 1 deletion

File tree

drivers/power/supply/bq27xxx_battery.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1836,6 +1836,7 @@ static int bq27xxx_battery_current_and_status(
18361836

18371837
static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
18381838
{
1839+
union power_supply_propval status = di->last_status;
18391840
struct bq27xxx_reg_cache cache = {0, };
18401841
bool has_singe_flag = di->opts & BQ27XXX_O_ZERO;
18411842

@@ -1860,14 +1861,24 @@ static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
18601861
if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR)
18611862
cache.cycle_count = bq27xxx_battery_read_cyct(di);
18621863

1864+
/*
1865+
* On gauges with signed current reporting the current must be
1866+
* checked to detect charging <-> discharging status changes.
1867+
*/
1868+
if (!(di->opts & BQ27XXX_O_ZERO))
1869+
bq27xxx_battery_current_and_status(di, NULL, &status, &cache);
1870+
18631871
/* We only have to read charge design full once */
18641872
if (di->charge_design_full <= 0)
18651873
di->charge_design_full = bq27xxx_battery_read_dcap(di);
18661874
}
18671875

18681876
if ((di->cache.capacity != cache.capacity) ||
1869-
(di->cache.flags != cache.flags))
1877+
(di->cache.flags != cache.flags) ||
1878+
(di->last_status.intval != status.intval)) {
1879+
di->last_status.intval = status.intval;
18701880
power_supply_changed(di->bat);
1881+
}
18711882

18721883
if (memcmp(&di->cache, &cache, sizeof(cache)) != 0)
18731884
di->cache = cache;

include/linux/power/bq27xxx_battery.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#ifndef __LINUX_BQ27X00_BATTERY_H__
33
#define __LINUX_BQ27X00_BATTERY_H__
44

5+
#include <linux/power_supply.h>
6+
57
enum bq27xxx_chip {
68
BQ27000 = 1, /* bq27000, bq27200 */
79
BQ27010, /* bq27010, bq27210 */
@@ -70,6 +72,7 @@ struct bq27xxx_device_info {
7072
int charge_design_full;
7173
bool removed;
7274
unsigned long last_update;
75+
union power_supply_propval last_status;
7376
struct delayed_work work;
7477
struct power_supply *bat;
7578
struct list_head list;

0 commit comments

Comments
 (0)