From 01d8a87b39171095c8cf34ad28e27ba67aa99266 Mon Sep 17 00:00:00 2001 From: Ruibin Chang Date: Fri, 21 Dec 2018 10:26:54 +0800 Subject: common/usb_pd_protocol: Try.SRC to TryWait.SNK timeout The port shall transition to TryWait.SNK after tDRPTry (75~150ms) and the SRC.Rd state has not been detected and Vbus is within vSafe0V, or after tTryTimeout(550~1100ms) and the SRC.Rd state has not been detected. This define in USB Type-C 1.3 spec section 4.5.2.2.10.2. BRANCH=None BUG=None TEST=GRL USBPD test Change-Id: I35be7acf24eb360232b1f22a43abb8c1a1dcde99 Signed-off-by: Ruibin Chang Reviewed-on: https://chromium-review.googlesource.com/1381592 Commit-Ready: ChromeOS CL Exonerator Bot Reviewed-by: Daisuke Nojiri Reviewed-by: Jett Rink Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1692379 Commit-Queue: Zhuohao Lee Tested-by: Zhuohao Lee --- common/usb_pd_protocol.c | 69 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 20 deletions(-) (limited to 'common') diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index c48e998a43..82141d1cf9 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 @@ -2877,32 +2878,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: @@ -3452,7 +3479,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); -- cgit v1.2.1