summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh-Tsai <josh_tsai@compal.corp-partner.google.com>2022-12-20 19:31:18 +0800
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-12-28 19:57:27 +0000
commit35805c0f419505e72857be3d933eb6ee1bdb9c9e (patch)
treebe40e1388a603b52cd7e666a28df12377b65e620
parent8870b48c9643ca22518105732194ed2800219157 (diff)
downloadchrome-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.h22
-rw-r--r--zephyr/shim/src/gpio.c40
-rw-r--r--zephyr/test/drivers/default/prj.conf1
-rw-r--r--zephyr/test/drivers/default/src/gpio.c74
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 =