From ede666158174d24839981e4dc029d212424f60f2 Mon Sep 17 00:00:00 2001
From: Martyn Welch <martyn@welchs.me.uk>
Date: Mon, 26 Feb 2018 19:00:32 +0000
Subject: [PATCH] Add support for presence detection, actual and remaining
 battery capacity

The battery monitor firmware now has support for detecting battery presence
and reporting actual and remaining battery capacity.

This patch removes the current support for battery presence detection, relying
in the battery monitor to provide this information instead. In adding reporting
for full capacity and current capacity, the variable used for current state of
charge is renamed to avoid confusion.

Signed-off-by: Martyn Welch <martyn@welchs.me.uk>
---
 drivers/power/supply/tcl-sbs-battery.c | 58 ++++++++++++++------------
 1 file changed, 31 insertions(+), 27 deletions(-)

diff --git a/drivers/power/supply/tcl-sbs-battery.c b/drivers/power/supply/tcl-sbs-battery.c
index 7594d80e50ff..5d4f2cf63fd6 100644
--- a/drivers/power/supply/tcl-sbs-battery.c
+++ b/drivers/power/supply/tcl-sbs-battery.c
@@ -49,12 +49,17 @@
 /* Battery Status, 2 bytes */
 #define SBS_BATTERY_STATUS		0x74
 # define BATTERY_STATUS_CHARGING	0
+# define BATTERY_STATUS_NOT_PRESENT	BIT(7)
 # define BATTERY_STATUS_DISCHARGING	BIT(6)
 # define BATTERY_STATUS_FULLY_CHARGED	BIT(5)
 /* State of charge in percentage, 1 byte */
 #define SBS_STATE_OF_CHARGE		0x76
 /* Cycle count, 2 bytes */
 #define SBS_CYCLE_COUNT			0x77
+/* Remaining capacity, 2 bytes */
+#define SBS_REM_CAPACITY		0x79
+/* Actual capcacity, 2 bytes */
+#define SBS_ACTUAL_CAPACITY		0x7b
 /* Firmware version, 1 byte */
 #define SBS_FIRMWARE_VERSION		0x7d
 
@@ -82,8 +87,10 @@ struct tcl_sbs_battery_data {
 	int voltage_uvolt;		/* units of uV */
 	int current_uamp;		/* units of uA */
 	int rated_capacity;		/* units of µAh */
+	int full_capacity;		/* units of µAh */
+	int rem_capacity;		/* units of µAh */
 	int cycle_count;
-	int rem_capacity;		/* percentage */
+	int charge_state;		/* percentage */
 	int life_sec;			/* units of seconds */
 	int status;			/* state of charge */
 	int design_voltage;		/* units of uV */
@@ -201,6 +208,16 @@ static int tcl_sbs_battery_read_status(struct tcl_sbs_battery_data *data)
 				data->map[SBS_PACK_CAPACITY]);
 	data->rated_capacity *= 1000;	/* convert from mAh to uAh */
 
+	data->full_capacity = (u16)((data->map[SBS_ACTUAL_CAPACITY + 1] << 8) |
+				data->map[SBS_ACTUAL_CAPACITY]);
+	data->full_capacity *= 1000;	/* convert from mAh to uAh */
+
+	data->rem_capacity = (u16)((data->map[SBS_REM_CAPACITY + 1] << 8) |
+				data->map[SBS_REM_CAPACITY]);
+	data->rem_capacity *= 1000;	/* convert from mAh to uAh */
+
+	data->presence = true;
+
 	uval = (u16)((data->map[SBS_BATTERY_STATUS + 1] << 8) |
 		data->map[SBS_BATTERY_STATUS]);
 	if (uval == BATTERY_STATUS_CHARGING)
@@ -209,15 +226,17 @@ static int tcl_sbs_battery_read_status(struct tcl_sbs_battery_data *data)
 		data->status = POWER_SUPPLY_STATUS_DISCHARGING;
 	else if (uval == BATTERY_STATUS_FULLY_CHARGED)
 		data->status = POWER_SUPPLY_STATUS_FULL;
+	else if (uval == BATTERY_STATUS_NOT_PRESENT)
+		data->presence = false;
 	else
 		data->status = POWER_SUPPLY_STATUS_UNKNOWN;
 
 	data->cycle_count = (u16)((data->map[SBS_CYCLE_COUNT + 1] << 8) |
 			     data->map[SBS_CYCLE_COUNT]);
 
-	data->rem_capacity = data->map[SBS_STATE_OF_CHARGE];
+	data->charge_state = data->map[SBS_STATE_OF_CHARGE];
 
-	uval = (data->rem_capacity * (data->rated_capacity / 1000)) / 100;
+	uval = (data->charge_state * (data->full_capacity / 1000)) / 100;
 	if (data->current_uamp)
 		data->life_sec = (3600l * uval) / (data->current_uamp / 1000);
 
@@ -247,28 +266,6 @@ static char *tcl_sbs_battery_supplied_to[] = {
 	"tps65217-charger",
 };
 
-/*
- * is_batt_present - See if the battery presents in place.
- */
-static bool is_batt_present(struct tcl_sbs_battery_data *data)
-{
-	union power_supply_propval val;
-	struct power_supply *psy;
-	bool present = false;
-	int ret;
-
-	psy = power_supply_get_by_name(tcl_sbs_battery_supplied_to[0]);
-	if (!psy)
-		return false;
-
-	ret = power_supply_get_property(psy, POWER_SUPPLY_PROP_PRESENT, &val);
-	if (ret == 0 && val.intval)
-		present = true;
-
-	power_supply_put(psy);
-
-	return present;
-}
 
 static int tcl_sbs_battery_get_property(struct power_supply *psy,
 					  enum power_supply_property psp,
@@ -289,7 +286,6 @@ static int tcl_sbs_battery_get_property(struct power_supply *psy,
 	}
 
 	if (!data->presence) {
-		data->presence = is_batt_present(data);
 		return -ENODEV;
 	}
 
@@ -313,11 +309,17 @@ static int tcl_sbs_battery_get_property(struct power_supply *psy,
 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
 		val->intval = data->rated_capacity;
 		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+		val->intval = data->full_capacity;
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_NOW:
+		val->intval = data->rem_capacity;
+		break;
 	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
 		val->intval = data->life_sec;
 		break;
 	case POWER_SUPPLY_PROP_CAPACITY:
-		val->intval = data->rem_capacity;
+		val->intval = data->charge_state;
 		break;
 	case POWER_SUPPLY_PROP_TECHNOLOGY:
 		val->intval = data->technology;
@@ -349,6 +351,8 @@ static enum power_supply_property tcl_sbs_battery_props[] = {
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
 	POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
 	POWER_SUPPLY_PROP_CAPACITY,
 	POWER_SUPPLY_PROP_TECHNOLOGY,
-- 
GitLab