This is an automated email from Gerrit.

"Steve Marple <stevemar...@googlemail.com>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/6967

-- gerrit

commit cff4398e51b1bfa469ada7f7c0f48dfba447277b
Author: Steve Marple <stevemar...@googlemail.com>
Date:   Wed May 4 22:51:48 2022 +0100

    jtag/adapter: add command 'adapter gpio'
    
    Most adapters define their own commands to obtain the GPIO number and
    other GPIO configuration information such as chip number, output drive
    type, active high/low.
    
    Define a general command 'adapter gpio' to be proposed as replacement of
    the driver-specific ones.
    
    Change-Id: I1ca9ca94f0c7df5713172e9f62ffb0ad64e9ee97
    Signed-off-by: Steve Marple <stevemar...@googlemail.com>

diff --git a/src/helper/command.c b/src/helper/command.c
index 1e769d7190..be7de854d9 100644
--- a/src/helper/command.c
+++ b/src/helper/command.c
@@ -1370,7 +1370,7 @@ DEFINE_PARSE_LONGLONG(_s32, int32_t, n < INT32_MIN, 
INT32_MAX)
 DEFINE_PARSE_LONGLONG(_s16, int16_t, n < INT16_MIN, INT16_MAX)
 DEFINE_PARSE_LONGLONG(_s8,  int8_t,  n < INT8_MIN,  INT8_MAX)
 
-static int command_parse_bool(const char *in, bool *out,
+int command_parse_bool(const char *in, bool *out,
        const char *on, const char *off)
 {
        if (strcasecmp(in, on) == 0)
diff --git a/src/helper/command.h b/src/helper/command.h
index 796cd9d3b3..b7c28f0ad5 100644
--- a/src/helper/command.h
+++ b/src/helper/command.h
@@ -508,6 +508,8 @@ DECLARE_PARSE_WRAPPER(_target_addr, target_addr_t);
                out = value; \
        } while (0)
 
+int command_parse_bool(const char *in, bool *out,
+       const char *on, const char *off);
 int command_parse_bool_arg(const char *in, bool *out);
 COMMAND_HELPER(handle_command_parse_bool, bool *out, const char *label);
 
diff --git a/src/jtag/adapter.c b/src/jtag/adapter.c
index 14452d42f2..9dcb13e0cd 100644
--- a/src/jtag/adapter.c
+++ b/src/jtag/adapter.c
@@ -36,6 +36,22 @@ enum adapter_clk_mode {
        CLOCK_MODE_RCLK
 };
 
+/* TODO: Set sane inital values for GPIO. Most should be something similar to 
this:
+const struct adapter_gpio_config push_pull_gpio = {
+       .gpio_num = -1,
+       .chip_num = -1,
+       .drive = DRIVE_MODE_PUSH_PULL,
+       .active_high = true,
+       .init_active = false,
+};
+*/
+
+/** All GPIOs which can be configured with the "adapter gpio" command */
+struct adaptor_gpio {
+       struct adapter_gpio_config tdo;
+       struct adapter_gpio_config led;
+};
+
 /**
  * Adapter configuration
  */
@@ -46,6 +62,7 @@ static struct {
        enum adapter_clk_mode clock_mode;
        int speed_khz;
        int rclk_fallback_speed_khz;
+       struct adaptor_gpio gpio;
 } adapter_config;
 
 bool is_adapter_initialized(void)
@@ -762,6 +779,130 @@ COMMAND_HANDLER(handle_adapter_reset_de_assert)
                                                  (srst == VALUE_DEASSERT) ? 
SRST_DEASSERT : SRST_ASSERT);
 }
 
