tcpmv2: Add usb_tcpmv2_tcpci test
Add a new test that runs a full set of TCPMv2 layers and state machines, talking to a simulated TCPC via I2C. Initial test cases: 1) Plug in a non-PD power supply -> we connect as sink. 2) AP S5 > S3 > S0 -> auto-toggle + low power. BUG=b:161167893 BRANCH=none TEST=make -j run-usb_tcpmv2_tcpci Signed-off-by: Edward Hill <ecgh@chromium.org> Change-Id: If8b8eb2cca722ed01cbe1d6000fb3e4f4b70149c Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2283911 Reviewed-by: Paul Fagerburg <pfagerburg@chromium.org> Reviewed-by: Denis Brockus <dbrockus@chromium.org> Reviewed-by: Jett Rink <jettrink@chromium.org>
This commit is contained in:
parent
3d0b129896
commit
f0d3fff8b1
|
@ -63,6 +63,8 @@ const struct i2c_port_t i2c_ports[] = {
|
|||
{"battery", I2C_PORT_BATTERY, 100, 0, 0},
|
||||
#elif defined I2C_PORT_LIGHTBAR
|
||||
{"lightbar", I2C_PORT_LIGHTBAR, 100, 0, 0},
|
||||
#elif defined I2C_PORT_HOST_TCPC
|
||||
{"tcpc", I2C_PORT_HOST_TCPC, 100, 0, 0},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ mock-$(HAS_MOCK_MKBP_EVENTS) += mkbp_events_mock.o
|
|||
mock-$(HAS_MOCK_ROLLBACK) += rollback_mock.o
|
||||
mock-$(HAS_MOCK_TCPC) += tcpc_mock.o
|
||||
mock-$(HAS_MOCK_TCPM) += tcpm_mock.o
|
||||
mock-$(HAS_MOCK_TCPCI_I2C) += tcpci_i2c_mock.o
|
||||
mock-$(HAS_MOCK_TIMER) += timer_mock.o
|
||||
mock-$(HAS_MOCK_USB_MUX) += usb_mux_mock.o
|
||||
mock-$(HAS_MOCK_USB_PD) += usb_pd_mock.o
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
/* Copyright 2020 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "mock/tcpci_i2c_mock.h"
|
||||
#include "task.h"
|
||||
#include "tcpci.h"
|
||||
#include "test_util.h"
|
||||
|
||||
struct tcpci_reg {
|
||||
const char *name;
|
||||
uint8_t size;
|
||||
uint16_t value;
|
||||
};
|
||||
|
||||
#define TCPCI_REG(reg_name, reg_size) \
|
||||
[reg_name] = { .name = #reg_name, .size = (reg_size) }
|
||||
|
||||
static struct tcpci_reg tcpci_regs[] = {
|
||||
TCPCI_REG(TCPC_REG_VENDOR_ID, 2),
|
||||
TCPCI_REG(TCPC_REG_PRODUCT_ID, 2),
|
||||
TCPCI_REG(TCPC_REG_BCD_DEV, 2),
|
||||
TCPCI_REG(TCPC_REG_TC_REV, 2),
|
||||
TCPCI_REG(TCPC_REG_PD_REV, 2),
|
||||
TCPCI_REG(TCPC_REG_PD_INT_REV, 2),
|
||||
TCPCI_REG(TCPC_REG_ALERT, 2),
|
||||
TCPCI_REG(TCPC_REG_ALERT_MASK, 2),
|
||||
TCPCI_REG(TCPC_REG_POWER_STATUS_MASK, 1),
|
||||
TCPCI_REG(TCPC_REG_FAULT_STATUS_MASK, 1),
|
||||
TCPCI_REG(TCPC_REG_EXT_STATUS_MASK, 1),
|
||||
TCPCI_REG(TCPC_REG_ALERT_EXTENDED_MASK, 1),
|
||||
TCPCI_REG(TCPC_REG_CONFIG_STD_OUTPUT, 1),
|
||||
TCPCI_REG(TCPC_REG_TCPC_CTRL, 1),
|
||||
TCPCI_REG(TCPC_REG_ROLE_CTRL, 1),
|
||||
TCPCI_REG(TCPC_REG_FAULT_CTRL, 1),
|
||||
TCPCI_REG(TCPC_REG_POWER_CTRL, 1),
|
||||
TCPCI_REG(TCPC_REG_CC_STATUS, 1),
|
||||
TCPCI_REG(TCPC_REG_POWER_STATUS, 1),
|
||||
TCPCI_REG(TCPC_REG_FAULT_STATUS, 1),
|
||||
TCPCI_REG(TCPC_REG_ALERT_EXT, 1),
|
||||
TCPCI_REG(TCPC_REG_DEV_CAP_1, 2),
|
||||
TCPCI_REG(TCPC_REG_DEV_CAP_2, 2),
|
||||
TCPCI_REG(TCPC_REG_STD_INPUT_CAP, 1),
|
||||
TCPCI_REG(TCPC_REG_STD_OUTPUT_CAP, 1),
|
||||
TCPCI_REG(TCPC_REG_CONFIG_EXT_1, 1),
|
||||
TCPCI_REG(TCPC_REG_MSG_HDR_INFO, 1),
|
||||
TCPCI_REG(TCPC_REG_RX_DETECT, 1),
|
||||
TCPCI_REG(TCPC_REG_RX_BYTE_CNT, 1),
|
||||
TCPCI_REG(TCPC_REG_RX_BUF_FRAME_TYPE, 1),
|
||||
TCPCI_REG(TCPC_REG_TRANSMIT, 1),
|
||||
TCPCI_REG(TCPC_REG_VBUS_VOLTAGE, 2),
|
||||
TCPCI_REG(TCPC_REG_VBUS_SINK_DISCONNECT_THRESH, 2),
|
||||
TCPCI_REG(TCPC_REG_VBUS_STOP_DISCHARGE_THRESH, 2),
|
||||
TCPCI_REG(TCPC_REG_VBUS_VOLTAGE_ALARM_HI_CFG, 2),
|
||||
TCPCI_REG(TCPC_REG_VBUS_VOLTAGE_ALARM_LO_CFG, 2),
|
||||
TCPCI_REG(TCPC_REG_COMMAND, 1),
|
||||
};
|
||||
|
||||
void mock_tcpci_reset(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tcpci_regs); i++)
|
||||
tcpci_regs[i].value = 0;
|
||||
}
|
||||
|
||||
void mock_tcpci_set_reg(int reg_offset, uint16_t value)
|
||||
{
|
||||
struct tcpci_reg *reg = tcpci_regs + reg_offset;
|
||||
|
||||
reg->value = value;
|
||||
ccprints("TCPCI mock set %s = 0x%x", reg->name, reg->value);
|
||||
}
|
||||
|
||||
uint16_t mock_tcpci_get_reg(int reg_offset)
|
||||
{
|
||||
return tcpci_regs[reg_offset].value;
|
||||
}
|
||||
|
||||
int tcpci_i2c_xfer(int port, uint16_t slave_addr_flags,
|
||||
const uint8_t *out, int out_size,
|
||||
uint8_t *in, int in_size, int flags)
|
||||
{
|
||||
struct tcpci_reg *reg;
|
||||
|
||||
if (port != I2C_PORT_HOST_TCPC) {
|
||||
ccprints("ERROR: wrong I2C port %d", port);
|
||||
return EC_ERROR_UNKNOWN;
|
||||
}
|
||||
if (slave_addr_flags != MOCK_TCPCI_I2C_ADDR_FLAGS) {
|
||||
ccprints("ERROR: wrong I2C address 0x%x", slave_addr_flags);
|
||||
return EC_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
if (out_size == 0) {
|
||||
ccprints("ERROR: out_size == 0");
|
||||
return EC_ERROR_UNKNOWN;
|
||||
}
|
||||
reg = tcpci_regs + *out;
|
||||
if (*out >= ARRAY_SIZE(tcpci_regs) || reg->size == 0) {
|
||||
ccprints("ERROR: unknown reg 0x%x", *out);
|
||||
return EC_ERROR_UNKNOWN;
|
||||
}
|
||||
if (out_size == 1) {
|
||||
if (in_size != reg->size) {
|
||||
ccprints("ERROR: in_size != %d", reg->size);
|
||||
return EC_ERROR_UNKNOWN;
|
||||
}
|
||||
ccprints("%s TCPCI read %s = 0x%x",
|
||||
task_get_name(task_get_current()),
|
||||
reg->name, reg->value);
|
||||
if (reg->size == 1)
|
||||
in[0] = reg->value;
|
||||
else if (reg->size == 2) {
|
||||
in[0] = reg->value;
|
||||
in[1] = reg->value >> 8;
|
||||
}
|
||||
} else {
|
||||
uint16_t value = 0;
|
||||
|
||||
if (in_size != 0) {
|
||||
ccprints("ERROR: in_size != 0");
|
||||
return EC_ERROR_UNKNOWN;
|
||||
}
|
||||
if (out_size != reg->size + 1) {
|
||||
ccprints("ERROR: out_size != %d", reg->size + 1);
|
||||
return EC_ERROR_UNKNOWN;
|
||||
}
|
||||
if (reg->size == 1)
|
||||
value = out[1];
|
||||
else if (reg->size == 2)
|
||||
value = out[1] + (out[2] << 8);
|
||||
ccprints("%s TCPCI write %s = 0x%x",
|
||||
task_get_name(task_get_current()),
|
||||
reg->name, value);
|
||||
reg->value = value;
|
||||
}
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
DECLARE_TEST_I2C_XFER(tcpci_i2c_xfer);
|
|
@ -89,7 +89,7 @@ void schedule_deferred_pd_interrupt(const int port)
|
|||
*/
|
||||
void pd_interrupt_handler_task(void *p)
|
||||
{
|
||||
const int port = (int) p;
|
||||
const int port = (int) ((intptr_t) p);
|
||||
const int port_mask = (PD_STATUS_TCPC_ALERT_0 << port);
|
||||
struct {
|
||||
int count;
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
/* Copyright 2020 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define MOCK_TCPCI_I2C_ADDR_FLAGS 0x99
|
||||
|
||||
void mock_tcpci_reset(void);
|
||||
|
||||
void mock_tcpci_set_reg(int reg, uint16_t value);
|
||||
|
||||
uint16_t mock_tcpci_get_reg(int reg_offset);
|
|
@ -87,6 +87,7 @@ test-list-host += usb_typec_vpd
|
|||
test-list-host += usb_typec_ctvpd
|
||||
test-list-host += usb_typec_drp_acc_trysrc
|
||||
test-list-host += usb_prl_old
|
||||
test-list-host += usb_tcpmv2_tcpci
|
||||
test-list-host += usb_prl
|
||||
test-list-host += usb_pe_drp
|
||||
test-list-host += utils
|
||||
|
@ -198,6 +199,7 @@ usb_prl_old-y=usb_prl_old.o usb_sm_checks.o fake_usbc.o
|
|||
usb_prl-y=usb_prl.o usb_sm_checks.o
|
||||
usb_pe_drp-y=usb_pe_drp.o usb_sm_checks.o \
|
||||
fake_battery.o fake_prl.o fake_usbc.o
|
||||
usb_tcpmv2_tcpci-y=usb_tcpmv2_tcpci.o vpd_api.o usb_sm_checks.o
|
||||
utils-y=utils.o
|
||||
utils_str-y=utils_str.o
|
||||
vboot-y=vboot.o
|
||||
|
|
|
@ -409,6 +409,29 @@ int ncp15wb_calculate_temp(uint16_t adc);
|
|||
#undef CONFIG_USB_PD_HOST_CMD
|
||||
#endif
|
||||
|
||||
#ifdef TEST_USB_TCPMV2_TCPCI
|
||||
#define CONFIG_USB_DRP_ACC_TRYSRC
|
||||
#define CONFIG_USB_PD_DUAL_ROLE
|
||||
#define CONFIG_USB_PD_DUAL_ROLE_AUTO_TOGGLE
|
||||
#define CONFIG_USB_PD_TCPC_LOW_POWER
|
||||
#define CONFIG_USB_PD_TRY_SRC
|
||||
#define CONFIG_USB_PD_TCPMV2
|
||||
#define CONFIG_USB_PD_PORT_MAX_COUNT 1
|
||||
#define CONFIG_USBC_SS_MUX
|
||||
#define CONFIG_USB_PD_VBUS_DETECT_TCPC
|
||||
#define CONFIG_USB_POWER_DELIVERY
|
||||
#define CONFIG_TEST_USB_PE_SM
|
||||
#define CONFIG_USB_PD_ALT_MODE_DFP
|
||||
#define CONFIG_USBC_VCONN
|
||||
#define CONFIG_USBC_VCONN_SWAP
|
||||
#define CONFIG_USB_PID 0x5036
|
||||
#define PD_VCONN_SWAP_DELAY 5000 /* us */
|
||||
#define CONFIG_USB_PD_TCPM_TCPCI
|
||||
#define CONFIG_I2C
|
||||
#define CONFIG_I2C_MASTER
|
||||
#define I2C_PORT_HOST_TCPC 0
|
||||
#endif
|
||||
|
||||
#ifdef TEST_USB_PD_INT
|
||||
#define CONFIG_USB_POWER_DELIVERY
|
||||
#define CONFIG_USB_PD_TCPMV1
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
/* Copyright 2020 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "hooks.h"
|
||||
#include "mock/tcpci_i2c_mock.h"
|
||||
#include "mock/usb_mux_mock.h"
|
||||
#include "task.h"
|
||||
#include "tcpci.h"
|
||||
#include "test_util.h"
|
||||
#include "timer.h"
|
||||
#include "usb_mux.h"
|
||||
#include "usb_tc_sm.h"
|
||||
|
||||
#define PORT0 0
|
||||
|
||||
enum mock_cc_state {
|
||||
MOCK_CC_SRC_OPEN = 0,
|
||||
MOCK_CC_SNK_OPEN = 0,
|
||||
MOCK_CC_SRC_RA = 1,
|
||||
MOCK_CC_SNK_RP_DEF = 1,
|
||||
MOCK_CC_SRC_RD = 2,
|
||||
MOCK_CC_SNK_RP_1_5 = 2,
|
||||
MOCK_CC_SNK_RP_3_0 = 3,
|
||||
};
|
||||
enum mock_connect_result {
|
||||
MOCK_CC_WE_ARE_SRC = 0,
|
||||
MOCK_CC_WE_ARE_SNK = 1,
|
||||
};
|
||||
|
||||
__maybe_unused static void mock_set_cc(enum mock_connect_result cr,
|
||||
enum mock_cc_state cc1, enum mock_cc_state cc2)
|
||||
{
|
||||
mock_tcpci_set_reg(TCPC_REG_CC_STATUS,
|
||||
TCPC_REG_CC_STATUS_SET(cr, cc1, cc2));
|
||||
}
|
||||
|
||||
__maybe_unused static void mock_set_role(int drp, enum tcpc_rp_value rp,
|
||||
enum tcpc_cc_pull cc1, enum tcpc_cc_pull cc2)
|
||||
{
|
||||
mock_tcpci_set_reg(TCPC_REG_ROLE_CTRL,
|
||||
TCPC_REG_ROLE_CTRL_SET(drp, rp, cc1, cc2));
|
||||
}
|
||||
|
||||
static int mock_alert_count;
|
||||
|
||||
__maybe_unused static void mock_set_alert(int alert)
|
||||
{
|
||||
mock_tcpci_set_reg(TCPC_REG_ALERT, alert);
|
||||
mock_alert_count = 1;
|
||||
schedule_deferred_pd_interrupt(PORT0);
|
||||
}
|
||||
|
||||
uint16_t tcpc_get_alert_status(void)
|
||||
{
|
||||
ccprints("mock_alert_count %d", mock_alert_count);
|
||||
if (mock_alert_count > 0) {
|
||||
mock_alert_count--;
|
||||
return PD_STATUS_TCPC_ALERT_0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct svdm_response svdm_rsp = {
|
||||
.identity = NULL,
|
||||
.svids = NULL,
|
||||
.modes = NULL,
|
||||
};
|
||||
|
||||
int pd_check_vconn_swap(int port)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void board_reset_pd_mcu(void) {}
|
||||
|
||||
const struct tcpc_config_t tcpc_config[CONFIG_USB_PD_PORT_MAX_COUNT] = {
|
||||
{
|
||||
.bus_type = EC_BUS_TYPE_I2C,
|
||||
.i2c_info = {
|
||||
.port = I2C_PORT_HOST_TCPC,
|
||||
.addr_flags = MOCK_TCPCI_I2C_ADDR_FLAGS,
|
||||
},
|
||||
.drv = &tcpci_tcpm_drv,
|
||||
.flags = TCPC_FLAGS_TCPCI_REV2_0,
|
||||
},
|
||||
};
|
||||
|
||||
const struct usb_mux usb_muxes[CONFIG_USB_PD_PORT_MAX_COUNT] = {
|
||||
{
|
||||
.driver = &mock_usb_mux_driver,
|
||||
}
|
||||
};
|
||||
|
||||
__maybe_unused static int test_connect_as_sink(void)
|
||||
{
|
||||
task_wait_event(10 * SECOND);
|
||||
|
||||
/* Simulate a non-PD power supply being plugged in. */
|
||||
mock_set_cc(MOCK_CC_WE_ARE_SNK, MOCK_CC_SNK_OPEN, MOCK_CC_SNK_RP_3_0);
|
||||
mock_set_alert(TCPC_REG_ALERT_CC_STATUS);
|
||||
|
||||
task_wait_event(50 * MSEC);
|
||||
|
||||
mock_tcpci_set_reg(TCPC_REG_POWER_STATUS,
|
||||
TCPC_REG_POWER_STATUS_VBUS_PRES);
|
||||
mock_set_alert(TCPC_REG_ALERT_POWER_STATUS);
|
||||
|
||||
task_wait_event(10 * SECOND);
|
||||
TEST_EQ(tc_is_attached_snk(PORT0), true, "%d");
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
__maybe_unused static int test_startup_and_resume(void)
|
||||
{
|
||||
/* Should be in low power mode before AP boots. */
|
||||
TEST_EQ(mock_tcpci_get_reg(TCPC_REG_COMMAND),
|
||||
TCPC_REG_COMMAND_I2CIDLE, "%d");
|
||||
task_wait_event(10 * SECOND);
|
||||
|
||||
hook_notify(HOOK_CHIPSET_STARTUP);
|
||||
task_wait_event(5 * MSEC);
|
||||
hook_notify(HOOK_CHIPSET_RESUME);
|
||||
|
||||
task_wait_event(10 * SECOND);
|
||||
/* Should be in low power mode and DRP auto-toggling with AP in S0. */
|
||||
TEST_EQ((mock_tcpci_get_reg(TCPC_REG_ROLE_CTRL)
|
||||
& TCPC_REG_ROLE_CTRL_DRP_MASK),
|
||||
TCPC_REG_ROLE_CTRL_DRP_MASK, "%d");
|
||||
/* TODO: check previous command was TCPC_REG_COMMAND_LOOK4CONNECTION */
|
||||
TEST_EQ(mock_tcpci_get_reg(TCPC_REG_COMMAND),
|
||||
TCPC_REG_COMMAND_I2CIDLE, "%d");
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
void before_test(void)
|
||||
{
|
||||
mock_usb_mux_reset();
|
||||
mock_tcpci_reset();
|
||||
|
||||
/* Restart the PD task and let it settle */
|
||||
task_set_event(TASK_ID_PD_C0, TASK_EVENT_RESET_DONE, 0);
|
||||
task_wait_event(SECOND);
|
||||
}
|
||||
|
||||
void run_test(int argc, char **argv)
|
||||
{
|
||||
test_reset();
|
||||
|
||||
RUN_TEST(test_connect_as_sink);
|
||||
RUN_TEST(test_startup_and_resume);
|
||||
|
||||
test_print_result();
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
/* Copyright 2020 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#define CONFIG_TEST_MOCK_LIST \
|
||||
MOCK(USB_MUX) \
|
||||
MOCK(TCPCI_I2C)
|
|
@ -0,0 +1,11 @@
|
|||
/* Copyright 2020 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* See CONFIG_TEST_TASK_LIST in config.h for details.
|
||||
*/
|
||||
#define CONFIG_TEST_TASK_LIST \
|
||||
TASK_TEST(PD_C0, pd_task, NULL, LARGER_TASK_STACK_SIZE) \
|
||||
TASK_TEST(PD_INT_C0, pd_interrupt_handler_task, 0, LARGER_TASK_STACK_SIZE)
|
Loading…
Reference in New Issue