1cad268936547566f126cfa6ce2938fbcfecec80
[openocd.git] / 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, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
19 /**
20 * @file
21 * This driver implements a bitbang jtag interface using gpio lines via
22 * sysfs.
23 * The aim of this driver implementation is use system GPIOs but avoid the
24 * need for a additional kernel driver.
25 * (Note memory mapped IO is another option, however it doesn't mix well with
26 * the kernel gpiolib driver - which makes sense I guess.)
27 *
28 * A gpio is required for tck, tms, tdi and tdo. One or both of srst and trst
29 * must be also be specified. The required jtag gpios are specified via the
30 * sysfsgpio_jtag_nums command or the relevant sysfsgpio_XXX_num commang.
31 * The srst and trst gpios are set via the sysfsgpio_srst_num and
32 * sysfsgpio_trst_num respectively. GPIO numbering follows the kernel
33 * convention of starting from 0.
34 *
35 * The gpios should not be in use by another entity, and must not be requested
36 * by a kernel driver without also being exported by it (otherwise they can't
37 * be exported by sysfs).
38 *
39 * The sysfs gpio interface can only manipulate one gpio at a time, so the
40 * bitbang write handler remembers the last state for tck, tms, tdi to avoid
41 * superfluous writes.
42 * For speed the sysfs "value" entry is opened at init and held open.
43 * This results in considerable gains over open-write-close (45s vs 900s)
44 *
45 * Further work could address:
46 * -srst and trst open drain/ push pull
47 * -configurable active high/low for srst & trst
48 */
49 #ifdef HAVE_CONFIG_H
50 #include "config.h"
51 #endif
52
53 #include <jtag/interface.h>
54 #include "bitbang.h"
55
56 /*
57 * Helper func to determine if gpio number valid
58 *
59 * Assume here that there will be less than 1000 gpios on a system
60 */
61 static int is_gpio_valid(int gpio)
62 {
63 return gpio >= 0 && gpio < 1000;
64 }
65
66 /*
67 * Helper func to open, write to and close a file
68 * name and valstr must be null terminated.
69 *
70 * Returns negative on failure.
71 */
72 static int open_write_close(const char *name, const char *valstr)
73 {
74 int ret;
75 int fd = open(name, O_WRONLY);
76 if (fd < 0)
77 return fd;
78
79 ret = write(fd, valstr, strlen(valstr));
80 close(fd);
81
82 return ret;
83 }
84
85 /*
86 * Helper func to unexport gpio from sysfs
87 */
88 static void unexport_sysfs_gpio(int gpio)
89 {
90 char gpiostr[4];
91
92 if (!is_gpio_valid(gpio))
93 return;
94
95 snprintf(gpiostr, sizeof(gpiostr), "%d", gpio);
96 if (open_write_close("/sys/class/gpio/unexport", gpiostr) < 0)
97 LOG_ERROR("Couldn't unexport gpio %d", gpio);
98
99 return;
100 }
101
102 /*
103 * Exports and sets up direction for gpio.
104 * If the gpio is an output, it is initialized according to init_high,
105 * otherwise it is ignored.
106 *
107 * If the gpio is already exported we just show a warning and continue; if
108 * openocd happened to crash (or was killed by user) then the gpios will not
109 * have been cleaned up.
110 */
111 static int setup_sysfs_gpio(int gpio, int is_output, int init_high)
112 {
113 char buf[40];
114 char gpiostr[4];
115 int ret;
116
117 if (!is_gpio_valid(gpio))
118 return ERROR_OK;
119
120 snprintf(gpiostr, sizeof(gpiostr), "%d", gpio);
121 ret = open_write_close("/sys/class/gpio/export", gpiostr);
122 if (ret < 0) {
123 if (errno == EBUSY) {
124 LOG_WARNING("gpio %d is already exported", gpio);
125 } else {
126 LOG_ERROR("Couldn't export gpio %d", gpio);
127 perror("sysfsgpio: ");
128 return ERROR_FAIL;
129 }
130 }
131
132 snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/direction", gpio);
133 ret = open_write_close(buf, is_output ? (init_high ? "high" : "low") : "in");
134 if (ret < 0) {
135 LOG_ERROR("Couldn't set direction for gpio %d", gpio);
136 perror("sysfsgpio: ");
137 unexport_sysfs_gpio(gpio);
138 return ERROR_FAIL;
139 }
140
141 snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/value", gpio);
142 if (is_output)
143 ret = open(buf, O_WRONLY | O_NONBLOCK | O_SYNC);
144 else
145 ret = open(buf, O_RDONLY | O_NONBLOCK | O_SYNC);
146
147 if (ret < 0)
148 unexport_sysfs_gpio(gpio);
149
150 return ret;
151 }
152
153 /*
154 * file descriptors for /sys/class/gpio/gpioXX/value
155 * Set up during init.
156 */
157 static int tck_fd = -1;
158 static int tms_fd = -1;
159 static int tdi_fd = -1;
160 static int tdo_fd = -1;
161 static int trst_fd = -1;
162 static int srst_fd = -1;
163
164 /*
165 * Bitbang interface read of TDO
166 *
167 * The sysfs value will read back either '0' or '1'. The trick here is to call
168 * lseek to bypass buffering in the sysfs kernel driver.
169 */
170 static int sysfsgpio_read(void)
171 {
172 char buf[1];
173
174 /* important to seek to signal sysfs of new read */
175 lseek(tdo_fd, 0, SEEK_SET);
176 int ret = read(tdo_fd, &buf, sizeof(buf));
177
178 if (ret < 0) {
179 LOG_WARNING("reading tdo failed");
180 return 0;
181 }
182
183 return buf[0] == '1';
184 }
185
186 /*
187 * Bitbang interface write of TCK, TMS, TDI
188 *
189 * Seeing as this is the only function where the outputs are changed,
190 * we can cache the old value to avoid needlessly writing it.
191 */
192 static void sysfsgpio_write(int tck, int tms, int tdi)
193 {
194 const char one[] = "1";
195 const char zero[] = "0";
196
197 static int last_tck;
198 static int last_tms;
199 static int last_tdi;
200
201 static int first_time;
202 size_t bytes_written;
203
204 if (!first_time) {
205 last_tck = !tck;
206 last_tms = !tms;
207 last_tdi = !tdi;
208 first_time = 1;
209 }
210
211 if (tdi != last_tdi) {
212 bytes_written = write(tdi_fd, tdi ? &one : &zero, 1);
213 if (bytes_written != 1)
214 LOG_WARNING("writing tdi failed");
215 }
216
217 if (tms != last_tms) {
218 bytes_written = write(tms_fd, tms ? &one : &zero, 1);
219 if (bytes_written != 1)
220 LOG_WARNING("writing tms failed");
221 }
222
223 /* write clk last */
224 if (tck != last_tck) {
225 bytes_written = write(tck_fd, tck ? &one : &zero, 1);
226 if (bytes_written != 1)
227 LOG_WARNING("writing tck failed");
228 }
229
230 last_tdi = tdi;
231 last_tms = tms;
232 last_tck = tck;
233 }
234
235 /*
236 * Bitbang interface to manipulate reset lines SRST and TRST
237 *
238 * (1) assert or (0) deassert reset lines
239 */
240 static void sysfsgpio_reset(int trst, int srst)
241 {
242 const char one[] = "1";
243 const char zero[] = "0";
244 size_t bytes_written;
245
246 /* assume active low */
247 if (srst_fd >= 0) {
248 bytes_written = write(srst_fd, srst ? &zero : &one, 1);
249 if (bytes_written != 1)
250 LOG_WARNING("writing srst failed");
251 }
252
253 /* assume active low */
254 if (trst_fd >= 0) {
255 bytes_written = write(trst_fd, trst ? &zero : &one, 1);
256 if (bytes_written != 1)
257 LOG_WARNING("writing trst failed");
258 }
259 }
260
261 /* No speed control is implemented yet */
262 static int sysfsgpio_speed(int speed)
263 {
264 return ERROR_OK;
265 }
266
267 static int sysfsgpio_khz(int khz, int *jtag_speed)
268 {
269 /* no adaptive clocking */
270 if (khz == 0)
271 return ERROR_FAIL;
272
273 *jtag_speed = 0;
274 return ERROR_OK;
275 }
276
277 static int sysfsgpio_speed_div(int speed, int *khz)
278 {
279 *khz = 1;
280 return ERROR_OK;
281 }
282
283 /* gpio numbers for each gpio. Negative values are invalid */
284 static int tck_gpio = -1;
285 static int tms_gpio = -1;
286 static int tdi_gpio = -1;
287 static int tdo_gpio = -1;
288 static int trst_gpio = -1;
289 static int srst_gpio = -1;
290
291 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionums)
292 {
293 if (CMD_ARGC == 4) {
294 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
295 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tms_gpio);
296 COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], tdi_gpio);
297 COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], tdo_gpio);
298 } else if (CMD_ARGC != 0) {
299 return ERROR_COMMAND_SYNTAX_ERROR;
300 }
301
302 command_print(CMD_CTX,
303 "SysfsGPIO nums: tck = %d, tms = %d, tdi = %d, tdi = %d",
304 tck_gpio, tms_gpio, tdi_gpio, tdo_gpio);
305
306 return ERROR_OK;
307 }
308
309 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tck)
310 {
311 if (CMD_ARGC == 1)
312 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
313
314 command_print(CMD_CTX, "SysfsGPIO num: tck = %d", tck_gpio);
315 return ERROR_OK;
316 }
317
318 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tms)
319 {
320 if (CMD_ARGC == 1)
321 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tms_gpio);
322
323 command_print(CMD_CTX, "SysfsGPIO num: tms = %d", tms_gpio);
324 return ERROR_OK;
325 }
326
327 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tdo)
328 {
329 if (CMD_ARGC == 1)
330 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdo_gpio);
331
332 command_print(CMD_CTX, "SysfsGPIO num: tdo = %d", tdo_gpio);
333 return ERROR_OK;
334 }
335
336 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tdi)
337 {
338 if (CMD_ARGC == 1)
339 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdi_gpio);
340
341 command_print(CMD_CTX, "SysfsGPIO num: tdi = %d", tdi_gpio);
342 return ERROR_OK;
343 }
344
345 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_srst)
346 {
347 if (CMD_ARGC == 1)
348 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], srst_gpio);
349
350 command_print(CMD_CTX, "SysfsGPIO num: srst = %d", srst_gpio);
351 return ERROR_OK;
352 }
353
354 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_trst)
355 {
356 if (CMD_ARGC == 1)
357 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], trst_gpio);
358
359 command_print(CMD_CTX, "SysfsGPIO num: trst = %d", trst_gpio);
360 return ERROR_OK;
361 }
362
363 static const struct command_registration sysfsgpio_command_handlers[] = {
364 {
365 .name = "sysfsgpio_jtag_nums",
366 .handler = &sysfsgpio_handle_jtag_gpionums,
367 .mode = COMMAND_CONFIG,
368 .help = "gpio numbers for tck, tms, tdi, tdo. (in that order)",
369 .usage = "(tck tms tdi tdo)* ",
370 },
371 {
372 .name = "sysfsgpio_tck_num",
373 .handler = &sysfsgpio_handle_jtag_gpionum_tck,
374 .mode = COMMAND_CONFIG,
375 .help = "gpio number for tck.",
376 },
377 {
378 .name = "sysfsgpio_tms_num",
379 .handler = &sysfsgpio_handle_jtag_gpionum_tms,
380 .mode = COMMAND_CONFIG,
381 .help = "gpio number for tms.",
382 },
383 {
384 .name = "sysfsgpio_tdo_num",
385 .handler = &sysfsgpio_handle_jtag_gpionum_tdo,
386 .mode = COMMAND_CONFIG,
387 .help = "gpio number for tdo.",
388 },
389 {
390 .name = "sysfsgpio_tdi_num",
391 .handler = &sysfsgpio_handle_jtag_gpionum_tdi,
392 .mode = COMMAND_CONFIG,
393 .help = "gpio number for tdi.",
394 },
395 {
396 .name = "sysfsgpio_srst_num",
397 .handler = &sysfsgpio_handle_jtag_gpionum_srst,
398 .mode = COMMAND_CONFIG,
399 .help = "gpio number for srst.",
400 },
401 {
402 .name = "sysfsgpio_trst_num",
403 .handler = &sysfsgpio_handle_jtag_gpionum_trst,
404 .mode = COMMAND_CONFIG,
405 .help = "gpio number for trst.",
406 },
407 COMMAND_REGISTRATION_DONE
408 };
409
410 static int sysfsgpio_init(void);
411 static int sysfsgpio_quit(void);
412
413 struct jtag_interface sysfsgpio_interface = {
414 .name = "sysfsgpio",
415 .supported = DEBUG_CAP_TMS_SEQ,
416 .execute_queue = bitbang_execute_queue,
417 .transports = jtag_only,
418 .speed = sysfsgpio_speed,
419 .khz = sysfsgpio_khz,
420 .speed_div = sysfsgpio_speed_div,
421 .commands = sysfsgpio_command_handlers,
422 .init = sysfsgpio_init,
423 .quit = sysfsgpio_quit,
424 };
425
426 static struct bitbang_interface sysfsgpio_bitbang = {
427 .read = sysfsgpio_read,
428 .write = sysfsgpio_write,
429 .reset = sysfsgpio_reset,
430 .blink = 0
431 };
432
433 /* helper func to close and cleanup files only if they were valid/ used */
434 static void cleanup_fd(int fd, int gpio)
435 {
436 if (gpio >= 0) {
437 if (fd >= 0)
438 close(fd);
439
440 unexport_sysfs_gpio(gpio);
441 }
442 }
443
444 static void cleanup_all_fds(void)
445 {
446 cleanup_fd(tck_fd, tck_gpio);
447 cleanup_fd(tms_fd, tms_gpio);
448 cleanup_fd(tdi_fd, tdi_gpio);
449 cleanup_fd(tdo_fd, tdo_gpio);
450 cleanup_fd(trst_fd, trst_gpio);
451 cleanup_fd(srst_fd, srst_gpio);
452 }
453
454 static int sysfsgpio_init(void)
455 {
456 bitbang_interface = &sysfsgpio_bitbang;
457
458 LOG_INFO("SysfsGPIO JTAG bitbang driver");
459
460 if (!(is_gpio_valid(tck_gpio)
461 && is_gpio_valid(tms_gpio)
462 && is_gpio_valid(tdi_gpio)
463 && is_gpio_valid(tdo_gpio))) {
464 if (!is_gpio_valid(tck_gpio))
465 LOG_ERROR("gpio num for tck is invalid");
466 if (!is_gpio_valid(tms_gpio))
467 LOG_ERROR("gpio num for tms is invalid");
468 if (!is_gpio_valid(tdo_gpio))
469 LOG_ERROR("gpio num for tdo is invalid");
470 if (!is_gpio_valid(tdi_gpio))
471 LOG_ERROR("gpio num for tdi is invalid");
472
473 LOG_ERROR("Require tck, tms, tdi and tdo gpios to all be specified");
474 return ERROR_JTAG_INIT_FAILED;
475 }
476
477 if (!is_gpio_valid(trst_gpio) && !is_gpio_valid(srst_gpio)) {
478 LOG_ERROR("Require at least one of trst or srst gpios to be specified");
479 return ERROR_JTAG_INIT_FAILED;
480 }
481
482 /*
483 * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
484 * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high.
485 */
486 tck_fd = setup_sysfs_gpio(tck_gpio, 1, 0);
487 if (tck_fd < 0)
488 goto out_error;
489
490 tms_fd = setup_sysfs_gpio(tms_gpio, 1, 1);
491 if (tms_fd < 0)
492 goto out_error;
493
494 tdi_fd = setup_sysfs_gpio(tdi_gpio, 1, 0);
495 if (tdi_fd < 0)
496 goto out_error;
497
498 tdo_fd = setup_sysfs_gpio(tdo_gpio, 0, 0);
499 if (tdo_fd < 0)
500 goto out_error;
501
502 /* assume active low*/
503 trst_fd = setup_sysfs_gpio(trst_gpio, 1, 1);
504 if (trst_gpio > 0 && trst_fd < 0)
505 goto out_error;
506
507 /* assume active low*/
508 srst_fd = setup_sysfs_gpio(srst_gpio, 1, 1);
509 if (srst_gpio > 0 && srst_fd < 0)
510 goto out_error;
511
512 return ERROR_OK;
513
514 out_error:
515 cleanup_all_fds();
516 return ERROR_JTAG_INIT_FAILED;
517 }
518
519 static int sysfsgpio_quit(void)
520 {
521 cleanup_all_fds();
522 return ERROR_OK;
523 }
524

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)