summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Michalec <tm@semihalf.com>2021-11-25 14:50:44 +0100
committerCommit Bot <commit-bot@chromium.org>2021-12-01 13:39:16 +0000
commitc11b139b0bdee8e9fc8dec8cd65ccb3bbb46c7db (patch)
tree14263723b2163377d113e820aa7a47ad70af6d86
parentfbacc63332b8fbb6662c717a575d824b24730365 (diff)
downloadchrome-ec-c11b139b0bdee8e9fc8dec8cd65ccb3bbb46c7db.tar.gz
zephyr: drivers: Add unit test for smart discharge
Add unit test of setting smart discharge zones using host command. Test if generic board_system_is_idle() recognizes smart discharge zones correctly. BUG=b:206903370 BRANCH=none TEST=zmake configure --test zephyr/test/drivers Signed-off-by: Tomasz Michalec <tm@semihalf.com> Change-Id: Ia8e8f9a33183fc0bf6ed4f6705c96e86e4f1ef5d Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3302214 Tested-by: Tomasz Michalec <tmichalec@google.com> Commit-Queue: Tomasz Michalec <tmichalec@google.com> Reviewed-by: Fabio Baltieri <fabiobaltieri@google.com>
-rw-r--r--zephyr/test/drivers/src/power_common.c174
1 files changed, 173 insertions, 1 deletions
diff --git a/zephyr/test/drivers/src/power_common.c b/zephyr/test/drivers/src/power_common.c
index fe056397d3..8c043d7a43 100644
--- a/zephyr/test/drivers/src/power_common.c
+++ b/zephyr/test/drivers/src/power_common.c
@@ -12,6 +12,14 @@
#include "stubs.h"
#include "task.h"
+#include "emul/emul_common_i2c.h"
+#include "emul/emul_smart_battery.h"
+
+#include "battery.h"
+#include "battery_smart.h"
+
+#define BATTERY_ORD DT_DEP_ORD(DT_NODELABEL(battery))
+
/* Description of all power states with chipset state masks */
static struct {
/* Power state */
@@ -274,6 +282,168 @@ static void test_power_reboot_ap_at_g3(void)
zassert_equal(POWER_G3S5, power_get_state(), NULL);
}
+/** Test setting cutoff and stay-up battery levels through host command */
+static void test_power_hc_smart_discharge(void)
+{
+ struct ec_response_smart_discharge response;
+ struct ec_params_smart_discharge params;
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND(EC_CMD_SMART_DISCHARGE, 0, response);
+ struct i2c_emul *emul;
+ int hours_to_zero;
+ int hibern_drate;
+ int cutoff_drate;
+ int stayup_cap;
+ int cutoff_cap;
+
+ emul = sbat_emul_get_ptr(BATTERY_ORD);
+
+ /* Set up host command parameters */
+ args.params = &params;
+ args.params_size = sizeof(params);
+
+ params.flags = EC_SMART_DISCHARGE_FLAGS_SET;
+
+ /* Test fail when battery capacity is not available */
+ i2c_common_emul_set_read_fail_reg(emul, SB_FULL_CHARGE_CAPACITY);
+ zassert_equal(EC_RES_UNAVAILABLE, host_command_process(&args), NULL);
+ i2c_common_emul_set_read_fail_reg(emul, I2C_COMMON_EMUL_NO_FAIL_REG);
+
+ /* Setup discharge rates */
+ params.drate.hibern = 10;
+ params.drate.cutoff = 100;
+ /* Test fail on higher discahrge in hibernation than cutoff */
+ zassert_equal(EC_RES_INVALID_PARAM, host_command_process(&args), NULL);
+
+ /* Setup discharge rates */
+ params.drate.hibern = 10;
+ params.drate.cutoff = 0;
+ /* Test fail on only one discharge rate set to 0 */
+ zassert_equal(EC_RES_INVALID_PARAM, host_command_process(&args), NULL);
+
+ /* Setup correct parameters */
+ hours_to_zero = 1000;
+ hibern_drate = 100; /* uA */
+ cutoff_drate = 10; /* uA */
+ /* Need at least 100 mA capacity to stay 1000h using 0.1mAh */
+ stayup_cap = hibern_drate * hours_to_zero / 1000;
+ /* Need at least 10 mA capacity to stay 1000h using 0.01mAh */
+ cutoff_cap = cutoff_drate * hours_to_zero / 1000;
+
+ params.drate.hibern = hibern_drate;
+ params.drate.cutoff = cutoff_drate;
+ params.hours_to_zero = hours_to_zero;
+
+ /* Test if correct values are set */
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+ zassert_equal(hibern_drate, response.drate.hibern, NULL);
+ zassert_equal(cutoff_drate, response.drate.cutoff, NULL);
+ zassert_equal(hours_to_zero, response.hours_to_zero, NULL);
+ zassert_equal(stayup_cap, response.dzone.stayup, NULL);
+ zassert_equal(cutoff_cap, response.dzone.cutoff, NULL);
+
+ /* Setup discharge rate to 0 */
+ params.drate.hibern = 0;
+ params.drate.cutoff = 0;
+ /* Update hours to zero */
+ hours_to_zero = 2000;
+ params.hours_to_zero = hours_to_zero;
+ /* Need at least 200 mA capacity to stay 2000h using 0.1mAh */
+ stayup_cap = hibern_drate * hours_to_zero / 1000;
+ /* Need at least 20 mA capacity to stay 2000h using 0.01mAh */
+ cutoff_cap = cutoff_drate * hours_to_zero / 1000;
+
+ /* Test that command doesn't change drate but apply new hours to zero */
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+ zassert_equal(hibern_drate, response.drate.hibern, NULL);
+ zassert_equal(cutoff_drate, response.drate.cutoff, NULL);
+ zassert_equal(hours_to_zero, response.hours_to_zero, NULL);
+ zassert_equal(stayup_cap, response.dzone.stayup, NULL);
+ zassert_equal(cutoff_cap, response.dzone.cutoff, NULL);
+
+ /* Setup any parameters != 0 */
+ params.drate.hibern = 1000;
+ params.drate.cutoff = 1000;
+ /* Clear set flag */
+ params.flags = 0;
+
+ /* Test that command doesn't change drate and dzone */
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+ zassert_equal(hibern_drate, response.drate.hibern, NULL);
+ zassert_equal(cutoff_drate, response.drate.cutoff, NULL);
+ zassert_equal(hours_to_zero, response.hours_to_zero, NULL);
+ zassert_equal(stayup_cap, response.dzone.stayup, NULL);
+ zassert_equal(cutoff_cap, response.dzone.cutoff, NULL);
+}
+
+/**
+ * Test if default board_system_is_idle() recognize cutoff and stay-up
+ * levels correctly.
+ */
+static void test_power_board_system_is_idle(void)
+{
+ struct ec_response_smart_discharge response;
+ struct ec_params_smart_discharge params;
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND(EC_CMD_SMART_DISCHARGE, 0, response);
+ struct sbat_emul_bat_data *bat;
+ struct i2c_emul *emul;
+ uint64_t last_shutdown_time = 0;
+ uint64_t target;
+ uint64_t now;
+
+ emul = sbat_emul_get_ptr(BATTERY_ORD);
+ bat = sbat_emul_get_bat_data(emul);
+
+ /* Set up host command parameters */
+ args.params = &params;
+ args.params_size = sizeof(params);
+ params.drate.hibern = 100; /* uA */
+ params.drate.cutoff = 10; /* uA */
+ params.hours_to_zero = 1000; /* h */
+ params.flags = EC_SMART_DISCHARGE_FLAGS_SET;
+ /* Set stay-up and cutoff zones */
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+
+ /* Test shutdown ignore is send when target time is in future */
+ target = 1125;
+ now = 1000;
+ zassert_equal(CRITICAL_SHUTDOWN_IGNORE,
+ board_system_is_idle(last_shutdown_time, &target, now),
+ NULL);
+
+ /* Set "now" time after target time */
+ now = target + 30;
+
+ /*
+ * Test hibernation is requested when battery remaining capacity
+ * is not available
+ */
+ i2c_common_emul_set_read_fail_reg(emul, SB_REMAINING_CAPACITY);
+ zassert_equal(CRITICAL_SHUTDOWN_HIBERNATE,
+ board_system_is_idle(last_shutdown_time, &target, now),
+ NULL);
+ i2c_common_emul_set_read_fail_reg(emul, I2C_COMMON_EMUL_NO_FAIL_REG);
+
+ /* Setup remaining capacity to trigger cutoff */
+ bat->cap = response.dzone.cutoff - 5;
+ zassert_equal(CRITICAL_SHUTDOWN_CUTOFF,
+ board_system_is_idle(last_shutdown_time, &target, now),
+ NULL);
+
+ /* Setup remaining capacity to trigger stay-up and ignore shutdown */
+ bat->cap = response.dzone.stayup - 5;
+ zassert_equal(CRITICAL_SHUTDOWN_IGNORE,
+ board_system_is_idle(last_shutdown_time, &target, now),
+ NULL);
+
+ /* Setup remaining capacity to be in safe zone to hibernate */
+ bat->cap = response.dzone.stayup + 5;
+ zassert_equal(CRITICAL_SHUTDOWN_HIBERNATE,
+ board_system_is_idle(last_shutdown_time, &target, now),
+ NULL);
+}
+
void test_suite_power_common(void)
{
ztest_test_suite(power_common,
@@ -281,6 +451,8 @@ void test_suite_power_common(void)
ztest_unit_test(
test_power_chipset_in_or_transitioning_to_state),
ztest_unit_test(test_power_exit_hard_off),
- ztest_unit_test(test_power_reboot_ap_at_g3));
+ ztest_unit_test(test_power_reboot_ap_at_g3),
+ ztest_unit_test(test_power_hc_smart_discharge),
+ ztest_unit_test(test_power_board_system_is_idle));
ztest_run_test_suite(power_common);
}