Merge "Merge android13-gs-pixel-5.10-tm-qpr3 into android13-gs-pixel-5.10-udc" into android13-gs-pixel-5.10-udc
diff --git a/gbms_power_supply.h b/gbms_power_supply.h
index 6d81e6b..12a4378 100644
--- a/gbms_power_supply.h
+++ b/gbms_power_supply.h
@@ -88,7 +88,6 @@
 	GBMS_PROP_BATTERY_AGE,		/* GBMS time in field */
 	GBMS_PROP_CAPACITY_FADE_RATE,	/* GBMS capaciy fade rate */
 	GBMS_PROP_CHARGE_FULL_ESTIMATE,	/* GBMS google_capacity */
-	GBMS_PROP_POGO_VOUT_ENABLED,	/* GBMS gogo vout enabled */
 	GBMS_PROP_WLC_OP_FREQ,		/* GBMS wlc frequency */
 	GBMS_PROP_WLC_VRECT,		/* GBMS wlc Vrect */
 };
diff --git a/google_bms.h b/google_bms.h
index 1cd3e6a..4bf9285 100644
--- a/google_bms.h
+++ b/google_bms.h
@@ -462,6 +462,10 @@
 #define VOTABLE_CSI_STATUS	"CSI_STATUS"
 #define VOTABLE_CSI_TYPE	"CSI_TYPE"
 
+#define VOTABLE_DC_CHG_AVAIL	"DC_AVAIL"
+#define REASON_DC_DRV		"DC_DRV"
+#define REASON_MDIS		"MDIS"
+
 #define FAN_LVL_UNKNOWN		-1
 #define FAN_LVL_NOT_CARE	0
 #define FAN_LVL_LOW		1
diff --git a/google_cpm.c b/google_cpm.c
index 9d57db4..f621c0b 100644
--- a/google_cpm.c
+++ b/google_cpm.c
@@ -167,6 +167,7 @@
 	int chg_psy_retries;
 	struct power_supply *chg_psy_avail[GCPM_MAX_CHARGERS];
 	const char *chg_psy_names[GCPM_MAX_CHARGERS];
+	struct gvotable_election *dc_chg_avail_votable;
 	struct mutex chg_psy_lock;
 	int chg_psy_active;
 	int chg_psy_count;
@@ -415,6 +416,11 @@
 	struct power_supply *chg_psy;
 	int ret;
 
+	ret = gcpm_update_gcpm_fcc(gcpm, "CC_MAX", gcpm->cc_max, false);
+	if (ret < 0)
+		pr_debug("PPS_DC: offline cannot update cp_fcc (%d)\n", ret);
+
+
 	chg_psy = gcpm_chg_get_charger(gcpm, index);
 	if (!chg_psy)
 		return 0;
@@ -701,6 +707,10 @@
 	if (ret < 0)
 		pr_debug("PPS_DC: start cannot update votes (%d)\n", ret);
 
