summaryrefslogtreecommitdiff
path: root/drivers/power
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2022-01-29 01:49:20 +0100
committerSebastian Reichel <sebastian.reichel@collabora.com>2022-02-11 20:24:53 +0100
commit965a990427b313a118865df1d33b82e30500c79a (patch)
tree98bb05dc9c9df96ca9ce3bce7d95f50efc600b29 /drivers/power
parent673b50322bb6e31f0e917eeb321648092528635a (diff)
power: supply: ab8500_fg: Safeguard compensated voltage
In some cases when the platform is dissapating more than 500mA the voltage measurements and compensation will become instable. Add a parameter to bail out of the voltage measurement if this happens. This code was found in a Samsung vendor tree. Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/supply/ab8500_fg.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c
index 1797518c4b0e..c659fdc8babd 100644
--- a/drivers/power/supply/ab8500_fg.c
+++ b/drivers/power/supply/ab8500_fg.c
@@ -46,6 +46,8 @@
#define NBR_AVG_SAMPLES 20
#define WAIT_FOR_INST_CURRENT_MAX 70
+/* Currents higher than -500mA (dissipating) will make compensation unstable */
+#define IGNORE_VBAT_HIGHCUR -500000
#define LOW_BAT_CHECK_INTERVAL (HZ / 16) /* 62.5 ms */
@@ -911,12 +913,13 @@ static int ab8500_fg_battery_resistance(struct ab8500_fg *di)
/**
* ab8500_load_comp_fg_bat_voltage() - get load compensated battery voltage
* @di: pointer to the ab8500_fg structure
+ * @always: always return a voltage, also uncompensated
*
* Returns compensated battery voltage (on success) else error code.
* If always is specified, we always return a voltage but it may be
* uncompensated.
*/
-static int ab8500_load_comp_fg_bat_voltage(struct ab8500_fg *di)
+static int ab8500_load_comp_fg_bat_voltage(struct ab8500_fg *di, bool always)
{
int i = 0;
int vbat_uv = 0;
@@ -941,6 +944,14 @@ static int ab8500_load_comp_fg_bat_voltage(struct ab8500_fg *di)
ab8500_fg_inst_curr_finalize(di, &di->inst_curr_ua);
+ /*
+ * If there is too high current dissipation, the compensation cannot be
+ * trusted so return an error unless we must return something here, as
+ * enforced by the "always" parameter.
+ */
+ if (!always && di->inst_curr_ua < IGNORE_VBAT_HIGHCUR)
+ return -EINVAL;
+
vbat_uv = vbat_uv / i;
/* Next we apply voltage compensation from internal resistance */
@@ -964,7 +975,7 @@ static int ab8500_fg_load_comp_volt_to_capacity(struct ab8500_fg *di)
{
int vbat_comp_uv;
- vbat_comp_uv = ab8500_load_comp_fg_bat_voltage(di);
+ vbat_comp_uv = ab8500_load_comp_fg_bat_voltage(di, true);
return ab8500_fg_volt_to_capacity(di, vbat_comp_uv);
}