summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorSam Hurst <shurst@google.com>2017-08-05 13:24:40 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-10-24 15:30:15 -0700
commitc91dbb26d87573b9789a6a8b3e05eac3a9c205fa (patch)
tree145ef633cb7ebaf387da040557399afecc44188f /test
parent5fd1540e62be47747c4fe234a0b348e58e0cfd3f (diff)
downloadchrome-ec-c91dbb26d87573b9789a6a8b3e05eac3a9c205fa.tar.gz
PD: Make current USB PD Stack REV 3 compliant
Implement the following required features in the USB PD Rev. 3.0 specification. Not_supported control message: Inform a port partner that a particular message is not supported. Battery capabilities extended message: Report battery design capacity and last full charge capacity. Battery status data message: Report battery state of charge Collision avoidance: New scheme to avoid collisions caused when both source and sink want to send messages. Cable communication: Only the VCONN source can communicate with the cable plug. This is NOT implemented because although the drivers have the capability of communicating with a cable plug, the PD stack doesn't currently need to talk to a cable plug. This is okay since the current PD design doesn't source or sink more than 3 amps and all Type-C cables are required to be 3 amp capable. BUG=b:64411727 BRANCH=None TEST=`make -j buildall` Passed relevant PD Rev 2.0 compliance tests Successful PD negotiation with PD Rev 2.0 and 3.0 chargers Tested with low power none PD charger. Modified a Kevin to operate as a PD 3.0 charger and sent all required messages and verified the return messages. Also tested collision avoidance by verifying that a sink only transmits when the source indicates it's okay. Used Twinkie to verify that PD was operating as v3.0. Signed-off-by: Sam Hurst <shurst@chromium.org> Change-Id: Ifd77e92ec4e9106236f9221393d2bfb97263d979 Reviewed-on: https://chromium-review.googlesource.com/603003 Commit-Ready: Sam Hurst <shurst@google.com> Tested-by: Sam Hurst <shurst@google.com> Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Diffstat (limited to 'test')
-rw-r--r--test/build.mk2
-rw-r--r--test/test_config.h9
-rw-r--r--test/usb_pd.c229
l---------test/usb_pd_rev30.tasklist1
4 files changed, 215 insertions, 26 deletions
diff --git a/test/build.mk b/test/build.mk
index 20a55fb3fc..ed22aea4d5 100644
--- a/test/build.mk
+++ b/test/build.mk
@@ -76,6 +76,7 @@ test-list-host += thermal
test-list-host += timer_dos
test-list-host += usb_pd
test-list-host += usb_pd_giveback
+test-list-host += usb_pd_rev30
test-list-host += utils
test-list-host += utils_str
test-list-host += vboot
@@ -130,6 +131,7 @@ timer_calib-y=timer_calib.o
timer_dos-y=timer_dos.o
usb_pd-y=usb_pd.o
usb_pd_giveback-y=usb_pd.o
+usb_pd_rev30-y=usb_pd.o
utils-y=utils.o
utils_str-y=utils_str.o
vboot-y=vboot.o
diff --git a/test/test_config.h b/test/test_config.h
index a912e08a0d..5dd714f98b 100644
--- a/test/test_config.h
+++ b/test/test_config.h
@@ -167,7 +167,8 @@ int ncp15wb_calculate_temp(uint16_t adc);
#define CONFIG_ALS_LIGHTBAR_DIMMING 0
#endif
-#if defined(TEST_USB_PD) || defined(TEST_USB_PD_GIVEBACK)
+#if defined(TEST_USB_PD) || defined(TEST_USB_PD_GIVEBACK) || \
+ defined(TEST_USB_PD_REV30)
#define CONFIG_USB_POWER_DELIVERY
#define CONFIG_USB_PD_CUSTOM_VDM
#define CONFIG_USB_PD_DUAL_ROLE
@@ -176,10 +177,14 @@ int ncp15wb_calculate_temp(uint16_t adc);
#define CONFIG_USB_PD_TCPM_STUB
#define CONFIG_SHA256
#define CONFIG_SW_CRC
+#ifdef TEST_USB_PD_REV30
+#define CONFIG_USB_PD_REV30
+#define CONFIG_USB_PID 0x5000
+#endif
#ifdef TEST_USB_PD_GIVEBACK
#define CONFIG_USB_PD_GIVE_BACK
#endif
-#endif /* TEST_USB_PD || TEST_USB_PD_GIVEBACK */
+#endif /* TEST_USB_PD || TEST_USB_PD_GIVEBACK || TEST_USB_PD_REV30 */
#if defined(TEST_CHARGE_MANAGER) || defined(TEST_CHARGE_MANAGER_DRP_CHARGING)
#define CONFIG_CHARGE_MANAGER
diff --git a/test/usb_pd.c b/test/usb_pd.c
index 7133af28e9..69b7448ea6 100644
--- a/test/usb_pd.c
+++ b/test/usb_pd.c
@@ -4,7 +4,7 @@
*
* Test USB PD module.
*/
-
+#include "battery.h"
#include "common.h"
#include "crc.h"
#include "task.h"
@@ -17,6 +17,11 @@
#define PORT0 0
#define PORT1 1
+#define BATTERY_DESIGN_VOLTAGE 7600
+#define BATTERY_DESIGN_CAPACITY 5131
+#define BATTERY_FULL_CHARGE_CAPACITY 5131
+#define BATTERY_REMAINING_CAPACITY 2566
+
struct pd_port_t {
int host_mode;
int has_vbus;
@@ -25,11 +30,60 @@ struct pd_port_t {
int polarity;
int partner_role; /* -1 for none */
int partner_polarity;
+ int rev;
} pd_port[CONFIG_USB_PD_PORT_COUNT];
static int give_back_called;
/* Mock functions */
+#ifdef CONFIG_USB_PD_REV30
+
+uint16_t pd_get_identity_vid(int port)
+{
+ return 0;
+}
+
+uint16_t pd_get_identity_pid(int port)
+{
+ return 0;
+}
+
+enum battery_present battery_is_present(void)
+{
+ return BP_YES;
+}
+
+int battery_status(int *status)
+{
+ *status = 1;
+ return 0;
+}
+
+int battery_remaining_capacity(int *capacity)
+{
+ *capacity = BATTERY_REMAINING_CAPACITY;
+ return 0;
+}
+
+int battery_full_charge_capacity(int *capacity)
+{
+ *capacity = BATTERY_FULL_CHARGE_CAPACITY;
+ return 0;
+}
+
+int battery_design_capacity(int *capacity)
+{
+ *capacity = BATTERY_DESIGN_CAPACITY;
+ return 0;
+}
+
+int battery_design_voltage(int *voltage)
+{
+ *voltage = BATTERY_DESIGN_VOLTAGE;
+ return 0;
+}
+
+#endif
int pd_adc_read(int port, int cc)
{
@@ -97,6 +151,11 @@ static void init_ports(void)
pd_port[i].host_mode = 0;
pd_port[i].partner_role = -1;
pd_port[i].has_vbus = 0;
+#ifdef CONFIG_USB_PD_REV30
+ pd_port[i].rev = PD_REV30;
+#else
+ pd_port[i].rev = PD_REV20;
+#endif
}
}
@@ -127,7 +186,7 @@ static void simulate_wait(int port)
{
uint16_t header = PD_HEADER(PD_CTRL_WAIT, PD_ROLE_SOURCE,
PD_ROLE_DFP, pd_port[port].msg_rx_id,
- 0);
+ 0, pd_port[port].rev, 0);
simulate_rx_msg(port, header, 0, NULL);
}
@@ -136,7 +195,7 @@ static void simulate_accept(int port)
{
uint16_t header = PD_HEADER(PD_CTRL_ACCEPT, PD_ROLE_SOURCE,
PD_ROLE_DFP, pd_port[port].msg_rx_id,
- 0);
+ 0, pd_port[port].rev, 0);
simulate_rx_msg(port, header, 0, NULL);
}
@@ -145,35 +204,71 @@ static void simulate_reject(int port)
{
uint16_t header = PD_HEADER(PD_CTRL_REJECT, PD_ROLE_SOURCE,
PD_ROLE_DFP, pd_port[port].msg_rx_id,
- 0);
+ 0, pd_port[port].rev, 0);
simulate_rx_msg(port, header, 0, NULL);
}
+
+#ifdef CONFIG_USB_PD_REV30
+static void simulate_get_bat_cap(int port)
+{
+ uint16_t msg[2];
+ uint16_t header = PD_HEADER(PD_EXT_GET_BATTERY_CAP, PD_ROLE_SOURCE,
+ PD_ROLE_DFP, pd_port[port].msg_rx_id,
+ 1, pd_port[port].rev, 1);
+
+ /* set extended header */
+ msg[0] = PD_EXT_HEADER(0, 0, 1);
+
+ /* set battery status ref */
+ msg[1] = 0;
+
+ simulate_rx_msg(port, header, 1, (const uint32_t *)msg);
+}
+
+static void simulate_get_bat_status(int port)
+{
+ uint16_t msg[2];
+ uint16_t header = PD_HEADER(PD_EXT_GET_BATTERY_STATUS, PD_ROLE_SOURCE,
+ PD_ROLE_DFP, pd_port[port].msg_rx_id,
+ 1, pd_port[port].rev, 1);
+
+ /* set extended header */
+ msg[0] = PD_EXT_HEADER(0, 0, 1);
+
+ /* set battery status ref */
+ msg[1] = 0;
+
+ simulate_rx_msg(port, header, 1, (const uint32_t *)msg);
+}
+#endif
+
static void simulate_source_cap(int port, uint32_t cnt)
{
uint32_t src_pdo_cnt = (cnt == 0) ? 1 : pd_src_pdo_cnt;
uint16_t header = PD_HEADER(PD_DATA_SOURCE_CAP, PD_ROLE_SOURCE,
PD_ROLE_DFP, pd_port[port].msg_rx_id,
- src_pdo_cnt);
+ src_pdo_cnt, pd_port[port].rev, 0);
simulate_rx_msg(port, header, src_pdo_cnt, pd_src_pdo);
}
static void simulate_goodcrc(int port, int role, int id)
{
- simulate_rx_msg(port, PD_HEADER(PD_CTRL_GOOD_CRC, role, role, id, 0),
- 0, NULL);
+ simulate_rx_msg(port, PD_HEADER(PD_CTRL_GOOD_CRC, role, role, id, 0,
+ pd_port[port].rev, 0), 0, NULL);
}
static int verify_goodcrc(int port, int role, int id)
{
+
return pd_test_tx_msg_verify_sop(port) &&
- pd_test_tx_msg_verify_short(port, PD_HEADER(PD_CTRL_GOOD_CRC,
- role, role, id, 0)) &&
- pd_test_tx_msg_verify_crc(port) &&
- pd_test_tx_msg_verify_eop(port);
+ pd_test_tx_msg_verify_short(port, PD_HEADER(PD_CTRL_GOOD_CRC,
+ role, role, id, 0, 0, 0)) &&
+ pd_test_tx_msg_verify_crc(port) &&
+ pd_test_tx_msg_verify_eop(port);
}
static void plug_in_source(int port, int polarity)
@@ -210,7 +305,7 @@ static void simulate_ps_rdy(int port)
{
uint16_t header = PD_HEADER(PD_CTRL_PS_RDY, PD_ROLE_SOURCE,
PD_ROLE_DFP, pd_port[port].msg_rx_id,
- 0);
+ 0, pd_port[port].rev, 0);
simulate_rx_msg(port, header, 0, NULL);
}
@@ -218,13 +313,34 @@ static void simulate_ps_rdy(int port)
static void simulate_goto_min(int port)
{
uint16_t header = PD_HEADER(PD_CTRL_GOTO_MIN, PD_ROLE_SOURCE,
- PD_ROLE_DFP, pd_port[port].msg_rx_id, 0);
+ PD_ROLE_DFP, pd_port[port].msg_rx_id, 0, pd_port[port].rev, 0);
simulate_rx_msg(port, header, 0, NULL);
}
static int test_request_with_wait_and_contract(void)
{
+#ifdef CONFIG_USB_PD_REV30
+ uint32_t expected_status_bsdo =
+ BSDO_CAP(DIV_ROUND_NEAREST(BATTERY_REMAINING_CAPACITY *
+ BATTERY_DESIGN_VOLTAGE, 100000)) |
+ BSDO_PRESENT;
+ uint16_t expected_cap_hdr = PD_EXT_HEADER(0, 0, 9);
+ uint16_t expected_cap_vid = USB_VID_GOOGLE;
+#ifdef CONFIG_USB_PID
+ uint16_t expected_cap_pid = CONFIG_USB_PID;
+#else
+ uint16_t expected_cap_pid = 0;
+#endif
+ uint16_t expected_cap_des =
+ DIV_ROUND_NEAREST(BATTERY_DESIGN_CAPACITY *
+ BATTERY_DESIGN_VOLTAGE, 100000);
+ uint16_t expected_cap_ful =
+ DIV_ROUND_NEAREST(BATTERY_FULL_CHARGE_CAPACITY *
+ BATTERY_DESIGN_VOLTAGE, 100000);
+ uint16_t expected_cap_type = 0;
+#endif
+
#ifdef CONFIG_USB_PD_GIVE_BACK
uint32_t expected_rdo =
RDO_FIXED(2, 3000, PD_MIN_CURRENT_MA, RDO_GIVE_BACK);
@@ -253,7 +369,7 @@ static int test_request_with_wait_and_contract(void)
TEST_ASSERT(pd_test_tx_msg_verify_sop(port));
TEST_ASSERT(pd_test_tx_msg_verify_short(port,
PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK, PD_ROLE_UFP,
- pd_port[port].msg_tx_id, 1)));
+ pd_port[port].msg_tx_id, 1, pd_port[port].rev, 0)));
TEST_ASSERT(pd_test_tx_msg_verify_word(port, expected_rdo));
TEST_ASSERT(pd_test_tx_msg_verify_crc(port));
TEST_ASSERT(pd_test_tx_msg_verify_eop(port));
@@ -294,7 +410,7 @@ static int test_request_with_wait_and_contract(void)
TEST_ASSERT(pd_test_tx_msg_verify_sop(port));
TEST_ASSERT(pd_test_tx_msg_verify_short(port,
PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK, PD_ROLE_UFP,
- pd_port[port].msg_tx_id, 1)));
+ pd_port[port].msg_tx_id, 1, pd_port[port].rev, 0)));
TEST_ASSERT(pd_test_tx_msg_verify_word(port, expected_rdo));
TEST_ASSERT(pd_test_tx_msg_verify_crc(port));
TEST_ASSERT(pd_test_tx_msg_verify_eop(port));
@@ -326,7 +442,9 @@ static int test_request_with_wait_and_contract(void)
TEST_ASSERT(pd_test_tx_msg_verify_sop(port));
TEST_ASSERT(pd_test_tx_msg_verify_short(port,
PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK, PD_ROLE_UFP,
- pd_port[port].msg_tx_id, 1)));
+ pd_port[port].msg_tx_id, 1,
+ pd_port[port].rev, 0
+ )));
TEST_ASSERT(pd_test_tx_msg_verify_word(port, expected_rdo));
TEST_ASSERT(pd_test_tx_msg_verify_crc(port));
TEST_ASSERT(pd_test_tx_msg_verify_eop(port));
@@ -358,6 +476,69 @@ static int test_request_with_wait_and_contract(void)
task_wait_event(30 * MSEC);
inc_rx_id(port);
+ /*
+ * Test Extended Get_Battery_Cap and Get_Battery_Status messages.
+ */
+#ifdef CONFIG_USB_PD_REV30
+ /* We're in SNK_READY. Send get battery cap. */
+ simulate_get_bat_cap(port);
+ task_wait_event(30 * MSEC);
+ TEST_ASSERT(verify_goodcrc(0, PD_ROLE_SINK, pd_port[port].msg_rx_id));
+
+ task_wake(PD_PORT_TO_TASK_ID(port));
+ task_wait_event(30 * MSEC);
+ inc_rx_id(port);
+
+ /* Process the request */
+ TEST_ASSERT(pd_test_tx_msg_verify_sop(port));
+ TEST_ASSERT(pd_test_tx_msg_verify_short(port,
+ PD_HEADER(PD_EXT_BATTERY_CAP, PD_ROLE_SINK, PD_ROLE_UFP,
+ pd_port[port].msg_tx_id, 3, pd_port[port].rev, 1)));
+ TEST_ASSERT(pd_test_tx_msg_verify_short(port, expected_cap_hdr));
+ TEST_ASSERT(pd_test_tx_msg_verify_short(port, expected_cap_vid));
+ TEST_ASSERT(pd_test_tx_msg_verify_short(port, expected_cap_pid));
+ TEST_ASSERT(pd_test_tx_msg_verify_short(port, expected_cap_des));
+ TEST_ASSERT(pd_test_tx_msg_verify_short(port, expected_cap_ful));
+ TEST_ASSERT(pd_test_tx_msg_verify_short(port, expected_cap_type));
+ TEST_ASSERT(pd_test_tx_msg_verify_crc(port));
+ TEST_ASSERT(pd_test_tx_msg_verify_eop(port));
+
+ task_wake(PD_PORT_TO_TASK_ID(port));
+ task_wait_event(30 * MSEC);
+
+ /* Request was good. Send GoodCRC */
+ simulate_goodcrc(port, PD_ROLE_SOURCE, pd_port[port].msg_tx_id);
+ task_wake(PD_PORT_TO_TASK_ID(port));
+ task_wait_event(30 * MSEC);
+ inc_tx_id(port);
+
+ /* Send get battery status. */
+ simulate_get_bat_status(port);
+ task_wait_event(30 * MSEC);
+ TEST_ASSERT(verify_goodcrc(0, PD_ROLE_SINK, pd_port[port].msg_rx_id));
+
+ task_wake(PD_PORT_TO_TASK_ID(port));
+ task_wait_event(30 * MSEC);
+ inc_rx_id(port);
+
+ /* Process the request */
+ TEST_ASSERT(pd_test_tx_msg_verify_sop(port));
+ TEST_ASSERT(pd_test_tx_msg_verify_short(port,
+ PD_HEADER(PD_DATA_BATTERY_STATUS, PD_ROLE_SINK, PD_ROLE_UFP,
+ pd_port[port].msg_tx_id, 1, pd_port[port].rev, 0)));
+ TEST_ASSERT(pd_test_tx_msg_verify_word(port, expected_status_bsdo));
+ TEST_ASSERT(pd_test_tx_msg_verify_crc(port));
+ TEST_ASSERT(pd_test_tx_msg_verify_eop(port));
+
+ task_wake(PD_PORT_TO_TASK_ID(port));
+ task_wait_event(30 * MSEC);
+
+ /* Request was good. Send GoodCRC */
+ simulate_goodcrc(port, PD_ROLE_SOURCE, pd_port[port].msg_tx_id);
+ task_wake(PD_PORT_TO_TASK_ID(port));
+ task_wait_event(30 * MSEC);
+ inc_tx_id(port);
+#endif
/* We're in SNK_READY. Send goto_min */
simulate_goto_min(port);
task_wait_event(30 * MSEC);
@@ -372,7 +553,6 @@ static int test_request_with_wait_and_contract(void)
#else
TEST_ASSERT(!give_back_called);
#endif
-
/* We're done */
unplug(port);
@@ -409,7 +589,7 @@ static int test_request_with_wait(void)
TEST_ASSERT(pd_test_tx_msg_verify_sop(port));
TEST_ASSERT(pd_test_tx_msg_verify_short(port,
PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK, PD_ROLE_UFP,
- pd_port[port].msg_tx_id, 1)));
+ pd_port[port].msg_tx_id, 1, pd_port[port].rev, 0)));
TEST_ASSERT(pd_test_tx_msg_verify_word(port, expected_rdo));
TEST_ASSERT(pd_test_tx_msg_verify_crc(port));
TEST_ASSERT(pd_test_tx_msg_verify_eop(port));
@@ -448,7 +628,7 @@ static int test_request_with_wait(void)
TEST_ASSERT(pd_test_tx_msg_verify_sop(port));
TEST_ASSERT(pd_test_tx_msg_verify_short(port,
PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK, PD_ROLE_UFP,
- pd_port[port].msg_tx_id, 1)));
+ pd_port[port].msg_tx_id, 1, pd_port[port].rev, 0)));
TEST_ASSERT(pd_test_tx_msg_verify_word(port, expected_rdo));
TEST_ASSERT(pd_test_tx_msg_verify_crc(port));
TEST_ASSERT(pd_test_tx_msg_verify_eop(port));
@@ -497,7 +677,7 @@ static int test_request_with_reject(void)
TEST_ASSERT(pd_test_tx_msg_verify_sop(port));
TEST_ASSERT(pd_test_tx_msg_verify_short(port,
PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK, PD_ROLE_UFP,
- pd_port[port].msg_tx_id, 1)));
+ pd_port[port].msg_tx_id, 1, pd_port[port].rev, 0)));
TEST_ASSERT(pd_test_tx_msg_verify_word(port, expected_rdo));
TEST_ASSERT(pd_test_tx_msg_verify_crc(port));
TEST_ASSERT(pd_test_tx_msg_verify_eop(port));
@@ -535,7 +715,7 @@ static int test_request_with_reject(void)
TEST_ASSERT(pd_test_tx_msg_verify_sop(port));
TEST_ASSERT(pd_test_tx_msg_verify_short(port,
PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK, PD_ROLE_UFP,
- pd_port[port].msg_tx_id, 1)));
+ pd_port[port].msg_tx_id, 1, pd_port[port].rev, 0)));
TEST_ASSERT(pd_test_tx_msg_verify_word(port, expected_rdo));
TEST_ASSERT(pd_test_tx_msg_verify_crc(port));
TEST_ASSERT(pd_test_tx_msg_verify_eop(port));
@@ -575,7 +755,7 @@ static int test_request(void)
TEST_ASSERT(pd_test_tx_msg_verify_sop(port));
TEST_ASSERT(pd_test_tx_msg_verify_short(port,
PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK, PD_ROLE_UFP,
- pd_port[port].msg_tx_id, 1)));
+ pd_port[port].msg_tx_id, 1, pd_port[port].rev, 0)));
TEST_ASSERT(pd_test_tx_msg_verify_word(port, expected_rdo));
TEST_ASSERT(pd_test_tx_msg_verify_crc(port));
TEST_ASSERT(pd_test_tx_msg_verify_eop(port));
@@ -595,7 +775,6 @@ static int test_request(void)
return EC_SUCCESS;
}
-
static int test_sink(void)
{
int i;
@@ -611,7 +790,8 @@ static int test_sink(void)
TEST_ASSERT(pd_test_tx_msg_verify_short(port,
PD_HEADER(PD_DATA_SOURCE_CAP, PD_ROLE_SOURCE,
PD_ROLE_DFP, pd_port[port].msg_tx_id,
- pd_src_pdo_cnt)));
+ pd_src_pdo_cnt, pd_port[port].rev, 0)));
+
for (i = 0; i < pd_src_pdo_cnt; ++i)
TEST_ASSERT(pd_test_tx_msg_verify_word(port, pd_src_pdo[i]));
@@ -646,5 +826,6 @@ void run_test(void)
RUN_TEST(test_request_with_wait);
RUN_TEST(test_request_with_wait_and_contract);
RUN_TEST(test_request_with_reject);
+
test_print_result();
}
diff --git a/test/usb_pd_rev30.tasklist b/test/usb_pd_rev30.tasklist
new file mode 120000
index 0000000000..45cc6c8aa2
--- /dev/null
+++ b/test/usb_pd_rev30.tasklist
@@ -0,0 +1 @@
+usb_pd.tasklist \ No newline at end of file