summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Yilun Lin <yllin@chromium.org>2022-11-23 13:18:26 +0800
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-12-02 10:06:15 +0000
commitf2024e853eed7aad2f4d291fcb3e1e528622152d (patch)
treeea348f461036914f74ced0ff9929840c65568b7f
parent1424acad7097fb51639a8c4003281f78fc0497c8 (diff)
downloadchrome-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.c18
-rw-r--r--zephyr/test/drivers/dps/CMakeLists.txt2
-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.c238
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);