summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Bettis <jbettis@google.com>2022-10-05 15:09:06 -0600
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-10-11 00:14:13 +0000
commit575a59ea39cbeadae46adfb986df652aa0d0074e (patch)
tree02ebe61be9bad5bb9dc7742e21704776f092be25
parent439186b7dade51b9255295afd9b62bde2221cb95 (diff)
downloadchrome-ec-575a59ea39cbeadae46adfb986df652aa0d0074e.tar.gz
zephyr: Add new qcom tests
Several new test cases for power/qcom.c BRANCH=None BUG=b:236074354 TEST=Yes Signed-off-by: Jeremy Bettis <jbettis@google.com> Change-Id: I47d5b66eab778e9d3ce1a6fbe99d0527cdd522c2 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3936946 Auto-Submit: Jeremy Bettis <jbettis@chromium.org> Code-Coverage: Zoss <zoss-cl-coverage@prod.google.com> Commit-Queue: Jeremy Bettis <jbettis@chromium.org> Tested-by: Jeremy Bettis <jbettis@chromium.org> Reviewed-by: Keith Short <keithshort@chromium.org>
-rw-r--r--zephyr/test/qcom_power/CMakeLists.txt13
-rw-r--r--zephyr/test/qcom_power/Kconfig5
-rw-r--r--zephyr/test/qcom_power/boards/native_posix.overlay140
-rw-r--r--zephyr/test/qcom_power/prj.conf39
-rw-r--r--zephyr/test/qcom_power/src/main.c202
-rw-r--r--zephyr/test/qcom_power/testcase.yaml4
6 files changed, 403 insertions, 0 deletions
diff --git a/zephyr/test/qcom_power/CMakeLists.txt b/zephyr/test/qcom_power/CMakeLists.txt
new file mode 100644
index 0000000000..4a211dcc85
--- /dev/null
+++ b/zephyr/test/qcom_power/CMakeLists.txt
@@ -0,0 +1,13 @@
+# Copyright 2021 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+cmake_minimum_required(VERSION 3.13.1)
+find_package(Zephyr REQUIRED HINTS "${ZEPHYR_BASE}")
+project(qcom_power)
+
+# Include the local test directory for shimmed_test_tasks.h
+zephyr_include_directories("${CMAKE_CURRENT_SOURCE_DIR}")
+
+FILE(GLOB_RECURSE test_sources src/*.c)
+target_sources(app PRIVATE ${test_sources})
diff --git a/zephyr/test/qcom_power/Kconfig b/zephyr/test/qcom_power/Kconfig
new file mode 100644
index 0000000000..ac7b264855
--- /dev/null
+++ b/zephyr/test/qcom_power/Kconfig
@@ -0,0 +1,5 @@
+# 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.
+
+source "Kconfig.zephyr"
diff --git a/zephyr/test/qcom_power/boards/native_posix.overlay b/zephyr/test/qcom_power/boards/native_posix.overlay
new file mode 100644
index 0000000000..cda68b4b4c
--- /dev/null
+++ b/zephyr/test/qcom_power/boards/native_posix.overlay
@@ -0,0 +1,140 @@
+/* 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 <board-overlays/native_posix.dts>
+#include <dt-bindings/gpio_defines.h>
+#include <cros/binman.dtsi>
+
+/ {
+ chosen {
+ cros-ec,flash-controller = &cros_flash;
+ };
+ aliases {
+ gpio-wp = &gpio_wp_l;
+ };
+ cros_flash: cros-flash {
+ compatible = "cros-ec,flash-emul";
+ };
+
+ /*
+ * Keep these GPIOs in pin order.
+ * If you need to add one, make sure you increase
+ * ngpios in the gpio0 node further down.
+ */
+ named-gpios {
+ compatible = "named-gpios";
+
+ gpio_acok_od: acok_od {
+ gpios = <&gpio0 0 GPIO_INPUT>;
+ enum-name = "GPIO_AC_PRESENT";
+ };
+ ec_bl_disable_l {
+ gpios = <&gpio0 1 GPIO_INPUT>;
+ enum-name = "GPIO_ENABLE_BACKLIGHT";
+ };
+ gpio_en_pp5000_s5: en_pp5000_s5 {
+ gpios = <&gpio0 2 GPIO_OUTPUT_HIGH>;
+ enum-name = "GPIO_EN_PP5000";
+ };
+ gpio_wp_l: wp_l {
+ gpios = <&gpio0 3 (GPIO_INPUT | GPIO_ACTIVE_LOW)>;
+ };
+ gpio_switchcap_pg_int_l: switchcap_pg_int_l {
+ gpios = <&gpio0 15 (GPIO_OUTPUT | GPIO_INPUT)>;
+ };
+ gpio_ap_rst_l: ap_rst_l {
+ gpios = <&gpio0 16 GPIO_INPUT>;
+ enum-name = "GPIO_AP_RST_L";
+ };
+ gpio_ps_hold: ps_hold {
+ gpios = <&gpio0 17 (GPIO_INPUT | GPIO_PULL_DOWN)>;
+ enum-name = "GPIO_PS_HOLD";
+ };
+ gpio_mb_power_good: mb_power_good {
+ gpios = <&gpio0 18 (GPIO_OUTPUT | GPIO_INPUT |
+ GPIO_PULL_DOWN)>;
+ enum-name = "GPIO_POWER_GOOD";
+ };
+ gpio_ap_suspend: ap_suspend {
+ gpios = <&gpio0 19 GPIO_INPUT>;
+ enum-name = "GPIO_AP_SUSPEND";
+ };
+ gpio_pmic_kpd_pwr_odl: pmic_kpd_pwr_odl {
+ gpios = <&gpio0 20 GPIO_OUTPUT_HIGH>;
+ enum-name = "GPIO_PMIC_KPD_PWR_ODL";
+ };
+ gpio_pmic_resin_l: pmic_resin_l {
+ gpios = <&gpio0 21 GPIO_OUTPUT_HIGH>;
+ enum-name = "GPIO_PMIC_RESIN_L";
+ };
+ gpio_warm_reset_l: warm_reset_l {
+ gpios = <&gpio0 22 GPIO_INPUT>;
+ enum-name = "GPIO_WARM_RESET_L";
+ };
+ gpio_lid_open_ec: lid_open_ec {
+ /* GPIO_PULL_UP will cause this start asserted. */
+ gpios = <&gpio0 23 (GPIO_INPUT | GPIO_PULL_UP)>;
+ enum-name = "GPIO_LID_OPEN";
+ };
+ gpio_switchcap_on: switchcap_on {
+ gpios = <&gpio0 24 (GPIO_INPUT | GPIO_OUTPUT_LOW)>;
+ };
+ gpio_ec_pwr_btn_odl: ec_pwr_btn_odl {
+ /* GPIO_PULL_UP will cause this start asserted,
+ * i.e. not pressed.
+ */
+ gpios = <&gpio0 25 (GPIO_INPUT | GPIO_PULL_UP)>;
+ enum-name = "GPIO_POWER_BUTTON_L";
+ };
+ };
+
+ gpio-interrupts {
+ compatible = "cros-ec,gpio-interrupts";
+
+ int_ap_rst: ap_rst {
+ irq-pin = <&gpio_ap_rst_l>;
+ flags = <GPIO_INT_EDGE_BOTH>;
+ handler = "chipset_ap_rst_interrupt";
+ };
+ int_lid_open_ec: lid_open_ec {
+ irq-pin = <&gpio_lid_open_ec>;
+ flags = <GPIO_INT_EDGE_BOTH>;
+ handler = "lid_interrupt";
+ };
+ int_mb_power_good: mb_power_good {
+ irq-pin = <&gpio_mb_power_good>;
+ flags = <GPIO_INT_EDGE_BOTH>;
+ handler = "power_signal_interrupt";
+ };
+ int_ap_suspend: ap_suspend {
+ irq-pin = <&gpio_ap_suspend>;
+ flags = <GPIO_INT_EDGE_BOTH>;
+ handler = "power_signal_interrupt";
+ };
+ };
+
+ gpio1: gpio@101 {
+ status = "okay";
+ compatible = "zephyr,gpio-emul";
+ reg = <0x101 0x4>;
+ rising-edge;
+ falling-edge;
+ high-level;
+ low-level;
+ gpio-controller;
+ #gpio-cells = <2>;
+ ngpios = <7>;
+ };
+
+ switchcap {
+ compatible = "switchcap-gpio";
+ enable-pin = <&gpio_switchcap_on>;
+ power-good-pin = <&gpio_switchcap_pg_int_l>;
+ };
+};
+
+&gpio0 {
+ ngpios = <32>;
+};
diff --git a/zephyr/test/qcom_power/prj.conf b/zephyr/test/qcom_power/prj.conf
new file mode 100644
index 0000000000..471e4cd9d5
--- /dev/null
+++ b/zephyr/test/qcom_power/prj.conf
@@ -0,0 +1,39 @@
+# 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.
+
+CONFIG_ZTEST=y
+CONFIG_ZTEST_ASSERT_VERBOSE=1
+CONFIG_ZTEST_MOCKING=y
+CONFIG_ZTEST_NEW_API=y
+CONFIG_TEST=y
+CONFIG_ASSERT=y
+
+# Print logs from Zephyr LOG_MODULE to stdout
+CONFIG_NATIVE_UART_0_ON_STDINOUT=y
+
+CONFIG_PLATFORM_EC=y
+CONFIG_CROS_EC=y
+CONFIG_SHIMMED_TASKS=y
+CONFIG_LOG=y
+CONFIG_EMUL=y
+CONFIG_GPIO=y
+CONFIG_GPIO_EMUL=y
+CONFIG_EMUL_CROS_FLASH=y
+CONFIG_FLASH=y
+CONFIG_SHELL_BACKEND_DUMMY=y
+CONFIG_SHELL_BACKEND_DUMMY_BUF_SIZE=1000
+CONFIG_SHELL_BACKEND_SERIAL=n
+CONFIG_SERIAL=y
+
+# QCom power sequencing
+CONFIG_PLATFORM_EC_POWERSEQ=y
+CONFIG_AP_ARM_QUALCOMM_SC7280=y
+CONFIG_PLATFORM_EC_POWERSEQ_SC7280=y
+CONFIG_PLATFORM_EC_POWERSEQ_HOST_SLEEP=y
+CONFIG_PLATFORM_EC_LID_SWITCH=y
+CONFIG_PLATFORM_EC_SWITCHCAP_GPIO=y
+CONFIG_PLATFORM_EC_POWER_BUTTON=y
+CONFIG_PLATFORM_EC_HOSTCMD=y
+CONFIG_PLATFORM_EC_EXTPOWER_GPIO=y
+CONFIG_PLATFORM_EC_EXTPOWER=y
diff --git a/zephyr/test/qcom_power/src/main.c b/zephyr/test/qcom_power/src/main.c
new file mode 100644
index 0000000000..3e06337241
--- /dev/null
+++ b/zephyr/test/qcom_power/src/main.c
@@ -0,0 +1,202 @@
+/* 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 <zephyr/device.h>
+#include <zephyr/devicetree.h>
+#include <zephyr/kernel.h>
+#include <zephyr/ztest.h>
+#include <zephyr/drivers/gpio/gpio_emul.h>
+#include <zephyr/shell/shell_dummy.h>
+
+#include "gpio_signal.h"
+#include "power/qcom.h"
+#include "battery.h"
+#include "ec_app_main.h"
+#include "power.h"
+#include "console.h"
+#include "task.h"
+#include "hooks.h"
+
+#define AP_RST_L_NODE DT_PATH(named_gpios, ap_rst_l)
+#define POWER_GOOD_NODE DT_PATH(named_gpios, mb_power_good)
+#define AP_SUSPEND_NODE DT_PATH(named_gpios, ap_suspend)
+
+static int chipset_reset_count;
+
+static void do_chipset_reset(void)
+{
+ chipset_reset_count++;
+}
+DECLARE_HOOK(HOOK_CHIPSET_RESET, do_chipset_reset, HOOK_PRIO_DEFAULT);
+
+/* Tests the chipset_ap_rst_interrupt() handler when in S3.
+ *
+ * When the system is in S3, and ap_rst_l is pulsed 1-3 times then
+ * HOOK_CHIPSET_RESET hooks will run, and interrupts will be disabled for
+ * ap_suspend (see power_chipset_handle_host_sleep_event). This may be
+ * artificial, since I'm not sure that this scenario can actually ever happen.
+ */
+static void do_chipset_ap_rst_interrupt_in_s3(int times)
+{
+ static const struct device *ap_rst_dev =
+ DEVICE_DT_GET(DT_GPIO_CTLR(AP_RST_L_NODE, gpios));
+ static const struct device *power_good_dev =
+ DEVICE_DT_GET(DT_GPIO_CTLR(POWER_GOOD_NODE, gpios));
+ static const struct device *ap_suspend_dev =
+ DEVICE_DT_GET(DT_GPIO_CTLR(AP_SUSPEND_NODE, gpios));
+
+ /* Preconditions */
+ power_signal_enable_interrupt(GPIO_AP_SUSPEND);
+ power_signal_enable_interrupt(GPIO_AP_RST_L);
+ zassert_ok(gpio_emul_input_set(power_good_dev,
+ DT_GPIO_PIN(POWER_GOOD_NODE, gpios), 1));
+ zassert_ok(gpio_emul_input_set(ap_suspend_dev,
+ DT_GPIO_PIN(AP_SUSPEND_NODE, gpios), 1));
+ power_set_state(POWER_S3);
+ task_wake(TASK_ID_CHIPSET);
+ k_sleep(K_MSEC(10));
+ zassert_equal(power_get_state(), POWER_S3);
+
+ shell_backend_dummy_clear_output(get_ec_shell());
+ chipset_reset_count = 0;
+
+ /* Pulse gpio_ap_rst_l `times` */
+ for (int i = 0; i < times; ++i) {
+ zassert_ok(gpio_emul_input_set(
+ ap_rst_dev, DT_GPIO_PIN(AP_RST_L_NODE, gpios), 1));
+ zassert_ok(gpio_emul_input_set(
+ ap_rst_dev, DT_GPIO_PIN(AP_RST_L_NODE, gpios), 0));
+ }
+
+ /* Wait for timeout AP_RST_TRANSITION_TIMEOUT. */
+ k_sleep(K_MSEC(500));
+
+ /* Verify that gpio_ap_suspend is ignored. */
+ zassert_ok(gpio_emul_input_set(ap_suspend_dev,
+ DT_GPIO_PIN(AP_SUSPEND_NODE, gpios), 0));
+ k_sleep(K_MSEC(10));
+ zassert_equal(power_get_state(), POWER_S3);
+ /* Verify that HOOK_CHIPSET_RESET was called once. */
+ zassert_equal(chipset_reset_count, 1);
+}
+
+ZTEST(qcom_power, test_notify_chipset_reset_s3_timeout)
+{
+ const char *buffer;
+ size_t buffer_size;
+
+ do_chipset_ap_rst_interrupt_in_s3(1);
+ buffer = shell_backend_dummy_get_output(get_ec_shell(), &buffer_size);
+ zassert_true(strstr(buffer, "AP_RST_L transitions not expected: 1") !=
+ NULL,
+ "Invalid console output %s", buffer);
+ zassert_true(strstr(buffer, "Chipset reset: exit s3") != NULL,
+ "Invalid console output %s", buffer);
+}
+
+ZTEST(qcom_power, test_notify_chipset_reset_s3)
+{
+ const char *buffer;
+ size_t buffer_size;
+
+ do_chipset_ap_rst_interrupt_in_s3(3);
+ buffer = shell_backend_dummy_get_output(get_ec_shell(), &buffer_size);
+ zassert_false(strstr(buffer, "AP_RST_L transitions not expected") !=
+ NULL,
+ "Invalid console output %s", buffer);
+ zassert_true(strstr(buffer, "Chipset reset: exit s3") != NULL,
+ "Invalid console output %s", buffer);
+}
+
+/* Tests the chipset_ap_rst_interrupt() handler when in S0.
+ *
+ * When the system is in S0, and ap_rst_l is pulsed 1-3 times then
+ * HOOK_CHIPSET_RESET hooks will run, and that is pretty much all that happens.
+ */
+static void do_chipset_ap_rst_interrupt_in_s0(int times)
+{
+ static const struct device *ap_rst_dev =
+ DEVICE_DT_GET(DT_GPIO_CTLR(AP_RST_L_NODE, gpios));
+ static const struct device *power_good_dev =
+ DEVICE_DT_GET(DT_GPIO_CTLR(POWER_GOOD_NODE, gpios));
+ static const struct device *ap_suspend_dev =
+ DEVICE_DT_GET(DT_GPIO_CTLR(AP_SUSPEND_NODE, gpios));
+
+ /* Preconditions */
+ zassert_ok(gpio_emul_input_set(power_good_dev,
+ DT_GPIO_PIN(POWER_GOOD_NODE, gpios), 1));
+ zassert_ok(gpio_emul_input_set(ap_suspend_dev,
+ DT_GPIO_PIN(AP_SUSPEND_NODE, gpios), 0));
+ power_set_state(POWER_S0);
+ power_signal_disable_interrupt(GPIO_AP_SUSPEND);
+ power_signal_enable_interrupt(GPIO_AP_RST_L);
+ task_wake(TASK_ID_CHIPSET);
+ k_sleep(K_MSEC(10));
+ zassert_equal(power_get_state(), POWER_S0);
+
+ shell_backend_dummy_clear_output(get_ec_shell());
+ chipset_reset_count = 0;
+
+ /* Pulse gpio_ap_rst_l `times` */
+ for (int i = 0; i < times; ++i) {
+ zassert_ok(gpio_emul_input_set(
+ ap_rst_dev, DT_GPIO_PIN(AP_RST_L_NODE, gpios), 1));
+ zassert_ok(gpio_emul_input_set(
+ ap_rst_dev, DT_GPIO_PIN(AP_RST_L_NODE, gpios), 0));
+ }
+
+ /* Wait for timeout AP_RST_TRANSITION_TIMEOUT. */
+ k_sleep(K_MSEC(500));
+
+ /* Verify that HOOK_CHIPSET_RESET was called once. */
+ zassert_equal(chipset_reset_count, 1);
+}
+
+ZTEST(qcom_power, test_notify_chipset_reset_s0_timeout)
+{
+ const char *buffer;
+ size_t buffer_size;
+
+ do_chipset_ap_rst_interrupt_in_s0(1);
+ buffer = shell_backend_dummy_get_output(get_ec_shell(), &buffer_size);
+ zassert_true(strstr(buffer, "AP_RST_L transitions not expected: 1") !=
+ NULL,
+ "Invalid console output %s", buffer);
+ zassert_false(strstr(buffer, "Chipset reset: exit s3") != NULL,
+ "Invalid console output %s", buffer);
+}
+
+ZTEST(qcom_power, test_notify_chipset_reset_s0)
+{
+ const char *buffer;
+ size_t buffer_size;
+
+ do_chipset_ap_rst_interrupt_in_s0(3);
+ buffer = shell_backend_dummy_get_output(get_ec_shell(), &buffer_size);
+ zassert_false(strstr(buffer, "AP_RST_L transitions not expected") !=
+ NULL,
+ "Invalid console output %s", buffer);
+ zassert_false(strstr(buffer, "Chipset reset: exit s3") != NULL,
+ "Invalid console output %s", buffer);
+}
+
+ZTEST_SUITE(qcom_power, NULL, NULL, NULL, NULL, NULL);
+
+/* Wait until battery is totally stable */
+int battery_wait_for_stable(void)
+{
+ return EC_SUCCESS;
+}
+
+void test_main(void)
+{
+ ec_app_main();
+ /* Fake sleep long enough to go to S5 and back to G3 again. */
+ k_sleep(K_SECONDS(11));
+
+ ztest_run_test_suites(NULL);
+
+ ztest_verify_all_test_suites_ran();
+}
diff --git a/zephyr/test/qcom_power/testcase.yaml b/zephyr/test/qcom_power/testcase.yaml
new file mode 100644
index 0000000000..fe580b27e8
--- /dev/null
+++ b/zephyr/test/qcom_power/testcase.yaml
@@ -0,0 +1,4 @@
+common:
+ platform_allow: native_posix
+tests:
+ qcom_power.default: {}