diff options
Diffstat (limited to 'zephyr/test/drivers/default/src/integration/usbc/usb_pd_ctrl_msg.c')
-rw-r--r-- | zephyr/test/drivers/default/src/integration/usbc/usb_pd_ctrl_msg.c | 395 |
1 files changed, 395 insertions, 0 deletions
diff --git a/zephyr/test/drivers/default/src/integration/usbc/usb_pd_ctrl_msg.c b/zephyr/test/drivers/default/src/integration/usbc/usb_pd_ctrl_msg.c new file mode 100644 index 0000000000..894deaed13 --- /dev/null +++ b/zephyr/test/drivers/default/src/integration/usbc/usb_pd_ctrl_msg.c @@ -0,0 +1,395 @@ +/* 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 <stdint.h> +#include <zephyr/ztest.h> + +#include "common.h" +#include "ec_tasks.h" +#include "emul/emul_isl923x.h" +#include "emul/tcpc/emul_tcpci_partner_drp.h" +#include "tcpm/tcpci.h" +#include "test/drivers/stubs.h" +#include "test/drivers/test_state.h" +#include "test/drivers/utils.h" +#include "test/usb_pe.h" +#include "usb_pd.h" + +#define TEST_USB_PORT 0 +BUILD_ASSERT(TEST_USB_PORT == USBC_PORT_C0); + +#define TEST_ADDED_PDO PDO_FIXED(10000, 3000, PDO_FIXED_UNCONSTRAINED) + +struct usb_pd_ctrl_msg_test_fixture { + struct tcpci_partner_data partner_emul; + struct tcpci_snk_emul_data snk_ext; + struct tcpci_src_emul_data src_ext; + struct tcpci_drp_emul_data drp_ext; + const struct emul *tcpci_emul; + const struct emul *charger_emul; + enum pd_power_role drp_partner_pd_role; +}; + +struct usb_pd_ctrl_msg_test_sink_fixture { + struct usb_pd_ctrl_msg_test_fixture fixture; +}; + +struct usb_pd_ctrl_msg_test_source_fixture { + struct usb_pd_ctrl_msg_test_fixture fixture; +}; + +static void +tcpci_drp_emul_connect_partner(struct tcpci_partner_data *partner_emul, + const struct emul *tcpci_emul, + const struct emul *charger_emul) +{ + /* + * TODO(b/221439302) Updating the TCPCI emulator registers, updating the + * vbus, as well as alerting should all be a part of the connect + * function. + */ + isl923x_emul_set_adc_vbus(charger_emul, 0); + tcpci_emul_set_reg(tcpci_emul, TCPC_REG_POWER_STATUS, + TCPC_REG_POWER_STATUS_VBUS_DET); + + tcpci_emul_set_reg(tcpci_emul, TCPC_REG_EXT_STATUS, + TCPC_REG_EXT_STATUS_SAFE0V); + + tcpci_tcpc_alert(TEST_USB_PORT); + + zassume_ok(tcpci_partner_connect_to_tcpci(partner_emul, tcpci_emul), + NULL); +} + +static void disconnect_partner(struct usb_pd_ctrl_msg_test_fixture *fixture) +{ + zassume_ok(tcpci_emul_disconnect_partner(fixture->tcpci_emul), NULL); + k_sleep(K_SECONDS(1)); +} + +static void *usb_pd_ctrl_msg_setup_emul(void) +{ + static struct usb_pd_ctrl_msg_test_fixture fixture; + + /* Get references for the emulators */ + fixture.tcpci_emul = EMUL_GET_USBC_BINDING(TEST_USB_PORT, tcpc); + fixture.charger_emul = EMUL_GET_USBC_BINDING(TEST_USB_PORT, chg); + + return &fixture; +} + +static void *usb_pd_ctrl_msg_sink_setup(void) +{ + struct usb_pd_ctrl_msg_test_fixture *fixture = + usb_pd_ctrl_msg_setup_emul(); + + fixture->drp_partner_pd_role = PD_ROLE_SINK; + + return fixture; +} + +static void *usb_pd_ctrl_msg_source_setup(void) +{ + struct usb_pd_ctrl_msg_test_fixture *fixture = + usb_pd_ctrl_msg_setup_emul(); + + fixture->drp_partner_pd_role = PD_ROLE_SOURCE; + + return fixture; +} + +static void usb_pd_ctrl_msg_before(void *data) +{ + struct usb_pd_ctrl_msg_test_fixture *fixture = data; + + set_test_runner_tid(); + + test_set_chipset_to_g3(); + k_sleep(K_SECONDS(1)); + + /* Set chipset to ON, this will set TCPM to DRP */ + test_set_chipset_to_s0(); + + /* TODO(b/214401892): Check why need to give time TCPM to spin */ + k_sleep(K_SECONDS(1)); + + /* Initialized DRP */ + tcpci_partner_init(&fixture->partner_emul, PD_REV20); + fixture->partner_emul.extensions = tcpci_drp_emul_init( + &fixture->drp_ext, &fixture->partner_emul, + fixture->drp_partner_pd_role, + tcpci_src_emul_init(&fixture->src_ext, &fixture->partner_emul, + NULL), + tcpci_snk_emul_init(&fixture->snk_ext, &fixture->partner_emul, + NULL)); + /* Add additional Sink PDO to partner to verify + * PE_DR_SNK_Get_Sink_Cap/PE_SRC_Get_Sink_Cap (these are shared PE + * states) state was reached + */ + fixture->snk_ext.pdo[1] = TEST_ADDED_PDO; + + /* Turn TCPCI rev 2 ON */ + tcpc_config[TEST_USB_PORT].flags |= TCPC_FLAGS_TCPCI_REV2_0; + + tcpci_drp_emul_connect_partner(&fixture->partner_emul, + fixture->tcpci_emul, + fixture->charger_emul); + + k_sleep(K_SECONDS(10)); +} + +static void usb_pd_ctrl_msg_after(void *data) +{ + struct usb_pd_ctrl_msg_test_fixture *fixture = data; + + disconnect_partner(fixture); +} + +/** ZTEST_SUITE to setup DRP partner_emul as SINK */ +ZTEST_SUITE(usb_pd_ctrl_msg_test_sink, drivers_predicate_post_main, + usb_pd_ctrl_msg_sink_setup, usb_pd_ctrl_msg_before, + usb_pd_ctrl_msg_after, NULL); + +/** ZTEST_SUITE to setup DRP partner_emul as SOURCE */ +ZTEST_SUITE(usb_pd_ctrl_msg_test_source, drivers_predicate_post_main, + usb_pd_ctrl_msg_source_setup, usb_pd_ctrl_msg_before, + usb_pd_ctrl_msg_after, NULL); + +ZTEST_F(usb_pd_ctrl_msg_test_sink, verify_vconn_swap) +{ + struct usb_pd_ctrl_msg_test_fixture *super_fixture = &fixture->fixture; + struct ec_response_typec_status snk_resp = { 0 }; + int rv = 0; + + snk_resp = host_cmd_typec_status(TEST_USB_PORT); + + zassert_equal(PD_ROLE_VCONN_SRC, snk_resp.vconn_role, + "SNK Returned vconn_role=%u", snk_resp.vconn_role); + + /* Send VCONN_SWAP request */ + rv = tcpci_partner_send_control_msg(&super_fixture->partner_emul, + PD_CTRL_VCONN_SWAP, 0); + zassert_ok(rv, "Failed to send VCONN_SWAP request, rv=%d", rv); + + k_sleep(K_SECONDS(1)); + + snk_resp = host_cmd_typec_status(TEST_USB_PORT); + zassert_equal(PD_ROLE_VCONN_OFF, snk_resp.vconn_role, + "SNK Returned vconn_role=%u", snk_resp.vconn_role); +} + +ZTEST_F(usb_pd_ctrl_msg_test_sink, verify_pr_swap) +{ + struct usb_pd_ctrl_msg_test_fixture *super_fixture = &fixture->fixture; + struct ec_response_typec_status snk_resp = { 0 }; + int rv = 0; + + snk_resp = host_cmd_typec_status(TEST_USB_PORT); + + zassert_equal(PD_ROLE_SINK, snk_resp.power_role, + "SNK Returned power_role=%u", snk_resp.power_role); + + /* Ignore ACCEPT in common handler for PR Swap request, + * causes soft reset + */ + tcpci_partner_common_handler_mask_msg(&super_fixture->partner_emul, + PD_CTRL_ACCEPT, true); + + /* Send PR_SWAP request */ + rv = tcpci_partner_send_control_msg(&super_fixture->partner_emul, + PD_CTRL_PR_SWAP, 0); + zassert_ok(rv, "Failed to send PR_SWAP request, rv=%d", rv); + + /* Send PS_RDY request */ + rv = tcpci_partner_send_control_msg(&super_fixture->partner_emul, + PD_CTRL_PS_RDY, 15); + zassert_ok(rv, "Failed to send PS_RDY request, rv=%d", rv); + + k_sleep(K_MSEC(20)); + + snk_resp = host_cmd_typec_status(TEST_USB_PORT); + zassert_equal(PD_ROLE_SOURCE, snk_resp.power_role, + "SNK Returned power_role=%u", snk_resp.power_role); +} + +/** + * @brief TestPurpose: Verify DR Swap when DRP partner is configured as sink. + * + * @details + * - TCPM is brought up as Sink/UFP + * - TCPM over time will evaluate and trigger DR Swap to Sink/DFP + * + * Expected Results + * - TypeC status query returns PD_ROLE_DFP + */ +ZTEST_F(usb_pd_ctrl_msg_test_sink, verify_dr_swap) +{ + struct ec_response_typec_status typec_status = + host_cmd_typec_status(TEST_USB_PORT); + + zassert_equal(PD_ROLE_DFP, typec_status.data_role, + "Returned data_role=%u", typec_status.data_role); +} + +/** + * @brief TestPurpose: Verify DR Swap is rejected when DRP partner is + * configured as source. + * + * @details + * - TCPM is configured initially as Sink/UFP. + * - TCPM initiates DR swap according to policy (Sink/DFP) + * - Partner requests DR Swap. + * - Verify Request is rejected due the TCPM not being UFP. + * + * Expected Results + * - Data role does not change on TEST_USB_PORT after DR Swap request. + */ +ZTEST_F(usb_pd_ctrl_msg_test_source, verify_dr_swap_rejected) +{ + struct usb_pd_ctrl_msg_test_fixture *super_fixture = &fixture->fixture; + struct ec_response_typec_status typec_status = { 0 }; + int rv = 0; + + typec_status = host_cmd_typec_status(TEST_USB_PORT); + zassert_equal(PD_ROLE_DFP, typec_status.data_role, + "Returned data_role=%u", typec_status.data_role); + + /* Send DR_SWAP request */ + rv = tcpci_partner_send_control_msg(&super_fixture->partner_emul, + PD_CTRL_DR_SWAP, 0); + zassert_ok(rv, "Failed to send DR_SWAP request, rv=%d", rv); + + k_sleep(K_MSEC(20)); + + /* Verify DR_Swap request is REJECTED */ + typec_status = host_cmd_typec_status(TEST_USB_PORT); + zassert_equal(PD_ROLE_DFP, typec_status.data_role, + "Returned data_role=%u", typec_status.data_role); +} + +/** + * @brief TestPurpose: Verify DR Swap via DPM request when DRP is configured + * as source + * + * @details + * - TCPM is configured initially as Sink/UFP. + * - TCPM initiates DR swap according to policy (Sink/DFP) + * - Test case initiates DPM DR Swap. + * - Verify DR Swap Request is processed. + * + * Expected Results + * - Data role changes after DPM DR Swap request + */ +ZTEST_F(usb_pd_ctrl_msg_test_source, verify_dpm_dr_swap) +{ + struct ec_response_typec_status typec_status = { 0 }; + + typec_status = host_cmd_typec_status(TEST_USB_PORT); + zassert_equal(PD_ROLE_DFP, typec_status.data_role, + "Returned data_role=%u", typec_status.data_role); + + pd_dpm_request(TEST_USB_PORT, DPM_REQUEST_DR_SWAP); + k_sleep(K_SECONDS(1)); + + typec_status = host_cmd_typec_status(TEST_USB_PORT); + zassert_equal(PD_ROLE_UFP, typec_status.data_role, + "Returned data_role=%u", typec_status.data_role); +} + +/** + * @brief TestPurpose: Verify TCPM initiates Get_Sink_Cap message during a typec + * status host command and receives sink_capabilities message. + * + * @details + * - TCPM is configured initially as Sink + * - TypeC Status Host Command is Invoked + * + * Expected Results + * - TypeC Status Host Command reveals sink capabilility PDOs. + */ +ZTEST(usb_pd_ctrl_msg_test_source, verify_dpm_get_sink_cap) +{ + struct ec_response_typec_status typec_status = { 0 }; + + typec_status = host_cmd_typec_status(TEST_USB_PORT); + + zassert_true(typec_status.sink_cap_count > 1, NULL); + zassert_equal(typec_status.sink_cap_pdos[1], TEST_ADDED_PDO, NULL); +} + +/** + * @brief TestPurpose: Verify TCPM initiates Get_Sink_Cap message during a typec + * status host command and receives sink_capabilities message. + * + * @details + * - TCPM is configured initially as Source + * - TypeC Status Host Command is Invoked + * + * Expected Results + * - TypeC Status Host Command reveals sink capabilility PDOs. + */ +ZTEST(usb_pd_ctrl_msg_test_sink, verify_get_sink_cap) +{ + struct ec_response_typec_status typec_status = { 0 }; + + typec_status = host_cmd_typec_status(TEST_USB_PORT); + + zassert_true(typec_status.sink_cap_count > 1, NULL); + zassert_equal(typec_status.sink_cap_pdos[1], TEST_ADDED_PDO, NULL); +} + +/** + * @brief TestPurpose: Verify BIST TX MODE 2. + * + * @details + * - TCPM is configured initially as Sink + * - Initiate BIST TX + * + * Expected Results + * - BIST occurs and we transition back to READY state + */ +ZTEST_F(usb_pd_ctrl_msg_test_source, verify_bist_tx_mode2) +{ + struct usb_pd_ctrl_msg_test_fixture *super_fixture = &fixture->fixture; + uint32_t bdo = BDO(BDO_MODE_CARRIER2, 0); + + tcpci_partner_send_data_msg(&super_fixture->partner_emul, PD_DATA_BIST, + &bdo, 1, 0); + + pd_dpm_request(TEST_USB_PORT, DPM_REQUEST_BIST_TX); + k_sleep(K_MSEC(10)); + zassert_equal(get_state_pe(TEST_USB_PORT), PE_BIST_TX, NULL); + + k_sleep(K_SECONDS(5)); + zassert_equal(get_state_pe(TEST_USB_PORT), PE_SNK_READY, NULL); +} + +/** + * @brief TestPurpose: Verify BIST TX TEST DATA. + * + * @details + * - TCPM is configured initially as Sink + * - Initiate BIST TX + * - End testing via signaling a Hard Reset + * + * Expected Results + * - Partner remains in BIST_TX state until hard reset is received. + */ +ZTEST_F(usb_pd_ctrl_msg_test_source, verify_bist_tx_test_data) +{ + struct usb_pd_ctrl_msg_test_fixture *super_fixture = &fixture->fixture; + uint32_t bdo = BDO(BDO_MODE_TEST_DATA, 0); + + tcpci_partner_send_data_msg(&super_fixture->partner_emul, PD_DATA_BIST, + &bdo, 1, 0); + + pd_dpm_request(TEST_USB_PORT, DPM_REQUEST_BIST_TX); + k_sleep(K_SECONDS(5)); + zassert_equal(get_state_pe(TEST_USB_PORT), PE_BIST_TX, NULL); + + tcpci_partner_common_send_hard_reset(&super_fixture->partner_emul); + k_sleep(K_SECONDS(1)); + zassert_equal(get_state_pe(TEST_USB_PORT), PE_SNK_READY, NULL); +} |