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 | 32 | ||||
l--------- | test/usb_pd_giveback.tasklist | 1 |
11 files changed, 111 insertions, 3 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 a0a2498945..7186e0fc45 100644 --- a/board/kevin/board.h +++ b/board/kevin/board.h @@ -135,6 +135,7 @@ #ifdef BOARD_KEVIN #define CONFIG_BATTERY_REQUESTS_NIL_WHEN_DEAD +#define CONFIG_USB_PD_GIVE_BACK #endif #define PD_OPERATING_POWER_MW 15000 @@ -142,6 +143,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 bc1910df55..d8cf201a94 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 6a3d8b3ee8..808b7e4bd1 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 d057fc54e6..0485f6316e 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -881,6 +881,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 56c9b3bde3..d1595d4247 100644 --- a/include/config.h +++ b/include/config.h @@ -2069,6 +2069,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 069125c432..c5feaf3699 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -911,6 +911,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 1e45061502..d6f1ac6cb8 100644 --- a/test/build.mk +++ b/test/build.mk @@ -39,6 +39,7 @@ test-list-host+=math_util motion_lid sbs_charging_v2 battery_get_params_smart test-list-host+=lightbar inductive_charging usb_pd fan charge_manager test-list-host+=charge_manager_drp_charging charge_ramp test-list-host+=rsa rsa3 +test-list-host+=usb_pd_giveback endif battery_get_params_smart-y=battery_get_params_smart.o @@ -78,6 +79,7 @@ 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 battery_get_params_smart-y=battery_get_params_smart.o lightbar-y=lightbar.o diff --git a/test/test_config.h b/test/test_config.h index 837dd8a5c0..9229c5cc8b 100644 --- a/test/test_config.h +++ b/test/test_config.h @@ -135,7 +135,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 @@ -144,7 +144,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 */ #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 3368484a24..f9a40aefa4 100644 --- a/test/usb_pd.c +++ b/test/usb_pd.c @@ -24,6 +24,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) @@ -158,9 +160,39 @@ 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(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 plug_in_source(0, 0); task_wake(PD_PORT_TO_TASK_ID(0)); 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 |