Skip to contentSkip to conversation

Updates for cpcap charger and battery

PATCH In review Tony Lindgren 2 participants 17 messages Jan 10, 2021 – Jan 14, 2021 Power supply

lore
Share & tools
lore
#0 lore raw

cover Updates for cpcap charger and battery

Hi all,

Here's a series of patches to update cpcap charger and battery support for showing capacity. I've reorganized and cleaned up the patches posted earlier and simplified few things in the process compared to the earlier patches. The first few patches contain minor fixes that can wait for the merge window no problem.

The battery capacity is only available if charge_full is written via sysfs based on calibration, and then a battery low or high value is seen. This follows what we already have for n900.

Regards,

Tony

Arthur Demchenkov (4):
power: supply: cpcap-battery: Add charge_full property
power: supply: cpcap-battery: Keep track of state for capacity
reporting
power: supply: cpcap-battery: Implement capacity reporting
power: supply: cpcap-battery: Add charge_now property

Pavel Machek (2):
power: supply: cpcap-charger: Limiting charge current on Droid 4
power: supply: cpcap-battery: Fix typo

Tony Lindgren (9):
power: supply: cpcap-charger: Fix missing power_supply_put()
power: supply: cpcap-battery: Fix missing power_supply_put()
power: supply: cpcap-charger: Fix flakey reboot with charger connected
power: supply: cpcap-charger: Make VBUS already provided debug only
power: supply: cpcap-charger: Use standard enumeration
power: supply: cpcap-charger: Drop internal state and use generic
stats
power: supply: cpcap-charger: Simplify things with enable and disable
power: supply: cpcap-charger: Provide state updates for battery from
charger
power: supply: cpcap-battery: Use charger status for battery full
detection

 drivers/power/supply/cpcap-battery.c | 178 ++++++++++++++++--
 drivers/power/supply/cpcap-charger.c | 259 +++++++++++++++++----------
 2 files changed, 329 insertions(+), 108 deletions(-)
Signature · 1 line
2.30.0
#1 lore raw

PATCH 1/15 power: supply: cpcap-charger: Fix missing power_supply_put()

Fix missing power_supply_put().

Cc Arthur Demchenkov <[email protected]>
Cc Carl Philipp Klemm <[email protected]>
Cc Merlijn Wajer <[email protected]>
Cc Pavel Machek <[email protected]>
Fixes 688ea049233 ("power: supply: cpcap-charger: Allow changing constant charge voltage")
---
 drivers/power/supply/cpcap-charger.c | 1 +
 1 file changed, 1 insertion(+)
drivers/power/supply/cpcap-charger.c +1 -0
@@ -302,6 +302,7 @@ cpcap_charger_get_bat_const_charge_voltage(struct cpcap_charger_ddata *ddata)
 		if (!error)
 			voltage = prop.intval;
 	}
+	power_supply_put(battery);
 
 	return voltage;
 }
Signature · 1 line
2.30.0
#2 lore raw

PATCH 2/15 power: supply: cpcap-battery: Fix missing power_supply_put()

In reply to Tony Lindgren

Fix missing power_supply_put().

Cc Arthur Demchenkov <[email protected]>
Cc Carl Philipp Klemm <[email protected]>
Cc Merlijn Wajer <[email protected]>
Cc Pavel Machek <[email protected]>
Fixes b0134cc14b9 ("power: supply: cpcap-battery: Fix handling of lowered charger voltage")
---
 drivers/power/supply/cpcap-battery.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/power/supply/cpcap-battery.c +7 -3
@@ -568,17 +568,21 @@ static int cpcap_battery_update_charger(struct cpcap_battery_ddata *ddata,
 				POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
 				&prop);
 	if (error)
-		return error;
+		goto out_put;
 
 	/* Allow charger const voltage lower than battery const voltage */
 	if (const_charge_voltage > prop.intval)
-		return 0;
+		goto out_put;
 
 	val.intval = const_charge_voltage;
 
-	return power_supply_set_property(charger,
+	error = power_supply_set_property(charger,
 			POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
 			&val);
+out_put:
+	power_supply_put(charger);
+
+	return error;
 }
 
 static int cpcap_battery_set_property(struct power_supply *psy,
Signature · 1 line
2.30.0
#3 lore raw

PATCH 3/15 power: supply: cpcap-charger: Fix flakey reboot with charger connected

In reply to Tony Lindgren

If we have a USB charger connected, reboot is flakey and often fails to reboot the device with the charger LED staying on.

Let's fix this by implementing .shutdown.

Cc Arthur Demchenkov <[email protected]>
Cc Carl Philipp Klemm <[email protected]>
Cc Merlijn Wajer <[email protected]>
Cc Pavel Machek <[email protected]>
---
 drivers/power/supply/cpcap-charger.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/power/supply/cpcap-charger.c +7 -1
@@ -886,7 +886,7 @@ static int cpcap_charger_probe(struct platform_device *pdev)
 	return 0;
 }
 
-static int cpcap_charger_remove(struct platform_device *pdev)
+static void cpcap_charger_shutdown(struct platform_device *pdev)
 {
 	struct cpcap_charger_ddata *ddata = platform_get_drvdata(pdev);
 	int error;
@@ -903,6 +903,11 @@ static int cpcap_charger_remove(struct platform_device *pdev)
 			 error);
 	cancel_delayed_work_sync(&ddata->vbus_work);
 	cancel_delayed_work_sync(&ddata->detect_work);
+}
+
+static int cpcap_charger_remove(struct platform_device *pdev)
+{
+	cpcap_charger_shutdown(pdev);
 
 	return 0;
 }
@@ -913,6 +918,7 @@ static struct platform_driver cpcap_charger_driver = {
 		.name	= "cpcap-charger",
 		.of_match_table = of_match_ptr(cpcap_charger_id_table),
 	},
+	.shutdown = cpcap_charger_shutdown,
 	.remove	= cpcap_charger_remove,
 };
 module_platform_driver(cpcap_charger_driver);
Signature · 1 line
2.30.0
#4 lore raw

PATCH 4/15 power: supply: cpcap-charger: Make VBUS already provided debug only

In reply to Tony Lindgren

This should be only shown when debug is enabled.

Cc Arthur Demchenkov <[email protected]>
Cc Carl Philipp Klemm <[email protected]>
Cc Merlijn Wajer <[email protected]>
Cc Pavel Machek <[email protected]>
---
 drivers/power/supply/cpcap-charger.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/power/supply/cpcap-charger.c +1 -1
