From 04574f6b119cccb8a5a22d7fc8508134e1f3b16a Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megi@xff.cz>
Date: Sat, 2 Apr 2022 02:45:47 +0200
Subject: [PATCH 313/389] power: supply: rk818-charger: Unify rk818-charger and
 rk818-battery

The BSP driver is still used, but there is now a one device handling
the battery/charger properties, which should confuse the userspace
less. This also makes writing a power manager for the keyboard easier.

Signed-off-by: Ondrej Jirman <megi@xff.cz>
---
 drivers/power/supply/Kconfig         |  8 ---
 drivers/power/supply/Makefile        |  3 +-
 drivers/power/supply/rk818_battery.c | 38 ++++++++++---
 drivers/power/supply/rk818_charger.c | 79 ++++++++++++++++++++++------
 4 files changed, 95 insertions(+), 33 deletions(-)

diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index d3bdf262ae01..7b6286443fbd 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -918,14 +918,6 @@ config BATTERY_UG3105
 	  device is off or suspended, the functionality of this driver is
 	  limited to reporting capacity only.
 
-config BATTERY_RK818
-	bool "RK818 Battery driver"
-	depends on MFD_RK808
-	default n
-	help
-	  If you say yes here you will get support for the battery of RK818 PMIC.
-	  This driver can give support for Rk818 Battery Charge Interface.
-
 config CHARGER_RK818
 	bool "RK818 Charger driver"
 	depends on MFD_RK808
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index 3b9ea8374538..9d286e2bf53a 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -110,5 +110,4 @@ obj-$(CONFIG_BATTERY_ACER_A500)	+= acer_a500_battery.o
 obj-$(CONFIG_BATTERY_SURFACE)	+= surface_battery.o
 obj-$(CONFIG_CHARGER_SURFACE)	+= surface_charger.o
 obj-$(CONFIG_BATTERY_UG3105)	+= ug3105_battery.o
-obj-$(CONFIG_BATTERY_RK818)	+= rk818_battery.o
-obj-$(CONFIG_CHARGER_RK818)	+= rk818_charger.o
+obj-$(CONFIG_CHARGER_RK818)	+= rk818_charger.o rk818_battery.o
diff --git a/drivers/power/supply/rk818_battery.c b/drivers/power/supply/rk818_battery.c
index cc409b7aafb5..e0e5ed0e3d2a 100644
--- a/drivers/power/supply/rk818_battery.c
+++ b/drivers/power/supply/rk818_battery.c
@@ -897,12 +897,10 @@ static int rk818_bat_get_charge_state(struct rk818_battery *di)
 	return di->current_avg > 0;
 }
 
