linuxgpiod: add SWDIO buffer

The SWDIO buffer requires a direction pin to select input or output
direction. Output is selected by a high logic level (matches
bcm2835gpio driver).

Change-Id: I240cb99a5dfea08121bb33d4b5e2108ce7597468
Signed-off-by: Steve Marple <stevemarple@googlemail.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/6936
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
Steve Marple 2022-04-12 18:25:40 +01:00 committed by Antonio Borneo
parent 9de084e006
commit 20adf85f34
1 changed files with 47 additions and 0 deletions

View File

@ -27,6 +27,7 @@ static int trst_gpio = -1;
static int srst_gpio = -1;
static int swclk_gpio = -1;
static int swdio_gpio = -1;
static int swdio_dir_gpio = -1;
static int led_gpio = -1;
static int gpiochip = -1;
static int tck_gpiochip = -1;
@ -37,6 +38,7 @@ static int trst_gpiochip = -1;
static int srst_gpiochip = -1;
static int swclk_gpiochip = -1;
static int swdio_gpiochip = -1;
static int swdio_dir_gpiochip = -1;
static int led_gpiochip = -1;
static struct gpiod_chip *gpiod_chip_tck;
@ -47,6 +49,7 @@ static struct gpiod_chip *gpiod_chip_trst;
static struct gpiod_chip *gpiod_chip_srst;
static struct gpiod_chip *gpiod_chip_swclk;
static struct gpiod_chip *gpiod_chip_swdio;
static struct gpiod_chip *gpiod_chip_swdio_dir;
static struct gpiod_chip *gpiod_chip_led;
static struct gpiod_line *gpiod_tck;
@ -56,6 +59,7 @@ static struct gpiod_line *gpiod_tdo;
static struct gpiod_line *gpiod_trst;
static struct gpiod_line *gpiod_swclk;
static struct gpiod_line *gpiod_swdio;
static struct gpiod_line *gpiod_swdio_dir;
static struct gpiod_line *gpiod_srst;
static struct gpiod_line *gpiod_led;
@ -63,6 +67,7 @@ static int last_swclk;
static int last_swdio;
static bool last_stored;
static bool swdio_input;
static bool swdio_dir_is_active_high = true;
/* Bitbang interface read of TDO */
static bb_value_t linuxgpiod_read(void)
@ -152,6 +157,11 @@ static void linuxgpiod_swdio_drive(bool is_output)
gpiod_line_release(gpiod_swdio);
if (is_output) {
if (gpiod_swdio_dir) {
retval = gpiod_line_set_value(gpiod_swdio_dir, swdio_dir_is_active_high ? 1 : 0);
if (retval < 0)
LOG_WARNING("Fail set swdio_dir");
}
retval = gpiod_line_request_output(gpiod_swdio, "OpenOCD", 1);
if (retval < 0)
LOG_WARNING("Fail request_output line swdio");
@ -159,6 +169,11 @@ static void linuxgpiod_swdio_drive(bool is_output)
retval = gpiod_line_request_input(gpiod_swdio, "OpenOCD");
if (retval < 0)
LOG_WARNING("Fail request_input line swdio");
if (gpiod_swdio_dir) {
retval = gpiod_line_set_value(gpiod_swdio_dir, swdio_dir_is_active_high ? 0 : 1);
if (retval < 0)
LOG_WARNING("Fail set swdio_dir");
}
}
last_stored = false;
@ -297,6 +312,8 @@ static int linuxgpiod_quit(void)
gpiod_chip_close(gpiod_chip_srst);
if (gpiod_chip_swdio != NULL)
gpiod_chip_close(gpiod_chip_swdio);
if (gpiod_chip_swdio_dir != NULL)
gpiod_chip_close(gpiod_chip_swdio_dir);
if (gpiod_chip_swclk != NULL)
gpiod_chip_close(gpiod_chip_swclk);
if (gpiod_chip_trst != NULL)
@ -451,10 +468,26 @@ static int linuxgpiod_init(void)
goto out_error;
}
if (is_gpio_valid(swdio_dir_gpio)) {
gpiod_chip_swdio_dir = gpiod_chip_open_by_number(swdio_dir_gpiochip);
if (!gpiod_chip_swdio_dir) {
LOG_ERROR("Cannot open LinuxGPIOD swdio_dir_gpiochip %d", swdio_dir_gpiochip);
goto out_error;
}
}
gpiod_swclk = helper_get_output_line("swclk", gpiod_chip_swclk, swclk_gpio, 1);
if (!gpiod_swclk)
goto out_error;
/* Set buffer direction before making SWDIO an output */
if (is_gpio_valid(swdio_dir_gpio)) {
gpiod_swdio_dir = helper_get_output_line("swdio_dir", gpiod_chip_swdio_dir, swdio_dir_gpio,
swdio_dir_is_active_high ? 1 : 0);
if (!gpiod_swdio_dir)
goto out_error;
}
gpiod_swdio = helper_get_output_line("swdio", gpiod_chip_swdio, swdio_gpio, 1);
if (!gpiod_swdio)
goto out_error;
@ -593,6 +626,12 @@ COMMAND_HANDLER(linuxgpiod_handle_swd_gpionum_swdio)
&swdio_gpio);
}
COMMAND_HANDLER(linuxgpiod_handle_swd_gpionum_swdio_dir)
{
return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "swdio_dir", &swdio_dir_gpiochip,
&swdio_dir_gpio);
}
COMMAND_HANDLER(linuxgpiod_handle_gpionum_led)
{
return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "led", &led_gpiochip,
@ -611,6 +650,7 @@ COMMAND_HANDLER(linuxgpiod_handle_gpiochip)
srst_gpiochip = gpiochip;
swclk_gpiochip = gpiochip;
swdio_gpiochip = gpiochip;
swdio_dir_gpiochip = gpiochip;
led_gpiochip = gpiochip;
}
@ -689,6 +729,13 @@ static const struct command_registration linuxgpiod_subcommand_handlers[] = {
.help = "gpio chip number (optional) and gpio number for swdio.",
.usage = "[chip] swdio",
},
{
.name = "swdio_dir_num",
.handler = linuxgpiod_handle_swd_gpionum_swdio_dir,
.mode = COMMAND_CONFIG,
.help = "gpio chip number (optional) and gpio number for swdio_dir.",
.usage = "[chip] swdio_dir",
},
{
.name = "led_num",
.handler = linuxgpiod_handle_gpionum_led,