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

Commit b0403c44 authored by Abhijeet Dharmapurikar's avatar Abhijeet Dharmapurikar Committed by Harry Yang
Browse files

power: smb-lib: cache USB Type-C status



Currently the USB Type-C status is retrieved from the hardware in real
time. The Type-C change IRQ should trigger on every change of the Type-C
status, therefore it is not necessary to read the status registers
multiple times if a Type-C change IRQ has not triggered. Furthermore,
workarounds which force UFP/DFP mode, or disable Type-C altogether could
mislead the software into thinking a removal has happened.

Cache all of the USB Type-C status registers upon receiving a USB Type-C
change IRQ, and use the cached status where appropriate.

CRs-Fixed: 2020132
Change-Id: I99f2ff29633207898ae803672162db0c3cec80dc
Signed-off-by: default avatarNicholas Troast <ntroast@codeaurora.org>
Signed-off-by: default avatarAbhijeet Dharmapurikar <adharmap@codeaurora.org>
parent 11330d9f
Loading
Loading
Loading
Loading
+29 −86
Original line number Diff line number Diff line
@@ -1144,7 +1144,7 @@ static int smblib_usb_irq_enable_vote_callback(struct votable *votable,
static int _smblib_vconn_regulator_enable(struct regulator_dev *rdev)
{
	struct smb_charger *chg = rdev_get_drvdata(rdev);
	u8 otg_stat, stat4;
	u8 otg_stat, val;
	int rc = 0, i;

	if (!chg->external_vconn) {
@@ -1175,17 +1175,12 @@ static int _smblib_vconn_regulator_enable(struct regulator_dev *rdev)
	 * VCONN_EN_ORIENTATION is overloaded with overriding the CC pin used
	 * for Vconn, and it should be set with reverse polarity of CC_OUT.
	 */
	rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat4);
	if (rc < 0) {
		smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
		return rc;
	}

	smblib_dbg(chg, PR_OTG, "enabling VCONN\n");
	stat4 = stat4 & CC_ORIENTATION_BIT ? 0 : VCONN_EN_ORIENTATION_BIT;
	val = chg->typec_status[3] &
			CC_ORIENTATION_BIT ? 0 : VCONN_EN_ORIENTATION_BIT;
	rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
				 VCONN_EN_VALUE_BIT | VCONN_EN_ORIENTATION_BIT,
				 VCONN_EN_VALUE_BIT | stat4);
				 VCONN_EN_VALUE_BIT | val);
	if (rc < 0) {
		smblib_err(chg, "Couldn't enable vconn setting rc=%d\n", rc);
		return rc;
@@ -2146,23 +2141,13 @@ int smblib_get_prop_charger_temp_max(struct smb_charger *chg,
int smblib_get_prop_typec_cc_orientation(struct smb_charger *chg,
					 union power_supply_propval *val)
{
	int rc = 0;
	u8 stat;

	rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
	if (rc < 0) {
		smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
		return rc;
	}
	smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n",
		   stat);

	if (stat & CC_ATTACHED_BIT)
		val->intval = (bool)(stat & CC_ORIENTATION_BIT) + 1;
	if (chg->typec_status[3] & CC_ATTACHED_BIT)
		val->intval =
			(bool)(chg->typec_status[3] & CC_ORIENTATION_BIT) + 1;
	else
		val->intval = 0;

	return rc;
	return 0;
}

static const char * const smblib_typec_mode_name[] = {
@@ -2180,17 +2165,7 @@ static const char * const smblib_typec_mode_name[] = {

static int smblib_get_prop_ufp_mode(struct smb_charger *chg)
{
	int rc;
	u8 stat;

	rc = smblib_read(chg, TYPE_C_STATUS_1_REG, &stat);
	if (rc < 0) {
		smblib_err(chg, "Couldn't read TYPE_C_STATUS_1 rc=%d\n", rc);
		return POWER_SUPPLY_TYPEC_NONE;
	}
	smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_1 = 0x%02x\n", stat);

	switch (stat) {
	switch (chg->typec_status[0]) {
	case 0:
		return POWER_SUPPLY_TYPEC_NONE;
	case UFP_TYPEC_RDSTD_BIT:
@@ -2208,17 +2183,7 @@ static int smblib_get_prop_ufp_mode(struct smb_charger *chg)

static int smblib_get_prop_dfp_mode(struct smb_charger *chg)
{
	int rc;
	u8 stat;

	rc = smblib_read(chg, TYPE_C_STATUS_2_REG, &stat);
	if (rc < 0) {
		smblib_err(chg, "Couldn't read TYPE_C_STATUS_2 rc=%d\n", rc);
		return POWER_SUPPLY_TYPEC_NONE;
	}
	smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_2 = 0x%02x\n", stat);

	switch (stat & DFP_TYPEC_MASK) {
	switch (chg->typec_status[1] & DFP_TYPEC_MASK) {
	case DFP_RA_RA_BIT:
		return POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER;
	case DFP_RD_RD_BIT:
@@ -2239,28 +2204,17 @@ static int smblib_get_prop_dfp_mode(struct smb_charger *chg)
int smblib_get_prop_typec_mode(struct smb_charger *chg,
			       union power_supply_propval *val)
{
	int rc;
	u8 stat;

	rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
	if (rc < 0) {
		smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
	if (!(chg->typec_status[3] & TYPEC_DEBOUNCE_DONE_STATUS_BIT)) {
		val->intval = POWER_SUPPLY_TYPEC_NONE;
		return rc;
	}
	smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n", stat);

	if (!(stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT)) {
		val->intval = POWER_SUPPLY_TYPEC_NONE;
		return rc;
		return 0;
	}

	if (stat & UFP_DFP_MODE_STATUS_BIT)
	if (chg->typec_status[3] & UFP_DFP_MODE_STATUS_BIT)
		val->intval = smblib_get_prop_dfp_mode(chg);
	else
		val->intval = smblib_get_prop_ufp_mode(chg);

	return rc;
	return 0;
}

int smblib_get_prop_typec_power_role(struct smb_charger *chg,
@@ -2548,18 +2502,11 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
			      const union power_supply_propval *val)
{
	int rc;
	u8 stat = 0;
	bool orientation;

	if (!get_effective_result(chg->pd_allowed_votable))
		return -EINVAL;

	rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
	if (rc < 0) {
		smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
		return rc;
	}

	chg->pd_active = val->intval;
	if (chg->pd_active) {
		vote(chg->apsd_disable_votable, PD_VOTER, true, 0);
@@ -2571,7 +2518,7 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
		 * line when TYPEC_SPARE_CFG_BIT (CC pin selection s/w override)
		 * is set or when VCONN_EN_VALUE_BIT is set.
		 */
		orientation = stat & CC_ORIENTATION_BIT;
		orientation = chg->typec_status[3] & CC_ORIENTATION_BIT;
		rc = smblib_masked_write(chg,
				TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
				VCONN_EN_ORIENTATION_BIT,
@@ -2622,7 +2569,8 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
			smblib_err(chg, "Couldn't enable HW cc_out rc=%d\n",
									rc);

		if ((stat & (TYPEC_DEBOUNCE_DONE_STATUS_BIT | UFP_DFP_MODE_BIT))
		if ((chg->typec_status[3] &
			(TYPEC_DEBOUNCE_DONE_STATUS_BIT | UFP_DFP_MODE_BIT))
			== TYPEC_DEBOUNCE_DONE_STATUS_BIT)
			try_rerun_apsd_for_hvdcp(chg);
	}
@@ -3735,37 +3683,32 @@ irqreturn_t smblib_handle_usb_typec_change_for_uusb(struct smb_charger *chg)
static void smblib_usb_typec_change(struct smb_charger *chg)
{
	int rc;
	u8 stat4, stat5;
	bool debounce_done, sink_attached, legacy_cable;

	rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat4);
	rc = smblib_multibyte_read(chg, TYPE_C_STATUS_1_REG,
							chg->typec_status, 5);
	if (rc < 0) {
		smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
		return;
	}

	rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat5);
	if (rc < 0) {
		smblib_err(chg, "Couldn't read TYPE_C_STATUS_5 rc=%d\n", rc);
		smblib_err(chg, "Couldn't cache USB Type-C status rc=%d\n", rc);
		return;
	}

	debounce_done = (bool)(stat4 & TYPEC_DEBOUNCE_DONE_STATUS_BIT);
	sink_attached = (bool)(stat4 & UFP_DFP_MODE_STATUS_BIT);
	legacy_cable = (bool)(stat5 & TYPEC_LEGACY_CABLE_STATUS_BIT);
	debounce_done =
		(bool)(chg->typec_status[3] & TYPEC_DEBOUNCE_DONE_STATUS_BIT);
	sink_attached =
		(bool)(chg->typec_status[3] & UFP_DFP_MODE_STATUS_BIT);
	legacy_cable =
		(bool)(chg->typec_status[4] & TYPEC_LEGACY_CABLE_STATUS_BIT);

	smblib_handle_typec_debounce_done(chg,
			debounce_done, sink_attached, legacy_cable);

	if (stat4 & TYPEC_VBUS_ERROR_STATUS_BIT)
	if (chg->typec_status[3] & TYPEC_VBUS_ERROR_STATUS_BIT)
		smblib_dbg(chg, PR_INTERRUPT, "IRQ: vbus-error\n");

	if (stat4 & TYPEC_VCONN_OVERCURR_STATUS_BIT)
	if (chg->typec_status[3] & TYPEC_VCONN_OVERCURR_STATUS_BIT)
		schedule_work(&chg->vconn_oc_work);

	power_supply_changed(chg->usb_psy);
	smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n", stat4);
	smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_5 = 0x%02x\n", stat5);
}

irqreturn_t smblib_handle_usb_typec_change(int irq, void *data)
+1 −0
Original line number Diff line number Diff line
@@ -309,6 +309,7 @@ struct smb_charger {
	bool			uusb_apsd_rerun_done;
	bool			pd_hard_reset;
	bool			typec_present;
	u8			typec_status[5];

	/* workaround flag */
	u32			wa_flags;