smblite: Add shim layer psy

Create a shim layer power supply that takes over as the "usb" psy
available to the system. This shim layer can be used to tweak psy
psy behaviour and reporting to the rest of the system while keeping
modifications to the actual smblite driver to a minimum.

Bug: 294057046
Signed-off-by: Andrei Ciubotariu <aciubotariu@google.com>
(cherry picked from https://partner-android-review.googlesource.com/q/commit:8ce5636d5540b9e4cb9a935893d2b19ff360c3df)
Merged-In: I64e1a454505c5422c7263d939998b0de6f91a37e
Change-Id: I64e1a454505c5422c7263d939998b0de6f91a37e
diff --git a/drivers/power/supply/qcom/Makefile b/drivers/power/supply/qcom/Makefile
index 8dc7d4c..ffa7bd4 100644
--- a/drivers/power/supply/qcom/Makefile
+++ b/drivers/power/supply/qcom/Makefile
@@ -7,7 +7,7 @@
 obj-$(CONFIG_QPNP_QG)	+= qcom-qpnp-qg.o
 qcom-qpnp-qg-y	+= qpnp-qg.o battery-profile-loader.o pmic-voter.o qg-util.o qg-soc.o qg-sdam.o qg-battery-profile.o qg-profile-lib.o fg-alg.o
 obj-$(CONFIG_QPNP_SMBLITE) += qpnp-smblite-main.o
-qpnp-smblite-main-y += step-chg-jeita.o battery.o qpnp-smblite.o smblite-lib.o pmic-voter-compat.o storm-watch.o battery-profile-loader.o schgm-flashlite.o smblite-iio.o smbx-get-chan.o smblite-remote-bms.o
+qpnp-smblite-main-y += step-chg-jeita.o battery.o qpnp-smblite.o smblite-lib.o pmic-voter-compat.o storm-watch.o battery-profile-loader.o schgm-flashlite.o smblite-iio.o smbx-get-chan.o smblite-remote-bms.o smblite-shim.o
 obj-$(CONFIG_SMB1398_CHARGER)           += qcom-smb1398-charger.o
 qcom-smb1398-charger-y += smb1398-charger.o pmic-voter.o
 obj-$(CONFIG_SMB1355_SLAVE_CHARGER)	+= qcom-smb1355-charger.o
diff --git a/drivers/power/supply/qcom/qpnp-smblite.c b/drivers/power/supply/qcom/qpnp-smblite.c
index 8777752..7e1ebff 100644
--- a/drivers/power/supply/qcom/qpnp-smblite.c
+++ b/drivers/power/supply/qcom/qpnp-smblite.c
@@ -21,6 +21,7 @@
 #include <linux/suspend.h>
 #include <linux/usb/typec.h>
 #include <linux/nvmem-consumer.h>
+#include "smblite-shim.h"
 #include "smblite-reg.h"
 #include "smblite-lib.h"
 #include "smb5-iio.h"
@@ -600,6 +601,8 @@ void smblite_update_usb_desc(struct smb_charger *chg)
 		usb_psy_desc.type = POWER_SUPPLY_TYPE_USB;
 		break;
 	}
+
+	smblite_shim_on_usb_type_updated(chg->shim, usb_psy_desc.type);
 }
 
 #define MIN_THERMAL_VOTE_UA	500000
@@ -637,8 +640,13 @@ static int smblite_usb_prop_is_writeable(struct power_supply *psy,
 	return 0;
 }
 
+/* Notifies usb shim psy of qcom_usb power_supply_changed() events */
+static char *usb_psy_supplied_to[] = {
+	"usb",
+};
+
 static struct power_supply_desc usb_psy_desc = {
-	.name = "usb",
+	.name = "qcom_usb",
 	.type = POWER_SUPPLY_TYPE_USB,
 	.properties = smblite_usb_props,
 	.num_properties = ARRAY_SIZE(smblite_usb_props),
@@ -656,6 +664,8 @@ static int smblite_init_usb_psy(struct smblite *chip)
 
 	usb_cfg.drv_data = chip;
 	usb_cfg.of_node = chg->dev->of_node;
+	usb_cfg.supplied_to = usb_psy_supplied_to;
+	usb_cfg.num_supplicants = ARRAY_SIZE(usb_psy_supplied_to);
 	chg->usb_psy = devm_power_supply_register(chg->dev,
 						  &usb_psy_desc,
 						  &usb_cfg);
@@ -664,7 +674,7 @@ static int smblite_init_usb_psy(struct smblite *chip)
 		return PTR_ERR(chg->usb_psy);
 	}
 
-	return 0;
+	return smblite_shim_on_usb_psy_created(chg->shim, &usb_psy_desc);
 }
 
 /*************************
@@ -2202,6 +2212,12 @@ static int smblite_probe(struct platform_device *pdev)
 		return rc;
 	}
 
+	chg->shim = smblite_shim_init(chg);
+	if (!chg->shim) {
+		pr_err("Could not initialize smblite_shim");
+		goto cleanup;
+	}
+
 	rc = smblite_extcon_init(chg);
 	if (rc < 0)
 		goto cleanup;
diff --git a/drivers/power/supply/qcom/smblite-lib.h b/drivers/power/supply/qcom/smblite-lib.h
index 550e3e5..d86449e 100644
--- a/drivers/power/supply/qcom/smblite-lib.h
+++ b/drivers/power/supply/qcom/smblite-lib.h
@@ -18,6 +18,7 @@
 #include <linux/extcon-provider.h>
 #include <linux/usb/typec.h>
 #include <linux/qti_power_supply.h>
+#include "smblite-shim.h"
 #include "storm-watch.h"
 #include "battery.h"
 #include "smblite-remote-bms.h"
@@ -291,6 +292,7 @@ struct smb_charger {
 	enum smb_mode		mode;
 	u8			subtype;
 	int			weak_chg_icl_ua;
+	struct smblite_shim	*shim;
 
 	/* locks */
 	struct mutex		typec_lock;
