diff options
author | Al Semjonovs <asemjonovs@google.com> | 2022-01-25 13:47:23 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2022-01-28 22:14:11 +0000 |
commit | 4a6ee66519fd49ce405614de30655ff637b4788b (patch) | |
tree | e5cb5278c261d7b52ac04ac3ef2866d674aaad63 /zephyr/test/drivers | |
parent | 60cdf31ebd01e26ec0d602902b0653f051607442 (diff) | |
download | chrome-ec-4a6ee66519fd49ce405614de30655ff637b4788b.tar.gz |
zephyr: drivers: Improve code coverage of gpio.c
Add test cases to improve code coverage of gpio.c
Created new GPIO_TEST enum to avoid affecting other
test cases.
BRANCH=none
BUG=b:216483477
TEST=zmake -D configure --coverage --test zephyr/test/drivers/
Signed-off-by: Al Semjonovs <asemjonovs@google.com>
Change-Id: I2ead3610e3ed64b04702488707aa96988f38f378
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3417013
Reviewed-by: Yuval Peress <peress@google.com>
Diffstat (limited to 'zephyr/test/drivers')
-rw-r--r-- | zephyr/test/drivers/include/stubs.h | 2 | ||||
-rw-r--r-- | zephyr/test/drivers/overlay.dts | 11 | ||||
-rw-r--r-- | zephyr/test/drivers/src/gpio.c | 339 | ||||
-rw-r--r-- | zephyr/test/drivers/src/stubs.c | 9 |
4 files changed, 360 insertions, 1 deletions
diff --git a/zephyr/test/drivers/include/stubs.h b/zephyr/test/drivers/include/stubs.h index 2ea3ec6288..2e03142d72 100644 --- a/zephyr/test/drivers/include/stubs.h +++ b/zephyr/test/drivers/include/stubs.h @@ -26,4 +26,6 @@ DECLARE_FAKE_VOID_FUNC(system_hibernate, uint32_t, uint32_t); void sys_arch_reboot(int type); +/* Declare GPIO_TEST interrupt handler */ +void gpio_test_interrupt(enum gpio_signal signal); #endif /* __TEST_DRIVERS_STUBS_H */ diff --git a/zephyr/test/drivers/overlay.dts b/zephyr/test/drivers/overlay.dts index fe8e604754..2cd815da00 100644 --- a/zephyr/test/drivers/overlay.dts +++ b/zephyr/test/drivers/overlay.dts @@ -132,6 +132,10 @@ gpios = <&gpio0 26 (GPIO_INPUT | GPIO_PULL_DOWN)>; enum-name = "GPIO_SWITCHCAP_PG"; }; + gpio_test: test { + gpios = <&gpio0 27 (GPIO_INPUT | GPIO_OUTPUT)>; + enum-name = "GPIO_TEST"; + }; }; gpio-interrupts { @@ -167,6 +171,11 @@ flags = <GPIO_INT_EDGE_FALLING>; handler = "ln9310_interrupt"; }; + int_gpio_test: test { + irq-gpio = <&gpio_test>; + flags = <GPIO_INT_EDGE_BOTH>; + handler = "gpio_test_interrupt"; + }; }; named-i2c-ports { @@ -653,7 +662,7 @@ }; &gpio0 { - ngpios = <27>; + ngpios = <28>; }; &i2c0 { diff --git a/zephyr/test/drivers/src/gpio.c b/zephyr/test/drivers/src/gpio.c new file mode 100644 index 0000000000..158c2e9321 --- /dev/null +++ b/zephyr/test/drivers/src/gpio.c @@ -0,0 +1,339 @@ +/* Copyright 2022 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * @file + * @brief Unit Tests for GPIO. + */ + +#include <device.h> + +#include <drivers/gpio/gpio_emul.h> +#include <logging/log.h> +#include <zephyr.h> +#include <ztest.h> + +#include "common.h" +#include "ec_tasks.h" +#include "gpio.h" +#include "gpio/gpio.h" +#include "stubs.h" +#include "util.h" +#include "test_state.h" + +/** + * @brief TestPurpose: Verify Zephyr to EC GPIO bitmask conversion. + * + * @details + * Validate Zephyr to EC GPIO bitmask conversion. + * + * Expected Results + * - GPIO bitmask conversions are successful + */ +ZTEST(gpio, test_convert_from_zephyr_flags) +{ + int retval; + struct { + int zephyr_bmask; + gpio_flags_t expected_ec_bmask; + } validate[] = { + { GPIO_DISCONNECTED, GPIO_FLAG_NONE }, + { GPIO_OUTPUT_INIT_LOW, GPIO_LOW }, + { GPIO_OUTPUT_INIT_HIGH, GPIO_HIGH }, + { GPIO_VOLTAGE_1P8, GPIO_SEL_1P8V }, + { GPIO_INT_ENABLE, GPIO_FLAG_NONE }, + { GPIO_INT_ENABLE | GPIO_INT_EDGE, GPIO_FLAG_NONE }, + { GPIO_INT_ENABLE | GPIO_INT_EDGE | GPIO_INT_HIGH_1, + GPIO_INT_F_RISING }, + { GPIO_INT_ENABLE | GPIO_INT_EDGE | GPIO_INT_LOW_0, + GPIO_INT_F_FALLING }, + { GPIO_INT_ENABLE | GPIO_INT_HIGH_1, GPIO_INT_F_HIGH }, + { GPIO_INT_ENABLE | GPIO_INT_LOW_0, GPIO_INT_F_LOW }, + { GPIO_OUTPUT_INIT_LOGICAL, 0 }, + { GPIO_OPEN_DRAIN | GPIO_PULL_UP, + GPIO_OPEN_DRAIN | GPIO_PULL_UP }, + }; + int num_tests = ARRAY_SIZE(validate); + + for (int i = 0; i < num_tests; i++) { + retval = convert_from_zephyr_flags(validate[i].zephyr_bmask); + zassert_equal(validate[i].expected_ec_bmask, retval, + "[%d] Expected 0x%08X, returned 0x%08X.", i, + validate[i].expected_ec_bmask, retval); + } +} + +/** + * @brief TestPurpose: Verify EC to Zephyr GPIO bitmask conversion. + * + * @details + * Validate EC to Zephyr GPIO bitmask conversion. + * + * Expected Results + * - GPIO bitmask conversions are successful + */ +ZTEST(gpio, test_convert_to_zephyr_flags) +{ + gpio_flags_t retval; + + struct { + gpio_flags_t ec_bmask; + int expected_zephyr_bmask; + } validate[] = { + { GPIO_FLAG_NONE, GPIO_DISCONNECTED }, + { GPIO_LOW, GPIO_OUTPUT_INIT_LOW }, + { GPIO_HIGH, GPIO_OUTPUT_INIT_HIGH }, + { GPIO_INT_F_RISING, + GPIO_INT_ENABLE | GPIO_INT_EDGE | GPIO_INT_HIGH_1 }, + { GPIO_INT_F_FALLING, + GPIO_INT_ENABLE | GPIO_INT_EDGE | GPIO_INT_LOW_0 }, + { GPIO_INT_F_LOW, GPIO_INT_ENABLE | GPIO_INT_LOW_0 }, + { GPIO_INT_F_HIGH, GPIO_INT_ENABLE | GPIO_INT_HIGH_1 }, + { GPIO_SEL_1P8V, GPIO_VOLTAGE_1P8 }, + { GPIO_LOCKED, 0 }, + }; + int num_tests = ARRAY_SIZE(validate); + + for (int i = 0; i < num_tests; i++) { + retval = convert_to_zephyr_flags(validate[i].ec_bmask); + zassert_equal(validate[i].expected_zephyr_bmask, retval, + "[%d] Expected 0x%08X, returned 0x%08X.", i, + validate[i].expected_zephyr_bmask, retval); + } +} + +/** + * @brief TestPurpose: Verify GPIO signal_is_gpio. + * + * @details + * Validate signal_is_gpio + * + * Expected Results + * - Success + */ +ZTEST(gpio, test_signal_is_gpio) +{ + zassert_true(signal_is_gpio(GPIO_TEST), "Expected true"); +} + +/** + * @brief TestPurpose: Verify GPIO set/get level. + * + * @details + * Validate set/get level + * + * Expected Results + * - Success + */ +ZTEST(gpio, test_gpio_get_set_level) +{ + enum gpio_signal signal = GPIO_TEST; + int level; + + /* Test invalid signal */ + gpio_set_level(GPIO_COUNT, 0); + zassert_equal(0, gpio_get_level(GPIO_COUNT), "Expected level==0"); + + /* Test valid signal */ + gpio_set_level(signal, 0); + zassert_equal(0, gpio_get_level(signal), "Expected level==0"); + + gpio_set_level(signal, 1); + zassert_equal(1, gpio_get_level(signal), "Expected level==1"); + + level = gpio_get_ternary(signal); + zassert_equal(2, level, "Expected level==2, returned=%d", level); + + gpio_set_level_verbose(CC_CHIPSET, signal, 0); + zassert_equal(0, gpio_get_level(signal), "Expected level==0"); +} + +/** + * @brief TestPurpose: Verify GPIO get name. + * + * @details + * Validate gpio_get_name + * + * Expected Results + * - Success + */ +ZTEST(gpio, test_gpio_get_name) +{ + enum gpio_signal signal = GPIO_TEST; + const char *signal_name; + + /* Test invalid signal */ + signal_name = gpio_get_name(GPIO_COUNT); + zassert_mem_equal("UNIMPLEMENTED", signal_name, strlen(signal_name), + "gpio_get_name returned a valid signal \'%s\'", + signal_name); + + /* Test valid signal */ + signal_name = gpio_get_name(signal); + zassert_mem_equal("test", signal_name, strlen(signal_name), + "gpio_get_name returned signal \'%s\'", signal_name); +} + +/** + * @brief Helper function to get GPIO flags + * + * @param signal + * @return gpio_flags_t + */ +gpio_flags_t gpio_helper_get_flags(enum gpio_signal signal) +{ + const struct gpio_dt_spec *spec; + gpio_flags_t flags; + + spec = gpio_get_dt_spec(signal); + gpio_emul_flags_get(spec->port, spec->pin, &flags); + + return flags; +} + +/** + * @brief TestPurpose: Verify GPIO get default flags. + * + * @details + * Validate gpio_get_default_flags + * + * Expected Results + * - Success + */ +ZTEST(gpio, test_gpio_get_default_flags) +{ + enum gpio_signal signal = GPIO_TEST; + gpio_flags_t flags; + gpio_flags_t flags_at_start[GPIO_COUNT]; + int def_flags; + + /* Snapshot of GPIO flags before testing */ + for (int i = 0; i < GPIO_COUNT; i++) + flags_at_start[i] = gpio_helper_get_flags(i); + + /* Test invalid signal */ + def_flags = gpio_get_default_flags(GPIO_COUNT); + zassert_equal(0, def_flags, "Expected 0x0, returned 0x%08X", def_flags); + gpio_set_flags(GPIO_COUNT, GPIO_INPUT); + + /* Verify flags didn't change */ + for (int i = 0; i < GPIO_COUNT; i++) { + flags = gpio_helper_get_flags(i); + zassert_equal(flags_at_start[i], flags, + "%s[%d] flags_at_start=0x%x, flags=0x%x", + gpio_get_name(i), i, flags_at_start[i], flags); + } + + /* Test valid signal */ + def_flags = gpio_get_default_flags(signal); + zassert_equal(GPIO_INPUT | GPIO_OUTPUT, def_flags, + "Expected 0x%08x, returned 0x%08X", + GPIO_INPUT | GPIO_OUTPUT, def_flags); + + gpio_set_flags(signal, GPIO_INPUT); + flags = gpio_helper_get_flags(signal); + zassert_equal(flags, GPIO_INPUT, "Flags set 0x%x", flags); + + gpio_set_flags(signal, GPIO_OUTPUT); + flags = gpio_helper_get_flags(signal); + zassert_equal(flags, GPIO_OUTPUT, "Flags set 0x%x", flags); +} + +/** + * @brief TestPurpose: Verify GPIO reset. + * + * @details + * Validate gpio_reset + * + * Expected Results + * - Success + */ +ZTEST(gpio, test_gpio_reset) +{ + enum gpio_signal signal = GPIO_TEST; + gpio_flags_t flags; + gpio_flags_t flags_at_start[GPIO_COUNT]; + + /* Snapshot of GPIO flags before testing */ + for (int i = 0; i < GPIO_COUNT; i++) + flags_at_start[i] = gpio_helper_get_flags(i); + + /* Test reset on invalid signal */ + gpio_reset(GPIO_COUNT); + + /* Verify flags didn't change */ + for (int i = 0; i < GPIO_COUNT; i++) { + flags = gpio_helper_get_flags(i); + zassert_equal(flags_at_start[i], flags, + "%s[%d] flags_at_start=0x%x, flags=0x%x", + gpio_get_name(i), i, flags_at_start[i], flags); + } + + /* Test reset on valid signal */ + gpio_set_flags(signal, GPIO_OUTPUT); + flags = gpio_helper_get_flags(signal); + zassert_equal(flags, GPIO_OUTPUT, "Flags set 0x%x", flags); + + gpio_reset(signal); + + flags = gpio_helper_get_flags(signal); + zassert_equal(flags, gpio_get_default_flags(signal), "Flags set 0x%x", + flags); +} + +/** + * @brief TestPurpose: Verify GPIO enable/disable interrupt. + * + * @details + * Validate gpio_enable_interrupt + * + * Expected Results + * - Success + */ +extern bool gpio_test_interrupt_triggered; +ZTEST(gpio, test_gpio_enable_interrupt) +{ + enum gpio_signal signal = GPIO_TEST; + + gpio_test_interrupt_triggered = false; + + /* Test invalid signal */ + zassert_not_equal(EC_SUCCESS, gpio_disable_interrupt(GPIO_COUNT), NULL); + zassert_not_equal(EC_SUCCESS, gpio_enable_interrupt(GPIO_COUNT), NULL); + zassert_false(gpio_test_interrupt_triggered, NULL); + + /* Test valid signal */ + zassert_ok(gpio_disable_interrupt(signal), NULL); + gpio_set_level(signal, 0); + zassert_false(gpio_test_interrupt_triggered, NULL); + gpio_set_level(signal, 1); + zassert_false(gpio_test_interrupt_triggered, NULL); + + zassert_ok(gpio_enable_interrupt(signal), NULL); + gpio_set_level(signal, 0); + zassert_true(gpio_test_interrupt_triggered, NULL); + gpio_test_interrupt_triggered = false; + gpio_set_level(signal, 1); + zassert_true(gpio_test_interrupt_triggered, NULL); +} + +/** + * @brief GPIO test setup handler. + */ +static void gpio_before(void *state) +{ + ARG_UNUSED(state); + /** TODO: Reset all signals here. Currently other tests fail when reset + * for(int i = 0; i < GPIO_COUNT; i++) { + * gpio_reset(i); + * } + */ + gpio_reset(GPIO_TEST); +} + +/** + * @brief Test Suite: Verifies GPIO functionality. + */ +ZTEST_SUITE(gpio, drivers_predicate_post_main, NULL, gpio_before, NULL, NULL); diff --git a/zephyr/test/drivers/src/stubs.c b/zephyr/test/drivers/src/stubs.c index 2921f0ef97..85d7e99d13 100644 --- a/zephyr/test/drivers/src/stubs.c +++ b/zephyr/test/drivers/src/stubs.c @@ -401,3 +401,12 @@ void sys_arch_reboot(int type) { ARG_UNUSED(type); } + +/* GPIO TEST interrupt handler */ +bool gpio_test_interrupt_triggered; +void gpio_test_interrupt(enum gpio_signal signal) +{ + ARG_UNUSED(signal); + printk("%s called\n", __func__); + gpio_test_interrupt_triggered = true; +} |