1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2012 by Creative Product Design, marc @ cpdesign.com.au *
5 ***************************************************************************/
7 /* 2014-12: Addition of the SWD protocol support is based on the initial work
8 * on bcm2835gpio.c by Paul Fertser and modifications by Jean-Christian de Rivaz. */
12 * This driver implements a bitbang jtag interface using gpio lines via
14 * The aim of this driver implementation is use system GPIOs but avoid the
15 * need for a additional kernel driver.
16 * (Note memory mapped IO is another option, however it doesn't mix well with
17 * the kernel gpiolib driver - which makes sense I guess.)
19 * A gpio is required for tck, tms, tdi and tdo. One or both of srst and trst
20 * must be also be specified. The required jtag gpios are specified via the
21 * sysfsgpio_jtag_nums command or the relevant sysfsgpio_XXX_num commands.
22 * The srst and trst gpios are set via the sysfsgpio_srst_num and
23 * sysfsgpio_trst_num respectively. GPIO numbering follows the kernel
24 * convention of starting from 0.
26 * The gpios should not be in use by another entity, and must not be requested
27 * by a kernel driver without also being exported by it (otherwise they can't
28 * be exported by sysfs).
30 * The sysfs gpio interface can only manipulate one gpio at a time, so the
31 * bitbang write handler remembers the last state for tck, tms, tdi to avoid
33 * For speed the sysfs "value" entry is opened at init and held open.
34 * This results in considerable gains over open-write-close (45s vs 900s)
36 * Further work could address:
37 * -srst and trst open drain/ push pull
38 * -configurable active high/low for srst & trst
44 #include <helper/time_support.h>
45 #include <jtag/interface.h>
46 #include <transport/transport.h>
50 * Helper func to determine if gpio number valid
52 * Assume here that there will be less than 10000 gpios on a system
54 static bool is_gpio_valid(int gpio
)
56 return gpio
>= 0 && gpio
< 10000;
60 * Helper func to open, write to and close a file
61 * name and valstr must be null terminated.
63 * Returns negative on failure.
65 static int open_write_close(const char *name
, const char *valstr
)
68 int fd
= open(name
, O_WRONLY
);
72 ret
= write(fd
, valstr
, strlen(valstr
));
79 * Helper func to unexport gpio from sysfs
81 static void unexport_sysfs_gpio(int gpio
)
85 if (!is_gpio_valid(gpio
))
88 snprintf(gpiostr
, sizeof(gpiostr
), "%d", gpio
);
89 if (open_write_close("/sys/class/gpio/unexport", gpiostr
) < 0)
90 LOG_ERROR("Couldn't unexport gpio %d", gpio
);
94 * Exports and sets up direction for gpio.
95 * If the gpio is an output, it is initialized according to init_high,
96 * otherwise it is ignored.
98 * If the gpio is already exported we just show a warning and continue; if
99 * openocd happened to crash (or was killed by user) then the gpios will not
100 * have been cleaned up.
102 static int setup_sysfs_gpio(int gpio
, int is_output
, int init_high
)
104 struct timeval timeout
, now
;
109 if (!is_gpio_valid(gpio
))
112 snprintf(gpiostr
, sizeof(gpiostr
), "%d", gpio
);
113 ret
= open_write_close("/sys/class/gpio/export", gpiostr
);
115 if (errno
== EBUSY
) {
116 LOG_WARNING("gpio %d is already exported", gpio
);
118 LOG_ERROR("Couldn't export gpio %d", gpio
);
119 LOG_ERROR("sysfsgpio: %s", strerror(errno
));
124 gettimeofday(&timeout
, NULL
);
125 timeval_add_time(&timeout
, 0, 500000);
127 snprintf(buf
, sizeof(buf
), "/sys/class/gpio/gpio%d/direction", gpio
);
129 ret
= open_write_close(buf
, is_output
? (init_high
? "high" : "low") : "in");
130 if (ret
>= 0 || errno
!= EACCES
)
132 gettimeofday(&now
, NULL
);
133 if (timeval_compare(&now
, &timeout
) >= 0)
138 LOG_ERROR("Couldn't set direction for gpio %d", gpio
);
139 LOG_ERROR("sysfsgpio: %s", strerror(errno
));
140 unexport_sysfs_gpio(gpio
);
144 snprintf(buf
, sizeof(buf
), "/sys/class/gpio/gpio%d/value", gpio
);
146 ret
= open(buf
, O_RDWR
| O_NONBLOCK
| O_SYNC
);
147 if (ret
>= 0 || errno
!= EACCES
)
149 gettimeofday(&now
, NULL
);
150 if (timeval_compare(&now
, &timeout
) >= 0)
155 LOG_ERROR("Couldn't open value for gpio %d", gpio
);
156 LOG_ERROR("sysfsgpio: %s", strerror(errno
));
157 unexport_sysfs_gpio(gpio
);
163 /* gpio numbers for each gpio. Negative values are invalid */
164 static int tck_gpio
= -1;
165 static int tms_gpio
= -1;
166 static int tdi_gpio
= -1;
167 static int tdo_gpio
= -1;
168 static int trst_gpio
= -1;
169 static int srst_gpio
= -1;
170 static int swclk_gpio
= -1;
171 static int swdio_gpio
= -1;
174 * file descriptors for /sys/class/gpio/gpioXX/value
175 * Set up during init.
177 static int tck_fd
= -1;
178 static int tms_fd
= -1;
179 static int tdi_fd
= -1;
180 static int tdo_fd
= -1;
181 static int trst_fd
= -1;
182 static int srst_fd
= -1;
183 static int swclk_fd
= -1;
184 static int swdio_fd
= -1;
186 static int last_swclk
;
187 static int last_swdio
;
188 static bool last_stored
;
189 static bool swdio_input
;
191 static void sysfsgpio_swdio_drive(bool is_output
)
196 snprintf(buf
, sizeof(buf
), "/sys/class/gpio/gpio%d/direction", swdio_gpio
);
197 ret
= open_write_close(buf
, is_output
? "high" : "in");
199 LOG_ERROR("Couldn't set direction for gpio %d", swdio_gpio
);
200 LOG_ERROR("sysfsgpio: %s", strerror(errno
));
204 swdio_input
= !is_output
;
207 static int sysfsgpio_swdio_read(void)
211 /* important to seek to signal sysfs of new read */
212 lseek(swdio_fd
, 0, SEEK_SET
);
213 int ret
= read(swdio_fd
, &buf
, sizeof(buf
));
216 LOG_WARNING("reading swdio failed");
220 return buf
[0] != '0';
223 static int sysfsgpio_swd_write(int swclk
, int swdio
)
225 const char one
[] = "1";
226 const char zero
[] = "0";
228 size_t bytes_written
;
231 if (!last_stored
|| (swdio
!= last_swdio
)) {
232 bytes_written
= write(swdio_fd
, swdio
? &one
: &zero
, 1);
233 if (bytes_written
!= 1)
234 LOG_WARNING("writing swdio failed");
238 /* write swclk last */
239 if (!last_stored
|| (swclk
!= last_swclk
)) {
240 bytes_written
= write(swclk_fd
, swclk
? &one
: &zero
, 1);
241 if (bytes_written
!= 1)
242 LOG_WARNING("writing swclk failed");
253 * Bitbang interface read of TDO
255 * The sysfs value will read back either '0' or '1'. The trick here is to call
256 * lseek to bypass buffering in the sysfs kernel driver.
258 static bb_value_t
sysfsgpio_read(void)
262 /* important to seek to signal sysfs of new read */
263 lseek(tdo_fd
, 0, SEEK_SET
);
264 int ret
= read(tdo_fd
, &buf
, sizeof(buf
));
267 LOG_WARNING("reading tdo failed");
271 return buf
[0] == '0' ? BB_LOW
: BB_HIGH
;
275 * Bitbang interface write of TCK, TMS, TDI
277 * Seeing as this is the only function where the outputs are changed,
278 * we can cache the old value to avoid needlessly writing it.
280 static int sysfsgpio_write(int tck
, int tms
, int tdi
)
282 const char one
[] = "1";
283 const char zero
[] = "0";
289 static int first_time
;
290 size_t bytes_written
;
299 if (tdi
!= last_tdi
) {
300 bytes_written
= write(tdi_fd
, tdi
? &one
: &zero
, 1);
301 if (bytes_written
!= 1)
302 LOG_WARNING("writing tdi failed");
305 if (tms
!= last_tms
) {
306 bytes_written
= write(tms_fd
, tms
? &one
: &zero
, 1);
307 if (bytes_written
!= 1)
308 LOG_WARNING("writing tms failed");
312 if (tck
!= last_tck
) {
313 bytes_written
= write(tck_fd
, tck
? &one
: &zero
, 1);
314 if (bytes_written
!= 1)
315 LOG_WARNING("writing tck failed");
326 * Bitbang interface to manipulate reset lines SRST and TRST
328 * (1) assert or (0) deassert reset lines
330 static int sysfsgpio_reset(int trst
, int srst
)
332 LOG_DEBUG("sysfsgpio_reset");
333 const char one
[] = "1";
334 const char zero
[] = "0";
335 size_t bytes_written
;
337 /* assume active low */
339 bytes_written
= write(srst_fd
, srst
? &zero
: &one
, 1);
340 if (bytes_written
!= 1)
341 LOG_WARNING("writing srst failed");
344 /* assume active low */
346 bytes_written
= write(trst_fd
, trst
? &zero
: &one
, 1);
347 if (bytes_written
!= 1)
348 LOG_WARNING("writing trst failed");
354 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionums
)
357 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tck_gpio
);
358 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], tms_gpio
);
359 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[2], tdi_gpio
);
360 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[3], tdo_gpio
);
361 } else if (CMD_ARGC
!= 0) {
362 return ERROR_COMMAND_SYNTAX_ERROR
;
366 "SysfsGPIO nums: tck = %d, tms = %d, tdi = %d, tdo = %d",
367 tck_gpio
, tms_gpio
, tdi_gpio
, tdo_gpio
);
372 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tck
)
375 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tck_gpio
);
377 command_print(CMD
, "SysfsGPIO num: tck = %d", tck_gpio
);
381 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tms
)
384 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tms_gpio
);
386 command_print(CMD
, "SysfsGPIO num: tms = %d", tms_gpio
);
390 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tdo
)
393 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tdo_gpio
);
395 command_print(CMD
, "SysfsGPIO num: tdo = %d", tdo_gpio
);
399 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tdi
)
402 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tdi_gpio
);
404 command_print(CMD
, "SysfsGPIO num: tdi = %d", tdi_gpio
);
408 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_srst
)
411 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], srst_gpio
);
413 command_print(CMD
, "SysfsGPIO num: srst = %d", srst_gpio
);
417 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_trst
)
420 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], trst_gpio
);
422 command_print(CMD
, "SysfsGPIO num: trst = %d", trst_gpio
);
426 COMMAND_HANDLER(sysfsgpio_handle_swd_gpionums
)
429 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swclk_gpio
);
430 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], swdio_gpio
);
431 } else if (CMD_ARGC
!= 0) {
432 return ERROR_COMMAND_SYNTAX_ERROR
;
436 "SysfsGPIO nums: swclk = %d, swdio = %d",
437 swclk_gpio
, swdio_gpio
);
442 COMMAND_HANDLER(sysfsgpio_handle_swd_gpionum_swclk
)
445 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swclk_gpio
);
447 command_print(CMD
, "SysfsGPIO num: swclk = %d", swclk_gpio
);
451 COMMAND_HANDLER(sysfsgpio_handle_swd_gpionum_swdio
)
454 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swdio_gpio
);
456 command_print(CMD
, "SysfsGPIO num: swdio = %d", swdio_gpio
);
460 static const struct command_registration sysfsgpio_subcommand_handlers
[] = {
463 .handler
= &sysfsgpio_handle_jtag_gpionums
,
464 .mode
= COMMAND_CONFIG
,
465 .help
= "gpio numbers for tck, tms, tdi, tdo. (in that order)",
466 .usage
= "[tck tms tdi tdo]",
470 .handler
= &sysfsgpio_handle_jtag_gpionum_tck
,
471 .mode
= COMMAND_CONFIG
,
472 .help
= "gpio number for tck.",
477 .handler
= &sysfsgpio_handle_jtag_gpionum_tms
,
478 .mode
= COMMAND_CONFIG
,
479 .help
= "gpio number for tms.",
484 .handler
= &sysfsgpio_handle_jtag_gpionum_tdo
,
485 .mode
= COMMAND_CONFIG
,
486 .help
= "gpio number for tdo.",
491 .handler
= &sysfsgpio_handle_jtag_gpionum_tdi
,
492 .mode
= COMMAND_CONFIG
,
493 .help
= "gpio number for tdi.",
498 .handler
= &sysfsgpio_handle_jtag_gpionum_srst
,
499 .mode
= COMMAND_CONFIG
,
500 .help
= "gpio number for srst.",
505 .handler
= &sysfsgpio_handle_jtag_gpionum_trst
,
506 .mode
= COMMAND_CONFIG
,
507 .help
= "gpio number for trst.",
512 .handler
= &sysfsgpio_handle_swd_gpionums
,
513 .mode
= COMMAND_CONFIG
,
514 .help
= "gpio numbers for swclk, swdio. (in that order)",
515 .usage
= "[swclk swdio]",
519 .handler
= &sysfsgpio_handle_swd_gpionum_swclk
,
520 .mode
= COMMAND_CONFIG
,
521 .help
= "gpio number for swclk.",
526 .handler
= &sysfsgpio_handle_swd_gpionum_swdio
,
527 .mode
= COMMAND_CONFIG
,
528 .help
= "gpio number for swdio.",
531 COMMAND_REGISTRATION_DONE
534 static const struct command_registration sysfsgpio_command_handlers
[] = {
538 .help
= "perform sysfsgpio management",
539 .chain
= sysfsgpio_subcommand_handlers
,
542 COMMAND_REGISTRATION_DONE
545 static int sysfsgpio_init(void);
546 static int sysfsgpio_quit(void);
548 static const char * const sysfsgpio_transports
[] = { "jtag", "swd", NULL
};
550 static struct jtag_interface sysfsgpio_interface
= {
551 .supported
= DEBUG_CAP_TMS_SEQ
,
552 .execute_queue
= bitbang_execute_queue
,
555 struct adapter_driver sysfsgpio_adapter_driver
= {
557 .transports
= sysfsgpio_transports
,
558 .commands
= sysfsgpio_command_handlers
,
560 .init
= sysfsgpio_init
,
561 .quit
= sysfsgpio_quit
,
562 .reset
= sysfsgpio_reset
,
564 .jtag_ops
= &sysfsgpio_interface
,
565 .swd_ops
= &bitbang_swd
,
568 static struct bitbang_interface sysfsgpio_bitbang
= {
569 .read
= sysfsgpio_read
,
570 .write
= sysfsgpio_write
,
571 .swdio_read
= sysfsgpio_swdio_read
,
572 .swdio_drive
= sysfsgpio_swdio_drive
,
573 .swd_write
= sysfsgpio_swd_write
,
577 /* helper func to close and cleanup files only if they were valid/ used */
578 static void cleanup_fd(int fd
, int gpio
)
584 unexport_sysfs_gpio(gpio
);
588 static void cleanup_all_fds(void)
590 if (transport_is_jtag()) {
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
);
597 if (transport_is_swd()) {
598 cleanup_fd(swclk_fd
, swclk_gpio
);
599 cleanup_fd(swdio_fd
, swdio_gpio
);
601 cleanup_fd(srst_fd
, srst_gpio
);
604 static bool sysfsgpio_jtag_mode_possible(void)
606 if (!is_gpio_valid(tck_gpio
))
608 if (!is_gpio_valid(tms_gpio
))
610 if (!is_gpio_valid(tdi_gpio
))
612 if (!is_gpio_valid(tdo_gpio
))
617 static bool sysfsgpio_swd_mode_possible(void)
619 if (!is_gpio_valid(swclk_gpio
))
621 if (!is_gpio_valid(swdio_gpio
))
626 static int sysfsgpio_init(void)
628 bitbang_interface
= &sysfsgpio_bitbang
;
630 LOG_INFO("SysfsGPIO JTAG/SWD bitbang driver");
633 * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
634 * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high.
635 * For SWD, SWCLK and SWDIO are configures as output high.
638 if (transport_is_jtag()) {
639 if (!sysfsgpio_jtag_mode_possible()) {
640 LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode");
641 return ERROR_JTAG_INIT_FAILED
;
644 tck_fd
= setup_sysfs_gpio(tck_gpio
, 1, 0);
648 tms_fd
= setup_sysfs_gpio(tms_gpio
, 1, 1);
652 tdi_fd
= setup_sysfs_gpio(tdi_gpio
, 1, 0);
656 tdo_fd
= setup_sysfs_gpio(tdo_gpio
, 0, 0);
660 /* assume active low*/
661 if (trst_gpio
>= 0) {
662 trst_fd
= setup_sysfs_gpio(trst_gpio
, 1, 1);
668 if (transport_is_swd()) {
669 if (!sysfsgpio_swd_mode_possible()) {
670 LOG_ERROR("Require swclk and swdio gpio for SWD mode");
671 return ERROR_JTAG_INIT_FAILED
;
674 swclk_fd
= setup_sysfs_gpio(swclk_gpio
, 1, 0);
678 swdio_fd
= setup_sysfs_gpio(swdio_gpio
, 1, 0);
683 /* assume active low*/
684 if (srst_gpio
>= 0) {
685 srst_fd
= setup_sysfs_gpio(srst_gpio
, 1, 1);
694 return ERROR_JTAG_INIT_FAILED
;
697 static int sysfsgpio_quit(void)
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)