diff options
author | Sam Hurst <shurst@google.com> | 2017-08-05 13:24:40 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-10-24 15:30:15 -0700 |
commit | c91dbb26d87573b9789a6a8b3e05eac3a9c205fa (patch) | |
tree | 145ef633cb7ebaf387da040557399afecc44188f /test | |
parent | 5fd1540e62be47747c4fe234a0b348e58e0cfd3f (diff) | |
download | chrome-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.mk | 2 | ||||
-rw-r--r-- | test/test_config.h | 9 | ||||
-rw-r--r-- | test/usb_pd.c | 229 | ||||
l--------- | test/usb_pd_rev30.tasklist | 1 |
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 |