diff options
author | Will Tsai <will_tsai@wistron.corp-partner.google.com> | 2022-09-07 19:40:00 +0800 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-10-19 10:26:14 +0000 |
commit | 13549841b89f14354eba1412c7a20fa018258d5f (patch) | |
tree | 304bf9dc93152a9fe959e3a1eebbf293772154cd | |
parent | fbc8ddd25c7c569213542034feab8fa9346b99d9 (diff) | |
download | chrome-ec-13549841b89f14354eba1412c7a20fa018258d5f.tar.gz |
dps: limit the minimum operating power when AC only
We found that the system will fail to boot without battery if PDO 5V/3A
is selected. To prevent boot failed, limit the minimum operating power
to the larger PDO when the system is booting up without battery.
BUG=b:240533589
TEST=On Joxer, confirm the selected power is equal to 9V when system
booting, and the system boot up successfully.
TEST=./twister -v -i --coverage -p native_posix -p unit_testing
BRANCH=none
Signed-off-by: Will Tsai <will_tsai@wistron.corp-partner.google.com>
Change-Id: I5d9655b09eead6791c5a3bf161e574f26f6beb02
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3878627
Reviewed-by: Diana Z <dzigterman@chromium.org>
Code-Coverage: Zoss <zoss-cl-coverage@prod.google.com>
Reviewed-by: Aaron Massey <aaronmassey@google.com>
-rw-r--r-- | common/dps.c | 63 | ||||
-rw-r--r-- | include/dps.h | 9 | ||||
-rw-r--r-- | zephyr/test/drivers/default/src/integration/usbc/usb_5v_3a_pd_source.c | 51 | ||||
-rw-r--r-- | zephyr/test/drivers/testcase.yaml | 2 |
4 files changed, 96 insertions, 29 deletions
diff --git a/common/dps.c b/common/dps.c index 13f551a95d..c5a8ba4045 100644 --- a/common/dps.c +++ b/common/dps.c @@ -16,6 +16,7 @@ #include "charge_manager.h" #include "charge_state.h" #include "ec_commands.h" +#include "hooks.h" #include "math_util.h" #include "task.h" #include "timer.h" @@ -30,13 +31,8 @@ #define T_REQUEST_STABLE_TIME (10 * SECOND) #define T_NEXT_CHECK_TIME (5 * SECOND) -#define DPS_FLAG_DISABLED BIT(0) -#define DPS_FLAG_NO_SRCCAP BIT(1) -#define DPS_FLAG_WAITING BIT(2) -#define DPS_FLAG_SAMPLED BIT(3) -#define DPS_FLAG_NEED_MORE_PWR BIT(4) - -#define DPS_FLAG_STOP_EVENTS (DPS_FLAG_DISABLED | DPS_FLAG_NO_SRCCAP) +#define DPS_FLAG_STOP_EVENTS \ + (DPS_FLAG_DISABLED | DPS_FLAG_NO_SRCCAP | DPS_FLAG_NO_BATTERY) #define DPS_FLAG_ALL GENMASK(31, 0) #define MAX_MOVING_AVG_WINDOW 5 @@ -52,7 +48,7 @@ static bool fake_enabled; static int fake_mv, fake_ma; static int dynamic_mv; static int dps_port = CHARGE_PORT_NONE; -static uint32_t flag; +static atomic_t flag; #define CPRINTF(format, args...) cprintf(CC_USBPD, "DPS " format, ##args) #define CPRINTS(format, args...) cprints(CC_USBPD, "DPS " format, ##args) @@ -370,18 +366,18 @@ __maybe_unused static bool has_new_power_request(struct pdo_candidate *cand) */ if (is_near_limit(input_pwr_avg, req_pwr) || is_near_limit(input_curr_avg, MIN(req_ma, input_curr_limit))) { - flag |= DPS_FLAG_NEED_MORE_PWR; + atomic_or(&flag, DPS_FLAG_NEED_MORE_PWR); if (!fake_enabled) input_pwr_avg = req_pwr + 1; } else { - flag &= ~DPS_FLAG_NEED_MORE_PWR; + atomic_clear_bits(&flag, DPS_FLAG_NEED_MORE_PWR); } if (debug_level) CPRINTS("C%d 0x%x last (%dmW %dmV) input (%dmW %dmV %dmA) " "avg (%dmW, %dmA)", - active_port, flag, req_pwr, req_mv, input_pwr, vbus, - input_curr, input_pwr_avg, input_curr_avg); + active_port, (int)flag, req_pwr, req_mv, input_pwr, + vbus, input_curr, input_pwr_avg, input_curr_avg); for (int i = 0; i < board_get_usb_pd_port_count(); ++i) { const uint32_t *const src_caps = pd_get_src_caps(i); @@ -498,29 +494,34 @@ void dps_task(void *u) dps_reset(); task_wait_event(-1); /* clear flags after wake up. */ - flag = 0; + atomic_clear(&flag); update_timeout(dps_config.t_check); continue; } else if (now.val < timeout.val) { - flag |= DPS_FLAG_WAITING; + atomic_or(&flag, DPS_FLAG_WAITING); task_wait_event(timeout.val - now.val); - flag &= ~DPS_FLAG_WAITING; + atomic_clear_bits(&flag, DPS_FLAG_WAITING); continue; } if (!is_enabled) { - flag |= DPS_FLAG_DISABLED; + atomic_or(&flag, DPS_FLAG_DISABLED); continue; } if (!has_srccap()) { - flag |= DPS_FLAG_NO_SRCCAP; + atomic_or(&flag, DPS_FLAG_NO_SRCCAP); + continue; + } + + if (battery_is_present() != BP_YES) { + atomic_or(&flag, DPS_FLAG_NO_BATTERY); continue; } if (!has_new_power_request(&curr_cand)) { sample_count = 0; - flag &= ~DPS_FLAG_SAMPLED; + atomic_clear_bits(&flag, DPS_FLAG_SAMPLED); } else { if (last_cand.port == curr_cand.port && last_cand.mv == curr_cand.mv && @@ -528,7 +529,7 @@ void dps_task(void *u) sample_count++; else sample_count = 1; - flag |= DPS_FLAG_SAMPLED; + atomic_or(&flag, DPS_FLAG_SAMPLED); } if (sample_count == dps_config.k_sample) { @@ -536,17 +537,28 @@ void dps_task(void *u) dps_port = curr_cand.port; pd_dpm_request(dps_port, DPM_REQUEST_NEW_POWER_LEVEL); sample_count = 0; - flag &= ~(DPS_FLAG_SAMPLED | DPS_FLAG_NEED_MORE_PWR); + atomic_clear_bits(&flag, (DPS_FLAG_SAMPLED | + DPS_FLAG_NEED_MORE_PWR)); } last_cand.port = curr_cand.port; last_cand.mv = curr_cand.mv; last_cand.mw = curr_cand.mw; - update_timeout(dps_config.t_check); } } +void check_battery_present(void) +{ + const struct batt_params *batt = charger_current_battery_params(); + + if (batt->is_present == BP_YES && (flag & DPS_FLAG_NO_BATTERY)) { + atomic_clear_bits(&flag, DPS_FLAG_NO_BATTERY); + task_wake(TASK_ID_DPS); + } +} +DECLARE_HOOK(HOOK_BATTERY_SOC_CHANGE, check_battery_present, HOOK_PRIO_DEFAULT); + static int command_dps(int argc, const char **argv) { int port = charge_manager_get_active_charge_port(); @@ -558,8 +570,9 @@ static int command_dps(int argc, const char **argv) int batt_mv; ccprintf("flag=0x%x k_more=%d k_less=%d k_sample=%d k_win=%d\n", - flag, dps_config.k_more_pwr, dps_config.k_less_pwr, - dps_config.k_sample, dps_config.k_window); + (int)flag, dps_config.k_more_pwr, + dps_config.k_less_pwr, dps_config.k_sample, + dps_config.k_window); ccprintf("t_stable=%d t_check=%d\n", dps_config.t_stable / SECOND, dps_config.t_check / SECOND); @@ -703,4 +716,8 @@ __test_only int *dps_get_debug_level(void) { return &debug_level; } +__test_only int dps_get_flag(void) +{ + return flag; +} #endif /* TEST_BUILD */ diff --git a/include/dps.h b/include/dps.h index 0cb2a9455b..8794220ab2 100644 --- a/include/dps.h +++ b/include/dps.h @@ -10,6 +10,13 @@ #include "common.h" +#define DPS_FLAG_DISABLED BIT(0) +#define DPS_FLAG_NO_SRCCAP BIT(1) +#define DPS_FLAG_WAITING BIT(2) +#define DPS_FLAG_SAMPLED BIT(3) +#define DPS_FLAG_NEED_MORE_PWR BIT(4) +#define DPS_FLAG_NO_BATTERY BIT(5) + /* Dynamic PDO Selection config. */ struct dps_config_t { /* (0, 100) coeff for transition to a lower power PDO*/ @@ -76,6 +83,8 @@ __test_only bool dps_is_fake_enabled(void); __test_only int dps_get_fake_mv(void); __test_only int dps_get_fake_ma(void); __test_only int *dps_get_debug_level(void); +__test_only int dps_get_flag(void); + #endif #endif /* __CROS_EC_DPS__H */ diff --git a/zephyr/test/drivers/default/src/integration/usbc/usb_5v_3a_pd_source.c b/zephyr/test/drivers/default/src/integration/usbc/usb_5v_3a_pd_source.c index fcc213d252..c73cf26f37 100644 --- a/zephyr/test/drivers/default/src/integration/usbc/usb_5v_3a_pd_source.c +++ b/zephyr/test/drivers/default/src/integration/usbc/usb_5v_3a_pd_source.c @@ -7,17 +7,23 @@ #include <zephyr/sys/slist.h> #include <zephyr/ztest.h> +#include "battery.h" #include "battery_smart.h" +#include "dps.h" #include "emul/emul_isl923x.h" #include "emul/emul_smart_battery.h" #include "emul/tcpc/emul_tcpci_partner_src.h" #include "system.h" +#include "task.h" #include "test/drivers/test_state.h" #include "test/drivers/utils.h" #include "usb_pd.h" #define BATTERY_NODE DT_NODELABEL(battery) +#define GPIO_BATT_PRES_ODL_PATH DT_PATH(named_gpios, ec_batt_pres_odl) +#define GPIO_BATT_PRES_ODL_PORT DT_GPIO_PIN(GPIO_BATT_PRES_ODL_PATH, gpios) + struct usb_attach_5v_3a_pd_source_fixture { struct tcpci_partner_data source_5v_3a; struct tcpci_src_emul_data src_ext; @@ -58,6 +64,15 @@ static void usb_attach_5v_3a_pd_source_after(void *data) disconnect_source_from_port(fixture->tcpci_emul, fixture->charger_emul); } +static void control_battery_present(bool present) +{ + const struct device *dev = + DEVICE_DT_GET(DT_GPIO_CTLR(GPIO_BATT_PRES_ODL_PATH, gpios)); + + /* 0 means battery present */ + zassume_ok(gpio_emul_input_set(dev, GPIO_BATT_PRES_ODL_PORT, !present)); +} + ZTEST_SUITE(usb_attach_5v_3a_pd_source, drivers_predicate_post_main, usb_attach_5v_3a_pd_source_setup, usb_attach_5v_3a_pd_source_before, usb_attach_5v_3a_pd_source_after, NULL); @@ -68,8 +83,7 @@ ZTEST(usb_attach_5v_3a_pd_source, test_battery_is_charging) uint16_t battery_status; zassume_ok(sbat_emul_get_word_val(emul, SB_BATTERY_STATUS, - &battery_status), - NULL); + &battery_status)); zassert_equal(battery_status & STATUS_DISCHARGING, 0, "Battery is discharging: %d", battery_status); } @@ -137,8 +151,7 @@ ZTEST_F(usb_attach_5v_3a_pd_source, test_disconnect_battery_not_charging) disconnect_source_from_port(fixture->tcpci_emul, fixture->charger_emul); zassert_ok(sbat_emul_get_word_val(emul, SB_BATTERY_STATUS, - &battery_status), - NULL); + &battery_status)); zassert_equal(battery_status & STATUS_DISCHARGING, STATUS_DISCHARGING, "Battery is not discharging: %d", battery_status); } @@ -225,7 +238,7 @@ ZTEST(usb_attach_5v_3a_pd_source, batt_data->design_cap / 100) - 1; - zassert_true(system_can_boot_ap(), NULL); + zassert_true(system_can_boot_ap()); } ZTEST_F(usb_attach_5v_3a_pd_source, @@ -246,7 +259,7 @@ ZTEST_F(usb_attach_5v_3a_pd_source, disconnect_source_from_port(fixture->tcpci_emul, fixture->charger_emul); - zassert_false(system_can_boot_ap(), NULL); + zassert_false(system_can_boot_ap()); } ZTEST_F(usb_attach_5v_3a_pd_source, test_uvdm_ignored) @@ -282,3 +295,29 @@ ZTEST_F(usb_attach_5v_3a_pd_source, test_uvdm_ignored) zassert_false(tcpm_response, "Sent unstructured VDM to TCPM; TCPM did not ignore"); } + +ZTEST_F(usb_attach_5v_3a_pd_source, test_dps_battery_absent) +{ + control_battery_present(false); + zassert_false(battery_is_present(), "dps battery is present"); + task_wake(TASK_ID_DPS); + /* wait dps_config.t_check*/ + k_sleep(K_MSEC(5000)); + zassert_true(dps_get_flag() & DPS_FLAG_NO_BATTERY, + "DPS_FLAG_NO_BATTERY is set"); + control_battery_present(true); + zassert_true(battery_is_present(), "dps battery is not present"); +} + +ZTEST_F(usb_attach_5v_3a_pd_source, test_dps_enable) +{ + dps_enable(false); + zassert_false(dps_is_enabled()); + task_wake(TASK_ID_DPS); + /* wait dps_config.t_check*/ + k_sleep(K_MSEC(5000)); + zassert_true(dps_get_flag() & DPS_FLAG_DISABLED, + "DPS_FLAG_DISABLED is set"); + dps_enable(true); + zassert_true(dps_is_enabled()); +} diff --git a/zephyr/test/drivers/testcase.yaml b/zephyr/test/drivers/testcase.yaml index 3cc47248af..d6530bcd9a 100644 --- a/zephyr/test/drivers/testcase.yaml +++ b/zephyr/test/drivers/testcase.yaml @@ -10,6 +10,7 @@ tests: - CONFIG_PLATFORM_EC_BATTERY_CUT_OFF=y - CONFIG_PLATFORM_EC_LID_ANGLE_UPDATE=y - CONFIG_PLATFORM_EC_CBI_EEPROM=y + - CONFIG_PLATFORM_EC_USB_PD_DPS=y drivers.default.mock_power: timeout: 240 extra_args: CONF_FILE="prj.conf;default/prj.conf" @@ -20,6 +21,7 @@ tests: - CONFIG_PLATFORM_EC_LID_ANGLE_UPDATE=y - CONFIG_POWER_SEQUENCE_MOCK=y - CONFIG_PLATFORM_EC_CBI_EEPROM=y + - CONFIG_PLATFORM_EC_USB_PD_DPS=y drivers.button: timeout: 240 extra_configs: |