@@ -434,7 +434,7 @@ static void cpcap_charger_vbus_work(struct work_struct *work)
 	if (ddata->vbus_enabled) {
 		vbus = cpcap_charger_vbus_valid(ddata);
 		if (vbus) {
-			dev_info(ddata->dev, "VBUS already provided\n");
+			dev_dbg(ddata->dev, "VBUS already provided\n");
 
 			return;
 		}
Signature · 1 line
2.30.0
#5 lore raw

PATCH 5/15 power: supply: cpcap-charger: Use standard enumeration

In reply to Tony Lindgren

Just get rid of the custom enumeration if favor of the standard one.

Cc Arthur Demchenkov <[email protected]>
Cc Carl Philipp Klemm <[email protected]>
Cc Merlijn Wajer <[email protected]>
Cc Pavel Machek <[email protected]>
---
 drivers/power/supply/cpcap-charger.c | 39 ++++++++++++++--------------
 1 file changed, 19 insertions(+), 20 deletions(-)
drivers/power/supply/cpcap-charger.c +19 -20
@@ -120,13 +120,6 @@ enum {
 	CPCAP_CHARGER_IIO_NR,
 };
 
-enum {
-	CPCAP_CHARGER_DISCONNECTED,
-	CPCAP_CHARGER_DETECTING,
-	CPCAP_CHARGER_CHARGING,
-	CPCAP_CHARGER_DONE,
-};
-
 struct cpcap_charger_ddata {
 	struct device *dev;
 	struct regmap *reg;
@@ -533,7 +526,7 @@ static void cpcap_charger_update_state(struct cpcap_charger_ddata *ddata,
 {
 	const char *status;
 
-	if (state > CPCAP_CHARGER_DONE) {
+	if (state > POWER_SUPPLY_STATUS_FULL) {
 		dev_warn(ddata->dev, "unknown state: %i\n", state);
 
 		return;
@@ -542,16 +535,16 @@ static void cpcap_charger_update_state(struct cpcap_charger_ddata *ddata,
 	ddata->state = state;
 
 	switch (state) {
-	case CPCAP_CHARGER_DISCONNECTED:
+	case POWER_SUPPLY_STATUS_DISCHARGING:
 		status = "DISCONNECTED";
 		break;
-	case CPCAP_CHARGER_DETECTING:
+	case POWER_SUPPLY_STATUS_NOT_CHARGING:
 		status = "DETECTING";
 		break;
-	case CPCAP_CHARGER_CHARGING:
+	case POWER_SUPPLY_STATUS_CHARGING:
 		status = "CHARGING";
 		break;
-	case CPCAP_CHARGER_DONE:
+	case POWER_SUPPLY_STATUS_FULL:
 		status = "DONE";
 		break;
 	default:
@@ -616,7 +609,8 @@ static void cpcap_usb_detect(struct work_struct *work)
 
 	/* Just init the state if a charger is connected with no chrg_det set */
 	if (!s.chrg_det && s.chrgcurr1 && s.vbusvld) {
-		cpcap_charger_update_state(ddata, CPCAP_CHARGER_DETECTING);
+		cpcap_charger_update_state(ddata,
+					   POWER_SUPPLY_STATUS_NOT_CHARGING);
 
 		return;
 	}
@@ -626,7 +620,8 @@ static void cpcap_usb_detect(struct work_struct *work)
 	 * charged to 4.35V by Android. Try again in 10 minutes.
 	 */
 	if (cpcap_charger_get_charge_voltage(ddata) > ddata->voltage) {
-		cpcap_charger_disconnect(ddata, CPCAP_CHARGER_DETECTING,
+		cpcap_charger_disconnect(ddata,
+					 POWER_SUPPLY_STATUS_NOT_CHARGING,
 					 HZ * 60 * 10);
 
 		return;
@@ -634,19 +629,21 @@ static void cpcap_usb_detect(struct work_struct *work)
 
 	/* Throttle chrgcurr2 interrupt for charger done and retry */
 	switch (ddata->state) {
-	case CPCAP_CHARGER_CHARGING:
+	case POWER_SUPPLY_STATUS_CHARGING:
 		if (s.chrgcurr2)
 			break;
 		if (s.chrgcurr1 && s.vbusvld) {
-			cpcap_charger_disconnect(ddata, CPCAP_CHARGER_DONE,
+			cpcap_charger_disconnect(ddata,
+						 POWER_SUPPLY_STATUS_FULL,
 						 HZ * 5);
 			return;
 		}
 		break;
-	case CPCAP_CHARGER_DONE:
+	case POWER_SUPPLY_STATUS_FULL:
 		if (!s.chrgcurr2)
 			break;
-		cpcap_charger_disconnect(ddata, CPCAP_CHARGER_DETECTING,
+		cpcap_charger_disconnect(ddata,
+					 POWER_SUPPLY_STATUS_NOT_CHARGING,
 					 HZ * 5);
 		return;
 	default:
@@ -669,12 +666,14 @@ static void cpcap_usb_detect(struct work_struct *work)
 						max_current, 0);
 		if (error)
 			goto out_err;
-		cpcap_charger_update_state(ddata, CPCAP_CHARGER_CHARGING);
+		cpcap_charger_update_state(ddata,
+					   POWER_SUPPLY_STATUS_CHARGING);
 	} else {
 		error = cpcap_charger_set_state(ddata, 0, 0, 0);
 		if (error)
 			goto out_err;
-		cpcap_charger_update_state(ddata, CPCAP_CHARGER_DISCONNECTED);
+		cpcap_charger_update_state(ddata,
+					   POWER_SUPPLY_STATUS_DISCHARGING);
 	}
 
 	power_supply_changed(ddata->usb);
Signature · 1 line
2.30.0
#6 lore raw

PATCH 6/15 power: supply: cpcap-charger: Limiting charge current on Droid 4

In reply to Tony Lindgren

From: Pavel Machek <[email protected]>

Droid 4 has same problem as N900: it is often necessary to manually tweak current draw from USB, for example when using thin charging cable.

Cc Arthur Demchenkov <[email protected]>
Cc Carl Philipp Klemm <[email protected]>
Cc Merlijn Wajer <[email protected]>
Cc Pavel Machek <[email protected]>
[[email protected]: rebased, cleaned up whitespace issues, updated comments]
---
 drivers/power/supply/cpcap-charger.c | 49 ++++++++++++++++++++++++----
 1 file changed, 43 insertions(+), 6 deletions(-)
drivers/power/supply/cpcap-charger.c +43 -6
@@ -89,6 +89,8 @@
  * CPCAP_REG_CRM charge currents. These seem to match MC13783UG.pdf
  * values in "Table 8-3. Charge Path Regulator Current Limit
  * Characteristics" for the nominal values.
+ *
+ * Except 70mA and 1.596A and unlimited, these are simply 88.7mA / step.
  */
 #define CPCAP_REG_CRM_ICHRG(val)	(((val) & 0xf) << 0)
 #define CPCAP_REG_CRM_ICHRG_0A000	CPCAP_REG_CRM_ICHRG(0x0)
@@ -140,6 +142,7 @@ struct cpcap_charger_ddata {
 	int status;
 	int state;
 	int voltage;
+	int limit_current;
 };
 
 struct cpcap_interrupt_desc {
@@ -166,6 +169,7 @@ static enum power_supply_property cpcap_charger_props[] = {
 	POWER_SUPPLY_PROP_STATUS,
 	POWER_SUPPLY_PROP_ONLINE,
 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
+	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 };
@@ -229,6 +233,9 @@ static int cpcap_charger_get_property(struct power_supply *psy,
 	case POWER_SUPPLY_PROP_STATUS:
 		val->intval = ddata->status;
 		break;
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+		val->intval = ddata->limit_current;
+		break;
 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
 		val->intval = ddata->voltage;
 		break;
@@ -300,6 +307,26 @@ cpcap_charger_get_bat_const_charge_voltage(struct cpcap_charger_ddata *ddata)
 	return voltage;
 }
 
+static int cpcap_charger_current_to_regval(int microamp)
+{
+	int miliamp = microamp / 1000;
+	int res;
+
+	if (miliamp < 0)
+		return -EINVAL;
+	if (miliamp < 70)
+		return CPCAP_REG_CRM_ICHRG(0x0);
+	if (miliamp < 177)
+		return CPCAP_REG_CRM_ICHRG(0x1);
+	if (miliamp > 1596)
+		return CPCAP_REG_CRM_ICHRG(0xe);
+
+	res = microamp / 88666;
+	if (res > 0xd)
+		res = 0xd;
+	return CPCAP_REG_CRM_ICHRG(res);
+}
+
 static int cpcap_charger_set_property(struct power_supply *psy,
 				      enum power_supply_property psp,
 				      const union power_supply_propval *val)
@@ -308,6 +335,12 @@ static int cpcap_charger_set_property(struct power_supply *psy,
 	int voltage, batvolt;
 
 	switch (psp) {
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+		if (cpcap_charger_current_to_regval(val->intval) < 0)
+			return -EINVAL;
+		ddata->limit_current = val->intval;
+		schedule_delayed_work(&ddata->detect_work, 0);
+		break;
 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
 		voltage = cpcap_charger_match_voltage(val->intval);
 		batvolt = cpcap_charger_get_bat_const_charge_voltage(ddata);
@@ -327,6 +360,7 @@ static int cpcap_charger_property_is_writeable(struct power_supply *psy,
 					       enum power_supply_property psp)
 {
 	switch (psp) {
+	case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
 		return 1;
 	default:
@@ -652,18 +686,20 @@ static void cpcap_usb_detect(struct work_struct *work)
 
 	if (!ddata->feeding_vbus && cpcap_charger_vbus_valid(ddata) &&
 	    s.chrgcurr1) {
-		int max_current;
-		int vchrg;
+		int max_current = 532000;
+		int vchrg, ichrg;
 
 		if (cpcap_charger_battery_found(ddata))
-			max_current = CPCAP_REG_CRM_ICHRG_1A596;
-		else
-			max_current = CPCAP_REG_CRM_ICHRG_0A532;
+			max_current = 1596000;
+
+		if (max_current > ddata->limit_current)
+			max_current = ddata->limit_current;
 
+		ichrg = cpcap_charger_current_to_regval(max_current);
 		vchrg = cpcap_charger_voltage_to_regval(ddata->voltage);
 		error = cpcap_charger_set_state(ddata,
 						CPCAP_REG_CRM_VCHRG(vchrg),
-						max_current, 0);
+						ichrg, 0);
 		if (error)
 			goto out_err;
 		cpcap_charger_update_state(ddata,
@@ -837,6 +873,7 @@ static int cpcap_charger_probe(struct platform_device *pdev)
 
 	ddata->dev = &pdev->dev;
 	ddata->voltage = 4200000;
+	ddata->limit_current = 532000;
 
 	ddata->reg = dev_get_regmap(ddata->dev->parent, NULL);
 	if (!ddata->reg)
Signature · 1 line
2.30.0
#7 lore raw

PATCH 7/15 power: supply: cpcap-charger: Drop internal state and use generic stats

In reply to Tony Lindgren

We currently have both state and status, get rid of state and use generic status instead.

Cc Arthur Demchenkov <[email protected]>
Cc Carl Philipp Klemm <[email protected]>
Cc Merlijn Wajer <[email protected]>
Cc Pavel Machek <[email protected]>
---
 drivers/power/supply/cpcap-charger.c | 81 ++++++++++++++--------------
 1 file changed, 42 insertions(+), 39 deletions(-)
drivers/power/supply/cpcap-charger.c +42 -39
@@ -140,7 +140,6 @@ struct cpcap_charger_ddata {
 	atomic_t active;
 
 	int status;
-	int state;
 	int voltage;
 	int limit_current;
 };
@@ -386,6 +385,39 @@ static void cpcap_charger_set_inductive_path(struct cpcap_charger_ddata *ddata,
 	gpiod_set_value(ddata->gpio[1], enabled);
 }
 
+static void cpcap_charger_update_state(struct cpcap_charger_ddata *ddata,
+				       int state)
+{
+	const char *status;
+
+	if (state > POWER_SUPPLY_STATUS_FULL) {
+		dev_warn(ddata->dev, "unknown state: %i\n", state);
+
+		return;
+	}
+
+	ddata->status = state;
+
+	switch (state) {
+	case POWER_SUPPLY_STATUS_DISCHARGING:
+		status = "DISCONNECTED";
+		break;
+	case POWER_SUPPLY_STATUS_NOT_CHARGING:
+		status = "DETECTING";
+		break;
+	case POWER_SUPPLY_STATUS_CHARGING:
+		status = "CHARGING";
+		break;
+	case POWER_SUPPLY_STATUS_FULL:
+		status = "DONE";
+		break;
+	default:
+		return;
+	}
+
+	dev_dbg(ddata->dev, "state: %s\n", status);
+}
+
 static int cpcap_charger_set_state(struct cpcap_charger_ddata *ddata,
 				   int max_voltage, int charge_current,
 				   int trickle_current)
@@ -402,11 +434,13 @@ static int cpcap_charger_set_state(struct cpcap_charger_ddata *ddata,
 					   CPCAP_REG_CRM_FET_OVRD |
 					   CPCAP_REG_CRM_FET_CTRL);
 		if (error) {
-			ddata->status = POWER_SUPPLY_STATUS_UNKNOWN;
+			cpcap_charger_update_state(ddata,
+						   POWER_SUPPLY_STATUS_UNKNOWN);
 			goto out_err;
 		}
 
-		ddata->status = POWER_SUPPLY_STATUS_DISCHARGING;
+		cpcap_charger_update_state(ddata,
+					   POWER_SUPPLY_STATUS_DISCHARGING);
 
 		return 0;
 	}
@@ -419,11 +453,13 @@ static int cpcap_charger_set_state(struct cpcap_charger_ddata *ddata,
 				   max_voltage |
 				   charge_current);
 	if (error) {
-		ddata->status = POWER_SUPPLY_STATUS_UNKNOWN;
+		cpcap_charger_update_state(ddata,
+					   POWER_SUPPLY_STATUS_UNKNOWN);
 		goto out_err;
 	}
 
-	ddata->status = POWER_SUPPLY_STATUS_CHARGING;
+	cpcap_charger_update_state(ddata,
+				   POWER_SUPPLY_STATUS_CHARGING);
 
 	return 0;
 
@@ -555,39 +591,6 @@ static int cpcap_charger_get_ints_state(struct cpcap_charger_ddata *ddata,
 	return 0;
 }
 
-static void cpcap_charger_update_state(struct cpcap_charger_ddata *ddata,
-				       int state)
-{
-	const char *status;
-
-	if (state > POWER_SUPPLY_STATUS_FULL) {
-		dev_warn(ddata->dev, "unknown state: %i\n", state);
-
-		return;
-	}
-
-	ddata->state = state;
-
-	switch (state) {
-	case POWER_SUPPLY_STATUS_DISCHARGING:
-		status = "DISCONNECTED";
-		break;
-	case POWER_SUPPLY_STATUS_NOT_CHARGING:
-		status = "DETECTING";
-		break;
-	case POWER_SUPPLY_STATUS_CHARGING:
-		status = "CHARGING";
-		break;
-	case POWER_SUPPLY_STATUS_FULL:
-		status = "DONE";
-		break;
-	default:
-		return;
-	}
-
-	dev_dbg(ddata->dev, "state: %s\n", status);
-}
-
 static int cpcap_charger_voltage_to_regval(int voltage)
 {
 	int offset;
@@ -662,7 +665,7 @@ static void cpcap_usb_detect(struct work_struct *work)
 	}
 
 	/* Throttle chrgcurr2 interrupt for charger done and retry */
-	switch (ddata->state) {
+	switch (ddata->status) {
 	case POWER_SUPPLY_STATUS_CHARGING:
 		if (s.chrgcurr2)
 			break;
Signature · 1 line
2.30.0
#8 lore raw

PATCH 8/15 power: supply: cpcap-charger: Simplify things with enable and disable

In reply to Tony Lindgren

Let's turn cpcap_charger_set_state() into separate cpcap_charger_enable() and cpcap_charger_disable() to simplify things, and to allow managing status separately. This can be then used for the follow-up patches to make battery full status behave a bit nicer.

Cc Arthur Demchenkov <[email protected]>
Cc Carl Philipp Klemm <[email protected]>
Cc Merlijn Wajer <[email protected]>
Cc Pavel Machek <[email protected]>
---
 drivers/power/supply/cpcap-charger.c | 81 ++++++++++++++--------------
 1 file changed, 39 insertions(+), 42 deletions(-)
drivers/power/supply/cpcap-charger.c +39 -42
@@ -418,32 +418,30 @@ static void cpcap_charger_update_state(struct cpcap_charger_ddata *ddata,
 	dev_dbg(ddata->dev, "state: %s\n", status);
 }
 
-static int cpcap_charger_set_state(struct cpcap_charger_ddata *ddata,
-				   int max_voltage, int charge_current,
-				   int trickle_current)
+static int cpcap_charger_disable(struct cpcap_charger_ddata *ddata)
 {
-	bool enable;
 	int error;
 
-	enable = (charge_current || trickle_current);
-	dev_dbg(ddata->dev, "%s enable: %i\n", __func__, enable);
+	error = regmap_update_bits(ddata->reg, CPCAP_REG_CRM, 0x3fff,
+				   CPCAP_REG_CRM_FET_OVRD |
+				   CPCAP_REG_CRM_FET_CTRL);
+	if (error)
+		dev_err(ddata->dev, "%s failed with %i\n", __func__, error);
 
-	if (!enable) {
-		error = regmap_update_bits(ddata->reg, CPCAP_REG_CRM,
-					   0x3fff,
-					   CPCAP_REG_CRM_FET_OVRD |
-					   CPCAP_REG_CRM_FET_CTRL);
-		if (error) {
-			cpcap_charger_update_state(ddata,
-						   POWER_SUPPLY_STATUS_UNKNOWN);
-			goto out_err;
-		}
+	return error;
+}
 
-		cpcap_charger_update_state(ddata,
-					   POWER_SUPPLY_STATUS_DISCHARGING);
+static int cpcap_charger_enable(struct cpcap_charger_ddata *ddata,
+				int max_voltage, int charge_current,
+				int trickle_current)
+{
+	int error;
 
-		return 0;
-	}
+	if (!max_voltage || !charge_current)
+		return -EINVAL;
+
+	dev_dbg(ddata->dev, "enable: %i %i %i\n",
+		max_voltage, charge_current, trickle_current);
 
 	error = regmap_update_bits(ddata->reg, CPCAP_REG_CRM, 0x3fff,
 				   CPCAP_REG_CRM_CHRG_LED_EN |
@@ -452,19 +450,8 @@ static int cpcap_charger_set_state(struct cpcap_charger_ddata *ddata,
 				   CPCAP_REG_CRM_FET_CTRL |
 				   max_voltage |
 				   charge_current);
-	if (error) {
-		cpcap_charger_update_state(ddata,
-					   POWER_SUPPLY_STATUS_UNKNOWN);
-		goto out_err;
-	}
-
-	cpcap_charger_update_state(ddata,
-				   POWER_SUPPLY_STATUS_CHARGING);
-
-	return 0;
-
-out_err:
-	dev_err(ddata->dev, "%s failed with %i\n", __func__, error);
+	if (error)
+		dev_err(ddata->dev, "%s failed with %i\n", __func__, error);
 
 	return error;
 }
@@ -506,10 +493,13 @@ static void cpcap_charger_vbus_work(struct work_struct *work)
 		cpcap_charger_set_cable_path(ddata, false);
 		cpcap_charger_set_inductive_path(ddata, false);
 
-		error = cpcap_charger_set_state(ddata, 0, 0, 0);
+		error = cpcap_charger_disable(ddata);
 		if (error)
 			goto out_err;
 
+		cpcap_charger_update_state(ddata,
+					   POWER_SUPPLY_STATUS_DISCHARGING);
+
 		error = regmap_update_bits(ddata->reg, CPCAP_REG_VUSBC,
 					   CPCAP_BIT_VBUS_SWITCH,
 					   CPCAP_BIT_VBUS_SWITCH);
@@ -540,6 +530,7 @@ static void cpcap_charger_vbus_work(struct work_struct *work)
 	return;
 
 out_err:
+	cpcap_charger_update_state(ddata, POWER_SUPPLY_STATUS_UNKNOWN);
 	dev_err(ddata->dev, "%s could not %s vbus: %i\n", __func__,
 		ddata->vbus_enabled ? "enable" : "disable", error);
 }
@@ -622,9 +613,11 @@ static void cpcap_charger_disconnect(struct cpcap_charger_ddata *ddata,
 {
 	int error;
 
-	error = cpcap_charger_set_state(ddata, 0, 0, 0);
-	if (error)
+	error = cpcap_charger_disable(ddata);
+	if (error) {
+		cpcap_charger_update_state(ddata, POWER_SUPPLY_STATUS_UNKNOWN);
 		return;
+	}
 
 	cpcap_charger_update_state(ddata, state);
 	power_supply_changed(ddata->usb);
@@ -700,15 +693,15 @@ static void cpcap_usb_detect(struct work_struct *work)
 
 		ichrg = cpcap_charger_current_to_regval(max_current);
 		vchrg = cpcap_charger_voltage_to_regval(ddata->voltage);
-		error = cpcap_charger_set_state(ddata,
-						CPCAP_REG_CRM_VCHRG(vchrg),
-						ichrg, 0);
+		error = cpcap_charger_enable(ddata,
+					     CPCAP_REG_CRM_VCHRG(vchrg),
+					     ichrg, 0);
 		if (error)
 			goto out_err;
 		cpcap_charger_update_state(ddata,
 					   POWER_SUPPLY_STATUS_CHARGING);
 	} else {
-		error = cpcap_charger_set_state(ddata, 0, 0, 0);
+		error = cpcap_charger_disable(ddata);
 		if (error)
 			goto out_err;
 		cpcap_charger_update_state(ddata,
@@ -719,6 +712,7 @@ static void cpcap_usb_detect(struct work_struct *work)
 	return;
 
 out_err:
+	cpcap_charger_update_state(ddata, POWER_SUPPLY_STATUS_UNKNOWN);
 	dev_err(ddata->dev, "%s failed with %i\n", __func__, error);
 }
 
@@ -936,10 +930,13 @@ static void cpcap_charger_shutdown(struct platform_device *pdev)
 		dev_warn(ddata->dev, "could not clear USB comparator: %i\n",
 			 error);
 
-	error = cpcap_charger_set_state(ddata, 0, 0, 0);
-	if (error)
+	error = cpcap_charger_disable(ddata);
+	if (error) {
+		cpcap_charger_update_state(ddata, POWER_SUPPLY_STATUS_UNKNOWN);
 		dev_warn(ddata->dev, "could not clear charger: %i\n",
 			 error);
+	}
+	cpcap_charger_update_state(ddata, POWER_SUPPLY_STATUS_DISCHARGING);
 	cancel_delayed_work_sync(&ddata->vbus_work);
 	cancel_delayed_work_sync(&ddata->detect_work);
 }
Signature · 1 line
2.30.0
#9 lore raw

PATCH 9/15 power: supply: cpcap-charger: Provide state updates for battery from charger

In reply to Tony Lindgren

We want to have the battery update it's status when the charge is done, and when the charger is disconnected. Otherwise the battery does not know when it's full unless there's a userspace app polling the battery status.

To do this, we add supplied_to handling to cpcap-battery, and implement power_supply_changed() for cpcap-charger. When cpcap-charger calls power_supply_changed(), cpcap-battery will update it's status.

Let's also use new_state variable for the POWER_SUPPLY_STATUS_CHARGING case to have unified handling for the switch.

Cc Arthur Demchenkov <[email protected]>
Cc Carl Philipp Klemm <[email protected]>
Cc Merlijn Wajer <[email protected]>
Cc Pavel Machek <[email protected]>
---
 drivers/power/supply/cpcap-battery.c | 13 +++++++++++
 drivers/power/supply/cpcap-charger.c | 34 ++++++++++++++++++++++------
 2 files changed, 40 insertions(+), 7 deletions(-)
drivers/power/supply/cpcap-battery.c +13 -0
@@ -416,6 +416,18 @@ static int cpcap_battery_update_status(struct cpcap_battery_ddata *ddata)
 	return 0;
 }
 
+/*
+ * Update battery status when cpcap-charger calls power_supply_changed().
+ * This allows us to detect battery full condition before the charger
+ * disconnects.
+ */
+static void cpcap_battery_external_power_changed(struct power_supply *psy)
+{
+	union power_supply_propval prop;
+
+	power_supply_get_property(psy, POWER_SUPPLY_PROP_STATUS, &prop);
+}
+
 static enum power_supply_property cpcap_battery_props[] = {
 	POWER_SUPPLY_PROP_STATUS,
 	POWER_SUPPLY_PROP_PRESENT,
@@ -914,6 +926,7 @@ static int cpcap_battery_probe(struct platform_device *pdev)
 	psy_desc->get_property = cpcap_battery_get_property;
 	psy_desc->set_property = cpcap_battery_set_property;
 	psy_desc->property_is_writeable = cpcap_battery_property_is_writeable;
+	psy_desc->external_power_changed = cpcap_battery_external_power_changed;
 
 	psy_cfg.of_node = pdev->dev.of_node;
 	psy_cfg.drv_data = ddata;
drivers/power/supply/cpcap-charger.c +27 -7
@@ -613,6 +613,16 @@ static void cpcap_charger_disconnect(struct cpcap_charger_ddata *ddata,
 {
 	int error;
 
+	/* Update battery state before disconnecting the charger */
+	switch (state) {
+	case POWER_SUPPLY_STATUS_DISCHARGING:
+	case POWER_SUPPLY_STATUS_FULL:
+		power_supply_changed(ddata->usb);
+		break;
+	default:
+		break;
+	}
+
 	error = cpcap_charger_disable(ddata);
 	if (error) {
 		cpcap_charger_update_state(ddata, POWER_SUPPLY_STATUS_UNKNOWN);
@@ -628,7 +638,7 @@ static void cpcap_usb_detect(struct work_struct *work)
 {
 	struct cpcap_charger_ddata *ddata;
 	struct cpcap_charger_ints_state s;
-	int error;
+	int error, new_state;
 
 	ddata = container_of(work, struct cpcap_charger_ddata,
 			     detect_work.work);
@@ -662,19 +672,23 @@ static void cpcap_usb_detect(struct work_struct *work)
 	case POWER_SUPPLY_STATUS_CHARGING:
 		if (s.chrgcurr2)
 			break;
+		new_state = POWER_SUPPLY_STATUS_FULL;
+
 		if (s.chrgcurr1 && s.vbusvld) {
-			cpcap_charger_disconnect(ddata,
-						 POWER_SUPPLY_STATUS_FULL,
-						 HZ * 5);
+			cpcap_charger_disconnect(ddata, new_state, HZ * 5);
 			return;
 		}
 		break;
 	case POWER_SUPPLY_STATUS_FULL:
 		if (!s.chrgcurr2)
 			break;
-		cpcap_charger_disconnect(ddata,
-					 POWER_SUPPLY_STATUS_NOT_CHARGING,
-					 HZ * 5);
+		if (s.vbusvld)
+			new_state = POWER_SUPPLY_STATUS_NOT_CHARGING;
+		else
+			new_state = POWER_SUPPLY_STATUS_DISCHARGING;
+
+		cpcap_charger_disconnect(ddata, new_state, HZ * 5);
+
 		return;
 	default:
 		break;
@@ -832,6 +846,10 @@ static int cpcap_charger_init_iio(struct cpcap_charger_ddata *ddata)
 	return error;
 }
 
+static char *cpcap_charger_supplied_to[] = {
+	"battery",
+};
+
 static const struct power_supply_desc cpcap_charger_usb_desc = {
 	.name		= "usb",
 	.type		= POWER_SUPPLY_TYPE_USB,
@@ -889,6 +907,8 @@ static int cpcap_charger_probe(struct platform_device *pdev)
 
 	psy_cfg.of_node = pdev->dev.of_node;
 	psy_cfg.drv_data = ddata;
+	psy_cfg.supplied_to = cpcap_charger_supplied_to;
+	psy_cfg.num_supplicants = ARRAY_SIZE(cpcap_charger_supplied_to),
 
 	ddata->usb = devm_power_supply_register(ddata->dev,
 						&cpcap_charger_usb_desc,
Signature · 1 line
2.30.0
#10 lore raw

PATCH 10/15 power: supply: cpcap-battery: Use charger status for battery full detection

In reply to Tony Lindgren

We now get battery full notification from cpcap-charger, so let's use that for battery full status and charger disconnect.

Note that any current based battery full detection we have tried earlier is flakey as it won't account for example for CPU load increasing the battery current. Anyways, if current based battery full detection is also still needed, we can reconsider adding it in addition to the charger status based detection.

Cc Arthur Demchenkov <[email protected]>
Cc Carl Philipp Klemm <[email protected]>
Cc Merlijn Wajer <[email protected]>
Cc Pavel Machek <[email protected]>
---
 drivers/power/supply/cpcap-battery.c | 56 ++++++++++++++++++++++++++--
 1 file changed, 52 insertions(+), 4 deletions(-)
drivers/power/supply/cpcap-battery.c +52 -4
@@ -135,6 +135,7 @@ struct cpcap_battery_ddata {
 	atomic_t active;
 	int status;
 	u16 vendor;
+	unsigned int is_full:1;
 };
 
 #define CPCAP_NO_BATTERY	-400
@@ -371,15 +372,62 @@ static int cpcap_battery_cc_get_avg_current(struct cpcap_battery_ddata *ddata)
 	return cpcap_battery_cc_to_ua(ddata, sample, acc, offset);
 }
 
+static int cpcap_battery_get_charger_status(struct cpcap_battery_ddata *ddata,
+					    int *val)
+{
+	union power_supply_propval prop;
+	struct power_supply *charger;
+	int error;
+
+	charger = power_supply_get_by_name("usb");
+	if (!charger)
+		return -ENODEV;
+
+	error = power_supply_get_property(charger, POWER_SUPPLY_PROP_STATUS,
+					  &prop);
+	if (error)
+		*val = POWER_SUPPLY_STATUS_UNKNOWN;
+	else
+		*val = prop.intval;
+
+	power_supply_put(charger);
+
+	return error;
+}
+
 static bool cpcap_battery_full(struct cpcap_battery_ddata *ddata)
 {
 	struct cpcap_battery_state_data *state = cpcap_battery_latest(ddata);
+	unsigned int vfull;
+	int error, val;
+
+	error = cpcap_battery_get_charger_status(ddata, &val);
+	if (!error) {
+		switch (val) {
+		case POWER_SUPPLY_STATUS_DISCHARGING:
+			dev_dbg(ddata->dev, "charger disconnected\n");
+			ddata->is_full = 0;
+			break;
+		case POWER_SUPPLY_STATUS_FULL:
+			dev_dbg(ddata->dev, "charger full status\n");
+			ddata->is_full = 1;
+			break;
+		default:
+			break;
+		}
+	}
+
+	/*
+	 * The full battery voltage here can be inaccurate, it's used just to
+	 * filter out any trickle charging events. We clear the is_full status
+	 * on charger disconnect above anyways.
+	 */
+	vfull = ddata->config.bat.constant_charge_voltage_max_uv - 120000;
 
-	if (state->voltage >=
-	    (ddata->config.bat.constant_charge_voltage_max_uv - 18000))
-		return true;
+	if (ddata->is_full && state->voltage < vfull)
+		ddata->is_full = 0;
 
-	return false;
+	return ddata->is_full;
 }
 
 static int cpcap_battery_update_status(struct cpcap_battery_ddata *ddata)
Signature · 1 line
2.30.0
#11 lore raw

PATCH 11/15 power: supply: cpcap-battery: Add charge_full property

In reply to Tony Lindgren

From: Arthur Demchenkov <[email protected]>

Add charge_full property and let user update it. This is needed for capacity reporting in the following patches.

Cc Arthur Demchenkov <[email protected]>
Cc Carl Philipp Klemm <[email protected]>
Cc Merlijn Wajer <[email protected]>
Cc Pavel Machek <[email protected]>
[[email protected]: updated comments]
---
 drivers/power/supply/cpcap-battery.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)
drivers/power/supply/cpcap-battery.c +17 -0
@@ -133,6 +133,7 @@ struct cpcap_battery_ddata {
 	struct cpcap_battery_state_data state[CPCAP_BATTERY_STATE_NR];
 	u32 cc_lsb;		/* μAms per LSB */
 	atomic_t active;
+	int charge_full;
 	int status;
 	u16 vendor;
 	unsigned int is_full:1;
@@ -486,6 +487,7 @@ static enum power_supply_property cpcap_battery_props[] = {
 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
 	POWER_SUPPLY_PROP_CURRENT_AVG,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
 	POWER_SUPPLY_PROP_CHARGE_COUNTER,
 	POWER_SUPPLY_PROP_POWER_NOW,
@@ -594,6 +596,11 @@ static int cpcap_battery_get_property(struct power_supply *psy,
 		else
 			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
 		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+		if (!ddata->charge_full)
+			return -ENODATA;
+		val->intval = ddata->charge_full;
+		break;
 	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
 		val->intval = ddata->config.info.charge_full_design;
 		break;
@@ -661,6 +668,15 @@ static int cpcap_battery_set_property(struct power_supply *psy,
 		ddata->config.bat.constant_charge_voltage_max_uv = val->intval;
 
 		return cpcap_battery_update_charger(ddata, val->intval);
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+		if (val->intval < 0)
+			return -EINVAL;
+		if (val->intval > ddata->config.info.charge_full_design)
+			return -EINVAL;
+
+		ddata->charge_full = val->intval;
+
+		return 0;
 	default:
 		return -EINVAL;
 	}
@@ -673,6 +689,7 @@ static int cpcap_battery_property_is_writeable(struct power_supply *psy,
 {
 	switch (psp) {
 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
 		return 1;
 	default:
 		return 0;
Signature · 1 line
2.30.0
#12 lore raw

PATCH 12/15 power: supply: cpcap-battery: Keep track of state for capacity reporting

In reply to Tony Lindgren

From: Arthur Demchenkov <[email protected]>

Save the battery empty and full states so we can use those to estimate the battery capacity in the following patches.

If the user provides us with charge_full value (which it could save in a permanent storage between reboots), initialize low and high counter_uah with calculated values.

If we hit battery low once, we should stick on reporting it until the charger is connected. This way low->counter_uah will be updated properly, and that will allow us to get more accurate charge_full value.

Based on an earlier patch by Tony Lindgren with charge_full usage and other improvments done by Arthur Demchenkov.

Cc Arthur Demchenkov <[email protected]>
Cc Carl Philipp Klemm <[email protected]>
Cc Merlijn Wajer <[email protected]>
Cc Pavel Machek <[email protected]>
[[email protected]: combined earlier patches, updated comments]
---
 drivers/power/supply/cpcap-battery.c | 56 +++++++++++++++++++++++++++-
 1 file changed, 55 insertions(+), 1 deletion(-)
drivers/power/supply/cpcap-battery.c +55 -1
@@ -111,6 +111,8 @@ struct cpcap_coulomb_counter_data {
 enum cpcap_battery_state {
 	CPCAP_BATTERY_STATE_PREVIOUS,
 	CPCAP_BATTERY_STATE_LATEST,
+	CPCAP_BATTERY_STATE_EMPTY,
+	CPCAP_BATTERY_STATE_FULL,
 	CPCAP_BATTERY_STATE_NR,
 };
 
@@ -166,6 +168,18 @@ cpcap_battery_previous(struct cpcap_battery_ddata *ddata)
 	return cpcap_battery_get_state(ddata, CPCAP_BATTERY_STATE_PREVIOUS);
 }
 
+static struct cpcap_battery_state_data *
+cpcap_battery_get_empty(struct cpcap_battery_ddata *ddata)
+{
+	return cpcap_battery_get_state(ddata, CPCAP_BATTERY_STATE_EMPTY);
+}
+
+static struct cpcap_battery_state_data *
+cpcap_battery_get_full(struct cpcap_battery_ddata *ddata)
+{
+	return cpcap_battery_get_state(ddata, CPCAP_BATTERY_STATE_FULL);
+}
+
 static int cpcap_charger_battery_temperature(struct cpcap_battery_ddata *ddata,
 					     int *value)
 {
@@ -431,9 +445,23 @@ static bool cpcap_battery_full(struct cpcap_battery_ddata *ddata)
 	return ddata->is_full;
 }
 
+static bool cpcap_battery_low(struct cpcap_battery_ddata *ddata)
+{
+	struct cpcap_battery_state_data *state = cpcap_battery_latest(ddata);
+	static bool is_low;
+
+	if (state->current_ua > 0 && (state->voltage <= 3350000 || is_low))
+		is_low = true;
+	else
+		is_low = false;
+
+	return is_low;
+}
+
 static int cpcap_battery_update_status(struct cpcap_battery_ddata *ddata)
 {
-	struct cpcap_battery_state_data state, *latest, *previous;
+	struct cpcap_battery_state_data state, *latest, *previous,
+					*empty, *full;
 	ktime_t now;
 	int error;
 
@@ -462,6 +490,32 @@ static int cpcap_battery_update_status(struct cpcap_battery_ddata *ddata)
 	memcpy(previous, latest, sizeof(*previous));
 	memcpy(latest, &state, sizeof(*latest));
 
+	if (cpcap_battery_full(ddata)) {
+		full = cpcap_battery_get_full(ddata);
+		memcpy(full, latest, sizeof(*full));
+
+		empty = cpcap_battery_get_empty(ddata);
+		if (empty->voltage && empty->voltage != -1) {
+			empty->voltage = -1;
+			ddata->charge_full =
+				empty->counter_uah - full->counter_uah;
+		} else if (ddata->charge_full) {
+			empty->voltage = -1;
+			empty->counter_uah =
+				full->counter_uah + ddata->charge_full;
+		}
+	} else if (cpcap_battery_low(ddata)) {
+		empty = cpcap_battery_get_empty(ddata);
+		memcpy(empty, latest, sizeof(*empty));
+
+		full = cpcap_battery_get_full(ddata);
+		if (full->voltage) {
+			full->voltage = 0;
+			ddata->charge_full =
+				empty->counter_uah - full->counter_uah;
+		}
+	}
+
 	return 0;
 }
 
Signature · 1 line
2.30.0
#13 lore raw

PATCH 13/15 power: supply: cpcap-battery: Implement capacity reporting

In reply to Tony Lindgren

From: Arthur Demchenkov <[email protected]>

Calculate percentage using charge_full value provided.

Cc Arthur Demchenkov <[email protected]>
Cc Carl Philipp Klemm <[email protected]>
Cc Merlijn Wajer <[email protected]>
Cc Pavel Machek <[email protected]>
[[email protected]: updated to apply after dropping my earlier patch]
---
 drivers/power/supply/cpcap-battery.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)
drivers/power/supply/cpcap-battery.c +12 -1
@@ -546,6 +546,7 @@ static enum power_supply_property cpcap_battery_props[] = {
 	POWER_SUPPLY_PROP_CHARGE_COUNTER,
 	POWER_SUPPLY_PROP_POWER_NOW,
 	POWER_SUPPLY_PROP_POWER_AVG,
+	POWER_SUPPLY_PROP_CAPACITY,
 	POWER_SUPPLY_PROP_CAPACITY_LEVEL,
 	POWER_SUPPLY_PROP_SCOPE,
 	POWER_SUPPLY_PROP_TEMP,
@@ -556,7 +557,7 @@ static int cpcap_battery_get_property(struct power_supply *psy,
 				      union power_supply_propval *val)
 {
 	struct cpcap_battery_ddata *ddata = power_supply_get_drvdata(psy);
-	struct cpcap_battery_state_data *latest, *previous;
+	struct cpcap_battery_state_data *latest, *previous, *empty;
 	u32 sample;
 	s32 accumulator;
 	int cached;
@@ -636,6 +637,16 @@ static int cpcap_battery_get_property(struct power_supply *psy,
 		tmp *= ((latest->voltage + previous->voltage) / 20000);
 		val->intval = div64_s64(tmp, 100);
 		break;
+	case POWER_SUPPLY_PROP_CAPACITY:
+		empty = cpcap_battery_get_empty(ddata);
+		if (!empty->voltage || !ddata->charge_full)
+			return -ENODATA;
+		/* (ddata->charge_full / 200) is needed for rounding */
+		val->intval = empty->counter_uah - latest->counter_uah +
+			ddata->charge_full / 200;
+		val->intval = clamp(val->intval, 0, ddata->charge_full);
+		val->intval = val->intval * 100 / ddata->charge_full;
+		break;
 	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
 		if (cpcap_battery_full(ddata))
 			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
Signature · 1 line
2.30.0
#14 lore raw

PATCH 14/15 power: supply: cpcap-battery: Add charge_now property

In reply to Tony Lindgren

From: Arthur Demchenkov <[email protected]>

Add charge_now property for capacity reporting.

Cc Arthur Demchenkov <[email protected]>
Cc Carl Philipp Klemm <[email protected]>
Cc Merlijn Wajer <[email protected]>
Cc Pavel Machek <[email protected]>
[[email protected]: updated to apply for naming changes]
---
 drivers/power/supply/cpcap-battery.c | 11 +++++++++++
 1 file changed, 11 insertions(+)
drivers/power/supply/cpcap-battery.c +11 -0
@@ -542,6 +542,7 @@ static enum power_supply_property cpcap_battery_props[] = {
 	POWER_SUPPLY_PROP_CURRENT_AVG,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CHARGE_FULL,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
 	POWER_SUPPLY_PROP_CHARGE_COUNTER,
 	POWER_SUPPLY_PROP_POWER_NOW,
@@ -661,6 +662,16 @@ static int cpcap_battery_get_property(struct power_supply *psy,
 		else
 			val->intval = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
 		break;
+	case POWER_SUPPLY_PROP_CHARGE_NOW:
+		empty = cpcap_battery_get_empty(ddata);
+		if (!empty->voltage)
+			return -ENODATA;
+		val->intval = empty->counter_uah - latest->counter_uah;
+		if (val->intval < 0)
+			val->intval = 0;
+		else if (ddata->charge_full && ddata->charge_full < val->intval)
+			val->intval = ddata->charge_full;
+		break;
 	case POWER_SUPPLY_PROP_CHARGE_FULL:
 		if (!ddata->charge_full)
 			return -ENODATA;
Signature · 1 line
2.30.0
#15 lore raw

PATCH 15/15 power: supply: cpcap-battery: Fix typo

In reply to Tony Lindgren

From: Pavel Machek <[email protected]>

Fix typo

Cc Arthur Demchenkov <[email protected]>
Cc Carl Philipp Klemm <[email protected]>
Cc Merlijn Wajer <[email protected]>
Cc Pavel Machek <[email protected]>
[[email protected]: separated out from charger changes]
---
 drivers/power/supply/cpcap-battery.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/power/supply/cpcap-battery.c +1 -1
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2017 Tony Lindgren <[email protected]>
  *
- * Some parts of the code based on earlie Motorola mapphone Linux kernel
+ * Some parts of the code based on earlier Motorola mapphone Linux kernel
  * drivers:
  *
  * Copyright (C) 2009-2010 Motorola, Inc.
Signature · 1 line
2.30.0
#16 lore raw
In reply to Tony Lindgren

Hi,

Quoted 11 lines · Tony Lindgren

Hi all,

Here's a series of patches to update cpcap charger and battery support for showing capacity. I've reorganized and cleaned up the patches posted earlier and simplified few things in the process compared to the earlier patches. The first few patches contain minor fixes that can wait for the merge window no problem.

The battery capacity is only available if charge_full is written via sysfs based on calibration, and then a battery low or high value is seen. This follows what we already have for n900.

Thanks, queued.

-- Sebastian

Quoted 37 lines

Regards,

Tony

Arthur Demchenkov (4):
power: supply: cpcap-battery: Add charge_full property
power: supply: cpcap-battery: Keep track of state for capacity
reporting
power: supply: cpcap-battery: Implement capacity reporting
power: supply: cpcap-battery: Add charge_now property

Pavel Machek (2):
power: supply: cpcap-charger: Limiting charge current on Droid 4
power: supply: cpcap-battery: Fix typo

Tony Lindgren (9):
power: supply: cpcap-charger: Fix missing power_supply_put()
power: supply: cpcap-battery: Fix missing power_supply_put()
power: supply: cpcap-charger: Fix flakey reboot with charger connected
power: supply: cpcap-charger: Make VBUS already provided debug only
power: supply: cpcap-charger: Use standard enumeration
power: supply: cpcap-charger: Drop internal state and use generic
stats
power: supply: cpcap-charger: Simplify things with enable and disable
power: supply: cpcap-charger: Provide state updates for battery from
charger
power: supply: cpcap-battery: Use charger status for battery full
detection

 drivers/power/supply/cpcap-battery.c | 178 ++++++++++++++++--
 drivers/power/supply/cpcap-charger.c | 259 +++++++++++++++++----------
 2 files changed, 329 insertions(+), 108 deletions(-)
Signature · 1 line
2.30.0