pd: Add PE FRS unit test for new stack

BUG=none
BRANCH=none
TEST=make buildall -j

Change-Id: I55453ddf1d1da0fdee902a33e14357716fb12c4a
Signed-off-by: Denis Brockus <dbrockus@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1859826
Reviewed-by: Jett Rink <jettrink@chromium.org>
This commit is contained in:
Denis Brockus 2019-10-14 14:06:05 -06:00 committed by Commit Bot
parent 2dd2eecaa7
commit 7a4e700b64
12 changed files with 551 additions and 2 deletions

View File

@ -15,6 +15,7 @@ ifneq ($(CONFIG_USB_PE_SM),)
all-obj-$(CONFIG_USB_TYPEC_VPD)+=$(_usbc_dir)usb_pe_ctvpd_sm.o
all-obj-$(CONFIG_USB_TYPEC_CTVPD)+=$(_usbc_dir)usb_pe_ctvpd_sm.o
all-obj-$(CONFIG_USB_TYPEC_DRP_ACC_TRYSRC)+=$(_usbc_dir)usb_pe_drp_sm.o
all-obj-$(CONFIG_TEST_USB_PE_SM)+=$(_usbc_dir)usb_pe_drp_sm.o
endif
all-obj-$(CONFIG_USB_TYPEC_VPD)+=$(_usbc_dir)usb_tc_vpd_sm.o
all-obj-$(CONFIG_USB_TYPEC_CTVPD)+=$(_usbc_dir)usb_tc_ctvpd_sm.o

View File

@ -437,7 +437,8 @@ static struct svdm_amode_data *get_modep(int port, uint16_t svid);
#endif
test_export_static enum usb_pe_state get_state_pe(const int port);
static void set_state_pe(const int port, const enum usb_pe_state new_state);
test_export_static void set_state_pe(const int port,
const enum usb_pe_state new_state);
static void pe_init(int port)
{
@ -730,7 +731,8 @@ void pe_exit_dp_mode(int port)
*/
/* Set the TypeC state machine to a new state. */
static void set_state_pe(const int port, const enum usb_pe_state new_state)
test_export_static void set_state_pe(const int port,
const enum usb_pe_state new_state)
{
set_state(port, &pe[port].ctx, &pe_states[new_state]);
}
@ -3384,6 +3386,7 @@ static void pe_do_port_discovery_entry(int port)
static void pe_do_port_discovery_run(int port)
{
#ifdef CONFIG_USB_PD_ALT_MODE_DFP
uint32_t *payload = (uint32_t *)emsg[port].buf;
struct svdm_amode_data *modep = get_modep(port, PD_VDO_VID(payload[0]));
int ret = 0;
@ -3473,6 +3476,7 @@ static void pe_do_port_discovery_run(int port)
pe[port].vdm_cnt = ret;
set_state_pe(port, PE_VDM_REQUEST);
}
#endif
}
/**
@ -5138,4 +5142,25 @@ const struct test_sm_data test_pe_sm_data[] = {
},
};
const int test_pe_sm_data_size = ARRAY_SIZE(test_pe_sm_data);
void pe_set_flag(int port, int flag)
{
PE_SET_FLAG(port, flag);
}
void pe_clr_flag(int port, int flag)
{
PE_CLR_FLAG(port, flag);
}
int pe_chk_flag(int port, int flag)
{
return PE_CHK_FLAG(port, flag);
}
int pe_get_all_flags(int port)
{
return pe[port].flags;
}
void pe_set_all_flags(int port, int flags)
{
pe[port].flags = flags;
}
#endif

View File

@ -924,6 +924,12 @@
*/
#define CONFIG_USB_PE_SM
/*
* Define to enable Policy Engine State Machine. This is an override
* that is used to just pull in PE for unit testing.
*/
#undef CONFIG_TEST_USB_PE_SM
/*
* Board specific maximum input current limit, in mA.
*/

View File

@ -121,5 +121,12 @@ void prl_start_ams(int port);
*/
void prl_end_ams(int port);
#ifdef TEST_BUILD
/**
* Fake to track the last sent control message
*/
enum pd_ctrl_msg_type fake_prl_get_last_sent_ctrl_msg(int port);
#endif
#endif /* __CROS_EC_USB_PRL_H */

View File

