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>
This commit is contained in:
parent
5765a0ce14
commit
2f424b7eb7
|
@ -278,7 +278,7 @@ static int linuxgpiod_quit(void)
|
||||||
return ERROR_OK;
|
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;
|
struct gpiod_line *line;
|
||||||
int retval;
|
int retval;
|
||||||
|
@ -289,33 +289,34 @@ static struct gpiod_line *helper_get_input_line(const char *label, unsigned int
|
||||||
return NULL;
|
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) {
|
if (retval < 0) {
|
||||||
LOG_ERROR("Error request_input line %s", label);
|
LOG_ERROR("Error requesting gpio line %s", label);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct gpiod_line *helper_get_input_line(const char *label, unsigned int offset)
|
||||||
|
{
|
||||||
|
return helper_get_line(label, offset, 0, GPIOD_LINE_REQUEST_DIRECTION_INPUT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static struct gpiod_line *helper_get_output_line(const char *label, unsigned int offset, int val)
|
static struct gpiod_line *helper_get_output_line(const char *label, unsigned int offset, int val)
|
||||||
{
|
{
|
||||||
struct gpiod_line *line;
|
return helper_get_line(label, offset, val, GPIOD_LINE_REQUEST_DIRECTION_OUTPUT, 0);
|
||||||
int retval;
|
|
||||||
|
|
||||||
line = gpiod_chip_get_line(gpiod_chip, offset);
|
|
||||||
if (!line) {
|
|
||||||
LOG_ERROR("Error get line %s", label);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = gpiod_line_request_output(line, "OpenOCD", val);
|
static struct gpiod_line *helper_get_open_drain_output_line(const char *label, unsigned int offset, int val)
|
||||||
if (retval < 0) {
|
{
|
||||||
LOG_ERROR("Error request_output line %s", label);
|
return helper_get_line(label, offset, val, GPIOD_LINE_REQUEST_DIRECTION_OUTPUT, GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN);
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return line;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int linuxgpiod_init(void)
|
static int linuxgpiod_init(void)
|
||||||
|
@ -381,7 +382,11 @@ static int linuxgpiod_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_gpio_valid(srst_gpio)) {
|
if (is_gpio_valid(srst_gpio)) {
|
||||||
|
if (jtag_get_reset_config() & RESET_SRST_PUSH_PULL)
|
||||||
gpiod_srst = helper_get_output_line("srst", srst_gpio, 1);
|
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)
|
if (!gpiod_srst)
|
||||||
goto out_error;
|
goto out_error;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue