summaryrefslogtreecommitdiff
path: root/drivers/power
diff options
context:
space:
mode:
authorPaul Kocialkowski <contact@paulk.fr>2017-04-25 17:09:05 +0200
committerSebastian Reichel <sre@kernel.org>2017-05-01 12:45:43 +0200
commit7f93e1fa032bb5ee19b868b9649bc98c82553003 (patch)
tree8a341c417abf7b2009a4352c5ac1011e17926fb3 /drivers/power
parent4df2cce4722d35eb35bb9371e7c9a600a84558f9 (diff)
power: supply: sbs-battery: Correct supply status with current draw
The status reported directly by the battery controller is not always reliable and should be corrected based on the current draw information. This implements such a correction with a dedicated function, called where the supply status is retrieved. Signed-off-by: Paul Kocialkowski <contact@paulk.fr> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/supply/sbs-battery.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/power/supply/sbs-battery.c b/drivers/power/supply/sbs-battery.c
index 7fd0f308189f..171c701a2d49 100644
--- a/drivers/power/supply/sbs-battery.c
+++ b/drivers/power/supply/sbs-battery.c
@@ -295,6 +295,31 @@ static int sbs_write_word_data(struct i2c_client *client, u8 address,
return 0;
}
+static int sbs_status_correct(struct i2c_client *client, int *intval)
+{
+ int ret;
+
+ ret = sbs_read_word_data(client, sbs_data[REG_CURRENT].addr);
+ if (ret < 0)
+ return ret;
+
+ ret = (s16)ret;
+
+ /* Not drawing current means full (cannot be not charging) */
+ if (ret == 0)
+ *intval = POWER_SUPPLY_STATUS_FULL;
+
+ if (*intval == POWER_SUPPLY_STATUS_FULL) {
+ /* Drawing or providing current when full */
+ if (ret > 0)
+ *intval = POWER_SUPPLY_STATUS_CHARGING;
+ else if (ret < 0)
+ *intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ }
+
+ return 0;
+}
+
static int sbs_get_battery_presence_and_health(
struct i2c_client *client, enum power_supply_property psp,
union power_supply_propval *val)
@@ -401,6 +426,8 @@ static int sbs_get_battery_property(struct i2c_client *client,
else
val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ sbs_status_correct(client, &val->intval);
+
if (chip->poll_time == 0)
chip->last_state = val->intval;
else if (chip->last_state != val->intval) {
@@ -721,6 +748,8 @@ static void sbs_delayed_work(struct work_struct *work)
else
ret = POWER_SUPPLY_STATUS_CHARGING;
+ sbs_status_correct(chip->client, &ret);
+
if (chip->last_state != ret) {
chip->poll_time = 0;
power_supply_changed(chip->power_supply);