This is an automated email from Gerrit.

"zapb <[email protected]>" just uploaded a new patch set to Gerrit, which you can 
find at https://review.openocd.org/c/openocd/+/9087

-- gerrit

commit b1d8a7c7789d0a786e94c9b6969b2e9ea0ef65fe
Author: Marc Schink <[email protected]>
Date:   Sun Jun 15 10:52:49 2025 +0000

    adapter: Add support for 'exit state' of GPIO signal
    
    In addition to a signal's 'init state', add support to configure its
    'exit state'. This option determines the state and configuration of a
    pin when the adapter terminates its operation.
    
    Change-Id: I0577ed9e3bc79715290b4e6a21e3f64c66f2ff9a
    Signed-off-by: Marc Schink <[email protected]>

diff --git a/doc/openocd.texi b/doc/openocd.texi
index 01ca7adfb3..c8aa922db1 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -2443,6 +2443,7 @@ dict get [adapter list] ftdi
         @option{-push-pull} | @option{-open-drain} | @option{-open-source} | @
         @option{-pull-none} | @option{-pull-up} | @option{-pull-down} | @
         @option{-init-inactive} | @option{-init-active} | @option{-init-input} 
@
+        @option{-exit-inactive} | @option{-exit-active} | @option{-exit-input} 
| @option{-exit-no-change} @
     ] ]}
 
 Define the GPIO mapping that the adapter will use. The following signals can be
