summaryrefslogtreecommitdiff
path: root/common/usbc/usb_pd_dpm.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/usbc/usb_pd_dpm.c')
-rw-r--r--common/usbc/usb_pd_dpm.c690
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,
- },
-};