From 9c293e92434e046a69a1dc6d3941959ce8bdd8dd Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megi@xff.cz>
Date: Sun, 3 Apr 2022 16:03:10 +0200
Subject: [PATCH 415/480] power: supply: ip5xxx: Add support for
 POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR

This property is better for preventing charging, then the status property,
because reading status property should return the actual status, and not
whether the charging is currently inhibited or not.

System may have charging enabled, but the battery may still be discharging
for a host of reasons.

Signed-off-by: Ondrej Jirman <megi@xff.cz>
---
 drivers/power/supply/ip5xxx_power.c | 30 +++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/power/supply/ip5xxx_power.c b/drivers/power/supply/ip5xxx_power.c
index 837cf95d77ed..9800cd91c20a 100644
--- a/drivers/power/supply/ip5xxx_power.c
+++ b/drivers/power/supply/ip5xxx_power.c
@@ -274,6 +274,7 @@ static int ip5xxx_initialize(struct power_supply *psy)
 static const enum power_supply_property ip5xxx_battery_properties[] = {
 	POWER_SUPPLY_PROP_STATUS,
 	POWER_SUPPLY_PROP_CHARGE_TYPE,
+	POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR,
 	POWER_SUPPLY_PROP_HEALTH,
 	POWER_SUPPLY_PROP_CAPACITY,
 	POWER_SUPPLY_PROP_CALIBRATE,
@@ -448,6 +449,18 @@ static int ip5xxx_battery_get_property(struct power_supply *psy,
 	case POWER_SUPPLY_PROP_STATUS:
 		return ip5xxx_battery_get_status(ip5xxx, &val->intval);
 
+	case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
+		ret = ip5xxx_read(ip5xxx, IP5XXX_SYS_CTL0, &rval);
+		if (ret)
+			return ret;
+
+		if (rval & IP5XXX_SYS_CTL0_CHARGER_EN)
+			val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO;
+		else
+			val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE;
+
+		return 0;
+
 	case POWER_SUPPLY_PROP_CHARGE_TYPE:
 		return ip5xxx_battery_get_charge_type(ip5xxx, &val->intval);
 
@@ -605,6 +618,21 @@ static int ip5xxx_battery_set_property(struct power_supply *psy,
 		}
 		return ip5xxx_write(ip5xxx, ip5xxx->regs.charger.enable, rval);
 
+	case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
+		switch (val->intval) {
+		case POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO:
+			rval = IP5XXX_SYS_CTL0_CHARGER_EN;
+			break;
+		case POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE:
+			rval = 0;
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		return ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL0,
+					  IP5XXX_SYS_CTL0_CHARGER_EN, rval);
+
 	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
 		return ip5xxx_battery_set_voltage_max(ip5xxx, val->intval);
 
@@ -636,6 +664,7 @@ static int ip5xxx_battery_property_is_writeable(struct power_supply *psy,
 {
 	return psp == POWER_SUPPLY_PROP_STATUS ||
 	       psp == POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN ||
+	       psp == POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR ||
 	       psp == POWER_SUPPLY_PROP_CALIBRATE ||
 	       psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT ||
 	       psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE;
@@ -649,6 +678,7 @@ static const struct power_supply_desc ip5xxx_battery_desc = {
 	.get_property		= ip5xxx_battery_get_property,
 	.set_property		= ip5xxx_battery_set_property,
 	.property_is_writeable	= ip5xxx_battery_property_is_writeable,
+	.charge_behaviours	= BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO) | BIT(POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE),
 };
 
 static const enum power_supply_property ip5xxx_boost_properties[] = {
-- 
2.49.0

