diff options
author | Jeremy Bettis <jbettis@google.com> | 2022-10-05 15:09:06 -0600 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-10-11 00:14:13 +0000 |
commit | 575a59ea39cbeadae46adfb986df652aa0d0074e (patch) | |
tree | 02ebe61be9bad5bb9dc7742e21704776f092be25 | |
parent | 439186b7dade51b9255295afd9b62bde2221cb95 (diff) | |
download | chrome-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.txt | 13 | ||||
-rw-r--r-- | zephyr/test/qcom_power/Kconfig | 5 | ||||
-rw-r--r-- | zephyr/test/qcom_power/boards/native_posix.overlay | 140 | ||||
-rw-r--r-- | zephyr/test/qcom_power/prj.conf | 39 | ||||
-rw-r--r-- | zephyr/test/qcom_power/src/main.c | 202 | ||||
-rw-r--r-- | zephyr/test/qcom_power/testcase.yaml | 4 |
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: {} |