diff options
author | Tom Hughes <tomhughes@chromium.org> | 2022-09-21 14:08:36 -0700 |
---|---|---|
committer | Tom Hughes <tomhughes@chromium.org> | 2022-09-22 12:59:38 -0700 |
commit | c453fd704268ef72de871b0c5ac7a989de662334 (patch) | |
tree | fcf6ce5810f9ff9e3c8cce434812dd75492269ed /common/usbc/tbt_alt_mode.c | |
parent | 6c1587ca70f558b4f96b3f0b18ad8b027d3ba99d (diff) | |
parent | 28712dae9d7ed1e694f7622cc083afa71090d4d5 (diff) | |
download | chrome-ec-c453fd704268ef72de871b0c5ac7a989de662334.tar.gz |
Merge remote-tracking branch cros/main into firmware-fpmcu-dartmonkey-releasefirmware-fpmcu-dartmonkey-release
Generated by: ./util/update_release_branch.py --board dartmonkey --relevant_paths_file
./util/fingerprint-relevant-paths.txt firmware-fpmcu-dartmonkey-release
Relevant changes:
git log --oneline 6c1587ca70..28712dae9d -- board/nocturne_fp
board/dartmonkey common/fpsensor docs/fingerprint driver/fingerprint
util/getversion.sh
ded9307b79 util/getversion.sh: Fix version when not in a git repo
956055e692 board: change Google USB vendor info
71b2ef709d Update license boilerplate text in source code files
33e11afda0 Revert "fpsensor: Build fpsensor source file with C++"
c8d0360723 fpsensor: Build fpsensor source file with C++
bc113abd53 fpsensor: Fix g++ compiler error
150a58a0dc fpsensor: Fix fp_set_sensor_mode return type
b33b5ce85b fpsensor: Remove nested designators for C++ compatibility
2e864b2539 tree-wide: const-ify argv for console commands
56d8b360f9 test: Add test for get ikm failure when seed not set
3a3d6c3690 test: Add test for fpsensor trivial key failure
233e6bbd08 fpsensor_crypto: Abstract calls to hmac_SHA256
0a041b285b docs/fingerprint: Typo correction
c03fab67e2 docs/fingerprint: Fix the path of fputils.py
0b5d4baf5a util/getversion.sh: Fix empty file list handling
6e128fe760 FPMCU dev board environment with Satlab
3eb29b6aa5 builtin: Move ssize_t to sys/types.h
345d62ebd1 docs/fingerprint: Update power numbers for latest dartmonkey release
c25ffdb316 common: Conditionally support printf %l and %i modifiers
9a3c514b45 test: Add a test to check if the debugger is connected
54e603413f Move standard library tests to their own file
43fa6b4bf8 docs/fingerprint: Update power numbers for latest bloonchipper release
25536f9a84 driver/fingerprint/fpc/bep/fpc_sensor_spi.c: Format with clang-format
4face99efd driver/fingerprint/fpc/libfp/fpc_sensor_pal.h: Format with clang-format
738de2b575 trng: Rename rand to trng_rand
14b8270edd docs/fingerprint: Update dragonclaw power numbers
0b268f93d1 driver/fingerprint/fpc/libfp/fpc_private.c: Format with clang-format
f80da163f2 driver/fingerprint/fpc/libfp/fpc_private.h: Format with clang-format
a0751778f4 board/nocturne_fp/ro_workarounds.c: Format with clang-format
5e9c85c9b1 driver/fingerprint/fpc/libfp/fpc_sensor_pal.c: Format with clang-format
c1f9dd3cf8 driver/fingerprint/fpc/libfp/fpc_bio_algorithm.h: Format with clang-format
eb1e1bed8d driver/fingerprint/fpc/libfp/fpc1145_private.h: Format with clang-format
6e7b611821 driver/fingerprint/fpc/bep/fpc_bio_algorithm.h: Format with clang-format
e0589cd5e2 driver/fingerprint/fpc/bep/fpc1035_private.h: Format with clang-format
58f0246dbe board/nocturne_fp/board_ro.c: Format with clang-format
7905e556a0 common/fpsensor/fpsensor_crypto.c: Format with clang-format
21289d170c driver/fingerprint/fpc/bep/fpc1025_private.h: Format with clang-format
98a20f937e common/fpsensor/fpsensor_state.c: Format with clang-format
a2d255d8af common/fpsensor/fpsensor.c: Format with clang-format
84e53a65da board/nocturne_fp/board.h: Format with clang-format
73055eeb3f driver/fingerprint/fpc/bep/fpc_private.c: Format with clang-format
0f7b5cb509 common/fpsensor/fpsensor_private.h: Format with clang-format
1ceade6e65 driver/fingerprint/fpc/bep/fpc_private.h: Format with clang-format
dca9d74321 Revert "trng: Rename rand to trng_rand"
a6b0b3554f trng: Rename rand to trng_rand
28d0b75b70 third_party/boringssl: Remove unused header
BRANCH=None
BUG=b:244387210 b:242720240 b:215613183 b:242720910 b:236386294
BUG=b:234181908 b:244781166 b:234781655 b:234143158 b:234181908
BUG=b:237344361 b:236025198 b:234181908 b:180945056 chromium:1098010
BUG=b:246424843 b:234181908 b:131913998
TEST=`make -j buildall`
TEST=./util/run_device_tests.py --board dartmonkey
Test "aes": PASSED
Test "cec": PASSED
Test "cortexm_fpu": PASSED
Test "crc": PASSED
Test "flash_physical": PASSED
Test "flash_write_protect": PASSED
Test "fpsensor_hw": PASSED
Test "fpsensor_spi_ro": PASSED
Test "fpsensor_spi_rw": PASSED
Test "fpsensor_uart_ro": PASSED
Test "fpsensor_uart_rw": PASSED
Test "mpu_ro": PASSED
Test "mpu_rw": PASSED
Test "mutex": PASSED
Test "pingpong": PASSED
Test "printf": PASSED
Test "queue": PASSED
Test "rollback_region0": PASSED
Test "rollback_region1": PASSED
Test "rollback_entropy": PASSED
Test "rtc": PASSED
Test "sha256": PASSED
Test "sha256_unrolled": PASSED
Test "static_if": PASSED
Test "stdlib": PASSED
Test "system_is_locked_wp_on": PASSED
Test "system_is_locked_wp_off": PASSED
Test "timer_dos": PASSED
Test "utils": PASSED
Test "utils_str": PASSED
Test "panic_data_dartmonkey_v2.0.2887": PASSED
Test "panic_data_nocturne_fp_v2.2.64": PASSED
Test "panic_data_nami_fp_v2.2.144": PASSED
Force-Relevant-Builds: all
Signed-off-by: Tom Hughes <tomhughes@chromium.org>
Change-Id: I2c312583a709fedae8fe11d92c22328c3b634bc7
Diffstat (limited to 'common/usbc/tbt_alt_mode.c')
-rw-r--r-- | common/usbc/tbt_alt_mode.c | 398 |
1 files changed, 290 insertions, 108 deletions
diff --git a/common/usbc/tbt_alt_mode.c b/common/usbc/tbt_alt_mode.c index 5baf9d1a73..d1ad031fad 100644 --- a/common/usbc/tbt_alt_mode.c +++ b/common/usbc/tbt_alt_mode.c @@ -1,4 +1,4 @@ -/* Copyright 2020 The Chromium OS Authors. All rights reserved. +/* Copyright 2020 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -14,6 +14,7 @@ #include "compile_time_macros.h" #include "console.h" #include "tcpm/tcpm.h" +#include "typec_control.h" #include "usb_common.h" #include "usb_mux.h" #include "usb_pd.h" @@ -57,8 +58,8 @@ */ #ifdef CONFIG_COMMON_RUNTIME -#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) -#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ##args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ##args) #else #define CPRINTF(format, args...) #define CPRINTS(format, args...) @@ -70,8 +71,8 @@ * with a partner. It may be fixed in b/159495742, in which case this * logic is unneeded. */ -#define TBT_FLAG_RETRY_DONE BIT(0) -#define TBT_FLAG_EXIT_DONE BIT(1) +#define TBT_FLAG_RETRY_DONE BIT(0) +#define TBT_FLAG_EXIT_DONE BIT(1) #define TBT_FLAG_CABLE_ENTRY_DONE BIT(2) static uint8_t tbt_flags[CONFIG_USB_PD_PORT_MAX_COUNT]; @@ -123,14 +124,12 @@ void tbt_init(int port) bool tbt_is_active(int port) { - return tbt_state[port] != TBT_INACTIVE && - tbt_state[port] != TBT_START; + return tbt_state[port] != TBT_INACTIVE && tbt_state[port] != TBT_START; } bool tbt_entry_is_done(int port) { - return tbt_state[port] == TBT_ACTIVE || - tbt_state[port] == TBT_INACTIVE; + return tbt_state[port] == TBT_ACTIVE || tbt_state[port] == TBT_INACTIVE; } bool tbt_cable_entry_is_done(int port) @@ -140,13 +139,15 @@ bool tbt_cable_entry_is_done(int port) static void tbt_exit_done(int port) { - /* - * If the EC exits an alt mode autonomously, don't try to enter it again. If - * the AP commands the EC to exit DP mode, it might command the EC to enter - * again later, so leave the state machine ready for that possibility. - */ - tbt_state[port] = IS_ENABLED(CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY) - ? TBT_START : TBT_INACTIVE; + /* + * If the EC exits an alt mode autonomously, don't try to enter it + * again. If the AP commands the EC to exit DP mode, it might command + * the EC to enter again later, so leave the state machine ready for + * that possibility. + */ + tbt_state[port] = IS_ENABLED(CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY) ? + TBT_START : + TBT_INACTIVE; TBT_CLR_FLAG(port, TBT_FLAG_RETRY_DONE); TBT_CLR_FLAG(port, TBT_FLAG_CABLE_ENTRY_DONE); @@ -159,10 +160,47 @@ static void tbt_exit_done(int port) tbt_prints("alt mode protocol failed!", port); } -void tbt_exit_mode_request(int port) +static bool tbt_is_lrd_active_cable(int port) { union tbt_mode_resp_cable cable_mode_resp; + cable_mode_resp.raw_value = + pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME); + if (get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE && + cable_mode_resp.tbt_active_passive == TBT_CABLE_ACTIVE) + return true; + + return false; +} + +/* Check if this port requires SOP' mode entry and exit */ +static bool tbt_sop_prime_needed(int port) +{ + /* + * We require SOP' entry if cable is + * active cable, or + * an LRD cable (passive in DiscoverIdentity, active in TBT mode) + */ + if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE || + tbt_is_lrd_active_cable(port)) + return true; + return false; +} + +/* Check if this port requires SOP'' mode entry and exit */ +static bool tbt_sop_prime_prime_needed(int port) +{ + const struct pd_discovery *disc; + + disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); + if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE && + disc->identity.product_t1.a_rev20.sop_p_p) + return true; + return false; +} + +void tbt_exit_mode_request(int port) +{ TBT_SET_FLAG(port, TBT_FLAG_RETRY_DONE); TBT_CLR_FLAG(port, TBT_FLAG_EXIT_DONE); /* @@ -172,26 +210,24 @@ void tbt_exit_mode_request(int port) * TODO (b/156749387): Remove once data reset feature is in place. */ if (tbt_state[port] == TBT_ENTER_SOP) { - cable_mode_resp.raw_value = - pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME); - /* * For Linear re-driver cables, the port enters USB4 mode * with Thunderbolt mode for SOP prime. Hence, on request to * exit, only exit Thunderbolt mode SOP prime */ - tbt_state[port] = - cable_mode_resp.tbt_active_passive == TBT_CABLE_ACTIVE ? - TBT_EXIT_SOP_PRIME : TBT_EXIT_SOP_PRIME_PRIME; + tbt_state[port] = tbt_sop_prime_prime_needed(port) ? + TBT_EXIT_SOP_PRIME_PRIME : + TBT_EXIT_SOP_PRIME; } } -static bool tbt_response_valid(int port, enum tcpci_msg_type type, - char *cmdt, int vdm_cmd) +static bool tbt_response_valid(int port, enum tcpci_msg_type type, char *cmdt, + int vdm_cmd) { enum tbt_states st = tbt_state[port]; union tbt_mode_resp_cable cable_mode_resp = { - .raw_value = pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME) }; + .raw_value = pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME) + }; /* * Check for an unexpected response. @@ -216,71 +252,50 @@ static void tbt_retry_enter_mode(int port) TBT_SET_FLAG(port, TBT_FLAG_RETRY_DONE); } -/* Send Exit Mode to SOP''(if supported), or SOP' */ -static void tbt_active_cable_exit_mode(int port) -{ - const struct pd_discovery *disc; - - disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); - - if (disc->identity.product_t1.a_rev20.sop_p_p) - tbt_state[port] = TBT_EXIT_SOP_PRIME_PRIME; - else - tbt_state[port] = TBT_EXIT_SOP_PRIME; -} - bool tbt_cable_entry_required_for_usb4(int port) { const struct pd_discovery *disc_sop_prime; - union tbt_mode_resp_cable cable_mode_resp; - /* Request to enter Thunderbolt mode for the cable prior to entering - * USB4 mode if - - * 1. Thunderbolt Mode SOP' VDO active/passive bit (B25) is - * TBT_CABLE_ACTIVE or - * 2. It's an active cable with VDM version < 2.0 or - * VDO version < 1.3 - */ if (tbt_cable_entry_is_done(port)) return false; - cable_mode_resp.raw_value = - pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME); - - if (cable_mode_resp.tbt_active_passive == TBT_CABLE_ACTIVE) + /* + * For some cables, the TCPM may need to enter TBT mode with the + * cable to support USB4 mode with the partner. Request to enter + * Thunderbolt mode for the cable prior to entering USB4 for + * the port partner if + * 1. The cable advertises itself as passive in its Identity VDO + * but active in its TBT mode VDO, or + * 2. The cable advertises itself as active, but its PD support + * is not new enough to support Enter_USB. + */ + if (tbt_is_lrd_active_cable(port)) return true; if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) { disc_sop_prime = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); if (pd_get_vdo_ver(port, TCPCI_MSG_SOP_PRIME) < VDM_VER20 || disc_sop_prime->identity.product_t1.a_rev30.vdo_ver < - VDO_VERSION_1_3) + VDO_VERSION_1_3) return true; } return false; } void intel_vdm_acked(int port, enum tcpci_msg_type type, int vdo_count, - uint32_t *vdm) + uint32_t *vdm) { - const struct pd_discovery *disc; const uint8_t vdm_cmd = PD_VDO_CMD(vdm[0]); int opos_sop, opos_sop_prime; - union tbt_mode_resp_cable cable_mode_resp; if (!tbt_response_valid(port, type, "ACK", vdm_cmd)) return; - disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); - switch (tbt_state[port]) { case TBT_ENTER_SOP_PRIME: tbt_prints("enter mode SOP'", port); - cable_mode_resp.raw_value = - pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME); /* For LRD cables, Enter mode SOP' -> Enter mode SOP */ - if (disc->identity.product_t1.a_rev20.sop_p_p && - cable_mode_resp.tbt_active_passive != TBT_CABLE_ACTIVE) { + if (tbt_sop_prime_prime_needed(port)) { tbt_state[port] = TBT_ENTER_SOP_PRIME_PRIME; } else { TBT_SET_FLAG(port, TBT_FLAG_CABLE_ENTRY_DONE); @@ -308,8 +323,11 @@ void intel_vdm_acked(int port, enum tcpci_msg_type type, int vdo_count, if (opos_sop > 0) pd_dfp_exit_mode(port, TCPCI_MSG_SOP, USB_VID_INTEL, opos_sop); - if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) { - tbt_active_cable_exit_mode(port); + + if (tbt_sop_prime_prime_needed(port)) { + tbt_state[port] = TBT_EXIT_SOP_PRIME_PRIME; + } else if (tbt_sop_prime_needed(port)) { + tbt_state[port] = TBT_EXIT_SOP_PRIME; } else { set_usb_mux_with_current_data_role(port); if (TBT_CHK_FLAG(port, TBT_FLAG_RETRY_DONE)) @@ -330,13 +348,12 @@ void intel_vdm_acked(int port, enum tcpci_msg_type type, int vdo_count, * Exit mode process is complete; go to inactive state. */ tbt_exit_done(port); - opos_sop_prime = - pd_alt_mode(port, TCPCI_MSG_SOP_PRIME, - USB_VID_INTEL); + opos_sop_prime = pd_alt_mode(port, TCPCI_MSG_SOP_PRIME, + USB_VID_INTEL); /* Clear Thunderbolt related signals */ pd_dfp_exit_mode(port, TCPCI_MSG_SOP_PRIME, - USB_VID_INTEL, opos_sop_prime); + USB_VID_INTEL, opos_sop_prime); set_usb_mux_with_current_data_role(port); } else { tbt_retry_enter_mode(port); @@ -351,8 +368,8 @@ void intel_vdm_acked(int port, enum tcpci_msg_type type, int vdo_count, break; default: /* Invalid or unexpected negotiation state */ - CPRINTF("%s called with invalid state %d\n", - __func__, tbt_state[port]); + CPRINTF("%s called with invalid state %d\n", __func__, + tbt_state[port]); tbt_exit_done(port); break; } @@ -378,9 +395,12 @@ void intel_vdm_naked(int port, enum tcpci_msg_type type, uint8_t vdm_cmd) case TBT_EXIT_SOP: /* Exit SOP got NAK'ed */ tbt_prints("exit mode SOP failed", port); - if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) - tbt_active_cable_exit_mode(port); - else { + + if (tbt_sop_prime_prime_needed(port)) { + tbt_state[port] = TBT_EXIT_SOP_PRIME_PRIME; + } else if (tbt_sop_prime_needed(port)) { + tbt_state[port] = TBT_EXIT_SOP_PRIME; + } else { set_usb_mux_with_current_data_role(port); if (TBT_CHK_FLAG(port, TBT_FLAG_RETRY_DONE)) /* Retried enter mode, still failed, give up */ @@ -406,8 +426,8 @@ void intel_vdm_naked(int port, enum tcpci_msg_type type, uint8_t vdm_cmd) } break; default: - CPRINTS("C%d: NAK for cmd %d in state %d", port, - vdm_cmd, tbt_state[port]); + CPRINTS("C%d: NAK for cmd %d in state %d", port, vdm_cmd, + tbt_state[port]); tbt_exit_done(port); break; } @@ -416,7 +436,7 @@ void intel_vdm_naked(int port, enum tcpci_msg_type type, uint8_t vdm_cmd) static bool tbt_mode_is_supported(int port, int vdo_count) { const struct pd_discovery *disc = - pd_get_am_discovery(port, TCPCI_MSG_SOP); + pd_get_am_discovery(port, TCPCI_MSG_SOP); if (!disc->identity.idh.modal_support) return false; @@ -430,8 +450,8 @@ static bool tbt_mode_is_supported(int port, int vdo_count) * SVID USB_VID_INTEL to enter Thunderbolt alt mode */ if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE && - !pd_is_mode_discovered_for_svid( - port, TCPCI_MSG_SOP_PRIME, USB_VID_INTEL)) + !pd_is_mode_discovered_for_svid(port, TCPCI_MSG_SOP_PRIME, + USB_VID_INTEL)) return false; return true; @@ -443,7 +463,6 @@ enum dpm_msg_setup_status tbt_setup_next_vdm(int port, int *vdo_count, { struct svdm_amode_data *modep; int vdo_count_ret = 0; - union tbt_mode_resp_cable cable_mode_resp; *tx_type = TCPCI_MSG_SOP; @@ -467,12 +486,8 @@ enum dpm_msg_setup_status tbt_setup_next_vdm(int port, int *vdo_count, */ usb_mux_set_safe_mode(port); - cable_mode_resp.raw_value = - pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME); - /* Active cable and LRD cables send Enter Mode SOP' first */ - if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE || - cable_mode_resp.tbt_active_passive == TBT_CABLE_ACTIVE) { + if (tbt_sop_prime_needed(port)) { tbt_state[port] = TBT_ENTER_SOP_PRIME; } else { /* Passive cable send Enter Mode SOP */ @@ -486,14 +501,12 @@ enum dpm_msg_setup_status tbt_setup_next_vdm(int port, int *vdo_count, *tx_type = TCPCI_MSG_SOP_PRIME; break; case TBT_ENTER_SOP_PRIME_PRIME: - vdo_count_ret = - enter_tbt_compat_mode( - port, TCPCI_MSG_SOP_PRIME_PRIME, vdm); + vdo_count_ret = enter_tbt_compat_mode( + port, TCPCI_MSG_SOP_PRIME_PRIME, vdm); *tx_type = TCPCI_MSG_SOP_PRIME_PRIME; break; case TBT_ENTER_SOP: - vdo_count_ret = - enter_tbt_compat_mode(port, TCPCI_MSG_SOP, vdm); + vdo_count_ret = enter_tbt_compat_mode(port, TCPCI_MSG_SOP, vdm); break; case TBT_ACTIVE: /* @@ -515,43 +528,38 @@ enum dpm_msg_setup_status tbt_setup_next_vdm(int port, int *vdo_count, return MSG_SETUP_MUX_WAIT; case TBT_EXIT_SOP: /* DPM will only call this after safe state set is done */ - modep = pd_get_amode_data(port, - TCPCI_MSG_SOP, USB_VID_INTEL); + modep = pd_get_amode_data(port, TCPCI_MSG_SOP, USB_VID_INTEL); if (!(modep && modep->opos)) return MSG_SETUP_ERROR; vdm[0] = VDO(USB_VID_INTEL, 1, CMD_EXIT_MODE) | - VDO_OPOS(modep->opos) | - VDO_CMDT(CMDT_INIT) | - VDO_SVDM_VERS( - pd_get_vdo_ver(port, TCPCI_MSG_SOP)); + VDO_OPOS(modep->opos) | VDO_CMDT(CMDT_INIT) | + VDO_SVDM_VERS(pd_get_vdo_ver(port, TCPCI_MSG_SOP)); vdo_count_ret = 1; break; case TBT_EXIT_SOP_PRIME_PRIME: - modep = pd_get_amode_data(port, - TCPCI_MSG_SOP_PRIME, USB_VID_INTEL); + modep = pd_get_amode_data(port, TCPCI_MSG_SOP_PRIME, + USB_VID_INTEL); if (!(modep && modep->opos)) return MSG_SETUP_ERROR; vdm[0] = VDO(USB_VID_INTEL, 1, CMD_EXIT_MODE) | - VDO_OPOS(modep->opos) | - VDO_CMDT(CMDT_INIT) | - VDO_SVDM_VERS(pd_get_vdo_ver(port, - TCPCI_MSG_SOP_PRIME_PRIME)); + VDO_OPOS(modep->opos) | VDO_CMDT(CMDT_INIT) | + VDO_SVDM_VERS(pd_get_vdo_ver( + port, TCPCI_MSG_SOP_PRIME_PRIME)); vdo_count_ret = 1; *tx_type = TCPCI_MSG_SOP_PRIME_PRIME; break; case TBT_EXIT_SOP_PRIME: - modep = pd_get_amode_data(port, - TCPCI_MSG_SOP_PRIME, USB_VID_INTEL); + modep = pd_get_amode_data(port, TCPCI_MSG_SOP_PRIME, + USB_VID_INTEL); if (!(modep && modep->opos)) return MSG_SETUP_ERROR; vdm[0] = VDO(USB_VID_INTEL, 1, CMD_EXIT_MODE) | - VDO_OPOS(modep->opos) | - VDO_CMDT(CMDT_INIT) | - VDO_SVDM_VERS(pd_get_vdo_ver(port, - TCPCI_MSG_SOP_PRIME)); + VDO_OPOS(modep->opos) | VDO_CMDT(CMDT_INIT) | + VDO_SVDM_VERS( + pd_get_vdo_ver(port, TCPCI_MSG_SOP_PRIME)); vdo_count_ret = 1; *tx_type = TCPCI_MSG_SOP_PRIME; break; @@ -559,8 +567,8 @@ enum dpm_msg_setup_status tbt_setup_next_vdm(int port, int *vdo_count, /* Thunderbolt mode is inactive */ return MSG_SETUP_UNSUPPORTED; default: - CPRINTF("%s called with invalid state %d\n", - __func__, tbt_state[port]); + CPRINTF("%s called with invalid state %d\n", __func__, + tbt_state[port]); return MSG_SETUP_ERROR; } @@ -571,3 +579,177 @@ enum dpm_msg_setup_status tbt_setup_next_vdm(int port, int *vdo_count, return MSG_SETUP_UNSUPPORTED; } + +uint32_t pd_get_tbt_mode_vdo(int port, enum tcpci_msg_type type) +{ + uint32_t tbt_mode_vdo[PDO_MODES]; + + return pd_get_mode_vdo_for_svid(port, type, USB_VID_INTEL, + tbt_mode_vdo) ? + tbt_mode_vdo[0] : + 0; +} + +void set_tbt_compat_mode_ready(int port) +{ + if (IS_ENABLED(CONFIG_USBC_SS_MUX) && + IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE)) { + /* Connect the SBU and USB lines to the connector. */ + typec_set_sbu(port, true); + + /* Set usb mux to Thunderbolt-compatible mode */ + usb_mux_set(port, USB_PD_MUX_TBT_COMPAT_ENABLED, + USB_SWITCH_CONNECT, + polarity_rm_dts(pd_get_polarity(port))); + } +} + +/* + * Ref: USB Type-C Cable and Connector Specification + * Figure F-1 TBT3 Discovery Flow + */ +static bool is_tbt_cable_superspeed(int port) +{ + const struct pd_discovery *disc; + + if (!IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) || + !IS_ENABLED(CONFIG_USB_PD_DECODE_SOP)) + return false; + + disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); + + /* Product type is Active cable, hence don't check for speed */ + if (disc->identity.idh.product_type == IDH_PTYPE_ACABLE) + return true; + + if (disc->identity.idh.product_type != IDH_PTYPE_PCABLE) + return false; + + if (IS_ENABLED(CONFIG_USB_PD_REV30) && + pd_get_rev(port, TCPCI_MSG_SOP_PRIME) == PD_REV30) + return disc->identity.product_t1.p_rev30.ss == + USB_R30_SS_U32_U40_GEN1 || + disc->identity.product_t1.p_rev30.ss == + USB_R30_SS_U32_U40_GEN2 || + disc->identity.product_t1.p_rev30.ss == + USB_R30_SS_U40_GEN3; + + return disc->identity.product_t1.p_rev20.ss == USB_R20_SS_U31_GEN1 || + disc->identity.product_t1.p_rev20.ss == USB_R20_SS_U31_GEN1_GEN2; +} + +static enum tbt_compat_cable_speed usb_rev30_to_tbt_speed(enum usb_rev30_ss ss) +{ + switch (ss) { + case USB_R30_SS_U32_U40_GEN1: + return TBT_SS_U31_GEN1; + case USB_R30_SS_U32_U40_GEN2: + return TBT_SS_U32_GEN1_GEN2; + case USB_R30_SS_U40_GEN3: + return TBT_SS_TBT_GEN3; + default: + return TBT_SS_U32_GEN1_GEN2; + } +} + +enum tbt_compat_cable_speed get_tbt_cable_speed(int port) +{ + union tbt_mode_resp_cable cable_mode_resp; + enum tbt_compat_cable_speed max_tbt_speed; + enum tbt_compat_cable_speed cable_tbt_speed; + + if (!is_tbt_cable_superspeed(port)) + return TBT_SS_RES_0; + + cable_mode_resp.raw_value = + pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME); + max_tbt_speed = board_get_max_tbt_speed(port); + + /* + * Ref: TBT4 PD Discovery Flow Application Notes Revision 0.9, Figure 2 + * For passive cable, if cable doesn't support USB_VID_INTEL, enter + * Thunderbolt alternate mode with speed from USB Highest Speed field of + * the Passive Cable VDO + * For active cable, if the cable doesn't support USB_VID_INTEL, do not + * enter Thunderbolt alternate mode. + */ + if (!cable_mode_resp.raw_value) { + const struct pd_discovery *disc; + + if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) + return TBT_SS_RES_0; + + disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME); + cable_tbt_speed = usb_rev30_to_tbt_speed( + disc->identity.product_t1.p_rev30.ss); + } else { + cable_tbt_speed = cable_mode_resp.tbt_cable_speed; + } + + return max_tbt_speed < cable_tbt_speed ? max_tbt_speed : + cable_tbt_speed; +} + +/* Note: Assumes that pins have already been set in safe state */ +int enter_tbt_compat_mode(int port, enum tcpci_msg_type sop, uint32_t *payload) +{ + union tbt_dev_mode_enter_cmd enter_dev_mode = { .raw_value = 0 }; + union tbt_mode_resp_device dev_mode_resp; + union tbt_mode_resp_cable cable_mode_resp; + enum tcpci_msg_type enter_mode_sop = + sop == TCPCI_MSG_SOP_PRIME_PRIME ? TCPCI_MSG_SOP_PRIME : sop; + + /* Table F-12 TBT3 Cable Enter Mode Command */ + /* + * The port doesn't query Discover SOP'' to the cable so, the port + * doesn't have opos for SOP''. Hence, send Enter Mode SOP'' with same + * opos and revision as SOP'. + */ + payload[0] = pd_dfp_enter_mode(port, enter_mode_sop, USB_VID_INTEL, 0) | + VDO_CMDT(CMDT_INIT) | + VDO_SVDM_VERS(pd_get_vdo_ver(port, enter_mode_sop)); + + /* For TBT3 Cable Enter Mode Command, number of Objects is 1 */ + if ((sop == TCPCI_MSG_SOP_PRIME) || (sop == TCPCI_MSG_SOP_PRIME_PRIME)) + return 1; + + dev_mode_resp.raw_value = pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP); + cable_mode_resp.raw_value = + pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME); + + /* Table F-13 TBT3 Device Enter Mode Command */ + enter_dev_mode.vendor_spec_b1 = dev_mode_resp.vendor_spec_b1; + enter_dev_mode.vendor_spec_b0 = dev_mode_resp.vendor_spec_b0; + enter_dev_mode.intel_spec_b0 = dev_mode_resp.intel_spec_b0; + + if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE || + cable_mode_resp.tbt_active_passive == TBT_CABLE_ACTIVE) + enter_dev_mode.cable = TBT_ENTER_ACTIVE_CABLE; + + enter_dev_mode.lsrx_comm = cable_mode_resp.lsrx_comm; + enter_dev_mode.retimer_type = cable_mode_resp.retimer_type; + enter_dev_mode.tbt_cable = cable_mode_resp.tbt_cable; + enter_dev_mode.tbt_rounded = cable_mode_resp.tbt_rounded; + enter_dev_mode.tbt_cable_speed = get_tbt_cable_speed(port); + enter_dev_mode.tbt_alt_mode = TBT_ALTERNATE_MODE; + + payload[1] = enter_dev_mode.raw_value; + + /* For TBT3 Device Enter Mode Command, number of Objects are 2 */ + return 2; +} + +enum tbt_compat_rounded_support get_tbt_rounded_support(int port) +{ + union tbt_mode_resp_cable cable_mode_resp = { + .raw_value = pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME) + }; + + /* tbt_rounded_support is zero when uninitialized */ + return cable_mode_resp.tbt_rounded; +} + +__overridable enum tbt_compat_cable_speed board_get_max_tbt_speed(int port) +{ + return TBT_SS_TBT_GEN3; +} |