diff options
author | Ayushee <ayushee.shah@intel.com> | 2020-01-14 18:08:15 -0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-01-31 20:57:57 +0000 |
commit | 42ca68d3cdf74193dd041d336b698bfe3ae1221a (patch) | |
tree | e6375405bf02fff7dbd65827b543fdcbaf5870bc /common/usb_pd_protocol.c | |
parent | a0d6b40c49c7615cddded5e6811a550468eba7b2 (diff) | |
download | chrome-ec-42ca68d3cdf74193dd041d336b698bfe3ae1221a.tar.gz |
TCPMv1: Add support for Thunderbolt active cables
For entering into Thunderbolt-Compatible mode with active
cable, the port sends Enter mode command for SOP', SOP''
(if the cable has a SOP'' controller) and SOP respectively.
If the port doesn't receive GoodCRC from Enter Mode SOP'',
the port resets the cable characteristic and exits the
Thunderbolt-Compatible mode discovery.
This CL enables SOP'' communication with the cable plug
and adds support to enter into Thunderbolt-compatible mode
with active cables.
BUG=b:140643923
BRANCH=None
TEST=Able to enter into Thunderbolt-Compatible mode for
active cables.
Change-Id: Iea0c652043933047e0158265c911775d4afe5758
Signed-off-by: Ayushee <ayushee.shah@intel.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2001938
Reviewed-by: Diana Z <dzigterman@chromium.org>
Diffstat (limited to 'common/usb_pd_protocol.c')
-rw-r--r-- | common/usb_pd_protocol.c | 72 |
1 files changed, 62 insertions, 10 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 18a6afdfbb..ea18fd05d4 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -2210,10 +2210,43 @@ static uint64_t vdm_get_ready_timeout(uint32_t vdm_hdr) return timeout; } +static void exit_tbt_mode_sop_prime(int port) +{ + /* Exit Thunderbolt-Compatible mode SOP' */ + uint16_t header; + int opos; + + if (!IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE)) + return; + + opos = pd_alt_mode(port, USB_VID_INTEL); + if (opos <= 0) + return; + + CPRINTS("C%d Cable exiting TBT Compat mode", port); + if (!pd_dfp_exit_mode(port, USB_VID_INTEL, opos)) + return; + + header = PD_HEADER(PD_DATA_VENDOR_DEF, pd[port].power_role, + pd[port].data_role, pd[port].msg_id, + (int)pd[port].vdo_count, pd_get_rev(port), 0); + + pd[port].vdo_data[0] = VDO(USB_VID_INTEL, 1, + CMD_EXIT_MODE | VDO_OPOS(opos)); + + pd_transmit(port, TCPC_TX_SOP_PRIME, header, pd[port].vdo_data, + AMS_START); + + usb_mux_set(port, USB_PD_MUX_USB_ENABLED, USB_SWITCH_CONNECT, + pd_get_polarity(port)); +} + static void pd_vdm_send_state_machine(int port) { int res; uint16_t header; + enum pd_msg_type msg_type = + pd_msg_tx_type(port, pd[port].data_role, pd[port].flags); switch (pd[port].vdm_state) { case VDM_STATE_READY: @@ -2241,8 +2274,8 @@ static void pd_vdm_send_state_machine(int port) * data role swap takes place during source and sink * negotiation and in case of failure, a soft reset is issued. */ - if (is_sop_prime_ready(port, pd[port].data_role, - pd[port].flags)) { + if ((msg_type == PD_MSG_SOP_PRIME) || + (msg_type == PD_MSG_SOP_PRIME_PRIME)) { /* Prepare SOP'/SOP'' header and send VDM */ header = PD_HEADER( PD_DATA_VENDOR_DEF, @@ -2252,13 +2285,26 @@ static void pd_vdm_send_state_machine(int port) (int)pd[port].vdo_count, pd_get_rev(port), 0); - res = pd_transmit(port, TCPC_TX_SOP_PRIME, header, - pd[port].vdo_data, AMS_START); + res = pd_transmit(port, + (msg_type == PD_MSG_SOP_PRIME) ? + TCPC_TX_SOP_PRIME : + TCPC_TX_SOP_PRIME_PRIME, + header, + pd[port].vdo_data, + AMS_START); /* - * If there is no ack from the cable, its a non-emark - * cable and since, the pd flow should continue - * irrespective of cable response, sending - * discover_identity so the pd flow remains intact. + * In the case of SOP', if there is no response from + * the cable, it's a non-emark cable and therefore the + * pd flow should continue irrespective of cable + * response, sending discover_identity so the pd flow + * remains intact. + * + * In the case of SOP'', if there is no response from + * the cable, exit Thunderbolt-Compatible mode + * discovery, reset the mux state since, the mux will + * be set to a safe state before entering + * Thunderbolt-Compatible mode and enter the default + * mode. */ if (res < 0) { header = PD_HEADER(PD_DATA_VENDOR_DEF, @@ -2267,8 +2313,14 @@ static void pd_vdm_send_state_machine(int port) pd[port].msg_id, (int)pd[port].vdo_count, pd_get_rev(port), 0); - pd[port].vdo_data[0] = - VDO(USB_SID_PD, 1, CMD_DISCOVER_SVID); + + if ((msg_type == PD_MSG_SOP_PRIME_PRIME) && + IS_ENABLED(CONFIG_USBC_SS_MUX)) { + exit_tbt_mode_sop_prime(port); + } else if (msg_type == PD_MSG_SOP_PRIME) { + pd[port].vdo_data[0] = VDO(USB_SID_PD, + 1, CMD_DISCOVER_SVID); + } res = pd_transmit(port, TCPC_TX_SOP, header, pd[port].vdo_data, AMS_START); reset_pd_cable(port); |