[PATCH] power: supply: bq27xxx: Introduce parameter to config cache regs

From: Hermes Zhang
Date: Mon Feb 19 2024 - 05:06:41 EST


Since all of the regs in the bq27xxx_reg_cache are now cached, a simple
property read (such as temperature) will need nine I2C transmissions.
Introduce a new module parameter to enable the reg cache to be configured,
which decrease the amount of unnecessary I2C transmission and preventing
the error -16 (EBUSY) happen when working on an I2C bus that is shared by
many devices.

Signed-off-by: Hermes Zhang <Hermes.Zhang@xxxxxxxx>
---
drivers/power/supply/bq27xxx_battery.c | 65 +++++++++++++++++++-------
include/linux/power/bq27xxx_battery.h | 9 ++++
2 files changed, 58 insertions(+), 16 deletions(-)

diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c
index 1c4a9d137744..45fd956ec961 100644
--- a/drivers/power/supply/bq27xxx_battery.c
+++ b/drivers/power/supply/bq27xxx_battery.c
@@ -1100,6 +1100,11 @@ module_param_cb(poll_interval, &param_ops_poll_interval, &poll_interval, 0644);
MODULE_PARM_DESC(poll_interval,
"battery poll interval in seconds - 0 disables polling");

+static unsigned int bq27xxx_cache_mask = 0xFF;
+module_param(bq27xxx_cache_mask, uint, 0644);
+MODULE_PARM_DESC(bq27xxx_cache_mask,
+ "mask for bq27xxx reg cache - 0 disables reg cache");
+
/*
* Common code for BQ27xxx devices
*/
@@ -1842,21 +1847,29 @@ static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di)
if ((cache.flags & 0xff) == 0xff)
cache.flags = -1; /* read error */
if (cache.flags >= 0) {
- cache.temperature = bq27xxx_battery_read_temperature(di);
- if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR)
+ if (bq27xxx_cache_mask & BQ27XXX_CACHE_TEMP)
+ cache.temperature = bq27xxx_battery_read_temperature(di);
+ if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR &&
+ bq27xxx_cache_mask & BQ27XXX_CACHE_TTE)
cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE);
- if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR)
+ if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR &&
+ bq27xxx_cache_mask & BQ27XXX_CACHE_TTECP)
cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP);
- if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR)
+ if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR &&
+ bq27xxx_cache_mask & BQ27XXX_CACHE_TTF)
cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF);

- cache.charge_full = bq27xxx_battery_read_fcc(di);
- cache.capacity = bq27xxx_battery_read_soc(di);
- if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR)
+ if (bq27xxx_cache_mask & BQ27XXX_CACHE_CHARGE_FULL)
+ cache.charge_full = bq27xxx_battery_read_fcc(di);
+ if (bq27xxx_cache_mask & BQ27XXX_CACHE_CAPACITY)
+ cache.capacity = bq27xxx_battery_read_soc(di);
+ if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR &&
+ bq27xxx_cache_mask & BQ27XXX_CACHE_ENERGY)
cache.energy = bq27xxx_battery_read_energy(di);
di->cache.flags = cache.flags;
cache.health = bq27xxx_battery_read_health(di);
- if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR)
+ if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR &&
+ bq27xxx_cache_mask & BQ27XXX_CACHE_CYCT)
cache.cycle_count = bq27xxx_battery_read_cyct(di);

