max77779: prevent suspend during model loading

Add pm_awake/pm_release during model loading related
EEPROM access

Bug: 340352537
Change-Id: I94e915fd68a523e354833441ad1446ee839cbec2
Signed-off-by: Chungro Lee <[email protected]>
diff --git a/max77779_fg.c b/max77779_fg.c
index a33f97d..48669ae 100644
--- a/max77779_fg.c
+++ b/max77779_fg.c
@@ -661,19 +661,21 @@
 
 	mutex_lock(&chip->save_data_lock);
 	ret = gbms_storage_read(GBMS_TAG_CNHS, &eeprom_cycle, sizeof(eeprom_cycle));
-	mutex_unlock(&chip->save_data_lock);
-
-	if (ret < 0) {
+	if (ret != sizeof(eeprom_cycle)) {
+		mutex_unlock(&chip->save_data_lock);
 		dev_info(chip->dev, "Fail to read eeprom cycle count (%d)", ret);
 		return ret;
 	}
 
 	if (eeprom_cycle == 0xFFFF) { /* empty storage */
-		chip->eeprom_cycle = max77779_fg_save_battery_cycle(chip, reg_cycle);
+		mutex_unlock(&chip->save_data_lock);
+		max77779_fg_save_battery_cycle(chip, reg_cycle);
 		return -EINVAL;
 	}
 
 	chip->eeprom_cycle = eeprom_cycle;
+	mutex_unlock(&chip->save_data_lock);
+
 	dev_info(chip->dev, "reg_cycle:%d, eeprom_cycle:%d, update:%c",
 		 reg_cycle, chip->eeprom_cycle, chip->eeprom_cycle > reg_cycle ? 'Y' : 'N');
 	if (chip->eeprom_cycle > reg_cycle) {
@@ -689,30 +691,28 @@
 static u16 max77779_fg_save_battery_cycle(struct max77779_fg_chip *chip, u16 reg_cycle)
 {
 	int ret = 0;
-	u16 eeprom_cycle = chip->eeprom_cycle;
 
-	if (chip->por || reg_cycle == 0)
-		return eeprom_cycle;
-
-	if (reg_cycle <= eeprom_cycle)
-		return eeprom_cycle;
-
+	__pm_stay_awake(chip->fg_wake_lock);
 	mutex_lock(&chip->save_data_lock);
-	if (chip->pm_notifier_suspended) {
-		mutex_unlock(&chip->save_data_lock);
-		return eeprom_cycle;
-	}
+
+	if (chip->por || reg_cycle == 0 || reg_cycle <= chip->eeprom_cycle)
+		goto max77779_fg_save_battery_cycle_exit;
 
 	ret = gbms_storage_write(GBMS_TAG_CNHS, &reg_cycle, sizeof(reg_cycle));
-	if (ret < 0) {
+
+	if (ret != sizeof(reg_cycle)) {
 		dev_info(chip->dev, "Fail to write %d eeprom cycle count (%d)", reg_cycle, ret);
 	} else {
-		dev_info(chip->dev, "update saved cycle:%d -> %d\n", eeprom_cycle, reg_cycle);
-		eeprom_cycle = reg_cycle;
+		dev_info(chip->dev, "update saved cycle:%d -> %d\n", chip->eeprom_cycle, reg_cycle);
+		chip->eeprom_cycle = reg_cycle;
 	}
-	mutex_unlock(&chip->save_data_lock);
 
-	return eeprom_cycle;
+
+max77779_fg_save_battery_cycle_exit:
+	mutex_unlock(&chip->save_data_lock);
+	__pm_relax(chip->fg_wake_lock);
+
+	return chip->eeprom_cycle;
 }
 
 #define MAX17201_HIST_CYCLE_COUNT_OFFSET	0x4
@@ -751,7 +751,7 @@
 		/* the value of MAX77779_FG_Cycles will be set as chip->eeprom_cycle */
 		reg_cycle = chip->eeprom_cycle;
 	} else {
-		chip->eeprom_cycle = max77779_fg_save_battery_cycle(chip, reg_cycle);
+		max77779_fg_save_battery_cycle(chip, reg_cycle);
 	}
 
 	chip->cycle_count = reg_to_cycles((u32)reg_cycle);
@@ -2649,16 +2649,13 @@
 static int debug_cnhs_reset(void *data, u64 val)
 {
 	struct max77779_fg_chip *chip = data;
-	u16 reset_val;
 	int ret;
 
-	reset_val = (u16)val;
+	ret = max77779_fg_save_battery_cycle(chip, (u16)val);
 
-	ret = gbms_storage_write(GBMS_TAG_CNHS, &reset_val,
-				sizeof(reset_val));
-	dev_info(chip->dev, "reset CNHS to %d, (ret=%d)\n", reset_val, ret);
+	dev_info(chip->dev, "reset CNHS to %d, (ret=%d)\n", (int)val, ret);
 
-	return ret == sizeof(reset_val) ? 0 : ret;
+	return ret == sizeof(u16) ? 0 : ret;
 }
 
 DEFINE_SIMPLE_ATTRIBUTE(debug_reset_cnhs_fops, NULL, debug_cnhs_reset, "%llu\n");
@@ -2967,16 +2964,9 @@
 		}
 	}
 