+	ret = gcpm_update_gcpm_fcc(gcpm, "CC_MAX", gcpm->cc_max, true);
+	if (ret < 0)
+		pr_debug("PPS_DC: start cannot update cp_fcc (%d)\n", ret);
+
 	/* this is the CP */
 	dc_psy = gcpm_chg_get_active_cp(gcpm);
 	if (!dc_psy) {
@@ -961,6 +971,7 @@
 static int gcpm_chg_select(struct gcpm_drv *gcpm)
 {
 	int index = GCPM_DEFAULT_CHARGER;
+	int ret;
 
 	if (!gcpm->dc_init_complete)
 		goto exit_done; /* index == GCPM_DEFAULT_CHARGER; */
@@ -973,6 +984,11 @@
 	if (gcpm->dc_ctl == GCPM_DC_CTL_DISABLE_BOTH)
 		goto exit_done; /* index == GCPM_DEFAULT_CHARGER; */
 
+	ret = gvotable_get_current_int_vote(gcpm->dc_chg_avail_votable);
+	dev_dbg(gcpm->device, "%s: dc_chg_avail vote: %d\n", __func__, ret);
+	if (ret <= 0)
+		goto exit_done;
+
 	/*
 	 * check demand first to react to thermal engine, then voltage to
 	 * make sure that we are over min and that we don't start over high
@@ -1637,7 +1653,6 @@
 			pps_ui = DC_ERROR_RETRY_MS;
 		} else {
 			pr_err("PPS_Work: ping DC failed, elap=%lld (%d)\n", elap, ret);
-
 			ret = gcpm_chg_offline(gcpm, gcpm->dc_index);
 			if (ret == 0)
 				ret = gcpm_enable_default(gcpm);
@@ -1850,6 +1865,21 @@
 	return 0;
 }
 
+static int gcpm_dc_chg_avail_callback(struct gvotable_election *el,
+				      const char *reason, void *value)
+{
+	struct gcpm_drv *gcpm = gvotable_get_data(el);
+	const int dc_chg_avail = GVOTABLE_PTR_TO_INT(value);
+
+	if (!gcpm->init_complete)
+		return 0;
+
+	mod_delayed_work(system_wq, &gcpm->select_work, 0);
+	pr_debug("DC_CHG_AVAIL: dc_avail=%d, reason=%s\n", dc_chg_avail, reason);
+
+	return 0;
+}
+
 /* --------------------------------------------------------------------- */
 
 
@@ -2550,6 +2580,7 @@
 	struct gcpm_drv *gcpm = tdev->gcpm;
 	int online = 0, in_idx = -1;
 	int msc_fcc, dc_icl, cp_fcc, ret;
+	bool mdis_crit_lvl;
 
 	if (tdev->thermal_levels <= 0 || lvl < 0 || lvl > tdev->thermal_levels)
 		return -EINVAL;
@@ -2559,7 +2590,8 @@
 	dev_dbg(gcpm->device, "MSC_THERM_MDIS lvl=%d->%d\n", tdev->current_level, (int)lvl);
 
 	tdev->current_level = lvl;
-	if (lvl == tdev->thermal_levels || tdev->thermal_mitigation[lvl] == 0) {
+	mdis_crit_lvl = lvl == tdev->thermal_levels || tdev->thermal_mitigation[lvl] == 0;
+	if (mdis_crit_lvl) {
 		msc_fcc = dc_icl = cp_fcc = 0;
 		gcpm->cp_fcc_hold_limit = gcpm_chg_select_check_cp_limit(gcpm);
 		gcpm->cp_fcc_hold = true;
@@ -2649,6 +2681,10 @@
 		lvl, in_idx, online, cp_fcc, gcpm->cp_fcc_hold,
 		gcpm->cp_fcc_hold_limit);
 
+	ret = gvotable_cast_int_vote(gcpm->dc_chg_avail_votable, REASON_MDIS,
+				     !mdis_crit_lvl, 1);
+	if (ret < 0)
+		dev_err(gcpm->device, "Unable to cast vote for DC Chg avail (%d)\n", ret);
 	/*
 	 * this might be in the callback for mdis_votable
 	 * . cp_fcc == 0 will apply msc_fcc, dc_icl and must cause the
@@ -4011,6 +4047,21 @@
 	gvotable_set_vote2str(gcpm->dc_fcc_votable, gvotable_v2s_int);
 	gvotable_election_set_name(gcpm->dc_fcc_votable, "DC_FCC");
 
+	gcpm->dc_chg_avail_votable = gvotable_create_int_election(
+			NULL, gvotable_comparator_int_min,
+			gcpm_dc_chg_avail_callback, gcpm);
+
+	if (IS_ERR_OR_NULL(gcpm->dc_chg_avail_votable)) {
+		ret = PTR_ERR(gcpm->dc_chg_avail_votable);
+		dev_err(gcpm->device, "no DC chg avail votable %d\n", ret);
+		return ret;
+	}
+
+	gvotable_set_default(gcpm->dc_chg_avail_votable, (void *)1);
+	gvotable_set_vote2str(gcpm->dc_chg_avail_votable, gvotable_v2s_int);
+	gvotable_election_set_name(gcpm->dc_chg_avail_votable, VOTABLE_DC_CHG_AVAIL);
+	gvotable_use_default(gcpm->dc_chg_avail_votable, true);
+
 	/* sysfs & debug */
 	gcpm->debug_entry = gcpm_init_fs(gcpm);
 	if (!gcpm->debug_entry)
diff --git a/google_dock.c b/google_dock.c
index 77ec0ff..ee094f5 100644
--- a/google_dock.c
+++ b/google_dock.c
@@ -453,9 +453,6 @@
 					     val->intval, true);
 		changed = true;
 		break;
-	case GBMS_PROP_POGO_VOUT_ENABLED:
-		ret = google_dock_set_pogo_vout(dock, val->intval);
-		break;
 	default:
 		return -EINVAL;
 	}
@@ -474,7 +471,6 @@
 {
 	switch (psp) {
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
-	case GBMS_PROP_POGO_VOUT_ENABLED:
 		return 1;
 	default:
 		break;
diff --git a/max77759.h b/max77759.h
index 35d02ba..ea7b8ed 100644
--- a/max77759.h
+++ b/max77759.h
@@ -128,6 +128,8 @@
 	bool pogo_vout;	/* pogo 5v vout */
 
 	u8 reg;
+
+	struct gvotable_election *dc_avail_votable;	/* DC_AVAIL */
 };
 
 /* internal system values */
diff --git a/max77759_charger.c b/max77759_charger.c
index 8eac855..7ce20c6 100644
--- a/max77759_charger.c
+++ b/max77759_charger.c
@@ -711,12 +711,6 @@
 			return -EINVAL;
 		}
 
-		if (dc_on) {
-			pr_warn("%s: no wlc_tx with dc_on for now\n", __func__);
-			/* TODO: GSU_MODE_USB_DC_WLC_TX */
-			wlc_tx = 0;
-		}
-
 		if (uc_data->ext_otg_only && cb_data->otg_on) {
 			pr_warn("%s: no wlc_tx with otg_on for now\n", __func__);
 			wlc_tx = 0;
@@ -766,14 +760,10 @@
 		dc_on = false;
 	} else if (wlc_tx) {
 
+		/* Disable DC when Rtx is on will handle by dc_avail_votable */
 		if (!buck_on) {
 			mode = MAX77759_CHGR_MODE_ALL_OFF;
 			usecase = GSU_MODE_WLC_TX;
-		} else if (dc_on) {
-			/* TODO: turn off DC and run off MW */
-			pr_err("WLC_TX+DC is not supported yet\n");
-			mode = MAX77759_CHGR_MODE_ALL_OFF;
-			usecase = GSU_MODE_USB_DC;
 		} else if (chgr_on) {
 			mode = MAX77759_CHGR_MODE_CHGR_BUCK_ON;
 			usecase = GSU_MODE_USB_CHG_WLC_TX;
@@ -831,6 +821,12 @@
 
 	}
 
+	if (!cb_data->dc_avail_votable)
+		cb_data->dc_avail_votable = gvotable_election_get_handle(VOTABLE_DC_CHG_AVAIL);
+	if (cb_data->dc_avail_votable)
+		gvotable_cast_int_vote(cb_data->dc_avail_votable,
+				       "WLC_TX", wlc_tx? 0 : 1, wlc_tx);
+
 	/* reg might be ignored later */
 	cb_data->reg = _chg_cnfg_00_cp_en_set(cb_data->reg, dc_on);
 	cb_data->reg = _chg_cnfg_00_mode_set(cb_data->reg, mode);
diff --git a/pca9468_charger.c b/pca9468_charger.c
index f94ccbd..a3fc6f6 100644
--- a/pca9468_charger.c
+++ b/pca9468_charger.c
@@ -20,6 +20,7 @@
 #include <linux/i2c.h>
 #include <linux/regmap.h>
 #include <linux/rtc.h>
+#include <misc/gvotable.h>
 
 #include "pca9468_regs.h"
 #include "pca9468_charger.h"
@@ -3353,9 +3354,25 @@
 				PCA9468_TA_MAX_CUR);
 			ret = pca9468_get_apdo_max_power(pca9468, ta_max_vol, 0);
 		}