@@ -2477,11 +2478,14 @@ equivalent to issuing the single command @command{gpio 
led 7 -chip 1
 signals which are inputs. The drive mode for the srst and trst signals must be
 set with the @command{adapter reset_config} command. It is not permissible to
 set the initial state of swdio_dir as it is derived from the initial state of
-swdio. The command @command{adapter gpio} prints the current configuration for
-all GPIOs while the command @command{adapter gpio gpio_name} prints the current
-configuration for gpio_name. Not all adapters support this generic GPIO 
mapping,
-some require their own commands to define the GPIOs used. Adapters that support
-the generic mapping may not support all of the listed options.
+swdio. Accordingly, the final state before the adapter terminates its 
operation,
+so-called “exit state”, can be set. By default the state and configuration of 
an
+output pin is not changed when the driver terminates its operation. The
+command @command{adapter gpio} prints the current configuration for all GPIOs
+while the command @command{adapter gpio gpio_name} prints the current 
configuration
+for gpio_name. Not all adapters support this generic GPIO mapping, some require
+their own commands to define the GPIOs used. Adapters that support the generic
+mapping may not support all of the listed options.
 @end deffn
 
 @deffn {Command} {adapter name}
diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c
index 6785a74ef1..173e6ee6b2 100644
--- a/src/jtag/adapter.c
+++ b/src/jtag/adapter.c
@@ -53,17 +53,18 @@ static const struct gpio_map {
        enum adapter_gpio_direction direction;
        bool permit_drive_option;
        bool permit_init_state_option;
+       bool permit_exit_state_option;
 } gpio_map[ADAPTER_GPIO_IDX_NUM] = {
-       [ADAPTER_GPIO_IDX_TDO] = { "tdo", ADAPTER_GPIO_DIRECTION_INPUT, false, 
true, },
-       [ADAPTER_GPIO_IDX_TDI] = { "tdi", ADAPTER_GPIO_DIRECTION_OUTPUT, true, 
true, },
-       [ADAPTER_GPIO_IDX_TMS] = { "tms", ADAPTER_GPIO_DIRECTION_OUTPUT, true, 
true, },
-       [ADAPTER_GPIO_IDX_TCK] = { "tck", ADAPTER_GPIO_DIRECTION_OUTPUT, true, 
true, },
-       [ADAPTER_GPIO_IDX_SWDIO] = { "swdio", 
ADAPTER_GPIO_DIRECTION_BIDIRECTIONAL, true, true, },
-       [ADAPTER_GPIO_IDX_SWDIO_DIR] = { "swdio_dir", 
ADAPTER_GPIO_DIRECTION_OUTPUT, true, false, },
-       [ADAPTER_GPIO_IDX_SWCLK] = { "swclk", ADAPTER_GPIO_DIRECTION_OUTPUT, 
true, true, },
-       [ADAPTER_GPIO_IDX_TRST] = { "trst", ADAPTER_GPIO_DIRECTION_OUTPUT, 
false, true, },
-       [ADAPTER_GPIO_IDX_SRST] = { "srst", ADAPTER_GPIO_DIRECTION_OUTPUT, 
false, true, },
-       [ADAPTER_GPIO_IDX_LED] = { "led", ADAPTER_GPIO_DIRECTION_OUTPUT, true, 
true, },
+       [ADAPTER_GPIO_IDX_TDO] = { "tdo", ADAPTER_GPIO_DIRECTION_INPUT, false, 
true, true },
+       [ADAPTER_GPIO_IDX_TDI] = { "tdi", ADAPTER_GPIO_DIRECTION_OUTPUT, true, 
true, true },
+       [ADAPTER_GPIO_IDX_TMS] = { "tms", ADAPTER_GPIO_DIRECTION_OUTPUT, true, 
true, true },
+       [ADAPTER_GPIO_IDX_TCK] = { "tck", ADAPTER_GPIO_DIRECTION_OUTPUT, true, 
true, true },
+       [ADAPTER_GPIO_IDX_SWDIO] = { "swdio", 
ADAPTER_GPIO_DIRECTION_BIDIRECTIONAL, true, true, true },
+       [ADAPTER_GPIO_IDX_SWDIO_DIR] = { "swdio_dir", 
ADAPTER_GPIO_DIRECTION_OUTPUT, true, false, false },
+       [ADAPTER_GPIO_IDX_SWCLK] = { "swclk", ADAPTER_GPIO_DIRECTION_OUTPUT, 
true, true, true },
+       [ADAPTER_GPIO_IDX_TRST] = { "trst", ADAPTER_GPIO_DIRECTION_OUTPUT, 
false, true, true },
+       [ADAPTER_GPIO_IDX_SRST] = { "srst", ADAPTER_GPIO_DIRECTION_OUTPUT, 
false, true, true },
+       [ADAPTER_GPIO_IDX_LED] = { "led", ADAPTER_GPIO_DIRECTION_OUTPUT, true, 
true, true },
 };
 
 static int adapter_config_khz(unsigned int khz);
@@ -850,6 +851,7 @@ static COMMAND_HELPER(helper_adapter_gpio_print_config, 
enum adapter_gpio_config
        const char *drive = "";
        const char *pull = "";
        const char *init_state = "";
+       const char *exit_state = "";
 
        if (gpio_config->gpio_num == ADAPTER_GPIO_NOT_SET) {
                command_print(CMD, "adapter gpio %s: not configured", 
gpio_map[gpio_idx].name);
@@ -908,9 +910,27 @@ static COMMAND_HELPER(helper_adapter_gpio_print_config, 
enum adapter_gpio_config
                }
        }
 
-       command_print(CMD, "adapter gpio %s (%s): num %u, chip %d, 
active-%s%s%s%s",
+       if (gpio_map[gpio_idx].permit_exit_state_option) {
+               switch (gpio_config->exit_state) {
+               case ADAPTER_GPIO_EXIT_STATE_NO_CHANGE:
+                       exit_state = ", exit-state no-change";
+                       break;
+               case ADAPTER_GPIO_EXIT_STATE_INACTIVE:
+                       exit_state = ", exit-state inactive";
+                       break;
+               case ADAPTER_GPIO_EXIT_STATE_ACTIVE:
+                       exit_state = ", exit-state active";
+                       break;
+               case ADAPTER_GPIO_EXIT_STATE_INPUT:
+                       exit_state = ", exit-state input";
+                       break;
+               }
+       }
+
+
+       command_print(CMD, "adapter gpio %s (%s): num %u, chip %d, 
active-%s%s%s%s%s",
                gpio_map[gpio_idx].name, dir, gpio_config->gpio_num, 
(int)gpio_config->chip_num, active_state,
-               drive, pull, init_state);
+               drive, pull, init_state, exit_state);
 
        return ERROR_OK;
 }
@@ -1031,6 +1051,31 @@ COMMAND_HANDLER(adapter_gpio_config_handler)
                        }
                }
 
