summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/usbc/usb_pe_drp_sm.c17
-rw-r--r--common/usbc/usb_tc_drp_acc_trysrc_sm.c147
-rw-r--r--include/usb_tc_sm.h10
-rw-r--r--test/fake_usbc.c3
4 files changed, 88 insertions, 89 deletions
diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c
index 1bc1eeeb60..5a7f008963 100644
--- a/common/usbc/usb_pe_drp_sm.c
+++ b/common/usbc/usb_pe_drp_sm.c
@@ -2183,12 +2183,6 @@ static void pe_src_transition_to_default_run(int port)
}
}
-static void pe_src_transition_to_default_exit(int port)
-{
- /* TC layer can now go unattached */
- tc_hard_reset_allow_unattach(port);
-}
-
/**
* PE_SNK_Startup State
*/
@@ -2338,16 +2332,6 @@ static void pe_snk_evaluate_capability_entry(int port)
/* Reset Hard Reset counter to zero */
pe[port].hard_reset_counter = 0;
- /*
- * If we were in a Hard Reset condition we have to delay until
- * now to let the TC know we are back to a stable connection.
- * Up to this point we have sent the reset and there is no
- * conversation from the other side until we receive the
- * capabilities message
- * TC layer can now go unattached
- */
- tc_hard_reset_allow_unattach(port);
-
/* Set to highest revision supported by both ports. */
prl_set_rev(port, TCPC_TX_SOP,
MIN(PD_REVISION, PD_HEADER_REV(rx_emsg[port].header)));
@@ -5634,7 +5618,6 @@ static const struct usb_state pe_states[] = {
[PE_SRC_TRANSITION_TO_DEFAULT] = {
.entry = pe_src_transition_to_default_entry,
.run = pe_src_transition_to_default_run,
- .exit = pe_src_transition_to_default_exit,
},
[PE_SNK_STARTUP] = {
.entry = pe_snk_startup_entry,
diff --git a/common/usbc/usb_tc_drp_acc_trysrc_sm.c b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
index bf918ffdde..51207a9acb 100644
--- a/common/usbc/usb_tc_drp_acc_trysrc_sm.c
+++ b/common/usbc/usb_tc_drp_acc_trysrc_sm.c
@@ -86,29 +86,24 @@
#define TC_FLAGS_PARTNER_PD_CAPABLE BIT(15)
/* Flag to note hard reset has been requested */
#define TC_FLAGS_HARD_RESET_REQUESTED BIT(16)
-/*
- * Flag to note hard reset has been performed and we can't go to unattached
- * until we have a source-sink connection again
- */
-#define TC_FLAGS_HARD_RESET_NO_UNATTACH BIT(17)
/* Flag to note port partner is USB comms capable */
-#define TC_FLAGS_PARTNER_USB_COMM BIT(18)
+#define TC_FLAGS_PARTNER_USB_COMM BIT(17)
/* Flag to note we are currently performing PR Swap */
-#define TC_FLAGS_PR_SWAP_IN_PROGRESS BIT(19)
+#define TC_FLAGS_PR_SWAP_IN_PROGRESS BIT(18)
/* Flag to note we need to perform PR Swap */
-#define TC_FLAGS_DO_PR_SWAP BIT(20)
+#define TC_FLAGS_DO_PR_SWAP BIT(19)
/* Flag to note we are performing Discover Identity */
-#define TC_FLAGS_DISC_IDENT_IN_PROGRESS BIT(21)
+#define TC_FLAGS_DISC_IDENT_IN_PROGRESS BIT(20)
/* Flag to note we should check for connection */
-#define TC_FLAGS_CHECK_CONNECTION BIT(22)
+#define TC_FLAGS_CHECK_CONNECTION BIT(21)
/* Flag to note pd_set_suspend SUSPEND state */
-#define TC_FLAGS_SUSPEND BIT(23)
+#define TC_FLAGS_SUSPEND BIT(22)
/*
* Flag to note TC_ATTACHED_SNK is coming from a warm start through
* tc_state_init and the default data role should not be changed from
* what is currently set
*/
-#define TC_FLAGS_TC_WARM_ATTACHED_SNK BIT(24)
+#define TC_FLAGS_TC_WARM_ATTACHED_SNK BIT(23)
/*
* Clear all flags except TC_FLAGS_LPM_ENGAGED and TC_FLAGS_SUSPEND.
@@ -136,7 +131,6 @@ enum ps_reset_sequence {
PS_STATE0,
PS_STATE1,
PS_STATE2,
- PS_STATE3
};
/* List of all TypeC-level states */
@@ -704,21 +698,6 @@ void tc_hard_reset_request(int port)
task_set_event(PD_PORT_TO_TASK_ID(port), PD_EVENT_SM, 0);
}
-/*
- * Hard Reset happened and this is how the PE will unblock leaving
- * the attached state.
- */
-void tc_hard_reset_allow_unattach(int port)
-{
- /* Only deal with HardReset if we are currently doing HardReset */
- if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET_NO_UNATTACH)) {
- TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET_NO_UNATTACH);
-
- /* Enable AutoDischargeDisconnect */
- tcpm_enable_auto_discharge_disconnect(port, 1);
- }
-}
-
void tc_disc_ident_in_progress(int port)
{
TC_SET_FLAG(port, TC_FLAGS_DISC_IDENT_IN_PROGRESS);
@@ -949,15 +928,17 @@ static bool tc_perform_src_hard_reset(int port)
/* Turn off VCONN */
set_vconn(port, 1);
- tc[port].ps_reset_state = PS_STATE3;
+ tc[port].ps_reset_state = PS_STATE2;
tc[port].timeout = get_time().val +
PD_POWER_SUPPLY_TURN_ON_DELAY;
return false;
case PS_STATE2:
- case PS_STATE3:
/* Tell Policy Engine Hard Reset is complete */
pe_ps_reset_complete(port);
+ /* Enable AutoDischargeDisconnect */
+ tcpm_enable_auto_discharge_disconnect(port, 1);
+
tc[port].ps_reset_state = PS_STATE0;
return true;
}
@@ -969,31 +950,69 @@ static bool tc_perform_src_hard_reset(int port)
*/
return true;
}
-#endif
-static void tc_perform_snk_hard_reset(int port)
+/*
+ * Wait for recovery after a hard reset. Call repeatedly until true is
+ * returned, signaling that the hard reset is complete.
+ */
+static bool tc_perform_snk_hard_reset(int port)
{
- tc_set_data_role(port, PD_ROLE_UFP);
+ switch (tc[port].ps_reset_state) {
+ case PS_STATE0:
+ /* Hard reset sets us back to default data role */
+ tc_set_data_role(port, PD_ROLE_UFP);
- /* Clear the input current limit */
- sink_stop_drawing_current(port);
+ /* Clear the input current limit */
+ sink_stop_drawing_current(port);
- /*
- * When VCONN is supported, the Hard Reset Shall cause
- * the Port with the Rd resistor asserted to turn off
- * VCONN.
- */
+ /*
+ * When VCONN is supported, the Hard Reset Shall cause
+ * the Port with the Rd resistor asserted to turn off
+ * VCONN.
+ */
#ifdef CONFIG_USBC_VCONN
- if (TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON))
- set_vconn(port, 0);
+ if (TC_CHK_FLAG(port, TC_FLAGS_VCONN_ON))
+ set_vconn(port, 0);
#endif
+ /* Wait tSafe0V + tSrcRecover, then check for Vbus presence */
+ tc[port].ps_reset_state = PS_STATE1;
+ tc[port].timeout = get_time().val + PD_T_SAFE_0V +
+ PD_T_SRC_RECOVER_MAX;
+ return false;
+ case PS_STATE1:
+ if (get_time().val < tc[port].timeout)
+ return false;
- /*
- * Inform policy engine that power supply
- * reset is complete
- */
- pe_ps_reset_complete(port);
+ /* Watch for Vbus to return */
+ tc[port].ps_reset_state = PS_STATE2;
+ tc[port].timeout = get_time().val + PD_T_SRC_TURN_ON;
+ return false;
+ case PS_STATE2:
+ if (pd_is_vbus_present(port)) {
+ /*
+ * Inform policy engine that power supply
+ * reset is complete
+ */
+ tc[port].ps_reset_state = PS_STATE0;
+ pe_ps_reset_complete(port);
+
+ /* Enable AutoDischargeDisconnect */
+ tcpm_enable_auto_discharge_disconnect(port, 1);
+ return true;
+ }
+ /*
+ * If Vbus isn't back after wait + tSrcTurnOn, go unattached
+ */
+ if (get_time().val > tc[port].timeout) {
+ tc[port].ps_reset_state = PS_STATE0;
+ set_state_tc(port, TC_UNATTACHED_SNK);
+ return true;
+ }
+ }
+
+ return false;
}
+#endif /* CONFIG_USB_PE_SM */
void tc_start_error_recovery(int port)
{
@@ -1935,20 +1954,23 @@ static void tc_attached_snk_run(const int port)
* Perform Hard Reset
*/
if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED)) {
- TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED);
- TC_SET_FLAG(port, TC_FLAGS_HARD_RESET_NO_UNATTACH);
- tc_perform_snk_hard_reset(port);
+ /*
+ * Wait to clear the hard reset request until Vbus has returned
+ * to default (or, if it didn't return, we transition to
+ * unattached)
+ */
+ if (tc_perform_snk_hard_reset(port))
+ TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED);
+
+ return;
}
/*
* The sink will be powered off during a power role swap but we don't
* want to trigger a disconnect.
- * If we are working on a Hard Reset we have to remain attached
- * even when vbus drops.
*/
if (!TC_CHK_FLAG(port, TC_FLAGS_POWER_OFF_SNK) &&
- !TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS) &&
- !TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET_NO_UNATTACH)) {
+ !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))
@@ -2311,14 +2333,22 @@ static void tc_dbg_acc_snk_run(const int port)
return;
}
+#ifdef CONFIG_USB_PE_SM
/*
* Perform Hard Reset
*/
if (TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED)) {
- TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED);
- TC_SET_FLAG(port, TC_FLAGS_HARD_RESET_NO_UNATTACH);
- tc_perform_snk_hard_reset(port);
+ /*
+ * Wait to clear the hard reset request until Vbus has returned
+ * to default (or, if it didn't return, we transition to
+ * unattached)
+ */
+ if (tc_perform_snk_hard_reset(port))
+ TC_CLR_FLAG(port, TC_FLAGS_HARD_RESET_REQUESTED);
+
+ return;
}
+#endif
/*
* The sink will be powered off during a power role swap but we
@@ -2327,8 +2357,7 @@ static void tc_dbg_acc_snk_run(const int port)
* even when vbus drops.
*/
if (!TC_CHK_FLAG(port, TC_FLAGS_POWER_OFF_SNK) &&
- !TC_CHK_FLAG(port, TC_FLAGS_PR_SWAP_IN_PROGRESS) &&
- !TC_CHK_FLAG(port, TC_FLAGS_HARD_RESET_NO_UNATTACH)) {
+ !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))
diff --git a/include/usb_tc_sm.h b/include/usb_tc_sm.h
index b6ed917d4d..293ed55a10 100644
--- a/include/usb_tc_sm.h
+++ b/include/usb_tc_sm.h
@@ -322,16 +322,6 @@ void tc_start_error_recovery(int port);
void tc_hard_reset_request(int port);
/**
- * Hard Reset was sent and we are required to remain attached until we have
- * restored our connection for the TypeC port.
- * A call to tc_hard_reset_allow_unattach will allow the connection to go
- * to an unattached state
- *
- * @param port USB-C port number
- */
-void tc_hard_reset_allow_unattach(int port);
-
-/**
* Hard Reset is complete for the TypeC port
*
* @param port USB-C port number
diff --git a/test/fake_usbc.c b/test/fake_usbc.c
index 731e15c3de..13a1945a0a 100644
--- a/test/fake_usbc.c
+++ b/test/fake_usbc.c
@@ -87,9 +87,6 @@ int tc_is_vconn_src(int port)
void tc_hard_reset_request(int port)
{}
-void tc_hard_reset_allow_unattach(int port)
-{}
-
void tc_hard_reset_complete(int port)
{}