-	if (rc == 0 && chip->model_next_update) {
-		mutex_lock(&chip->save_data_lock);
-		if (chip->pm_notifier_suspended) {
-			mutex_unlock(&chip->save_data_lock);
-			return 0;
-		}
-
+	if (rc == 0 && chip->model_next_update)
 		rc = max77779_save_state_data(chip->model_data);
-		mutex_unlock(&chip->save_data_lock);
-	}
+
 	/*
 	 * cycle register LSB is 25% of one cycle
 	 * schedule next update at multiples of 4
@@ -3001,7 +2991,7 @@
 	ret = max77779_load_state_data(chip->model_data);
 	if (ret == -EAGAIN)
 		return -EAGAIN;
-	if (ret < 0)
+	if (ret != 0)
 		dev_warn(chip->dev, "Load Model Using Default State (%d)\n", ret);
 
 	/* get fw version from pmic if it's not ready during init */
@@ -3053,6 +3043,7 @@
 	if (!chip->model_data)
 		return;
 
+	__pm_stay_awake(chip->fg_wake_lock);
 	mutex_lock(&chip->model_lock);
 
 	if (chip->model_reload >= MAX77779_FG_LOAD_MODEL_REQUEST) {
@@ -3095,6 +3086,7 @@
 	}
 
 	mutex_unlock(&chip->model_lock);
+	__pm_relax(chip->fg_wake_lock);
 
 	/*
 	 * notify event only when no more model loading activities
@@ -3192,29 +3184,6 @@
 	return 0;
 }
 
-static int max77779_fg_pm_notifier(struct notifier_block *nb,
-				   unsigned long action, void *nb_data)
-{
-	struct max77779_fg_chip *chip = container_of(nb, struct max77779_fg_chip, pm_nb);
-
-	mutex_lock(&chip->save_data_lock);
-
-	switch (action) {
-	case PM_SUSPEND_PREPARE:
-		chip->pm_notifier_suspended = true;
-		break;
-	case PM_POST_SUSPEND:
-		chip->pm_notifier_suspended = false;
-		break;
-	default:
-		break;
-	}
-
-	mutex_unlock(&chip->save_data_lock);
-
-	return NOTIFY_OK;
-}
-
 static int max77779_fg_init_chip(struct max77779_fg_chip *chip)
 {
 	int ret;
@@ -3287,10 +3256,6 @@
 	MAX77779_FG_REGMAP_WRITE(&chip->regmap, MAX77779_FG_FG_INT_MASK,
 				 MAX77779_FG_FG_INT_MASK_dSOCi_m_CLEAR);
 
-	chip->pm_notifier_suspended = false;
-	chip->pm_nb.notifier_call = max77779_fg_pm_notifier;
-	register_pm_notifier(&chip->pm_nb);
-
 	max77779_fg_update_cycle_count(chip);
 
 	/* triggers loading of the model in the irq handler on POR */
@@ -3728,6 +3693,10 @@
 	INIT_DELAYED_WORK(&chip->init_work, max77779_fg_init_work);
 	INIT_DELAYED_WORK(&chip->model_work, max77779_fg_model_work);
 
+	chip->fg_wake_lock = wakeup_source_register(NULL, "max77779-fg");
+	if (!chip->fg_wake_lock)
+		dev_warn(dev, "failed to register wake source\n");
+
 	schedule_delayed_work(&chip->init_work, 0);
 
 	return 0;
@@ -3748,6 +3717,11 @@
 		chip->ce_log = NULL;
 	}
 
+	if (chip->fg_wake_lock) {
+		wakeup_source_unregister(chip->fg_wake_lock);
+		chip->fg_wake_lock = NULL;
+	}
+
 	if (chip->model_data)
 		max77779_free_data(chip->model_data);
 	cancel_delayed_work(&chip->init_work);
@@ -3762,7 +3736,6 @@
 		power_supply_unregister(chip->psy);
 
 	maxfg_free_capture_buf(&chip->cb_lh);
-	unregister_pm_notifier(&chip->pm_nb);
 }
 EXPORT_SYMBOL_GPL(max77779_fg_remove);
 
diff --git a/max77779_fg.h b/max77779_fg.h
index 0007316..0a143f0 100644
--- a/max77779_fg.h
+++ b/max77779_fg.h
@@ -184,9 +184,8 @@
 	struct maxfg_capture_buf cb_lh;
 
 	/* get suspend/resume notification */
-	struct notifier_block	pm_nb;
-	bool pm_notifier_suspended;
 	struct mutex save_data_lock;
