From 62c0a7e74cac24cc24a3d0f1876bed598eb8e2a5 Mon Sep 17 00:00:00 2001 From: Aseda Aboagye Date: Fri, 8 Jun 2018 18:19:59 -0700 Subject: 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 Reviewed-on: https://chromium-review.googlesource.com/1094264 Commit-Ready: Aseda Aboagye Tested-by: Aseda Aboagye Reviewed-by: Jonathan Brandmeyer --- common/usb_pd_protocol.c | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file 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))) { -- cgit v1.2.1