diff options
author | Diana Z <dzigterman@chromium.org> | 2020-03-02 16:30:50 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-03-06 23:30:58 +0000 |
commit | 7f8843dfaa31f3748ba4c5c8be052e2ecdc79f04 (patch) | |
tree | 275148aa20a3af2d16ecd4466e235fa6a0471d5e | |
parent | 1fdc50545f63390ed5924f584130f8661b3f2529 (diff) | |
download | chrome-ec-7f8843dfaa31f3748ba4c5c8be052e2ecdc79f04.tar.gz |
TCPMv2: Probe cable identity from Ready states
Cable identity may be probed from the SRC_Ready and SNK_Ready states
when a port is:
- Vconn source
- DFP (for PD 2.0)
This change adds probing to the ready states in these conditions.
Additionally, it down-revs the cable revision when sinking and the port
partner is PD 2.0.
BRANCH=None
BUG=b:148834626
TEST=On kindred, verified:
1. When sourcing:
a. partner with no e-marker is probed no more than 20
times between discovery probing and ready
b. cable which was not probed in discovery is probed in ready
2. When sinking:
a. no probing when partner does not allow us to Vconn source
b. probing takes place once chromebook is DFP/Vconn source
with PD 2.0 partner
Signed-off-by: Diana Z <dzigterman@chromium.org>
Change-Id: I27da70e324d617ad4d30285554a8cd3c0e5db3e5
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2084013
Reviewed-by: Jett Rink <jettrink@chromium.org>
-rw-r--r-- | common/usbc/usb_pe_drp_sm.c | 51 |
1 files changed, 50 insertions, 1 deletions
diff --git a/common/usbc/usb_pe_drp_sm.c b/common/usbc/usb_pe_drp_sm.c index f9647f5715..d1e1b6bc56 100644 --- a/common/usbc/usb_pe_drp_sm.c +++ b/common/usbc/usb_pe_drp_sm.c @@ -653,6 +653,33 @@ static void pe_invalidate_explicit_contract(int port) PE_CLR_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT); } +/* + * Determine if this port may communicate with the cable plug. + * + * In both PD 2.0 and 3.0 (2.5.4 SOP'/SOP'' Communication with Cable Plugs): + * + * When no Contract or an Implicit Contract is in place (e.g. after a Power Role + * Swap or Fast Role Swap) only the Source port that is supplying Vconn is + * allowed to send packets to a Cable Plug + * + * When in an explicit contract, PD 3.0 requires that a port be Vconn source to + * communicate with the cable. PD 2.0 requires that a port be DFP to + * communicate with the cable plug, with an implication that it must be Vconn + * source as well (6.3.11 VCONN_Swap Message). + */ +static bool pe_can_send_sop_prime(int port) +{ + if (PE_CHK_FLAG(port, PE_FLAGS_EXPLICIT_CONTRACT)) + if (prl_get_rev(port, TCPC_TX_SOP) == PD_REV20) + return tc_is_vconn_src(port) && + pe[port].data_role == PD_ROLE_DFP; + else + return tc_is_vconn_src(port); + else + return tc_is_vconn_src(port) && + pe[port].power_role == PD_ROLE_SOURCE; +} + void pe_report_error(int port, enum pe_error e) { /* This should only be called from the PD task */ @@ -1226,7 +1253,8 @@ static void pe_src_discovery_run(int port) * requests properly. */ if (pe[port].cable.discovery == PD_DISC_NEEDED && - get_time().val > pe[port].discover_port_identity_timer) { + get_time().val > pe[port].discover_port_identity_timer && + pe_can_send_sop_prime(port)) { set_state_pe(port, PE_VDM_IDENTITY_REQUEST_CBL); return; } @@ -1559,6 +1587,13 @@ static void pe_src_ready_run(int port) PE_CLR_FLAG(port, PE_FLAGS_FIRST_MSG); pe[port].wait_and_add_jitter_timer = TIMER_DISABLED; + if (pe[port].cable.discovery == PD_DISC_NEEDED && + get_time().val > pe[port].discover_port_identity_timer && + pe_can_send_sop_prime(port)) { + set_state_pe(port, PE_VDM_IDENTITY_REQUEST_CBL); + return; + } + /* * Start Port Discovery when: * 1) The DiscoverIdentityTimer times out. @@ -2012,6 +2047,13 @@ static void pe_snk_evaluate_capability_entry(int port) prl_set_rev(port, TCPC_TX_SOP, (PD_HEADER_REV(header) > PD_REV30) ? PD_REV30 : PD_HEADER_REV(header)); + /* + * If port partner runs PD 2.0, cable communication must + * also be PD 2.0 + */ + if (prl_get_rev(port, TCPC_TX_SOP) == PD_REV20) + prl_set_rev(port, TCPC_TX_SOP_PRIME, PD_REV20); + pe[port].src_cap_cnt = num; for (i = 0; i < num; i++) @@ -2282,6 +2324,13 @@ static void pe_snk_ready_run(int port) return; } + if (pe[port].cable.discovery == PD_DISC_NEEDED && + get_time().val > pe[port].discover_port_identity_timer && + pe_can_send_sop_prime(port)) { + set_state_pe(port, PE_VDM_IDENTITY_REQUEST_CBL); + return; + } + /* * Start Port Discovery when: * 1) The PortDiscoverIdentityTimer times out. |