mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-27 18:25:05 +00:00
Add unit test for usb_pd
Initial commit of usb_pd unit test. The test cases are very simple. We'll add more test cases in similar format. BUG=chrome-os-partner:31200 TEST=Pass usb_pd test BRANCH=None Change-Id: I9e3de5b2c032ee1d3670cde6d8227ce0378ae8a0 Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/211643 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
This commit is contained in:
committed by
chrome-internal-fetch
parent
e68bdb6eb5
commit
0739074fbf
@@ -16,6 +16,11 @@
|
||||
#undef CONFIG_WATCHDOG
|
||||
#define CONFIG_SWITCH
|
||||
|
||||
#define CONFIG_USB_POWER_DELIVERY
|
||||
#define CONFIG_USB_PD_CUSTOM_VDM
|
||||
#define CONFIG_USB_PD_DUAL_ROLE
|
||||
#define CONFIG_SW_CRC
|
||||
|
||||
#undef CONFIG_CONSOLE_HISTORY
|
||||
#define CONFIG_CONSOLE_HISTORY 4
|
||||
|
||||
|
||||
@@ -12,3 +12,4 @@ board-y=board.o
|
||||
board-$(HAS_TASK_CHIPSET)+=chipset.o
|
||||
board-$(CONFIG_BATTERY_MOCK)+=battery.o charger.o
|
||||
board-$(CONFIG_FANS)+=fan.o
|
||||
board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o usb_pd_config.o
|
||||
|
||||
@@ -20,4 +20,6 @@
|
||||
#define CONFIG_TASK_LIST \
|
||||
TASK_ALWAYS(HOOKS, hook_task, NULL, TASK_STACK_SIZE) \
|
||||
TASK_ALWAYS(HOSTCMD, host_command_task, NULL, TASK_STACK_SIZE) \
|
||||
TASK_ALWAYS(CONSOLE, console_task, NULL, TASK_STACK_SIZE)
|
||||
TASK_ALWAYS(CONSOLE, console_task, NULL, TASK_STACK_SIZE) \
|
||||
TASK_ALWAYS(PD_C0, pd_task, NULL, LARGER_TASK_STACK_SIZE) \
|
||||
TASK_ALWAYS(PD_C1, pd_task, NULL, LARGER_TASK_STACK_SIZE)
|
||||
|
||||
35
board/host/usb_pd_config.c
Normal file
35
board/host/usb_pd_config.c
Normal file
@@ -0,0 +1,35 @@
|
||||
/* Copyright (c) 2014 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.
|
||||
*/
|
||||
|
||||
/* USB Power delivery board configuration */
|
||||
|
||||
#include "test_util.h"
|
||||
|
||||
test_mockable void pd_select_polarity(int port, int polarity)
|
||||
{
|
||||
/* Not implemented */
|
||||
}
|
||||
|
||||
test_mockable void pd_tx_init(void)
|
||||
{
|
||||
/* Not implemented */
|
||||
}
|
||||
|
||||
test_mockable void pd_set_host_mode(int port, int enable)
|
||||
{
|
||||
/* Not implemented */
|
||||
}
|
||||
|
||||
test_mockable int pd_adc_read(int port, int cc)
|
||||
{
|
||||
/* Not implemented */
|
||||
return 0;
|
||||
}
|
||||
|
||||
test_mockable int pd_snk_is_vbus_provided(int port)
|
||||
{
|
||||
/* Not implemented */
|
||||
return 1;
|
||||
}
|
||||
41
board/host/usb_pd_config.h
Normal file
41
board/host/usb_pd_config.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/* Copyright (c) 2014 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.
|
||||
*/
|
||||
|
||||
/* USB Power delivery board configuration */
|
||||
|
||||
#ifndef __USB_PD_CONFIG_H
|
||||
#define __USB_PD_CONFIG_H
|
||||
|
||||
/* Port and task configuration */
|
||||
#define PD_PORT_COUNT 2
|
||||
#define PORT_TO_TASK_ID(port) ((port) ? TASK_ID_PD_C1 : TASK_ID_PD_C0)
|
||||
#define TASK_ID_TO_PORT(id) ((id) == TASK_ID_PD_C0 ? 0 : 1)
|
||||
|
||||
/* Use software CRC */
|
||||
#define CONFIG_SW_CRC
|
||||
|
||||
void pd_select_polarity(int port, int polarity);
|
||||
|
||||
void pd_tx_init(void);
|
||||
|
||||
void pd_set_host_mode(int port, int enable);
|
||||
|
||||
int pd_adc_read(int port, int cc);
|
||||
|
||||
int pd_snk_is_vbus_provided(int port);
|
||||
|
||||
/* Standard-current DFP : no-connect voltage is 1.55V */
|
||||
#define PD_SRC_VNC 1550 /* mV */
|
||||
|
||||
/* UFP-side : threshold for DFP connection detection */
|
||||
#define PD_SNK_VA 200 /* mV */
|
||||
|
||||
/* start as a sink in case we have no other power supply/battery */
|
||||
#define PD_DEFAULT_STATE PD_STATE_SNK_DISCONNECTED
|
||||
|
||||
/* delay necessary for the voltage transition on the power supply */
|
||||
#define PD_POWER_SUPPLY_TRANSITION_DELAY 50000 /* us */
|
||||
|
||||
#endif /* __USB_PD_CONFIG_H */
|
||||
122
board/host/usb_pd_policy.c
Normal file
122
board/host/usb_pd_policy.c
Normal file
@@ -0,0 +1,122 @@
|
||||
/* Copyright (c) 2014 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"
|
||||
#include "console.h"
|
||||
#include "usb_pd.h"
|
||||
#include "util.h"
|
||||
|
||||
const uint32_t pd_src_pdo[] = {
|
||||
PDO_FIXED(5000, 500, PDO_FIXED_EXTERNAL),
|
||||
PDO_FIXED(5000, 900, 0),
|
||||
};
|
||||
const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo);
|
||||
|
||||
const uint32_t pd_snk_pdo[] = {
|
||||
PDO_BATT(4500, 5500, 15000),
|
||||
PDO_BATT(11500, 12500, 36000),
|
||||
};
|
||||
const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo);
|
||||
|
||||
/* Cap on the max voltage requested as a sink (in millivolts) */
|
||||
static unsigned max_mv = -1; /* no cap */
|
||||
|
||||
int pd_choose_voltage(int cnt, uint32_t *src_caps, uint32_t *rdo)
|
||||
{
|
||||
int i;
|
||||
int sel_mv;
|
||||
int max_uw = 0;
|
||||
int max_i = -1;
|
||||
|
||||
/* Get max power */
|
||||
for (i = 0; i < cnt; i++) {
|
||||
int uw;
|
||||
int mv = ((src_caps[i] >> 10) & 0x3FF) * 50;
|
||||
if ((src_caps[i] & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) {
|
||||
uw = 250000 * (src_caps[i] & 0x3FF);
|
||||
} else {
|
||||
int ma = (src_caps[i] & 0x3FF) * 10;
|
||||
uw = ma * mv;
|
||||
}
|
||||
if ((uw > max_uw) && (mv <= max_mv)) {
|
||||
max_i = i;
|
||||
max_uw = uw;
|
||||
sel_mv = mv;
|
||||
}
|
||||
}
|
||||
if (max_i < 0)
|
||||
return -EC_ERROR_UNKNOWN;
|
||||
|
||||
/* request all the power ... */
|
||||
if ((src_caps[max_i] & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) {
|
||||
int uw = 250000 * (src_caps[max_i] & 0x3FF);
|
||||
*rdo = RDO_BATT(max_i + 1, uw/2, uw, 0);
|
||||
ccprintf("Request [%d] %dV %d/%d mW\n",
|
||||
max_i, sel_mv/1000, uw/1000, uw/1000);
|
||||
} else {
|
||||
int ma = 10 * (src_caps[max_i] & 0x3FF);
|
||||
*rdo = RDO_FIXED(max_i + 1, ma / 2, ma, 0);
|
||||
ccprintf("Request [%d] %dV %d/%d mA\n",
|
||||
max_i, sel_mv/1000, max_i, ma/2, ma);
|
||||
}
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
void pd_set_max_voltage(unsigned mv)
|
||||
{
|
||||
max_mv = mv;
|
||||
}
|
||||
|
||||
int pd_request_voltage(uint32_t rdo)
|
||||
{
|
||||
int op_ma = rdo & 0x3FF;
|
||||
int max_ma = (rdo >> 10) & 0x3FF;
|
||||
int idx = rdo >> 28;
|
||||
uint32_t pdo;
|
||||
uint32_t pdo_ma;
|
||||
|
||||
if (!idx || idx > pd_src_pdo_cnt)
|
||||
return EC_ERROR_INVAL; /* Invalid index */
|
||||
|
||||
/* check current ... */
|
||||
pdo = pd_src_pdo[idx - 1];
|
||||
pdo_ma = (pdo & 0x3ff);
|
||||
if (op_ma > pdo_ma)
|
||||
return EC_ERROR_INVAL; /* too much op current */
|
||||
if (max_ma > pdo_ma)
|
||||
return EC_ERROR_INVAL; /* too much max current */
|
||||
|
||||
ccprintf("Switch to %d V %d mA (for %d/%d mA)\n",
|
||||
((pdo >> 10) & 0x3ff) * 50, (pdo & 0x3ff) * 10,
|
||||
((rdo >> 10) & 0x3ff) * 10, (rdo & 0x3ff) * 10);
|
||||
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
int pd_set_power_supply_ready(int port)
|
||||
{
|
||||
/* Not implemented */
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
void pd_power_supply_reset(int port)
|
||||
{
|
||||
/* Not implemented */
|
||||
}
|
||||
|
||||
void pd_set_input_current_limit(uint32_t max_ma)
|
||||
{
|
||||
/* Not implemented */
|
||||
}
|
||||
|
||||
int pd_board_checks(void)
|
||||
{
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
int pd_custom_vdm(int port, int cnt, uint32_t *payload, uint32_t **rpayload)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -11,3 +11,4 @@ CORE:=host
|
||||
chip-y=system.o gpio.o uart.o persistence.o flash.o lpc.o reboot.o i2c.o \
|
||||
clock.o
|
||||
chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o
|
||||
chip-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_phy.o
|
||||
|
||||
289
chip/host/usb_pd_phy.c
Normal file
289
chip/host/usb_pd_phy.c
Normal file
@@ -0,0 +1,289 @@
|
||||
/* Copyright 2014 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"
|
||||
#include "console.h"
|
||||
#include "crc.h"
|
||||
#include "task.h"
|
||||
#include "usb_pd.h"
|
||||
#include "usb_pd_config.h"
|
||||
#include "util.h"
|
||||
|
||||
#define PREAMBLE_OFFSET 60 /* Any number should do */
|
||||
|
||||
/*
|
||||
* Maximum size of a Power Delivery packet (in bits on the wire) :
|
||||
* 16-bit header + 0..7 32-bit data objects (+ 4b5b encoding)
|
||||
* 64-bit preamble + SOP (4x 5b) + message in 4b5b + 32-bit CRC + EOP (1x 5b)
|
||||
* = 64 + 4*5 + 16 * 5/4 + 7 * 32 * 5/4 + 32 * 5/4 + 5
|
||||
*/
|
||||
#define PD_BIT_LEN 429
|
||||
|
||||
static struct pd_physical {
|
||||
int hw_init_done;
|
||||
|
||||
uint8_t bits[PD_BIT_LEN];
|
||||
int total;
|
||||
int has_preamble;
|
||||
int rx_started;
|
||||
int rx_monitoring;
|
||||
|
||||
int preamble_written;
|
||||
int has_msg;
|
||||
int last_edge_written;
|
||||
uint8_t out_msg[PD_BIT_LEN / 5];
|
||||
int verified_idx;
|
||||
} pd_phy[PD_PORT_COUNT];
|
||||
|
||||
static const uint16_t enc4b5b[] = {
|
||||
0x1E, 0x09, 0x14, 0x15, 0x0A, 0x0B, 0x0E, 0x0F, 0x12, 0x13, 0x16,
|
||||
0x17, 0x1A, 0x1B, 0x1C, 0x1D};
|
||||
|
||||
/* Test utilities */
|
||||
|
||||
void pd_test_rx_set_preamble(int port, int has_preamble)
|
||||
{
|
||||
pd_phy[port].has_preamble = has_preamble;
|
||||
}
|
||||
|
||||
void pd_test_rx_msg_append_bits(int port, uint32_t bits, int nb)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nb; ++i) {
|
||||
pd_phy[port].bits[pd_phy[port].total++] = bits & 1;
|
||||
bits >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void pd_test_rx_msg_append_kcode(int port, uint8_t kcode)
|
||||
{
|
||||
pd_test_rx_msg_append_bits(port, kcode, 5);
|
||||
}
|
||||
|
||||
void pd_test_rx_msg_append_sop(int port)
|
||||
{
|
||||
pd_test_rx_msg_append_kcode(port, PD_SYNC1);
|
||||
pd_test_rx_msg_append_kcode(port, PD_SYNC1);
|
||||
pd_test_rx_msg_append_kcode(port, PD_SYNC1);
|
||||
pd_test_rx_msg_append_kcode(port, PD_SYNC2);
|
||||
}
|
||||
|
||||
void pd_test_rx_msg_append_eop(int port)
|
||||
{
|
||||
pd_test_rx_msg_append_kcode(port, PD_EOP);
|
||||
}
|
||||
|
||||
void pd_test_rx_msg_append_4b(int port, uint8_t val)
|
||||
{
|
||||
pd_test_rx_msg_append_bits(port, enc4b5b[val & 0xF], 5);
|
||||
}
|
||||
|
||||
void pd_test_rx_msg_append_short(int port, uint16_t val)
|
||||
{
|
||||
pd_test_rx_msg_append_4b(port, (val >> 0) & 0xF);
|
||||
pd_test_rx_msg_append_4b(port, (val >> 4) & 0xF);
|
||||
pd_test_rx_msg_append_4b(port, (val >> 8) & 0xF);
|
||||
pd_test_rx_msg_append_4b(port, (val >> 12) & 0xF);
|
||||
}
|
||||
|
||||
void pd_test_rx_msg_append_word(int port, uint32_t val)
|
||||
{
|
||||
pd_test_rx_msg_append_short(port, val & 0xFFFF);
|
||||
pd_test_rx_msg_append_short(port, val >> 16);
|
||||
}
|
||||
|
||||
void pd_simulate_rx(int port)
|
||||
{
|
||||
if (!pd_phy[port].rx_monitoring)
|
||||
return;
|
||||
pd_rx_start(port);
|
||||
pd_rx_disable_monitoring(port);
|
||||
pd_rx_event(port);
|
||||
}
|
||||
|
||||
static int pd_test_tx_msg_verify(int port, uint8_t raw)
|
||||
{
|
||||
int verified_idx = pd_phy[port].verified_idx++;
|
||||
return pd_phy[port].out_msg[verified_idx] == raw;
|
||||
}
|
||||
|
||||
int pd_test_tx_msg_verify_kcode(int port, uint8_t kcode)
|
||||
{
|
||||
return pd_test_tx_msg_verify(port, kcode);
|
||||
}
|
||||
|
||||
int pd_test_tx_msg_verify_sop(int port)
|
||||
{
|
||||
crc32_init();
|
||||
return pd_test_tx_msg_verify_kcode(port, PD_SYNC1) &&
|
||||
pd_test_tx_msg_verify_kcode(port, PD_SYNC1) &&
|
||||
pd_test_tx_msg_verify_kcode(port, PD_SYNC1) &&
|
||||
pd_test_tx_msg_verify_kcode(port, PD_SYNC2);
|
||||
}
|
||||
|
||||
int pd_test_tx_msg_verify_eop(int port)
|
||||
{
|
||||
return pd_test_tx_msg_verify_kcode(port, PD_EOP);
|
||||
}
|
||||
|
||||
int pd_test_tx_msg_verify_4b5b(int port, uint8_t b4)
|
||||
{
|
||||
return pd_test_tx_msg_verify(port, enc4b5b[b4]);
|
||||
}
|
||||
|
||||
int pd_test_tx_msg_verify_short(int port, uint16_t val)
|
||||
{
|
||||
crc32_hash16(val);
|
||||
return pd_test_tx_msg_verify_4b5b(port, (val >> 0) & 0xF) &&
|
||||
pd_test_tx_msg_verify_4b5b(port, (val >> 4) & 0xF) &&
|
||||
pd_test_tx_msg_verify_4b5b(port, (val >> 8) & 0xF) &&
|
||||
pd_test_tx_msg_verify_4b5b(port, (val >> 12) & 0xF);
|
||||
}
|
||||
|
||||
int pd_test_tx_msg_verify_word(int port, uint32_t val)
|
||||
{
|
||||
return pd_test_tx_msg_verify_short(port, val & 0xFFFF) &&
|
||||
pd_test_tx_msg_verify_short(port, val >> 16);
|
||||
}
|
||||
|
||||
int pd_test_tx_msg_verify_crc(int port)
|
||||
{
|
||||
return pd_test_tx_msg_verify_word(port, crc32_result());
|
||||
}
|
||||
|
||||
|
||||
/* Mock functions */
|
||||
|
||||
void pd_init_dequeue(int port)
|
||||
{
|
||||
}
|
||||
|
||||
int pd_dequeue_bits(int port, int off, int len, uint32_t *val)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Rx must have started to receive message */
|
||||
ASSERT(pd_phy[port].rx_started);
|
||||
|
||||
if (pd_phy[port].total <= off + len - PREAMBLE_OFFSET)
|
||||
return -1;
|
||||
*val = 0;
|
||||
for (i = 0; i < len; ++i)
|
||||
*val |= pd_phy[port].bits[off + i - PREAMBLE_OFFSET] << i;
|
||||
return off + len;
|
||||
}
|
||||
|
||||
int pd_find_preamble(int port)
|
||||
{
|
||||
return pd_phy[port].has_preamble ? PREAMBLE_OFFSET : -1;
|
||||
}
|
||||
|
||||
int pd_write_preamble(int port)
|
||||
{
|
||||
ASSERT(pd_phy[port].preamble_written == 0);
|
||||
pd_phy[port].preamble_written = 1;
|
||||
ASSERT(pd_phy[port].has_msg == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t decode_bmc(uint32_t val10)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 5; ++i)
|
||||
if (!!(val10 & (1 << (2 * i))) !=
|
||||
!!(val10 & (1 << (2 * i + 1))))
|
||||
ret |= (1 << i);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pd_write_sym(int port, int bit_off, uint32_t val10)
|
||||
{
|
||||
pd_phy[port].out_msg[bit_off] = decode_bmc(val10);
|
||||
pd_phy[port].has_msg = 1;
|
||||
return bit_off + 1;
|
||||
}
|
||||
|
||||
int pd_write_last_edge(int port, int bit_off)
|
||||
{
|
||||
pd_phy[port].last_edge_written = 1;
|
||||
return bit_off;
|
||||
}
|
||||
|
||||
void pd_dump_packet(int port, const char *msg)
|
||||
{
|
||||
/* Not implemented */
|
||||
}
|
||||
|
||||
void pd_tx_set_circular_mode(int port)
|
||||
{
|
||||
/* Not implemented */
|
||||
}
|
||||
|
||||
void pd_start_tx(int port, int polarity, int bit_len)
|
||||
{
|
||||
ASSERT(pd_phy[port].hw_init_done);
|
||||
pd_phy[port].has_msg = 0;
|
||||
pd_phy[port].preamble_written = 0;
|
||||
pd_phy[port].verified_idx = 0;
|
||||
|
||||
/*
|
||||
* Hand over to test runner. The test runner must wake us after
|
||||
* processing the packet.
|
||||
*/
|
||||
task_wake(TASK_ID_TEST_RUNNER);
|
||||
task_wait_event(-1);
|
||||
}
|
||||
|
||||
void pd_tx_done(int port, int polarity)
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
void pd_rx_start(int port)
|
||||
{
|
||||
ASSERT(pd_phy[port].hw_init_done);
|
||||
pd_phy[port].rx_started = 1;
|
||||
}
|
||||
|
||||
void pd_rx_complete(int port)
|
||||
{
|
||||
ASSERT(pd_phy[port].hw_init_done);
|
||||
pd_phy[port].rx_started = 0;
|
||||
}
|
||||
|
||||
int pd_rx_started(int port)
|
||||
{
|
||||
return pd_phy[port].rx_started;
|
||||
}
|
||||
|
||||
void pd_rx_enable_monitoring(int port)
|
||||
{
|
||||
ASSERT(pd_phy[port].hw_init_done);
|
||||
pd_phy[port].rx_monitoring = 1;
|
||||
}
|
||||
|
||||
void pd_rx_disable_monitoring(int port)
|
||||
{
|
||||
ASSERT(pd_phy[port].hw_init_done);
|
||||
pd_phy[port].rx_monitoring = 0;
|
||||
}
|
||||
|
||||
void pd_hw_release(int port)
|
||||
{
|
||||
pd_phy[port].hw_init_done = 0;
|
||||
}
|
||||
|
||||
void pd_hw_init(int port)
|
||||
{
|
||||
pd_phy[port].hw_init_done = 1;
|
||||
}
|
||||
|
||||
void pd_set_clock(int port, int freq)
|
||||
{
|
||||
/* Not implemented */
|
||||
}
|
||||
@@ -31,18 +31,20 @@ test-list-host+=thermal flash queue kb_8042 extpwr_gpio console_edit system
|
||||
test-list-host+=sbs_charging adapter host_command thermal_falco led_spring
|
||||
test-list-host+=bklight_lid bklight_passthru interrupt timer_dos button
|
||||
test-list-host+=motion_sense math_util sbs_charging_v2 battery_get_params_smart
|
||||
test-list-host+=usb_pd
|
||||
|
||||
adapter-y=adapter.o
|
||||
button-y=button.o
|
||||
battery_get_params_smart-y=battery_get_params_smart.o
|
||||
bklight_lid-y=bklight_lid.o
|
||||
bklight_passthru-y=bklight_passthru.o
|
||||
button-y=button.o
|
||||
console_edit-y=console_edit.o
|
||||
extpwr_gpio-y=extpwr_gpio.o
|
||||
flash-y=flash.o
|
||||
hooks-y=hooks.o
|
||||
host_command-y=host_command.o
|
||||
kb_8042-y=kb_8042.o
|
||||
interrupt-y=interrupt.o
|
||||
kb_8042-y=kb_8042.o
|
||||
kb_mkbp-y=kb_mkbp.o
|
||||
kb_scan-y=kb_scan.o
|
||||
led_spring-y=led_spring.o led_spring_impl.o
|
||||
@@ -62,5 +64,5 @@ thermal-y=thermal.o
|
||||
thermal_falco-y=thermal_falco.o
|
||||
timer_calib-y=timer_calib.o
|
||||
timer_dos-y=timer_dos.o
|
||||
usb_pd-y=usb_pd.o
|
||||
utils-y=utils.o
|
||||
battery_get_params_smart-y=battery_get_params_smart.o
|
||||
|
||||
204
test/usb_pd.c
Normal file
204
test/usb_pd.c
Normal file
@@ -0,0 +1,204 @@
|
||||
/* Copyright 2014 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 PD module.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "crc.h"
|
||||
#include "task.h"
|
||||
#include "test_util.h"
|
||||
#include "timer.h"
|
||||
#include "usb_pd.h"
|
||||
#include "usb_pd_config.h"
|
||||
#include "usb_pd_test_util.h"
|
||||
#include "util.h"
|
||||
|
||||
struct pd_port_t {
|
||||
int host_mode;
|
||||
int cc_volt[2]; /* -1 for Hi-Z */
|
||||
int has_vbus;
|
||||
int msg_tx_id;
|
||||
int msg_rx_id;
|
||||
int polarity;
|
||||
} pd_port[PD_PORT_COUNT];
|
||||
|
||||
/* Mock functions */
|
||||
|
||||
int pd_adc_read(int port, int cc)
|
||||
{
|
||||
int val = pd_port[port].cc_volt[cc];
|
||||
if (val == -1)
|
||||
return pd_port[port].host_mode ? 3000 : 0;
|
||||
return val;
|
||||
}
|
||||
|
||||
int pd_snk_is_vbus_provided(int port)
|
||||
{
|
||||
return pd_port[port].has_vbus;
|
||||
}
|
||||
|
||||
void pd_set_host_mode(int port, int enable)
|
||||
{
|
||||
pd_port[port].host_mode = enable;
|
||||
}
|
||||
|
||||
void pd_select_polarity(int port, int polarity)
|
||||
{
|
||||
pd_port[port].polarity = polarity;
|
||||
}
|
||||
|
||||
/* Tests */
|
||||
|
||||
void inc_tx_id(int port)
|
||||
{
|
||||
pd_port[port].msg_tx_id = (pd_port[port].msg_tx_id + 1) % 7;
|
||||
}
|
||||
|
||||
void inc_rx_id(int port)
|
||||
{
|
||||
pd_port[port].msg_rx_id = (pd_port[port].msg_rx_id + 1) % 7;
|
||||
}
|
||||
|
||||
static void init_ports(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PD_PORT_COUNT; ++i) {
|
||||
pd_port[i].host_mode = 0;
|
||||
pd_port[i].cc_volt[0] = pd_port[i].cc_volt[1] = -1;
|
||||
pd_port[i].has_vbus = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void simulate_rx_msg(int port, uint16_t header, int cnt,
|
||||
const uint32_t *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
pd_test_rx_set_preamble(port, 1);
|
||||
pd_test_rx_msg_append_sop(port);
|
||||
pd_test_rx_msg_append_short(port, header);
|
||||
|
||||
crc32_init();
|
||||
crc32_hash16(header);
|
||||
for (i = 0; i < cnt; ++i) {
|
||||
pd_test_rx_msg_append_word(port, data[i]);
|
||||
crc32_hash32(data[i]);
|
||||
}
|
||||
pd_test_rx_msg_append_word(port, crc32_result());
|
||||
|
||||
pd_test_rx_msg_append_eop(port);
|
||||
|
||||
pd_simulate_rx(port);
|
||||
}
|
||||
|
||||
static void simulate_source_cap(int port)
|
||||
{
|
||||
uint16_t header = PD_HEADER(PD_DATA_SOURCE_CAP, PD_ROLE_SOURCE,
|
||||
pd_port[port].msg_rx_id, pd_src_pdo_cnt);
|
||||
simulate_rx_msg(port, header, pd_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, id, 0),
|
||||
0, NULL);
|
||||
}
|
||||
|
||||
static int verify_goodcrc(int port, int role, int id)
|
||||
{
|
||||
return pd_test_tx_msg_verify_sop(0) &&
|
||||
pd_test_tx_msg_verify_short(0, PD_HEADER(PD_CTRL_GOOD_CRC,
|
||||
role, id, 0)) &&
|
||||
pd_test_tx_msg_verify_crc(0) &&
|
||||
pd_test_tx_msg_verify_eop(0);
|
||||
}
|
||||
|
||||
static void plug_in_source(int port, int polarity)
|
||||
{
|
||||
pd_port[port].has_vbus = 1;
|
||||
pd_port[port].cc_volt[polarity] = 3000;
|
||||
}
|
||||
|
||||
static void plug_in_sink(int port, int polarity)
|
||||
{
|
||||
pd_port[port].has_vbus = 0;
|
||||
pd_port[port].cc_volt[polarity] = 0;
|
||||
}
|
||||
|
||||
static void unplug(int port)
|
||||
{
|
||||
pd_port[port].has_vbus = 0;
|
||||
pd_port[port].cc_volt[0] = -1;
|
||||
pd_port[port].cc_volt[1] = -1;
|
||||
task_wake(PORT_TO_TASK_ID(port));
|
||||
usleep(30 * MSEC);
|
||||
}
|
||||
|
||||
static int test_request(void)
|
||||
{
|
||||
plug_in_source(0, 0);
|
||||
task_wake(PORT_TO_TASK_ID(0));
|
||||
usleep(30 * MSEC);
|
||||
TEST_ASSERT(pd_port[0].polarity == 0);
|
||||
|
||||
simulate_source_cap(0);
|
||||
task_wait_event(3 * MSEC);
|
||||
TEST_ASSERT(verify_goodcrc(0, PD_ROLE_SINK, pd_port[0].msg_rx_id));
|
||||
task_wake(PORT_TO_TASK_ID(0));
|
||||
task_wait_event(35 * MSEC); /* tSenderResponse: 24~30 ms */
|
||||
inc_rx_id(0);
|
||||
|
||||
/* Process the request */
|
||||
TEST_ASSERT(pd_test_tx_msg_verify_sop(0));
|
||||
TEST_ASSERT(pd_test_tx_msg_verify_short(0,
|
||||
PD_HEADER(PD_DATA_REQUEST, PD_ROLE_SINK,
|
||||
pd_port[0].msg_tx_id, 1)));
|
||||
TEST_ASSERT(pd_test_tx_msg_verify_word(0, RDO_FIXED(2, 450, 900, 0)));
|
||||
TEST_ASSERT(pd_test_tx_msg_verify_crc(0));
|
||||
TEST_ASSERT(pd_test_tx_msg_verify_eop(0));
|
||||
inc_tx_id(0);
|
||||
unplug(0);
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
static int test_sink(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
plug_in_sink(1, 1);
|
||||
task_wake(PORT_TO_TASK_ID(1));
|
||||
task_wait_event(250 * MSEC); /* tTypeCSinkWaitCap: 210~250 ms */
|
||||
TEST_ASSERT(pd_port[1].polarity == 1);
|
||||
|
||||
TEST_ASSERT(pd_test_tx_msg_verify_sop(1));
|
||||
TEST_ASSERT(pd_test_tx_msg_verify_short(1,
|
||||
PD_HEADER(PD_DATA_SOURCE_CAP, PD_ROLE_SOURCE,
|
||||
pd_port[1].msg_tx_id, pd_src_pdo_cnt)));
|
||||
for (i = 0; i < pd_src_pdo_cnt; ++i)
|
||||
TEST_ASSERT(pd_test_tx_msg_verify_word(1, pd_src_pdo[i]));
|
||||
TEST_ASSERT(pd_test_tx_msg_verify_crc(1));
|
||||
TEST_ASSERT(pd_test_tx_msg_verify_eop(1));
|
||||
|
||||
simulate_goodcrc(1, PD_ROLE_SINK, pd_port[1].msg_tx_id);
|
||||
task_wake(PORT_TO_TASK_ID(1));
|
||||
usleep(30 * MSEC);
|
||||
inc_tx_id(1);
|
||||
|
||||
unplug(1);
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
||||
void run_test(void)
|
||||
{
|
||||
test_reset();
|
||||
init_ports();
|
||||
pd_set_dual_role(PD_DRP_TOGGLE_ON);
|
||||
|
||||
RUN_TEST(test_request);
|
||||
RUN_TEST(test_sink);
|
||||
|
||||
test_print_result();
|
||||
}
|
||||
17
test/usb_pd.tasklist
Normal file
17
test/usb_pd.tasklist
Normal file
@@ -0,0 +1,17 @@
|
||||
/* Copyright (c) 2013 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* List of enabled tasks in the priority order
|
||||
*
|
||||
* The first one has the lowest priority.
|
||||
*
|
||||
* For each task, use the macro TASK_TEST(n, r, d, s) where :
|
||||
* 'n' in the name of the task
|
||||
* 'r' in the main routine of the task
|
||||
* 'd' in an opaque parameter passed to the routine at startup
|
||||
* 's' is the stack size in bytes; must be a multiple of 8
|
||||
*/
|
||||
#define CONFIG_TEST_TASK_LIST
|
||||
31
test/usb_pd_test_util.h
Normal file
31
test/usb_pd_test_util.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/* Copyright 2014 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 utilities for USB PD unit test.
|
||||
*/
|
||||
|
||||
#ifndef __USB_PD_TEST_UTIL_H
|
||||
#define __USB_PD_TEST_UTIL_H
|
||||
|
||||
/* Simulate Rx message */
|
||||
void pd_test_rx_set_preamble(int port, int has_preamble);
|
||||
void pd_test_rx_msg_append_bits(int port, uint32_t bits, int nb);
|
||||
void pd_test_rx_msg_append_kcode(int port, uint8_t kcode);
|
||||
void pd_test_rx_msg_append_sop(int port);
|
||||
void pd_test_rx_msg_append_eop(int port);
|
||||
void pd_test_rx_msg_append_4b(int port, uint8_t val);
|
||||
void pd_test_rx_msg_append_short(int port, uint16_t val);
|
||||
void pd_test_rx_msg_append_word(int port, uint32_t val);
|
||||
void pd_simulate_rx(int port);
|
||||
|
||||
/* Verify Tx message */
|
||||
int pd_test_tx_msg_verify_kcode(int port, uint8_t kcode);
|
||||
int pd_test_tx_msg_verify_sop(int port);
|
||||
int pd_test_tx_msg_verify_eop(int port);
|
||||
int pd_test_tx_msg_verify_4b5b(int port, uint8_t b4);
|
||||
int pd_test_tx_msg_verify_short(int port, uint16_t val);
|
||||
int pd_test_tx_msg_verify_word(int port, uint32_t val);
|
||||
int pd_test_tx_msg_verify_crc(int port);
|
||||
|
||||
#endif /* __USB_PD_TEST_UTIL_H */
|
||||
Reference in New Issue
Block a user