diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/usb_common.c | 2 | ||||
-rw-r--r-- | common/usb_pd_alt_mode_dfp.c | 94 | ||||
-rw-r--r-- | common/usb_pd_console_cmd.c | 3 | ||||
-rw-r--r-- | common/usb_pd_host_cmd.c | 8 | ||||
-rw-r--r-- | common/usb_pd_policy.c | 18 | ||||
-rw-r--r-- | common/usb_pd_protocol.c | 21 | ||||
-rw-r--r-- | common/usbc/dp_alt_mode.c | 10 | ||||
-rw-r--r-- | common/usbc/usb_pd_dpm.c | 2 | ||||
-rw-r--r-- | common/usbc/usb_pe_drp_sm.c | 72 | ||||
-rw-r--r-- | common/usbc/usb_tc_drp_acc_trysrc_sm.c | 38 |
10 files changed, 168 insertions, 100 deletions
diff --git a/common/usb_common.c b/common/usb_common.c index 156dc816cb..974e136a7b 100644 --- a/common/usb_common.c +++ b/common/usb_common.c @@ -645,7 +645,7 @@ static void pd_usb_billboard_deferred(void) * 1. Will we have multiple type-C port UFPs * 2. Will there be other modes applicable to DFPs besides DP */ - if (!pd_alt_mode(0, USB_SID_DISPLAYPORT)) + if (!pd_alt_mode(0, TCPC_TX_SOP, USB_SID_DISPLAYPORT)) usb_connect(); } } diff --git a/common/usb_pd_alt_mode_dfp.c b/common/usb_pd_alt_mode_dfp.c index a5d7120669..421ae72024 100644 --- a/common/usb_pd_alt_mode_dfp.c +++ b/common/usb_pd_alt_mode_dfp.c @@ -50,33 +50,37 @@ __overridable const struct svdm_response svdm_rsp = { .modes = NULL, }; -static int pd_get_mode_idx(int port, uint16_t svid) +static int pd_get_mode_idx(int port, enum tcpm_transmit_type type, + uint16_t svid) { - int i; - /* TODO(b/150611251): Support SOP' */ - struct pd_discovery *disc = pd_get_am_discovery(port, TCPC_TX_SOP); + int amode_idx; + struct partner_active_modes *active = + pd_get_partner_active_modes(port, type); - for (i = 0; i < PD_AMODE_COUNT; i++) { - if (disc->amodes[i].fx && - (disc->amodes[i].fx->svid == svid)) - return i; + for (amode_idx = 0; amode_idx < PD_AMODE_COUNT; amode_idx++) { + if (active->amodes[amode_idx].fx && + (active->amodes[amode_idx].fx->svid == svid)) + return amode_idx; } return -1; } -static int pd_allocate_mode(int port, uint16_t svid) +static int pd_allocate_mode(int port, enum tcpm_transmit_type type, + uint16_t svid) { int i, j; struct svdm_amode_data *modep; - int mode_idx = pd_get_mode_idx(port, svid); - /* TODO(b/150611251): Support SOP' and SOP'' */ - struct pd_discovery *disc = pd_get_am_discovery(port, TCPC_TX_SOP); + int mode_idx = pd_get_mode_idx(port, type, svid); + struct pd_discovery *disc = pd_get_am_discovery(port, type); + struct partner_active_modes *active = + pd_get_partner_active_modes(port, type); + assert(active); if (mode_idx != -1) return mode_idx; /* There's no space to enter another mode */ - if (disc->amode_idx == PD_AMODE_COUNT) { + if (active->amode_idx == PD_AMODE_COUNT) { CPRINTF("ERR:NO AMODE SPACE\n"); return -1; } @@ -91,16 +95,18 @@ static int pd_allocate_mode(int port, uint16_t svid) * discovered SVIDs; must also match the passed-in SVID * if that was non-zero. Otherwise, go to the next * discovered SVID. + * TODO(b/155890173): Support AP-directed mode entry + * where the mode is unknown to the TCPM. */ if ((svidp->svid != supported_modes[i].svid) || (svid && (svidp->svid != svid))) continue; - modep = &disc->amodes[disc->amode_idx]; + modep = &active->amodes[active->amode_idx]; modep->fx = &supported_modes[i]; modep->data = &disc->svids[j]; - disc->amode_idx++; - return disc->amode_idx - 1; + active->amode_idx++; + return active->amode_idx - 1; } } return -1; @@ -169,7 +175,7 @@ void pd_prepare_sysjump(void) int pd_dfp_dp_get_pin_mode(int port, uint32_t status) { struct svdm_amode_data *modep = - pd_get_amode_data(port, USB_SID_DISPLAYPORT); + pd_get_amode_data(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT); uint32_t mode_caps; uint32_t pin_caps; @@ -199,30 +205,31 @@ int pd_dfp_dp_get_pin_mode(int port, uint32_t status) return 1 << get_next_bit(&pin_caps); } -struct svdm_amode_data *pd_get_amode_data(int port, uint16_t svid) +struct svdm_amode_data *pd_get_amode_data(int port, + enum tcpm_transmit_type type, uint16_t svid) { - int idx = pd_get_mode_idx(port, svid); - /* TODO(b/150611251): Support SOP' */ - struct pd_discovery *disc = pd_get_am_discovery(port, TCPC_TX_SOP); + int idx = pd_get_mode_idx(port, type, svid); + struct partner_active_modes *active = + pd_get_partner_active_modes(port, type); + assert(active); - return (idx == -1) ? NULL : &disc->amodes[idx]; + return (idx == -1) ? NULL : &active->amodes[idx]; } /* * Enter default mode ( payload[0] == 0 ) or attempt to enter mode via svid & * opos */ -uint32_t pd_dfp_enter_mode(int port, uint16_t svid, int opos) +uint32_t pd_dfp_enter_mode(int port, enum tcpm_transmit_type type, + uint16_t svid, int opos) { - int mode_idx = pd_allocate_mode(port, svid); - /* TODO(b/150611251): Support SOP' */ - struct pd_discovery *disc = pd_get_am_discovery(port, TCPC_TX_SOP); + int mode_idx = pd_allocate_mode(port, type, svid); struct svdm_amode_data *modep; uint32_t mode_caps; if (mode_idx == -1) return 0; - modep = &disc->amodes[mode_idx]; + modep = &pd_get_partner_active_modes(port, type)->amodes[mode_idx]; if (!opos) { /* choose the lowest as default */ @@ -230,7 +237,7 @@ uint32_t pd_dfp_enter_mode(int port, uint16_t svid, int opos) } else if (opos <= modep->data->mode_cnt) { modep->opos = opos; } else { - CPRINTF("opos error\n"); + CPRINTS("C%d: Invalid opos %d for SVID %x", port, opos, svid); return 0; } @@ -244,11 +251,12 @@ uint32_t pd_dfp_enter_mode(int port, uint16_t svid, int opos) return VDO(modep->fx->svid, 1, CMD_ENTER_MODE | VDO_OPOS(modep->opos)); } -int pd_dfp_exit_mode(int port, uint16_t svid, int opos) +int pd_dfp_exit_mode(int port, enum tcpm_transmit_type type, uint16_t svid, + int opos) { struct svdm_amode_data *modep; - /* TODO(b/150611251): Support SOP' */ - struct pd_discovery *disc = pd_get_am_discovery(port, TCPC_TX_SOP); + struct partner_active_modes *active = + pd_get_partner_active_modes(port, type); int idx; /* @@ -258,8 +266,8 @@ int pd_dfp_exit_mode(int port, uint16_t svid, int opos) */ if (!svid) { for (idx = 0; idx < PD_AMODE_COUNT; idx++) - if (disc->amodes[idx].fx) - disc->amodes[idx].fx->exit(port); + if (active->amodes[idx].fx) + active->amodes[idx].fx->exit(port); pd_dfp_discovery_init(port); return 0; @@ -271,7 +279,7 @@ int pd_dfp_exit_mode(int port, uint16_t svid, int opos) * to exit all modes. We currently don't have any UFPs that support * multiple modes on one SVID. */ - modep = pd_get_amode_data(port, svid); + modep = pd_get_amode_data(port, type, svid); if (!modep || !validate_mode_request(modep, svid, opos)) return 0; @@ -289,7 +297,8 @@ void dfp_consume_attention(int port, uint32_t *payload) { uint16_t svid = PD_VDO_VID(payload[0]); int opos = PD_VDO_OPOS(payload[0]); - struct svdm_amode_data *modep = pd_get_amode_data(port, svid); + struct svdm_amode_data *modep = + pd_get_amode_data(port, TCPC_TX_SOP, svid); if (!modep || !validate_mode_request(modep, svid, opos)) return; @@ -434,9 +443,9 @@ int dfp_discover_modes(int port, uint32_t *payload) return 1; } -int pd_alt_mode(int port, uint16_t svid) +int pd_alt_mode(int port, enum tcpm_transmit_type type, uint16_t svid) { - struct svdm_amode_data *modep = pd_get_amode_data(port, svid); + struct svdm_amode_data *modep = pd_get_amode_data(port, type, svid); return (modep) ? modep->opos : -1; } @@ -846,7 +855,12 @@ int enter_tbt_compat_mode(int port, enum tcpm_transmit_type sop, struct pd_cable *cable = pd_get_cable_attributes(port); /* Table F-12 TBT3 Cable Enter Mode Command */ - payload[0] = pd_dfp_enter_mode(port, USB_VID_INTEL, 0) | + /* + * Although TCPMv2 contemplates separate mode storage for each SOP + * type, TCPMv1 stores everything in the array for SOP. + */ + /* TODO(b/148528713): Make this function generic to TCPM version. */ + payload[0] = pd_dfp_enter_mode(port, TCPC_TX_SOP, USB_VID_INTEL, 0) | VDO_SVDM_VERS(VDM_VER20); /* For TBT3 Cable Enter Mode Command, number of Objects is 1 */ @@ -1061,7 +1075,7 @@ __overridable int svdm_enter_dp_mode(int port, uint32_t mode_caps) __overridable int svdm_dp_status(int port, uint32_t *payload) { - int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT); + int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT); payload[0] = VDO(USB_SID_DISPLAYPORT, 1, CMD_DP_STATUS | VDO_OPOS(opos)); @@ -1083,7 +1097,7 @@ __overridable uint8_t get_dp_pin_mode(int port) __overridable int svdm_dp_config(int port, uint32_t *payload) { - int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT); + int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT); int mf_pref = PD_VDO_DPSTS_MF_PREF(dp_status[port]); uint8_t pin_mode = get_dp_pin_mode(port); mux_state_t mux_mode; diff --git a/common/usb_pd_console_cmd.c b/common/usb_pd_console_cmd.c index 22039eddc3..3fc6a6f35f 100644 --- a/common/usb_pd_console_cmd.c +++ b/common/usb_pd_console_cmd.c @@ -64,7 +64,8 @@ static void dump_pe(int port) disc->svids[i].mode_vdo[j]); ccprintf("\n"); - modep = pd_get_amode_data(port, disc->svids[i].svid); + modep = pd_get_amode_data(port, TCPC_TX_SOP, + disc->svids[i].svid); if (modep) { mode_caps = modep->data->mode_vdo[modep->opos - 1]; ccprintf("MODE[%d]: svid:%04x caps:%08x\n", modep->opos, diff --git a/common/usb_pd_host_cmd.c b/common/usb_pd_host_cmd.c index 8bd9f16aea..6e8afe761e 100644 --- a/common/usb_pd_host_cmd.c +++ b/common/usb_pd_host_cmd.c @@ -125,7 +125,7 @@ static enum ec_status hc_remote_pd_set_amode(struct host_cmd_handler_args *args) switch (p->cmd) { case PD_EXIT_MODE: - if (pd_dfp_exit_mode(p->port, p->svid, p->opos)) + if (pd_dfp_exit_mode(p->port, TCPC_TX_SOP, p->svid, p->opos)) pd_send_vdm(p->port, p->svid, CMD_EXIT_MODE | VDO_OPOS(p->opos), NULL, 0); else { @@ -134,7 +134,7 @@ static enum ec_status hc_remote_pd_set_amode(struct host_cmd_handler_args *args) } break; case PD_ENTER_MODE: - if (pd_dfp_enter_mode(p->port, p->svid, p->opos)) + if (pd_dfp_enter_mode(p->port, TCPC_TX_SOP, p->svid, p->opos)) pd_send_vdm(p->port, p->svid, CMD_ENTER_MODE | VDO_OPOS(p->opos), NULL, 0); break; @@ -190,10 +190,10 @@ static enum ec_status hc_remote_pd_get_amode(struct host_cmd_handler_args *args) r->opos = 0; memcpy(r->vdo, pd_get_mode_vdo(p->port, p->svid_idx, TCPC_TX_SOP), sizeof(uint32_t) * PDO_MODES); - modep = pd_get_amode_data(p->port, r->svid); + modep = pd_get_amode_data(p->port, TCPC_TX_SOP, r->svid); if (modep) - r->opos = pd_alt_mode(p->port, r->svid); + r->opos = pd_alt_mode(p->port, TCPC_TX_SOP, r->svid); args->response_size = sizeof(*r); return EC_RES_SUCCESS; diff --git a/common/usb_pd_policy.c b/common/usb_pd_policy.c index 0d468b0ce8..b10b9cb8c7 100644 --- a/common/usb_pd_policy.c +++ b/common/usb_pd_policy.c @@ -206,6 +206,7 @@ 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 partner_active_modes partner_amodes[CONFIG_USB_PD_PORT_MAX_COUNT]; static bool is_tbt_compat_enabled(int port) { @@ -331,6 +332,7 @@ static bool is_cable_ready_to_enter_usb4(int port, int cnt) void pd_dfp_discovery_init(int port) { memset(&discovery[port], 0, sizeof(struct pd_discovery)); + memset(&partner_amodes[port], 0, sizeof(partner_amodes[0])); } static int dfp_discover_ident(uint32_t *payload) @@ -354,6 +356,13 @@ struct pd_discovery *pd_get_am_discovery(int port, enum tcpm_transmit_type type) return &discovery[port]; } +struct partner_active_modes *pd_get_partner_active_modes(int port, + enum tcpm_transmit_type type) +{ + assert(type < AMODE_TYPE_COUNT); + return &partner_amodes[port]; +} + /* Note: Enter mode flag is not needed by TCPMv1 */ void pd_set_dfp_enter_mode_flag(int port, bool set) { @@ -656,7 +665,8 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload, #ifdef CONFIG_USB_PD_ALT_MODE_DFP struct svdm_amode_data *modep; - modep = pd_get_amode_data(port, PD_VDO_VID(payload[0])); + modep = pd_get_amode_data(port, TCPC_TX_SOP, + PD_VDO_VID(payload[0])); #endif switch (cmd) { #ifdef CONFIG_USB_PD_ALT_MODE_DFP @@ -705,7 +715,8 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload, * SVID. */ disable_tbt_compat_mode(port); - payload[0] = pd_dfp_enter_mode(port, 0, 0); + payload[0] = pd_dfp_enter_mode(port, + TCPC_TX_SOP, 0, 0); if (payload[0]) rsize = 1; } @@ -722,7 +733,8 @@ int pd_svdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload, rsize = 0; } else { if (!modep->opos) - pd_dfp_enter_mode(port, 0, 0); + pd_dfp_enter_mode(port, TCPC_TX_SOP, 0, + 0); if (modep->opos) { rsize = modep->fx->status(port, diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 442432890e..b8cd5d7340 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -791,7 +791,7 @@ static inline void set_state(int port, enum pd_states next_state) charge_manager_update_dualrole(port, CAP_UNKNOWN); #endif #ifdef CONFIG_USB_PD_ALT_MODE_DFP - pd_dfp_exit_mode(port, 0, 0); + pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0); #endif /* * Indicate that the port is disconnected by setting role to @@ -1325,7 +1325,7 @@ void pd_execute_hard_reset(int port) pd[port].msg_id = 0; invalidate_last_message_id(port); #ifdef CONFIG_USB_PD_ALT_MODE_DFP - pd_dfp_exit_mode(port, 0, 0); + pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0); #endif #ifdef CONFIG_USB_PD_REV30 @@ -2131,12 +2131,17 @@ static void exit_tbt_mode_sop_prime(int port) if (!IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE)) return; - opos = pd_alt_mode(port, USB_VID_INTEL); + opos = pd_alt_mode(port, TCPC_TX_SOP, USB_VID_INTEL); if (opos <= 0) return; CPRINTS("C%d Cable exiting TBT Compat mode", port); - if (!pd_dfp_exit_mode(port, USB_VID_INTEL, opos)) + /* + * Note: TCPMv2 contemplates separate discovery structures for each SOP + * type. TCPMv1 only uses one discovery structure, so all accesses + * specify TCPC_TX_SOP. + */ + if (!pd_dfp_exit_mode(port, TCPC_TX_SOP, USB_VID_INTEL, opos)) return; header = PD_HEADER(PD_DATA_VENDOR_DEF, pd[port].power_role, @@ -2333,10 +2338,12 @@ __maybe_unused static void exit_supported_alt_mode(int port) return; for (i = 0; i < supported_modes_cnt; i++) { - int opos = pd_alt_mode(port, supported_modes[i].svid); + int opos = pd_alt_mode(port, TCPC_TX_SOP, + supported_modes[i].svid); if (opos > 0 && - pd_dfp_exit_mode(port, supported_modes[i].svid, opos)) { + pd_dfp_exit_mode( + port, TCPC_TX_SOP, supported_modes[i].svid, opos)) { CPRINTS("C%d Exiting ALT mode with SVID = 0x%x", port, supported_modes[i].svid); pd_send_vdm(port, supported_modes[i].svid, @@ -4969,7 +4976,7 @@ int pd_is_port_enabled(int port) void pd_send_hpd(int port, enum hpd_event hpd) { uint32_t data[1]; - int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT); + int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT); if (!opos) return; diff --git a/common/usbc/dp_alt_mode.c b/common/usbc/dp_alt_mode.c index ba0b35550b..ff8909bbd6 100644 --- a/common/usbc/dp_alt_mode.c +++ b/common/usbc/dp_alt_mode.c @@ -58,11 +58,12 @@ void dp_vdm_acked(int port, enum tcpm_transmit_type type, int vdo_count, uint32_t *vdm) { const struct svdm_amode_data *modep = - pd_get_amode_data(port, USB_SID_DISPLAYPORT); + pd_get_amode_data(port, type, USB_SID_DISPLAYPORT); const uint8_t vdm_cmd = PD_VDO_CMD(vdm[0]); if (type != TCPC_TX_SOP || next_vdm_cmd[port] != vdm_cmd) { print_unexpected_response(port, type, CMDT_RSP_ACK, vdm_cmd); + dpm_set_mode_entry_done(port); return; } @@ -105,8 +106,8 @@ void dp_reset_next_command(int port) int dp_setup_next_vdm(int port, int vdo_count, uint32_t *vdm) { - const struct svdm_amode_data *modep = - pd_get_amode_data(port, USB_SID_DISPLAYPORT); + const struct svdm_amode_data *modep = pd_get_amode_data(port, + TCPC_TX_SOP, USB_SID_DISPLAYPORT); int vdo_count_ret; if (vdo_count < VDO_MAX_SIZE) @@ -115,7 +116,8 @@ int dp_setup_next_vdm(int port, int vdo_count, uint32_t *vdm) switch (next_vdm_cmd[port]) { case CMD_ENTER_MODE: /* Enter the first supported mode for DisplayPort. */ - vdm[0] = pd_dfp_enter_mode(port, USB_SID_DISPLAYPORT, 0); + vdm[0] = pd_dfp_enter_mode(port, TCPC_TX_SOP, + USB_SID_DISPLAYPORT, 0); if (vdm[0] == 0) return -1; /* CMDT_INIT is 0, so this is a no-op */ diff --git a/common/usbc/usb_pd_dpm.c b/common/usbc/usb_pd_dpm.c index 44ec46e588..adfb64d8fd 100644 --- a/common/usbc/usb_pd_dpm.c +++ b/common/usbc/usb_pd_dpm.c @@ -101,7 +101,7 @@ void dpm_attempt_mode_entry(int port) * TODO(b/155890173): Provide a host command to request that the PE send * an arbitrary VDM via this mechanism. */ - if (!pd_setup_vdm_request(port, vdm, vdo_count)) { + if (!pd_setup_vdm_request(port, TCPC_TX_SOP, vdm, vdo_count)) { dpm_set_mode_entry_done(port); return; } diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c index 0db15df6ee..7c6d8a9f98 100644 --- a/common/usbc/usb_pe_drp_sm.c +++ b/common/usbc/usb_pe_drp_sm.c @@ -466,6 +466,8 @@ static struct policy_engine { int32_t vpd_vdo; /* Alternate mode discovery results */ struct pd_discovery discovery[DISCOVERY_TYPE_COUNT]; + /* Active alternate modes */ + struct partner_active_modes partner_amodes[AMODE_TYPE_COUNT]; /* Alternate mode object position */ int8_t alt_opos; @@ -1063,7 +1065,7 @@ void pd_send_vdm(int port, uint32_t vid, int cmd, const uint32_t *data, void pe_exit_dp_mode(int port) { if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) { - int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT); + int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT); if (opos <= 0) return; @@ -1075,7 +1077,8 @@ void pe_exit_dp_mode(int port) * the mode to be cleaned up before return. */ CPRINTS("C%d Exiting DP mode", port); - if (!pd_dfp_exit_mode(port, USB_SID_DISPLAYPORT, opos)) + if (!pd_dfp_exit_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT, + opos)) return; /* @@ -1439,13 +1442,13 @@ static bool pe_attempt_port_discovery(int port) } #endif -bool pd_setup_vdm_request(int port, uint32_t *vdm, uint32_t vdo_cnt) +bool pd_setup_vdm_request(int port, enum tcpm_transmit_type tx_type, + uint32_t *vdm, uint32_t vdo_cnt) { if (vdo_cnt < VDO_HDR_SIZE || vdo_cnt > VDO_MAX_SIZE) return false; - /* TODO(b/155890173): Support cable plug */ - pe[port].partner_type = PORT; + pe[port].tx_type = tx_type; memcpy(pe[port].vdm_data, vdm, vdo_cnt * sizeof(*vdm)); pe[port].vdm_cnt = vdo_cnt; @@ -4183,7 +4186,7 @@ static void pe_do_port_discovery_run(int port) #ifdef CONFIG_USB_PD_ALT_MODE_DFP uint32_t *payload = (uint32_t *)rx_emsg[port].buf; struct svdm_amode_data *modep = - pd_get_amode_data(port, PD_VDO_VID(payload[0])); + pd_get_amode_data(port, TCPC_TX_SOP, PD_VDO_VID(payload[0])); int ret = 0; if (!PE_CHK_FLAG(port, @@ -4205,7 +4208,8 @@ static void pe_do_port_discovery_run(int port) break; case CMD_DISCOVER_MODES: pe[port].vdm_cmd = CMD_ENTER_MODE; - pe[port].vdm_data[0] = pd_dfp_enter_mode(port, 0, 0); + pe[port].vdm_data[0] = + pd_dfp_enter_mode(port, TCPC_TX_SOP, 0, 0); if (pe[port].vdm_data[0]) ret = 1; break; @@ -4860,6 +4864,12 @@ static void pe_vdm_request_entry(int port) { print_current_state(port); + if (pe[port].tx_type == TCPC_TX_INVALID) { + CPRINTS("C%d: TX type expected to be set, returning", port); + set_state_pe(port, get_last_state_pe(port)); + return; + } + /* All VDM sequences are Interruptible */ PE_SET_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS); @@ -4873,8 +4883,7 @@ static void pe_vdm_request_entry(int port) tx_emsg[port].len = pe[port].vdm_cnt * 4; } - /* TODO(b/155890173): Support cable plug */ - send_data_msg(port, TCPC_TX_SOP, PD_DATA_VENDOR_DEF); + send_data_msg(port, pe[port].tx_type, PD_DATA_VENDOR_DEF); pe[port].vdm_response_timer = TIMER_DISABLED; } @@ -4909,9 +4918,8 @@ static void pe_vdm_request_run(int port) cnt = PD_HEADER_CNT(rx_emsg[port].header); ext = PD_HEADER_EXT(rx_emsg[port].header); - if ((sop == TCPC_TX_SOP || sop == TCPC_TX_SOP_PRIME) && - type == PD_DATA_VENDOR_DEF && cnt > 0 && - ext == 0) { + if (sop == pe[port].tx_type && type == PD_DATA_VENDOR_DEF && + cnt > 0 && ext == 0) { if (PD_VDO_CMDT(payload[0]) == CMDT_RSP_ACK) { set_state_pe(port, PE_VDM_ACKED); return; @@ -4925,7 +4933,7 @@ static void pe_vdm_request_run(int port) PE_FLAGS_VDM_REQUEST_BUSY); } } else { - if ((sop == TCPC_TX_SOP || sop == TCPC_TX_SOP_PRIME) && + if (sop == pe[port].tx_type && type == PD_CTRL_NOT_SUPPORTED && cnt == 0 && ext == 0) { /* Equivalent meaning to a NAK */ @@ -4962,7 +4970,8 @@ static void pe_vdm_request_run(int port) PE_SET_FLAG(port, PE_FLAGS_VDM_REQUEST_BUSY); } else if (get_time().val > pe[port].vdm_response_timer) { CPRINTF("C%d: VDM %s Response Timeout\n", port, - pe[port].partner_type ? "Cable" : "Port"); + pe[port].tx_type == TCPC_TX_SOP + ? "Port" : "Cable"); PE_SET_FLAG(port, PE_FLAGS_VDM_REQUEST_NAKED); } @@ -4990,6 +4999,9 @@ static void pe_vdm_request_run(int port) static void pe_vdm_request_exit(int port) { + /* Invalidate TX type so that it must be set before next call */ + pe[port].tx_type = TCPC_TX_INVALID; + PE_CLR_FLAG(port, PE_FLAGS_INTERRUPTIBLE_AMS); } @@ -5012,24 +5024,18 @@ static void pe_vdm_acked_entry(int port) payload = (uint32_t *)rx_emsg[port].buf; svid = PD_VDO_VID(payload[0]); vdo_cmd = PD_VDO_CMD(payload[0]); - sop = PD_HEADER_GET_SOP(rx_emsg[port].header); - /* TODO(b/155890173): Support cable plug */ - if (sop == TCPC_TX_SOP) { - /* - * Handle Message From Port Partner - */ - /* vdo_count must have been >= 1 to get into this state. */ - dpm_vdm_acked(port, sop, vdo_count, payload); + /* vdo_count must have been >= 1 to get into this state. */ + dpm_vdm_acked(port, sop, vdo_count, payload); - /* - * TODO(b/155890173): Respect distinction between discovery and - * mode entry in flags. - */ - if (svid == USB_SID_DISPLAYPORT && vdo_cmd == CMD_DP_CONFIG) - PE_SET_FLAG(port, PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE); - } + /* + * TODO(b/155890173): Respect distinction between discovery and mode + * entry in flags. + */ + if (sop == TCPC_TX_SOP && svid == USB_SID_DISPLAYPORT && + vdo_cmd == CMD_DP_CONFIG) + PE_SET_FLAG(port, PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE); if (pe[port].power_role == PD_ROLE_SOURCE) { set_state_pe(port, PE_SRC_READY); @@ -5659,6 +5665,7 @@ uint8_t pd_get_src_cap_cnt(int port) void pd_dfp_discovery_init(int port) { memset(&pe[port].discovery, 0, sizeof(pe[port].discovery)); + memset(pe[port].partner_amodes, 0, sizeof(pe[port].partner_amodes)); /* Reset the DPM and DP modules to enable alternate mode entry. */ dpm_init(port); @@ -5671,6 +5678,13 @@ struct pd_discovery *pd_get_am_discovery(int port, enum tcpm_transmit_type type) return &pe[port].discovery[type]; } +struct partner_active_modes *pd_get_partner_active_modes(int port, + enum tcpm_transmit_type type) +{ + assert(type < AMODE_TYPE_COUNT); + return &pe[port].partner_amodes[type]; +} + struct pd_cable *pd_get_cable_attributes(int port) { return &pe[port].cable; diff --git a/common/usbc/usb_tc_drp_acc_trysrc_sm.c b/common/usbc/usb_tc_drp_acc_trysrc_sm.c index 8258f9666f..b39ea83ca6 100644 --- a/common/usbc/usb_tc_drp_acc_trysrc_sm.c +++ b/common/usbc/usb_tc_drp_acc_trysrc_sm.c @@ -1475,7 +1475,7 @@ static void handle_new_power_state(int port) void pd_send_hpd(int port, enum hpd_event hpd) { uint32_t data[1]; - int opos = pd_alt_mode(port, USB_SID_DISPLAYPORT); + int opos = pd_alt_mode(port, TCPC_TX_SOP, USB_SID_DISPLAYPORT); if (!opos) return; @@ -1907,7 +1907,9 @@ static void tc_attach_wait_snk_run(const int port) get_time().val > tc[port].pd_debounce) { if (IS_ENABLED(CONFIG_USB_PE_SM) && IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) { - pd_dfp_exit_mode(port, 0, 0); + pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0); + pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME, 0, 0); + pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME_PRIME, 0, 0); } /* We are detached */ @@ -2054,8 +2056,12 @@ static void tc_attached_snk_run(const int port) !TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) { /* Detach detection */ if (!pd_is_vbus_present(port)) { - if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) - pd_dfp_exit_mode(port, 0, 0); + if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) { + pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0); + pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME, 0, 0); + pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME_PRIME, + 0, 0); + } set_state_tc(port, TC_UNATTACHED_SNK); return; @@ -2444,8 +2450,12 @@ static void tc_dbg_acc_snk_run(const int port) !TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS)) { /* Detach detection */ if (!pd_is_vbus_present(port)) { - if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) - pd_dfp_exit_mode(port, 0, 0); + if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) { + pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0); + pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME, 0, 0); + pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME_PRIME, + 0, 0); + } set_state_tc(port, TC_UNATTACHED_SNK); return; @@ -2862,8 +2872,12 @@ static void tc_attached_src_run(const int port) !TC_CHK_FLAG(port, TC_FLAGS_DISC_IDENT_IN_PROGRESS)) { if (IS_ENABLED(CONFIG_USB_PE_SM)) - if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) - pd_dfp_exit_mode(port, 0, 0); + if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) { + pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0); + pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME, 0, 0); + pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME_PRIME, + 0, 0); + } set_state_tc(port, IS_ENABLED(CONFIG_USB_PD_TRY_SRC) ? TC_TRY_WAIT_SNK : TC_UNATTACHED_SNK); @@ -3303,8 +3317,12 @@ static void tc_ct_unattached_snk_run(int port) if (get_time().val > tc[port].cc_debounce) { if (new_cc_state == PD_CC_NONE && pd_check_vbus_level(port, VBUS_SAFE0V)) { - if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) - pd_dfp_exit_mode(port, 0, 0); + if (IS_ENABLED(CONFIG_USB_PD_ALT_MODE_DFP)) { + pd_dfp_exit_mode(port, TCPC_TX_SOP, 0, 0); + pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME, 0, 0); + pd_dfp_exit_mode(port, TCPC_TX_SOP_PRIME_PRIME, + 0, 0); + } set_state_tc(port, TC_UNATTACHED_SNK); return; |