1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2013 by Paul Fertser, fercerpav@gmail.com *
6 * Copyright (C) 2012 by Creative Product Design, marc @ cpdesign.com.au *
7 * Based on at91rm9200.c (c) Anders Larsen *
8 * and RPi GPIO examples by Gert van Loo & Dom *
9 ***************************************************************************/
15 #include <jtag/adapter.h>
16 #include <jtag/interface.h>
17 #include <transport/transport.h>
22 uint32_t bcm2835_peri_base
= 0x20000000;
23 #define BCM2835_GPIO_BASE (bcm2835_peri_base + 0x200000) /* GPIO controller */
25 #define BCM2835_PADS_GPIO_0_27 (bcm2835_peri_base + 0x100000)
26 #define BCM2835_PADS_GPIO_0_27_OFFSET (0x2c / 4)
28 /* See "GPIO Function Select Registers (GPFSELn)" in "Broadcom BCM2835 ARM Peripherals" datasheet. */
29 #define BCM2835_GPIO_MODE_INPUT 0
30 #define BCM2835_GPIO_MODE_OUTPUT 1
32 /* GPIO setup macros */
33 #define MODE_GPIO(g) (*(pio_base+((g)/10))>>(((g)%10)*3) & 7)
34 #define INP_GPIO(g) do { *(pio_base+((g)/10)) &= ~(7<<(((g)%10)*3)); } while (0)
35 #define SET_MODE_GPIO(g, m) do { /* clear the mode bits first, then set as necessary */ \
37 *(pio_base+((g)/10)) |= ((m)<<(((g)%10)*3)); } while (0)
38 #define OUT_GPIO(g) SET_MODE_GPIO(g, BCM2835_GPIO_MODE_OUTPUT)
40 #define GPIO_SET (*(pio_base+7)) /* sets bits which are 1, ignores bits which are 0 */
41 #define GPIO_CLR (*(pio_base+10)) /* clears bits which are 1, ignores bits which are 0 */
42 #define GPIO_LEV (*(pio_base+13)) /* current level of the pin */
44 static int dev_mem_fd
;
45 static volatile uint32_t *pio_base
= MAP_FAILED
;
46 static volatile uint32_t *pads_base
= MAP_FAILED
;
48 /* Transition delay coefficients */
49 static int speed_coeff
= 113714;
50 static int speed_offset
= 28;
51 static unsigned int jtag_delay
;
53 static const struct adapter_gpio_config
*adapter_gpio_config
;
54 static struct initial_gpio_state
{
56 unsigned int output_level
;
57 } initial_gpio_state
[ADAPTER_GPIO_IDX_NUM
];
58 static uint32_t initial_drive_strength_etc
;
60 static bool is_gpio_config_valid(enum adapter_gpio_config_index idx
)
62 /* Only chip 0 is supported, accept unset value (-1) too */
63 return adapter_gpio_config
[idx
].chip_num
>= -1
64 && adapter_gpio_config
[idx
].chip_num
<= 0
65 && adapter_gpio_config
[idx
].gpio_num
>= 0
66 && adapter_gpio_config
[idx
].gpio_num
<= 31;
69 static void set_gpio_value(const struct adapter_gpio_config
*gpio_config
, int value
)
71 value
= value
^ (gpio_config
->active_low
? 1 : 0);
72 switch (gpio_config
->drive
) {
73 case ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL
:
75 GPIO_SET
= 1 << gpio_config
->gpio_num
;
77 GPIO_CLR
= 1 << gpio_config
->gpio_num
;
78 /* For performance reasons assume the GPIO is already set as an output
79 * and therefore the call can be omitted here.
82 case ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN
:
84 INP_GPIO(gpio_config
->gpio_num
);
86 GPIO_CLR
= 1 << gpio_config
->gpio_num
;
87 OUT_GPIO(gpio_config
->gpio_num
);
90 case ADAPTER_GPIO_DRIVE_MODE_OPEN_SOURCE
:
92 GPIO_SET
= 1 << gpio_config
->gpio_num
;
93 OUT_GPIO(gpio_config
->gpio_num
);
95 INP_GPIO(gpio_config
->gpio_num
);
101 static void restore_gpio(enum adapter_gpio_config_index idx
)
103 if (is_gpio_config_valid(idx
)) {
104 SET_MODE_GPIO(adapter_gpio_config
[idx
].gpio_num
, initial_gpio_state
[idx
].mode
);
105 if (initial_gpio_state
[idx
].mode
== BCM2835_GPIO_MODE_OUTPUT
) {
106 if (initial_gpio_state
[idx
].output_level
)
107 GPIO_SET
= 1 << adapter_gpio_config
[idx
].gpio_num
;
109 GPIO_CLR
= 1 << adapter_gpio_config
[idx
].gpio_num
;
114 static void initialize_gpio(enum adapter_gpio_config_index idx
)
116 if (!is_gpio_config_valid(idx
))
119 initial_gpio_state
[idx
].mode
= MODE_GPIO(adapter_gpio_config
[idx
].gpio_num
);
120 unsigned int shift
= adapter_gpio_config
[idx
].gpio_num
;
121 initial_gpio_state
[idx
].output_level
= (GPIO_LEV
>> shift
) & 1;
122 LOG_DEBUG("saved GPIO mode for %s (GPIO %d %d): %d",
123 adapter_gpio_get_name(idx
), adapter_gpio_config
[idx
].chip_num
, adapter_gpio_config
[idx
].gpio_num
,
124 initial_gpio_state
[idx
].mode
);
126 if (adapter_gpio_config
[idx
].pull
!= ADAPTER_GPIO_PULL_NONE
) {
127 LOG_WARNING("BCM2835 GPIO does not support pull-up or pull-down settings (signal %s)",
128 adapter_gpio_get_name(idx
));
131 switch (adapter_gpio_config
[idx
].init_state
) {
132 case ADAPTER_GPIO_INIT_STATE_INACTIVE
:
133 set_gpio_value(&adapter_gpio_config
[idx
], 0);
135 case ADAPTER_GPIO_INIT_STATE_ACTIVE
:
136 set_gpio_value(&adapter_gpio_config
[idx
], 1);
138 case ADAPTER_GPIO_INIT_STATE_INPUT
:
139 INP_GPIO(adapter_gpio_config
[idx
].gpio_num
);
143 /* Direction for non push-pull is already set by set_gpio_value() */
144 if (adapter_gpio_config
[idx
].drive
== ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL
)
145 OUT_GPIO(adapter_gpio_config
[idx
].gpio_num
);
148 static bb_value_t
bcm2835gpio_read(void)
150 unsigned int shift
= adapter_gpio_config
[ADAPTER_GPIO_IDX_TDO
].gpio_num
;
151 uint32_t value
= (GPIO_LEV
>> shift
) & 1;
152 return value
^ (adapter_gpio_config
[ADAPTER_GPIO_IDX_TDO
].active_low
? BB_HIGH
: BB_LOW
);
156 static int bcm2835gpio_write(int tck
, int tms
, int tdi
)
158 uint32_t set
= tck
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_TCK
].gpio_num
|
159 tms
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_TMS
].gpio_num
|
160 tdi
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_TDI
].gpio_num
;
161 uint32_t clear
= !tck
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_TCK
].gpio_num
|
162 !tms
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_TMS
].gpio_num
|
163 !tdi
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_TDI
].gpio_num
;
168 for (unsigned int i
= 0; i
< jtag_delay
; i
++)
174 /* Requires push-pull drive mode for swclk and swdio */
175 static int bcm2835gpio_swd_write_fast(int swclk
, int swdio
)
177 swclk
= swclk
^ (adapter_gpio_config
[ADAPTER_GPIO_IDX_SWCLK
].active_low
? 1 : 0);
178 swdio
= swdio
^ (adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].active_low
? 1 : 0);
180 uint32_t set
= swclk
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_SWCLK
].gpio_num
|
181 swdio
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].gpio_num
;
182 uint32_t clear
= !swclk
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_SWCLK
].gpio_num
|
183 !swdio
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].gpio_num
;
188 for (unsigned int i
= 0; i
< jtag_delay
; i
++)
194 /* Generic mode that works for open-drain/open-source drive modes, but slower */
195 static int bcm2835gpio_swd_write_generic(int swclk
, int swdio
)
197 set_gpio_value(&adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
], swdio
);
198 set_gpio_value(&adapter_gpio_config
[ADAPTER_GPIO_IDX_SWCLK
], swclk
); /* Write clock last */
200 for (unsigned int i
= 0; i
< jtag_delay
; ++i
)
206 /* (1) assert or (0) deassert reset lines */
207 static int bcm2835gpio_reset(int trst
, int srst
)
209 /* As the "adapter reset_config" command keeps the srst and trst gpio drive
210 * mode settings in sync we can use our standard set_gpio_value() function
211 * that honours drive mode and active low.
213 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_SRST
))
214 set_gpio_value(&adapter_gpio_config
[ADAPTER_GPIO_IDX_SRST
], srst
);
216 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_TRST
))
217 set_gpio_value(&adapter_gpio_config
[ADAPTER_GPIO_IDX_TRST
], trst
);
219 LOG_DEBUG("BCM2835 GPIO: bcm2835gpio_reset(%d, %d), trst_gpio: %d %d, srst_gpio: %d %d",
221 adapter_gpio_config
[ADAPTER_GPIO_IDX_TRST
].chip_num
, adapter_gpio_config
[ADAPTER_GPIO_IDX_TRST
].gpio_num
,
222 adapter_gpio_config
[ADAPTER_GPIO_IDX_SRST
].chip_num
, adapter_gpio_config
[ADAPTER_GPIO_IDX_SRST
].gpio_num
);
226 static void bcm2835_swdio_drive(bool is_output
)
229 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_SWDIO_DIR
))
230 set_gpio_value(&adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO_DIR
], 1);
231 OUT_GPIO(adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].gpio_num
);
233 INP_GPIO(adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].gpio_num
);
234 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_SWDIO_DIR
))
235 set_gpio_value(&adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO_DIR
], 0);
239 static int bcm2835_swdio_read(void)
241 unsigned int shift
= adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].gpio_num
;
242 uint32_t value
= (GPIO_LEV
>> shift
) & 1;
243 return value
^ (adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].active_low
? 1 : 0);
246 static int bcm2835gpio_khz(int khz
, int *jtag_speed
)
249 LOG_DEBUG("BCM2835 GPIO: RCLK not supported");
252 *jtag_speed
= speed_coeff
/khz
- speed_offset
;
258 static int bcm2835gpio_speed_div(int speed
, int *khz
)
260 *khz
= speed_coeff
/(speed
+ speed_offset
);
264 static int bcm2835gpio_speed(int speed
)
270 COMMAND_HANDLER(bcm2835gpio_handle_speed_coeffs
)
273 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], speed_coeff
);
274 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], speed_offset
);
277 command_print(CMD
, "BCM2835 GPIO: speed_coeffs = %d, speed_offset = %d",
278 speed_coeff
, speed_offset
);
282 COMMAND_HANDLER(bcm2835gpio_handle_peripheral_base
)
285 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], bcm2835_peri_base
);
287 command_print(CMD
, "BCM2835 GPIO: peripheral_base = 0x%08x",
292 static const struct command_registration bcm2835gpio_subcommand_handlers
[] = {
294 .name
= "speed_coeffs",
295 .handler
= &bcm2835gpio_handle_speed_coeffs
,
296 .mode
= COMMAND_CONFIG
,
297 .help
= "SPEED_COEFF and SPEED_OFFSET for delay calculations.",
298 .usage
= "[SPEED_COEFF SPEED_OFFSET]",
301 .name
= "peripheral_base",
302 .handler
= &bcm2835gpio_handle_peripheral_base
,
303 .mode
= COMMAND_CONFIG
,
304 .help
= "peripheral base to access GPIOs (RPi1 0x20000000, RPi2 0x3F000000).",
308 COMMAND_REGISTRATION_DONE
311 static const struct command_registration bcm2835gpio_command_handlers
[] = {
313 .name
= "bcm2835gpio",
315 .help
= "perform bcm2835gpio management",
316 .chain
= bcm2835gpio_subcommand_handlers
,
319 COMMAND_REGISTRATION_DONE
322 static bool bcm2835gpio_jtag_mode_possible(void)
324 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TCK
))
326 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TMS
))
328 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TDI
))
330 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TDO
))
335 static bool bcm2835gpio_swd_mode_possible(void)
337 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_SWCLK
))
339 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_SWDIO
))
344 static void bcm2835gpio_munmap(void)
346 if (pio_base
!= MAP_FAILED
) {
347 munmap((void *)pio_base
, sysconf(_SC_PAGE_SIZE
));
348 pio_base
= MAP_FAILED
;
351 if (pads_base
!= MAP_FAILED
) {
352 munmap((void *)pads_base
, sysconf(_SC_PAGE_SIZE
));
353 pads_base
= MAP_FAILED
;
357 static int bcm2835gpio_blink(int on
)
359 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_LED
))
360 set_gpio_value(&adapter_gpio_config
[ADAPTER_GPIO_IDX_LED
], on
);
365 static struct bitbang_interface bcm2835gpio_bitbang
= {
366 .read
= bcm2835gpio_read
,
367 .write
= bcm2835gpio_write
,
368 .swdio_read
= bcm2835_swdio_read
,
369 .swdio_drive
= bcm2835_swdio_drive
,
370 .swd_write
= bcm2835gpio_swd_write_generic
,
371 .blink
= bcm2835gpio_blink
,
374 static int bcm2835gpio_init(void)
376 LOG_INFO("BCM2835 GPIO JTAG/SWD bitbang driver");
378 bitbang_interface
= &bcm2835gpio_bitbang
;
379 adapter_gpio_config
= adapter_gpio_get_config();
381 if (transport_is_jtag() && !bcm2835gpio_jtag_mode_possible()) {
382 LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode");
383 return ERROR_JTAG_INIT_FAILED
;
386 if (transport_is_swd() && !bcm2835gpio_swd_mode_possible()) {
387 LOG_ERROR("Require swclk and swdio gpio for SWD mode");
388 return ERROR_JTAG_INIT_FAILED
;
391 dev_mem_fd
= open("/dev/gpiomem", O_RDWR
| O_SYNC
);
392 if (dev_mem_fd
< 0) {
393 LOG_DEBUG("Cannot open /dev/gpiomem, fallback to /dev/mem");
394 dev_mem_fd
= open("/dev/mem", O_RDWR
| O_SYNC
);
396 if (dev_mem_fd
< 0) {
397 LOG_ERROR("open: %s", strerror(errno
));
398 return ERROR_JTAG_INIT_FAILED
;
401 pio_base
= mmap(NULL
, sysconf(_SC_PAGE_SIZE
), PROT_READ
| PROT_WRITE
,
402 MAP_SHARED
, dev_mem_fd
, BCM2835_GPIO_BASE
);
404 if (pio_base
== MAP_FAILED
) {
405 LOG_ERROR("mmap: %s", strerror(errno
));
407 return ERROR_JTAG_INIT_FAILED
;
410 pads_base
= mmap(NULL
, sysconf(_SC_PAGE_SIZE
), PROT_READ
| PROT_WRITE
,
411 MAP_SHARED
, dev_mem_fd
, BCM2835_PADS_GPIO_0_27
);
413 if (pads_base
== MAP_FAILED
) {
414 LOG_ERROR("mmap: %s", strerror(errno
));
415 bcm2835gpio_munmap();
417 return ERROR_JTAG_INIT_FAILED
;
422 /* set 4mA drive strength, slew rate limited, hysteresis on */
423 initial_drive_strength_etc
= pads_base
[BCM2835_PADS_GPIO_0_27_OFFSET
] & 0x1f;
424 pads_base
[BCM2835_PADS_GPIO_0_27_OFFSET
] = 0x5a000008 + 1;
426 /* Configure JTAG/SWD signals. Default directions and initial states are handled
427 * by adapter.c and "adapter gpio" command.
429 if (transport_is_jtag()) {
430 initialize_gpio(ADAPTER_GPIO_IDX_TDO
);
431 initialize_gpio(ADAPTER_GPIO_IDX_TDI
);
432 initialize_gpio(ADAPTER_GPIO_IDX_TMS
);
433 initialize_gpio(ADAPTER_GPIO_IDX_TCK
);
434 initialize_gpio(ADAPTER_GPIO_IDX_TRST
);
437 if (transport_is_swd()) {
438 /* swdio and its buffer should be initialized in the order that prevents
439 * two outputs from being connected together. This will occur if the
440 * swdio GPIO of the AM335x is configured as an output while its
441 * external buffer is configured to send the swdio signal from the
442 * target to the AM335x.
444 if (adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].init_state
== ADAPTER_GPIO_INIT_STATE_INPUT
) {
445 initialize_gpio(ADAPTER_GPIO_IDX_SWDIO
);
446 initialize_gpio(ADAPTER_GPIO_IDX_SWDIO_DIR
);
448 initialize_gpio(ADAPTER_GPIO_IDX_SWDIO_DIR
);
449 initialize_gpio(ADAPTER_GPIO_IDX_SWDIO
);
452 initialize_gpio(ADAPTER_GPIO_IDX_SWCLK
);
454 if (adapter_gpio_config
[ADAPTER_GPIO_IDX_SWCLK
].drive
== ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL
&&
455 adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].drive
== ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL
) {
456 LOG_DEBUG("BCM2835 GPIO using fast mode for SWD write");
457 bcm2835gpio_bitbang
.swd_write
= bcm2835gpio_swd_write_fast
;
459 LOG_DEBUG("BCM2835 GPIO using generic mode for SWD write");
460 bcm2835gpio_bitbang
.swd_write
= bcm2835gpio_swd_write_generic
;
464 initialize_gpio(ADAPTER_GPIO_IDX_SRST
);
465 initialize_gpio(ADAPTER_GPIO_IDX_LED
);
470 static int bcm2835gpio_quit(void)
472 if (transport_is_jtag()) {
473 restore_gpio(ADAPTER_GPIO_IDX_TDO
);
474 restore_gpio(ADAPTER_GPIO_IDX_TDI
);
475 restore_gpio(ADAPTER_GPIO_IDX_TCK
);
476 restore_gpio(ADAPTER_GPIO_IDX_TMS
);
477 restore_gpio(ADAPTER_GPIO_IDX_TRST
);
480 if (transport_is_swd()) {
481 /* Restore swdio/swdio_dir to their initial modes, even if that means
482 * connecting two outputs. Begin by making swdio an input so that the
483 * current and final states of swdio and swdio_dir do not have to be
484 * considered to calculate the safe restoration order.
486 INP_GPIO(adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].gpio_num
);
487 restore_gpio(ADAPTER_GPIO_IDX_SWDIO_DIR
);
488 restore_gpio(ADAPTER_GPIO_IDX_SWDIO
);
489 restore_gpio(ADAPTER_GPIO_IDX_SWCLK
);
492 restore_gpio(ADAPTER_GPIO_IDX_SRST
);
493 restore_gpio(ADAPTER_GPIO_IDX_LED
);
495 /* Restore drive strength. MSB is password ("5A") */
496 pads_base
[BCM2835_PADS_GPIO_0_27_OFFSET
] = 0x5A000000 | initial_drive_strength_etc
;
497 bcm2835gpio_munmap();
503 static const char * const bcm2835_transports
[] = { "jtag", "swd", NULL
};
505 static struct jtag_interface bcm2835gpio_interface
= {
506 .supported
= DEBUG_CAP_TMS_SEQ
,
507 .execute_queue
= bitbang_execute_queue
,
509 struct adapter_driver bcm2835gpio_adapter_driver
= {
510 .name
= "bcm2835gpio",
511 .transports
= bcm2835_transports
,
512 .commands
= bcm2835gpio_command_handlers
,
514 .init
= bcm2835gpio_init
,
515 .quit
= bcm2835gpio_quit
,
516 .reset
= bcm2835gpio_reset
,
517 .speed
= bcm2835gpio_speed
,
518 .khz
= bcm2835gpio_khz
,
519 .speed_div
= bcm2835gpio_speed_div
,
521 .jtag_ops
= &bcm2835gpio_interface
,
522 .swd_ops
= &bitbang_swd
,
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)