jtag/drivers/bcm2835gpio: extend peripheral_base to off_t
[openocd.git] / src / jtag / drivers / bcm2835gpio.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2013 by Paul Fertser, fercerpav@gmail.com *
5 * *
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 ***************************************************************************/
10
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
14
15 #include <jtag/adapter.h>
16 #include <jtag/interface.h>
17 #include <transport/transport.h>
18 #include "bitbang.h"
19
20 #include <sys/mman.h>
21
22 static off_t bcm2835_peri_base = 0x20000000;
23 #define BCM2835_GPIO_BASE (bcm2835_peri_base + 0x200000) /* GPIO controller */
24
25 #define BCM2835_PADS_GPIO_0_27 (bcm2835_peri_base + 0x100000)
26 #define BCM2835_PADS_GPIO_0_27_OFFSET (0x2c / 4)
27
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
31
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 */ \
36 INP_GPIO(g); \
37 *(pio_base+((g)/10)) |= ((m)<<(((g)%10)*3)); } while (0)
38 #define OUT_GPIO(g) SET_MODE_GPIO(g, BCM2835_GPIO_MODE_OUTPUT)
39
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 */
43
44 static int dev_mem_fd;
45 static volatile uint32_t *pio_base = MAP_FAILED;
46 static volatile uint32_t *pads_base = MAP_FAILED;
47
48 /* Transition delay coefficients */
49 static int speed_coeff = 113714;
50 static int speed_offset = 28;
51 static unsigned int jtag_delay;
52
53 static const struct adapter_gpio_config *adapter_gpio_config;
54 static struct initial_gpio_state {
55 unsigned int mode;
56 unsigned int output_level;
57 } initial_gpio_state[ADAPTER_GPIO_IDX_NUM];
58 static uint32_t initial_drive_strength_etc;
59
60 static inline void bcm2835_gpio_synchronize(void)
61 {
62 /* Ensure that previous writes to GPIO registers are flushed out of
63 * the inner shareable domain to prevent pipelined writes to the
64 * same address being merged.
65 */
66 __sync_synchronize();
67 }
68
69 static inline void bcm2835_delay(void)
70 {
71 for (unsigned int i = 0; i < jtag_delay; i++)
72 asm volatile ("");
73 }
74
75 static bool is_gpio_config_valid(enum adapter_gpio_config_index idx)
76 {
77 /* Only chip 0 is supported, accept unset value (-1) too */
78 return adapter_gpio_config[idx].chip_num >= -1
79 && adapter_gpio_config[idx].chip_num <= 0
80 && adapter_gpio_config[idx].gpio_num >= 0
81 && adapter_gpio_config[idx].gpio_num <= 31;
82 }
83
84 static void set_gpio_value(const struct adapter_gpio_config *gpio_config, int value)
85 {
86 value = value ^ (gpio_config->active_low ? 1 : 0);
87 switch (gpio_config->drive) {
88 case ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL:
89 if (value)
90 GPIO_SET = 1 << gpio_config->gpio_num;
91 else
92 GPIO_CLR = 1 << gpio_config->gpio_num;
93 /* For performance reasons assume the GPIO is already set as an output
94 * and therefore the call can be omitted here.
95 */
96 break;
97 case ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN:
98 if (value) {
99 INP_GPIO(gpio_config->gpio_num);
100 } else {
101 GPIO_CLR = 1 << gpio_config->gpio_num;
102 OUT_GPIO(gpio_config->gpio_num);
103 }
104 break;
105 case ADAPTER_GPIO_DRIVE_MODE_OPEN_SOURCE:
106 if (value) {
107 GPIO_SET = 1 << gpio_config->gpio_num;
108 OUT_GPIO(gpio_config->gpio_num);
109 } else {
110 INP_GPIO(gpio_config->gpio_num);
111 }
112 break;
113 }
114 bcm2835_gpio_synchronize();
115 }
116
117 static void restore_gpio(enum adapter_gpio_config_index idx)
118 {
119 if (is_gpio_config_valid(idx)) {
120 SET_MODE_GPIO(adapter_gpio_config[idx].gpio_num, initial_gpio_state[idx].mode);
121 if (initial_gpio_state[idx].mode == BCM2835_GPIO_MODE_OUTPUT) {
122 if (initial_gpio_state[idx].output_level)
123 GPIO_SET = 1 << adapter_gpio_config[idx].gpio_num;
124 else
125 GPIO_CLR = 1 << adapter_gpio_config[idx].gpio_num;
126 }
127 }
128 bcm2835_gpio_synchronize();
129 }
130
131 static void initialize_gpio(enum adapter_gpio_config_index idx)
132 {
133 if (!is_gpio_config_valid(idx))
134 return;
135
136 initial_gpio_state[idx].mode = MODE_GPIO(adapter_gpio_config[idx].gpio_num);
137 unsigned int shift = adapter_gpio_config[idx].gpio_num;
138 initial_gpio_state[idx].output_level = (GPIO_LEV >> shift) & 1;
139 LOG_DEBUG("saved GPIO mode for %s (GPIO %d %d): %d",
140 adapter_gpio_get_name(idx), adapter_gpio_config[idx].chip_num, adapter_gpio_config[idx].gpio_num,
141 initial_gpio_state[idx].mode);
142
143 if (adapter_gpio_config[idx].pull != ADAPTER_GPIO_PULL_NONE) {
144 LOG_WARNING("BCM2835 GPIO does not support pull-up or pull-down settings (signal %s)",
145 adapter_gpio_get_name(idx));
146 }
147
148 switch (adapter_gpio_config[idx].init_state) {
149 case ADAPTER_GPIO_INIT_STATE_INACTIVE:
150 set_gpio_value(&adapter_gpio_config[idx], 0);
151 break;
152 case ADAPTER_GPIO_INIT_STATE_ACTIVE:
153 set_gpio_value(&adapter_gpio_config[idx], 1);
154 break;
155 case ADAPTER_GPIO_INIT_STATE_INPUT:
156 INP_GPIO(adapter_gpio_config[idx].gpio_num);
157 break;
158 }
159
160 /* Direction for non push-pull is already set by set_gpio_value() */
161 if (adapter_gpio_config[idx].drive == ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL)
162 OUT_GPIO(adapter_gpio_config[idx].gpio_num);
163 bcm2835_gpio_synchronize();
164 }
165
166 static bb_value_t bcm2835gpio_read(void)
167 {
168 unsigned int shift = adapter_gpio_config[ADAPTER_GPIO_IDX_TDO].gpio_num;
169 uint32_t value = (GPIO_LEV >> shift) & 1;
170 return value ^ (adapter_gpio_config[ADAPTER_GPIO_IDX_TDO].active_low ? BB_HIGH : BB_LOW);
171
172 }
173
174 static int bcm2835gpio_write(int tck, int tms, int tdi)
175 {
176 uint32_t set = tck << adapter_gpio_config[ADAPTER_GPIO_IDX_TCK].gpio_num |
177 tms << adapter_gpio_config[ADAPTER_GPIO_IDX_TMS].gpio_num |
178 tdi << adapter_gpio_config[ADAPTER_GPIO_IDX_TDI].gpio_num;
179 uint32_t clear = !tck << adapter_gpio_config[ADAPTER_GPIO_IDX_TCK].gpio_num |
180 !tms << adapter_gpio_config[ADAPTER_GPIO_IDX_TMS].gpio_num |
181 !tdi << adapter_gpio_config[ADAPTER_GPIO_IDX_TDI].gpio_num;
182
183 GPIO_SET = set;
184 GPIO_CLR = clear;
185 bcm2835_gpio_synchronize();
186
187 bcm2835_delay();
188
189 return ERROR_OK;
190 }
191
192 /* Requires push-pull drive mode for swclk and swdio */
193 static int bcm2835gpio_swd_write_fast(int swclk, int swdio)
194 {
195 swclk = swclk ^ (adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK].active_low ? 1 : 0);
196 swdio = swdio ^ (adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].active_low ? 1 : 0);
197
198 uint32_t set = swclk << adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK].gpio_num |
199 swdio << adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num;
200 uint32_t clear = !swclk << adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK].gpio_num |
201 !swdio << adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num;
202
203 GPIO_SET = set;
204 GPIO_CLR = clear;
205 bcm2835_gpio_synchronize();
206
207 bcm2835_delay();
208
209 return ERROR_OK;
210 }
211
212 /* Generic mode that works for open-drain/open-source drive modes, but slower */
213 static int bcm2835gpio_swd_write_generic(int swclk, int swdio)
214 {
215 set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO], swdio);
216 set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK], swclk); /* Write clock last */
217
218 bcm2835_delay();
219
220 return ERROR_OK;
221 }
222
223 /* (1) assert or (0) deassert reset lines */
224 static int bcm2835gpio_reset(int trst, int srst)
225 {
226 /* As the "adapter reset_config" command keeps the srst and trst gpio drive
227 * mode settings in sync we can use our standard set_gpio_value() function
228 * that honours drive mode and active low.
229 */
230 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_SRST))
231 set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_SRST], srst);
232
233 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_TRST))
234 set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_TRST], trst);
235
236 LOG_DEBUG("BCM2835 GPIO: bcm2835gpio_reset(%d, %d), trst_gpio: %d %d, srst_gpio: %d %d",
237 trst, srst,
238 adapter_gpio_config[ADAPTER_GPIO_IDX_TRST].chip_num, adapter_gpio_config[ADAPTER_GPIO_IDX_TRST].gpio_num,
239 adapter_gpio_config[ADAPTER_GPIO_IDX_SRST].chip_num, adapter_gpio_config[ADAPTER_GPIO_IDX_SRST].gpio_num);
240 return ERROR_OK;
241 }
242
243 static void bcm2835_swdio_drive(bool is_output)
244 {
245 if (is_output) {
246 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_SWDIO_DIR))
247 set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO_DIR], 1);
248 OUT_GPIO(adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num);
249 } else {
250 INP_GPIO(adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num);
251 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_SWDIO_DIR))
252 set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO_DIR], 0);
253 }
254 bcm2835_gpio_synchronize();
255 }
256
257 static int bcm2835_swdio_read(void)
258 {
259 unsigned int shift = adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num;
260 uint32_t value = (GPIO_LEV >> shift) & 1;
261 return value ^ (adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].active_low ? 1 : 0);
262 }
263
264 static int bcm2835gpio_khz(int khz, int *jtag_speed)
265 {
266 if (!khz) {
267 LOG_DEBUG("BCM2835 GPIO: RCLK not supported");
268 return ERROR_FAIL;
269 }
270 *jtag_speed = DIV_ROUND_UP(speed_coeff, khz) - speed_offset;
271 LOG_DEBUG("jtag_delay %d", *jtag_speed);
272 if (*jtag_speed < 0)
273 *jtag_speed = 0;
274 return ERROR_OK;
275 }
276
277 static int bcm2835gpio_speed_div(int speed, int *khz)
278 {
279 int divisor = speed + speed_offset;
280 /* divide with roundig to the closest */
281 *khz = (speed_coeff + divisor / 2) / divisor;
282 return ERROR_OK;
283 }
284
285 static int bcm2835gpio_speed(int speed)
286 {
287 jtag_delay = speed;
288 return ERROR_OK;
289 }
290
291 COMMAND_HANDLER(bcm2835gpio_handle_speed_coeffs)
292 {
293 if (CMD_ARGC == 2) {
294 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], speed_coeff);
295 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], speed_offset);
296 }
297
298 command_print(CMD, "BCM2835 GPIO: speed_coeffs = %d, speed_offset = %d",
299 speed_coeff, speed_offset);
300 return ERROR_OK;
301 }
302
303 COMMAND_HANDLER(bcm2835gpio_handle_peripheral_base)
304 {
305 uint64_t tmp_base;
306 if (CMD_ARGC == 1) {
307 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], tmp_base);
308 bcm2835_peri_base = (off_t)tmp_base;
309 }
310
311 tmp_base = bcm2835_peri_base;
312 command_print(CMD, "BCM2835 GPIO: peripheral_base = 0x%08" PRIu64,
313 tmp_base);
314 return ERROR_OK;
315 }
316
317 static const struct command_registration bcm2835gpio_subcommand_handlers[] = {
318 {
319 .name = "speed_coeffs",
320 .handler = &bcm2835gpio_handle_speed_coeffs,
321 .mode = COMMAND_CONFIG,
322 .help = "SPEED_COEFF and SPEED_OFFSET for delay calculations.",
323 .usage = "[SPEED_COEFF SPEED_OFFSET]",
324 },
325 {
326 .name = "peripheral_base",
327 .handler = &bcm2835gpio_handle_peripheral_base,
328 .mode = COMMAND_CONFIG,
329 .help = "peripheral base to access GPIOs, not needed with /dev/gpiomem.",
330 .usage = "[base]",
331 },
332
333 COMMAND_REGISTRATION_DONE
334 };
335
336 static const struct command_registration bcm2835gpio_command_handlers[] = {
337 {
338 .name = "bcm2835gpio",
339 .mode = COMMAND_ANY,
340 .help = "perform bcm2835gpio management",
341 .chain = bcm2835gpio_subcommand_handlers,
342 .usage = "",
343 },
344 COMMAND_REGISTRATION_DONE
345 };
346
347 static bool bcm2835gpio_jtag_mode_possible(void)
348 {
349 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TCK))
350 return false;
351 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TMS))
352 return false;
353 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TDI))
354 return false;
355 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TDO))
356 return false;
357 return true;
358 }
359
360 static bool bcm2835gpio_swd_mode_possible(void)
361 {
362 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_SWCLK))
363 return false;
364 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_SWDIO))
365 return false;
366 return true;
367 }
368
369 static void bcm2835gpio_munmap(void)
370 {
371 if (pio_base != MAP_FAILED) {
372 munmap((void *)pio_base, sysconf(_SC_PAGE_SIZE));
373 pio_base = MAP_FAILED;
374 }
375
376 if (pads_base != MAP_FAILED) {
377 munmap((void *)pads_base, sysconf(_SC_PAGE_SIZE));
378 pads_base = MAP_FAILED;
379 }
380 }
381
382 static int bcm2835gpio_blink(int on)
383 {
384 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_LED))
385 set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_LED], on);
386
387 return ERROR_OK;
388 }
389
390 static struct bitbang_interface bcm2835gpio_bitbang = {
391 .read = bcm2835gpio_read,
392 .write = bcm2835gpio_write,
393 .swdio_read = bcm2835_swdio_read,
394 .swdio_drive = bcm2835_swdio_drive,
395 .swd_write = bcm2835gpio_swd_write_generic,
396 .blink = bcm2835gpio_blink,
397 };
398
399 static int bcm2835gpio_init(void)
400 {
401 LOG_INFO("BCM2835 GPIO JTAG/SWD bitbang driver");
402
403 bitbang_interface = &bcm2835gpio_bitbang;
404 adapter_gpio_config = adapter_gpio_get_config();
405
406 if (transport_is_jtag() && !bcm2835gpio_jtag_mode_possible()) {
407 LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode");
408 return ERROR_JTAG_INIT_FAILED;
409 }
410
411 if (transport_is_swd() && !bcm2835gpio_swd_mode_possible()) {
412 LOG_ERROR("Require swclk and swdio gpio for SWD mode");
413 return ERROR_JTAG_INIT_FAILED;
414 }
415
416 bool pad_mapping_possible = false;
417
418 dev_mem_fd = open("/dev/gpiomem", O_RDWR | O_SYNC);
419 if (dev_mem_fd < 0) {
420 LOG_DEBUG("Cannot open /dev/gpiomem, fallback to /dev/mem");
421 dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
422 pad_mapping_possible = true;
423 }
424 if (dev_mem_fd < 0) {
425 LOG_ERROR("open: %s", strerror(errno));
426 return ERROR_JTAG_INIT_FAILED;
427 }
428
429 pio_base = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
430 MAP_SHARED, dev_mem_fd, BCM2835_GPIO_BASE);
431
432 if (pio_base == MAP_FAILED) {
433 LOG_ERROR("mmap: %s", strerror(errno));
434 close(dev_mem_fd);
435 return ERROR_JTAG_INIT_FAILED;
436 }
437
438 /* TODO: move pads config to a separate utility */
439 if (pad_mapping_possible) {
440 pads_base = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
441 MAP_SHARED, dev_mem_fd, BCM2835_PADS_GPIO_0_27);
442
443 if (pads_base == MAP_FAILED) {
444 LOG_ERROR("mmap pads: %s", strerror(errno));
445 LOG_WARNING("Continuing with unchanged GPIO pad settings (drive strength and slew rate)");
446 }
447 } else {
448 pads_base = MAP_FAILED;
449 }
450
451 close(dev_mem_fd);
452
453 if (pads_base != MAP_FAILED) {
454 /* set 4mA drive strength, slew rate limited, hysteresis on */
455 initial_drive_strength_etc = pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] & 0x1f;
456 LOG_INFO("initial pads conf %08x", pads_base[BCM2835_PADS_GPIO_0_27_OFFSET]);
457 pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000008 + 1;
458 LOG_INFO("pads conf set to %08x", pads_base[BCM2835_PADS_GPIO_0_27_OFFSET]);
459 }
460
461 /* Configure JTAG/SWD signals. Default directions and initial states are handled
462 * by adapter.c and "adapter gpio" command.
463 */
464 if (transport_is_jtag()) {
465 initialize_gpio(ADAPTER_GPIO_IDX_TDO);
466 initialize_gpio(ADAPTER_GPIO_IDX_TDI);
467 initialize_gpio(ADAPTER_GPIO_IDX_TMS);
468 initialize_gpio(ADAPTER_GPIO_IDX_TCK);
469 initialize_gpio(ADAPTER_GPIO_IDX_TRST);
470 }
471
472 if (transport_is_swd()) {
473 /* swdio and its buffer should be initialized in the order that prevents
474 * two outputs from being connected together. This will occur if the
475 * swdio GPIO of the AM335x is configured as an output while its
476 * external buffer is configured to send the swdio signal from the
477 * target to the AM335x.
478 */
479 if (adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].init_state == ADAPTER_GPIO_INIT_STATE_INPUT) {
480 initialize_gpio(ADAPTER_GPIO_IDX_SWDIO);
481 initialize_gpio(ADAPTER_GPIO_IDX_SWDIO_DIR);
482 } else {
483 initialize_gpio(ADAPTER_GPIO_IDX_SWDIO_DIR);
484 initialize_gpio(ADAPTER_GPIO_IDX_SWDIO);
485 }
486
487 initialize_gpio(ADAPTER_GPIO_IDX_SWCLK);
488
489 if (adapter_gpio_config[ADAPTER_GPIO_IDX_SWCLK].drive == ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL &&
490 adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].drive == ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL) {
491 LOG_DEBUG("BCM2835 GPIO using fast mode for SWD write");
492 bcm2835gpio_bitbang.swd_write = bcm2835gpio_swd_write_fast;
493 } else {
494 LOG_DEBUG("BCM2835 GPIO using generic mode for SWD write");
495 bcm2835gpio_bitbang.swd_write = bcm2835gpio_swd_write_generic;
496 }
497 }
498
499 initialize_gpio(ADAPTER_GPIO_IDX_SRST);
500 initialize_gpio(ADAPTER_GPIO_IDX_LED);
501
502 return ERROR_OK;
503 }
504
505 static int bcm2835gpio_quit(void)
506 {
507 if (transport_is_jtag()) {
508 restore_gpio(ADAPTER_GPIO_IDX_TDO);
509 restore_gpio(ADAPTER_GPIO_IDX_TDI);
510 restore_gpio(ADAPTER_GPIO_IDX_TCK);
511 restore_gpio(ADAPTER_GPIO_IDX_TMS);
512 restore_gpio(ADAPTER_GPIO_IDX_TRST);
513 }
514
515 if (transport_is_swd()) {
516 /* Restore swdio/swdio_dir to their initial modes, even if that means
517 * connecting two outputs. Begin by making swdio an input so that the
518 * current and final states of swdio and swdio_dir do not have to be
519 * considered to calculate the safe restoration order.
520 */
521 INP_GPIO(adapter_gpio_config[ADAPTER_GPIO_IDX_SWDIO].gpio_num);
522 restore_gpio(ADAPTER_GPIO_IDX_SWDIO_DIR);
523 restore_gpio(ADAPTER_GPIO_IDX_SWDIO);
524 restore_gpio(ADAPTER_GPIO_IDX_SWCLK);
525 }
526
527 restore_gpio(ADAPTER_GPIO_IDX_SRST);
528 restore_gpio(ADAPTER_GPIO_IDX_LED);
529
530 if (pads_base != MAP_FAILED) {
531 /* Restore drive strength. MSB is password ("5A") */
532 pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5A000000 | initial_drive_strength_etc;
533 }
534 bcm2835gpio_munmap();
535
536 return ERROR_OK;
537 }
538
539
540 static const char * const bcm2835_transports[] = { "jtag", "swd", NULL };
541
542 static struct jtag_interface bcm2835gpio_interface = {
543 .supported = DEBUG_CAP_TMS_SEQ,
544 .execute_queue = bitbang_execute_queue,
545 };
546 struct adapter_driver bcm2835gpio_adapter_driver = {
547 .name = "bcm2835gpio",
548 .transports = bcm2835_transports,
549 .commands = bcm2835gpio_command_handlers,
550
551 .init = bcm2835gpio_init,
552 .quit = bcm2835gpio_quit,
553 .reset = bcm2835gpio_reset,
554 .speed = bcm2835gpio_speed,
555 .khz = bcm2835gpio_khz,
556 .speed_div = bcm2835gpio_speed_div,
557
558 .jtag_ops = &bcm2835gpio_interface,
559 .swd_ops = &bitbang_swd,
560 };

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)