diff options
author | Eric Yilun Lin <yllin@chromium.org> | 2022-11-23 13:18:26 +0800 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-12-02 10:06:15 +0000 |
commit | f2024e853eed7aad2f4d291fcb3e1e528622152d (patch) | |
tree | ea348f461036914f74ced0ff9929840c65568b7f | |
parent | 1424acad7097fb51639a8c4003281f78fc0497c8 (diff) | |
download | chrome-ec-f2024e853eed7aad2f4d291fcb3e1e528622152d.tar.gz |
dps: add PDO selection tests
It tests when the selected PDO is aligned to the
system power and the efficient PDO.
1. renames dps.c to dps_config.c
2. adds dps_selection.c
BUG=b:257200275 b:243840939
TEST=./twister -T test
BRANCH=none
Change-Id: Ie4f5e7171a922e63cbb276177a98024e11351245
Signed-off-by: Eric Yilun Lin <yllin@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4060443
Code-Coverage: Zoss <zoss-cl-coverage@prod.google.com>
Tested-by: Eric Yilun Lin <yllin@google.com>
Commit-Queue: Eric Yilun Lin <yllin@google.com>
Auto-Submit: Eric Yilun Lin <yllin@google.com>
Reviewed-by: Sung-Chi Li <lschyi@chromium.org>
Reviewed-by: Ting Shen <phoenixshen@chromium.org>
-rw-r--r-- | common/dps.c | 18 | ||||
-rw-r--r-- | zephyr/test/drivers/dps/CMakeLists.txt | 2 | ||||
-rw-r--r-- | zephyr/test/drivers/dps/src/dps_config.c (renamed from zephyr/test/drivers/dps/src/dps.c) | 40 | ||||
-rw-r--r-- | zephyr/test/drivers/dps/src/dps_selection.c | 238 |
4 files changed, 271 insertions, 27 deletions
diff --git a/common/dps.c b/common/dps.c index b0751acc39..8facc57c68 100644 --- a/common/dps.c +++ b/common/dps.c @@ -169,7 +169,7 @@ bool is_more_efficient(int curr_mv, int prev_mv, int batt_mv, int batt_mw, * * @return input_power of the result of vbus * input_curr in mW */ -static int get_desired_input_power(int *vbus, int *input_current) +test_mockable_static int get_desired_input_power(int *vbus, int *input_current) { int active_port; int charger_id; @@ -197,7 +197,7 @@ static int get_desired_input_power(int *vbus, int *input_current) return (*vbus) * (*input_current) / 1000; } -static int get_battery_target_voltage(int *target_mv) +test_mockable_static int get_battery_target_voltage(int *target_mv) { int charger_id = charge_get_active_chg_chip(); int error = charger_get_voltage(charger_id, target_mv); @@ -231,7 +231,7 @@ static int get_battery_target_voltage(int *target_mv) * * @return 0 if error occurs, else battery efficient voltage in mV */ -static int get_efficient_voltage(void) +test_mockable_static int get_efficient_voltage(void) { int eff_mv = 0; int batt_mv; @@ -290,13 +290,20 @@ struct pdo_candidate { return false; \ } while (0) +test_mockable_static int get_batt_charge_power(void) +{ + const struct batt_params *batt = charger_current_battery_params(); + + return batt->current * batt->voltage / 1000; +} + /* * Evaluate the system power if a new PD power request is needed. * * @param struct pdo_candidate: The candidate PDO. (Return value) * @return true if a new power request, or false otherwise. */ -__maybe_unused static bool has_new_power_request(struct pdo_candidate *cand) +test_mockable_static bool has_new_power_request(struct pdo_candidate *cand) { int vbus, input_curr, input_pwr; int input_pwr_avg = 0, input_curr_avg = 0; @@ -311,7 +318,6 @@ __maybe_unused static bool has_new_power_request(struct pdo_candidate *cand) static int prev_active_port = CHARGE_PORT_NONE; static int prev_req_mv; static int moving_avg_count; - const struct batt_params *batt = charger_current_battery_params(); /* set a default value in case it early returns. */ UPDATE_CANDIDATE(CHARGE_PORT_NONE, INT32_MAX, 0); @@ -335,7 +341,7 @@ __maybe_unused static bool has_new_power_request(struct pdo_candidate *cand) prev_req_mv = req_mv; req_pwr = req_mv * req_ma / 1000; - batt_pwr = batt->current * batt->voltage / 1000; + batt_pwr = get_batt_charge_power(); input_pwr = get_desired_input_power(&vbus, &input_curr); if (!input_pwr) diff --git a/zephyr/test/drivers/dps/CMakeLists.txt b/zephyr/test/drivers/dps/CMakeLists.txt index 0e175e182f..0433fe951b 100644 --- a/zephyr/test/drivers/dps/CMakeLists.txt +++ b/zephyr/test/drivers/dps/CMakeLists.txt @@ -2,4 +2,4 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -target_sources(app PRIVATE src/dps.c) +target_sources(app PRIVATE src/dps_config.c src/dps_selection.c) diff --git a/zephyr/test/drivers/dps/src/dps.c b/zephyr/test/drivers/dps/src/dps_config.c index a573da670b..a3c7736e31 100644 --- a/zephyr/test/drivers/dps/src/dps.c +++ b/zephyr/test/drivers/dps/src/dps_config.c @@ -11,14 +11,14 @@ #include <zephyr/ztest.h> -struct dps_fixture { +struct dps_config_fixture { struct dps_config_t saved_config; int saved_debug_level; }; static void *dps_config_setup(void) { - static struct dps_fixture fixture; + static struct dps_config_fixture fixture; fixture.saved_config = *dps_get_config(); fixture.saved_debug_level = *dps_get_debug_level(); @@ -33,14 +33,14 @@ static void dps_config_before(void *data) static void dps_config_after(void *data) { - struct dps_fixture *f = (struct dps_fixture *)data; + struct dps_config_fixture *f = (struct dps_config_fixture *)data; *dps_get_config() = f->saved_config; *dps_get_debug_level() = f->saved_debug_level; dps_enable(true); } -ZTEST_F(dps, test_enable) +ZTEST_F(dps_config, test_enable) { zassert_true(dps_is_enabled(), NULL); dps_enable(false); @@ -49,7 +49,7 @@ ZTEST_F(dps, test_enable) zassert_true(dps_is_enabled(), NULL); } -ZTEST_F(dps, test_config) +ZTEST_F(dps_config, test_config) { struct dps_config_t *config = dps_get_config(); @@ -69,13 +69,13 @@ ZTEST_F(dps, test_config) *config = fixture->saved_config; } -ZTEST(dps, console_cmd__print_info) +ZTEST(dps_config, console_cmd__print_info) { /* Print current status to console */ zassert_ok(shell_execute_cmd(get_ec_shell(), "dps"), NULL); } -ZTEST(dps, console_cmd__enable) +ZTEST(dps_config, console_cmd__enable) { /* Disable DPS first, then try enabling */ dps_enable(false); @@ -86,7 +86,7 @@ ZTEST(dps, console_cmd__enable) zassert_true(dps_is_enabled(), NULL); } -ZTEST(dps, console_cmd__disable) +ZTEST(dps_config, console_cmd__disable) { /* Should already by enabled due to before() function */ zassert_true(dps_is_enabled(), NULL); @@ -96,13 +96,13 @@ ZTEST(dps, console_cmd__disable) zassert_false(dps_is_enabled(), NULL); } -ZTEST(dps, console_cmd__fakepwr_print) +ZTEST(dps_config, console_cmd__fakepwr_print) { /* Print current fake power status to console */ zassert_ok(shell_execute_cmd(get_ec_shell(), "dps fakepwr"), NULL); } -ZTEST(dps, console_cmd__fakepwr_enable_disable) +ZTEST(dps_config, console_cmd__fakepwr_enable_disable) { zassert_false(dps_is_fake_enabled(), "fakepwr shouldn't be enabled by default"); @@ -119,7 +119,7 @@ ZTEST(dps, console_cmd__fakepwr_enable_disable) zassert_false(dps_is_fake_enabled(), NULL); } -ZTEST(dps, console_cmd__fakepwr_invalid) +ZTEST(dps_config, console_cmd__fakepwr_invalid) { /* Various invalid parameters */ zassert_ok(!shell_execute_cmd(get_ec_shell(), "dps fakepwr 100"), NULL); @@ -129,7 +129,7 @@ ZTEST(dps, console_cmd__fakepwr_invalid) NULL); } -ZTEST(dps, console_cmd__debuglevel) +ZTEST(dps_config, console_cmd__debuglevel) { zassert_ok(shell_execute_cmd(get_ec_shell(), "dps debug 999"), NULL); @@ -137,7 +137,7 @@ ZTEST(dps, console_cmd__debuglevel) *dps_get_debug_level()); } -ZTEST(dps, console_cmd__setkmore) +ZTEST(dps_config, console_cmd__setkmore) { struct dps_config_t *config = dps_get_config(); char cmd[32]; @@ -165,7 +165,7 @@ ZTEST(dps, console_cmd__setkmore) config->k_less_pwr + 1); } -ZTEST(dps, console_cmd__setkless) +ZTEST(dps_config, console_cmd__setkless) { struct dps_config_t *config = dps_get_config(); char cmd[32]; @@ -193,7 +193,7 @@ ZTEST(dps, console_cmd__setkless) config->k_more_pwr - 1); } -ZTEST(dps, console_cmd__setksample) +ZTEST(dps_config, console_cmd__setksample) { struct dps_config_t *config = dps_get_config(); @@ -209,7 +209,7 @@ ZTEST(dps, console_cmd__setksample) config->k_sample); } -ZTEST(dps, console_cmd__setkwindow) +ZTEST(dps_config, console_cmd__setkwindow) { struct dps_config_t *config = dps_get_config(); @@ -222,7 +222,7 @@ ZTEST(dps, console_cmd__setkwindow) zassert_equal(4, config->k_window, "k_window is %d", config->k_window); } -ZTEST(dps, console_cmd__settcheck) +ZTEST(dps_config, console_cmd__settcheck) { struct dps_config_t *config = dps_get_config(); @@ -237,7 +237,7 @@ ZTEST(dps, console_cmd__settcheck) config->t_check); } -ZTEST(dps, console_cmd__settstable) +ZTEST(dps_config, console_cmd__settstable) { struct dps_config_t *config = dps_get_config(); @@ -252,11 +252,11 @@ ZTEST(dps, console_cmd__settstable) config->t_stable); } -ZTEST(dps, console_cmd__invalid) +ZTEST(dps_config, console_cmd__invalid) { /* Non-existent subcommand should fail */ zassert_ok(!shell_execute_cmd(get_ec_shell(), "dps foobar xyz"), NULL); } -ZTEST_SUITE(dps, drivers_predicate_pre_main, dps_config_setup, +ZTEST_SUITE(dps_config, drivers_predicate_pre_main, dps_config_setup, dps_config_before, dps_config_after, NULL); diff --git a/zephyr/test/drivers/dps/src/dps_selection.c b/zephyr/test/drivers/dps/src/dps_selection.c new file mode 100644 index 0000000000..a06aabc67f --- /dev/null +++ b/zephyr/test/drivers/dps/src/dps_selection.c @@ -0,0 +1,238 @@ +/* Copyright 2022 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "battery.h" +#include "charge_state_v2.h" +#include "console.h" +#include "dps.h" +#include "ec_commands.h" +#include "ec_tasks.h" +#include "emul/emul_isl923x.h" +#include "emul/tcpc/emul_tcpci.h" +#include "emul/tcpc/emul_tcpci_partner_common.h" +#include "emul/tcpc/emul_tcpci_partner_drp.h" +#include "emul/tcpc/emul_tcpci_partner_src.h" +#include "host_command.h" +#include "tcpm/tcpci.h" +#include "test/drivers/stubs.h" +#include "test/drivers/test_state.h" +#include "test/drivers/utils.h" +#include "usb_pd.h" + +#include <stdint.h> + +#include <zephyr/drivers/gpio/gpio_emul.h> +#include <zephyr/fff.h> +#include <zephyr/kernel.h> +#include <zephyr/shell/shell_dummy.h> +#include <zephyr/ztest.h> + +#define TEST_PORT 0 + +FAKE_VALUE_FUNC(int, get_batt_charge_power, int *); +FAKE_VALUE_FUNC(int, get_battery_target_voltage, int *); +FAKE_VALUE_FUNC(int, get_desired_input_power, int *, int *); + +struct common_fixture { + const struct emul *tcpci_emul; + const struct emul *charger_emul; + struct tcpci_partner_data partner; + struct tcpci_snk_emul_data snk_ext; + struct tcpci_src_emul_data src_ext; + struct tcpci_drp_emul_data drp_ext; +}; + +struct dps_selection_fixture { + struct common_fixture common; +}; + +/* FFF fakes for driver functions. These get assigned to members of the + * charger_drv struct + */ +static int target_mv_custom_fake; +static int get_battery_target_voltage_custom_fake(int *target_mv) +{ + *target_mv = target_mv_custom_fake; + + return EC_SUCCESS; +} + +static int vbus_custom_fake; +static int input_current_custom_fake; +static int get_desired_input_power_custom_fake(int *vbus, int *input_current) +{ + *vbus = vbus_custom_fake; + *input_current = input_current_custom_fake; + + return vbus_custom_fake * input_current_custom_fake / 1000; +} + +static void reset(void) +{ + /* Reset fakes */ + RESET_FAKE(get_batt_charge_power); + RESET_FAKE(get_battery_target_voltage); + RESET_FAKE(get_desired_input_power); +} + +static void connect_partner_to_port(const struct emul *tcpc_emul, + const struct emul *charger_emul, + struct tcpci_partner_data *partner_emul, + const struct tcpci_src_emul_data *src_ext) +{ + /* + * TODO(b/221439302): Updating the TCPCI emulator registers, updating + * the charger, and alerting should all be a part of the connect + * function. + */ + set_ac_enabled(true); + zassert_ok(tcpci_partner_connect_to_tcpci(partner_emul, tcpc_emul), + NULL); + + isl923x_emul_set_adc_vbus(charger_emul, + PDO_FIXED_GET_VOLT(src_ext->pdo[0])); + + /* Wait for PD negotiation and current ramp. */ + k_sleep(K_SECONDS(10)); +} + +static void disconnect_partner_from_port(const struct emul *tcpc_emul, + const struct emul *charger_emul) +{ + zassert_ok(tcpci_emul_disconnect_partner(tcpc_emul), NULL); + isl923x_emul_set_adc_vbus(charger_emul, 0); + k_sleep(K_SECONDS(1)); +} + +static void *common_setup(void) +{ + static struct dps_selection_fixture outer_fixture; + struct common_fixture *fixture = &outer_fixture.common; + struct tcpci_partner_data *partner = &fixture->partner; + struct tcpci_src_emul_data *src_ext = &fixture->src_ext; + struct tcpci_snk_emul_data *snk_ext = &fixture->snk_ext; + + tcpci_partner_init(partner, PD_REV30); + fixture->partner.extensions = tcpci_drp_emul_init( + &fixture->drp_ext, partner, PD_ROLE_SOURCE, + tcpci_src_emul_init(src_ext, partner, NULL), + tcpci_snk_emul_init(snk_ext, partner, NULL)); + + /* Get references for the emulators */ + fixture->tcpci_emul = EMUL_GET_USBC_BINDING(TEST_PORT, tcpc); + fixture->charger_emul = EMUL_GET_USBC_BINDING(TEST_PORT, chg); + + return &outer_fixture; +} + +static void *dps_selection_setup(void) +{ + return common_setup(); +} + +static void common_before(struct common_fixture *fixture) +{ + /* Set chipset to ON, this will set TCPM to DRP */ + test_set_chipset_to_s0(); + + /* TODO(b/214401892): Check why need to give time TCPM to spin */ + k_sleep(K_SECONDS(1)); +} + +static void dps_selection_before(void *data) +{ + struct dps_selection_fixture *outer = data; + + common_before(&outer->common); + + reset(); +} + +static void common_after(struct common_fixture *fixture) +{ + if (pd_is_connected(TEST_PORT)) { + disconnect_partner_from_port(fixture->tcpci_emul, + fixture->charger_emul); + } +} + +static void dps_selection_after(void *data) +{ + struct dps_selection_fixture *outer = data; + + common_after(&outer->common); + + reset(); +} + +ZTEST_USER_F(dps_selection, dps_pdo_switch) +{ + struct common_fixture *common = &fixture->common; + struct tcpci_src_emul_data *src_ext = &common->src_ext; + uint32_t *partner_pdo = src_ext->pdo; + + /* Attach a partner with all of the Source Capability attributes that + * "pd <port> srccaps" checks for. + */ + partner_pdo[0] = + PDO_FIXED(5000, 3000, + PDO_FIXED_DUAL_ROLE | PDO_FIXED_UNCONSTRAINED | + PDO_FIXED_COMM_CAP | PDO_FIXED_DATA_SWAP | + PDO_FIXED_FRS_CURR_MASK); + partner_pdo[1] = PDO_FIXED(9000, 3000, PDO_FIXED_UNCONSTRAINED); + partner_pdo[2] = PDO_FIXED(10000, 3000, PDO_FIXED_UNCONSTRAINED); + partner_pdo[3] = PDO_FIXED(12000, 3000, PDO_FIXED_UNCONSTRAINED); + partner_pdo[4] = PDO_FIXED(15000, 3000, PDO_FIXED_UNCONSTRAINED); + partner_pdo[5] = PDO_FIXED(20000, 3000, PDO_FIXED_UNCONSTRAINED); + connect_partner_to_port(common->tcpci_emul, common->charger_emul, + &common->partner, &common->src_ext); + + get_battery_target_voltage_fake.custom_fake = + get_battery_target_voltage_custom_fake; + get_desired_input_power_fake.custom_fake = + get_desired_input_power_custom_fake; + + /* This value is not used if not have board overridden. */ + get_batt_charge_power_fake.return_val = 5566; + + /* Assume the charge targeting at 9V. */ + target_mv_custom_fake = 9000; + + k_sleep(K_SECONDS(1)); + /* Assumes the system sinks 15W. */ + vbus_custom_fake = 20000; + input_current_custom_fake = 750; + + /* DPS should request the PDO with the highest voltage at first. */ + zassert_equal(pd_get_requested_voltage(TEST_PORT), 20000, NULL); + + /* Wait for DPS to changing voltage */ + k_sleep(K_SECONDS(20)); + + /* DPS should switch to 9V. */ + zassert_equal(pd_get_requested_voltage(TEST_PORT), 9000, NULL); + + /* Assumes the system sinks 27W/9V/3A. */ + vbus_custom_fake = 9000; + input_current_custom_fake = 3000; + k_sleep(K_SECONDS(20)); + /* PDO 10V/3A should be requested. */ + zassert_equal(pd_get_requested_voltage(TEST_PORT), 10000, NULL); + + /* Assumes the system sinks 30W/10V/3A. */ + vbus_custom_fake = 10000; + k_sleep(K_SECONDS(20)); + /* PDO 12V/3A should be requested. */ + zassert_equal(pd_get_requested_voltage(TEST_PORT), 12000, NULL); + + /* Assumes the system sinks 36W/12V/3A. */ + vbus_custom_fake = 12000; + k_sleep(K_SECONDS(20)); + /* PDO 15V/3A should be requested. */ + zassert_equal(pd_get_requested_voltage(TEST_PORT), 15000, NULL); +} + +ZTEST_SUITE(dps_selection, drivers_predicate_post_main, dps_selection_setup, + dps_selection_before, dps_selection_after, NULL); |