diff options
author | Tom Hughes <tomhughes@chromium.org> | 2022-09-21 14:10:01 -0700 |
---|---|---|
committer | Tom Hughes <tomhughes@chromium.org> | 2022-09-22 12:49:33 -0700 |
commit | 2bcf863b492fe7ed8105c853814dba6ed32ba719 (patch) | |
tree | fcf6ce5810f9ff9e3c8cce434812dd75492269ed /zephyr/test/drivers/default/src/tcpci_test_common.c | |
parent | e5fb0b9ba488614b5684e640530f00821ab7b943 (diff) | |
parent | 28712dae9d7ed1e694f7622cc083afa71090d4d5 (diff) | |
download | chrome-ec-firmware-fpmcu-bloonchipper-release.tar.gz |
Merge remote-tracking branch cros/main into firmware-fpmcu-bloonchipper-releasefirmware-fpmcu-bloonchipper-release
Generated by: ./util/update_release_branch.py --board bloonchipper
--relevant_paths_file ./util/fingerprint-relevant-paths.txt firmware-
fpmcu-bloonchipper-release
Relevant changes:
git log --oneline e5fb0b9ba4..28712dae9d -- board/hatch_fp
board/bloonchipper common/fpsensor docs/fingerprint driver/fingerprint
util/getversion.sh
ded9307b79 util/getversion.sh: Fix version when not in a git repo
956055e692 board: change Google USB vendor info
71b2ef709d Update license boilerplate text in source code files
33e11afda0 Revert "fpsensor: Build fpsensor source file with C++"
c8d0360723 fpsensor: Build fpsensor source file with C++
bc113abd53 fpsensor: Fix g++ compiler error
150a58a0dc fpsensor: Fix fp_set_sensor_mode return type
b33b5ce85b fpsensor: Remove nested designators for C++ compatibility
2e864b2539 tree-wide: const-ify argv for console commands
56d8b360f9 test: Add test for get ikm failure when seed not set
3a3d6c3690 test: Add test for fpsensor trivial key failure
233e6bbd08 fpsensor_crypto: Abstract calls to hmac_SHA256
0a041b285b docs/fingerprint: Typo correction
c03fab67e2 docs/fingerprint: Fix the path of fputils.py
0b5d4baf5a util/getversion.sh: Fix empty file list handling
6e128fe760 FPMCU dev board environment with Satlab
3eb29b6aa5 builtin: Move ssize_t to sys/types.h
345d62ebd1 docs/fingerprint: Update power numbers for latest dartmonkey release
c25ffdb316 common: Conditionally support printf %l and %i modifiers
9a3c514b45 test: Add a test to check if the debugger is connected
54e603413f Move standard library tests to their own file
43fa6b4bf8 docs/fingerprint: Update power numbers for latest bloonchipper release
25536f9a84 driver/fingerprint/fpc/bep/fpc_sensor_spi.c: Format with clang-format
4face99efd driver/fingerprint/fpc/libfp/fpc_sensor_pal.h: Format with clang-format
738de2b575 trng: Rename rand to trng_rand
14b8270edd docs/fingerprint: Update dragonclaw power numbers
0b268f93d1 driver/fingerprint/fpc/libfp/fpc_private.c: Format with clang-format
f80da163f2 driver/fingerprint/fpc/libfp/fpc_private.h: Format with clang-format
5e9c85c9b1 driver/fingerprint/fpc/libfp/fpc_sensor_pal.c: Format with clang-format
c1f9dd3cf8 driver/fingerprint/fpc/libfp/fpc_bio_algorithm.h: Format with clang-format
eb1e1bed8d driver/fingerprint/fpc/libfp/fpc1145_private.h: Format with clang-format
6e7b611821 driver/fingerprint/fpc/bep/fpc_bio_algorithm.h: Format with clang-format
e0589cd5e2 driver/fingerprint/fpc/bep/fpc1035_private.h: Format with clang-format
7905e556a0 common/fpsensor/fpsensor_crypto.c: Format with clang-format
21289d170c driver/fingerprint/fpc/bep/fpc1025_private.h: Format with clang-format
98a20f937e common/fpsensor/fpsensor_state.c: Format with clang-format
a2d255d8af common/fpsensor/fpsensor.c: Format with clang-format
73055eeb3f driver/fingerprint/fpc/bep/fpc_private.c: Format with clang-format
0f7b5cb509 common/fpsensor/fpsensor_private.h: Format with clang-format
1ceade6e65 driver/fingerprint/fpc/bep/fpc_private.h: Format with clang-format
dc3e9008b8 board/hatch_fp/board.h: Format with clang-format
dca9d74321 Revert "trng: Rename rand to trng_rand"
a6b0b3554f trng: Rename rand to trng_rand
28d0b75b70 third_party/boringssl: Remove unused header
BRANCH=None
BUG=b:246424843 b:234181908 b:244781166 b:234181908 b:244387210
BUG=b:242720240 chromium:1098010 b:180945056 b:236025198 b:234181908
BUG=b:234181908 b:237344361 b:131913998 b:236386294 b:234143158
BUG=b:234781655 b:215613183 b:242720910
TEST=`make -j buildall`
TEST=./test/run_device_tests.py --board bloonchipper
Test "aes": PASSED
Test "cec": PASSED
Test "cortexm_fpu": PASSED
Test "crc": PASSED
Test "flash_physical": PASSED
Test "flash_write_protect": PASSED
Test "fpsensor_hw": PASSED
Test "fpsensor_spi_ro": PASSED
Test "fpsensor_spi_rw": PASSED
Test "fpsensor_uart_ro": PASSED
Test "fpsensor_uart_rw": PASSED
Test "mpu_ro": PASSED
Test "mpu_rw": PASSED
Test "mutex": PASSED
Test "pingpong": PASSED
Test "printf": PASSED
Test "queue": PASSED
Test "rollback_region0": PASSED
Test "rollback_region1": PASSED
Test "rollback_entropy": PASSED
Test "rtc": PASSED
Test "sha256": PASSED
Test "sha256_unrolled": PASSED
Test "static_if": PASSED
Test "stdlib": PASSED
Test "system_is_locked_wp_on": PASSED
Test "system_is_locked_wp_off": PASSED
Test "timer_dos": PASSED
Test "utils": PASSED
Test "utils_str": PASSED
Test "stm32f_rtc": PASSED
Test "panic_data_bloonchipper_v2.0.4277": PASSED
Test "panic_data_bloonchipper_v2.0.5938": PASSED
Force-Relevant-Builds: all
Signed-off-by: Tom Hughes <tomhughes@chromium.org>
Change-Id: I264ad0ffe7afcd507a1e483c6e934a9c4fea47c3
Diffstat (limited to 'zephyr/test/drivers/default/src/tcpci_test_common.c')
-rw-r--r-- | zephyr/test/drivers/default/src/tcpci_test_common.c | 1030 |
1 files changed, 1030 insertions, 0 deletions
diff --git a/zephyr/test/drivers/default/src/tcpci_test_common.c b/zephyr/test/drivers/default/src/tcpci_test_common.c new file mode 100644 index 0000000000..f2c0c58bf9 --- /dev/null +++ b/zephyr/test/drivers/default/src/tcpci_test_common.c @@ -0,0 +1,1030 @@ +/* Copyright 2021 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <zephyr/kernel.h> +#include <zephyr/ztest.h> + +#include "common.h" +#include "emul/emul_common_i2c.h" +#include "emul/tcpc/emul_tcpci.h" +#include "test/drivers/tcpci_test_common.h" + +#include "tcpm/tcpci.h" + +/** Check TCPC register value */ +void check_tcpci_reg_f(const struct emul *emul, int reg, uint16_t exp_val, + int line) +{ + uint16_t reg_val; + + zassert_ok(tcpci_emul_get_reg(emul, reg, ®_val), + "Failed tcpci_emul_get_reg(); line: %d", line); + zassert_equal(exp_val, reg_val, "Expected 0x%x, got 0x%x; line: %d", + exp_val, reg_val, line); +} + +/** Check TCPC register value with mask */ +void check_tcpci_reg_with_mask_f(const struct emul *emul, int reg, + uint16_t exp_val, uint16_t mask, int line) +{ + uint16_t reg_val; + + zassert_ok(tcpci_emul_get_reg(emul, reg, ®_val), + "Failed tcpci_emul_get_reg(); line: %d", line); + zassert_equal(exp_val & mask, reg_val & mask, + "Expected 0x%x, got 0x%x, mask 0x%x; line: %d", exp_val, + reg_val, mask, line); +} + +/** Test TCPCI init and vbus level */ +void test_tcpci_init(const struct emul *emul, + struct i2c_common_emul_data *common_data, + enum usbc_port port) +{ + const struct tcpm_drv *drv = tcpc_config[port].drv; + uint16_t exp_mask; + + tcpc_config[port].flags |= TCPC_FLAGS_TCPCI_REV2_0_NO_VSAFE0V; + + /* Test fail on power status read */ + i2c_common_emul_set_read_fail_reg(common_data, TCPC_REG_POWER_STATUS); + zassert_equal(EC_ERROR_INVAL, drv->init(port), NULL); + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Test fail on uninitialised bit set */ + tcpci_emul_set_reg(emul, TCPC_REG_POWER_STATUS, + TCPC_REG_POWER_STATUS_UNINIT); + zassert_equal(EC_ERROR_TIMEOUT, drv->init(port), NULL); + + /* + * Set expected alert mask. It is used in test until vSafe0V tcpc + * config flag is revmoved. + */ + exp_mask = TCPC_REG_ALERT_TX_SUCCESS | TCPC_REG_ALERT_TX_FAILED | + TCPC_REG_ALERT_TX_DISCARDED | TCPC_REG_ALERT_RX_STATUS | + TCPC_REG_ALERT_RX_HARD_RST | TCPC_REG_ALERT_CC_STATUS | + TCPC_REG_ALERT_FAULT | TCPC_REG_ALERT_POWER_STATUS; + + /* Set TCPCI emulator VBUS to safe0v (disconnected) */ + tcpci_emul_set_reg(emul, TCPC_REG_POWER_STATUS, + TCPC_REG_POWER_STATUS_VBUS_DET); + + /* Test init with VBUS safe0v without vSafe0V tcpc config flag */ + zassert_equal(EC_SUCCESS, drv->init(port), NULL); + zassert_true(drv->check_vbus_level(port, VBUS_SAFE0V), NULL); + zassert_false(drv->check_vbus_level(port, VBUS_PRESENT), NULL); + check_tcpci_reg(emul, TCPC_REG_POWER_STATUS_MASK, + TCPC_REG_POWER_STATUS_VBUS_PRES); + check_tcpci_reg(emul, TCPC_REG_ALERT_MASK, exp_mask); + + /* Set TCPCI emulator VBUS to present (connected, above 4V) */ + tcpci_emul_set_reg(emul, TCPC_REG_POWER_STATUS, + TCPC_REG_POWER_STATUS_VBUS_PRES | + TCPC_REG_POWER_STATUS_VBUS_DET); + + /* Test init with VBUS present without vSafe0V tcpc config flag */ + zassert_equal(EC_SUCCESS, drv->init(port), NULL); + zassert_false(drv->check_vbus_level(port, VBUS_SAFE0V), NULL); + zassert_true(drv->check_vbus_level(port, VBUS_PRESENT), NULL); + check_tcpci_reg(emul, TCPC_REG_POWER_STATUS_MASK, + TCPC_REG_POWER_STATUS_VBUS_PRES); + check_tcpci_reg(emul, TCPC_REG_ALERT_MASK, exp_mask); + + /* Disable vSafe0V tcpc config flag and update expected alert mask */ + exp_mask |= TCPC_REG_ALERT_EXT_STATUS; + tcpc_config[port].flags = TCPC_FLAGS_TCPCI_REV2_0; + + /* Test init with VBUS present with vSafe0V tcpc config flag */ + zassert_equal(EC_SUCCESS, drv->init(port), NULL); + zassert_false(drv->check_vbus_level(port, VBUS_SAFE0V), NULL); + zassert_true(drv->check_vbus_level(port, VBUS_PRESENT), NULL); + check_tcpci_reg(emul, TCPC_REG_POWER_STATUS_MASK, + TCPC_REG_POWER_STATUS_VBUS_PRES); + check_tcpci_reg(emul, TCPC_REG_ALERT_MASK, exp_mask); + + /* Set TCPCI emulator VBUS to safe0v (disconnected) */ + tcpci_emul_set_reg(emul, TCPC_REG_POWER_STATUS, + TCPC_REG_POWER_STATUS_VBUS_DET); + tcpci_emul_set_reg(emul, TCPC_REG_EXT_STATUS, + TCPC_REG_EXT_STATUS_SAFE0V); + + /* Test init with VBUS safe0v with vSafe0V tcpc config flag */ + zassert_equal(EC_SUCCESS, drv->init(port), NULL); + zassert_true(drv->check_vbus_level(port, VBUS_SAFE0V), NULL); + zassert_false(drv->check_vbus_level(port, VBUS_PRESENT), NULL); + check_tcpci_reg(emul, TCPC_REG_POWER_STATUS_MASK, + TCPC_REG_POWER_STATUS_VBUS_PRES); + check_tcpci_reg(emul, TCPC_REG_ALERT_MASK, exp_mask); + + /* + * Set TCPCI emulator VBUS to disconnected but not at vSafe0V + * (VBUS in 0.8V - 3.5V range) + */ + tcpci_emul_set_reg(emul, TCPC_REG_EXT_STATUS, 0); + + /* Test init with VBUS not safe0v with vSafe0V tcpc config flag */ + zassert_equal(EC_SUCCESS, drv->init(port), NULL); + zassert_false(drv->check_vbus_level(port, VBUS_SAFE0V), NULL); + zassert_false(drv->check_vbus_level(port, VBUS_PRESENT), NULL); + check_tcpci_reg(emul, TCPC_REG_POWER_STATUS_MASK, + TCPC_REG_POWER_STATUS_VBUS_PRES); + check_tcpci_reg(emul, TCPC_REG_ALERT_MASK, exp_mask); +} + +/** Test TCPCI release */ +void test_tcpci_release(const struct emul *emul, + struct i2c_common_emul_data *common_data, + enum usbc_port port) +{ + const struct tcpm_drv *drv = tcpc_config[port].drv; + + tcpci_emul_set_reg(emul, TCPC_REG_ALERT, 0xffff); + + zassert_equal(EC_SUCCESS, drv->release(port), NULL); + check_tcpci_reg(emul, TCPC_REG_POWER_STATUS_MASK, 0); + check_tcpci_reg(emul, TCPC_REG_ALERT_MASK, 0); + check_tcpci_reg(emul, TCPC_REG_ALERT, 0); +} + +/** Test TCPCI get cc */ +void test_tcpci_get_cc(const struct emul *emul, + struct i2c_common_emul_data *common_data, + enum usbc_port port) +{ + const struct tcpm_drv *drv = tcpc_config[port].drv; + enum tcpc_cc_voltage_status cc1, cc2; + uint16_t cc_status, role_ctrl; + + struct { + /* TCPCI CC status register */ + enum tcpc_cc_voltage_status cc[2]; + bool connect_result; + /* TCPCI ROLE ctrl register */ + enum tcpc_cc_pull role_cc[2]; + enum tcpc_drp drp; + } test_param[] = { + /* Test DRP with open state */ + { + .cc = { TYPEC_CC_VOLT_OPEN, TYPEC_CC_VOLT_OPEN }, + .connect_result = false, + .drp = TYPEC_DRP, + }, + /* Test DRP with cc1 open state, cc2 src RA */ + { + .cc = { TYPEC_CC_VOLT_OPEN, TYPEC_CC_VOLT_RA }, + .connect_result = false, + .drp = TYPEC_DRP, + }, + /* Test DRP with cc1 src RA, cc2 src RD */ + { + .cc = { TYPEC_CC_VOLT_RA, TYPEC_CC_VOLT_RD }, + .connect_result = false, + .drp = TYPEC_DRP, + }, + /* Test DRP with cc1 snk open, cc2 snk default */ + { + .cc = { TYPEC_CC_VOLT_OPEN, TYPEC_CC_VOLT_RP_DEF }, + .connect_result = true, + .drp = TYPEC_DRP, + }, + /* Test DRP with cc1 snk 1.5, cc2 snk 3.0 */ + { + .cc = { TYPEC_CC_VOLT_RP_1_5, TYPEC_CC_VOLT_RP_3_0 }, + .connect_result = true, + .drp = TYPEC_DRP, + }, + /* Test no DRP with cc1 src open, cc2 src RA */ + { + .cc = { TYPEC_CC_VOLT_OPEN, TYPEC_CC_VOLT_RA }, + .connect_result = false, + .drp = TYPEC_NO_DRP, + .role_cc = { TYPEC_CC_RP, TYPEC_CC_RP }, + }, + /* Test no DRP with cc1 src RD, cc2 snk default */ + { + .cc = { TYPEC_CC_VOLT_RD, TYPEC_CC_VOLT_RP_DEF }, + .connect_result = false, + .drp = TYPEC_NO_DRP, + .role_cc = { TYPEC_CC_RP, TYPEC_CC_RD }, + }, + /* Test no DRP with cc1 snk default, cc2 snk open */ + { + .cc = { TYPEC_CC_VOLT_RP_DEF, TYPEC_CC_VOLT_OPEN }, + .connect_result = false, + .drp = TYPEC_NO_DRP, + .role_cc = { TYPEC_CC_RD, TYPEC_CC_RD }, + }, + /* Test no DRP with cc1 snk 3.0, cc2 snk 1.5 */ + { + .cc = { TYPEC_CC_VOLT_RP_3_0, TYPEC_CC_VOLT_RP_1_5 }, + .connect_result = false, + .drp = TYPEC_NO_DRP, + .role_cc = { TYPEC_CC_RD, TYPEC_CC_RD }, + }, + }; + + for (int i = 0; i < ARRAY_SIZE(test_param); i++) { + role_ctrl = TCPC_REG_ROLE_CTRL_SET(test_param[i].drp, 0, + test_param[i].role_cc[0], + test_param[i].role_cc[1]); + /* If CC status is TYPEC_CC_VOLT_RP_*, then BIT(2) is ignored */ + cc_status = TCPC_REG_CC_STATUS_SET(test_param[i].connect_result, + test_param[i].cc[0], + test_param[i].cc[1]); + tcpci_emul_set_reg(emul, TCPC_REG_ROLE_CTRL, role_ctrl); + tcpci_emul_set_reg(emul, TCPC_REG_CC_STATUS, cc_status); + zassert_equal( + EC_SUCCESS, drv->get_cc(port, &cc1, &cc2), + "Failed to get CC in test case %d (CC 0x%x, role 0x%x)", + i, cc_status, role_ctrl); + zassert_equal( + test_param[i].cc[0], cc1, + "0x%x != (cc1 = 0x%x) in test case %d (CC 0x%x, role 0x%x)", + test_param[i].cc[0], cc1, i, cc_status, role_ctrl); + zassert_equal( + test_param[i].cc[1], cc2, + "0x%x != (cc2 = 0x%x) in test case %d (CC 0x%x, role 0x%x)", + test_param[i].cc[0], cc1, i, cc_status, role_ctrl); + } +} + +/** Test TCPCI set cc */ +void test_tcpci_set_cc(const struct emul *emul, + struct i2c_common_emul_data *common_data, + enum usbc_port port) +{ + const struct tcpm_drv *drv = tcpc_config[port].drv; + enum tcpc_rp_value rp; + enum tcpc_cc_pull cc; + + /* Test setting default RP and cc open */ + rp = TYPEC_RP_USB; + cc = TYPEC_CC_OPEN; + zassert_equal(EC_SUCCESS, drv->select_rp_value(port, rp), NULL); + zassert_equal(EC_SUCCESS, drv->set_cc(port, cc), NULL); + check_tcpci_reg(emul, TCPC_REG_ROLE_CTRL, + TCPC_REG_ROLE_CTRL_SET(TYPEC_NO_DRP, rp, cc, cc)); + + /* Test error on failed role ctrl set */ + i2c_common_emul_set_write_fail_reg(common_data, TCPC_REG_ROLE_CTRL); + zassert_equal(EC_ERROR_INVAL, drv->set_cc(port, TYPEC_CC_OPEN), NULL); + i2c_common_emul_set_write_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Test setting 1.5 RP and cc RD */ + rp = TYPEC_RP_1A5; + cc = TYPEC_CC_RD; + zassert_equal(EC_SUCCESS, drv->select_rp_value(port, rp), NULL); + zassert_equal(EC_SUCCESS, drv->set_cc(port, cc), NULL); + check_tcpci_reg(emul, TCPC_REG_ROLE_CTRL, + TCPC_REG_ROLE_CTRL_SET(TYPEC_NO_DRP, rp, cc, cc)); + + /* Test setting 3.0 RP and cc RP */ + rp = TYPEC_RP_3A0; + cc = TYPEC_CC_RP; + zassert_equal(EC_SUCCESS, drv->select_rp_value(port, rp), NULL); + zassert_equal(EC_SUCCESS, drv->set_cc(port, cc), NULL); + check_tcpci_reg(emul, TCPC_REG_ROLE_CTRL, + TCPC_REG_ROLE_CTRL_SET(TYPEC_NO_DRP, rp, cc, cc)); + + /* + * Test setting 3.0 RP and cc RA. drv->select_rp_value() is + * intentionally not called to check if selected rp is persistent. + */ + cc = TYPEC_CC_RA; + zassert_equal(EC_SUCCESS, drv->set_cc(port, cc), NULL); + check_tcpci_reg(emul, TCPC_REG_ROLE_CTRL, + TCPC_REG_ROLE_CTRL_SET(TYPEC_NO_DRP, rp, cc, cc)); +} + +/** Test TCPCI set polarity */ +void test_tcpci_set_polarity(const struct emul *emul, + struct i2c_common_emul_data *common_data, + enum usbc_port port) +{ + const struct tcpm_drv *drv = tcpc_config[port].drv; + uint8_t initial_ctrl; + uint8_t exp_ctrl; + + /* Set initial value for TCPC ctrl register. Chosen arbitrary. */ + initial_ctrl = TCPC_REG_TCPC_CTRL_DEBUG_ACC_CONTROL | + TCPC_REG_TCPC_CTRL_BIST_TEST_MODE; + tcpci_emul_set_reg(emul, TCPC_REG_TCPC_CTRL, initial_ctrl); + + /* Test error on failed polarity set */ + exp_ctrl = initial_ctrl; + i2c_common_emul_set_write_fail_reg(common_data, TCPC_REG_TCPC_CTRL); + zassert_equal(EC_ERROR_INVAL, drv->set_polarity(port, POLARITY_CC2), + NULL); + i2c_common_emul_set_write_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + check_tcpci_reg(emul, TCPC_REG_TCPC_CTRL, exp_ctrl); + + /* Test setting polarity CC2 */ + exp_ctrl = initial_ctrl | TCPC_REG_TCPC_CTRL_SET(1); + zassert_equal(EC_SUCCESS, drv->set_polarity(port, POLARITY_CC2), NULL); + check_tcpci_reg(emul, TCPC_REG_TCPC_CTRL, exp_ctrl); + + /* Test setting polarity CC1 */ + exp_ctrl = initial_ctrl & ~TCPC_REG_TCPC_CTRL_SET(1); + zassert_equal(EC_SUCCESS, drv->set_polarity(port, POLARITY_CC1), NULL); + check_tcpci_reg(emul, TCPC_REG_TCPC_CTRL, exp_ctrl); + + /* Test setting polarity CC2 DTS */ + exp_ctrl = initial_ctrl | TCPC_REG_TCPC_CTRL_SET(1); + zassert_equal(EC_SUCCESS, drv->set_polarity(port, POLARITY_CC2_DTS), + NULL); + check_tcpci_reg(emul, TCPC_REG_TCPC_CTRL, exp_ctrl); + + /* Test setting polarity CC1 DTS */ + exp_ctrl = initial_ctrl & ~TCPC_REG_TCPC_CTRL_SET(1); + zassert_equal(EC_SUCCESS, drv->set_polarity(port, POLARITY_CC1_DTS), + NULL); + check_tcpci_reg(emul, TCPC_REG_TCPC_CTRL, exp_ctrl); +} + +/** Test TCPCI set vconn */ +void test_tcpci_set_vconn(const struct emul *emul, + struct i2c_common_emul_data *common_data, + enum usbc_port port) +{ + const struct tcpm_drv *drv = tcpc_config[port].drv; + uint8_t initial_ctrl; + uint8_t exp_ctrl; + + /* Set initial value for POWER ctrl register. Chosen arbitrary. */ + initial_ctrl = TCPC_REG_POWER_CTRL_VBUS_VOL_MONITOR_DIS | + TCPC_REG_POWER_CTRL_FORCE_DISCHARGE; + tcpci_emul_set_reg(emul, TCPC_REG_POWER_CTRL, initial_ctrl); + + /* Test error on failed vconn set */ + exp_ctrl = initial_ctrl; + i2c_common_emul_set_write_fail_reg(common_data, TCPC_REG_POWER_CTRL); + zassert_equal(EC_ERROR_INVAL, drv->set_vconn(port, 1), NULL); + i2c_common_emul_set_write_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + check_tcpci_reg(emul, TCPC_REG_POWER_CTRL, exp_ctrl); + + /* Test vconn enable */ + exp_ctrl = initial_ctrl | TCPC_REG_POWER_CTRL_SET(1); + zassert_equal(EC_SUCCESS, drv->set_vconn(port, 1), NULL); + check_tcpci_reg(emul, TCPC_REG_POWER_CTRL, exp_ctrl); + + /* Test vconn disable */ + exp_ctrl = initial_ctrl & ~TCPC_REG_POWER_CTRL_SET(1); + zassert_equal(EC_SUCCESS, drv->set_vconn(port, 0), NULL); + check_tcpci_reg(emul, TCPC_REG_POWER_CTRL, exp_ctrl); +} + +/** Test TCPCI set msg header */ +void test_tcpci_set_msg_header(const struct emul *emul, + struct i2c_common_emul_data *common_data, + enum usbc_port port) +{ + const struct tcpm_drv *drv = tcpc_config[port].drv; + + /* Test error on failed header set */ + i2c_common_emul_set_write_fail_reg(common_data, TCPC_REG_MSG_HDR_INFO); + zassert_equal(EC_ERROR_INVAL, + drv->set_msg_header(port, PD_ROLE_SINK, PD_ROLE_UFP), + NULL); + i2c_common_emul_set_write_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Test setting sink UFP */ + zassert_equal(EC_SUCCESS, + drv->set_msg_header(port, PD_ROLE_SINK, PD_ROLE_UFP), + NULL); + check_tcpci_reg(emul, TCPC_REG_MSG_HDR_INFO, + TCPC_REG_MSG_HDR_INFO_SET(PD_ROLE_UFP, PD_ROLE_SINK)); + + /* Test setting sink DFP */ + zassert_equal(EC_SUCCESS, + drv->set_msg_header(port, PD_ROLE_SINK, PD_ROLE_DFP), + NULL); + check_tcpci_reg(emul, TCPC_REG_MSG_HDR_INFO, + TCPC_REG_MSG_HDR_INFO_SET(PD_ROLE_DFP, PD_ROLE_SINK)); + + /* Test setting source UFP */ + zassert_equal(EC_SUCCESS, + drv->set_msg_header(port, PD_ROLE_SOURCE, PD_ROLE_UFP), + NULL); + check_tcpci_reg(emul, TCPC_REG_MSG_HDR_INFO, + TCPC_REG_MSG_HDR_INFO_SET(PD_ROLE_UFP, PD_ROLE_SOURCE)); + + /* Test setting source DFP */ + zassert_equal(EC_SUCCESS, + drv->set_msg_header(port, PD_ROLE_SOURCE, PD_ROLE_DFP), + NULL); + check_tcpci_reg(emul, TCPC_REG_MSG_HDR_INFO, + TCPC_REG_MSG_HDR_INFO_SET(PD_ROLE_DFP, PD_ROLE_SOURCE)); +} + +/** Test TCPCI rx and sop prime enable */ +void test_tcpci_set_rx_detect(const struct emul *emul, + struct i2c_common_emul_data *common_data, + enum usbc_port port) +{ + const struct tcpm_drv *drv = tcpc_config[port].drv; + + /* Test error from rx_enable on rx detect set */ + i2c_common_emul_set_write_fail_reg(common_data, TCPC_REG_RX_DETECT); + zassert_equal(EC_ERROR_INVAL, drv->set_rx_enable(port, 1), NULL); + i2c_common_emul_set_write_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Test rx disable */ + zassert_equal(EC_SUCCESS, drv->set_rx_enable(port, 0), NULL); + check_tcpci_reg(emul, TCPC_REG_RX_DETECT, 0x0); + + /* Test setting sop prime with rx disable doesn't change RX_DETECT */ + zassert_equal(EC_SUCCESS, drv->sop_prime_enable(port, 1), NULL); + check_tcpci_reg(emul, TCPC_REG_RX_DETECT, 0x0); + + /* Test that enabling rx after sop prime will set RX_DETECT properly */ + zassert_equal(EC_SUCCESS, drv->set_rx_enable(port, 1), NULL); + check_tcpci_reg(emul, TCPC_REG_RX_DETECT, + TCPC_REG_RX_DETECT_SOP_SOPP_SOPPP_HRST_MASK); + + /* Test error from sop_prime on rx detect set */ + i2c_common_emul_set_write_fail_reg(common_data, TCPC_REG_RX_DETECT); + zassert_equal(EC_ERROR_INVAL, drv->sop_prime_enable(port, 0), NULL); + i2c_common_emul_set_write_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Test disabling sop prime with rx enabled does change RX_DETECT */ + zassert_equal(EC_SUCCESS, drv->sop_prime_enable(port, 0), NULL); + check_tcpci_reg(emul, TCPC_REG_RX_DETECT, + TCPC_REG_RX_DETECT_SOP_HRST_MASK); + + /* Test that enabling rx after disabling sop prime set RX_DETECT */ + zassert_equal(EC_SUCCESS, drv->set_rx_enable(port, 0), NULL); + check_tcpci_reg(emul, TCPC_REG_RX_DETECT, 0x0); + zassert_equal(EC_SUCCESS, drv->set_rx_enable(port, 1), NULL); + check_tcpci_reg(emul, TCPC_REG_RX_DETECT, + TCPC_REG_RX_DETECT_SOP_HRST_MASK); +} + +/** Test TCPCI get raw message from TCPC */ +void test_tcpci_get_rx_message_raw(const struct emul *emul, + struct i2c_common_emul_data *common_data, + enum usbc_port port) +{ + const struct tcpm_drv *drv = tcpc_config[port].drv; + struct tcpci_emul_msg msg; + uint32_t payload[7]; + uint16_t rx_mask; + uint8_t buf[32]; + int exp_head; + int i, head; + int size; + + tcpci_emul_set_reg(emul, TCPC_REG_ALERT, 0x0); + tcpci_emul_set_reg(emul, TCPC_REG_DEV_CAP_2, + TCPC_REG_DEV_CAP_2_LONG_MSG); + tcpci_emul_set_reg(emul, TCPC_REG_RX_DETECT, + TCPC_REG_RX_DETECT_SOP | TCPC_REG_RX_DETECT_SOPP); + + for (i = 0; i < 32; i++) { + buf[i] = i + 1; + } + msg.buf = buf; + msg.cnt = 31; + msg.sop_type = TCPCI_MSG_SOP; + zassert_equal(TCPCI_EMUL_TX_SUCCESS, + tcpci_emul_add_rx_msg(emul, &msg, true), + "Failed to setup emulator message"); + + /* Test fail on reading byte count */ + i2c_common_emul_set_read_fail_reg(common_data, TCPC_REG_RX_BUFFER); + zassert_equal(EC_ERROR_UNKNOWN, + drv->get_message_raw(port, payload, &head), NULL); + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + /* Get raw message should always clean RX alerts */ + rx_mask = TCPC_REG_ALERT_RX_BUF_OVF | TCPC_REG_ALERT_RX_STATUS; + check_tcpci_reg_with_mask(emul, TCPC_REG_ALERT, 0x0, rx_mask); + + /* Test too short message */ + msg.cnt = 1; + zassert_equal(TCPCI_EMUL_TX_SUCCESS, + tcpci_emul_add_rx_msg(emul, &msg, true), + "Failed to setup emulator message"); + zassert_equal(EC_ERROR_UNKNOWN, + drv->get_message_raw(port, payload, &head), NULL); + check_tcpci_reg_with_mask(emul, TCPC_REG_ALERT, 0x0, rx_mask); + + /* Test too long message */ + msg.cnt = 31; + zassert_equal(TCPCI_EMUL_TX_SUCCESS, + tcpci_emul_add_rx_msg(emul, &msg, true), + "Failed to setup emulator message"); + zassert_equal(EC_ERROR_UNKNOWN, + drv->get_message_raw(port, payload, &head), NULL); + check_tcpci_reg_with_mask(emul, TCPC_REG_ALERT, 0x0, rx_mask); + + /* Test alert register and message payload on success */ + size = 28; + msg.cnt = size + 2; + msg.sop_type = TCPCI_MSG_SOP_PRIME; + zassert_equal(TCPCI_EMUL_TX_SUCCESS, + tcpci_emul_add_rx_msg(emul, &msg, true), + "Failed to setup emulator message"); + zassert_equal(EC_SUCCESS, drv->get_message_raw(port, payload, &head), + NULL); + check_tcpci_reg_with_mask(emul, TCPC_REG_ALERT, 0x0, rx_mask); + /* + * Type is in bits 31-28 of header, buf[0] is in bits 7-0, + * buf[1] is in bits 15-8 + */ + exp_head = (TCPCI_MSG_SOP_PRIME << 28) | (buf[1] << 8) | buf[0]; + zassert_equal(exp_head, head, + "Received header 0x%08lx, expected 0x%08lx", head, + exp_head); + zassert_mem_equal(payload, buf + 2, size, NULL); +} + +/** Test TCPCI transmitting message from TCPC */ +void test_tcpci_transmit(const struct emul *emul, + struct i2c_common_emul_data *common_data, + enum usbc_port port) +{ + const struct tcpm_drv *drv = tcpc_config[port].drv; + struct tcpci_emul_msg *msg; + uint32_t data[6]; + uint16_t header; + int i; + + msg = tcpci_emul_get_tx_msg(emul); + + /* Fill transmit data with pattern */ + for (i = 0; i < 6 * sizeof(uint32_t); i++) { + ((uint8_t *)data)[i] = i; + } + + /* Test transmit hard reset fail */ + i2c_common_emul_set_write_fail_reg(common_data, TCPC_REG_TRANSMIT); + zassert_equal(EC_ERROR_INVAL, + drv->transmit(port, TCPCI_MSG_TX_HARD_RESET, 0, NULL), + NULL); + i2c_common_emul_set_write_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Test transmit cabel reset */ + zassert_equal(EC_SUCCESS, + drv->transmit(port, TCPCI_MSG_CABLE_RESET, 0, NULL), + NULL); + zassert_equal(TCPCI_MSG_CABLE_RESET, msg->sop_type, NULL); + + /* Test transmit hard reset */ + zassert_equal(EC_SUCCESS, + drv->transmit(port, TCPCI_MSG_TX_HARD_RESET, 0, NULL), + NULL); + zassert_equal(TCPCI_MSG_TX_HARD_RESET, msg->sop_type, NULL); + + /* Test transmit fail on rx buffer */ + i2c_common_emul_set_write_fail_reg(common_data, TCPC_REG_TX_BUFFER); + zassert_equal(EC_ERROR_INVAL, + drv->transmit(port, TCPCI_MSG_SOP_PRIME, 0, data), NULL); + i2c_common_emul_set_write_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Test transmit only header */ + /* Build random header with count 0 */ + header = PD_HEADER(PD_CTRL_PING, PD_ROLE_SOURCE, PD_ROLE_UFP, 0, 0, + PD_REV20, 0); + zassert_equal(EC_SUCCESS, + drv->transmit(port, TCPCI_MSG_SOP_PRIME, header, data), + NULL); + zassert_equal(TCPCI_MSG_SOP_PRIME, msg->sop_type, NULL); + zassert_mem_equal(msg->buf, &header, 2, NULL); + zassert_equal(2, msg->cnt, NULL); + + /* Test transmit message */ + /* Build random header with count 6 */ + header = PD_HEADER(PD_CTRL_PING, PD_ROLE_SOURCE, PD_ROLE_UFP, 0, 6, + PD_REV20, 0); + zassert_equal(EC_SUCCESS, + drv->transmit(port, TCPCI_MSG_SOP_PRIME, header, data), + NULL); + zassert_equal(TCPCI_MSG_SOP_PRIME, msg->sop_type, NULL); + zassert_mem_equal(msg->buf, &header, 2, NULL); + zassert_mem_equal(msg->buf + 2, data, 6 * sizeof(uint32_t), NULL); + zassert_equal(2 + 6 * sizeof(uint32_t), msg->cnt, NULL); +} + +/** Test TCPCI alert */ +void test_tcpci_alert(const struct emul *emul, + struct i2c_common_emul_data *common_data, + enum usbc_port port) +{ + const struct tcpm_drv *drv = tcpc_config[port].drv; + + /* Test alert read fail */ + i2c_common_emul_set_read_fail_reg(common_data, TCPC_REG_ALERT); + drv->tcpc_alert(port); + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Handle overcurrent */ + tcpci_emul_set_reg(emul, TCPC_REG_ALERT, TCPC_REG_ALERT_FAULT); + tcpci_emul_set_reg(emul, TCPC_REG_FAULT_STATUS, + TCPC_REG_FAULT_STATUS_VCONN_OVER_CURRENT); + drv->tcpc_alert(port); + check_tcpci_reg(emul, TCPC_REG_ALERT, 0x0); + check_tcpci_reg(emul, TCPC_REG_FAULT_STATUS, 0x0); + + /* Test TX complete */ + tcpci_emul_set_reg(emul, TCPC_REG_ALERT, TCPC_REG_ALERT_TX_COMPLETE); + drv->tcpc_alert(port); + + /* Test clear alert and ext_alert */ + tcpci_emul_set_reg(emul, TCPC_REG_ALERT, TCPC_REG_ALERT_ALERT_EXT); + tcpci_emul_set_reg(emul, TCPC_REG_ALERT_EXT, + TCPC_REG_ALERT_EXT_TIMER_EXPIRED); + drv->tcpc_alert(port); + check_tcpci_reg(emul, TCPC_REG_ALERT, 0x0); + check_tcpci_reg(emul, TCPC_REG_FAULT_STATUS, 0x0); + + /* Test CC changed, CC status chosen arbitrary */ + tcpci_emul_set_reg(emul, TCPC_REG_CC_STATUS, + TCPC_REG_CC_STATUS_SET(1, TYPEC_CC_VOLT_RP_1_5, + TYPEC_CC_VOLT_RP_3_0)); + tcpci_emul_set_reg(emul, TCPC_REG_ALERT, TCPC_REG_ALERT_CC_STATUS); + drv->tcpc_alert(port); + + /* Test Hard reset */ + tcpci_emul_set_reg(emul, TCPC_REG_ALERT, TCPC_REG_ALERT_RX_HARD_RST); + drv->tcpc_alert(port); +} + +/** Test TCPCI alert RX message */ +void test_tcpci_alert_rx_message(const struct emul *emul, + struct i2c_common_emul_data *common_data, + enum usbc_port port) +{ + const struct tcpm_drv *drv = tcpc_config[port].drv; + struct tcpci_emul_msg msg1, msg2; + uint8_t buf1[32], buf2[32]; + uint32_t payload[7]; + int exp_head; + int i, head; + int size; + + tcpci_emul_set_reg(emul, TCPC_REG_DEV_CAP_2, + TCPC_REG_DEV_CAP_2_LONG_MSG); + tcpci_emul_set_reg(emul, TCPC_REG_RX_DETECT, + TCPC_REG_RX_DETECT_SOP | TCPC_REG_RX_DETECT_SOPP); + + for (i = 0; i < 32; i++) { + buf1[i] = i + 1; + buf2[i] = i + 33; + } + size = 23; + msg1.buf = buf1; + msg1.cnt = size + 3; + msg1.sop_type = TCPCI_MSG_SOP; + + msg2.buf = buf2; + msg2.cnt = size + 3; + msg2.sop_type = TCPCI_MSG_SOP_PRIME; + + /* Test receiving one message */ + zassert_equal(TCPCI_EMUL_TX_SUCCESS, + tcpci_emul_add_rx_msg(emul, &msg1, true), + "Failed to setup emulator message"); + drv->tcpc_alert(port); + check_tcpci_reg(emul, TCPC_REG_ALERT, 0x0); + + /* Check if msg1 is in queue */ + zassert_true(tcpm_has_pending_message(port), NULL); + zassert_equal(EC_SUCCESS, tcpm_dequeue_message(port, payload, &head), + NULL); + exp_head = (TCPCI_MSG_SOP << 28) | (buf1[1] << 8) | buf1[0]; + zassert_equal(exp_head, head, + "Received header 0x%08lx, expected 0x%08lx", head, + exp_head); + zassert_mem_equal(payload, buf1 + 2, size, NULL); + zassert_false(tcpm_has_pending_message(port), NULL); + + /* Test receiving two messages */ + zassert_equal(TCPCI_EMUL_TX_SUCCESS, + tcpci_emul_add_rx_msg(emul, &msg1, true), + "Failed to setup emulator message"); + zassert_equal(TCPCI_EMUL_TX_SUCCESS, + tcpci_emul_add_rx_msg(emul, &msg2, true), + "Failed to setup emulator message"); + drv->tcpc_alert(port); + check_tcpci_reg(emul, TCPC_REG_ALERT, 0x0); + + /* Check if msg1 is in queue */ + zassert_true(tcpm_has_pending_message(port), NULL); + zassert_equal(EC_SUCCESS, tcpm_dequeue_message(port, payload, &head), + NULL); + exp_head = (TCPCI_MSG_SOP << 28) | (buf1[1] << 8) | buf1[0]; + zassert_equal(exp_head, head, + "Received header 0x%08lx, expected 0x%08lx", head, + exp_head); + zassert_mem_equal(payload, buf1 + 2, size, NULL); + /* Check if msg2 is in queue */ + zassert_true(tcpm_has_pending_message(port), NULL); + zassert_equal(EC_SUCCESS, tcpm_dequeue_message(port, payload, &head), + NULL); + exp_head = (TCPCI_MSG_SOP_PRIME << 28) | (buf2[1] << 8) | buf2[0]; + zassert_equal(exp_head, head, + "Received header 0x%08lx, expected 0x%08lx", head, + exp_head); + zassert_mem_equal(payload, buf2 + 2, size, NULL); + zassert_false(tcpm_has_pending_message(port), NULL); + + /* Test with too long first message */ + msg1.cnt = 32; + tcpci_emul_set_reg(emul, TCPC_REG_DEV_CAP_2, + TCPC_REG_DEV_CAP_2_LONG_MSG); + zassert_equal(TCPCI_EMUL_TX_SUCCESS, + tcpci_emul_add_rx_msg(emul, &msg1, true), + "Failed to setup emulator message"); + zassert_equal(TCPCI_EMUL_TX_SUCCESS, + tcpci_emul_add_rx_msg(emul, &msg2, true), + "Failed to setup emulator message"); + drv->tcpc_alert(port); + check_tcpci_reg(emul, TCPC_REG_ALERT, 0x0); + + /* Check if msg2 is in queue */ + zassert_true(tcpm_has_pending_message(port), NULL); + zassert_equal(EC_SUCCESS, tcpm_dequeue_message(port, payload, &head), + NULL); + exp_head = (TCPCI_MSG_SOP_PRIME << 28) | (buf2[1] << 8) | buf2[0]; + zassert_equal(exp_head, head, + "Received header 0x%08lx, expected 0x%08lx", head, + exp_head); + zassert_mem_equal(payload, buf2 + 2, size, NULL); + zassert_false(tcpm_has_pending_message(port), NULL); + + /* Test constant read message failure */ + zassert_equal(TCPCI_EMUL_TX_SUCCESS, + tcpci_emul_add_rx_msg(emul, &msg1, true), + "Failed to setup emulator message"); + /* Create loop with one message with wrong size */ + msg1.next = &msg1; + drv->tcpc_alert(port); + /* Nothing should be in queue */ + zassert_false(tcpm_has_pending_message(port), NULL); + + /* Test constant correct messages stream */ + msg1.cnt = size + 3; + drv->tcpc_alert(port); + msg1.next = NULL; + + /* msg1 should be at least twice in queue */ + exp_head = (TCPCI_MSG_SOP << 28) | (buf1[1] << 8) | buf1[0]; + for (i = 0; i < 2; i++) { + zassert_true(tcpm_has_pending_message(port), NULL); + zassert_equal(EC_SUCCESS, + tcpm_dequeue_message(port, payload, &head), NULL); + zassert_equal(exp_head, head, + "Received header 0x%08lx, expected 0x%08lx", head, + exp_head); + zassert_mem_equal(payload, buf1 + 2, size, NULL); + } + tcpm_clear_pending_messages(port); + zassert_false(tcpm_has_pending_message(port), NULL); + + /* Read message that is left in TCPC buffer */ + drv->tcpc_alert(port); + check_tcpci_reg(emul, TCPC_REG_ALERT, 0x0); + + /* Check if msg1 is in queue */ + zassert_true(tcpm_has_pending_message(port), NULL); + zassert_equal(EC_SUCCESS, tcpm_dequeue_message(port, payload, &head), + NULL); + exp_head = (TCPCI_MSG_SOP << 28) | (buf1[1] << 8) | buf1[0]; + zassert_equal(exp_head, head, + "Received header 0x%08lx, expected 0x%08lx", head, + exp_head); + zassert_mem_equal(payload, buf1 + 2, size, NULL); + zassert_false(tcpm_has_pending_message(port), NULL); +} + +/** Test TCPCI auto discharge on disconnect */ +void test_tcpci_auto_discharge(const struct emul *emul, + struct i2c_common_emul_data *common_data, + enum usbc_port port) +{ + const struct tcpm_drv *drv = tcpc_config[port].drv; + uint8_t initial_ctrl; + uint8_t exp_ctrl; + + /* Set initial value for POWER ctrl register. Chosen arbitrary. */ + initial_ctrl = TCPC_REG_POWER_CTRL_VBUS_VOL_MONITOR_DIS | + TCPC_REG_POWER_CTRL_FORCE_DISCHARGE; + tcpci_emul_set_reg(emul, TCPC_REG_POWER_CTRL, initial_ctrl); + + /* Test discharge enable */ + exp_ctrl = initial_ctrl | TCPC_REG_POWER_CTRL_AUTO_DISCHARGE_DISCONNECT; + drv->tcpc_enable_auto_discharge_disconnect(port, 1); + check_tcpci_reg(emul, TCPC_REG_POWER_CTRL, exp_ctrl); + + /* Test discharge disable */ + exp_ctrl = initial_ctrl & + ~TCPC_REG_POWER_CTRL_AUTO_DISCHARGE_DISCONNECT; + drv->tcpc_enable_auto_discharge_disconnect(port, 0); + check_tcpci_reg(emul, TCPC_REG_POWER_CTRL, exp_ctrl); +} + +/** Test TCPCI drp toggle */ +void test_tcpci_drp_toggle(const struct emul *emul, + struct i2c_common_emul_data *common_data, + enum usbc_port port) +{ + const struct tcpm_drv *drv = tcpc_config[port].drv; + uint8_t exp_tcpc_ctrl, exp_role_ctrl, initial_tcpc_ctrl; + + /* Test error on failed role CTRL set */ + i2c_common_emul_set_write_fail_reg(common_data, TCPC_REG_ROLE_CTRL); + zassert_equal(EC_ERROR_INVAL, drv->drp_toggle(port), NULL); + + /* Test error on failed TCPC CTRL set */ + i2c_common_emul_set_write_fail_reg(common_data, TCPC_REG_TCPC_CTRL); + zassert_equal(EC_ERROR_INVAL, drv->drp_toggle(port), NULL); + + /* Test error on failed command set */ + i2c_common_emul_set_write_fail_reg(common_data, TCPC_REG_COMMAND); + zassert_equal(EC_ERROR_INVAL, drv->drp_toggle(port), NULL); + i2c_common_emul_set_write_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Set initial value for TCPC ctrl register. Chosen arbitrary. */ + initial_tcpc_ctrl = TCPC_REG_TCPC_CTRL_DEBUG_ACC_CONTROL | + TCPC_REG_TCPC_CTRL_BIST_TEST_MODE; + tcpci_emul_set_reg(emul, TCPC_REG_TCPC_CTRL, initial_tcpc_ctrl); + + /* + * Test correct registers values for rev 2.0. Role control CC lines + * have to be set to RP with DRP enabled and smallest RP value. + */ + exp_tcpc_ctrl = initial_tcpc_ctrl | + TCPC_REG_TCPC_CTRL_EN_LOOK4CONNECTION_ALERT; + exp_role_ctrl = TCPC_REG_ROLE_CTRL_SET(TYPEC_DRP, TYPEC_RP_USB, + TYPEC_CC_RP, TYPEC_CC_RP); + zassert_equal(EC_SUCCESS, drv->drp_toggle(port), NULL); + check_tcpci_reg(emul, TCPC_REG_TCPC_CTRL, exp_tcpc_ctrl); + check_tcpci_reg(emul, TCPC_REG_ROLE_CTRL, exp_role_ctrl); + check_tcpci_reg(emul, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_LOOK4CONNECTION); + + /* Set TCPCI to revision 1 */ + tcpc_config[port].flags = 0; + tcpci_emul_set_rev(emul, TCPCI_EMUL_REV1_0_VER1_0); + + /* Set initial value for TCPC ctrl register. Chosen arbitrary. */ + initial_tcpc_ctrl = TCPC_REG_TCPC_CTRL_DEBUG_ACC_CONTROL | + TCPC_REG_TCPC_CTRL_BIST_TEST_MODE; + tcpci_emul_set_reg(emul, TCPC_REG_TCPC_CTRL, initial_tcpc_ctrl); + + /* + * Test correct registers values for rev 1.0. Role control CC lines + * have to be set to RD with DRP enabled and smallest RP value. + * Only CC lines setting is different from rev 2.0 + */ + exp_tcpc_ctrl = initial_tcpc_ctrl | + TCPC_REG_TCPC_CTRL_EN_LOOK4CONNECTION_ALERT; + exp_role_ctrl = TCPC_REG_ROLE_CTRL_SET(TYPEC_DRP, TYPEC_RP_USB, + TYPEC_CC_RD, TYPEC_CC_RD); + zassert_equal(EC_SUCCESS, drv->drp_toggle(port), NULL); + check_tcpci_reg(emul, TCPC_REG_TCPC_CTRL, exp_tcpc_ctrl); + check_tcpci_reg(emul, TCPC_REG_ROLE_CTRL, exp_role_ctrl); + check_tcpci_reg(emul, TCPC_REG_COMMAND, + TCPC_REG_COMMAND_LOOK4CONNECTION); +} + +/** Test TCPCI get chip info */ +void test_tcpci_get_chip_info(const struct emul *emul, + struct i2c_common_emul_data *common_data, + enum usbc_port port) +{ + const struct tcpm_drv *drv = tcpc_config[port].drv; + struct ec_response_pd_chip_info_v1 info; + uint16_t vendor, product, bcd; + + /* Test error on failed vendor id get */ + i2c_common_emul_set_read_fail_reg(common_data, TCPC_REG_VENDOR_ID); + zassert_equal(EC_ERROR_INVAL, drv->get_chip_info(port, 1, &info), NULL); + + /* Test error on failed product id get */ + i2c_common_emul_set_read_fail_reg(common_data, TCPC_REG_PRODUCT_ID); + zassert_equal(EC_ERROR_INVAL, drv->get_chip_info(port, 1, &info), NULL); + + /* Test error on failed BCD get */ + i2c_common_emul_set_read_fail_reg(common_data, TCPC_REG_VENDOR_ID); + zassert_equal(EC_ERROR_INVAL, drv->get_chip_info(port, 1, &info), NULL); + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Test reading chip info. Values chosen arbitrary. */ + vendor = 0x1234; + product = 0x5678; + bcd = 0x9876; + tcpci_emul_set_reg(emul, TCPC_REG_VENDOR_ID, vendor); + tcpci_emul_set_reg(emul, TCPC_REG_PRODUCT_ID, product); + tcpci_emul_set_reg(emul, TCPC_REG_BCD_DEV, bcd); + zassert_equal(EC_SUCCESS, drv->get_chip_info(port, 1, &info), NULL); + zassert_equal(vendor, info.vendor_id, NULL); + zassert_equal(product, info.product_id, NULL); + zassert_equal(bcd, info.device_id, NULL); + + /* Test reading cached chip info */ + info.vendor_id = 0; + info.product_id = 0; + info.device_id = 0; + /* Make sure, that TCPC is not accessed */ + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_FAIL_ALL_REG); + zassert_equal(EC_SUCCESS, drv->get_chip_info(port, 0, &info), NULL); + i2c_common_emul_set_read_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + zassert_equal(vendor, info.vendor_id, NULL); + zassert_equal(product, info.product_id, NULL); + zassert_equal(bcd, info.device_id, NULL); +} + +/** Test TCPCI enter low power mode */ +void test_tcpci_low_power_mode(const struct emul *emul, + struct i2c_common_emul_data *common_data, + enum usbc_port port) +{ + const struct tcpm_drv *drv = tcpc_config[port].drv; + + /* Test error on failed command set */ + i2c_common_emul_set_write_fail_reg(common_data, TCPC_REG_COMMAND); + zassert_equal(EC_ERROR_INVAL, drv->enter_low_power_mode(port), NULL); + i2c_common_emul_set_write_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Test correct command is issued */ + zassert_equal(EC_SUCCESS, drv->enter_low_power_mode(port), NULL); + check_tcpci_reg(emul, TCPC_REG_COMMAND, TCPC_REG_COMMAND_I2CIDLE); +} + +/** Test TCPCI set bist test mode */ +void test_tcpci_set_bist_mode(const struct emul *emul, + struct i2c_common_emul_data *common_data, + enum usbc_port port) +{ + const struct tcpm_drv *drv = tcpc_config[port].drv; + uint16_t exp_mask, initial_mask; + uint8_t exp_ctrl, initial_ctrl; + + /* Test error on TCPC CTRL set */ + i2c_common_emul_set_write_fail_reg(common_data, TCPC_REG_TCPC_CTRL); + zassert_equal(EC_ERROR_INVAL, drv->set_bist_test_mode(port, 1), NULL); + + /* Test error on alert mask set */ + i2c_common_emul_set_write_fail_reg(common_data, TCPC_REG_ALERT_MASK); + zassert_equal(EC_ERROR_INVAL, drv->set_bist_test_mode(port, 1), NULL); + i2c_common_emul_set_write_fail_reg(common_data, + I2C_COMMON_EMUL_NO_FAIL_REG); + + /* Set initial value for alert mask register. Chosen arbitrary. */ + initial_mask = TCPC_REG_ALERT_MASK_ALL; + tcpci_emul_set_reg(emul, TCPC_REG_ALERT_MASK, initial_mask); + + /* Set initial value for TCPC ctrl register. Chosen arbitrary. */ + initial_ctrl = TCPC_REG_TCPC_CTRL_DEBUG_ACC_CONTROL | + TCPC_REG_TCPC_CTRL_EN_LOOK4CONNECTION_ALERT; + tcpci_emul_set_reg(emul, TCPC_REG_TCPC_CTRL, initial_ctrl); + + /* Test enabling bist test mode */ + exp_mask = initial_mask & ~TCPC_REG_ALERT_RX_STATUS; + exp_ctrl = initial_ctrl | TCPC_REG_TCPC_CTRL_BIST_TEST_MODE; + zassert_equal(EC_SUCCESS, drv->set_bist_test_mode(port, 1), NULL); + check_tcpci_reg(emul, TCPC_REG_TCPC_CTRL, exp_ctrl); + check_tcpci_reg(emul, TCPC_REG_ALERT_MASK, exp_mask); + + /* Test disabling bist test mode */ + exp_mask = initial_mask | TCPC_REG_ALERT_RX_STATUS; + exp_ctrl = initial_ctrl & ~TCPC_REG_TCPC_CTRL_BIST_TEST_MODE; + zassert_equal(EC_SUCCESS, drv->set_bist_test_mode(port, 0), NULL); + check_tcpci_reg(emul, TCPC_REG_TCPC_CTRL, exp_ctrl); + check_tcpci_reg(emul, TCPC_REG_ALERT_MASK, exp_mask); +} + +void test_tcpci_hard_reset_reinit(const struct emul *emul, + struct i2c_common_emul_data *common_data, + enum usbc_port port) +{ + const struct tcpm_drv *drv = tcpc_config[port].drv; + uint16_t power_status_mask; + uint16_t alert_mask; + + zassume_equal(EC_SUCCESS, drv->init(port), NULL); + tcpci_emul_get_reg(emul, TCPC_REG_POWER_STATUS_MASK, + &power_status_mask); + tcpci_emul_get_reg(emul, TCPC_REG_ALERT_MASK, &alert_mask); + zassert_ok(tcpci_hard_reset_reinit(USBC_PORT_C0), NULL); + check_tcpci_reg(emul, TCPC_REG_POWER_STATUS_MASK, power_status_mask); + check_tcpci_reg(emul, TCPC_REG_ALERT_MASK, alert_mask); +} |