jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / jtag / drivers / linuxgpiod.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3 * Bitbang driver for Linux GPIO descriptors through libgpiod
4 * Copyright (C) 2020 Antonio Borneo <borneo.antonio@gmail.com>
5 *
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>
10 */
11
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15
16 #include <gpiod.h>
17 #include <jtag/interface.h>
18 #include <transport/transport.h>
19 #include "bitbang.h"
20
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;
43
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;
54
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;
65
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;
71
72 /* Bitbang interface read of TDO */
73 static bb_value_t linuxgpiod_read(void)
74 {
75 int retval;
76
77 retval = gpiod_line_get_value(gpiod_tdo);
78 if (retval < 0) {
79 LOG_WARNING("reading tdo failed");
80 return 0;
81 }
82
83 return retval ? BB_HIGH : BB_LOW;
84 }
85
86 /*
87 * Bitbang interface write of TCK, TMS, TDI
88 *
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.
91 */
92 static int linuxgpiod_write(int tck, int tms, int tdi)
93 {
94 static int last_tck;
95 static int last_tms;
96 static int last_tdi;
97
98 static int first_time;
99
100 int retval;
101
102 if (!first_time) {
103 last_tck = !tck;
104 last_tms = !tms;
105 last_tdi = !tdi;
106 first_time = 1;
107 }
108
109 if (tdi != last_tdi) {
110 retval = gpiod_line_set_value(gpiod_tdi, tdi);
111 if (retval < 0)
112 LOG_WARNING("writing tdi failed");
113 }
114
115 if (tms != last_tms) {
116 retval = gpiod_line_set_value(gpiod_tms, tms);
117 if (retval < 0)
118 LOG_WARNING("writing tms failed");
119 }
120
121 /* write clk last */
122 if (tck != last_tck) {
123 retval = gpiod_line_set_value(gpiod_tck, tck);
124 if (retval < 0)
125 LOG_WARNING("writing tck failed");
126 }
127
128 last_tdi = tdi;
129 last_tms = tms;
130 last_tck = tck;
131
132 return ERROR_OK;
133 }
134
135 static int linuxgpiod_swdio_read(void)
136 {
137 int retval;
138
139 retval = gpiod_line_get_value(gpiod_swdio);
140 if (retval < 0) {
141 LOG_WARNING("Fail read swdio");
142 return 0;
143 }
144
145 return retval;
146 }
147
148 static void linuxgpiod_swdio_drive(bool is_output)
149 {
150 int retval;
151
152 /*
153 * FIXME: change direction requires release and re-require the line
154 * https://stackoverflow.com/questions/58735140/
155 * this would change in future libgpiod
156 */
157 gpiod_line_release(gpiod_swdio);
158
159 if (is_output) {
160 if (gpiod_swdio_dir) {
161 retval = gpiod_line_set_value(gpiod_swdio_dir, swdio_dir_is_active_high ? 1 : 0);
162 if (retval < 0)
163 LOG_WARNING("Fail set swdio_dir");
164 }
165 retval = gpiod_line_request_output(gpiod_swdio, "OpenOCD", 1);
166 if (retval < 0)
167 LOG_WARNING("Fail request_output line swdio");
168 } else {
169 retval = gpiod_line_request_input(gpiod_swdio, "OpenOCD");
170 if (retval < 0)
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);
174 if (retval < 0)
175 LOG_WARNING("Fail set swdio_dir");
176 }
177 }
178
179 last_stored = false;
180 swdio_input = !is_output;
181 }
182
183 static int linuxgpiod_swd_write(int swclk, int swdio)
184 {
185 int retval;
186
187 if (!swdio_input) {
188 if (!last_stored || (swdio != last_swdio)) {
189 retval = gpiod_line_set_value(gpiod_swdio, swdio);
190 if (retval < 0)
191 LOG_WARNING("Fail set swdio");
192 }
193 }
194
195 /* write swclk last */
196 if (!last_stored || (swclk != last_swclk)) {
197 retval = gpiod_line_set_value(gpiod_swclk, swclk);
198 if (retval < 0)
199 LOG_WARNING("Fail set swclk");
200 }
201
202 last_swdio = swdio;
203 last_swclk = swclk;
204 last_stored = true;
205
206 return ERROR_OK;
207 }
208
209 static int linuxgpiod_blink(int on)
210 {
211 int retval;
212
213 if (!gpiod_led)
214 return ERROR_OK;
215
216 retval = gpiod_line_set_value(gpiod_led, on);
217 if (retval < 0)
218 LOG_WARNING("Fail set led");
219 return retval;
220 }
221
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,
229 };
230
231 /*
232 * Bitbang interface to manipulate reset lines SRST and TRST
233 *
234 * (1) assert or (0) deassert reset lines
235 */
236 static int linuxgpiod_reset(int trst, int srst)
237 {
238 int retval1 = 0, retval2 = 0;
239
240 LOG_DEBUG("linuxgpiod_reset");
241
242 /* assume active low */
243 if (gpiod_srst) {
244 retval1 = gpiod_line_set_value(gpiod_srst, srst ? 0 : 1);
245 if (retval1 < 0)
246 LOG_WARNING("set srst value failed");
247 }
248
249 /* assume active low */
250 if (gpiod_trst) {
251 retval2 = gpiod_line_set_value(gpiod_trst, trst ? 0 : 1);
252 if (retval2 < 0)
253 LOG_WARNING("set trst value failed");
254 }
255
256 return ((retval1 < 0) || (retval2 < 0)) ? ERROR_FAIL : ERROR_OK;
257 }
258
259 /*
260 * Helper function to determine if gpio number is valid
261 *
262 * Assume here that there will be less than 10000 gpios per gpiochip
263 */
264 static bool is_gpio_valid(int gpio)
265 {
266 return gpio >= 0 && gpio < 10000;
267 }
268
269 static bool linuxgpiod_jtag_mode_possible(void)
270 {
271 if (!is_gpio_valid(tck_gpio))
272 return false;
273 if (!is_gpio_valid(tms_gpio))
274 return false;
275 if (!is_gpio_valid(tdi_gpio))
276 return false;
277 if (!is_gpio_valid(tdo_gpio))
278 return false;
279 return true;
280 }
281
282 static bool linuxgpiod_swd_mode_possible(void)
283 {
284 if (!is_gpio_valid(swclk_gpio))
285 return false;
286 if (!is_gpio_valid(swdio_gpio))
287 return false;
288 return true;
289 }
290
291 static inline void helper_release(struct gpiod_line *line, struct gpiod_chip *chip)
292 {
293 if (line)
294 gpiod_line_release(line);
295 if (chip)
296 gpiod_chip_close(chip);
297 }
298
299 static int linuxgpiod_quit(void)
300 {
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);
311
312 return ERROR_OK;
313 }
314
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)
318 {
319 struct gpiod_line *line;
320 int retval;
321
322 line = gpiod_chip_get_line(gpiod_chip, offset);
323 if (!line) {
324 LOG_ERROR("Error get line %s", label);
325 return NULL;
326 }
327
328 struct gpiod_line_request_config config = {
329 .consumer = "OpenOCD",
330 .request_type = dir,
331 .flags = flags,
332 };
333
334 retval = gpiod_line_request(line, &config, val);
335 if (retval < 0) {
336 LOG_ERROR("Error requesting gpio line %s", label);
337 return NULL;
338 }
339
340 return line;
341 }
342
343 static struct gpiod_line *helper_get_input_line(const char *label,
344 struct gpiod_chip *gpiod_chip, unsigned int offset)
345 {
346 return helper_get_line(label, gpiod_chip, offset, 0,
347 GPIOD_LINE_REQUEST_DIRECTION_INPUT, 0);
348 }
349
350 static struct gpiod_line *helper_get_output_line(const char *label,
351 struct gpiod_chip *gpiod_chip, unsigned int offset, int val)
352 {
353 return helper_get_line(label, gpiod_chip, offset, val,
354 GPIOD_LINE_REQUEST_DIRECTION_OUTPUT, 0);
355 }
356
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)
359 {
360 return helper_get_line(label, gpiod_chip, offset, val,
361 GPIOD_LINE_REQUEST_DIRECTION_OUTPUT, GPIOD_LINE_REQUEST_FLAG_OPEN_DRAIN);
362 }
363
364 static int linuxgpiod_init(void)
365 {
366 LOG_INFO("Linux GPIOD JTAG/SWD bitbang driver");
367
368 bitbang_interface = &linuxgpiod_bitbang;
369
370 /*
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.
374 */
375
376 if (transport_is_jtag()) {
377 if (!linuxgpiod_jtag_mode_possible()) {
378 LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode");
379 goto out_error;
380 }
381
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);
385 goto out_error;
386 }
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);
390 goto out_error;
391 }
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);
395 goto out_error;
396 }
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);
400 goto out_error;
401 }
402
403 gpiod_tdo = helper_get_input_line("tdo", gpiod_chip_tdo, tdo_gpio);
404 if (!gpiod_tdo)
405 goto out_error;
406
407 gpiod_tdi = helper_get_output_line("tdi", gpiod_chip_tdi, tdi_gpio, 0);
408 if (!gpiod_tdi)
409 goto out_error;
410
411 gpiod_tck = helper_get_output_line("tck", gpiod_chip_tck, tck_gpio, 0);
412 if (!gpiod_tck)
413 goto out_error;
414
415 gpiod_tms = helper_get_output_line("tms", gpiod_chip_tms, tms_gpio, 1);
416 if (!gpiod_tms)
417 goto out_error;
418
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);
423 goto out_error;
424 }
425
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);
428 else
429 gpiod_trst = helper_get_output_line("trst", gpiod_chip_trst, trst_gpio, 1);
430
431 if (!gpiod_trst)
432 goto out_error;
433 }
434 }
435
436 if (transport_is_swd()) {
437 if (!linuxgpiod_swd_mode_possible()) {
438 LOG_ERROR("Require swclk and swdio gpio for SWD mode");
439 goto out_error;
440 }
441
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);
445 goto out_error;
446 }
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);
450 goto out_error;
451 }
452
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);
457 goto out_error;
458 }
459 }
460
461 gpiod_swclk = helper_get_output_line("swclk", gpiod_chip_swclk, swclk_gpio, 1);
462 if (!gpiod_swclk)
463 goto out_error;
464
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)
470 goto out_error;
471 }
472
473 gpiod_swdio = helper_get_output_line("swdio", gpiod_chip_swdio, swdio_gpio, 1);
474 if (!gpiod_swdio)
475 goto out_error;
476 }
477
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);
482 goto out_error;
483 }
484
485 if (jtag_get_reset_config() & RESET_SRST_PUSH_PULL)
486 gpiod_srst = helper_get_output_line("srst", gpiod_chip_srst, srst_gpio, 1);
487 else
488 gpiod_srst = helper_get_open_drain_output_line("srst", gpiod_chip_srst, srst_gpio, 1);
489
490 if (!gpiod_srst)
491 goto out_error;
492 }
493
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);
498 goto out_error;
499 }
500
501 gpiod_led = helper_get_output_line("led", gpiod_chip_led, led_gpio, 0);
502 if (!gpiod_led)
503 goto out_error;
504 }
505
506 return ERROR_OK;
507
508 out_error:
509 linuxgpiod_quit();
510
511 return ERROR_JTAG_INIT_FAILED;
512 }
513
514 COMMAND_HELPER(linuxgpiod_helper_gpionum, const char *name, int *chip, int *line)
515 {
516 int i = 0;
517 if (CMD_ARGC > 2)
518 return ERROR_COMMAND_SYNTAX_ERROR;
519 if (CMD_ARGC == 2) {
520 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], *chip);
521 i = 1;
522 }
523 if (CMD_ARGC > 0)
524 COMMAND_PARSE_NUMBER(int, CMD_ARGV[i], *line);
525 command_print(CMD, "LinuxGPIOD %s: chip = %d, num = %d", name, *chip, *line);
526 return ERROR_OK;
527 }
528
529 COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionums)
530 {
531 if (CMD_ARGC == 4) {
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;
538 }
539
540 command_print(CMD,
541 "LinuxGPIOD nums: tck = %d, tms = %d, tdi = %d, tdo = %d",
542 tck_gpio, tms_gpio, tdi_gpio, tdo_gpio);
543
544 return ERROR_OK;
545 }
546
547 COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionum_tck)
548 {
549 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "tck", &tck_gpiochip,
550 &tck_gpio);
551 }
552
553 COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionum_tms)
554 {
555 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "tms", &tms_gpiochip,
556 &tms_gpio);
557 }
558
559 COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionum_tdo)
560 {
561 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "tdo", &tdo_gpiochip,
562 &tdo_gpio);
563 }
564
565 COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionum_tdi)
566 {
567 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "tdi", &tdi_gpiochip,
568 &tdi_gpio);
569 }
570
571 COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionum_srst)
572 {
573 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "srst", &srst_gpiochip,
574 &srst_gpio);
575 }
576
577 COMMAND_HANDLER(linuxgpiod_handle_jtag_gpionum_trst)
578 {
579 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "trst", &trst_gpiochip,
580 &trst_gpio);
581 }
582
583 COMMAND_HANDLER(linuxgpiod_handle_swd_gpionums)
584 {
585 if (CMD_ARGC == 2) {
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;
590 }
591
592 command_print(CMD,
593 "LinuxGPIOD nums: swclk = %d, swdio = %d",
594 swclk_gpio, swdio_gpio);
595
596 return ERROR_OK;
597 }
598
599 COMMAND_HANDLER(linuxgpiod_handle_swd_gpionum_swclk)
600 {
601 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "swclk", &swclk_gpiochip,
602 &swclk_gpio);
603 }
604
605 COMMAND_HANDLER(linuxgpiod_handle_swd_gpionum_swdio)
606 {
607 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "swdio", &swdio_gpiochip,
608 &swdio_gpio);
609 }
610
611 COMMAND_HANDLER(linuxgpiod_handle_swd_gpionum_swdio_dir)
612 {
613 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "swdio_dir", &swdio_dir_gpiochip,
614 &swdio_dir_gpio);
615 }
616
617 COMMAND_HANDLER(linuxgpiod_handle_gpionum_led)
618 {
619 return CALL_COMMAND_HANDLER(linuxgpiod_helper_gpionum, "led", &led_gpiochip,
620 &led_gpio);
621 }
622
623 COMMAND_HANDLER(linuxgpiod_handle_gpiochip)
624 {
625 if (CMD_ARGC == 1) {
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;
637 }
638
639 command_print(CMD, "LinuxGPIOD gpiochip = %d", gpiochip);
640 return ERROR_OK;
641 }
642
643 static const struct command_registration linuxgpiod_subcommand_handlers[] = {
644 {
645 .name = "jtag_nums",
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",
650 },
651 {
652 .name = "tck_num",
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",
657 },
658 {
659 .name = "tms_num",
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",
664 },
665 {
666 .name = "tdo_num",
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",
671 },
672 {
673 .name = "tdi_num",
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",
678 },
679 {
680 .name = "srst_num",
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",
685 },
686 {
687 .name = "trst_num",
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",
692 },
693 {
694 .name = "swd_nums",
695 .handler = linuxgpiod_handle_swd_gpionums,
696 .mode = COMMAND_CONFIG,
697 .help = "gpio numbers for swclk, swdio. (in that order)",
698 .usage = "swclk swdio",
699 },
700 {
701 .name = "swclk_num",
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",
706 },
707 {
708 .name = "swdio_num",
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",
713 },
714 {
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",
720 },
721 {
722 .name = "led_num",
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",
727 },
728 {
729 .name = "gpiochip",
730 .handler = linuxgpiod_handle_gpiochip,
731 .mode = COMMAND_CONFIG,
732 .help = "number of the gpiochip.",
733 .usage = "gpiochip",
734 },
735 COMMAND_REGISTRATION_DONE
736 };
737
738 static const struct command_registration linuxgpiod_command_handlers[] = {
739 {
740 .name = "linuxgpiod",
741 .mode = COMMAND_ANY,
742 .help = "perform linuxgpiod management",
743 .chain = linuxgpiod_subcommand_handlers,
744 .usage = "",
745 },
746 COMMAND_REGISTRATION_DONE
747 };
748
749 static const char *const linuxgpiod_transport[] = { "swd", "jtag", NULL };
750
751 static struct jtag_interface linuxgpiod_interface = {
752 .supported = DEBUG_CAP_TMS_SEQ,
753 .execute_queue = bitbang_execute_queue,
754 };
755
756 struct adapter_driver linuxgpiod_adapter_driver = {
757 .name = "linuxgpiod",
758 .transports = linuxgpiod_transport,
759 .commands = linuxgpiod_command_handlers,
760
761 .init = linuxgpiod_init,
762 .quit = linuxgpiod_quit,
763 .reset = linuxgpiod_reset,
764
765 .jtag_ops = &linuxgpiod_interface,
766 .swd_ops = &bitbang_swd,
767 };

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)