diff options
author | Josh-Tsai <josh_tsai@compal.corp-partner.google.com> | 2022-12-20 19:31:18 +0800 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-12-28 19:57:27 +0000 |
commit | 35805c0f419505e72857be3d933eb6ee1bdb9c9e (patch) | |
tree | be40e1388a603b52cd7e666a28df12377b65e620 | |
parent | 8870b48c9643ca22518105732194ed2800219157 (diff) | |
download | chrome-ec-35805c0f419505e72857be3d933eb6ee1bdb9c9e.tar.gz |
shim/src/gpio: Add save/restore GPIO controller port configure function
We need to save the IO expander GPIO status before the device reset,
and restore the status after the device is reset completely.
create the function to save and restore the port configure
BRANCH=None
BUG=b:260534665
TEST=zmake build winterhold
TEST=IO expander GPIOs status will not clear after tcpc reset
TEST=./twister -v -i --coverage -p native_posix -p unit_testing
-s external/platform/ec/zephyr/test/drivers/drivers.default
Change-Id: Ic35e7e412792a56fde670de252887a9bdb557b36
Signed-off-by: Josh-Tsai <josh_tsai@compal.corp-partner.google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4115054
Reviewed-by: Elthan Huang <elthan_huang@compal.corp-partner.google.com>
Reviewed-by: Keith Short <keithshort@chromium.org>
Code-Coverage: Zoss <zoss-cl-coverage@prod.google.com>
Commit-Queue: Keith Short <keithshort@chromium.org>
-rw-r--r-- | include/gpio.h | 22 | ||||
-rw-r--r-- | zephyr/shim/src/gpio.c | 40 | ||||
-rw-r--r-- | zephyr/test/drivers/default/prj.conf | 1 | ||||
-rw-r--r-- | zephyr/test/drivers/default/src/gpio.c | 74 |
4 files changed, 137 insertions, 0 deletions
diff --git a/include/gpio.h b/include/gpio.h index 2c5006a8ec..5fc0b07d66 100644 --- a/include/gpio.h +++ b/include/gpio.h @@ -402,6 +402,28 @@ void gpio_reset(enum gpio_signal signal); #ifdef CONFIG_ZEPHYR /** + * @brief Save state of a GPIO controller port + * + * This function saves all pins current state from selected port. + * + * @param port Port to save + * @param flags Buffer to hold gpio flags + */ +int gpio_save_port_config(const struct device *port, gpio_flags_t *flags, + int buff_size); + +/** + * @brief Restore state of a GPIO controller port + * + * This function restore all pins current state from selected port. + * + * @param port Port to restore + * @param flags Buffer with gpio flags saved by ioex_save_gpio_config + */ +int gpio_restore_port_config(const struct device *port, gpio_flags_t *flags, + int buff_size); + +/** * @brief Reset all the GPIOs to default state * * This returns all pins from selected port to default state. The default flags diff --git a/zephyr/shim/src/gpio.c b/zephyr/shim/src/gpio.c index a629c77a11..1f81b6203c 100644 --- a/zephyr/shim/src/gpio.c +++ b/zephyr/shim/src/gpio.c @@ -322,6 +322,46 @@ void gpio_reset(enum gpio_signal signal) configs[signal].init_flags); } +int gpio_save_port_config(const struct device *port, gpio_flags_t *flags, + int buff_size) +{ + int state_offset = 0; + + for (size_t i = 0; i < ARRAY_SIZE(configs); ++i) { + if (state_offset >= buff_size) { + LOG_ERR("%s buffer is too small", __func__); + return EC_ERROR_UNKNOWN; + } + + if (port == configs[i].spec.port) { + gpio_pin_get_config_dt(&configs[i].spec, + &flags[state_offset++]); + } + } + + return EC_SUCCESS; +} + +int gpio_restore_port_config(const struct device *port, gpio_flags_t *flags, + int buff_size) +{ + int state_offset = 0; + + for (size_t i = 0; i < ARRAY_SIZE(configs); ++i) { + if (state_offset >= buff_size) { + LOG_ERR("%s buffer is too small", __func__); + return EC_ERROR_UNKNOWN; + } + + if (port == configs[i].spec.port) { + gpio_pin_configure_dt(&configs[i].spec, + flags[state_offset++]); + } + } + + return EC_SUCCESS; +} + void gpio_reset_port(const struct device *port) { for (size_t i = 0; i < ARRAY_SIZE(configs); ++i) { diff --git a/zephyr/test/drivers/default/prj.conf b/zephyr/test/drivers/default/prj.conf index bf94510c1d..75a0556013 100644 --- a/zephyr/test/drivers/default/prj.conf +++ b/zephyr/test/drivers/default/prj.conf @@ -10,3 +10,4 @@ CONFIG_PLATFORM_EC_VOLUME_BUTTONS=y CONFIG_TASK_HOSTCMD_THREAD_MAIN=y CONFIG_SYSTEM_FAKE=y +CONFIG_GPIO_GET_CONFIG=y
\ No newline at end of file diff --git a/zephyr/test/drivers/default/src/gpio.c b/zephyr/test/drivers/default/src/gpio.c index 7304324532..e9a89d9b68 100644 --- a/zephyr/test/drivers/default/src/gpio.c +++ b/zephyr/test/drivers/default/src/gpio.c @@ -381,6 +381,80 @@ ZTEST(gpio, test_gpio_reset) flags); } +ZTEST(gpio, test_gpio_save_port_config) +{ + const struct device *port = + DEVICE_DT_GET(DT_GPIO_CTLR(DT_NODELABEL(gpio_test), gpios)); + const struct gpio_dt_spec *spec; + gpio_flags_t flags[32] = { 0 }; + gpio_flags_t zephyr_flags; + gpio_flags_t flags_at_start[GPIO_COUNT]; + int index = 0; + + /* Snapshot of GPIO flags before testing */ + for (int i = 0; i < GPIO_COUNT; i++) { + flags_at_start[i] = gpio_helper_get_flags(i); + gpio_set_flags(i, GPIO_OUTPUT); + } + + /* save the current state of the port */ + gpio_save_port_config(port, flags, sizeof(flags)); + + for (int i = 0; i < GPIO_COUNT; i++) { + spec = gpio_get_dt_spec(i); + if (spec->port == port) { + gpio_pin_get_config_dt(spec, &zephyr_flags); + zassert_equal(flags[index], zephyr_flags, + "Flags get 0x%x", flags[index]); + index++; + } + } + + for (int i = 0; i < GPIO_COUNT; ++i) { + gpio_set_flags(i, flags_at_start[i]); + } +} + +ZTEST(gpio, test_gpio_restore_port_config) +{ + const struct device *port = + DEVICE_DT_GET(DT_GPIO_CTLR(DT_NODELABEL(gpio_test), gpios)); + const struct gpio_dt_spec *spec; + gpio_flags_t flags[32] = { 0 }; + gpio_flags_t zephyr_flags; + gpio_flags_t flags_at_start[GPIO_COUNT]; + int index = 0; + + /* Snapshot of GPIO flags before testing */ + for (int i = 0; i < GPIO_COUNT; i++) { + flags_at_start[i] = gpio_helper_get_flags(i); + gpio_set_flags(i, GPIO_OUTPUT); + } + + /* save the current state of the port */ + gpio_save_port_config(port, flags, sizeof(flags)); + + /* reset the port */ + gpio_reset_port(port); + + /* restore the port config and check */ + gpio_restore_port_config(port, flags, sizeof(flags)); + + for (int i = 0; i < GPIO_COUNT; i++) { + spec = gpio_get_dt_spec(i); + if (spec->port == port) { + gpio_pin_get_config_dt(spec, &zephyr_flags); + zassert_equal(flags[index], zephyr_flags, + "Flags get 0x%x", flags[index]); + index++; + } + } + + for (int i = 0; i < GPIO_COUNT; ++i) { + gpio_set_flags(i, flags_at_start[i]); + } +} + ZTEST(gpio, test_gpio_reset_port) { const struct device *port = |