Message ID | 392c7aa891d466bc4df06a076090150319e0e7dc.1637061794.git.matti.vaittinen@fi.rohmeurope.com (mailing list archive) |
---|---|
State | Not Applicable, archived |
Headers | show |
Series | power: supply: Add some fuel-gauge logic | expand |
On Tue, Nov 16, 2021 at 1:27 PM Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> wrote: > The battery info functions computing the state-of-charge (SOC) based > on open-circuit-voltage (OCV) are returning SOC using units of 1%. > > Some capacity estimation computations require higher accuracy. Add > functions that return SOC using units of 0.1% to reduce rounding error. > > Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> That sounds useful. > +int power_supply_ocv2dcap_simple(struct power_supply_battery_ocv_table *table, > + int table_len, int ocv) > +{ > + int i, cap, tmp; Why a whole new function? Just rename the original power_supply_ocv2cap_simple() to power_supply_ocv2dcap_simple and patch it to return the finegrained value, then add a wrapper that use that function but drops it down by one order of magnitude. > +int power_supply_batinfo_ocv2dcap(struct power_supply_battery_info *info, > + int ocv, int temp) Same with this, saves a lot of code! (Also will use my new interpolation routines since you refactor on top of that.) Yours, Linus Walleij
On 11/19/21 03:49, Linus Walleij wrote: > On Tue, Nov 16, 2021 at 1:27 PM Matti Vaittinen > <matti.vaittinen@fi.rohmeurope.com> wrote: > >> The battery info functions computing the state-of-charge (SOC) based >> on open-circuit-voltage (OCV) are returning SOC using units of 1%. >> >> Some capacity estimation computations require higher accuracy. Add >> functions that return SOC using units of 0.1% to reduce rounding error. >> >> Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> > > That sounds useful. > >> +int power_supply_ocv2dcap_simple(struct power_supply_battery_ocv_table *table, >> + int table_len, int ocv) >> +{ >> + int i, cap, tmp; > > Why a whole new function? Just rename the original power_supply_ocv2cap_simple() > to power_supply_ocv2dcap_simple and patch it to return the finegrained value, > then add a wrapper that use that function but drops it down by one order > of magnitude. /me feels slightly stupid. I wonder ehy you had to explain this to me :) Well, thanks and agreed! > >> +int power_supply_batinfo_ocv2dcap(struct power_supply_battery_info *info, >> + int ocv, int temp) > > Same with this, saves a lot of code! > > (Also will use my new interpolation routines since you refactor > on top of that.) yup. I think this will be _much_ cleaner. I need to revise also the IC driver patches because I think I implemented something like your interpolation routines there too. So - thanks. Best Regards Matti
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index ebc961b5aa45..62ea113db3b4 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -1003,6 +1003,45 @@ int power_supply_ocv2cap_simple(struct power_supply_battery_ocv_table *table, } EXPORT_SYMBOL_GPL(power_supply_ocv2cap_simple); +/** + * power_supply_ocv2dcap_simple() - find the battery capacity at 0.1% accuracy + * @table: Pointer to battery OCV lookup table + * @table_len: OCV table length + * @ocv: Current OCV value + * + * This helper function is used to look up battery capacity according to + * current OCV value from one OCV table, and the OCV table must be ordered + * descending. Return the SOC in the units of 0.1% for improved accuracy. + * + * Return: the battery capacity using the unit 0.1%. + */ +int power_supply_ocv2dcap_simple(struct power_supply_battery_ocv_table *table, + int table_len, int ocv) +{ + int i, cap, tmp; + + for (i = 0; i < table_len; 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) * 10; + tmp /= table[i - 1].ocv - table[i].ocv; + cap = tmp + table[i].capacity * 10; + } else if (i == 0) { + cap = table[0].capacity * 10; + } else { + cap = table[table_len - 1].capacity * 10; + } + + if (cap < 0) + cap = 0; + + return cap; +} +EXPORT_SYMBOL_GPL(power_supply_ocv2dcap_simple); + struct power_supply_battery_ocv_table * power_supply_find_ocv2cap_table(struct power_supply_battery_info *info, int temp, int *table_len) @@ -1054,6 +1093,32 @@ int power_supply_batinfo_dcap2ocv(struct power_supply_battery_info *info, } EXPORT_SYMBOL_GPL(power_supply_batinfo_dcap2ocv); +/** + * power_supply_batinfo_ocv2dcap - compute SOC based on OCV and temperature + * @info: pointer to battery information + * @ocv: Open circuit voltage in uV + * @temp: Temperature in Celsius + * + * Use OCV tables in battery info to compute the battery capacity based on + * provided open circuit voltage at given and temperature. + * + * Return: battery capacity correspondinggiven OCV and temperature at 0.1%. + * -EINVAL if OCV table is not present. + */ +int power_supply_batinfo_ocv2dcap(struct power_supply_battery_info *info, + int ocv, int temp) +{ + struct power_supply_battery_ocv_table *table; + int table_len; + + table = power_supply_find_ocv2cap_table(info, temp, &table_len); + if (!table) + return -EINVAL; + + return power_supply_ocv2dcap_simple(table, table_len, ocv); +} +EXPORT_SYMBOL_GPL(power_supply_batinfo_ocv2dcap); + int power_supply_batinfo_ocv2cap(struct power_supply_battery_info *info, int ocv, int temp) { diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index c5118265b3ab..5e6575e97492 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -444,6 +444,10 @@ extern int power_supply_ocv2cap_simple(struct power_supply_battery_ocv_table *ta int table_len, int ocv); int power_supply_dcap2ocv_simple(struct power_supply_battery_ocv_table *table, int table_len, int dcap); +int power_supply_ocv2dcap_simple(struct power_supply_battery_ocv_table *table, + int table_len, int ocv); +int power_supply_batinfo_ocv2dcap(struct power_supply_battery_info *info, + int ocv, int temp); extern struct power_supply_battery_ocv_table * power_supply_find_ocv2cap_table(struct power_supply_battery_info *info,
The battery info functions computing the state-of-charge (SOC) based on open-circuit-voltage (OCV) are returning SOC using units of 1%. Some capacity estimation computations require higher accuracy. Add functions that return SOC using units of 0.1% to reduce rounding error. Signed-off-by: Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com> --- RFCv3 changes: - Kerneldoc fixes --- drivers/power/supply/power_supply_core.c | 65 ++++++++++++++++++++++++ include/linux/power_supply.h | 4 ++ 2 files changed, 69 insertions(+)