summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenny Ho <hsiufangho@google.com>2023-07-27 07:52:04 +0800
committerJenny Ho <hsiufangho@google.com>2023-08-25 14:14:59 +0000
commit31bdf26e329f2b7021d3e71f278e3834b460e246 (patch)
tree47534efcb896d9b5bdf74b939292a6b060424171
parent66e2728440d22c5fe385068087b330772cfd5642 (diff)
downloadbms-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.c117
-rw-r--r--max_m5.h2
2 files changed, 89 insertions, 30 deletions
diff --git a/max_m5.c b/max_m5.c
index 062bd6c..58a8f51 100644
--- a/max_m5.c
+++ b/max_m5.c
@@ -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)
diff --git a/max_m5.h b/max_m5.h
index 02d5b91..69d3e62 100644
--- a/max_m5.h
+++ b/max_m5.h
@@ -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;