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

Commit 20fee4a8 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 b331014e
Loading
Loading
Loading
Loading
+42 −1
Original line number Diff line number Diff line
@@ -150,6 +150,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)
@@ -203,9 +212,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;

@@ -213,6 +225,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)
@@ -234,6 +271,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
@@ -17,6 +17,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);
+22 −2
Original line number Diff line number Diff line
@@ -642,6 +642,17 @@ static int smb5_parse_dt(struct smb5 *chip)
	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;
}

@@ -1233,14 +1244,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);
@@ -1292,6 +1309,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);
+32 −4
Original line number Diff line number Diff line
@@ -879,6 +879,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,
				union power_supply_propval *val)
@@ -2655,10 +2686,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) {
+2 −0
Original line number Diff line number Diff line
@@ -551,6 +551,7 @@ struct smb_charger {
	int			usbin_forced_max_uv;
	int			init_thermal_ua;
	u32			comp_clamp_level;
	bool			hvdcp3_standalone_config;

	/* workaround flag */
	u32			wa_flags;
@@ -784,6 +785,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);