Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0c8f37a3 authored by Ashay Jaiswal's avatar Ashay Jaiswal
Browse files

power: smb5: Add QC 3.0 support for dual charging with charge-pump



In case of QC 3.0 with SMB1390 configuration, SMB1390 output
current is restricted to 90% of the configured ILIM to accommodate
SMB1390's ILIM sensing inaccuracy, add support to adjust and add this
ILIM offset current to main charger's FCC configuration.

While at it, add a DT property to select the supported ICL for QC 3.0,
this is used to limit the ILIM.

Change-Id: I840416a9535078eed2f96e26334ad0cb5cb36db8
Signed-off-by: default avatarAshay Jaiswal <ashayj@codeaurora.org>
parent e51c6cff
Loading
Loading
Loading
Loading
+42 −1
Original line number Diff line number Diff line
@@ -142,6 +142,15 @@ enum {
/*********
 * HELPER*
 *********/
static bool is_usb_available(struct pl_data *chip)
{
	if (!chip->usb_psy)
		chip->usb_psy =
			power_supply_get_by_name("usb");

	return !!chip->usb_psy;
}

static bool is_cp_available(struct pl_data *chip)
{
	if (!chip->cp_master_psy)
@@ -195,9 +204,12 @@ static int cp_get_parallel_mode(struct pl_data *chip, int mode)
 */
static void cp_configure_ilim(struct pl_data *chip, const char *voter, int ilim)
{
	int rc, fcc;
	int rc, fcc, main_icl, target_icl = chip->chg_param->hvdcp3_max_icl_ua;
	union power_supply_propval pval = {0, };

	if (!is_usb_available(chip))
		return;

	if (!is_cp_available(chip))
		return;

@@ -205,6 +217,31 @@ static void cp_configure_ilim(struct pl_data *chip, const char *voter, int ilim)
					== POWER_SUPPLY_PL_OUTPUT_VPH)
		return;

	rc = power_supply_get_property(chip->usb_psy,
				POWER_SUPPLY_PROP_REAL_TYPE, &pval);
	if (rc < 0)
		return;

	/*
	 * For HVDCP3 adapters limit max. ILIM based on DT configuration
	 * of HVDCP3 ICL value.
	 * Input VBUS:
	 * target_icl = HVDCP3_ICL - main_ICL
	 * Input VMID
	 * target_icl = HVDCP3_ICL
	 */
	if (pval.intval == POWER_SUPPLY_TYPE_USB_HVDCP_3) {
		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;
		}

		ilim = min(target_icl, ilim);
	}

	rc = power_supply_get_property(chip->cp_master_psy,
				POWER_SUPPLY_PROP_MIN_ICL, &pval);
	if (rc < 0)
@@ -226,6 +263,10 @@ static void cp_configure_ilim(struct pl_data *chip, const char *voter, int ilim)
			vote(chip->cp_ilim_votable, voter, true, pval.intval);
		else
			vote(chip->cp_ilim_votable, voter, true, ilim);

		pl_dbg(chip, PR_PARALLEL,
			"ILIM: vote: %d voter:%s min_ilim=%d fcc = %d\n",
			ilim, voter, pval.intval, fcc);
	}
}

+1 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ struct charger_param {
	u32 fcc_step_delay_ms;
	u32 fcc_step_size_ua;
	u32 smb_version;
	u32 hvdcp3_max_icl_ua;
};

int qcom_batt_init(struct charger_param *param);
+23 −2
Original line number Diff line number Diff line
@@ -584,6 +584,18 @@ static int smb5_parse_dt_misc(struct smb5 *chip, struct device_node *node)
	if (chg->chg_param.fcc_step_size_ua <= 0)
		chg->chg_param.fcc_step_size_ua = DEFAULT_FCC_STEP_SIZE_UA;

	/*
	 * If property is present parallel charging with CP is disabled
	 * with HVDCP3 adapter.
	 */
	chg->hvdcp3_standalone_config = of_property_read_bool(node,
					"qcom,hvdcp3-standalone-config");

	of_property_read_u32(node, "qcom,hvdcp3-max-icl-ua",
					&chg->chg_param.hvdcp3_max_icl_ua);
	if (chg->chg_param.hvdcp3_max_icl_ua <= 0)
		chg->chg_param.hvdcp3_max_icl_ua = MICRO_3PA;

	return 0;
}

