bitbang: remove superfluous switch between jtag and swd
[fw/openocd] / src / jtag / drivers / sysfsgpio.c
1 /***************************************************************************
2  *   Copyright (C) 2012 by Creative Product Design, marc @ cpdesign.com.au *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
16  ***************************************************************************/
17
18 /* 2014-12: Addition of the SWD protocol support is based on the initial work
19  * on bcm2835gpio.c by Paul Fertser and modifications by Jean-Christian de Rivaz. */
20
21 /**
22  * @file
23  * This driver implements a bitbang jtag interface using gpio lines via
24  * sysfs.
25  * The aim of this driver implementation is use system GPIOs but avoid the
26  * need for a additional kernel driver.
27  * (Note memory mapped IO is another option, however it doesn't mix well with
28  * the kernel gpiolib driver - which makes sense I guess.)
29  *
30  * A gpio is required for tck, tms, tdi and tdo. One or both of srst and trst
31  * must be also be specified. The required jtag gpios are specified via the
32  * sysfsgpio_jtag_nums command or the relevant sysfsgpio_XXX_num commang.
33  * The srst and trst gpios are set via the sysfsgpio_srst_num and
34  * sysfsgpio_trst_num respectively. GPIO numbering follows the kernel
35  * convention of starting from 0.
36  *
37  * The gpios should not be in use by another entity, and must not be requested
38  * by a kernel driver without also being exported by it (otherwise they can't
39  * be exported by sysfs).
40  *
41  * The sysfs gpio interface can only manipulate one gpio at a time, so the
42  * bitbang write handler remembers the last state for tck, tms, tdi to avoid
43  * superfluous writes.
44  * For speed the sysfs "value" entry is opened at init and held open.
45  * This results in considerable gains over open-write-close (45s vs 900s)
46  *
47  * Further work could address:
48  *  -srst and trst open drain/ push pull
49  *  -configurable active high/low for srst & trst
50  */
51 #ifdef HAVE_CONFIG_H
52 #include "config.h"
53 #endif
54
55 #include <helper/time_support.h>
56 #include <jtag/interface.h>
57 #include "bitbang.h"
58
59 /*
60  * Helper func to determine if gpio number valid
61  *
62  * Assume here that there will be less than 10000 gpios on a system
63  */
64 static bool is_gpio_valid(int gpio)
65 {
66         return gpio >= 0 && gpio < 10000;
67 }
68
69 /*
70  * Helper func to open, write to and close a file
71  * name and valstr must be null terminated.
72  *
73  * Returns negative on failure.
74  */
75 static int open_write_close(const char *name, const char *valstr)
76 {
77         int ret;
78         int fd = open(name, O_WRONLY);
79         if (fd < 0)
80                 return fd;
81
82         ret = write(fd, valstr, strlen(valstr));
83         close(fd);
84
85         return ret;
86 }
87
88 /*
89  * Helper func to unexport gpio from sysfs
90  */
91 static void unexport_sysfs_gpio(int gpio)
92 {
93         char gpiostr[5];
94
95         if (!is_gpio_valid(gpio))
96                 return;
97
98         snprintf(gpiostr, sizeof(gpiostr), "%d", gpio);
99         if (open_write_close("/sys/class/gpio/unexport", gpiostr) < 0)
100                 LOG_ERROR("Couldn't unexport gpio %d", gpio);
101 }
102
103 /*
104  * Exports and sets up direction for gpio.
105  * If the gpio is an output, it is initialized according to init_high,
106  * otherwise it is ignored.
107  *
108  * If the gpio is already exported we just show a warning and continue; if
109  * openocd happened to crash (or was killed by user) then the gpios will not
110  * have been cleaned up.
111  */
112 static int setup_sysfs_gpio(int gpio, int is_output, int init_high)
113 {
114         struct timeval timeout, now;
115         char buf[40];
116         char gpiostr[5];
117         int ret;
118
119         if (!is_gpio_valid(gpio))
120                 return ERROR_OK;
121
122         snprintf(gpiostr, sizeof(gpiostr), "%d", gpio);
123         ret = open_write_close("/sys/class/gpio/export", gpiostr);
124         if (ret < 0) {
125                 if (errno == EBUSY) {
126                         LOG_WARNING("gpio %d is already exported", gpio);
127                 } else {
128                         LOG_ERROR("Couldn't export gpio %d", gpio);
129                         perror("sysfsgpio: ");
130                         return ERROR_FAIL;
131                 }
132         }
133
134         gettimeofday(&timeout, NULL);
135         timeval_add_time(&timeout, 0, 500000);
136
137         snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/direction", gpio);
138         for (;;) {
139                 ret = open_write_close(buf, is_output ? (init_high ? "high" : "low") : "in");
140                 if (ret >= 0 || errno != EACCES)
141                         break;
142                 gettimeofday(&now, NULL);
143                 if (timeval_compare(&now, &timeout) >= 0)
144                         break;
145                 jtag_sleep(10000);
146         }
147         if (ret < 0) {
148                 LOG_ERROR("Couldn't set direction for gpio %d", gpio);
149                 perror("sysfsgpio: ");
150                 unexport_sysfs_gpio(gpio);
151                 return ERROR_FAIL;
152         }
153
154         snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", gpio);
155         for (;;) {
156                 ret = open(buf, O_RDWR | O_NONBLOCK | O_SYNC);
157                 if (ret >= 0 || errno != EACCES)
158                         break;
159                 gettimeofday(&now, NULL);
160                 if (timeval_compare(&now, &timeout) >= 0)
161                         break;
162                 jtag_sleep(10000);
163         }
164         if (ret < 0) {
165                 LOG_ERROR("Couldn't open value for gpio %d", gpio);
166                 perror("sysfsgpio: ");
167                 unexport_sysfs_gpio(gpio);
168         }
169
170         return ret;
171 }
172
173 /* gpio numbers for each gpio. Negative values are invalid */
174 static int tck_gpio = -1;
175 static int tms_gpio = -1;
176 static int tdi_gpio = -1;
177 static int tdo_gpio = -1;
178 static int trst_gpio = -1;
179 static int srst_gpio = -1;
180 static int swclk_gpio = -1;
181 static int swdio_gpio = -1;
182
183 /*
184  * file descriptors for /sys/class/gpio/gpioXX/value
185  * Set up during init.
186  */
187 static int tck_fd = -1;
188 static int tms_fd = -1;
189 static int tdi_fd = -1;
190 static int tdo_fd = -1;
191 static int trst_fd = -1;
192 static int srst_fd = -1;
193 static int swclk_fd = -1;
194 static int swdio_fd = -1;
195
196 static int last_swclk;
197 static int last_swdio;
198 static bool last_stored;
199 static bool swdio_input;
200
201 static void sysfsgpio_swdio_drive(bool is_output)
202 {
203         char buf[40];
204         int ret;
205
206         snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/direction", swdio_gpio);
207         ret = open_write_close(buf, is_output ? "high" : "in");
208         if (ret < 0) {
209                 LOG_ERROR("Couldn't set direction for gpio %d", swdio_gpio);
210                 perror("sysfsgpio: ");
211         }
212
213         last_stored = false;
214         swdio_input = !is_output;
215 }
216
217 static int sysfsgpio_swdio_read(void)
218 {
219         char buf[1];
220
221         /* important to seek to signal sysfs of new read */
222         lseek(swdio_fd, 0, SEEK_SET);
223         int ret = read(swdio_fd, &buf, sizeof(buf));
224
225         if (ret < 0) {
226                 LOG_WARNING("reading swdio failed");
227                 return 0;
228         }
229
230         return buf[0] != '0';
231 }
232
233 static void sysfsgpio_swdio_write(int swclk, int swdio)
234 {
235         const char one[] = "1";
236         const char zero[] = "0";
237
238         size_t bytes_written;
239
240         if (!swdio_input) {
241                 if (!last_stored || (swdio != last_swdio)) {
242                         bytes_written = write(swdio_fd, swdio ? &one : &zero, 1);
243                         if (bytes_written != 1)
244                                 LOG_WARNING("writing swdio failed");
245                 }
246         }
247
248         /* write swclk last */
249         if (!last_stored || (swclk != last_swclk)) {
250                 bytes_written = write(swclk_fd, swclk ? &one : &zero, 1);
251                 if (bytes_written != 1)
252                         LOG_WARNING("writing swclk failed");
253         }
254
255         last_swdio = swdio;
256         last_swclk = swclk;
257         last_stored = true;
258 }
259
260 /*
261  * Bitbang interface read of TDO
262  *
263  * The sysfs value will read back either '0' or '1'. The trick here is to call
264  * lseek to bypass buffering in the sysfs kernel driver.
265  */
266 static bb_value_t sysfsgpio_read(void)
267 {
268         char buf[1];
269
270         /* important to seek to signal sysfs of new read */
271         lseek(tdo_fd, 0, SEEK_SET);
272         int ret = read(tdo_fd, &buf, sizeof(buf));
273
274         if (ret < 0) {
275                 LOG_WARNING("reading tdo failed");
276                 return 0;
277         }
278
279         return buf[0] == '0' ? BB_LOW : BB_HIGH;
280 }
281
282 /*
283  * Bitbang interface write of TCK, TMS, TDI
284  *
285  * Seeing as this is the only function where the outputs are changed,
286  * we can cache the old value to avoid needlessly writing it.
287  */
288 static int sysfsgpio_write(int tck, int tms, int tdi)
289 {
290         if (swd_mode) {
291                 sysfsgpio_swdio_write(tck, tdi);
292                 return ERROR_OK;
293         }
294
295         const char one[] = "1";
296         const char zero[] = "0";
297
298         static int last_tck;
299         static int last_tms;
300         static int last_tdi;
301
302         static int first_time;
303         size_t bytes_written;
304
305         if (!first_time) {
306                 last_tck = !tck;
307                 last_tms = !tms;
308                 last_tdi = !tdi;
309                 first_time = 1;
310         }
311
312         if (tdi != last_tdi) {
313                 bytes_written = write(tdi_fd, tdi ? &one : &zero, 1);
314                 if (bytes_written != 1)
315                         LOG_WARNING("writing tdi failed");
316         }
317
318         if (tms != last_tms) {
319                 bytes_written = write(tms_fd, tms ? &one : &zero, 1);
320                 if (bytes_written != 1)
321                         LOG_WARNING("writing tms failed");
322         }
323
324         /* write clk last */
325         if (tck != last_tck) {
326                 bytes_written = write(tck_fd, tck ? &one : &zero, 1);
327                 if (bytes_written != 1)
328                         LOG_WARNING("writing tck failed");
329         }
330
331         last_tdi = tdi;
332         last_tms = tms;
333         last_tck = tck;
334
335         return ERROR_OK;
336 }
337
338 /*
339  * Bitbang interface to manipulate reset lines SRST and TRST
340  *
341  * (1) assert or (0) deassert reset lines
342  */
343 static int sysfsgpio_reset(int trst, int srst)
344 {
345         LOG_DEBUG("sysfsgpio_reset");
346         const char one[] = "1";
347         const char zero[] = "0";
348         size_t bytes_written;
349
350         /* assume active low */
351         if (srst_fd >= 0) {
352                 bytes_written = write(srst_fd, srst ? &zero : &one, 1);
353                 if (bytes_written != 1)
354                         LOG_WARNING("writing srst failed");
355         }
356
357         /* assume active low */
358         if (trst_fd >= 0) {
359                 bytes_written = write(trst_fd, trst ? &zero : &one, 1);
360                 if (bytes_written != 1)
361                         LOG_WARNING("writing trst failed");
362         }
363
364         return ERROR_OK;
365 }
366
367 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionums)
368 {
369         if (CMD_ARGC == 4) {
370                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
371                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tms_gpio);
372                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], tdi_gpio);
373                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], tdo_gpio);
374         } else if (CMD_ARGC != 0) {
375                 return ERROR_COMMAND_SYNTAX_ERROR;
376         }
377
378         command_print(CMD,
379                         "SysfsGPIO nums: tck = %d, tms = %d, tdi = %d, tdo = %d",
380                         tck_gpio, tms_gpio, tdi_gpio, tdo_gpio);
381
382         return ERROR_OK;
383 }
384
385 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tck)
386 {
387         if (CMD_ARGC == 1)
388                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
389
390         command_print(CMD, "SysfsGPIO num: tck = %d", tck_gpio);
391         return ERROR_OK;
392 }
393
394 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tms)
395 {
396         if (CMD_ARGC == 1)
397                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tms_gpio);
398
399         command_print(CMD, "SysfsGPIO num: tms = %d", tms_gpio);
400         return ERROR_OK;
401 }
402
403 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tdo)
404 {
405         if (CMD_ARGC == 1)
406                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdo_gpio);
407
408         command_print(CMD, "SysfsGPIO num: tdo = %d", tdo_gpio);
409         return ERROR_OK;
410 }
411
412 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tdi)
413 {
414         if (CMD_ARGC == 1)
415                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdi_gpio);
416
417         command_print(CMD, "SysfsGPIO num: tdi = %d", tdi_gpio);
418         return ERROR_OK;
419 }
420
421 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_srst)
422 {
423         if (CMD_ARGC == 1)
424                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], srst_gpio);
425
426         command_print(CMD, "SysfsGPIO num: srst = %d", srst_gpio);
427         return ERROR_OK;
428 }
429
430 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_trst)
431 {
432         if (CMD_ARGC == 1)
433                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], trst_gpio);
434
435         command_print(CMD, "SysfsGPIO num: trst = %d", trst_gpio);
436         return ERROR_OK;
437 }
438
439 COMMAND_HANDLER(sysfsgpio_handle_swd_gpionums)
440 {
441         if (CMD_ARGC == 2) {
442                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
443                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], swdio_gpio);
444         } else if (CMD_ARGC != 0) {
445                 return ERROR_COMMAND_SYNTAX_ERROR;
446         }
447
448         command_print(CMD,
449                         "SysfsGPIO nums: swclk = %d, swdio = %d",
450                         swclk_gpio, swdio_gpio);
451
452         return ERROR_OK;
453 }
454
455 COMMAND_HANDLER(sysfsgpio_handle_swd_gpionum_swclk)
456 {
457         if (CMD_ARGC == 1)
458                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
459
460         command_print(CMD, "SysfsGPIO num: swclk = %d", swclk_gpio);
461         return ERROR_OK;
462 }
463
464 COMMAND_HANDLER(sysfsgpio_handle_swd_gpionum_swdio)
465 {
466         if (CMD_ARGC == 1)
467                 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swdio_gpio);
468
469         command_print(CMD, "SysfsGPIO num: swdio = %d", swdio_gpio);
470         return ERROR_OK;
471 }
472
473 static const struct command_registration sysfsgpio_command_handlers[] = {
474         {
475                 .name = "sysfsgpio_jtag_nums",
476                 .handler = &sysfsgpio_handle_jtag_gpionums,
477                 .mode = COMMAND_CONFIG,
478                 .help = "gpio numbers for tck, tms, tdi, tdo. (in that order)",
479                 .usage = "[tck tms tdi tdo]",
480         },
481         {
482                 .name = "sysfsgpio_tck_num",
483                 .handler = &sysfsgpio_handle_jtag_gpionum_tck,
484                 .mode = COMMAND_CONFIG,
485                 .help = "gpio number for tck.",
486                 .usage = "[tck]",
487         },
488         {
489                 .name = "sysfsgpio_tms_num",
490                 .handler = &sysfsgpio_handle_jtag_gpionum_tms,
491                 .mode = COMMAND_CONFIG,
492                 .help = "gpio number for tms.",
493                 .usage = "[tms]",
494         },
495         {
496                 .name = "sysfsgpio_tdo_num",
497                 .handler = &sysfsgpio_handle_jtag_gpionum_tdo,
498                 .mode = COMMAND_CONFIG,
499                 .help = "gpio number for tdo.",
500                 .usage = "[tdo]",
501         },
502         {
503                 .name = "sysfsgpio_tdi_num",
504                 .handler = &sysfsgpio_handle_jtag_gpionum_tdi,
505                 .mode = COMMAND_CONFIG,
506                 .help = "gpio number for tdi.",
507                 .usage = "[tdi]",
508         },
509         {
510                 .name = "sysfsgpio_srst_num",
511                 .handler = &sysfsgpio_handle_jtag_gpionum_srst,
512                 .mode = COMMAND_CONFIG,
513                 .help = "gpio number for srst.",
514                 .usage = "[srst]",
515         },
516         {
517                 .name = "sysfsgpio_trst_num",
518                 .handler = &sysfsgpio_handle_jtag_gpionum_trst,
519                 .mode = COMMAND_CONFIG,
520                 .help = "gpio number for trst.",
521                 .usage = "[trst]",
522         },
523         {
524                 .name = "sysfsgpio_swd_nums",
525                 .handler = &sysfsgpio_handle_swd_gpionums,
526                 .mode = COMMAND_CONFIG,
527                 .help = "gpio numbers for swclk, swdio. (in that order)",
528                 .usage = "[swclk swdio]",
529         },
530         {
531                 .name = "sysfsgpio_swclk_num",
532                 .handler = &sysfsgpio_handle_swd_gpionum_swclk,
533                 .mode = COMMAND_CONFIG,
534                 .help = "gpio number for swclk.",
535                 .usage = "[swclk]",
536         },
537         {
538                 .name = "sysfsgpio_swdio_num",
539                 .handler = &sysfsgpio_handle_swd_gpionum_swdio,
540                 .mode = COMMAND_CONFIG,
541                 .help = "gpio number for swdio.",
542                 .usage = "[swdio]",
543         },
544         COMMAND_REGISTRATION_DONE
545 };
546
547 static int sysfsgpio_init(void);
548 static int sysfsgpio_quit(void);
549
550 static const char * const sysfsgpio_transports[] = { "jtag", "swd", NULL };
551
552 static struct jtag_interface sysfsgpio_interface = {
553         .supported = DEBUG_CAP_TMS_SEQ,
554         .execute_queue = bitbang_execute_queue,
555 };
556
557 struct adapter_driver sysfsgpio_adapter_driver = {
558         .name = "sysfsgpio",
559         .transports = sysfsgpio_transports,
560         .commands = sysfsgpio_command_handlers,
561
562         .init = sysfsgpio_init,
563         .quit = sysfsgpio_quit,
564         .reset = sysfsgpio_reset,
565
566         .jtag_ops = &sysfsgpio_interface,
567         .swd_ops = &bitbang_swd,
568 };
569
570 static struct bitbang_interface sysfsgpio_bitbang = {
571         .read = sysfsgpio_read,
572         .write = sysfsgpio_write,
573         .swdio_read = sysfsgpio_swdio_read,
574         .swdio_drive = sysfsgpio_swdio_drive,
575         .blink = 0
576 };
577
578 /* helper func to close and cleanup files only if they were valid/ used */
579 static void cleanup_fd(int fd, int gpio)
580 {
581         if (gpio >= 0) {
582                 if (fd >= 0)
583                         close(fd);
584
585                 unexport_sysfs_gpio(gpio);
586         }
587 }
588
589 static void cleanup_all_fds(void)
590 {
591         cleanup_fd(tck_fd, tck_gpio);
592         cleanup_fd(tms_fd, tms_gpio);
593         cleanup_fd(tdi_fd, tdi_gpio);
594         cleanup_fd(tdo_fd, tdo_gpio);
595         cleanup_fd(trst_fd, trst_gpio);
596         cleanup_fd(srst_fd, srst_gpio);
597         cleanup_fd(swclk_fd, swclk_gpio);
598         cleanup_fd(swdio_fd, swdio_gpio);
599 }
600
601 static bool sysfsgpio_jtag_mode_possible(void)
602 {
603         if (!is_gpio_valid(tck_gpio))
604                 return false;
605         if (!is_gpio_valid(tms_gpio))
606                 return false;
607         if (!is_gpio_valid(tdi_gpio))
608                 return false;
609         if (!is_gpio_valid(tdo_gpio))
610                 return false;
611         return true;
612 }
613
614 static bool sysfsgpio_swd_mode_possible(void)
615 {
616         if (!is_gpio_valid(swclk_gpio))
617                 return false;
618         if (!is_gpio_valid(swdio_gpio))
619                 return false;
620         return true;
621 }
622
623 static int sysfsgpio_init(void)
624 {
625         bitbang_interface = &sysfsgpio_bitbang;
626
627         LOG_INFO("SysfsGPIO JTAG/SWD bitbang driver");
628
629         if (sysfsgpio_jtag_mode_possible()) {
630                 if (sysfsgpio_swd_mode_possible())
631                         LOG_INFO("JTAG and SWD modes enabled");
632                 else
633                         LOG_INFO("JTAG only mode enabled (specify swclk and swdio gpio to add SWD mode)");
634         } else if (sysfsgpio_swd_mode_possible()) {
635                 LOG_INFO("SWD only mode enabled (specify tck, tms, tdi and tdo gpios to add JTAG mode)");
636         } else {
637                 LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode and/or swclk and swdio gpio for SWD mode");
638                 return ERROR_JTAG_INIT_FAILED;
639         }
640
641
642         /*
643          * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
644          * as outputs.  Drive TDI and TCK low, and TMS/TRST/SRST high.
645          * For SWD, SWCLK and SWDIO are configures as output high.
646          */
647         if (tck_gpio >= 0) {
648                 tck_fd = setup_sysfs_gpio(tck_gpio, 1, 0);
649                 if (tck_fd < 0)
650                         goto out_error;
651         }
652
653         if (tms_gpio >= 0) {
654                 tms_fd = setup_sysfs_gpio(tms_gpio, 1, 1);
655                 if (tms_fd < 0)
656                         goto out_error;
657         }
658
659         if (tdi_gpio >= 0) {
660                 tdi_fd = setup_sysfs_gpio(tdi_gpio, 1, 0);
661                 if (tdi_fd < 0)
662                         goto out_error;
663         }
664
665         if (tdo_gpio >= 0) {
666                 tdo_fd = setup_sysfs_gpio(tdo_gpio, 0, 0);
667                 if (tdo_fd < 0)
668                         goto out_error;
669         }
670
671         /* assume active low*/
672         if (trst_gpio >= 0) {
673                 trst_fd = setup_sysfs_gpio(trst_gpio, 1, 1);
674                 if (trst_fd < 0)
675                         goto out_error;
676         }
677
678         /* assume active low*/
679         if (srst_gpio >= 0) {
680                 srst_fd = setup_sysfs_gpio(srst_gpio, 1, 1);
681                 if (srst_fd < 0)
682                         goto out_error;
683         }
684
685         if (swclk_gpio >= 0) {
686                 swclk_fd = setup_sysfs_gpio(swclk_gpio, 1, 0);
687                 if (swclk_fd < 0)
688                         goto out_error;
689         }
690
691         if (swdio_gpio >= 0) {
692                 swdio_fd = setup_sysfs_gpio(swdio_gpio, 1, 0);
693                 if (swdio_fd < 0)
694                         goto out_error;
695         }
696
697         return ERROR_OK;
698
699 out_error:
700         cleanup_all_fds();
701         return ERROR_JTAG_INIT_FAILED;
702 }
703
704 static int sysfsgpio_quit(void)
705 {
706         cleanup_all_fds();
707         return ERROR_OK;
708 }