power: supply: axp288_fuel_gauge: Fix full status reporting
authorHans de Goede <hdegoede@redhat.com>
Thu, 15 Feb 2018 14:00:36 +0000 (15:00 +0100)
committerSebastian Reichel <sebastian.reichel@collabora.co.uk>
Fri, 9 Mar 2018 17:02:20 +0000 (18:02 +0100)
Commit 2b5a4b4bf222 ("power: supply: axp288_fuel_gauge: Rework
get_status()"), switched from 0A current detection to using the capacity
register for full detection.

It turns out this fixes full reporting on some devices which keep trickle
charging long after the capacity register reach 100%, but breaks it on
some other devices where the charger stops charging before the capacity
register reaches 100%. This commit fixes this by also checking for
0A current when the reported capacity is above 90%.

Fixes: 2b5a4b4bf222 ("psy: axp288_fuel_gauge: Rework get_status()")
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
drivers/power/supply/axp288_fuel_gauge.c

index 903891a..fd8f0b2 100644 (file)
@@ -343,7 +343,7 @@ static inline void fuel_gauge_remove_debugfs(struct axp288_fg_info *info)
 
 static void fuel_gauge_get_status(struct axp288_fg_info *info)
 {
-       int pwr_stat, fg_res;
+       int pwr_stat, fg_res, curr, ret;
 
        pwr_stat = fuel_gauge_reg_readb(info, AXP20X_PWR_INPUT_STATUS);
        if (pwr_stat < 0) {
@@ -353,19 +353,42 @@ static void fuel_gauge_get_status(struct axp288_fg_info *info)
        }
 
        /* Report full if Vbus is valid and the reported capacity is 100% */
-       if (pwr_stat & PS_STAT_VBUS_VALID) {
-               fg_res = fuel_gauge_reg_readb(info, AXP20X_FG_RES);
-               if (fg_res < 0) {
-                       dev_err(&info->pdev->dev,
-                               "FG RES read failed: %d\n", fg_res);
-                       return;
-               }
-               if (fg_res == (FG_REP_CAP_VALID | 100)) {
-                       info->status = POWER_SUPPLY_STATUS_FULL;
-                       return;
-               }
+       if (!(pwr_stat & PS_STAT_VBUS_VALID))
+               goto not_full;
+
+       fg_res = fuel_gauge_reg_readb(info, AXP20X_FG_RES);
+       if (fg_res < 0) {
+               dev_err(&info->pdev->dev, "FG RES read failed: %d\n", fg_res);
+               return;
+       }
+       if (!(fg_res & FG_REP_CAP_VALID))
+               goto not_full;
+
+       fg_res &= ~FG_REP_CAP_VALID;
+       if (fg_res == 100) {
+               info->status = POWER_SUPPLY_STATUS_FULL;
+               return;
+       }
+
+       /*
+        * Sometimes the charger turns itself off before fg-res reaches 100%.
+        * When this happens the AXP288 reports a not-charging status and
+        * 0 mA discharge current.
+        */
+       if (fg_res < 90 || (pwr_stat & PS_STAT_BAT_CHRG_DIR))
+               goto not_full;
+
+       ret = iio_read_channel_raw(info->iio_channel[BAT_D_CURR], &curr);
+       if (ret < 0) {
+               dev_err(&info->pdev->dev, "FG get current failed: %d\n", ret);
+               return;
+       }
+       if (curr == 0) {
+               info->status = POWER_SUPPLY_STATUS_FULL;
+               return;
        }
 
+not_full:
        if (pwr_stat & PS_STAT_BAT_CHRG_DIR)
                info->status = POWER_SUPPLY_STATUS_CHARGING;
        else