diff options
author | Alex Crawford <openocd@code.acrawford.com> | 2021-09-16 10:00:25 -0700 |
---|---|---|
committer | Antonio Borneo <borneo.antonio@gmail.com> | 2021-09-25 13:15:05 +0000 |
commit | 2f424b7eb776b3d32f2b58a3ffd91ff1d5657404 (patch) | |
tree | ed3e258647f1fd9f298d2eaddd20b0514d34169b /src | |
parent | 5765a0ce14485aadc6b74c6e2b4f15b73df14603 (diff) | |
download | riscv-openocd-2f424b7eb776b3d32f2b58a3ffd91ff1d5657404.zip riscv-openocd-2f424b7eb776b3d32f2b58a3ffd91ff1d5657404.tar.gz riscv-openocd-2f424b7eb776b3d32f2b58a3ffd91ff1d5657404.tar.bz2 |
driver/linuxgpiod: add support for opendrain srst
Some MCUs (e.g. the STM32F3) directly expose the internal reset line to
an external pin. When this signal is driven by a push/pull line, it can
actually be inhibited by the external driver. This results in a setup
where the MCU cannot reset itself, for example, by a watchdog timeout or
a sysreset request. To fix this condition, support for open drain output
on the SRST line is required.
Note that because `reset_config srst_open_drain` is the default, all
users of this adapter will switch over to an open drain output unless
explicitly configured otherwise.
Signed-off-by: Alex Crawford <openocd@code.acrawford.com>
Change-Id: I89b39b03aa03f826ed3c45793412780448940bcc
Reviewed-on: https://review.openocd.org/c/openocd/+/6559
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/jtag/drivers/linuxgpiod.c | 43 |
1 files changed, 24 insertions, 19 deletions
diff --git a/src/jtag/drivers/linuxgpiod.c b/src/jtag/drivers/linuxgpiod.c index 42c8a31..dd50b44 100644 --- a/src/jtag/drivers/linuxgpiod.c +++ b/src/jtag/drivers/linuxgpiod.c @@ -278,7 +278,7 @@ static int linuxgpiod_quit(void) return ERROR_OK; } -static struct gpiod_line *helper_get_input_line(const char *label, unsigned int offset) +static struct gpiod_line *helper_get_line(const char *label, unsigned int offset, int val, int dir, int flags) { struct gpiod_line *line; int retval; @@ -289,33 +289,34 @@ static struct gpiod_line *helper_get_input_line(const char *label, unsigned int return NULL; } - retval = gpiod_line_request_input(line, "OpenOCD"); + struct gpiod_line_request_config config = { + .consumer = "OpenOCD", + .request_type = dir, + .flags = flags, + }; + + retval = gpiod_line_request(line, &config, val); if (retval < 0) { - LOG_ERROR("Error request_input line %s", label); + LOG_ERROR("Error requesting gpio line %s", label); return NULL; } return line; } -static struct gpiod_line *helper_get_output_line(const char *label, unsigned int offset, int val) +static struct gpiod_line *helper_get_input_line(const char *label, unsigned int offset) { - struct gpiod_line *line; - int retval; - - line = gpiod_chip_get_line(gpiod_chip, offset); - if (!line) { - LOG_ERROR("Error get line %s", label); - return NULL; - } + return helper_get_line(label, offset, 0, GPIOD_LINE_REQUEST_DIRECTION_INPUT, 0); +} - retval = gpiod_line_request_output(line, "OpenOCD", val); - if (retval < 0) { - LOG_ERROR("Error request_output line %s", label); - return NULL; - } +static struct gpiod_line *helper_get_output_line(const char *label, unsigned int offset, int val) +{ + return helper_get_line(label, offset, val, GPIOD_LINE_REQUEST_DIRECTION_OUTPUT, 0); +} - return line; +static struct gpiod_line *helper_get_open_drain_output_line(const char *label, unsigned int offset, int val) +{ + return helper_get_line(label, offset, val, GPIOD_LINE_REQUEST_DIRECTION_OUTPUT, GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN); } static int linuxgpiod_init(void) @@ -381,7 +382,11 @@ static int linuxgpiod_init(void) } if (is_gpio_valid(srst_gpio)) { - gpiod_srst = helper_get_output_line("srst", srst_gpio, 1); + if (jtag_get_reset_config() & RESET_SRST_PUSH_PULL) + gpiod_srst = helper_get_output_line("srst", srst_gpio, 1); + else + gpiod_srst = helper_get_open_drain_output_line("srst", srst_gpio, 1); + if (!gpiod_srst) goto out_error; } |