summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiana Z <dzigterman@chromium.org>2020-05-14 09:38:50 -0600
committerCommit Bot <commit-bot@chromium.org>2020-05-16 00:15:21 +0000
commit2afbf01e37f4937905b28586a7bf55b1822c6f68 (patch)
tree7f1291cda176eea192a92e3a4edc0aa963eefcc2
parenta8638087604a975980cb0379558f4f80b8d33eea (diff)
downloadchrome-ec-2afbf01e37f4937905b28586a7bf55b1822c6f68.tar.gz
TCPMv2: Move sink hard reset recovery into TC
The PD spec requires that PE_SNK_Transition_to_default exits when the sink has reached the default level. Change how the TC handles sink hard resets to wait on notifying the PE hard reset is complete until Vbus has returned. BRANCH=None BUG=b:155923935,b:153593929 TEST=on kindred with TCPMv2, ensure: - port goes unattached after removing suzy-q - hard reset as source succeeds, gets back to SRC_Ready - hard reset as sink succeeds, no extra hard resets sent while source is recovering Signed-off-by: Diana Z <dzigterman@chromium.org> Change-Id: I60427204380067fc5ee36432eab0146a9ab0687b Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2202077 Tested-by: Denis Brockus <dbrockus@chromium.org> Reviewed-by: Denis Brockus <dbrockus@chromium.org> Commit-Queue: Denis Brockus <dbrockus@chromium.org>
-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)
{}