summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Chao <scott_chao@wistron.corp-partner.google.com>2023-01-12 16:01:36 +0800
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-01-18 22:56:20 +0000
commitf18eeff0fc684bd4240258b2a35327d66725232b (patch)
treea0af38c5c50639ca05431bf05a48eac6f5fdb1ed
parentbcdc60f600c507d99cab3dc9b98c3b8987b90411 (diff)
downloadchrome-ec-f18eeff0fc684bd4240258b2a35327d66725232b.tar.gz
tcpci: handle tcpc tx discarded event
In Revision 2.0, Version 1.3 USB Type-C® Port Controller Interface Specification 4.7.1. If the transmission was discarded due to an incoming received message, the TCPC sets the TransmitSOP*MessageDiscarded bit in the ALERT register. In the old process, TCPM will always send soft reset if TCPC did not set TransmitSOP*MessageSuccessful. It will cause the pending message be cleared. For example, when TCPC get ATTENTION from USB-C dock and TCPM send GET_SINK_CAP to TCPC at the same time. The TCPC will set TransmitSOP*MessageDiscarded and TCPM will send soft reset and cause TCPM did not get ATTENTION message. BUG=b:265247056 BRANCH=none TEST=make sure dock can display. TEST=make buildall TEST=./twister -v -T zephyr/test Change-Id: I2597894c1f7abceea3c352ba1066d270d2d01ba0 Signed-off-by: Scott Chao <scott_chao@wistron.corp-partner.google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4160814 Reviewed-by: Diana Z <dzigterman@chromium.org>
-rw-r--r--driver/tcpm/tcpci.c16
-rw-r--r--zephyr/test/drivers/usb_malfunction_sink/src/usb_malfunction_sink.c61
2 files changed, 70 insertions, 7 deletions
diff --git a/driver/tcpm/tcpci.c b/driver/tcpm/tcpci.c
index 7924f653b7..84fdbe8cbc 100644
--- a/driver/tcpm/tcpci.c
+++ b/driver/tcpm/tcpci.c
@@ -1221,10 +1221,18 @@ void tcpci_tcpc_alert(int port)
* completion events. This will send an event to the PD tasks
* immediately
*/
- if (alert & TCPC_REG_ALERT_TX_COMPLETE)
- pd_transmit_complete(port, alert & TCPC_REG_ALERT_TX_SUCCESS ?
- TCPC_TX_COMPLETE_SUCCESS :
- TCPC_TX_COMPLETE_FAILED);
+ if (alert & TCPC_REG_ALERT_TX_COMPLETE) {
+ int tx_status;
+
+ if (alert & TCPC_REG_ALERT_TX_SUCCESS)
+ tx_status = TCPC_TX_COMPLETE_SUCCESS;
+ else if (alert & TCPC_REG_ALERT_TX_DISCARDED)
+ tx_status = TCPC_TX_COMPLETE_DISCARDED;
+ else
+ tx_status = TCPC_TX_COMPLETE_FAILED;
+
+ pd_transmit_complete(port, tx_status);
+ }
tcpc_get_bist_test_mode(port, &bist_mode);
diff --git a/zephyr/test/drivers/usb_malfunction_sink/src/usb_malfunction_sink.c b/zephyr/test/drivers/usb_malfunction_sink/src/usb_malfunction_sink.c
index fd6cab7bad..dd50f2b35b 100644
--- a/zephyr/test/drivers/usb_malfunction_sink/src/usb_malfunction_sink.c
+++ b/zephyr/test/drivers/usb_malfunction_sink/src/usb_malfunction_sink.c
@@ -248,14 +248,14 @@ ZTEST_F(usb_malfunction_sink, test_ignore_source_cap_and_pd_disable)
struct ec_response_typec_status typec_status;
/*
- * Ignore first SourceCapabilities message and discard others by sending
- * different messages. This will lead to PD disable.
+ * Ignore first SourceCapabilities message and failed others.
+ * This will lead to PD disable.
*/
fixture->actions[0].action_mask = TCPCI_FAULTY_EXT_IGNORE_SRC_CAP;
fixture->actions[0].count = 1;
tcpci_faulty_ext_append_action(&fixture->faulty_snk_ext,
&fixture->actions[0]);
- fixture->actions[1].action_mask = TCPCI_FAULTY_EXT_DISCARD_SRC_CAP;
+ fixture->actions[1].action_mask = TCPCI_FAULTY_EXT_FAIL_SRC_CAP;
fixture->actions[1].count = TCPCI_FAULTY_EXT_INFINITE_ACTION;
tcpci_faulty_ext_append_action(&fixture->faulty_snk_ext,
&fixture->actions[1]);
@@ -270,3 +270,58 @@ ZTEST_F(usb_malfunction_sink, test_ignore_source_cap_and_pd_disable)
zassert_true(typec_status.dev_connected);
zassert_false(typec_status.sop_connected);
}
+
+ZTEST_F(usb_malfunction_sink, test_discard_source_cap)
+{
+ struct tcpci_partner_log_msg *msg;
+ uint16_t header;
+ int msg_cnt = 0;
+
+ /*
+ * Discard SourceCapabilities messages, this will lead to SoftReset.
+ */
+ fixture->actions[0].action_mask = TCPCI_FAULTY_EXT_DISCARD_SRC_CAP;
+ fixture->actions[0].count = TCPCI_FAULTY_EXT_INFINITE_ACTION;
+ tcpci_faulty_ext_append_action(&fixture->faulty_snk_ext,
+ &fixture->actions[0]);
+
+ tcpci_partner_common_enable_pd_logging(&fixture->sink, true);
+ connect_sink_to_port(&fixture->sink, fixture->tcpci_emul,
+ fixture->charger_emul);
+ tcpci_partner_common_enable_pd_logging(&fixture->sink, false);
+
+ /*
+ * Check if SourceCapability message alternate with Accept and
+ * SoftReset.
+ * The sequence will be
+ * TCPM: SourceCapability -> TCPC: Accept -> TCPM: SoftReset ->
+ * TCPC: Accept
+ */
+ SYS_SLIST_FOR_EACH_CONTAINER(&fixture->sink.msg_log, msg, node)
+ {
+ header = sys_get_le16(msg->buf);
+
+ switch (msg_cnt % 4) {
+ case 0:
+ zassert_equal(
+ PD_HEADER_TYPE(header), PD_DATA_SOURCE_CAP,
+ "Expected message %d to be SourceCapabilities, not 0x%x",
+ msg_cnt, PD_HEADER_TYPE(header));
+ break;
+ case 1:
+ case 3:
+ zassert_equal(
+ PD_HEADER_TYPE(header), PD_CTRL_ACCEPT,
+ "Expected message %d to be Accept, not 0x%x",
+ msg_cnt, PD_HEADER_TYPE(header));
+ break;
+ case 2:
+ zassert_equal(
+ PD_HEADER_TYPE(header), PD_CTRL_SOFT_RESET,
+ "Expected message %d to be SoftReset, not 0x%x",
+ msg_cnt, PD_HEADER_TYPE(header));
+ break;
+ }
+ msg_cnt++;
+ }
+}