From 537def8417e4cdf7f381474c57ec93f6cb963a3c Mon Sep 17 00:00:00 2001 From: Eric Yilun Lin Date: Thu, 14 Oct 2021 17:00:38 +0800 Subject: charge: respect PDO current maximum limit The current input limit setting doesn't respect the PDO's current limit (e.g. when the current limit is less than CONFIG_INPUT_CURRENT_LIMIT) and this might cause the over-draining the charger. BUG=b:172878439 TEST=1) make buildall 2) modified servo-v4 which only broadcast PDOs with 250mA current limit and ensure the goroh won't sink more than 250mA. (while the CONFIG_INPUT_CURRENT_LIMIT is 512mA) BRANCH=main Change-Id: I09f8e6fb39a072ee38ea09a5c9898984f4122513 Signed-off-by: Eric Yilun Lin Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3220037 Commit-Queue: Eric Yilun Lin Tested-by: Eric Yilun Lin Reviewed-by: Aseda Aboagye Reviewed-by: Diana Z --- common/charge_manager.c | 15 +++++++++++++++ common/charge_state_v2.c | 13 +++++++++++++ include/charge_manager.h | 9 +++++++++ 3 files changed, 37 insertions(+) diff --git a/common/charge_manager.c b/common/charge_manager.c index 862bb28725..14c869c3b2 100644 --- a/common/charge_manager.c +++ b/common/charge_manager.c @@ -107,6 +107,7 @@ static int charge_current = CHARGE_CURRENT_UNINITIALIZED; static int charge_current_uncapped = CHARGE_CURRENT_UNINITIALIZED; static int charge_voltage; static int charge_supplier = CHARGE_SUPPLIER_NONE; +static int charge_pd_current_uncapped = CHARGE_CURRENT_UNINITIALIZED; static int override_port = OVERRIDE_OFF; static int delayed_override_port = OVERRIDE_OFF; @@ -267,6 +268,11 @@ static int charge_manager_is_seeded(void) return 1; } +int charge_manager_get_pd_current_uncapped(void) +{ + return charge_pd_current_uncapped; +} + #ifndef TEST_BUILD /** * Get the maximum charge current for a port. @@ -828,6 +834,15 @@ static void charge_manager_refresh(void) available_charge[new_supplier][new_port].voltage; } + /* + * Record the PD current limit to prevent from over-sinking + * the charger. + */ + if (new_supplier == CHARGE_SUPPLIER_PD) + charge_pd_current_uncapped = new_charge_current_uncapped; + else + charge_pd_current_uncapped = CHARGE_CURRENT_UNINITIALIZED; + /* Change the charge limit + charge port/supplier if modified. */ if (new_port != charge_port || new_charge_current != charge_current || new_supplier != charge_supplier) { diff --git a/common/charge_state_v2.c b/common/charge_state_v2.c index 59f38edee8..abfabda7a3 100644 --- a/common/charge_state_v2.c +++ b/common/charge_state_v2.c @@ -2694,6 +2694,19 @@ int charge_set_input_current_limit(int ma, int mv) /* Limit input current limit to max limit for this board */ ma = MIN(ma, CONFIG_CHARGER_MAX_INPUT_CURRENT); #endif + + if (IS_ENABLED(CONFIG_CHARGE_MANAGER)) { + int pd_current_uncapped = + charge_manager_get_pd_current_uncapped(); + + /* + * clamp the input current to not exceeded the PD's limitation. + */ + if (pd_current_uncapped != CHARGE_CURRENT_UNINITIALIZED && + ma > pd_current_uncapped) + ma = pd_current_uncapped; + } + curr.desired_input_current = ma; #ifdef CONFIG_EC_EC_COMM_BATTERY_CLIENT /* Wake up charger task to allocate current between lid and base. */ diff --git a/include/charge_manager.h b/include/charge_manager.h index cb6591df3b..2cded28295 100644 --- a/include/charge_manager.h +++ b/include/charge_manager.h @@ -231,6 +231,15 @@ enum charge_supplier charge_manager_get_supplier(void); */ int charge_manager_get_vbus_voltage(int port); +/** + * Get the current limit of CHARGE_PD_SUPPLIER. + * + * @return The CHARGE_SUPPLIER_PD current limit in mA or + * CHARGE_CURRENT_UNINITIALIZED if the supplier is not + * CHARGE_SUPPLIER_PD. + */ +int charge_manager_get_pd_current_uncapped(void); + #ifdef CONFIG_USB_PD_LOGGING /* Save power state log entry for the given port */ void charge_manager_save_log(int port); -- cgit v1.2.1