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