diff options
-rw-r--r-- | board/host/board.h | 3 | ||||
-rw-r--r-- | board/kevin/board.h | 4 | ||||
-rw-r--r-- | board/kevin/usb_pd_policy.c | 10 | ||||
-rw-r--r-- | common/usb_pd_policy.c | 30 | ||||
-rw-r--r-- | common/usb_pd_protocol.c | 15 | ||||
-rw-r--r-- | include/config.h | 3 | ||||
-rw-r--r-- | include/usb_pd.h | 9 | ||||
-rw-r--r-- | test/build.mk | 2 | ||||
-rw-r--r-- | test/test_config.h | 5 | ||||
-rw-r--r-- | test/usb_pd.c | 74 | ||||
l--------- | test/usb_pd_giveback.tasklist | 1 |
11 files changed, 152 insertions, 4 deletions
diff --git a/board/host/board.h b/board/host/board.h index a5b6a5dc20..aa82d600d4 100644 --- a/board/host/board.h +++ b/board/host/board.h @@ -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 */ diff --git a/board/kevin/board.h b/board/kevin/board.h index 304de3da1e..2985609b75 100644 --- a/board/kevin/board.h +++ b/board/kevin/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 */ diff --git a/board/kevin/usb_pd_policy.c b/board/kevin/usb_pd_policy.c index dbd8bceec3..deef42c250 100644 --- a/board/kevin/usb_pd_policy.c +++ b/board/kevin/usb_pd_policy.c @@ -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; diff --git a/common/usb_pd_policy.c b/common/usb_pd_policy.c index fe204b9301..97e7718bf6 100644 --- a/common/usb_pd_policy.c +++ b/common/usb_pd_policy.c @@ -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; } diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 28f7796240..ecd593e1e3 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -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) { diff --git a/include/config.h b/include/config.h index 27f7fbb789..dd1ab1167b 100644 --- a/include/config.h +++ b/include/config.h @@ -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 diff --git a/include/usb_pd.h b/include/usb_pd.h index 08eef75822..940424ecfa 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -904,6 +904,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. */ diff --git a/test/build.mk b/test/build.mk index 19fa51f5b0..ae1304cf59 100644 --- a/test/build.mk +++ b/test/build.mk @@ -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 diff --git a/test/test_config.h b/test/test_config.h index d2438c9612..fcad730c7f 100644 --- a/test/test_config.h +++ b/test/test_config.h @@ -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 diff --git a/test/usb_pd.c b/test/usb_pd.c index 233714e3ad..d87a4c3960 100644 --- a/test/usb_pd.c +++ b/test/usb_pd.c @@ -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(); } diff --git a/test/usb_pd_giveback.tasklist b/test/usb_pd_giveback.tasklist new file mode 120000 index 0000000000..45cc6c8aa2 --- /dev/null +++ b/test/usb_pd_giveback.tasklist @@ -0,0 +1 @@ +usb_pd.tasklist
\ No newline at end of file |