summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/power/qcom-charger/smb-lib.c44
-rw-r--r--drivers/power/qcom-charger/smb-lib.h2
-rw-r--r--drivers/power/qcom-charger/smb-reg.h19
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 {