1 /***************************************************************************
2 * Copyright (C) 2017 by Grzegorz Kostka, kostka.grzegorz@gmail.com *
4 * Based on bcm2835gpio.c *
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. *
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. *
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 ***************************************************************************/
24 #include <jtag/interface.h>
29 #define IMX_GPIO_BASE 0x0209c000
30 #define IMX_GPIO_SIZE 0x00004000
31 #define IMX_GPIO_REGS_COUNT 8
33 static uint32_t imx_gpio_peri_base
= IMX_GPIO_BASE
;
35 struct imx_gpio_regs
{
44 } __attribute__((aligned(IMX_GPIO_SIZE
)));
46 static int dev_mem_fd
;
47 static volatile struct imx_gpio_regs
*pio_base
;
49 /* GPIO setup functions */
50 static inline bool gpio_mode_get(int g
)
52 return pio_base
[g
/ 32].gdir
>> (g
& 0x1F) & 1;
55 static inline void gpio_mode_input_set(int g
)
57 pio_base
[g
/ 32].gdir
&= ~(1u << (g
& 0x1F));
60 static inline void gpio_mode_output_set(int g
)
62 pio_base
[g
/ 32].gdir
|= (1u << (g
& 0x1F));
65 static inline void gpio_mode_set(int g
, int m
)
67 (m
) ? gpio_mode_output_set(g
) : gpio_mode_input_set(g
);
70 static inline void gpio_set(int g
)
72 pio_base
[g
/ 32].dr
|= (1u << (g
& 0x1F));
75 static inline void gpio_clear(int g
)
77 pio_base
[g
/ 32].dr
&= ~(1u << (g
& 0x1F));
80 static inline bool gpio_level(int g
)
82 return pio_base
[g
/ 32].dr
>> (g
& 0x1F) & 1;
85 static bb_value_t
imx_gpio_read(void);
86 static int imx_gpio_write(int tck
, int tms
, int tdi
);
88 static int imx_gpio_swdio_read(void);
89 static void imx_gpio_swdio_drive(bool is_output
);
90 static int imx_gpio_swd_write(int swclk
, int swdio
);
92 static int imx_gpio_init(void);
93 static int imx_gpio_quit(void);
95 static struct bitbang_interface imx_gpio_bitbang
= {
96 .read
= imx_gpio_read
,
97 .write
= imx_gpio_write
,
98 .swdio_read
= imx_gpio_swdio_read
,
99 .swdio_drive
= imx_gpio_swdio_drive
,
100 .swd_write
= imx_gpio_swd_write
,
104 /* GPIO numbers for each signal. Negative values are invalid */
105 static int tck_gpio
= -1;
106 static int tck_gpio_mode
;
107 static int tms_gpio
= -1;
108 static int tms_gpio_mode
;
109 static int tdi_gpio
= -1;
110 static int tdi_gpio_mode
;
111 static int tdo_gpio
= -1;
112 static int tdo_gpio_mode
;
113 static int trst_gpio
= -1;
114 static int trst_gpio_mode
;
115 static int srst_gpio
= -1;
116 static int srst_gpio_mode
;
117 static int swclk_gpio
= -1;
118 static int swclk_gpio_mode
;
119 static int swdio_gpio
= -1;
120 static int swdio_gpio_mode
;
122 /* Transition delay coefficients. Tuned for IMX6UL 528MHz. Adjusted
123 * experimentally for:10kHz, 100Khz, 500KHz. Speeds above 800Khz are impossible
124 * to reach via memory mapped method (at least for IMX6UL@528MHz).
125 * Measured mmap raw GPIO toggling speed on IMX6UL@528MHz: 1.3MHz.
127 static int speed_coeff
= 50000;
128 static int speed_offset
= 100;
129 static unsigned int jtag_delay
;
131 static bb_value_t
imx_gpio_read(void)
133 return gpio_level(tdo_gpio
) ? BB_HIGH
: BB_LOW
;
136 static int imx_gpio_write(int tck
, int tms
, int tdi
)
138 tms
? gpio_set(tms_gpio
) : gpio_clear(tms_gpio
);
139 tdi
? gpio_set(tdi_gpio
) : gpio_clear(tdi_gpio
);
140 tck
? gpio_set(tck_gpio
) : gpio_clear(tck_gpio
);
142 for (unsigned int i
= 0; i
< jtag_delay
; i
++)
148 static int imx_gpio_swd_write(int swclk
, int swdio
)
150 swdio
? gpio_set(swdio_gpio
) : gpio_clear(swdio_gpio
);
151 swclk
? gpio_set(swclk_gpio
) : gpio_clear(swclk_gpio
);
153 for (unsigned int i
= 0; i
< jtag_delay
; i
++)
159 /* (1) assert or (0) deassert reset lines */
160 static int imx_gpio_reset(int trst
, int srst
)
163 trst
? gpio_clear(trst_gpio
) : gpio_set(trst_gpio
);
166 srst
? gpio_clear(srst_gpio
) : gpio_set(srst_gpio
);
171 static void imx_gpio_swdio_drive(bool is_output
)
174 gpio_mode_output_set(swdio_gpio
);
176 gpio_mode_input_set(swdio_gpio
);
179 static int imx_gpio_swdio_read(void)
181 return gpio_level(swdio_gpio
);
184 static int imx_gpio_khz(int khz
, int *jtag_speed
)
187 LOG_DEBUG("RCLK not supported");
190 *jtag_speed
= speed_coeff
/khz
- speed_offset
;
196 static int imx_gpio_speed_div(int speed
, int *khz
)
198 *khz
= speed_coeff
/(speed
+ speed_offset
);
202 static int imx_gpio_speed(int speed
)
208 static int is_gpio_valid(int gpio
)
210 return gpio
>= 0 && gpio
< 32 * IMX_GPIO_REGS_COUNT
;
213 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionums
)
216 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tck_gpio
);
217 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], tms_gpio
);
218 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[2], tdi_gpio
);
219 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[3], tdo_gpio
);
220 } else if (CMD_ARGC
!= 0) {
221 return ERROR_COMMAND_SYNTAX_ERROR
;
225 "imx_gpio GPIO config: tck = %d, tms = %d, tdi = %d, tdo = %d",
226 tck_gpio
, tms_gpio
, tdi_gpio
, tdo_gpio
);
231 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tck
)
234 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tck_gpio
);
236 command_print(CMD
, "imx_gpio GPIO config: tck = %d", tck_gpio
);
240 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tms
)
243 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tms_gpio
);
245 command_print(CMD
, "imx_gpio GPIO config: tms = %d", tms_gpio
);
249 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tdo
)
252 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tdo_gpio
);
254 command_print(CMD
, "imx_gpio GPIO config: tdo = %d", tdo_gpio
);
258 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tdi
)
261 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tdi_gpio
);
263 command_print(CMD
, "imx_gpio GPIO config: tdi = %d", tdi_gpio
);
267 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_srst
)
270 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], srst_gpio
);
272 command_print(CMD
, "imx_gpio GPIO config: srst = %d", srst_gpio
);
276 COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_trst
)
279 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], trst_gpio
);
281 command_print(CMD
, "imx_gpio GPIO config: trst = %d", trst_gpio
);
285 COMMAND_HANDLER(imx_gpio_handle_swd_gpionums
)
288 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swclk_gpio
);
289 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], swdio_gpio
);
290 } else if (CMD_ARGC
!= 0) {
291 return ERROR_COMMAND_SYNTAX_ERROR
;
295 "imx_gpio GPIO nums: swclk = %d, swdio = %d",
296 swclk_gpio
, swdio_gpio
);
301 COMMAND_HANDLER(imx_gpio_handle_swd_gpionum_swclk
)
304 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swclk_gpio
);
306 command_print(CMD
, "imx_gpio num: swclk = %d", swclk_gpio
);
310 COMMAND_HANDLER(imx_gpio_handle_swd_gpionum_swdio
)
313 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swdio_gpio
);
315 command_print(CMD
, "imx_gpio num: swdio = %d", swdio_gpio
);
319 COMMAND_HANDLER(imx_gpio_handle_speed_coeffs
)
322 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], speed_coeff
);
323 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], speed_offset
);
326 command_print(CMD
, "imx_gpio: speed_coeffs = %d, speed_offset = %d",
327 speed_coeff
, speed_offset
);
331 COMMAND_HANDLER(imx_gpio_handle_peripheral_base
)
334 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], imx_gpio_peri_base
);
336 command_print(CMD
, "imx_gpio: peripheral_base = 0x%08x",
341 static const struct command_registration imx_gpio_command_handlers
[] = {
343 .name
= "imx_gpio_jtag_nums",
344 .handler
= &imx_gpio_handle_jtag_gpionums
,
345 .mode
= COMMAND_CONFIG
,
346 .help
= "gpio numbers for tck, tms, tdi, tdo. (in that order)",
347 .usage
= "[tck tms tdi tdo]",
350 .name
= "imx_gpio_tck_num",
351 .handler
= &imx_gpio_handle_jtag_gpionum_tck
,
352 .mode
= COMMAND_CONFIG
,
353 .help
= "gpio number for tck.",
357 .name
= "imx_gpio_tms_num",
358 .handler
= &imx_gpio_handle_jtag_gpionum_tms
,
359 .mode
= COMMAND_CONFIG
,
360 .help
= "gpio number for tms.",
364 .name
= "imx_gpio_tdo_num",
365 .handler
= &imx_gpio_handle_jtag_gpionum_tdo
,
366 .mode
= COMMAND_CONFIG
,
367 .help
= "gpio number for tdo.",
371 .name
= "imx_gpio_tdi_num",
372 .handler
= &imx_gpio_handle_jtag_gpionum_tdi
,
373 .mode
= COMMAND_CONFIG
,
374 .help
= "gpio number for tdi.",
378 .name
= "imx_gpio_swd_nums",
379 .handler
= &imx_gpio_handle_swd_gpionums
,
380 .mode
= COMMAND_CONFIG
,
381 .help
= "gpio numbers for swclk, swdio. (in that order)",
382 .usage
= "[swclk swdio]",
385 .name
= "imx_gpio_swclk_num",
386 .handler
= &imx_gpio_handle_swd_gpionum_swclk
,
387 .mode
= COMMAND_CONFIG
,
388 .help
= "gpio number for swclk.",
392 .name
= "imx_gpio_swdio_num",
393 .handler
= &imx_gpio_handle_swd_gpionum_swdio
,
394 .mode
= COMMAND_CONFIG
,
395 .help
= "gpio number for swdio.",
399 .name
= "imx_gpio_srst_num",
400 .handler
= &imx_gpio_handle_jtag_gpionum_srst
,
401 .mode
= COMMAND_CONFIG
,
402 .help
= "gpio number for srst.",
406 .name
= "imx_gpio_trst_num",
407 .handler
= &imx_gpio_handle_jtag_gpionum_trst
,
408 .mode
= COMMAND_CONFIG
,
409 .help
= "gpio number for trst.",
413 .name
= "imx_gpio_speed_coeffs",
414 .handler
= &imx_gpio_handle_speed_coeffs
,
415 .mode
= COMMAND_CONFIG
,
416 .help
= "SPEED_COEFF and SPEED_OFFSET for delay calculations.",
417 .usage
= "[SPEED_COEFF SPEED_OFFSET]",
420 .name
= "imx_gpio_peripheral_base",
421 .handler
= &imx_gpio_handle_peripheral_base
,
422 .mode
= COMMAND_CONFIG
,
423 .help
= "peripheral base to access GPIOs (0x0209c000 for most IMX).",
427 COMMAND_REGISTRATION_DONE
430 static const char * const imx_gpio_transports
[] = { "jtag", "swd", NULL
};
432 static struct jtag_interface imx_gpio_interface
= {
433 .supported
= DEBUG_CAP_TMS_SEQ
,
434 .execute_queue
= bitbang_execute_queue
,
437 struct adapter_driver imx_gpio_adapter_driver
= {
439 .transports
= imx_gpio_transports
,
440 .commands
= imx_gpio_command_handlers
,
442 .init
= imx_gpio_init
,
443 .quit
= imx_gpio_quit
,
444 .reset
= imx_gpio_reset
,
445 .speed
= imx_gpio_speed
,
447 .speed_div
= imx_gpio_speed_div
,
449 .jtag_ops
= &imx_gpio_interface
,
450 .swd_ops
= &bitbang_swd
,
453 static bool imx_gpio_jtag_mode_possible(void)
455 if (!is_gpio_valid(tck_gpio
))
457 if (!is_gpio_valid(tms_gpio
))
459 if (!is_gpio_valid(tdi_gpio
))
461 if (!is_gpio_valid(tdo_gpio
))
466 static bool imx_gpio_swd_mode_possible(void)
468 if (!is_gpio_valid(swclk_gpio
))
470 if (!is_gpio_valid(swdio_gpio
))
475 static int imx_gpio_init(void)
477 bitbang_interface
= &imx_gpio_bitbang
;
479 LOG_INFO("imx_gpio GPIO JTAG/SWD bitbang driver");
481 if (imx_gpio_jtag_mode_possible()) {
482 if (imx_gpio_swd_mode_possible())
483 LOG_INFO("JTAG and SWD modes enabled");
485 LOG_INFO("JTAG only mode enabled (specify swclk and swdio gpio to add SWD mode)");
486 } else if (imx_gpio_swd_mode_possible()) {
487 LOG_INFO("SWD only mode enabled (specify tck, tms, tdi and tdo gpios to add JTAG mode)");
489 LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode and/or swclk and swdio gpio for SWD mode");
490 return ERROR_JTAG_INIT_FAILED
;
493 dev_mem_fd
= open("/dev/mem", O_RDWR
| O_SYNC
);
494 if (dev_mem_fd
< 0) {
496 return ERROR_JTAG_INIT_FAILED
;
500 LOG_INFO("imx_gpio mmap: pagesize: %u, regionsize: %u",
501 (unsigned int) sysconf(_SC_PAGE_SIZE
), IMX_GPIO_REGS_COUNT
* IMX_GPIO_SIZE
);
502 pio_base
= mmap(NULL
, IMX_GPIO_REGS_COUNT
* IMX_GPIO_SIZE
,
503 PROT_READ
| PROT_WRITE
,
504 MAP_SHARED
, dev_mem_fd
, imx_gpio_peri_base
);
506 if (pio_base
== MAP_FAILED
) {
509 return ERROR_JTAG_INIT_FAILED
;
513 * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
514 * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high.
516 if (imx_gpio_jtag_mode_possible()) {
517 tdo_gpio_mode
= gpio_mode_get(tdo_gpio
);
518 tdi_gpio_mode
= gpio_mode_get(tdi_gpio
);
519 tck_gpio_mode
= gpio_mode_get(tck_gpio
);
520 tms_gpio_mode
= gpio_mode_get(tms_gpio
);
522 gpio_clear(tdi_gpio
);
523 gpio_clear(tck_gpio
);
526 gpio_mode_input_set(tdo_gpio
);
527 gpio_mode_output_set(tdi_gpio
);
528 gpio_mode_output_set(tck_gpio
);
529 gpio_mode_output_set(tms_gpio
);
531 if (imx_gpio_swd_mode_possible()) {
532 swclk_gpio_mode
= gpio_mode_get(swclk_gpio
);
533 swdio_gpio_mode
= gpio_mode_get(swdio_gpio
);
535 gpio_clear(swdio_gpio
);
536 gpio_clear(swclk_gpio
);
537 gpio_mode_output_set(swclk_gpio
);
538 gpio_mode_output_set(swdio_gpio
);
540 if (trst_gpio
!= -1) {
541 trst_gpio_mode
= gpio_mode_get(trst_gpio
);
543 gpio_mode_output_set(trst_gpio
);
545 if (srst_gpio
!= -1) {
546 srst_gpio_mode
= gpio_mode_get(srst_gpio
);
548 gpio_mode_output_set(srst_gpio
);
551 LOG_DEBUG("saved pinmux settings: tck %d tms %d tdi %d "
552 "tdo %d trst %d srst %d", tck_gpio_mode
, tms_gpio_mode
,
553 tdi_gpio_mode
, tdo_gpio_mode
, trst_gpio_mode
, srst_gpio_mode
);
558 static int imx_gpio_quit(void)
560 if (imx_gpio_jtag_mode_possible()) {
561 gpio_mode_set(tdo_gpio
, tdo_gpio_mode
);
562 gpio_mode_set(tdi_gpio
, tdi_gpio_mode
);
563 gpio_mode_set(tck_gpio
, tck_gpio_mode
);
564 gpio_mode_set(tms_gpio
, tms_gpio_mode
);
566 if (imx_gpio_swd_mode_possible()) {
567 gpio_mode_set(swclk_gpio
, swclk_gpio_mode
);
568 gpio_mode_set(swdio_gpio
, swdio_gpio_mode
);
571 gpio_mode_set(trst_gpio
, trst_gpio_mode
);
573 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)