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.c73
1 files changed, 40 insertions, 33 deletions
diff --git a/common/usb_pd_policy.c b/common/usb_pd_policy.c
index b10b9cb8c7..2ab397c0e7 100644
--- a/common/usb_pd_policy.c
+++ b/common/usb_pd_policy.c
@@ -113,6 +113,11 @@ uint8_t pd_get_src_cap_cnt(int port)
static struct pd_cable cable[CONFIG_USB_PD_PORT_MAX_COUNT];
+enum pd_rev_type get_usb_pd_cable_revision(int port)
+{
+ return cable[port].rev;
+}
+
bool consume_sop_prime_repeat_msg(int port, uint8_t msg_id)
{
@@ -205,7 +210,8 @@ void disable_enter_usb4_mode(int port)
#ifdef CONFIG_USB_PD_ALT_MODE_DFP
-static struct pd_discovery discovery[CONFIG_USB_PD_PORT_MAX_COUNT];
+static struct pd_discovery
+ discovery[CONFIG_USB_PD_PORT_MAX_COUNT][DISCOVERY_TYPE_COUNT];
static struct partner_active_modes partner_amodes[CONFIG_USB_PD_PORT_MAX_COUNT];
static bool is_tbt_compat_enabled(int port)
@@ -237,6 +243,18 @@ static inline bool is_limit_tbt_cable_speed(int port)
return !!(cable[port].flags & CABLE_FLAGS_TBT_COMPAT_LIMIT_SPEED);
}
+static bool is_intel_svid(int port, enum tcpm_transmit_type type)
+{
+ int i;
+
+ for (i = 0; i < discovery[port][type].svid_cnt; i++) {
+ if (pd_get_svid(port, i, type) == USB_VID_INTEL)
+ return true;
+ }
+
+ return false;
+}
+
static inline bool is_usb4_mode_enabled(int port)
{
return (IS_ENABLED(CONFIG_USB_PD_USB4) &&
@@ -292,13 +310,13 @@ static inline void disable_usb4_mode(int port)
static bool is_cable_ready_to_enter_usb4(int port, int cnt)
{
/* TODO: USB4 enter mode for Active cables */
-
+ struct pd_discovery *disc = &discovery[port][TCPC_TX_SOP_PRIME];
if (IS_ENABLED(CONFIG_USB_PD_USB4) &&
(get_usb_pd_cable_type(port) == IDH_PTYPE_PCABLE) &&
is_vdo_present(cnt, VDO_INDEX_PTYPE_CABLE1)) {
switch (cable[port].rev) {
case PD_REV30:
- switch (cable[port].attr.p_rev30.ss) {
+ switch (disc->identity.product_t1.p_rev30.ss) {
case USB_R30_SS_U40_GEN3:
case USB_R30_SS_U32_U40_GEN1:
return true;
@@ -312,7 +330,7 @@ static bool is_cable_ready_to_enter_usb4(int port, int cnt)
return false;
}
case PD_REV20:
- switch (cable[port].attr.p_rev20.ss) {
+ switch (disc->identity.product_t1.p_rev20.ss) {
case USB_R20_SS_U31_GEN1_GEN2:
/* Check if DFP is Gen 3 capable */
if (IS_ENABLED(CONFIG_USB_PD_TBT_GEN3_CAPABLE))
@@ -349,11 +367,7 @@ static int dfp_discover_svids(uint32_t *payload)
struct pd_discovery *pd_get_am_discovery(int port, enum tcpm_transmit_type type)
{
- /*
- * TCPMv2 separates discovered data by partner (SOP vs. SOP'); TCPMv1
- * depends on both types being in the same structure.
- */
- return &discovery[port];
+ return &discovery[port][type];
}
struct partner_active_modes *pd_get_partner_active_modes(int port,
@@ -377,10 +391,11 @@ static int process_am_discover_ident_sop(int port, int cnt,
uint32_t head, uint32_t *payload,
enum tcpm_transmit_type *rtype)
{
+ pd_dfp_discovery_init(port);
+ dfp_consume_identity(port, TCPC_TX_SOP, cnt, payload);
+
if (IS_ENABLED(CONFIG_USB_PD_DECODE_SOP) && is_sop_prime_ready(port) &&
board_is_tbt_usb4_port(port)) {
- pd_dfp_discovery_init(port);
- dfp_consume_identity(port, cnt, payload);
/* Enable USB4 mode if USB4 VDO present and port partner
* supports USB Rev 3.0.
@@ -401,9 +416,6 @@ static int process_am_discover_ident_sop(int port, int cnt,
*rtype = TCPC_TX_SOP_PRIME;
return dfp_discover_ident(payload);
}
- } else {
- pd_dfp_discovery_init(port);
- dfp_consume_identity(port, cnt, payload);
}
return dfp_discover_svids(payload);
@@ -412,8 +424,8 @@ static int process_am_discover_ident_sop(int port, int cnt,
static int process_am_discover_ident_sop_prime(int port, int cnt,
uint32_t head, uint32_t *payload)
{
- /* Store cable type */
- dfp_consume_cable_response(port, cnt, payload, head);
+ dfp_consume_identity(port, TCPC_TX_SOP_PRIME, cnt, payload);
+ cable[port].rev = PD_HEADER_REV(head);
/*
* Enter USB4 mode if the cable supports USB4 operation and has USB4
@@ -446,14 +458,12 @@ static int process_am_discover_svids(int port, int cnt, uint32_t *payload,
enum tcpm_transmit_type sop,
enum tcpm_transmit_type *rtype)
{
- int prev_svid_cnt = discovery[port].svid_cnt;
-
/*
* The pd_discovery structure stores SOP and SOP' discovery results
* separately, but TCPMv1 depends on one-dimensional storage of SVIDs
* and modes. Therefore, always use TCPC_TX_SOP in TCPMv1.
*/
- dfp_consume_svids(port, TCPC_TX_SOP, cnt, payload);
+ dfp_consume_svids(port, sop, cnt, payload);
/*
* Ref: USB Type-C Cable and Connector Specification,
@@ -470,8 +480,7 @@ static int process_am_discover_svids(int port, int cnt, uint32_t *payload,
* passive Gen 2 cable.
*/
if (is_tbt_compat_enabled(port)) {
- bool intel_svid = is_intel_svid(port, prev_svid_cnt);
-
+ bool intel_svid = is_intel_svid(port, sop);
if (!intel_svid) {
if (is_usb4_mode_enabled(port)) {
disable_tbt_compat_mode(port);
@@ -500,6 +509,7 @@ static int process_tbt_compat_discover_modes(int port,
enum tcpm_transmit_type *rtype)
{
int rsize;
+ struct pd_discovery *disc;
/* Initialize transmit type to SOP */
*rtype = TCPC_TX_SOP;
@@ -540,6 +550,7 @@ static int process_tbt_compat_discover_modes(int port,
} else {
/* Store Discover Mode SOP response */
cable[port].dev_mode_resp.raw_value = payload[1];
+ disc = &discovery[port][TCPC_TX_SOP_PRIME];
if (is_limit_tbt_cable_speed(port)) {
/*
@@ -549,16 +560,16 @@ static int process_tbt_compat_discover_modes(int port,
* Thunderbolt-compatible mode.
*/
cable[port].cable_mode_resp.tbt_cable_speed =
- (cable[port].rev == PD_REV30 &&
- cable[port].attr.p_rev30.ss >
+ cable[port].rev == PD_REV30 &&
+ (disc->identity.product_t1.p_rev30.ss >
USB_R30_SS_U32_U40_GEN2) ?
TBT_SS_U32_GEN1_GEN2 :
- cable[port].attr.p_rev30.ss;
+ disc->identity.product_t1.p_rev30.ss;
rsize = enter_tbt_compat_mode(port, *rtype, payload);
} else {
/* Discover modes for SOP' */
- discovery[port].svid_idx--;
+ discovery[port][TCPC_TX_SOP].svid_idx--;
rsize = dfp_discover_modes(port, payload);
*rtype = TCPC_TX_SOP_PRIME;
}
@@ -571,10 +582,12 @@ static int obj_cnt_enter_tbt_compat_mode(int port,
enum tcpm_transmit_type sop, uint32_t *payload,
enum tcpm_transmit_type *rtype)
{
+ struct pd_discovery *disc = &discovery[port][TCPC_TX_SOP_PRIME];
+
/* Enter mode SOP' for active cables */
if (sop == TCPC_TX_SOP_PRIME) {
/* Check if the cable has a SOP'' controller */
- if (cable[port].attr.a_rev20.sop_p_p)
+ if (disc->identity.product_t1.a_rev20.sop_p_p)
*rtype = TCPC_TX_SOP_PRIME_PRIME;
return enter_tbt_compat_mode(port, *rtype, payload);
}
@@ -692,13 +705,7 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload,
sop, rtype);
break;
case CMD_DISCOVER_MODES:
- /*
- * The pd_discovery structure stores SOP and SOP'
- * discovery results separately, but TCPMv1 depends on
- * one-dimensional storage of SVIDs and modes.
- * Therefore, always use TCPC_TX_SOP in TCPMv1.
- */
- dfp_consume_modes(port, TCPC_TX_SOP, cnt, payload);
+ dfp_consume_modes(port, sop, cnt, payload);
if (is_tbt_compat_enabled(port) &&
is_tbt_compat_mode(port, cnt, payload)) {
rsize = process_tbt_compat_discover_modes(