summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiana Z <dzigterman@chromium.org>2020-03-02 16:30:50 -0700
committerCommit Bot <commit-bot@chromium.org>2020-03-06 23:30:58 +0000
commit7f8843dfaa31f3748ba4c5c8be052e2ecdc79f04 (patch)
tree275148aa20a3af2d16ecd4466e235fa6a0471d5e
parent1fdc50545f63390ed5924f584130f8661b3f2529 (diff)
downloadchrome-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.c51
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.