+               if (gpio_map[gpio_idx].permit_exit_state_option) {
+                       if (strcmp(CMD_ARGV[i], "-exit-no-change") == 0) {
+                               ++i;
+                               gpio_config->exit_state = 
ADAPTER_GPIO_EXIT_STATE_NO_CHANGE;
+                               continue;
+                       }
+                       if (strcmp(CMD_ARGV[i], "-exit-inactive") == 0) {
+                               ++i;
+                               gpio_config->exit_state = 
ADAPTER_GPIO_EXIT_STATE_INACTIVE;
+                               continue;
+                       }
+                       if (strcmp(CMD_ARGV[i], "-exit-active") == 0) {
+                               ++i;
+                               gpio_config->exit_state = 
ADAPTER_GPIO_EXIT_STATE_ACTIVE;
+                               continue;
+                       }
+
+                       if (gpio_map[gpio_idx].direction == 
ADAPTER_GPIO_DIRECTION_BIDIRECTIONAL &&
+                                       strcmp(CMD_ARGV[i], "-exit-input") == 
0) {
+                               ++i;
+                               gpio_config->exit_state = 
ADAPTER_GPIO_EXIT_STATE_INPUT;
+                               continue;
+                       }
+               }
+
                LOG_ERROR("illegal option for adapter %s %s: %s",
                                CMD_NAME, gpio_map[gpio_idx].name, CMD_ARGV[i]);
                return ERROR_COMMAND_SYNTAX_ERROR;
@@ -1168,7 +1213,8 @@ static const struct command_registration 
adapter_command_handlers[] = {
                        "[-active-high|-active-low] "
                        "[-push-pull|-open-drain|-open-source] "
                        "[-pull-none|-pull-up|-pull-down]"
-                       "[-init-inactive|-init-active|-init-input] ]",
+                       "[-init-inactive|-init-active|-init-input] ]"
+                       
"[-exit-no-change,exit-inactive|-exit-active|-exit-input] ]",
        },
        COMMAND_REGISTRATION_DONE
 };
diff --git a/src/jtag/adapter.h b/src/jtag/adapter.h
index 556952f8d7..ed58fe5aaa 100644
--- a/src/jtag/adapter.h
+++ b/src/jtag/adapter.h
@@ -33,6 +33,14 @@ enum adapter_gpio_init_state {
        ADAPTER_GPIO_INIT_STATE_INPUT,
 };
 
+/** Supported exit states for GPIO */
+enum adapter_gpio_exit_state {
+       ADAPTER_GPIO_EXIT_STATE_NO_CHANGE, /* Should be zero so it is the 
default state */
+       ADAPTER_GPIO_EXIT_STATE_INACTIVE,
+       ADAPTER_GPIO_EXIT_STATE_ACTIVE,
+       ADAPTER_GPIO_EXIT_STATE_INPUT,
+};
+
 /** Supported pull directions for GPIO */
 enum adapter_gpio_pull {
        ADAPTER_GPIO_PULL_NONE,
@@ -61,6 +69,7 @@ struct adapter_gpio_config {
        unsigned int chip_num;
        enum adapter_gpio_drive_mode drive; /* For outputs only */
        enum adapter_gpio_init_state init_state;
+       enum adapter_gpio_exit_state exit_state;
        bool active_low;
        enum adapter_gpio_pull pull;
 };

-- 

Reply via email to