@ -80,6 +80,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
test-list-host += usb_pe_drp
test-list-host += utils
test-list-host += utils_str
test-list-host += vboot
@ -158,6 +159,8 @@ usb_typec_ctvpd-y=usb_typec_ctvpd.o vpd_api.o usb_sm_checks.o
usb_typec_drp_acc_trysrc-y=usb_typec_drp_acc_trysrc.o vpd_api.o \
usb_sm_checks.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
utils-y=utils.o
utils_str-y=utils_str.o
vboot-y=vboot.o

42
test/fake_battery.c Normal file
View File

@ -0,0 +1,42 @@
/* Copyright 2019 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.
*
* Fake BATTERY module.
*/
#include "battery.h"
#include "common.h"
int battery_design_voltage(int *voltage)
{
*voltage = 0;
return 0;
}
enum battery_present battery_is_present(void)
{
return BP_NO;
}
int battery_design_capacity(int *capacity)
{
*capacity = 0;
return 0;
}
int battery_full_charge_capacity(int *capacity)
{
*capacity = 0;
return 0;
}
int battery_remaining_capacity(int *capacity)
{
*capacity = 0;
return 0;
}
int battery_status(int *status)
{
return EC_ERROR_UNIMPLEMENTED;
}

60
test/fake_prl.c Normal file
View File

@ -0,0 +1,60 @@
/* Copyright 2019 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.
*
* Fake Protocol Layer module.
*/
#include "common.h"
#include "usb_emsg.h"
#include "usb_prl_sm.h"
struct extended_msg emsg[CONFIG_USB_PD_PORT_COUNT];
void prl_end_ams(int port)
{}
void prl_execute_hard_reset(int port)
{}
enum pd_rev_type prl_get_rev(int port)
{
return PD_REV30;
}
void prl_hard_reset_complete(int port)
{}
int prl_is_running(int port)
{
return 0;
}
void prl_reset(int port)
{}
static enum pd_ctrl_msg_type last_ctrl_msg[CONFIG_USB_PD_PORT_COUNT];
void prl_send_ctrl_msg(int port, enum tcpm_transmit_type type,
enum pd_ctrl_msg_type msg)
{
last_ctrl_msg[port] = msg;
}
void prl_send_data_msg(int port, enum tcpm_transmit_type type,
enum pd_data_msg_type msg)
{}
void prl_send_ext_data_msg(int port, enum tcpm_transmit_type type,
enum pd_ext_msg_type msg)
{}
void prl_set_rev(int port, enum pd_rev_type rev)
{}
void prl_start_ams(int port)
{}
enum pd_ctrl_msg_type fake_prl_get_last_sent_ctrl_msg(int port)
{
return last_ctrl_msg[port];
}

116
test/fake_usbc.c Normal file
View File

@ -0,0 +1,116 @@
/* Copyright 2019 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.
*
* Test USB Type-C module.
*/
#include "common.h"
#include "usb_tc_sm.h"
int pd_is_vbus_present(int port)
{
return 0;
}
void pd_request_data_swap(int port)
{}
void pd_request_power_swap(int port)
{}
void pd_request_vconn_swap_off(int port)
{}
void pd_request_vconn_swap_on(int port)
{}
static int data_role;
int tc_get_data_role(int port)
{
return data_role;
}
void tc_set_data_role(int port, int role)
{
data_role = role;
}
static int power_role;
int tc_get_power_role(int port)
{
return power_role;
}
void tc_set_power_role(int port, int role)
{
power_role = role;
}
int tc_check_vconn_swap(int port)
{
return 0;
}
void tc_ctvpd_detected(int port)
{}
void tc_disc_ident_complete(int port)
{}
static int attached_snk;
int tc_is_attached_snk(int port)
{
return attached_snk;
}
static int attached_src;
int tc_is_attached_src(int port)
{
return attached_src;
}
int tc_is_vconn_src(int port)
{
return 0;
}
void tc_hard_reset(int port)
{}
void tc_partner_dr_data(int port, int en)
{}
void tc_partner_dr_power(int port, int en)
{}
void tc_partner_extpower(int port, int en)
{}
void tc_partner_usb_comm(int port, int en)
{}
void tc_pd_connection(int port, int en)
{}
void tc_pr_swap_complete(int port)
{}
void tc_prs_snk_src_assert_rp(int port)
{
attached_snk = 0;
attached_src = 1;
}
void tc_prs_src_snk_assert_rd(int port)
{
attached_snk = 1;
attached_src = 0;
}
void tc_set_timeout(int port, uint64_t timeout)
{}
void tc_start_error_recovery(int port)
{}
void tc_snk_power_off(int port)
{}

