max1720x_battery: update GMSR only when needed

Do not save battery state unless is needed, fix next-update counter.

Bug: 175042667
Signed-off-by: AleX Pelosi <[email protected]>
Change-Id: Ib3a10491fa08031d488b2105064bf96d12bbcbaa
diff --git a/max1720x_battery.c b/max1720x_battery.c
index c5e14b8..2734111 100644
--- a/max1720x_battery.c
+++ b/max1720x_battery.c
@@ -141,11 +141,12 @@
 	void *model_data;
 	struct mutex model_lock;
 	struct delayed_work model_work;
-	long model_next_update;
+	int model_next_update;
 	/* also used to restore model state from permanent storage */
 	u16 reg_prop_capacity_raw;
-	bool model_state_valid;
+	bool model_state_valid;	/* state read from persistent */
 	int model_reload;
+	bool model_ok;		/* model is running */
 
 	/* history */
 	struct mutex history_lock;
@@ -816,7 +817,7 @@
 		return -EINVAL;
 
 	mutex_lock(&chip->model_lock);
-	len += scnprintf(&buf[len], PAGE_SIZE, "ModelNextUpdate: %ld\n",
+	len += scnprintf(&buf[len], PAGE_SIZE, "ModelNextUpdate: %d\n",
 			 chip->model_next_update);
 	len += max_m5_model_state_cstr(&buf[len], PAGE_SIZE - len,
 				       chip->model_data);
@@ -843,6 +844,7 @@
 	/* REQUEST -> IDLE or set to the number of retries */
 	dev_info(chip->dev, "Reload FG Model for ID=%d\n", chip->batt_id);
 	chip->model_reload = MAX_M5_LOAD_MODEL_REQUEST;
+	chip->model_ok = false;
 	mod_delayed_work(system_wq, &chip->model_work, 0);
 }
 
@@ -2914,6 +2916,7 @@
 	if (chip->gauge_type == MAX_M5_GAUGE_TYPE)
 		debugfs_create_file("fg_model", 0440, de, chip,
 				    &debug_m5_custom_model_fops);
+	debugfs_create_bool("model_ok", 0444, de, &chip->model_ok);
 
 	/* capacity drift fixup, one of MAX1720X_DA_VER_* */
 	debugfs_create_u32("algo_ver", 0644, de, &chip->drift_data.algo_ver);
@@ -3112,6 +3115,33 @@
 				  0x0);
 }
 
+/* read state from fg (if needed) and set the next update field */
+static int max1720x_set_next_update(struct max1720x_chip *chip)
+{
+	int rc, cycle_count;
+
+	cycle_count = max1720x_get_cycle_count(chip);
+	if (cycle_count < 0)
+		return cycle_count;
+
+	if (chip->model_next_update && cycle_count < chip->model_next_update)
+		return 0;
+
+	/* read new state from Fuel gauge, save to storage if needed */
+	rc = max_m5_model_read_state(chip->model_data);
+	if (rc == 0 && chip->model_next_update)
+		rc = max_m5_save_state_data(chip->model_data);
+	if (rc == 0)
+		chip->model_next_update = (cycle_count + (1 << 6)) &
+					  ~((1 << 6) - 1);
+
+	pr_debug("%s: cycle_count=%d next_update=%ld rc=%d\n",
+			__func__, cycle_count, chip->model_next_update,
+			rc);
+
+	return 0;
+}
+
 static int max1720x_model_load(struct max1720x_chip *chip)
 {
 	int ret;
@@ -3143,9 +3173,15 @@
 			__func__, ret);
 
 
+	/* loading model might change cycle count */
+	ret = max1720x_set_next_update(chip);
+	if (ret < 0)
+		dev_err(chip->dev, "%s: error setting next update rc=%d\n",
+			__func__, ret);
+
+	/* mark model state as "safe" */
 	chip->reg_prop_capacity_raw = MAX1720X_REPSOC;
 	chip->model_state_valid = true;
-
 	return 0;
 }
 
