summaryrefslogtreecommitdiff
path: root/common/usb_pd_protocol.c
diff options
context:
space:
mode:
authorAyushee <ayushee.shah@intel.com>2020-01-14 18:08:15 -0800
committerCommit Bot <commit-bot@chromium.org>2020-01-31 20:57:57 +0000
commit42ca68d3cdf74193dd041d336b698bfe3ae1221a (patch)
treee6375405bf02fff7dbd65827b543fdcbaf5870bc /common/usb_pd_protocol.c
parenta0d6b40c49c7615cddded5e6811a550468eba7b2 (diff)
downloadchrome-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.c72
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);