View File

@ -284,6 +284,19 @@ int ncp15wb_calculate_temp(uint16_t adc);
#define CONFIG_SW_CRC
#endif
#if defined(TEST_USB_PE_DRP)
#define CONFIG_TEST_USB_PE_SM
#define CONFIG_USB_PD_PORT_COUNT 1
#define CONFIG_USB_PE_SM
#define CONFIG_USB_PID 0x5036
#define CONFIG_USB_POWER_DELIVERY
#undef CONFIG_USB_PRL_SM
#define CONFIG_USB_SM_FRAMEWORK
#undef CONFIG_USB_TYPEC_SM
#define CONFIG_USBC_VCONN
#define PD_VCONN_SWAP_DELAY 5000 /* us */
#endif
/* Common TypeC tests defines */
#if defined(TEST_USB_TYPEC_VPD) || \
defined(TEST_USB_TYPEC_CTVPD) || \

133
test/usb_pe.h Normal file
View File

@ -0,0 +1,133 @@
/* Copyright 2019 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.
*
* Test USB PE module.
*/
#ifndef __CROS_TEST_USB_PE_H
#define __CROS_TEST_USB_PE_H
#include "common.h"
/*
* Test references to port
*/
#define PORT0 0
/*
* Parameters for pe_run
*
* pe_run(port, evt, enable)
* evt - currently ignored in the implementation
* enable - 0 Disable/1 Enable
*/
#define EVT_IGNORED 0
#define ENABLED 1
#define DISABLED 0
/**
* usb_pe_drp_sm.c locally defined. If it changes there, it must
* be changed here as well.
*/
/* Policy Engine Layer Flags */
#define PE_FLAGS_PD_CONNECTION BIT(0)
#define PE_FLAGS_ACCEPT BIT(1)
#define PE_FLAGS_PS_READY BIT(2)
#define PE_FLAGS_PROTOCOL_ERROR BIT(3)
#define PE_FLAGS_MODAL_OPERATION BIT(4)
#define PE_FLAGS_TX_COMPLETE BIT(5)
#define PE_FLAGS_MSG_RECEIVED BIT(6)
#define PE_FLAGS_HARD_RESET_PENDING BIT(7)
#define PE_FLAGS_WAIT BIT(8)
#define PE_FLAGS_EXPLICIT_CONTRACT BIT(9)
#define PE_FLAGS_SNK_WAIT_CAP_TIMEOUT BIT(10)
#define PE_FLAGS_PS_TRANSITION_TIMEOUT BIT(11)
#define PE_FLAGS_INTERRUPTIBLE_AMS BIT(12)
#define PE_FLAGS_PS_RESET_COMPLETE BIT(13)
#define PE_FLAGS_SEND_SVDM BIT(14)
#define PE_FLAGS_VCONN_SWAP_COMPLETE BIT(15)
#define PE_FLAGS_DISCOVER_PORT_IDENTITY_DONE BIT(16)
#define PE_FLAGS_DISCOVER_VDM_IDENTITY_DONE BIT(17)
#define PE_FLAGS_RUN_SOURCE_START_TIMER BIT(19)
#define PE_FLAGS_VDM_REQUEST_BUSY BIT(20)
#define PE_FLAGS_VDM_REQUEST_NAKED BIT(21)
#define PE_FLAGS_FAST_ROLE_SWAP_PATH BIT(22)/* FRS/PRS Exec Path */
#define PE_FLAGS_FAST_ROLE_SWAP_ENABLED BIT(23)/* FRS Listening State */
#define PE_FLAGS_FAST_ROLE_SWAP_SIGNALED BIT(24)/* FRS PPC/TCPC Signal */
/* List of all Policy Engine level states */
enum usb_pe_state {
/* Normal States */
PE_SRC_STARTUP,
PE_SRC_DISCOVERY,
PE_SRC_SEND_CAPABILITIES,
PE_SRC_NEGOTIATE_CAPABILITY,
PE_SRC_TRANSITION_SUPPLY,
PE_SRC_READY,
PE_SRC_DISABLED,
PE_SRC_CAPABILITY_RESPONSE,
PE_SRC_HARD_RESET,
PE_SRC_HARD_RESET_RECEIVED,
PE_SRC_TRANSITION_TO_DEFAULT,
PE_SRC_VDM_IDENTITY_REQUEST,
PE_SNK_STARTUP,
PE_SNK_DISCOVERY,
PE_SNK_WAIT_FOR_CAPABILITIES,
PE_SNK_EVALUATE_CAPABILITY,
PE_SNK_SELECT_CAPABILITY,
PE_SNK_READY,
PE_SNK_HARD_RESET,
PE_SNK_TRANSITION_TO_DEFAULT,
PE_SNK_GIVE_SINK_CAP,
PE_SNK_GET_SOURCE_CAP,
PE_SNK_TRANSITION_SINK,
PE_SEND_SOFT_RESET,
PE_SOFT_RESET,
PE_SEND_NOT_SUPPORTED,
PE_SRC_PING,
PE_GIVE_BATTERY_CAP,
PE_GIVE_BATTERY_STATUS,
PE_DRS_EVALUATE_SWAP,
PE_DRS_CHANGE,
PE_DRS_SEND_SWAP,
PE_PRS_SRC_SNK_EVALUATE_SWAP,
PE_PRS_SRC_SNK_TRANSITION_TO_OFF,
PE_PRS_SRC_SNK_WAIT_SOURCE_ON,
PE_PRS_SRC_SNK_SEND_SWAP,
PE_PRS_SNK_SRC_EVALUATE_SWAP,
PE_PRS_SNK_SRC_TRANSITION_TO_OFF,
PE_PRS_SNK_SRC_ASSERT_RP,
PE_PRS_SNK_SRC_SOURCE_ON,
PE_PRS_SNK_SRC_SEND_SWAP,
PE_FRS_SNK_SRC_START_AMS,
PE_VCS_EVALUATE_SWAP,
PE_VCS_SEND_SWAP,
PE_VCS_WAIT_FOR_VCONN_SWAP,
PE_VCS_TURN_ON_VCONN_SWAP,
PE_VCS_TURN_OFF_VCONN_SWAP,
PE_VCS_SEND_PS_RDY_SWAP,
PE_DO_PORT_DISCOVERY,
PE_VDM_REQUEST,
PE_VDM_ACKED,
PE_VDM_RESPONSE,
PE_HANDLE_CUSTOM_VDM_REQUEST,
PE_WAIT_FOR_ERROR_RECOVERY,
PE_BIST,
PE_DR_SNK_GET_SINK_CAP,
/* Super States */
PE_PRS_FRS_SHARED,
};
void set_state_pe(const int port, const enum usb_pe_state new_state);
enum usb_pe_state get_state_pe(const int port);
void pe_set_flag(int port, int flag);
void pe_clr_flag(int port, int flag);
int pe_chk_flag(int port, int flag);
int pe_get_all_flags(int port);
void pe_set_all_flags(int port, int flags);
#endif /* __CROS_TEST_USB_PE_H */

