max1720x_battery: impedance and activation impedance
Cleanup in reading of resistance, impedance and activation impedance to
support google_resistance metric for BHI.
Bug: 223759710
Signed-off-by: AleX Pelosi <[email protected]>
Change-Id: Iea686c164e7c02b74fa9514363dc36b16d945cd2
diff --git a/max1720x_battery.c b/max1720x_battery.c
index e44e252..2b0558e 100644
--- a/max1720x_battery.c
+++ b/max1720x_battery.c
@@ -64,7 +64,7 @@
#define BHI_IMPEDANCE_SOC_HI 55
#define BHI_IMPEDANCE_TEMP_LO 250
#define BHI_IMPEDANCE_TEMP_HI 300
-#define BHI_IMPEDANCE_CYCLE_CNT 10
+#define BHI_IMPEDANCE_CYCLE_CNT 5
#define BHI_IMPEDANCE_TIMERH 50 /* 7*24 / 3.2hr */
#include "max1720x.h"
@@ -951,6 +951,49 @@
return count;
}
+
+
+
+/* resistance and impedance ------------------------------------------------ */
+
+static int max17x0x_read_resistance_avg(struct max1720x_chip *chip)
+{
+ u16 ravg;
+ int ret = 0;
+
+ ret = gbms_storage_read(GBMS_TAG_RAVG, &ravg, sizeof(ravg));
+ if (ret < 0)
+ return ret;
+
+ return reg_to_resistance_micro_ohms(ravg, chip->RSense);
+}
+
+static int max17x0x_read_resistance_raw(struct max1720x_chip *chip)
+{
+ u16 data;
+ int ret;
+
+ ret = REGMAP_READ(&chip->regmap, MAX1720X_RCELL, &data);
+ if (ret < 0)
+ return ret;
+
+ return data;
+}
+
+static int max17x0x_read_resistance(struct max1720x_chip *chip)
+{
+ int rslow;
+
+ rslow = max17x0x_read_resistance_raw(chip);
+ if (rslow < 0)
+ return rslow;
+
+ return reg_to_resistance_micro_ohms(rslow, chip->RSense);
+}
+
+
+/* ----------------------------------------------------------------------- */
+
static DEVICE_ATTR(m5_model_state, 0640, max1720x_model_show_state,
max1720x_model_set_state);
@@ -994,16 +1037,8 @@
{
struct power_supply *psy = container_of(dev, struct power_supply, dev);
struct max1720x_chip *chip = power_supply_get_drvdata(psy);
- struct max17x0x_regmap *map = &chip->regmap;
- u16 data = 0;
- int err;
- err = REGMAP_READ(map, MAX1720X_RCELL, &data);
- if (err < 0)
- return err;
-
- return scnprintf(buff, PAGE_SIZE, "%d\n",
- reg_to_resistance_micro_ohms(data, chip->RSense));
+ return scnprintf(buff, PAGE_SIZE, "%d\n", max17x0x_read_resistance(chip));
}
static const DEVICE_ATTR_RO(resistance);
@@ -1235,13 +1270,13 @@
int current_qh, nvram_qh;
u16 data = 0, nvram_capacity;
+ /* not available without shadow */
if (!chip->regmap_nvram.regmap) {
max1720x_prime_battery_qh_capacity(chip,
POWER_SUPPLY_STATUS_UNKNOWN);
return;
}
-
/* Capacity data is stored as complement so it will not be zero. Using
* zero case to detect new un-primed pack
*/
@@ -1829,7 +1864,46 @@
return 0;
}
+/* call holding chip->model_lock */
+static int max1720x_check_impedance(struct max1720x_chip *chip, u16 *th)
+{
+ struct max17x0x_regmap *map = &chip->regmap;
+ int soc, temp, cycle_count, ret;
+ u16 data, timerh;
+
+ if (!chip->model_state_valid)
+ return -EAGAIN;
+
+ soc = max1720x_get_battery_soc(chip);
+ if (soc < BHI_IMPEDANCE_SOC_LO || soc > BHI_IMPEDANCE_SOC_HI)
+ return -EAGAIN;
+
+ ret = max17x0x_reg_read(map, MAX17X0X_TAG_temp, &data);
+ if (ret < 0)
+ return -EIO;
+
+ temp = reg_to_deci_deg_cel(data);
+ if (temp < BHI_IMPEDANCE_TEMP_LO || temp > BHI_IMPEDANCE_TEMP_HI)
+ return -EAGAIN;
+
+ cycle_count = max1720x_get_cycle_count(chip);
+ if (cycle_count < 0)
+ return -EINVAL;
+
+ ret = REGMAP_READ(&chip->regmap, MAX1720X_TIMERH, &timerh);
+ if (ret < 0 || timerh == 0)
+ return -EINVAL;
+
+ /* wait for a few cyles and time in field before validating the value */
+ if (cycle_count < BHI_IMPEDANCE_CYCLE_CNT || timerh < BHI_IMPEDANCE_TIMERH)
+ return -ENODATA;
+
+ *th = timerh;
+ return 0;
+}
+
/* ------------------------------------------------------------------------- */
+
#define SEL_RES_AVG 0
#define SEL_RES_FILTER_COUNT 1
static int batt_res_registers(struct max1720x_chip *chip, bool bread,
@@ -1878,58 +1952,23 @@
return err;
}
-/* call holding chip->model_lock */
-static int max1720x_check_impedance(struct max1720x_chip *chip, u16 *th)
+static int max1720x_health_write_ai(u16 act_impedance, u16 act_timerh)
{
- struct max17x0x_regmap *map = &chip->regmap;
- int soc, temp, cycle_count, ret;
- u16 data, timerh;
-
- if (!chip->model_state_valid)
- return -EAGAIN;
-
- soc = max1720x_get_battery_soc(chip);
- if (soc < BHI_IMPEDANCE_SOC_LO || soc > BHI_IMPEDANCE_SOC_HI)
- return -ENODATA;
-
- ret = max17x0x_reg_read(map, MAX17X0X_TAG_temp, &data);
- if (ret < 0)
- return -EINVAL;
-
- temp = reg_to_deci_deg_cel(data);
- if (temp < BHI_IMPEDANCE_TEMP_LO || temp > BHI_IMPEDANCE_TEMP_HI)
- return -ENODATA;
-
- ret = REGMAP_READ(&chip->regmap, MAX1720X_TIMERH, &timerh);
- if (ret < 0 || timerh == 0)
- return -ENODATA;
-
- cycle_count = max1720x_get_cycle_count(chip);
- if (cycle_count < 0)
- return -EINVAL;
-
- /* wait for a few cyles and time in field before validating the value */
- if (cycle_count < BHI_IMPEDANCE_CYCLE_CNT || timerh < BHI_IMPEDANCE_TIMERH)
- return -ENODATA;
-
- *th = timerh;
- return 0;
-}
-
-static int max17x0x_read_resistance(struct max1720x_chip *chip)
-{
- u16 data;
int ret;
- ret = REGMAP_READ(&chip->regmap, MAX1720X_RCELL, &data);
+ ret = gbms_storage_write(GBMS_TAG_ACIM, &act_impedance, sizeof(act_impedance));
if (ret < 0)
- return ret;
+ return -EIO;
- return reg_to_resistance_micro_ohms(data, chip->RSense);
+ ret = gbms_storage_write(GBMS_TAG_THAS, &act_timerh, sizeof(act_timerh));
+ if (ret < 0)
+ return -EIO;
+
+ return ret;
}
/* will return error if the value is not valid */
-static int max1720x_get_health_act_impedance(struct max1720x_chip *chip)
+static int max1720x_health_get_ai(struct max1720x_chip *chip)
{
u16 act_impedance, act_timerh;
int ret;
@@ -1946,42 +1985,35 @@
if (ret < 0)
return -EIO;
- pr_debug("%s: act_impedance=%d act_timerh=%d\n", __func__,
- act_impedance, act_timerh);
-
- /* need to get sstating impedance */
+ /* need to get starting impedance (if qualified) */
if (act_impedance == 0xffff || act_timerh == 0xffff) {
- int resistance;
-
ret = max1720x_check_impedance(chip, &act_timerh);
if (ret < 0)
- return -EINVAL;
+ return ret;
- resistance = max17x0x_read_resistance(chip);
- if (resistance < 0)
- return -EIO;
- act_impedance = resistance;
-
- ret = gbms_storage_write(GBMS_TAG_ACIM, &act_impedance, sizeof(act_impedance));
+ ret = REGMAP_READ(&chip->regmap, MAX1720X_RCELL, &act_impedance);
if (ret < 0)
return -EIO;
- ret = gbms_storage_write(GBMS_TAG_THAS, &act_timerh, sizeof(act_timerh));
+ ret = max1720x_health_write_ai(act_impedance, act_timerh);
if (ret < 0)
return -EIO;
}
- /* TODO: scale act_impedance with timerh OR invalidate it */
- chip->bhi_acim = act_impedance;
+ /* not zero, not negative */
+ chip->bhi_acim = reg_to_resistance_micro_ohms(act_impedance, chip->RSense);;
- pr_info("%s: act_impedance=%d act_timerh=%d\n", __func__,
- act_impedance, act_timerh);
+ /* TODO: corrrect impedance with timerh */
+
+
+ pr_info("%s: chip->bhi_acim =%d act_impedance=%x act_timerh=%x\n",
+ __func__, chip->bhi_acim, act_impedance, act_timerh);
return chip->bhi_acim;
}
/* will return negative if the value is not qualified */
-static int max1720x_get_health_impedance(struct max1720x_chip *chip)
+static int max1720x_health_read_impedance(struct max1720x_chip *chip)
{
u16 timerh;
int ret;
@@ -1993,6 +2025,7 @@
return max17x0x_read_resistance(chip);
}
+/* in hours (3.2 hours resolution) */
static int max1720x_get_age(struct max1720x_chip *chip)
{
u16 timerh;
@@ -2230,10 +2263,19 @@
val->strval = chip->serial_number;
break;
case GBMS_PROP_HEALTH_ACT_IMPEDANCE:
- val->intval = max1720x_get_health_act_impedance(chip);
+ val->intval = max1720x_health_get_ai(chip);
break;
case GBMS_PROP_HEALTH_IMPEDANCE:
- val->intval = max1720x_get_health_impedance(chip);
+ val->intval = max1720x_health_read_impedance(chip);
+ break;
+ case GBMS_PROP_RESISTANCE:
+ val->intval = max17x0x_read_resistance(chip);
+ break;
+ case GBMS_PROP_RESISTANCE_RAW:
+ val->intval = max17x0x_read_resistance_raw(chip);
+ break;
+ case GBMS_PROP_RESISTANCE_AVG:
+ val->intval = max17x0x_read_resistance_avg(chip);
break;
case GBMS_PROP_BATTERY_AGE:
val->intval = max1720x_get_age(chip);
@@ -3708,9 +3750,69 @@
* break;
*/
-static int max17x0x_init_debugfs(struct max1720x_chip *chip)
+static ssize_t act_impedance_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count) {
+ struct power_supply *psy = container_of(dev, struct power_supply, dev);
+ struct max1720x_chip *chip = power_supply_get_drvdata(psy);
+ unsigned int rcell = 0xffff;
+ u16 timerh = 0xffff;
+ int value, ret = 0;
+
+ ret = kstrtoint(buf, 0, &value);
+ if (ret < 0)
+ return ret;
+
+ mutex_lock(&chip->model_lock);
+
+ if (value) {
+
+ /* mOhms to reg*/
+ rcell = (value * 4096) / (1000 * chip->RSense);
+ if (rcell > 0xffff) {
+ pr_info("value=%d, rcell=%d out of bounds\n", value, rcell);
+ mutex_unlock(&chip->model_lock);
+ return -ERANGE;
+ }
+
+ ret = REGMAP_READ(&chip->regmap, MAX1720X_TIMERH, &timerh);
+ if (ret < 0 || timerh == 0) {
+ mutex_unlock(&chip->model_lock);
+ return -EIO;
+ }
+ }
+
+ ret = max1720x_health_write_ai(rcell, timerh);
+ if (ret == 0)
+ chip->bhi_acim = 0;
+
+ pr_info("value=%d act_impedance=%x timerh=%x (%d)\n",
+ value, rcell, timerh, ret);
+
+ mutex_unlock(&chip->model_lock);
+ return count;
+}
+
+static ssize_t act_impedance_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct power_supply *psy = container_of(dev, struct power_supply, dev);
+ struct max1720x_chip *chip = power_supply_get_drvdata(psy);
+
+ return scnprintf(buf, PAGE_SIZE, "%d\n", max1720x_health_get_ai(chip));
+}
+
+static const DEVICE_ATTR_RW(act_impedance);
+
+static int max17x0x_init_sysfs(struct max1720x_chip *chip)
{
struct dentry *de;
+ int ret;
+
+ /* stats */
+ ret = device_create_file(&chip->psy->dev, &dev_attr_act_impedance);
+ if (ret)
+ dev_err(&chip->psy->dev, "Failed to create act_impedance\n");
de = debugfs_create_dir(chip->max1720x_psy_desc.name, 0);
if (IS_ERR_OR_NULL(de))
@@ -5000,7 +5102,7 @@
ret = reg->size;
break;
- /* Was POWER_SUPPLY_PROP_RESISTANCE_AVG */
+ /* RAVG: was POWER_SUPPLY_PROP_RESISTANCE_AVG, TODO: merge with EEPROM */
case GBMS_TAG_RAVG:
if (size != sizeof(u16))
return -ERANGE;
@@ -5011,7 +5113,7 @@
*(u16 *)buff = -1;
return 0;
- /* Was POWER_SUPPLY_PROP_RES_FILTER_COUNT */
+ /* RAVG: was POWER_SUPPLY_PROP_RES_FILTER_COUNT, TODO: merge with EEPROM */
case GBMS_TAG_RFCN:
if (size != sizeof(u16))
return -ERANGE;
@@ -5056,14 +5158,13 @@
return -ERANGE;
break;
- /* Was POWER_SUPPLY_PROP_RESISTANCE_AVG */
+ /* RAVG: Was POWER_SUPPLY_PROP_RESISTANCE_AVG, TODO: merge with EEPROM */
case GBMS_TAG_RAVG:
if (size != sizeof(u16))
return -ERANGE;
return batt_res_registers(chip, false, SEL_RES_AVG,
(u16 *)buff);
-
- /* Was POWER_SUPPLY_PROP_RES_FILTER_COUNT */
+ /* RAVG: Was POWER_SUPPLY_PROP_RES_FILTER_COUNT, TODO: merge with EEPROM */
case GBMS_TAG_RFCN:
if (size != sizeof(u16))
return -ERANGE;
@@ -5092,6 +5193,7 @@
return ret;
}
+/* when without eeprom */
static struct gbms_storage_desc max17x0x_storage_dsc = {
.info = max17x0x_storage_info,
.iter = max17x0x_storage_iter,
@@ -5104,8 +5206,7 @@
static int max17x0x_prop_iter(int index, gbms_tag_t *tag, void *ptr)
{
- static gbms_tag_t keys[] = {GBMS_TAG_BRES, GBMS_TAG_GCFE,
- GBMS_TAG_CLHI};
+ static gbms_tag_t keys[] = {GBMS_TAG_CLHI};
const int count = ARRAY_SIZE(keys);
if (index >= 0 && index < count) {
@@ -5121,33 +5222,8 @@
{
struct max1720x_chip *chip = (struct max1720x_chip *)ptr;
int ret = -ENOENT;
- u16 data;
switch (tag) {
- /* Was POWER_SUPPLY_PROP_RESISTANCE */
- case GBMS_TAG_BRES:
- if (size != sizeof(u32))
- return -ERANGE;
-
- ret = REGMAP_READ(&chip->regmap, MAX1720X_RCELL, &data);
- if (ret < 0)
- return ret;
-
- *(u32 *)buff = reg_to_resistance_micro_ohms(data, chip->RSense);
- break;
-
- /* Was POWER_SUPPLY_PROP_CHARGE_FULL_ESTIMATE */
- case GBMS_TAG_GCFE:
- if (size != sizeof(u16))
- return -ERANGE;
-
- ret = batt_ce_full_estimate(&chip->cap_estimate);
- if (ret < 0)
- return ret;
-
- *(u16 *)buff = ret & 0xffff;
- break;
-
case GBMS_TAG_CLHI:
ret = max17x0x_collect_history_data(buff, size, chip);
break;
@@ -5229,7 +5305,8 @@
chip->resume_complete = true;
chip->init_complete = true;
chip->bhi_acim = 0;
- max17x0x_init_debugfs(chip);
+
+ max17x0x_init_sysfs(chip);
/*
* Handle any IRQ that might have been set before init
@@ -5566,7 +5643,6 @@
* TODO:
* POWER_SUPPLY_PROP_CHARGE_FULL_ESTIMATE -> GBMS_TAG_GCFE
* POWER_SUPPLY_PROP_RES_FILTER_COUNT -> GBMS_TAG_RFCN
- * POWER_SUPPLY_PROP_RESISTANCE_AVG -> GBMS_TAG_RAVG
*/
/* M5 battery model needs batt_id and is setup during init() */