From 91deb1e486a51f8d5519b39ffe393817bb4d2a8e Mon Sep 17 00:00:00 2001 From: Shawn Nematbakhsh Date: Mon, 17 Oct 2016 14:12:38 -0700 Subject: pd: Limit input current to 500mA on PD voltage transition Upon requesting a PD power contract at a new voltage, keep the input current limit at 500mA until PD_RDY is received. BUG=b:30744563,chrome-os-partner:59311,chrome-os-partner:44340 BRANCH=ryu, gru, glados TEST=Manual on kevin, set ilim to 5V through `chglim` console command, attach zinger. Set ilim to 20V through `chglim`, verify that ilim goes from 3A to 500mA to 3A. Signed-off-by: Shawn Nematbakhsh Change-Id: I452f183cfb958780e336a9f99dc6398356de17a0 Reviewed-on: https://chromium-review.googlesource.com/399918 Commit-Ready: Shawn N Tested-by: Shawn N Reviewed-by: Todd Broch Reviewed-by: Vincent Palatin Reviewed-on: https://chromium-review.googlesource.com/430245 (cherry picked from commit 92b3623dad47f47e06168bc5f4a04417254b7028) Reviewed-on: https://chromium-review.googlesource.com/430632 Commit-Queue: Vincent Palatin Tested-by: Vincent Palatin --- common/charge_manager.c | 18 ++++++++++++++++++ common/usb_pd_protocol.c | 13 ++++++++++--- include/charge_manager.h | 10 ++++++++++ test/charge_manager.c | 8 ++++++++ 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/common/charge_manager.c b/common/charge_manager.c index 673a85ab6f..b055c5d28d 100644 --- a/common/charge_manager.c +++ b/common/charge_manager.c @@ -720,6 +720,24 @@ void charge_manager_set_ceil(int port, enum ceil_requestor requestor, int ceil) } } +void charge_manager_force_ceil(int port, int ceil) +{ + ASSERT(port >= 0 && port < CONFIG_USB_PD_PORT_COUNT); + + /* + * Force our input current to ceil if we're exceeding it, without + * waiting for our deferred task to run. + */ + if (port == charge_port && ceil < charge_current) + board_set_charge_limit(ceil, CHARGE_SUPPLIER_PD); + + /* + * Now inform charge_manager so it stays in sync with the state of + * the world. + */ + charge_manager_set_ceil(port, CEIL_REQUESTOR_PD, ceil); +} + /** * Select an 'override port', a port which is always the preferred charge port. * Returns EC_SUCCESS on success, ec_error_list status on failure. diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 4c4ad4b40d..d3b1c4972a 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -606,9 +606,16 @@ static void pd_send_request_msg(int port, int always_send_request) */ return; - /* Don't re-request the same voltage */ - if (!always_send_request && pd[port].prev_request_mv == supply_voltage) - return; + if (!always_send_request) { + /* Don't re-request the same voltage */ + if (pd[port].prev_request_mv == supply_voltage) + return; +#ifdef CONFIG_CHARGE_MANAGER + /* Limit current to PD_MIN_MA during transition */ + else + charge_manager_force_ceil(port, PD_MIN_MA); +#endif + } CPRINTF("Req C%d [%d] %dmV %dmA", port, RDO_POS(rdo), supply_voltage, curr_limit); diff --git a/include/charge_manager.h b/include/charge_manager.h index faca0104eb..a88cbe6e06 100644 --- a/include/charge_manager.h +++ b/include/charge_manager.h @@ -54,6 +54,16 @@ enum ceil_requestor { /* Update charge ceiling for a given port / requestor */ void charge_manager_set_ceil(int port, enum ceil_requestor requestor, int ceil); +/* + * Update PD charge ceiling for a given port. In the event that our ceiling + * is currently above ceil, change the current limit before returning, without + * waiting for a charge manager refresh. This function should only be used in + * time-critical situations where we absolutely cannot proceed without limiting + * our input current, and it should only be called from the PD tasks. + * If you ever call this function then you are a terrible person. + */ +void charge_manager_force_ceil(int port, int ceil); + /* Select an 'override port', which is always the preferred charge port */ int charge_manager_set_override(int port); int charge_manager_get_override(void); diff --git a/test/charge_manager.c b/test/charge_manager.c index 98871cd1b5..8bbfcf11ea 100644 --- a/test/charge_manager.c +++ b/test/charge_manager.c @@ -293,6 +293,14 @@ static int test_charge_ceil(void) TEST_ASSERT(active_charge_port == 1); TEST_ASSERT(active_charge_limit == 2500); + /* Verify forced ceil takes effect immediately */ + charge_manager_force_ceil(1, 500); + TEST_ASSERT(active_charge_port == 1); + TEST_ASSERT(active_charge_limit == 500); + wait_for_charge_manager_refresh(); + TEST_ASSERT(active_charge_port == 1); + TEST_ASSERT(active_charge_limit == 500); + return EC_SUCCESS; } -- cgit v1.2.1