@@ -3153,34 +3189,31 @@
 {
 	struct max1720x_chip *chip = container_of(work, struct max1720x_chip,
 						  model_work.work);
-	int cycle_count;
+	bool new_model = false;
 	int rc;
 
 	if (!chip->model_data)
 		return;
 
-	cycle_count = max1720x_get_cycle_count(chip);
-	if (cycle_count < 0)
-		cycle_count = chip->model_next_update;
-
-	pr_debug("%s: reload=%d cycle_count=%d\n", __func__,
-		 chip->model_reload, cycle_count);
-
 	mutex_lock(&chip->model_lock);
 
-	/* set model_reload to the #attempts */
+	/* set model_reload to the #attempts, might change cycle count */
 	if (chip->model_reload >= MAX_M5_LOAD_MODEL_REQUEST) {
 
 		rc = max1720x_model_load(chip);
 		if (rc == 0) {
 			rc = max1720x_clear_por(chip);
+
 			dev_info(chip->dev, "%s Power-On Reset clear (%d)\n",
 				 __func__, rc);
 
 			/* TODO: keep trying to clear POR if the above fail */
 			chip->model_reload = MAX_M5_LOAD_MODEL_IDLE;
+			chip->model_ok = true;
+			new_model = true;
 		} else if (rc != -EAGAIN) {
 			chip->model_reload = MAX_M5_LOAD_MODEL_DISABLED;
+			chip->model_ok = false;
 		} else {
 			chip->model_reload -= 1;
 		}
@@ -3190,22 +3223,12 @@
 	if (max1720x_check_drift_enabled(&chip->drift_data))
 		max1720x_fixup_capacity(chip, chip->cap_estimate.cable_in);
 
-	/* save model data */
-	if (cycle_count > chip->model_next_update) {
-
-		pr_debug("%s: cycle_count=%d next_update=%ld\n", __func__,
-			 cycle_count, chip->model_next_update);
-
-		/* read new state from Fuel gauge, save to storage */
-		rc = max_m5_model_read_state(chip->model_data);
-		if (rc == 0)
-			rc = max_m5_save_state_data(chip->model_data);
-		if (rc == 0) {
-			chip->model_next_update = (cycle_count + (1 << 6)) &
-						  ~((1 << 6) - 1);
-			power_supply_changed(chip->psy);
-		}
-
+	/* save state only when model is running */
+	if (chip->model_ok) {
+		rc = max1720x_set_next_update(chip);
+		if (rc < 0)
+			dev_err(chip->dev, "%s cannot set next update (%d)\n",
+				 __func__, rc);
 	}
 
 	if (chip->model_reload >= MAX_M5_LOAD_MODEL_REQUEST) {
@@ -3214,6 +3237,9 @@
 		schedule_delayed_work(&chip->model_work, delay);
 	}
 
+	if (new_model)
+		power_supply_changed(chip->psy);
+
 	mutex_unlock(&chip->model_lock);
 }
 
@@ -3480,19 +3506,27 @@
 				   MAX1720X_STATUS_BI, 0x0);
 	}
 
-	if (!ret && data & MAX1720X_STATUS_POR) {
+	/* max_m5 load the model in the irq handler when por is set  */
+	if (!por && chip->gauge_type == MAX_M5_GAUGE_TYPE) {
 
-		if (chip->gauge_type != MAX_M5_GAUGE_TYPE) {
-			ret = regmap_update_bits(chip->regmap.regmap,
-						 MAX1720X_STATUS,
-						 MAX1720X_STATUS_POR, 0x0);
-			dev_info(chip->dev,
-				 "Clearing Power-On Reset bit (%d)\n", ret);
-
+		ret = max_m5_model_read_state(chip->model_data);
+		if (ret == 0)
+			ret = max1720x_set_next_update(chip);
+		if (ret < 0) {
+			dev_err(chip->dev, "FG Model Error (%d)\n", ret);
+		} else {
+			dev_info(chip->dev, "FG Model OK, next_update=%d\n",
+				 chip->model_next_update);
 			chip->reg_prop_capacity_raw = MAX1720X_REPSOC;
+			chip->model_ok = true;
 		}
 
-		/* POR for M5 is handled in the irq_thread() */
+	} else if (por && chip->gauge_type != MAX_M5_GAUGE_TYPE) {
+		ret = regmap_update_bits(chip->regmap.regmap,
+					 MAX1720X_STATUS,
+					 MAX1720X_STATUS_POR, 0x0);
+		dev_info(chip->dev, "Clearing Power-On Reset bit (%d)\n", ret);
+		chip->reg_prop_capacity_raw = MAX1720X_REPSOC;
 	}
 
 	/* Fix capacity drift b/134500876 */