diff options
Diffstat (limited to 'common/usb_pd_policy.c')
-rw-r--r-- | common/usb_pd_policy.c | 73 |
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( |