max_m5: add support for TaskPeriod for RC2
Add support for TaskPeriod register (0x3c) and enable RC2.
Bug: 174788070
Test: Boot, check model load
Signed-off-by: AleX Pelosi <[email protected]>
Change-Id: Iaff1824f1516240b35a9b26b9877016638ed47db
diff --git a/max1720x_battery.c b/max1720x_battery.c
index 7eaaeaa..a380495 100644
--- a/max1720x_battery.c
+++ b/max1720x_battery.c
@@ -503,6 +503,27 @@
return (val & 0x7F) * 40;
}
+/* b/177099997 TaskPeriod ----------------------------------------------- */
+
+static inline int reg_to_capacity_uah(u16 val, struct max1720x_chip *chip)
+{
+ const int lsb = max_m5_cap_lsb(chip->model_data);
+
+ return reg_to_micro_amp_h(val, chip->RSense) * lsb;
+}
+
+#if 0
+/* TODO: will need in outliers */
+static inline int capacity_uah_to_reg(int capacity, struct max1720x_chip *chip)
+{
+ const int lsb = max_m5_cap_lsb(chip->model_data);
+
+ return micro_amp_h_to_reg(capacity / lsb, chip->RSense);
+}
+#endif
+
+/* log ----------------------------------------------------------------- */
+
static void max1730x_read_log_write_status(struct max1720x_chip *chip,
u16 *buffer)
{
@@ -832,8 +853,8 @@
*/
static void max1720x_model_reload(struct max1720x_chip *chip, bool force)
{
- const bool pending = chip->model_reload == MAX_M5_LOAD_MODEL_REQUEST;
const bool disabled = chip->model_reload == MAX_M5_LOAD_MODEL_DISABLED;
+ const bool pending = chip->model_reload != MAX_M5_LOAD_MODEL_IDLE;
pr_debug("model_reload=%d force=%d pending=%d disabled=%d\n",
chip->model_reload, force, pending, disabled);
@@ -842,7 +863,12 @@
return;
/* REQUEST -> IDLE or set to the number of retries */
- dev_info(chip->dev, "Reload FG Model for ID=%d\n", chip->batt_id);
+ dev_info(chip->dev, "Schedule Load FG Model, ID=%d, %d->%d cap_lsb=%d\n",
+ chip->batt_id,
+ max_m5_model_read_version(chip->model_data),
+ max_m5_fg_model_version(chip->model_data),
+ max_m5_cap_lsb(chip->model_data));
+
chip->model_reload = MAX_M5_LOAD_MODEL_REQUEST;
chip->model_ok = false;
mod_delayed_work(system_wq, &chip->model_work, 0);
@@ -1636,8 +1662,7 @@
if (err < 0)
break;
- val->intval = reg_to_micro_amp_h(chip->current_capacity,
- chip->RSense);
+ val->intval = reg_to_capacity_uah(chip->current_capacity, chip);
break;
case POWER_SUPPLY_PROP_CHARGE_FULL:
/*
@@ -1656,12 +1681,12 @@
err = REGMAP_READ(map, MAX1720X_FULLCAPNOM, &data);
if (err == 0)
- val->intval = reg_to_micro_amp_h(data, chip->RSense);
+ val->intval = reg_to_capacity_uah(data, chip);
break;
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
err = REGMAP_READ(map, MAX1720X_DESIGNCAP, &data);
if (err == 0)
- val->intval = reg_to_micro_amp_h(data, chip->RSense);
+ val->intval = reg_to_capacity_uah(data, chip);
break;
/* current is positive value when flowing to device */
case POWER_SUPPLY_PROP_CURRENT_AVG:
@@ -2184,13 +2209,13 @@
return 0;
}
+/* */
static struct device_node *max1720x_find_batt_node(struct max1720x_chip *chip)
{
const int batt_id = chip->batt_id;
const struct device *dev = chip->dev;
- const int algo_ver = chip->drift_data.algo_ver;
struct device_node *config_node, *child_node;
- u32 batt_id_range = 20, algo = 0, batt_id_kohm;
+ u32 batt_id_range = 20, batt_id_kohm;
int ret;
config_node = of_find_node_by_name(dev->of_node, "maxim,config");
@@ -2205,17 +2230,22 @@
dev_warn(dev, "failed to read maxim,batt-id-range-pct\n");
for_each_child_of_node(config_node, child_node) {
- ret = of_property_read_u32(child_node, "maxim,fg-algo", &algo);
- if (ret < 0)
- algo = 0;
- if (algo_ver != algo)
- continue;
-
ret = of_property_read_u32(child_node, "maxim,batt-id-kohm",
&batt_id_kohm);
if (ret != 0)
continue;
+ /* only look for matching algo_ver if set */
+ if (chip->drift_data.algo_ver != MAX1720X_DA_VER_NONE) {
+ u32 algo_ver;
+
+ ret = of_property_read_u32(child_node,
+ "maxim,algo-version",
+ &algo_ver);
+ if (ret == 0 && chip->drift_data.algo_ver != algo_ver)
+ continue;
+ }
+
if (!batt_id_range && batt_id == batt_id_kohm)
return child_node;
if ((batt_id < (batt_id_kohm * (100 + batt_id_range) / 100)) &&
@@ -2690,8 +2720,9 @@
/* ->batt_id negative for no lookup */
if (chip->batt_id >= 0) {
chip->batt_node = max1720x_find_batt_node(chip);
- pr_debug("node found=%d for ID=%d\n", !!chip->batt_node,
- chip->batt_id);
+ pr_debug("node found=%d for ID=%d algo=%d\n",
+ !!chip->batt_node, chip->batt_id,
+ chip->drift_data.algo_ver);
}
/* TODO: split allocation and initialization */
@@ -2702,11 +2733,23 @@
return PTR_ERR(model_data);
chip->model_data = model_data;
+
if (!chip->batt_node) {
- dev_warn(chip->dev, "No child node for ID=%d\n", chip->batt_id);
+ dev_warn(chip->dev, "No child node for ID=%d, algo=%d\n",
+ chip->batt_id, chip->drift_data.algo_ver);
chip->model_reload = MAX_M5_LOAD_MODEL_DISABLED;
} else {
- pr_debug("model_data ok for ID=%d", chip->batt_id);
+ u32 data32;
+ int rc;
+
+ /* align algo_ver for capacity drift to model */
+ rc = of_property_read_u32(chip->batt_node, "maxim,algo-version",
+ &data32);
+ if (rc == 0)
+ chip->drift_data.algo_ver = data32;
+
+ pr_debug("model_data ok for ID=%d, algo=%d\n",
+ chip->batt_id, chip->drift_data.algo_ver);
chip->model_reload = MAX_M5_LOAD_MODEL_IDLE;
}
@@ -3165,8 +3208,7 @@
/* failure on the gauge: retry as long as model_reload > IDLE */
ret = max_m5_load_gauge_model(chip->model_data);
if (ret < 0) {
- dev_err(chip->dev, "%s: Load Gauge Model Failed rc=%d\n",
- __func__, ret);
+ dev_err(chip->dev, "Load Gauge Model Failed ret=%d\n", ret);
return -EAGAIN;
}
@@ -3208,8 +3250,8 @@
if (rc == 0) {
rc = max1720x_clear_por(chip);
- dev_info(chip->dev, "%s Power-On Reset clear (%d)\n",
- __func__, rc);
+ dev_info(chip->dev, "Model OK, Clear Power-On Reset (%d)\n",
+ rc);
/* TODO: keep trying to clear POR if the above fail */
chip->model_reload = MAX_M5_LOAD_MODEL_IDLE;
@@ -3218,7 +3260,7 @@
} else if (rc != -EAGAIN) {
chip->model_reload = MAX_M5_LOAD_MODEL_DISABLED;
chip->model_ok = false;
- } else {
+ } else if (chip->model_reload > MAX_M5_LOAD_MODEL_IDLE) {
chip->model_reload -= 1;
}
}
@@ -3241,8 +3283,13 @@
schedule_delayed_work(&chip->model_work, delay);
}
- if (new_model)
+ if (new_model) {
+ dev_info(chip->dev, "FG Model OK, ver=%d cap_lsb=%d next_update=%d\n",
+ max_m5_fg_model_version(chip->model_data),
+ max_m5_cap_lsb(chip->model_data),
+ chip->model_next_update);
power_supply_changed(chip->psy);
+ }
mutex_unlock(&chip->model_lock);
}
@@ -3261,7 +3308,7 @@
return of_property_read_u32(chip->dev->of_node, property, data32);
}
-/* capacity outliers, capacity drift */
+/* fix capacity drift after loading the model */
static int max17201_init_fix_capacity(struct max1720x_chip *chip)
{
struct max1720x_drift_data *ddata = &chip->drift_data;
@@ -3287,7 +3334,7 @@
/* device dependent values */
ddata->rsense = chip->RSense;
-
+ /* update design_capacity after loading the model if not set in dt */
ret = of_property_read_u32(chip->dev->of_node, "maxim,capacity-design",
&data32);
if (ret < 0) {
@@ -3348,20 +3395,24 @@
ddata->cycle_band = BATTERY_MAX_CYCLE_BAND;
}
- ret = of_property_read_u32(chip->dev->of_node, "maxim,algo-version",
- &data32);
- if (ret < 0)
+ /*
+ * Set to force loading the model with corresponding algo-version.
+ * MW A0+ MW-A0 should use MAX1720X_DA_VER_ORIG while and MW-A1 should
+ * use MAX1720X_DA_VER_MWA1 for RC1 or MAX1720X_DA_VER_NONE for RC2.
+ * MW-A2 should use MAX1720X_DA_VER_NONE for RC1 and RC2.
+ * Not used for max1720x and max1730x.
+ */
+ if (max_m5_check_devname(chip->devname) ) {
+ ret = of_property_read_u32(chip->dev->of_node,
+ "maxim,algo-version",
+ &data32);
+ if (ret < 0 || data32 > MAX1720X_DA_VER_MWA2)
+ ddata->algo_ver = MAX1720X_DA_VER_NONE;
+ else
+ ddata->algo_ver = data32;
+ } else {
ddata->algo_ver = MAX1720X_DA_VER_ORIG;
- else if (data32 < MAX1720X_DA_VER_NONE || data32 > MAX1720X_DA_VER_MWA2)
- ddata->algo_ver = MAX1720X_DA_VER_NONE;
- else
- ddata->algo_ver = MAX1720X_DA_VER_NONE;
-
- dev_info(chip->dev, "ver=%d rsns=%d cnts=%d,%d dc=%d cap_sta=%d cap_fad=%d rcomp0=0x%x tempco=0x%x\n",
- ddata->algo_ver, ddata->rsense,
- chip->comp_update_count, chip->dxacc_update_count,
- ddata->design_capacity, ddata->cycle_stable, ddata->cycle_fade,
- ddata->ini_rcomp0, ddata->ini_tempco);
+ }
ret = read_chip_property_u32(chip, "maxim,capacity-filtercfg", &data32);
if (ret < 0)
@@ -3369,8 +3420,9 @@
else
ddata->ini_filtercfg = data32;
- if (ddata->ini_filtercfg)
- dev_info(chip->dev, "ini_filtercfg=0x%x\n", ddata->ini_filtercfg);
+ if (ddata->ini_filtercfg != -1)
+ dev_info(chip->dev, "ini_filtercfg=0x%x\n",
+ ddata->ini_filtercfg);
return 0;
}
@@ -3445,7 +3497,7 @@
MAX1720X_NAGEFCCFG, 0);
}
- /* */
+ /* device dependent fixups to the registers */
if (chip->fixups_fn) {
ret = chip->fixups_fn(chip);
if (ret < 0) {
@@ -3470,9 +3522,38 @@
chip->batt_id);
}
- /* init model data, needs batt_id */
+ /* fuel gauge model needs to know the batt_id */
mutex_init(&chip->model_lock);
- max1720x_init_model(chip);
+
+ /*
+ * The behavior of the drift workaround changes with the capacity
+ * learning algo used in the part. Integrated FG might have
+ * configurable capacity learning.
+ */
+ ret = max17201_init_fix_capacity(chip);
+ if (ret < 0)
+ dev_err(chip->dev, "Capacity drift WAR not enabled(%d)\n", ret);
+ /*
+ * FG model is ony used for integrated FG (MW). Loading a model might
+ * change the capacity drift WAR algo_ver and design_capacity.
+ * NOTE: design_capacity used for drift might be updated after loading
+ * a FG model.
+ */
+ ret = max1720x_init_model(chip);
+ if (ret < 0)
+ dev_err(chip->dev, "Cannot init FG model (%d)\n", ret);
+
+ /* dump capacity drift fixup configuration only when enabled */
+ if (chip->drift_data.algo_ver != MAX1720X_DA_VER_NONE) {
+ struct max1720x_drift_data *ddata = &chip->drift_data;
+
+ dev_info(chip->dev, "ver=%d rsns=%d cnts=%d,%d dc=%d cap_sta=%d cap_fad=%d rcomp0=0x%x tempco=0x%x\n",
+ ddata->algo_ver, ddata->rsense,
+ chip->comp_update_count, chip->dxacc_update_count,
+ ddata->design_capacity, ddata->cycle_stable,
+ ddata->cycle_fade, ddata->ini_rcomp0,
+ ddata->ini_tempco);
+ }
/* not needed for FG with NVRAM */
ret = max17x0x_handle_dt_shadow_config(chip);
@@ -3510,7 +3591,7 @@
MAX1720X_STATUS_BI, 0x0);
}
- /* max_m5 load the model in the irq handler when por is set */
+ /* max_m5 triggers loading of the model in the irq handler on POR */
if (!por && chip->gauge_type == MAX_M5_GAUGE_TYPE) {
ret = max_m5_model_read_state(chip->model_data);
@@ -3518,9 +3599,17 @@
ret = max1720x_set_next_update(chip);
if (ret < 0) {
dev_err(chip->dev, "FG Model Error (%d)\n", ret);
+ } else if (!max_m5_fg_model_check_version(chip->model_data)) {
+
+ /* reload only when enabled */
+ if (chip->model_reload != MAX_M5_LOAD_MODEL_DISABLED)
+ max1720x_model_reload(chip, false);
} else {
- dev_info(chip->dev, "FG Model OK, next_update=%d\n",
+ dev_info(chip->dev, "FG Model OK, ver=%d cap_lsb=%d next_update=%d\n",
+ max_m5_model_read_version(chip->model_data),
+ max_m5_cap_lsb(chip->model_data),
chip->model_next_update);
+
chip->reg_prop_capacity_raw = MAX1720X_REPSOC;
chip->model_ok = true;
}
@@ -3533,11 +3622,6 @@
chip->reg_prop_capacity_raw = MAX1720X_REPSOC;
}
- /* Fix capacity drift b/134500876 */
- ret = max17201_init_fix_capacity(chip);
- if (ret < 0)
- dev_err(chip->dev, "Failed to initialize capacity fix (%d)\n",
- ret);
max1720x_restore_battery_qh_capacity(chip);
@@ -4201,13 +4285,6 @@
uint8_t buf[2] = { };
int ret, gauge_type;
- ret = of_property_read_u32(chip->dev->of_node, "maxim,gauge-type",
- &gauge_type);
- if (ret == 0) {
- dev_warn(chip->dev, "forced gauge type to %d\n", gauge_type);
- return gauge_type;
- }
-
/* some maxim IF-PMIC corrupt reads w/o Rs b/152373060 */
xfer[0].addr = chip->primary->addr;
xfer[0].flags = 0;
@@ -4223,9 +4300,20 @@
if (ret != 2)
return -EIO;
+ /* it might need devname later */
chip->devname = buf[1] << 8 | buf[0];
- if (!chip->devname)
- return -ENODEV;
+
+ ret = of_property_read_u32(chip->dev->of_node, "maxim,gauge-type",
+ &gauge_type);
+ if (ret == 0) {
+ dev_warn(chip->dev, "forced gauge type to %d\n", gauge_type);
+ return gauge_type;
+ }
+
+ /* 0 not M5, !=0 M5 */
+ ret = max_m5_check_devname(chip->devname);
+ if (ret)
+ return MAX_M5_GAUGE_TYPE;
switch (chip->devname >> 4) {
case 0x404: /* max1730x sample */
@@ -4233,13 +4321,10 @@
case 0x406: /* max1730x pass2 silicon */
gauge_type = MAX1730X_GAUGE_TYPE;
break;
- case 0x620: /* m5 algo */
- gauge_type = MAX_M5_GAUGE_TYPE;
- break;
- default: /* default to max1720x */
- dev_warn(chip->dev, "devname=%x defaults to max17201\n",
- chip->devname);
+ default:
gauge_type = MAX1720X_GAUGE_TYPE;
+ dev_warn(chip->dev, "devname=%x defaults to %d\n",
+ chip->devname, gauge_type);
break;
}