+	struct wakeup_source *fg_wake_lock;
 };
 
 /** ------------------------------------------------------------------------ */
diff --git a/max77779_fg_model.c b/max77779_fg_model.c
index 0fef11f..c431317 100644
--- a/max77779_fg_model.c
+++ b/max77779_fg_model.c
@@ -73,12 +73,20 @@
 int max77779_reset_state_data(struct max77779_model_data *model_data)
 {
 	struct model_state_save data;
+	struct max77779_fg_chip *chip = dev_get_drvdata(model_data->dev);
 	int ret = 0;
 
+	__pm_stay_awake(chip->fg_wake_lock);
+	mutex_lock(&chip->save_data_lock);
+
 	memset(&data, 0xff, sizeof(data));
 
 	ret = gbms_storage_write(GBMS_TAG_GMSR, &data, sizeof(data));
-	if (ret < 0)
+
+	mutex_unlock(&chip->save_data_lock);
+	__pm_relax(chip->fg_wake_lock);
+
+	if (ret != GBMS_GMSR_LEN)
 		dev_warn(model_data->dev, "Erase GMSR fail (%d)\n", ret);
 
 	return ret == sizeof(data) ? 0 : ret;
@@ -462,6 +470,7 @@
 int max77779_load_state_data(struct max77779_model_data *model_data)
 {
 	struct max77779_custom_parameters *cp = &model_data->parameters;
+	struct max77779_fg_chip *chip = dev_get_drvdata(model_data->dev);
 	u8 crc;
 	int ret;
 
@@ -469,9 +478,12 @@
 		return -EINVAL;
 
 	/* might return -EAGAIN during init */
+	mutex_lock(&chip->save_data_lock);
 	ret = gbms_storage_read(GBMS_TAG_GMSR, &model_data->model_save,
 				sizeof(model_data->model_save));
-	if (ret < 0) {
+	mutex_unlock(&chip->save_data_lock);
+
+	if (ret != GBMS_GMSR_LEN) {
 		dev_info(model_data->dev, "Saved Model Data empty\n");
 		return ret;
 	}
@@ -501,9 +513,14 @@
 int max77779_save_state_data(struct max77779_model_data *model_data)
 {
 	struct max77779_custom_parameters *cp = &model_data->parameters;
+	struct max77779_fg_chip *chip = dev_get_drvdata(model_data->dev);
+
 	struct model_state_save rb;
 	int ret = 0;
 
+	__pm_stay_awake(chip->fg_wake_lock);
+	mutex_lock(&chip->save_data_lock);
+
 	model_data->model_save.qrtable00 = cp->qresidual00;
 	model_data->model_save.qrtable10 = cp->qresidual10;
 	model_data->model_save.qrtable20 = cp->qresidual20;
@@ -516,19 +533,22 @@
 
 	model_data->model_save.crc = max77779_fg_data_crc("save", &model_data->model_save);
 
+
 	ret = gbms_storage_write(GBMS_TAG_GMSR, (const void *)&model_data->model_save,
 				 sizeof(model_data->model_save));
-	if (ret < 0)
-		return ret;
+	if (ret != GBMS_GMSR_LEN)
+		goto max77779_save_state_data_exit;
 
-	if (ret != sizeof(model_data->model_save))
-		return -ERANGE;
+	if (ret != sizeof(model_data->model_save)) {
+		ret = -ERANGE;
+		goto max77779_save_state_data_exit;
+	}
 
 	/* Read back to make sure data all good */
 	ret = gbms_storage_read(GBMS_TAG_GMSR, &rb, sizeof(rb));
-	if (ret < 0) {
+	if (ret != GBMS_GMSR_LEN) {
 		dev_info(model_data->dev, "Read Back Data Failed ret=%d\n", ret);
-		return ret;
+		goto max77779_save_state_data_exit;
 	}
 
 	if (rb.rcomp0 != model_data->model_save.rcomp0 ||
@@ -537,9 +557,15 @@
 	    rb.fullcapnom != model_data->model_save.fullcapnom ||
 	    rb.cycles != model_data->model_save.cycles ||
 	    rb.crc != model_data->model_save.crc)
-		return -EINVAL;
+		ret = -EINVAL;
+	else
+		ret = 0;
 
-	return 0;
+max77779_save_state_data_exit:
+	mutex_unlock(&chip->save_data_lock);
+	__pm_relax(chip->fg_wake_lock);
+
+	return ret;
 }
 
 /* 0 ok, < 0 error. Call after reading from the FG */
@@ -623,6 +649,8 @@
 	ret = gbms_storage_read(GBMS_TAG_GMSR, &saved_data, GBMS_GMSR_LEN);
 	if (ret < 0)
 		return ret;
+	if (ret != GBMS_GMSR_LEN)
+		return -EIO;
 
 	len = scnprintf(&buf[len], max - len,
 			"rcomp0     :%04X\ntempco     :%04X\n"