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 static char *bcm2835_peri_mem_dev
;
23 static off_t bcm2835_peri_base
= 0x20000000;
24 #define BCM2835_GPIO_BASE (bcm2835_peri_base + 0x200000) /* GPIO controller */
26 #define BCM2835_PADS_GPIO_0_27 (bcm2835_peri_base + 0x100000)
27 #define BCM2835_PADS_GPIO_0_27_OFFSET (0x2c / 4)
29 /* See "GPIO Function Select Registers (GPFSELn)" in "Broadcom BCM2835 ARM Peripherals" datasheet. */
30 #define BCM2835_GPIO_MODE_INPUT 0
31 #define BCM2835_GPIO_MODE_OUTPUT 1
33 /* GPIO setup macros */
34 #define MODE_GPIO(g) (*(pio_base+((g)/10))>>(((g)%10)*3) & 7)
35 #define INP_GPIO(g) do { *(pio_base+((g)/10)) &= ~(7<<(((g)%10)*3)); } while (0)
36 #define SET_MODE_GPIO(g, m) do { /* clear the mode bits first, then set as necessary */ \
38 *(pio_base+((g)/10)) |= ((m)<<(((g)%10)*3)); } while (0)
39 #define OUT_GPIO(g) SET_MODE_GPIO(g, BCM2835_GPIO_MODE_OUTPUT)
41 #define GPIO_SET (*(pio_base+7)) /* sets bits which are 1, ignores bits which are 0 */
42 #define GPIO_CLR (*(pio_base+10)) /* clears bits which are 1, ignores bits which are 0 */
43 #define GPIO_LEV (*(pio_base+13)) /* current level of the pin */
45 static int dev_mem_fd
;
46 static volatile uint32_t *pio_base
= MAP_FAILED
;
47 static volatile uint32_t *pads_base
= MAP_FAILED
;
49 /* Transition delay coefficients */
50 static int speed_coeff
= 113714;
51 static int speed_offset
= 28;
52 static unsigned int jtag_delay
;
54 static const struct adapter_gpio_config
*adapter_gpio_config
;
55 static struct initial_gpio_state
{
57 unsigned int output_level
;
58 } initial_gpio_state
[ADAPTER_GPIO_IDX_NUM
];
59 static uint32_t initial_drive_strength_etc
;
61 static inline const char *bcm2835_get_mem_dev(void)
63 if (bcm2835_peri_mem_dev
)
64 return bcm2835_peri_mem_dev
;
66 return "/dev/gpiomem";
69 static inline void bcm2835_gpio_synchronize(void)
71 /* Ensure that previous writes to GPIO registers are flushed out of
72 * the inner shareable domain to prevent pipelined writes to the
73 * same address being merged.
78 static inline void bcm2835_delay(void)
80 for (unsigned int i
= 0; i
< jtag_delay
; i
++)
84 static bool is_gpio_config_valid(enum adapter_gpio_config_index idx
)
86 /* Only chip 0 is supported, accept unset value (-1) too */
87 return adapter_gpio_config
[idx
].chip_num
>= -1
88 && adapter_gpio_config
[idx
].chip_num
<= 0
89 && adapter_gpio_config
[idx
].gpio_num
>= 0
90 && adapter_gpio_config
[idx
].gpio_num
<= 31;
93 static void set_gpio_value(const struct adapter_gpio_config
*gpio_config
, int value
)
95 value
= value
^ (gpio_config
->active_low
? 1 : 0);
96 switch (gpio_config
->drive
) {
97 case ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL
:
99 GPIO_SET
= 1 << gpio_config
->gpio_num
;
101 GPIO_CLR
= 1 << gpio_config
->gpio_num
;
102 /* For performance reasons assume the GPIO is already set as an output
103 * and therefore the call can be omitted here.
106 case ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN
:
108 INP_GPIO(gpio_config
->gpio_num
);
110 GPIO_CLR
= 1 << gpio_config
->gpio_num
;
111 OUT_GPIO(gpio_config
->gpio_num
);
114 case ADAPTER_GPIO_DRIVE_MODE_OPEN_SOURCE
:
116 GPIO_SET
= 1 << gpio_config
->gpio_num
;
117 OUT_GPIO(gpio_config
->gpio_num
);
119 INP_GPIO(gpio_config
->gpio_num
);
123 bcm2835_gpio_synchronize();
126 static void restore_gpio(enum adapter_gpio_config_index idx
)
128 if (is_gpio_config_valid(idx
)) {
129 SET_MODE_GPIO(adapter_gpio_config
[idx
].gpio_num
, initial_gpio_state
[idx
].mode
);
130 if (initial_gpio_state
[idx
].mode
== BCM2835_GPIO_MODE_OUTPUT
) {
131 if (initial_gpio_state
[idx
].output_level
)
132 GPIO_SET
= 1 << adapter_gpio_config
[idx
].gpio_num
;
134 GPIO_CLR
= 1 << adapter_gpio_config
[idx
].gpio_num
;
137 bcm2835_gpio_synchronize();
140 static void initialize_gpio(enum adapter_gpio_config_index idx
)
142 if (!is_gpio_config_valid(idx
))
145 initial_gpio_state
[idx
].mode
= MODE_GPIO(adapter_gpio_config
[idx
].gpio_num
);
146 unsigned int shift
= adapter_gpio_config
[idx
].gpio_num
;
147 initial_gpio_state
[idx
].output_level
= (GPIO_LEV
>> shift
) & 1;
148 LOG_DEBUG("saved GPIO mode for %s (GPIO %d %d): %d",
149 adapter_gpio_get_name(idx
), adapter_gpio_config
[idx
].chip_num
, adapter_gpio_config
[idx
].gpio_num
,
150 initial_gpio_state
[idx
].mode
);
152 if (adapter_gpio_config
[idx
].pull
!= ADAPTER_GPIO_PULL_NONE
) {
153 LOG_WARNING("BCM2835 GPIO does not support pull-up or pull-down settings (signal %s)",
154 adapter_gpio_get_name(idx
));
157 switch (adapter_gpio_config
[idx
].init_state
) {
158 case ADAPTER_GPIO_INIT_STATE_INACTIVE
:
159 set_gpio_value(&adapter_gpio_config
[idx
], 0);
161 case ADAPTER_GPIO_INIT_STATE_ACTIVE
:
162 set_gpio_value(&adapter_gpio_config
[idx
], 1);
164 case ADAPTER_GPIO_INIT_STATE_INPUT
:
165 INP_GPIO(adapter_gpio_config
[idx
].gpio_num
);
169 /* Direction for non push-pull is already set by set_gpio_value() */
170 if (adapter_gpio_config
[idx
].drive
== ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL
171 && adapter_gpio_config
[idx
].init_state
!= ADAPTER_GPIO_INIT_STATE_INPUT
)
172 OUT_GPIO(adapter_gpio_config
[idx
].gpio_num
);
173 bcm2835_gpio_synchronize();
176 static bb_value_t
bcm2835gpio_read(void)
178 unsigned int shift
= adapter_gpio_config
[ADAPTER_GPIO_IDX_TDO
].gpio_num
;
179 uint32_t value
= (GPIO_LEV
>> shift
) & 1;
180 return value
^ (adapter_gpio_config
[ADAPTER_GPIO_IDX_TDO
].active_low
? BB_HIGH
: BB_LOW
);
184 static int bcm2835gpio_write(int tck
, int tms
, int tdi
)
186 uint32_t set
= tck
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_TCK
].gpio_num
|
187 tms
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_TMS
].gpio_num
|
188 tdi
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_TDI
].gpio_num
;
189 uint32_t clear
= !tck
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_TCK
].gpio_num
|
190 !tms
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_TMS
].gpio_num
|
191 !tdi
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_TDI
].gpio_num
;
195 bcm2835_gpio_synchronize();
202 /* Requires push-pull drive mode for swclk and swdio */
203 static int bcm2835gpio_swd_write_fast(int swclk
, int swdio
)
205 swclk
= swclk
^ (adapter_gpio_config
[ADAPTER_GPIO_IDX_SWCLK
].active_low
? 1 : 0);
206 swdio
= swdio
^ (adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].active_low
? 1 : 0);
208 uint32_t set
= swclk
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_SWCLK
].gpio_num
|
209 swdio
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].gpio_num
;
210 uint32_t clear
= !swclk
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_SWCLK
].gpio_num
|
211 !swdio
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].gpio_num
;
215 bcm2835_gpio_synchronize();
222 /* Generic mode that works for open-drain/open-source drive modes, but slower */
223 static int bcm2835gpio_swd_write_generic(int swclk
, int swdio
)
225 set_gpio_value(&adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
], swdio
);
226 set_gpio_value(&adapter_gpio_config
[ADAPTER_GPIO_IDX_SWCLK
], swclk
); /* Write clock last */
233 /* (1) assert or (0) deassert reset lines */
234 static int bcm2835gpio_reset(int trst
, int srst
)
236 /* As the "adapter reset_config" command keeps the srst and trst gpio drive
237 * mode settings in sync we can use our standard set_gpio_value() function
238 * that honours drive mode and active low.
240 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_SRST
))
241 set_gpio_value(&adapter_gpio_config
[ADAPTER_GPIO_IDX_SRST
], srst
);
243 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_TRST
))
244 set_gpio_value(&adapter_gpio_config
[ADAPTER_GPIO_IDX_TRST
], trst
);
246 LOG_DEBUG("BCM2835 GPIO: bcm2835gpio_reset(%d, %d), trst_gpio: %d %d, srst_gpio: %d %d",
248 adapter_gpio_config
[ADAPTER_GPIO_IDX_TRST
].chip_num
, adapter_gpio_config
[ADAPTER_GPIO_IDX_TRST
].gpio_num
,
249 adapter_gpio_config
[ADAPTER_GPIO_IDX_SRST
].chip_num
, adapter_gpio_config
[ADAPTER_GPIO_IDX_SRST
].gpio_num
);
253 static void bcm2835_swdio_drive(bool is_output
)
256 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_SWDIO_DIR
))
257 set_gpio_value(&adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO_DIR
], 1);
258 OUT_GPIO(adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].gpio_num
);
260 INP_GPIO(adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].gpio_num
);
261 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_SWDIO_DIR
))
262 set_gpio_value(&adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO_DIR
], 0);
264 bcm2835_gpio_synchronize();
267 static int bcm2835_swdio_read(void)
269 unsigned int shift
= adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].gpio_num
;
270 uint32_t value
= (GPIO_LEV
>> shift
) & 1;
271 return value
^ (adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].active_low
? 1 : 0);
274 static int bcm2835gpio_khz(int khz
, int *jtag_speed
)
277 LOG_DEBUG("BCM2835 GPIO: RCLK not supported");
280 *jtag_speed
= DIV_ROUND_UP(speed_coeff
, khz
) - speed_offset
;
281 LOG_DEBUG("jtag_delay %d", *jtag_speed
);
287 static int bcm2835gpio_speed_div(int speed
, int *khz
)
289 int divisor
= speed
+ speed_offset
;
290 /* divide with roundig to the closest */
291 *khz
= (speed_coeff
+ divisor
/ 2) / divisor
;
295 static int bcm2835gpio_speed(int speed
)
301 COMMAND_HANDLER(bcm2835gpio_handle_speed_coeffs
)
304 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], speed_coeff
);
305 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], speed_offset
);
308 command_print(CMD
, "BCM2835 GPIO: speed_coeffs = %d, speed_offset = %d",
309 speed_coeff
, speed_offset
);
313 COMMAND_HANDLER(bcm2835gpio_handle_peripheral_mem_dev
)
316 free(bcm2835_peri_mem_dev
);
317 bcm2835_peri_mem_dev
= strdup(CMD_ARGV
[0]);
320 command_print(CMD
, "BCM2835 GPIO: peripheral_mem_dev = %s",
321 bcm2835_get_mem_dev());
325 COMMAND_HANDLER(bcm2835gpio_handle_peripheral_base
)
329 COMMAND_PARSE_NUMBER(u64
, CMD_ARGV
[0], tmp_base
);
330 bcm2835_peri_base
= (off_t
)tmp_base
;
333 tmp_base
= bcm2835_peri_base
;
334 command_print(CMD
, "BCM2835 GPIO: peripheral_base = 0x%08" PRIx64
,
339 static const struct command_registration bcm2835gpio_subcommand_handlers
[] = {
341 .name
= "speed_coeffs",
342 .handler
= &bcm2835gpio_handle_speed_coeffs
,
343 .mode
= COMMAND_CONFIG
,
344 .help
= "SPEED_COEFF and SPEED_OFFSET for delay calculations.",
345 .usage
= "[SPEED_COEFF SPEED_OFFSET]",
348 .name
= "peripheral_mem_dev",
349 .handler
= &bcm2835gpio_handle_peripheral_mem_dev
,
350 .mode
= COMMAND_CONFIG
,
351 .help
= "device to map memory mapped GPIOs from.",
355 .name
= "peripheral_base",
356 .handler
= &bcm2835gpio_handle_peripheral_base
,
357 .mode
= COMMAND_CONFIG
,
358 .help
= "peripheral base to access GPIOs, not needed with /dev/gpiomem.",
362 COMMAND_REGISTRATION_DONE
365 static const struct command_registration bcm2835gpio_command_handlers
[] = {
367 .name
= "bcm2835gpio",
369 .help
= "perform bcm2835gpio management",
370 .chain
= bcm2835gpio_subcommand_handlers
,
373 COMMAND_REGISTRATION_DONE
376 static bool bcm2835gpio_jtag_mode_possible(void)
378 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TCK
))
380 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TMS
))
382 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TDI
))
384 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TDO
))
389 static bool bcm2835gpio_swd_mode_possible(void)
391 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_SWCLK
))
393 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_SWDIO
))
398 static void bcm2835gpio_munmap(void)
400 if (pio_base
!= MAP_FAILED
) {
401 munmap((void *)pio_base
, sysconf(_SC_PAGE_SIZE
));
402 pio_base
= MAP_FAILED
;
405 if (pads_base
!= MAP_FAILED
) {
406 munmap((void *)pads_base
, sysconf(_SC_PAGE_SIZE
));
407 pads_base
= MAP_FAILED
;
411 static int bcm2835gpio_blink(int on
)
413 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_LED
))
414 set_gpio_value(&adapter_gpio_config
[ADAPTER_GPIO_IDX_LED
], on
);
419 static struct bitbang_interface bcm2835gpio_bitbang
= {
420 .read
= bcm2835gpio_read
,
421 .write
= bcm2835gpio_write
,
422 .swdio_read
= bcm2835_swdio_read
,
423 .swdio_drive
= bcm2835_swdio_drive
,
424 .swd_write
= bcm2835gpio_swd_write_generic
,
425 .blink
= bcm2835gpio_blink
,
428 static int bcm2835gpio_init(void)
430 LOG_INFO("BCM2835 GPIO JTAG/SWD bitbang driver");
432 bitbang_interface
= &bcm2835gpio_bitbang
;
433 adapter_gpio_config
= adapter_gpio_get_config();
435 if (transport_is_jtag() && !bcm2835gpio_jtag_mode_possible()) {
436 LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode");
437 return ERROR_JTAG_INIT_FAILED
;
440 if (transport_is_swd() && !bcm2835gpio_swd_mode_possible()) {
441 LOG_ERROR("Require swclk and swdio gpio for SWD mode");
442 return ERROR_JTAG_INIT_FAILED
;
445 bool is_gpiomem
= strcmp(bcm2835_get_mem_dev(), "/dev/gpiomem") == 0;
446 bool pad_mapping_possible
= !is_gpiomem
;
448 dev_mem_fd
= open(bcm2835_get_mem_dev(), O_RDWR
| O_SYNC
);
449 if (dev_mem_fd
< 0) {
450 LOG_ERROR("open %s: %s", bcm2835_get_mem_dev(), strerror(errno
));
451 /* TODO: add /dev/mem specific doc and refer to it
452 * if (!is_gpiomem && (errno == EACCES || errno == EPERM))
453 * LOG_INFO("Consult the user's guide chapter 4.? how to set permissions and capabilities");
455 return ERROR_JTAG_INIT_FAILED
;
458 pio_base
= mmap(NULL
, sysconf(_SC_PAGE_SIZE
), PROT_READ
| PROT_WRITE
,
459 MAP_SHARED
, dev_mem_fd
, BCM2835_GPIO_BASE
);
461 if (pio_base
== MAP_FAILED
) {
462 LOG_ERROR("mmap: %s", strerror(errno
));
464 return ERROR_JTAG_INIT_FAILED
;
467 /* TODO: move pads config to a separate utility */
468 if (pad_mapping_possible
) {
469 pads_base
= mmap(NULL
, sysconf(_SC_PAGE_SIZE
), PROT_READ
| PROT_WRITE
,
470 MAP_SHARED
, dev_mem_fd
, BCM2835_PADS_GPIO_0_27
);
472 if (pads_base
== MAP_FAILED
) {
473 LOG_ERROR("mmap pads: %s", strerror(errno
));
474 LOG_WARNING("Continuing with unchanged GPIO pad settings (drive strength and slew rate)");
477 pads_base
= MAP_FAILED
;
482 if (pads_base
!= MAP_FAILED
) {
483 /* set 4mA drive strength, slew rate limited, hysteresis on */
484 initial_drive_strength_etc
= pads_base
[BCM2835_PADS_GPIO_0_27_OFFSET
] & 0x1f;
485 LOG_INFO("initial pads conf %08x", pads_base
[BCM2835_PADS_GPIO_0_27_OFFSET
]);
486 pads_base
[BCM2835_PADS_GPIO_0_27_OFFSET
] = 0x5a000008 + 1;
487 LOG_INFO("pads conf set to %08x", pads_base
[BCM2835_PADS_GPIO_0_27_OFFSET
]);
490 /* Configure JTAG/SWD signals. Default directions and initial states are handled
491 * by adapter.c and "adapter gpio" command.
493 if (transport_is_jtag()) {
494 initialize_gpio(ADAPTER_GPIO_IDX_TDO
);
495 initialize_gpio(ADAPTER_GPIO_IDX_TDI
);
496 initialize_gpio(ADAPTER_GPIO_IDX_TMS
);
497 initialize_gpio(ADAPTER_GPIO_IDX_TCK
);
498 initialize_gpio(ADAPTER_GPIO_IDX_TRST
);
501 if (transport_is_swd()) {
502 /* swdio and its buffer should be initialized in the order that prevents
503 * two outputs from being connected together. This will occur if the
504 * swdio GPIO of the AM335x is configured as an output while its
505 * external buffer is configured to send the swdio signal from the
506 * target to the AM335x.
508 if (adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].init_state
== ADAPTER_GPIO_INIT_STATE_INPUT
) {
509 initialize_gpio(ADAPTER_GPIO_IDX_SWDIO
);
510 initialize_gpio(ADAPTER_GPIO_IDX_SWDIO_DIR
);
512 initialize_gpio(ADAPTER_GPIO_IDX_SWDIO_DIR
);
513 initialize_gpio(ADAPTER_GPIO_IDX_SWDIO
);
516 initialize_gpio(ADAPTER_GPIO_IDX_SWCLK
);
518 if (adapter_gpio_config
[ADAPTER_GPIO_IDX_SWCLK
].drive
== ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL
&&
519 adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].drive
== ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL
) {
520 LOG_DEBUG("BCM2835 GPIO using fast mode for SWD write");
521 bcm2835gpio_bitbang
.swd_write
= bcm2835gpio_swd_write_fast
;
523 LOG_DEBUG("BCM2835 GPIO using generic mode for SWD write");
524 bcm2835gpio_bitbang
.swd_write
= bcm2835gpio_swd_write_generic
;
528 initialize_gpio(ADAPTER_GPIO_IDX_SRST
);
529 initialize_gpio(ADAPTER_GPIO_IDX_LED
);
534 static int bcm2835gpio_quit(void)
536 if (transport_is_jtag()) {
537 restore_gpio(ADAPTER_GPIO_IDX_TDO
);
538 restore_gpio(ADAPTER_GPIO_IDX_TDI
);
539 restore_gpio(ADAPTER_GPIO_IDX_TCK
);
540 restore_gpio(ADAPTER_GPIO_IDX_TMS
);
541 restore_gpio(ADAPTER_GPIO_IDX_TRST
);
544 if (transport_is_swd()) {
545 /* Restore swdio/swdio_dir to their initial modes, even if that means
546 * connecting two outputs. Begin by making swdio an input so that the
547 * current and final states of swdio and swdio_dir do not have to be
548 * considered to calculate the safe restoration order.
550 INP_GPIO(adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].gpio_num
);
551 restore_gpio(ADAPTER_GPIO_IDX_SWDIO_DIR
);
552 restore_gpio(ADAPTER_GPIO_IDX_SWDIO
);
553 restore_gpio(ADAPTER_GPIO_IDX_SWCLK
);
556 restore_gpio(ADAPTER_GPIO_IDX_SRST
);
557 restore_gpio(ADAPTER_GPIO_IDX_LED
);
559 if (pads_base
!= MAP_FAILED
) {
560 /* Restore drive strength. MSB is password ("5A") */
561 pads_base
[BCM2835_PADS_GPIO_0_27_OFFSET
] = 0x5A000000 | initial_drive_strength_etc
;
563 bcm2835gpio_munmap();
564 free(bcm2835_peri_mem_dev
);
570 static const char * const bcm2835_transports
[] = { "jtag", "swd", NULL
};
572 static struct jtag_interface bcm2835gpio_interface
= {
573 .supported
= DEBUG_CAP_TMS_SEQ
,
574 .execute_queue
= bitbang_execute_queue
,
576 struct adapter_driver bcm2835gpio_adapter_driver
= {
577 .name
= "bcm2835gpio",
578 .transports
= bcm2835_transports
,
579 .commands
= bcm2835gpio_command_handlers
,
581 .init
= bcm2835gpio_init
,
582 .quit
= bcm2835gpio_quit
,
583 .reset
= bcm2835gpio_reset
,
584 .speed
= bcm2835gpio_speed
,
585 .khz
= bcm2835gpio_khz
,
586 .speed_div
= bcm2835gpio_speed_div
,
588 .jtag_ops
= &bcm2835gpio_interface
,
589 .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)