summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomasz Michalec <tm@semihalf.com>2021-11-25 15:08:39 +0100
committerCommit Bot <commit-bot@chromium.org>2021-12-01 13:39:20 +0000
commit3e87d882a28737dc76ce2257b931af528f353552 (patch)
tree3bbde24682070af555ee4bba64deed6337375c68
parentc11b139b0bdee8e9fc8dec8cd65ccb3bbb46c7db (diff)
downloadchrome-ec-factory-kukui-14374.B-main.tar.gz
zephyr: drivers: Add hibernation delay unit testfactory-kukui-14374.B-main
Add unit test for hibernation delay set using host command and UART command. system_hibernate() function in test stubs is replaced with FFF fake function to allow tests to check if it was called. BUG=b:206903370 BRANCH=none TEST=zmake configure --test zephyr/test/drivers Signed-off-by: Tomasz Michalec <tm@semihalf.com> Change-Id: I7546a736f9dfa731875741930fa4e6dd9106d22d Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3302215 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/include/stubs.h4
-rw-r--r--zephyr/test/drivers/src/power_common.c231
-rw-r--r--zephyr/test/drivers/src/stubs.c5
3 files changed, 236 insertions, 4 deletions
diff --git a/zephyr/test/drivers/include/stubs.h b/zephyr/test/drivers/include/stubs.h
index 0e96b777e1..af32a988c6 100644
--- a/zephyr/test/drivers/include/stubs.h
+++ b/zephyr/test/drivers/include/stubs.h
@@ -6,6 +6,7 @@
#ifndef __TEST_DRIVERS_STUBS_H
#define __TEST_DRIVERS_STUBS_H
+#include "fff.h"
#include "power.h"
enum usbc_port { USBC_PORT_C0 = 0, USBC_PORT_C1, USBC_PORT_COUNT };
@@ -31,4 +32,7 @@ void force_power_state(bool force, enum power_state state);
*/
void board_set_ps8xxx_product_id(uint16_t product_id);
+/* Declare fake function to allow tests to examine calls to this function */
+DECLARE_FAKE_VOID_FUNC(system_hibernate, uint32_t, uint32_t);
+
#endif /* __TEST_DRIVERS_STUBS_H */
diff --git a/zephyr/test/drivers/src/power_common.c b/zephyr/test/drivers/src/power_common.c
index 8c043d7a43..19003c8dde 100644
--- a/zephyr/test/drivers/src/power_common.c
+++ b/zephyr/test/drivers/src/power_common.c
@@ -4,9 +4,15 @@
*/
#include <ztest.h>
+#include <drivers/gpio.h>
+#include <drivers/gpio/gpio_emul.h>
+#include <shell/shell.h>
+#include <shell/shell_uart.h>
#include "chipset.h"
#include "common.h"
+#include "extpower.h"
+#include "hooks.h"
#include "host_command.h"
#include "power.h"
#include "stubs.h"
@@ -20,6 +26,9 @@
#define BATTERY_ORD DT_DEP_ORD(DT_NODELABEL(battery))
+#define GPIO_ACOK_OD_NODE DT_PATH(named_gpios, acok_od)
+#define GPIO_ACOK_OD_PIN DT_GPIO_PIN(GPIO_ACOK_OD_NODE, gpios)
+
/* Description of all power states with chipset state masks */
static struct {
/* Power state */
@@ -444,6 +453,220 @@ static void test_power_board_system_is_idle(void)
NULL);
}
+/**
+ * Common setup for hibernation delay tests. Smart discharge zone is setup,
+ * battery is set in safe zone (which trigger hibernation), power state is
+ * set to G3 and AC is disabled. system_hibernate mock is reset.
+ */
+static void setup_hibernation_delay(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);
+ const struct device *acok_dev =
+ DEVICE_DT_GET(DT_GPIO_CTLR(GPIO_ACOK_OD_NODE, gpios));
+ struct sbat_emul_bat_data *bat;
+ struct i2c_emul *emul;
+
+ emul = sbat_emul_get_ptr(BATTERY_ORD);
+ bat = sbat_emul_get_bat_data(emul);
+
+ /* Setup smart discharge zone and set capacity to safe zone */
+ args.params = &params;
+ args.params_size = sizeof(params);
+ params.drate.hibern = 100; /* uA */
+ params.drate.cutoff = 10; /* uA */
+ params.hours_to_zero = 10000; /* h */
+ params.flags = EC_SMART_DISCHARGE_FLAGS_SET;
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+ /*
+ * Make sure that battery is in safe zone in good condition to
+ * not trigger hibernate in charge_state_v2.c
+ */
+ bat->cap = response.dzone.stayup + 5;
+ bat->volt = battery_get_info()->voltage_normal;
+
+ /* Force initial state */
+ force_power_state(true, POWER_G3);
+ zassert_equal(POWER_G3, power_get_state(), NULL);
+
+ /* Stop forcing state */
+ force_power_state(false, 0);
+
+ /* Disable AC */
+ zassert_ok(gpio_emul_input_set(acok_dev, GPIO_ACOK_OD_PIN, 0), NULL);
+ msleep(CONFIG_EXTPOWER_DEBOUNCE_MS + 1);
+ zassert_equal(0, extpower_is_present(), NULL);
+
+ RESET_FAKE(system_hibernate);
+}
+
+/** Test setting hibernation delay through host command */
+static void test_power_hc_hibernation_delay(void)
+{
+ struct ec_response_hibernation_delay response;
+ struct ec_params_hibernation_delay params;
+ struct host_cmd_handler_args args =
+ BUILD_HOST_COMMAND(EC_CMD_HIBERNATION_DELAY, 0, response);
+ const struct device *acok_dev =
+ DEVICE_DT_GET(DT_GPIO_CTLR(GPIO_ACOK_OD_NODE, gpios));
+ uint32_t h_delay;
+ int sleep_time;
+
+ /* Setup hibernation delay host command */
+ args.params = &params;
+ args.params_size = sizeof(params);
+
+ /* Set hibernate delay */
+ h_delay = 9;
+ params.seconds = h_delay;
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+
+ zassert_equal(0, response.time_g3, "Time from last G3 enter %d != 0",
+ response.time_g3);
+ zassert_equal(h_delay, response.time_remaining,
+ "Time to hibernation %d != %d",
+ response.time_remaining, h_delay);
+ zassert_equal(h_delay, response.hibernate_delay,
+ "Hibernation delay %d != %d",
+ h_delay, response.hibernate_delay);
+
+ /* Kick chipset task to process new hibernation delay */
+ task_wake(TASK_ID_CHIPSET);
+ /* Wait some arbitrary time less than hibernate delay */
+ sleep_time = 6;
+ k_msleep(sleep_time * 1000);
+
+ /* Get hibernate delay */
+ params.seconds = 0;
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+
+ zassert_equal(sleep_time, response.time_g3,
+ "Time from last G3 enter %d != %d",
+ response.time_g3, sleep_time);
+ zassert_equal(h_delay - sleep_time, response.time_remaining,
+ "Time to hibernation %d != %d",
+ response.time_remaining, h_delay - sleep_time);
+ zassert_equal(h_delay, response.hibernate_delay,
+ "Hibernation delay %d != %d",
+ h_delay, response.hibernate_delay);
+ zassert_equal(0, system_hibernate_fake.call_count,
+ "system_hibernate() shouldn't be called before delay");
+
+ /* Wait to end of the hibenate delay */
+ k_msleep((h_delay - sleep_time) * 1000);
+
+ /* Get hibernate delay */
+ params.seconds = 0;
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+
+ zassert_equal(h_delay, response.time_g3,
+ "Time from last G3 enter %d != %d",
+ response.time_g3, h_delay);
+ zassert_equal(0, response.time_remaining,
+ "Time to hibernation %d != 0",
+ response.time_remaining);
+ zassert_equal(h_delay, response.hibernate_delay,
+ "Hibernation delay %d != %d",
+ h_delay, response.hibernate_delay);
+ zassert_equal(1, system_hibernate_fake.call_count,
+ "system_hibernate() should be called after delay %d",
+ system_hibernate_fake.call_count);
+
+ /* Wait some more time */
+ k_msleep(2000);
+
+ /* Get hibernate delay */
+ params.seconds = 0;
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+
+ /* After hibernation, remaining time shouldn't be negative */
+ zassert_equal(0, response.time_remaining,
+ "Time to hibernation %d != 0",
+ response.time_remaining);
+
+ /* Enable AC */
+ zassert_ok(gpio_emul_input_set(acok_dev, GPIO_ACOK_OD_PIN, 1), NULL);
+ msleep(CONFIG_EXTPOWER_DEBOUNCE_MS + 1);
+ zassert_equal(1, extpower_is_present(), NULL);
+
+ /* Reset system_hibernate fake to check that it is not called on AC */
+ RESET_FAKE(system_hibernate);
+ /* Allow chipset task to spin with enabled AC */
+ task_wake(TASK_ID_CHIPSET);
+ k_msleep(1);
+
+ /* Get hibernate delay */
+ params.seconds = 0;
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+
+ zassert_equal(0, response.time_g3,
+ "Time from last G3 enter %d should be 0 on AC",
+ response.time_g3);
+ zassert_equal(0, system_hibernate_fake.call_count,
+ "system_hibernate() shouldn't be called on AC");
+
+ /* Disable AC */
+ zassert_ok(gpio_emul_input_set(acok_dev, GPIO_ACOK_OD_PIN, 0), NULL);
+ msleep(CONFIG_EXTPOWER_DEBOUNCE_MS + 1);
+ zassert_equal(0, extpower_is_present(), NULL);
+
+ /* Go to different state */
+ force_power_state(true, POWER_G3S5);
+ zassert_equal(POWER_G3S5, power_get_state(), NULL);
+
+ /* Stop forcing state */
+ force_power_state(false, 0);
+
+ /* Get hibernate delay */
+ params.seconds = 0;
+ zassert_equal(EC_RES_SUCCESS, host_command_process(&args), NULL);
+
+ zassert_equal(0, response.time_g3,
+ "Time from last G3 enter %d should be 0 on state != G3",
+ response.time_g3);
+}
+
+/** Test setting hibernation delay through UART command */
+static void test_power_cmd_hibernation_delay(void)
+{
+ uint32_t h_delay;
+ int sleep_time;
+
+ /* Test success on call without argument */
+ zassert_equal(EC_SUCCESS,
+ shell_execute_cmd(shell_backend_uart_get_ptr(),
+ "hibdelay"), NULL);
+
+ /* Test error on hibernation delay argument that is not a number */
+ zassert_equal(EC_ERROR_PARAM1,
+ shell_execute_cmd(shell_backend_uart_get_ptr(),
+ "hibdelay test1"), NULL);
+
+ /* Set hibernate delay */
+ h_delay = 3;
+ zassert_equal(EC_SUCCESS,
+ shell_execute_cmd(shell_backend_uart_get_ptr(),
+ "hibdelay 3"), NULL);
+
+ /* Kick chipset task to process new hibernation delay */
+ task_wake(TASK_ID_CHIPSET);
+ /* Wait some arbitrary time less than hibernate delay */
+ sleep_time = 2;
+ k_msleep(sleep_time * 1000);
+
+ zassert_equal(0, system_hibernate_fake.call_count,
+ "system_hibernate() shouldn't be called before delay");
+
+ /* Wait to end of the hibenate delay */
+ k_msleep((h_delay - sleep_time) * 1000);
+
+ zassert_equal(1, system_hibernate_fake.call_count,
+ "system_hibernate() should be called after delay %d",
+ system_hibernate_fake.call_count);
+}
+
void test_suite_power_common(void)
{
ztest_test_suite(power_common,
@@ -453,6 +676,12 @@ void test_suite_power_common(void)
ztest_unit_test(test_power_exit_hard_off),
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_unit_test(test_power_board_system_is_idle),
+ ztest_unit_test_setup_teardown(
+ test_power_hc_hibernation_delay,
+ setup_hibernation_delay, unit_test_noop),
+ ztest_unit_test_setup_teardown(
+ test_power_cmd_hibernation_delay,
+ setup_hibernation_delay, unit_test_noop));
ztest_run_test_suite(power_common);
}
diff --git a/zephyr/test/drivers/src/stubs.c b/zephyr/test/drivers/src/stubs.c
index f90412089c..ee531557a5 100644
--- a/zephyr/test/drivers/src/stubs.c
+++ b/zephyr/test/drivers/src/stubs.c
@@ -11,6 +11,7 @@
#include "charger/isl923x_public.h"
#include "charger/isl9241_public.h"
#include "config.h"
+#include "fff.h"
#include "hooks.h"
#include "i2c/i2c.h"
#include "power.h"
@@ -301,9 +302,7 @@ struct ppc_config_t ppc_chips[] = {
BUILD_ASSERT(ARRAY_SIZE(ppc_chips) == USBC_PORT_COUNT);
unsigned int ppc_cnt = ARRAY_SIZE(ppc_chips);
-void system_hibernate(uint32_t seconds, uint32_t microseconds)
-{
-}
+DEFINE_FAKE_VOID_FUNC(system_hibernate, uint32_t, uint32_t);
uint16_t tcpc_get_alert_status(void)
{