From 1e078bcf88708ee3f1b78b7a0bd765ba94674ab9 Mon Sep 17 00:00:00 2001 From: Edward Hill Date: Tue, 10 Dec 2019 18:12:19 -0700 Subject: nct38xx: Set pull on both CC lines on disconnect tcpci_nct38xx_set_cc() only sets the pull resistor on one CC line according to polarity. This is correct when attached, but on disconnect we need to set the pull resistor on both CC lines, since polarity is no longer known (unless DRP toggle is enabled, since that will take care of setting both CC lines to do the toggling). This workaround for chromium:951681 can be removed once that bug is fixed in the TCPCI common code. BUG=b:146003980, chromium:951681 BRANCH=none TEST=Charging works with both plug orientations with AP off Change-Id: I1406263011a4c8d595be0d7093f2ab220690de3f Signed-off-by: Edward Hill Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1961305 Reviewed-by: Denis Brockus Commit-Queue: Denis Brockus --- driver/tcpm/nct38xx.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'driver') diff --git a/driver/tcpm/nct38xx.c b/driver/tcpm/nct38xx.c index d89c91522d..6630d570c9 100644 --- a/driver/tcpm/nct38xx.c +++ b/driver/tcpm/nct38xx.c @@ -8,8 +8,10 @@ #include "common.h" #include "console.h" +#include "hooks.h" #include "ioexpander_nct38xx.h" #include "nct38xx.h" +#include "task.h" #include "tcpci.h" #if !defined(CONFIG_USB_PD_TCPM_TCPCI) @@ -29,6 +31,7 @@ static unsigned char txBuf[33]; static unsigned char rxBuf[33]; /* Save the selected rp value */ static int selected_rp[CONFIG_USB_PD_PORT_MAX_COUNT]; +static int selected_pull[CONFIG_USB_PD_PORT_MAX_COUNT]; static int nct38xx_tcpm_init(int port) { @@ -36,6 +39,7 @@ static int nct38xx_tcpm_init(int port) int reg; cable_polarity[port] = POLARITY_NONE; + selected_pull[port] = TYPEC_CC_OPEN; rv = tcpci_tcpm_init(port); if (rv) @@ -150,9 +154,10 @@ int tcpci_nct38xx_select_rp_value(int port, int rp) */ static int tcpci_nct38xx_set_cc(int port, int pull) { - int rv; + selected_pull[port] = pull; + if (cable_polarity[port] == POLARITY_NONE) { rv = tcpci_nct38xx_check_cable_polarity(port); if (rv) @@ -174,6 +179,30 @@ static int tcpci_nct38xx_set_cc(int port, int pull) return rv; } +/* + * tcpci_nct38xx_set_cc() only sets the pull resistor on one CC line according + * to polarity. This is correct when attached, but on disconnect we need to + * set the pull resistor on both CC lines, since polarity is no longer known + * (unless DRP toggle is enabled, since that will take care of setting both + * CC lines to do the toggling). + * TODO(crbug.com/951681): This code can be removed once that bug is fixed. + */ +static void disconnect_hook(void) +{ + int port = TASK_ID_TO_PD_PORT(task_get_current()); + int rv; + + if (pd_get_dual_role(port) != PD_DRP_TOGGLE_ON + && selected_pull[port] != TYPEC_CC_OPEN) { + rv = tcpc_write(port, TCPC_REG_ROLE_CTRL, + TCPC_REG_ROLE_CTRL_SET(0, selected_rp[port], + selected_pull[port], selected_pull[port])); + if (rv) + CPRINTS("C%d failed to set pull on disconnect", port); + } +} +DECLARE_HOOK(HOOK_USB_PD_DISCONNECT, disconnect_hook, HOOK_PRIO_DEFAULT); + static int tcpci_nct38xx_get_cc(int port, enum tcpc_cc_voltage_status *cc1, enum tcpc_cc_voltage_status *cc2) { -- cgit v1.2.1