pd: support gotoMin and giveBack
In Sink mode, on the receipt of a GotoMin message, reduce the current consumption to some minimum level. BUG=chrome-os-partner:33688 TEST=Manual testing Used a Kevin, with test routine, to test GotoMin feature on another Kevin unit. Test routine: if (!strcasecmp(argv[2], "gm")) { ccprintf("send goto min\n"); send_control(port, PD_CTRL_GOTO_MIN); send_control(port, PD_CTRL_PS_RDY); } Kevin with GotoMin feature: # ectool usbpdpower 0 Port 0: SNK DRP PD 4277mV / 3000mA, max 5000mV / 3000mA / 15000mW Port 1: Disconnected After Test routine is executed: # ectool usbpdpower 0 Port 0: SNK DRP PD 4906mV / 500mA, max 5000mV / 500mA / 2500mW Port 1: Disconnected BRANCH=none Change-Id: Iaac6e19706ceb10ccaff4d602d63fc086c808c8f Reviewed-on: https://chromium-review.googlesource.com/425728 Commit-Ready: Sam Hurst <shurst@google.com> Tested-by: Sam Hurst <shurst@google.com> Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
This commit is contained in:
parent
7736c887d7
commit
17515de32c
|
@ -69,4 +69,7 @@ extern const int supplier_priority[];
|
|||
#define PD_MAX_CURRENT_MA 3000
|
||||
#define PD_MAX_VOLTAGE_MV 20000
|
||||
|
||||
#define PD_MIN_CURRENT_MA 500
|
||||
#define PD_MIN_POWER_MW 7500
|
||||
|
||||
#endif /* __CROS_EC_BOARD_H */
|
||||
|
|
|
@ -141,6 +141,7 @@
|
|||
|
||||
#ifdef BOARD_KEVIN
|
||||
#define CONFIG_BATTERY_REQUESTS_NIL_WHEN_DEAD
|
||||
#define CONFIG_USB_PD_GIVE_BACK
|
||||
#endif
|
||||
|
||||
#define PD_OPERATING_POWER_MW 15000
|
||||
|
@ -148,6 +149,9 @@
|
|||
#define PD_MAX_CURRENT_MA 3000
|
||||
#define PD_MAX_VOLTAGE_MV 20000
|
||||
|
||||
#define PD_MIN_CURRENT_MA 500
|
||||
#define PD_MIN_POWER_MW 2500
|
||||
|
||||
#define PD_POWER_SUPPLY_TURN_ON_DELAY 30000 /* us */
|
||||
#define PD_POWER_SUPPLY_TURN_OFF_DELAY 50000 /* us */
|
||||
#define PD_VCONN_SWAP_DELAY 5000 /* us */
|
||||
|
|
|
@ -60,6 +60,16 @@ int board_vbus_source_enabled(int port)
|
|||
return vbus_en[port];
|
||||
}
|
||||
|
||||
void pd_snk_give_back(int port, uint32_t * const ma, uint32_t * const mv)
|
||||
{
|
||||
/* Just reduce the current */
|
||||
*ma = PD_MIN_CURRENT_MA;
|
||||
pd_set_input_current_limit(port, *ma, *mv);
|
||||
#ifdef CONFIG_CHARGE_MANAGER
|
||||
charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, *ma);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void board_vbus_update_source_current(int port)
|
||||
{
|
||||
enum gpio_signal gpio = port ? GPIO_USB_C1_5V_EN : GPIO_USB_C0_5V_EN;
|
||||
|
|
|
@ -179,6 +179,8 @@ int pd_build_request(int cnt, uint32_t *src_caps, uint32_t *rdo,
|
|||
{
|
||||
int pdo_index, flags = 0;
|
||||
int uw;
|
||||
int max_or_min_ma;
|
||||
int max_or_min_mw;
|
||||
|
||||
if (req_type == PD_REQUEST_VSAFE5V)
|
||||
/* src cap 0 should be vSafe5V */
|
||||
|
@ -197,11 +199,35 @@ int pd_build_request(int cnt, uint32_t *src_caps, uint32_t *rdo,
|
|||
if (uw < (1000 * PD_OPERATING_POWER_MW))
|
||||
flags |= RDO_CAP_MISMATCH;
|
||||
|
||||
#ifdef CONFIG_USB_PD_GIVE_BACK
|
||||
/* Tell source we are give back capable. */
|
||||
flags |= RDO_GIVE_BACK;
|
||||
|
||||
/*
|
||||
* BATTERY PDO: Inform the source that the sink will reduce
|
||||
* power to this minimum level on receipt of a GotoMin Request.
|
||||
*/
|
||||
max_or_min_mw = PD_MIN_POWER_MW;
|
||||
|
||||
/*
|
||||
* FIXED or VARIABLE PDO: Inform the source that the sink will reduce
|
||||
* current to this minimum level on receipt of a GotoMin Request.
|
||||
*/
|
||||
max_or_min_ma = PD_MIN_CURRENT_MA;
|
||||
#else
|
||||
/*
|
||||
* Can't give back, so set maximum current and power to operating
|
||||
* level.
|
||||
*/
|
||||
max_or_min_ma = *ma;
|
||||
max_or_min_mw = uw / 1000;
|
||||
#endif
|
||||
|
||||
if ((src_caps[pdo_index] & PDO_TYPE_MASK) == PDO_TYPE_BATTERY) {
|
||||
int mw = uw / 1000;
|
||||
*rdo = RDO_BATT(pdo_index + 1, mw, mw, flags);
|
||||
*rdo = RDO_BATT(pdo_index + 1, mw, max_or_min_mw, flags);
|
||||
} else {
|
||||
*rdo = RDO_FIXED(pdo_index + 1, *ma, *ma, flags);
|
||||
*rdo = RDO_FIXED(pdo_index + 1, *ma, max_or_min_ma, flags);
|
||||
}
|
||||
return EC_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -927,6 +927,21 @@ static void handle_ctrl_request(int port, uint16_t head,
|
|||
break;
|
||||
#ifdef CONFIG_USB_PD_DUAL_ROLE
|
||||
case PD_CTRL_GOTO_MIN:
|
||||
#ifdef CONFIG_USB_PD_GIVE_BACK
|
||||
if (pd[port].task_state == PD_STATE_SNK_READY) {
|
||||
/*
|
||||
* Reduce power consumption now!
|
||||
*
|
||||
* The source will restore power to this sink
|
||||
* by sending a new source cap message at a
|
||||
* later time.
|
||||
*/
|
||||
pd_snk_give_back(port, &pd[port].curr_limit,
|
||||
&pd[port].supply_voltage);
|
||||
set_state(port, PD_STATE_SNK_TRANSITION);
|
||||
}
|
||||
#endif
|
||||
|
||||
break;
|
||||
case PD_CTRL_PS_RDY:
|
||||
if (pd[port].task_state == PD_STATE_SNK_SWAP_SRC_DISABLE) {
|
||||
|
|
|
@ -2140,6 +2140,9 @@
|
|||
/* Check whether PD is the sole power source before flash erase operation */
|
||||
#undef CONFIG_USB_PD_FLASH_ERASE_CHECK
|
||||
|
||||
/* Define if this board, operating as a sink, can give power back to a source */
|
||||
#undef CONFIG_USB_PD_GIVE_BACK
|
||||
|
||||
/* Major and Minor ChromeOS specific PD device Hardware IDs. */
|
||||
#undef CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR
|
||||
#undef CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR
|
||||
|
|
|
@ -903,6 +903,15 @@ int pd_is_max_request_allowed(void);
|
|||
*/
|
||||
void pd_process_source_cap(int port, int cnt, uint32_t *src_caps);
|
||||
|
||||
/**
|
||||
* Reduce the sink power consumption to a minimum value.
|
||||
*
|
||||
* @param port USB-C port number
|
||||
* @param ma reduce current to minimum value.
|
||||
* @param mv reduce voltage to minimum value.
|
||||
*/
|
||||
void pd_snk_give_back(int port, uint32_t * const ma, uint32_t * const mv);
|
||||
|
||||
/**
|
||||
* Put a cap on the max voltage requested as a sink.
|
||||
* @param mv maximum voltage in millivolts.
|
||||
|
|
|
@ -71,6 +71,7 @@ test-list-host += system
|
|||
test-list-host += thermal
|
||||
test-list-host += timer_dos
|
||||
test-list-host += usb_pd
|
||||
test-list-host += usb_pd_giveback
|
||||
test-list-host += utils
|
||||
endif
|
||||
|
||||
|
@ -115,4 +116,5 @@ thermal-y=thermal.o
|
|||
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
|
||||
utils-y=utils.o
|
||||
|
|
|
@ -141,7 +141,7 @@ int ncp15wb_calculate_temp(uint16_t adc);
|
|||
#define CONFIG_ALS_LIGHTBAR_DIMMING 0
|
||||
#endif
|
||||
|
||||
#ifdef TEST_USB_PD
|
||||
#if defined(TEST_USB_PD) || defined(TEST_USB_PD_GIVEBACK)
|
||||
#define CONFIG_USB_POWER_DELIVERY
|
||||
#define CONFIG_USB_PD_CUSTOM_VDM
|
||||
#define CONFIG_USB_PD_DUAL_ROLE
|
||||
|
@ -150,7 +150,10 @@ int ncp15wb_calculate_temp(uint16_t adc);
|
|||
#define CONFIG_USB_PD_TCPM_STUB
|
||||
#define CONFIG_SHA256
|
||||
#define CONFIG_SW_CRC
|
||||
#ifdef TEST_USB_PD_GIVEBACK
|
||||
#define CONFIG_USB_PD_GIVE_BACK
|
||||
#endif
|
||||
#endif /* TEST_USB_PD || TEST_USB_PD_GIVEBACK */
|
||||
|
||||
#ifdef TEST_CHARGE_MANAGER
|
||||
#define CONFIG_CHARGE_MANAGER
|
||||
|
|
|
@ -27,6 +27,8 @@ struct pd_port_t {
|
|||
int partner_polarity;
|
||||
} pd_port[CONFIG_USB_PD_PORT_COUNT];
|
||||
|
||||
static int give_back_called;
|
||||
|
||||
/* Mock functions */
|
||||
|
||||
int pd_adc_read(int port, int cc)
|
||||
|
@ -193,9 +195,37 @@ static void unplug(int port)
|
|||
usleep(30 * MSEC);
|
||||
}
|
||||
|
||||
void pd_snk_give_back(int port, uint32_t * const ma, uint32_t * const mv)
|
||||
{
|
||||
if (*ma == 3000)
|
||||
give_back_called = 1;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
simulate_rx_msg(port, header, 0, NULL);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
simulate_rx_msg(port, header, 0, NULL);
|
||||
}
|
||||
|
||||
static int test_request_with_wait_and_contract(void)
|
||||
{
|
||||
#ifdef CONFIG_USB_PD_GIVE_BACK
|
||||
uint32_t expected_rdo =
|
||||
RDO_FIXED(2, 3000, PD_MIN_CURRENT_MA, RDO_GIVE_BACK);
|
||||
#else
|
||||
uint32_t expected_rdo = RDO_FIXED(2, 3000, 3000, 0);
|
||||
#endif
|
||||
uint8_t port = PORT0;
|
||||
|
||||
plug_in_source(port, 0);
|
||||
|
@ -310,6 +340,34 @@ static int test_request_with_wait_and_contract(void)
|
|||
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);
|
||||
|
||||
/* We're in SNK_TRANSITION. Send ps_rdy */
|
||||
simulate_ps_rdy(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);
|
||||
|
||||
/* We're in SNK_READY. Send goto_min */
|
||||
simulate_goto_min(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);
|
||||
|
||||
#ifdef CONFIG_USB_PD_GIVE_BACK
|
||||
TEST_ASSERT(give_back_called);
|
||||
#else
|
||||
TEST_ASSERT(!give_back_called);
|
||||
#endif
|
||||
|
||||
/* We're done */
|
||||
unplug(port);
|
||||
|
||||
|
@ -318,7 +376,12 @@ static int test_request_with_wait_and_contract(void)
|
|||
|
||||
static int test_request_with_wait(void)
|
||||
{
|
||||
#ifdef CONFIG_USB_PD_GIVE_BACK
|
||||
uint32_t expected_rdo = RDO_FIXED(1, 900, PD_MIN_CURRENT_MA,
|
||||
RDO_CAP_MISMATCH | RDO_GIVE_BACK);
|
||||
#else
|
||||
uint32_t expected_rdo = RDO_FIXED(1, 900, 900, RDO_CAP_MISMATCH);
|
||||
#endif
|
||||
uint8_t port = PORT0;
|
||||
|
||||
plug_in_source(port, 0);
|
||||
|
@ -401,7 +464,12 @@ static int test_request_with_wait(void)
|
|||
|
||||
static int test_request_with_reject(void)
|
||||
{
|
||||
#ifdef CONFIG_USB_PD_GIVE_BACK
|
||||
uint32_t expected_rdo = RDO_FIXED(1, 900, PD_MIN_CURRENT_MA,
|
||||
RDO_CAP_MISMATCH | RDO_GIVE_BACK);
|
||||
#else
|
||||
uint32_t expected_rdo = RDO_FIXED(1, 900, 900, RDO_CAP_MISMATCH);
|
||||
#endif
|
||||
uint8_t port = PORT0;
|
||||
|
||||
plug_in_source(port, 0);
|
||||
|
@ -474,7 +542,12 @@ static int test_request_with_reject(void)
|
|||
|
||||
static int test_request(void)
|
||||
{
|
||||
#ifdef CONFIG_USB_PD_GIVE_BACK
|
||||
uint32_t expected_rdo = RDO_FIXED(1, 900, PD_MIN_CURRENT_MA,
|
||||
RDO_CAP_MISMATCH | RDO_GIVE_BACK);
|
||||
#else
|
||||
uint32_t expected_rdo = RDO_FIXED(1, 900, 900, RDO_CAP_MISMATCH);
|
||||
#endif
|
||||
uint8_t port = PORT0;
|
||||
|
||||
plug_in_source(port, 0);
|
||||
|
@ -562,6 +635,5 @@ 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();
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
usb_pd.tasklist
|
Loading…
Reference in New Issue