From 1de35c0b76ea138895370f65849831c3c7d397ff Mon Sep 17 00:00:00 2001 From: Antonio Borneo Date: Sun, 24 Mar 2024 15:53:33 +0100 Subject: [PATCH] jtag: linuxgpiod: adapt for libgpiod v2 API Signed-off-by: Antonio Borneo Signed-off-by: Michael Heimpold --- configure.ac | 15 +- src/jtag/drivers/linuxgpiod.c | 487 ++++++++++++++++++++++++++++------ 2 files changed, 419 insertions(+), 83 deletions(-) --- a/configure.ac +++ b/configure.ac @@ -659,7 +659,20 @@ PKG_CHECK_MODULES([LIBFTDI], [libftdi1], PKG_CHECK_MODULES([LIBFTDI], [libftdi], [use_libftdi=yes], [use_libftdi=no]) ]) -PKG_CHECK_MODULES([LIBGPIOD], [libgpiod], [use_libgpiod=yes], [use_libgpiod=no]) +PKG_CHECK_MODULES([LIBGPIOD], [libgpiod >= 2.0] , [ + use_libgpiod=yes + AC_DEFINE([HAVE_LIBGPIOD_V1], [0], [define if libgpiod is version v1.x]) +], [ + PKG_CHECK_MODULES([LIBGPIOD], [libgpiod], [ + use_libgpiod=yes + AC_DEFINE([HAVE_LIBGPIOD_V1], [1], [define if libgpiod is version v1.x]) + + PKG_CHECK_EXISTS([libgpiod >= 1.5], + [AC_DEFINE([HAVE_LIBGPIOD1_FLAGS_BIAS], [1], [define if libgpiod v1 has line request flags bias])]) + ], [ + use_libgpiod=no + ]) +]) PKG_CHECK_MODULES([LIBJAYLINK], [libjaylink >= 0.2], [use_libjaylink=yes], [use_libjaylink=no]) --- a/src/jtag/drivers/linuxgpiod.c +++ b/src/jtag/drivers/linuxgpiod.c @@ -19,8 +19,267 @@ #include #include "bitbang.h" +/* + * In case of libgpiod v1, use as much as possible API from v2 plus + * the dummy wrappers below. + */ +#if HAVE_LIBGPIOD_V1 + +#define GPIOD_LINE_DIRECTION_INPUT GPIOD_LINE_REQUEST_DIRECTION_INPUT +#define GPIOD_LINE_DIRECTION_OUTPUT GPIOD_LINE_REQUEST_DIRECTION_OUTPUT + +#define GPIOD_LINE_VALUE_INACTIVE 0 +#define GPIOD_LINE_VALUE_ACTIVE 1 + +#define GPIOD_LINE_DRIVE_PUSH_PULL 0 +#define GPIOD_LINE_DRIVE_OPEN_DRAIN GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN +#define GPIOD_LINE_DRIVE_OPEN_SOURCE GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE + +#define GPIOD_LINE_BIAS_DISABLED GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE +#define GPIOD_LINE_BIAS_PULL_UP GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP +#define GPIOD_LINE_BIAS_PULL_DOWN GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN + +struct gpiod_line_settings { + int direction; + int value; + int drive; + int bias; + int active_low; +}; + +static struct gpiod_line_settings *gpiod_line_settings_new(void) +{ + struct gpiod_line_settings *rv; + + rv = calloc(sizeof(struct gpiod_line_settings), 1); + if (!rv) + return NULL; + + return rv; +} + +static void gpiod_line_settings_free(struct gpiod_line_settings *settings) +{ + free(settings); +} + +static int gpiod_line_settings_set_direction(struct gpiod_line_settings *settings, + int direction) +{ + settings->direction = direction; + + return 0; +} + +static int gpiod_line_settings_set_output_value(struct gpiod_line_settings *settings, + int value) +{ + settings->value = value; + + return 0; +} + +static int gpiod_line_settings_set_drive(struct gpiod_line_settings *settings, int drive) +{ + settings->drive = drive; + + return 0; +} + +static void gpiod_line_settings_set_active_low(struct gpiod_line_settings *settings, + bool active_low) +{ + if (active_low) + settings->active_low = GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW; +} + +#ifdef HAVE_LIBGPIOD1_FLAGS_BIAS + +static int gpiod_line_settings_set_bias(struct gpiod_line_settings *settings, int bias) +{ + settings->bias = bias; + + return 0; +} + +#else /* HAVE_LIBGPIOD1_FLAGS_BIAS */ + +static int gpiod_line_settings_set_bias(struct gpiod_line_settings *settings, int bias) +{ + if (bias == GPIOD_LINE_BIAS_DISABLED) + return 0; + + LOG_WARNING("linuxgpiod: ignoring request for pull-%s: not supported by libgpiod v%s", + (bias == GPIOD_LINE_BIAS_PULL_UP) ? "up" : "down", + gpiod_version_string()); + + return 0; +} + +#endif /* HAVE_LIBGPIOD1_FLAGS_BIAS */ + +struct gpiod_line_config { + unsigned int gpio_num; + struct gpiod_line_settings *line_settings; +}; + +static struct gpiod_line_config *gpiod_line_config_new(void) +{ + struct gpiod_line_config *rv; + + rv = calloc(sizeof(struct gpiod_line_config), 1); + if (!rv) + return NULL; + + return rv; +} + +static void gpiod_line_config_free(struct gpiod_line_config *config) +{ + free(config); +} + +static int gpiod_line_config_add_line_settings(struct gpiod_line_config *config, + const unsigned int *offsets, size_t num_offsets, struct gpiod_line_settings *settings) +{ + assert(num_offsets == 1); + + config->gpio_num = *offsets; + config->line_settings = settings; + + return 0; +} + +struct gpiod_request_config { + const char *consumer; +}; + +static struct gpiod_request_config *gpiod_request_config_new(void) +{ + struct gpiod_request_config *rv; + + rv = calloc(sizeof(struct gpiod_request_config), 1); + if (!rv) + return NULL; + + return rv; +} + +static void gpiod_request_config_free(struct gpiod_request_config *config) +{ + free(config); +} + +static void gpiod_request_config_set_consumer(struct gpiod_request_config *config, + const char *consumer) +{ + config->consumer = consumer; +} + +struct gpiod_line_request { + struct gpiod_line *gpio_line; + struct gpiod_chip *chip; + struct gpiod_request_config *req_cfg; + struct gpiod_line_config *line_cfg; +}; + +static struct gpiod_line_request *gpiod_chip_request_lines(struct gpiod_chip *chip, + struct gpiod_request_config *req_cfg, struct gpiod_line_config *line_cfg) +{ + struct gpiod_line_request *line_req; + int rv, flags = 0; + + assert(req_cfg); + + line_req = calloc(sizeof(struct gpiod_line_request), 1); + if (!line_req) + return NULL; + + line_req->gpio_line = gpiod_chip_get_line(chip, line_cfg->gpio_num); + if (!line_req->gpio_line) { + free(line_req); + return NULL; + } + + /* remember stuff in case we need to reconfigure later */ + line_req->chip = chip; + line_req->req_cfg = req_cfg; + line_req->line_cfg = line_cfg; + + flags |= line_cfg->line_settings->drive; + flags |= line_cfg->line_settings->bias; + flags |= line_cfg->line_settings->active_low; + + struct gpiod_line_request_config config = { + .consumer = line_req->req_cfg->consumer, + .request_type = line_cfg->line_settings->direction, + .flags = flags, + }; + + rv = gpiod_line_request(line_req->gpio_line, &config, line_cfg->line_settings->value); + if (rv < 0) { + gpiod_line_release(line_req->gpio_line); + free(line_req); + return NULL; + } + + return line_req; +} + +static int gpiod_line_request_get_value(struct gpiod_line_request *request, + __attribute__((unused)) unsigned int offset) +{ + return gpiod_line_get_value(request->gpio_line); +} + +static int gpiod_line_request_set_value(struct gpiod_line_request *request, + __attribute__((unused)) unsigned int offset, int value) +{ + return gpiod_line_set_value(request->gpio_line, value); +} + +static void gpiod_line_request_release(struct gpiod_line_request *request) +{ + gpiod_line_release(request->gpio_line); + free(request); +} + +static int gpiod_line_request_reconfigure_lines(struct gpiod_line_request *request, + struct gpiod_line_config *line_cfg) +{ + int rv, flags = 0; + + /* in libgpiod v1 we have to release the line and re-aquire it */ + gpiod_line_release(request->gpio_line); + request->gpio_line = gpiod_chip_get_line(request->chip, request->line_cfg->gpio_num); + if (!request->gpio_line) + return -1; + + flags |= line_cfg->line_settings->drive; + flags |= line_cfg->line_settings->bias; + flags |= line_cfg->line_settings->active_low; + + struct gpiod_line_request_config config = { + .consumer = request->req_cfg->consumer, + .request_type = line_cfg->line_settings->direction, + .flags = flags, + }; + + rv = gpiod_line_request(request->gpio_line, &config, line_cfg->line_settings->value); + if (rv < 0) + return -1; + + /* remember updated line_cfg */ + request->line_cfg = line_cfg; + return 0; +} + +#endif /* HAVE_LIBGPIOD_V1 */ + static struct gpiod_chip *gpiod_chip[ADAPTER_GPIO_IDX_NUM] = {}; -static struct gpiod_line *gpiod_line[ADAPTER_GPIO_IDX_NUM] = {}; +static struct gpiod_line_settings *gpiod_line_settings[ADAPTER_GPIO_IDX_NUM] = {}; +static struct gpiod_line_config *gpiod_line_config[ADAPTER_GPIO_IDX_NUM] = {}; +static struct gpiod_line_request *gpiod_line_req[ADAPTER_GPIO_IDX_NUM] = {}; static int last_swclk; static int last_swdio; @@ -29,6 +288,20 @@ static bool swdio_input; static const struct adapter_gpio_config *adapter_gpio_config; +/* Helper to get/set a single line */ +static int linuxgpiod_line_get_value(enum adapter_gpio_config_index idx) +{ + return gpiod_line_request_get_value(gpiod_line_req[idx], + adapter_gpio_config[idx].gpio_num); +} + +static int linuxgpiod_line_set_value(enum adapter_gpio_config_index idx, int value) +{ + return gpiod_line_request_set_value(gpiod_line_req[idx], + adapter_gpio_config[idx].gpio_num, + value); +} + /* * Helper function to determine if gpio config is valid * @@ -48,7 +321,7 @@ static bb_value_t linuxgpiod_read(void) { int retval; - retval = gpiod_line_get_value(gpiod_line[ADAPTER_GPIO_IDX_TDO]); + retval = linuxgpiod_line_get_value(ADAPTER_GPIO_IDX_TDO); if (retval < 0) { LOG_WARNING("reading tdo failed"); return 0; @@ -81,20 +354,20 @@ static int linuxgpiod_write(int tck, int } if (tdi != last_tdi) { - retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_TDI], tdi); + retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_TDI, tdi); if (retval < 0) LOG_WARNING("writing tdi failed"); } if (tms != last_tms) { - retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_TMS], tms); + retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_TMS, tms); if (retval < 0) LOG_WARNING("writing tms failed"); } /* write clk last */ if (tck != last_tck) { - retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_TCK], tck); + retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_TCK, tck); if (retval < 0) LOG_WARNING("writing tck failed"); } @@ -110,7 +383,7 @@ static int linuxgpiod_swdio_read(void) { int retval; - retval = gpiod_line_get_value(gpiod_line[ADAPTER_GPIO_IDX_SWDIO]); + retval = linuxgpiod_line_get_value(ADAPTER_GPIO_IDX_SWDIO); if (retval < 0) { LOG_WARNING("Fail read swdio"); return 0; @@ -123,30 +396,54 @@ static void linuxgpiod_swdio_drive(bool { int retval; - /* - * FIXME: change direction requires release and re-require the line - * https://stackoverflow.com/questions/58735140/ - * this would change in future libgpiod - */ - gpiod_line_release(gpiod_line[ADAPTER_GPIO_IDX_SWDIO]); - if (is_output) { - if (gpiod_line[ADAPTER_GPIO_IDX_SWDIO_DIR]) { - retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWDIO_DIR], 1); + if (gpiod_line_req[ADAPTER_GPIO_IDX_SWDIO_DIR]) { + retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_SWDIO_DIR, 1); if (retval < 0) - LOG_WARNING("Fail set swdio_dir"); + LOG_WARNING("Failed to set swdio_dir=1"); } - retval = gpiod_line_request_output(gpiod_line[ADAPTER_GPIO_IDX_SWDIO], "OpenOCD", 1); + + retval = gpiod_line_settings_set_direction(gpiod_line_settings[ADAPTER_GPIO_IDX_SWDIO], + GPIOD_LINE_DIRECTION_OUTPUT); if (retval < 0) - LOG_WARNING("Fail request_output line swdio"); + LOG_WARNING("Failed to set new direction of swdio"); + + retval = gpiod_line_settings_set_output_value(gpiod_line_settings[ADAPTER_GPIO_IDX_SWDIO], + GPIOD_LINE_VALUE_ACTIVE); + if (retval < 0) + LOG_WARNING("Failed to set output value of swdio"); + + retval = gpiod_line_config_add_line_settings(gpiod_line_config[ADAPTER_GPIO_IDX_SWDIO], + (unsigned int *)&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num, 1, + gpiod_line_settings[ADAPTER_GPIO_IDX_SWDIO]); + if (retval < 0) + LOG_WARNING("Failed to apply output configuration to swdio"); + + retval = gpiod_line_request_reconfigure_lines(gpiod_line_req[ADAPTER_GPIO_IDX_SWDIO], + gpiod_line_config[ADAPTER_GPIO_IDX_SWDIO]); + if (retval < 0) + LOG_WARNING("Failed to switch swdio to output"); } else { - retval = gpiod_line_request_input(gpiod_line[ADAPTER_GPIO_IDX_SWDIO], "OpenOCD"); + retval = gpiod_line_settings_set_direction(gpiod_line_settings[ADAPTER_GPIO_IDX_SWDIO], + GPIOD_LINE_DIRECTION_INPUT); + if (retval < 0) + LOG_WARNING("Failed to switch swdio to output"); + + retval = gpiod_line_config_add_line_settings(gpiod_line_config[ADAPTER_GPIO_IDX_SWDIO], + (unsigned int *)&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num, 1, + gpiod_line_settings[ADAPTER_GPIO_IDX_SWDIO]); if (retval < 0) - LOG_WARNING("Fail request_input line swdio"); - if (gpiod_line[ADAPTER_GPIO_IDX_SWDIO_DIR]) { - retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWDIO_DIR], 0); + LOG_WARNING("Failed to apply input configuration to swdio"); + + retval = gpiod_line_request_reconfigure_lines(gpiod_line_req[ADAPTER_GPIO_IDX_SWDIO], + gpiod_line_config[ADAPTER_GPIO_IDX_SWDIO]); + if (retval < 0) + LOG_WARNING("Failed to switch swdio to input"); + + if (gpiod_line_req[ADAPTER_GPIO_IDX_SWDIO_DIR]) { + retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_SWDIO_DIR, 0); if (retval < 0) - LOG_WARNING("Fail set swdio_dir"); + LOG_WARNING("Failed to set swdio_dir=0"); } } @@ -159,16 +456,16 @@ static int linuxgpiod_swd_write(int swcl int retval; if (!swdio_input) { - if (!last_stored || (swdio != last_swdio)) { - retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWDIO], swdio); + if (!last_stored || swdio != last_swdio) { + retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_SWDIO, swdio); if (retval < 0) LOG_WARNING("Fail set swdio"); } } /* write swclk last */ - if (!last_stored || (swclk != last_swclk)) { - retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SWCLK], swclk); + if (!last_stored || swclk != last_swclk) { + retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_SWCLK, swclk); if (retval < 0) LOG_WARNING("Fail set swclk"); } @@ -187,7 +484,7 @@ static int linuxgpiod_blink(int on) if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_LED)) return ERROR_OK; - retval = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_LED], on); + retval = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_LED, on); if (retval < 0) LOG_WARNING("Fail set led"); return retval; @@ -214,17 +511,17 @@ static int linuxgpiod_reset(int trst, in LOG_DEBUG("linuxgpiod_reset"); /* - * active low behaviour handled by "adaptor gpio" command and + * active low behavior handled by "adaptor gpio" command and * GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW flag when requesting the line. */ - if (gpiod_line[ADAPTER_GPIO_IDX_SRST]) { - retval1 = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_SRST], srst); + if (gpiod_line_req[ADAPTER_GPIO_IDX_SRST]) { + retval1 = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_SRST, srst); if (retval1 < 0) LOG_WARNING("set srst value failed"); } - if (gpiod_line[ADAPTER_GPIO_IDX_TRST]) { - retval2 = gpiod_line_set_value(gpiod_line[ADAPTER_GPIO_IDX_TRST], trst); + if (gpiod_line_req[ADAPTER_GPIO_IDX_TRST]) { + retval2 = linuxgpiod_line_set_value(ADAPTER_GPIO_IDX_TRST, trst); if (retval2 < 0) LOG_WARNING("set trst value failed"); } @@ -256,9 +553,17 @@ static bool linuxgpiod_swd_mode_possible static inline void helper_release(enum adapter_gpio_config_index idx) { - if (gpiod_line[idx]) { - gpiod_line_release(gpiod_line[idx]); - gpiod_line[idx] = NULL; + if (gpiod_line_req[idx]) { + gpiod_line_request_release(gpiod_line_req[idx]); + gpiod_line_req[idx] = NULL; + } + if (gpiod_line_config[idx]) { + gpiod_line_config_free(gpiod_line_config[idx]); + gpiod_line_config[idx] = NULL; + } + if (gpiod_line_settings[idx]) { + gpiod_line_settings_free(gpiod_line_settings[idx]); + gpiod_line_settings[idx] = NULL; } if (gpiod_chip[idx]) { gpiod_chip_close(gpiod_chip[idx]); @@ -277,84 +582,102 @@ static int linuxgpiod_quit(void) static int helper_get_line(enum adapter_gpio_config_index idx) { + struct gpiod_request_config *req_cfg = NULL; + char chip_path[24]; + int rv = 0; + if (!is_gpio_config_valid(idx)) return ERROR_OK; - int dir = GPIOD_LINE_REQUEST_DIRECTION_INPUT, flags = 0, val = 0, retval; - - gpiod_chip[idx] = gpiod_chip_open_by_number(adapter_gpio_config[idx].chip_num); + snprintf(chip_path, sizeof(chip_path), "/dev/gpiochip%u", adapter_gpio_config[idx].chip_num); + gpiod_chip[idx] = gpiod_chip_open(chip_path); if (!gpiod_chip[idx]) { LOG_ERROR("Cannot open LinuxGPIOD chip %d for %s", adapter_gpio_config[idx].chip_num, adapter_gpio_get_name(idx)); return ERROR_JTAG_INIT_FAILED; } - gpiod_line[idx] = gpiod_chip_get_line(gpiod_chip[idx], adapter_gpio_config[idx].gpio_num); - if (!gpiod_line[idx]) { - LOG_ERROR("Error get line %s", adapter_gpio_get_name(idx)); + gpiod_line_settings[idx] = gpiod_line_settings_new(); + gpiod_line_config[idx] = gpiod_line_config_new(); + req_cfg = gpiod_request_config_new(); + + if (!gpiod_line_settings[idx] || !gpiod_line_config[idx] || !req_cfg) { + LOG_ERROR("Cannot configure LinuxGPIOD line for %s", adapter_gpio_get_name(idx)); + gpiod_request_config_free(req_cfg); return ERROR_JTAG_INIT_FAILED; } + gpiod_request_config_set_consumer(req_cfg, "OpenOCD"); + switch (adapter_gpio_config[idx].init_state) { case ADAPTER_GPIO_INIT_STATE_INPUT: - dir = GPIOD_LINE_REQUEST_DIRECTION_INPUT; + rv = gpiod_line_settings_set_direction(gpiod_line_settings[idx], GPIOD_LINE_DIRECTION_INPUT); break; case ADAPTER_GPIO_INIT_STATE_INACTIVE: - dir = GPIOD_LINE_REQUEST_DIRECTION_OUTPUT; - val = 0; + rv = gpiod_line_settings_set_direction(gpiod_line_settings[idx], GPIOD_LINE_DIRECTION_OUTPUT); + rv |= gpiod_line_settings_set_output_value(gpiod_line_settings[idx], GPIOD_LINE_VALUE_INACTIVE); break; case ADAPTER_GPIO_INIT_STATE_ACTIVE: - dir = GPIOD_LINE_REQUEST_DIRECTION_OUTPUT; - val = 1; + rv = gpiod_line_settings_set_direction(gpiod_line_settings[idx], GPIOD_LINE_DIRECTION_OUTPUT); + rv |= gpiod_line_settings_set_output_value(gpiod_line_settings[idx], GPIOD_LINE_VALUE_ACTIVE); break; } + if (rv < 0) { + LOG_ERROR("Error while configuring LinuxGPIOD line init state for %s", adapter_gpio_get_name(idx)); + gpiod_request_config_free(req_cfg); + return ERROR_JTAG_INIT_FAILED; + } switch (adapter_gpio_config[idx].drive) { case ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL: + rv = gpiod_line_settings_set_drive(gpiod_line_settings[idx], GPIOD_LINE_DRIVE_PUSH_PULL); break; case ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN: - flags |= GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN; + rv = gpiod_line_settings_set_drive(gpiod_line_settings[idx], GPIOD_LINE_DRIVE_OPEN_DRAIN); break; case ADAPTER_GPIO_DRIVE_MODE_OPEN_SOURCE: - flags |= GPIOD_LINE_REQUEST_FLAG_OPEN_SOURCE; + rv = gpiod_line_settings_set_drive(gpiod_line_settings[idx], GPIOD_LINE_DRIVE_OPEN_SOURCE); break; } + if (rv < 0) { + LOG_ERROR("Error while configuring LinuxGPIOD line driving for %s", adapter_gpio_get_name(idx)); + gpiod_request_config_free(req_cfg); + return ERROR_JTAG_INIT_FAILED; + } switch (adapter_gpio_config[idx].pull) { case ADAPTER_GPIO_PULL_NONE: -#ifdef GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE - flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_DISABLE; -#endif + rv = gpiod_line_settings_set_bias(gpiod_line_settings[idx], GPIOD_LINE_BIAS_DISABLED); break; case ADAPTER_GPIO_PULL_UP: -#ifdef GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP - flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_UP; -#else - LOG_WARNING("linuxgpiod: ignoring request for pull-up on %s: not supported by gpiod v%s", - adapter_gpio_get_name(idx), gpiod_version_string()); -#endif + rv = gpiod_line_settings_set_bias(gpiod_line_settings[idx], GPIOD_LINE_BIAS_PULL_UP); break; case ADAPTER_GPIO_PULL_DOWN: -#ifdef GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN - flags |= GPIOD_LINE_REQUEST_FLAG_BIAS_PULL_DOWN; -#else - LOG_WARNING("linuxgpiod: ignoring request for pull-down on %s: not supported by gpiod v%s", - adapter_gpio_get_name(idx), gpiod_version_string()); -#endif + rv = gpiod_line_settings_set_bias(gpiod_line_settings[idx], GPIOD_LINE_BIAS_PULL_DOWN); break; } + if (rv < 0) { + LOG_ERROR("Error while configuring LinuxGPIOD line biasing for %s", adapter_gpio_get_name(idx)); + gpiod_request_config_free(req_cfg); + return ERROR_JTAG_INIT_FAILED; + } - if (adapter_gpio_config[idx].active_low) - flags |= GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW; + gpiod_line_settings_set_active_low(gpiod_line_settings[idx], adapter_gpio_config[idx].active_low); - struct gpiod_line_request_config config = { - .consumer = "OpenOCD", - .request_type = dir, - .flags = flags, - }; + rv = gpiod_line_config_add_line_settings(gpiod_line_config[idx], + (unsigned int *)&adapter_gpio_config[idx].gpio_num, 1, + gpiod_line_settings[idx]); + if (rv < 0) { + LOG_ERROR("Error configuring gpio line %s", adapter_gpio_get_name(idx)); + gpiod_request_config_free(req_cfg); + return ERROR_JTAG_INIT_FAILED; + } - retval = gpiod_line_request(gpiod_line[idx], &config, val); - if (retval < 0) { + gpiod_line_req[idx] = gpiod_chip_request_lines(gpiod_chip[idx], req_cfg, gpiod_line_config[idx]); + + gpiod_request_config_free(req_cfg); + + if (!gpiod_line_req[idx]) { LOG_ERROR("Error requesting gpio line %s", adapter_gpio_get_name(idx)); return ERROR_JTAG_INIT_FAILED; } @@ -380,12 +703,12 @@ static int linuxgpiod_init(void) goto out_error; } - if (helper_get_line(ADAPTER_GPIO_IDX_TDO) != ERROR_OK || - helper_get_line(ADAPTER_GPIO_IDX_TDI) != ERROR_OK || - helper_get_line(ADAPTER_GPIO_IDX_TCK) != ERROR_OK || - helper_get_line(ADAPTER_GPIO_IDX_TMS) != ERROR_OK || - helper_get_line(ADAPTER_GPIO_IDX_TRST) != ERROR_OK) - goto out_error; + if (helper_get_line(ADAPTER_GPIO_IDX_TDO) != ERROR_OK + || helper_get_line(ADAPTER_GPIO_IDX_TDI) != ERROR_OK + || helper_get_line(ADAPTER_GPIO_IDX_TCK) != ERROR_OK + || helper_get_line(ADAPTER_GPIO_IDX_TMS) != ERROR_OK + || helper_get_line(ADAPTER_GPIO_IDX_TRST) != ERROR_OK) + goto out_error; } if (transport_is_swd()) { @@ -415,9 +738,9 @@ static int linuxgpiod_init(void) goto out_error; } - if (helper_get_line(ADAPTER_GPIO_IDX_SRST) != ERROR_OK || - helper_get_line(ADAPTER_GPIO_IDX_LED) != ERROR_OK) - goto out_error; + if (helper_get_line(ADAPTER_GPIO_IDX_SRST) != ERROR_OK + || helper_get_line(ADAPTER_GPIO_IDX_LED) != ERROR_OK) + goto out_error; return ERROR_OK;