jtag: linuxgpiod: drop extra parenthesis
[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 char *bcm2835_peri_mem_dev;
23 static off_t bcm2835_peri_base = 0x20000000;
24 #define BCM2835_GPIO_BASE (bcm2835_peri_base + 0x200000) /* GPIO controller */
25
26 #define BCM2835_PADS_GPIO_0_27 (bcm2835_peri_base + 0x100000)
27 #define BCM2835_PADS_GPIO_0_27_OFFSET (0x2c / 4)
28
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
32
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 */ \
37 INP_GPIO(g); \
38 *(pio_base+((g)/10)) |= ((m)<<(((g)%10)*3)); } while (0)
39 #define OUT_GPIO(g) SET_MODE_GPIO(g, BCM2835_GPIO_MODE_OUTPUT)
40
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 */
44
45 static int dev_mem_fd;
46 static volatile uint32_t *pio_base = MAP_FAILED;
47 static volatile uint32_t *pads_base = MAP_FAILED;
48
49 /* Transition delay coefficients */
50 static int speed_coeff = 113714;
51 static int speed_offset = 28;
52 static unsigned int jtag_delay;
53
54 static const struct adapter_gpio_config *adapter_gpio_config;
55 static struct initial_gpio_state {
56 unsigned int mode;
57 unsigned int output_level;
58 } initial_gpio_state[ADAPTER_GPIO_IDX_NUM];
59 static uint32_t initial_drive_strength_etc;
60
61 static inline const char *bcm2835_get_mem_dev(void)
62 {
63 if (bcm2835_peri_mem_dev)
64 return bcm2835_peri_mem_dev;
65
66 return "/dev/gpiomem";
67 }
68
69 static inline void bcm2835_gpio_synchronize(void)
70 {
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.
74 */
75 __sync_synchronize();
76 }
77
78 static inline void bcm2835_delay(void)
79 {
80 for (unsigned int i = 0; i < jtag_delay; i++)
81 asm volatile ("");
82 }
83
84 static bool is_gpio_config_valid(enum adapter_gpio_config_index idx)
85 {
86 /* Only chip 0 is supported, accept unset value (-1) too */
87 return adapter_gpio_config[idx].gpio_num <= 31;
88 }
89
90 static void set_gpio_value(const struct adapter_gpio_config *gpio_config, int value)
91 {
92 value = value ^ (gpio_config->active_low ? 1 : 0);
93 switch (gpio_config->drive) {
94 case ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL:
95 if (value)
96 GPIO_SET = 1 << gpio_config->gpio_num;
97 else
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.
101 */
102 break;
103 case ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN:
104 if (value) {
105 INP_GPIO(gpio_config->gpio_num);
106 } else {
107 GPIO_CLR = 1 << gpio_config->gpio_num;
108 OUT_GPIO(gpio_config->gpio_num);
109 }
110 break;
111 case ADAPTER_GPIO_DRIVE_MODE_OPEN_SOURCE:
112 if (value) {
113 GPIO_SET = 1 << gpio_config->gpio_num;
114 OUT_GPIO(gpio_config->gpio_num);
115 } else {
116 INP_GPIO(gpio_config->gpio_num);
117 }
118 break;
119 }
120 bcm2835_gpio_synchronize();
121 }
122
123 static void restore_gpio(enum adapter_gpio_config_index idx)
124 {
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;
130 else
131 GPIO_CLR = 1 << adapter_gpio_config[idx].gpio_num;
132 }
133 }
134 bcm2835_gpio_synchronize();
135 }
136
137 static void initialize_gpio(enum adapter_gpio_config_index idx)
138 {
139 if (!is_gpio_config_valid(idx))
140 return;
141
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);
148
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));
152 }
153
154 switch (adapter_gpio_config[idx].init_state) {
155 case ADAPTER_GPIO_INIT_STATE_INACTIVE:
156 set_gpio_value(&adapter_gpio_config[idx], 0);
157 break;
158 case ADAPTER_GPIO_INIT_STATE_ACTIVE:
159 set_gpio_value(&adapter_gpio_config[idx], 1);
160 break;
161 case ADAPTER_GPIO_INIT_STATE_INPUT:
162 INP_GPIO(adapter_gpio_config[idx].gpio_num);
163 break;
164 }
165
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();
171 }
172
173 static bb_value_t bcm2835gpio_read(void)
174 {
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);
178
179 }
180
181 static int bcm2835gpio_write(int tck, int tms, int tdi)
182 {
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;
189
190 GPIO_SET = set;
191 GPIO_CLR = clear;
192 bcm2835_gpio_synchronize();
193
194 bcm2835_delay();
195
196 return ERROR_OK;
197 }
198
199 /* Requires push-pull drive mode for swclk and swdio */
200 static int bcm2835gpio_swd_write_fast(int swclk, int swdio)
201 {
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);
204
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;
209
210 GPIO_SET = set;
211 GPIO_CLR = clear;
212 bcm2835_gpio_synchronize();
213
214 bcm2835_delay();
215
216 return ERROR_OK;
217 }
218
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)
221 {
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 */
224
225 bcm2835_delay();
226
227 return ERROR_OK;
228 }
229
230 /* (1) assert or (0) deassert reset lines */
231 static int bcm2835gpio_reset(int trst, int srst)
232 {
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.
236 */
237 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_SRST))
238 set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_SRST], srst);
239
240 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_TRST))
241 set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_TRST], trst);
242
243 LOG_DEBUG("trst %d gpio: %d %d, srst %d gpio: %d %d",
244 trst,
245 (int)adapter_gpio_config[ADAPTER_GPIO_IDX_TRST].chip_num,
246 (int)adapter_gpio_config[ADAPTER_GPIO_IDX_TRST].gpio_num,
247 srst,
248 (int)adapter_gpio_config[ADAPTER_GPIO_IDX_SRST].chip_num,
249 (int)adapter_gpio_config[ADAPTER_GPIO_IDX_SRST].gpio_num);
250 return ERROR_OK;
251 }
252
253 static void bcm2835_swdio_drive(bool is_output)
254 {
255 if (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);
259 } else {
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);
263 }
264 bcm2835_gpio_synchronize();
265 }
266
267 static int bcm2835_swdio_read(void)
268 {
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);
272 }
273
274 static int bcm2835gpio_khz(int khz, int *jtag_speed)
275 {
276 if (!khz) {
277 LOG_DEBUG("BCM2835 GPIO: RCLK not supported");
278 return ERROR_FAIL;
279 }
280 *jtag_speed = DIV_ROUND_UP(speed_coeff, khz) - speed_offset;
281 LOG_DEBUG("jtag_delay %d", *jtag_speed);
282 if (*jtag_speed < 0)
283 *jtag_speed = 0;
284 return ERROR_OK;
285 }
286
287 static int bcm2835gpio_speed_div(int speed, int *khz)
288 {
289 int divisor = speed + speed_offset;
290 /* divide with roundig to the closest */
291 *khz = (speed_coeff + divisor / 2) / divisor;
292 return ERROR_OK;
293 }
294
295 static int bcm2835gpio_speed(int speed)
296 {
297 jtag_delay = speed;
298 return ERROR_OK;
299 }
300
301 COMMAND_HANDLER(bcm2835gpio_handle_speed_coeffs)
302 {
303 if (CMD_ARGC == 2) {
304 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], speed_coeff);
305 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], speed_offset);
306 }
307
308 command_print(CMD, "BCM2835 GPIO: speed_coeffs = %d, speed_offset = %d",
309 speed_coeff, speed_offset);
310 return ERROR_OK;
311 }
312
313 COMMAND_HANDLER(bcm2835gpio_handle_peripheral_mem_dev)
314 {
315 if (CMD_ARGC == 1) {
316 free(bcm2835_peri_mem_dev);
317 bcm2835_peri_mem_dev = strdup(CMD_ARGV[0]);
318 }
319
320 command_print(CMD, "BCM2835 GPIO: peripheral_mem_dev = %s",
321 bcm2835_get_mem_dev());
322 return ERROR_OK;
323 }
324
325 COMMAND_HANDLER(bcm2835gpio_handle_peripheral_base)
326 {
327 uint64_t tmp_base;
328 if (CMD_ARGC == 1) {
329 COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], tmp_base);
330 bcm2835_peri_base = (off_t)tmp_base;
331 }
332
333 tmp_base = bcm2835_peri_base;
334 command_print(CMD, "BCM2835 GPIO: peripheral_base = 0x%08" PRIx64,
335 tmp_base);
336 return ERROR_OK;
337 }
338
339 static const struct command_registration bcm2835gpio_subcommand_handlers[] = {
340 {
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]",
346 },
347 {
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.",
352 .usage = "[device]",
353 },
354 {
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.",
359 .usage = "[base]",
360 },
361
362 COMMAND_REGISTRATION_DONE
363 };
364
365 static const struct command_registration bcm2835gpio_command_handlers[] = {
366 {
367 .name = "bcm2835gpio",
368 .mode = COMMAND_ANY,
369 .help = "perform bcm2835gpio management",
370 .chain = bcm2835gpio_subcommand_handlers,
371 .usage = "",
372 },
373 COMMAND_REGISTRATION_DONE
374 };
375
376 static bool bcm2835gpio_jtag_mode_possible(void)
377 {
378 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TCK))
379 return false;
380 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TMS))
381 return false;
382 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TDI))
383 return false;
384 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_TDO))
385 return false;
386 return true;
387 }
388
389 static bool bcm2835gpio_swd_mode_possible(void)
390 {
391 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_SWCLK))
392 return false;
393 if (!is_gpio_config_valid(ADAPTER_GPIO_IDX_SWDIO))
394 return false;
395 return true;
396 }
397
398 static void bcm2835gpio_munmap(void)
399 {
400 if (pio_base != MAP_FAILED) {
401 munmap((void *)pio_base, sysconf(_SC_PAGE_SIZE));
402 pio_base = MAP_FAILED;
403 }
404
405 if (pads_base != MAP_FAILED) {
406 munmap((void *)pads_base, sysconf(_SC_PAGE_SIZE));
407 pads_base = MAP_FAILED;
408 }
409 }
410
411 static int bcm2835gpio_blink(int on)
412 {
413 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_LED))
414 set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_LED], on);
415
416 return ERROR_OK;
417 }
418
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,
426 };
427
428 static int bcm2835gpio_init(void)
429 {
430 LOG_INFO("BCM2835 GPIO JTAG/SWD bitbang driver");
431
432 bitbang_interface = &bcm2835gpio_bitbang;
433 adapter_gpio_config = adapter_gpio_get_config();
434
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;
438 }
439
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;
443 }
444
445 bool is_gpiomem = strcmp(bcm2835_get_mem_dev(), "/dev/gpiomem") == 0;
446 bool pad_mapping_possible = !is_gpiomem;
447
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");
454 */
455 return ERROR_JTAG_INIT_FAILED;
456 }
457
458 pio_base = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE,
459 MAP_SHARED, dev_mem_fd, BCM2835_GPIO_BASE);
460
461 if (pio_base == MAP_FAILED) {
462 LOG_ERROR("mmap: %s", strerror(errno));
463 close(dev_mem_fd);
464 return ERROR_JTAG_INIT_FAILED;
465 }
466
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);
471
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)");
475 }
476 } else {
477 pads_base = MAP_FAILED;
478 }
479
480 close(dev_mem_fd);
481
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]);
488 }
489
490 /* Configure JTAG/SWD signals. Default directions and initial states are handled
491 * by adapter.c and "adapter gpio" command.
492 */
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);
499 }
500
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.
507 */
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);
511 } else {
512 initialize_gpio(ADAPTER_GPIO_IDX_SWDIO_DIR);
513 initialize_gpio(ADAPTER_GPIO_IDX_SWDIO);
514 }
515
516 initialize_gpio(ADAPTER_GPIO_IDX_SWCLK);
517
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;
522 } else {
523 LOG_DEBUG("BCM2835 GPIO using generic mode for SWD write");
524 bcm2835gpio_bitbang.swd_write = bcm2835gpio_swd_write_generic;
525 }
526 }
527
528 initialize_gpio(ADAPTER_GPIO_IDX_SRST);
529 initialize_gpio(ADAPTER_GPIO_IDX_LED);
530
531 return ERROR_OK;
532 }
533
534 static int bcm2835gpio_quit(void)
535 {
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);
542 }
543
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.
549 */
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);
554 }
555
556 restore_gpio(ADAPTER_GPIO_IDX_SRST);
557 restore_gpio(ADAPTER_GPIO_IDX_LED);
558
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;
562 }
563 bcm2835gpio_munmap();
564 free(bcm2835_peri_mem_dev);
565
566 return ERROR_OK;
567 }
568
569
570 static const char * const bcm2835_transports[] = { "jtag", "swd", NULL };
571
572 static struct jtag_interface bcm2835gpio_interface = {
573 .supported = DEBUG_CAP_TMS_SEQ,
574 .execute_queue = bitbang_execute_queue,
575 };
576 struct adapter_driver bcm2835gpio_adapter_driver = {
577 .name = "bcm2835gpio",
578 .transports = bcm2835_transports,
579 .commands = bcm2835gpio_command_handlers,
580
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,
587
588 .jtag_ops = &bcm2835gpio_interface,
589 .swd_ops = &bitbang_swd,
590 };

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)