1 /***************************************************************************
2 * Copyright (C) 2013 by Paul Fertser, fercerpav@gmail.com *
4 * Copyright (C) 2012 by Creative Product Design, marc @ cpdesign.com.au *
5 * Based on at91rm9200.c (c) Anders Larsen *
6 * and RPi GPIO examples by Gert van Loo & Dom *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
22 ***************************************************************************/
28 #include <jtag/interface.h>
33 uint32_t bcm2835_peri_base
= 0x20000000;
34 #define BCM2835_GPIO_BASE (bcm2835_peri_base + 0x200000) /* GPIO controller */
36 #define BCM2835_PADS_GPIO_0_27 (bcm2835_peri_base + 0x100000)
37 #define BCM2835_PADS_GPIO_0_27_OFFSET (0x2c / 4)
39 /* GPIO setup macros */
40 #define MODE_GPIO(g) (*(pio_base+((g)/10))>>(((g)%10)*3) & 7)
41 #define INP_GPIO(g) do { *(pio_base+((g)/10)) &= ~(7<<(((g)%10)*3)); } while (0)
42 #define SET_MODE_GPIO(g, m) do { /* clear the mode bits first, then set as necessary */ \
44 *(pio_base+((g)/10)) |= ((m)<<(((g)%10)*3)); } while (0)
45 #define OUT_GPIO(g) SET_MODE_GPIO(g, 1)
47 #define GPIO_SET (*(pio_base+7)) /* sets bits which are 1, ignores bits which are 0 */
48 #define GPIO_CLR (*(pio_base+10)) /* clears bits which are 1, ignores bits which are 0 */
49 #define GPIO_LEV (*(pio_base+13)) /* current level of the pin */
51 static int dev_mem_fd
;
52 static volatile uint32_t *pio_base
;
54 static int bcm2835gpio_read(void);
55 static void bcm2835gpio_write(int tck
, int tms
, int tdi
);
56 static void bcm2835gpio_reset(int trst
, int srst
);
58 static int bcm2835_swdio_read(void);
59 static void bcm2835_swdio_drive(bool is_output
);
61 static int bcm2835gpio_init(void);
62 static int bcm2835gpio_quit(void);
64 static struct bitbang_interface bcm2835gpio_bitbang
= {
65 .read
= bcm2835gpio_read
,
66 .write
= bcm2835gpio_write
,
67 .reset
= bcm2835gpio_reset
,
68 .swdio_read
= bcm2835_swdio_read
,
69 .swdio_drive
= bcm2835_swdio_drive
,
73 /* GPIO numbers for each signal. Negative values are invalid */
74 static int tck_gpio
= -1;
75 static int tck_gpio_mode
;
76 static int tms_gpio
= -1;
77 static int tms_gpio_mode
;
78 static int tdi_gpio
= -1;
79 static int tdi_gpio_mode
;
80 static int tdo_gpio
= -1;
81 static int tdo_gpio_mode
;
82 static int trst_gpio
= -1;
83 static int trst_gpio_mode
;
84 static int srst_gpio
= -1;
85 static int srst_gpio_mode
;
86 static int swclk_gpio
= -1;
87 static int swclk_gpio_mode
;
88 static int swdio_gpio
= -1;
89 static int swdio_gpio_mode
;
91 /* Transition delay coefficients */
92 static int speed_coeff
= 113714;
93 static int speed_offset
= 28;
94 static unsigned int jtag_delay
;
96 static int bcm2835gpio_read(void)
98 return !!(GPIO_LEV
& 1<<tdo_gpio
);
101 static void bcm2835gpio_write(int tck
, int tms
, int tdi
)
103 uint32_t set
= tck
<<tck_gpio
| tms
<<tms_gpio
| tdi
<<tdi_gpio
;
104 uint32_t clear
= !tck
<<tck_gpio
| !tms
<<tms_gpio
| !tdi
<<tdi_gpio
;
109 for (unsigned int i
= 0; i
< jtag_delay
; i
++)
113 static void bcm2835gpio_swd_write(int tck
, int tms
, int tdi
)
115 uint32_t set
= tck
<<swclk_gpio
| tdi
<<swdio_gpio
;
116 uint32_t clear
= !tck
<<swclk_gpio
| !tdi
<<swdio_gpio
;
121 for (unsigned int i
= 0; i
< jtag_delay
; i
++)
125 /* (1) assert or (0) deassert reset lines */
126 static void bcm2835gpio_reset(int trst
, int srst
)
132 set
|= !trst
<<trst_gpio
;
133 clear
|= trst
<<trst_gpio
;
137 set
|= !srst
<<srst_gpio
;
138 clear
|= srst
<<srst_gpio
;
145 static void bcm2835_swdio_drive(bool is_output
)
148 OUT_GPIO(swdio_gpio
);
150 INP_GPIO(swdio_gpio
);
153 static int bcm2835_swdio_read(void)
155 return !!(GPIO_LEV
& 1 << swdio_gpio
);
158 static int bcm2835gpio_khz(int khz
, int *jtag_speed
)
161 LOG_DEBUG("RCLK not supported");
164 *jtag_speed
= speed_coeff
/khz
- speed_offset
;
170 static int bcm2835gpio_speed_div(int speed
, int *khz
)
172 *khz
= speed_coeff
/(speed
+ speed_offset
);
176 static int bcm2835gpio_speed(int speed
)
182 static int is_gpio_valid(int gpio
)
184 return gpio
>= 0 && gpio
<= 53;
187 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionums
)
190 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tck_gpio
);
191 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], tms_gpio
);
192 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[2], tdi_gpio
);
193 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[3], tdo_gpio
);
194 } else if (CMD_ARGC
!= 0) {
195 return ERROR_COMMAND_SYNTAX_ERROR
;
198 command_print(CMD_CTX
,
199 "BCM2835 GPIO config: tck = %d, tms = %d, tdi = %d, tdo = %d",
200 tck_gpio
, tms_gpio
, tdi_gpio
, tdo_gpio
);
205 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tck
)
208 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tck_gpio
);
210 command_print(CMD_CTX
, "BCM2835 GPIO config: tck = %d", tck_gpio
);
214 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tms
)
217 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tms_gpio
);
219 command_print(CMD_CTX
, "BCM2835 GPIO config: tms = %d", tms_gpio
);
223 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tdo
)
226 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tdo_gpio
);
228 command_print(CMD_CTX
, "BCM2835 GPIO config: tdo = %d", tdo_gpio
);
232 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tdi
)
235 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tdi_gpio
);
237 command_print(CMD_CTX
, "BCM2835 GPIO config: tdi = %d", tdi_gpio
);
241 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_srst
)
244 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], srst_gpio
);
246 command_print(CMD_CTX
, "BCM2835 GPIO config: srst = %d", srst_gpio
);
250 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_trst
)
253 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], trst_gpio
);
255 command_print(CMD_CTX
, "BCM2835 GPIO config: trst = %d", trst_gpio
);
259 COMMAND_HANDLER(bcm2835gpio_handle_swd_gpionums
)
262 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swclk_gpio
);
263 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], swdio_gpio
);
264 } else if (CMD_ARGC
!= 0) {
265 return ERROR_COMMAND_SYNTAX_ERROR
;
268 command_print(CMD_CTX
,
269 "BCM2835 GPIO nums: swclk = %d, swdio = %d",
270 swclk_gpio
, swdio_gpio
);
275 COMMAND_HANDLER(bcm2835gpio_handle_swd_gpionum_swclk
)
278 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swclk_gpio
);
280 command_print(CMD_CTX
, "BCM2835 num: swclk = %d", swclk_gpio
);
284 COMMAND_HANDLER(bcm2835gpio_handle_swd_gpionum_swdio
)
287 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swdio_gpio
);
289 command_print(CMD_CTX
, "BCM2835 num: swdio = %d", swdio_gpio
);
293 COMMAND_HANDLER(bcm2835gpio_handle_speed_coeffs
)
296 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], speed_coeff
);
297 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], speed_offset
);
302 COMMAND_HANDLER(bcm2835gpio_handle_peripheral_base
)
305 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], bcm2835_peri_base
);
309 static const struct command_registration bcm2835gpio_command_handlers
[] = {
311 .name
= "bcm2835gpio_jtag_nums",
312 .handler
= &bcm2835gpio_handle_jtag_gpionums
,
313 .mode
= COMMAND_CONFIG
,
314 .help
= "gpio numbers for tck, tms, tdi, tdo. (in that order)",
315 .usage
= "(tck tms tdi tdo)* ",
318 .name
= "bcm2835gpio_tck_num",
319 .handler
= &bcm2835gpio_handle_jtag_gpionum_tck
,
320 .mode
= COMMAND_CONFIG
,
321 .help
= "gpio number for tck.",
324 .name
= "bcm2835gpio_tms_num",
325 .handler
= &bcm2835gpio_handle_jtag_gpionum_tms
,
326 .mode
= COMMAND_CONFIG
,
327 .help
= "gpio number for tms.",
330 .name
= "bcm2835gpio_tdo_num",
331 .handler
= &bcm2835gpio_handle_jtag_gpionum_tdo
,
332 .mode
= COMMAND_CONFIG
,
333 .help
= "gpio number for tdo.",
336 .name
= "bcm2835gpio_tdi_num",
337 .handler
= &bcm2835gpio_handle_jtag_gpionum_tdi
,
338 .mode
= COMMAND_CONFIG
,
339 .help
= "gpio number for tdi.",
342 .name
= "bcm2835gpio_swd_nums",
343 .handler
= &bcm2835gpio_handle_swd_gpionums
,
344 .mode
= COMMAND_CONFIG
,
345 .help
= "gpio numbers for swclk, swdio. (in that order)",
346 .usage
= "(swclk swdio)* ",
349 .name
= "bcm2835gpio_swclk_num",
350 .handler
= &bcm2835gpio_handle_swd_gpionum_swclk
,
351 .mode
= COMMAND_CONFIG
,
352 .help
= "gpio number for swclk.",
355 .name
= "bcm2835gpio_swdio_num",
356 .handler
= &bcm2835gpio_handle_swd_gpionum_swdio
,
357 .mode
= COMMAND_CONFIG
,
358 .help
= "gpio number for swdio.",
361 .name
= "bcm2835gpio_srst_num",
362 .handler
= &bcm2835gpio_handle_jtag_gpionum_srst
,
363 .mode
= COMMAND_CONFIG
,
364 .help
= "gpio number for srst.",
367 .name
= "bcm2835gpio_trst_num",
368 .handler
= &bcm2835gpio_handle_jtag_gpionum_trst
,
369 .mode
= COMMAND_CONFIG
,
370 .help
= "gpio number for trst.",
373 .name
= "bcm2835gpio_speed_coeffs",
374 .handler
= &bcm2835gpio_handle_speed_coeffs
,
375 .mode
= COMMAND_CONFIG
,
376 .help
= "SPEED_COEFF and SPEED_OFFSET for delay calculations.",
379 .name
= "bcm2835gpio_peripheral_base",
380 .handler
= &bcm2835gpio_handle_peripheral_base
,
381 .mode
= COMMAND_CONFIG
,
382 .help
= "peripheral base to access GPIOs (RPi1 0x20000000, RPi2 0x3F000000).",
385 COMMAND_REGISTRATION_DONE
388 static const char * const bcm2835_transports
[] = { "jtag", "swd", NULL
};
390 struct jtag_interface bcm2835gpio_interface
= {
391 .name
= "bcm2835gpio",
392 .supported
= DEBUG_CAP_TMS_SEQ
,
393 .execute_queue
= bitbang_execute_queue
,
394 .transports
= bcm2835_transports
,
396 .speed
= bcm2835gpio_speed
,
397 .khz
= bcm2835gpio_khz
,
398 .speed_div
= bcm2835gpio_speed_div
,
399 .commands
= bcm2835gpio_command_handlers
,
400 .init
= bcm2835gpio_init
,
401 .quit
= bcm2835gpio_quit
,
404 static bool bcm2835gpio_jtag_mode_possible(void)
406 if (!is_gpio_valid(tck_gpio
))
408 if (!is_gpio_valid(tms_gpio
))
410 if (!is_gpio_valid(tdi_gpio
))
412 if (!is_gpio_valid(tdo_gpio
))
417 static bool bcm2835gpio_swd_mode_possible(void)
419 if (!is_gpio_valid(swclk_gpio
))
421 if (!is_gpio_valid(swdio_gpio
))
426 static int bcm2835gpio_init(void)
428 bitbang_interface
= &bcm2835gpio_bitbang
;
430 LOG_INFO("BCM2835 GPIO JTAG/SWD bitbang driver");
432 if (bcm2835gpio_jtag_mode_possible()) {
433 if (bcm2835gpio_swd_mode_possible())
434 LOG_INFO("JTAG and SWD modes enabled");
436 LOG_INFO("JTAG only mode enabled (specify swclk and swdio gpio to add SWD mode)");
437 if (!is_gpio_valid(trst_gpio
) && !is_gpio_valid(srst_gpio
)) {
438 LOG_ERROR("Require at least one of trst or srst gpios to be specified");
439 return ERROR_JTAG_INIT_FAILED
;
441 } else if (bcm2835gpio_swd_mode_possible()) {
442 LOG_INFO("SWD only mode enabled (specify tck, tms, tdi and tdo gpios to add JTAG mode)");
444 LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode and/or swclk and swdio gpio for SWD mode");
445 return ERROR_JTAG_INIT_FAILED
;
448 dev_mem_fd
= open("/dev/mem", O_RDWR
| O_SYNC
);
449 if (dev_mem_fd
< 0) {
451 return ERROR_JTAG_INIT_FAILED
;
454 pio_base
= mmap(NULL
, sysconf(_SC_PAGE_SIZE
), PROT_READ
| PROT_WRITE
,
455 MAP_SHARED
, dev_mem_fd
, BCM2835_GPIO_BASE
);
457 if (pio_base
== MAP_FAILED
) {
460 return ERROR_JTAG_INIT_FAILED
;
463 static volatile uint32_t *pads_base
;
464 pads_base
= mmap(NULL
, sysconf(_SC_PAGE_SIZE
), PROT_READ
| PROT_WRITE
,
465 MAP_SHARED
, dev_mem_fd
, BCM2835_PADS_GPIO_0_27
);
467 if (pads_base
== MAP_FAILED
) {
470 return ERROR_JTAG_INIT_FAILED
;
473 /* set 16mA drive strength */
474 pads_base
[BCM2835_PADS_GPIO_0_27_OFFSET
] = 0x5a000018 + 7;
476 tdo_gpio_mode
= MODE_GPIO(tdo_gpio
);
477 tdi_gpio_mode
= MODE_GPIO(tdi_gpio
);
478 tck_gpio_mode
= MODE_GPIO(tck_gpio
);
479 tms_gpio_mode
= MODE_GPIO(tms_gpio
);
480 swclk_gpio_mode
= MODE_GPIO(swclk_gpio
);
481 swdio_gpio_mode
= MODE_GPIO(swdio_gpio
);
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.
488 GPIO_CLR
= 1<<tdi_gpio
| 1<<tck_gpio
| 1<<swdio_gpio
| 1<<swclk_gpio
;
489 GPIO_SET
= 1<<tms_gpio
;
494 OUT_GPIO(swclk_gpio
);
495 OUT_GPIO(swdio_gpio
);
496 if (trst_gpio
!= -1) {
497 trst_gpio_mode
= MODE_GPIO(trst_gpio
);
498 GPIO_SET
= 1 << trst_gpio
;
501 if (srst_gpio
!= -1) {
502 srst_gpio_mode
= MODE_GPIO(srst_gpio
);
503 GPIO_SET
= 1 << srst_gpio
;
507 LOG_DEBUG("saved pinmux settings: tck %d tms %d tdi %d "
508 "tdo %d trst %d srst %d", tck_gpio_mode
, tms_gpio_mode
,
509 tdi_gpio_mode
, tdo_gpio_mode
, trst_gpio_mode
, srst_gpio_mode
);
512 bcm2835gpio_bitbang
.write
= bcm2835gpio_swd_write
;
513 bitbang_switch_to_swd();
519 static int bcm2835gpio_quit(void)
521 SET_MODE_GPIO(tdo_gpio
, tdo_gpio_mode
);
522 SET_MODE_GPIO(tdi_gpio
, tdi_gpio_mode
);
523 SET_MODE_GPIO(tck_gpio
, tck_gpio_mode
);
524 SET_MODE_GPIO(tms_gpio
, tms_gpio_mode
);
525 SET_MODE_GPIO(swclk_gpio
, swclk_gpio_mode
);
526 SET_MODE_GPIO(swdio_gpio
, swdio_gpio_mode
);
528 SET_MODE_GPIO(trst_gpio
, trst_gpio_mode
);
530 SET_MODE_GPIO(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)