diff options
Diffstat (limited to 'common/usbc/usb_pd_dpm.c')
-rw-r--r-- | common/usbc/usb_pd_dpm.c | 690 |
1 files changed, 254 insertions, 436 deletions
diff --git a/common/usbc/usb_pd_dpm.c b/common/usbc/usb_pd_dpm.c index 775ea0da46..daccc2ba2a 100644 --- a/common/usbc/usb_pd_dpm.c +++ b/common/usbc/usb_pd_dpm.c @@ -25,13 +25,12 @@ #include "usb_mode.h" #include "usb_mux.h" #include "usb_pd.h" -#include "usb_pd_dpm_sm.h" +#include "usb_pd_dpm.h" #include "usb_pd_pdo.h" #include "usb_pd_tcpm.h" #include "usb_pd_timer.h" #include "usb_pe_sm.h" #include "usb_tbt_alt_mode.h" -#include "usb_tc_sm.h" #ifdef CONFIG_ZEPHYR #include "temp_sensor/temp_sensor.h" @@ -49,8 +48,6 @@ #define DPM_ATTENION_MAX_VDO 2 static struct { - /* state machine context */ - struct sm_ctx ctx; atomic_t flags; uint32_t vdm_req[VDO_MAX_SIZE]; int vdm_req_cnt; @@ -72,51 +69,10 @@ static struct { #define DPM_FLAG_ENTER_ANY \ (DPM_FLAG_ENTER_DP | DPM_FLAG_ENTER_TBT | DPM_FLAG_ENTER_USB4) #define DPM_FLAG_SEND_VDM_REQ BIT(5) -#define DPM_FLAG_DATA_RESET_DONE BIT(6) -#define DPM_FLAG_PD_BUTTON_PRESSED BIT(7) -#define DPM_FLAG_PD_BUTTON_RELEASED BIT(8) -#define DPM_FLAG_PE_READY BIT(9) - -/* List of all Device Policy Manager level states */ -enum usb_dpm_state { - /* Normal States */ - DPM_WAITING, - DPM_DFP_READY, - DPM_UFP_READY, - DPM_DATA_RESET, -}; - -/* Forward declare the full list of states. This is indexed by usb_pd_state */ -static const struct usb_state dpm_states[]; - -/* List of human readable state names for console debugging */ -__maybe_unused static __const_data const char *const dpm_state_names[] = { - /* Normal States */ - [DPM_WAITING] = "DPM Waiting", - [DPM_DFP_READY] = "DPM DFP Ready", - [DPM_UFP_READY] = "DPM UFP Ready", - [DPM_DATA_RESET] = "DPM Data Reset", -}; - -static enum sm_local_state local_state[CONFIG_USB_PD_PORT_MAX_COUNT]; - -/* Set the DPM state machine to a new state. */ -static void set_state_dpm(const int port, const enum usb_dpm_state new_state) -{ - set_state(port, &dpm[port].ctx, &dpm_states[new_state]); -} - -/* Get the current TypeC state. */ -__maybe_unused test_export_static enum usb_dpm_state -get_state_dpm(const int port) -{ - return dpm[port].ctx.current - &dpm_states[0]; -} - -static void print_current_state(const int port) -{ - CPRINTS("C%d: %s", port, dpm_state_names[get_state_dpm(port)]); -} +#define DPM_FLAG_DATA_RESET_REQUESTED BIT(6) +#define DPM_FLAG_DATA_RESET_DONE BIT(7) +#define DPM_FLAG_PD_BUTTON_PRESSED BIT(8) +#define DPM_FLAG_PD_BUTTON_RELEASED BIT(9) #ifdef CONFIG_ZEPHYR static int init_vdm_req_mutex(const struct device *dev) @@ -224,9 +180,6 @@ void dpm_init(int port) { dpm[port].flags = 0; dpm[port].pd_button_state = DPM_PD_BUTTON_IDLE; - - /* Ensure that DPM state machine gets reset */ - set_state_dpm(port, DPM_WAITING); } void dpm_mode_exit_complete(int port) @@ -250,22 +203,11 @@ void dpm_set_mode_exit_request(int port) void dpm_data_reset_complete(int port) { + DPM_CLR_FLAG(port, DPM_FLAG_DATA_RESET_REQUESTED); DPM_SET_FLAG(port, DPM_FLAG_DATA_RESET_DONE); DPM_CLR_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE); } -void dpm_set_pe_ready(int port, bool enable) -{ - /* - * DPM should remain DPM_WAITING state until the PE is in its ready - * state and is able to accept requests from the DPM layer. - */ - if (enable) - DPM_SET_FLAG(port, DPM_FLAG_PE_READY); - else - DPM_CLR_FLAG(port, DPM_FLAG_PE_READY); -} - static void dpm_clear_mode_exit_request(int port) { DPM_CLR_FLAG(port, DPM_FLAG_EXIT_REQUEST); @@ -344,6 +286,236 @@ void dpm_vdm_naked(int port, enum tcpci_msg_type type, uint16_t svid, } } +/* + * Requests that the PE send one VDM, whichever is next in the mode entry + * sequence. This only happens if preconditions for mode entry are met. If + * CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY is enabled, this function waits for the + * AP to direct mode entry. + */ +static void dpm_attempt_mode_entry(int port) +{ + int vdo_count = 0; + uint32_t vdm[VDO_MAX_SIZE]; + enum tcpci_msg_type tx_type = TCPCI_MSG_SOP; + bool enter_mode_requested = + IS_ENABLED(CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY) ? false : true; + enum dpm_msg_setup_status status = MSG_SETUP_UNSUPPORTED; + + if (pd_get_data_role(port) != PD_ROLE_DFP) { + if (DPM_CHK_FLAG(port, DPM_FLAG_ENTER_DP | DPM_FLAG_ENTER_TBT | + DPM_FLAG_ENTER_USB4)) + DPM_CLR_FLAG(port, DPM_FLAG_ENTER_DP | + DPM_FLAG_ENTER_TBT | + DPM_FLAG_ENTER_USB4); + /* + * TODO(b/168030639): Notify the AP that the enter mode request + * failed. + */ + return; + } + +#ifdef CONFIG_AP_POWER_CONTROL + /* + * Do not try to enter mode while CPU is off. + * CPU transitions (e.g b/158634281) can occur during the discovery + * phase or during enter/exit negotiations, and the state + * of the modes can get out of sync, causing the attempt to + * enter the mode to fail prematurely. + */ + if (!chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON)) + return; +#endif + /* + * If discovery has not occurred for modes, do not attempt to switch + * to alt mode. + */ + if (pd_get_svids_discovery(port, TCPCI_MSG_SOP) != PD_DISC_COMPLETE || + pd_get_modes_discovery(port, TCPCI_MSG_SOP) != PD_DISC_COMPLETE) + return; + + if (dp_entry_is_done(port) || + (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) && + tbt_entry_is_done(port)) || + (IS_ENABLED(CONFIG_USB_PD_USB4) && enter_usb_entry_is_done(port))) { + dpm_set_mode_entry_done(port); + return; + } + + /* + * If muxes are still settling, then wait on our next VDM. We must + * ensure we correctly sequence actions such as USB safe state with TBT + * entry or DP configuration. + */ + if (IS_ENABLED(CONFIG_USBC_SS_MUX) && !usb_mux_set_completed(port)) + return; + + if (IS_ENABLED(CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY) && + IS_ENABLED(CONFIG_USB_PD_DATA_RESET_MSG) && + DPM_CHK_FLAG(port, DPM_FLAG_ENTER_ANY) && + !DPM_CHK_FLAG(port, DPM_FLAG_DATA_RESET_REQUESTED) && + !DPM_CHK_FLAG(port, DPM_FLAG_DATA_RESET_DONE)) { + pd_dpm_request(port, DPM_REQUEST_DATA_RESET); + DPM_SET_FLAG(port, DPM_FLAG_DATA_RESET_REQUESTED); + return; + } + + if (IS_ENABLED(CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY) && + IS_ENABLED(CONFIG_USB_PD_DATA_RESET_MSG) && + !DPM_CHK_FLAG(port, DPM_FLAG_DATA_RESET_DONE)) { + return; + } + + /* Check if port, port partner and cable support USB4. */ + if (IS_ENABLED(CONFIG_USB_PD_USB4) && board_is_tbt_usb4_port(port) && + enter_usb_port_partner_is_capable(port) && + enter_usb_cable_is_capable(port) && + dpm_mode_entry_requested(port, TYPEC_MODE_USB4)) { + /* + * For certain cables, enter Thunderbolt alt mode with the + * cable and USB4 mode with the port partner. + */ + if (tbt_cable_entry_required_for_usb4(port)) { + vdo_count = ARRAY_SIZE(vdm); + status = tbt_setup_next_vdm(port, &vdo_count, vdm, + &tx_type); + } else { + pd_dpm_request(port, DPM_REQUEST_ENTER_USB); + return; + } + } + + /* If not, check if they support Thunderbolt alt mode. */ + if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) && + board_is_tbt_usb4_port(port) && + pd_is_mode_discovered_for_svid(port, TCPCI_MSG_SOP, + USB_VID_INTEL) && + dpm_mode_entry_requested(port, TYPEC_MODE_TBT)) { + enter_mode_requested = true; + vdo_count = ARRAY_SIZE(vdm); + status = tbt_setup_next_vdm(port, &vdo_count, vdm, &tx_type); + } + + /* If not, check if they support DisplayPort alt mode. */ + if (status == MSG_SETUP_UNSUPPORTED && + !DPM_CHK_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE) && + pd_is_mode_discovered_for_svid(port, TCPCI_MSG_SOP, + USB_SID_DISPLAYPORT) && + dpm_mode_entry_requested(port, TYPEC_MODE_DP)) { + enter_mode_requested = true; + vdo_count = ARRAY_SIZE(vdm); + status = dp_setup_next_vdm(port, &vdo_count, vdm); + } + + /* Not ready to send a VDM, check again next cycle */ + if (status == MSG_SETUP_MUX_WAIT) + return; + + /* + * If the PE didn't discover any supported (requested) alternate mode, + * just mark setup done and get out of here. + */ + if (status != MSG_SETUP_SUCCESS && + !DPM_CHK_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE)) { + if (enter_mode_requested) { + /* + * TODO(b/168030639): Notify the AP that mode entry + * failed. + */ + CPRINTS("C%d: No supported alt mode discovered", port); + } + /* + * If the AP did not request mode entry, it may do so in the + * future, but the DPM is done trying for now. + */ + dpm_set_mode_entry_done(port); + return; + } + + if (status != MSG_SETUP_SUCCESS) { + dpm_set_mode_entry_done(port); + CPRINTS("C%d: Couldn't construct alt mode VDM", port); + return; + } + + /* + * 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, tx_type, vdm, vdo_count)) { + dpm_set_mode_entry_done(port); + return; + } + + pd_dpm_request(port, DPM_REQUEST_VDM); +} + +static void dpm_attempt_mode_exit(int port) +{ + uint32_t vdm[VDO_MAX_SIZE]; + int vdo_count = ARRAY_SIZE(vdm); + enum dpm_msg_setup_status status = MSG_SETUP_ERROR; + enum tcpci_msg_type tx_type = TCPCI_MSG_SOP; + + /* First, try Data Reset. If Data Reset completes, all the alt mode + * state checked below will reset to its inactive state. If Data Reset + * is not supported, exit active modes individually. + */ + if (IS_ENABLED(CONFIG_USB_PD_DATA_RESET_MSG)) { + if (!DPM_CHK_FLAG(port, DPM_FLAG_DATA_RESET_REQUESTED) && + !DPM_CHK_FLAG(port, DPM_FLAG_DATA_RESET_DONE)) { + pd_dpm_request(port, DPM_REQUEST_DATA_RESET); + DPM_SET_FLAG(port, DPM_FLAG_DATA_RESET_REQUESTED); + return; + } else if (!DPM_CHK_FLAG(port, DPM_FLAG_DATA_RESET_DONE)) { + return; + } + } + + /* TODO(b/209625351): Data Reset is the only real way to exit from USB4 + * mode. If that failed, the TCPM shouldn't try anything else. + */ + if (IS_ENABLED(CONFIG_USB_PD_USB4) && enter_usb_entry_is_done(port)) { + CPRINTS("C%d: USB4 teardown", port); + usb4_exit_mode_request(port); + } + + /* + * If muxes are still settling, then wait on our next VDM. We must + * ensure we correctly sequence actions such as USB safe state with TBT + * or DP mode exit. + */ + if (IS_ENABLED(CONFIG_USBC_SS_MUX) && !usb_mux_set_completed(port)) + return; + + 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. + */ + CPRINTS("C%d: TBT teardown", port); + tbt_exit_mode_request(port); + status = tbt_setup_next_vdm(port, &vdo_count, vdm, &tx_type); + } else if (dp_is_active(port)) { + CPRINTS("C%d: DP teardown", port); + status = dp_setup_next_vdm(port, &vdo_count, vdm); + } else { + /* Clear exit mode request */ + dpm_clear_mode_exit_request(port); + return; + } + + /* This covers error, wait mux, and unsupported cases */ + if (status != MSG_SETUP_SUCCESS) + return; + + if (!pd_setup_vdm_request(port, tx_type, vdm, vdo_count)) { + dpm_clear_mode_exit_request(port); + return; + } + + pd_dpm_request(port, DPM_REQUEST_VDM); +} + static void dpm_send_req_vdm(int port) { /* Set up VDM REQ msg that was passed in previously */ @@ -468,6 +640,24 @@ static void dpm_run_pd_button_sm(int port) DPM_CLR_FLAG(port, DPM_FLAG_PD_BUTTON_RELEASED); } +void dpm_run(int port) +{ + if (pd_get_data_role(port) == PD_ROLE_DFP) { + /* Run DFP related DPM requests */ + if (DPM_CHK_FLAG(port, DPM_FLAG_EXIT_REQUEST)) + dpm_attempt_mode_exit(port); + else if (!DPM_CHK_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE)) + dpm_attempt_mode_entry(port); + + /* Run USB PD Power button state machine */ + dpm_run_pd_button_sm(port); + } + + /* Run any VDM REQ messages */ + if (DPM_CHK_FLAG(port, DPM_FLAG_SEND_VDM_REQ)) + dpm_send_req_vdm(port); +} + /* * Source-out policy variables and APIs * @@ -1009,375 +1199,3 @@ uint8_t pd_get_bist_share_mode(void) { return bist_shared_mode_enabled; } - -/* - * Requests that the PE send one VDM, whichever is next in the mode entry - * sequence. This only happens if preconditions for mode entry are met. If - * CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY is enabled, this function waits for the - * AP to direct mode entry. - * - * Returns true when the DPM state is changed in this function. - */ -static bool dpm_dfp_enter_mode_msg(int port) -{ - int vdo_count = 0; - uint32_t vdm[VDO_MAX_SIZE]; - enum tcpci_msg_type tx_type = TCPCI_MSG_SOP; - bool enter_mode_requested = - IS_ENABLED(CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY) ? false : true; - enum dpm_msg_setup_status status = MSG_SETUP_UNSUPPORTED; - -#ifdef CONFIG_AP_POWER_CONTROL - /* - * Do not try to enter mode while CPU is off. - * CPU transitions (e.g b/158634281) can occur during the discovery - * phase or during enter/exit negotiations, and the state - * of the modes can get out of sync, causing the attempt to - * enter the mode to fail prematurely. - */ - if (!chipset_in_state(CHIPSET_STATE_ANY_SUSPEND | CHIPSET_STATE_ON)) - return false; -#endif - /* - * If discovery has not occurred for modes, do not attempt to switch - * to alt mode. - */ - if (pd_get_svids_discovery(port, TCPCI_MSG_SOP) != PD_DISC_COMPLETE || - pd_get_modes_discovery(port, TCPCI_MSG_SOP) != PD_DISC_COMPLETE) - return false; - - if (dp_entry_is_done(port) || - (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) && - tbt_entry_is_done(port)) || - (IS_ENABLED(CONFIG_USB_PD_USB4) && enter_usb_entry_is_done(port))) { - dpm_set_mode_entry_done(port); - return false; - } - - /* - * If AP mode entry is enabled, and a Data Reset has not been done, then - * first request Data Reset prior to attempting to enter any modes. - */ - if (IS_ENABLED(CONFIG_USB_PD_REQUIRE_AP_MODE_ENTRY) && - IS_ENABLED(CONFIG_USB_PD_DATA_RESET_MSG) && - DPM_CHK_FLAG(port, DPM_FLAG_ENTER_ANY) && - !DPM_CHK_FLAG(port, DPM_FLAG_DATA_RESET_DONE)) { - set_state_dpm(port, DPM_DATA_RESET); - return true; - } - - /* Check if port, port partner and cable support USB4. */ - if (IS_ENABLED(CONFIG_USB_PD_USB4) && board_is_tbt_usb4_port(port) && - enter_usb_port_partner_is_capable(port) && - enter_usb_cable_is_capable(port) && - dpm_mode_entry_requested(port, TYPEC_MODE_USB4)) { - /* - * For certain cables, enter Thunderbolt alt mode with the - * cable and USB4 mode with the port partner. - */ - if (tbt_cable_entry_required_for_usb4(port)) { - vdo_count = ARRAY_SIZE(vdm); - status = tbt_setup_next_vdm(port, &vdo_count, vdm, - &tx_type); - } else { - pd_dpm_request(port, DPM_REQUEST_ENTER_USB); - return false; - } - } - - /* If not, check if they support Thunderbolt alt mode. */ - if (IS_ENABLED(CONFIG_USB_PD_TBT_COMPAT_MODE) && - board_is_tbt_usb4_port(port) && - pd_is_mode_discovered_for_svid(port, TCPCI_MSG_SOP, - USB_VID_INTEL) && - dpm_mode_entry_requested(port, TYPEC_MODE_TBT)) { - enter_mode_requested = true; - vdo_count = ARRAY_SIZE(vdm); - status = tbt_setup_next_vdm(port, &vdo_count, vdm, &tx_type); - } - - /* If not, check if they support DisplayPort alt mode. */ - if (status == MSG_SETUP_UNSUPPORTED && - !DPM_CHK_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE) && - pd_is_mode_discovered_for_svid(port, TCPCI_MSG_SOP, - USB_SID_DISPLAYPORT) && - dpm_mode_entry_requested(port, TYPEC_MODE_DP)) { - enter_mode_requested = true; - vdo_count = ARRAY_SIZE(vdm); - status = dp_setup_next_vdm(port, &vdo_count, vdm); - } - - /* Not ready to send a VDM, check again next cycle */ - if (status == MSG_SETUP_MUX_WAIT) - return false; - - /* - * If the PE didn't discover any supported (requested) alternate mode, - * just mark setup done and get out of here. - */ - if (status != MSG_SETUP_SUCCESS && - !DPM_CHK_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE)) { - if (enter_mode_requested) { - /* - * TODO(b/168030639): Notify the AP that mode entry - * failed. - */ - CPRINTS("C%d: No supported alt mode discovered", port); - } - /* - * If the AP did not request mode entry, it may do so in the - * future, but the DPM is done trying for now. - */ - dpm_set_mode_entry_done(port); - return false; - } - - if (status != MSG_SETUP_SUCCESS) { - dpm_set_mode_entry_done(port); - CPRINTS("C%d: Couldn't construct alt mode VDM", port); - return false; - } - - /* - * 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, tx_type, vdm, vdo_count)) { - dpm_set_mode_entry_done(port); - return false; - } - - /* Wait for PE to handle VDM request */ - pd_dpm_request(port, DPM_REQUEST_VDM); - set_state_dpm(port, DPM_WAITING); - - return true; -} - -/* - * Checks to see if either USB4 or ALT-DP/TBT modes need to be exited. If the - * DPM is requesting the PE to send an exit message, then this function will - * return true to indicate that the DPM state has been changed. - */ -static bool dpm_dfp_exit_mode_msg(int port) -{ - uint32_t vdm[VDO_MAX_SIZE]; - int vdo_count = ARRAY_SIZE(vdm); - enum dpm_msg_setup_status status = MSG_SETUP_ERROR; - enum tcpci_msg_type tx_type = TCPCI_MSG_SOP; - - /* First, try Data Reset. If Data Reset completes, all the alt mode - * state checked below will reset to its inactive state. If Data Reset - * is not supported, exit active modes individually. - */ - if (IS_ENABLED(CONFIG_USB_PD_DATA_RESET_MSG) && - !DPM_CHK_FLAG(port, DPM_FLAG_DATA_RESET_DONE)) { - set_state_dpm(port, DPM_DATA_RESET); - return true; - } - - /* TODO(b/209625351): Data Reset is the only real way to exit from USB4 - * mode. If that failed, the TCPM shouldn't try anything else. - */ - if (IS_ENABLED(CONFIG_USB_PD_USB4) && enter_usb_entry_is_done(port)) { - CPRINTS("C%d: USB4 teardown", port); - usb4_exit_mode_request(port); - } - - 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. - */ - CPRINTS("C%d: TBT teardown", port); - tbt_exit_mode_request(port); - status = tbt_setup_next_vdm(port, &vdo_count, vdm, &tx_type); - } else if (dp_is_active(port)) { - CPRINTS("C%d: DP teardown", port); - status = dp_setup_next_vdm(port, &vdo_count, vdm); - } else { - /* Clear exit mode request */ - dpm_clear_mode_exit_request(port); - return false; - } - - /* This covers error, wait mux, and unsupported cases */ - if (status != MSG_SETUP_SUCCESS) - return false; - - if (!pd_setup_vdm_request(port, tx_type, vdm, vdo_count)) { - dpm_clear_mode_exit_request(port); - return false; - } - - pd_dpm_request(port, DPM_REQUEST_VDM); - set_state_dpm(port, DPM_WAITING); - - return true; -} - -void dpm_run(int port, int evt, int en) -{ - switch (local_state[port]) { - case SM_PAUSED: - if (!en) - break; - __fallthrough; - case SM_INIT: - dpm_init(port); - local_state[port] = SM_RUN; - __fallthrough; - case SM_RUN: - if (!en) { - local_state[port] = SM_PAUSED; - /* - * While we are paused, exit all states and wait until - * initialized again. - */ - set_state(port, &dpm[port].ctx, NULL); - break; - } - - /* Run state machine */ - run_state(port, &dpm[port].ctx); - - break; - } -} - -/* - * DPM_WAITING - */ -static void dpm_waiting_entry(const int port) -{ - DPM_CLR_FLAG(port, DPM_FLAG_PE_READY); - print_current_state(port); -} - -static void dpm_waiting_run(const int port) -{ - enum pd_data_role dr = pd_get_data_role(port); - - if (DPM_CHK_FLAG(port, DPM_FLAG_PE_READY)) { - if (dr == PD_ROLE_UFP) { - set_state_dpm(port, DPM_UFP_READY); - } else if (dr == PD_ROLE_DFP) { - set_state_dpm(port, DPM_DFP_READY); - } - } -} - -/* - * DPM_DFP_READY - */ -static void dpm_dfp_ready_entry(const int port) -{ - print_current_state(port); -} - -static void dpm_dfp_ready_run(const int port) -{ - if (!DPM_CHK_FLAG(port, DPM_FLAG_PE_READY)) { - set_state_dpm(port, DPM_WAITING); - return; - } - - /* Run power button state machine */ - dpm_run_pd_button_sm(port); - - /* - * If muxes are still settling, then wait on our next VDM. We must - * ensure we correctly sequence actions such as USB safe state with TBT - * or DP mode exit. - */ - if (IS_ENABLED(CONFIG_USBC_SS_MUX) && !usb_mux_set_completed(port)) - return; - - /* Run DFP related DPM requests */ - if (DPM_CHK_FLAG(port, DPM_FLAG_EXIT_REQUEST)) { - if (dpm_dfp_exit_mode_msg(port)) - return; - } else if (!DPM_CHK_FLAG(port, DPM_FLAG_MODE_ENTRY_DONE)) { - if (dpm_dfp_enter_mode_msg(port)) - return; - } - - /* Run any VDM REQ messages */ - if (DPM_CHK_FLAG(port, DPM_FLAG_SEND_VDM_REQ)) { - dpm_send_req_vdm(port); - set_state_dpm(port, DPM_WAITING); - return; - } -} - -/* - * DPM_UFP_READY - */ -static void dpm_ufp_ready_entry(const int port) -{ - print_current_state(port); -} - -static void dpm_ufp_ready_run(const int port) -{ - if (!DPM_CHK_FLAG(port, DPM_FLAG_PE_READY)) { - set_state_dpm(port, DPM_WAITING); - return; - } - - if (DPM_CHK_FLAG(port, DPM_FLAG_ENTER_ANY)) { - DPM_CLR_FLAG(port, DPM_FLAG_ENTER_DP | DPM_FLAG_ENTER_TBT | - DPM_FLAG_ENTER_USB4); - /* - * TODO(b/168030639): Notify the AP that the - * enter mode request failed. - */ - return; - } - - /* Run any VDM REQ messages */ - if (DPM_CHK_FLAG(port, DPM_FLAG_SEND_VDM_REQ)) { - dpm_send_req_vdm(port); - set_state_dpm(port, DPM_WAITING); - return; - } -} - -/* - * DPM_DATA_RESET - */ -static void dpm_data_reset_entry(const int port) -{ - print_current_state(port); - - pd_dpm_request(port, DPM_REQUEST_DATA_RESET); -} - -static void dpm_data_reset_run(const int port) -{ - /* Wait for Data Reset to Complete */ - if (!DPM_CHK_FLAG(port, DPM_FLAG_DATA_RESET_DONE)) - return; - - set_state_dpm(port, DPM_DFP_READY); -} - -static __const_data const struct usb_state dpm_states[] = { - /* Normal States */ - [DPM_WAITING] = { - .entry = dpm_waiting_entry, - .run = dpm_waiting_run, - }, - [DPM_DFP_READY] = { - .entry = dpm_dfp_ready_entry, - .run = dpm_dfp_ready_run, - }, - [DPM_UFP_READY] = { - .entry = dpm_ufp_ready_entry, - .run = dpm_ufp_ready_run, - }, - [DPM_DATA_RESET] = { - .entry = dpm_data_reset_entry, - .run = dpm_data_reset_run, - }, -}; |