/*
@@ -2004,6 +2017,7 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
{
int ret = 0;
struct bq27xxx_device_info *di = power_supply_get_drvdata(psy);
+ int tmp;

mutex_lock(&di->lock);
if (time_is_before_jiffies(di->last_update + 5 * HZ))
@@ -2027,24 +2041,37 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
ret = bq27xxx_battery_current_and_status(di, val, NULL, NULL);
break;
case POWER_SUPPLY_PROP_CAPACITY:
- ret = bq27xxx_simple_value(di->cache.capacity, val);
+ tmp = bq27xxx_cache_mask & BQ27XXX_CACHE_CAPACITY ?
+ di->cache.capacity : bq27xxx_battery_read_soc(di);
+ ret = bq27xxx_simple_value(tmp, val);
break;
case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
ret = bq27xxx_battery_capacity_level(di, val);
break;
case POWER_SUPPLY_PROP_TEMP:
- ret = bq27xxx_simple_value(di->cache.temperature, val);
+ tmp = bq27xxx_cache_mask & BQ27XXX_CACHE_TEMP ?
+ di->cache.temperature : bq27xxx_battery_read_temperature(di);
+ ret = bq27xxx_simple_value(tmp, val);
if (ret == 0)
val->intval -= 2731; /* convert decidegree k to c */
break;
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
- ret = bq27xxx_simple_value(di->cache.time_to_empty, val);
+ tmp = bq27xxx_cache_mask & BQ27XXX_CACHE_TTE ?
+ di->cache.time_to_empty :
+ bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE);
+ ret = bq27xxx_simple_value(tmp, val);
break;
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
- ret = bq27xxx_simple_value(di->cache.time_to_empty_avg, val);
+ tmp = bq27xxx_cache_mask & BQ27XXX_CACHE_TTECP ?
+ di->cache.time_to_empty_avg :
+ bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP);
+ ret = bq27xxx_simple_value(tmp, val);
break;
case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
- ret = bq27xxx_simple_value(di->cache.time_to_full, val);
+ tmp = bq27xxx_cache_mask & BQ27XXX_CACHE_TTF ?
+ di->cache.time_to_full :
+ bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF);
+ ret = bq27xxx_simple_value(tmp, val);
break;
case POWER_SUPPLY_PROP_TECHNOLOGY:
if (di->opts & BQ27XXX_O_MUL_CHEM)
@@ -2059,7 +2086,9 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
ret = bq27xxx_simple_value(bq27xxx_battery_read_rc(di), val);
break;
case POWER_SUPPLY_PROP_CHARGE_FULL:
- ret = bq27xxx_simple_value(di->cache.charge_full, val);
+ tmp = bq27xxx_cache_mask & BQ27XXX_CACHE_CHARGE_FULL ?
+ di->cache.charge_full : bq27xxx_battery_read_fcc(di);
+ ret = bq27xxx_simple_value(tmp, val);
break;
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
ret = bq27xxx_simple_value(di->charge_design_full, val);
@@ -2072,10 +2101,14 @@ static int bq27xxx_battery_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
return -EINVAL;
case POWER_SUPPLY_PROP_CYCLE_COUNT:
- ret = bq27xxx_simple_value(di->cache.cycle_count, val);
+ tmp = bq27xxx_cache_mask & BQ27XXX_CACHE_CYCT ?
+ di->cache.cycle_count : bq27xxx_battery_read_cyct(di);
+ ret = bq27xxx_simple_value(tmp, val);
break;
case POWER_SUPPLY_PROP_ENERGY_NOW:
- ret = bq27xxx_simple_value(di->cache.energy, val);
+ tmp = bq27xxx_cache_mask & BQ27XXX_CACHE_ENERGY ?
+ di->cache.energy : bq27xxx_battery_read_energy(di);
+ ret = bq27xxx_simple_value(tmp, val);
break;
case POWER_SUPPLY_PROP_POWER_AVG:
ret = bq27xxx_battery_pwr_avg(di, val);
diff --git a/include/linux/power/bq27xxx_battery.h b/include/linux/power/bq27xxx_battery.h
index 7d8025fb74b7..29d1e7107ee2 100644
--- a/include/linux/power/bq27xxx_battery.h
+++ b/include/linux/power/bq27xxx_battery.h
@@ -4,6 +4,15 @@

#include <linux/power_supply.h>

+#define BQ27XXX_CACHE_TEMP (1 << 0)
+#define BQ27XXX_CACHE_TTE (1 << 1)
+#define BQ27XXX_CACHE_TTECP (1 << 2)
+#define BQ27XXX_CACHE_TTF (1 << 3)
+#define BQ27XXX_CACHE_CHARGE_FULL (1 << 4)
+#define BQ27XXX_CACHE_CYCT (1 << 5)
+#define BQ27XXX_CACHE_CAPACITY (1 << 6)
+#define BQ27XXX_CACHE_ENERGY (1 << 7)
+
enum bq27xxx_chip {
BQ27000 = 1, /* bq27000, bq27200 */
BQ27010, /* bq27010, bq27210 */
--
2.39.2