From 57f548caa1a95ee36ab8033ee4c1063dfefd2bce Mon Sep 17 00:00:00 2001 From: Shengfei Xu Date: Sun, 18 May 2025 16:04:45 +0800 Subject: [PATCH] power: supply: rk817_battery: Implement temperature filtering functionality Implement temperature filtering functionality to mitigate abrupt temperature fluctuations caused by probabilistic acquisition of erroneous thermistor resistance values. Change-Id: Iedda4af3f75e3cee1b132e659857a2c032681d3a Signed-off-by: Shengfei Xu --- drivers/power/supply/rk817_battery.c | 102 +++++++++++++++++++++++---- 1 file changed, 90 insertions(+), 12 deletions(-) diff --git a/drivers/power/supply/rk817_battery.c b/drivers/power/supply/rk817_battery.c index 8981ce333d49..7691871f1eb2 100644 --- a/drivers/power/supply/rk817_battery.c +++ b/drivers/power/supply/rk817_battery.c @@ -132,6 +132,14 @@ module_param_named(dbg_level, dbg_enable, int, 0644); #define TS_MAX_VOL 1100 #define TS_MIN_VOL 500 +/* Number of samples in moving window */ +#define SAMPLE_SIZE 10 +/* 2.0 threshold (scaled by 10) */ +#define TEMP_DIFF_THRESH 20 +/* 5.0 jump threshold (scaled by 10) */ +#define JUMP_DETECT_THRESH 50 +/* Resistance value scaling factor */ +#define RES_SCALE 1000 enum ts_fun { TS_FUN_SOURCE_CURRENT, @@ -446,6 +454,17 @@ struct contact_res_info { int ts10uA_update; }; +struct ntc_filter { + /* Sample buffer (scaled by RES_SCALE) */ + u32 samples[SAMPLE_SIZE]; + /* Current write index */ + u32 idx; + /* Valid sample count */ + u32 count; + /* Consecutive discard counter */ + u32 discard_cnt; +}; + struct battery_platform_data { u32 *ocv_table; u32 ocv_size; @@ -491,6 +510,7 @@ struct rk817_battery_device { struct timer_list caltimer; struct contact_res_info ts_info; + struct ntc_filter *f; int sample_res; int bat_res; bool is_first_power_on; @@ -1661,24 +1681,22 @@ static void rk817_bat_calculate_contact_res(struct rk817_battery_device *battery } } -static void rk817_bat_update_temperature(struct rk817_battery_device *battery) +/* Convert resistance to temperature (0.1) */ +static int rk817_bat_res_to_temp(struct rk817_battery_device *battery, u32 res) { + int temperature = VIRTUAL_TEMPERATURE; u32 ntc_size, *ntc_table; - int i, res; + int i; ntc_table = battery->pdata->ntc_table; ntc_size = battery->pdata->ntc_size; if (ntc_size) { - res = rk817_bat_get_ntc_res(battery); - if (res == 0) - return; - if (res < ntc_table[ntc_size - 1]) { - battery->temperature = (ntc_size + battery->pdata->ntc_degree_from) * 10; + temperature = (ntc_size + battery->pdata->ntc_degree_from) * 10; DBG("bat ntc upper max degree: R=%d\n", res); } else if (res > ntc_table[0]) { - battery->temperature = battery->pdata->ntc_degree_from * 10; + temperature = battery->pdata->ntc_degree_from * 10; DBG("bat ntc lower min degree: R=%d\n", res); } else { for (i = 0; i < ntc_size; i++) { @@ -1687,12 +1705,72 @@ static void rk817_bat_update_temperature(struct rk817_battery_device *battery) } if (i <= 0) - battery->temperature = - (battery->pdata->ntc_degree_from) * 10; + temperature = battery->pdata->ntc_degree_from * 10; else - battery->temperature = - (i + battery->pdata->ntc_degree_from) * 10; + temperature = (i + battery->pdata->ntc_degree_from) * 10; } + DBG("Temperature: %d\n", temperature); + } + return temperature; +} + +/* + * Process new sample and return filtered value + */ +static int32_t rk817_bat_ntc_filter(struct rk817_battery_device *battery, u32 new_res) +{ + struct ntc_filter *f = battery->f; + int avg_temp, new_temp, temp_diff; + u32 avg_res, sum = 0; + int i; + + /* Calculate current average */ + for (i = 0; i < f->count; i++) + sum += f->samples[i]; + + /* Temperature validation logic */ + if (f->count > 0) { + avg_res = (int32_t)(sum / f->count); + avg_temp = rk817_bat_res_to_temp(battery, avg_res); + new_temp = rk817_bat_res_to_temp(battery, new_res); + temp_diff = abs(new_temp - avg_temp); + + /* Check if sample should be discarded */ + if (temp_diff > TEMP_DIFF_THRESH) { + /* Detect temperature jump condition */ + if (temp_diff < JUMP_DETECT_THRESH && ++f->discard_cnt >= SAMPLE_SIZE) { + f->discard_cnt = 0; + goto accept_sample; /* Valid jump detected */ + } + /* Return average, discard new sample */ + return avg_res; + } + /* Reset counter on valid sample */ + f->discard_cnt = 0; + } + +accept_sample: + /* Store valid sample */ + f->samples[f->idx] = new_res; + f->idx = (f->idx + 1) % SAMPLE_SIZE; + if (f->count < SAMPLE_SIZE) + f->count++; + + /* Recalculate average */ + sum = 0; + for (i = 0; i < f->count; i++) + sum += f->samples[i]; + return (int32_t)(sum / f->count); +} + +static void rk817_bat_update_temperature(struct rk817_battery_device *battery) +{ + int res; + + if (battery->pdata->ntc_size) { + res = rk817_bat_get_ntc_res(battery); + res = rk817_bat_ntc_filter(battery, res); + battery->temperature = rk817_bat_res_to_temp(battery, res); DBG("Temperature: %d\n", battery->temperature); rk817_bat_temperature_chrg(battery, battery->temperature / 10); }