-static int rk818_battery_get_property(struct power_supply *psy,
-				      enum power_supply_property psp,
-				      union power_supply_propval *val)
+int rk818_battery_get_property(struct rk818_battery *di,
+			       enum power_supply_property psp,
+			       union power_supply_propval *val)
 {
-	struct rk818_battery *di = power_supply_get_drvdata(psy);
-
 	switch (psp) {
 	case POWER_SUPPLY_PROP_CURRENT_NOW:
 		val->intval = di->current_avg * 1000;/*uA*/
@@ -961,16 +959,26 @@ static int rk818_battery_get_property(struct power_supply *psy,
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(rk818_battery_get_property);
+
+static int rk818_battery_get_property_psy(struct power_supply *psy,
+				      enum power_supply_property psp,
+				      union power_supply_propval *val)
+{
+	struct rk818_battery *di = power_supply_get_drvdata(psy);
+
+	return rk818_battery_get_property(di, psp, val);
+}
 
 static const struct power_supply_desc rk818_bat_desc = {
 	.name		= "battery",
 	.type		= POWER_SUPPLY_TYPE_BATTERY,
 	.properties	= rk818_bat_props,
 	.num_properties	= ARRAY_SIZE(rk818_bat_props),
-	.get_property	= rk818_battery_get_property,
+	.get_property	= rk818_battery_get_property_psy,
 };
 
-static int rk818_bat_init_power_supply(struct rk818_battery *di)
+static __maybe_unused int rk818_bat_init_power_supply(struct rk818_battery *di)
 {
 	struct power_supply_config psy_cfg = { .drv_data = di, };
 
@@ -2422,7 +2430,10 @@ static void rk818_bat_power_supply_changed(struct rk818_battery *di)
 	status = (status & CHRG_STATUS_MSK) >> 4;
 	old_soc = di->dsoc;
 	di->last_dsoc = di->dsoc;
-	power_supply_changed(di->bat);
+
+	if (di->bat)
+		power_supply_changed(di->bat);
+
 	BAT_INFO("changed: dsoc=%d, rsoc=%d, v=%d, ov=%d c=%d, "
 		 "cap=%d, f=%d, st=%s, hotdie=%d\n",
 		 di->dsoc, di->rsoc, di->voltage_avg, di->voltage_ocv,
@@ -3251,6 +3262,14 @@ static const struct of_device_id rk818_battery_of_match[] = {
 	{ },
 };
 
+static struct rk818_battery* bat;
+
+struct rk818_battery* rk818_battery_get(void)
+{
+	return bat;
+}
+EXPORT_SYMBOL_GPL(rk818_battery_get);
+
 static int rk818_battery_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *of_id =
@@ -3291,11 +3310,13 @@ static int rk818_battery_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	/*
 	ret = rk818_bat_init_power_supply(di);
 	if (ret) {
 		dev_err(di->dev, "rk818 power supply register failed!\n");
 		return ret;
 	}
+	*/
 
 	rk818_bat_init_info(di);
 	rk818_bat_init_fg(di);
@@ -3309,6 +3330,7 @@ static int rk818_battery_probe(struct platform_device *pdev)
 
 	BAT_INFO("driver version %s\n", DRIVER_VERSION);
 
+	bat = di;
 	return ret;
 }
 
diff --git a/drivers/power/supply/rk818_charger.c b/drivers/power/supply/rk818_charger.c
index 6a9f2d1a7086..16bc4686b547 100644
--- a/drivers/power/supply/rk818_charger.c
+++ b/drivers/power/supply/rk818_charger.c
@@ -355,14 +355,36 @@ static int rk818_charger_get_voltage_max(struct rk818_charger *cg, int *val)
 	return 0;
 }
 
+struct rk818_battery;
+struct rk818_battery* rk818_battery_get(void);
+int rk818_battery_get_property(struct rk818_battery *di,
+			       enum power_supply_property psp,
+			       union power_supply_propval *val);
+
 static int rk818_charger_get_property(struct power_supply *psy,
 				      enum power_supply_property psp,
 				      union power_supply_propval *val)
 {
 	struct rk818_charger *cg = power_supply_get_drvdata(psy);
+	struct rk818_battery* di = rk818_battery_get();
 	unsigned reg;
 	int ret;
 
+	switch (psp) {
+		case POWER_SUPPLY_PROP_CURRENT_NOW:
+		case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		case POWER_SUPPLY_PROP_PRESENT:
+		case POWER_SUPPLY_PROP_CAPACITY:
+		case POWER_SUPPLY_PROP_TEMP:
+		case POWER_SUPPLY_PROP_STATUS:
+		case POWER_SUPPLY_PROP_CHARGE_COUNTER:
+		case POWER_SUPPLY_PROP_CHARGE_FULL:
+			if (!di)
+				return -ENODEV;
+			return rk818_battery_get_property(di, psp, val);
+		default:;
+	}
+
 	switch (psp) {
 	case POWER_SUPPLY_PROP_ONLINE:
 		ret = regmap_read(cg->regmap, RK818_CHRG_CTRL_REG1, &reg);
@@ -374,6 +396,20 @@ static int rk818_charger_get_property(struct power_supply *psy,
 		val->intval = !!(reg & RK818_CHRG_CTRL_REG1_CHRG_EN);
 		break;
 
+	case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
+		ret = regmap_read(cg->regmap, RK818_CHRG_CTRL_REG1, &reg);
+		if (ret) {
+			dev_err(cg->dev, "failed to read the charger state (%d)\n", ret);
+			return ret;
+		}
+
+		if (reg & RK818_CHRG_CTRL_REG1_CHRG_EN)
+			val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO;
+		else
+			val->intval = POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE;
+
+		return 0;
+
 	case POWER_SUPPLY_PROP_STATUS:
 		ret = regmap_read(cg->regmap, RK818_SUP_STS_REG, &reg);
 		if (ret)
@@ -480,14 +516,18 @@ static int rk818_charger_set_property(struct power_supply *psy,
 	int ret;
 
 	switch (psp) {
-	case POWER_SUPPLY_PROP_ONLINE:
-		ret = regmap_update_bits(cg->regmap, RK818_CHRG_CTRL_REG1,
-					 RK818_CHRG_CTRL_REG1_CHRG_EN,
-					 val->intval ? RK818_CHRG_CTRL_REG1_CHRG_EN : 0);
-		if (ret)
-			dev_err(cg->dev, "failed to setup the charger (%d)\n", ret);
-
-		return ret;
+	case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
+		switch (val->intval) {
+		case POWER_SUPPLY_CHARGE_BEHAVIOUR_AUTO:
+			return regmap_update_bits(cg->regmap, RK818_CHRG_CTRL_REG1,
+						  RK818_CHRG_CTRL_REG1_CHRG_EN,
+						  RK818_CHRG_CTRL_REG1_CHRG_EN);
+		case POWER_SUPPLY_CHARGE_BEHAVIOUR_INHIBIT_CHARGE:
+			return regmap_update_bits(cg->regmap, RK818_CHRG_CTRL_REG1,
+						  RK818_CHRG_CTRL_REG1_CHRG_EN, 0);
+		default:
+			return -EINVAL;
+		}
 
 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
                 return rk818_charger_set_voltage_max(cg, val->intval);
@@ -506,7 +546,7 @@ static int rk818_charger_prop_writeable(struct power_supply *psy,
 	switch (psp) {
 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
-	case POWER_SUPPLY_PROP_ONLINE:
+	case POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR:
 		return 1;
 
 	default:
@@ -518,6 +558,7 @@ static enum power_supply_property rk818_charger_props[] = {
 	POWER_SUPPLY_PROP_ONLINE,
 	POWER_SUPPLY_PROP_HEALTH,
 	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_CHARGE_BEHAVIOUR,
 	POWER_SUPPLY_PROP_CHARGE_TYPE,
 	POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
@@ -525,17 +566,25 @@ static enum power_supply_property rk818_charger_props[] = {
 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
 	POWER_SUPPLY_PROP_PRECHARGE_CURRENT,
+
+	// inherited from BSP battery driver
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_CAPACITY,
+	POWER_SUPPLY_PROP_TEMP,
+	POWER_SUPPLY_PROP_CHARGE_COUNTER,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
 };
 
 /*
- * TODO: This functionality should be in a battery driver/supply, but that one
- * is such a mess, I don't want to touch it now. Let's have a separate supply
- * for controlling the charger for now, and a prayer for the poor soul that
- * will have to understand and clean up the battery driver.
+ * We import some capacity tracking functionality from the BSP battery driver.
+ * Some poor soul will have to understand and clean up the BSP battery driver,
+ * but not me, not now. :)
  */
 static const struct power_supply_desc rk818_charger_desc = {
-	.name			= "rk818-charger",
-	.type			= POWER_SUPPLY_TYPE_MAINS,
+	.name			= "rk818-battery",
+	.type			= POWER_SUPPLY_TYPE_BATTERY,
 	.properties		= rk818_charger_props,
 	.num_properties		= ARRAY_SIZE(rk818_charger_props),
 	.property_is_writeable	= rk818_charger_prop_writeable,
-- 
2.35.3

