summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAyushee <ayushee.shah@intel.com>2020-10-10 22:26:20 -0700
committerCommit Bot <commit-bot@chromium.org>2020-11-06 03:08:01 +0000
commitec32c12885a1800cb30916d2e28089432a794595 (patch)
tree0807071a02413c30b304721a39da4230c7a6928a
parente541093661124cd63d3ef9ca1877676311df9861 (diff)
downloadchrome-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>
-rw-r--r--common/usb_pd_alt_mode_dfp.c15
-rw-r--r--common/usbc/tbt_alt_mode.c44
-rw-r--r--common/usbc/usb_mode.c100
-rw-r--r--common/usbc/usb_pd_dpm.c11
-rw-r--r--driver/retimer/bb_retimer.c13
-rw-r--r--include/usb_pd_tbt.h21
6 files changed, 135 insertions, 69 deletions
diff --git a/common/usb_pd_alt_mode_dfp.c b/common/usb_pd_alt_mode_dfp.c
index cee2a9e4e7..65d77054ff 100644
--- a/common/usb_pd_alt_mode_dfp.c
+++ b/common/usb_pd_alt_mode_dfp.c
@@ -845,9 +845,11 @@ int enter_tbt_compat_mode(int port, enum tcpm_transmit_type sop,
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;
- enter_dev_mode.cable =
- get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE ?
- TBT_ENTER_PASSIVE_CABLE : TBT_ENTER_ACTIVE_CABLE;
+
+ 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;
@@ -958,7 +960,12 @@ uint32_t get_enter_usb_msg_payload(int port)
CABLE_TYPE_ACTIVE_REDRIVER;
}
} else {
- eudo.cable_type = CABLE_TYPE_PASSIVE;
+ cable_mode_resp.raw_value =
+ pd_get_tbt_mode_vdo(port, TCPC_TX_SOP_PRIME);
+
+ eudo.cable_type =
+ cable_mode_resp.tbt_active_passive == TBT_CABLE_ACTIVE ?
+ CABLE_TYPE_ACTIVE_REDRIVER : CABLE_TYPE_PASSIVE;
}
switch (disc->identity.product_t1.p_rev20.vbus_cur) {
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 {
diff --git a/common/usbc/usb_mode.c b/common/usbc/usb_mode.c
index 818f1e18c3..900552b451 100644
--- a/common/usbc/usb_mode.c
+++ b/common/usbc/usb_mode.c
@@ -46,51 +46,61 @@ enum usb4_states {
};
/*
- * USB4 flow for Active cable
+ * USB4 PD flow:
*
- * Structured
- * VDM version
- * (cable revision)-- <2.0 -------->|
- * | |
- * >=2.0 |
- * | |
- * VDO version---- <1.3 -------> Modal op? -- N --|
- * (B21:23 of | |
- * Discover ID SOP'- y |
- * Active cable VDO1) | |
- * | TBT SVID? -- N --|
- * >=1.3 | |
- * | y |
- * Cable USB4 support? - N | |
- * | | Gen4 cable? - N - Skip USB4 mode entry
- * y Skip USB4 |
- * | mode entry |
- * Enter USB4 y
- * (SOP',SOP'',SOP) |
- * |
- * |<---- NAK ----- Enter mode TBT SOP'<---|
- * | | |
- * | ACK |
- * | | |
- * |<---- NAK ----- Enter mode TBT SOP'' |
- * | | |
- * Exit TBT mode SOP ACK |
- * | | |
- * ACK/NAK Enter USB4 mode |
- * | SOP |
- * Exit TBT mode SOP'' |
- * | |
- * ACK/NAK |
- * | |
- * Exit TBT mode SOP' |
- * | |
- * ACK/NAK |
- * | |
- * |--------Retry done? ---- N ------------|
- * |
- * y
- * |
- * Skip USB4 mode entry
+ * Cable type
+ * |
+ * |-------- Passive ---|---- Active -----|
+ * | |
+ * USB Highest Speed Structured VDM version
+ * | (cable revision)-- <2.0---->|
+ * --------|--------|------| | |
+ * | | | | >=2.0 |
+ * >=Gen3 Gen2 Gen1 USB2.0 | |
+ * | | | | VDO version--- <1.3 ---> Modal op? -- N --|
+ * Enter USB | | | (B21:23 of | |
+ * SOP with | | | Discover ID SOP'- y |
+ * Gen3 cable | | Skip Active cable VDO1) | |
+ * speed | | USB4 | TBT SVID? -- N --|
+ * | | mode >=1.3 | |
+ * Is modal op? | entry | y |
+ * | | Cable USB4 - N | |
+ * y | support? | Gen4 cable? - N - Skip
+ * | | | Skip USB4 | USB4
+ * Is TBT SVID? -N- Enter | mode entry | mode
+ * | USB4 SOP | | entry
+ * y with Gen2 y |
+ * | cable speed | |
+ * | | |
+ * Is Discover mode | |
+ * SOP' B25? - N - Enter Enter USB4 mode |
+ * | USB4 SOP (SOP, SOP', SOP'') |
+ * | with speed |
+ * y from TBT mode |
+ * | SOP' VDO |
+ * | |<-- NAK -- Enter mode TBT SOP'<---|
+ * |---->Enter TBT SOP'-------NAK------>| | | |
+ * | | | | ACK |
+ * | ACK | | | |
+ * | | | |<-- NAK -- Enter mode TBT SOP'' |
+ * | Enter USB4 SOP | | | |
+ * | with speed from Exit TBT mode SOP ACK |
+ * | TBT mode SOP' VDO | | | |
+ * | ACK/NAK Enter USB4 SOP |
+ * | | | with speed from |
+ * | Exit TBT mode SOP'' TBT mode SOP' VDO |
+ * | | | |
+ * | ACK/NAK |
+ * | | | |
+ * | Exit TBT mode SOP' |
+ * | | | |
+ * | ACK/NAK |
+ * | | | |
+ * |---- N ----Retry done? -------------| |--------Retry done? ---- N -------|
+ * | |
+ * y y
+ * | |
+ * Skip USB4 mode entry Skip USB4 mode entry
*/
static enum usb4_states usb4_state[CONFIG_USB_PD_PORT_MAX_COUNT];
@@ -154,8 +164,6 @@ bool enter_usb_port_partner_is_capable(int port)
bool enter_usb_cable_is_capable(int port)
{
- /* TODO: b/156749387 Add support for LRD cable */
-
if (get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE) {
if (get_usb4_cable_speed(port) < USB_R30_SS_U32_U40_GEN1)
return false;
diff --git a/common/usbc/usb_pd_dpm.c b/common/usbc/usb_pd_dpm.c
index 193ea9802c..d71e590922 100644
--- a/common/usbc/usb_pd_dpm.c
+++ b/common/usbc/usb_pd_dpm.c
@@ -222,14 +222,19 @@ static void dpm_attempt_mode_entry(int port)
dpm_mode_entry_requested(port, TYPEC_MODE_USB4)) {
struct pd_discovery *disc_sop_prime =
pd_get_am_discovery(port, TCPC_TX_SOP_PRIME);
+ union tbt_mode_resp_cable cable_mode_resp = {
+ .raw_value = pd_get_tbt_mode_vdo(port,
+ TCPC_TX_SOP_PRIME) };
/*
* Enter USB mode if -
- * 1. It's a passive cable or
- * 2. It's an active cable with VDM version >= 2.0 and
+ * 1. It's a passive cable and Thunderbolt Mode SOP' VDO
+ * active/passive bit (B25) is TBT_CABLE_PASSIVE or
+ * 2. It's a active cable with VDM version >= 2.0 and
* VDO version >= 1.3 or
* 3. The cable has entered Thunderbolt mode.
*/
- if (get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE ||
+ if ((get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE &&
+ cable_mode_resp.tbt_active_passive == TBT_CABLE_PASSIVE) ||
(get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE &&
pd_get_vdo_ver(port, TCPC_TX_SOP_PRIME) >= VDM_VER20 &&
disc_sop_prime->identity.product_t1.a_rev30.vdo_ver >=
diff --git a/driver/retimer/bb_retimer.c b/driver/retimer/bb_retimer.c
index 7c5eacdb8b..b9fb42081b 100644
--- a/driver/retimer/bb_retimer.c
+++ b/driver/retimer/bb_retimer.c
@@ -130,7 +130,8 @@ __overridable void bb_retimer_power_handle(const struct usb_mux *me, int on_off)
static void retimer_set_state_dfp(int port, mux_state_t mux_state,
uint32_t *set_retimer_con)
{
- union tbt_mode_resp_cable cable_resp;
+ union tbt_mode_resp_cable cable_resp = {
+ .raw_value = pd_get_tbt_mode_vdo(port, TCPC_TX_SOP_PRIME) };
union tbt_mode_resp_device dev_resp;
enum idh_ptype cable_type = get_usb_pd_cable_type(port);
struct pd_discovery *disc;
@@ -173,13 +174,12 @@ static void retimer_set_state_dfp(int port, mux_state_t mux_state,
* set according to Discover mode SOP' response.
*/
if ((mux_state & BB_RETIMER_MUX_USB_ALT_MODE) &&
- (cable_type == IDH_PTYPE_ACABLE))
+ ((cable_type == IDH_PTYPE_ACABLE) ||
+ cable_resp.tbt_active_passive == TBT_CABLE_ACTIVE))
*set_retimer_con |= BB_RETIMER_ACTIVE_PASSIVE;
if (mux_state & USB_PD_MUX_TBT_COMPAT_ENABLED ||
mux_state & USB_PD_MUX_USB4_ENABLED) {
- cable_resp.raw_value =
- pd_get_tbt_mode_vdo(port, TCPC_TX_SOP_PRIME);
dev_resp.raw_value = pd_get_tbt_mode_vdo(port, TCPC_TX_SOP);
/*
@@ -227,8 +227,9 @@ static void retimer_set_state_dfp(int port, mux_state_t mux_state,
* 1 - Active with uni-directional LSRX communication
* Set to "0" when passive cable plug
*/
- if (cable_type == IDH_PTYPE_ACABLE &&
- cable_resp.lsrx_comm == UNIDIR_LSRX_COMM)
+ if ((cable_type == IDH_PTYPE_ACABLE ||
+ cable_resp.tbt_active_passive == TBT_CABLE_ACTIVE) &&
+ cable_resp.lsrx_comm == UNIDIR_LSRX_COMM)
*set_retimer_con |= BB_RETIMER_TBT_ACTIVE_LINK_TRAINING;
/*
diff --git a/include/usb_pd_tbt.h b/include/usb_pd_tbt.h
index e168277808..e052052813 100644
--- a/include/usb_pd_tbt.h
+++ b/include/usb_pd_tbt.h
@@ -124,7 +124,17 @@ union tbt_mode_resp_device {
/*
* Table F-11 TBT3 Cable Discover Mode VDO Responses
* -------------------------------------------------------------
- * <31:24> : Reserved
+ * <31:26> : Reserved
+ * <25> : Active Passive
+ * Errata: Reserved B25 has been changed to Active passive bit
+ * Refer USB Type-C ENGINEERING CHANGE NOTICE (ECN)
+ * "USB Type-C ECN Thunderbolt 3 Compatibility Updates.pdf"
+ * with Title: Thunderbolt 3 Compatibility Updates
+ * for the document fix published by USB-IF.
+ * 0b = Passive cable
+ * 1b = Active cable
+ * NOTE: This change is only applicable to rev 3 cables
+ * <24> : Reserved
* <23> : Active Cable Plug Link Training
* 0 = Active with bi-directional LSRX1 communication or when Passive
* 1 = Active with uni-directional LSRX1 communication
@@ -148,6 +158,11 @@ union tbt_mode_resp_device {
* <15:0> : TBT Alternate Mode
* 0x0001 = TBT Mode
*/
+enum tbt_active_passive_cable {
+ TBT_CABLE_PASSIVE,
+ TBT_CABLE_ACTIVE,
+};
+
enum tbt_compat_cable_speed {
TBT_SS_RES_0,
TBT_SS_U31_GEN1,
@@ -189,7 +204,9 @@ union tbt_mode_resp_cable {
enum tbt_cable_type tbt_cable : 1;
enum usb_retimer_type retimer_type : 1;
enum link_lsrx_comm lsrx_comm : 1;
- uint8_t reserved0 : 8;
+ uint8_t reserved1 : 1;
+ enum tbt_active_passive_cable tbt_active_passive : 1;
+ uint8_t reserved0 : 6;
};
uint32_t raw_value;
};