summaryrefslogtreecommitdiff
path: root/common/usb_pd_policy.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/usb_pd_policy.c')
-rw-r--r--common/usb_pd_policy.c87
1 files changed, 66 insertions, 21 deletions
diff --git a/common/usb_pd_policy.c b/common/usb_pd_policy.c
index 7ff9c3342d..93ce6fccb4 100644
--- a/common/usb_pd_policy.c
+++ b/common/usb_pd_policy.c
@@ -173,6 +173,12 @@ bool is_transmit_msg_sop_prime(int port)
(cable[port].flags & CABLE_FLAGS_SOP_PRIME_ENABLE));
}
+static bool is_transmit_msg_sop_prime_prime(int port)
+{
+ return (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP) &&
+ (cable[port].flags & CABLE_FLAGS_SOP_PRIME_PRIME_ENABLE));
+}
+
int cable_consume_repeat_message(int port, uint8_t msg_id)
{
@@ -182,7 +188,6 @@ int cable_consume_repeat_message(int port, uint8_t msg_id)
}
CPRINTF("C%d Cable repeat msg_id %d\n", port, msg_id);
return 1;
-
}
static void disable_transmit_sop_prime(int port)
@@ -191,9 +196,14 @@ static void disable_transmit_sop_prime(int port)
cable[port].flags &= ~CABLE_FLAGS_SOP_PRIME_ENABLE;
}
-uint8_t is_sop_prime_ready(int port,
- enum pd_data_role data_role,
- uint32_t pd_flags)
+static void disable_transmit_sop_prime_prime(int port)
+{
+ if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP))
+ cable[port].flags &= ~CABLE_FLAGS_SOP_PRIME_PRIME_ENABLE;
+}
+
+enum pd_msg_type pd_msg_tx_type(int port, enum pd_data_role data_role,
+ uint32_t pd_flags)
{
/*
* Ref: USB PD 3.0 sec 2.5.4: When an Explicit Contract is in place the
@@ -208,17 +218,27 @@ uint8_t is_sop_prime_ready(int port,
*/
if (pd_flags & PD_FLAGS_VCONN_ON && (IS_ENABLED(CONFIG_USB_PD_REV30) ||
data_role == PD_ROLE_DFP)) {
- return is_transmit_msg_sop_prime(port);
+ if (is_transmit_msg_sop_prime(port))
+ return PD_MSG_SOP_PRIME;
+ if (is_transmit_msg_sop_prime_prime(port))
+ return PD_MSG_SOP_PRIME_PRIME;
}
+
if (is_transmit_msg_sop_prime(port)) {
/*
* Clear the CABLE_FLAGS_SOP_PRIME_ENABLE flag if the port is
* unable to communicate with the cable plug.
*/
disable_transmit_sop_prime(port);
+ } else if (is_transmit_msg_sop_prime_prime(port)) {
+ /*
+ * Clear the CABLE_FLAGS_SOP_PRIME_PRIME_ENABLE flag if the port
+ * is unable to communicate with the cable plug.
+ */
+ disable_transmit_sop_prime_prime(port);
}
- return 0;
+ return PD_MSG_SOP;
}
void reset_pd_cable(int port)
@@ -368,6 +388,12 @@ static void enable_transmit_sop_prime(int port)
cable[port].flags |= CABLE_FLAGS_SOP_PRIME_ENABLE;
}
+static void enable_transmit_sop_prime_prime(int port)
+{
+ if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP))
+ cable[port].flags |= CABLE_FLAGS_SOP_PRIME_PRIME_ENABLE;
+}
+
static bool is_tbt_compat_enabled(int port)
{
return (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) &&
@@ -850,7 +876,8 @@ static int enter_tbt_compat_mode(int port, uint32_t *payload)
VDO_SVDM_VERS(VDM_VER20);
/* For TBT3 Cable Enter Mode Command, number of Objects is 1 */
- if (is_transmit_msg_sop_prime(port))
+ if (is_transmit_msg_sop_prime(port) ||
+ is_transmit_msg_sop_prime_prime(port))
return 1;
usb_mux_set_safe_mode(port);
@@ -1195,6 +1222,36 @@ static int process_tbt_compat_discover_modes(int port, uint32_t *payload)
return rsize;
}
+
+/*
+ * This function returns number of objects required to enter
+ * Thunderbolt-Compatible mode i.e.
+ * 2 - When SOP is enabled.
+ * 1 - When SOP' or SOP'' is enabled.
+ * 0 - Acknowledge.
+ */
+static int enter_mode_tbt_compat(int port, uint32_t *payload)
+{
+ /* Enter mode SOP' for active cables */
+ if (is_transmit_msg_sop_prime(port)) {
+ disable_transmit_sop_prime(port);
+ /* Check if the cable has a SOP'' controller */
+ if (cable[port].attr.a_rev20.sop_p_p)
+ enable_transmit_sop_prime_prime(port);
+ return enter_tbt_compat_mode(port, payload);
+ }
+
+ /* Enter Mode SOP'' for active cables with SOP'' controller */
+ if (is_transmit_msg_sop_prime_prime(port)) {
+ disable_transmit_sop_prime_prime(port);
+ return enter_tbt_compat_mode(port, payload);
+ }
+
+ /* Update Mux state to Thunderbolt-compatible mode. */
+ set_tbt_compat_mode_ready(port);
+ /* No response once device (and cable) acks */
+ return 0;
+}
#endif /* CONFIG_USB_PD_ALT_MODE_DFP */
int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload,
@@ -1270,7 +1327,7 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload,
switch (cmd) {
#ifdef CONFIG_USB_PD_ALT_MODE_DFP
case CMD_DISCOVER_IDENT:
- /* Received a SOP Prime Discover Ident msg */
+ /* Received a SOP' Discover Ident msg */
if (is_transmit_msg_sop_prime(port)) {
/* Store cable type */
dfp_consume_cable_response(port, cnt, payload,
@@ -1406,20 +1463,8 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload,
}
break;
case CMD_ENTER_MODE:
- /* No response once device (and cable) acks */
if (is_tbt_compat_enabled(port)) {
- if (is_transmit_msg_sop_prime(port)) {
- disable_transmit_sop_prime(port);
- rsize = enter_tbt_compat_mode(port,
- payload);
- } else {
- /*
- * Update Mux state to
- * Thunderbolt-compatible mode.
- */
- set_tbt_compat_mode_ready(port);
- rsize = 0;
- }
+ rsize = enter_mode_tbt_compat(port, payload);
/*
* Continue with PD flow if Thunderbolt-compatible mode
* is disabled.