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

Commit 6489cf0c authored by Guru Das Srinagesh's avatar Guru Das Srinagesh
Browse files

power: smb5-lib: Modify max USBIN voltage seen by userspace



Non-QC2.0-compliant adaptors, as the name suggests, support only a
subset of the three voltage levels (5, 9 and 12V). For example, a
non-compliant adaptor might support only up to 9V and not 12V (5V is
supported as a bare minimum). Thus, when a request for 12V is made, it
will collapse and unexpected behaviour will ensue.

Therefore for such adaptors, modify the maximum USBIN voltage provided
to userspace as follows: return the voltage that is the next lesser
value than the voltage that has been determined to be unsupported by the
adaptor. Also, reject all requests from userspace for these unsupported
voltage levels.

NOTE:
  This is only applicable to platforms that use SW INOV. The existing
  MAX_PULSES based solution works only for platforms that use HW INOV.
  To be clear, modifying the MAX_PULSES register happens in both HW and
  SW INOV modes, but only produces the desired effect in SW INOV mode.
  These two solutions do not interfere with each other and can coexist.

Change-Id: I99abea1651c5c89d5d895eb51587e30c0d5c52ea
Signed-off-by: default avatarGuru Das Srinagesh <gurus@codeaurora.org>
parent af21981a
Loading
Loading
Loading
Loading
+25 −4
Original line number Diff line number Diff line
@@ -1893,11 +1893,21 @@ int smblib_dp_dm(struct smb_charger *chg, int val)
			pr_err("Failed to force 5V\n");
		break;
	case POWER_SUPPLY_DP_DM_FORCE_9V:
		if (chg->qc2_unsupported_voltage == QC2_NON_COMPLIANT_9V) {
			smblib_err(chg, "Couldn't set 9V: unsupported\n");
			return -EINVAL;
		}

		rc = smblib_force_vbus_voltage(chg, FORCE_9V_BIT);
		if (rc < 0)
			pr_err("Failed to force 9V\n");
		break;
	case POWER_SUPPLY_DP_DM_FORCE_12V:
		if (chg->qc2_unsupported_voltage == QC2_NON_COMPLIANT_12V) {
			smblib_err(chg, "Couldn't set 12V: unsupported\n");
			return -EINVAL;
		}

		rc = smblib_force_vbus_voltage(chg, FORCE_12V_BIT);
		if (rc < 0)
			pr_err("Failed to force 12V\n");
@@ -2094,6 +2104,15 @@ int smblib_get_prop_usb_voltage_max(struct smb_charger *chg,
{
	switch (chg->real_charger_type) {
	case POWER_SUPPLY_TYPE_USB_HVDCP:
		if (chg->qc2_unsupported_voltage == QC2_NON_COMPLIANT_9V) {
			val->intval = MICRO_5V;
			break;
		} else if (chg->qc2_unsupported_voltage ==
				QC2_NON_COMPLIANT_12V) {
			val->intval = MICRO_9V;
			break;
		}
		/* else, fallthrough */
	case POWER_SUPPLY_TYPE_USB_HVDCP_3:
	case POWER_SUPPLY_TYPE_USB_PD:
		if (chg->smb_version == PMI632_SUBTYPE)
@@ -3118,7 +3137,8 @@ irqreturn_t usbin_uv_irq_handler(int irq, void *data)
	wdata = &chg->irq_info[SWITCHER_POWER_OK_IRQ].irq_data->storm_data;
	reset_storm_count(wdata);

	if (!chg->non_compliant_chg_detected &&
	/* Workaround for non-QC2.0-compliant chargers follows */
	if (!chg->qc2_unsupported_voltage &&
			apsd->pst == POWER_SUPPLY_TYPE_USB_HVDCP) {
		rc = smblib_read(chg, QC_CHANGE_STATUS_REG, &stat);
		if (rc < 0)
@@ -3133,11 +3153,11 @@ irqreturn_t usbin_uv_irq_handler(int irq, void *data)
			smblib_err(chg,
				"Couldn't read QC2 max pulses rc=%d\n", rc);

		chg->non_compliant_chg_detected = true;
		chg->qc2_max_pulses = (max_pulses &
				HVDCP_PULSE_COUNT_MAX_QC2_MASK);

		if (stat & QC_12V_BIT) {
			chg->qc2_unsupported_voltage = QC2_NON_COMPLIANT_12V;
			rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG,
					HVDCP_PULSE_COUNT_MAX_QC2_MASK,
					HVDCP_PULSE_COUNT_MAX_QC2_9V);
@@ -3146,6 +3166,7 @@ irqreturn_t usbin_uv_irq_handler(int irq, void *data)
						rc);

		} else if (stat & QC_9V_BIT) {
			chg->qc2_unsupported_voltage = QC2_NON_COMPLIANT_9V;
			rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG,
					HVDCP_PULSE_COUNT_MAX_QC2_MASK,
					HVDCP_PULSE_COUNT_MAX_QC2_5V);
@@ -3745,7 +3766,7 @@ static void typec_src_removal(struct smb_charger *chg)
	 * if non-compliant charger caused UV, restore original max pulses
	 * and turn SUSPEND_ON_COLLAPSE_USBIN_BIT back on.
	 */
	if (chg->non_compliant_chg_detected) {
	if (chg->qc2_unsupported_voltage) {
		rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG,
				HVDCP_PULSE_COUNT_MAX_QC2_MASK,
				chg->qc2_max_pulses);
@@ -3760,7 +3781,7 @@ static void typec_src_removal(struct smb_charger *chg)
			smblib_err(chg, "Couldn't turn on SUSPEND_ON_COLLAPSE_USBIN_BIT rc=%d\n",
					rc);

		chg->non_compliant_chg_detected = false;
		chg->qc2_unsupported_voltage = QC2_COMPLIANT;
	}

	if (chg->use_extcon)
+7 −1
Original line number Diff line number Diff line
@@ -79,6 +79,12 @@ enum sink_src_mode {
	UNATTACHED_MODE,
};

enum qc2_non_comp_voltage {
	QC2_COMPLIANT,
	QC2_NON_COMPLIANT_9V,
	QC2_NON_COMPLIANT_12V
};

enum {
	BOOST_BACK_WA			= BIT(0),
};
@@ -373,7 +379,7 @@ struct smb_charger {
	u32			wa_flags;
	int			boost_current_ua;
	int                     qc2_max_pulses;
	bool                    non_compliant_chg_detected;
	enum qc2_non_comp_voltage qc2_unsupported_voltage;

	/* extcon for VBUS / ID notification to USB for uUSB */
	struct extcon_dev	*extcon;