diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c index d3abfbfbbc43..fa4232d4436c 100644 --- a/drivers/power/supply/qcom/qpnp-smb2.c +++ b/drivers/power/supply/qcom/qpnp-smb2.c @@ -432,6 +432,7 @@ static enum power_supply_property smb2_usb_props[] = { POWER_SUPPLY_PROP_CTM_CURRENT_MAX, POWER_SUPPLY_PROP_HW_CURRENT_MAX, POWER_SUPPLY_PROP_REAL_TYPE, + POWER_SUPPLY_PROP_PR_SWAP, }; static int smb2_usb_get_prop(struct power_supply *psy, @@ -536,6 +537,9 @@ static int smb2_usb_get_prop(struct power_supply *psy, case POWER_SUPPLY_PROP_HW_CURRENT_MAX: rc = smblib_get_charge_current(chg, &val->intval); break; + case POWER_SUPPLY_PROP_PR_SWAP: + rc = smblib_get_prop_pr_swap_in_progress(chg, val); + break; default: pr_err("get prop %d is not supported in usb\n", psp); rc = -EINVAL; @@ -594,6 +598,9 @@ static int smb2_usb_set_prop(struct power_supply *psy, rc = vote(chg->usb_icl_votable, CTM_VOTER, val->intval >= 0, val->intval); break; + case POWER_SUPPLY_PROP_PR_SWAP: + rc = smblib_set_prop_pr_swap_in_progress(chg, val); + break; default: pr_err("set prop %d is not supported\n", psp); rc = -EINVAL; diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index 4c66bc500ab4..dee387bc87e7 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -3669,6 +3669,17 @@ static void smblib_handle_typec_removal(struct smb_charger *chg) if (rc < 0) smblib_err(chg, "Couldn't restore crude sensor rc=%d\n", rc); + mutex_lock(&chg->vconn_oc_lock); + if (!chg->vconn_en) + goto unlock; + + smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, + VCONN_EN_VALUE_BIT, 0); + chg->vconn_en = false; + +unlock: + mutex_unlock(&chg->vconn_oc_lock); + typec_sink_removal(chg); smblib_update_usb_type(chg); } @@ -3699,15 +3710,15 @@ static void smblib_handle_typec_debounce_done(struct smb_charger *chg, union power_supply_propval pval = {0, }; if (rising) { - if (!chg->typec_present) { + if (!chg->typec_present && !chg->pr_swap_in_progress) { chg->typec_present = true; - smblib_dbg(chg, PR_MISC, "TypeC insertion\n"); + smblib_dbg(chg, PR_MISC, "TypeC insertion\n"); smblib_handle_typec_insertion(chg, sink_attached); } } else { - if (chg->typec_present) { + if (chg->typec_present && !chg->pr_swap_in_progress) { chg->typec_present = false; - smblib_dbg(chg, PR_MISC, "TypeC removal\n"); + smblib_dbg(chg, PR_MISC, "TypeC removal\n"); smblib_handle_typec_removal(chg); } } @@ -3841,6 +3852,30 @@ irqreturn_t smblib_handle_wdog_bark(int irq, void *data) return IRQ_HANDLED; } +/************** + * Additional USB PSY getters/setters + * that call interrupt functions +***************/ + +int smblib_get_prop_pr_swap_in_progress(struct smb_charger *chg, + union power_supply_propval *val) +{ + val->intval = chg->pr_swap_in_progress; + return 0; +} + +int smblib_set_prop_pr_swap_in_progress(struct smb_charger *chg, + const union power_supply_propval *val) +{ + chg->pr_swap_in_progress = val->intval; + /* + * call the cc changed irq to handle real removals while + * PR_SWAP was in progress + */ + smblib_usb_typec_change(chg); + return 0; +} + /*************** * Work Queues * ***************/ diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h index 41015d49b31e..70219e259e05 100644 --- a/drivers/power/supply/qcom/smb-lib.h +++ b/drivers/power/supply/qcom/smb-lib.h @@ -321,6 +321,7 @@ struct smb_charger { u8 typec_status[5]; bool typec_legacy_valid; int fake_input_current_limited; + bool pr_swap_in_progress; /* workaround flag */ u32 wa_flags; @@ -506,6 +507,10 @@ int smblib_rerun_aicl(struct smb_charger *chg); int smblib_set_icl_current(struct smb_charger *chg, int icl_ua); int smblib_get_icl_current(struct smb_charger *chg, int *icl_ua); int smblib_get_charge_current(struct smb_charger *chg, int *total_current_ua); +int smblib_get_prop_pr_swap_in_progress(struct smb_charger *chg, + union power_supply_propval *val); +int smblib_set_prop_pr_swap_in_progress(struct smb_charger *chg, + const union power_supply_propval *val); int smblib_init(struct smb_charger *chg); int smblib_deinit(struct smb_charger *chg);