+
 		if (ret < 0) {
+			int ret1;
+
 			pr_err("%s: No APDO to support 2:1\n", __func__);
 			pca9468->chg_mode = CHG_NO_DC_MODE;
+
+			if (!pca9468->dc_avail)
+				pca9468->dc_avail =
+					gvotable_election_get_handle(VOTABLE_DC_CHG_AVAIL);
+
+			if (pca9468->dc_avail) {
+				ret1 = gvotable_cast_int_vote(pca9468->dc_avail,
+							      REASON_DC_DRV, 0, 1);
+				if (ret1 < 0)
+					dev_err(pca9468->dev,
+						"Unable to cast vote for DC Chg avail (%d)\n",
+						ret1);
+			}
 			goto error;
 		}
 
@@ -3860,6 +3877,7 @@
 			"%s: timer_id=%d->%d, charging_state=%u->%u, period=%ld ret=%d",
 			__func__, timer_id, pca9468->timer_id, charging_state,
 			pca9468->charging_state, pca9468->timer_period, ret);
+
 	pca9468_stop_charging(pca9468);
 }
 
@@ -4307,6 +4325,20 @@
 				       __func__, ret);
 
 			pca9468->mains_online = false;
+
+			/* Reset DC Chg un-avail on disconnect */
+			if (!pca9468->dc_avail)
+				pca9468->dc_avail =
+				gvotable_election_get_handle(VOTABLE_DC_CHG_AVAIL);
+
+			if (pca9468->dc_avail) {
+				ret = gvotable_cast_int_vote(pca9468->dc_avail,
+							     REASON_DC_DRV, 1, 1);
+				if (ret < 0)
+					dev_err(pca9468->dev,
+						"Unable to cast vote for DC Chg avail (%d)\n",
+						ret);
+			}
 		} else if (pca9468->mains_online == false) {
 			pca9468->mains_online = true;
 		}
@@ -5083,6 +5115,9 @@
 		}
 	}
 #endif
+
+	pca9468_chg->dc_avail = NULL;
+
 	pca9468_chg->init_done = true;
 	pr_info("pca9468: probe_done\n");
 	pr_debug("%s: =========END=========\n", __func__);
diff --git a/pca9468_charger.h b/pca9468_charger.h
index bf47ff0..5633514 100644
--- a/pca9468_charger.h
+++ b/pca9468_charger.h
@@ -266,6 +266,8 @@
 	u32 wlc_ramp_out_vout_target;
 
 	struct p9468_chg_stats	chg_data;
+
+	struct gvotable_election *dc_avail;
 /* Google Integration END */
 
 };