diff options
author | Scott Collyer <scollyer@google.com> | 2022-11-15 15:11:37 -0800 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-11-29 00:45:31 +0000 |
commit | 6df1ce73533c970762dfef6c878523d01648f846 (patch) | |
tree | 43cb509eb3148b625c219a1a358455847e0e358d | |
parent | 1fc2ef1334bb550a558fedf6d9ed824be3272c41 (diff) | |
download | chrome-ec-6df1ce73533c970762dfef6c878523d01648f846.tar.gz |
zephyr: test: Add tests for USB_Enter/DATA_RESET messages
This CL adds support for USB_Enter and DATA_RESET messages to the
tcpc emmulator. In addition it adds a test suite for USB4 mode.
The usbc_tbt_mode test suite was used as a starting reference.
BUG=b:260095516
BRANCH=none
TEST=manual
twister -c -v -i -s <path>/drivers/drivers.usbc_usb4_mode and
verify that the tests pass.
Signed-off-by: Scott Collyer <scollyer@google.com>
Change-Id: I34e104a1e53b1540b20451fbd0631bbd9d42559b
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4029517
Code-Coverage: Zoss <zoss-cl-coverage@prod.google.com>
Commit-Queue: Scott Collyer <scollyer@chromium.org>
Tested-by: Scott Collyer <scollyer@chromium.org>
Reviewed-by: Abe Levkoy <alevkoy@chromium.org>
-rw-r--r-- | zephyr/emul/tcpc/emul_tcpci_partner_common.c | 36 | ||||
-rw-r--r-- | zephyr/include/emul/tcpc/emul_tcpci_partner_common.h | 2 | ||||
-rw-r--r-- | zephyr/test/drivers/CMakeLists.txt | 1 | ||||
-rw-r--r-- | zephyr/test/drivers/Kconfig | 5 | ||||
-rw-r--r-- | zephyr/test/drivers/testcase.yaml | 4 | ||||
-rw-r--r-- | zephyr/test/drivers/usbc_usb4_mode/CMakeLists.txt | 5 | ||||
-rw-r--r-- | zephyr/test/drivers/usbc_usb4_mode/src/usbc_usb4_mode.c | 269 |
7 files changed, 322 insertions, 0 deletions
diff --git a/zephyr/emul/tcpc/emul_tcpci_partner_common.c b/zephyr/emul/tcpc/emul_tcpci_partner_common.c index cb12d37b63..0473f967dc 100644 --- a/zephyr/emul/tcpc/emul_tcpci_partner_common.c +++ b/zephyr/emul/tcpc/emul_tcpci_partner_common.c @@ -759,6 +759,27 @@ tcpci_partner_common_vdm_handler(struct tcpci_partner_data *data, } static enum tcpci_partner_handler_res +tcpci_partner_enter_usb_handler(struct tcpci_partner_data *data, + const struct tcpci_emul_msg *message) +{ + /* + * Validate received Enter_USB message against EUDO contents in + * tcpci_partner_data. + * + * TODO(b/260095516): This support needs to be expanded to validate the + * message contents, in a bit field basis. Currently, using this field + * as simple ACCEPT/REJECT criteria. If this value is 0 (default case), + * then ACCEPT this message, else reject it. + */ + if (data->enter_usb_accept) + tcpci_partner_send_control_msg(data, PD_CTRL_ACCEPT, 0); + else + tcpci_partner_send_control_msg(data, PD_CTRL_REJECT, 0); + + return TCPCI_PARTNER_COMMON_MSG_HANDLED; +} + +static enum tcpci_partner_handler_res tcpci_partner_common_cable_handler(struct tcpci_partner_data *data, const struct tcpci_emul_msg *message, enum tcpci_msg_type sop_type) @@ -1081,6 +1102,8 @@ tcpci_partner_common_sop_msg_handler(struct tcpci_partner_data *data, switch (PD_HEADER_TYPE(header)) { case PD_DATA_VENDOR_DEF: return tcpci_partner_common_vdm_handler(data, tx_msg); + case PD_DATA_ENTER_USB: + return tcpci_partner_enter_usb_handler(data, tx_msg); default: /* No other common handlers for data messages */ return TCPCI_PARTNER_COMMON_MSG_NOT_HANDLED; @@ -1160,6 +1183,18 @@ tcpci_partner_common_sop_msg_handler(struct tcpci_partner_data *data, tcpci_partner_common_send_soft_reset(data); return TCPCI_PARTNER_COMMON_MSG_HANDLED; + case PD_CTRL_DATA_RESET: + /* + * Send Accept/Reject message + * TODO(b/260095516): To fully exercise this code path, there + * needs to be a mechanism (trigger) to either accept or reject + * this message. + */ + tcpci_partner_send_control_msg(data, PD_CTRL_ACCEPT, 0); + return TCPCI_PARTNER_COMMON_MSG_HANDLED; + case PD_CTRL_DATA_RESET_COMPLETE: + /* There is no expected reply message from the port parter */ + return TCPCI_PARTNER_COMMON_MSG_HANDLED; } return TCPCI_PARTNER_COMMON_MSG_NOT_HANDLED; @@ -1599,6 +1634,7 @@ void tcpci_partner_init(struct tcpci_partner_data *data, enum pd_rev_type rev) data->identity_vdos = 0; data->svids_vdos = 0; data->modes_vdos = 0; + data->enter_usb_accept = false; tcpci_partner_common_clear_ams_ctrl_msg(data); diff --git a/zephyr/include/emul/tcpc/emul_tcpci_partner_common.h b/zephyr/include/emul/tcpc/emul_tcpci_partner_common.h index d0d0a2d183..dd8909c2ca 100644 --- a/zephyr/include/emul/tcpc/emul_tcpci_partner_common.h +++ b/zephyr/include/emul/tcpc/emul_tcpci_partner_common.h @@ -187,6 +187,8 @@ struct tcpci_partner_data { */ bool have_response[PD_BATT_MAX]; } battery_capabilities; + /* Used to control accept/reject for partner port of Enter_USB msg */ + bool enter_usb_accept; /* * Cable which is "plugged in" to this port partner diff --git a/zephyr/test/drivers/CMakeLists.txt b/zephyr/test/drivers/CMakeLists.txt index 3a1390fddf..7c7ff22b31 100644 --- a/zephyr/test/drivers/CMakeLists.txt +++ b/zephyr/test/drivers/CMakeLists.txt @@ -41,6 +41,7 @@ add_subdirectory_ifdef(CONFIG_LINK_TEST_SUITE_USBC_CONSOLE_PD usbc_console_pd) add_subdirectory_ifdef(CONFIG_LINK_TEST_SUITE_USBC_CTVPD usbc_ctvpd) add_subdirectory_ifdef(CONFIG_LINK_TEST_SUITE_USBC_SVDM_DFP_ONLY usbc_svdm_dfp_only) add_subdirectory_ifdef(CONFIG_LINK_TEST_SUITE_USBC_TBT_MODE usbc_tbt_mode) +add_subdirectory_ifdef(CONFIG_LINK_TEST_SUITE_USBC_USB4_MODE usbc_usb4_mode) add_subdirectory_ifdef(CONFIG_LINK_TEST_SUITE_USBC_VCONN_SWAP usbc_vconn_swap) add_subdirectory_ifdef(CONFIG_LINK_TEST_SUITE_USBC_OCP usbc_ocp) add_subdirectory_ifdef(CONFIG_LINK_TEST_SUITE_USBC_PPC usbc_ppc) diff --git a/zephyr/test/drivers/Kconfig b/zephyr/test/drivers/Kconfig index 0994444f23..8cc1131193 100644 --- a/zephyr/test/drivers/Kconfig +++ b/zephyr/test/drivers/Kconfig @@ -118,6 +118,11 @@ config LINK_TEST_SUITE_USBC_SVDM_DFP_ONLY config LINK_TEST_SUITE_USBC_TBT_MODE bool "Link and test the usbc_tbt_mode tests" +config LINK_TEST_SUITE_USBC_USB4_MODE + bool "Link and test the usbc_usb4_mode tests" + help + Include the usbc_usb4 test suite in the binary. + config LINK_TEST_SUITE_USBC_VCONN_SWAP bool "Link and test the usbc_vconn_swap tests" help diff --git a/zephyr/test/drivers/testcase.yaml b/zephyr/test/drivers/testcase.yaml index f74289086a..896562f4f8 100644 --- a/zephyr/test/drivers/testcase.yaml +++ b/zephyr/test/drivers/testcase.yaml @@ -228,6 +228,10 @@ tests: drivers.usbc_tbt_mode: extra_configs: - CONFIG_LINK_TEST_SUITE_USBC_TBT_MODE=y + drivers.usbc_usb4_mode: + extra_configs: + - CONFIG_LINK_TEST_SUITE_USBC_USB4_MODE=y + - CONFIG_PLATFORM_EC_USB_PD_DATA_RESET_MSG=y drivers.usbc_vconn_swap: extra_configs: - CONFIG_LINK_TEST_SUITE_USBC_VCONN_SWAP=y diff --git a/zephyr/test/drivers/usbc_usb4_mode/CMakeLists.txt b/zephyr/test/drivers/usbc_usb4_mode/CMakeLists.txt new file mode 100644 index 0000000000..dcf03ae2f6 --- /dev/null +++ b/zephyr/test/drivers/usbc_usb4_mode/CMakeLists.txt @@ -0,0 +1,5 @@ +# Copyright 2022 The ChromiumOS Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +target_sources(app PRIVATE src/usbc_usb4_mode.c) diff --git a/zephyr/test/drivers/usbc_usb4_mode/src/usbc_usb4_mode.c b/zephyr/test/drivers/usbc_usb4_mode/src/usbc_usb4_mode.c new file mode 100644 index 0000000000..536f41577e --- /dev/null +++ b/zephyr/test/drivers/usbc_usb4_mode/src/usbc_usb4_mode.c @@ -0,0 +1,269 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "ec_commands.h" +#include "ec_tasks.h" +#include "emul/tcpc/emul_tcpci.h" +#include "emul/tcpc/emul_tcpci_partner_snk.h" +#include "host_command.h" +#include "test/drivers/stubs.h" +#include "tcpm/tcpci.h" +#include "test/drivers/utils.h" +#include "test/drivers/test_state.h" +#include "usb_pd_vdo.h" + +#include <zephyr/kernel.h> +#include <zephyr/sys/byteorder.h> +#include <zephyr/ztest.h> + +#include <stdint.h> + +#define TEST_PORT USBC_PORT_C0 +/* Remove polarity for any mux checks */ +#define USB_MUX_CHECK_MASK ~USB_PD_MUX_POLARITY_INVERTED + +struct usbc_usb4_mode_fixture { + const struct emul *tcpci_emul; + const struct emul *charger_emul; + struct tcpci_partner_data partner; + struct tcpci_snk_emul_data snk_ext; +}; + +/* Passive USB4 cable */ +struct tcpci_cable_data passive_usb4 = { + .identity_vdm[VDO_INDEX_HDR] = + VDO(USB_SID_PD, /* structured VDM */ true, + VDO_CMDT(CMDT_RSP_ACK) | CMD_DISCOVER_IDENT), + .identity_vdm[VDO_INDEX_IDH] = VDO_IDH( + /* USB host */ false, /* USB device */ false, IDH_PTYPE_PCABLE, + /* modal operation */ false, USB_VID_GOOGLE), + .identity_vdm[VDO_INDEX_CSTAT] = 0, + .identity_vdm[VDO_INDEX_PRODUCT] = VDO_PRODUCT(0x1234, 0xABCD), + .identity_vdm[VDO_INDEX_PTYPE_CABLE1] = + VDO_REV30_PASSIVE(USB_R30_SS_U40_GEN3, USB_VBUS_CUR_3A, + USB_REV30_LATENCY_1m, USB_REV30_TYPE_C), + .identity_vdos = VDO_INDEX_PTYPE_CABLE1 + 1, + +}; + +static void add_sop_vdm_responses(struct tcpci_partner_data *partner) +{ + /* Add Discover Identity response */ + partner->identity_vdm[VDO_INDEX_HDR] = + VDO(USB_SID_PD, /* structured VDM */ true, + VDO_CMDT(CMDT_RSP_ACK) | CMD_DISCOVER_IDENT); + partner->identity_vdm[VDO_INDEX_IDH] = VDO_IDH_REV30( + /* USB host */ false, /* USB device */ true, + /* ptype_u */ IDH_PTYPE_HUB, /* modal */ false, + /* ptype_d */ IDH_PTYPE_UNDEF, /* ctype */ USB_TYPEC_RECEPTACLE, + USB_VID_GOOGLE); + partner->identity_vdm[VDO_INDEX_CSTAT] = 0; + partner->identity_vdm[VDO_INDEX_PRODUCT] = VDO_PRODUCT(0x1234, 0x5678); + partner->identity_vdm[VDO_INDEX_PTYPE_UFP1_VDO] = VDO_UFP1( + /* capability */ (VDO_UFP1_CAPABILITY_USB20 | + VDO_UFP1_CAPABILITY_USB32 | + VDO_UFP1_CAPABILITY_USB4), + /* ctype */ USB_TYPEC_RECEPTACLE, + /* alt modes */ VDO_UFP1_ALT_MODE_TBT3, + /* speed */ USB_R30_SS_U40_GEN3); + partner->identity_vdm[VDO_INDEX_PTYPE_UFP2_VDO] = 0; + partner->identity_vdos = VDO_INDEX_PTYPE_UFP2_VDO + 1; + + /* Add Discover SVIDs response */ + /* + * TODO(b/260095516): USB4 entry does not depend on the contents of + * Discover SVIDs, but a valid Discover SVID response needs to to exist + * to ensure that discovery completes as that's a dependency in the DPM + * module to attempt either Enter_USB or DATA_RESET. + */ + partner->svids_vdm[VDO_INDEX_HDR] = + VDO(USB_SID_PD, /* structured VDM */ true, + VDO_CMDT(CMDT_RSP_ACK) | CMD_DISCOVER_SVID); + partner->svids_vdm[VDO_INDEX_HDR + 1] = VDO_SVID(USB_VID_INTEL, 0); + partner->svids_vdos = VDO_INDEX_HDR + 2; + + /* Add Discover Modes response */ + /* + * TODO(b/260095516): USB4 entry does not depend on the contents of + * Discover Modes, but a valid Discover Modes response needs to to exist + * to ensure that discovery completes as that's a dependency in the DPM + * module to attempt either Enter_USB or DATA_RESET. + */ + /* Support one mode for TBT (Intel) VID */ + partner->modes_vdm[VDO_INDEX_HDR] = + VDO(USB_VID_INTEL, /* structured VDM */ true, + VDO_CMDT(CMDT_RSP_ACK) | CMD_DISCOVER_MODES); + partner->modes_vdm[VDO_INDEX_HDR + 1] = TBT_ALTERNATE_MODE; + partner->modes_vdos = VDO_INDEX_HDR + 2; +} + +static void verify_cable_found(struct tcpci_cable_data *cable) +{ + uint8_t response_buffer[EC_LPC_HOST_PACKET_SIZE]; + struct ec_response_typec_discovery *discovery = + (struct ec_response_typec_discovery *)response_buffer; + + host_cmd_typec_discovery(TEST_PORT, TYPEC_PARTNER_SOP_PRIME, + response_buffer, sizeof(response_buffer)); + + /* The host command does not count the VDM header in identity_count. */ + zassert_equal(discovery->identity_count, cable->identity_vdos - 1, + "Expected %d identity VDOs, got %d", + cable->identity_vdos - 1, discovery->identity_count); + zassert_mem_equal(discovery->discovery_vdo, cable->identity_vdm + 1, + discovery->identity_count * + sizeof(*discovery->discovery_vdo), + "Discovered SOP' identity ACK did not match"); +} + +static void *usbc_usb4_mode_setup(void) +{ + static struct usbc_usb4_mode_fixture fixture; + struct tcpci_partner_data *partner = &fixture.partner; + struct tcpci_snk_emul_data *snk_ext = &fixture.snk_ext; + + tcpci_partner_init(partner, PD_REV30); + partner->extensions = tcpci_snk_emul_init(snk_ext, partner, NULL); + + /* Get references for the emulators */ + fixture.tcpci_emul = EMUL_DT_GET(DT_NODELABEL(tcpci_emul)); + fixture.charger_emul = EMUL_DT_GET(DT_NODELABEL(isl923x_emul)); + + add_sop_vdm_responses(partner); + /* Note: cable behavior will vary by test case */ + + return &fixture; +} + +static void usbc_usb4_mode_before(void *data) +{ + struct usbc_usb4_mode_fixture *fix = data; + + /* Set chipset to ON, this will set TCPM to DRP */ + test_set_chipset_to_s0(); + + /* TODO(b/214401892): Check why need to give TCPM time to spin */ + k_sleep(K_SECONDS(1)); + + /* Enable message logging after TCPM spin */ + tcpci_partner_common_enable_pd_logging(&fix->partner, true); + + /* Initialize parter port Enter_USB msg accept/reject state */ + fix->partner.enter_usb_accept = false; +} + +static void usbc_usb4_mode_after(void *data) +{ + struct usbc_usb4_mode_fixture *fix = data; + + disconnect_sink_from_port(fix->tcpci_emul); + tcpci_partner_common_enable_pd_logging(&fix->partner, false); + tcpci_partner_common_clear_logged_msgs(&fix->partner); +} + +ZTEST_F(usbc_usb4_mode, verify_discovery) +{ + uint8_t response_buffer[EC_LPC_HOST_PACKET_SIZE]; + struct ec_response_typec_discovery *discovery = + (struct ec_response_typec_discovery *)response_buffer; + + connect_sink_to_port(&fixture->partner, fixture->tcpci_emul, + fixture->charger_emul); + + host_cmd_typec_discovery(TEST_PORT, TYPEC_PARTNER_SOP, response_buffer, + sizeof(response_buffer)); + + /* The host command does not count the VDM header in identity_count. */ + zassert_equal(discovery->identity_count, + fixture->partner.identity_vdos - 1, + "Expected %d identity VDOs, got %d", + fixture->partner.identity_vdos - 1, + discovery->identity_count); + zassert_mem_equal( + discovery->discovery_vdo, fixture->partner.identity_vdm + 1, + discovery->identity_count * sizeof(*discovery->discovery_vdo), + "Discovered SOP identity ACK did not match"); +} + +/* Without an e-marked cable, USB4 mode cannot be entered */ +ZTEST_F(usbc_usb4_mode, verify_usb4_entry_fail) +{ + struct ec_response_typec_status status; + + fixture->partner.cable = NULL; + connect_sink_to_port(&fixture->partner, fixture->tcpci_emul, + fixture->charger_emul); + + status = host_cmd_typec_status(TEST_PORT); + zassert_equal((status.mux_state & USB_MUX_CHECK_MASK), + USB_PD_MUX_USB_ENABLED, "Unexpected starting mux: 0x%02x", + status.mux_state); + + host_cmd_typec_control_enter_mode(TEST_PORT, TYPEC_MODE_USB4); + k_sleep(K_SECONDS(1)); + + /* + * TODO(b/260095516): Notify the AP that the enter mode request + * failed. + */ + + status = host_cmd_typec_status(TEST_PORT); + zassert_equal((status.mux_state & USB_MUX_CHECK_MASK), + USB_PD_MUX_USB_ENABLED, "Failed to see USB still set"); + zassert_not_equal((status.mux_state & USB_MUX_CHECK_MASK), + USB_PD_MUX_USB4_ENABLED, "Unexpected USB4 mode set"); +} + +/* With passive e-marked cable, USB4 mode can be entered on SOP only */ +ZTEST_F(usbc_usb4_mode, verify_usb4_passive_entry_exit) +{ + struct ec_response_typec_status status; + + fixture->partner.cable = &passive_usb4; + connect_sink_to_port(&fixture->partner, fixture->tcpci_emul, + fixture->charger_emul); + + /* Instruct partner port to accept Enter_USB message */ + fixture->partner.enter_usb_accept = true; + + /* Verify that we properly identify a USB4 capable passive cable */ + verify_cable_found(fixture->partner.cable); + + status = host_cmd_typec_status(TEST_PORT); + zassert_equal((status.mux_state & USB_MUX_CHECK_MASK), + USB_PD_MUX_USB_ENABLED, "Unexpected starting mux: 0x%02x", + status.mux_state); + + host_cmd_typec_control_enter_mode(TEST_PORT, TYPEC_MODE_USB4); + k_sleep(K_SECONDS(2)); + + /* + * TODO(b/260095516): Notify the AP that the enter mode request + * succeeded. + */ + + /* Verify we entered USB4 mode */ + status = host_cmd_typec_status(TEST_PORT); + zassert_equal((status.mux_state & USB_MUX_CHECK_MASK), + USB_PD_MUX_USB4_ENABLED, "Failed to see USB4 set"); + + /* Exit modes now */ + host_cmd_typec_control_exit_modes(TEST_PORT); + k_sleep(K_SECONDS(1)); + + /* Verify that USB4 mode was exited by checking current mux state. */ + status = host_cmd_typec_status(TEST_PORT); + zassert_equal((status.mux_state & USB_MUX_CHECK_MASK), + USB_PD_MUX_USB_ENABLED, "Failed to see USB set"); +} + +/* + * TODO(b/260095516): This test suite is only testing the default good case, and + * one error case where the cable doesn't support USB4. This suite needs to be + * expanded to cover cases where the port partner rejects Enter_USB along with + * active cable cases. + */ +ZTEST_SUITE(usbc_usb4_mode, drivers_predicate_post_main, usbc_usb4_mode_setup, + usbc_usb4_mode_before, usbc_usb4_mode_after, NULL); |