summaryrefslogtreecommitdiff
path: root/zephyr/test/drivers/default/src/gpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'zephyr/test/drivers/default/src/gpio.c')
-rw-r--r--zephyr/test/drivers/default/src/gpio.c421
1 files changed, 421 insertions, 0 deletions
diff --git a/zephyr/test/drivers/default/src/gpio.c b/zephyr/test/drivers/default/src/gpio.c
new file mode 100644
index 0000000000..acfa0de26e
--- /dev/null
+++ b/zephyr/test/drivers/default/src/gpio.c
@@ -0,0 +1,421 @@
+/* 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.
+ */
+
+/**
+ * @file
+ * @brief Unit Tests for GPIO.
+ */
+
+#include <zephyr/device.h>
+
+#include <zephyr/drivers/gpio/gpio_emul.h>
+#include <zephyr/logging/log.h>
+#include <zephyr/kernel.h>
+#include <zephyr/ztest.h>
+
+#include "common.h"
+#include "ec_tasks.h"
+#include "gpio.h"
+#include "gpio/gpio.h"
+#include "gpio/gpio_int.h"
+#include "test/drivers/stubs.h"
+#include "util.h"
+#include "test/drivers/test_state.h"
+
+extern bool gpio_test_interrupt_triggered;
+/**
+ * @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 },
+ };
+ 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_SIGNAL(DT_NODELABEL(gpio_test))),
+ "Expected true");
+}
+
+/**
+ * @brief TestPurpose: Verify legacy API GPIO set/get level.
+ *
+ * @details
+ * Validate set/get level for legacy API
+ * This tests the legacy API, though no Zepyhr
+ * based code should use it.
+ *
+ * Expected Results
+ * - Success
+ */
+ZTEST(gpio, test_legacy_gpio_get_set_level)
+{
+ enum gpio_signal signal = GPIO_SIGNAL(DT_NODELABEL(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);
+ gpio_set_level_verbose(CC_CHIPSET, signal, 0);
+ zassert_equal(0, gpio_get_level(signal), "Expected level==0");
+}
+
+/**
+ * @brief TestPurpose: Verify legacy GPIO enable/disable interrupt.
+ *
+ * @details
+ * Validate gpio_enable_interrupt/gpio_disable_interrupt
+ * Uses the legacy API. No Zephyr code should use this API.
+ *
+ * Expected Results
+ * - Success
+ */
+
+ZTEST(gpio, test_legacy_gpio_enable_interrupt)
+{
+ enum gpio_signal signal = GPIO_SIGNAL(DT_NODELABEL(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 TestPurpose: Verify GPIO set/get level.
+ *
+ * @details
+ * Validate set/get level
+ *
+ * Expected Results
+ * - Success
+ */
+ZTEST(gpio, test_gpio_pin_get_set_level)
+{
+ const struct gpio_dt_spec *gp = GPIO_DT_FROM_NODELABEL(gpio_test);
+
+ /* Test invalid signal */
+ zassert_equal(NULL, gpio_get_dt_spec(-1), "Expected NULL ptr");
+
+ zassert_false(gp == NULL, "Unexpected NULL ptr");
+ /* Test valid signal */
+ gpio_pin_set_dt(gp, 0);
+ zassert_equal(0, gpio_pin_get_dt(gp), "Expected level==0");
+
+ gpio_pin_set_dt(gp, 1);
+ zassert_equal(1, gpio_pin_get_dt(gp), "Expected level==1");
+}
+
+/**
+ * @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_SIGNAL(DT_NODELABEL(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_SIGNAL(DT_NODELABEL(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 no-auto-init.
+ *
+ * @details
+ * Validate no-auto-init device tree property,
+ * which will not initialise the GPIO at startup.
+ *
+ * Expected Results
+ * - Success
+ */
+ZTEST(gpio, test_gpio_no_auto_init)
+{
+ const struct gpio_dt_spec *gp = GPIO_DT_FROM_NODELABEL(gpio_no_init);
+ enum gpio_signal signal = GPIO_SIGNAL(DT_NODELABEL(gpio_no_init));
+ gpio_flags_t flags;
+
+ flags = gpio_helper_get_flags(signal);
+ zassert_equal(0, flags, "Expected 0x%08x, returned 0x%08X", 0, flags);
+
+ /* Configure pin. */
+ gpio_pin_configure_dt(gp, GPIO_INPUT | GPIO_OUTPUT);
+ flags = gpio_helper_get_flags(signal);
+ zassert_equal(flags, (GPIO_ACTIVE_LOW | GPIO_OUTPUT | GPIO_INPUT),
+ "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_SIGNAL(DT_NODELABEL(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_dt_interrupt
+ *
+ * Expected Results
+ * - Success
+ */
+ZTEST(gpio, test_gpio_enable_dt_interrupt)
+{
+ const struct gpio_dt_spec *gp = GPIO_DT_FROM_NODELABEL(gpio_test);
+ const struct gpio_int_config *intr =
+ GPIO_INT_FROM_NODELABEL(int_gpio_test);
+
+ gpio_test_interrupt_triggered = false;
+
+ /* Test valid signal */
+ zassert_ok(gpio_disable_dt_interrupt(intr), NULL);
+ gpio_pin_set_dt(gp, 0);
+ zassert_false(gpio_test_interrupt_triggered, NULL);
+ gpio_pin_set_dt(gp, 1);
+ zassert_false(gpio_test_interrupt_triggered, NULL);
+
+ zassert_ok(gpio_enable_dt_interrupt(intr), NULL);
+ gpio_pin_set_dt(gp, 0);
+ zassert_true(gpio_test_interrupt_triggered, NULL);
+ gpio_test_interrupt_triggered = false;
+ gpio_pin_set_dt(gp, 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_SIGNAL(DT_NODELABEL(gpio_test)));
+}
+
+/**
+ * @brief Test Suite: Verifies GPIO functionality.
+ */
+ZTEST_SUITE(gpio, drivers_predicate_post_main, NULL, gpio_before, NULL, NULL);