jtag/drivers: send bitstream size to firmware via libusb
[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].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;
91 }
92
93 static void set_gpio_value(const struct adapter_gpio_config *gpio_config, int value)
94 {
95 value = value ^ (gpio_config->active_low ? 1 : 0);
96 switch (gpio_config->drive) {
97 case ADAPTER_GPIO_DRIVE_MODE_PUSH_PULL:
98 if (value)
99 GPIO_SET = 1 << gpio_config->gpio_num;
100 else
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.
104 */
105 break;
106 case ADAPTER_GPIO_DRIVE_MODE_OPEN_DRAIN:
107 if (value) {
108 INP_GPIO(gpio_config->gpio_num);
109 } else {
110 GPIO_CLR = 1 << gpio_config->gpio_num;
111 OUT_GPIO(gpio_config->gpio_num);
112 }
113 break;
114 case ADAPTER_GPIO_DRIVE_MODE_OPEN_SOURCE:
115 if (value) {
116 GPIO_SET = 1 << gpio_config->gpio_num;
117 OUT_GPIO(gpio_config->gpio_num);
118 } else {
119 INP_GPIO(gpio_config->gpio_num);
120 }
121 break;
122 }
123 bcm2835_gpio_synchronize();
124 }
125
126 static void restore_gpio(enum adapter_gpio_config_index idx)
127 {
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;
133 else
134 GPIO_CLR = 1 << adapter_gpio_config[idx].gpio_num;
135 }
136 }
137 bcm2835_gpio_synchronize();
138 }
139
140 static void initialize_gpio(enum adapter_gpio_config_index idx)
141 {
142 if (!is_gpio_config_valid(idx))
143 return;
144
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);
151
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));
155 }
156
157 switch (adapter_gpio_config[idx].init_state) {
158 case ADAPTER_GPIO_INIT_STATE_INACTIVE:
159 set_gpio_value(&adapter_gpio_config[idx], 0);
160 break;
161 case ADAPTER_GPIO_INIT_STATE_ACTIVE:
162 set_gpio_value(&adapter_gpio_config[idx], 1);
163 break;
164 case ADAPTER_GPIO_INIT_STATE_INPUT:
165 INP_GPIO(adapter_gpio_config[idx].gpio_num);
166 break;
167 }
168
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();
174 }
175
176 static bb_value_t bcm2835gpio_read(void)
177 {
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);
181
182 }
183
184 static int bcm2835gpio_write(int tck, int tms, int tdi)
185 {
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;
192
193 GPIO_SET = set;
194 GPIO_CLR = clear;
195 bcm2835_gpio_synchronize();
196
197 bcm2835_delay();
198
199 return ERROR_OK;
200 }
201
202 /* Requires push-pull drive mode for swclk and swdio */
203 static int bcm2835gpio_swd_write_fast(int swclk, int swdio)
204 {
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);
207
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;
212
213 GPIO_SET = set;
214 GPIO_CLR = clear;
215 bcm2835_gpio_synchronize();
216
217 bcm2835_delay();
218
219 return ERROR_OK;
220 }
221
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)
224 {
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 */
227
228 bcm2835_delay();
229
230 return ERROR_OK;
231 }
232
233 /* (1) assert or (0) deassert reset lines */
234 static int bcm2835gpio_reset(int trst, int srst)
235 {
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.
239 */
240 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_SRST))
241 set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_SRST], srst);
242
243 if (is_gpio_config_valid(ADAPTER_GPIO_IDX_TRST))
244 set_gpio_value(&adapter_gpio_config[ADAPTER_GPIO_IDX_TRST], trst);
245
246 LOG_DEBUG("BCM2835 GPIO: bcm2835gpio_reset(%d, %d), trst_gpio: %d %d, srst_gpio: %d %d",
247 trst, srst,
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);
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)