diff options
author | Jenny Ho <hsiufangho@google.com> | 2023-07-27 07:52:04 +0800 |
---|---|---|
committer | Jenny Ho <hsiufangho@google.com> | 2023-08-25 14:14:59 +0000 |
commit | 31bdf26e329f2b7021d3e71f278e3834b460e246 (patch) | |
tree | 47534efcb896d9b5bdf74b939292a6b060424171 | |
parent | 66e2728440d22c5fe385068087b330772cfd5642 (diff) | |
download | bms-31bdf26e329f2b7021d3e71f278e3834b460e246.tar.gz |
max_m5: add criteria to rerun loading custom parameters
Test for a race condition between AP SW and FG firmware during the model loading process. Add register value checks and rerun on failure due to the simultaneous update of the value by firmware.
Bug: 240115405
Change-Id: I39da136336be92cc6afa1d3f650383121b0a52ac
Signed-off-by: Jenny Ho <hsiufangho@google.com>
-rw-r--r-- | max_m5.c | 117 | ||||
-rw-r--r-- | max_m5.h | 2 |
2 files changed, 89 insertions, 30 deletions
@@ -455,41 +455,12 @@ static int max_m5_period2caplsb(u16 taskperiod) return cap_lsb; } -/* 0 is ok */ -int max_m5_load_gauge_model(struct max_m5_data *m5_data) +static int max_m5_update_gauge_custom_parameters(struct max_m5_data *m5_data) { struct max17x0x_regmap *regmap = m5_data->regmap; int ret, retries; u16 data; - if (!regmap) - return -EIO; - - if (!m5_data || !m5_data->custom_model || !m5_data->custom_model_size) - return -ENODATA; - - /* check FStat.DNR to wait it clear for data ready */ - for (retries = 20; retries > 0; retries--) { - ret = REGMAP_READ(regmap, MAX_M5_FSTAT, &data); - if (ret == 0 && !(data & MAX_M5_FSTAT_DNR)) - break; - msleep(50); - } - dev_info(m5_data->dev, "retries:%d, FSTAT:%#x\n", retries, data); - - /* loading in progress, this is not good (tm) */ - ret = REGMAP_READ(regmap, MAX_M5_CONFIG2, &data); - if (ret == 0 && (data & MAX_M5_CONFIG2_LDMDL)) { - dev_err(m5_data->dev, "load model in progress (%x)\n", data); - return -EINVAL; - } - - ret = max_m5_update_custom_model(m5_data); - if (ret < 0) { - dev_err(m5_data->dev, "cannot update custom model (%d)\n", ret); - return ret; - } - /* write parameters (which include state) */ ret = max_m5_update_custom_parameters(m5_data); if (ret < 0) { @@ -566,6 +537,92 @@ int max_m5_load_gauge_model(struct max_m5_data *m5_data) return -ETIMEDOUT; } +/* protected from mutex_lock(&chip->model_lock) */ +static int max_m5_check_model_parameters(struct max_m5_data *m5_data) +{ + struct max_m5_custom_parameters *cp = &m5_data->parameters; + struct max17x0x_regmap *regmap = m5_data->regmap; + int ret, cap_delta_threshold, cap_delta_real; + u16 fullcaprep, fullcapnom; + + /* b/240115405#comment44 */ + cap_delta_threshold = abs(cp->fullcapnom - cp->fullcaprep) + cp->designcap / 100; + + ret = REGMAP_READ(regmap, MAX_M5_FULLCAPREP, &fullcaprep); + if (ret < 0) + return ret; + + ret = REGMAP_READ(regmap, MAX_M5_FULLCAPNOM, &fullcapnom); + if (ret < 0) + return ret; + + cap_delta_real = abs(fullcapnom - fullcaprep); + + dev_info(m5_data->dev, "write: nom:%#x, rep:%#x, design:%#x (threshold=%d)," + " read: nom:%#x, rep:%#x (delta=%d), retry:%d\n", + cp->fullcapnom, cp->fullcaprep, cp->designcap, cap_delta_threshold, + fullcapnom, fullcaprep, cap_delta_real, m5_data->load_retry); + + if (cap_delta_real > cap_delta_threshold && m5_data->load_retry < MAX_M5_RETRY_TIMES) + return -ERANGE; + + return 0; +} + +/* 0 is ok , protected from mutex_lock(&chip->model_lock) in max7102x_battery.c */ +int max_m5_load_gauge_model(struct max_m5_data *m5_data) +{ + struct max17x0x_regmap *regmap = m5_data->regmap; + int ret, retries; + u16 data; + + if (!regmap) + return -EIO; + + if (!m5_data || !m5_data->custom_model || !m5_data->custom_model_size) + return -ENODATA; + + /* check FStat.DNR to wait it clear for data ready */ + for (retries = 20; retries > 0; retries--) { + ret = REGMAP_READ(regmap, MAX_M5_FSTAT, &data); + if (ret == 0 && !(data & MAX_M5_FSTAT_DNR)) + break; + msleep(50); + } + dev_info(m5_data->dev, "retries:%d, FSTAT:%#x\n", retries, data); + + /* loading in progress, this is not good (tm) */ + ret = REGMAP_READ(regmap, MAX_M5_CONFIG2, &data); + if (ret == 0 && (data & MAX_M5_CONFIG2_LDMDL)) { + dev_err(m5_data->dev, "load model in progress (%x)\n", data); + return -EINVAL; + } + + ret = max_m5_update_custom_model(m5_data); + if (ret < 0) { + dev_err(m5_data->dev, "cannot update custom model (%d)\n", ret); + return ret; + } + + do { + msleep(500); + + ret = max_m5_update_gauge_custom_parameters(m5_data); + if (ret < 0) + return ret; + + ret = max_m5_check_model_parameters(m5_data); + if (ret < 0) { + m5_data->load_retry++; + } else { + m5_data->load_retry = 0; + break; + } + } while (m5_data->load_retry < MAX_M5_RETRY_TIMES); + + return ret; +} + /* algo version is ignored here, check code in max1720x_outliers */ int max_m5_fixup_outliers(struct max1720x_drift_data *ddata, struct max_m5_data *m5_data) @@ -45,6 +45,7 @@ /* model version */ #define MAX_M5_INVALID_VERSION -1 +#define MAX_M5_RETRY_TIMES 3 /** ------------------------------------------------------------------------ */ @@ -117,6 +118,7 @@ struct max_m5_data { u16 *custom_model; u32 model_version; bool force_reset_model_data; + int load_retry; /* to/from GMSR */ struct model_state_save model_save; |