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, ®_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"