1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 * Bitbang driver for Linux GPIO descriptors through libgpiod
4 * Copyright (C) 2020 Antonio Borneo <borneo.antonio@gmail.com>
6 * Largely based on sysfsgpio driver
7 * Copyright (C) 2012 by Creative Product Design, marc @ cpdesign.com.au
8 * Copyright (C) 2014 by Jean-Christian de Rivaz <jc@eclis.ch>
9 * Copyright (C) 2014 by Paul Fertser <fercerpav@gmail.com>
17 #include <jtag/interface.h>
18 #include <transport/transport.h>
21 /* gpio numbers for each gpio. Negative values are invalid */
22 static int tck_gpio
= -1;
23 static int tms_gpio
= -1;
24 static int tdi_gpio
= -1;
25 static int tdo_gpio
= -1;
26 static int trst_gpio
= -1;
27 static int srst_gpio
= -1;
28 static int swclk_gpio
= -1;
29 static int swdio_gpio
= -1;
30 static int swdio_dir_gpio
= -1;
31 static int led_gpio
= -1;
32 static int gpiochip
= -1;
33 static int tck_gpiochip
= -1;
34 static int tms_gpiochip
= -1;
35 static int tdi_gpiochip
= -1;
36 static int tdo_gpiochip
= -1;
37 static int trst_gpiochip
= -1;
38 static int srst_gpiochip
= -1;
39 static int swclk_gpiochip
= -1;
40 static int swdio_gpiochip
= -1;
41 static int swdio_dir_gpiochip
= -1;
42 static int led_gpiochip
= -1;
44 static struct gpiod_chip
*gpiod_chip_tck
;
45 static struct gpiod_chip
*gpiod_chip_tms
;
46 static struct gpiod_chip
*gpiod_chip_tdi
;
47 static struct gpiod_chip
*gpiod_chip_tdo
;
48 static struct gpiod_chip
*gpiod_chip_trst
;
49 static struct gpiod_chip
*gpiod_chip_srst
;
50 static struct gpiod_chip
*gpiod_chip_swclk
;
51 static struct gpiod_chip
*gpiod_chip_swdio
;
52 static struct gpiod_chip
*gpiod_chip_swdio_dir
;
53 static struct gpiod_chip
*gpiod_chip_led
;
55 static struct gpiod_line
*gpiod_tck
;
56 static struct gpiod_line
*gpiod_tms
;
57 static struct gpiod_line
*gpiod_tdi
;
58 static struct gpiod_line
*gpiod_tdo
;
59 static struct gpiod_line
*gpiod_trst
;
60 static struct gpiod_line
*gpiod_swclk
;
61 static struct gpiod_line
*gpiod_swdio
;
62 static struct gpiod_line
*gpiod_swdio_dir
;
63 static struct gpiod_line
*gpiod_srst
;
64 static struct gpiod_line
*gpiod_led
;
66 static int last_swclk
;
67 static int last_swdio
;
68 static bool last_stored
;
69 static bool swdio_input
;
70 static bool swdio_dir_is_active_high
= true;
72 /* Bitbang interface read of TDO */
73 static bb_value_t
linuxgpiod_read(void)
77 retval
= gpiod_line_get_value(gpiod_tdo
);
79 LOG_WARNING("reading tdo failed");
83 return retval
? BB_HIGH
: BB_LOW
;
87 * Bitbang interface write of TCK, TMS, TDI
89 * Seeing as this is the only function where the outputs are changed,
90 * we can cache the old value to avoid needlessly writing it.
92 static int linuxgpiod_write(int tck
, int tms
, int tdi
)
98 static int first_time
;
109 if (tdi
!= last_tdi
) {
110 retval
= gpiod_line_set_value(gpiod_tdi
, tdi
);
112 LOG_WARNING("writing tdi failed");
115 if (tms
!= last_tms
) {
116 retval
= gpiod_line_set_value(gpiod_tms
, tms
);
118 LOG_WARNING("writing tms failed");
122 if (tck
!= last_tck
) {
123 retval
= gpiod_line_set_value(gpiod_tck
, tck
);
125 LOG_WARNING("writing tck failed");
135 static int linuxgpiod_swdio_read(void)
139 retval
= gpiod_line_get_value(gpiod_swdio
);
141 LOG_WARNING("Fail read swdio");
148 static void linuxgpiod_swdio_drive(bool is_output
)
153 * FIXME: change direction requires release and re-require the line
154 * https://stackoverflow.com/questions/58735140/
155 * this would change in future libgpiod
157 gpiod_line_release(gpiod_swdio
);
160 if (gpiod_swdio_dir
) {
161 retval
= gpiod_line_set_value(gpiod_swdio_dir
, swdio_dir_is_active_high
? 1 : 0);
163 LOG_WARNING("Fail set swdio_dir");
165 retval
= gpiod_line_request_output(gpiod_swdio
, "OpenOCD", 1);
167 LOG_WARNING("Fail request_output line swdio");
169 retval
= gpiod_line_request_input(gpiod_swdio
, "OpenOCD");
171 LOG_WARNING("Fail request_input line swdio");
172 if (gpiod_swdio_dir
) {
173 retval
= gpiod_line_set_value(gpiod_swdio_dir
, swdio_dir_is_active_high
? 0 : 1);
175 LOG_WARNING("Fail set swdio_dir");
180 swdio_input
= !is_output
;
183 static int linuxgpiod_swd_write(int swclk
, int swdio
)
188 if (!last_stored
|| (swdio
!= last_swdio
)) {
189 retval
= gpiod_line_set_value(gpiod_swdio
, swdio
);
191 LOG_WARNING("Fail set swdio");
195 /* write swclk last */
196 if (!last_stored
|| (swclk
!= last_swclk
)) {
197 retval
= gpiod_line_set_value(gpiod_swclk
, swclk
);
199 LOG_WARNING("Fail set swclk");
209 static int linuxgpiod_blink(int on
)
216 retval
= gpiod_line_set_value(gpiod_led
, on
);
218 LOG_WARNING("Fail set led");
222 static struct bitbang_interface linuxgpiod_bitbang
= {
223 .read
= linuxgpiod_read
,
224 .write
= linuxgpiod_write
,
225 .swdio_read
= linuxgpiod_swdio_read
,
226 .swdio_drive
= linuxgpiod_swdio_drive
,
227 .swd_write
= linuxgpiod_swd_write
,
228 .blink
= linuxgpiod_blink
,
232 * Bitbang interface to manipulate reset lines SRST and TRST
234 * (1) assert or (0) deassert reset lines
236 static int linuxgpiod_reset(int trst
, int srst
)
238 int retval1
= 0, retval2
= 0;
240 LOG_DEBUG("linuxgpiod_reset");
242 /* assume active low */
244 retval1
= gpiod_line_set_value(gpiod_srst
, srst
? 0 : 1);
246 LOG_WARNING("set srst value failed");
249 /* assume active low */
251 retval2
= gpiod_line_set_value(gpiod_trst
, trst
? 0 : 1);
253 LOG_WARNING("set trst value failed");
256 return ((retval1
< 0) || (retval2
< 0)) ? ERROR_FAIL
: ERROR_OK
;
260 * Helper function to determine if gpio number is valid
262 * Assume here that there will be less than 10000 gpios per gpiochip
264 static bool is_gpio_valid(int gpio
)
266 return gpio
>= 0 && gpio
< 10000;
269 static bool linuxgpiod_jtag_mode_possible(void)
271 if (!is_gpio_valid(tck_gpio
))
273 if (!is_gpio_valid(tms_gpio
))
275 if (!is_gpio_valid(tdi_gpio
))
277 if (!is_gpio_valid(tdo_gpio
))
282 static bool linuxgpiod_swd_mode_possible(void)
284 if (!is_gpio_valid(swclk_gpio
))
286 if (!is_gpio_valid(swdio_gpio
))
291 static inline void helper_release(struct gpiod_line
*line
, struct gpiod_chip
*chip
)
294 gpiod_line_release(line
);
296 gpiod_chip_close(chip
);
299 static int linuxgpiod_quit(void)
301 helper_release(gpiod_led
, gpiod_chip_led
);
302 helper_release(gpiod_srst
, gpiod_chip_srst
);
303 helper_release(gpiod_swdio
, gpiod_chip_swdio
);
304 helper_release(gpiod_swdio_dir
, gpiod_chip_swdio_dir
);
305 helper_release(gpiod_swclk
, gpiod_chip_swclk
);
306 helper_release(gpiod_trst
, gpiod_chip_trst
);
307 helper_release(gpiod_tms
, gpiod_chip_tms
);
308 helper_release(gpiod_tck
, gpiod_chip_tck
);
309 helper_release(gpiod_tdi
, gpiod_chip_tdi
);
310 helper_release(gpiod_tdo
, gpiod_chip_tdo
);
315 static struct gpiod_line
*helper_get_line(const char *label
,
316 struct gpiod_chip
*gpiod_chip
, unsigned int offset
,
317 int val
, int dir
, int flags
)
319 struct gpiod_line
*line
;
322 line
= gpiod_chip_get_line(gpiod_chip
, offset
);
324 LOG_ERROR("Error get line %s", label
);
328 struct gpiod_line_request_config config
= {
329 .consumer
= "OpenOCD",
334 retval
= gpiod_line_request(line
, &config
, val
);
336 LOG_ERROR("Error requesting gpio line %s", label
);
343 static struct gpiod_line
*helper_get_input_line(const char *label
,
344 struct gpiod_chip
*gpiod_chip
, unsigned int offset
)
346 return helper_get_line(label
, gpiod_chip
, offset
, 0,
347 GPIOD_LINE_REQUEST_DIRECTION_INPUT
, 0);
350 static struct gpiod_line
*helper_get_output_line(const char *label
,
351 struct gpiod_chip
*gpiod_chip
, unsigned int offset
, int val
)
353 return helper_get_line(label
, gpiod_chip
, offset
, val
,
354 GPIOD_LINE_REQUEST_DIRECTION_OUTPUT
, 0);
357 static struct gpiod_line
*helper_get_open_drain_output_line(const char *label
,
358 struct gpiod_chip
*gpiod_chip
, unsigned int offset
, int val
)
360 return helper_get_line(label
, gpiod_chip
, offset
, val
,
361 GPIOD_LINE_REQUEST_DIRECTION_OUTPUT
, GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN
);
364 static int linuxgpiod_init(void)
366 LOG_INFO("Linux GPIOD JTAG/SWD bitbang driver");
368 bitbang_interface
= &linuxgpiod_bitbang
;
371 * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
372 * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high.
373 * For SWD, SWCLK and SWDIO are configures as output high.
376 if (transport_is_jtag()) {
377 if (!linuxgpiod_jtag_mode_possible()) {
378 LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode");
382 gpiod_chip_tdo
= gpiod_chip_open_by_number(tdo_gpiochip
);
383 if (!gpiod_chip_tdo
) {
384 LOG_ERROR("Cannot open LinuxGPIOD tdo_gpiochip %d", tdo_gpiochip
);
387 gpiod_chip_tdi
= gpiod_chip_open_by_number(tdi_gpiochip
);
388 if (!gpiod_chip_tdi
) {
389 LOG_ERROR("Cannot open LinuxGPIOD tdi_gpiochip %d", tdi_gpiochip
);
392 gpiod_chip_tck
= gpiod_chip_open_by_number(tck_gpiochip
);
393 if (!gpiod_chip_tck
) {
394 LOG_ERROR("Cannot open LinuxGPIOD tck_gpiochip %d", tck_gpiochip
);
397 gpiod_chip_tms
= gpiod_chip_open_by_number(tms_gpiochip
);
398 if (!gpiod_chip_tms
) {
399 LOG_ERROR("Cannot open LinuxGPIOD tms_gpiochip %d", tms_gpiochip
);
403 gpiod_tdo
= helper_get_input_line("tdo", gpiod_chip_tdo
, tdo_gpio
);
407 gpiod_tdi
= helper_get_output_line("tdi", gpiod_chip_tdi
, tdi_gpio
, 0);
411 gpiod_tck
= helper_get_output_line("tck", gpiod_chip_tck
, tck_gpio
, 0);
415 gpiod_tms
= helper_get_output_line("tms", gpiod_chip_tms
, tms_gpio
, 1);
419 if (is_gpio_valid(trst_gpio
)) {
420 gpiod_chip_trst
= gpiod_chip_open_by_number(trst_gpiochip
);
421 if (!gpiod_chip_trst
) {
422 LOG_ERROR("Cannot open LinuxGPIOD trst_gpiochip %d", trst_gpiochip
);
426 if (jtag_get_reset_config() & RESET_TRST_OPEN_DRAIN
)
427 gpiod_trst
= helper_get_open_drain_output_line("trst", gpiod_chip_trst
, trst_gpio
, 1);
429 gpiod_trst
= helper_get_output_line("trst", gpiod_chip_trst
, trst_gpio
, 1);
436 if (transport_is_swd()) {
437 if (!linuxgpiod_swd_mode_possible()) {
438 LOG_ERROR("Require swclk and swdio gpio for SWD mode");
442 gpiod_chip_swclk
= gpiod_chip_open_by_number(swclk_gpiochip
);
443 if (!gpiod_chip_swclk
) {
444 LOG_ERROR("Cannot open LinuxGPIOD swclk_gpiochip %d", swclk_gpiochip
);
447 gpiod_chip_swdio
= gpiod_chip_open_by_number(swdio_gpiochip
);
448 if (!gpiod_chip_swdio
) {
449 LOG_ERROR("Cannot open LinuxGPIOD swdio_gpiochip %d", swdio_gpiochip
);
453 if (is_gpio_valid(swdio_dir_gpio
)) {
454 gpiod_chip_swdio_dir
= gpiod_chip_open_by_number(swdio_dir_gpiochip
);
455 if (!gpiod_chip_swdio_dir
) {
456 LOG_ERROR("Cannot open LinuxGPIOD swdio_dir_gpiochip %d", swdio_dir_gpiochip
);
461 gpiod_swclk
= helper_get_output_line("swclk", gpiod_chip_swclk
, swclk_gpio
, 1);
465 /* Set buffer direction before making SWDIO an output */
466 if (is_gpio_valid(swdio_dir_gpio
)) {
467 gpiod_swdio_dir
= helper_get_output_line("swdio_dir", gpiod_chip_swdio_dir
, swdio_dir_gpio
,
468 swdio_dir_is_active_high
? 1 : 0);
469 if (!gpiod_swdio_dir
)
473 gpiod_swdio
= helper_get_output_line("swdio", gpiod_chip_swdio
, swdio_gpio
, 1);
478 if (is_gpio_valid(srst_gpio
)) {
479 gpiod_chip_srst
= gpiod_chip_open_by_number(srst_gpiochip
);
480 if (!gpiod_chip_srst
) {
481 LOG_ERROR("Cannot open LinuxGPIOD srst_gpiochip %d", srst_gpiochip
);
485 if (jtag_get_reset_config() & RESET_SRST_PUSH_PULL
)
486 gpiod_srst
= helper_get_output_line("srst", gpiod_chip_srst
, srst_gpio
, 1);
488 gpiod_srst
= helper_get_open_drain_output_line("srst", gpiod_chip_srst
, srst_gpio
, 1);
494 if (is_gpio_valid(led_gpio
)) {
495 gpiod_chip_led
= gpiod_chip_open_by_number(led_gpiochip
);
496 if (!gpiod_chip_led
) {
497 LOG_ERROR("Cannot open LinuxGPIOD led_gpiochip %d", led_gpiochip
);
501 gpiod_led
= helper_get_output_line("led", gpiod_chip_led
, led_gpio
, 0);
511 return ERROR_JTAG_INIT_FAILED
;
514 COMMAND_HELPER(linuxgpiod_helper_gpionum
, const char *name
, int *chip
, int *line
)
518 return ERROR_COMMAND_SYNTAX_ERROR
;
520 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], *chip
);
524 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[i
], *line
);
525 command_print(CMD
, "LinuxGPIOD %s: chip = %d, num = %d", name
, *chip
, *line
);
529 COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionums
)
532 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tck_gpio
);
533 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], tms_gpio
);
534 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[2], tdi_gpio
);
535 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[3], tdo_gpio
);
536 } else if (CMD_ARGC
!= 0) {
537 return ERROR_COMMAND_SYNTAX_ERROR
;
541 "LinuxGPIOD nums: tck = %d, tms = %d, tdi = %d, tdo = %d",
542 tck_gpio
, tms_gpio
, tdi_gpio
, tdo_gpio
);
547 COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionum_tck
)
549 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum
, "tck", &tck_gpiochip
,
553 COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionum_tms
)
555 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum
, "tms", &tms_gpiochip
,
559 COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionum_tdo
)
561 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum
, "tdo", &tdo_gpiochip
,
565 COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionum_tdi
)
567 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum
, "tdi", &tdi_gpiochip
,
571 COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionum_srst
)
573 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum
, "srst", &srst_gpiochip
,
577 COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionum_trst
)
579 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum
, "trst", &trst_gpiochip
,
583 COMMAND_HANDLER(linuxgpiod_handle_swd_gpionums
)
586 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swclk_gpio
);
587 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], swdio_gpio
);
588 } else if (CMD_ARGC
!= 0) {
589 return ERROR_COMMAND_SYNTAX_ERROR
;
593 "LinuxGPIOD nums: swclk = %d, swdio = %d",
594 swclk_gpio
, swdio_gpio
);
599 COMMAND_HANDLER(linuxgpiod_handle_swd_gpionum_swclk
)
601 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum
, "swclk", &swclk_gpiochip
,
605 COMMAND_HANDLER(linuxgpiod_handle_swd_gpionum_swdio
)
607 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum
, "swdio", &swdio_gpiochip
,
611 COMMAND_HANDLER(linuxgpiod_handle_swd_gpionum_swdio_dir
)
613 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum
, "swdio_dir", &swdio_dir_gpiochip
,
617 COMMAND_HANDLER(linuxgpiod_handle_gpionum_led
)
619 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum
, "led", &led_gpiochip
,
623 COMMAND_HANDLER(linuxgpiod_handle_gpiochip
)
626 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], gpiochip
);
627 tck_gpiochip
= gpiochip
;
628 tms_gpiochip
= gpiochip
;
629 tdi_gpiochip
= gpiochip
;
630 tdo_gpiochip
= gpiochip
;
631 trst_gpiochip
= gpiochip
;
632 srst_gpiochip
= gpiochip
;
633 swclk_gpiochip
= gpiochip
;
634 swdio_gpiochip
= gpiochip
;
635 swdio_dir_gpiochip
= gpiochip
;
636 led_gpiochip
= gpiochip
;
639 command_print(CMD
, "LinuxGPIOD gpiochip = %d", gpiochip
);
643 static const struct command_registration linuxgpiod_subcommand_handlers
[] = {
646 .handler
= linuxgpiod_handle_jtag_gpionums
,
647 .mode
= COMMAND_CONFIG
,
648 .help
= "gpio numbers for tck, tms, tdi, tdo. (in that order)",
649 .usage
= "tck tms tdi tdo",
653 .handler
= linuxgpiod_handle_jtag_gpionum_tck
,
654 .mode
= COMMAND_CONFIG
,
655 .help
= "gpio chip number (optional) and gpio number for tck.",
656 .usage
= "[chip] tck",
660 .handler
= linuxgpiod_handle_jtag_gpionum_tms
,
661 .mode
= COMMAND_CONFIG
,
662 .help
= "gpio chip number (optional) and gpio number for tms.",
663 .usage
= "[chip] tms",
667 .handler
= linuxgpiod_handle_jtag_gpionum_tdo
,
668 .mode
= COMMAND_CONFIG
,
669 .help
= "gpio chip number (optional) and gpio number for tdo.",
670 .usage
= "[chip] tdo",
674 .handler
= linuxgpiod_handle_jtag_gpionum_tdi
,
675 .mode
= COMMAND_CONFIG
,
676 .help
= "gpio chip number (optional) and gpio number for tdi.",
677 .usage
= "[chip] tdi",
681 .handler
= linuxgpiod_handle_jtag_gpionum_srst
,
682 .mode
= COMMAND_CONFIG
,
683 .help
= "gpio chip number (optional) and gpio number for srst.",
684 .usage
= "[chip] srst",
688 .handler
= linuxgpiod_handle_jtag_gpionum_trst
,
689 .mode
= COMMAND_CONFIG
,
690 .help
= "gpio chip number (optional) and gpio number for trst.",
691 .usage
= "[chip] trst",
695 .handler
= linuxgpiod_handle_swd_gpionums
,
696 .mode
= COMMAND_CONFIG
,
697 .help
= "gpio numbers for swclk, swdio. (in that order)",
698 .usage
= "swclk swdio",
702 .handler
= linuxgpiod_handle_swd_gpionum_swclk
,
703 .mode
= COMMAND_CONFIG
,
704 .help
= "gpio chip number (optional) and gpio number for swclk.",
705 .usage
= "[chip] swclk",
709 .handler
= linuxgpiod_handle_swd_gpionum_swdio
,
710 .mode
= COMMAND_CONFIG
,
711 .help
= "gpio chip number (optional) and gpio number for swdio.",
712 .usage
= "[chip] swdio",
715 .name
= "swdio_dir_num",
716 .handler
= linuxgpiod_handle_swd_gpionum_swdio_dir
,
717 .mode
= COMMAND_CONFIG
,
718 .help
= "gpio chip number (optional) and gpio number for swdio_dir.",
719 .usage
= "[chip] swdio_dir",
723 .handler
= linuxgpiod_handle_gpionum_led
,
724 .mode
= COMMAND_CONFIG
,
725 .help
= "gpio chip number (optional) and gpio number for LED.",
726 .usage
= "[chip] led",
730 .handler
= linuxgpiod_handle_gpiochip
,
731 .mode
= COMMAND_CONFIG
,
732 .help
= "number of the gpiochip.",
735 COMMAND_REGISTRATION_DONE
738 static const struct command_registration linuxgpiod_command_handlers
[] = {
740 .name
= "linuxgpiod",
742 .help
= "perform linuxgpiod management",
743 .chain
= linuxgpiod_subcommand_handlers
,
746 COMMAND_REGISTRATION_DONE
749 static const char *const linuxgpiod_transport
[] = { "swd", "jtag", NULL
};
751 static struct jtag_interface linuxgpiod_interface
= {
752 .supported
= DEBUG_CAP_TMS_SEQ
,
753 .execute_queue
= bitbang_execute_queue
,
756 struct adapter_driver linuxgpiod_adapter_driver
= {
757 .name
= "linuxgpiod",
758 .transports
= linuxgpiod_transport
,
759 .commands
= linuxgpiod_command_handlers
,
761 .init
= linuxgpiod_init
,
762 .quit
= linuxgpiod_quit
,
763 .reset
= linuxgpiod_reset
,
765 .jtag_ops
= &linuxgpiod_interface
,
766 .swd_ops
= &bitbang_swd
,
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)