From patchwork Tue Nov 16 12:27:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Vaittinen, Matti" X-Patchwork-Id: 12622297 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DED01C433EF for ; Tue, 16 Nov 2021 12:27:51 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C834A61B3D for ; Tue, 16 Nov 2021 12:27:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236200AbhKPMar (ORCPT ); Tue, 16 Nov 2021 07:30:47 -0500 Received: from mail-lj1-f180.google.com ([209.85.208.180]:34527 "EHLO mail-lj1-f180.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236215AbhKPMaq (ORCPT ); Tue, 16 Nov 2021 07:30:46 -0500 Received: by mail-lj1-f180.google.com with SMTP id k23so14776263lje.1; Tue, 16 Nov 2021 04:27:49 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=FmTMfd20hULSCl+7yMqqQJbPyDaNAZmbbo2TAAoDw2E=; b=zwDfv9DjngjH3j/ctAG9XXDQxX5b3WQaTyedkk6RPrYag0foN0g5jiJFOfjK51zGfw UGvP5dKtm1QsBWi9/KQcPMQ0vmmcXWDZCtNkszuWyfOwu8GsXrC3ONBTwiC4RVMJEQ/K e1DdXrAHd/VyyGUXT3Y2S6n7qReZctOBg/IjA6nvbnnYqjRX6oOSN8bx8bgbc1jPXVEV GXS5lgqWGHgb/+XDbNhNOpsuJhNbzr0CmKks3q3zbwrOOsmMUNycOWK4DE+DBZrKZTXJ t6CojzlOHbFHX5G9vLIQ8b7bdLkgRxgJiMfk61HM/oTkkJdwhyDVTT3bnES0MealhXDZ ASMA== X-Gm-Message-State: AOAM530eMxGt/d+36oB7OpQAlDgaWFEWrt6KgimDifdgVvCLYexXNd/w dGfk3EN6mtYvKe0NqAnTyGI= X-Google-Smtp-Source: ABdhPJwwHvXfBpPHnGHb13uz+BAtjbE6+rk2VK8KQ9qO8unppGwXzMBU9/0JniLgBGOKl44xj+/byg== X-Received: by 2002:a05:651c:905:: with SMTP id e5mr6684944ljq.238.1637065668414; Tue, 16 Nov 2021 04:27:48 -0800 (PST) Received: from fedora (dc73szyyyyyyyyyyyyycy-3.rev.dnainternet.fi. [2001:14ba:16ee:fa00::4]) by smtp.gmail.com with ESMTPSA id w36sm1751324lfu.81.2021.11.16.04.27.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 16 Nov 2021 04:27:47 -0800 (PST) Date: Tue, 16 Nov 2021 14:27:40 +0200 From: Matti Vaittinen To: Matti Vaittinen , Matti Vaittinen Cc: Sebastian Reichel , Rob Herring , Matti Vaittinen , Lee Jones , Linus Walleij , rostokus@gmail.com, fan.chen@mediatek.com, linux-pm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-power@fi.rohmeurope.com Subject: [RFC PATCH v3 6/9] power: supply: Add batinfo functions for OCV to SOC with 0.1% accuracy Message-ID: <392c7aa891d466bc4df06a076090150319e0e7dc.1637061794.git.matti.vaittinen@fi.rohmeurope.com> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org 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 --- RFCv3 changes: - Kerneldoc fixes --- drivers/power/supply/power_supply_core.c | 65 ++++++++++++++++++++++++ include/linux/power_supply.h | 4 ++ 2 files changed, 69 insertions(+) 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,