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, see <http://www.gnu.org/licenses/>. *
20 ***************************************************************************/
26 #include <jtag/interface.h>
31 uint32_t bcm2835_peri_base
= 0x20000000;
32 #define BCM2835_GPIO_BASE (bcm2835_peri_base + 0x200000) /* GPIO controller */
34 #define BCM2835_PADS_GPIO_0_27 (bcm2835_peri_base + 0x100000)
35 #define BCM2835_PADS_GPIO_0_27_OFFSET (0x2c / 4)
37 /* GPIO setup macros */
38 #define MODE_GPIO(g) (*(pio_base+((g)/10))>>(((g)%10)*3) & 7)
39 #define INP_GPIO(g) do { *(pio_base+((g)/10)) &= ~(7<<(((g)%10)*3)); } while (0)
40 #define SET_MODE_GPIO(g, m) do { /* clear the mode bits first, then set as necessary */ \
42 *(pio_base+((g)/10)) |= ((m)<<(((g)%10)*3)); } while (0)
43 #define OUT_GPIO(g) SET_MODE_GPIO(g, 1)
45 #define GPIO_SET (*(pio_base+7)) /* sets bits which are 1, ignores bits which are 0 */
46 #define GPIO_CLR (*(pio_base+10)) /* clears bits which are 1, ignores bits which are 0 */
47 #define GPIO_LEV (*(pio_base+13)) /* current level of the pin */
49 static int dev_mem_fd
;
50 static volatile uint32_t *pio_base
;
52 static bb_value_t
bcm2835gpio_read(void);
53 static int bcm2835gpio_write(int tck
, int tms
, int tdi
);
54 static int bcm2835gpio_reset(int trst
, int srst
);
56 static int bcm2835_swdio_read(void);
57 static void bcm2835_swdio_drive(bool is_output
);
59 static int bcm2835gpio_init(void);
60 static int bcm2835gpio_quit(void);
62 static struct bitbang_interface bcm2835gpio_bitbang
= {
63 .read
= bcm2835gpio_read
,
64 .write
= bcm2835gpio_write
,
65 .reset
= bcm2835gpio_reset
,
66 .swdio_read
= bcm2835_swdio_read
,
67 .swdio_drive
= bcm2835_swdio_drive
,
71 /* GPIO numbers for each signal. Negative values are invalid */
72 static int tck_gpio
= -1;
73 static int tck_gpio_mode
;
74 static int tms_gpio
= -1;
75 static int tms_gpio_mode
;
76 static int tdi_gpio
= -1;
77 static int tdi_gpio_mode
;
78 static int tdo_gpio
= -1;
79 static int tdo_gpio_mode
;
80 static int trst_gpio
= -1;
81 static int trst_gpio_mode
;
82 static int srst_gpio
= -1;
83 static int srst_gpio_mode
;
84 static int swclk_gpio
= -1;
85 static int swclk_gpio_mode
;
86 static int swdio_gpio
= -1;
87 static int swdio_gpio_mode
;
89 /* Transition delay coefficients */
90 static int speed_coeff
= 113714;
91 static int speed_offset
= 28;
92 static unsigned int jtag_delay
;
94 static bb_value_t
bcm2835gpio_read(void)
96 return (GPIO_LEV
& 1<<tdo_gpio
) ? BB_HIGH
: BB_LOW
;
99 static int bcm2835gpio_write(int tck
, int tms
, int tdi
)
101 uint32_t set
= tck
<<tck_gpio
| tms
<<tms_gpio
| tdi
<<tdi_gpio
;
102 uint32_t clear
= !tck
<<tck_gpio
| !tms
<<tms_gpio
| !tdi
<<tdi_gpio
;
107 for (unsigned int i
= 0; i
< jtag_delay
; i
++)
113 static int 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
++)
127 /* (1) assert or (0) deassert reset lines */
128 static int bcm2835gpio_reset(int trst
, int srst
)
134 set
|= !trst
<<trst_gpio
;
135 clear
|= trst
<<trst_gpio
;
139 set
|= !srst
<<srst_gpio
;
140 clear
|= srst
<<srst_gpio
;
149 static void bcm2835_swdio_drive(bool is_output
)
152 OUT_GPIO(swdio_gpio
);
154 INP_GPIO(swdio_gpio
);
157 static int bcm2835_swdio_read(void)
159 return !!(GPIO_LEV
& 1 << swdio_gpio
);
162 static int bcm2835gpio_khz(int khz
, int *jtag_speed
)
165 LOG_DEBUG("RCLK not supported");
168 *jtag_speed
= speed_coeff
/khz
- speed_offset
;
174 static int bcm2835gpio_speed_div(int speed
, int *khz
)
176 *khz
= speed_coeff
/(speed
+ speed_offset
);
180 static int bcm2835gpio_speed(int speed
)
186 static int is_gpio_valid(int gpio
)
188 return gpio
>= 0 && gpio
<= 53;
191 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionums
)
194 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tck_gpio
);
195 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], tms_gpio
);
196 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[2], tdi_gpio
);
197 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[3], tdo_gpio
);
198 } else if (CMD_ARGC
!= 0) {
199 return ERROR_COMMAND_SYNTAX_ERROR
;
202 command_print(CMD_CTX
,
203 "BCM2835 GPIO config: tck = %d, tms = %d, tdi = %d, tdo = %d",
204 tck_gpio
, tms_gpio
, tdi_gpio
, tdo_gpio
);
209 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tck
)
212 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tck_gpio
);
214 command_print(CMD_CTX
, "BCM2835 GPIO config: tck = %d", tck_gpio
);
218 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tms
)
221 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tms_gpio
);
223 command_print(CMD_CTX
, "BCM2835 GPIO config: tms = %d", tms_gpio
);
227 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tdo
)
230 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tdo_gpio
);
232 command_print(CMD_CTX
, "BCM2835 GPIO config: tdo = %d", tdo_gpio
);
236 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_tdi
)
239 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tdi_gpio
);
241 command_print(CMD_CTX
, "BCM2835 GPIO config: tdi = %d", tdi_gpio
);
245 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_srst
)
248 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], srst_gpio
);
250 command_print(CMD_CTX
, "BCM2835 GPIO config: srst = %d", srst_gpio
);
254 COMMAND_HANDLER(bcm2835gpio_handle_jtag_gpionum_trst
)
257 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], trst_gpio
);
259 command_print(CMD_CTX
, "BCM2835 GPIO config: trst = %d", trst_gpio
);
263 COMMAND_HANDLER(bcm2835gpio_handle_swd_gpionums
)
266 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swclk_gpio
);
267 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], swdio_gpio
);
268 } else if (CMD_ARGC
!= 0) {
269 return ERROR_COMMAND_SYNTAX_ERROR
;
272 command_print(CMD_CTX
,
273 "BCM2835 GPIO nums: swclk = %d, swdio = %d",
274 swclk_gpio
, swdio_gpio
);
279 COMMAND_HANDLER(bcm2835gpio_handle_swd_gpionum_swclk
)
282 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swclk_gpio
);
284 command_print(CMD_CTX
, "BCM2835 num: swclk = %d", swclk_gpio
);
288 COMMAND_HANDLER(bcm2835gpio_handle_swd_gpionum_swdio
)
291 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swdio_gpio
);
293 command_print(CMD_CTX
, "BCM2835 num: swdio = %d", swdio_gpio
);
297 COMMAND_HANDLER(bcm2835gpio_handle_speed_coeffs
)
300 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], speed_coeff
);
301 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], speed_offset
);
304 command_print(CMD_CTX
, "BCM2835 GPIO: speed_coeffs = %d, speed_offset = %d",
305 speed_coeff
, speed_offset
);
309 COMMAND_HANDLER(bcm2835gpio_handle_peripheral_base
)
312 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], bcm2835_peri_base
);
314 command_print(CMD_CTX
, "BCM2835 GPIO: peripheral_base = 0x%08x",
319 static const struct command_registration bcm2835gpio_command_handlers
[] = {
321 .name
= "bcm2835gpio_jtag_nums",
322 .handler
= &bcm2835gpio_handle_jtag_gpionums
,
323 .mode
= COMMAND_CONFIG
,
324 .help
= "gpio numbers for tck, tms, tdi, tdo. (in that order)",
325 .usage
= "[tck tms tdi tdo]",
328 .name
= "bcm2835gpio_tck_num",
329 .handler
= &bcm2835gpio_handle_jtag_gpionum_tck
,
330 .mode
= COMMAND_CONFIG
,
331 .help
= "gpio number for tck.",
335 .name
= "bcm2835gpio_tms_num",
336 .handler
= &bcm2835gpio_handle_jtag_gpionum_tms
,
337 .mode
= COMMAND_CONFIG
,
338 .help
= "gpio number for tms.",
342 .name
= "bcm2835gpio_tdo_num",
343 .handler
= &bcm2835gpio_handle_jtag_gpionum_tdo
,
344 .mode
= COMMAND_CONFIG
,
345 .help
= "gpio number for tdo.",
349 .name
= "bcm2835gpio_tdi_num",
350 .handler
= &bcm2835gpio_handle_jtag_gpionum_tdi
,
351 .mode
= COMMAND_CONFIG
,
352 .help
= "gpio number for tdi.",
356 .name
= "bcm2835gpio_swd_nums",
357 .handler
= &bcm2835gpio_handle_swd_gpionums
,
358 .mode
= COMMAND_CONFIG
,
359 .help
= "gpio numbers for swclk, swdio. (in that order)",
360 .usage
= "[swclk swdio]",
363 .name
= "bcm2835gpio_swclk_num",
364 .handler
= &bcm2835gpio_handle_swd_gpionum_swclk
,
365 .mode
= COMMAND_CONFIG
,
366 .help
= "gpio number for swclk.",
370 .name
= "bcm2835gpio_swdio_num",
371 .handler
= &bcm2835gpio_handle_swd_gpionum_swdio
,
372 .mode
= COMMAND_CONFIG
,
373 .help
= "gpio number for swdio.",
377 .name
= "bcm2835gpio_srst_num",
378 .handler
= &bcm2835gpio_handle_jtag_gpionum_srst
,
379 .mode
= COMMAND_CONFIG
,
380 .help
= "gpio number for srst.",
384 .name
= "bcm2835gpio_trst_num",
385 .handler
= &bcm2835gpio_handle_jtag_gpionum_trst
,
386 .mode
= COMMAND_CONFIG
,
387 .help
= "gpio number for trst.",
391 .name
= "bcm2835gpio_speed_coeffs",
392 .handler
= &bcm2835gpio_handle_speed_coeffs
,
393 .mode
= COMMAND_CONFIG
,
394 .help
= "SPEED_COEFF and SPEED_OFFSET for delay calculations.",
395 .usage
= "[SPEED_COEFF SPEED_OFFSET]",
398 .name
= "bcm2835gpio_peripheral_base",
399 .handler
= &bcm2835gpio_handle_peripheral_base
,
400 .mode
= COMMAND_CONFIG
,
401 .help
= "peripheral base to access GPIOs (RPi1 0x20000000, RPi2 0x3F000000).",
405 COMMAND_REGISTRATION_DONE
408 static const char * const bcm2835_transports
[] = { "jtag", "swd", NULL
};
410 struct jtag_interface bcm2835gpio_interface
= {
411 .name
= "bcm2835gpio",
412 .supported
= DEBUG_CAP_TMS_SEQ
,
413 .execute_queue
= bitbang_execute_queue
,
414 .transports
= bcm2835_transports
,
416 .speed
= bcm2835gpio_speed
,
417 .khz
= bcm2835gpio_khz
,
418 .speed_div
= bcm2835gpio_speed_div
,
419 .commands
= bcm2835gpio_command_handlers
,
420 .init
= bcm2835gpio_init
,
421 .quit
= bcm2835gpio_quit
,
424 static bool bcm2835gpio_jtag_mode_possible(void)
426 if (!is_gpio_valid(tck_gpio
))
428 if (!is_gpio_valid(tms_gpio
))
430 if (!is_gpio_valid(tdi_gpio
))
432 if (!is_gpio_valid(tdo_gpio
))
437 static bool bcm2835gpio_swd_mode_possible(void)
439 if (!is_gpio_valid(swclk_gpio
))
441 if (!is_gpio_valid(swdio_gpio
))
446 static int bcm2835gpio_init(void)
448 bitbang_interface
= &bcm2835gpio_bitbang
;
450 LOG_INFO("BCM2835 GPIO JTAG/SWD bitbang driver");
452 if (bcm2835gpio_jtag_mode_possible()) {
453 if (bcm2835gpio_swd_mode_possible())
454 LOG_INFO("JTAG and SWD modes enabled");
456 LOG_INFO("JTAG only mode enabled (specify swclk and swdio gpio to add SWD mode)");
457 } else if (bcm2835gpio_swd_mode_possible()) {
458 LOG_INFO("SWD only mode enabled (specify tck, tms, tdi and tdo gpios to add JTAG mode)");
460 LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode and/or swclk and swdio gpio for SWD mode");
461 return ERROR_JTAG_INIT_FAILED
;
464 dev_mem_fd
= open("/dev/mem", O_RDWR
| O_SYNC
);
465 if (dev_mem_fd
< 0) {
467 return ERROR_JTAG_INIT_FAILED
;
470 pio_base
= mmap(NULL
, sysconf(_SC_PAGE_SIZE
), PROT_READ
| PROT_WRITE
,
471 MAP_SHARED
, dev_mem_fd
, BCM2835_GPIO_BASE
);
473 if (pio_base
== MAP_FAILED
) {
476 return ERROR_JTAG_INIT_FAILED
;
479 static volatile uint32_t *pads_base
;
480 pads_base
= mmap(NULL
, sysconf(_SC_PAGE_SIZE
), PROT_READ
| PROT_WRITE
,
481 MAP_SHARED
, dev_mem_fd
, BCM2835_PADS_GPIO_0_27
);
483 if (pads_base
== MAP_FAILED
) {
486 return ERROR_JTAG_INIT_FAILED
;
489 /* set 4mA drive strength, slew rate limited, hysteresis on */
490 pads_base
[BCM2835_PADS_GPIO_0_27_OFFSET
] = 0x5a000008 + 1;
492 tdo_gpio_mode
= MODE_GPIO(tdo_gpio
);
493 tdi_gpio_mode
= MODE_GPIO(tdi_gpio
);
494 tck_gpio_mode
= MODE_GPIO(tck_gpio
);
495 tms_gpio_mode
= MODE_GPIO(tms_gpio
);
496 swclk_gpio_mode
= MODE_GPIO(swclk_gpio
);
497 swdio_gpio_mode
= MODE_GPIO(swdio_gpio
);
499 * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
500 * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high.
504 GPIO_CLR
= 1<<tdi_gpio
| 1<<tck_gpio
| 1<<swdio_gpio
| 1<<swclk_gpio
;
505 GPIO_SET
= 1<<tms_gpio
;
510 OUT_GPIO(swclk_gpio
);
511 OUT_GPIO(swdio_gpio
);
512 if (trst_gpio
!= -1) {
513 trst_gpio_mode
= MODE_GPIO(trst_gpio
);
514 GPIO_SET
= 1 << trst_gpio
;
517 if (srst_gpio
!= -1) {
518 srst_gpio_mode
= MODE_GPIO(srst_gpio
);
519 GPIO_SET
= 1 << srst_gpio
;
523 LOG_DEBUG("saved pinmux settings: tck %d tms %d tdi %d "
524 "tdo %d trst %d srst %d", tck_gpio_mode
, tms_gpio_mode
,
525 tdi_gpio_mode
, tdo_gpio_mode
, trst_gpio_mode
, srst_gpio_mode
);
528 bcm2835gpio_bitbang
.write
= bcm2835gpio_swd_write
;
529 bitbang_switch_to_swd();
535 static int bcm2835gpio_quit(void)
537 SET_MODE_GPIO(tdo_gpio
, tdo_gpio_mode
);
538 SET_MODE_GPIO(tdi_gpio
, tdi_gpio_mode
);
539 SET_MODE_GPIO(tck_gpio
, tck_gpio_mode
);
540 SET_MODE_GPIO(tms_gpio
, tms_gpio_mode
);
541 SET_MODE_GPIO(swclk_gpio
, swclk_gpio_mode
);
542 SET_MODE_GPIO(swdio_gpio
, swdio_gpio_mode
);
544 SET_MODE_GPIO(trst_gpio
, trst_gpio_mode
);
546 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)