134
test/usb_pe_drp.c Normal file
View File

@ -0,0 +1,134 @@
/* Copyright 2019 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.
*
* Test USB PE module.
*/
#include "battery.h"
#include "common.h"
#include "task.h"
#include "test_util.h"
#include "timer.h"
#include "usb_emsg.h"
#include "usb_pe.h"
#include "usb_pe_sm.h"
#include "usb_prl_sm.h"
#include "usb_sm_checks.h"
#include "usb_tc_sm.h"
/**
* STUB Section
*/
const struct svdm_response svdm_rsp = {
.identity = NULL,
.svids = NULL,
.modes = NULL,
};
/**
* Test section
*/
/* PE Fast Role Swap */
static int test_pe_frs(void)
{
pe_run(PORT0, EVT_IGNORED, ENABLED);
TEST_ASSERT(pe_is_running(PORT0));
/*
* FRS will only trigger when we are SNK, with an Explicit
* contract. So set this state up manually
*/
tc_prs_src_snk_assert_rd(PORT0);
pe_set_flag(PORT0, PE_FLAGS_EXPLICIT_CONTRACT);
set_state_pe(PORT0, PE_SNK_READY);
pe_run(PORT0, EVT_IGNORED, ENABLED);
TEST_ASSERT(get_state_pe(PORT0) == PE_SNK_READY);
/*
* Trigger the Fast Role Switch from simulated ISR
*/
pe_got_frs_signal(PORT0);
TEST_ASSERT(pe_chk_flag(PORT0, PE_FLAGS_FAST_ROLE_SWAP_SIGNALED));
/*
* Verify we detected FRS and ready to start swap
*/
pe_run(PORT0, EVT_IGNORED, ENABLED);
TEST_ASSERT(get_state_pe(PORT0) == PE_PRS_SNK_SRC_SEND_SWAP);
TEST_ASSERT(pe_chk_flag(PORT0, PE_FLAGS_FAST_ROLE_SWAP_PATH));
TEST_ASSERT(!pe_chk_flag(PORT0, PE_FLAGS_EXPLICIT_CONTRACT));
/*
* Make sure that we sent FR_Swap
*/
pe_run(PORT0, EVT_IGNORED, ENABLED);
TEST_ASSERT(fake_prl_get_last_sent_ctrl_msg(PORT0) == PD_CTRL_FR_SWAP);
TEST_ASSERT(get_state_pe(PORT0) == PE_PRS_SNK_SRC_SEND_SWAP);
TEST_ASSERT(pe_chk_flag(PORT0, PE_FLAGS_FAST_ROLE_SWAP_PATH));
/*
* Accept the partners PS_RDY control message
*/
emsg[PORT0].header = PD_HEADER(PD_CTRL_ACCEPT, 0, 0, 0, 0, 0, 0);
pe_set_flag(PORT0, PE_FLAGS_MSG_RECEIVED);
pe_run(PORT0, EVT_IGNORED, ENABLED);
TEST_ASSERT(!pe_chk_flag(PORT0, PE_FLAGS_MSG_RECEIVED));
TEST_ASSERT(get_state_pe(PORT0) == PE_PRS_SNK_SRC_TRANSITION_TO_OFF);
TEST_ASSERT(pe_chk_flag(PORT0, PE_FLAGS_FAST_ROLE_SWAP_PATH));
/*
* Send back our PS_RDY
*/
emsg[PORT0].header = PD_HEADER(PD_CTRL_PS_RDY, 0, 0, 0, 0, 0, 0);
pe_set_flag(PORT0, PE_FLAGS_MSG_RECEIVED);
TEST_ASSERT(!tc_is_attached_src(PORT0));
pe_run(PORT0, EVT_IGNORED, ENABLED);
TEST_ASSERT(!pe_chk_flag(PORT0, PE_FLAGS_MSG_RECEIVED));
TEST_ASSERT(tc_is_attached_src(PORT0));
TEST_ASSERT(get_state_pe(PORT0) == PE_PRS_SNK_SRC_ASSERT_RP);
TEST_ASSERT(pe_chk_flag(PORT0, PE_FLAGS_FAST_ROLE_SWAP_PATH));
/*
* We are now attached source, so move to next state
*/
pe_run(PORT0, EVT_IGNORED, ENABLED);
TEST_ASSERT(get_state_pe(PORT0) == PE_PRS_SNK_SRC_SOURCE_ON);
TEST_ASSERT(pe_chk_flag(PORT0, PE_FLAGS_FAST_ROLE_SWAP_PATH));
/*
* Move the time to be after our wait time.
*/
force_time((timestamp_t)(get_time().val +
PD_POWER_SUPPLY_TURN_ON_DELAY));
/*
* After delay we are ready to send our PS_RDY
*/
pe_run(PORT0, EVT_IGNORED, ENABLED);
TEST_ASSERT(get_state_pe(PORT0) == PE_PRS_SNK_SRC_SOURCE_ON);
TEST_ASSERT(pe_chk_flag(PORT0, PE_FLAGS_FAST_ROLE_SWAP_PATH));
TEST_ASSERT(fake_prl_get_last_sent_ctrl_msg(PORT0) == PD_CTRL_PS_RDY);
/*
* Fake the Transmit complete and this will bring us to Source Startup
*/
pe_set_flag(PORT0, PE_FLAGS_TX_COMPLETE);
pe_run(PORT0, EVT_IGNORED, ENABLED);
TEST_ASSERT(get_state_pe(PORT0) == PE_SRC_STARTUP);
TEST_ASSERT(!pe_chk_flag(PORT0, PE_FLAGS_FAST_ROLE_SWAP_PATH));
return EC_SUCCESS;
}
void run_test(void)
{
test_reset();
RUN_TEST(test_pe_frs);
/* Do basic state machine sanity checks last. */
RUN_TEST(test_pe_no_parent_cycles);
RUN_TEST(test_pe_no_empty_state);
test_print_result();
}

9
test/usb_pe_drp.tasklist Normal file
View File

@ -0,0 +1,9 @@
/* Copyright 2019 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