From f549f20ac45ddb46be7a96dd1bd754079ff0405b Mon Sep 17 00:00:00 2001 From: Frank Wang Date: Wed, 17 Apr 2024 16:26:40 +0800 Subject: [PATCH] usb: typec: husb311: fix non-standard cable that cc double pull-up For the non-standard cables that double Rp connected to VBUS, when husb311 detects one of CC is Rp, let do clear the another CC status in anyway to dodge being stuck in the SNK_ATTACH_WAIT state. [ 59.366185] VBUS on [ 59.403488] CC1: 0 -> 3, CC2: 0 -> 3 [state TOGGLING, polarity 0, connected] Signed-off-by: Frank Wang Change-Id: Ief2f01c97d1a7be81bca7dd26ecd975d35ea9877 --- drivers/usb/typec/tcpm/tcpci_husb311.c | 33 ++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/usb/typec/tcpm/tcpci_husb311.c b/drivers/usb/typec/tcpm/tcpci_husb311.c index d2c1591c3829..e9f3942afc10 100644 --- a/drivers/usb/typec/tcpm/tcpci_husb311.c +++ b/drivers/usb/typec/tcpm/tcpci_husb311.c @@ -172,6 +172,39 @@ done: static irqreturn_t husb311_irq(int irq, void *dev_id) { struct husb311_chip *chip = dev_id; + enum typec_cc_status cc1, cc2; + u8 reg, role_ctrl; + u8 status; + + husb311_read8(chip, TCPC_ALERT, &status); + dev_dbg(chip->dev, "status 0x%02x", status); + + /* + * If husb311 detects one of CC is Rp, let do clear the another CC + * status in anyway to dodge the non-standard cables that double Rp + * connected to VBUS which produced by Huawei and etc. + */ + if (status & TCPC_ALERT_CC_STATUS) { + husb311_read8(chip, TCPC_ROLE_CTRL, &role_ctrl); + husb311_read8(chip, TCPC_CC_STATUS, ®); + cc1 = tcpci_to_typec_cc((reg >> TCPC_CC_STATUS_CC1_SHIFT) & + TCPC_CC_STATUS_CC1_MASK, + reg & TCPC_CC_STATUS_TERM || + tcpc_presenting_rd(role_ctrl, CC1)); + cc2 = tcpci_to_typec_cc((reg >> TCPC_CC_STATUS_CC2_SHIFT) & + TCPC_CC_STATUS_CC2_MASK, + reg & TCPC_CC_STATUS_TERM || + tcpc_presenting_rd(role_ctrl, CC2)); + + dev_dbg(chip->dev, "CC1 %u, CC2 %u", cc1, cc2); + if (cc1 == TYPEC_CC_RP_DEF) { + role_ctrl |= TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC2_SHIFT; + husb311_write8(chip, TCPC_ROLE_CTRL, role_ctrl); + } else if (cc2 == TYPEC_CC_RP_DEF) { + role_ctrl |= TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC1_SHIFT; + husb311_write8(chip, TCPC_ROLE_CTRL, role_ctrl); + } + } return tcpci_irq(chip->tcpci); }