google_battery: ravg and new algos
Add soc_low to google_resistance, cleanup the code and the logging.
Add debug entries to set/reset the value.
Bug: 223759710
Signed-off-by: AleX Pelosi <[email protected]>
Change-Id: I48a92218f6c54e7d1644eca73e5462365a495b98
diff --git a/google_battery.c b/google_battery.c
index e166129..c4056da 100644
--- a/google_battery.c
+++ b/google_battery.c
@@ -188,9 +188,10 @@
int prev_soc;
};
-#define DEFAULT_RES_TEMP_HIGH 390
#define DEFAULT_RES_TEMP_LOW 350
-#define DEFAULT_RES_SSOC_THR 75
+#define DEFAULT_RES_TEMP_HIGH 390
+#define DEFAULT_RAVG_SOC_LOW 5
+#define DEFAULT_RAVG_SOC_HIGH 75
#define DEFAULT_RES_FILT_LEN 10
/* TODO: move google_resistance to bhi_data */
@@ -207,7 +208,8 @@
/* configuration */
int estimate_filter;
- int ssoc_threshold;
+ int ravg_soc_low;
+ int ravg_soc_high;
int res_temp_low;
int res_temp_high;
};
@@ -2161,7 +2163,7 @@
static void batt_res_dump_logs(struct batt_res *rstate)
{
- pr_info("RES: req:%d, sample:%d[%d], filt_cnt:%d, res_avg:%d\n",
+ pr_info("RAVG: req:%d, sample:%d[%d], filt_cnt:%d, res_avg:%d\n",
rstate->estimate_requested, rstate->sample_accumulator,
rstate->sample_count, rstate->filter_count,
rstate->resistance_avg);
@@ -2172,17 +2174,41 @@
rstate->estimate_requested = breq;
rstate->sample_accumulator = 0;
rstate->sample_count = 0;
- batt_res_dump_logs(rstate);
}
-static void batt_res_store_data(struct batt_res *rstate,
- struct power_supply *fg_psy)
+static int batt_ravg_write(int resistance_avg, int filter_count)
{
- int ret = 0;
+ const u16 ravg = (resistance_avg > 0xffff ) ? 0xffff : resistance_avg;
+ const u16 rfcn = filter_count & 0xffff;
+ int ret;
+
+ ret = gbms_storage_write(GBMS_TAG_RAVG, &ravg, sizeof(ravg));
+ if (ret < 0) {
+ pr_debug("RAVG: failed to write RAVG (%d)\n", ret);
+ return -EIO;
+ }
+
+ /*
+ * filter_count <= estimate_filter
+ * TODO: we might not need this...
+ * TODO: check the error path (ravg saved but filter count not saved)
+ */
+ ret = gbms_storage_write(GBMS_TAG_RFCN, &rfcn, sizeof(rfcn));
+ if (ret < 0) {
+ pr_debug("RAVG: failed to write RFCN (%d)\n", ret);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static void batt_res_update(struct batt_res *rstate)
+{
int filter_estimate = 0;
int total_estimate = 0;
long new_estimate = 0;
+ /* accumulator is scaled */
new_estimate = rstate->sample_accumulator / rstate->sample_count;
filter_estimate = rstate->resistance_avg * rstate->filter_count;
@@ -2191,86 +2217,93 @@
rstate->filter_count = rstate->estimate_filter;
filter_estimate -= rstate->resistance_avg;
}
+
total_estimate = filter_estimate + new_estimate;
rstate->resistance_avg = total_estimate / rstate->filter_count;
-
- ret = gbms_storage_write(GBMS_TAG_RAVG, &rstate->resistance_avg,
- sizeof(rstate->resistance_avg));
- if (ret < 0)
- pr_err("failed to write resistance_avg\n");
-
- ret = gbms_storage_write(GBMS_TAG_RFCN, &rstate->filter_count,
- sizeof(rstate->filter_count));
- if (ret < 0)
- pr_err("failed to write resistenace filt_count\n");
-
- batt_res_dump_logs(rstate);
}
static int batt_res_load_data(struct batt_res *rstate,
struct power_supply *fg_psy)
{
- int ret = 0;
+ u16 resistance_avg = 0, filter_count = 0;
+ int ret;
- ret = gbms_storage_read(GBMS_TAG_RAVG, &rstate->resistance_avg,
- sizeof(rstate->resistance_avg));
+ ret = gbms_storage_read(GBMS_TAG_RAVG, &resistance_avg,
+ sizeof(resistance_avg));
if (ret < 0) {
pr_err("failed to get resistance_avg(%d)\n", ret);
- return ret;
+ goto error_done;
}
- ret = gbms_storage_read(GBMS_TAG_RFCN, &rstate->filter_count,
- sizeof(rstate->filter_count));
+ ret = gbms_storage_read(GBMS_TAG_RFCN, &filter_count,
+ sizeof(filter_count));
if (ret < 0) {
- rstate->resistance_avg = 0;
pr_err("failed to get resistance filt_count(%d)\n", ret);
- return ret;
+ goto error_done;
}
- batt_res_dump_logs(rstate);
+ /* no value in storage: start now (or start over) */
+ if (resistance_avg == 0xffff || filter_count == 0xffff) {
+ resistance_avg = 0;
+ filter_count = 0;
+ }
+
+error_done:
+ rstate->resistance_avg = resistance_avg;
+ rstate->filter_count = filter_count;
return 0;
}
+/*
+ * accumulate and resistance when SOC is between ravg_soc_low and ravg_soc_high
+ * and temperature is in the right range. Discard the new sample if the device
+ * is disconencted.
+ * NOTE: call holding chg_lock
+ */
static void batt_res_work(struct batt_drv *batt_drv)
{
- u32 data32;
- int temp, ret, resistance;
+ const int soc = ssoc_get_real(&batt_drv->ssoc_state);
+ struct power_supply *fg_psy = batt_drv->fg_psy;
struct batt_res *rstate = &batt_drv->res_state;
- const int ssoc_threshold = rstate->ssoc_threshold;
- const int res_temp_low = rstate->res_temp_low;
- const int res_temp_high = rstate->res_temp_high;
+ int ret, temp, resistance;
- temp = GPSY_GET_INT_PROP(batt_drv->fg_psy,
- POWER_SUPPLY_PROP_TEMP, &ret);
- if (ret < 0 || temp < res_temp_low || temp > res_temp_high) {
- if (ssoc_get_real(&batt_drv->ssoc_state) > ssoc_threshold) {
- if (rstate->sample_count > 0) {
- /* update the filter */
- batt_res_store_data(&batt_drv->res_state,
- batt_drv->fg_psy);
- batt_res_state_set(rstate, false);
- }
+ if (soc >= rstate->ravg_soc_high) {
+
+ /* done: recalculate resistance_avg and save it */
+ if (rstate->sample_count > 0) {
+ batt_res_update(rstate);
+
+ ret = batt_ravg_write(rstate->resistance_avg,
+ rstate->filter_count);
+ if (ret == 0)
+ batt_res_dump_logs(rstate);
}
+
+ /* loose the new data when it cannot save */
+ batt_res_state_set(rstate, false);
return;
}
- ret = gbms_storage_read(GBMS_TAG_BRES, &data32, sizeof(data32));
+ /* wait for it */
+ if (soc < rstate->ravg_soc_low)
+ return;
+
+ /* do not collect samples when temperature is outside the range */
+ temp = GPSY_GET_INT_PROP(fg_psy, POWER_SUPPLY_PROP_TEMP, &ret);
+ if (ret < 0 || temp < rstate->res_temp_low || temp > rstate->res_temp_high)
+ return;
+
+ /* resistance in mOhm, skip read errors */
+ resistance = GPSY_GET_INT_PROP(fg_psy, GBMS_PROP_RESISTANCE, &ret);
if (ret < 0)
return;
- resistance = data32;
- if (ssoc_get_real(&batt_drv->ssoc_state) < ssoc_threshold) {
- rstate->sample_accumulator += resistance / 100;
- rstate->sample_count++;
- batt_res_dump_logs(rstate);
- } else {
- if (rstate->sample_count > 0) {
- /* update the filter here */
- batt_res_store_data(&batt_drv->res_state,
- batt_drv->fg_psy);
- }
- batt_res_state_set(rstate, false);
- }
+ /* accumulate samples if temperature and SOC are within range */
+ rstate->sample_accumulator += resistance / 100;
+ rstate->sample_count++;
+ pr_debug("RAVG: sample:%d[%d], filt_cnt:%d\n",
+ rstate->sample_accumulator, rstate->sample_count,
+ rstate->filter_count);
}
/* ------------------------------------------------------------------------- */
@@ -3289,7 +3322,7 @@
}
/* will return -ENODATA until the value is valid. Call during charging */
-static int bhi_perf_data_update(struct bhi_data *bhi_data, struct power_supply *fg_psy)
+static int bhi_impedance_data_update(struct bhi_data *bhi_data, struct power_supply *fg_psy)
{
int cur_impedance = -1, act_impedance = -1, age = -1;
int ret = -ENODATA;
@@ -3371,7 +3404,7 @@
/*
* TODO: bounds check cur_impedance with res10
*
- * TODO: bounds check cur_impedance google_resistance
+ * TODO: bounds check cur_impedance google_resistance?
* batt_drv->res_state->resistance_avg
*/
@@ -3922,7 +3955,6 @@
/* here on: disconnect */
batt_chg_stats_pub(batt_drv, "disconnect", false, false);
- batt_res_state_set(&batt_drv->res_state, false);
/* change curve before changing the state. */
ssoc_change_curve(&batt_drv->ssoc_state, ssoc_delta,
@@ -3933,7 +3965,7 @@
batt_update_cycle_count(batt_drv);
batt_rl_reset(batt_drv);
- /* this will trigger another google_capacity learning. */
+ /* trigger google_capacity learning. */
err = GPSY_SET_PROP(batt_drv->fg_psy,
GBMS_PROP_BATT_CE_CTRL,
false);
@@ -3956,6 +3988,12 @@
}
mutex_unlock(&batt_drv->bpst_state.lock);
+ /* google_resistance: batt_res_work will update the metric as
+ * appropriate
+ */
+ batt_res_work(batt_drv);
+ batt_res_state_set(&batt_drv->res_state, false);
+
/* bhi_capacity_index is updated on disconnect */
rc = bhi_cap_data_update(BHI_ALGO_MAX1720X, batt_drv);
if (rc == 0)
@@ -3983,6 +4021,7 @@
ssoc_change_curve(&batt_drv->ssoc_state, ssoc_delta,
SSOC_UIC_TYPE_CHG);
+ /* google_resistance is calculated while charging */
if (batt_drv->res_state.estimate_filter)
batt_res_state_set(&batt_drv->res_state, true);
@@ -3996,7 +4035,7 @@
err = GPSY_SET_PROP(batt_drv->fg_psy, GBMS_PROP_BATT_CE_CTRL, true);
if (err < 0)
- pr_err("Cannot set the BATT_CE_CTRL.\n");
+ pr_err("Cannot set the BATT_CE_CTRL (%d)\n", err);
/* released in battery_work() */
__pm_stay_awake(batt_drv->poll_ws);
@@ -4396,50 +4435,44 @@
static const DEVICE_ATTR_RW(cycle_counts);
-/* Was POWER_SUPPLY_PROP_RESISTANCE */
static ssize_t resistance_show(struct device *dev,
struct device_attribute *attr,
char *buff)
{
- u32 data;
- int ret;
+ struct power_supply *psy = container_of(dev, struct power_supply, dev);
+ struct batt_drv *batt_drv = power_supply_get_drvdata(psy);
+ int value;
- ret = gbms_storage_read(GBMS_TAG_BRES, &data, sizeof(data));
-
- return scnprintf(buff, PAGE_SIZE, "%d\n", ret < 0 ? ret : data);
+ value = GPSY_GET_PROP(batt_drv->fg_psy, GBMS_PROP_RESISTANCE);
+ return scnprintf(buff, PAGE_SIZE, "%d\n", value);
}
static const DEVICE_ATTR_RO(resistance);
-/* Was POWER_SUPPLY_PROP_RESISTANCE_AVG */
static ssize_t resistance_avg_show(struct device *dev,
struct device_attribute *attr,
char *buff)
{
struct power_supply *psy = container_of(dev, struct power_supply, dev);
struct batt_drv *batt_drv = power_supply_get_drvdata(psy);
- struct batt_res *res_state = &batt_drv->res_state;
- int value = 0;
- if (res_state->filter_count >= res_state->estimate_filter)
- value = res_state->resistance_avg;
-
- return scnprintf(buff, PAGE_SIZE, "%d\n", value);
+ /* resistance_avg is scaled */
+ return scnprintf(buff, PAGE_SIZE, "%d\n",
+ batt_drv->res_state.resistance_avg * 100);
}
static const DEVICE_ATTR_RO(resistance_avg);
-/* Was POWER_SUPPLY_PROP_CHARGE_FULL_ESTIMATE */
static ssize_t charge_full_estimate_show(struct device *dev,
struct device_attribute *attr,
char *buff)
{
- u16 data;
- int ret;
+ struct power_supply *psy = container_of(dev, struct power_supply, dev);
+ struct batt_drv *batt_drv = power_supply_get_drvdata(psy);
+ int value;
- ret = gbms_storage_read(GBMS_TAG_GCFE, &data, sizeof(data));
-
- return scnprintf(buff, PAGE_SIZE, "%d\n", ret < 0 ? ret : data * 1000);
+ value = GPSY_GET_PROP(batt_drv->fg_psy, GBMS_PROP_CHARGE_FULL_ESTIMATE);
+ return scnprintf(buff, PAGE_SIZE, "%d\n", value);
}
static const DEVICE_ATTR_RO(charge_full_estimate);
@@ -4801,6 +4834,36 @@
DEFINE_SIMPLE_ATTRIBUTE(debug_bpst_sbd_status_fops,
debug_bpst_sbd_status_read,
debug_bpst_sbd_status_write, "%llu\n");
+
+static int debug_ravg_fops_write(void *data, u64 val)
+{
+ struct batt_drv *batt_drv = (struct batt_drv *)data;
+ int resistance_avg = val / 100, filter_count = 1;
+ int ret;
+
+ mutex_lock(&batt_drv->chg_lock);
+
+ batt_res_state_set(&batt_drv->res_state, false);
+ batt_drv->res_state.resistance_avg = resistance_avg;
+ batt_drv->res_state.filter_count = filter_count;
+
+ /* reset storage to defaults */
+ if (val == 0) {
+ resistance_avg = 0xffff;
+ filter_count = 0xffff;
+ }
+
+ ret = batt_ravg_write(resistance_avg, filter_count);
+ pr_info("RAVG: update val=%d, resistance_avg=%x filter_count=%x (%d)\n",
+ (int)val, resistance_avg, filter_count, ret);
+ mutex_unlock(&batt_drv->chg_lock);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_ravg_fops, NULL, debug_ravg_fops_write, "%llu\n");
+
+
#endif
/* ------------------------------------------------------------------------- */
@@ -6560,12 +6623,19 @@
/* battery virtual sensor*/
debugfs_create_u32("batt_vs_w", 0600, de, &batt_drv->batt_vs_w);
- /* pwoer metrics */
+ /* power metrics */
debugfs_create_file("power_metrics", 0400, de, batt_drv, &debug_power_metrics_fops);
/* bhi fullcapnom count */
debugfs_create_u32("fcn_count", 0644, de, &batt_drv->health_data.bhi_data.fcn_count);
+ /* google_resistance, tuning */
+ debugfs_create_u32("ravg_temp_low", 0644, de, &batt_drv->res_state.res_temp_low);
+ debugfs_create_u32("ravg_temp_high", 0644, de, &batt_drv->res_state.res_temp_high);
+ debugfs_create_u32("ravg_soc_low", 0644, de, &batt_drv->res_state.ravg_soc_low);
+ debugfs_create_u32("ravg_soc_high", 0644, de, &batt_drv->res_state.ravg_soc_high);
+ debugfs_create_file("ravg", 0400, de, batt_drv, &debug_ravg_fops);
+
return 0;
}
@@ -7032,8 +7102,8 @@
if (ret < 0)
pr_warn("write save_soc fail, ret=%d\n", ret);
- /* update resitance all the time and capacity on disconnect */
- ret = bhi_perf_data_update(&batt_drv->health_data.bhi_data, fg_psy);
+ /* update resistance all the time and capacity on disconnect */
+ ret = bhi_impedance_data_update(&batt_drv->health_data.bhi_data, fg_psy);
if (ret < 0 && ret != -ENODATA)
pr_warn("cannot update perf index ret=%d\n", ret);
@@ -7102,6 +7172,7 @@
if (batt_drv->batt_fast_update_cnt == 0)
__pm_relax(batt_drv->poll_ws);
+ /* set a connect */
if (batt_drv->res_state.estimate_requested)
batt_res_work(batt_drv);
@@ -7784,7 +7855,7 @@
ret = of_property_read_u32(batt_drv->device->of_node, "google,bhi-algo-ver",
&health_data->bhi_algo);
if (ret < 0)
- health_data->bhi_algo = BHI_ALGO_V1;
+ health_data->bhi_algo = BHI_ALGO_ACHI_QRES;
/* weights */
ret = of_property_read_u32(batt_drv->device->of_node, "google,bhi-w_ci",
@@ -7820,7 +7891,7 @@
/* design (in device tree) or from the device */
health_data->bhi_data.capacity_design = batt_drv->battery_capacity;
- ret = bhi_perf_data_update(&health_data->bhi_data, batt_drv->fg_psy);
+ ret = bhi_impedance_data_update(&health_data->bhi_data, batt_drv->fg_psy);
if (ret < 0)
pr_err("bhi perf data not available (%d)\n", ret);
@@ -8055,21 +8126,23 @@
/* time to full */
ret = ttf_stats_init(&batt_drv->ttf_stats, batt_drv->device,
batt_drv->battery_capacity);
- if (ret < 0) {
+ if (ret < 0)
pr_info("time to full not available\n");
- } else {
- batt_drv->ttf_stats.ttf_log = logbuffer_register("ttf");
- if (IS_ERR(batt_drv->ttf_stats.ttf_log)) {
- ret = PTR_ERR(batt_drv->ttf_stats.ttf_log);
- dev_err(batt_drv->device,
- "failed to create ttf_log, ret=%d\n", ret);
- batt_drv->ttf_stats.ttf_log = NULL;
- }
+ /* TTF log is used report more things nowadays */
+ batt_drv->ttf_stats.ttf_log = logbuffer_register("ttf");
+ if (IS_ERR(batt_drv->ttf_stats.ttf_log)) {
+ ret = PTR_ERR(batt_drv->ttf_stats.ttf_log);
+ dev_err(batt_drv->device, "failed to create ttf_log, ret=%d\n", ret);
+
+ batt_drv->ttf_stats.ttf_log = NULL;
}
/* google_resistance */
- batt_res_load_data(&batt_drv->res_state, batt_drv->fg_psy);
+ ret = batt_res_load_data(&batt_drv->res_state, batt_drv->fg_psy);
+ if (ret < 0)
+ dev_warn(batt_drv->device, "RAVG not available (%d)\n", ret);
+ batt_res_dump_logs(&batt_drv->res_state);
/* health based charging, triggers */
batt_drv->chg_health.always_on_soc = -1;
@@ -8150,7 +8223,6 @@
if (ret < 0)
pr_err("BHI: not available\n");
-
/* these don't require nvm storage */
ret = gbms_storage_register(&batt_prop_dsc, "battery", batt_drv);
if (ret == -EBUSY)
@@ -8255,9 +8327,13 @@
batt_drv->res_state.res_temp_low = DEFAULT_RES_TEMP_LOW;
ret = of_property_read_u32(pdev->dev.of_node, "google,res-soc-thresh",
- &batt_drv->res_state.ssoc_threshold);
+ &batt_drv->res_state.ravg_soc_high);
if (ret < 0)
- batt_drv->res_state.ssoc_threshold = DEFAULT_RES_SSOC_THR;
+ batt_drv->res_state.ravg_soc_high = DEFAULT_RAVG_SOC_HIGH;
+ ret = of_property_read_u32(pdev->dev.of_node, "google,ravg-soc-low",
+ &batt_drv->res_state.ravg_soc_low);
+ if (ret < 0)
+ batt_drv->res_state.ravg_soc_low = DEFAULT_RAVG_SOC_LOW;
ret = of_property_read_u32(pdev->dev.of_node, "google,res-filt-length",
&batt_drv->res_state.estimate_filter);