1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2017 by Grzegorz Kostka, kostka.grzegorz@gmail.com *
6 * Based on bcm2835gpio.c *
7 ***************************************************************************/
13 #include <jtag/interface.h>
14 #include <transport/transport.h>
19 #define IMX_GPIO_BASE 0x0209c000
20 #define IMX_GPIO_SIZE 0x00004000
21 #define IMX_GPIO_REGS_COUNT 8
23 static uint32_t imx_gpio_peri_base
= IMX_GPIO_BASE
;
25 struct imx_gpio_regs
{
34 } __attribute__((aligned(IMX_GPIO_SIZE
)));
36 static int dev_mem_fd
;
37 static volatile struct imx_gpio_regs
*pio_base
;
39 /* GPIO setup functions */
40 static inline bool gpio_mode_get(int g
)
42 return pio_base
[g
/ 32].gdir
>> (g
& 0x1F) & 1;
45 static inline void gpio_mode_input_set(int g
)
47 pio_base
[g
/ 32].gdir
&= ~(1u << (g
& 0x1F));
50 static inline void gpio_mode_output_set(int g
)
52 pio_base
[g
/ 32].gdir
|= (1u << (g
& 0x1F));
55 static inline void gpio_mode_set(int g
, int m
)
57 (m
) ? gpio_mode_output_set(g
) : gpio_mode_input_set(g
);
60 static inline void gpio_set(int g
)
62 pio_base
[g
/ 32].dr
|= (1u << (g
& 0x1F));
65 static inline void gpio_clear(int g
)
67 pio_base
[g
/ 32].dr
&= ~(1u << (g
& 0x1F));
70 static inline bool gpio_level(int g
)
72 return pio_base
[g
/ 32].dr
>> (g
& 0x1F) & 1;
75 static bb_value_t
imx_gpio_read(void);
76 static int imx_gpio_write(int tck
, int tms
, int tdi
);
78 static int imx_gpio_swdio_read(void);
79 static void imx_gpio_swdio_drive(bool is_output
);
80 static int imx_gpio_swd_write(int swclk
, int swdio
);
82 static int imx_gpio_init(void);
83 static int imx_gpio_quit(void);
85 static struct bitbang_interface imx_gpio_bitbang
= {
86 .read
= imx_gpio_read
,
87 .write
= imx_gpio_write
,
88 .swdio_read
= imx_gpio_swdio_read
,
89 .swdio_drive
= imx_gpio_swdio_drive
,
90 .swd_write
= imx_gpio_swd_write
,
94 /* GPIO numbers for each signal. Negative values are invalid */
95 static int tck_gpio
= -1;
96 static int tck_gpio_mode
;
97 static int tms_gpio
= -1;
98 static int tms_gpio_mode
;
99 static int tdi_gpio
= -1;
100 static int tdi_gpio_mode
;
101 static int tdo_gpio
= -1;
102 static int tdo_gpio_mode
;
103 static int trst_gpio
= -1;
104 static int trst_gpio_mode
;
105 static int srst_gpio
= -1;
106 static int srst_gpio_mode
;
107 static int swclk_gpio
= -1;
108 static int swclk_gpio_mode
;
109 static int swdio_gpio
= -1;
110 static int swdio_gpio_mode
;
112 /* Transition delay coefficients. Tuned for IMX6UL 528MHz. Adjusted
113 * experimentally for:10kHz, 100Khz, 500KHz. Speeds above 800Khz are impossible
114 * to reach via memory mapped method (at least for IMX6UL@528MHz).
115 * Measured mmap raw GPIO toggling speed on IMX6UL@528MHz: 1.3MHz.
117 static int speed_coeff
= 50000;
118 static int speed_offset
= 100;
119 static unsigned int jtag_delay
;
121 static bb_value_t
imx_gpio_read(void)
123 return gpio_level(tdo_gpio
) ? BB_HIGH
: BB_LOW
;
126 static int imx_gpio_write(int tck
, int tms
, int tdi
)
128 tms
? gpio_set(tms_gpio
) : gpio_clear(tms_gpio
);
129 tdi
? gpio_set(tdi_gpio
) : gpio_clear(tdi_gpio
);
130 tck
? gpio_set(tck_gpio
) : gpio_clear(tck_gpio
);
132 for (unsigned int i
= 0; i
< jtag_delay
; i
++)
138 static int imx_gpio_swd_write(int swclk
, int swdio
)
140 swdio
? gpio_set(swdio_gpio
) : gpio_clear(swdio_gpio
);
141 swclk
? gpio_set(swclk_gpio
) : gpio_clear(swclk_gpio
);
143 for (unsigned int i
= 0; i
< jtag_delay
; i
++)
149 /* (1) assert or (0) deassert reset lines */
150 static int imx_gpio_reset(int trst
, int srst
)
153 trst
? gpio_clear(trst_gpio
) : gpio_set(trst_gpio
);
156 srst
? gpio_clear(srst_gpio
) : gpio_set(srst_gpio
);
161 static void imx_gpio_swdio_drive(bool is_output
)
164 gpio_mode_output_set(swdio_gpio
);
166 gpio_mode_input_set(swdio_gpio
);
169 static int imx_gpio_swdio_read(void)
171 return gpio_level(swdio_gpio
);
174 static int imx_gpio_khz(int khz
, int *jtag_speed
)
177 LOG_DEBUG("RCLK not supported");
180 *jtag_speed
= speed_coeff
/khz
- speed_offset
;
186 static int imx_gpio_speed_div(int speed
, int *khz
)
188 *khz
= speed_coeff
/(speed
+ speed_offset
);
192 static int imx_gpio_speed(int speed
)
198 static int is_gpio_valid(int gpio
)
200 return gpio
>= 0 && gpio
< 32 * IMX_GPIO_REGS_COUNT
;
203 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionums
)
206 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tck_gpio
);
207 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], tms_gpio
);
208 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[2], tdi_gpio
);
209 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[3], tdo_gpio
);
210 } else if (CMD_ARGC
!= 0) {
211 return ERROR_COMMAND_SYNTAX_ERROR
;
215 "imx_gpio GPIO config: tck = %d, tms = %d, tdi = %d, tdo = %d",
216 tck_gpio
, tms_gpio
, tdi_gpio
, tdo_gpio
);
221 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tck
)
224 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tck_gpio
);
226 command_print(CMD
, "imx_gpio GPIO config: tck = %d", tck_gpio
);
230 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tms
)
233 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tms_gpio
);
235 command_print(CMD
, "imx_gpio GPIO config: tms = %d", tms_gpio
);
239 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tdo
)
242 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tdo_gpio
);
244 command_print(CMD
, "imx_gpio GPIO config: tdo = %d", tdo_gpio
);
248 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tdi
)
251 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tdi_gpio
);
253 command_print(CMD
, "imx_gpio GPIO config: tdi = %d", tdi_gpio
);
257 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_srst
)
260 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], srst_gpio
);
262 command_print(CMD
, "imx_gpio GPIO config: srst = %d", srst_gpio
);
266 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_trst
)
269 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], trst_gpio
);
271 command_print(CMD
, "imx_gpio GPIO config: trst = %d", trst_gpio
);
275 COMMAND_HANDLER(imx_gpio_handle_swd_gpionums
)
278 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swclk_gpio
);
279 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], swdio_gpio
);
280 } else if (CMD_ARGC
!= 0) {
281 return ERROR_COMMAND_SYNTAX_ERROR
;
285 "imx_gpio GPIO nums: swclk = %d, swdio = %d",
286 swclk_gpio
, swdio_gpio
);
291 COMMAND_HANDLER(imx_gpio_handle_swd_gpionum_swclk
)
294 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swclk_gpio
);
296 command_print(CMD
, "imx_gpio num: swclk = %d", swclk_gpio
);
300 COMMAND_HANDLER(imx_gpio_handle_swd_gpionum_swdio
)
303 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swdio_gpio
);
305 command_print(CMD
, "imx_gpio num: swdio = %d", swdio_gpio
);
309 COMMAND_HANDLER(imx_gpio_handle_speed_coeffs
)
312 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], speed_coeff
);
313 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], speed_offset
);
316 command_print(CMD
, "imx_gpio: speed_coeffs = %d, speed_offset = %d",
317 speed_coeff
, speed_offset
);
321 COMMAND_HANDLER(imx_gpio_handle_peripheral_base
)
324 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], imx_gpio_peri_base
);
326 command_print(CMD
, "imx_gpio: peripheral_base = 0x%08x",
331 static const struct command_registration imx_gpio_command_handlers
[] = {
333 .name
= "imx_gpio_jtag_nums",
334 .handler
= &imx_gpio_handle_jtag_gpionums
,
335 .mode
= COMMAND_CONFIG
,
336 .help
= "gpio numbers for tck, tms, tdi, tdo. (in that order)",
337 .usage
= "[tck tms tdi tdo]",
340 .name
= "imx_gpio_tck_num",
341 .handler
= &imx_gpio_handle_jtag_gpionum_tck
,
342 .mode
= COMMAND_CONFIG
,
343 .help
= "gpio number for tck.",
347 .name
= "imx_gpio_tms_num",
348 .handler
= &imx_gpio_handle_jtag_gpionum_tms
,
349 .mode
= COMMAND_CONFIG
,
350 .help
= "gpio number for tms.",
354 .name
= "imx_gpio_tdo_num",
355 .handler
= &imx_gpio_handle_jtag_gpionum_tdo
,
356 .mode
= COMMAND_CONFIG
,
357 .help
= "gpio number for tdo.",
361 .name
= "imx_gpio_tdi_num",
362 .handler
= &imx_gpio_handle_jtag_gpionum_tdi
,
363 .mode
= COMMAND_CONFIG
,
364 .help
= "gpio number for tdi.",
368 .name
= "imx_gpio_swd_nums",
369 .handler
= &imx_gpio_handle_swd_gpionums
,
370 .mode
= COMMAND_CONFIG
,
371 .help
= "gpio numbers for swclk, swdio. (in that order)",
372 .usage
= "[swclk swdio]",
375 .name
= "imx_gpio_swclk_num",
376 .handler
= &imx_gpio_handle_swd_gpionum_swclk
,
377 .mode
= COMMAND_CONFIG
,
378 .help
= "gpio number for swclk.",
382 .name
= "imx_gpio_swdio_num",
383 .handler
= &imx_gpio_handle_swd_gpionum_swdio
,
384 .mode
= COMMAND_CONFIG
,
385 .help
= "gpio number for swdio.",
389 .name
= "imx_gpio_srst_num",
390 .handler
= &imx_gpio_handle_jtag_gpionum_srst
,
391 .mode
= COMMAND_CONFIG
,
392 .help
= "gpio number for srst.",
396 .name
= "imx_gpio_trst_num",
397 .handler
= &imx_gpio_handle_jtag_gpionum_trst
,
398 .mode
= COMMAND_CONFIG
,
399 .help
= "gpio number for trst.",
403 .name
= "imx_gpio_speed_coeffs",
404 .handler
= &imx_gpio_handle_speed_coeffs
,
405 .mode
= COMMAND_CONFIG
,
406 .help
= "SPEED_COEFF and SPEED_OFFSET for delay calculations.",
407 .usage
= "[SPEED_COEFF SPEED_OFFSET]",
410 .name
= "imx_gpio_peripheral_base",
411 .handler
= &imx_gpio_handle_peripheral_base
,
412 .mode
= COMMAND_CONFIG
,
413 .help
= "peripheral base to access GPIOs (0x0209c000 for most IMX).",
417 COMMAND_REGISTRATION_DONE
420 static const char * const imx_gpio_transports
[] = { "jtag", "swd", NULL
};
422 static struct jtag_interface imx_gpio_interface
= {
423 .supported
= DEBUG_CAP_TMS_SEQ
,
424 .execute_queue
= bitbang_execute_queue
,
427 struct adapter_driver imx_gpio_adapter_driver
= {
429 .transports
= imx_gpio_transports
,
430 .commands
= imx_gpio_command_handlers
,
432 .init
= imx_gpio_init
,
433 .quit
= imx_gpio_quit
,
434 .reset
= imx_gpio_reset
,
435 .speed
= imx_gpio_speed
,
437 .speed_div
= imx_gpio_speed_div
,
439 .jtag_ops
= &imx_gpio_interface
,
440 .swd_ops
= &bitbang_swd
,
443 static bool imx_gpio_jtag_mode_possible(void)
445 if (!is_gpio_valid(tck_gpio
))
447 if (!is_gpio_valid(tms_gpio
))
449 if (!is_gpio_valid(tdi_gpio
))
451 if (!is_gpio_valid(tdo_gpio
))
456 static bool imx_gpio_swd_mode_possible(void)
458 if (!is_gpio_valid(swclk_gpio
))
460 if (!is_gpio_valid(swdio_gpio
))
465 static int imx_gpio_init(void)
467 bitbang_interface
= &imx_gpio_bitbang
;
469 LOG_INFO("imx_gpio GPIO JTAG/SWD bitbang driver");
471 if (transport_is_jtag() && !imx_gpio_jtag_mode_possible()) {
472 LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode");
473 return ERROR_JTAG_INIT_FAILED
;
476 if (transport_is_swd() && !imx_gpio_swd_mode_possible()) {
477 LOG_ERROR("Require swclk and swdio gpio for SWD mode");
478 return ERROR_JTAG_INIT_FAILED
;
481 dev_mem_fd
= open("/dev/mem", O_RDWR
| O_SYNC
);
482 if (dev_mem_fd
< 0) {
483 LOG_ERROR("open: %s", strerror(errno
));
484 return ERROR_JTAG_INIT_FAILED
;
487 LOG_INFO("imx_gpio mmap: pagesize: %u, regionsize: %u",
488 (unsigned int) sysconf(_SC_PAGE_SIZE
), IMX_GPIO_REGS_COUNT
* IMX_GPIO_SIZE
);
489 pio_base
= mmap(NULL
, IMX_GPIO_REGS_COUNT
* IMX_GPIO_SIZE
,
490 PROT_READ
| PROT_WRITE
,
491 MAP_SHARED
, dev_mem_fd
, imx_gpio_peri_base
);
493 if (pio_base
== MAP_FAILED
) {
494 LOG_ERROR("mmap: %s", strerror(errno
));
496 return ERROR_JTAG_INIT_FAILED
;
500 * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
501 * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high.
503 if (transport_is_jtag()) {
504 tdo_gpio_mode
= gpio_mode_get(tdo_gpio
);
505 tdi_gpio_mode
= gpio_mode_get(tdi_gpio
);
506 tck_gpio_mode
= gpio_mode_get(tck_gpio
);
507 tms_gpio_mode
= gpio_mode_get(tms_gpio
);
509 gpio_clear(tdi_gpio
);
510 gpio_clear(tck_gpio
);
513 gpio_mode_input_set(tdo_gpio
);
514 gpio_mode_output_set(tdi_gpio
);
515 gpio_mode_output_set(tck_gpio
);
516 gpio_mode_output_set(tms_gpio
);
518 if (trst_gpio
!= -1) {
519 trst_gpio_mode
= gpio_mode_get(trst_gpio
);
521 gpio_mode_output_set(trst_gpio
);
525 if (transport_is_swd()) {
526 swclk_gpio_mode
= gpio_mode_get(swclk_gpio
);
527 swdio_gpio_mode
= gpio_mode_get(swdio_gpio
);
529 gpio_clear(swdio_gpio
);
530 gpio_clear(swclk_gpio
);
531 gpio_mode_output_set(swclk_gpio
);
532 gpio_mode_output_set(swdio_gpio
);
535 if (srst_gpio
!= -1) {
536 srst_gpio_mode
= gpio_mode_get(srst_gpio
);
538 gpio_mode_output_set(srst_gpio
);
541 LOG_DEBUG("saved pinmux settings: tck %d tms %d tdi %d "
542 "tdo %d trst %d srst %d", tck_gpio_mode
, tms_gpio_mode
,
543 tdi_gpio_mode
, tdo_gpio_mode
, trst_gpio_mode
, srst_gpio_mode
);
548 static int imx_gpio_quit(void)
550 if (transport_is_jtag()) {
551 gpio_mode_set(tdo_gpio
, tdo_gpio_mode
);
552 gpio_mode_set(tdi_gpio
, tdi_gpio_mode
);
553 gpio_mode_set(tck_gpio
, tck_gpio_mode
);
554 gpio_mode_set(tms_gpio
, tms_gpio_mode
);
557 gpio_mode_set(trst_gpio
, trst_gpio_mode
);
560 if (transport_is_swd()) {
561 gpio_mode_set(swclk_gpio
, swclk_gpio_mode
);
562 gpio_mode_set(swdio_gpio
, swdio_gpio_mode
);
566 gpio_mode_set(srst_gpio
, srst_gpio_mode
);
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)