diff --git a/drivers/power/supply/qcom/smblite-shim.c b/drivers/power/supply/qcom/smblite-shim.c
new file mode 100644
index 0000000..5c5e77d
--- /dev/null
+++ b/drivers/power/supply/qcom/smblite-shim.c
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright 2023 Google LLC */
+
+#define pr_fmt(fmt) "smblite-shim:%s: " fmt, __func__
+
+#include <linux/jiffies.h>
+#include <linux/pmic-voter.h>
+#include <linux/power_supply.h>
+#include <linux/workqueue.h>
+#include "smblite-shim.h"
+
+static struct power_supply_desc usb_psy_desc;
+
+static int smblite_shim_usb_get_prop(struct power_supply *psy,
+				enum power_supply_property psp,
+				union power_supply_propval *val)
+{
+	struct smblite_shim *shim = power_supply_get_drvdata(psy);
+	struct smb_charger *chg = shim->chg;
+	const struct power_supply_desc *real_usb_desc = chg->usb_psy->desc;
+
+	return real_usb_desc->get_property(chg->usb_psy, psp, val);
+}
+
+static int smblite_shim_usb_set_prop(struct power_supply *psy,
+				enum power_supply_property psp,
+				const union power_supply_propval *val)
+{
+	struct smblite_shim *shim = power_supply_get_drvdata(psy);
+	struct smb_charger *chg = shim->chg;
+	const struct power_supply_desc *real_usb_desc = chg->usb_psy->desc;
+
+	return real_usb_desc->set_property(chg->usb_psy, psp, val);
+}
+
+static int smblite_shim_usb_prop_is_writeable(struct power_supply *psy,
+					enum power_supply_property psp)
+{
+	struct smblite_shim *shim = power_supply_get_drvdata(psy);
+	struct smb_charger *chg = shim->chg;
+	const struct power_supply_desc *real_usb_desc = chg->usb_psy->desc;
+
+	return real_usb_desc->property_is_writeable(chg->usb_psy, psp);
+}
+
+static void smblite_shim_external_power_changed(struct power_supply *psy)
+{
+	power_supply_changed(psy);
+}
+
+struct smblite_shim *smblite_shim_init(struct smb_charger *chg)
+{
+	struct smblite_shim *shim;
+
+	shim = devm_kzalloc(chg->dev, sizeof(*shim), GFP_KERNEL);
+
+	if (!shim)
+		return NULL;
+
+	shim->chg = chg;
+	return shim;
+}
+
+int smblite_shim_on_usb_psy_created(struct smblite_shim *shim,
+				struct power_supply_desc *existing_usb_desc)
+{
+	struct power_supply_config usb_cfg = {};
+
+	memcpy(&usb_psy_desc, existing_usb_desc, sizeof(usb_psy_desc));
+
+	usb_psy_desc.name = "usb";
+	usb_psy_desc.get_property = smblite_shim_usb_get_prop;
+	usb_psy_desc.set_property = smblite_shim_usb_set_prop;
+	usb_psy_desc.property_is_writeable = smblite_shim_usb_prop_is_writeable;
+	usb_psy_desc.external_power_changed = smblite_shim_external_power_changed;
+
+	usb_cfg.drv_data = shim;
+	usb_cfg.of_node = shim->chg->dev->of_node;
+	shim->psy = devm_power_supply_register(shim->chg->dev,
+						&usb_psy_desc, &usb_cfg);
+	if (IS_ERR(shim->psy)) {
+		pr_err("Couldn't register smblite shim USB power supply\n");
+		return PTR_ERR(shim->psy);
+	}
+
+	return 0;
+}
+
+void smblite_shim_on_usb_type_updated(struct smblite_shim *shim,
+				enum power_supply_type type)
+{
+	usb_psy_desc.type = type;
+}
diff --git a/drivers/power/supply/qcom/smblite-shim.h b/drivers/power/supply/qcom/smblite-shim.h
new file mode 100644
index 0000000..342b198
--- /dev/null
+++ b/drivers/power/supply/qcom/smblite-shim.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright 2023 Google LLC */
+
+#ifndef __SMBLITE_SHIM_H__
+#define __SMBLITE_SHIM_H__
+
+#include <linux/power_supply.h>
+#include "smblite-lib.h"
+
+struct smblite_shim {
+	struct smb_charger *chg;
+	struct power_supply *psy;
+};
+
+struct smblite_shim *smblite_shim_init(struct smb_charger *chg);
+
+int smblite_shim_on_usb_psy_created(struct smblite_shim *shim,
+				struct power_supply_desc *existing_usb_desc);
+
+void smblite_shim_on_usb_type_updated(struct smblite_shim *shim,
+				enum power_supply_type type);
+
+#endif