diff options
author | Ayushee <ayushee.shah@intel.com> | 2020-10-10 22:26:20 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-11-06 03:08:01 +0000 |
commit | ec32c12885a1800cb30916d2e28089432a794595 (patch) | |
tree | 0807071a02413c30b304721a39da4230c7a6928a /common/usbc/tbt_alt_mode.c | |
parent | e541093661124cd63d3ef9ca1877676311df9861 (diff) | |
download | chrome-ec-ec32c12885a1800cb30916d2e28089432a794595.tar.gz |
TCPMv2: Add support for linear re-driver cables
The linear re-driver cables enumerate as passive cables in the Discover
mode SOP' response from the cable. But they have Active/Passive bit
(B25) in the discover mode SOP' response set. Hence, if the cable is
LRD, the port enters Thunderbolt mode SOP' before entering USB and
it also sets the cable as active in the mux and retimer setting.
USB4 PD flow for LRD cables:
Is Discover mode SOP'
B25? ----- N ----- Enter USB4 SOP with Gen 2 cable speed
|
y
|
Enter TBT SOP'
|
Enter USB4 SOP as per cable speed.
TBT PD flow for LRD cables:
Is Discover mode SOP'
B25? ----- N ----- Enter TBT SOP
|
y
|
Enter TBT SOP'
|
Enter TBT SOP
This CL also updates the retimer setting and Enter USB Data object for
USB4 according to the type of cable detected (LRD/Active/passive)
BUG=b:156749387
BRANCH=None
TEST=With Linear re-driver cable,
1. Able to enter USB4 mode
2. Able to enter Thunderbolt mode
3. Able to exit and re-enter USB4 on reboot
4. Able to exit and re-enter Thunderbolt mode on reboot
Change-Id: Ie5258f792e13a205dea71fc9f06b1d8987ec9194
Signed-off-by: Ayushee <ayushee.shah@intel.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2470209
Reviewed-by: Tanu Malhotra <tanu.malhotra@intel.com>
Reviewed-by: Abe Levkoy <alevkoy@chromium.org>
Commit-Queue: Abe Levkoy <alevkoy@chromium.org>
Diffstat (limited to 'common/usbc/tbt_alt_mode.c')
-rw-r--r-- | common/usbc/tbt_alt_mode.c | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/common/usbc/tbt_alt_mode.c b/common/usbc/tbt_alt_mode.c index a0ec41da86..144126baa1 100644 --- a/common/usbc/tbt_alt_mode.c +++ b/common/usbc/tbt_alt_mode.c @@ -154,6 +154,8 @@ static void tbt_exit_done(int port) void tbt_exit_mode_request(int port) { + union tbt_mode_resp_cable cable_mode_resp; + TBT_SET_FLAG(port, TBT_FLAG_RETRY_DONE); TBT_CLR_FLAG(port, TBT_FLAG_EXIT_DONE); /* @@ -162,14 +164,27 @@ void tbt_exit_mode_request(int port) * cable. * TODO (b/156749387): Remove once data reset feature is in place. */ - if (tbt_state[port] == TBT_ENTER_SOP) - tbt_state[port] = TBT_EXIT_SOP_PRIME_PRIME; + if (tbt_state[port] == TBT_ENTER_SOP) { + cable_mode_resp.raw_value = + pd_get_tbt_mode_vdo(port, TCPC_TX_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; + } } static bool tbt_response_valid(int port, enum tcpm_transmit_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, TCPC_TX_SOP_PRIME) }; /* * Check for an unexpected response. @@ -179,6 +194,7 @@ static bool tbt_response_valid(int port, enum tcpm_transmit_type type, */ if ((st != TBT_INACTIVE && state_vdm_cmd[st] != vdm_cmd) || (get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE && + cable_mode_resp.tbt_active_passive == TBT_CABLE_PASSIVE && type != TCPC_TX_SOP)) { tbt_exit_done(port); return false; @@ -212,6 +228,7 @@ void intel_vdm_acked(int port, enum tcpm_transmit_type type, int vdo_count, 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; @@ -220,7 +237,12 @@ void intel_vdm_acked(int port, enum tcpm_transmit_type type, int vdo_count, switch (tbt_state[port]) { case TBT_ENTER_SOP_PRIME: - if (disc->identity.product_t1.a_rev20.sop_p_p) { + tbt_prints("enter mode SOP'", port); + cable_mode_resp.raw_value = + pd_get_tbt_mode_vdo(port, TCPC_TX_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) { tbt_state[port] = TBT_ENTER_SOP_PRIME_PRIME; } else { TBT_SET_FLAG(port, TBT_FLAG_CABLE_ENTRY_DONE); @@ -228,6 +250,7 @@ void intel_vdm_acked(int port, enum tcpm_transmit_type type, int vdo_count, } break; case TBT_ENTER_SOP_PRIME_PRIME: + tbt_prints("enter mode SOP''", port); TBT_SET_FLAG(port, TBT_FLAG_CABLE_ENTRY_DONE); tbt_state[port] = TBT_ENTER_SOP; break; @@ -404,6 +427,7 @@ int tbt_setup_next_vdm(int port, int vdo_count, uint32_t *vdm, { struct svdm_amode_data *modep; int vdo_count_ret = 0; + union tbt_mode_resp_cable cable_mode_resp; *tx_type = TCPC_TX_SOP; @@ -419,11 +443,15 @@ int tbt_setup_next_vdm(int port, int vdo_count, uint32_t *vdm, tbt_prints("attempt to enter mode", port); else tbt_prints("retry to enter mode", port); - /* Active cable send Enter Mode SOP' first */ - if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) { - vdo_count_ret = - enter_tbt_compat_mode( - port, TCPC_TX_SOP_PRIME, vdm); + + cable_mode_resp.raw_value = + pd_get_tbt_mode_vdo(port, TCPC_TX_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) { + vdo_count_ret = enter_tbt_compat_mode(port, + TCPC_TX_SOP_PRIME, vdm); *tx_type = TCPC_TX_SOP_PRIME; tbt_state[port] = TBT_ENTER_SOP_PRIME; } else { |