All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] power: supply: axp288_fuel_gauge: Fix full status reporting
@ 2018-02-15 14:00 Hans de Goede
  2018-02-15 14:00 ` [PATCH 2/2] power: supply: axp288_fuel_gauge: Remove polling from the driver Hans de Goede
  0 siblings, 1 reply; 2+ messages in thread
From: Hans de Goede @ 2018-02-15 14:00 UTC (permalink / raw)
  To: Sebastian Reichel; +Cc: Hans de Goede, Chen-Yu Tsai, linux-pm

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>
---
 drivers/power/supply/axp288_fuel_gauge.c | 47 ++++++++++++++++++++++++--------
 1 file changed, 35 insertions(+), 12 deletions(-)

diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c
index 4cc6e038dfdd..e58aad011eb7 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
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [PATCH 2/2] power: supply: axp288_fuel_gauge: Remove polling from the driver
  2018-02-15 14:00 [PATCH 1/2] power: supply: axp288_fuel_gauge: Fix full status reporting Hans de Goede
@ 2018-02-15 14:00 ` Hans de Goede
  0 siblings, 0 replies; 2+ messages in thread
From: Hans de Goede @ 2018-02-15 14:00 UTC (permalink / raw)
  To: Sebastian Reichel; +Cc: Hans de Goede, Chen-Yu Tsai, linux-pm

Userspace class/power_supply consumers such as upower, already know some
supplies need to be polled to get up2date info. Doing this in the kernel
and then waking up userspace just causes unnecessary wakeups and i2c
transfers.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 drivers/power/supply/axp288_fuel_gauge.c | 16 ----------------
 1 file changed, 16 deletions(-)

diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c
index e58aad011eb7..c5a24aee901c 100644
--- a/drivers/power/supply/axp288_fuel_gauge.c
+++ b/drivers/power/supply/axp288_fuel_gauge.c
@@ -24,7 +24,6 @@
 #include <linux/regmap.h>
 #include <linux/jiffies.h>
 #include <linux/interrupt.h>
-#include <linux/workqueue.h>
 #include <linux/mfd/axp20x.h>
 #include <linux/platform_device.h>
 #include <linux/power_supply.h>
@@ -88,7 +87,6 @@
 #define FG_LOW_CAP_CRIT_THR			4   /* 4 perc */
 #define FG_LOW_CAP_SHDN_THR			0   /* 0 perc */
 
-#define STATUS_MON_DELAY_JIFFIES    (HZ * 60)   /*60 sec */
 #define NR_RETRY_CNT    3
 #define DEV_NAME	"axp288_fuel_gauge"
 
@@ -128,7 +126,6 @@ struct axp288_fg_info {
 	struct mutex lock;
 	int status;
 	int max_volt;
-	struct delayed_work status_monitor;
 	struct dentry *debug_file;
 };
 
@@ -592,16 +589,6 @@ static int fuel_gauge_property_is_writeable(struct power_supply *psy,
 	return ret;
 }
 
-static void fuel_gauge_status_monitor(struct work_struct *work)
-{
-	struct axp288_fg_info *info = container_of(work,
-		struct axp288_fg_info, status_monitor.work);
-
-	fuel_gauge_get_status(info);
-	power_supply_changed(info->bat);
-	schedule_delayed_work(&info->status_monitor, STATUS_MON_DELAY_JIFFIES);
-}
-
 static irqreturn_t fuel_gauge_thread_handler(int irq, void *dev)
 {
 	struct axp288_fg_info *info = dev;
@@ -764,7 +751,6 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, info);
 
 	mutex_init(&info->lock);
-	INIT_DELAYED_WORK(&info->status_monitor, fuel_gauge_status_monitor);
 
 	for (i = 0; i < IIO_CHANNEL_NUM; i++) {
 		/*
@@ -824,7 +810,6 @@ static int axp288_fuel_gauge_probe(struct platform_device *pdev)
 
 	fuel_gauge_create_debugfs(info);
 	fuel_gauge_init_irq(info);
-	schedule_delayed_work(&info->status_monitor, STATUS_MON_DELAY_JIFFIES);
 
 	return 0;
 
@@ -847,7 +832,6 @@ static int axp288_fuel_gauge_remove(struct platform_device *pdev)
 	struct axp288_fg_info *info = platform_get_drvdata(pdev);
 	int i;
 
-	cancel_delayed_work_sync(&info->status_monitor);
 	power_supply_unregister(info->bat);
 	fuel_gauge_remove_debugfs(info);
 
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2018-02-15 14:00 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-15 14:00 [PATCH 1/2] power: supply: axp288_fuel_gauge: Fix full status reporting Hans de Goede
2018-02-15 14:00 ` [PATCH 2/2] power: supply: axp288_fuel_gauge: Remove polling from the driver Hans de Goede

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.