@@ -1293,14 +1305,20 @@ static int smb5_usb_main_set_prop(struct power_supply *psy,
	struct smb5 *chip = power_supply_get_drvdata(psy);
	struct smb_charger *chg = &chip->chg;
	union power_supply_propval pval = {0, };
	int rc = 0;
	int rc = 0, offset_ua = 0;

	switch (psp) {
	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
		rc = smblib_set_charge_param(chg, &chg->param.fv, val->intval);
		break;
	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
		rc = smblib_set_charge_param(chg, &chg->param.fcc, val->intval);
		/* Adjust Main FCC for QC3.0 + SMB1390 */
		rc = smblib_get_qc3_main_icl_offset(chg, &offset_ua);
		if (rc < 0)
			offset_ua = 0;

		rc = smblib_set_charge_param(chg, &chg->param.fcc,
						val->intval + offset_ua);
		break;
	case POWER_SUPPLY_PROP_CURRENT_MAX:
		rc = smblib_set_icl_current(chg, val->intval);
@@ -1352,6 +1370,9 @@ static int smb5_usb_main_set_prop(struct power_supply *psy,
	case POWER_SUPPLY_PROP_FORCE_MAIN_ICL:
		vote_override(chg->usb_icl_votable, CC_MODE_VOTER,
				(val->intval < 0) ? false : true, val->intval);
		/* Main ICL updated re-calculate ILIM */
		if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_HVDCP_3)
			rerun_election(chg->fcc_votable);
		break;
	case POWER_SUPPLY_PROP_COMP_CLAMP_LEVEL:
		rc = smb5_set_prop_comp_clamp_level(chg, val);
+34 −10
Original line number Diff line number Diff line
@@ -872,6 +872,37 @@ int smblib_set_aicl_cont_threshold(struct smb_chg_param *param,
/********************
 * HELPER FUNCTIONS *
 ********************/
static bool is_cp_available(struct smb_charger *chg)
{
	if (!chg->cp_psy)
		chg->cp_psy = power_supply_get_by_name("charge_pump_master");

	return !!chg->cp_psy;
}

#define CP_TO_MAIN_ICL_OFFSET_PC		10
int smblib_get_qc3_main_icl_offset(struct smb_charger *chg, int *offset_ua)
{
	union power_supply_propval pval = {0, };
	int rc;

	if ((chg->real_charger_type != POWER_SUPPLY_TYPE_USB_HVDCP_3)
		|| chg->hvdcp3_standalone_config || !is_cp_available(chg)) {
		*offset_ua = 0;
		return 0;
	}

	rc = power_supply_get_property(chg->cp_psy, POWER_SUPPLY_PROP_CP_ILIM,
					&pval);
	if (rc < 0) {
		smblib_err(chg, "Couldn't get CP ILIM rc=%d\n", rc);
		return rc;
	}

	*offset_ua = (pval.intval * CP_TO_MAIN_ICL_OFFSET_PC * 2) / 100;

	return 0;
}

int smblib_get_prop_from_bms(struct smb_charger *chg,
				enum power_supply_property psp,
@@ -2685,10 +2716,7 @@ static int smblib_update_thermal_readings(struct smb_charger *chg)
	}

	if (chg->sec_chg_selected == POWER_SUPPLY_CHARGER_SEC_CP) {
		if (!chg->cp_psy)
			chg->cp_psy =
				power_supply_get_by_name("charge_pump_master");
		if (chg->cp_psy) {
		if (is_cp_available(chg)) {
			rc = power_supply_get_property(chg->cp_psy,
				POWER_SUPPLY_PROP_CP_DIE_TEMP, &pval);
			if (rc < 0) {
@@ -6216,12 +6244,8 @@ static bool is_cp_topo_vbatt(struct smb_charger *chg)
	bool is_vbatt;
	union power_supply_propval pval;

	if (!chg->cp_psy) {
		chg->cp_psy = power_supply_get_by_name("charge_pump_master");

		if (!chg->cp_psy)
	if (!is_cp_available(chg))
		return false;
	}

	rc = power_supply_get_property(chg->cp_psy,
				POWER_SUPPLY_PROP_PARALLEL_OUTPUT_MODE, &pval);
+2 −0
Original line number Diff line number Diff line
@@ -553,6 +553,7 @@ struct smb_charger {
	u32			comp_clamp_level;
	int			wls_icl_ua;
	bool			dcin_aicl_done;
	bool			hvdcp3_standalone_config;

	/* workaround flag */
	u32			wa_flags;
@@ -799,6 +800,7 @@ void smblib_apsd_enable(struct smb_charger *chg, bool enable);
int smblib_force_vbus_voltage(struct smb_charger *chg, u8 val);
int smblib_get_irq_status(struct smb_charger *chg,
				union power_supply_propval *val);
int smblib_get_qc3_main_icl_offset(struct smb_charger *chg, int *offset_ua);

int smblib_init(struct smb_charger *chg);
int smblib_deinit(struct smb_charger *chg);