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
].gpio_num
<= 31;
90 static void set_gpio_value(const struct adapter_gpio_config
*gpio_config
, int value
)
92 value
= value
^ (gpio_config
->active_low
? 1 : 0);
93 switch (gpio_config
->drive
) {
94 case ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL
:
96 GPIO_SET
= 1 << gpio_config
->gpio_num
;
98 GPIO_CLR
= 1 << gpio_config
->gpio_num
;
99 /* For performance reasons assume the GPIO is already set as an output
100 * and therefore the call can be omitted here.
103 case ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN
:
105 INP_GPIO(gpio_config
->gpio_num
);
107 GPIO_CLR
= 1 << gpio_config
->gpio_num
;
108 OUT_GPIO(gpio_config
->gpio_num
);
111 case ADAPTER_GPIO_DRIVE_MODE_OPEN_SOURCE
:
113 GPIO_SET
= 1 << gpio_config
->gpio_num
;
114 OUT_GPIO(gpio_config
->gpio_num
);
116 INP_GPIO(gpio_config
->gpio_num
);
120 bcm2835_gpio_synchronize();
123 static void restore_gpio(enum adapter_gpio_config_index idx
)
125 if (is_gpio_config_valid(idx
)) {
126 SET_MODE_GPIO(adapter_gpio_config
[idx
].gpio_num
, initial_gpio_state
[idx
].mode
);
127 if (initial_gpio_state
[idx
].mode
== BCM2835_GPIO_MODE_OUTPUT
) {
128 if (initial_gpio_state
[idx
].output_level
)
129 GPIO_SET
= 1 << adapter_gpio_config
[idx
].gpio_num
;
131 GPIO_CLR
= 1 << adapter_gpio_config
[idx
].gpio_num
;
134 bcm2835_gpio_synchronize();
137 static void initialize_gpio(enum adapter_gpio_config_index idx
)
139 if (!is_gpio_config_valid(idx
))
142 initial_gpio_state
[idx
].mode
= MODE_GPIO(adapter_gpio_config
[idx
].gpio_num
);
143 unsigned int shift
= adapter_gpio_config
[idx
].gpio_num
;
144 initial_gpio_state
[idx
].output_level
= (GPIO_LEV
>> shift
) & 1;
145 LOG_DEBUG("saved GPIO mode for %s (GPIO %d %d): %d",
146 adapter_gpio_get_name(idx
), adapter_gpio_config
[idx
].chip_num
, adapter_gpio_config
[idx
].gpio_num
,
147 initial_gpio_state
[idx
].mode
);
149 if (adapter_gpio_config
[idx
].pull
!= ADAPTER_GPIO_PULL_NONE
) {
150 LOG_WARNING("BCM2835 GPIO does not support pull-up or pull-down settings (signal %s)",
151 adapter_gpio_get_name(idx
));
154 switch (adapter_gpio_config
[idx
].init_state
) {
155 case ADAPTER_GPIO_INIT_STATE_INACTIVE
:
156 set_gpio_value(&adapter_gpio_config
[idx
], 0);
158 case ADAPTER_GPIO_INIT_STATE_ACTIVE
:
159 set_gpio_value(&adapter_gpio_config
[idx
], 1);
161 case ADAPTER_GPIO_INIT_STATE_INPUT
:
162 INP_GPIO(adapter_gpio_config
[idx
].gpio_num
);
166 /* Direction for non push-pull is already set by set_gpio_value() */
167 if (adapter_gpio_config
[idx
].drive
== ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL
168 && adapter_gpio_config
[idx
].init_state
!= ADAPTER_GPIO_INIT_STATE_INPUT
)
169 OUT_GPIO(adapter_gpio_config
[idx
].gpio_num
);
170 bcm2835_gpio_synchronize();
173 static bb_value_t
bcm2835gpio_read(void)
175 unsigned int shift
= adapter_gpio_config
[ADAPTER_GPIO_IDX_TDO
].gpio_num
;
176 uint32_t value
= (GPIO_LEV
>> shift
) & 1;
177 return value
^ (adapter_gpio_config
[ADAPTER_GPIO_IDX_TDO
].active_low
? BB_HIGH
: BB_LOW
);
181 static int bcm2835gpio_write(int tck
, int tms
, int tdi
)
183 uint32_t set
= tck
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_TCK
].gpio_num
|
184 tms
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_TMS
].gpio_num
|
185 tdi
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_TDI
].gpio_num
;
186 uint32_t clear
= !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
;
192 bcm2835_gpio_synchronize();
199 /* Requires push-pull drive mode for swclk and swdio */
200 static int bcm2835gpio_swd_write_fast(int swclk
, int swdio
)
202 swclk
= swclk
^ (adapter_gpio_config
[ADAPTER_GPIO_IDX_SWCLK
].active_low
? 1 : 0);
203 swdio
= swdio
^ (adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].active_low
? 1 : 0);
205 uint32_t set
= swclk
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_SWCLK
].gpio_num
|
206 swdio
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].gpio_num
;
207 uint32_t clear
= !swclk
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_SWCLK
].gpio_num
|
208 !swdio
<< adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
].gpio_num
;
212 bcm2835_gpio_synchronize();
219 /* Generic mode that works for open-drain/open-source drive modes, but slower */
220 static int bcm2835gpio_swd_write_generic(int swclk
, int swdio
)
222 set_gpio_value(&adapter_gpio_config
[ADAPTER_GPIO_IDX_SWDIO
], swdio
);
223 set_gpio_value(&adapter_gpio_config
[ADAPTER_GPIO_IDX_SWCLK
], swclk
); /* Write clock last */
230 /* (1) assert or (0) deassert reset lines */
231 static int bcm2835gpio_reset(int trst
, int srst
)
233 /* As the "adapter reset_config" command keeps the srst and trst gpio drive
234 * mode settings in sync we can use our standard set_gpio_value() function
235 * that honours drive mode and active low.
237 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_SRST
))
238 set_gpio_value(&adapter_gpio_config
[ADAPTER_GPIO_IDX_SRST
], srst
);
240 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_TRST
))
241 set_gpio_value(&adapter_gpio_config
[ADAPTER_GPIO_IDX_TRST
], trst
);
243 LOG_DEBUG("trst %d gpio: %d %d, srst %d gpio: %d %d",
245 (int)adapter_gpio_config
[ADAPTER_GPIO_IDX_TRST
].chip_num
,
246 (int)adapter_gpio_config
[ADAPTER_GPIO_IDX_TRST
].gpio_num
,
248 (int)adapter_gpio_config
[ADAPTER_GPIO_IDX_SRST
].chip_num
,
249 (int)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)