+static struct adapter_gpio_config *get_gpio_config(const char *signal_name)
+{
+       if (strcmp(signal_name, "tdo") == 0)
+               return &adapter_config.gpio.tdo;
+       if (strcmp(signal_name, "led") == 0)
+               return &adapter_config.gpio.led;
+       return NULL;
+}
+
+const struct adapter_gpio_config *adapter_get_gpio_config(const char 
*signal_name)
+{
+       return (const struct adapter_gpio_config *)get_gpio_config(signal_name);
+}
+
+COMMAND_HELPER(helper_adapter_gpio_options, bool is_output, unsigned int *i,
+       struct adapter_gpio_config *gpio_config)
+{
+       const char *opt = CMD_ARGV[*i];
+       if (strcmp(opt, "-chip") == 0) {
+               if (CMD_ARGC - *i < 2) {
+                       LOG_ERROR("-chip option requires a parameter");
+                       return ERROR_FAIL;
+               } else {
+                       LOG_DEBUG("-chip arg is %s", CMD_ARGV[*i + 1]);
+                       int chip_num; /* Use a meaningful output parameter for 
more helpful error messages */
+                       COMMAND_PARSE_NUMBER(int, CMD_ARGV[*i + 1], chip_num);
+                       gpio_config->chip_num = chip_num;
+                       *i += 2;
+                       return ERROR_OK;
+               }
+       }
+
+       if (strcmp(opt, "-active-high") == 0) {
+               ++(*i);
+               gpio_config->active_high = true;
+               return ERROR_OK;
+       }
+       if (strcmp(opt, "-active-low") == 0) {
+               ++(*i);
+               gpio_config->active_high = false;
+               return ERROR_OK;
+       }
+
+       if (is_output) {
+               /* Drive */
+               if (strcmp(opt, "-push-pull") == 0) {
+                       ++(*i);
+                       gpio_config->drive = DRIVE_MODE_PUSH_PULL;
+                       return ERROR_OK;
+               }
+               if (strcmp(opt, "-open-drain") == 0) {
+                       ++(*i);
+                       gpio_config->drive = DRIVE_MODE_OPEN_DRAIN;
+                       return ERROR_OK;
+               }
+               if (strcmp(opt, "-open-source") == 0) {
+                       ++(*i);
+                       gpio_config->drive = DRIVE_MODE_OPEN_SOURCE;
+                       return ERROR_OK;
+               }
+
+               /* Initial state */
+               if (strcmp(opt, "-init-state") == 0) {
+                       if (CMD_ARGC - *i < 2) {
+                               LOG_ERROR("-init-state option requires a 
parameter");
+                               return ERROR_FAIL;
+                       }
+                       LOG_DEBUG("-init-state arg is %s", CMD_ARGV[*i + 1]);
+                       int retval = command_parse_bool(CMD_ARGV[*i + 1],
+                               &(gpio_config->init_active), "active", 
"inactive");
+                       *i += 2;
+                       return retval;
+               }
+       }
+
+       LOG_ERROR("unknown option for %s: %s", CMD_NAME, opt);
+       return ERROR_COMMAND_SYNTAX_ERROR;
+}
+
+COMMAND_HELPER(adapter_gpio_config_handler, bool is_output)
+{
+       unsigned int i = 0;
+       struct adapter_gpio_config *gpio_config;
+       if (CMD_ARGC < 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       gpio_config = get_gpio_config(CMD_NAME);
+       if (!gpio_config) {
+               LOG_ERROR("adapter has no gpio named %s", CMD_NAME);
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       while (i < CMD_ARGC) {
+               LOG_DEBUG("Processing %s", CMD_ARGV[i]);
+               if (isdigit(*CMD_ARGV[i])) {
+                       int gpio_num; /* Use a meaningful output parameter for 
more helpful error messages */
+                       COMMAND_PARSE_NUMBER(int, CMD_ARGV[i], gpio_num);
+                       gpio_config->gpio_num = gpio_num;
+                       ++i;
+               } else {
+                       if (*CMD_ARGV[i] == '-') {
+                               int retval = 
CALL_COMMAND_HANDLER(helper_adapter_gpio_options, is_output, &i, gpio_config);
+                               if (retval != ERROR_OK)
+                                       return retval;
+                       } else {
+                               LOG_ERROR("unknown option for %s: %s", 
CMD_NAME, CMD_ARGV[i]);
+                               return ERROR_COMMAND_SYNTAX_ERROR;
+                       }
+               }
+       }
+
+       return ERROR_OK;
+}
+
+COMMAND_HANDLER(adapter_gpio_input_config_handler)
+{
+       return CALL_COMMAND_HANDLER(adapter_gpio_config_handler, false);
+}
+
+COMMAND_HANDLER(adapter_gpio_output_config_handler)
+{
+       return CALL_COMMAND_HANDLER(adapter_gpio_config_handler, true);
+}
+
 #ifdef HAVE_LIBUSB_GET_PORT_NUMBERS
 COMMAND_HANDLER(handle_usb_location_command)
 {
@@ -805,6 +946,30 @@ static const struct command_registration 
adapter_srst_command_handlers[] = {
        COMMAND_REGISTRATION_DONE
 };
 
+static const struct command_registration adapter_gpio_name_handlers[] = {
+       {
+               .name = "tdo",
+               .handler = adapter_gpio_input_config_handler,
+               .mode = COMMAND_CONFIG,
+               .help = "tdo gpio configuration",
+               .usage = "[number] "
+                       "[-chip chip_number] "
+                       "[-active-high|-active-low]",
+       },
+       {
+               .name = "led",
+               .handler = adapter_gpio_output_config_handler,
+               .mode = COMMAND_CONFIG,
+               .help = "led gpio configuration",
+               .usage = "[number] "
+                       "[-chip chip_number] "
+                       "[-active-high|-active-low] "
+                       "[-push-pull|-open-drain|-open-source] "
+                       "[-init-state active|inactive]",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+
 static const struct command_registration adapter_command_handlers[] = {
        {
                .name = "driver",
@@ -879,6 +1044,13 @@ static const struct command_registration 
adapter_command_handlers[] = {
                .help = "Controls SRST and TRST lines.",
                .usage = "|assert [srst|trst [deassert|assert srst|trst]]",
        },
+       {
+               .name = "gpio",
+               .mode = COMMAND_CONFIG,
+               .help = "gpio adapter command group",
+               .usage = "",
+               .chain = adapter_gpio_name_handlers,
+       },
        COMMAND_REGISTRATION_DONE
 };
 
diff --git a/src/jtag/adapter.h b/src/jtag/adapter.h
index 300769c229..30930f4bb3 100644
--- a/src/jtag/adapter.h
+++ b/src/jtag/adapter.h
@@ -11,6 +11,22 @@
 #include <stddef.h>
 #include <stdint.h>
 
+/** Supported output drive modes for adaptor GPIO */
+enum adapter_gpio_drive_mode {
+       DRIVE_MODE_PUSH_PULL,
+       DRIVE_MODE_OPEN_DRAIN,
+       DRIVE_MODE_OPEN_SOURCE,
+};
+
+/** Configuration options for a single GPIO */
+struct adapter_gpio_config {
+       int gpio_num;
+       int chip_num;
+       enum adapter_gpio_drive_mode drive; /* For outputs only */
+       bool active_high;
+       bool init_active;
+};
+
 struct command_context;
 
 /** Register the adapter's commands */
@@ -58,4 +74,9 @@ unsigned int adapter_get_speed_khz(void);
 /** Retrieves the serial number set with command 'adapter serial' */
 const char *adapter_get_required_serial(void);
 
+/**
+ * Retrieves gpio configuration set with command 'adapter gpio <signal_name>'
+ */
+const struct adapter_gpio_config *adapter_get_gpio_config(const char 
*signal_name);
+
 #endif /* OPENOCD_JTAG_ADAPTER_H */

-- 

Reply via email to