diff options
-rw-r--r-- | common/usb_pd_alt_mode_dfp.c | 299 | ||||
-rw-r--r-- | common/usb_pd_console_cmd.c | 4 | ||||
-rw-r--r-- | common/usb_pd_host_cmd.c | 11 | ||||
-rw-r--r-- | common/usbc/tbt_alt_mode.c | 175 | ||||
-rw-r--r-- | common/usbc/usb_mode.c | 104 | ||||
-rw-r--r-- | common/usbc/usb_pd_dpm.c | 5 |
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) { |