summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/usb_pd_alt_mode_dfp.c299
-rw-r--r--common/usb_pd_console_cmd.c4
-rw-r--r--common/usb_pd_host_cmd.c11
-rw-r--r--common/usbc/tbt_alt_mode.c175
-rw-r--r--common/usbc/usb_mode.c104
-rw-r--r--common/usbc/usb_pd_dpm.c5
6 files changed, 295 insertions, 303 deletions
diff --git a/common/usb_pd_alt_mode_dfp.c b/common/usb_pd_alt_mode_dfp.c
index 6c2917ff33..81b7e1a53b 100644
--- a/common/usb_pd_alt_mode_dfp.c
+++ b/common/usb_pd_alt_mode_dfp.c
@@ -846,305 +846,6 @@ bool is_active_cable_element_retimer(int port)
disc->identity.product_t2.a2_rev30.active_elem == ACTIVE_RETIMER;
}
-/*
- * ############################################################################
- *
- * Thunderbolt-Compatible functions
- *
- * ############################################################################
- */
-
-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;
-}
-
-/* TODO (b/148528713): Need to enable Thunderbolt-compatible mode on TCPMv2 */
-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) &&
- is_pd_rev3(port, TCPCI_MSG_SOP_PRIME))
- 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;
-}
-/*
- * ############################################################################
- *
- * USB4 functions
- *
- * ############################################################################
- */
-
-/*
- * For Cable rev 3.0: USB4 cable speed is set according to speed supported by
- * the port and the response received from the cable, whichever is least.
- *
- * For Cable rev 2.0: If get_tbt_cable_speed() is less than
- * TBT_SS_U31_GEN1, return USB_R30_SS_U2_ONLY speed since the board
- * doesn't support superspeed else the USB4 cable speed is set according to
- * the cable response.
- */
-enum usb_rev30_ss get_usb4_cable_speed(int port)
-{
- enum tbt_compat_cable_speed tbt_speed = get_tbt_cable_speed(port);
- enum usb_rev30_ss max_usb4_speed;
-
- if (tbt_speed < TBT_SS_U31_GEN1)
- return USB_R30_SS_U2_ONLY;
-
- /*
- * Converting Thunderbolt-Compatible board speed to equivalent USB4
- * speed.
- */
- max_usb4_speed = tbt_speed == TBT_SS_TBT_GEN3 ? USB_R30_SS_U40_GEN3 :
- USB_R30_SS_U32_U40_GEN2;
-
- if ((get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) &&
- is_pd_rev3(port, TCPCI_MSG_SOP_PRIME)) {
- const struct pd_discovery *disc =
- pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
- union active_cable_vdo1_rev30 a_rev30 =
- disc->identity.product_t1.a_rev30;
-
- if (a_rev30.vdo_ver >= VDO_VERSION_1_3) {
- return max_usb4_speed < a_rev30.ss ? max_usb4_speed :
- a_rev30.ss;
- }
- }
-
- return max_usb4_speed;
-}
-
-uint32_t get_enter_usb_msg_payload(int port)
-{
- /*
- * Ref: USB Power Delivery Specification Revision 3.0, Version 2.0
- * Table 6-47 Enter_USB Data Object
- */
- union enter_usb_data_obj eudo;
- const struct pd_discovery *disc;
- union tbt_mode_resp_cable cable_mode_resp;
-
- if (!IS_ENABLED(CONFIG_USB_PD_USB4))
- return 0;
-
- disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
- eudo.mode = USB_PD_40;
- eudo.usb4_drd_cap = IS_ENABLED(CONFIG_USB_PD_USB4_DRD);
- eudo.usb3_drd_cap = IS_ENABLED(CONFIG_USB_PD_USB32_DRD);
- eudo.cable_speed = get_usb4_cable_speed(port);
-
- if (disc->identity.idh.product_type == IDH_PTYPE_ACABLE) {
- if (is_pd_rev3(port, TCPCI_MSG_SOP_PRIME)) {
- enum retimer_active_element active_element =
- disc->identity.product_t2.a2_rev30.active_elem;
- eudo.cable_type = active_element == ACTIVE_RETIMER ?
- CABLE_TYPE_ACTIVE_RETIMER :
- CABLE_TYPE_ACTIVE_REDRIVER;
- } else {
- cable_mode_resp.raw_value =
- pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME);
-
- eudo.cable_type = cable_mode_resp.retimer_type ==
- USB_RETIMER ?
- CABLE_TYPE_ACTIVE_RETIMER :
- CABLE_TYPE_ACTIVE_REDRIVER;
- }
- } else {
- cable_mode_resp.raw_value =
- pd_get_tbt_mode_vdo(port, TCPCI_MSG_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) {
- case USB_VBUS_CUR_3A:
- eudo.cable_current = USB4_CABLE_CURRENT_3A;
- break;
- case USB_VBUS_CUR_5A:
- eudo.cable_current = USB4_CABLE_CURRENT_5A;
- break;
- default:
- eudo.cable_current = USB4_CABLE_CURRENT_INVALID;
- break;
- }
- eudo.pcie_supported = IS_ENABLED(CONFIG_USB_PD_PCIE_TUNNELING);
- eudo.dp_supported = IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP);
- eudo.tbt_supported = IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE);
- eudo.host_present = 1;
-
- return eudo.raw_value;
-}
-
-__overridable bool board_is_tbt_usb4_port(int port)
-{
- return true;
-}
-
__overridable void svdm_safe_dp_mode(int port)
{
/* make DP interface safe until configure */
diff --git a/common/usb_pd_console_cmd.c b/common/usb_pd_console_cmd.c
index 7a271c0492..23f2a27b1e 100644
--- a/common/usb_pd_console_cmd.c
+++ b/common/usb_pd_console_cmd.c
@@ -134,7 +134,9 @@ static int command_cable(int argc, const char **argv)
cable_rev = pd_get_rev(port, TCPCI_MSG_SOP_PRIME);
disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
cable_mode_resp.raw_value =
- pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME);
+ IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) ?
+ pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME) :
+ 0;
/* Cable revision */
ccprintf("Cable Rev: %d.0\n", cable_rev + 1);
diff --git a/common/usb_pd_host_cmd.c b/common/usb_pd_host_cmd.c
index 1d26213135..8d43571a3f 100644
--- a/common/usb_pd_host_cmd.c
+++ b/common/usb_pd_host_cmd.c
@@ -241,7 +241,8 @@ static uint8_t get_pd_control_flags(int port)
union tbt_mode_resp_device device_resp;
uint8_t control_flags = 0;
- if (!IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP))
+ if (!IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP) ||
+ !IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE))
return 0;
cable_resp.raw_value = pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME);
@@ -364,8 +365,12 @@ static enum ec_status hc_usb_pd_control(struct host_cmd_handler_args *args)
r_v2->control_flags = get_pd_control_flags(p->port);
if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) {
r_v2->dp_mode = get_dp_pin_mode(p->port);
- r_v2->cable_speed = get_tbt_cable_speed(p->port);
- r_v2->cable_gen = get_tbt_rounded_support(p->port);
+ if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE)) {
+ r_v2->cable_speed =
+ get_tbt_cable_speed(p->port);
+ r_v2->cable_gen =
+ get_tbt_rounded_support(p->port);
+ }
}
if (args->version == 1)
diff --git a/common/usbc/tbt_alt_mode.c b/common/usbc/tbt_alt_mode.c
index 7710f13f18..d1ad031fad 100644
--- a/common/usbc/tbt_alt_mode.c
+++ b/common/usbc/tbt_alt_mode.c
@@ -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"
@@ -578,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;
+}
diff --git a/common/usbc/usb_mode.c b/common/usbc/usb_mode.c
index cf3155da08..8f4824e4e9 100644
--- a/common/usbc/usb_mode.c
+++ b/common/usbc/usb_mode.c
@@ -312,3 +312,107 @@ uint32_t enter_usb_setup_next_msg(int port, enum tcpci_msg_type *type)
}
return get_enter_usb_msg_payload(port);
}
+
+/*
+ * For Cable rev 3.0: USB4 cable speed is set according to speed supported by
+ * the port and the response received from the cable, whichever is least.
+ *
+ * For Cable rev 2.0: If get_tbt_cable_speed() is less than
+ * TBT_SS_U31_GEN1, return USB_R30_SS_U2_ONLY speed since the board
+ * doesn't support superspeed else the USB4 cable speed is set according to
+ * the cable response.
+ */
+enum usb_rev30_ss get_usb4_cable_speed(int port)
+{
+ enum tbt_compat_cable_speed tbt_speed = get_tbt_cable_speed(port);
+ enum usb_rev30_ss max_usb4_speed;
+
+ if (tbt_speed < TBT_SS_U31_GEN1)
+ return USB_R30_SS_U2_ONLY;
+
+ /*
+ * Converting Thunderbolt-Compatible board speed to equivalent USB4
+ * speed.
+ */
+ max_usb4_speed = tbt_speed == TBT_SS_TBT_GEN3 ? USB_R30_SS_U40_GEN3 :
+ USB_R30_SS_U32_U40_GEN2;
+
+ if ((get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) &&
+ pd_get_rev(port, TCPCI_MSG_SOP_PRIME) == PD_REV30) {
+ const struct pd_discovery *disc =
+ pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
+ union active_cable_vdo1_rev30 a_rev30 =
+ disc->identity.product_t1.a_rev30;
+
+ if (a_rev30.vdo_ver >= VDO_VERSION_1_3) {
+ return max_usb4_speed < a_rev30.ss ? max_usb4_speed :
+ a_rev30.ss;
+ }
+ }
+
+ return max_usb4_speed;
+}
+
+uint32_t get_enter_usb_msg_payload(int port)
+{
+ /*
+ * Ref: USB Power Delivery Specification Revision 3.0, Version 2.0
+ * Table 6-47 Enter_USB Data Object
+ */
+ union enter_usb_data_obj eudo;
+ const struct pd_discovery *disc;
+ union tbt_mode_resp_cable cable_mode_resp;
+
+ if (!IS_ENABLED(CONFIG_USB_PD_USB4))
+ return 0;
+
+ disc = pd_get_am_discovery(port, TCPCI_MSG_SOP_PRIME);
+ eudo.mode = USB_PD_40;
+ eudo.usb4_drd_cap = IS_ENABLED(CONFIG_USB_PD_USB4_DRD);
+ eudo.usb3_drd_cap = IS_ENABLED(CONFIG_USB_PD_USB32_DRD);
+ eudo.cable_speed = get_usb4_cable_speed(port);
+
+ if (disc->identity.idh.product_type == IDH_PTYPE_ACABLE) {
+ if (pd_get_rev(port, TCPCI_MSG_SOP_PRIME) == PD_REV30) {
+ enum retimer_active_element active_element =
+ disc->identity.product_t2.a2_rev30.active_elem;
+ eudo.cable_type = active_element == ACTIVE_RETIMER ?
+ CABLE_TYPE_ACTIVE_RETIMER :
+ CABLE_TYPE_ACTIVE_REDRIVER;
+ } else {
+ cable_mode_resp.raw_value =
+ pd_get_tbt_mode_vdo(port, TCPCI_MSG_SOP_PRIME);
+
+ eudo.cable_type = cable_mode_resp.retimer_type ==
+ USB_RETIMER ?
+ CABLE_TYPE_ACTIVE_RETIMER :
+ CABLE_TYPE_ACTIVE_REDRIVER;
+ }
+ } else {
+ cable_mode_resp.raw_value =
+ pd_get_tbt_mode_vdo(port, TCPCI_MSG_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) {
+ case USB_VBUS_CUR_3A:
+ eudo.cable_current = USB4_CABLE_CURRENT_3A;
+ break;
+ case USB_VBUS_CUR_5A:
+ eudo.cable_current = USB4_CABLE_CURRENT_5A;
+ break;
+ default:
+ eudo.cable_current = USB4_CABLE_CURRENT_INVALID;
+ break;
+ }
+ eudo.pcie_supported = IS_ENABLED(CONFIG_USB_PD_PCIE_TUNNELING);
+ eudo.dp_supported = IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP);
+ eudo.tbt_supported = IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE);
+ eudo.host_present = 1;
+
+ return eudo.raw_value;
+}
diff --git a/common/usbc/usb_pd_dpm.c b/common/usbc/usb_pd_dpm.c
index d8fbccc522..8141e92fd7 100644
--- a/common/usbc/usb_pd_dpm.c
+++ b/common/usbc/usb_pd_dpm.c
@@ -88,6 +88,11 @@ static int init_vdm_attention_mutex(const struct device *dev)
SYS_INIT(init_vdm_attention_mutex, POST_KERNEL, 50);
#endif /* CONFIG_ZEPHYR */
+__overridable bool board_is_tbt_usb4_port(int port)
+{
+ return true;
+}
+
enum ec_status pd_request_vdm_attention(int port, const uint32_t *data,
int vdo_count)
{