tcl/interface: replace last deprecated commands
[fw/openocd] / src / jtag / drivers / bcm2835gpio.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4  *   Copyright (C) 2013 by Paul Fertser, fercerpav@gmail.com               *
5  *                                                                         *
6  *   Copyright (C) 2012 by Creative Product Design, marc @ cpdesign.com.au *
7  *   Based on at91rm9200.c (c) Anders Larsen                               *
8  *   and RPi GPIO examples by Gert van Loo & Dom                           *
9  ***************************************************************************/
10
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
14
15 #include <jtag/interface.h>
16 #include <transport/transport.h>
17 #include "bitbang.h"
18
19 #include <sys/mman.h>
20
21 uint32_t bcm2835_peri_base = 0x20000000;
22 #define BCM2835_GPIO_BASE       (bcm2835_peri_base + 0x200000) /* GPIO controller */
23
24 #define BCM2835_PADS_GPIO_0_27          (bcm2835_peri_base + 0x100000)
25 #define BCM2835_PADS_GPIO_0_27_OFFSET   (0x2c / 4)
26
27 /* GPIO setup macros */
28 #define MODE_GPIO(g) (*(pio_base+((g)/10))>>(((g)%10)*3) & 7)
29 #define INP_GPIO(g) do { *(pio_base+((g)/10)) &= ~(7<<(((g)%10)*3)); } while (0)
30 #define SET_MODE_GPIO(g, m) do { /* clear the mode bits first, then set as necessary */ \
31                 INP_GPIO(g);                                            \
32                 *(pio_base+((g)/10)) |=  ((m)<<(((g)%10)*3)); } while (0)
33 #define OUT_GPIO(g) SET_MODE_GPIO(g, 1)
34
35 #define GPIO_SET (*(pio_base+7))  /* sets   bits which are 1, ignores bits which are 0 */
36 #define GPIO_CLR (*(pio_base+10)) /* clears bits which are 1, ignores bits which are 0 */
37 #define GPIO_LEV (*(pio_base+13)) /* current level of the pin */
38
39 static int dev_mem_fd;
40 static volatile uint32_t *pio_base;
41
42 static bb_value_t bcm2835gpio_read(void);
43 static int bcm2835gpio_write(int tck, int tms, int tdi);
44
45 static int bcm2835_swdio_read(void);
46 static void bcm2835_swdio_drive(bool is_output);
47 static int bcm2835gpio_swd_write(int swclk, int swdio);
48
49 static int bcm2835gpio_init(void);
50 static int bcm2835gpio_quit(void);
51
52 static struct bitbang_interface bcm2835gpio_bitbang = {
53         .read = bcm2835gpio_read,
54         .write = bcm2835gpio_write,
55         .swdio_read = bcm2835_swdio_read,
56         .swdio_drive = bcm2835_swdio_drive,
57         .swd_write = bcm2835gpio_swd_write,
58         .blink = NULL
59 };
60
61 /* GPIO numbers for each signal. Negative values are invalid */
62 static int tck_gpio = -1;
63 static int tck_gpio_mode;
64 static int tms_gpio = -1;
65 static int tms_gpio_mode;
66 static int tdi_gpio = -1;
67 static int tdi_gpio_mode;
68 static int tdo_gpio = -1;
69 static int tdo_gpio_mode;
70 static int trst_gpio = -1;
71 static int trst_gpio_mode;
72 static int srst_gpio = -1;
73 static int srst_gpio_mode;
74 static int swclk_gpio = -1;
75 static int swclk_gpio_mode;
76 static int swdio_gpio = -1;
77 static int swdio_gpio_mode;
78 static int swdio_dir_gpio = -1;
79 static int swdio_dir_gpio_mode;
80
81 /* Transition delay coefficients */
82 static int speed_coeff = 113714;
83 static int speed_offset = 28;
84 static unsigned int jtag_delay;
85
86 static int is_gpio_valid(int gpio)
87 {
88         return gpio >= 0 && gpio <= 31;
89 }
90
91 static bb_value_t bcm2835gpio_read(void)
92 {
93         return (GPIO_LEV & 1<<tdo_gpio) ? BB_HIGH : BB_LOW;
94 }
95
96 static int bcm2835gpio_write(int tck, int tms, int tdi)
97 {
98         uint32_t set = tck<<tck_gpio | tms<<tms_gpio | tdi<<tdi_gpio;
99         uint32_t clear = !tck<<tck_gpio | !tms<<tms_gpio | !tdi<<tdi_gpio;
100
101         GPIO_SET = set;
102         GPIO_CLR = clear;
103
104         for (unsigned int i = 0; i < jtag_delay; i++)
105                 asm volatile ("");
106
107         return ERROR_OK;
108 }
109
110 static int bcm2835gpio_swd_write(int swclk, int swdio)
111 {
112         uint32_t set = swclk << swclk_gpio | swdio << swdio_gpio;
113         uint32_t clear = !swclk << swclk_gpio | !swdio << swdio_gpio;
114
115         GPIO_SET = set;
116         GPIO_CLR = clear;
117
118         for (unsigned int i = 0; i < jtag_delay; i++)
119                 asm volatile ("");
120
121         return ERROR_OK;
122 }
123
124 /* (1) assert or (0) deassert reset lines */
125 static int bcm2835gpio_reset(int trst, int srst)
126 {
127         uint32_t set = 0;
128         uint32_t clear = 0;
129
130         if (is_gpio_valid(trst_gpio)) {
131                 set |= !trst<<trst_gpio;
132                 clear |= trst<<trst_gpio;
133         }
134
135         if (is_gpio_valid(srst_gpio)) {
136                 set |= !srst<<srst_gpio;
137                 clear |= srst<<srst_gpio;
138         }
139
140         GPIO_SET = set;
141         GPIO_CLR = clear;
142
143         return ERROR_OK;
144 }
145
146 static void bcm2835_swdio_drive(bool is_output)
147 {
148         if (is_gpio_valid(swdio_dir_gpio)) {
149                 if (is_output) {
150                         GPIO_SET = 1 << swdio_dir_gpio;
151                         OUT_GPIO(swdio_gpio);
152                 } else {
153                         INP_GPIO(swdio_gpio);
154                         GPIO_CLR = 1 << swdio_dir_gpio;
155                 }
156         } else {
157                 if (is_output)
158                         OUT_GPIO(swdio_gpio);
159                 else
160                         INP_GPIO(swdio_gpio);
161         }
162 }
163
164 static int bcm2835_swdio_read(void)
165 {
166         return !!(GPIO_LEV & 1 << swdio_gpio);
167 }
168
169 static int bcm2835gpio_khz(int khz, int *jtag_speed)
170 {
171         if (!khz) {
172                 LOG_DEBUG("RCLK not supported");
173                 return ERROR_FAIL;
174         }
175         *jtag_speed = speed_coeff/khz - speed_offset;
176         if (*jtag_speed < 0)
177                 *jtag_speed = 0;
178         return ERROR_OK;
179 }
180
181 static int bcm2835gpio_speed_div(int speed, int *khz)
182 {
183         *khz = speed_coeff/(speed + speed_offset);
184         return ERROR_OK;
185 }
186
187 static int bcm2835gpio_speed(int speed)
188 {
189         jtag_delay = speed;
190         return ERROR_OK;
191 }
192
193 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionums)
194 {
195         if (CMD_ARGC == 4) {
196                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
197                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tms_gpio);
198                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], tdi_gpio);
199                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], tdo_gpio);
200         } else if (CMD_ARGC != 0) {
201                 return ERROR_COMMAND_SYNTAX_ERROR;
202         }
203
204         command_print(CMD,
205                         "BCM2835 GPIO config: tck = %d, tms = %d, tdi = %d, tdo = %d",
206                         tck_gpio, tms_gpio, tdi_gpio, tdo_gpio);
207
208         return ERROR_OK;
209 }
210
211 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tck)
212 {
213         if (CMD_ARGC == 1)
214                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
215
216         command_print(CMD, "BCM2835 GPIO config: tck = %d", tck_gpio);
217         return ERROR_OK;
218 }
219
220 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tms)
221 {
222         if (CMD_ARGC == 1)
223                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tms_gpio);
224
225         command_print(CMD, "BCM2835 GPIO config: tms = %d", tms_gpio);
226         return ERROR_OK;
227 }
228
229 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tdo)
230 {
231         if (CMD_ARGC == 1)
232                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdo_gpio);
233
234         command_print(CMD, "BCM2835 GPIO config: tdo = %d", tdo_gpio);
235         return ERROR_OK;
236 }
237
238 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tdi)
239 {
240         if (CMD_ARGC == 1)
241                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdi_gpio);
242
243         command_print(CMD, "BCM2835 GPIO config: tdi = %d", tdi_gpio);
244         return ERROR_OK;
245 }
246
247 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_srst)
248 {
249         if (CMD_ARGC == 1)
250                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], srst_gpio);
251
252         command_print(CMD, "BCM2835 GPIO config: srst = %d", srst_gpio);
253         return ERROR_OK;
254 }
255
256 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_trst)
257 {
258         if (CMD_ARGC == 1)
259                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], trst_gpio);
260
261         command_print(CMD, "BCM2835 GPIO config: trst = %d", trst_gpio);
262         return ERROR_OK;
263 }
264
265 COMMAND_HANDLER(bcm2835gpio_handle_swd_gpionums)
266 {
267         if (CMD_ARGC == 2) {
268                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
269                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], swdio_gpio);
270         } else if (CMD_ARGC != 0) {
271                 return ERROR_COMMAND_SYNTAX_ERROR;
272         }
273
274         command_print(CMD,
275                         "BCM2835 GPIO nums: swclk = %d, swdio = %d",
276                         swclk_gpio, swdio_gpio);
277
278         return ERROR_OK;
279 }
280
281 COMMAND_HANDLER(bcm2835gpio_handle_swd_gpionum_swclk)
282 {
283         if (CMD_ARGC == 1)
284                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
285
286         command_print(CMD, "BCM2835 num: swclk = %d", swclk_gpio);
287         return ERROR_OK;
288 }
289
290 COMMAND_HANDLER(bcm2835gpio_handle_swd_gpionum_swdio)
291 {
292         if (CMD_ARGC == 1)
293                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swdio_gpio);
294
295         command_print(CMD, "BCM2835 num: swdio = %d", swdio_gpio);
296         return ERROR_OK;
297 }
298
299 COMMAND_HANDLER(bcm2835gpio_handle_swd_dir_gpionum_swdio)
300 {
301         if (CMD_ARGC == 1)
302                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swdio_dir_gpio);
303
304         command_print(CMD, "BCM2835 num: swdio_dir = %d", swdio_dir_gpio);
305         return ERROR_OK;
306 }
307
308 COMMAND_HANDLER(bcm2835gpio_handle_speed_coeffs)
309 {
310         if (CMD_ARGC == 2) {
311                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], speed_coeff);
312                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], speed_offset);
313         }
314
315         command_print(CMD, "BCM2835 GPIO: speed_coeffs = %d, speed_offset = %d",
316                                   speed_coeff, speed_offset);
317         return ERROR_OK;
318 }
319
320 COMMAND_HANDLER(bcm2835gpio_handle_peripheral_base)
321 {
322         if (CMD_ARGC == 1)
323                 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], bcm2835_peri_base);
324
325         command_print(CMD, "BCM2835 GPIO: peripheral_base = 0x%08x",
326                                   bcm2835_peri_base);
327         return ERROR_OK;
328 }
329
330 static const struct command_registration bcm2835gpio_subcommand_handlers[] = {
331         {
332                 .name = "jtag_nums",
333                 .handler = &bcm2835gpio_handle_jtag_gpionums,
334                 .mode = COMMAND_CONFIG,
335                 .help = "gpio numbers for tck, tms, tdi, tdo. (in that order)",
336                 .usage = "[tck tms tdi tdo]",
337         },
338         {
339                 .name = "tck_num",
340                 .handler = &bcm2835gpio_handle_jtag_gpionum_tck,
341                 .mode = COMMAND_CONFIG,
342                 .help = "gpio number for tck.",
343                 .usage = "[tck]",
344         },
345         {
346                 .name = "tms_num",
347                 .handler = &bcm2835gpio_handle_jtag_gpionum_tms,
348                 .mode = COMMAND_CONFIG,
349                 .help = "gpio number for tms.",
350                 .usage = "[tms]",
351         },
352         {
353                 .name = "tdo_num",
354                 .handler = &bcm2835gpio_handle_jtag_gpionum_tdo,
355                 .mode = COMMAND_CONFIG,
356                 .help = "gpio number for tdo.",
357                 .usage = "[tdo]",
358         },
359         {
360                 .name = "tdi_num",
361                 .handler = &bcm2835gpio_handle_jtag_gpionum_tdi,
362                 .mode = COMMAND_CONFIG,
363                 .help = "gpio number for tdi.",
364                 .usage = "[tdi]",
365         },
366         {
367                 .name = "swd_nums",
368                 .handler = &bcm2835gpio_handle_swd_gpionums,
369                 .mode = COMMAND_CONFIG,
370                 .help = "gpio numbers for swclk, swdio. (in that order)",
371                 .usage = "[swclk swdio]",
372         },
373         {
374                 .name = "swclk_num",
375                 .handler = &bcm2835gpio_handle_swd_gpionum_swclk,
376                 .mode = COMMAND_CONFIG,
377                 .help = "gpio number for swclk.",
378                 .usage = "[swclk]",
379         },
380         {
381                 .name = "swdio_num",
382                 .handler = &bcm2835gpio_handle_swd_gpionum_swdio,
383                 .mode = COMMAND_CONFIG,
384                 .help = "gpio number for swdio.",
385                 .usage = "[swdio]",
386         },
387         {
388                 .name = "swdio_dir_num",
389                 .handler = &bcm2835gpio_handle_swd_dir_gpionum_swdio,
390                 .mode = COMMAND_CONFIG,
391                 .help = "gpio number for swdio direction control pin (set=output mode, clear=input mode)",
392                 .usage = "[swdio_dir]",
393         },
394         {
395                 .name = "srst_num",
396                 .handler = &bcm2835gpio_handle_jtag_gpionum_srst,
397                 .mode = COMMAND_CONFIG,
398                 .help = "gpio number for srst.",
399                 .usage = "[srst]",
400         },
401         {
402                 .name = "trst_num",
403                 .handler = &bcm2835gpio_handle_jtag_gpionum_trst,
404                 .mode = COMMAND_CONFIG,
405                 .help = "gpio number for trst.",
406                 .usage = "[trst]",
407         },
408         {
409                 .name = "speed_coeffs",
410                 .handler = &bcm2835gpio_handle_speed_coeffs,
411                 .mode = COMMAND_CONFIG,
412                 .help = "SPEED_COEFF and SPEED_OFFSET for delay calculations.",
413                 .usage = "[SPEED_COEFF SPEED_OFFSET]",
414         },
415         {
416                 .name = "peripheral_base",
417                 .handler = &bcm2835gpio_handle_peripheral_base,
418                 .mode = COMMAND_CONFIG,
419                 .help = "peripheral base to access GPIOs (RPi1 0x20000000, RPi2 0x3F000000).",
420                 .usage = "[base]",
421         },
422
423         COMMAND_REGISTRATION_DONE
424 };
425
426 static const struct command_registration bcm2835gpio_command_handlers[] = {
427         {
428                 .name = "bcm2835gpio",
429                 .mode = COMMAND_ANY,
430                 .help = "perform bcm2835gpio management",
431                 .chain = bcm2835gpio_subcommand_handlers,
432                 .usage = "",
433         },
434         COMMAND_REGISTRATION_DONE
435 };
436
437 static const char * const bcm2835_transports[] = { "jtag", "swd", NULL };
438
439 static struct jtag_interface bcm2835gpio_interface = {
440         .supported = DEBUG_CAP_TMS_SEQ,
441         .execute_queue = bitbang_execute_queue,
442 };
443
444 struct adapter_driver bcm2835gpio_adapter_driver = {
445         .name = "bcm2835gpio",
446         .transports = bcm2835_transports,
447         .commands = bcm2835gpio_command_handlers,
448
449         .init = bcm2835gpio_init,
450         .quit = bcm2835gpio_quit,
451         .reset = bcm2835gpio_reset,
452         .speed = bcm2835gpio_speed,
453         .khz = bcm2835gpio_khz,
454         .speed_div = bcm2835gpio_speed_div,
455
456         .jtag_ops = &bcm2835gpio_interface,
457         .swd_ops = &bitbang_swd,
458 };
459
460 static bool bcm2835gpio_jtag_mode_possible(void)
461 {
462         if (!is_gpio_valid(tck_gpio))
463                 return 0;
464         if (!is_gpio_valid(tms_gpio))
465                 return 0;
466         if (!is_gpio_valid(tdi_gpio))
467                 return 0;
468         if (!is_gpio_valid(tdo_gpio))
469                 return 0;
470         return 1;
471 }
472
473 static bool bcm2835gpio_swd_mode_possible(void)
474 {
475         if (!is_gpio_valid(swclk_gpio))
476                 return 0;
477         if (!is_gpio_valid(swdio_gpio))
478                 return 0;
479         return 1;
480 }
481
482 static int bcm2835gpio_init(void)
483 {
484         bitbang_interface = &bcm2835gpio_bitbang;
485
486         LOG_INFO("BCM2835 GPIO JTAG/SWD bitbang driver");
487
488         if (transport_is_jtag() && !bcm2835gpio_jtag_mode_possible()) {
489                 LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode");
490                 return ERROR_JTAG_INIT_FAILED;
491         }
492
493         if (transport_is_swd() && !bcm2835gpio_swd_mode_possible()) {
494                 LOG_ERROR("Require swclk and swdio gpio for SWD mode");
495                 return ERROR_JTAG_INIT_FAILED;
496         }
497
498         dev_mem_fd = open("/dev/gpiomem", O_RDWR | O_SYNC);
499         if (dev_mem_fd < 0) {
500                 LOG_DEBUG("Cannot open /dev/gpiomem, fallback to /dev/mem");
501                 dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
502         }
503         if (dev_mem_fd < 0) {
504                 LOG_ERROR("open: %s", strerror(errno));
505                 return ERROR_JTAG_INIT_FAILED;
506         }
507
508         pio_base = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
509                                 MAP_SHARED, dev_mem_fd, BCM2835_GPIO_BASE);
510
511         if (pio_base == MAP_FAILED) {
512                 LOG_ERROR("mmap: %s", strerror(errno));
513                 close(dev_mem_fd);
514                 return ERROR_JTAG_INIT_FAILED;
515         }
516
517         static volatile uint32_t *pads_base;
518         pads_base = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
519                                 MAP_SHARED, dev_mem_fd, BCM2835_PADS_GPIO_0_27);
520
521         if (pads_base == MAP_FAILED) {
522                 LOG_ERROR("mmap: %s", strerror(errno));
523                 close(dev_mem_fd);
524                 return ERROR_JTAG_INIT_FAILED;
525         }
526
527         /* set 4mA drive strength, slew rate limited, hysteresis on */
528         pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000008 + 1;
529
530         /*
531          * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
532          * as outputs.  Drive TDI and TCK low, and TMS/TRST/SRST high.
533          */
534         if (transport_is_jtag()) {
535                 tdo_gpio_mode = MODE_GPIO(tdo_gpio);
536                 tdi_gpio_mode = MODE_GPIO(tdi_gpio);
537                 tck_gpio_mode = MODE_GPIO(tck_gpio);
538                 tms_gpio_mode = MODE_GPIO(tms_gpio);
539
540                 INP_GPIO(tdo_gpio);
541
542                 GPIO_CLR = 1<<tdi_gpio | 1<<tck_gpio;
543                 GPIO_SET = 1<<tms_gpio;
544
545                 OUT_GPIO(tdi_gpio);
546                 OUT_GPIO(tck_gpio);
547                 OUT_GPIO(tms_gpio);
548
549                 if (is_gpio_valid(trst_gpio)) {
550                         trst_gpio_mode = MODE_GPIO(trst_gpio);
551                         GPIO_SET = 1 << trst_gpio;
552                         OUT_GPIO(trst_gpio);
553                 }
554         }
555
556         if (transport_is_swd()) {
557                 /* Make buffer an output before the GPIO connected to it */
558                 if (is_gpio_valid(swdio_dir_gpio)) {
559                         swdio_dir_gpio_mode = MODE_GPIO(swdio_dir_gpio);
560                         GPIO_SET = 1 << swdio_dir_gpio;
561                         OUT_GPIO(swdio_dir_gpio);
562                 }
563
564                 swclk_gpio_mode = MODE_GPIO(swclk_gpio);
565                 swdio_gpio_mode = MODE_GPIO(swdio_gpio);
566
567                 GPIO_CLR = 1<<swdio_gpio | 1<<swclk_gpio;
568
569                 OUT_GPIO(swclk_gpio);
570                 OUT_GPIO(swdio_gpio);
571         }
572
573         if (is_gpio_valid(srst_gpio)) {
574                 srst_gpio_mode = MODE_GPIO(srst_gpio);
575                 GPIO_SET = 1 << srst_gpio;
576                 OUT_GPIO(srst_gpio);
577         }
578
579         LOG_DEBUG("saved pinmux settings: tck %d tms %d tdi %d "
580                   "tdo %d trst %d srst %d", tck_gpio_mode, tms_gpio_mode,
581                   tdi_gpio_mode, tdo_gpio_mode, trst_gpio_mode, srst_gpio_mode);
582
583         return ERROR_OK;
584 }
585
586 static int bcm2835gpio_quit(void)
587 {
588         if (transport_is_jtag()) {
589                 SET_MODE_GPIO(tdo_gpio, tdo_gpio_mode);
590                 SET_MODE_GPIO(tdi_gpio, tdi_gpio_mode);
591                 SET_MODE_GPIO(tck_gpio, tck_gpio_mode);
592                 SET_MODE_GPIO(tms_gpio, tms_gpio_mode);
593                 if (is_gpio_valid(trst_gpio))
594                         SET_MODE_GPIO(trst_gpio, trst_gpio_mode);
595         }
596
597         if (transport_is_swd()) {
598                 SET_MODE_GPIO(swclk_gpio, swclk_gpio_mode);
599                 SET_MODE_GPIO(swdio_gpio, swdio_gpio_mode);
600         }
601
602         if (is_gpio_valid(srst_gpio))
603                 SET_MODE_GPIO(srst_gpio, srst_gpio_mode);
604
605         if (is_gpio_valid(swdio_dir_gpio))
606                 SET_MODE_GPIO(swdio_dir_gpio, swdio_dir_gpio_mode);
607
608         return ERROR_OK;
609 }