From 521fee88b61d730f477e0b5de8cd80bb45e944e4 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megi@xff.cz>
Date: Sun, 3 Apr 2022 16:03:10 +0200
Subject: [PATCH 395/463] 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 c567244679977..ff2f4eeea8754 100644
--- a/drivers/power/supply/ip5xxx_power.c
+++ b/drivers/power/supply/ip5xxx_power.c
@@ -183,6 +183,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,
@@ -341,6 +342,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);
 
@@ -492,6 +505,21 @@ static int ip5xxx_battery_set_property(struct power_supply *psy,
 		return ip5xxx_update_bits(ip5xxx, IP5XXX_SYS_CTL0,
 					  IP5XXX_SYS_CTL0_CHARGER_EN, 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);
 
@@ -525,6 +553,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;
@@ -538,6 +567,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.46.0

