Skip to content

Commit 5638b0d

Browse files
Xu Yanggregkh
authored andcommitted
usb: typec: tcpci: don't touch CC line if it's Vconn source
With the AMS and Collision Avoidance, tcpm often needs to change the CC's termination. When one CC line is sourcing Vconn, if we still change its termination, the voltage of the another CC line is likely to be fluctuant and unstable. Therefore, we should verify whether a CC line is sourcing Vconn before changing its termination and only change the termination that is not a Vconn line. This can be done by reading the Vconn Present bit of POWER_ STATUS register. To determine the polarity, we can read the Plug Orientation bit of TCPC_CONTROL register. Since Vconn can only be sourced if Plug Orientation is set. Fixes: 0908c5a ("usb: typec: tcpm: AMS and Collision Avoidance") cc: <[email protected]> Reviewed-by: Guenter Roeck <[email protected]> Acked-by: Heikki Krogerus <[email protected]> Signed-off-by: Xu Yang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 945c37e commit 5638b0d

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

drivers/usb/typec/tcpm/tcpci.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,25 @@ static int tcpci_write16(struct tcpci *tcpci, unsigned int reg, u16 val)
7575
static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc)
7676
{
7777
struct tcpci *tcpci = tcpc_to_tcpci(tcpc);
78+
bool vconn_pres;
79+
enum typec_cc_polarity polarity = TYPEC_POLARITY_CC1;
7880
unsigned int reg;
7981
int ret;
8082

83+
ret = regmap_read(tcpci->regmap, TCPC_POWER_STATUS, &reg);
84+
if (ret < 0)
85+
return ret;
86+
87+
vconn_pres = !!(reg & TCPC_POWER_STATUS_VCONN_PRES);
88+
if (vconn_pres) {
89+
ret = regmap_read(tcpci->regmap, TCPC_TCPC_CTRL, &reg);
90+
if (ret < 0)
91+
return ret;
92+
93+
if (reg & TCPC_TCPC_CTRL_ORIENTATION)
94+
polarity = TYPEC_POLARITY_CC2;
95+
}
96+
8197
switch (cc) {
8298
case TYPEC_CC_RA:
8399
reg = (TCPC_ROLE_CTRL_CC_RA << TCPC_ROLE_CTRL_CC1_SHIFT) |
@@ -112,6 +128,16 @@ static int tcpci_set_cc(struct tcpc_dev *tcpc, enum typec_cc_status cc)
112128
break;
113129
}
114130

131+
if (vconn_pres) {
132+
if (polarity == TYPEC_POLARITY_CC2) {
133+
reg &= ~(TCPC_ROLE_CTRL_CC1_MASK << TCPC_ROLE_CTRL_CC1_SHIFT);
134+
reg |= (TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC1_SHIFT);
135+
} else {
136+
reg &= ~(TCPC_ROLE_CTRL_CC2_MASK << TCPC_ROLE_CTRL_CC2_SHIFT);
137+
reg |= (TCPC_ROLE_CTRL_CC_OPEN << TCPC_ROLE_CTRL_CC2_SHIFT);
138+
}
139+
}
140+
115141
ret = regmap_write(tcpci->regmap, TCPC_ROLE_CTRL, reg);
116142
if (ret < 0)
117143
return ret;

drivers/usb/typec/tcpm/tcpci.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
#define TCPC_POWER_STATUS_SOURCING_VBUS BIT(4)
9999
#define TCPC_POWER_STATUS_VBUS_DET BIT(3)
100100
#define TCPC_POWER_STATUS_VBUS_PRES BIT(2)
101+
#define TCPC_POWER_STATUS_VCONN_PRES BIT(1)
101102
#define TCPC_POWER_STATUS_SINKING_VBUS BIT(0)
102103

103104
#define TCPC_FAULT_STATUS 0x1f

0 commit comments

Comments
 (0)