summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/usb_pd_alt_mode_dfp.c24
-rw-r--r--common/usb_pd_host_cmd.c4
-rw-r--r--common/usbc/tbt_alt_mode.c28
-rw-r--r--common/usbc/usb_mode.c171
-rw-r--r--common/usbc/usb_pd_dpm.c32
-rw-r--r--common/usbc/usb_pe_drp_sm.c20
-rw-r--r--include/usb_mode.h18
-rw-r--r--include/usb_pd.h2
-rw-r--r--include/usb_pd_vdo.h13
-rw-r--r--include/usb_tbt_alt_mode.h9
10 files changed, 267 insertions, 54 deletions
diff --git a/common/usb_pd_alt_mode_dfp.c b/common/usb_pd_alt_mode_dfp.c
index b7d81e2e64..a2dc62afd8 100644
--- a/common/usb_pd_alt_mode_dfp.c
+++ b/common/usb_pd_alt_mode_dfp.c
@@ -929,6 +929,7 @@ uint32_t get_enter_usb_msg_payload(int port)
*/
union enter_usb_data_obj eudo;
struct pd_discovery *disc;
+ union tbt_mode_resp_cable cable_mode_resp;
if (!IS_ENABLED(CONFIG_USB_PD_USB4))
return 0;
@@ -939,13 +940,22 @@ uint32_t get_enter_usb_msg_payload(int port)
eudo.usb3_drd_cap = IS_ENABLED(CONFIG_USB_PD_USB32_DRD);
eudo.cable_speed = get_usb4_cable_speed(port);
- if (is_rev3_vdo(port, TCPC_TX_SOP_PRIME) &&
- (disc->identity.idh.product_type == IDH_PTYPE_ACABLE)) {
- eudo.cable_type =
- (disc->identity.product_t2.a2_rev30.active_elem ==
- ACTIVE_RETIMER) ? CABLE_TYPE_ACTIVE_RETIMER :
- CABLE_TYPE_ACTIVE_REDRIVER;
- /* TODO: Add eudo.cable_type for Revisiosn 2 active cables */
+ if (disc->identity.idh.product_type == IDH_PTYPE_ACABLE) {
+ if (is_rev3_vdo(port, TCPC_TX_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, TCPC_TX_SOP_PRIME);
+
+ eudo.cable_type =
+ cable_mode_resp.retimer_type == USB_RETIMER ?
+ CABLE_TYPE_ACTIVE_RETIMER :
+ CABLE_TYPE_ACTIVE_REDRIVER;
+ }
} else {
eudo.cable_type = CABLE_TYPE_PASSIVE;
}
diff --git a/common/usb_pd_host_cmd.c b/common/usb_pd_host_cmd.c
index 11174ee7d4..62b7045630 100644
--- a/common/usb_pd_host_cmd.c
+++ b/common/usb_pd_host_cmd.c
@@ -372,7 +372,9 @@ static enum ec_status hc_usb_pd_control(struct host_cmd_handler_args *args)
if (mux_state & USB_PD_MUX_USB4_ENABLED) {
r_v2->cable_speed =
get_usb4_cable_speed(p->port);
- } else if (mux_state & USB_PD_MUX_TBT_COMPAT_ENABLED) {
+ }
+ if (mux_state & USB_PD_MUX_TBT_COMPAT_ENABLED ||
+ mux_state & USB_PD_MUX_USB4_ENABLED) {
r_v2->cable_speed =
get_tbt_cable_speed(p->port);
r_v2->cable_gen =
diff --git a/common/usbc/tbt_alt_mode.c b/common/usbc/tbt_alt_mode.c
index 1319263e74..0785376355 100644
--- a/common/usbc/tbt_alt_mode.c
+++ b/common/usbc/tbt_alt_mode.c
@@ -69,8 +69,9 @@
* 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];
@@ -115,6 +116,7 @@ void tbt_init(int port)
tbt_state[port] = TBT_START;
TBT_CLR_FLAG(port, TBT_FLAG_RETRY_DONE);
TBT_SET_FLAG(port, TBT_FLAG_EXIT_DONE);
+ TBT_CLR_FLAG(port, TBT_FLAG_CABLE_ENTRY_DONE);
}
bool tbt_is_active(int port)
@@ -129,10 +131,16 @@ bool tbt_entry_is_done(int port)
tbt_state[port] == TBT_INACTIVE;
}
+bool tbt_cable_entry_is_done(int port)
+{
+ return TBT_CHK_FLAG(port, TBT_FLAG_CABLE_ENTRY_DONE);
+}
+
static void tbt_exit_done(int port)
{
tbt_state[port] = TBT_INACTIVE;
TBT_CLR_FLAG(port, TBT_FLAG_RETRY_DONE);
+ TBT_CLR_FLAG(port, TBT_FLAG_CABLE_ENTRY_DONE);
if (!TBT_CHK_FLAG(port, TBT_FLAG_EXIT_DONE)) {
TBT_SET_FLAG(port, TBT_FLAG_EXIT_DONE);
@@ -147,6 +155,14 @@ void tbt_exit_mode_request(int port)
{
TBT_SET_FLAG(port, TBT_FLAG_RETRY_DONE);
TBT_CLR_FLAG(port, TBT_FLAG_EXIT_DONE);
+ /*
+ * If the port has entered USB4 mode with Thunderbolt mode for the
+ * cable, on request to exit, only exit Thunderbolt mode for the
+ * 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;
}
static bool tbt_response_valid(int port, enum tcpm_transmit_type type,
@@ -203,12 +219,15 @@ 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)
+ if (disc->identity.product_t1.a_rev20.sop_p_p) {
tbt_state[port] = TBT_ENTER_SOP_PRIME_PRIME;
- else
+ } else {
+ TBT_SET_FLAG(port, TBT_FLAG_CABLE_ENTRY_DONE);
tbt_state[port] = TBT_ENTER_SOP;
+ }
break;
case TBT_ENTER_SOP_PRIME_PRIME:
+ TBT_SET_FLAG(port, TBT_FLAG_CABLE_ENTRY_DONE);
tbt_state[port] = TBT_ENTER_SOP;
break;
case TBT_ENTER_SOP:
@@ -315,6 +334,7 @@ void intel_vdm_naked(int port, enum tcpm_transmit_type type, uint8_t vdm_cmd)
break;
case TBT_EXIT_SOP:
/* Exit SOP got NAK'ed */
+ tbt_prints("exit mode SOP failed", port);
set_usb_mux_with_current_data_role(port);
if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE)
tbt_active_cable_exit_mode(port);
diff --git a/common/usbc/usb_mode.c b/common/usbc/usb_mode.c
index c48002f0d1..818f1e18c3 100644
--- a/common/usbc/usb_mode.c
+++ b/common/usbc/usb_mode.c
@@ -19,7 +19,6 @@
#include "usb_mux.h"
#include "usb_pd.h"
#include "usb_pd_dpm.h"
-#include "usb_pd_tbt.h"
#include "usb_pe_sm.h"
#include "usbc_ppc.h"
@@ -37,11 +36,63 @@ enum usb4_mode_status {
};
enum usb4_states {
+ USB4_START,
USB4_ENTER_SOP,
+ USB4_ENTER_SOP_PRIME,
+ USB4_ENTER_SOP_PRIME_PRIME,
USB4_ACTIVE,
USB4_INACTIVE,
USB4_STATE_COUNT,
};
+
+/*
+ * USB4 flow for Active cable
+ *
+ * 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
+ */
+
static enum usb4_states usb4_state[CONFIG_USB_PD_PORT_MAX_COUNT];
static void usb4_debug_prints(int port, enum usb4_mode_status usb4_status)
@@ -58,7 +109,7 @@ bool enter_usb_entry_is_done(int port)
void enter_usb_init(int port)
{
- usb4_state[port] = USB4_ENTER_SOP;
+ usb4_state[port] = USB4_START;
}
void enter_usb_failed(int port)
@@ -87,30 +138,86 @@ static bool enter_usb_response_valid(int port, enum tcpm_transmit_type type)
return true;
}
-bool enter_usb_is_capable(int port)
+bool enter_usb_port_partner_is_capable(int port)
{
const struct pd_discovery *disc =
pd_get_am_discovery(port, TCPC_TX_SOP);
- /*
- * TODO: b/156749387 Add support for entering the USB4 mode with an
- * active cable.
- */
- if (!IS_ENABLED(CONFIG_USB_PD_USB4) ||
- !PD_PRODUCT_IS_USB4(disc->identity.product_t1.raw_value) ||
- get_usb4_cable_speed(port) < USB_R30_SS_U32_U40_GEN1 ||
- usb4_state[port] == USB4_INACTIVE ||
- get_usb_pd_cable_type(port) != IDH_PTYPE_PCABLE)
+
+ if (usb4_state[port] == USB4_INACTIVE)
+ return false;
+
+ if (!PD_PRODUCT_IS_USB4(disc->identity.product_t1.raw_value))
return false;
return true;
}
+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;
+ } else if (get_usb_pd_cable_type(port) == IDH_PTYPE_ACABLE) {
+ struct pd_discovery *disc_sop_prime =
+ pd_get_am_discovery(port, TCPC_TX_SOP_PRIME);
+
+ if (pd_get_vdo_ver(port, TCPC_TX_SOP_PRIME) >= VDM_VER20 &&
+ disc_sop_prime->identity.product_t1.a_rev30.vdo_ver >=
+ VDO_VERSION_1_3) {
+ union active_cable_vdo2_rev30 a2_rev30 =
+ disc_sop_prime->identity.product_t2.a2_rev30;
+ /*
+ * For VDM version >= 2.0 and VD0 version is >= 1.3,
+ * do not enter USB4 mode if the cable isn't USB4
+ * capable.
+ */
+ if (a2_rev30.usb_40_support == USB4_NOT_SUPPORTED)
+ return false;
+ /*
+ * For VDM version < 2.0 or VDO version < 1.3, do not enter USB4
+ * mode if the cable -
+ * doesn't support modal operation or
+ * doesn't support Intel SVID or
+ * doesn't have rounded support.
+ */
+ } else {
+ const struct pd_discovery *disc =
+ pd_get_am_discovery(port, TCPC_TX_SOP);
+ union tbt_mode_resp_cable cable_mode_resp = {
+ .raw_value = pd_get_tbt_mode_vdo(port,
+ TCPC_TX_SOP_PRIME) };
+
+ if (!disc->identity.idh.modal_support ||
+ !pd_is_mode_discovered_for_svid(port,
+ TCPC_TX_SOP_PRIME, USB_VID_INTEL) ||
+ cable_mode_resp.tbt_rounded !=
+ TBT_GEN3_GEN4_ROUNDED_NON_ROUNDED)
+ return false;
+ }
+ }
+ return true;
+}
+
void enter_usb_accepted(int port, enum tcpm_transmit_type type)
{
+ struct pd_discovery *disc;
+
if (!enter_usb_response_valid(port, type))
return;
switch (usb4_state[port]) {
+ case USB4_ENTER_SOP_PRIME:
+ disc = pd_get_am_discovery(port, TCPC_TX_SOP_PRIME);
+ if (disc->identity.product_t1.a_rev20.sop_p_p)
+ usb4_state[port] = USB4_ENTER_SOP_PRIME_PRIME;
+ else
+ usb4_state[port] = USB4_ENTER_SOP;
+ break;
+ case USB4_ENTER_SOP_PRIME_PRIME:
+ usb4_state[port] = USB4_ENTER_SOP;
+ break;
case USB4_ENTER_SOP:
/* Connect the SBU and USB lines to the connector */
if (IS_ENABLED(CONFIG_USBC_PPC_SBU))
@@ -140,24 +247,44 @@ void enter_usb_rejected(int port, enum tcpm_transmit_type type)
enter_usb_failed(port);
}
-uint32_t enter_usb_setup_next_msg(int port)
+uint32_t enter_usb_setup_next_msg(int port, enum tcpm_transmit_type *type)
{
+ struct pd_discovery *disc_sop_prime;
+
switch (usb4_state[port]) {
+ case USB4_START:
+ disc_sop_prime = pd_get_am_discovery(port, TCPC_TX_SOP_PRIME);
+
+ if (pd_get_vdo_ver(port, TCPC_TX_SOP_PRIME) < VDM_VER20 ||
+ disc_sop_prime->identity.product_t1.a_rev30.vdo_ver <
+ VDO_VERSION_1_3 ||
+ get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE) {
+ usb4_state[port] = USB4_ENTER_SOP;
+ /* Ref: TBT4 PD Discover Flow */
+ usb_mux_set_safe_mode(port);
+ } else {
+ usb4_state[port] = USB4_ENTER_SOP_PRIME;
+ *type = TCPC_TX_SOP_PRIME;
+ }
+ break;
+ case USB4_ENTER_SOP_PRIME:
+ *type = TCPC_TX_SOP_PRIME;
+ break;
+ case USB4_ENTER_SOP_PRIME_PRIME:
+ *type = TCPC_TX_SOP_PRIME_PRIME;
+ break;
case USB4_ENTER_SOP:
+ *type = TCPC_TX_SOP;
/*
- * Set the USB mux to safe state to avoid damaging the mux pins
- * since, they are being re-purposed for USB4.
- *
- * TODO: b/141363146 Remove once data reset feature is in place
+ * Set the USB mux to safe state to avoid damaging the mux pins,
+ * since they are being re-purposed for USB4.
*/
usb_mux_set_safe_mode(port);
-
- usb4_state[port] = USB4_ENTER_SOP;
- return get_enter_usb_msg_payload(port);
+ break;
case USB4_ACTIVE:
return -1;
default:
- break;
+ return 0;
}
- return 0;
+ return get_enter_usb_msg_payload(port);
}
diff --git a/common/usbc/usb_pd_dpm.c b/common/usbc/usb_pd_dpm.c
index 69956c3685..193ea9802c 100644
--- a/common/usbc/usb_pd_dpm.c
+++ b/common/usbc/usb_pd_dpm.c
@@ -216,10 +216,28 @@ static void dpm_attempt_mode_entry(int port)
}
/* Check if the device and cable support USB4. */
- if (IS_ENABLED(CONFIG_USB_PD_USB4) && enter_usb_is_capable(port) &&
- dpm_mode_entry_requested(port, TYPEC_MODE_USB4)) {
- pd_dpm_request(port, DPM_REQUEST_ENTER_USB);
- return;
+ if (IS_ENABLED(CONFIG_USB_PD_USB4) &&
+ enter_usb_port_partner_is_capable(port) &&
+ enter_usb_cable_is_capable(port) &&
+ dpm_mode_entry_requested(port, TYPEC_MODE_USB4)) {
+ struct pd_discovery *disc_sop_prime =
+ pd_get_am_discovery(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
+ * VDO version >= 1.3 or
+ * 3. The cable has entered Thunderbolt mode.
+ */
+ if (get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE ||
+ (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 >=
+ VDO_VERSION_1_3) ||
+ tbt_cable_entry_is_done(port)) {
+ pd_dpm_request(port, DPM_REQUEST_ENTER_USB);
+ return;
+ }
}
/* If not, check if they support Thunderbolt alt mode. */
@@ -284,9 +302,13 @@ static void dpm_attempt_mode_exit(int port)
int vdo_count = 0;
enum tcpm_transmit_type tx_type = TCPC_TX_SOP;
- /* TODO(b/156749387): Support Data Reset for exiting USB4. */
if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) &&
tbt_is_active(port)) {
+ /*
+ * When the port is in USB4 mode and receives an exit request,
+ * it leaves USB4 SOP in active state.
+ * TODO(b/156749387): Support Data Reset for exiting USB4 SOP.
+ */
CPRINTS("C%d: TBT teardown", port);
tbt_exit_mode_request(port);
vdo_count = tbt_setup_next_vdm(port, VDO_MAX_SIZE, &vdm,
diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c
index 37afaa9c0e..139e8454b0 100644
--- a/common/usbc/usb_pe_drp_sm.c
+++ b/common/usbc/usb_pe_drp_sm.c
@@ -5513,28 +5513,32 @@ static void pe_enter_usb_entry(int port)
return;
}
- usb4_payload = enter_usb_setup_next_msg(port);
-
/* Port is already in USB4 mode, do not send enter USB message again */
- if (usb4_payload < 0) {
+ if (enter_usb_entry_is_done(port)) {
pe_set_ready_state(port);
return;
}
+ if ((pe[port].tx_type == TCPC_TX_SOP_PRIME ||
+ pe[port].tx_type == TCPC_TX_SOP_PRIME_PRIME) &&
+ !tc_is_vconn_src(port)) {
+ if (port_try_vconn_swap(port))
+ return;
+ }
+
+ pe[port].tx_type = TCPC_TX_SOP;
+ usb4_payload = enter_usb_setup_next_msg(port, &pe[port].tx_type);
+
if (!usb4_payload) {
enter_usb_failed(port);
pe_set_ready_state(port);
return;
}
- /*
- * TODO: b/156749387 In case of Enter USB SOP'/SOP'', check if the port
- * is the VCONN source, if not, request for a VCONN swap.
- */
tx_emsg[port].len = sizeof(usb4_payload);
memcpy(tx_emsg[port].buf, &usb4_payload, tx_emsg[port].len);
- send_data_msg(port, TCPC_TX_SOP, PD_DATA_ENTER_USB);
+ send_data_msg(port, pe[port].tx_type, PD_DATA_ENTER_USB);
pe_sender_response_msg_entry(port);
}
diff --git a/include/usb_mode.h b/include/usb_mode.h
index 728d7abc44..69170594ab 100644
--- a/include/usb_mode.h
+++ b/include/usb_mode.h
@@ -40,13 +40,22 @@ bool enter_usb_entry_is_done(int port);
void enter_usb_failed(int port);
/*
- * Returns True if port, port partner and cable supports USB4 mode
+ * Returns True if port partner supports USB4 mode
*
* @param port USB-C port number
- * @return True if USB4 mode is supported,
+ * @return True if USB4 mode is supported by the port partner,
* False otherwise
*/
-bool enter_usb_is_capable(int port);
+bool enter_usb_port_partner_is_capable(int port);
+
+/*
+ * Returns True if cable supports USB4 mode
+ *
+ * @param port USB-C port number
+ * @return True if USB4 mode is supported by the cable,
+ * False otherwise
+ */
+bool enter_usb_cable_is_capable(int port);
/*
* Handles accepted USB4 response
@@ -68,7 +77,8 @@ void enter_usb_rejected(int port, enum tcpm_transmit_type type);
* Constructs the next USB4 EUDO that should be sent.
*
* @param port USB-C port number
+ * @param type Transmit type (SOP, SOP', SOP'') for request
*/
-uint32_t enter_usb_setup_next_msg(int port);
+uint32_t enter_usb_setup_next_msg(int port, enum tcpm_transmit_type *type);
#endif
diff --git a/include/usb_pd.h b/include/usb_pd.h
index c2eea9bd76..01c061c8db 100644
--- a/include/usb_pd.h
+++ b/include/usb_pd.h
@@ -2146,7 +2146,7 @@ bool is_tbt_cable_superspeed(int port);
* port supports lesser speed than the cable
*
* @param port USB-C port number
- * @return thunderbolt-cable cable speed
+ * @return Thunderbolt cable speed
*/
enum tbt_compat_cable_speed get_tbt_cable_speed(int port);
diff --git a/include/usb_pd_vdo.h b/include/usb_pd_vdo.h
index 2cecec5d84..e0b1bf65dc 100644
--- a/include/usb_pd_vdo.h
+++ b/include/usb_pd_vdo.h
@@ -243,6 +243,10 @@ union passive_cable_vdo_rev30 {
* 011b = [USB4] Gen3
* 100b..111b = Reserved, Shall Not be used
*/
+enum vdo_version {
+ VDO_VERSION_1_3 = 3,
+};
+
union active_cable_vdo1_rev30 {
struct {
enum usb_rev30_ss ss: 3;
@@ -257,7 +261,7 @@ union active_cable_vdo1_rev30 {
uint32_t reserved0 : 1;
uint32_t connector : 2;
uint32_t reserved1 : 1;
- uint32_t vdo_version : 3;
+ enum vdo_version vdo_ver : 3;
uint32_t fw_version : 4;
uint32_t hw_version : 4;
};
@@ -326,6 +330,11 @@ enum active_cable_usb2_support {
USB2_NOT_SUPPORTED,
};
+enum active_cable_usb4_support {
+ USB4_SUPPORTED,
+ USB4_NOT_SUPPORTED,
+};
+
union active_cable_vdo2_rev30 {
struct {
uint8_t usb_gen : 1;
@@ -335,7 +344,7 @@ union active_cable_vdo2_rev30 {
uint8_t usb_32_support : 1;
enum active_cable_usb2_support usb_20_support : 1;
uint8_t usb_20_hub_hop : 2;
- uint8_t usb_40_support : 1;
+ enum active_cable_usb4_support usb_40_support : 1;
enum retimer_active_element active_elem : 1;
uint8_t physical_conn : 1;
uint8_t u3_to_u0 : 1;
diff --git a/include/usb_tbt_alt_mode.h b/include/usb_tbt_alt_mode.h
index 73a776e3dc..de203667b0 100644
--- a/include/usb_tbt_alt_mode.h
+++ b/include/usb_tbt_alt_mode.h
@@ -40,6 +40,15 @@ void tbt_exit_mode_request(int port);
bool tbt_entry_is_done(int port);
/*
+ * Checks if the cable entry into Thunderbolt alternate mode is done
+ *
+ * @param port USB-C port number
+ * @return True if TBT_FLAG_CABLE_ENTRY_DONE is set
+ * False otherwise
+ */
+bool tbt_cable_entry_is_done(int port);
+
+/*
* Returns True if Thunderbolt mode is not in inactive state
*
* @param port USB-C port number