summaryrefslogtreecommitdiff
path: root/common/usb_pd_protocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/usb_pd_protocol.c')
-rw-r--r--common/usb_pd_protocol.c69
1 files changed, 49 insertions, 20 deletions
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 53b06b800e..72c88c10d4 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -184,6 +184,7 @@ static struct pd_protocol {
int prev_request_mv;
/* Time for Try.SRC states */
uint64_t try_src_marker;
+ uint64_t try_timeout;
#endif
#ifdef CONFIG_USB_PD_TCPC_LOW_POWER
@@ -2891,32 +2892,58 @@ void pd_task(void *u)
pd[port].cc_state = PD_CC_NONE;
set_state(port,
PD_STATE_SRC_DISCONNECTED_DEBOUNCE);
+ break;
}
#if defined(CONFIG_USB_PD_DUAL_ROLE)
+ now = get_time();
/*
- * Try.SRC state is embedded here. Wait for SNK
- * detect, or if timer expires, transition to
- * SNK_DISCONNETED.
- *
- * If Try.SRC state is not active, then this block
- * handles the normal DRP toggle from SRC->SNK
+ * Try.SRC state is embedded here. The port
+ * shall transition to TryWait.SNK after
+ * tDRPTry (PD_T_DRP_TRY) and Vbus is within
+ * vSafe0V, or after tTryTimeout
+ * (PD_T_TRY_TIMEOUT). Otherwise we should stay
+ * within Try.SRC (break).
*/
- else if ((pd[port].flags & PD_FLAGS_TRY_SRC &&
- get_time().val >= pd[port].try_src_marker) ||
- (!(pd[port].flags & PD_FLAGS_TRY_SRC) &&
- drp_state[port] != PD_DRP_FORCE_SOURCE &&
- drp_state[port] != PD_DRP_FREEZE &&
- get_time().val >= next_role_swap)) {
- pd_set_power_role(port, PD_ROLE_SINK);
+ if (pd[port].flags & PD_FLAGS_TRY_SRC) {
+ if (now.val < pd[port].try_src_marker) {
+ break;
+ } else if (now.val < pd[port].try_timeout) {
+ if (pd_is_vbus_present(port))
+ break;
+ }
+
+ /*
+ * Transition to TryWait.SNK now, so set
+ * state and update src marker time.
+ */
set_state(port, PD_STATE_SNK_DISCONNECTED);
+ pd_set_power_role(port, PD_ROLE_SINK);
tcpm_set_cc(port, TYPEC_CC_RD);
- next_role_swap = get_time().val + PD_T_DRP_SNK;
- pd[port].try_src_marker = get_time().val
- + PD_T_DEBOUNCE;
-
- /* Swap states quickly */
- timeout = 2*MSEC;
+ pd[port].try_src_marker =
+ get_time().val + PD_T_DEBOUNCE;
+ timeout = 2 * MSEC;
+ break;
}
+
+ /*
+ * If Try.SRC state is not active, then handle
+ * the normal DRP toggle from SRC->SNK.
+ */
+ if (now.val < next_role_swap ||
+ drp_state[port] == PD_DRP_FORCE_SOURCE ||
+ drp_state[port] == PD_DRP_FREEZE)
+ break;
+
+ /*
+ * Transition to SNK now, so set state and
+ * update next role swap time.
+ */
+ set_state(port, PD_STATE_SNK_DISCONNECTED);
+ pd_set_power_role(port, PD_ROLE_SINK);
+ tcpm_set_cc(port, TYPEC_CC_RD);
+ next_role_swap = get_time().val + PD_T_DRP_SNK;
+ /* Swap states quickly */
+ timeout = 2 * MSEC;
#endif
break;
case PD_STATE_SRC_DISCONNECTED_DEBOUNCE:
@@ -3466,7 +3493,9 @@ void pd_task(void *u)
* then force attempt to connect as source.
*/
pd[port].try_src_marker = get_time().val
- + PD_T_TRY_SRC;
+ + PD_T_DRP_TRY;
+ pd[port].try_timeout = get_time().val
+ + PD_T_TRY_TIMEOUT;
/* Swap roles to source */
pd_set_power_role(port, PD_ROLE_SOURCE);
tcpm_set_cc(port, TYPEC_CC_RP);