[PATCH v4] power: supply: core: Use library interpolation
From: Linus Walleij <hidden>
Date: 2021-11-16 23:04:39
Subsystem:
power supply class/subsystem and drivers, the rest · Maintainers:
Sebastian Reichel, Linus Torvalds
The power supply core appears to contain two open coded linear interpolations. Use the kernel fixpoint arithmetic interpolation library function instead. Cc: Chunyan Zhang <redacted> Cc: Baolin Wang <baolin.wang@linux.alibaba.com> Signed-off-by: Linus Walleij <redacted> --- ChangeLog v3->v4: - Fix the code to really provide the same x index for both datapoints at the end of the table. Thanks again Baolin! ChangeLog v2->v3: - Actually implement the code as I say. Missed one occurence. ChangeLog v1->v2: - Break the table loop at table_len - 1 so we don't index past the end of the table. (Thanks Baolin!) Chunyan: The sc27xx fuel gauge seems to be the only driver using this, so it'd be great if you could test this to make sure it works as intended. --- drivers/power/supply/power_supply_core.c | 61 ++++++++++++------------ 1 file changed, 31 insertions(+), 30 deletions(-)
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
index fc12a4f407f4..2907b84ceea9 100644
--- a/drivers/power/supply/power_supply_core.c
+++ b/drivers/power/supply/power_supply_core.c@@ -21,6 +21,7 @@ #include <linux/power_supply.h> #include <linux/property.h> #include <linux/thermal.h> +#include <linux/fixp-arith.h> #include "power_supply.h" /* exported for the APM Power driver, APM emulation */
@@ -783,26 +784,25 @@ EXPORT_SYMBOL_GPL(power_supply_put_battery_info); int power_supply_temp2resist_simple(struct power_supply_resistance_temp_table *table, int table_len, int temp) { - int i, resist; + int i, high, low; - for (i = 0; i < table_len; i++) + /* Break loop at table_len - 1 because that is the highest index */ + for (i = 0; i < table_len - 1; i++) if (temp > table[i].temp) break; - if (i > 0 && i < table_len) { - int tmp; - - tmp = (table[i - 1].resistance - table[i].resistance) * - (temp - table[i].temp); - tmp /= table[i - 1].temp - table[i].temp; - resist = tmp + table[i].resistance; - } else if (i == 0) { - resist = table[0].resistance; - } else { - resist = table[table_len - 1].resistance; - } - - return resist; + /* The library function will deal with high == low */ + if ((i == 0) || (i == (table_len - 1))) + high = i; + else + high = i - 1; + low = i; + + return fixp_linear_interpolate(table[low].temp, + table[low].resistance, + table[high].temp, + table[high].resistance, + temp); } EXPORT_SYMBOL_GPL(power_supply_temp2resist_simple);
@@ -821,24 +821,25 @@ EXPORT_SYMBOL_GPL(power_supply_temp2resist_simple); int power_supply_ocv2cap_simple(struct power_supply_battery_ocv_table *table, int table_len, int ocv) { - int i, cap, tmp; + int i, high, low; - for (i = 0; i < table_len; i++) + /* Break loop at table_len - 1 because that is the highest index */ + for (i = 0; i < table_len - 1; i++) if (ocv > table[i].ocv) break; - if (i > 0 && i < table_len) { - tmp = (table[i - 1].capacity - table[i].capacity) * - (ocv - table[i].ocv); - tmp /= table[i - 1].ocv - table[i].ocv; - cap = tmp + table[i].capacity; - } else if (i == 0) { - cap = table[0].capacity; - } else { - cap = table[table_len - 1].capacity; - } - - return cap; + /* The library function will deal with high == low */ + if ((i == 0) || (i == (table_len - 1))) + high = i - 1; + else + high = i; /* i.e. i == 0 */ + low = i; + + return fixp_linear_interpolate(table[low].ocv, + table[low].capacity, + table[high].ocv, + table[high].capacity, + ocv); } EXPORT_SYMBOL_GPL(power_supply_ocv2cap_simple);
--
2.31.1