diff options
author | Aseda Aboagye <aaboagye@google.com> | 2018-06-08 18:19:59 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-07-04 05:43:46 -0700 |
commit | 62c0a7e74cac24cc24a3d0f1876bed598eb8e2a5 (patch) | |
tree | 0078e3c5293116bda0b05dce76dae5969c3ab97d | |
parent | a84165968ca78fe7d783e522f79dd01abc6303fd (diff) | |
download | chrome-ec-62c0a7e74cac24cc24a3d0f1876bed598eb8e2a5.tar.gz |
USB PD: Initialize CC polarity during init.
Previously, explicit PD contracts were not maintained after a reset, but
that has recently changed. Now, if a PD contract is in place, a
SoftReset is sent to the port partner to renogotiate the contract
without dropping VBUS. However, the CC polarity was not initialized in
this code path. On a system with external TCPCs, we may have been lucky
and depending upon the orientation, the right CC line may have been
used. This was actually breaking boards that did lose their TCPC state
after reset.
This commit simply initializes the CC polarity before potentially
sending any PD messages.
BUG=b:111114159
BRANCH=whichever take the new SoftReset after reset patches.
TEST=Flash servo_v4; Plug in PD source to CHG port, reboot, verify that
PD communication still works with the source following a reboot.
TEST=Flash scarlet; Plug in a charge through hub with a charger and USB
storage devices plugged in, reboot, verify that PD communication still
works with the source following a reboot. Repeat the test in the other
orientation.
Change-Id: I85a16dd8982747a66883579bb8cf3673dbdd95d8
Signed-off-by: Aseda Aboagye <aaboagye@google.com>
Reviewed-on: https://chromium-review.googlesource.com/1094264
Commit-Ready: Aseda Aboagye <aaboagye@chromium.org>
Tested-by: Aseda Aboagye <aaboagye@chromium.org>
Reviewed-by: Jonathan Brandmeyer <jbrandmeyer@chromium.org>
-rw-r--r-- | common/usb_pd_protocol.c | 45 |
1 files changed, 36 insertions, 9 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 0cae3bde9e..567d9240d9 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -2245,9 +2245,6 @@ void pd_task(void *u) pd_set_data_role(port, (saved_flgs & PD_BBRMFLG_DATA_ROLE) ? PD_ROLE_DFP : PD_ROLE_UFP); - /* Set the terminations to match our power role. */ - tcpm_set_cc(port, pd[port].power_role ? - TYPEC_CC_RP : TYPEC_CC_RD); /* * Since there is an explicit contract in place, let's @@ -2258,13 +2255,17 @@ void pd_task(void *u) this_state = PD_STATE_SOFT_RESET; /* - * Enable TCPC RX so we can hear back from our port - * partner. + * Set the TCPC reset event such that we can set our CC + * terminations, determine polarity, and enable RX so we + * can hear back from our port partner. */ - tcpm_set_rx_enable(port, 1); + task_set_event(task_get_current(), + PD_EVENT_TCPC_RESET, + 0); } } #endif /* defined(CONFIG_USB_PD_DUAL_ROLE) */ + pd[port].vdm_state = VDM_STATE_DONE; set_state(port, this_state); #ifdef CONFIG_USB_PD_MAX_SINGLE_SOURCE_CURRENT @@ -2348,9 +2349,34 @@ void pd_task(void *u) if ((evt & PD_EVENT_TCPC_RESET) && (pd[port].task_state != PD_STATE_DRP_AUTO_TOGGLE)) { #endif - /* Ensure CC termination is default */ - tcpm_set_cc(port, PD_ROLE_DEFAULT(port) == - PD_ROLE_SOURCE ? TYPEC_CC_RP : TYPEC_CC_RD); +#ifdef CONFIG_USB_PD_DUAL_ROLE + if (pd[port].task_state == PD_STATE_SOFT_RESET) { + int cc1, cc2; + + /* + * Set the terminations to match our power + * role. + */ + tcpm_set_cc(port, pd[port].power_role ? + TYPEC_CC_RP : TYPEC_CC_RD); + + /* Determine the polarity. */ + tcpm_get_cc(port, &cc1, &cc2); + if (pd[port].power_role == PD_ROLE_SINK) { + pd[port].polarity = + get_snk_polarity(cc1, cc2); + } else { + pd[port].polarity = + (cc1 != TYPEC_CC_VOLT_RD); + } + } else +#endif /* CONFIG_USB_PD_DUAL_ROLE */ + { + /* Ensure CC termination is default */ + tcpm_set_cc(port, PD_ROLE_DEFAULT(port) == + PD_ROLE_SOURCE ? TYPEC_CC_RP : + TYPEC_CC_RD); + } /* * If we have a stable contract in the default role, @@ -2363,6 +2389,7 @@ void pd_task(void *u) #ifdef CONFIG_USB_PD_DUAL_ROLE (PD_ROLE_DEFAULT(port) == PD_ROLE_SINK && pd[port].task_state == PD_STATE_SNK_READY) || + (pd[port].task_state == PD_STATE_SOFT_RESET) || #endif (PD_ROLE_DEFAULT(port) == PD_ROLE_SOURCE && pd[port].task_state == PD_STATE_SRC_READY))) { |