diff options
author | Tomasz Michalec <tm@semihalf.com> | 2021-11-25 14:50:44 +0100 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-12-01 13:39:16 +0000 |
commit | c11b139b0bdee8e9fc8dec8cd65ccb3bbb46c7db (patch) | |
tree | 14263723b2163377d113e820aa7a47ad70af6d86 | |
parent | fbacc63332b8fbb6662c717a575d824b24730365 (diff) | |
download | chrome-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.c | 174 |
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 = ¶ms; + 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 = ¶ms; + 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); } |