diff options
| -rw-r--r-- | drivers/power/qcom-charger/smb-lib.c | 44 | ||||
| -rw-r--r-- | drivers/power/qcom-charger/smb-lib.h | 2 | ||||
| -rw-r--r-- | drivers/power/qcom-charger/smb-reg.h | 19 |
3 files changed, 65 insertions, 0 deletions
diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c index bc1b8b2bf03e..5ed22b226162 100644 --- a/drivers/power/qcom-charger/smb-lib.c +++ b/drivers/power/qcom-charger/smb-lib.c @@ -474,6 +474,11 @@ static int smblib_detach_typec(struct smb_charger *chg) /* cc removed, disable pd_allowed */ vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, true, 0); vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, true, 0); + vote(chg->pd_disallowed_votable_indirect, LEGACY_CABLE_VOTER, true, 0); + vote(chg->pd_disallowed_votable_indirect, VBUS_CC_SHORT_VOTER, true, 0); + + /* reset votes from vbus_cc_short */ + vote(chg->hvdcp_disable_votable, VBUS_CC_SHORT_VOTER, true, 0); vote(chg->apsd_disable_votable, PD_VOTER, false, 0); @@ -2361,6 +2366,43 @@ static void smblib_handle_typec_debounce_done(struct smb_charger *chg, smblib_typec_mode_name[pval.intval]); } +static void smblib_handle_legacy_cable(struct smb_charger *chg, + bool typec_debounced) +{ + int rc, rp; + u8 stat; + bool legacy_cable; + bool vbus_cc_short = false; + + if (!typec_debounced) + return; + + rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat); + if (rc < 0) { + dev_err(chg->dev, "Couldn't read TYPE_C_STATUS_5 rc=%d\n", + rc); + return; + } + + legacy_cable = stat & TYPEC_LEGACY_CABLE_STATUS_BIT; + vote(chg->pd_disallowed_votable_indirect, LEGACY_CABLE_VOTER, + legacy_cable, 0); + + if (legacy_cable) { + rp = smblib_get_prop_ufp_mode(chg); + if (rp == POWER_SUPPLY_TYPEC_SOURCE_HIGH + || rp == POWER_SUPPLY_TYPEC_NON_COMPLIANT) { + vbus_cc_short = true; + pr_err("Disabling PD and HVDCP, VBUS-CC shorted, rp = %d found\n", + rp); + } + } + + vote(chg->hvdcp_disable_votable, VBUS_CC_SHORT_VOTER, vbus_cc_short, 0); + vote(chg->pd_disallowed_votable_indirect, VBUS_CC_SHORT_VOTER, + vbus_cc_short, 0); +} + irqreturn_t smblib_handle_usb_typec_change(int irq, void *data) { struct smb_irq_data *irq_data = data; @@ -2382,6 +2424,8 @@ irqreturn_t smblib_handle_usb_typec_change(int irq, void *data) (bool)(stat & CC_ATTACHED_BIT), (bool)(stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT), (bool)(stat & UFP_DFP_MODE_STATUS_BIT)); + smblib_handle_legacy_cable(chg, + (bool)(stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT)); power_supply_changed(chg->usb_psy); diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h index fc1c3ba94a15..910a9f7b9a30 100644 --- a/drivers/power/qcom-charger/smb-lib.h +++ b/drivers/power/qcom-charger/smb-lib.h @@ -41,6 +41,8 @@ enum print_reason { #define HVDCP_TIMEOUT_VOTER "HVDCP_TIMEOUT_VOTER" #define PD_DISALLOWED_INDIRECT_VOTER "PD_DISALLOWED_INDIRECT_VOTER" #define PD_HARD_RESET_VOTER "PD_HARD_RESET_VOTER" +#define VBUS_CC_SHORT_VOTER "VBUS_CC_SHORT_VOTER" +#define LEGACY_CABLE_VOTER "LEGACY_CABLE_VOTER" enum smb_mode { PARALLEL_MASTER = 0, diff --git a/drivers/power/qcom-charger/smb-reg.h b/drivers/power/qcom-charger/smb-reg.h index a499d354086c..c567ec2752c1 100644 --- a/drivers/power/qcom-charger/smb-reg.h +++ b/drivers/power/qcom-charger/smb-reg.h @@ -506,6 +506,15 @@ enum { #define CC_ORIENTATION_BIT BIT(1) #define CC_ATTACHED_BIT BIT(0) +#define TYPE_C_STATUS_5_REG (USBIN_BASE + 0x0F) +#define TRY_SOURCE_FAILED_BIT BIT(6) +#define TRY_SINK_FAILED_BIT BIT(5) +#define TIMER_STAGE_2_BIT BIT(4) +#define TYPEC_LEGACY_CABLE_STATUS_BIT BIT(3) +#define TYPEC_NONCOMP_LEGACY_CABLE_STATUS_BIT BIT(2) +#define TYPEC_TRYSOURCE_DETECT_STATUS_BIT BIT(1) +#define TYPEC_TRYSINK_DETECT_STATUS_BIT BIT(0) + /* USBIN Interrupt Bits */ #define TYPE_C_CHANGE_RT_STS_BIT BIT(7) #define USBIN_ICL_CHANGE_RT_STS_BIT BIT(6) @@ -555,6 +564,16 @@ enum { #define TYPE_C_UFP_MODE_BIT BIT(1) #define EN_80UA_180UA_CUR_SOURCE_BIT BIT(0) +#define TYPE_C_CFG_3_REG (USBIN_BASE + 0x5A) +#define TVBUS_DEBOUNCE_BIT BIT(7) +#define TYPEC_LEGACY_CABLE_INT_EN_BIT BIT(6) +#define TYPEC_NONCOMPLIANT_LEGACY_CABLE_INT_EN_BIT BIT(5) +#define TYPEC_TRYSOURCE_DETECT_INT_EN_BIT BIT(4) +#define TYPEC_TRYSINK_DETECT_INT_EN_BIT BIT(3) +#define EN_TRYSINK_MODE_BIT BIT(2) +#define EN_LEGACY_CABLE_DETECTION_BIT BIT(1) +#define ALLOW_PD_DRING_UFP_TCCDB_BIT BIT(0) + #define USBIN_ADAPTER_ALLOW_CFG_REG (USBIN_BASE + 0x60) #define USBIN_ADAPTER_ALLOW_MASK GENMASK(3, 0) enum { |
