summaryrefslogtreecommitdiff
path: root/drivers/power
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2018-02-15 17:00:36 +0300
committerSebastian Reichel <sebastian.reichel@collabora.co.uk>2018-03-09 20:02:20 +0300
commitf451655c722b6f8a15d152d7912ab8526a3fe8bd (patch)
tree6d1d10364588265f0edca8afea71154a8cb4c998 /drivers/power
parent7638eb5666eb3c216dfdef63b573933ed9740676 (diff)
downloadlinux-f451655c722b6f8a15d152d7912ab8526a3fe8bd.tar.xz
power: supply: axp288_fuel_gauge: Fix full status reporting
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>
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/supply/axp288_fuel_gauge.c47
1 files changed, 35 insertions, 12 deletions
diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c
index 903891a9bcf0..fd8f0b2210bc 100644
--- a/drivers/power/supply/axp288_fuel_gauge.c
+++ b/drivers/power/supply/axp288_fuel_gauge.c
@@ -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