jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / jtag / drivers / am335xgpio.c
1 /***************************************************************************
2 * Copyright (C) 2022 by Steve Marple, stevemarple@googlemail.com *
3 * *
4 * Based on bcm2835gpio.c and linuxgpiod.c *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 ***************************************************************************/
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <jtag/interface.h>
25 #include <transport/transport.h>
26 #include "bitbang.h"
27
28 #include <sys/mman.h>
29
30 /*
31 * GPIO register base addresses. Values taken from "AM335x and AMIC110 Sitara
32 * Processors Technical Reference Manual", Chapter 2 Memory Map.
33 */
34 #define AM335XGPIO_NUM_GPIO_PORTS 4
35 #define AM335XGPIO_GPIO0_HW_ADDR 0x44E07000
36 #define AM335XGPIO_GPIO1_HW_ADDR 0x4804C000
37 #define AM335XGPIO_GPIO2_HW_ADDR 0x481AC000
38 #define AM335XGPIO_GPIO3_HW_ADDR 0x481AE000
39
40 /* 32-bit offsets from GPIO port base address. Values taken from "AM335x and
41 * AMIC110 Sitara Processors Technical Reference Manual", Chapter 25
42 * General-Purpose Input/Output.
43 */
44 #define AM335XGPIO_GPIO_OE_OFFSET (0x134 / 4)
45 #define AM335XGPIO_GPIO_DATAIN_OFFSET (0x138 / 4)
46 #define AM335XGPIO_GPIO_DATAOUT_OFFSET (0x13C / 4) /* DATAOUT register uses 0 for output, 1 for input */
47 #define AM335XGPIO_GPIO_CLEARDATAOUT_OFFSET (0x190 / 4)
48 #define AM335XGPIO_GPIO_SETDATAOUT_OFFSET (0x194 / 4)
49
50 /* GPIOs are integer values; need to map to a port module, and the pin within
51 * that module. GPIOs 0 to 31 map to GPIO0, 32 to 63 to GPIO1 etc. This scheme
52 * matches that used by Linux on the BeagleBone.
53 */
54 #define AM335XGPIO_PORT_NUM(gpio_num) ((gpio_num) / 32)
55 #define AM335XGPIO_BIT_NUM(gpio_num) ((gpio_num) % 32)
56 #define AM335XGPIO_BIT_MASK(gpio_num) BIT(AM335XGPIO_BIT_NUM(gpio_num))
57
58 #define AM335XGPIO_READ_REG(gpio_num, offset) \
59 (*(am335xgpio_gpio_port_mmap_addr[AM335XGPIO_PORT_NUM(gpio_num)] + (offset)))
60
61 #define AM335XGPIO_WRITE_REG(gpio_num, offset, value) \
62 (*(am335xgpio_gpio_port_mmap_addr[AM335XGPIO_PORT_NUM(gpio_num)] + (offset)) = (value))
63
64 #define AM335XGPIO_SET_REG_BITS(gpio_num, offset, bit_mask) \
65 (*(am335xgpio_gpio_port_mmap_addr[AM335XGPIO_PORT_NUM(gpio_num)] + (offset)) |= (bit_mask))
66
67 #define AM335XGPIO_CLEAR_REG_BITS(gpio_num, offset, bit_mask) \
68 (*(am335xgpio_gpio_port_mmap_addr[AM335XGPIO_PORT_NUM(gpio_num)] + (offset)) &= ~(bit_mask))
69
70 enum amx335gpio_gpio_mode {
71 AM335XGPIO_GPIO_MODE_INPUT,
72 AM335XGPIO_GPIO_MODE_OUTPUT, /* To set output mode but not state */
73 AM335XGPIO_GPIO_MODE_OUTPUT_LOW,
74 AM335XGPIO_GPIO_MODE_OUTPUT_HIGH,
75 };
76
77 static const uint32_t am335xgpio_gpio_port_hw_addr[AM335XGPIO_NUM_GPIO_PORTS] = {
78 AM335XGPIO_GPIO0_HW_ADDR,
79 AM335XGPIO_GPIO1_HW_ADDR,
80 AM335XGPIO_GPIO2_HW_ADDR,
81 AM335XGPIO_GPIO3_HW_ADDR,
82 };
83
84 /* Memory-mapped address pointers */
85 static volatile uint32_t *am335xgpio_gpio_port_mmap_addr[AM335XGPIO_NUM_GPIO_PORTS];
86
87 static int dev_mem_fd;
88
89 /* GPIO numbers for each signal. Negative values are invalid */
90 static int tck_gpio = -1;
91 static enum amx335gpio_gpio_mode tck_gpio_mode;
92 static int tms_gpio = -1;
93 static enum amx335gpio_gpio_mode tms_gpio_mode;
94 static int tdi_gpio = -1;
95 static enum amx335gpio_gpio_mode tdi_gpio_mode;
96 static int tdo_gpio = -1;
97 static enum amx335gpio_gpio_mode tdo_gpio_mode;
98 static int trst_gpio = -1;
99 static enum amx335gpio_gpio_mode trst_gpio_mode;
100 static int srst_gpio = -1;
101 static enum amx335gpio_gpio_mode srst_gpio_mode;
102 static int swclk_gpio = -1;
103 static enum amx335gpio_gpio_mode swclk_gpio_mode;
104 static int swdio_gpio = -1;
105 static enum amx335gpio_gpio_mode swdio_gpio_mode;
106 static int swdio_dir_gpio = -1;
107 static enum amx335gpio_gpio_mode swdio_dir_gpio_mode;
108 static int led_gpio = -1;
109 static enum amx335gpio_gpio_mode led_gpio_mode = -1;
110
111 static bool swdio_dir_is_active_high = true; /* Active state means output */
112 static bool led_is_active_high = true;
113
114 /* Transition delay coefficients */
115 static int speed_coeff = 600000;
116 static int speed_offset = 575;
117 static unsigned int jtag_delay;
118
119 static int is_gpio_valid(int gpio_num)
120 {
121 return gpio_num >= 0 && gpio_num < (32 * AM335XGPIO_NUM_GPIO_PORTS);
122 }
123
124 static int get_gpio_value(int gpio_num)
125 {
126 unsigned int shift = AM335XGPIO_BIT_NUM(gpio_num);
127 return (AM335XGPIO_READ_REG(gpio_num, AM335XGPIO_GPIO_DATAIN_OFFSET) >> shift) & 1;
128 }
129
130 static void set_gpio_value(int gpio_num, int value)
131 {
132 if (value)
133 AM335XGPIO_WRITE_REG(gpio_num, AM335XGPIO_GPIO_SETDATAOUT_OFFSET, AM335XGPIO_BIT_MASK(gpio_num));
134 else
135 AM335XGPIO_WRITE_REG(gpio_num, AM335XGPIO_GPIO_CLEARDATAOUT_OFFSET, AM335XGPIO_BIT_MASK(gpio_num));
136 }
137
138 static enum amx335gpio_gpio_mode get_gpio_mode(int gpio_num)
139 {
140 if (AM335XGPIO_READ_REG(gpio_num, AM335XGPIO_GPIO_OE_OFFSET) & AM335XGPIO_BIT_MASK(gpio_num)) {
141 return AM335XGPIO_GPIO_MODE_INPUT;
142 } else {
143 /* Return output level too so that pin mode can be fully restored */
144 if (AM335XGPIO_READ_REG(gpio_num, AM335XGPIO_GPIO_DATAOUT_OFFSET) & AM335XGPIO_BIT_MASK(gpio_num))
145 return AM335XGPIO_GPIO_MODE_OUTPUT_HIGH;
146 else
147 return AM335XGPIO_GPIO_MODE_OUTPUT_LOW;
148 }
149 }
150
151 static void set_gpio_mode(int gpio_num, enum amx335gpio_gpio_mode gpio_mode)
152 {
153 if (gpio_mode == AM335XGPIO_GPIO_MODE_INPUT) {
154 AM335XGPIO_SET_REG_BITS(gpio_num, AM335XGPIO_GPIO_OE_OFFSET, AM335XGPIO_BIT_MASK(gpio_num));
155 return;
156 }
157
158 if (gpio_mode == AM335XGPIO_GPIO_MODE_OUTPUT_LOW)
159 set_gpio_value(gpio_num, 0);
160 if (gpio_mode == AM335XGPIO_GPIO_MODE_OUTPUT_HIGH)
161 set_gpio_value(gpio_num, 1);
162
163 if (gpio_mode == AM335XGPIO_GPIO_MODE_OUTPUT ||
164 gpio_mode == AM335XGPIO_GPIO_MODE_OUTPUT_LOW ||
165 gpio_mode == AM335XGPIO_GPIO_MODE_OUTPUT_HIGH) {
166 AM335XGPIO_CLEAR_REG_BITS(gpio_num, AM335XGPIO_GPIO_OE_OFFSET, AM335XGPIO_BIT_MASK(gpio_num));
167 }
168 }
169
170 static const char *get_gpio_mode_name(enum amx335gpio_gpio_mode gpio_mode)
171 {
172 switch (gpio_mode) {
173 case AM335XGPIO_GPIO_MODE_INPUT:
174 return "input";
175 case AM335XGPIO_GPIO_MODE_OUTPUT:
176 return "output";
177 case AM335XGPIO_GPIO_MODE_OUTPUT_LOW:
178 return "output (low)";
179 case AM335XGPIO_GPIO_MODE_OUTPUT_HIGH:
180 return "output (high)";
181 default:
182 return "unknown";
183 }
184 }
185
186 static bb_value_t am335xgpio_read(void)
187 {
188 return get_gpio_value(tdo_gpio) ? BB_HIGH : BB_LOW;
189 }
190
191 static int am335xgpio_write(int tck, int tms, int tdi)
192 {
193 set_gpio_value(tdi_gpio, tdi);
194 set_gpio_value(tms_gpio, tms);
195 set_gpio_value(tck_gpio, tck); /* Write clock last */
196
197 for (unsigned int i = 0; i < jtag_delay; ++i)
198 asm volatile ("");
199
200 return ERROR_OK;
201 }
202
203 static int am335xgpio_swd_write(int swclk, int swdio)
204 {
205 set_gpio_value(swdio_gpio, swdio);
206 set_gpio_value(swclk_gpio, swclk); /* Write clock last */
207
208 for (unsigned int i = 0; i < jtag_delay; ++i)
209 asm volatile ("");
210
211 return ERROR_OK;
212 }
213
214 /* (1) assert or (0) deassert reset lines */
215 static int am335xgpio_reset(int trst, int srst)
216 {
217 /* assume active low */
218 if (is_gpio_valid(srst_gpio)) {
219 if (jtag_get_reset_config() & RESET_SRST_PUSH_PULL)
220 set_gpio_mode(srst_gpio, srst ? AM335XGPIO_GPIO_MODE_OUTPUT_LOW : AM335XGPIO_GPIO_MODE_OUTPUT_HIGH);
221 else
222 set_gpio_mode(srst_gpio, srst ? AM335XGPIO_GPIO_MODE_OUTPUT_LOW : AM335XGPIO_GPIO_MODE_INPUT);
223 }
224
225 /* assume active low */
226 if (is_gpio_valid(trst_gpio)) {
227 if (jtag_get_reset_config() & RESET_TRST_OPEN_DRAIN)
228 set_gpio_mode(trst_gpio, trst ? AM335XGPIO_GPIO_MODE_OUTPUT_LOW : AM335XGPIO_GPIO_MODE_INPUT);
229 else
230 set_gpio_mode(trst_gpio, trst ? AM335XGPIO_GPIO_MODE_OUTPUT_LOW : AM335XGPIO_GPIO_MODE_OUTPUT_HIGH);
231 }
232
233 LOG_DEBUG("am335xgpio_reset(%d, %d), trst_gpio: %d (%s), srst_gpio: %d (%s)",
234 trst, srst,
235 trst_gpio, get_gpio_mode_name(get_gpio_mode(trst_gpio)),
236 srst_gpio, get_gpio_mode_name(get_gpio_mode(srst_gpio)));
237 return ERROR_OK;
238 }
239
240 static void am335xgpio_swdio_drive(bool is_output)
241 {
242 if (is_output) {
243 set_gpio_value(swdio_dir_gpio, swdio_dir_is_active_high ? 1 : 0);
244 set_gpio_mode(swdio_gpio, AM335XGPIO_GPIO_MODE_OUTPUT);
245 } else {
246 set_gpio_mode(swdio_gpio, AM335XGPIO_GPIO_MODE_INPUT);
247 set_gpio_value(swdio_dir_gpio, swdio_dir_is_active_high ? 0 : 1);
248 }
249 }
250
251 static int am335xgpio_swdio_read(void)
252 {
253 return get_gpio_value(swdio_gpio);
254 }
255
256 static int am335xgpio_blink(int on)
257 {
258 if (is_gpio_valid(led_gpio))
259 set_gpio_value(led_gpio, (!on ^ led_is_active_high) ? 1 : 0);
260
261 return ERROR_OK;
262 }
263
264 static struct bitbang_interface am335xgpio_bitbang = {
265 .read = am335xgpio_read,
266 .write = am335xgpio_write,
267 .swdio_read = am335xgpio_swdio_read,
268 .swdio_drive = am335xgpio_swdio_drive,
269 .swd_write = am335xgpio_swd_write,
270 .blink = am335xgpio_blink
271 };
272
273 static int am335xgpio_khz(int khz, int *jtag_speed)
274 {
275 if (!khz) {
276 LOG_DEBUG("RCLK not supported");
277 return ERROR_FAIL;
278 }
279 *jtag_speed = speed_coeff / khz - speed_offset;
280 if (*jtag_speed < 0)
281 *jtag_speed = 0;
282 return ERROR_OK;
283 }
284
285 static int am335xgpio_speed_div(int speed, int *khz)
286 {
287 *khz = speed_coeff / (speed + speed_offset);
288 return ERROR_OK;
289 }
290
291 static int am335xgpio_speed(int speed)
292 {
293 jtag_delay = speed;
294 return ERROR_OK;
295 }
296
297 COMMAND_HANDLER(am335xgpio_handle_jtag_gpionums)
298 {
299 if (CMD_ARGC == 4) {
300 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
301 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tms_gpio);
302 COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], tdi_gpio);
303 COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], tdo_gpio);
304 } else if (CMD_ARGC != 0) {
305 return ERROR_COMMAND_SYNTAX_ERROR;
306 }
307
308 command_print(CMD, "AM335x GPIO config: tck = %d, tms = %d, tdi = %d, tdo = %d",
309 tck_gpio, tms_gpio, tdi_gpio, tdo_gpio);
310 return ERROR_OK;
311 }
312
313 COMMAND_HANDLER(am335xgpio_handle_jtag_gpionum_tck)
314 {
315 if (CMD_ARGC == 1)
316 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio);
317
318 command_print(CMD, "AM335x GPIO config: tck = %d", tck_gpio);
319 return ERROR_OK;
320 }
321
322 COMMAND_HANDLER(am335xgpio_handle_jtag_gpionum_tms)
323 {
324 if (CMD_ARGC == 1)
325 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tms_gpio);
326
327 command_print(CMD, "AM335x GPIO config: tms = %d", tms_gpio);
328 return ERROR_OK;
329 }
330
331 COMMAND_HANDLER(am335xgpio_handle_jtag_gpionum_tdo)
332 {
333 if (CMD_ARGC == 1)
334 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdo_gpio);
335
336 command_print(CMD, "AM335x GPIO config: tdo = %d", tdo_gpio);
337 return ERROR_OK;
338 }
339
340 COMMAND_HANDLER(am335xgpio_handle_jtag_gpionum_tdi)
341 {
342 if (CMD_ARGC == 1)
343 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdi_gpio);
344
345 command_print(CMD, "AM335x GPIO config: tdi = %d", tdi_gpio);
346 return ERROR_OK;
347 }
348
349 COMMAND_HANDLER(am335xgpio_handle_jtag_gpionum_srst)
350 {
351 if (CMD_ARGC == 1)
352 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], srst_gpio);
353
354 command_print(CMD, "AM335x GPIO config: srst = %d", srst_gpio);
355 return ERROR_OK;
356 }
357
358 COMMAND_HANDLER(am335xgpio_handle_jtag_gpionum_trst)
359 {
360 if (CMD_ARGC == 1)
361 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], trst_gpio);
362
363 command_print(CMD, "AM335x GPIO config: trst = %d", trst_gpio);
364 return ERROR_OK;
365 }
366
367 COMMAND_HANDLER(am335xgpio_handle_swd_gpionums)
368 {
369 if (CMD_ARGC == 2) {
370 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
371 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], swdio_gpio);
372 } else if (CMD_ARGC != 0) {
373 return ERROR_COMMAND_SYNTAX_ERROR;
374 }
375
376 command_print(CMD, "AM335x GPIO config: swclk = %d, swdio = %d", swclk_gpio, swdio_gpio);
377
378 return ERROR_OK;
379 }
380
381 COMMAND_HANDLER(am335xgpio_handle_swd_gpionum_swclk)
382 {
383 if (CMD_ARGC == 1)
384 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio);
385
386 command_print(CMD, "AM335x GPIO config: swclk = %d", swclk_gpio);
387 return ERROR_OK;
388 }
389
390 COMMAND_HANDLER(am335xgpio_handle_swd_gpionum_swdio)
391 {
392 if (CMD_ARGC == 1)
393 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swdio_gpio);
394
395 command_print(CMD, "AM335x GPIO config: swdio = %d", swdio_gpio);
396 return ERROR_OK;
397 }
398
399 COMMAND_HANDLER(am335xgpio_handle_swd_gpionum_swdio_dir)
400 {
401 if (CMD_ARGC == 1)
402 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swdio_dir_gpio);
403
404 command_print(CMD, "AM335x GPIO config: swdio_dir = %d", swdio_dir_gpio);
405 return ERROR_OK;
406 }
407
408 COMMAND_HANDLER(am335xgpio_handle_swd_dir_output_state)
409 {
410 if (CMD_ARGC == 1)
411 COMMAND_PARSE_BOOL(CMD_ARGV[0], swdio_dir_is_active_high, "high", "low");
412
413 command_print(CMD, "AM335x GPIO config: swdio_dir_output_state = %s", swdio_dir_is_active_high ? "high" : "low");
414 return ERROR_OK;
415 }
416
417 COMMAND_HANDLER(am335xgpio_handle_gpionum_led)
418 {
419 if (CMD_ARGC == 1)
420 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], led_gpio);
421
422 command_print(CMD, "AM335x GPIO config: led = %d", led_gpio);
423 return ERROR_OK;
424 }
425
426 COMMAND_HANDLER(am335xgpio_handle_led_on_state)
427 {
428 if (CMD_ARGC == 1)
429 COMMAND_PARSE_BOOL(CMD_ARGV[0], led_is_active_high, "high", "low");
430
431 command_print(CMD, "AM335x GPIO config: led_on_state = %s", led_is_active_high ? "high" : "low");
432 return ERROR_OK;
433 }
434
435 COMMAND_HANDLER(am335xgpio_handle_speed_coeffs)
436 {
437 if (CMD_ARGC == 2) {
438 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], speed_coeff);
439 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], speed_offset);
440 }
441
442 command_print(CMD, "AM335x GPIO config: speed_coeffs = %d, speed_offset = %d",
443 speed_coeff, speed_offset);
444 return ERROR_OK;
445 }
446
447 static const struct command_registration am335xgpio_subcommand_handlers[] = {
448 {
449 .name = "jtag_nums",
450 .handler = am335xgpio_handle_jtag_gpionums,
451 .mode = COMMAND_CONFIG,
452 .help = "gpio numbers for tck, tms, tdi, tdo (in that order).",
453 .usage = "[tck tms tdi tdo]",
454 },
455 {
456 .name = "tck_num",
457 .handler = am335xgpio_handle_jtag_gpionum_tck,
458 .mode = COMMAND_CONFIG,
459 .help = "gpio number for tck.",
460 .usage = "[tck]",
461 },
462 {
463 .name = "tms_num",
464 .handler = am335xgpio_handle_jtag_gpionum_tms,
465 .mode = COMMAND_CONFIG,
466 .help = "gpio number for tms.",
467 .usage = "[tms]",
468 },
469 {
470 .name = "tdo_num",
471 .handler = am335xgpio_handle_jtag_gpionum_tdo,
472 .mode = COMMAND_CONFIG,
473 .help = "gpio number for tdo.",
474 .usage = "[tdo]",
475 },
476 {
477 .name = "tdi_num",
478 .handler = am335xgpio_handle_jtag_gpionum_tdi,
479 .mode = COMMAND_CONFIG,
480 .help = "gpio number for tdi.",
481 .usage = "[tdi]",
482 },
483 {
484 .name = "swd_nums",
485 .handler = am335xgpio_handle_swd_gpionums,
486 .mode = COMMAND_CONFIG,
487 .help = "gpio numbers for swclk, swdio (in that order).",
488 .usage = "[swclk swdio]",
489 },
490 {
491 .name = "swclk_num",
492 .handler = am335xgpio_handle_swd_gpionum_swclk,
493 .mode = COMMAND_CONFIG,
494 .help = "gpio number for swclk.",
495 .usage = "[swclk]",
496 },
497 {
498 .name = "swdio_num",
499 .handler = am335xgpio_handle_swd_gpionum_swdio,
500 .mode = COMMAND_CONFIG,
501 .help = "gpio number for swdio.",
502 .usage = "[swdio]",
503 },
504 {
505 .name = "swdio_dir_num",
506 .handler = am335xgpio_handle_swd_gpionum_swdio_dir,
507 .mode = COMMAND_CONFIG,
508 .help = "gpio number for swdio direction control pin.",
509 .usage = "[swdio_dir]",
510 },
511 {
512 .name = "swdio_dir_output_state",
513 .handler = am335xgpio_handle_swd_dir_output_state,
514 .mode = COMMAND_CONFIG,
515 .help = "required state for swdio_dir pin to select SWDIO buffer to be output.",
516 .usage = "['off'|'on']",
517 },
518 {
519 .name = "srst_num",
520 .handler = am335xgpio_handle_jtag_gpionum_srst,
521 .mode = COMMAND_CONFIG,
522 .help = "gpio number for srst.",
523 .usage = "[srst]",
524 },
525 {
526 .name = "trst_num",
527 .handler = am335xgpio_handle_jtag_gpionum_trst,
528 .mode = COMMAND_CONFIG,
529 .help = "gpio number for trst.",
530 .usage = "[trst]",
531 },
532 {
533 .name = "led_num",
534 .handler = am335xgpio_handle_gpionum_led,
535 .mode = COMMAND_CONFIG,
536 .help = "gpio number for led.",
537 .usage = "[led]",
538 },
539 {
540 .name = "led_on_state",
541 .handler = am335xgpio_handle_led_on_state,
542 .mode = COMMAND_CONFIG,
543 .help = "required state for led pin to turn on LED.",
544 .usage = "['off'|'on']",
545 },
546 {
547 .name = "speed_coeffs",
548 .handler = am335xgpio_handle_speed_coeffs,
549 .mode = COMMAND_CONFIG,
550 .help = "SPEED_COEFF and SPEED_OFFSET for delay calculations.",
551 .usage = "[SPEED_COEFF SPEED_OFFSET]",
552 },
553 COMMAND_REGISTRATION_DONE
554 };
555
556 static const struct command_registration am335xgpio_command_handlers[] = {
557 {
558 .name = "am335xgpio",
559 .mode = COMMAND_ANY,
560 .help = "perform am335xgpio management",
561 .chain = am335xgpio_subcommand_handlers,
562 .usage = "",
563 },
564 COMMAND_REGISTRATION_DONE
565 };
566
567 static const char * const am335xgpio_transports[] = { "jtag", "swd", NULL };
568
569 static struct jtag_interface am335xgpio_interface = {
570 .supported = DEBUG_CAP_TMS_SEQ,
571 .execute_queue = bitbang_execute_queue,
572 };
573
574 static bool am335xgpio_jtag_mode_possible(void)
575 {
576 if (!is_gpio_valid(tck_gpio))
577 return false;
578 if (!is_gpio_valid(tms_gpio))
579 return false;
580 if (!is_gpio_valid(tdi_gpio))
581 return false;
582 if (!is_gpio_valid(tdo_gpio))
583 return false;
584 return true;
585 }
586
587 static bool am335xgpio_swd_mode_possible(void)
588 {
589 if (!is_gpio_valid(swclk_gpio))
590 return false;
591 if (!is_gpio_valid(swdio_gpio))
592 return false;
593 return true;
594 }
595
596 static int am335xgpio_init(void)
597 {
598 bitbang_interface = &am335xgpio_bitbang;
599
600 LOG_INFO("AM335x GPIO JTAG/SWD bitbang driver");
601
602 if (transport_is_jtag() && !am335xgpio_jtag_mode_possible()) {
603 LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode");
604 return ERROR_JTAG_INIT_FAILED;
605 }
606
607 if (transport_is_swd() && !am335xgpio_swd_mode_possible()) {
608 LOG_ERROR("Require swclk and swdio gpio for SWD mode");
609 return ERROR_JTAG_INIT_FAILED;
610 }
611
612 dev_mem_fd = open("/dev/gpiomem", O_RDWR | O_SYNC);
613 if (dev_mem_fd < 0) {
614 LOG_DEBUG("Cannot open /dev/gpiomem, fallback to /dev/mem");
615 dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
616 }
617 if (dev_mem_fd < 0) {
618 LOG_ERROR("open: %s", strerror(errno));
619 return ERROR_JTAG_INIT_FAILED;
620 }
621
622 for (unsigned int i = 0; i < AM335XGPIO_NUM_GPIO_PORTS; ++i) {
623 am335xgpio_gpio_port_mmap_addr[i] = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
624 MAP_SHARED, dev_mem_fd, am335xgpio_gpio_port_hw_addr[i]);
625
626 if (am335xgpio_gpio_port_mmap_addr[i] == MAP_FAILED) {
627 LOG_ERROR("mmap: %s", strerror(errno));
628 close(dev_mem_fd);
629 return ERROR_JTAG_INIT_FAILED;
630 }
631 }
632
633 /*
634 * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST as outputs.
635 * Drive TDI and TCK low, and TMS high.
636 */
637 if (transport_is_jtag()) {
638 tdo_gpio_mode = get_gpio_mode(tdo_gpio);
639 tdi_gpio_mode = get_gpio_mode(tdi_gpio);
640 tck_gpio_mode = get_gpio_mode(tck_gpio);
641 tms_gpio_mode = get_gpio_mode(tms_gpio);
642 LOG_DEBUG("saved GPIO mode for tdo (GPIO #%d): %s", tdo_gpio, get_gpio_mode_name(tdo_gpio_mode));
643 LOG_DEBUG("saved GPIO mode for tdi (GPIO #%d): %s", tdi_gpio, get_gpio_mode_name(tdi_gpio_mode));
644 LOG_DEBUG("saved GPIO mode for tck (GPIO #%d): %s", tck_gpio, get_gpio_mode_name(tck_gpio_mode));
645 LOG_DEBUG("saved GPIO mode for tms (GPIO #%d): %s", tms_gpio, get_gpio_mode_name(tms_gpio_mode));
646
647 set_gpio_mode(tdo_gpio, AM335XGPIO_GPIO_MODE_INPUT);
648 set_gpio_mode(tdi_gpio, AM335XGPIO_GPIO_MODE_OUTPUT_LOW);
649 set_gpio_mode(tms_gpio, AM335XGPIO_GPIO_MODE_OUTPUT_HIGH);
650 set_gpio_mode(tck_gpio, AM335XGPIO_GPIO_MODE_OUTPUT_LOW);
651
652 if (is_gpio_valid(trst_gpio)) {
653 trst_gpio_mode = get_gpio_mode(trst_gpio);
654 LOG_DEBUG("saved GPIO mode for trst (GPIO #%d): %s", trst_gpio, get_gpio_mode_name(trst_gpio_mode));
655 }
656 }
657
658 if (transport_is_swd()) {
659 swclk_gpio_mode = get_gpio_mode(swclk_gpio);
660 swdio_gpio_mode = get_gpio_mode(swdio_gpio);
661 LOG_DEBUG("saved GPIO mode for swclk (GPIO #%d): %s", swclk_gpio, get_gpio_mode_name(swclk_gpio_mode));
662 LOG_DEBUG("saved GPIO mode for swdio (GPIO #%d): %s", swdio_gpio, get_gpio_mode_name(swdio_gpio_mode));
663 if (is_gpio_valid(swdio_dir_gpio)) {
664 swdio_dir_gpio_mode = get_gpio_mode(swdio_dir_gpio);
665 LOG_DEBUG("saved GPIO mode for swdio_dir (GPIO #%d): %s",
666 swdio_dir_gpio, get_gpio_mode_name(swdio_dir_gpio_mode));
667 set_gpio_mode(swdio_dir_gpio,
668 swdio_dir_is_active_high ? AM335XGPIO_GPIO_MODE_OUTPUT_HIGH : AM335XGPIO_GPIO_MODE_OUTPUT_LOW);
669
670 }
671 set_gpio_mode(swdio_gpio, AM335XGPIO_GPIO_MODE_OUTPUT_LOW);
672 set_gpio_mode(swclk_gpio, AM335XGPIO_GPIO_MODE_OUTPUT_LOW);
673 }
674
675 if (is_gpio_valid(srst_gpio)) {
676 srst_gpio_mode = get_gpio_mode(srst_gpio);
677 LOG_DEBUG("saved GPIO mode for srst (GPIO #%d): %s", srst_gpio, get_gpio_mode_name(srst_gpio_mode));
678 }
679
680 if (is_gpio_valid(led_gpio)) {
681 led_gpio_mode = get_gpio_mode(led_gpio);
682 LOG_DEBUG("saved GPIO mode for led (GPIO #%d): %s", led_gpio, get_gpio_mode_name(led_gpio_mode));
683 set_gpio_mode(led_gpio,
684 led_is_active_high ? AM335XGPIO_GPIO_MODE_OUTPUT_LOW : AM335XGPIO_GPIO_MODE_OUTPUT_HIGH);
685 }
686
687 /* Set GPIO modes for TRST and SRST and make both inactive */
688 am335xgpio_reset(0, 0);
689 return ERROR_OK;
690 }
691
692 static int am335xgpio_quit(void)
693 {
694 if (transport_is_jtag()) {
695 set_gpio_mode(tdo_gpio, tdo_gpio_mode);
696 set_gpio_mode(tdi_gpio, tdi_gpio_mode);
697 set_gpio_mode(tck_gpio, tck_gpio_mode);
698 set_gpio_mode(tms_gpio, tms_gpio_mode);
699 if (is_gpio_valid(trst_gpio))
700 set_gpio_mode(trst_gpio, trst_gpio_mode);
701 }
702
703 if (transport_is_swd()) {
704 set_gpio_mode(swclk_gpio, swclk_gpio_mode);
705 set_gpio_mode(swdio_gpio, swdio_gpio_mode);
706 if (is_gpio_valid(swdio_dir_gpio))
707 set_gpio_mode(swdio_dir_gpio, swdio_dir_gpio_mode);
708 }
709
710 if (is_gpio_valid(srst_gpio))
711 set_gpio_mode(srst_gpio, srst_gpio_mode);
712
713 if (is_gpio_valid(led_gpio))
714 set_gpio_mode(led_gpio, led_gpio_mode);
715
716 return ERROR_OK;
717 }
718
719 struct adapter_driver am335xgpio_adapter_driver = {
720 .name = "am335xgpio",
721 .transports = am335xgpio_transports,
722 .commands = am335xgpio_command_handlers,
723
724 .init = am335xgpio_init,
725 .quit = am335xgpio_quit,
726 .reset = am335xgpio_reset,
727 .speed = am335xgpio_speed,
728 .khz = am335xgpio_khz,
729 .speed_div = am335xgpio_speed_div,
730
731 .jtag_ops = &am335xgpio_interface,
732 .swd_ops = &bitbang_swd,
733 };

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)