Merge "power: battery: Add support to enable PPS to work in CV mode"
diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c
index a87725b..8a119ca 100644
--- a/drivers/power/supply/qcom/battery.c
+++ b/drivers/power/supply/qcom/battery.c
@@ -43,6 +43,7 @@
 #define FCC_STEPPER_VOTER		"FCC_STEPPER_VOTER"
 #define FCC_VOTER			"FCC_VOTER"
 #define MAIN_FCC_VOTER			"MAIN_FCC_VOTER"
+#define PD_VOTER			"PD_VOTER"
 
 struct pl_data {
 	int			pl_mode;
@@ -190,30 +191,57 @@ static int cp_get_parallel_mode(struct pl_data *chip, int mode)
 	return pval.intval;
 }
 
-static int get_hvdcp3_icl_limit(struct pl_data *chip)
+static int get_adapter_icl_based_ilim(struct pl_data *chip)
 {
-	int main_icl, target_icl = -EINVAL;
+	int main_icl, adapter_icl = -EINVAL, rc = -EINVAL, final_icl = -EINVAL;
+	union power_supply_propval pval = {0, };
 
+	rc = power_supply_get_property(chip->usb_psy,
+			POWER_SUPPLY_PROP_PD_ACTIVE, &pval);
+	if (rc < 0)
+		pr_err("Failed to read PD_ACTIVE status rc=%d\n",
+				rc);
+	/* Check for QC 3, 3.5 and PPS adapters, return if its none of them */
 	if (chip->charger_type != POWER_SUPPLY_TYPE_USB_HVDCP_3 &&
-		chip->charger_type != POWER_SUPPLY_TYPE_USB_HVDCP_3P5)
-		return target_icl;
+		chip->charger_type != POWER_SUPPLY_TYPE_USB_HVDCP_3P5 &&
+		pval.intval != POWER_SUPPLY_PD_PPS_ACTIVE)
+		return final_icl;
 
 	/*
-	 * For HVDCP3 adapters, limit max. ILIM as follows:
-	 * HVDCP3_ICL: Maximum ICL of HVDCP3 adapter(from DT configuration)
-	 * For Parallel input configurations:
-	 * VBUS: target_icl = HVDCP3_ICL - main_ICL
-	 * VMID: target_icl = HVDCP3_ICL
+	 * For HVDCP3/HVDCP_3P5 adapters, limit max. ILIM as:
+	 * HVDCP3_ICL: Maximum ICL of HVDCP3 adapter(from DT
+	 * configuration).
+	 *
+	 * For PPS adapters, limit max. ILIM to
+	 * MIN(qc4_max_icl, PD_CURRENT_MAX)
 	 */
-	target_icl = chip->chg_param->hvdcp3_max_icl_ua;
+	if (pval.intval == POWER_SUPPLY_PD_PPS_ACTIVE) {
+		adapter_icl = min_t(int, chip->chg_param->qc4_max_icl_ua,
+				get_client_vote_locked(chip->usb_icl_votable,
+				PD_VOTER));
+		if (adapter_icl <= 0)
+			adapter_icl = chip->chg_param->qc4_max_icl_ua;
+	} else {
+		adapter_icl = chip->chg_param->hvdcp3_max_icl_ua;
+	}
+
+	/*
+	 * For Parallel input configurations:
+	 * VBUS: final_icl = adapter_icl - main_ICL
+	 * VMID: final_icl = adapter_icl
+	 */
+	final_icl = adapter_icl;
 	if (cp_get_parallel_mode(chip, PARALLEL_INPUT_MODE)
 					== POWER_SUPPLY_PL_USBIN_USBIN) {
 		main_icl = get_effective_result_locked(chip->usb_icl_votable);
-		if ((main_icl >= 0) && (main_icl < target_icl))
-			target_icl -= main_icl;
+		if ((main_icl >= 0) && (main_icl < adapter_icl))
+			final_icl = adapter_icl - main_icl;
 	}
 
-	return target_icl;
+	pr_debug("charger_type=%d final_icl=%d adapter_icl=%d main_icl=%d\n",
+		chip->charger_type, final_icl, adapter_icl, main_icl);
+
+	return final_icl;
 }
 
 /*
@@ -244,7 +272,7 @@ static void cp_configure_ilim(struct pl_data *chip, const char *voter, int ilim)
 					== POWER_SUPPLY_PL_OUTPUT_VPH)
 		return;
 
-	target_icl = get_hvdcp3_icl_limit(chip);
+	target_icl = get_adapter_icl_based_ilim(chip);
 	ilim = (target_icl > 0) ? min(ilim, target_icl) : ilim;
 
 	rc = power_supply_get_property(chip->cp_master_psy,
@@ -742,7 +770,7 @@ static void get_fcc_stepper_params(struct pl_data *chip, int main_fcc_ua,
 		if (!chip->cp_ilim_votable)
 			chip->cp_ilim_votable = find_votable("CP_ILIM");
 
-		target_icl = get_hvdcp3_icl_limit(chip) * 2;
+		target_icl = get_adapter_icl_based_ilim(chip) * 2;
 		total_fcc_ua -= chip->main_fcc_ua;
 
 		/*
diff --git a/drivers/power/supply/qcom/battery.h b/drivers/power/supply/qcom/battery.h
index acb4984..c614544 100644
--- a/drivers/power/supply/qcom/battery.h
+++ b/drivers/power/supply/qcom/battery.h
@@ -13,6 +13,7 @@ struct charger_param {
 	u32 hvdcp2_max_icl_ua;
 	u32 hvdcp3_max_icl_ua;
 	u32 forced_main_fcc;
+	u32 qc4_max_icl_ua;
 };
 
 int qcom_batt_init(struct charger_param *param);
diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c
index 103ca3a..5672c31 100644
--- a/drivers/power/supply/qcom/qpnp-smb5.c
+++ b/drivers/power/supply/qcom/qpnp-smb5.c
@@ -433,6 +433,7 @@ static int smb5_configure_internal_pull(struct smb_charger *chg, int type,
 #define MICRO_P1A			100000
 #define MICRO_1PA			1000000
 #define MICRO_3PA			3000000
+#define MICRO_4PA			4000000
 #define OTG_DEFAULT_DEGLITCH_TIME_MS	50
 #define DEFAULT_WD_BARK_TIME		64
 #define DEFAULT_WD_SNARL_TIME_8S	0x07
@@ -605,6 +606,12 @@ static int smb5_parse_dt_misc(struct smb5 *chip, struct device_node *node)
 	if (chg->chg_param.hvdcp2_max_icl_ua <= 0)
 		chg->chg_param.hvdcp2_max_icl_ua = MICRO_3PA;
 
+	/* Used only in Adapter CV mode of operation */
+	of_property_read_u32(node, "qcom,qc4-max-icl-ua",
+					&chg->chg_param.qc4_max_icl_ua);
+	if (chg->chg_param.qc4_max_icl_ua <= 0)
+		chg->chg_param.qc4_max_icl_ua = MICRO_4PA;
+
 	return 0;
 }