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

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)